1. 程式人生 > >Qt+VLC播放多個視訊的Demo

Qt+VLC播放多個視訊的Demo

這個Demo做的是同時播放9個相同的視訊:


目前做的這個小Demo程式碼微微做了一點小優化,單獨封裝的類:

#ifndef SVLCCONTROL_H
#define SVLCCONTROL_H

#include <QWidget>
#include <QLabel>
struct libvlc_media_track_info_t;
struct libvlc_media_t;
struct libvlc_instance_t;
struct libvlc_media_player_t;
struct libvlc_event_t;

class SVLCControl : public QWidget
{
    Q_OBJECT
public:
    explicit SVLCControl(QLabel* lab, QWidget *parent = 0);

    bool load(const QString &filepath);
    void play();
    void pause();
    void stop();
    bool loadVlc(const QString &filepath);
    void freeVlc();
protected:
    static void vlcEvents(const libvlc_event_t *ev, void *param);

private:
    QLabel* m_lab = Q_NULLPTR;
    libvlc_instance_t *m_vlcInstance = Q_NULLPTR;
    libvlc_media_t *m_media = Q_NULLPTR;
    libvlc_media_player_t *m_mediaPlayer = Q_NULLPTR;

    QMutex m_mutex;
    qint64 m_duration = 0;
    bool m_bPlaying = false;
};

#endif // SVLCCONTROL_H
#include "svlccontrol.h"
#include <QDir>
#include <QFile>
#include <QGraphicsScene>
#include <QGraphicsProxyWidget>
#include <QGraphicsView>
#include "vlc/vlc.h"
#include <QDebug>

SVLCControl::SVLCControl(QLabel *lab, QWidget *parent) : QWidget(parent)
{
    m_lab = lab;
}

bool SVLCControl::load(const QString &filepath)
{
    if(filepath.isEmpty()){
        qDebug() << "filepath isEmpty";
        return false;
    }
    if(!QFile::exists(filepath)){
        qDebug() << "QFile no exists";
        return false;
    }
    bool bload = loadVlc(QDir::toNativeSeparators(filepath).toUtf8().constData());
    if(!bload){
        qDebug() << "bload no isEmpty";
        return false;
    }
    return true;
}

void SVLCControl::play()
{
    if(libvlc_Ended == libvlc_media_get_state(m_media)){
        stop();//vlc這個設定太奇怪了,當自然播放結束,重新播放還得主動呼叫一次stop();
    }
    libvlc_media_player_play(m_mediaPlayer);
}

void SVLCControl::pause()
{
    if((bool)libvlc_media_player_is_playing(m_mediaPlayer)){
        m_bPlaying = false;
        libvlc_media_player_set_pause(m_mediaPlayer, 1);//暫停
    }
}

void SVLCControl::stop()
{
    m_bPlaying = false;
    libvlc_media_player_stop(m_mediaPlayer);
}

bool SVLCControl::loadVlc(const QString &filepath)
{
    m_vlcInstance = libvlc_new(0, NULL);
    m_media = libvlc_media_new_path(m_vlcInstance, filepath.toUtf8().data());
    if(!m_media){
        freeVlc();
        return m_media;
    }
    qDebug() << "SVLCControl:loadVlc:" << qPrintable(filepath);
    m_mediaPlayer = libvlc_media_player_new_from_media(m_media);
    if(!m_mediaPlayer){
        freeVlc();
        return false;
    }
    libvlc_media_parse(m_media);
    libvlc_event_manager_t *em = libvlc_media_player_event_manager(m_mediaPlayer);
    libvlc_event_attach(em, libvlc_MediaPlayerTimeChanged, vlcEvents, this);
    libvlc_event_attach(em, libvlc_MediaPlayerEndReached, vlcEvents, this);
    libvlc_event_attach(em, libvlc_MediaPlayerStopped, vlcEvents, this);
    libvlc_event_attach(em, libvlc_MediaPlayerPlaying, vlcEvents, this);
    libvlc_event_attach(em, libvlc_MediaPlayerPaused, vlcEvents, this);

    libvlc_media_player_set_hwnd(m_mediaPlayer, (void *)m_lab->winId());
    return true;
}

void SVLCControl::freeVlc()
{
    if(m_media){
        libvlc_media_release(m_media);
        m_media = Q_NULLPTR;
    }
    if(m_mediaPlayer){
        libvlc_media_player_stop(m_mediaPlayer);
        libvlc_media_player_release(m_mediaPlayer);
        m_mediaPlayer = Q_NULLPTR;
    }
    if(m_vlcInstance){
        libvlc_release(m_vlcInstance);
        m_vlcInstance = Q_NULLPTR;
    }
}

void SVLCControl::vlcEvents(const libvlc_event_t *ev, void *param)
{
    Q_UNUSED(param);
    switch (ev->type) {
    case libvlc_MediaPlayerTimeChanged:
        break;
    case libvlc_MediaPlayerEndReached://不能在回撥裡呼叫stop();否則會卡死
        break;
    case libvlc_MediaPlayerStopped:
        qDebug() << "libvlc_MediaPlayerStopped";
        break;
    case libvlc_MediaPlayerPlaying:
        qDebug() << "libvlc_MediaPlayerPlay";
        break;
    case libvlc_MediaPlayerPaused:
        qDebug() << "libvlc_MediaPlayerPaused";
        break;
    }
}
呼叫方法:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QFileDialog>
#include <QLabel>
#include "svlccontrol.h"

namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
 private slots:
    void on_pushButton_clicked();
    void on_pB_Stop_clicked();
    void on_pB_Open_clicked();

private:
    Ui::MainWindow *ui;
    QFileDialog *m_fileDialog = Q_NULLPTR;
    QList <QLabel*> m_allBgs;
    QList <SVLCControl*> m_allVideos;
};

#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDir>
#include <QFile>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    m_fileDialog = new QFileDialog(this);
    m_fileDialog->setWindowTitle(tr("Open Video"));
    m_fileDialog->setDirectory(".");
    m_fileDialog->setNameFilter(tr("Video Files(*.mp4 *.mp3 *flv *3gp *rmvb)"));
    m_fileDialog->hide();
    qDebug() << "is:" << ui->widget->size();
    int tmpW = ui->widget->width()/3;
    int tmpH = ui->widget->height()/3;
    for(int i = 0; i < 9; i++) {
        QLabel* lab = new QLabel(ui->widget);
        lab->setFrameShape(QLabel::Shape::Box);
        lab->resize(tmpW - 1, tmpH - 1);
        lab->move(i%3*tmpW, i/3*tmpH);
        SVLCControl* vlcC = new SVLCControl(lab, this);
        m_allBgs << lab;
        m_allVideos << vlcC;
    }
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_clicked()
{
    if(ui->pushButton->text() == "播放") {
        foreach (SVLCControl* vlcT, m_allVideos) {
            vlcT->play();
        }
        ui->pushButton->setText("暫停");
    } else if(ui->pushButton->text() == "暫停") {
        foreach (SVLCControl* vlcT, m_allVideos) {
            vlcT->pause();
        }
        ui->pushButton->setText("播放");
    }
}

void MainWindow::on_pB_Stop_clicked()
{
    foreach (SVLCControl* vlcT, m_allVideos) {
        vlcT->stop();
    }
    ui->pushButton->setText("播放");
}

void MainWindow::on_pB_Open_clicked()
{
    foreach (SVLCControl* vlcT, m_allVideos) {
        vlcT->freeVlc();
    }
    m_fileDialog->show();
    if(m_fileDialog->exec() == QDialog::Accepted) {
        QString path = m_fileDialog->selectedFiles()[0];
        ui->lB_Path->setText(path);
        foreach (SVLCControl* vlcT, m_allVideos) {
            vlcT->load(path);
        }
    }
}