FFMPEG 之 DXVA2 硬解

一:FFMPEG 支持的硬解方式有很多:

DXVA2、D3D11VA、CUDA、QSV、OPENCL、DRM、VAAPI、VDPAU、VIDEOTOOLBOX、MEDIACODEC。

有的支持 Windows 平台,有的支持 linux 平台,有的支持 apple ios 平台,有的支持 android 平台。

二:Windows 平台,我们可以使用利用 DXVA2、DX11、OpenGL、Vulkan、等技术,直接显示 GPU 显卡中的数据。

FFPLAY 最新源码,使用 Vulkan 的方式来进行硬解加速渲染的。

为什么使用 Vulkan ?

A:Vulkan 跨平台;

B:Vulkan 可以做渲染;

C:Vulkan 可以做计算,做图像处理;

D:Vulkan 可以做视频解码编码;

E:Vulkan 可以和 CUDA、DRM、VAAPI 互操作;

三:使用 DXVA2 硬解加速渲染:

没有了内存复制(av_hwframe_transfer_data)。

没有了sws_scale 解码到图片也。

界面绘制由原来的 GDI 绘制,变成了 DX 绘制。

非常之高效。

四:Windows 操作系统支持 DXVA2 方式硬解。

DXVA2 封装了显卡解码。你就不用操心不同显卡了。

这也是为什么网上介绍硬解时,大多数是介绍 DXVA2 方式硬解。

当然,如果你的显卡不支持某种格式视频(H265 格式视频)的硬解,即使你使用 DXVA2 硬解,那也是行不通的。

五:Windows 操作系统支持 DXVA2 方式硬解。

不使用 FFMPEG 也是可以的。按照 DXVA2 的规范写就可以了。当然这不在本文讨论范围内。

感兴趣的可以参看:https://github.com/mofo7777/H264Dxva2Decoder.git

六:我们只要在 FFMPEG 硬解示例程序的基础上,修改硬解方式为 dxva2,就 OK 了。

其它不用作任何修改。就是 DXVA2 硬解码了。

当然我们的目的是使用 DX 的方式来渲染图像。

七:这个 DX 渲染函数很关键。

网上绝大多数的代码,都是将 hwcontext_dxva2.c 代码从 FFMPEG 源代码复制出来,

添加到自己的代码中,并改写为 ffmpeg_dxva2.cpp 。

其实完全没有这个必要。而且这种方式肯定也是不可取的。

而且我相信 FFMPEG 的源代码作者肯定也不想你这么干。

我使用的方法,适用于所有语言。

20 行的代码就可以完成 DX 绘制了。更具有通用性。

八:DX 渲染函数原理:

1:用户在调用 av_hwdevice_ctx_create 函数,初始化硬件加速上下文时,

会调用 hwcontext.c 的 av_hwdevice_ctx_create 函数进行 DXVA2 的初始化。

av_hwdevice_ctx_create(hwcontext.c) 初始化成功后,将设备上下文信息保存在 data 里面,返回给了调用者;

2:av_hwdevice_ctx_create(hwcontext.c) 会进行 DXVA2 的创建。

ret = device_ctx->internal->hw_type->device_create(device_ctx, device, opts, flags);

这里将调用 hwcontext_dxva2.c 的 dxva2_device_create 函数进行 DXVA2 的初始化。

创建成功后,将 DX 设备信息保存在设备上下文信息的 user_opaque 里面,返回给了调用者。

3:至此,我们可以拿到:设备上下文信息、DX 设备信息。可以直接进行 DX 界面绘制了。

九:测试发现:解码效率比网上那些复制改写 hwcontext_dxva2.c 的程序,快了将近 200 多帧。果然高效!!!

十:核心代码及其说明:

cpp 复制代码
while ((ret = avcodec_receive_frame(videoCodecCtx, Frame)) >= 0) 
{
    ......
    
    surface    = (LPDIRECT3DSURFACE9)Frame->data[3];                     // 待绘制的数据
    device_ctx = (AVHWDeviceContext*)videoCodecCtx->hw_device_ctx->data; // 设备上下文信息
    priv       = (DXVA2DevicePriv*)device_ctx->user_opaque;              // DX 设备信息

    ......

    /* 开始 DX 渲染 */
    priv->d3d9device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
    priv->d3d9device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &BackBuffer);
    RECT SourceRect = { 0, 0, videoCodecCtx->width, videoCodecCtx->height };
    priv->d3d9device->StretchRect(surface, &SourceRect, BackBuffer, NULL, D3DTEXF_LINEAR);
    priv->d3d9device->Present(NULL, NULL, NULL, NULL);

    ......
}
相关推荐
简鹿办公22 分钟前
使用 FFmpeg 进行音视频转换的相关命令行参数解释
ffmpeg·简鹿视频格式转换器·ffmpeg视频转换
EasyCVR4 小时前
萤石设备视频接入平台EasyCVR多品牌摄像机视频平台海康ehome平台(ISUP)接入EasyCVR不在线如何排查?
运维·服务器·网络·人工智能·ffmpeg·音视频
runing_an_min4 小时前
ffmpeg 视频滤镜:屏蔽边框杂色- fillborders
ffmpeg·音视频·fillborders
岁月小龙14 小时前
如何让ffmpeg运行时从当前目录加载库,而不是从/lib64
ffmpeg·origin·ffprobe·rpath
行者记2 天前
ffmpeg命令——从wireshark包中的rtp包中分离h264
测试工具·ffmpeg·wireshark
EasyCVR2 天前
国标GB28181视频平台EasyCVR私有化视频平台工地防盗视频监控系统方案
运维·科技·ffmpeg·音视频·1024程序员节·监控视频接入
hypoqqq2 天前
使用ffmpeg播放rtsp视频流
ffmpeg
cuijiecheng20182 天前
音视频入门基础:FLV专题(24)——FFmpeg源码中,获取FLV文件视频信息的实现
ffmpeg·音视频
QMCY_jason2 天前
黑豹X2 armbian 编译rkmpp ffmpeg 实现CPU视频转码
ffmpeg
苍天饶过谁?2 天前
SDL基本使用
ffmpeg