honeylab's blog

各種ハードウェアの改造、主にファミコンミニなどをやってます(ました)

ATOM Cam内部解析:あれこれして圧縮前の静止画を取得する

なんだか結構ATOM Camのことで検索してくる人が多いようです。
面白いプロダクトで、中の人も積極的にサポートしてくれてるようでユーザの反応も悪くないのですかね。
普通に使ってもいいですが、やはり我々頭のおかしい人間にとっても結構面白いものなので、やばくない範囲でこの機械を徹底解剖していきます。

 

 

尚、気づいてる人もいると思いますが、今年の頭ぐらいから結構頑張ってamazonのリンクを張ったりしています。
もしブログが気に入った方、私の生活費になりますのでブログ内のリンクからいろいろ買ってみてくださいね。(現在、500円/月ぐらいアフィリエイト報酬を頂いています)

というわけで、今回のターゲットは改めてこちら。

このへんの記事で結構書いていますが、中身はLinuxですので結構いじることができます。

honeylab.hatenablog.jp

しかし、実はできることは少ないのです(矛盾?)

いわゆる、組み込みLinuxボード、例えばraspbery piに汎用のusb webカメラなどを接続して監視カメラを作った場合、デバイスはVideo For Linuxの標準的な方法で取り扱うことができ、対応しているストリーミング、キャプチャ、画像認識などのアプリケーションが利用可能です。

それに対し、このような出来合いの、特に中国で設計されている監視カメラでは、
イメージセンサの入力が直接SoC内に接続されたり、SoC内のエンコーダに接続され、独自形式のデータストリームとなってしまい、一般的なLinuxアプリケーションから取り扱うことが難しくなっています。
この ATOM Camでも Ingenicというメーカーの「T31にイメージセンサを接続するためのSDK」を使用しているため、ユーザが頑張って、例えばmjpg-streamerなどのアプリをインストールしたところで全く動かすことはできません
製造メーカでは、このSDKにリンクする形でカメラ映像を自社のサーバに転送できるようにアプリを書くことでこの製品の機能を実現しています。
それ以外の機能を実装しようとしても、元のアプリを改造するか、改めてチップメーカ提供のSDKを利用してアプリを書くしかありません。
しかし、そういったSDKは入手が困難です。

そこで、もともと入っているシステムを解析したり、改造したりする必要が出てきます。

ATOMCamは

・電源を入れるとブートローダ(u-boot)が起動する

・u-boot内で、RESETボタンが押されていればSDからファーム更新を行う

・そうでなければLinuxを起動する

Linuxが起動すると以下のプロセスが起動する

・・shell call sdk tool : "localsdk"が外部プロセスを実行させる仕組み

・・「assis」プロセス :ファームウェア更新など

・・「iCamera_app」プロセス :イメージセンサから画像を取得する。動画を保存したりする。

・・「hl_client」プロセス : クラウドとの接続・P2Pの仲介を行う

 

hl_clientはtcp:9999ポートで待ち受けて、iCamera_appプロセスとプロセス間通信で協調動作します。また、iCamera_appは 先述した"localsdk"と呼ばれるイメージセンサからの画像取得・動画保存関数を呼び出しています。

localsdkには、例えば以下のような関数があります

f:id:honeylab:20200601020031p:plain

このあたりの動作は、シリアルコンソールのログにちょろっと出ています。

 

f:id:honeylab:20200601020301p:plain

 

OSD表示のために、フレームが生成されると呼び出されるコールバックを設定できるようです。左下のロゴや、日時表示の設定を行っています。

 f:id:honeylab:20200601020533p:plain

この顔文字、日本ではあまり使われないですねw

 

さて、ここで見てわかるように、OSDの乗せられた画像はエンコーダに突っ込まれているようです。
ATOMCamのアプリからローカル録画をONにすれば、毎分ごとのmp4を取得することはできますが、これはあくまで動画であり、結構きつい圧縮がかかっているため、きれいな静止画を取得することはできません。

はてはて困ったな、と思っていると、アプリのバイナリと同じところに"impdbg"という怪しい実行ファイルを見つけました。

f:id:honeylab:20200601021100p:plain

ファイル名から推測すると、"IMage Processor DeBuGger"では??

ためらわずに実行してみます。

[root@Ingenic:bin]# ./impdbg
usage: ./impdbg --option [args]
--enc_info get encoder info
--enc_rc_s chn:offset:size:data set encoder rc
--fs_info get frame source info
--save_pic [path] save pic data
--pic_type [RAW/NV12/YUYV422/UYVY422/RGB565BE] save pic type
--system_info get system info
[root@Ingenic:bin]
 

 おやおや??save_picコマンドがありますぞよ?

それぞれのコマンドを実行してみます。

[root@Ingenic:bin]# ./impdbg --system_info
info: func_dispatch,170func mid:fid:name= 3:2:misc_system_info
tree item: 3
Framesource-0 update_cnt=26980(qframecnt=26983, dqframecnt=26980, sem_msg_cnt=16, sem_cnt=0)
OSD-0 update_cnt=26980(sem_msg_cnt=16, sem_cnt=0)
Encoder-0 update_cnt=26980(sem_msg_cnt=16, sem_cnt=0)
---Framesource-0-----OSD-0-------------Encoder-0
tree item: 3
Framesource-1 update_cnt=26980(qframecnt=26983, dqframecnt=26980, sem_msg_cnt=16, sem_cnt=0)
OSD-1 update_cnt=26980(sem_msg_cnt=16, sem_cnt=0)
Encoder-1 update_cnt=26980(sem_msg_cnt=16, sem_cnt=0)
---Framesource-1-----OSD-1-------------Encoder-1
tree item: 1
Framesource-2 update_cnt=0(qframecnt=0, dqframecnt=0, sem_msg_cnt=16, sem_cnt=0)
---Framesource-2

ふむふむ

 

[root@Ingenic:bin]# ./impdbg --fs_info
info: func_dispatch,170func mid:fid:name= 1:0:fs_info
CHANNEL(0)
INFO 1920x 1080 RUN 20/ 1(fps) NV12
CROP DIS left(0) top(0) width(1920) height(1080)
SCALER EN width(1920) height(1080)
CHANNEL(1)
INFO 640x 360 RUN 20/ 1(fps) NV12
CROP DIS left(0) top(0) width(640) height(360)
SCALER EN width(640) height(360)
CHANNEL(2)
INFO 1280x 720 OPEN 20/ 1(fps) NV12
CROP DIS left(0) top(0) width(1280) height(720)
SCALER EN width(1280) height(720)

ふむふむ。

どうやら、3ストリームがあるように見えます。
適当にいろいろ試してみたところ、なんと以下のコマンドで画像らしきものが保存できました。

[root@Ingenic:bin]# ./impdbg --save_pic /tmp/test.bin --pic_type NV12
info: func_dispatch,170func mid:fid:name= 3:0:misc_save_pic
info: save pic file name : /tmp/test.bin type : 1
info: func_dispatch,219 size = 0
[root@Ingenic:bin]# ls /tmp/test.bin -la
-rw-r--r-- 1 root root 3110400 May 31 09:15 /tmp/test.bin

これをmicroSDに入れてバイナリビューアで見てみます。

f:id:honeylab:20200601021637p:plain

 

確かに画像っぽい!

というわけで、どうやら内部コマンドをちょっと突っついてやるとイメージセンサから取得したばっかりの画像が撮れそうです。

しかし、これは"NV12"というYUV形式の画像のため、ちょっと変換してやらないといけません。(内部でmp4のエンコーダに突っ込まれているため。mp4では色空間はRGBではなくYUVなのです(雑に説明))

変換のため、VisualStudioでプログラムを書きます(なんかツールありそうな気がするんだけど…)

f:id:honeylab:20200601023830p:plain

 

すると

……

 

…………

 

おおおおおおおお!画像出た!

1920x1080の綺麗な静止画です。

f:id:honeylab:20200601023712p:plain


あとはこれを何らかのストリーマに食わせてやれば、自力で綺麗な静止画が取得できそうですね。

 

…っていうめんどくさい手順を取らなくていいように、

是非!ONVIF対応を!!!!!!

(それが対応されれば、普通に外部から画が取れるので)