Debian/Linuxで複数のUSBウェブカメラを実行すると、次のエラーが発生します。
libv4l2: error turning on stream: No space left on device
VIDIOC_STREAMON: No space left on device
最初にOpenCVのプログラミングの問題のように見えたものは、チーズとxawtvを実行して同じエラーが発生した後、謎のハードウェア/ソフトウェアの問題の探求に変わりました。
どうやらそれは、USBホストコントローラーで利用可能なすべての帯域幅を要求するWebカメラが原因です。それを念頭に置いて、wiresharkとcapinfosを実行して、 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メガビットをサポートするデバイスに属している両方のWebカメラを表示します。
次のコマンドを実行して最大値を要求するのではなく、帯域幅の使用量を計算することをWebカメラに強制する1つのソリューションが提案されました。
Sudo rmmod uvcvideo
Sudo modprobe uvcvideo quirks=128
残念ながら、それでも違いはなかったので、別の解決策を試すことにしました。投稿 on StackOverflow は、WebカメラにMJPEGなどの低いFPSまたは圧縮ビデオ形式を使用するように指示することを提案しましたが、v4lctl listを実行した後どちらのWebカメラもビデオモードの変更をサポートしていないようです。
そして、それは私が行き詰まっているところです。 USB 2の最大速度を大幅に下回る2つのWebカメラでこのエラーが発生するのはなぜですか?
ps:これはディスク容量の問題ではありません。dfは、ウェブカメラの起動時に変更を表示しません。
pps:違いがある場合は、ここに lsusbの出力を示します。
ディンディン! freenodeの#v4lにいる素敵な人々の助けを借りて、この問題を理解することができました。
短い話:v4l2-ctlは、USBカメラの問題をデバッグするための最良のツールです。利用可能なすべてのコマンドとマニュアルページを読んでください。約束するのは楽しいでしょう。 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以下の解像度で満足している場合を除きます。*
答えは、SwDevRefugeeによって記述され、上記で説明したuvcvideoの変更を使用することです。彼と私は協力して、修正されたコードをOpenWrt用にコンパイルし、成功しました。私がそれを実行しているバージョンは、tplink wdr3600ルーター上のOpenWRT DESIGNATED DRIVER(Bleeding Edge、r48130)です。
結果:USB 2.0ハブを介して、MJPG形式で1280x960と15fpsで同時に3 * c270(logitech)を実行できます。接続する4番目のc270がありません。申し訳ありません。
2 * c270と1 * GEMBIRD 640 * 480 * 15fpsをYUV形式で使用することもできますが、2つ目のGEMBIRDを追加すると、「キャプチャを開始できません:デバイスに空き領域がありません」(space ==ここでは帯域幅)よく知っています:))。 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に組み込む用意があると思います。
Uvcvideoドライバーを確認しましたが、ストリームがmjpeg圧縮されている場合、quirks = 128モジュールパラメーターは無視されます。
私が選んだウェブカメラはLogitech C500とLogitech C270で、C500が1280x1024で生成した画像は100kバイトで、C270が1280x960で生成した画像は200kバイトであることがわかりました。
C270を10fpsで実行する場合、必要なビットレートは10x200000x8 = 16Mbit/sです。 Ubuntu 14.04では、フレームレートに関係なく、uvcdriverモジュールは常に196Mビット/秒を割り当てます。 C500の場合、動作は少し良くなりますが、帯域幅を独占します。
V4L2インターフェイスを介してドライバーに「圧縮」係数を提供できるように、uvcvideoドライバーを変更しました。値を指定するためにstruct v4l2_pix_formatのpriv属性を使用したという点で、これは「少しハック」です。ドライバーでは、非圧縮イメージのサイズを計算し、圧縮係数で除算して、使用するUSB帯域幅を計算します。
デフォルトでは、10の圧縮係数を使用します。これにより、圧縮するのが特に難しい画像にカメラが遭遇した場合でも、大きなマージンが得られます。 1280x960、10fpsで動作するC270は41Mbit/sを使用し、1つのバスで4台のカメラを簡単に実行できます。
誰かがこの機能に興味を持っているなら、私はuvcvideoメンテナに「圧縮」要素の概念を検討してもらうように試みます。