如何在directx 11和Windows 7中使用硬件加速视频/ H.264解码?

时间:2013-11-07 21:10:52

标签: directx h.264 directx-11 hardware-acceleration dxva

我一直在研究,并没有走得太远。我在Windows 7上,使用directx 11.(我的最终输出是DX11纹理上的视频帧) 我想解码一些非常大的H.264视频文件,CPU(使用libav)不会削减它。

我已经看过使用DXVA2的libav的hwaccel功能,但是当我需要创建一个只能用D3D9接口创建的IDirectXVideoDecoder时遇到了障碍。 (我没有使用DX11)

每当我查找DXVA文档时,它都没有引用DX11,是否在DX10或11中删除了? (找不到任何关于此的确认,也没有任何说明DXVA2是多余的,可能是它被DXVA-HD超越了吗?)

然后我查看了媒体基础SDK,因为它看起来像我应该用于DX11 ...但我的标题中没有任何类型(文档说只是包含,但这不会产生任何结果) )。他们还指定了最少的窗口8来使用它。

我相信使用MF我需要windows 8 SDK,它现在包含所有directx libs / headers。

因此,这与Windows 7存在差距......是否有可能获得硬件加速视频解码?如果是的话,我应该使用哪种API?

3 个答案:

答案 0 :(得分:22)

D3D11的视频api基本上是DXVA2,上面的界面略有改动。 你需要很好地理解h.264比特流(真的!)。即确保您手头有一个h.264解析器来提取SPS和PPS结构的字段以及编码帧的所有切片。

1)从您的ID3D11Device获取ID3D11VideoDevice实例,从您的直接D3D11设备上下文获取ID3D11VideoContext 注意:在Win7上,您必须创建功能级别为9_3的设备才能获得视频支持! (在Win8中它才有效)

2)为h.264创建一个ID3D11VideoDecoder实例 使用ID3D11VideoDevice :: GetVideoDecoderProfileCount,GetVideoDecoderProfile,CheckVideoDecodeRFormat ... 迭代所有支持的配置文件,并找到一个GUID D3D11_DECODER_PROFILE_H264_VLD_NOFGT 对于没有胶片的h264。作为OutputFormat,最好的选择是DXGI_FORMAT_NV12。

3)各帧的解码见Supporting Direct3D 11 Video Decoding in Media Foundation

  • ID3D11VideoContext :: DecoderBeginFrame(解码器,outputView - >解码帧纹理)
  • 填充缓冲区:
    • D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS
    • D3D11_VIDEO_DECODER_BUFFER_INVERSE_QUANTIZATION_MATRIX
    • D3D11_VIDEO_DECODER_BUFFER_BITSTREAM
    • D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL

缓冲区用相应的DXVA2结构填充(参见dxva2.h) 完整的DXVA2规范就在这里,您需要它来相应地映射h.264 sps / pps字段。

见:

然后:

  • ID3D11VideoContext :: SubmitBuffers提交所有已填充的缓冲区
  • ID3D11VideoContext :: DecoderEndFrame完成当前帧

3)D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS缓冲区还包含所有参考帧/表面的信息 - 您需要自己管理它们,即确保GPU可以使用表面/纹理!

这很复杂,查看ffmpeg和Media Player Classic,他们都有DXVA2(虽然不是通过DX11)支持。

4)从NV12转换为RGB(A),某些GPU(D3D11功能级别)允许使用NV12作为着色器输入,有些则不允许。如果无法直接使用NV12,请查看D3D11VideoProcessor接口,该接口具有支持D3D11支持的所有GPU的NV12 / YUV420-> RGB转换。

可以使用以下代码执行转换:

// Setup ID3D11Video*
ID3D11VideoProcessor * d3dVideoProc = ...;
ID3D11VideoDevice    * d3dVideoDevice = ...;
ID3D11VideoProcessorEnumerator * d3dVideoProcEnum = ...;


ID3D11Texture2D * srcTextureNV12Fmt = ...;
ID3D11Texture2D * dstTextureRGBFmt = ...;

// Use Video Processor

// Create views for VideoProc In/Output
ID3D11VideoProcessorInputView * videoProcInputView;
ID3D11VideoProcessorOutputView * videoProcOutputView;

{

    D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC inputViewDesc = { 0 };
    inputViewDesc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D;
    inputViewDesc.Texture2D.ArraySlice = arraySliceIdx;
    inputViewDesc.Texture2D.MipSlice = 0;
    hr = d3dVideoDevice->CreateVideoProcessorInputView(srcTextureNV12Fmt, d3dVideoProcEnum, &inputViewDesc, &videoProcInputView);
}


{
    D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC outputViewDesc = { D3D11_VPOV_DIMENSION_TEXTURE2D };
    outputViewDesc.Texture2D.MipSlice = 0;
    hr = d3dVideoDevice->CreateVideoProcessorOutputView(dstTextureRGBFmt, d3dVideoProcEnum, &outputViewDesc, &videoProcOutputView);
}


// Setup streams
D3D11_VIDEO_PROCESSOR_STREAM streams = { 0 };
streams.Enable = TRUE;
streams.pInputSurface = videoProcInputView.get();

RECT srcRect = { /* source rectangle in pixels*/ };
RECT dstRect = { /* destination rectangle in pixels*/ };

// Perform VideoProc Blit Operation (with color conversion)
hr = videoCtx_->VideoProcessorBlt(d3dVideoProc, videoProcOutputView.get(), 0, 1, &streams);

答案 1 :(得分:1)

作为后续行动,我目前正在使用MediaFoundation与Windows 7,8和10,使用directx(或者只是8 +的Windows SDK)

它支持更少的格式(或更确切地说,分辨率/配置文件级别),目前我还不确定它是否使用硬件加速......

但此API兼容,这是原始查询

答案 2 :(得分:0)

  

如何在DirectX 11和Windows 7中使用硬件加速视频/H.264解码?

您不能。

ID3D11VideoDevice仅适用于Windows 8 ID3D11VideoDevice

ID3D11VideoDecoder仅适用于Windows 8 ID3D11VideoDecoder

在Windows 7上,您只能将DirectX 9用于硬件加速视频/H.264。谢谢微软。全新的IDirect3D9Ex可以工作...是的... 另一个好消息是,在Windows 7上使用DirectX9,GPU解码性能非常好。

这是H264Dxva2Decoder项目下Windows 7和DirectX 9的源代码:mofo7777