I need to display RGBA encoded videos (that is, video with a transparent background) using qt. The idea is to merge videos in real time. I usually use libmpv but it does not seem to be allow rendering transparent background video. I am trying to use a QMediaPlayer with the following code:
QMainWindow w;
w.resize(1920,1080);
QVideoWidget videoWidget(&w);
videoWidget.move(0,100);
videoWidget.resize(1920,1080);
QMediaPlayer *player = new QMediaPlayer(&w);
w.resize(w.size());
player->setMedia( QUrl::fromLocalFile(PATH+"video2.mov") );
player->setVideoOutput(&videoWidget);
w.show();
player->play();
This successfully loads the video (which is an RGBA mov video) but fills the video widget with a black background where it should be transparent thus covering any item behind the video player.
Is there any way to actually load a transparent video using QVideoPlayer/QVideoWidget? If not, is there an efficient alternative (I would rather not use a lower level solution such as opencv).
Thanks a lot,
Fred
here's the solution I finally found:
Subclass a QAbstractVideoSurface:
class alphaVideoDrawer : public QAbstractVideoSurface
{
Q_OBJECT
public:
alphaVideoDrawer(QLabel *displayLbl);
private:
QLabel *displayLbl;
protected:
bool present(const QVideoFrame &frame);
QList<QVideoFrame::PixelFormat> supportedPixelFormats(
QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const
{
Q_UNUSED(handleType);
return QList<QVideoFrame::PixelFormat>() << QVideoFrame::Format_ARGB32;
}
};
The surface will receive the frame convert and forward it to the qlabel which displays the video.
alphaVideoDrawer::alphaVideoDrawer(QLabel *displayLbl):displayLbl(displayLbl)
{
}
extern QImage qt_imageFromVideoFrame(const QVideoFrame &f);
bool alphaVideoDrawer::present(const QVideoFrame &frame)
{
QImage image = qt_imageFromVideoFrame(frame);
displayLbl->setPixmap(QPixmap::fromImage(image));
return true;
}
Then we subclass a QLabel which will be our video output:
class alphaVideo : public QLabel
{
Q_OBJECT
public:
alphaVideo(QLabel *parent = nullptr);
private:
alphaVideoDrawer *videoDrawer;
QMediaPlayer *videoPlayer;
QMediaPlaylist *playlist;
};
It loads the drawer and the player and start playing/rendering the video:
alphaVideo::alphaVideo(QLabel *parent): QLabel(parent)
{
setStyleSheet("QLabel { background-color : transparent; }");
videoDrawer = new alphaVideoDrawer(this);
videoPlayer = new QMediaPlayer(this);
playlist = new QmediaPlaylist();
videoPlayer->setPlaylist(playlist);
videoPlayer->setVideoOutput(videoDrawer);
playlist->addMedia( Qurl::fromLocalFile(“your RGBA video file.mp4”) );
videoPlayer->play();
}