创建 DXVA-HD 视频处理器
Microsoft DirectX 视频加速高清 (DXVA-HD) 使用两个主要接口:
- IDXVAHD_Device。 表示 DXVA-HD 设备。 使用此接口查询设备功能和创建视频处理器。
- IDXVAHD_VideoProcessor。 表示一组视频处理功能。 使用此接口执行视频处理 blit。
在下面的代码中,假定使用以下全局变量:
IDirect3D9Ex *g_pD3D = NULL;
IDirect3DDevice9Ex *g_pD3DDevice = NULL; // Direct3D device.
IDXVAHD_Device *g_pDXVAHD = NULL; // DXVA-HD device.
IDXVAHD_VideoProcessor *g_pDXVAVP = NULL; // DXVA-HD video processor.
IDirect3DSurface9 *g_pSurface = NULL; // Video surface.
const D3DFORMAT RENDER_TARGET_FORMAT = D3DFMT_X8R8G8B8;
const D3DFORMAT VIDEO_FORMAT = D3DFMT_X8R8G8B8;
const UINT VIDEO_FPS = 60;
const UINT VIDEO_WIDTH = 640;
const UINT VIDEO_HEIGHT = 480;
创建 DXVA-HD 视频处理器:
使用视频内容的说明填充 DXVAHD_CONTENT_DESC 结构。 驱动程序使用此信息作为优化视频处理器功能的提示。 结构不包含完整的格式说明。
DXVAHD_RATIONAL fps = { VIDEO_FPS, 1 }; DXVAHD_CONTENT_DESC desc; desc.InputFrameFormat = DXVAHD_FRAME_FORMAT_PROGRESSIVE; desc.InputFrameRate = fps; desc.InputWidth = VIDEO_WIDTH; desc.InputHeight = VIDEO_HEIGHT; desc.OutputFrameRate = fps; desc.OutputWidth = VIDEO_WIDTH; desc.OutputHeight = VIDEO_HEIGHT;
调用 DXVAHD_CreateDevice 以创建 DXVA-HD 设备。 此函数返回指向 IDXVAHD_Device 接口的 指针。
hr = DXVAHD_CreateDevice(g_pD3DDevice, &desc, DXVAHD_DEVICE_USAGE_PLAYBACK_NORMAL, NULL, &pDXVAHD);
调用 IDXVAHD_Device::GetVideoProcessorDeviceCaps。 此方法使用设备功能填充 DXVAHD_VPDEVCAPS 结构。 如果需要特定的视频处理功能(如 luma 键控制或图像筛选),请使用此结构检查其可用性。
DXVAHD_VPDEVCAPS caps; hr = pDXVAHD->GetVideoProcessorDeviceCaps(&caps);
检查 DXVA-HD 设备是否支持所需的输入视频格式。 检查 支持的 DXVA-HD 格式 主题更详细地介绍了此步骤。
检查 DXVA-HD 设备是否支持所需的输出格式。 检查支持的 DXVA-HD 格式部分更详细地介绍了此步骤。
分配 DXVAHD_VPCAPS 结构的数组。 必须分配的数组元素数由DXVAHD_VPDEVCAPS结构的 VideoProcessorCount 成员提供,在步骤 3 中获取。
// Create the array of video processor caps. DXVAHD_VPCAPS *pVPCaps = new (std::nothrow) DXVAHD_VPCAPS[ caps.VideoProcessorCount ]; if (pVPCaps == NULL) { return E_OUTOFMEMORY; }
每个 DXVAHD_VPCAPS 结构表示不同的视频处理器。 可以循环访问此数组,以发现每个视频处理器的功能。 结构包括有关视频处理器的去交错、电视拍摄和帧速率转换功能的信息。
选择要创建的视频处理器。 DXVAHD_VPCAPS 结构的 VPGuid 成员包含唯一标识视频处理器的 GUID。 将此 GUID 传递给 IDXVAHD_Device::CreateVideoProcessor 方法。 方法返回 IDXVAHD_VideoProcessor 指针。
HRESULT hr = pDXVAHD->GetVideoProcessorCaps( caps.VideoProcessorCount, pVPCaps);
(可选)调用 IDXVAHD_Device::CreateVideoSurface 以创建输入视频图面数组。
下面的代码示例演示了完整的步骤序列:
// Initializes the DXVA-HD video processor.
// NOTE: The following example makes some simplifying assumptions:
//
// 1. There is a single input stream.
// 2. The input frame rate matches the output frame rate.
// 3. No advanced DXVA-HD features are needed, such as luma keying or IVTC.
// 4. The application uses a single input video surface.
HRESULT InitializeDXVAHD()
{
if (g_pD3DDevice == NULL)
{
return E_FAIL;
}
HRESULT hr = S_OK;
IDXVAHD_Device *pDXVAHD = NULL;
IDXVAHD_VideoProcessor *pDXVAVP = NULL;
IDirect3DSurface9 *pSurf = NULL;
DXVAHD_RATIONAL fps = { VIDEO_FPS, 1 };
DXVAHD_CONTENT_DESC desc;
desc.InputFrameFormat = DXVAHD_FRAME_FORMAT_PROGRESSIVE;
desc.InputFrameRate = fps;
desc.InputWidth = VIDEO_WIDTH;
desc.InputHeight = VIDEO_HEIGHT;
desc.OutputFrameRate = fps;
desc.OutputWidth = VIDEO_WIDTH;
desc.OutputHeight = VIDEO_HEIGHT;
#ifdef USE_SOFTWARE_PLUGIN
HMODULE hSWPlugin = LoadLibrary(L"C:\\dxvahdsw.dll");
PDXVAHDSW_Plugin pSWPlugin = (PDXVAHDSW_Plugin)GetProcAddress(hSWPlugin, "DXVAHDSW_Plugin");
hr = DXVAHD_CreateDevice(g_pD3DDevice, &desc,DXVAHD_DEVICE_USAGE_PLAYBACK_NORMAL,
pSWPlugin, &pDXVAHD);
#else
hr = DXVAHD_CreateDevice(g_pD3DDevice, &desc, DXVAHD_DEVICE_USAGE_PLAYBACK_NORMAL,
NULL, &pDXVAHD);
#endif
if (FAILED(hr))
{
goto done;
}
DXVAHD_VPDEVCAPS caps;
hr = pDXVAHD->GetVideoProcessorDeviceCaps(&caps);
if (FAILED(hr))
{
goto done;
}
// Check whether the device supports the input and output formats.
hr = CheckInputFormatSupport(pDXVAHD, caps, VIDEO_FORMAT);
if (FAILED(hr))
{
goto done;
}
hr = CheckOutputFormatSupport(pDXVAHD, caps, RENDER_TARGET_FORMAT);
if (FAILED(hr))
{
goto done;
}
// Create the VP device.
hr = CreateVPDevice(pDXVAHD, caps, &pDXVAVP);
if (FAILED(hr))
{
goto done;
}
// Create the video surface for the primary video stream.
hr = pDXVAHD->CreateVideoSurface(
VIDEO_WIDTH,
VIDEO_HEIGHT,
VIDEO_FORMAT,
caps.InputPool,
0, // Usage
DXVAHD_SURFACE_TYPE_VIDEO_INPUT,
1, // Number of surfaces to create
&pSurf, // Array of surface pointers
NULL
);
if (FAILED(hr))
{
goto done;
}
g_pDXVAHD = pDXVAHD;
g_pDXVAHD->AddRef();
g_pDXVAVP = pDXVAVP;
g_pDXVAVP->AddRef();
g_pSurface = pSurf;
g_pSurface->AddRef();
done:
SafeRelease(&pDXVAHD);
SafeRelease(&pDXVAVP);
SafeRelease(&pSurf);
return hr;
}
此示例中的 CreateVPDevice 函数 show 创建视频处理器 (步骤 5-7) :
// Creates a DXVA-HD video processor.
HRESULT CreateVPDevice(
IDXVAHD_Device *pDXVAHD,
const DXVAHD_VPDEVCAPS& caps,
IDXVAHD_VideoProcessor **ppDXVAVP
)
{
// Create the array of video processor caps.
DXVAHD_VPCAPS *pVPCaps =
new (std::nothrow) DXVAHD_VPCAPS[ caps.VideoProcessorCount ];
if (pVPCaps == NULL)
{
return E_OUTOFMEMORY;
}
HRESULT hr = pDXVAHD->GetVideoProcessorCaps(
caps.VideoProcessorCount, pVPCaps);
// At this point, an application could loop through the array and examine
// the capabilities. For purposes of this example, however, we simply
// create the first video processor in the list.
if (SUCCEEDED(hr))
{
// The VPGuid member contains the GUID that identifies the video
// processor.
hr = pDXVAHD->CreateVideoProcessor(&pVPCaps[0].VPGuid, ppDXVAVP);
}
delete [] pVPCaps;
return hr;
}
相关主题