我想解码一些非常大的H.264视频文件,而cpu(使用libav)不会被剪切.
我使用DXVA2查看了libav的hwaccel功能,但是当我需要创建一个只能使用D3D9接口创建的IDirectXVideoDecoder时,打了一个路障. (我没有使用DX11)
每当我查看DXVA文档时,它都不参考DX11,DX10或11中是否已被删除? (找不到任何确认信息,也不知道DXVA2是多余的,可能是DXVA-HD超越了吗?)
然后我看了媒体基础SDK,看起来像我应该用于DX11 …但是没有一个类型存在于我的头文件(文档说只是包含,但这不产生任何东西).他们还指定使用最少的Windows 8.
我相信使用MF我需要Windows 8 SDK,现在包括所有的directx库/标题.
所以这与Windows 7保持一个空白…是否可以获得硬件加速视频解码?如果是,我应该使用哪个API?
你需要很好的了解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(decode,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字段.
看到:
> 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 /表面可用.
这是相当复杂的,检查ffmpeg和媒体播放器经典,他们都有DXVA2(虽然不通过DX11)的支持.
4)从NV12转换为RGB(A),某些GPU(D3D11功能级别)允许使用NV12作为着色器输入,有些则不使用.如果无法直接使用NV12,请查看所有具有D3D11支持的GPU的D3D11VideoProcessor接口,它们具有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,&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(),1,&streams);