14

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

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

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

然后我查看了媒体基础 SDK,因为它看起来像我应该用于 DX11 ......但是我的标题中不存在任何类型(文档说只包含 <d3d11.h>,但是这个什么都没有产生)。他们还指定了最少的 Windows 8 来使用它。

我相信要使用 MF,我需要 windows 8 SDK,它现在包含所有的 directx 库/头文件。

所以这与 Windows 7 存在差距......是否有可能获得硬件加速视频解码?如果是这样,我应该使用哪个 API?

编辑:作为另一个跟进,我的 MediaFoundation(和 AVF、android、magic jump 等)实现在我的开源项目中 https://github.com/NewChromantics/POPH264 Edit2:但我不知道它是否支持赢7 :)

4

3 回答 3

23

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... 遍历所有支持的配置文件,并为没有胶片颗粒的 h264 找到一个具有 GUID D3D11_DECODER_PROFILE_H264_VLD_NOFGT 的配置文件。作为 OutputFormat,您最好的选择是 DXGI_FORMAT_NV12。

3) 单个帧的解码请参阅Supporting Direct3D 11 Video Decoding in Media Foundation

  • ID3D11VideoContext::DecoderBeginFrame(decoder, 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 接口,该接口具有 NV12/YUV420->RGB 转换功能,适用于所有支持 D3D11 的 GPU。

可以在如下代码中执行转换:

// 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);
于 2014-07-08T10:45:45.700 回答
1

作为后续,我目前正在使用带有 Windows 7、8 和 10 的 MediaFoundation,带有 directx(或者在 8+ 的情况下仅使用 Windows SDK)

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

但是这个 API 是兼容的,这是原来的查询

于 2016-01-06T14:40:47.963 回答
1

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

你不能。

ID3D11VideoDevice 仅适用于 windows 8 ID3D11VideoDevice

ID3D11VideoDecoder 仅适用于 windows 8 ID3D11VideoDecoder

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

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

于 2018-10-16T21:26:43.740 回答