我想解码一些非常大的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);