Après une introduction à GStreamer qui vous, je l'espère, donné l'eau à la bouche, nous allons poursuivre la découverte de ce superbe framework en nous focalisant sur les fonctions de streaming audio et vidéo.
Premier streaming vidéo: Theora et UDP
Nous allons dans ce premier exemple diffuser un flux vidéo (venant d'une Webcam) en utilisant le protocole UDP. Nous utiliserons le codec libre Theora (wiki) pour compresser la vidéo.
Sur la machine cliente (celle qui va recevoir et afficher le flux vidéo), il faut saisir la ligne suivante:
# gst-launch -v udpsrc port=1234 ! theoradec ! autovideosink
En clair, GStreamer va écouter le flux vidéo sur le port UDP/1234 (avec udpsrc) puis décompressé le flux Theora (theoradec) et enfin l'afficher sur l'écran (autovideosink).
Sur le serveur (la machine sur laquelle la Webcam est connectée et accessible par /dev/video1), nous allons saisir:
# gst-launch -v v4l2src device=/dev/video1 ! ffmpegcolorspace \
! videoscale method=1 ! video/x-raw-yuv,width=320,height=240,framerate=\(fraction\)15/1 \
! theoraenc bitrate=150 ! udpsink host=127.0.0.1 port=1234
Plusieurs remarques sur cette ligne de commande. On utilise la fonction videoscale pour redimensionner le format d'entrée de la vidéo (en taille et en nombre d'images par seconde) afin de limiter la bande passante. Je force ainsi dans ce cas le codec Theora à 150 Kbps. Enfin, la fonction udpsink permet de diffuser en UDP sur le réseau (port 1234 et adresse destination 127.0.0.1 - celle du client).
Remarque importante: il faut que le client soit lancé avant le serveur.
Streaming vidéo: Theora et TCP
Nous allons modifier légèrement notre premier exemple pour utiliser le protocole TCP en lieu et place du protocole UDP.
Le framework au niveau du client (le poste qui va recevoir le flux vidéo) est:
gst-launch -v tcpserversrc host=127.0.0.1 port=1234 ! decodebin ! autovideosink
GStreamer lance un serveur TCP (en écoute sur le port 1234 de l'adresse 127.0.0.1) et affiche le résultat (on peut utiliser decodebin à la place de theoradec) sur l'écran.
Sur le serveur (la machine avec la WebCam) on lance la commande:
gst-launch -v v4l2src device=/dev/video1 ! ffmpegcolorspace \
! video/x-raw-yuv,width=320,height=240,framerate=\(fraction\)10/1 \
! theoraenc bitrate=200 ! oggmux \
! tcpclientsink host=127.0.0.1 port=1234
On utilise la fonction
videoscale pour redimensionner le format d'entrée de la vidéo (en
taille et en nombre d'images par seconde) afin de limiter la bande
passante. Je force ainsi dans ce cas le codec Theora à 150 Kbps. Enfin,
la fonction tcpclientsink permet de diffuser en TCP sur le réseau (port 1234 et adresse destination 127.0.0.1 - celle du client).
Remarque importante: il faut que le client soit lancé avant le serveur.
Streaming vidéo: Theora et RTP/RTCP
On va compliquer encore un peu plus notre système de streaming en utilisant les protocoles RTP (pour les données) et RTCP (pour les flux de contrôle de ces données).
Contrairement aux deux premiers exemples, il faut lancer le client après le serveur. En effet, il est nécessaire de renseigner, au niveau du client, une chaine de configuration (caps) généré par le serveur.
gst-launch -v v4l2src \
! videoscale method=1 ! video/x-raw-yuv,width=320,height=240,framerate=\(fraction\)15/2 \
! theoraenc ! rtptheorapay \
! .send_rtp_sink gstrtpsession name=session .send_rtp_src ! udpsink port=5000 host=127.0.0.1 \
session.send_rtcp_src ! udpsink port=5001 host=127.0.0.1
Le serveur va encoder le flux vidéo avec le codec Theora, ajouter les entêtes RTP Theora (rtptheorapay) puis diffuser le flux en UDP (RTP/UDP sur le port 5000) grâce aux plugins gstrtpsession et udpsink. En parallèle, un serveur RTCP (RTCP/UDP) est lancé. Il envoie les information RTCP vers le port 5001 de la machine cliente (127.0.0.1).
Notez le paramètre -v passé à gst-launch. Il est nécessaire pour l'obtention de la chaine de configuration (caps).
Lors du lancement de cette commande, un grand nombre de messages va s'afficher. Il faut récupérer la dernière occurence du type:
caps = application/x-rtp, media=(string) video ... seqnum-base=(guint)39194
Nous pouvons alors lancer notre client:
gst-launch udpsrc port=5000 caps="application/x-rtp, media=(string) video ... seqnum-base=(guint)39194" \
! .recv_rtp_sink gstrtpsession name=session .recv_rtp_src \
! rtptheoradepay ! theoradec ! xvimagesink \
udpsrc port=5001 caps="application/x-rtcp" ! session.recv_rtcp_sink
Le client écoute le flux de donnée vidéo sur le port UDP/5000. Grâce aux informations fournies dans le champs caps, il peut décoder le flux. On enlève l'entête RTP (rtptheoradepay) puis on décode le flux théora (theoradec) et on affiche. En parallèle, on écoute les flux de contrôle de ces données (RTCP) sur le port 5001 et on les injectent dans le gestionnaire RTP (gstrtpsession).
Streaming vidéo: H.264 et RTP/RTCP
Nous allons modifier l'exemple précedant en remplacant le codec H.264 au lieu de Theora. Pour celà, nous allons utiliser le plugins X.264 (développé par l'équipe VideoLAN). Sous Ubuntu 8.10, ce dernier se trouve dans les plugins Multiverse. A installer avec la commande suivante:
sudo apt-get install gstreamer0.10-plugins-bad-multiverse gstreamer0.10-plugins-ugly-multiverse
On doit également installé le plugin permettant de relier GStreamer à FFMpeg (pour le décodage des flux H.264):
sudo apt-get install gstreamer0.10-ffmpeg
Contrairement au codec Theora, il n'ait pas nécessaire de passer la chaine de configuration "caps" du serveur vers le client.
On a donc la configuration suivante au niveau du serveur (à lancer en premier):
gst-launch -v v4l2src \
! videoscale method=1 ! video/x-raw-yuv,width=640,height=480,framerate=\(fraction\)15/2 \
! x264enc byte-stream=true bitrate=300 vbv-buf-capacity=300 me=0 subme=3 ! rtph264pay \
! .send_rtp_sink gstrtpsession name=session .send_rtp_src ! udpsink port=5000 \
session.send_rtcp_src ! udpsink port=5001
La seule différence avec l'exemple du chapitre précedant est l'utilisation de l'encodeur X.264 (x264enc qui génére un flux H.264). Pour une description des nombreux paramètres de ce plugin, je vous conseille la lecture de la documentation:
gst-inspect x264enc
La ligne de commande du client est la suivante:
gst-launch-0.10 udpsrc port=5000 caps="application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, profile-level-id=(string)4d4033, sprop-parameter-sets=(string)\"Z01AM6tAoP2AiAAAAwAQAAADAPR4wZU\\=\", ssrc=(guint)4139150394, payload=(int)96, clock-base=(guint)171857483, seqnum-base=(guint)1329" \
! .recv_rtp_sink gstrtpsession name=session .recv_rtp_src ! rtph264depay ! ffdec_h264 ! xvimagesink \
udpsrc port=5001 caps="application/x-rtcp" ! session.recv_rtcp_sink
On utilise le décodeur H.264 fourni par FFMpeg (ffdec_h264).
Streaming audio et vidéo: H.264, Speex et RTP/RTCP
Dernier exemple de ce billet qui va streamer un flux vidéo et un flux audio (venant du périphérique de capture standard de votre système). La vidéo sera encodé en H.264 et la vidéo en Speex. Le tout en utilisant le protocole RTP/RTCP.
Le serveur (à lancer en premier). Il faut récupérer la chaine "caps" pour la partie audio Speex.
gst-launch -v gstrtpbin name=rtpbin \
v4l2src ! videoscale method=1 ! video/x-raw-yuv,width=640,height=480,framerate=\(fraction\)15/2 \
! queue ! x264enc byte-stream=true bitrate=300 vbv-buf-capacity=300 me=0 subme=3 ! rtph264pay \
! rtpbin.send_rtp_sink_0 \
rtpbin.send_rtp_src_0 ! udpsink port=5000 host=127.0.0.1 \
rtpbin.send_rtcp_src_0 ! udpsink port=5001 host=127.0.0.1 sync=false async=false \
udpsrc port=5002 ! rtpbin.recv_rtcp_sink_0 \
alsasrc \
! queue ! speexenc ! rtpspeexpay \
! rtpbin.send_rtp_sink_1 \
rtpbin.send_rtp_src_1 ! udpsink port=5003 host=127.0.0.1 \
rtpbin.send_rtcp_src_1 ! udpsink port=5004 host=127.0.0.1 sync=false async=false \
udpsrc port=5005 ! rtpbin.recv_rtcp_sink_1
Et le client:
gst-launch-0.10 -v gstrtpbin name=rtpbin latency=200 \
udpsrc caps="application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, profile-level-id=(string)4d4033, sprop-parameter-sets=(string)Z01AM6tAUB7YCIAAAAMBAAADAA9HjBlQ, ssrc=(guint)614294178, payload=(int)96, clock-base=(guint)3718899905, seqnum-base=(guint)59615" port=5000 \
! rtpbin.recv_rtp_sink_0 \
rtpbin. ! rtph264depay ! ffdec_h264 ! xvimagesink \
udpsrc port=5001 ! rtpbin.recv_rtcp_sink_0 \
rtpbin.send_rtcp_src_0 ! udpsink port=5002 host=127.0.0.1 sync=false async=false \
udpsrc caps="application/x-rtp, media=(string)audio, clock-rate=(int)44100, encoding-name=(string)SPEEX, encoding-params=(string)1, ssrc=(guint)419764010, payload=(int)110, clock-base=(guint)3478167082, seqnum-base=(guint)57894" port=5003 \
! rtpbin.recv_rtp_sink_1 \
rtpbin. ! rtpspeexdepay ! decodebin ! alsasink \
udpsrc port=5004 ! rtpbin.recv_rtcp_sink_1 \
rtpbin.send_rtcp_src_1 ! udpsink port=5005 host=127.0.0.1 sync=false async=false
Bon stream à vous !







Open-source

Abonnez-vous
11 commentaires au billet “J'ai streamé avec GStreamer”
Super intéressants tes posts sur Gstreamer, merci beaucoup tu me fais découvrir ce framework : j'avais tendance à n'utiliser que vlc pour la diffusion ou avidemux pour bidouiller une vidéo. J'espère qu'on verra un jour un équivalent à avidemux avec Gstreamer.
J'ai une petite question : quid de la communication avec vlc ?
Est-ce qu'un flux diffusé avec vlc peut être lu avec gstreamer ?
Exemple pratique : est-ce qu'il est envisageable de coder un plugin pour totem qui permettrait de lire les flux TV provenant d'une Freebox ? Réciproquement est-ce qu'on pourrait envisager de streamer une vidéo depuis son PC vers la Freebox/freeplayer ?
Merci encore !
++
Chicha
@chicha: il est tout à fait possible de récupérer un flux "streamé" avec Gstreamer sur un client VLC. Par exemple pour récupéré le flux vidéo RTP + H.264, il faut créer un fichier .sdp et ouvrir ce fichier avec VLC.
test.sdp:
-----------
v=0
o=- 1188340656180883 1 IN IP4 127.0.0.1
s=Session streamed by GStreamer
i=server.sh
t=0 0
a=tool:GStreamer
a=type:broadcast
m=video 5000 RTP/AVP 96
c=IN IP4 127.0.0.1
a=rtpmap:96 H264/90000
Je vais créer de ce pas une nouvelle catégorie GStreamer dans le forum pour en discuter (http://forum.nicolargo.com).
Merci beaucoup !
En revanche je me demande s'il est possible de streamer depuis Gstreamer vers une freebox/freeplayer (vlc inside) ? j'ai peur que le stream doit contenir des informations propres à vlc ...
@chicha: j'avoue ne pas avoir essayé. Mais je suis intéressé par le résultat.
Je te tiendrais au courant de mes essais
Superbe tous ces articles sur gstreamer qui montre les possibilités de ce framework multimedia de gnome et maintenant de xfce hors norme et d'ailleurs sous-exploité.
Personnellement, je connaissais ce blog pour toutes ces informations concernant le réseau (qui en passant n'est pas du tout ma tasse de thé contrairement au multimedia et à la vidéo + precisemment) mais pas pour le multimedia. C'est certainement la raison qui m'a fait "plonger" dans les entrailles de gstreamer et j'ai découvert ses possibilités d'acquisition (dvb;1394;v4l2,..) et de decodage/d'encodage. Pour le prochain article pourrait-il traiter de l'acquisiton / enregistrement d'un flux (1394 ou dvb si possible) et/ou encodage d'un flux. Plus généralement, traiterat-il des possibilités (pad, cap, property et autres détails) et des messages d'erreurs et de leurs causes ainsi que le "liage" de gstreamer avec un language, python par exemple...?????
Merci de m'avoir fait découvrir tout cela et vivement la suite.La je suis accroché et je me demande si je ne vais pas m'inscrire sur le forum...;
@cenwen: merci pour le message, je suis loin d'être un spécialiste sur ce superbe framework libre qu'est gstreamer. J'ai l'occasion de l'utiliser dans le cadre de mon boulot et comme j'aime bien comprendre de quoi je parle, j'ai écris ces qq tutos (et d'autres à venir). Un des gars de mon équipe fait son stage sue le sujet. Tu peux suivre son travail sur ce blog:
http://lorenzocam.wordpress.com/
A+ et à bientôt sur le forum (qu'il faut faire vivre coté GStreamer...).
Tous ces articles sont très intéressants pour la prise en main de Gstreamer.
Je me pose une question : Est-il possible d'encoder en MPEG4 sans utiliser "ffenc_mpeg4" ?
@Julien: oui, en utilisant le x264enc.
Merci, Tous ces articles sont très intéressants
Mais j'ai essayé de streamé la voix à partir d'un microphone avec les commandes suivantes:
SERVEUR: gst-launch -v osssrc ! audio/x-raw-int, endianness=1234, signed=true, width=16, depth=16, rate=44100, channels=2 ! tee name=t ! queue ! faac ! mp4mux ! udpsink port=5000 host=10.1.1.43 t.
CLIENT : gst-launch -v udpsrc port=5000 ! ffdemux_mov_mp4_m4a_3gp_3g2_mj2 ! faad ! osssink
En tant que client j'ai eu ce message d'erreur:
gst-launch -v udpsrc port=5000 ! ffdemux_mov_mp4_m4a_3gp_3g2_mj2 ! faad ! osssink
Définition du pipeline à PAUSED...
Le pipeline est actif et n'a pas besoin de phase PREROLL...
Passage du pipeline à la phase PLAYING...
New clock: GstSystemClock
ERREUR : de l'élément /GstPipeline:pipeline0/ffdemux_mov_mp4_m4a_3gp_3g2_mj2:ffdemux_mov_mp4_m4a_3gp_3g2_mj20 : GStreamer a rencontré une erreur générale de bibliothèque de prise en charge.
Information de débogage supplémentaire :
gstffmpegdemux.c(1243): gst_ffmpegdemux_open (): /GstPipeline:pipeline0/ffdemux_mov_mp4_m4a_3gp_3g2_mj2:ffdemux_mov_mp4_m4a_3gp_3g2_mj20:
Unhandled error code received
Execution ended after 21482342886 ns.
Définition du pipeline à PAUSED...
Définition du pipeline à READY (prêt)...
Définition du pipeline à NULL...
Libération du pipeline...
Par contre j'ai essayé d'enregistrer la voix dans un fichier et ça bien marcher avec ces commandes:
COMMANDE D'ENREGISTREMENT:
gst-launch -v osssrc num-buffers=2000 ! audio/x-raw-int, endianness=1234, signed=true, width=16, depth=16, rate=44100, channels=2 ! tee name=t ! queue ! faac ! mp4mux ! filesink location=mm.aac t. ! queue ! alsasink sync=false
COMMANDE D'ECOUTE:
gst-launch-0.10 -v filesrc location=mm.aac ! ffdemux_mov_mp4_m4a_3gp_3g2_mj2 ! faad ! osssink
Pouvez vous m'aidez dans ce probleme.
Cordialement
Merci pour ce Tutorial !
Une question concernant la gestion du débit (par le serveur RTP) dans le cas d'un flux MPEG2 TS sur RTP:
les éléments gst exploitent-ils les timestamps PCR contenus dans les paquets TS ?
Si ce n'est pas le cas, comment gst cadence l'envoi des paquets RTP sur le réseau ?
Publier un commentaire
Utiliser
pour lier des documents à vos commentaires.
Pour des discutions techniques, merci d'utiliser le forum.