Streaming live MPEG-4 entre Windows et Linux avec GStreamer
Nous allons dans ce billet aborder un sujet plutôt inhabituel pour ce blog: Windows !
Le but étant de récupérer un flux vidéo live (venant par exemple d'une caméra) à partir d'une machine sous Windaube (Xp, Se7en ou autres trucs dans le genre) vers une autre machine (Linux mais aussi Mac ou Windows). Pour cela, nous allons utiliser le framework open-source GStreamer qui va permettre d’unifier tout ce beau monde.
Avant de commencer
Pour illustrer cet article nous allons faire un streaming live depuis une machine Windows Xp vers une machine GNU/Linux Fedora 14 connecté sur le même réseau LAN.
On commence donc par installer GStreamer sur la machine Windows en récupérant et installant la dernière version à partir du site WinBuilds. Je parts sur le principe ou votre Gstreamer est installé dans le répertoire C:\Program Files\OSSBuild\GStreamer\v0.10.6 (si ce n'est pas le cas, il suffit d'adapter le script .BAT, variable GSTPATH, en conséquence).
Ensuite on installe Gstreamer sur son PC GNU/Linux (procédure ici pour Fedora et là pour Ubuntu).
Ok, on a donc le framework GStreamer installé sur les deux machines que nous allons utilisé pour faire nos tests.
Streaming depuis Windows
On commence par éditer un fichier texte (Notepad est ton ami) que l'on va nommer client.bat contenant:
REM
REM Streaming from WebCam + MPEG4-ISO encoding + RTP + UDP
REM
set GSTPATH="C:\Program Files\OSSBuild\GStreamer\v0.10.6"
set CAPS="video/x-raw-yuv,width=(int)640,height=(int)480,framerate=(fraction)10/1"
set STREAMTO="192.168.0.10"
set STREAMPORT=5000
%GSTPATH%\bin\gst-launch.exe -tv --gst-plugin-path=%GSTPATH%\lib ^
gstrtpbin name=rtpbin latency=0 buffer-mode=0 ^
autovideosrc ! ffmpegcolorspace ^
! queue ! videoscale method=1 ! videorate ! %CAPS% ^
! timeoverlay ^
! queue ! ffenc_mpeg4 pass=0 bitrate=256000 rc-buffer-aggressivity=99 trellis=0 ^
! tee name="display" ^
! rtpmp4vpay send-config=true ^
! rtpbin.send_rtp_sink_0 ^
rtpbin.send_rtp_src_0 ! udpsink port=%STREAMPORT% host=%STREAMTO% ^
display. ^
! queue ! decodebin ! ffmpegcolorspace ! autovideosink
pause
Il faut adapter les deux lignes set à votre configuration sachant que STREAMTO doit être associé à l'adresse IP de votre machine cible (la machine Fedora 14 dans mon cas) et que la résolution de votre Webcam doit être compatible avec les valeur de CAPS.
On exécute ensuite le fichier .bat (une fenêtre CMD va s'ouvrir et afficher les éventuels message d'erreurs).
La ligne de commande qui va s'occuper de l'encodage MPEG-4 est la suivante:
ffenc_mpeg4 pass=0 bitrate=256000 rc-buffer-aggressivity=99 trellis=0
Le paramètre bitrate (256 Kbps) va fixer le débit cible du streaming. Cette valeur est bien sur à adapter selon la résolution et la fréquence (fps) de votre source vidéo.
L'encapsultation dans une trame RTP est faite grâce à la commande:
rtpmp4vpay send-config=true
L'option send-config (=true) permet à Gstreamer d'envoyer régulièrement sur le réseau (trame RTP) des informations sur les caractéristiques du stream au lieu de les envoyer seulement au début de la session.
Réception du stream depuis GNU/Linux
C'est (un peu) plus simple, on va créer un shell script server.sh:
#!/bin/sh
CAPS="application/x-rtp,media=\(string\)video,clock-rate=\(int\)90000,encoding-name=\(string\)MP4V-ES,payload=\(int\)96"
PORT=5000
gst-launch -tv gstrtpbin name=rtpbin latency=0 buffer-mode=0 \
udpsrc caps=$CAPS port=$PORT do-timestamp=true \
! rtpbin.recv_rtp_sink_0 \
rtpbin. ! rtpmp4vdepay ! ffdec_mpeg4 ! autovideosink
Une fois le script édité, il faut le rendre exécutable:
chmod a+x server.sh
Puis executer le script pour recevoir le stream venant du PC Window
./server.sh
Et si on veut ajouter du son ?
Il suffit d'adapter les pipelines ! A tittre d'exemple, vous pouvez consulter les scripts suivants:
- Streaming vidéo MPEG-4 + audio aLaw: Émetteur Windows / Récepteur GNU/Linux
- Streaming vidéo MPEG-4 + audio Celt: Émetteur Windows / Récepteur GNU/Linux
J'ai également essayé d'utiliser le codec X.264 (x264enc + x264dec) succés pour l'instant (qualité très mauvaise).