Использование нескольких веб-камер USB в Linux
Запуск более одной веб-камеры USB в Debian/Linux приводит к следующей ошибке:
libv4l2: error turning on stream: No space left on device
VIDIOC_STREAMON: No space left on device
То, что изначально казалось проблемой программирования в OpenCV, превратилось в поиск загадочной проблемы с аппаратным и программным обеспечением после того, как те же ошибки возникли при запуске cheese и xawtv.
Очевидно, это вызвано тем, что веб-камеры запрашивают всю доступную полосу пропускания на хост-контроллере USB. Имея это в виду, я решил запустить wireshark и capinfos, чтобы увидеть, какую пропускную способность использует одна камера.
4 megabits per second at 320x240
14 megabits per second at 640x480
32 megabits per second at 1280x720
Интересно! Это может объяснить, почему две камеры с разрешением 320x240 работают, но любое более высокое разрешение дает сбой. Как будто мой USB-контроллер работает только на скорости USB 1, но lsusb показывает обе веб-камеры, принадлежащие устройству, которое предположительно поддерживает 480 мегабит в секунду.
В одном решении предлагалось заставить веб-камеры рассчитывать использование полосы пропускания, а не запрашивать их максимум, выполнив следующие команды:
sudo rmmod uvcvideo
sudo modprobe uvcvideo quirks=128
К сожалению, это не имело никакого значения, поэтому я решил попробовать другое решение. В сообщении на StackOverflow предлагалось указать моим веб-камерам использовать более низкий FPS или сжатый видеоформат, такой как MJPEG, но после запуска списка v4lctl ни одна из моих веб-камер не поддерживает изменение их видео-режима.
И вот где я застрял. Почему две веб-камеры, работающие значительно ниже максимальной скорости USB 2, могут вызвать такую ошибку?
ps: это не проблема дискового пространства, df не отображает изменений при запуске веб-камер.
pps: если это имеет значение, вот вывод команды lsusb
4 ответа
Дин Дин! Удалось выяснить это с помощью хороших людей из #v4l на freenode.
Короче говоря: 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 или ниже.*
Ответ заключается в использовании модификаций uvcvideo, написанных SwDevRefugee и описанных выше. Он и я работали вместе, чтобы успешно скомпилировать модифицированный код для OpenWrt. Версия, на которой я его запускаю, - это ДРАЙВЕР, ОПИСАННЫЙ OpenWRT (Bleeding Edge, r48130), на маршрутизаторе tplink wdr3600:
РЕЗУЛЬТАТ: у меня может быть 3*c270 (logitech), работающий одновременно с разрешением 1280x960 и 15 кадров в секунду в формате MJPG, через концентратор USB 2.0. У меня нет четвертого с270, чтобы подключить, извините.
Я также могу иметь 2*c270 и 1*GEMBIRD 640*480*15 кадров в секунду в формате YUV, но добавление 2-го GEMBIRD приводит к ужасному "Невозможно начать захват: на устройстве не осталось места" (пробел == пропускная способность здесь, так как вы хорошо знать:)). Обратите внимание, что GEMBIRD (1908: 2311) == http://www.penguin.cz/~utx/hardware/USB_Camera_AX2311/.
Использование процессора с 3 * c270 вполне разумно на 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 и параметр модуля quirks = 128 игнорируется, если поток сжат в формате mjpeg.
Моими любимыми веб-камерами были Logitech C500 и Logitech C270, и я обнаружил, что изображение, создаваемое C500 в разрешении 1280x1024, имеет размер 100 Кбайт, а изображение, создаваемое C270 при разрешении 1280x960, составляет 200 Кбайт.
Если я запускаю C270 со скоростью 10 кадров в секунду, то требуемая скорость передачи данных составляет 10x200000x8 = 16 Мбит / с. В Ubuntu 14.04 модуль uvcdriver всегда выделяет 196 Мбит / с независимо от частоты кадров. Для C500 он немного лучше себя ведет, но все еще является проблемой пропускной способности.
Я изменил драйвер uvcvideo, так что я могу обеспечить коэффициент "сжатия" для драйвера через интерфейс V4L2. Это немного "хакерство", потому что я использовал атрибут priv в struct v4l2_pix_format, чтобы указать значение. В драйвере он вычисляет размер несжатого изображения, а затем делит на коэффициент сжатия, чтобы определить, какую полосу пропускания USB использовать.
По умолчанию я использую коэффициент сжатия 10, который позволяет с большим запасом, если камера сталкивается с особенно жестким изображением для сжатия. C270, работающий со скоростью 1280x960 и 10 кадров в секунду, теперь использует 41 Мбит / с, и я легко могу запустить 4 камеры на одной шине.
Если кого-то заинтересует эта функция, я постараюсь убедить сопровождающих uvcvideo рассмотреть концепцию фактора "сжатия".
Я получил это из-за ошибки космоса тоже. То, что работало, состояло в том, чтобы отключить одну из камер и подключить ее к другому USB-порту на моем стационарном ПК - вокруг него разбросано 6 или 7 USB-портов. Запуск 'show_webcams 0 1', а затем внезапно поднял два изображения.