DXVA-HD 비디오 프로세서 만들기
Microsoft DirectX 비디오 가속 고화질(DXVA-HD)은 다음 두 가지 기본 인터페이스를 사용합니다.
- IDXVAHD_Device. DXVA-HD 디바이스를 나타냅니다. 이 인터페이스를 사용하여 디바이스 기능을 쿼리하고 비디오 프로세서를 만듭니다.
- IDXVAHD_VideoProcessor. 비디오 처리 기능 집합을 나타냅니다. 이 인터페이스를 사용하여 비디오 처리 블릿을 수행합니다.
다음 코드에서는 다음과 같은 전역 변수가 가정됩니다.
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 구조를 채웁니다. 루마 키 또는 이미지 필터링과 같은 특정 비디오 처리 기능이 필요한 경우 이 구조를 사용하여 가용성을 검사.
DXVAHD_VPDEVCAPS caps; hr = pDXVAHD->GetVideoProcessorDeviceCaps(&caps);
DXVA-HD 디바이스가 필요한 입력 비디오 형식을 지원하는지 확인합니다. 지원되는 DXVA-HD 형식 확인 항목에서는 이 단계를 자세히 설명합니다.
DXVA-HD 디바이스가 필요한 출력 형식을 지원하는지 확인합니다. 지원되는 DXVA-HD 형식 확인 섹션에서는 이 단계를 자세히 설명합니다.
DXVAHD_VPCAPS 구조체 배열을 할당합니다. 할당해야 하는 배열 요소의 수는 3단계에서 가져온 DXVAHD_VPDEVCAPS 구조체의 VideoProcessorCount 멤버가 지정합니다.
// 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 함수는 비디오 프로세서를 만듭니다(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;
}
관련 항목