如何使用ID3D11VideoContext::GetDecoderBuffer()实现DirectX11 H.264解码
DirectX11 H.264解码问题解答
一、无需手动解析NALU的便捷参数获取方法
Windows平台没有和Mac的CMVideoFormatDescriptionCreateFromH264ParameterSets完全对应的直接API,但可以借助**Media Foundation(MF)**的组件来避免手动解析H.264的NALU(参数集SPS/PPS),步骤如下:
- 初始化Media Foundation:调用
MFInitialize(MF_INIT_FLAG_VIDEO_ONLY)。 - 创建媒体类型:使用
MFCreateMediaType获取IMFMediaType指针。 - 设置媒体类型属性:
- 设置主类型为
MFMediaType_Video,子类型为MFVideoFormat_H264。 - 用
MFSetAttributeBlob将SPS、PPS数据分别传入MF_MT_H264_SPS和MF_MT_H264_PPS属性。
- 设置主类型为
- 提取解码所需参数:通过
IMFMediaType的属性查询接口(如MFGetAttributeBlob、MFGetAttributeUINT32),直接获取profile_idc、level_idc、图像分辨率等关键参数,无需手动解析NALU的RBSP格式。
如果需要更直接的DXVA参数映射,也可以使用MF的H.264解码器变换(IMFTransform),将媒体类型传入后,通过查询解码器的输出格式或内部状态,间接获取适配DXVA 2.0的参数结构。
二、解码器缓冲区的正确填充方法
DirectX11视频解码确实复用DXVA 2.0的数据结构,你的猜测是正确的,以下是各缓冲区的填充细节:
1. D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS
调用GetDecoderBuffer时,需要将DXVA_PictureParameters指针的地址强制转换为void**传入,具体代码逻辑如下:
DXVA_PictureParameters* picParams = nullptr; UINT32 bufferSize = 0; // 获取参数缓冲区 hr = pVideoContext->GetDecoderBuffer(pDecoder, D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS, (void**)&picParams, &bufferSize); if (SUCCEEDED(hr)) { // 填充通用字段 picParams->wDecodedPictureIndex = 你的解码帧索引; picParams->wCurrentPictureIndex = 当前帧索引; picParams->bPicStructure = 帧结构类型(如DXVA_PicStruct_Frame); // 填充H.264特有的参数 DXVA_PicParams_H264& h264Params = picParams->PicParamsH264; h264Params.wProfileIDC = 从MF获取的profile_idc; h264Params.wLevelIDC = 从MF获取的level_idc; h264Params.wSeqParameterSetID = SPS的ID; h264Params.wPicParameterSetID = PPS的ID; // 其他H.264参数如帧大小、参考帧数量等按需填充 }
2. 其他缓冲区填充
- D3D11_VIDEO_DECODER_BUFFER_INVERSE_QUANTIZATION_MATRIX:对应
DXVA_Qmatrix结构体,将H.264 PPS中的量化矩阵数据填充到Qmatrix4x4或Qmatrix8x8成员中(取决于profile)。 - D3D11_VIDEO_DECODER_BUFFER_BITSTREAM:直接填入H.264的字节流数据(包含NALU起始码或按Annex B格式组织的码流),注意缓冲区大小要匹配码流长度。
- D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL:对应
DXVA_Slice_H264结构体,需要为每个切片填充起始偏移、长度、切片类型等信息。如果是单切片帧,只需填充一个切片控制结构即可;多切片帧则需要逐个添加。
内容的提问来源于stack exchange,提问作者luckybroma
相关产品推荐
相关产品推荐

