I have a C++ on windows GUI project which we build using visual studio 2017. The GUI is written using QT 5. We dont use qt creator. In one of the widget I have to play a video using QT for which I am trying to use QMediaPlayer. I took a code snippet from the documentation. In the gui we select a file and then click on the play button which is supposed to play the video.
Code builds properly but while running video is not displayed and the widget screen remains blank. The m_mediaPlayer->state() and m_mediaPlayer->mediaStatus() both are always 0.
After the call to API setMedia() we see a mediaplayer error 5 i.e. QMediaPlayer::ServiceMissingError
How to play the video using qt api in this c++ windows code?
Code is as follows:
Header File
#include <QFileDialog>
#include <QStandardPaths>
#include <QtMultimedia/qmediacontent.h>
#include <QtMultimedia/qmediaplayer.h>
#include <QtMultimediaWidgets/qvideowidget.h>
#include <QtMultimedia/qmediaplaylist.h>
class signalWidget : public QWidget
{
public:
QVideoWidget *videoWidget;
QMediaPlayer* m_mediaPlayer;
QAbstractButton *m_playButton;
QSlider *m_positionSlider;
QLabel *m_errorLabel;
void setUrl(const QUrl &url);
public slots:
void openFile();
void play();
void mediaStateChanged(QMediaPlayer::State state);
void positionChanged(qint64 position);
void durationChanged(qint64 duration);
void setPosition(int position);
void handleError();
};
Source File
void signalWidget::handleError()
{
m_playButton->setEnabled(false);
const QString errorString = m_mediaPlayer->errorString();
QString message = "Error: ";
if (errorString.isEmpty())
message += " #" + QString::number(int(m_mediaPlayer->error()));
else
message += errorString;
m_errorLabel->setText(message);
std::cout << " ERROR = " << message.toStdString() << "\n";
}
void signalWidget::positionChanged(qint64 position)
{
std::cout << " position = " << position << "\n";
m_positionSlider->setValue(position);
}
void signalWidget::durationChanged(qint64 duration)
{
std::cout << " duration = " << duration << "\n";
m_positionSlider->setRange(0, duration);
}
void signalWidget::setPosition(int position)
{
std::cout << " position = " << position << "\n";
m_mediaPlayer->setPosition(position);
}
void signalWidget::mediaStateChanged(QMediaPlayer::State state)
{
std::cout << " state = " << state << "\n";
switch(state) {
case QMediaPlayer::PlayingState:
m_playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPause));
break;
default:
m_playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay));
break;
}
}
void signalWidget::MediaError(QMediaPlayer::Error error)
{
std::cout << " Media Error: " << error << "\n";
}
void signalWidget::ChangedStatus(QMediaPlayer::MediaStatus status)
{
std::cout << " Status changed to: " << status << "\n";
}
void signalWidget::play()
{
std::cout << " currentMedia = " << m_mediaPlayer->currentMedia().canonicalUrl().toString().toStdString() <<
", playerState = " << m_mediaPlayer->state() << " E\n";
switch (m_mediaPlayer->state()) {
case QMediaPlayer::PlayingState:
m_mediaPlayer->pause();
break;
default:
m_mediaPlayer->play();
break;
}
std::cout << " playerState = " << m_mediaPlayer->state() << ", playerMediaState = " << m_mediaPlayer->mediaStatus() << "\n";
}
void signalWidget::setUrl(const QUrl &url)
{
m_errorLabel->setText(QString());
setWindowFilePath(url.isLocalFile() ? url.toLocalFile() : QString());
m_mediaPlayer->setMedia(url);
m_playButton->setEnabled(true);
std::cout << " currentMedia = " << m_mediaPlayer->currentMedia().canonicalUrl().toString().toStdString() <<
", player State = " << m_mediaPlayer->state() <<
", player ERROR = " << m_mediaPlayer->error();
}
void signalWidget::openFile()
{
QFileDialog fileDialog(this);
fileDialog.setAcceptMode(QFileDialog::AcceptOpen);
fileDialog.setWindowTitle(tr("Open Movie"));
QStringList supportedMimeTypes = m_mediaPlayer->supportedMimeTypes();
if (!supportedMimeTypes.isEmpty())
fileDialog.setMimeTypeFilters(supportedMimeTypes);
fileDialog.setDirectory(QStandardPaths::standardLocations(QStandardPaths::MoviesLocation).value(0, QDir::homePath()));
if (fileDialog.exec() == QDialog::Accepted)
setUrl(fileDialog.selectedUrls().constFirst());
}
Use of the above code
signalWidget::signalWidget(int widget_id)
{
m_mediaPlayer = new QMediaPlayer(this, QMediaPlayer::VideoSurface);
videoWidget = new QVideoWidget;
QAbstractButton *openButton = new QPushButton(tr("Open..."));
connect(openButton,SIGNAL(clicked()),this,SLOT(openFile()));
m_playButton = new QPushButton;
m_playButton->setEnabled(false);
m_playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay));
connect(m_playButton, SIGNAL(clicked()), this, SLOT(play()));
m_positionSlider = new QSlider(Qt::Horizontal);
m_positionSlider->setRange(0, 0);
connect(m_positionSlider, SIGNAL(sliderMoved()), this, SLOT(setPosition()));
m_errorLabel = new QLabel;
m_errorLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
m_errorLabel->setAutoFillBackground(true); // IMPORTANT!
m_errorLabel->setStyleSheet("QLabel { background-color : pink; color : blue; }");
QBoxLayout *controlLayout = new QHBoxLayout;
controlLayout->setMargin(0);
controlLayout->addWidget(openButton);
controlLayout->addWidget(m_playButton);
controlLayout->addWidget(m_positionSlider);
QBoxLayout *layout = new QVBoxLayout;
layout->addWidget(videoWidget);
layout->addLayout(controlLayout);
layout->addWidget(m_errorLabel);
layout->setMargin(0); //! to avoid wasting spaces with margins
setLayout(layout);
m_mediaPlayer->setVideoOutput(videoWidget);
connect(m_mediaPlayer, SIGNAL(stateChanged()), this, SLOT(mediaStateChanged()));
connect(m_mediaPlayer, SIGNAL(positionChanged()), this, SLOT(mediaStateChanged()));
connect(m_mediaPlayer, SIGNAL(durationChanged()), this, SLOT(durationChanged()));
connect(m_mediaPlayer, SIGNAL(Error()), this, SLOT(handleError()));
}
