在 Debian/Linux 中运行多个 USB 网络摄像头会导致以下错误:
libv4l2: error turning on stream: No space left on device
VIDIOC_STREAMON: No space left on device
最初看似是 OpenCV 中的编程问题,但在运行 cheese 和 xawtv 时出现相同错误后,就变成了神秘的硬件/软件问题。
显然这是由于网络摄像头请求 USB 主控制器上的所有可用带宽造成的。考虑到这一点,我决定运行wireshark和首都信息网查看单个摄像头使用了多少带宽。
4 megabits per second at 320x240
14 megabits per second at 640x480
32 megabits per second at 1280x720
有趣!这也许可以解释为什么两个 320x240 的摄像头可以工作,但任何更高分辨率的摄像头都无法工作。就好像我的 USB 控制器只能以 USB 1 的速度运行,但系统盘显示两个网络摄像头都属于一个据称支持每秒 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 集线器让 3 个 c270 (logitech) 同时以 1280x960 和 15fps 的 MJPG 格式运行。抱歉,我没有第四个 c270 可以连接。
我也可以拥有 2*c270 和 1*GEMBIRD 640*480*15fps 的 YUV 格式,但添加第二个 GEMBIRD 会导致可怕的“无法开始捕获:设备上没有剩余空间”(这里的空间==带宽,您也知道:))。请注意,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
我也遇到了空间不足的错误。有效的方法是拔下其中一个摄像头并将其插入我的固定 PC 上的另一个 USB 端口 - 那里散布着大约 6 或 7 个 USB 端口。运行“show_webcams 0 1”后,突然出现了两个图像。