¡Ding Ding! Me las arreglé para resolver esto con la ayuda de la buena gente en #v4l en freenode.
En pocas palabras:v4l2-ctl es la mejor herramienta para depurar problemas de la cámara USB. Lea todos los comandos disponibles y la página del manual, será divertido, lo prometo. Usando v4l2-ctl Descubrí que una de mis cámaras no admitía ningún modo de video comprimido. Puede verificar qué modos admiten sus cámaras ejecutando el siguiente comando:
v4l2-ctl -d /dev/video0 --list-formats
Lo que debería generar algo como esto.
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)
Si el único formato de píxel devuelto es "YUYV", "IUYV", "I420" o "GBRG", solo podrá ejecutar una cámara por controlador USB* ya que esos formatos no están comprimidos. El uso de varias cámaras web que admitan MJPEG o alguna otra forma de compresión funcionará bien.
Si usa OpenCV como yo, no se preocupe si el formato de píxel predeterminado no está comprimido, ya que parece que OpenCV usa compresión por defecto de todos modos.
**A menos que esté satisfecho con una resolución de 320 x 240 o inferior.*
La respuesta es usar las modificaciones de uvcvideo escritas por SwDevRefugee y descritas anteriormente. Él y yo hemos trabajado juntos para compilar el código mod'ed para OpenWrt, con éxito. La versión en la que lo estoy ejecutando es OpenWRT DESIGNATED DRIVER (Bleeding Edge, r48130), en un enrutador tplink wdr3600:
RESULTADO:Puedo tener 3*c270 (logitech) funcionando simultáneamente a 1280x960 y 15fps en formato MJPG, a través de un hub usb 2.0. No tengo un cuarto c270 para conectar, lo siento.
También puedo tener 2*c270 y 1*GEMBIRD 640*480*15fps con formato YUV, pero agregar un segundo GEMBIRD genera el temido mensaje "No se puede iniciar la captura:no queda espacio en el dispositivo" (espacio==ancho de banda aquí, como conocer bien:)). Tenga en cuenta que GEMBIRD (1908:2311) ==http://www.penguin.cz/~utx/hardware/USB_Camera_AX2311/ .
El uso de CPU con 3*c270 es bastante razonable en un 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 --
Si la comunidad brinda algo de reputación y apoyo, creo que SwDevRefugee está dispuesto a introducir el código en uvc-linux.
Miré el controlador uvcvideo y el parámetro del módulo quirks=128 se ignora si la transmisión está comprimida con mjpeg.
Mis cámaras web preferidas han sido Logitech C500 y Logitech C270, y descubrí que la imagen producida por el C500 a 1280x1024 es de 100kbytes y la imagen producida por el C270 a 1280x960 es de 200kbytes.
Si ejecuto el C270 a 10 fps, la tasa de bits requerida es 10x200000x8 =16 Mbit/s. En Ubuntu 14.04, el módulo uvcdriver siempre asigna 196 Mbits/s independientemente de la velocidad de fotogramas. Para el C500 se comporta un poco mejor, pero aún consume mucho ancho de banda.
Modifiqué el controlador uvcvideo para poder proporcionar un factor de "compresión" al controlador a través de la interfaz V4L2. Es un "pequeño truco" en el sentido de que utilicé el atributo priv en la estructura v4l2_pix_format para especificar el valor. En el controlador, calcula el tamaño de la imagen sin comprimir y luego la divide por el factor de compresión para determinar qué ancho de banda USB usar.
De forma predeterminada, uso un factor de compresión de 10 que permite un gran margen si la cámara encuentra una imagen particularmente difícil de comprimir. El C270 que funciona a 1280x960 y 10 fps ahora usa 41 Mbit/s y puedo ejecutar fácilmente 4 cámaras en un bus.
Si alguien está interesado en esta función, intentaré que los mantenedores de uvcvideo consideren el concepto del factor de "compresión".