VMR 창 없는 모드

[이 페이지와 연결된 기능인 DirectShow는 레거시 기능입니다. MediaPlayer, IMFMediaEngineMedia 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

창 없는 모드에 대한 VMR-7 구성

창 없는 모드에 대해 VMR-7을 구성하려면 VMR의 입력 핀을 연결하기 전에 다음 단계를 모두 수행합니다.

  1. 필터를 만들고 그래프에 추가합니다.

  2. VMRMode_Windowless 플래그를 사용하여 IVMRFilterConfig::SetRenderingMode 메서드를 호출합니다.

  3. 필요에 따라 IVMRFilterConfig::SetNumberOfStreams를 호출하여 여러 입력 스트림에 대한 VMR을 구성합니다. VMR은 각 스트림에 대한 입력 핀을 만듭니다. IVMRMixerControl 인터페이스를 사용하여 스트림에 대한 Z 순서 및 기타 매개 변수를 설정합니다. 자세한 내용은 여러 스트림이 있는 VMR(혼합 모드)을 참조하세요.

    SetNumberOfStreams를 호출하지 않으면 VMR-7은 기본적으로 하나의 입력 핀으로 설정됩니다. 입력 핀이 연결되면 핀 수를 변경할 수 없습니다.

  4. IVMRWindowlessControl::SetVideoClippingWindow를 호출하여 렌더링된 비디오가 표시되는 창을 지정합니다.

이러한 단계가 완료되면 VMR 필터의 입력 핀을 연결할 수 있습니다. 핀을 직접 연결하거나, IGraphBuilder::RenderFile과 같은 Intelligent Connect 메서드를 사용하거나, 캡처 그래프 작성기의 ICaptureGraphBuilder2::RenderStream 메서드를 사용하는 등 다양한 방법으로 그래프를 빌드할 수 있습니다. 자세한 내용은 일반 Graph-Building 기술을 참조하세요.

애플리케이션 창 내에서 비디오의 위치를 설정하려면 IVMRWindowlessControl::SetVideoPosition 메서드를 호출합니다. IVMRWindowlessControl::GetNativeVideoSize 메서드는 네이티브 비디오 크기를 반환합니다. 재생하는 동안 애플리케이션은 VMR에 다음 Windows 메시지를 알려야 합니다.

참고

MFC 애플리케이션은 빈 WM_ERASEBKGND 메시지 처리기를 정의해야 합니다. 그렇지 않으면 비디오 표시 영역이 올바르게 다시 그려지지 않습니다.

 

창 없는 모드에 대한 VMR-9 구성

창 없는 모드에 대해 VMR-9를 구성하려면 창 없는 모드용 VMR-7에 대해 설명된 단계를 사용하지만 IVMRFilterConfig9IVMRWindowlessControl9 인터페이스를 사용합니다. 유일한 중요한 차이점은 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;
}

창 없는 모드 사용