Programmation Qt

Visionner une vidéo

Objectif : Être capable de visionner une vidéo à partir d’une application GUI/Qt.

Il y a plusieurs possibilités pour visionner une vidéo sous Qt :

  • en Qt4 avec le module Phonon qui contient des espaces de noms et des classes pour les fonctionnalités multimédia.
  • en Qt5 avec le module Multimedia qui fournit des fonctionnalités audio, vidéo, radio et caméra.

Remarque : Qt fournit aussi une classe QMovie pour afficher des animations simples sans son.

Le module Phonon (Qt4)

Phonon est un framework multimédia qui permet l’utilisation de contenu audio et vidéo dans les applications Qt. L’espace de noms Phonon contient une liste de toutes les classes, fonctions et espaces de noms fournis par le module.

Le document Phonon Overview présente l’architecture et les fonctionnalités de Phonon.

Les applications qui utilisent les classes de Phonon doivent être configurées pour intégrer le module Phonon. Il faut donc ajouter au fichier de projet .pro:

QT += phonon

D’autre part, il faudra aussi disposer des bibliothèques phonon pour le développement :

$ sudo apt-get install phonon libphonon-dev

Remarques : Sous Linux, Phonon utilise GStreamer (version 0.10 minimum) et ses plugins. Sous Windows, Phonon nécessite DirectX et DirectShow (version 9 ou plus).

Principe

Qt4 utilise donc le framework Phonon pour fournir les fonctionnalités de lecture des formats multimédia les plus courants. Les médias peuvent être lus à partir de fichiers ou diffusés sur un réseau, en utilisant un QURL.

Phonon a trois concepts de base :

  • les objets multimédias (en utilisant la classe MediaObject) : pour gérer une source multimédia ;
  • les sinks (un récepteur) : généralement un périphérique de rendu (pour une vidéo on utilisera un VideoWidget) ;
  • les paths : pour connecter les objets Phonon.

L’objet multimédia gère une source multimédia (ici un fichier vidéo) en offrant un contrôle de lecture simple, tel que le démarrage, l’arrêt et la pause de la lecture. Le récepteur (sink) sort le média de Phonon en rendant la vidéo sur un widget (ou en envoyant l’audio à une carte son).

Documentations :

Exemple

#ifndef MAFENETRE_H
#define MAFENETRE_H

#include <QtGui>

#include <Phonon/MediaObject>
#include <Phonon/VideoWidget>
#include <Phonon/VideoPlayer>

class MaFenetre : public QWidget
{
    Q_OBJECT

    public:
        explicit MaFenetre(QWidget *parent = 0);
        ~MaFenetre();
    
    private:
          Phonon::MediaObject *media;
          Phonon::VideoWidget *vwidget;

    signals:
    
    public slots:
};

#endif // MAFENETRE_H
#include "mafenetre.h"

MaFenetre::MaFenetre(QWidget *parent) : QWidget(parent)
{
    // instancie un objet multimedia
    media = new Phonon::MediaObject(this); // 1
    
    // instancie un récepteur
    vwidget = new Phonon::VideoWidget(this); // 2
    
    // connecte l'objet multimédia au récepteur
    Phonon::createPath(media, vwidget); // 3
    
    // pour l'affichage dans la fenêtre
    QVBoxLayout *layoutPrincipal = new QVBoxLayout;
    layoutPrincipal->addWidget(vwidget);
    setLayout(layoutPrincipal);
    setWindowTitle(QString::fromUtf8("player"));
    setFixedHeight(sizeHint().height());
    setFixedWidth(sizeHint().width());
    
    // associe le fichier vidéo à l'objet multimedia
    QString fichier = "/test.avi";
    media->setCurrentSource(QUrl::fromLocalFile(QCoreApplication::applicationDirPath() + fichier));  // 4
    
    // lecture de la vidéo
    media->play(); // 5
}

MaFenetre::~MaFenetre()
{
}

On obtient ceci :

Code source fourni : test-qt-video.zip

Pour aller plus loin : Media Player (example)

Le module Multimedia (Qt5)

Le module QtMultimedia est le remplaçant de Phonon pour Qt5. Ce module fournit des fonctionnalités audio, vidéo, radio et caméra.

Le document Multimedia Overview présente les fonctionnalités et les composants du module. Il existe aussi le document Video Overview pour les composants Vidéo.

Les applications qui utilisent les classes de QtMultimedia doivent être configurées pour intégrer les modules ci-dessous. Il faut donc ajouter au fichier de projet .pro:

QT += multimedia multimediawidgets

D’autre part, il faudra aussi disposer du module multimedia pour le développement (et des plugins pour les codecs) :

$ sudo apt-get install qtmultimedia5-dev qtmultimedia5-examples

Quelques classes de base :

  • La classe QMediaObject est la classe de base pour les objets multimédias : QMediaObject
  • La classe QMediaPlaylist fournit la gestion d’une liste de contenu multimédia à lire : QMediaPlaylist
  • La classe QMediaPlayer permet la lecture d’une source multimédia : QMediaPlayer
  • La classe QVideoWidget fournit un widget pour le rendu produit par un objet multimédia : QVideoWidget

Exemple de base :

#ifndef MAFENETRE_H
#define MAFENETRE_H

#include <QtWidgets>

#include <QtMultimedia>
#include <QtMultimediaWidgets>

class MaFenetre : public QWidget
{
    Q_OBJECT
public:
    explicit MaFenetre(QWidget *parent = 0);
    ~MaFenetre();
    
private:
      QMediaPlaylist *playlist;
      QMediaPlayer *player;
      QVideoWidget *videoWidget;

signals:
    
public slots:
    void stateChanged(QMediaPlayer::State state);
    void metaDataChanged();
    void metaDataChanged(const QString &key, const QVariant &value);
    void error(QMediaPlayer::Error error);
};

#endif // MAFENETRE_H
#include "mafenetre.h"
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsVideoItem>
#include <QDebug>

MaFenetre::MaFenetre(QWidget *parent) :
    QWidget(parent)
{
    QString fichier = QCoreApplication::applicationDirPath() + QString("/test.mpg");
    qDebug() << QUrl::fromLocalFile(fichier);
    
    playlist = new QMediaPlaylist;
    //playlist->addMedia(QUrl::fromLocalFile(QCoreApplication::applicationDirPath() + QString("/test.mpg")));
    //playlist->addMedia(QUrl::fromLocalFile(QCoreApplication::applicationDirPath() + QString("/test.mkv")));
    //playlist->addMedia(QUrl::fromLocalFile(QCoreApplication::applicationDirPath() + QString("/test.mp4")));
    //playlist->addMedia(QUrl::fromLocalFile(QCoreApplication::applicationDirPath() + QString("/test.ogv")));
    //playlist->addMedia(QUrl("http://example.com/movie.mp4"));
    //playlist->setCurrentIndex(1);    
    //qDebug() << playlist->media(0).canonicalUrl().toLocalFile();

    player = new QMediaPlayer;
    player->setMedia(QUrl::fromLocalFile(QCoreApplication::applicationDirPath() + QString("/test.mpg")));
    // ou :
    //player->setPlaylist(playlist);    

    // GUI 1
    QVBoxLayout *layoutPrincipal = new QVBoxLayout;
    videoWidget = new QVideoWidget(this);
    layoutPrincipal->addWidget(videoWidget);    
    player->setVideoOutput(videoWidget);    
    setLayout(layoutPrincipal);
    
    // GUI 2
    /*QGraphicsView * graphicsView = new QGraphicsView;
    QVBoxLayout *layoutPrincipal = new QVBoxLayout();
    layoutPrincipal->addWidget(graphicsView);    
    QGraphicsScene * scene = new QGraphicsScene;
    graphicsView->setScene(scene); 
    QGraphicsVideoItem *item = new QGraphicsVideoItem;
    player->setVideoOutput(item);
    graphicsView->scene()->addItem(item);
    graphicsView->showFullScreen();
    setLayout(layoutPrincipal);*/
    
    setWindowTitle(QString::fromUtf8("player"));
    setFixedWidth(320);
    setFixedHeight(240);
    // ou :
    //showFullScreen();

    connect(player, SIGNAL(stateChanged(QMediaPlayer::State)), this, SLOT(stateChanged(QMediaPlayer::State)));
    //connect(player, SIGNAL(metaDataChanged()), this, SLOT(metaDataChanged()));
    connect(player, SIGNAL(metaDataChanged(const QString &, const QVariant &)), this, SLOT(metaDataChanged(const QString &, const QVariant &)));
    connect(player, SIGNAL(error(QMediaPlayer::Error)), this, SLOT(error(QMediaPlayer::Error)));

    player->play();
}

MaFenetre::~MaFenetre()
{

}

void MaFenetre::stateChanged(QMediaPlayer::State state)
{
    qDebug() << Q_FUNC_INFO << state;
    /*if (state == QMediaPlayer::StoppedState)
    {
        videoWidget->update();
    }*/
}

void MaFenetre::metaDataChanged()
{
    qDebug() << player->availableMetaData();
    if (player->isMetaDataAvailable()) 
    {
        qDebug() << player->metaData(QMediaMetaData::Title).toString();
        qDebug() << player->metaData(QMediaMetaData::Size);
        qDebug() << player->metaData(QMediaMetaData::Duration);
        qDebug() << player->metaData(QMediaMetaData::Resolution);
    }
}

void MaFenetre::metaDataChanged(const QString &key, const QVariant &value)
{
    // "AudioBitRate", "AudioCodec", "PixelAspectRatio", "Resolution", "VideoCodec"
    if(key == "AudioCodec")
        qDebug() << key << value;
    if(key == "VideoCodec")
        qDebug() << key << value;
    if(key == "Resolution")
        qDebug() << key << value;
}

void MaFenetre::error(QMediaPlayer::Error error)
{
    qDebug() << Q_FUNC_INFO << player->errorString() << error;
}

Code source fourni : test-qt5-video.zip

Documentation :

Retour au sommaire