Using multiple USB webcams in Linux

31

16

Running more than one USB webcam in Debian/Linux results in the the following error:

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

What initially seemed to be a programming issue in OpenCV turned into a quest for a mysterious hardware/software problem after the same errors were produced by running cheese and xawtv.

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. It's as if my USB controller is only operating at USB 1 speeds, yet lsusb shows both webcams belonging to a device which supposedly supports 480 megabits per second.

One solution proposed forcing the webcams to calculate their bandwidth usage instead of requesting their maximum by running the following commands:

sudo rmmod uvcvideo
sudo modprobe uvcvideo quirks=128

Unfortunately that made no difference, so I decided to try another solution. A post on StackOverflow suggested telling my webcams to use a lower FPS or compressed video format like MJPEG, but after running v4lctl list it doesn't appear either of my webcams support changing their video mode.

And that's where I'm stuck. Why would two webcams operating well below the maximum speed of USB 2 would produce this error?

ps: It's not a disk space issue, df displays no change when the webcams are started.

pps: If it makes a difference, here's the output of lsusb

rachelderp

Posted 2012-06-02T09:09:04.627

Reputation: 681

Answers

25

Ding ding! Managed to figure this one out with some help from the nice people in #v4l on freenode.

Long story short: v4l2-ctl is the best tool for debugging USB camera issues. Read all the available commands and the man page, it'll be fun I promise. Using v4l2-ctl I discovered one of my cameras did not support any compressed video modes. You can check what modes your cameras support by running the following command:

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

Which should output something like this.

 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)

If the only pixel format returned is "YUYV", "IUYV", "I420", or "GBRG" you'll only be able to run one camera per USB controller* since those formats are uncompressed. Using multiple webcams which support MJPEG or some other form of compression will work fine.

If you use OpenCV like me, don't worry if the default pixel format isn't compressed as it appears OpenCV defaults to using compression anyway.

**Unless you're happy with 320x240 resolution or lower.*

rachelderp

Posted 2012-06-02T09:09:04.627

Reputation: 681

When using resolutions of 320x240 or lower, I get mixed results. I bought 4 cheap USB webcams, all of the same make/model. When trying to run 2 at 160x120, some of them would work fine together and some gave the memory error. I see no rhyme or reason to it. Granted, these webcams cost $3/each, so I guess I got what I paid for. – Cerin – 2015-04-17T13:54:48.553

Connecting two or more of those cameras to USB3.0 works fine, even through a USB2.0 hub. Checked with YUYV. – Michał Leon – 2016-12-01T23:09:38.437

1Hi, if possible, can you tell me how I should set the pixel format of 2 cameras so that I can capture both at 640x480? I am using OpenCV and currently experiencing the same situation like you have where both cameras will only work at 320x240 or lower – lexma – 2012-12-04T21:30:01.283

Aha! v4l2-ctl is indeed an excellent tool for debugging. Found out a lot about my camera, and was able to fix the issue. Anyways, I was able to fix it by forcing my camera's resolution to 320x240 and using YUYV as the camera output mode. guvcview also helped a lot. – Sheharyar – 2014-03-22T20:48:36.403

8

The answer is to use the uvcvideo modifications written by SwDevRefugee, and described above. He and I have worked together to get the mod'ed code compiled for OpenWrt, with success. The version I am running it on is OpenWRT DESIGNATED DRIVER (Bleeding Edge, r48130), on a tplink wdr3600 router:

RESULT: I can have 3*c270 (logitech) running simulataneously at 1280x960 and 15fps in MJPG format, through a usb 2.0 hub. I do not have a fourth c270 to hook up, sorry.

I can also have 2*c270 and 1*GEMBIRD 640*480*15fps with YUV format, but adding a 2nd GEMBIRD leads to the dreaded "Unable to start capture: No space left on device" (space==bandwidth here, as you know well:)). Note that GEMBIRD (1908:2311) == http://www.penguin.cz/~utx/hardware/USB_Camera_AX2311/ .

CPU usage with 3*c270 is fairly reasonable on a 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 --

If the community gives some reputation and support, I think SwDevRefugee is willing to get the code into uvc-linux.

reikred

Posted 2012-06-02T09:09:04.627

Reputation: 253

4

I looked at the uvcvideo driver and the quirks=128 module parameter is ignored if the stream is mjpeg compressed.

My webcams of choice have been the Logitech C500 and the Logitech C270, and I found that the image produced by the C500 at 1280x1024 is 100kbytes and the image produced by the C270 at 1280x960 is 200kbytes.

If I run the C270 at 10fps then the bitrate required is 10x200000x8 = 16Mbit/s. In Ubuntu 14.04 the uvcdriver module always allocates 196Mbits/s regardless of the frame rate. For the C500 it is a little better behaved, but is still a bandwidth hog.

I have modified the uvcvideo driver so that I can provide a "compression" factor to the driver through the V4L2 interface. It is a "little hacky" in that I used the priv attribute in the struct v4l2_pix_format to specify the value. In the driver it calculates the size of the uncompressed image and then divides by the compression factor to work out what USB bandwidth to use.

By default I use a compression factor of 10 which allows a large margin for if the camera encounters a particularly hard image to compress. The C270 running at 1280x960 and 10fps now uses 41Mbit/s and I can easily run 4 cameras on one bus.

If anyone is interested in this feature then I will attempt to get the uvcvideo maintainers to consider the "compression" factor concept.

SwDevAlien

Posted 2012-06-02T09:09:04.627

Reputation: 49

I, and potentially others in the OpenROV community would be keen to see your mod to the uvc driver @SwDevRefugee. I'm working on trying to integrate two webcams into the OpenROV (one for downward looking visual odometry, the other for normal piloting/viewing), but running into the same BW issue. Have you thought about posting your mod / or submitting a pull request for your change?

– None – 2016-04-15T13:21:43.737

The official way to request changes to the uvc driver is via this mailing list: linux-uvc-devel@lists.sourceforge.net. I posted my change request on 30-Dec-2015 along with some other subsequent posts with further information. I have had no response from a maintainer. Two other people have expressed an interest in the change. I don't know how many are required to get any action. Perhaps @laughlinb could post to the mailing list as well. – SwDevAlien – 2016-05-10T03:59:54.400

@SwDevRefugee : I would like your advice http://unix.stackexchange.com/q/287279/52764

– Ragav – 2016-06-02T19:47:01.030

@Ragav: I think you need to isolate the problem by opening all the cameras simultaneously at the appropriate resolutions using a well behaved application like luvcview which should give you informative error messages if there is a failure. – SwDevAlien – 2016-06-10T03:11:26.427

@SwDevRefugee can you point me to your edited uvc video source.let me try using that driver – Ragav – 2016-06-11T10:31:21.077

1Ragav's problem is that his cameras only support YUYV and when he uses the quirks=0x80 flag the driver forces him to use at least 1024 bytes/microframe (65.5 Mbit/s) per camera. This is compounded by the fact that the lowest greater bandwidth that the cameras support is 2040 bytes/microframe so even though he only wants 320x240 at 6fps he can only have 2 cameras on one USB bus. The minimum of 1024 bytes/microframe restriction was added to the uvcvideo driver somewhere between the 2.6.32 and 3.16 releases of the kernel. – SwDevAlien – 2016-08-19T03:09:15.230

-1

I got that out of space error too. What worked was to unplug one of the cameras and plug it into another USB port on my stationary PC - there are some 6 or 7 USB ports scattered about it. Running 'show_webcams 0 1' then suddenly brought up the two images.

Peter Thejll

Posted 2012-06-02T09:09:04.627

Reputation: 1