Armadilloフォーラム

guvcviewでFrameRateを上げたい

taroyoshida30

2015年1月29日 10時33分

お世話になります。吉田と申します。

現在、NTSC出力のカメラ(※)の信号を「Armadillo810+ATB-A800NTSC-Kit」で読み込み、
guvcviewでカメラで撮った動画を確認したのですが、遅延が発生しています。

FrameRateを上げたいと考えているのですが、guvcviewで指定出来るのは「11fps」のみでした。

疑問点についてまとめましたので、アドバイスをいただけませんでしょうか。

Q1:カーネルおよびユーザランドのコードを変更することで、
guvcviewから指定できるFrameRateを変更できるようにすることは可能でしょうか。

Q2:以下のボード構成でFrameRateを上げた映像(60fpsなど)を取得することは技術的に可能でしょうか。
- Armadillo-810
- ATB-A800NTSC-Kit

(※):FM10X Micro 700TVL Zoom Camera
http://www.flytron.com/camera-video-equipment/267-fm10x-micro-700tvl-zo…

情報の不足などれあればご指摘お願いします。

■参考

□カーネルおよびユーザーランドイメージ
http://www.advaly.co.jp/work/ATB/A800NTSC/packeage/atb_a800_ntsc_201408…
└ /atb_a800_ntsc_20140804/atb_a800_ntsc/binary/a810/
・linux.bin.gz
・romfs.img.gz

以上

コメント

at_shota.tamura

2015年2月2日 11時36分

田村です。

> Q1:カーネルおよびユーザランドのコードを変更することで、
> guvcviewから指定できるFrameRateを変更できるようにすることは可能でしょうか。

Armadillo のデバイスドライバを変更することで、
guvcview から指定できるフレームレートを変更することが可能です。

しかし、 guvcview を使う場合、 R-Mobile A1 の USB2.0 Function Module
がボトルネックとなってしまうため、 Armadillo のデバイスドライバの変更
を行っても、フレームレートを上げることは出来ません。

このボトルネックについては、以下のスレッドが参考になります。

https://armadillo.atmark-techno.com/forum/armadillo/897

> Q2:以下のボード構成でFrameRateを上げた映像(60fpsなど)を取得することは技術的に可能でしょうか。
> - Armadillo-810
> - ATB-A800NTSC-Kit

ATB-A800NTSC-Kit から Armadillo のRAM上に転送するまでは
NTSC信号のフレームレート(29.97fps)で取り込むことが可能です。

お世話になっております。質問者の吉田です。

>>田村さん
質問への回答ありがとうございます。
大変有益な情報でした。

>>Q1:カーネルおよびユーザランドのコードを変更することで、
>>guvcviewから指定できるFrameRateを変更できるようにすることは可能でしょうか。
>Armadillo のデバイスドライバを変更することで、
>guvcview
>から指定できるフレームレートを変更することが可能です。
>
>しかし、 guvcview を使う場合、 R-Mobile A1 の USB2.0 Function Module
>がボトルネックとなってしまうため、 Armadillo
>のデバイスドライバの変更
>を行っても、フレームレートを上げることは出来ません。
>
>このボトルネックについては、以下のスレッドが参考になります。
>
> https://armadillo.atmark-techno.com/forum/armadillo/897

ご解説ありがとうございます。理解できました。
「USB経由ではデータ転送量がボトルネックになり、結果的にフレームレートを上げることができない」
ということですね。

別のデータ転送経路を検討したいと思います。

>>Q2:以下のボード構成でFrameRateを上げた映像(60fpsなど)を取得することは技術的に可能でしょうか。
>> - Armadillo-810
>> - ATB-A800NTSC-Kit
>ATB-A800NTSC-Kit から Armadillo のRAM上に転送するまでは
>NTSC信号のフレームレート(29.97fps)で取り込むことが可能です。

ご解説&情報ありがとうございます。
ArmadilloまではNTSCのフレームレートを維持したままデータを取り込めるのですね。
実現可能性の部分が不透明であったので、大変助かりました。

上記に対して追加で質問があります。
「ArmadilloのRAM上には転送する」とは具体的にはどのような方法でしょうか。

参考にと教えていただいたスレッドでは、結論は以下であると読み取りました。
- システムコール:select()を使用すると画像データが準備できるのを待つため、十分なフレームレートを得られない

システムコール:select()を使用しないとなると、直接ハードを制御するのではと考えています。
今は以下のようなデータの流れをイメージしています。

(1)NTSCカメラのコンポジット信号 ==> ビデオデコーダ ==> 8bit Y/Cb/Cr

(2)8bit Y/Cb/Cr ==> ATB-A800NTSC-Kit:CN1:ピン50~57 ==> ピン50~57:CON1:Armadillo-810

(3)ピン50~57:CON1:Armadillo-810 ==> DMAコントローラなど ==> Armadillo-810上のRAM

ご意見などいただければ幸いです。

参考までに処理時間を計測した結果を添付いたします。
⇒使用コード:「Armadillo-800 EVAをUVCカメラとして使用する 」のスレッドでsugar_hagiさんが作成した「capturtime_v4l.c」
https://armadillo.atmark-techno.com/forum/armadillo/897

以上、よろしくお願いいたします。

ファイル ファイルの説明
capturv4l_result.txt

at_shota.tamura

2015年2月3日 19時55分

田村です。

> 「ArmadilloのRAM上に転送する」とは具体的にはどのような方法でしょうか。

ATB-A800NTSC-Kit から ArmadilloのRAM上への転送は R-Mobile A1 の CEU が
行なっています。

> (3)ピン50~57:CON1:Armadillo-810 ==> DMAコントローラなど ==> Armadillo-810上のRAM

これに当てはめると

(3) ピン50~57:CON1:Armadillo-810 ==> R-Mobile A1 CEU ==> Armadillo-810上のRAM

のようになります。

> 参考にと教えていただいたスレッドでは、結論は以下であると読み取りました。
> - システムコール:select()を使用すると画像データが準備できるのを待つため、十分なフレームレートを得られない

select() によって、フレームレートが低下することはありません。

select() から正常なディスクリプタが返ってきた時には、
ATB-A800NTSC-kit から Armadillo-810 のRAM上に転送が完了し、画像データ
が読むことが可能であることがわかります。

> 別のデータ転送経路を検討したいと思います。

ATB-A810LAN や 市販のUSB有線LANアダプタ などを使用し、ehternet 経由で
転送することで、NTSC信号のフレームレートのまま、PCなどでカメラからの映
像を確認することも可能です。

ATB-A810LAN : http://armadillo.atmark-techno.com/devices/atb-a810lan

以上です。

お世話になっております。質問者の吉田です。

>>田村さん
早急な質問への回答ありがとうございます。

>> 参考にと教えていただいたスレッドでは、結論は以下であると読み取りました。
>> - システムコール:select()を使用すると画像データが準備できるのを待つため、十分なフレームレートを得られない
>
>select() によって、フレームレートが低下することはありません。
>
>select() から正常なディスクリプタが返ってきた時には、
>ATB-A800NTSC-kit から Armadillo-810 のRAM上に転送が完了し、画像データ
>が読むことが可能であることがわかります。

select()はフレームレートの低下の原因ではないと理解しました。
先の処理時間計測プログラムをselect()のみにして実行してみました。
結果は「0.013ms」であったため、select()はフレームレートの妨げになっていないことが確認できました。

>> 別のデータ転送経路を検討したいと思います。
>
>ATB-A810LAN や 市販のUSB有線LANアダプタ などを使用し、ehternet 経由で
>転送することで、NTSC信号のフレームレートのまま、PCなどでカメラからの映
>像を確認することも可能です。
>
>ATB-A810LAN : http://armadillo.atmark-techno.com/devices/atb-a810lan

現在、手元にATB-A810WLANしかないため、すぐに確認できない状態です。
ATB-A810LANの購入を購入し、Mjpg-Streamerなどで映像を確認をしたいと思います。

後日、結果を報告したいと思います。

以上、色々とありがとうございました。

フォーラムへの結果報告

お世話になっております。質問者の吉田です。

以下の製品を使った結果を報告します。
ATB-A810LAN : http://armadillo.atmark-techno.com/devices/atb-a810lan

結論としては満足したフレームレートで映像を取得できませんでした。

- Mjpg-Streamer(16FPS) > Gstreamer >= guvcview(11FPS)

現在の転送方法で何が足りないかアドバイスいただけないでしょうか。
情報に不足ありましたらご指摘ください。

■構成

NTSCカメラ ==> Almadillo810 ==> ATB-A810LAN ==> Ethernet HUB ==> PC

※AVこーデックミドルウェアは常に有効

■使用したストリーミングソフト
・Mjpg-Streamer
・Gstreamer

■結果
・Mjpg-Streamer
→ guvcviewよりも遅延も少なく、フレームレートも向上した。
→ フレームレートは瞬間的な上振れはあるが、16FPS前後に収まった。
→ 「http://IPアドレス:8080/javascript.html」の「Runtime info:」で確認

・Gstreamer
→ guvcviewよりも若干遅延が少なく感じた。
→ Mjpg-Streamerと違いフレームレート値を出力していないので客観性はない。

■ストリーミング映像の確認方法

□Mjpg-Streamer使用時

◆Armadillo810側
以下のコマンドを実行する。

$>mjpg_streamer -i "/usr/lib/mjpg_streamer/input_uvc.so -f 30 -r 720x480 -d /dev/video0" -o "/usr/lib/mjpg_streamer/output_http.so -w /usr/lib/mjpg_streamer/www -p 8080"

◆PC側
Webブラウザで以下のアドレスを参照する。
http://IPアドレス:8080/javascript.html

□Gstreamer使用時

◆Armadillo810側
ATB-A800NTSC付属の映像配信用の以下のスクリプトを実行する。
/{ATB-A800_src}/atb_a800_ntsc/scripts/server-H264-only.sh

◆PC(windows)側
ATB-A800NTSC付属の映像参照用のスクリプトを変更して実行する。

gst-launch.exe -v gstrtpbin name=gstrtpbin udpsrc caps=application/x-rtp,media=(string)video,clock-rate=(int)90000,encoding-name=(string)H264 port=5000 ! gstrtpbin.recv_rtp_sink_0 gstrtpbin. ! rtph264depay ! ffdec_h264 ! ffmpegcolorspace ! dshowvideosink max-lateness=2000000000 udpsrc port=5001 ! gstrtpbin.recv_rtcp_sink_0 gstrtpbin.send_rtcp_src_0 ! udpsink port=5005 host=IPアドレス sync=false async=false

・avdec_h264 =変更=> ffdec_h264
・videoconvert =変更=> ffmpegcolorspace
・ximagesink =変更=> dshowvideosink

◆PC(linux)側
ATB-A800NTSC付属の映像配信用の以下のスクリプトを実行する。
/{ATB-A800_src}/atb_a800_ntsc/scripts/client-H264-only.sh
→ パイプラインに変更無し。改行などを都合の良いように削除した。

以上、よろしくお願いいたします。

小西と申します。

的外れでしたら、すみません。
こちらでも、mjpeg-streamerを使用したので、参考程度に書き込ませていただきます。

構成
 UVCカメラ(マイクロソフト LifeCam Studio Q2F-00020)-Armadillo840-GbE-Ubuntu(Chrome)

Armadillo内で同様に
mjpeg-streamerを使用しました。

同様に「http://IPアドレス:8080/javascript.html」の「Runtime info:」
にてフレームレートの確認とaction=streamにて目測の残像を見てみました。
注.カメラ性能が違うため、mjpeg_streamerのパラメータで同様の解像度に落として
確認しています。

●パターン1
mjpg_streamer -i "input_uvc.so -f 60 -r 720x480 -d /dev/video0" -o "output_http.so -w /usr/lib/mjpg_streamer/www -p 8080" -b
平均フレームレート:26~30fps

●パターン2
mjpg_streamer -i "input_uvc.so -f 60 -r 720x480 -d /dev/video0 -yuv" -o "output_http.so -w /usr/lib/mjpg_streamer/www -p 8080" -b
平均フレームレート:16~20fps

となりました。
このため、もしかしたらですが、UVCカメラの場合はmjpegで元々取り込んでいるので、
その分、フレームレートがでていますが、NTSC取り込みを行った場合、
mjpeg-streamerのライブラリinput_uvc.so
(plugins/input_uvc/配下のソース)
内でjpeg圧縮されていると思います。
これがCPUを使用しているため、遅くなっているとのことは無いでしょうか?

お世話になっております。質問者の吉田です。

>>小西さん
有益な参考情報、助言ありがとうございます。

こちらにもUSBカメラがあったので比較対象としてフレームレートを確認しました。
結果としては、小西さんにいただいた数値と同じような値でした。
また、CPU使用率についても調べた結果、パターン2ではCPUをフルに使っている状態でした。

そこで以下のようにJPEG圧縮をSHプロセッサに投げることで、問題を解決できるのではと現在考えています。

NTSCカメラ => AVコーデックミドルウェア(a) => Gstreamer(b) => JPEGファイル出力 => Mjpg_Streamer(b)

(a)... SHを使用
(b)... ARMを使用

イメージとしては、以下のような流れです。
1. Gstreamerで30msに一度JPEG画像を所定の位置に保存する。
2. 所定の位置のJPEG画像をMjpg_Streamerで送信する。
→ 入力プラグインを「input_file.so」にする。

--------以下、USBカメラのFPS測定のまとめ--------

■USBカメラを使用した場合のフレームレート
任意のタイミングで止めて「Runtime info:」のFPSの値を確認した。

●パターン1

mjpg_streamer -i "input_uvc.so -f 60 -r 640x480 -d /dev/video0" -o "output_http.so -w /usr/lib/mjpg_streamer/www -p 8080"

→ 7回測定:平均28.23、中央値27.78fps

●パターン2

mjpg_streamer -i "input_uvc.so -f 60 -r 640x480 -d /dev/video0 -yuv" -o "output_http.so -w /usr/lib/mjpg_streamer/www -p 8080"

→ 7回測定:平均17.95、中央値17.86fps

※画面サイズを「640x480」に変更しています。

■使用したUSBカメラ

・Webカメラ:UCAM-DLI500TBK
http://www2.elecom.co.jp/multimedia/pc-camera/ucam-dli500t/

■考察
・USBカメラを使用した場合のFPSはほぼ同じであることがわかった。
従って、USBカメラのスペックの差ではないことがわかった。
・同じデバイスでもフォーマットが違うとFPSに大きな違いがあることがわかった。
- パターン1 : MJPEG
- パターン2 : YUV

>このため、もしかしたらですが、UVCカメラの場合はmjpegで元々取り込んでいるので、
>その分、フレームレートがでていますが、NTSC取り込みを行った場合、
>mjpeg-streamerのライブラリinput_uvc.so
>(plugins/input_uvc/配下のソース)
>内でjpeg圧縮されていると思います。
>これがCPUを使用しているため、遅くなっているとのことは無いでしょうか?

CPU使用率を調べてみた所、明らかに「パターン2」の場合の方がCPU使用率が高くなっていました。
小西さんのご助言のCPUのリソース不足のために遅くなっているのでは、に私も同意見です。

□CPU使用率の測定方法と結果

◆測定方法
Mjpg_Streamerをバックグラウンドで動かしながら、「top」コマンドを実行

◆測定結果
・パターン1:平均0.91%、 中央値0.60%
・パターン2:平均93.97%、中央値94.00%

以上

吉田様
kensakuと申します。

> 1. Gstreamerで30msに一度JPEG画像を所定の位置に保存する。
> 2. 所定の位置のJPEG画像をMjpg_Streamerで送信する。
> → 入力プラグインを「input_file.so」にする。

本件、私が半年前に試作した内容とほぼ同じような事をされている様なので情報を展開します。
※アットマークさんとメールでやり取りしてましたので本フォーラムにはのっていません

まず、
>そこで以下のようにJPEG圧縮をSHプロセッサに投げることで、問題を解決できるのではと現在考えています。
ですが、このSH-4AのJPEGエンコードには下記の動作制約があります。

①SH-4A JPEGエンコードの入力画像形式がNV12(YUV420)限定
 ⇒カメラ入力がYUV422やI420の場合はGstのpipeline(videoconvert)でARM上でNV12へ変換が必要
  下記はI420のYUVをSH-4Aでエンコードする為のコマンド例
gst-launch-1.0 -e v4l2src device=/dev/video0 ! video/x-raw,format=I420,width=640,height=480,framerate=30/1 ! videoconvert! video/x-raw,format=NV12 ! acmjpegenc ! qtmux ! multifilesink location=/run/shm/output%d.jpeg
  データの配列変換のみとはいえ、ミリレベルで処理時間を喰います。

②ARM側とSH-4Aが同時に動けない制約があり、ARM側のアプリケーション(MjpegStreamer)でリアルタイムにMJPEG画像を送信出来ない。
 ※すみません、この部分は秘匿情報の可能性があるため、少し抽象的にしました。
   問題がなければアットマークさん側でフォロー下さい。
 ⇒結果的にはMjpegStreamerのWebクライアントで見ると約30FPS程度の時と約2程度FPSの時が交互に出現し、フレーム飛びが発生する。
  キャッシュに溜めとく等の試作をすれば対策出来る可能性があるが、「リアルタイム」では無くなってしまう

以上より、こちらでは、SH-4Aを使わないようにした経緯があります。
MjpegStreamerのJPEGエンコードより、Gstのソフトエンコードの方が処理速度が早いです。
よって、GstでARM上でエンコードしたものをMjpegStreamerのinput_fileを使われる事をお勧めします。

また、下記2点の対応をされる事をお勧めします。

①libjpeg-turboを入れる(NEON最適化)
 ⇒これだけで速度は変わります
②input_fileのファイルチェック処理(inotify_add_watch)のパラメータ指定を変える。
 ⇒Gstの作りの問題で出力先に仮ファイルが生成される為、inotify_add_watchのチェックにひっかかってしまいます。
   IN_CLOSE_WRITEかIN_MOVED_TOのみにしてあげる事で仮ファイルをチェック対象から外す事が出来ます。

すみません、殴り書きで日本語がへたくそでした。
>MjpegStreamerのJPEGエンコードより、Gstのソフトエンコードの方が処理速度が早いです。
>よって、GstでARM上でエンコードしたものをMjpegStreamerのinput_fileを使われる事をお勧めします。

MjpegStreamerのJPEGエンコードより、GstのJPEGエンコードの方が処理速度が早いです。
よって、GstでARM上でエンコードしたものをMjpegStreamerのinput_fileで実施する事をお勧めします。

です。

./mjpg_streamer -i "./input_file.so -f /run/shm" -o "./output_http.so -w ./www -p 8081"
でファイル格納待機待ちしながら
gst-launch-1.0 -e v4l2src device=/dev/video0 ! video/x-raw,format=I420,width=640,height=480,framerate=30/1 ! jpegenc ! qtmux ! multifilesink location=/run/shm/output%d.jpeg
でカメラから撮ったYUV画像を連続JPEGファイルで格納していく。
(formatはカメラのYUV入力フォーマットで適時変更下さい)

この操作(後は前回書き込みした①と②の対応をFIX)により、VGAであればYUV画像でも約30FPSをキープしてストリーム表示出来る所までは確認しました。
お試しくださいませ。

お世話になっております。質問者の吉田です。

>>kensaku様
お礼の返信が大変遅れてしまい申し訳ありません。
有益な情報ありがとうございました。
まさにこちらで実現したいことそのままだと思います。

現在、別案件によりこちらに手が付けられていない状態です。
後ほど試した結果をご報告したいと思います。

以上