window 显示驱动开发-提供视频解码功能(二)

发布于:2025-06-05 ⋅ 阅读:(26) ⋅ 点赞:(0)

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:

  1. 查询GUID数量:首先获取支持的GUID总数
  2. 获取GUID列表:然后获取具体的GUID列表

数据结构与参数说明
D3DDDIARG_GETCAPS 结构关键成员

typedef struct _D3DDDIARG_GETCAPS {
    D3DDDICAPS_TYPE Type;  // 指定请求类型
    VOID* pInfo;           // 此场景下始终为NULL
    VOID* 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;
    }
    // ...其他类型处理
    }
}

性能优化建议

  1. 缓存结果:UMD应缓存GUID列表避免重复计算
  2. 静态数据:多数情况下GUID列表是静态不变的
  3. 快速路径:对已知请求类型实现快速返回
  4. 并行安全:确保多线程调用安全性

这种两步查询机制允许运行时先确定所需缓冲区大小,再准确获取完整数据,是DirectX VA中标准的能力发现模式。


网站公告

今日签到

点亮在社区的每一天
去签到