Si vous lisez régulièrement ce blog, vous savez que je m'intéresse au FrameWork multimédia GStreamer (cliquez ici pour voir la liste des billets sur le sujet). Nous allons poursuivre la découverte de cette superbe trousse à outil multimédia en l'appliquant sur la récupération et l'exploitation de flux vidéo venant de caméras IP. Nous nous focaliserons ici sur les caméras IP AXIS, non pas que j'ai des actions dans cette société mais il faut avouer que leurs caméras sont de très bonne qualité et l'accès aux flux vidéos assez simple.
Avant de nous plonger dans le vif du sujet et si vous souhaitez faire ces tests chez vous, il faut au préhalable installer GStreamer sur votre système.
Ma configuration de test est la suivante:
Lors de la rédaction de ce billet, j'ai utilisé la caméra AXIS 213:
La configuration de cette caméra (cam01) est la suivante:Format CIF
Compression 50%
Frame rate: 25 images/s
Configuration du PC1:
OS: GNU/Linux Debian 5.0 + Gstreamer 0.10.19-3
Hardware: Pentium Quad core CPU 2.8 Ghz + 4 Go RAM
Configuration du PC2:
OS: GNU/Linux Ubuntu 8.10 + Gstreamer 0.10.21-4
Hardware: Pentium Dual core CPU 3.0 Ghz + 512 Mo RAM
Affichage du flux vidéo
Cette caméra (comme toutes les caméras AXIS) permet la diffusion sur le réseau en utilisant deux formats:
- MJPEG sur HTTP
- MPEG-4 sur RTSP
Affichage du flux MJPEG/HTTP
On lance la commande suivante sur la machine PC1:
gst-launch gnomevfssrc location=http://cam01/axis-cgi/mjpg/video.cgi?resolution=CIF ! jpegdec ! ffmpegcolorspace ! autovideosinksink
Un rapide ntop sur notre machine PC1 nous indique que le fux est gourmand en bande passante (de l'ordre de 3.3 Mbps). L'occupation CPU varie entre 20% et 60%. La vidéo est fluide.
Affichage du flux MPEG4/RTSP
On lance la commande suivante sur la machine PC1:
gst-launch-0.10 rtspsrc location=rtsp://cam01:554/mpeg4/media.amp latency=0 ! decodebin ! ffmpegcolorspace ! autovideosink
La bande passante entre la caméra et le PC1 est alors de 1 Mbps en pics (moyenne de 400 Kbps quand il y a peu de mouvement devant la caméra). L'occupation CPU varie entre 5% et 15%. La vidéo est fluide.
Le paramètre latency (qui est par défaut à 3000, soit 3 secondes) permet de réduire la taille du buffer d'entrée. Si vous êtes sur un réseau LAN, vous pouvez sans problème mettre comme valeur 0 (comme je l'ai fait dans mon exemple). Par contre sur des réseaux moins performant (en terme de débit, de perte de paquets...), il vaut mieux conserver un buffer un peu plus élevé.
Encodage du flux vidéo dans un fichier
Nous allons continuer notre test en essayant d'encoder "à la volée" le flux vidéo venant de la caméra IP. Détaillons un peu notre pipeline:
- récupérer le flux MPEG4/RTSP de la caméra
- l'afficher sur l'écran
- réduire le nombre d'images par seconde (fps) à 1
- encoder le flux en MJPG
- sauvegarder dans un fichier AVI (output.avi)
La ligne de commande correspondante à lancer sur PC1 est:
gst-launch rtspsrc location=rtsp://cam01:554/mpeg4/media.amp latency=0 ! queue ! decodebin ! ffmpegcolorspace ! tee name=save ! queue ! autovideosink save. ! queue ! videorate ! capsfilter caps="video/x-raw-yuv,framerate=(fraction)1/1" ! queue ! jpegenc ! avimux ! filesink location=output.avi .save
Le fichier généré (output.avi) occupe un espace disque d'environ 15 Ko par seconde (soit 54 Mo/heure).
Afin d'optimiser cette taille, il est possible d'utiliser Theora (dans un fichier OGG), un codec vidéo libre et efficace. La commande devient alors:
gst-launch rtspsrc location=rtsp://cam01:554/mpeg4/media.amp latency=0 ! queue ! decodebin ! ffmpegcolorspace ! tee name=save ! queue ! autovideosink save. ! queue ! videorate ! capsfilter caps="video/x-raw-yuv,framerate=(fraction)1/1" ! queue ! theoraenc ! oggmux ! filesink location=output.ogg .save
On a alors une taille de fichier de sortie (output/ogg) d'environ 6 Ko par seconde (soit 21 Mo/heure).
Mixer plusieurs vidéos en une
Si vous disposé de plusieurs caméras, il peut être utile de mixer ces différentes sources dans une même image (un peu comme le mode PIN des télévisions).
Je vais dans l'exemple ci-dessous, prendre deux sources (Camera AXIS + Webcam USB) et les mixer:
La pipeline est la suivante:
gst-launch v4l2src ! queue ! videoscale ! capsfilter caps="video/x-raw-yuv,width=64,height=48,framerate=(fraction)5/1" ! ffmpegcolorspace ! videobox border-alpha=0 alpha=1.0 top=-230 left=-278 ! videomixer name=mix ! ffmpegcolorspace ! autovideosink mix. rtspsrc location=rtsp://cam01:554/mpeg4/media.amp latency=0 ! queue ! decodebin ! queue ! videorate ! capsfilter caps="video/x-raw-yuv,width=352,height=288,framerate=(fraction)25/1" ! ffmpegcolorspace ! mix.
Attention de bien fixer les framerates (videorate ou videoscale + capsfilter), car videomixer (le plugin qui s'occupe de faire le mixage vidéo) semble assez sensible sur ce point.
Streaming vers une autre machine
Nous allons maintenant voir comment transcoder le flux vidéo d'une caméra IP pour le diffuser (streamer vers une autre machine).
La description du pipeline du PC1 est la suivante:
- récupérer le flux MPEG4/RTSP de la caméra
- réencodage en Theora (à 250 Kbps)
- diffusion en UDP vers le PC2
puis celle du PC2:
- récupérer de flux Theora/UDP venant du PC1
- décodage Theora
- affichage de la vidéo
et les commandes correspondantes, sur le PC2 (il faut lancer cette commande en premier):
gst-launch -v udpsrc port=1234 ! theoradec ! autovideosink
puis sur le PC1:
gst-launch rtspsrc location=rtsp://cam01:554/mpeg4/media.amp latency=0 ! queue ! decodebin ! ffmpegcolorspace ! queue ! videorate ! capsfilter caps="video/x-raw-yuv,framerate=(fraction)25/1" ! queue ! theoraenc bitrate=250 ! queue ! udpsink host=pc2 port=1234
En moyenne, le débit observé entre PC1 et PC2 est de l'ordre de 250 Kbps (conforme donc a ce que l'on a configuré dans le plugin theoraenc), on observe cependant des pics à 250 Kps+30%. La consommation de CPU est de l'ordre de 25% sur PC1 et de 5% sur PC2. La vidéo est recue de manière fluide sur le PC2. Là encore, il ne faut pas oublier de fixer le nombre d'images par seconde avec videorate + capsfilter.
L'avantage avec GStreamer, c'est qu'il intégre une liste de plugins assez impressionnante, il est alors facile de les insérer dans notre pipeline. Par exemple, si l'on souhaite reprendre l'exemple ci-dessus et y ajouter un texte en sur-impression (overlay), il suffit d'utiliser le plugin cairotextoverlay.
La commande sur le PC1 devient alors:
gst-launch-0.10 rtspsrc location=rtsp://cam01:554/mpeg4/media.amp latency=0 ! queue ! decodebin ! ffmpegcolorspace ! queue ! cairotextoverlay text="Attention Tigrou !" shaded-background=true ! queue ! videorate ! capsfilter caps="video/x-raw-yuv,framerate=(fraction)25/1" ! queue ! theoraenc bitrate=250 ! queue ! udpsink host=pc2 port=1234
et le résultat sur PC2:
Pour conclure
Ce billet nous a permis de mettre le pied dans le monde passionnant du traitement des flux vidéo. Ce n'est qu'une introduction et la seule limite est votre imagination. Je vous rappelle que GStreamer peut être simplement intégré à vos applications grâce aux API disponibles. Si vous avez des questions et remarques sur le sujet, il existe une section spéciale dans le forum !