【硬件解码系列】之DXVA2

 本文小编也是在学习dxva2解码,所以很多资料都是来源网上搜集加自己理解。

1. DXVA2解码过程

(1)、调用DXVA2CreateDirect3DDeviceManager9函数获取到IDirect3DDeviceManager9接口的一个对象。
(2)、调用IDirect3DDeviceManager9::OpenDeviceHandle 函数获取到一个Direct3D 设备对象句柄。
(3)、调用IDirect3DDeviceManager9::GetVideoService 函数并且传递Direct3D设备句柄,这个函数返回IDirectXVideoDecoderService接口对象指针。
(4)、调用 IDirectXVideoDecoderService::GetDecoderDeviceGuids 函数返回解码设备GUID的数组。
(5)、循环遍历解码设备GUID数组找到一个目前硬件驱动能支持的GUID解码设备。例如,如果驱动只支持MPEG-2 解码,则需要找到DXVA2_ModeMPEG2_MOCOMP, DXVA2_ModeMPEG2_IDCT, or DXVA2_ModeMPEG2_VLD这几个GUID才能解码。
(6)、如果你找到了一个解码设备GUID,传递这个GUID给IDirectXVideoDecoderService::GetDecoderRenderTargets 函数,这个函数返回一个类型为D3DFORMAT 的渲染目标格式数组(render target format)。
(7)、循环遍历渲染目标格式数组,找到一个匹配的输出格式。通常一个解码设备只支持一个渲染目标输出格式。
(8)、调用IDirectXVideoDecoderService::GetDecoderConfigurations函数,并且传递解码设备GUID和DXVA2_VideoDesc结构体(描述视频信息)。这个函数返回一个 DXVA2_ConfigPictureDecode结构体的数组,这个数组中的每一项描述一个可能的解码配置信息。
(9)、调用IDirectXVideoDecoderService::CreateVideoDecoder函数,并且传递解码设备GUID和DXVA2_VideoDesc结构体, DXVA2_ConfigPictureDecode,渲染目标surface数组。这个函数将返回一个IDirectXVideoDecoder 接口对象。
(10)、调用函数 IDirectXVideoDecoder::BeginFrame
(11)、调用下面过程多次:

  1. 调用IDirectXVideoDecoder::GetBuffer 函数得到一个DXVA解码缓冲区( DXVA decoder buffer )。
  2. 将数据填充到这个DXVA解码缓冲区中。
  3. 调用 IDirectXVideoDecoder::ReleaseBuffer 释放这个DXVA解码缓冲区。

(12)、调用 IDirectXVideoDecoder::Execute 函数执行这一帧的解码操作。
(13)、调用IDirectXVideoDecoder::EndFrame

注意:在每一帧解码之前必须调用函数IDirect3DDeviceManager9::TestDevice测试设备句柄是否修改。如果设备已经修改,此函数将返回DXVA2_E_NEW_VIDEO_DEVICE。如果这种情况发生,执行下面操作:

  1. 通过调用IDirect3DDeviceManager9::CloseDeviceHandle函数关闭设备句柄对象。
  2. 释放 IDirectXVideoDecoderServiceIDirectXVideoDecoder 对象指针。
  3. 打开一个新的设备句柄。
  4. 协商一个新的解码配置项。
  5. 创建一个新的解码设备。

摘抄自参考网址:https://www.cnblogs.com/betterwgo/p/6125507.html , 此参考网址将dxva的调用流程说的很清楚。

上面的函数是为创建IDirectXVideoDecoder 接口对象使用的。而实际的解码函数,主要由2个函数组成:

ff_dxva2_common_end_frame
ff_dxva2_commit_buffer

此2个函数由不同的函数调用,例如对于h264格式的码流是由ff_h264_dxva2_hwaccel 中的.end_frame = dxva2_h264_end_frame函数调用。

AVHWAccel ff_h264_dxva2_hwaccel = {
    .name           = "h264_dxva2",
    .type           = AVMEDIA_TYPE_VIDEO,
    .id             = AV_CODEC_ID_H264,
    .pix_fmt        = AV_PIX_FMT_DXVA2_VLD,
    .start_frame    = dxva2_h264_start_frame,
    .decode_slice   = dxva2_h264_decode_slice,
    .end_frame      = dxva2_h264_end_frame,
    .frame_priv_data_size = sizeof(struct dxva2_picture_context),
};

ff_h264_dxva2_hwaccel结构体是由int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt)函数中的if (!setup_hwaccel(avctx, ret, desc->name)) 调用(此函数源自 libavcodec/utils.c),

可参考目前网上已有的工程:
也可参考ffmpeg自带的sample:例如ffmpeg-3.2中的ffmpeg_dxva2.c

参考网址:https://blog.csdn.net/xiaoyafang123/article/details/82905452
参考网址:https://blog.csdn.net/lishuzhai/article/details/52497110

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值