Introduction

Qt, dans son souci de framework généraliste, n’implémente pas toujours tout ce dont on peut avoir besoin, surtout lorsque cela n’est pas d’usage courant. Les vidéos font partie de ce qui n’est pas couvert par Qt. Cependant, un grand nombre de librairies et autres backends existent. Nous allons voir comment utiliser l’une d’entre elle: VLC.

Pré-requis

Voici ce dont vous aurez besoin :

  • Les librairies VLC >= 0.8.6 (Page de téléchargement)
  • La documentation des fonctions internes de VLC
  • Il semblerait que VLC soit difficilement compilable sous Visual C++. Comme ce tutoriel suppose de pouvoir lier votre application avec les libraires VLC, les personnes désireuses de développer sous Windows devront utiliser Mingw pour générer leur application.

Pour compiler VLC 0.9.0 (la version actuellement en cours de développement, récupérable depuis le SVN), vous aurez besoin de :

Lecteur vidéo

Ce tutoriel détaille la manière d'utiliser l'API VLC au travers d'une application Qt.

L’avantage de cette méthode est que le contrôle de VLC est plus simple et précis et ne nécessite pas d’exécuter/piloter un processus externe (contrairement à l'utilisation de MPlayer).

Nous allons créer un petit exemple simple de lecteur vidéo, ce dernier permettant :

  • d’initialiser VLC,
  • de charger un flux vidéo,
  • de naviguer dans la vidéo (avance/retour),
  • de modifier le volume.

Une image valant mieux qu'un long discours, voici une capture d'écran du résultat final :

vlc.jpg

Le code de ce tutorial (source + .pro)

Compilation

La compilation de l’exemple nécessite bien entendu les includes et les libraires de VLC. Celles ci doivent êtres dans dans les chemins de recherche

Linux/Unix

Voici le fichier pro typique :

TEMPLATE = app
DEPENDPATH += .
INCLUDEPATH += . 
SOURCES += tuto_vlc.cpp
LIBS+=-lvlc

Explications

Si l'on résume les étapes nécessaires à la lecture d'un vidéo dans une application Qt :

  1. initialiser un contexte VLC,
  2. ajouter un flux à la playlist,
  3. rediriger la fenêtre vidéo de sortie vlc sur un widget Qt de l'application,
  4. démarrer la lecture du flux.

Certaines fonctions de l'API de VLC seront détaillées. Toutes ces fonctions et bien plus encore sont disponibles dans la documentation de VLC.

Initialisation d'un contexte VLC

Normalement seule l'inclusion de l'entête vlc/libvlc.h est nécessaire pour utiliser toutes les fonctions VLC.

#include <vlc/libvlc.h>

VLC reporte toutes ses erreurs dans une structure particulière libvlc_exception_t. Avant tout appel à une fonction VLC, il nous faudra donc une telle structure :

libvlc_exception_t _vlcexcep; //déclaration de la structure
libvlc_exception_init (&_vlcexcep); //initialisation de la structure

Quelques fonctions pratiques à utiliser avec libvlc_exception_t :

if(libvlc_exception_raised(&_vlcexcep)!=0) {....} //teste si une erreur a eu lieu.
libvlc_exception_get_message(&_vlcexcep); //retourne le message d'erreur
libvlc_exception_clear(&_vlcexcep); //efface la/les erreurs précédentes

Il est maintenant temps de créer un contexte VLC, de type libvlc_instance_t, nécessaire à la plupart des fonctions :

libvlc_instance_t *_vlcinstance;
_vlcinstance=libvlc_new(argc,argv,&_vlcexcep);

Il n'est possible de lire qu'un seul flux vidéo à la fois par contexte. Pour lire plusieurs flux en parallèle, il faut donc initialiser plusieurs contextes. Lorsqu'un contexte, n'est plus utile, ne pas oublier de le libérer :

libvlc_destroy (_vlcinstance, &_vlcexcep);

Ajout d'un flux

Le chargement d'un flux vidéo se fait dans un contexte initialisé et dans l'élément playlist de VLC (se réfèrer à la doc quant à la gestion des playlist, ce tutoriel n'en faisant pas d'autres mentions).

libvlc_playlist_clear(_vlcinstance,&_vlcexcep); //on vide la playlist
libvlc_playlist_add (_vlcinstance,URL,NULL,&_vlcexcep);//on ajoute le nouveau flux

Note : à ce niveau, le fichier est dans la playlist, il n'est pas en cours de lecture ou n'a pas interrompu la lecture en cours.

Avec URL une chaine de caractère de la forme (principalement) :

Type Forme
Fichier local file://chemin
Url http http://ip:port/file
Fichier ftp ftp://ip:port/file
DVD dvd://[device]
Flux UDP udp:[]@[][:]%%

Redirection du flux sur un widget Qt

La redirection de la sortie vidéo sur un widget de l'application est une des étapes les plus importantes pour l'intégration (ce n'est pas la plus compliquée ;-) ).

A noter que VLC, se chargera d'adapter la taille de la vidéo à la taille du widget tout en conservant l'aspect de la video (VLC se chargera aussi de resizer la video si la taille du widget venait a changer en cours de lecture).

N'importe quel widget peut servir pour afficher une video, mais dans la mesure ou il sera complètement recouvert, un simple QWidget suffit.

//Notez l'usage de Widget->winId() pour indiquer on dessiner la video
libvlc_video_set_parent(_vlcinstance ,Widget->winId(),&_vlcexcep);

Functions vidéos/audios

Certaines fonctions requièrent un pointeur sur libvlc_input_t .Pour obtenir ce pointeur, un flux doit etre en cours de lecture/pause :

libvlc_input_t *input=libvlc_playlist_get_input (_vlcinstance,&_vlcexcep); //obtenir un pointeur input
libvlc_input_free (input); //il est en general de bon ton de libérer input après usage
Contrôle de la vidéo
  • Démarrer la lecture :
libvlc_playlist_play (_vlcinstance , -1, 0, NULL, &_vlcexcep);
// avec :
//          -1 pour indiquer de lire l'element suivant de la playlist
//          0 le nombre d'option a passer au flux a lire
//          NULL : les options
  • Stopper la lecture :
libvlc_playlist_stop (_vlcinstance, &_vlcexcep);
  • Mettre en pause la lecture :
libvlc_playlist_pause (_vlcinstance, &_vlcexcep);
  • Connaître l'état :
int etat=libvlc_playlist_isplaying(_vlcinstance, &_vlcexcep);
//etat=0 si stop ou pause
//etat=1 si lecture en cours
  • Lire en boucle :
int loop=1; //mettre a 0 pour stopper la lecture en boucle
libvlc_playlist_loop (_vlcinstance, loop,&_vlcexcep);
  • Connaître la durée totale du flux (nécessite un pointeur input) :
long long duree=libvlc_input_get_length (input, &_vlcexcep);
  • Connaître la position actuelle en ms (nécessite un pointeur input) :
long long position=libvlc_input_get_time (input, &_vlcexcep);
  • Se positionner dans le flux (position en ms - nécessite un pointeur input) :
libvlc_input_set_time (input, 42000,&_vlcexcep); //se positionne a 42 sec
  • Connaître la position actuelle en pourcentage (nécessite un pointeur input) :
float posEnPourcent=libvlc_input_get_position (input, &_vlcexcep)*100.0;
  • Se positionner dans le flux (position en pourcentage du temps total - nécessite un pointeur input) :
libvlc_input_set_position(input, 0.42f,&_vlcexcep); // se positionne a 42% du flux ???
Contrôle du volume
  • Obtenir la valeur du volume comprise entre 0 et 100 - 0 étant le minimum :
int volume=libvlc_audio_get_volume (_vlcinstance, &_vlcexcep);
  • Positionner le volume (valeur en 0 et 100) :
libvlc_audio_set_volume (_vlcinstance, 42,&_vlcexcep); //volume a 42%