如何在DirectX 11和Windows 7中使用硬件加速视频/H.264解码? [英] How do I use Hardware accelerated video/H.264 decoding with directx 11 and windows 7?

查看:1082
本文介绍了如何在DirectX 11和Windows 7中使用硬件加速视频/H.264解码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我整天都在研究,并且还没有走很远.我在Windows 7上,使用DirectX11.(我的最终输出是将视频帧显示到DX11纹理上) 我想解码一些非常大的H.264视频文件,而CPU(使用libav)不能将其剪切.

I've been researching all day and not gotten very far. I'm on windows 7, using directx 11. (My final output is to be a frame of video onto a DX11 texture) I want to decode some very large H.264 video files, and the CPU (using libav) doesn't cut it.

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

I've looked at the hwaccel capabilities of libav using DXVA2, but hit a road block when I need to create a IDirectXVideoDecoder, which can only be created with a D3D9 interface. (which I don't have using DX11)

每当我查阅DXVA文档时,它都不会引用DX11,这是在DX10或11中删除的吗? (找不到任何确认,也没有任何地方说DXVA2是多余的,可能是它被DXVA-HD取代了吗?)

Whenever I've looked up DXVA documentation, it doesn't reference DX11, was this removed in DX10 or 11? (Can't find any confirmation of this, nor anywhere that says DXVA2 is redundant, possibly that it's been superceeded by DXVA-HD?)

然后,我研究了Media Foundation SDK,因为它看起来像我应该用于DX11的东西...但是我的标头中没有任何类型(文档说只包含include,但这不会产生任何结果) ).他们还指定了最少要使用的Windows 8.

Then I've looked into the media foundation SDK as that looks like what I'm supposed to use for DX11... But none of the types exist in my headers (The docs say to just include , but this yields nothing). They also specify a minimum of windows 8 to use it.

我相信要使用MF,我需要Windows 8 SDK,该SDK现在包括所有的DirectX库/标题.

I believe to use MF I need the windows 8 SDK, which now includes all the directx libs/headers.

因此,这与Windows 7留有缝隙...是否有可能获得硬件加速的视频解码?如果可以,我应该使用哪个API?

So this leaves a gap with windows 7... Is it possible to get hardware accelerated video decoding? and if so, which API am I supposed to be using?

推荐答案

D3D11具有一个视频api,它基本上是DXVA2,上面的界面略有变化. 您需要充分了解h.264比特流才能继续(确实!).也就是说,请确保您有一个h.264解析器,以提取SPS和PPS结构的字段以及编码帧的所有切片.

D3D11 features a video api which is basically DXVA2 with a slightly altered interface above. You need a good understand of h.264 bitstreams to proceed (really!). i.e. make sure you have a h.264 parser at hand to extract fields of the SPS and PPS structures and all slices of an encoded frame.

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

1) Obtain ID3D11VideoDevice instance from your ID3D11Device, and ID3D11VideoContext from your immediate D3D11 device context NOTE: On Win7, you have to create your device with feature level 9_3 to get video support! (In Win8 it just works)

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

2) Create a ID3D11VideoDecoder instance for h.264 Use ID3D11VideoDevice::GetVideoDecoderProfileCount, GetVideoDecoderProfile, CheckVideoDecodeRFormat... to iterate through all supported profiles, and find one with GUID D3D11_DECODER_PROFILE_H264_VLD_NOFGT for h264 without filmgrain. As OutputFormat your best bet is DXGI_FORMAT_NV12.

3)各个帧的解码,请参见在媒体基金会:

3) Decoding of the individual frames see 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
    • ID3D11VideoContext::DecoderBeginFrame( decoder, outputView -> decoded frame texture )
    • Fill buffers:
      • 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字段.

      The buffers are filled with the corresponding DXVA2 structures (see dxva2.h) The full DXVA2 spec is here, you'll need it to map the h.264 sps/pps fields accordingly.

      请参阅:

      • About DXVA 2.0
      • https://software.intel.com/sites/default/files/m/b/4/7/DXVA_H264.pdf

      然后:

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

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

      3) D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS buffer also contains info on all references frames/surface - you need to manage them yourself, i.e. make sure the surfaces/textures are available to the GPU!

      这非常复杂,请检查ffmpeg和Media Player Classic,它们都支持DXVA2(尽管不是通过DX11).

      It's quite complicated, check ffmpeg and Media Player Classic, they both have DXVA2 (though not via DX11) support.

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

      4) Convert from NV12 to RGB(A), some GPUs (D3D11 feature levels) allow to use NV12 as shader input, some don't. In case it's not possible to use NV12 directly, have a look at the D3D11VideoProcessor interfaces which feature NV12/YUV420->RGB conversion for all GPUs with D3D11 support.

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

      The conversion could be performed in code like this:

      // 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);
      

      这篇关于如何在DirectX 11和Windows 7中使用硬件加速视频/H.264解码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆