@Christian-Ehrlicher I'm sorry that I may misunderstand your meaning.
Here's the PlayerWidget class, still works well in Qt 6.3.2 and 5.14.2, but can't work in Qt 6.5.3.
playerwidget.h:
#ifndef PLAYERWIDGET_H
#define PLAYERWIDGET_H
#define Multimedia_And_Widgets_Enabled
#define Multimedia_Private_Enabled
#include <QWidget>
#include <QLabel>
#include <QFileInfo>
#include <QKeyEvent>
#ifdef Multimedia_And_Widgets_Enabled
#include <QImageWriter>
#include <QCamera>
#include <QMediaPlayer>
#include <QVideoWidget>
#include <QMediaMetaData>
#include <QVideoFrame>
#include <QGraphicsVideoItem>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QAudioOutput>
#include <QMediaRecorder>
#include <QAudioDecoder>
#if(QT_VERSION>=QT_VERSION_CHECK(6,0,0))
#include <QVideoSink>
#include <QVideoFrameFormat>
#else
#ifdef Multimedia_Private_Enabled
#include <private/qvideoframe_p.h>
#endif
#include <QVideoProbe>
#include <QAbstractVideoSurface>
#include <QAudioRecorder>
#include <QAudioEncoderSettings>
#include <QVideoEncoderSettings>
#endif
#endif
class PlayerWidget : public QWidget
{
Q_OBJECT
public:
explicit PlayerWidget(QWidget *parent = nullptr);
~PlayerWidget();
enum State
{
StoppedState,
PlayingState,
PausedState
};
bool eventFilter(QObject *watched, QEvent *event);
bool setFilePath(QString p);
QString filePath();
QMediaPlayer* mediaPlayer();
bool play();
void pause();
void stop();
void setPosition(int position);
int duration();
int volume();
void setVolume(int v);
bool hasVideo();
bool hasAudio();
QVideoFrame videoFrame();
QMediaPlayer::MediaStatus mediaStatus();
PlayerWidget::State state();
void lock();
void unlock();
bool isLocked();
signals:
void keyRelease(QKeyEvent* event);
void error(QMediaPlayer::Error e,QString errorString);
void statusChanged(QMediaPlayer::MediaStatus status);
void positionChanged(int position);
void durationChanged(int duration);
void videoFrameChanged(QVideoFrame frame);
void hasVideoChanged(bool available);
void hasAudioChanged(bool available);
void stateChanged(PlayerWidget::State state);
void statusChanged_private(QMediaPlayer::MediaStatus status);
void error_private(QMediaPlayer::Error e,QString errorString);
private:
QEventLoop* loop;
QMediaPlayer* player;
QVideoWidget* videowidget;
QLabel* label;
QAudioOutput* audiooutput;
QVideoFrame frame;
QString filepath = "";
bool videoAvailable = false;
bool audioAvailable = false;
bool enable = true;
bool ret;
bool widgetmode = false;
QPoint startpoint = QPoint(-1,-1);
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
QVideoSink* sink;
#else
QVideoProbe* probe;
#endif
};
#endif // PLAYERWIDGET_H
playerwidget.cpp:
#include "playerwidget.h"
static bool hasFilePermission(QString filepath,QIODevice::OpenModeFlag device = QIODevice::ReadWrite)
{
bool check = true;
if(filepath != "")
{
QFile* file = new QFile(filepath);
if(!file->exists())
check = false;
if(file->open(device))
{
file->close();
delete file;
if(!check)
QFile::remove(filepath);
return true;
}
else
{
delete file;
return false;
}
}
else
{
return false;
}
}
PlayerWidget::PlayerWidget(QWidget *parent) :
QWidget(parent)
{
qDebug() << "thread of playerwidget.cpp : " << this->thread();
this->setStyleSheet("background-color: black;");
this->setAttribute(Qt::WA_AcceptTouchEvents, true);
player = new QMediaPlayer;
videowidget = new QVideoWidget(this);
audiooutput = new QAudioOutput;
label = new QLabel(this);
loop = new QEventLoop(this);
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
sink = new QVideoSink;
#else
probe = new QVideoProbe;
#endif
label->setStyleSheet("background-color: black;");
label->resize(this->size());
label->setAlignment(Qt::AlignCenter);
if(widgetmode)
{
videowidget->show();
label->hide();
}
else
{
videowidget->hide();
label->show();
}
player->setVideoOutput(videowidget);
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
player->setAudioOutput(audiooutput);
player->setVideoSink(sink);
#else
probe->setSource(player);
#endif
this->installEventFilter(this);
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
connect(player,&QMediaPlayer::errorChanged,[this](){
emit error_private(player->error(),player->errorString());
emit error(player->error(),player->errorString());
});
connect(player,&QMediaPlayer::hasVideoChanged,[this](){
videoAvailable = player->hasVideo();
emit hasVideoChanged(videoAvailable);
if(this->hasVideo())
{
label->show();
}
else
{
label->clear();
label->hide();
}
});
connect(player,&QMediaPlayer::hasAudioChanged,[this](){
audioAvailable = player->hasAudio();
emit hasAudioChanged(audioAvailable);
if(this->hasVideo())
{
label->show();
}
else
{
label->clear();
label->hide();
}
});
connect(player,&QMediaPlayer::playbackStateChanged,[this](){
emit stateChanged(this->state());
});
connect(sink,&QVideoSink::videoFrameChanged,[this](const QVideoFrame &f){
frame = f;
emit videoFrameChanged(frame);
if(f.isValid() && widgetmode == false && !this->isLocked())
{
label->setPixmap(QPixmap::fromImage(f.toImage().scaled(label->size(),Qt::KeepAspectRatio)));
}
});
#else
QObject::connect(player,QOverload<QMediaPlayer::Error>::of(&QMediaPlayer::error),[=](){
emit error_private(player->error(),player->errorString());
emit error(player->error(),player->errorString());
});
QObject::connect(player,QOverload<bool>::of(&QMediaPlayer::videoAvailableChanged),[=](bool available){
videoAvailable = available;
emit hasVideoChanged(videoAvailable);
if(this->hasVideo())
{
label->show();
}
else
{
label->clear();
label->hide();
}
});
QObject::connect(player,QOverload<bool>::of(&QMediaPlayer::audioAvailableChanged),[=](bool available){
audioAvailable = available;
emit hasAudioChanged(audioAvailable);
if(this->hasVideo())
{
label->show();
}
else
{
label->clear();
label->hide();
}
});
QObject::connect(probe,QOverload<const QVideoFrame &>::of(&QVideoProbe::videoFrameProbed),[=](const QVideoFrame &f){
frame = f;
emit videoFrameChanged(frame);
if(f.isValid() && enable == true && widgetmode == false)
{
QImage image = qt_imageFromVideoFrame(f);
#ifdef Q_OS_WIN
image = image.mirrored();
#endif
if(!image.isNull())
{
image = image.scaled(label->size(),Qt::KeepAspectRatio);
label->setPixmap(QPixmap::fromImage(image));
}
}
});
QObject::connect(player,QOverload<QMediaPlayer::State>::of(&QMediaPlayer::stateChanged),[=](){
emit stateChanged(this->state());
});
#endif
connect(player,&QMediaPlayer::mediaStatusChanged,[this](){
emit statusChanged_private(player->mediaStatus());
emit statusChanged(player->mediaStatus());
});
connect(player,&QMediaPlayer::positionChanged,[this](){
emit positionChanged(player->position());
});
connect(player,&QMediaPlayer::durationChanged,[this](){
emit durationChanged(player->duration());
});
}
bool PlayerWidget::eventFilter(QObject *watched, QEvent *event)
{
if(watched == this)
{
if(event->type() == QEvent::KeyRelease)
{
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
emit keyRelease(keyEvent);
}
else if(event->type() == QEvent::Resize)
{
if(widgetmode)
videowidget->resize(this->size());
else
label->resize(this->size());
}
else if(event->type() == QEvent::Close)
{
player->stop();
}
else if(event->type() == QEvent::Hide)
{
if(widgetmode)
videowidget->hide();
else
label->hide();
}
else if(event->type() == QEvent::Show)
{
if(widgetmode)
videowidget->show();
else
label->show();
}
}
return QObject::eventFilter(watched,event);
}
PlayerWidget::~PlayerWidget()
{
}
bool PlayerWidget::setFilePath(QString p)
{
if(QFileInfo(p).isFile() && hasFilePermission(p,QIODevice::ReadOnly))
{
filepath = p;
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
player->setSource(QUrl::fromLocalFile(filepath));
#else
player->setMedia(QUrl::fromLocalFile(filepath));
#endif
return true;
}
else
{
filepath = "";
return false;
}
}
QString PlayerWidget::filePath()
{
return filepath;
}
QMediaPlayer* PlayerWidget::mediaPlayer()
{
return player;
}
bool PlayerWidget::play()
{
//QEventLoop* loop = new QEventLoop;
player->play();
QObject::connect(this,QOverload<QMediaPlayer::Error,QString>::of(&PlayerWidget::error_private),[=](QMediaPlayer::Error error,QString string){
if(error != QMediaPlayer::Error::NoError)
{
this->disconnect(this,SIGNAL(error_private(QMediaPlayer::Error,QString)),0,0);
filepath = "";
loop->quit();
//loop->exit(0);
}
});
QObject::connect(this,QOverload<QMediaPlayer::MediaStatus>::of(&PlayerWidget::statusChanged_private),[=](QMediaPlayer::MediaStatus status){
if(status == QMediaPlayer::BufferedMedia)
{
this->disconnect(this,SIGNAL(statusChanged_private(QMediaPlayer::MediaStatus)),0,0);
loop->quit();
//loop->exit(0);
}
});
this->lock();
loop->exec();
this->unlock();
return bool(player->error()==QMediaPlayer::Error::NoError);
}
void PlayerWidget::pause()
{
player->pause();
}
void PlayerWidget::stop()
{
player->stop();
}
void PlayerWidget::setPosition(int position)
{
if(position >= 0)
player->setPosition(position);
}
int PlayerWidget::duration()
{
return player->duration();
}
int PlayerWidget::volume()
{
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
return int(player->audioOutput()->volume()*100.0);
#else
return player->volume();
#endif
}
void PlayerWidget::setVolume(int v)
{
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
player->audioOutput()->setVolume(float(v)/100.0);
#else
player->setVolume(v);
#endif
}
bool PlayerWidget::hasVideo()
{
//return player->hasVideo();
return videoAvailable;
}
bool PlayerWidget::hasAudio()
{
//return player->hasAudio();
return audioAvailable;
}
QVideoFrame PlayerWidget::videoFrame()
{
return frame;
}
QMediaPlayer::MediaStatus PlayerWidget::mediaStatus()
{
return player->mediaStatus();
}
PlayerWidget::State PlayerWidget::state()
{
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
if(player->playbackState() == QMediaPlayer::PlaybackState::PlayingState)
{
return PlayerWidget::State::PlayingState;
}
else if(player->playbackState() == QMediaPlayer::PlaybackState::PausedState)
{
return PlayerWidget::State::PausedState;
}
else
{
return PlayerWidget::State::StoppedState;
}
#else
if(player->state() == QMediaPlayer::State::PlayingState)
{
return PlayerWidget::State::PlayingState;
}
else if(player->state() == QMediaPlayer::State::PausedState)
{
return PlayerWidget::State::PausedState;
}
else
{
return PlayerWidget::State::StoppedState;
}
#endif
}
void PlayerWidget::lock()
{
enable = false;
}
void PlayerWidget::unlock()
{
enable = true;
}
bool PlayerWidget::isLocked()
{
if(enable == true)
return false;
else
return true;
}
how to use:
PlayerWidget* widget = new PlayerWidget(this);
if(widget->setFilePath(QFileDialog::getOpenFileName()) && widget->play())
{
return true;
}
else
{
return false;
}