window 显示驱动开发-提供视频解码功能(二)
D3DDDICAPS_GETDECODEGUIDCOUNT和D3DDDICAPS_GETDECODEGUIDS请求类型
以下子主题列出了可能的请求类型及其关联的视频解码功能。
Direct3D 运行时调用 GetCaps 来请求 GUID 的数量,然后再次调用 GetCaps ,并请求支持的 GUID 列表。 UMD 返回以下列表中的数字和 GUID 列表,它支持视频加速 (VA) 解码。 D3DDDIARG_GETCAPS。对于这两种请求类型,pInfo 成员均为 NULL。
DEFINE_GUID(DXVADDI_ModeMPEG2_MoComp, 0xe6a9f44b, 0x61b0, 0x4563,0x9e,0xa4,0x63,0xd2,0xa3,0xc6,0xfe,0x66);
DEFINE_GUID(DXVADDI_ModeMPEG2_IDCT, 0xbf22ad00, 0x03ea, 0x4690,0x80,0x77,0x47,0x33,0x46,0x20,0x9b,0x7e);
DEFINE_GUID(DXVADDI_ModeMPEG2_VLD, 0xee27417f, 0x5e28, 0x4e65,0xbe,0xea,0x1d,0x26,0xb5,0x08,0xad,0xc9);DEFINE_GUID(DXVADDI_ModeH264_A, 0x1b81be64, 0xa0c7, 0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
DEFINE_GUID(DXVADDI_ModeH264_B, 0x1b81be65, 0xa0c7, 0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
DEFINE_GUID(DXVADDI_ModeH264_C, 0x1b81be66, 0xa0c7, 0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
DEFINE_GUID(DXVADDI_ModeH264_D, 0x1b81be67, 0xa0c7, 0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
DEFINE_GUID(DXVADDI_ModeH264_E, 0x1b81be68, 0xa0c7, 0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
DEFINE_GUID(DXVADDI_ModeH264_F, 0x1b81be69, 0xa0c7, 0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);DEFINE_GUID(DXVADDI_ModeWMV8_A, 0x1b81be80, 0xa0c7, 0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
DEFINE_GUID(DXVADDI_ModeWMV8_B, 0x1b81be81, 0xa0c7, 0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);DEFINE_GUID(DXVADDI_ModeWMV9_A, 0x1b81be90, 0xa0c7, 0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
DEFINE_GUID(DXVADDI_ModeWMV9_B, 0x1b81be91, 0xa0c7, 0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
DEFINE_GUID(DXVADDI_ModeWMV9_C, 0x1b81be94, 0xa0c7, 0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);DEFINE_GUID(DXVADDI_ModeVC1_A, 0x1b81beA0, 0xa0c7, 0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
DEFINE_GUID(DXVADDI_ModeVC1_B, 0x1b81beA1, 0xa0c7, 0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
DEFINE_GUID(DXVADDI_ModeVC1_C, 0x1b81beA2, 0xa0c7, 0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
DEFINE_GUID(DXVADDI_ModeVC1_D, 0x1b81beA3, 0xa0c7, 0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);#define DXVADDI_ModeMPEG2_MOCOMP DXVADDI_ModeMPEG2_MoComp#define DXVADDI_ModeWMV8_PostProc DXVADDI_ModeWMV8_A
#define DXVADDI_ModeWMV8_MoComp DXVADDI_ModeWMV8_B#define DXVADDI_ModeWMV9_PostProc DXVADDI_ModeWMV9_A
#define DXVADDI_ModeWMV9_MoComp DXVADDI_ModeWMV9_B
#define DXVADDI_ModeWMV9_IDCT DXVADDI_ModeWMV9_C#define DXVADDI_ModeVC1_PostProc DXVADDI_ModeVC1_A
#define DXVADDI_ModeVC1_MoComp DXVADDI_ModeVC1_B
#define DXVADDI_ModeVC1_IDCT DXVADDI_ModeVC1_C
#define DXVADDI_ModeVC1_VLD DXVADDI_ModeVC1_D#define DXVADDI_ModeH264_MoComp_NoFGT DXVADDI_ModeH264_A
#define DXVADDI_ModeH264_MoComp_FGT DXVADDI_ModeH264_B
#define DXVADDI_ModeH264_IDCT_NoFGT DXVADDI_ModeH264_C
#define DXVADDI_ModeH264_IDCT_FGT DXVADDI_ModeH264_D
#define DXVADDI_ModeH264_VLD_NoFGT DXVADDI_ModeH264_E
#define DXVADDI_ModeH264_VLD_FGT DXVADDI_ModeH264_F
核心查询机制
Direct3D 运行时通过两步流程查询用户模式驱动程序(UMD)支持的视频加速解码GUID:
- 查询GUID数量:首先获取支持的GUID总数
- 获取GUID列表:然后获取具体的GUID列表
数据结构与参数说明
D3DDDIARG_GETCAPS 结构关键成员
typedef struct _D3DDDIARG_GETCAPS {D3DDDICAPS_TYPE Type; // 指定请求类型VOID* pInfo; // 此场景下始终为NULLVOID* pData; // 指向返回数据的缓冲区UINT DataSize; // 缓冲区大小(输入)/返回数据大小(输出)
} D3DDDIARG_GETCAPS;
详细查询流程
第一步:查询支持的GUID数量 (D3DDDICAPS_GETDECODEGUIDCOUNT)
运行时调用
D3DDDIARG_GETCAPS getCapsArgs = {};
getCapsArgs.Type = D3DDDICAPS_GETDECODEGUIDCOUNT;
getCapsArgs.pInfo = NULL;
getCapsArgs.pData = &guidCount; // 指向UINT变量
getCapsArgs.DataSize = sizeof(UINT);pUMD->GetCaps(&getCapsArgs);
UMD响应要求:
- 返回支持的视频解码GUID总数
- 不要求提供pInfo参数
- 通过pData返回计数值
- 设置DataSize为实际写入的数据大小
第二步:查询GUID列表 (D3DDDICAPS_GETDECODEGUIDS)
运行时调用:
std::vector<GUID> guidList(guidCount); // 根据前一步的数量预分配D3DDDIARG_GETCAPS getCapsArgs = {};
getCapsArgs.Type = D3DDDICAPS_GETDECODEGUIDS;
getCapsArgs.pInfo = NULL;
getCapsArgs.pData = guidList.data();
getCapsArgs.DataSize = guidCount * sizeof(GUID);pUMD->GetCaps(&getCapsArgs);
UMD响应要求:
- 填充pData缓冲区所有支持的GUID
- 按连续数组形式排列GUID
- 设置DataSize为实际写入的数据总字节数
- 保持GUID顺序一致(推荐按优先级排序)
典型支持的视频解码GUID
UMD可能返回的常见DXVA解码器GUID示例:
GUID | 描述 |
---|---|
DXVA2_ModeMPEG2_VLD | MPEG-2可变长度解码 |
DXVA2_ModeH264_E | H.264硬件加速解码 |
DXVA2_ModeVC1_D | VC-1解码 |
DXVA2_ModeHEVC_VLD_Main | HEVC/H.265主配置解码 |
DXVA2_ModeVP9_VLD_Profile0 | VP9 Profile0解码 |
错误处理规范
UMD应当处理以下情况:
缓冲区不足:当DataSize小于所需大小时
- 返回E_INVALIDARG或类似错误码
- 不修改缓冲区内容
无效参数:
- 当pData为NULL时返回E_POINTER
- 当Type不匹配时返回E_INVALIDARG
功能不支持:
- 若完全不支持视频解码,返回0个GUID
实现示例代码
UMD侧实现伪代码:
HRESULT UMD::GetCaps(D3DDDIARG_GETCAPS* pArgs) {if (!pArgs) return E_INVALIDARG;switch (pArgs->Type) {case D3DDDICAPS_GETDECODEGUIDCOUNT:if (pArgs->DataSize < sizeof(UINT)) return E_INVALIDARG;*(UINT*)pArgs->pData = SUPPORTED_GUIDS_COUNT;pArgs->DataSize = sizeof(UINT);return S_OK;case D3DDDICAPS_GETDECODEGUIDS: {size_t requiredSize = SUPPORTED_GUIDS_COUNT * sizeof(GUID);if (pArgs->DataSize < requiredSize) return E_INVALIDARG;memcpy(pArgs->pData, SUPPORTED_GUIDS_ARRAY, requiredSize);pArgs->DataSize = requiredSize;return S_OK;}// ...其他类型处理}
}
性能优化建议
- 缓存结果:UMD应缓存GUID列表避免重复计算
- 静态数据:多数情况下GUID列表是静态不变的
- 快速路径:对已知请求类型实现快速返回
- 并行安全:确保多线程调用安全性
这种两步查询机制允许运行时先确定所需缓冲区大小,再准确获取完整数据,是DirectX VA中标准的能力发现模式。