提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

前言

最近使用ffmpeg的api对视频流进行硬解码时遇到了一个这样的问题:

采用ffmpeg官方的例子进行硬解码(dev/examples下hw_decode.c),解码后与软解码时的cpu占用率没有什么差别,依然很高。


一、解决办法

这个问题困扰了我很长时间,于是就设个断点debug了一下,发现av_hwframe_transfer_data之前调用的avcodec_receive_frame最开始是返回-11的,也就是AVERROR(EAGAIN)(原因可能是ffmpeg内部的缓冲区里面的视频帧还不足以输出,与h264算法有关)。于是加了一个容错判断,cpu的占用率居然降下来了。具体什么原因还没有深究,但是猜测之前应该是处理无效的frame时产生了大的空间开销。

二、代码示例

代码如下(示例):

re = avcodec_receive_frame(codec, frame);
if(re != 0){
 mux.unlock();
    av_frame_free(&frame);
    av_frame_free(&sw_frame);
    return NULL;
}
mux.unlock();
av_hwframe_transfer_data(sw_frame, frame, 0);

更正

其实cpu占用高并不是调用ffmpeg代码未加容错判断的问题,最本质的东西是例子中的av_hwframe_transfer_data(sw_frame, frame, 0)是将硬解后得到显存中的纹理(就是解码后得到的yuv数据)拉取到了内存中,这是一个很耗时消耗性能的操作。正确的做法与ffmpeg官方给的硬解的例子是不同的,需要将显存中的纹理调用不同平台的api对显存内的纹理直接进行渲染。linux是硬解得到VDPAU(英伟达)或VAAPI(amd英特尔的纹理)格式的纹理,再通过不同显卡厂商的api渲染出来(当然也是可以先转换为opengl或vulkan的纹理再使用二者的渲染api进行渲染)。windows可以硬解得到d3d9或d3d11(当然也可以通过硬解后的qsv、cuda的纹理来操作),再通过Direct3D 9 / 11进行渲染其纹理。

Logo

音视频技术社区,一个全球开发者共同探讨、分享、学习音视频技术的平台,加入我们,与全球开发者一起创造更加优秀的音视频产品!

更多推荐