QT學習之QMediaPlayer


在用FFmpeg與QT實現播放器之前,先看看QT自帶的播放器示例,研究下,是怎麼實現的。必然又需要看看需要使用哪些QT類來完成這個任務。

QMediaPlayer

QMediaPlayer類的定義這裏就不貼出來了,主要記錄一下關於類如何使用的關鍵信息
QMediaPlayer類的player播放狀態:State

狀態枚舉名稱 枚舉值 說明
StoppedState 0 播放停止狀態
PlayingState 1 播放狀態
PausedState 2 播放暫停狀態

QMediaPlayer類的媒體狀態:MediaStatus

狀態枚舉名稱 枚舉值 說明
UnknownMediaStatus 0 未知狀態
NoMedia 1 無媒體文件,player處於StoppedState
LoadingMedia 2 媒體文件加載中,player可以處於任何狀態
LoadedMedia 3 媒體文件已加載,player處於StoppedState
StalledMedia 4 媒體處於延遲或者暫時的中斷狀態,palyer處於 PlayingState或者PausedState
BufferingMedia 5 媒體正在緩衝數據,palyer處於 PlayingState或者PausedState
BufferedMedia 6 媒體緩衝數據完成,palyer處於 PlayingState或者PausedState
EndOfMedia 7 媒體結束,player處於StoppedState
InvalidMedia 8 非法的媒體文件,player處於StoppedState

QMediaPlayer類的player播放標誌位:Flags

狀態枚舉名稱 枚舉值 說明
LowLatency 1 播放未壓縮的音頻數據,播放表現爲低延時,主要播放beeps, ringtones等
StreamPlayback 2 播放基於 QIODevice構建的媒體文件,QMediaPlayer或自動選擇支持的流進行播放
VideoSurface 4 渲染視頻到QAbstractVideoSurface output

QMediaPlayer類的player錯誤標誌位:Error

狀態枚舉名稱 枚舉值 說明
NoError 0 無錯誤
ResourceError 1 媒體源錯誤
FormatError 2 格式錯誤,播放可能會丟失音頻或者視頻
NetworkError 3 網絡錯誤
AccessDeniedError 4 訪問權限錯誤
ServiceMissingError 5 服務丟失錯誤

QMediaPlayer類的屬性:

屬性名稱 取值類型 說明 訪問函數
audioAvailable const bool 音頻是否可用,audioAvailableChanged信號函數用於監控其狀態 bool isAudioAvailable() const
audioRole QAudio::Role 音頻流播放role QAudio::Role audioRole() const,void setAudioRole(QAudio::Role audioRole)
bufferStatus const int 緩衝數據的百分比,在開始播放或者回復播放之前 int bufferStatus() const, void bufferStatusChanged(int percentFilled)
currentMedia const QMediaContent 當前激活的媒體,在使用Playlist時,可能與mdia屬性不同 QMediaContent currentMedia() const, void currentMediaChanged(const QMediaContent &media)
duration const qint64 currentMedia的播放時長,單位ms qint64 duration() const, void durationChanged(qint64 duration)
media QMediaContent 激活的並被使用的媒體源 QMediaContent media() const, void setMedia(const QMediaContent &media, QIODevice *stream = nullptr), void mediaChanged(const QMediaContent &media)
playbackRate qreal 當前媒體的播放速度,默認爲1.0 qreal playbackRate() const, void setPlaybackRate(qreal rate), void playbackRateChanged(qreal rate)
playlist QMediaPlaylist* 播放列表 QMediaPlaylist * playlist() const, void setPlaylist(QMediaPlaylist *playlist),
volume int 音量,取值範圍0—100 int volume() const, void setVolume(int volume), void volumeChanged(int volume

播放音頻步驟

player = new QMediaPlayer;
connect(player, SIGNAL(positionChanged(qint64)), this, SLOT(positionChanged(qint64)));
player->setMedia(QUrl::fromLocalFile("./Music/test.mp3"));
player->setVolume(50);
player->play();

播放視頻頻步驟

QMediaPlayer要播放視頻需要使用輔助類QVideoWidgetQGraphicsVideoItem,將輔助類對象設置爲QMediaPlayer的視頻輸出窗口,就可以播放視頻。

playlist = new QMediaPlaylist;
playlist->addMedia(QUrl("movie1.mp4"));
playlist->addMedia(QUrl("movie2.mp4"));
playlist->addMedia(QUrl("movie3.mp4"));
playlist->setCurrentIndex(1);

player = new QMediaPlayer;
player->setPlaylist(playlist);

videoWidget = new QVideoWidget;
player->setVideoOutput(videoWidget);
videoWidget->show();

player->play();

QMediaPlaylist

QMediaPlaylist類,可以爲QMediaPlayer提供一個播放列表,它其實是QMediaContent對象的列表,
QMediaPlayer通過函數setPlayList來設置一個播放列表
QMediaPlaylist通過函數addMedia想播放列表添加一個媒體文件
QMediaPlaylist類的播放模式:PlaybackMode

狀態枚舉名稱 枚舉值 說明
CurrentItemOnce 0 當前選中的媒體文件僅播放一次
CurrentItemInLoop 1 當前選中的媒體文件循環播放
Sequential 2 從當前選中的媒體文件開始,列表中的文件順序播放一次直到最後一個文件
Loop 3 列表中的文件順序循環播放
Random 4 列表中的文件隨機播放

QMediaPlaylist屬性:

名稱 類型 說明
currentIndex int 當前播放的媒體文件在列表中的索引
currentMedia const QMediaContent 當前選中的媒體文件
palybackMode QMediaPlaylist::PlaybackMode 從當前選中的媒體文件開始,列表中的文件順序播放一次直到最後一個文件

QMediaPlaylist函數:

返回值類型 函數名稱 描述說明
bool addMedia(const QMediaContent &content) Public Functions,列表添加單個媒體文件
bool addMedia(const QList &items) Public Functions,列表添加多個媒體文件
int currentIndex() const 獲得當前播放媒體的索引
QMediaContent currentMedia() const 獲得當前播放的媒體文件
QMediaPlaylist::Error error() const 列表錯誤狀態
QString errorString() const 播放列表錯誤字符串信息
bool insertMedia(int pos, const QMediaContent &content) 向播放列表插入一個媒體文件
bool insertMedia(int pos, const QList &items) 向播放列表插入多個媒體文件
bool isEmpty() const 清空列表
bool isReadOnly() const 清空列表
void load(const QNetworkRequest &request, const char *format = nullptr) 加載網絡媒體
void load(const QUrl &location, const char *format = nullptr) 加載本地媒體文件
void load(QIODevice *device, const char *format = nullptr) 加載IO設備文件
QMediaContent media(int index) const 獲得指定索引的媒體文件
int mediaCount() const 統計播放列表的文件數量
bool moveMedia(int from, int to) 根據位置參數移動媒體文件
int nextIndex(int steps = 1) const 當前播放文件的下一個文件索引
PlaybackMode playbackMode() const 獲取列表播放模式
int previousIndex(int steps = 1) const 當前播放文件的上一個文件索引
bool removeMedia(int pos) 刪除列表中指定位置的文件
bool removeMedia(int start, int end) 刪除列表中start到end之間的文件
bool save(const QUrl &location, const char *format = nullptr) 保存列表QUrl 指定位置
bool save(QIODevice *device, const char *format) 保存列表到IO設備
void setPlaybackMode(QMediaPlaylist::PlaybackMode mode) 設置列表播放模式

QMediaPlaylist槽:

返回值類型 函數名稱 描述說明
void next() 下一個文件
void previous() 上一個文件
void setCurrentIndex(int playlistPosition) 設置當前播放媒體的索引
void shuffle() 媒體順序洗牌,重建媒體的索引

QMediaPlaylist信號:

返回值類型 函數名稱 描述說明
void currentIndexChanged(int position) 當前索引改變信號
void currentMediaChanged(const QMediaContent &content) 當前媒體文件改變信號
void loadFailed() 加載失敗信號
void loaded() 加載完成信號
void mediaAboutToBeInserted(int start, int end) 媒體即將被插入信號
void mediaAboutToBeRemoved(int start, int end) 媒體即將被刪除信號
void mediaChanged(int start, int end) 媒體文件改變信號
void mediaInserted(int start, int end) 媒體文件插入信號
void mediaRemoved(int start, int end) 媒體文件刪除信號
void playbackModeChanged(QMediaPlaylist::PlaybackMode mode) 列表播放模式改變信號

QVideoWidget

QVideoWidget是一個用來展示視頻的類,需要先定義一個QMediaPlayer對象,然後將QMediaPlayerVideoOutput設置爲QVideoWidget對象即可
QVideoWidget屬性:

名稱 類型 說明
aspectRatioMode : Qt::AspectRatioMode 屏幕高寬比
brightness int 亮度
contrast int 對比度
fullScreen bool 是否全屏
hue int 色調
mediaObject QMediaObject* const 視頻媒體對象
saturation int 飽和度

QVideoWidget函數:

返回值類型 函數名稱 描述說明
Qt::AspectRatioMode aspectRatioMode() const 獲取視頻畫面寬高比
int saturation() const 獲取飽和度
int brightness() const 獲取亮度
int contrast() const 獲取對比度
int hue() const 獲取色調
bool isFullScreen() const 獲取全屏狀態

QVideoWidget槽:

返回值類型 函數名稱 描述說明
void setAspectRatioMode(Qt::AspectRatioMode mode) 設置寬高比
void setBrightness(int brightness) 設置亮度
void setContrast(int contrast) 設置對比度
void setFullScreen(bool fullScreen) 設置全屏狀態
void setHue(int hue) 設置色調
void setSaturation(int saturation) 設置飽和度

QMediaPlaylist信號:

返回值類型 函數名稱 描述說明
void brightnessChanged(int brightness) 亮度改變信號
void contrastChanged(int contrast) 對比度改變信號
void fullScreenChanged(bool fullScreen) 全屏狀態信號
void hueChanged(int hue) 色調改變信號
void saturationChanged(int saturation) 飽和度改變信號

完整示例代碼

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QMediaPlayer>
class QMediaPlaylist;

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_pushButton_2_clicked();

    void on_pushButton_3_clicked();

    void on_horizontalSlider_sliderMoved(int position);

private:
    Ui::MainWindow *ui;
    QMediaPlayer *player;

    QMediaPlaylist *playlist;

private slots:
    void updatePosition(qint64 position);

    void stateChanged(QMediaPlayer::State state);
    void mediaStatusChanged(QMediaPlayer::MediaStatus status);
    void showError(QMediaPlayer::Error error);

    void metaDataAvailableChanged(bool available);
};

#endif // MAINWINDOW_H

mainwindow.cpp

// mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMediaPlaylist>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    player = new QMediaPlayer(this);
    connect(player, &QMediaPlayer::positionChanged,
            this, &MainWindow::updatePosition);

    connect(player, &QMediaPlayer::stateChanged, this, &MainWindow::stateChanged);
    connect(player, &QMediaPlayer::mediaStatusChanged,
            this, &MainWindow::mediaStatusChanged);
    connect(player, static_cast<void(QMediaPlayer::*)(QMediaPlayer::Error)>
            (&QMediaPlayer::error), this, &MainWindow::showError);

    connect(player, &QMediaPlayer::metaDataAvailableChanged,
            this, &MainWindow::metaDataAvailableChanged);


    playlist = new QMediaPlaylist;
    playlist->addMedia(QUrl::fromLocalFile("/home/luke/Music/music.mp3"));
    playlist->addMedia(QUrl::fromLocalFile("/home/luke/Music/music2.mp3"));
    playlist->addMedia(QUrl::fromLocalFile("/home/luke/Music/music3.mp3"));
    playlist->setCurrentIndex(0);
    playlist->setPlaybackMode(QMediaPlaylist::Loop);
    player->setPlaylist(playlist);
}


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

void MainWindow::on_pushButton_clicked()
{ // 播放
    player->play();
}

void MainWindow::on_pushButton_2_clicked()
{ // 暫停
    player->pause();
}

void MainWindow::on_pushButton_3_clicked()
{ // 停止
    player->stop();
}


void MainWindow::on_horizontalSlider_sliderMoved(int position)
{ // 設置播放進度
    player->setPosition(position * 1000);
}

void MainWindow::updatePosition(qint64 position)
{ // 更新滑塊顯示
    ui->horizontalSlider->setMaximum(player->duration() / 1000);
    ui->horizontalSlider->setValue(position / 1000);
}

void MainWindow::mediaStatusChanged(QMediaPlayer::MediaStatus status)
{
    switch (status) {
    case QMediaPlayer::UnknownMediaStatus:
        ui->label->setText(tr("媒體未知狀況!"));
        break;
    case QMediaPlayer::NoMedia:
        ui->label->setText(tr("沒有媒體文件!"));
        break;
    case QMediaPlayer::BufferingMedia:
        ui->label->setText(tr("正在緩衝媒體文件!"));
        break;
    case QMediaPlayer::BufferedMedia:
        ui->label->setText(tr("媒體文件緩衝完成!"));
        break;
    case QMediaPlayer::LoadingMedia:
        ui->label->setText(tr("正在加載媒體!"));
        break;
    case QMediaPlayer::StalledMedia:
        ui->label->setText(tr("播放停滯!"));
        break;
    case QMediaPlayer::EndOfMedia:
        ui->label->setText(tr("播放結束!"));
        break;
    case QMediaPlayer::LoadedMedia:
        ui->label->setText(tr("媒體加載完成!"));
        break;
    case QMediaPlayer::InvalidMedia:
        ui->label->setText(tr("不可用的媒體文件!"));
        break;
    default: break;
    }
}

void MainWindow::stateChanged(QMediaPlayer::State state)
{
    switch (state) {
    case QMediaPlayer::StoppedState:
        ui->label_2->setText(tr("停止狀態!"));
        break;
    case QMediaPlayer::PlayingState:
        ui->label_2->setText(tr("播放狀態!"));
        break;
    case QMediaPlayer::PausedState:
        ui->label_2->setText(tr("暫停狀態!"));
        break;
    default: break;
    }
}

void MainWindow::showError(QMediaPlayer::Error error)
{
    switch (error) {
    case QMediaPlayer::NoError:
        ui->label_3->setText(tr("沒有錯誤!"));
        break;
    case QMediaPlayer::ResourceError:
        ui->label_3->setText(tr("媒體資源無法被解析!"));
        break;
    case QMediaPlayer::FormatError:
        ui->label_3->setText(tr("不支持該媒體格式!"));
        break;
    case QMediaPlayer::NetworkError:
        ui->label_3->setText(tr("發生了一個網絡錯誤!"));
        break;
    case QMediaPlayer::AccessDeniedError:
        ui->label_3->setText(tr("沒有播放權限!"));
        break;
    case QMediaPlayer::ServiceMissingError:
        ui->label_3->setText(tr("沒有發現有效的播放服務!"));
        break;
    default: break;
    }
}

// 獲取元數據
void MainWindow::metaDataAvailableChanged(bool available)
{
    if(available) {
        QString title = player->metaData("Title").toString();
        QString author = player->metaData("Author").toString();
        setWindowTitle(title + "-" + author);
    }
}

main.cpp

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章