Linux で複数の USB ウェブカメラを使用する

Linux で複数の USB ウェブカメラを使用する

Debian/Linux で複数の USB ウェブカメラを実行すると、次のエラーが発生します。

libv4l2: error turning on stream: No space left on device
VIDIOC_STREAMON: No space left on device

当初は OpenCV のプログラミングの問題と思われていましたが、cheese と xawtv を実行しても同じエラーが発生したため、謎のハードウェア/ソフトウェアの問題を調査するようになりました。

どうやらこれは、ウェブカメラがUSBホストコントローラの利用可能な帯域幅をすべて要求していることが原因であるようです。それを念頭に置いて、私は実行することにしました。ワイヤーシャークそしてキャップ情報1 台のカメラがどれだけの帯域幅を使用したかを確認します。

4 megabits per second at 320x240
14 megabits per second at 640x480
32 megabits per second at 1280x720

面白いですね!320x240のカメラ2台は機能するのに、それ以上の解像度では機能しないのは、これで説明がつくかもしれません。私のUSBコントローラーはUSB 1の速度でしか動作していないようですが、lsusb は両方のウェブカメラが、480 メガビット/秒をサポートすると思われるデバイスに属していることがわかります。

1 つの解決策として、次のコマンドを実行して、最大値を要求するのではなく、Web カメラに帯域幅の使用量を計算するように強制することが提案されました。

sudo rmmod uvcvideo
sudo modprobe uvcvideo quirks=128

残念ながら、それは何も変わらなかったため、別の解決策を試すことにしました。投稿StackOverflowでウェブカメラに低FPSやMJPEGのような圧縮ビデオ形式を使用するように指示しましたが、v4lctl リスト私のウェブカメラはどちらもビデオモードの変更をサポートしていないようです。

そこで行き詰まっています。USB 2 の最大速度を大幅に下回る速度で動作する 2 台の Web カメラで、なぜこのエラーが発生するのでしょうか?

ps: これはディスク容量の問題ではありません。Web カメラを起動しても df には変化は表示されません。

pps: 違いがあるなら、ここにlsusbの出力

答え1

ディンディン!freenode の #v4l の親切な人たちの助けを借りて、なんとかこの問題を解決することができました。

簡単に言うと:v4l2-ctlUSBカメラの問題をデバッグするのに最適なツールです。利用可能なコマンドとマニュアルページをすべて読んでみてください。きっと楽しいと思います。v4l2-ctl私のカメラの 1 台が圧縮ビデオ モードをサポートしていないことがわかりました。次のコマンドを実行すると、カメラがサポートするモードを確認できます。

v4l2-ctl -d /dev/video0 --list-formats

次のような出力が得られるはずです。

 ioctl: VIDIOC_ENUM_FMT
 Index       : 0
 Type        : Video Capture
 Pixel Format: 'MJPG' (compressed)
 Name        : MJPEG

 Index       : 1
 Type        : Video Capture
 Pixel Format: 'YUYV'
 Name        : YUV 4:2:2 (YUYV)

返されるピクセル形式が「YUYV」、「IUYV」、「I420」、または「GBRG」のみの場合、これらの形式は圧縮されていないため、USB コントローラーごとに 1 台のカメラしか実行できません。MJPEG またはその他の形式の圧縮をサポートする複数の Web カメラを使用すると、問題なく動作します。

私のように OpenCV を使用している場合、デフォルトのピクセル形式が圧縮されていなくても心配する必要はありません。OpenCV はデフォルトで圧縮を使用するようです。

**320x240 以下の解像度で満足できる場合を除きます。*

答え2

答えは、SwDevRefugee が書いた、上で説明した uvcvideo の変更を使用することです。彼と私は、OpenWrt 用にコンパイルされた改造コードの作成に協力し、成功しました。私が実行しているバージョンは、tplink wdr3600 ルーター上の OpenWRT DESIGNATED DRIVER (Bleeding Edge、r48130) です。

結果: USB 2.0 ハブを介して、3 台の c270 (logitech) を 1280x960、15fps、MJPG 形式で同時に実行できます。接続できる 4 台目の c270 はありません。申し訳ありません。

2*c270 と 1*GEMBIRD 640*480*15fps の YUV フォーマットも使用できますが、2 つ目の GEMBIRD を追加すると、恐ろしい「キャプチャを開始できません: デバイスに空き容量がありません」というエラーが発生します (ご存知のとおり、ここでは空き容量 = 帯域幅です:))。GEMBIRD (1908:2311) == に注意してください。http://www.penguin.cz/~utx/hardware/USB_Camera_AX2311/

3*c270 の CPU 使用率は wdr3600 でかなり妥当です。

Mem: 50600K used, 75444K free, 320K shrd, 3436K buff, 8800K cached

CPU:  16% usr  27% sys   0% nic  45% idle   0% io   0% irq  10% sirq

Load average: 1.20 0.85 0.44 4/60 2546

  PID  PPID USER     STAT   VSZ %VSZ %CPU COMMAND

 2240  1679 root     S    15348  12%  17% mjpg_streamer --input input_uvc.so --

 2505  1679 root     S    15368  12%  11% mjpg_streamer --input input_uvc.so --

 2239  1679 root     S    15532  12%  11% mjpg_streamer --input input_uvc.so --

コミュニティが一定の評価とサポートを与えれば、SwDevRefugee はコードを uvc-linux に取り入れる用意があると思います。

答え3

uvcvideo ドライバーを調べたところ、ストリームが mjpeg 圧縮されている場合、quirks=128 モジュール パラメーターは無視されます。

私が選んだウェブカメラは Logitech C500 と Logitech C270 ですが、C500 で 1280x1024 で生成された画像は 100k バイトで、C270 で 1280x960 で生成された画像は 200k バイトであることがわかりました。

C270 を 10fps で実行する場合、必要なビットレートは 10x200000x8 = 16Mbit/s です。Ubuntu 14.04 では、uvcdriver モジュールはフレーム レートに関係なく常に 196Mbit/s を割り当てます。C500 の場合、動作は少し改善されていますが、それでも帯域幅を大量に消費します。

私は、uvcvideo ドライバーを変更して、V4L2 インターフェイスを通じてドライバーに「圧縮」係数を提供できるようにしました。これは、struct v4l2_pix_format の priv 属性を使用して値を指定するという点で、「少しハック」です。ドライバーでは、圧縮されていない画像のサイズを計算し、それを圧縮係数で割って、使用する USB 帯域幅を算出します。

デフォルトでは、圧縮係数 10 を使用します。これにより、カメラが圧縮するのが特に難しい画像に遭遇した場合に備えて、大きな余裕が生まれます。1280x960 および 10fps で動作する C270 は現在 41Mbit/s を使用し、1 つのバスで 4 台のカメラを簡単に実行できます。

この機能に興味がある方がいらっしゃいましたら、uvcvideo のメンテナーに「圧縮」係数の概念を考慮するよう依頼します。

答え4

私も容量不足のエラーに遭遇しました。カメラの 1 つを取り外し、固定 PC の別の USB ポートに接続するとうまくいきました。固定 PC には USB ポートが 6 つか 7 つあります。「show_webcams 0 1」を実行すると、突然 2 つの画像が表示されました。

関連情報