L'exécution de plus d'une webcam USB sous Debian/Linux génère l'erreur suivante:
libv4l2: error turning on stream: No space left on device
VIDIOC_STREAMON: No space left on device
Ce qui semblait initialement être un problème de programmation dans OpenCV s'est transformé en une quête d'un mystérieux problème matériel/logiciel après que les mêmes erreurs ont été générées en exécutant cheese et xawtv.
Apparemment, cela est causé par les webcams qui demandent toute la bande passante disponible sur le contrôleur hôte USB. Gardant cela à l'esprit, j'ai décidé de lancer Wirehark et capinfos pour déterminer la bande passante utilisée par une seule caméra.
4 megabits per second at 320x240
14 megabits per second at 640x480
32 megabits per second at 1280x720
Intéressant! Cela pourrait expliquer pourquoi deux caméras au format 320x240 fonctionnent mais que toute résolution supérieure échoue. C'est comme si mon contrôleur USB ne fonctionne qu'à la vitesse USB 1, pourtant lsusb indique les deux webcams appartenant à un appareil censé prendre en charge 480 mégabits par seconde.
Une solution a proposé de forcer les webcams à calculer leur consommation de bande passante au lieu de demander leur maximum en exécutant les commandes suivantes:
Sudo rmmod uvcvideo
Sudo modprobe uvcvideo quirks=128
Malheureusement, cela ne faisait aucune différence, alors j'ai décidé d'essayer une autre solution. Un article sur StackOverflow a suggéré de dire à mes webcams d’utiliser un format de FPS inférieur ou compressé comme MJPEG, mais après avoir exécuté la liste v4lctl il semble qu'aucune de mes webcams ne supporte le changement de mode vidéo.
Et c'est là que je suis coincé. Pourquoi deux webcams fonctionnant bien en dessous de la vitesse maximale de l'USB 2 produiraient-elles cette erreur?
ps: ce n'est pas un problème d'espace disque, df n'affiche aucun changement au démarrage des webcams.
pps: Si cela fait une différence, voici la sortie de lsusb
Ding Ding! J'ai réussi à comprendre celui-ci avec l'aide du peuple de Nice dans # v4l sur freenode.
Longue histoire courte: v4l2-ctl est le meilleur outil pour déboguer les problèmes de caméra USB. Lisez toutes les commandes disponibles et la page de manuel, ce sera amusant, je vous le promets. En utilisant v4l2-ctl , j’ai découvert que l’un de mes appareils photo ne supportait aucun mode vidéo compressé. Vous pouvez vérifier les modes pris en charge par vos caméras en exécutant la commande suivante:
v4l2-ctl -d /dev/video0 --list-formats
Ce qui devrait produire quelque chose comme ça.
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 le seul format de pixels renvoyé est "YUYV", "IUYV", "I420" ou "GBRG", vous ne pourrez utiliser qu'un seul appareil photo par contrôleur *, car ces formats ne sont pas compressés. L'utilisation de plusieurs webcams prenant en charge MJPEG ou une autre forme de compression fonctionnera correctement.
Si vous utilisez OpenCV comme moi, ne vous inquiétez pas si le format de pixel par défaut n'est pas compressé car il apparaît que, par défaut, OpenCV utilise la compression.
** Sauf si vous êtes satisfait de la résolution 320x240 ou inférieure. *
La solution consiste à utiliser les modifications uvcvideo écrites par SwDevRefugee et décrites ci-dessus. Lui et moi avons travaillé ensemble pour obtenir le code modulé compilé pour OpenWrt, avec succès. La version sur laquelle je l’utilise est OpenWRT DESIGNATED DRIVER (Bleeding Edge, r48130), sur un routeur tplink wdr3600:
RÉSULTAT: Je peux avoir 3 * C270 (Logitech) fonctionnant simultanément à 1280x960 et 15 images par seconde au format MJPG, via un hub USB 2.0. Je n'ai pas de quatrième C270 à brancher, désolé.
Je peux aussi avoir 2 * C270 et 1 * GEMBIRD 640 * 480 * 15 ips avec le format YUV, mais l’ajout d’un 2e GEMBIRD mène au redoutable "Impossible de démarrer la capture: il n’ya plus d’espace libre sur le périphérique" (espace = Bien connaître:)). Notez que GEMBIRD (1908: 2311) == http://www.penguin.cz/~utx/hardware/USB_Camera_AX2311/ .
L'utilisation du processeur avec 3 * c270 est relativement raisonnable sur 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 communauté donne une réputation et un soutien, je pense que SwDevRefugee est prêt à obtenir le code dans uvc-linux.
J'ai regardé le pilote uvcvideo et le paramètre de module quirks = 128 est ignoré si le flux est compressé au format mjpeg.
Mes webcams préférées étaient les Logitech C500 et Logitech C270. J'ai constaté que l'image produite par le C500 en 1280x1024 était de 100 Ko et celle produite par le C270 en 1280x960 de 200 Ko.
Si je lance le C270 à 10fps, le débit binaire requis est de 10x200000x8 = 16 Mbit/s. Dans Ubuntu 14.04, le module uvcdriver alloue toujours 196 Mbits/s, quel que soit le taux de trame. Pour le C500, il se comporte un peu mieux, mais reste tout de même un gros casse-tête.
J'ai modifié le pilote uvcvideo afin de pouvoir fournir un facteur de "compression" au pilote via l'interface V4L2. C'est un "petit hacky" dans le sens où j'ai utilisé l'attribut priv dans la struct v4l2_pix_format pour spécifier la valeur. Dans le pilote, il calcule la taille de l'image non compressée, puis se divise par le facteur de compression pour déterminer la bande passante USB à utiliser.
Par défaut, j'utilise un facteur de compression de 10, ce qui permet une marge importante si la caméra rencontre une image particulièrement difficile à compresser. Le C270 tournant à 1280x960 et 10fps utilise maintenant 41 Mbit/s et je peux facilement faire fonctionner 4 caméras sur un bus.
Si cette fonctionnalité intéresse quelqu'un, je vais essayer de faire en sorte que les responsables de la maintenance d'uvvideo considèrent le concept de facteur de "compression".