本文介绍了使用 qt 显示带有 alpha 通道的视频的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要使用qt显示RGBA编码的视频(即具有透明背景的视频).这个想法是实时合并视频.我通常使用 libmpv 但它似乎不允许渲染透明背景视频.我正在尝试使用带有以下代码的 QMediaPlayer:

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();

这成功加载了视频(这是一个 RGBA mov 视频),但用黑色背景填充视频小部件,它应该是透明的,从而覆盖视频播放器后面的任何项目.

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.

有没有办法使用 QVideoPlayer/QVideoWidget 实际加载透明视频?如果没有,是否有有效的替代方案(我宁愿不使用较低级别的解决方案,例如 opencv).

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).

非常感谢,

弗雷德

推荐答案

这是我最终找到的解决方案:

here's the solution I finally found:

将 QAbstractVideoSurface 子类化:

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;
    }
};

表面将接收帧转换并将其转发到显示视频的qlabel.

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;
}

然后我们将一个 QLabel 子类化,这将是我们的视频输出:

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();
}

这篇关于使用 qt 显示带有 alpha 通道的视频的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-01 11:14