如何将已解码的缓冲区从ffmpeg映射到QVideoFrame?

时间:2019-02-12 01:20:03

标签: c++ qt video ffmpeg h.264

我正尝试将解码的ffmpeg缓冲区放入QFrame中,因此我可以将该帧放入QAbstractVideoBuffer中,然后将该缓冲区放入QMediaPlayer中。

这是VideoSurface的代码。根据QT的文档,我只需要实现这两个函数:构造函数和bool present,即可将帧处理为名为QVideoFrame的{​​{1}}

frame

查看QList<QVideoFrame::PixelFormat> VideoSurface::supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const { Q_UNUSED(handleType); // Return the formats you will support return QList<QVideoFrame::PixelFormat>() << QVideoFrame::Format_YUV420P; } bool VideoSurface::present(const QVideoFrame &frame) { //Q_UNUSED(frame); std:: cout << "VideoSurface processing 1 frame " << std::endl; QVideoFrame frametodraw(frame); if(!frametodraw.map(QAbstractVideoBuffer::ReadOnly)) { setError(ResourceError); return false; } // Handle the frame and do your processing const size_t bufferSize = 398304; uint8_t frameBuffer[bufferSize]; this->mediaStream->receiveFrame(frameBuffer, bufferSize); //Frame is now in frameBuffer, we must put into frametodraw, I guess // ------------What should I do here?------------- frametodraw.unmap(); return true; } 。这行代码将YUV420P格式的新h264帧解码为this->mediaStream.decodeFrame(frameBuffer, bufferSize)

我的想法是使用frameBuffer函数,然后尝试使用map函数接收缓冲区指针,并尝试将此指针指向另一件事,但是我不认为这是方法。我认为我应该将frametodraw.bits()的内容复制到该指针,但是例如,该指针并不能告诉我其大小,所以我想这也不是办法。

所以...我应该如何将缓冲区映射到名为frameBuffer的{​​{1}}中?

我还注意到,当我将QVideoFrame实例放入frame时,从未调用VideoSurface。我认为有问题,即使使用QMediaPlayer 这很重要

我也没有present中解码图像的大小,我只有它的总大小。我认为这也应该是一个问题。

我还注意到player->play()不是可显示的元素...那么哪个窗口小部件将显示我的视频?在我看来,这很重要。

1 个答案:

答案 0 :(得分:2)

我认为您误会了每个班级的角色。您正在子类化QAbstractVideoSurface,它应该有助于访问准备好进行演示的数据。在本方法内部,将提供一个已解码的QVideoFrame。如果要在屏幕上显示此内容,则需要在VideoSurface类中实现它。

您可以在QMediaPlayer上设置VideoSurface,并且媒体播放器已经可以处理视频的解码和像素格式的协商。您现在收到的VideoSurface中的QVideoFrame已经具有来自媒体播放器的高度/宽度和像素格式。媒体播放器的典型用法是使它加载和解码文件,并通过视频小部件在屏幕上显示。

如果需要使用自己的自定义ffmpeg解码器,我的建议是将帧从yuv420转换为rgb(libswscale?),创建自己的自定义小部件,您也可以传递帧数据,并可以使用将QPainter加载到QPixmap后使用。