QT5视频播放器制作

这里使用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

QT5视频播放器制作_第1张图片

头文件

#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同一目录下即可。

你可能感兴趣的:(QT学习)