GStreamer, la théorie...
Nous allons dans ce billet aller un peu plus dans le détail du fonctionnement de GStreamer (le Framework multimédia libre).
C'est quoi donc ?
GStreamer est un framework multimédia: c'est à dire un ensemble de bibliothèques, d'outils et de conventions permettant le développement d'applications (source Wikipédia). Par multimédia, on attend ici la manipulation d'objets vidéo et audio.
Il est composé:
- d'une architecture logicielle comprenant un coeur et de nombreux plugins (plus de 150 pour la version 0.10)
- d'API pour le développement avec le support de nombreux langages
- d'outils de tests (gst-launch), de documentation (gst-inspect) et de présentation (gsteditor)
Architecture générale de GStreamer
GStreamer est composé d'un cœur (GStreamer Core) permettant de construire une séquence d'actions à effectuer sur vos objets multimédia. Ce cœur s'occupe de la communication entre les différentes briques en gérant les entrées/sorties. Il manipule les données sous forme de blocs et se base sur une architecture logicielle objet.
Les plugins manipulent les objets multimédia. On peut diviser les plugins en différentes catégories:
- gestion des entrées (sources) audio et vidéo: les entrées peuvent être des fichiers multimédia, des équipements (Webcam, caméra DV) ou des flux réseaux (par exemple venant d'un streaming).
- gestion des protocoles: permet une gestion des protocoles de communication réseau. Avec le support de protocoles simples (UDP, TCP) ou plus complexes (RTP/RTSP).
- gestions des formats: les données multimédias sont dans des conteneurs (AVI, OGG, MPEG...). Gstreamer permet, via des plugins, de gérer ces conteneurs (lecture, mux, demux...).
- gestions des codecs: le fait que les codecs audio/vidéo soit proposé dans Gstreamer sous la forme de plugins comporte de gros avantages (normalisation d'un codec à l'autre, facilité de changement de codec dans une application, cicle de développement plus cours pour inclure un plugin dans GStreamer).
- gestion des filtres: il existe autant de possibilité de filtres audio et vidéo que votre imagination peut produire.
- gestion des sorties (sinks) audio et vidéo: Les sorties peuvent être des fichiers, des équipements (écrans) ou des flux réseaux.
Il faut noter que les plugins GStreamer sont livrés sous la forme de 3 packages:
gst-plugins-good: ceux sont les plugins jugés de bonnes qualités par les développeurs et qui sont distribué sous licences LGPL.
gst-plugins-ugly: ceux sont les plugins jugés de bonnes qualités mais qui peuvent poser des problèmes de licenses (non libres).
gst-plugins-bad: ceux sont les plugins en développement dont la qualité et/ou stabilité doivent être améliorés.
Comment fonctionne GStreamer
Afin d'expliquer le plus simplement le fonctionnement de GStreamer, nous allons prendre l'exemple d'une application ayant pour but de lire un fichier multimédia au format OGG (contenant des données audio encodées en Vorbis et vidéo encodées en Theroa) pour l'afficher sur votre écran et l'écouter sur vos haut parleurs.
Le schéma du framework correspondant est le suivant:
Pipeline
La classe principal est nommé pipeline. C'est l'enveloppe qui va contenir l'ensemble des actions a effectuer.
Element
Le Pipeline contient une chaine d'élements (elements). L'élément est la classe la plus importante dans GStreamer. A chaque élément est associé une fonction (plugin).
On distingue 3 types d'élements:
- Les éléments sources ("source element"). Ils produisent des données.
- Les éléments de sorties ("sink element"). Ils ne produisent pas de donnée. Ils sont donc souvent en bout de pipeline (exemple: xvideosink, permet d'afficher une vidéo à l'écran).
- Les éléments de filtrage ("filter element"). Ils ont une ou plusieurs entrées et une ou plusieurs sorties. Ils effectuent des traitements sur les données et les réinjecte dans le pipeline.
Voici par exemple l'élément qui permet la lecture d'un fichier depuis votre disque dur: file-source.
Pour vous donner une idée, voici le code C qui permet la création d'un élément de test (fakesrc):
#include <gst/gst.h>
int
main (int argc,
char *argv[])
{
GstElement *element;
/* init GStreamer */
gst_init (&argc, &argv);
/* create element */
element = gst_element_factory_make ("fakesrc", "source");
if (!element) {
g_print ("Failed to create element of type ’fakesrc’ ");
return -1;
}
gst_object_unref (GST_OBJECT (element));
return 0;
}
Les lecteurs familiers avec GLib ne seront pas dépaysés...
Pads
Les pads sont les entrées/sorties des éléments. Ils servent à interconnecter les éléments entre eux. Il peut inclure des fonctions de vérification afin de s'assurer que le format des données correspond à ce qu'il attend. On peut distinguer deux sous ensembles de pad:
- les pads de type "sink", permettant de faire entrer des données dans un élément
- les pads de type "src" (source), permettant de faire sortie des données d'un élément
Il est possible d'associer plusieurs pads sinks et srcs à un même élément.
Exemples de pads pour l'élément vorbis-decoder:
Les liens entre les éléments se font toujours entre un pad src et un pad sink:
Les pads sont de loin les objets les plus complexes dans GStreamer. Ils contiennent un ensemble de paramètres (statique ou dynamique) permettant de définir les données attendues ou générées. Par exemple en tapant la commande "gst-inspect theoraenc" qui donne la description du plugin de décodage video Theroa:
Pad Templates:
SRC template: 'src'
Availability: Always
Capabilities:
video/x-raw-yuv
format: I420
framerate: [ 0/1, 2147483647/1 ]
width: [ 1, 2147483647 ]
height: [ 1, 2147483647 ]SINK template: 'sink'
Availability: Always
Capabilities:
video/x-theora
On peut y voir qu'il s'attend à avoir comme source une vidéo au format RAW-YUV, avec un nombre d'image par seconde et une taille pouvant varier selon le range affiché. En sortie, l'élement produira un vidéo au format THEORA.
Bins
Les bins sont des pipelines prédéfinis que l'on peut inclure comme de simple éléments dans une nouveau pipeline. Celà permet de simplifier grandement certaines actions complexe (rtpbin en est un bon exemple !).
Exemple de création d'un bin en langage C:
#include <gst/gst.h>
int
main (int argc,
char *argv[])
{
GstElement *bin, *pipeline, *source, *sink;
/* init */
gst_init (&argc, &argv);
/* create */
pipeline = gst_pipeline_new ("my_pipeline");
bin = gst_bin_new ("my_bin");
source = gst_element_factory_make ("fakesrc", "source");
sink = gst_element_factory_make ("fakesink", "sink");
/* First add the elements to the bin */
gst_bin_add_many (GST_BIN (bin), source, sink, NULL);
/* add the bin to the pipeline */
gst_bin_add (GST_BIN (pipeline), bin);
/* link the elements */
gst_element_link (source, sink);
[..]
}
Conclusion
J'espère que cette rapide introduction vous aura un peu éclairé sur les possibilités de GStreamer. Nhésitez pas à poser des questions et remarques sur le sujet dans l'espace GStreamer du forum de Nicolargo.
Sources: