在用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
要播放視頻需要使用輔助類QVideoWidget
、QGraphicsVideoItem
,將輔助類對象設置爲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
對象,然後將QMediaPlayer
的VideoOutput
設置爲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();
}