在 Debian/Linux 中運行多個 USB 網路攝影機會導致以下錯誤:
libv4l2: error turning on stream: No space left on device
VIDIOC_STREAMON: No space left on device
在運行 Cheese 和 xawtv 產生相同的錯誤後,最初看似 OpenCV 中的程式設計問題變成了對神秘硬體/軟體問題的探索。
顯然,這是由網路攝影機請求 USB 主控制器上的所有可用頻寬引起的。考慮到這一點,我決定跑步線鯊和卡普資訊系統查看單一攝影機使用了多少頻寬。
4 megabits per second at 320x240
14 megabits per second at 640x480
32 megabits per second at 1280x720
有趣的!這或許可以解釋為什麼兩個 320x240 的攝影機可以工作,但任何更高解析度的攝影機都會失敗。就好像我的 USB 控制器僅以 USB 1 速度運行,但是LSSB顯示了屬於據稱支援每秒 480 兆位元的裝置的兩個網路攝影機。
一種解決方案建議強製網路攝影機計算其頻寬使用情況,而不是透過執行以下命令來請求其最大值:
sudo rmmod uvcvideo
sudo modprobe uvcvideo quirks=128
不幸的是,這沒有什麼區別,所以我決定嘗試另一種解決方案。一個貼文在 StackOverflow 上建議告訴我的網路攝影機使用較低的 FPS 或壓縮視訊格式(如 MJPEG),但運行後v4lctl列表我的兩個網路攝影機似乎都不支援更改視訊模式。
這就是我被困的地方。為什麼兩個網路攝影機在遠低於 USB 2 最大速度的情況下運作會產生此錯誤?
ps:這不是磁碟空間問題,啟動網路攝影機時 df 顯示沒有任何變化。
pps:如果有什麼不同,這裡是lsusb 的輸出
答案1
丁丁!在 freenode 上 #v4l 中的好人的幫助下,我設法解決了這個問題。
長話短說:v4l2-ctl是調試 USB 攝影機問題的最佳工具。閱讀所有可用的命令和手冊頁,我保證這會很有趣。使用v4l2-ctl我發現我的一台相機不支援任何壓縮視訊模式。您可以透過執行以下命令來檢查您的相機支援哪些模式:
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 控制器* 只能運行一台相機,因為這些格式未壓縮。使用支援 MJPEG 或某種其他形式的壓縮的多個網路攝影機就可以正常工作。
如果您像我一樣使用 OpenCV,請不要擔心預設像素格式是否未壓縮,因為 OpenCV 似乎預設使用壓縮。
**除非您對 320x240 或更低的解析度感到滿意。
答案2
答案是使用 SwDevRefugee 編寫的 uvcvideo 修改,如上所述。他和我共同努力為 OpenWrt 編譯了修改後的程式碼,並取得了成功。我運行的版本是 OpenWRT DESIGNATED DRIVER (Bleeding Edge, r48130),在 tplink wdr3600 路由器上:
結果:我可以透過 USB 2.0 集線器以 1280x960 和 15fps 以 MJPG 格式同時運行 3*c270 (logitech)。抱歉,我沒有第四個 c270 可以連線。
我還可以使用YUV 格式擁有2*c270 和1*GEMBIRD 640*480*15fps,但是添加第二個GMBIRD 會導致可怕的“無法開始捕獲:設備上沒有剩餘空間”(此處的空間==頻寬,如您所示)熟悉:))。請注意,GEMBIRD (1908:2311) ==http://www.penguin.cz/~utx/hardware/USB_Camera_AX2311/。
在 wdr3600 上,3*c270 的 CPU 使用率相當合理:
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 下產生的影像為 100kbytes,而 C270 在 1280x960 下產生的影像為 200kbytes。
如果我以 10fps 運行 C270,則所需的位元率為 10x200000x8 = 16Mbit/s。在 Ubuntu 14.04 中,uvcdriver 模組始終分配 196Mbits/s,無論幀速率如何。對於 C500 來說,它的表現要好一些,但仍然佔用頻寬。
我修改了uvcvideo驅動程序,以便可以透過V4L2介面向驅動程式提供「壓縮」因子。這是一個“小黑客”,因為我使用 struct v4l2_pix_format 中的 priv 屬性來指定值。在驅動程式中,它會計算未壓縮影像的大小,然後除以壓縮係數以計算要使用的 USB 頻寬。
預設情況下,我使用的壓縮係數為 10,如果相機遇到特別難壓縮的影像,則可以留出很大的餘裕。以 1280x960 和 10fps 運行的 C270 現在使用 41Mbit/s,我可以輕鬆地在一輛總線上運行 4 個攝影機。
如果有人對此功能感興趣,那麼我將嘗試讓 uvcvideo 維護者考慮「壓縮」因子概念。
答案4
我也遇到了空間不足的錯誤。有效的方法是拔下其中一台相機並將其插入我的固定電腦上的另一個 USB 連接埠 - 它周圍散佈著 6 或 7 個 USB 連接埠。執行“show_webcams 0 1”然後突然顯示這兩個圖像。