VMR 창 없는 모드
[이 페이지와 연결된 기능인 DirectShow는 레거시 기능입니다. MediaPlayer, IMFMediaEngine 및 Media Foundation의 오디오/비디오 캡처로 대체되었습니다. 이러한 기능은 Windows 10 및 Windows 11 최적화되었습니다. 가능한 경우 새 코드에서 DirectShow 대신 MediaPlayer, IMFMediaEngine 및 오디오/비디오 캡처를 사용하는 것이 좋습니다. 가능한 경우 레거시 API를 사용하는 기존 코드를 다시 작성하여 새 API를 사용하도록 제안합니다.]
창 없는 모드는 애플리케이션이 애플리케이션 창 내에서 비디오를 렌더링하는 데 선호되는 방법입니다. 창 없는 모드에서 비디오 혼합 렌더러는 Window Manager 구성 요소를 로드하지 않으므로 IBasicVideo 또는 IVideoWindow 인터페이스를 지원하지 않습니다. 대신 애플리케이션은 재생 창을 제공하고 VMR이 비디오를 그릴 수 있도록 클라이언트 영역에서 대상 사각형을 설정합니다. VMR은 DirectDraw clipper 개체를 사용하여 비디오가 애플리케이션의 창으로 잘리고 다른 창에 표시되지 않도록 합니다. VMR은 애플리케이션 창을 서브클래스하거나 시스템/프로세스 후크를 설치하지 않습니다.
창 없는 모드에서는 연결 중 이벤트 시퀀스를 실행하고 실행 상태로 전환하는 순서는 다음과 같습니다.
- 업스트림 필터는 VMR이 허용하거나 거부하는 미디어 형식을 제안합니다.
- 미디어 유형이 수락되면 VMR은 할당자-발표자를 호출하여 DirectDraw 표면을 가져옵니다. 표면이 성공적으로 만들어지면 핀이 연결되고 VMR이 실행 상태로 전환될 준비가 됩니다.
- 필터 그래프가 실행되면 디코더는 GetBuffer 를 호출하여 할당자에서 미디어 샘플을 가져옵니다. VMR은 할당자-발표자를 쿼리하여 DirectDraw 표면의 픽셀 깊이, 사각형 크기 및 기타 매개 변수가 들어오는 비디오와 호환되는지 확인합니다. 호환되는 경우 VMR은 DirectDraw 표면을 디코더에 반환합니다. 디코더가 표면으로 디코딩된 후 VMR의 코어 동기화 단위는 타임스탬프를 확인합니다. 이 단원에서는 프레젠테이션 시간이 도착할 때까지 수신 호출을 차단합니다. 이 시점에서 VMR은 할당자-발표자에서 PresentImage를 호출하여 그래픽 카드 표면을 표시합니다.
다음 그림에서는 여러 입력 스트림이 있는 창 없는 모드의 VMR을 보여 줍니다.
창 없는 모드에 대한 VMR-7 구성
창 없는 모드에 대해 VMR-7을 구성하려면 VMR의 입력 핀을 연결하기 전에 다음 단계를 모두 수행합니다.
필터를 만들고 그래프에 추가합니다.
VMRMode_Windowless 플래그를 사용하여 IVMRFilterConfig::SetRenderingMode 메서드를 호출합니다.
필요에 따라 IVMRFilterConfig::SetNumberOfStreams를 호출하여 여러 입력 스트림에 대한 VMR을 구성합니다. VMR은 각 스트림에 대한 입력 핀을 만듭니다. IVMRMixerControl 인터페이스를 사용하여 스트림에 대한 Z 순서 및 기타 매개 변수를 설정합니다. 자세한 내용은 여러 스트림이 있는 VMR(혼합 모드)을 참조하세요.
SetNumberOfStreams를 호출하지 않으면 VMR-7은 기본적으로 하나의 입력 핀으로 설정됩니다. 입력 핀이 연결되면 핀 수를 변경할 수 없습니다.
IVMRWindowlessControl::SetVideoClippingWindow를 호출하여 렌더링된 비디오가 표시되는 창을 지정합니다.
이러한 단계가 완료되면 VMR 필터의 입력 핀을 연결할 수 있습니다. 핀을 직접 연결하거나, IGraphBuilder::RenderFile과 같은 Intelligent Connect 메서드를 사용하거나, 캡처 그래프 작성기의 ICaptureGraphBuilder2::RenderStream 메서드를 사용하는 등 다양한 방법으로 그래프를 빌드할 수 있습니다. 자세한 내용은 일반 Graph-Building 기술을 참조하세요.
애플리케이션 창 내에서 비디오의 위치를 설정하려면 IVMRWindowlessControl::SetVideoPosition 메서드를 호출합니다. IVMRWindowlessControl::GetNativeVideoSize 메서드는 네이티브 비디오 크기를 반환합니다. 재생하는 동안 애플리케이션은 VMR에 다음 Windows 메시지를 알려야 합니다.
- WM_PAINT: IVMRWindowlessControl::RepaintVideo 를 호출하여 이미지를 다시 칠합니다.
- WM_DISPLAYCHANGE: IVMRWindowlessControl::D isplayModeChanged를 호출합니다. VMR은 비디오를 새 해상도 또는 색 깊이로 표시하는 데 필요한 모든 작업을 수행합니다.
- WM_SIZE: 비디오의 위치를 다시 계산하고 필요한 경우 SetVideoPosition 을 다시 호출합니다.
참고
MFC 애플리케이션은 빈 WM_ERASEBKGND 메시지 처리기를 정의해야 합니다. 그렇지 않으면 비디오 표시 영역이 올바르게 다시 그려지지 않습니다.
창 없는 모드에 대한 VMR-9 구성
창 없는 모드에 대해 VMR-9를 구성하려면 창 없는 모드용 VMR-7에 대해 설명된 단계를 사용하지만 IVMRFilterConfig9 및 IVMRWindowlessControl9 인터페이스를 사용합니다. 유일한 중요한 차이점은 VMR-9가 기본적으로 하나의 입력 핀이 아닌 4개의 입력 핀을 만든다는 것입니다. 따라서 4개 이상의 비디오 스트림을 혼합하는 경우에만 SetNumberOfStreams 를 호출하면 됩니다.
예제 코드
다음 코드에서는 VMR-7 필터를 만들고 DirectShow 필터 그래프에 추가한 다음 VMR을 창 없는 모드로 설정하는 방법을 보여 줍니다. VMR-9의 경우 CoCreateInstance 의 CLSID_VideoMixingRenderer9 및 해당 VMR-9 인터페이스를 사용합니다.
HRESULT InitializeWindowlessVMR(
HWND hwndApp, // Application window.
IFilterGraph* pFG, // Pointer to the Filter Graph Manager.
IVMRWindowlessControl** ppWc, // Receives the interface.
DWORD dwNumStreams, // Number of streams to use.
BOOL fBlendAppImage // Are we alpha-blending a bitmap?
)
{
IBaseFilter* pVmr = NULL;
IVMRWindowlessControl* pWc = NULL;
*ppWc = NULL;
// Create the VMR and add it to the filter graph.
HRESULT hr = CoCreateInstance(CLSID_VideoMixingRenderer, NULL,
CLSCTX_INPROC, IID_IBaseFilter, (void**)&pVmr);
if (FAILED(hr))
{
return hr;
}
hr = pFG->AddFilter(pVmr, L"Video Mixing Renderer");
if (FAILED(hr))
{
pVmr->Release();
return hr;
}
// Set the rendering mode and number of streams.
IVMRFilterConfig* pConfig;
hr = pVmr->QueryInterface(IID_IVMRFilterConfig, (void**)&pConfig);
if (SUCCEEDED(hr))
{
pConfig->SetRenderingMode(VMRMode_Windowless);
// Set the VMR-7 to mixing mode if you want more than one video
// stream, or you want to mix a static bitmap over the video.
// (The VMR-9 defaults to mixing mode with four inputs.)
if (dwNumStreams > 1 || fBlendAppImage)
{
pConfig->SetNumberOfStreams(dwNumStreams);
}
pConfig->Release();
hr = pVmr->QueryInterface(IID_IVMRWindowlessControl, (void**)&pWc);
if (SUCCEEDED(hr))
{
pWc->SetVideoClippingWindow(hwndApp);
*ppWc = pWc; // The caller must release this interface.
}
}
pVmr->Release();
// Now the VMR can be connected to other filters.
return hr;
}
관련 항목