共用方式為


VMR 無視窗模式

[與此頁面 相關的功能 DirectShow是舊版功能。 它已被 MediaPlayerIMFMediaEngineMedia Foundation 中的音訊/視訊擷取取代。 這些功能已針對Windows 10和Windows 11進行優化。 Microsoft 強烈建議新程式碼盡可能使用 MediaPlayerIMFMediaEngine音訊/視訊擷取 ,而不是 DirectShow。 Microsoft 建議盡可能重寫使用舊版 API 的現有程式碼,以使用新的 API。]

無視窗模式是應用程式在應用程式視窗內轉譯視訊的慣用方式。 在無視窗模式中,視訊混合轉譯器不會載入其視窗管理員元件,因此不支援 IBasicVideoIVideoWindow 介面。 相反地,應用程式會提供播放視窗,並在工作區中設定目的地矩形,讓 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 方法,或使用 Capture Graph Builder 的 ICaptureGraphBuilder2::RenderStream 方法,來建置圖形,例如直接連接針腳。 如需詳細資訊,請參閱 一般Graph-Building技術

若要設定影片在應用程式視窗中的位置,請呼叫 IVMRWindowlessControl::SetVideoPosition 方法。 IVMRWindowlessControl::GetNativeVideoSize方法會傳回原生視訊大小。 在播放期間,應用程式應該通知 VMR 下列 Windows 訊息:

注意

MFC 應用程式必須定義空WM_ERASEBKGND訊息處理常式,否則影片顯示區域將無法正確重繪。

 

設定無視窗模式的 VMR-9

若要針對無視窗模式設定 VMR-9,請使用針對無視窗模式的 VMR-7 所述的步驟,但使用 IVMRFilterConfig9IVMRWindowlessControl9 介面。 唯一的顯著差異在於 VMR-9 預設會建立四個輸入針腳,而不是一個輸入針腳。 因此,如果您混合了四個以上的視訊串流,您只需要呼叫 SetNumberOfStreams

範例程式碼

下列程式碼示範如何建立 VMR-7 篩選器、將它新增至 DirectShow 篩選圖形,然後將 VMR 放入無視窗模式。 針對 VMR-9,請在 CoCreateInstance 和對應的 VMR-9 介面中使用CLSID_VideoMixingRenderer9。

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;
}

使用無視窗模式