Les webcams et le H.264 : un vrai gâchis

Il y a à peu près 10 ans, je parlais des webcams qui encodent en H.264 en interne. Et bien une décennie plus tard, ça n’a pas changé : c’est une curiosité inutile qui aurait pu être intéressante.

Un peu de contexte : dans la majorité des cas, les webcams transmettent une image qui est compressée. L’USB 2.0 (et évidemment l’USB 1.1) a une bande passante limitée en pratique et même le 720p n’est pas réellement utilisable sans compression, sauf à vouloir 24 images/s ou moins. En pratique, on compresse en MJPEG, un codec assez basique. C’est assez efficace dans l’absolu, vu qu’on compresse chaque image en JPEG séparément, mais la compression est faible. Sur les webcams modernes, on est passé à l’USB 3.0, qui peut travailler sans compression même sur des définitions élevées.

Au début des années 2010, une solution est apparue : compresser en H.264 dans la webcam. Ce n’est pas idiot : les puces nécessaires devenaient abordables, le codec est efficace sur les définitions employées dans le webcams (vers 1080p30 au mieux à l’époque) et la décompression H.264 matérielle était déjà la norme. Mais assez bizarrement, cette solution n’a pas pris. Les webcams sont rares et il existe au moins trois manières de transférer le flux, ce qui ne simplifie pas les choses.

La première, la plus courante, est la C920 de chez Logitech. Attention, si c’est une webcam encore en vente, les versions modernes ne sont plus compatibles. Logitech a abandonné cette solution il y a quelques années, en arguant que les CPU peuvent encoder matériellement et donc que c’est inutile (et probablement coûteux). Un moyen simple de déterminer la compatibilité vient probablement de la marque : si vous avez un logo Logi, elle n’est a priori pas compatible. Avec un logo Logitech, c’est normalement le cas. Sinon, si vous avez la boîte, c’est indiqué dessus.

Une C920 compatible avec le logo Logitech

De ce que j’ai trouvé comme informations, la compatibilité H.264 de ce modèle est très limitée. Pour ce qui nous intéresse ici, macOS, c’est simple : ça ne fonctionne pas. Sous Windows, Skype et les outils de Logitech de l’époque sont compatibles. Sous GNU/Linux, il est possible de récupérer le flux aussi, on va le voir plus bas. D’un point de vue pratique, c’est un peu compliqué : elle encode en H.264 sans suivre le standard. Elle est compatible UVC 1.1 (la norme classique) et envoie le flux H.264 comme s’il s’agissait d’un flux MJPEG.

La seconde, moins courante, est la Logitech C930e. Elle utilise la norme UVC 1.5 (qui accepte le H.264) mais transmet le flux de façon bizarre. Elle est officiellement compatible avec certains outils Microsoft (Lync) et c’est à peu près tout et dans la majorité des cas, elle fonctionne en MJPEG. Pour le côté bizarre, le flux H.264 est en fait couplé au flux MJPEG en UVC 1.1. Visiblement, chaque image JPEG contient des métadonnées (JFIF) qui intègrent les frames du flux H.264. Il y a au moins deux autres caméras Logitech qui ont le même fonctionnement : la (vieille) C922 et la C925. Dans la pratique, le flux est donc très compliqué à récupérer. Au passage, dans mes recherches, je suis tombé sur une des explications de ce fonctionnement : il permet d’afficher la version MJPEG en local (simple à décoder) tout en transmettant la version H.264 sur le réseau en parallèle. Cette page donne quelques indices pour récupérer les données, mais ça ne semble pas fonctionner avec la C930e. En fait, je l’ai vu après, l’encodeur est a priori désactivé par défaut et je n’ai pas trouvé comment l’activer.

Une C930e

La troisième solution, je ne l’ai pas essayée, c’est celle de la caméra Theta S de chez Ricoh, une caméra portable. Elle est UVC 1.5 et transmet le flux en suivant la norme… que les principaux OS ne prennent pas réellement en charge.

Quelques essais

J’ai une Logitech C930e depuis un moment, et une C920 compatible H.264 achetée pour l’occasion, donc j’ai fait quelques essais.

Pour commencer, j’ai testé avec GNU/Linux (on va dire Linux dans la suite) dans une machine virtuelle. Je suis parti des outils sur cette vieille page, et j’ai un peu bidouillé. Le plus simple dans le cas présent est de lancer VLC. En faisant Media -> Open Capture Device, on peut choisir le flux dans Advanced options -> Video input chroma format. Si vous tapez MJPG, vous aurez le flux MJPEG, et si vous tapez H264… vous aurez le H.264 (attention, la capitalisation est importante). Ensuite, il suffit d’enregistrer le flux avec VLC (clic droit -> Record). Pour se donner une idée, le flux H.264 est à 3 Mb/s en 1080p, le flux MJPEG à 68 Mb/s en 1080p et le flux sans compression à 177 Mb/s… mais en 800 x 600 à 24 images/s.

Le H.264


Sans compression (en 800×600)


En MJPEG


Sous Linux, on liste bien le H.264

On peut par ailleurs noter que le flux H.264 est (beaucoup) plus propre que le celui en MJPEG dès qu’on est en basse lumière, c’est flagrant sur les captures d’écran et encore plus en vidéo, parce que le flux MJPEG fourmille énormément. Soyons clairs : la différence ne saute pas aux yeux (sauf dans un environnement sombre) et ce n’est pas comme passer de la VHS au Blu-ray, mais l’image reste un peu plus propre en H.264 tout de même.

Mon bureau mal rangé en H.264


Mon bureau mal rangé en MJPEG


H.264 (plus net)


MJPEG


H.264, moins bruité


MJPEG

J’ai tenté de tester la même caméra sous Windows, mais elle ne fonctionne pas dans ma machine virtuelle avec les outils de Logitech. En théorie, les outils de l’époque (LWS) doivent permettre de récupérer le flux H.264 selon les forums de Logitech, mais c’est compliqué à vérifier : la société a fermé ses forums. Sur d’autres OS, Android doit en théorie accéder au flux H.264 parce que le développeur de cette application japonaise donne pas mal de détails… mais je ne peux pas l’installer. Elle indique que mes appareils sont incompatibles, et elle se coupe automatiquement après 3 minutes si je passe par l’APK de la version gratuite. Plus largement, accéder au flux H.264 en dehors de Linux est visiblement compliqué.

Pour la C930e, c’est beaucoup plus compliqué. La prise en charge de l’UVC 1.5 n’est pas complète sous Linux, et sous Windows, il faut le pilote de Logitech ou une version récente de Windows (bon, dès Windows 8). Mais même comme ça, le système ne donne pas accès au flux. Mais après quelques (longues) recherches, je suis tombé sur un programme : fmp4streamer. Le script Python fonctionne sous Linux et permet de récupérer le flux H.264 de la C930e.

Une fois installé et lancé, le tout est disponible en streaming (en local dans mon cas). Il donne surtout quelques détails sur la caméra : le H.264 est désactivé par défaut et le bitrate peut varier de 64 Kb/s à 12 Mb/s (3 Mb/s par défaut). Il indique aussi que ça fonctionne avec la C922 (avant 2020), la C925e ou la C920 qui a un encodeur H.264.

Le résultat ? Le même que pour la C920 : un flux avec un débit plus faible (3 Mb/s contre un peu moins de 70 Mb/s) mais surtout une image plus propre, même dans un environnement sombre.

H.264


MJPEG


H.264


MJPEG

Dans les deux cas, j’ai comme une impression de gâchis : les deux webcams peuvent fournir une image de meilleure qualité que ce qui est réellement disponible. Et au-delà de la qualité de l’image, le H.264 natif simplifie les choses en pratique : on peut l’envoyer directement pour du streaming dans certains cas, sans devoir compresser du MJPEG bruité. Mais dans la pratique, on se retrouve avec deux webcams courantes qui ne fonctionnent pas de la même façon, avec une implémentation obscure et une compatibilité aléatoire vu qu’elle dépend de l’âge de la caméra.

Sur les caméras modernes, la solution est finalement plus simple : on transmet sans compression en USB 3.0. Pour rester chez Logitech, la StreamCam fait par exemple assez bien ça.