最近更新: 2013-07-09

libv4l2 error turning on stream~ No space left on device

當開啟兩隻以上的 USB Video Camera (WebCam) 時,有時會發生 "No space left on device" 的錯誤。

使用 guvcview 即可再現錯誤情境。步驟如下:

  1. 準備兩隻 WebCam 。
  2. 執行 guvcview -d /dev/video0 -f yuyv -s 1280x720 。開啟一隻 WebCam ,保持執行狀態。
  3. 接著執行 guvcview -d /dev/video1 -f yuyv -s 1280x720 。開啟第二隻 WebCam 。
  4. 此時第二個執行的 guvcview 不會顯示影像。而終端機上會印出下列錯誤訊息:
libv4l2: error turning on stream: 裝置上已無多餘空間
VIDIOC_STREAMON - Unable to start capture: 裝置上已無多餘空間
libv4l2: error turning on stream: 裝置或系統資源忙碌中
VIDIOC_STREAMON - Unable to start capture: 裝置或系統資源忙碌中

libv4l2: error turning on stream: No space left on device
VIDIOC_STREAMON - Unable to start capture: No space left on device
libv4l2: error turning on stream: Device or resource busy
VIDIOC_STREAMON - Unable to start capture: Device or resource busy

「無多餘空間」並不是指磁碟與記憶體沒有空間,而是 USB 的資料頻寬。 關於 WebCam 影像傳輸所需的資料頻寬可參考下列文章。

Apparently it's caused by webcams requesting all the available bandwidth on the USB host controller. With that in mind I decided to run wireshark and capinfos to see just how much bandwidth a single camera used.

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

Interesting! That might explain why two cameras at 320x240 work but any higher resolution fails.

at Using multiple USB webcams in Linux

愈大的影像解析度,就要求更多的資料傳輸速率。 故當我要開啟第二隻 WebCam 時, USB 沒有足夠的資料頻寬傳輸資料,就發生 No space left on device 的錯誤了。

Most likely there is USB bandwidth contention reported by the driver of the video capture device. Check if the pixel format is YUYV, which happens to be uncompressed. On the contrary, if the pixel format is MJPG (compressed), it is possible to have multiple devices on the same USB channel.

at Capturing multiple webcams (uvcvideo) with OpenCV on Linux

故解決方案是降低 WebCam 的資料傳輸速率。可控制的項目有三:

  • 要求 WebCam 使用壓縮過的像素格式 (compressed pixel format) 。
    大多數的 WebCam 會同時支援兩種像素格式,即 YUYV 和 MJPG 。YUYV 是 lossless (無折損) 格式,MJPG 則是 lossy-compressed (折損壓縮)格式。YUYV 的資料傳輸速率比 MJPG 更大。故選擇 MJPG 格式以避免 USB 資料頻寬不足。
    至於 MJPG 影像內容的折損程度,視 WebCam 內建的演算模組而定,需要從肉眼或其他圖學計算工具評估。
  • 選擇較低的影像解析度,例如 640x480 。較小的解析度使用較低的資料傳輸速率,但也會縮小影像可視面積。
  • 選擇較低的 fps 。其法對資料傳輸速度的降低幅度有限,且畫面效果于人遲頓感。

下列指令可以查看 WebCam 提供的像素格式 (pixel format):

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

實驗。重複開頭所提的4步驟,但 guvcview 執行參數改用 -f MJPG ,指定使用 MJPG 格式。

$ guvcview -d /dev/video0 -f MJPG -s 1280x720
$ guvcview -d /dev/video1 -f MJPG -s 1280x720

此時通常可以同時開啟兩隻 WebCam 。如果還是不行,那就要調低解析度。

樂多舊網址: http://blog.roodo.com/rocksaying/archives/25359530.html

樂多舊回應
edt1023@gmail.com(qtnez) (#comment-24325488)
Mon, 10 Mar 2014 10:30:46 +0800
> guvcview 執行參數改用 -f MJPG

這樣似乎是指 rawvideo -> mjpeg 的意義?嘗試去改裡頭的格式:

v4l2-ctl -v pixelformat='MJPG'

從 v4l2-ctl -V 來看,是修改成功了。

root[~]# v4l2-ctl -V
Format Video Capture:
Width/Height : 640/480
Pixel Format : 'MJPG'
Field : None
Bytes per Line: 0
Size Image : 921600
Colorspace : SRGB


但是只要去錄影或看鏡頭,就又自動改回 YUYV。是我哪裡搞錯了嗎?
未留名 (#comment-24325848)
Mon, 10 Mar 2014 13:30:32 +0800
注意,v4l2-ctl 改變的狀態,一樣是暫時的,會被後來的程式改變。當電腦重開或 webcam 拔插之後,也會重置。

你應該去設定你的錄影程式或播放程式的參數。
因為它們可能會根據自己的設定內容,改回 YUYV 格式。
例如本文就是用 guvcview -f MJPG 要求 guvcview 在播放/錄影時使用 MJPG 格式。

guvcview 本身不會做 rawvideo 轉 mjpg 的工作。加上 -f MJPG 的結果,和 v4l2-ctl 的動作是一樣的,都是對 webcam 下指令。

edt1023@gmail.com(qtnez) (#comment-24327076)
Mon, 10 Mar 2014 22:29:26 +0800
謝謝回應!

因為這些東西我不太懂,所以可能理解得不是很明白。以下是我執行時的情形:

qtnez:~$ guvcview -d /dev/video-cam1 -f MJPG -s 640x480
[...]
Init. Webcam C170 (location: usb-0000:00:1d.7-2)
{ pixelformat = 'YUYV', description = 'YUV 4:2:2 (YUYV)' }
[...]

是不是說傳輸的還是 YUYV,只是 guvcview 接收後才轉碼的(libv4lconvert ?)?

不過也可能我這個簡單的視訊頭,guvcview 沒辦法驅動它改用 mjpg 格式(確定這個視訊頭有支援 mjpg)?