共用方式為


VMR 無視窗模式

[與此頁面相關聯的功能,DirectShow是舊版功能。 它已被 MediaPlayer、imfMediaEngine 取代,並在媒體基金會 音訊/視訊擷取。 這些功能已針對 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 篩選器的輸入針腳。 有各種方式可以建置圖形,例如直接連接釘選、使用智慧型 Connect 方法,例如 IGraphBuilder::RenderFile,或使用擷取圖形產生器的 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;
}

使用無視窗模式