VMR 無視窗模式
[與此頁面 相關的功能 DirectShow是舊版功能。 它已被 MediaPlayer、 IMFMediaEngine和 Media Foundation 中的音訊/視訊擷取取代。 這些功能已針對Windows 10和Windows 11進行優化。 Microsoft 強烈建議新程式碼盡可能使用 MediaPlayer、 IMFMediaEngine 和 音訊/視訊擷取 ,而不是 DirectShow。 Microsoft 建議盡可能重寫使用舊版 API 的現有程式碼,以使用新的 API。]
無視窗模式是應用程式在應用程式視窗內轉譯視訊的慣用方式。 在無視窗模式中,視訊混合轉譯器不會載入其視窗管理員元件,因此不支援 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 方法,或使用 Capture Graph Builder 的 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 預設會建立四個輸入針腳,而不是一個輸入針腳。 因此,如果您混合了四個以上的視訊串流,您只需要呼叫 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;
}
相關主題