c++ 在Qt中显示解码视频帧的最有效的方法是什么?

什么是最快的方式显示图像到Qt窗口小部件?我已经解码视频使用libavformat和libavcodec,所以我已经有原始RGB或YCbCr 4:2:0帧。我目前使用QGraphicsView与QGraphicsScene对象包含一个QGraphicsPixmapItem。我目前通过使用QImage构造函数从内存缓冲区并将其转换为QPixmap使用QPixmap :: fromImage()获取帧数据到QPixmap。

我喜欢这个结果,它似乎相对较快,但我不禁想到,一定有一个更有效的方式。我也听说过QImage到QPixmap的转换是很贵的。我实现了一个解决方案,使用SDL覆盖在一个小部件,但我想保持只是Qt,因为我能够轻松地捕获点击和其他用户与视频显示使用QGraphicsView的交互。

我使用libswscale进行任何所需的视频缩放或颜色空间转换,所以我只想知道是否有人有一个更有效的方式来显示图像数据后,所有的处理已经执行。

谢谢。

最佳答案
感谢答案,但我终于重温了这个问题,并提出了一个相当简单的解决方案,提供良好的性能。它涉及从QGLWidget派生并覆盖paintEvent()函数。在paintEvent()函数中,你可以调用QPainter :: drawImage(…),它将执行缩放到指定的矩形,如果可用的话,使用硬件。所以它看起来像这样:

class QGLCanvas : public QGLWidget
{
public:
    QGLCanvas(QWidget* parent = NULL);
    void setImage(const QImage& image);
protected:
    void paintEvent(QPaintEvent*);
private:
    QImage img;
};

QGLCanvas::QGLCanvas(QWidget* parent)
    : QGLWidget(parent)
{
}

void QGLCanvas::setImage(const QImage& image)
{
    img = image;
}

void QGLCanvas::paintEvent(QPaintEvent*)
{
    QPainter p(this);

    //Set the painter to use a smooth scaling algorithm.
    p.setRenderHint(QPainter::SmoothPixmapTransform, 1);

    p.drawImage(this->rect(), img);
}

有了这个,我仍然需要将YUV 420P转换为RGB32,但ffmpeg有一个非常快的实现这种转换在libswscale。主要收益来自两件事:

>无需软件缩放。缩放在视频卡上完成(如果可用)
>在QPainter :: drawImage()函数中发生的从QImage到QPixmap的转换在原始图像分辨率下执行,而不是按比例放大的全屏分辨率。

我是我的处理器只是显示(解码正在做另一个线程)与我以前的方法。现在我的显示线程只使用大约8-9%的核心来进行全屏1920×1200 30fps播放。我相信它可能会更好,如果我可以直接发送YUV数据到视频卡,但这是足够好了现在。

转载注明原文:c++ 在Qt中显示解码视频帧的最有效的方法是什么? - 代码日志