这里使用QT自带的QMediaPlayer
QMediaPlayer是对底层播放框架DirectShowPlayerService的封装,具体格式依赖播放框架,Windows上就是DirectShow,安装LAV Filters之类的DirectShow解码框架就可以支持更多的格式,Linux下是GStreamer
附上两个链接
LAVFilters论坛
LAVFilters下载
安装完成后即可支持更多格式的视频播放,不再提示DirectShowPlayerService::doRender: Unresolved error code 80040266这样的错误。
或者下载安装k-lite解码器
http://www.codecguide.com/download_k-lite_codec_pack_standard.htm
头文件
#pragma once
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "ui_QtMediaplayer.h"
class VideoWidget : public QVideoWidget
{
Q_OBJECT
public:
VideoWidget(QWidget *parent = 0);
protected:
void keyPressEvent(QKeyEvent *event) override;
void mouseDoubleClickEvent(QMouseEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
};
class QtMediaplayer : public QWidget
{
Q_OBJECT
public:
QtMediaplayer(QWidget *parent = Q_NULLPTR);
~QtMediaplayer();
bool isPlayerAvailable() const;
signals:
void fullScreenChanged(bool fullScreen);
private slots:
void open();
void durationChanged(qint64 duration);
void positionChanged(qint64 progress);
void metaDataChanged();
void playClicked();
void updateRate();
void setState(QMediaPlayer::State state);
void seek(int seconds);
void statusChanged(QMediaPlayer::MediaStatus status);
void bufferingProgress(int progress);
void videoAvailableChanged(bool available);
void displayErrorMessage();
private:
void setTrackInfo(const QString &info);
void setStatusInfo(const QString &info);
void handleCursor(QMediaPlayer::MediaStatus status);
void updateDurationInfo(qint64 currentInfo);
QMediaPlayer *player;
//QMediaPlaylist *playlist;
VideoWidget *videoWidget;
QLabel *coverLabel;
QToolButton *playButton;
QComboBox *rateBox;
QSlider *slider;
QLabel *labelDuration;
QPushButton *fullScreenButton;
QVideoProbe *videoProbe;
QAudioProbe *audioProbe;
QString trackInfo;
QString statusInfo;
qint64 duration;
private:
Ui::QtMediaplayerClass ui;
};
cpp
#include
#include
#include
#include
#include
#include
#include
#include
#include "QtMediaplayer.h"
VideoWidget::VideoWidget(QWidget *parent)
: QVideoWidget(parent)
{
setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
QPalette p = palette();
p.setColor(QPalette::Window, Qt::black);
setPalette(p);
setAttribute(Qt::WA_OpaquePaintEvent);
}
void VideoWidget::keyPressEvent(QKeyEvent *event)
{
if (event->key() == Qt::Key_Escape && isFullScreen()) {
setFullScreen(false);
event->accept();
}
else if (event->key() == Qt::Key_Enter && event->modifiers() & Qt::Key_Alt) {
setFullScreen(!isFullScreen());
event->accept();
}
else {
QVideoWidget::keyPressEvent(event);
}
}
void VideoWidget::mouseDoubleClickEvent(QMouseEvent *event)
{
setFullScreen(!isFullScreen());
event->accept();
}
void VideoWidget::mousePressEvent(QMouseEvent *event)
{
QVideoWidget::mousePressEvent(event);
}
QtMediaplayer::QtMediaplayer(QWidget *parent)
: QWidget(parent)
, videoWidget(0)
, coverLabel(0)
, slider(0)
{
ui.setupUi(this);
player = new QMediaPlayer(this);
connect(player, SIGNAL(durationChanged(qint64)), SLOT(durationChanged(qint64)));
connect(player, SIGNAL(positionChanged(qint64)), SLOT(positionChanged(qint64)));
connect(player, SIGNAL(metaDataChanged()), SLOT(metaDataChanged()));
connect(player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)),
this, SLOT(statusChanged(QMediaPlayer::MediaStatus)));
connect(player, SIGNAL(bufferStatusChanged(int)), this, SLOT(bufferingProgress(int)));
connect(player, SIGNAL(videoAvailableChanged(bool)), this, SLOT(videoAvailableChanged(bool)));
connect(player, SIGNAL(error(QMediaPlayer::Error)), this, SLOT(displayErrorMessage()));
connect(player, SIGNAL(stateChanged(QMediaPlayer::State)), this, SLOT(setState(QMediaPlayer::State)));
videoWidget = new VideoWidget(this);
player->setVideoOutput(videoWidget);
slider = new QSlider(Qt::Horizontal, this);
slider->setRange(0, player->duration() / 1000);
labelDuration = new QLabel(this);
connect(slider, SIGNAL(sliderMoved(int)), this, SLOT(seek(int)));
videoProbe = new QVideoProbe(this);
videoProbe->setSource(player);
audioProbe = new QAudioProbe(this);
audioProbe->setSource(player);
QPushButton *openButton = new QPushButton(tr("Open"), this);
connect(openButton, SIGNAL(clicked()), this, SLOT(open()));
fullScreenButton = new QPushButton(tr("FullScreen"), this);
fullScreenButton->setCheckable(true);
playButton = new QToolButton(this);
playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay));
connect(playButton, SIGNAL(clicked()), this, SLOT(playClicked()));
rateBox = new QComboBox(this);
rateBox->addItem("0.5x", QVariant(0.5));
rateBox->addItem("1.0x", QVariant(1.0));
rateBox->addItem("2.0x", QVariant(2.0));
rateBox->setCurrentIndex(1);
connect(rateBox, SIGNAL(activated(int)), this, SLOT(updateRate()));
QBoxLayout *displayLayout = new QHBoxLayout;
displayLayout->addWidget(videoWidget);
QBoxLayout *controlLayout = new QHBoxLayout;
controlLayout->setMargin(0);
controlLayout->addWidget(openButton);
controlLayout->addStretch(1);
controlLayout->addWidget(playButton);
controlLayout->addStretch(1);
controlLayout->addWidget(rateBox);
controlLayout->addStretch(1);
controlLayout->addWidget(fullScreenButton);
QBoxLayout *layout = new QVBoxLayout;
layout->addLayout(displayLayout, 10);
QHBoxLayout *hLayout = new QHBoxLayout;
hLayout->addWidget(slider);
hLayout->addWidget(labelDuration);
layout->addLayout(hLayout);
layout->addLayout(controlLayout);
setLayout(layout);
if (!isPlayerAvailable()) {
QMessageBox::warning(this, tr("Service not available"),
tr("The QMediaPlayer object does not have a valid service.\n"\
"Please check the media service plugins are installed."));
openButton->setEnabled(false);
fullScreenButton->setEnabled(false);
}
metaDataChanged();
}
QtMediaplayer::~QtMediaplayer()
{
}
bool QtMediaplayer::isPlayerAvailable() const
{
return player->isAvailable();
}
void QtMediaplayer::open()
{
QFileDialog fileDialog(this);
fileDialog.setAcceptMode(QFileDialog::AcceptOpen);
fileDialog.setWindowTitle(tr("Open Files"));
QStringList supportedMimeTypes = player->supportedMimeTypes();
if (!supportedMimeTypes.isEmpty()) {
supportedMimeTypes.append("audio/x-m3u"); // MP3 playlists
fileDialog.setMimeTypeFilters(supportedMimeTypes);
}
fileDialog.setDirectory(QStandardPaths::standardLocations(QStandardPaths::MoviesLocation).value(0, QDir::homePath()));
if (fileDialog.exec() == QDialog::Accepted)
{
player->setMedia(fileDialog.selectedUrls().at(0));
player->play();
}
}
void QtMediaplayer::durationChanged(qint64 duration)
{
this->duration = duration / 1000;
slider->setMaximum(duration / 1000);
}
void QtMediaplayer::positionChanged(qint64 progress)
{
if (!slider->isSliderDown()) {
slider->setValue(progress / 1000);
}
updateDurationInfo(progress / 1000);
}
void QtMediaplayer::metaDataChanged()
{
if (player->isMetaDataAvailable()) {
setTrackInfo(QString("%1 - %2")
.arg(player->metaData(QMediaMetaData::AlbumArtist).toString())
.arg(player->metaData(QMediaMetaData::Title).toString()));
if (coverLabel) {
QUrl url = player->metaData(QMediaMetaData::CoverArtUrlLarge).value();
coverLabel->setPixmap(!url.isEmpty()
? QPixmap(url.toString())
: QPixmap());
}
}
}
void QtMediaplayer::playClicked()
{
switch (player->state()) {
case QMediaPlayer::StoppedState:
case QMediaPlayer::PausedState:
player->play();
break;
case QMediaPlayer::PlayingState:
player->pause();
break;
}
}
void QtMediaplayer::updateRate()
{
player->setPlaybackRate(rateBox->itemData(rateBox->currentIndex()).toDouble());
}
void QtMediaplayer::setState(QMediaPlayer::State state)
{
switch (state) {
case QMediaPlayer::PlayingState:
playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPause));
break;
case QMediaPlayer::PausedState:
playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay));
break;
}
}
void QtMediaplayer::seek(int seconds)
{
player->setPosition(seconds * 1000);
}
void QtMediaplayer::statusChanged(QMediaPlayer::MediaStatus status)
{
handleCursor(status);
// handle status message
switch (status) {
case QMediaPlayer::UnknownMediaStatus:
case QMediaPlayer::NoMedia:
case QMediaPlayer::LoadedMedia:
case QMediaPlayer::BufferingMedia:
case QMediaPlayer::BufferedMedia:
setStatusInfo(QString());
break;
case QMediaPlayer::LoadingMedia:
setStatusInfo(tr("Loading..."));
break;
case QMediaPlayer::StalledMedia:
setStatusInfo(tr("Media Stalled"));
break;
case QMediaPlayer::EndOfMedia:
QApplication::alert(this);
break;
case QMediaPlayer::InvalidMedia:
displayErrorMessage();
break;
}
}
void QtMediaplayer::handleCursor(QMediaPlayer::MediaStatus status)
{
#ifndef QT_NO_CURSOR
if (status == QMediaPlayer::LoadingMedia ||
status == QMediaPlayer::BufferingMedia ||
status == QMediaPlayer::StalledMedia)
setCursor(QCursor(Qt::BusyCursor));
else
unsetCursor();
#endif
}
void QtMediaplayer::bufferingProgress(int progress)
{
setStatusInfo(tr("Buffering %4%").arg(progress));
}
void QtMediaplayer::videoAvailableChanged(bool available)
{
if (!available) {
disconnect(fullScreenButton, SIGNAL(clicked(bool)),
videoWidget, SLOT(setFullScreen(bool)));
disconnect(videoWidget, SIGNAL(fullScreenChanged(bool)),
fullScreenButton, SLOT(setChecked(bool)));
videoWidget->setFullScreen(false);
}
else {
connect(fullScreenButton, SIGNAL(clicked(bool)),
videoWidget, SLOT(setFullScreen(bool)));
connect(videoWidget, SIGNAL(fullScreenChanged(bool)),
fullScreenButton, SLOT(setChecked(bool)));
if (fullScreenButton->isChecked())
videoWidget->setFullScreen(true);
}
}
void QtMediaplayer::setTrackInfo(const QString &info)
{
trackInfo = info;
if (!statusInfo.isEmpty())
setWindowTitle(QString("%1 | %2").arg(trackInfo).arg(statusInfo));
else
setWindowTitle(trackInfo);
}
void QtMediaplayer::setStatusInfo(const QString &info)
{
statusInfo = info;
if (!statusInfo.isEmpty())
setWindowTitle(QString("%1 | %2").arg(trackInfo).arg(statusInfo));
else
setWindowTitle(trackInfo);
}
void QtMediaplayer::displayErrorMessage()
{
setStatusInfo(player->errorString());
}
void QtMediaplayer::updateDurationInfo(qint64 currentInfo)
{
QString tStr;
if (currentInfo || duration) {
QTime currentTime((currentInfo / 3600) % 60, (currentInfo / 60) % 60, currentInfo % 60, (currentInfo * 1000) % 1000);
QTime totalTime((duration / 3600) % 60, (duration / 60) % 60, duration % 60, (duration * 1000) % 1000);
QString format = "mm:ss";
if (duration > 3600)
format = "hh:mm:ss";
tStr = currentTime.toString(format) + " / " + totalTime.toString(format);
}
labelDuration->setText(tStr);
}
main
#include "QtMediaplayer.h"
#include
#include
#include
#include
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QCoreApplication::setApplicationName("Player Example");
QCoreApplication::setOrganizationName("QtProject");
QCoreApplication::setApplicationVersion(QT_VERSION_STR);
QCommandLineParser parser;
parser.setApplicationDescription("Qt MultiMedia Player Example");
parser.addHelpOption();
parser.addVersionOption();
parser.addPositionalArgument("url", "The URL to open.");
parser.process(app);
QtMediaplayer player;
#if defined(Q_WS_SIMULATOR)
player.setAttribute(Qt::WA_LockLandscapeOrientation);
player.showMaximized();
#else
player.show();
#endif
return app.exec();
}
如果发布后,发现报错:Error : The QMediaPlayer object does not have a valid service ;
则需要找到 plugins / mediaservice,将整个mediaservice文件夹复制到与exe同一目录下即可。