2016-09-23 75 views
2

我正在使用DirectShow.NET創建攝像頭控件。我想將相機的視頻渲染到WPF窗口中。目前發生的事情是,IVMRWindowlessControl9似乎沒有進入無窗口模式,並且沒有被指定給我的窗口,即使我正在調用適當的方法。IVMRWindowlessControl9未呈現到父級WPF窗口

爲什麼這些方法不被調用?還有什麼我不是在做什麼?

下面是相關的代碼片段:

IGraphBuilder graphBuilder = (IGraphBuilder) new FilterGraph(); 
ICaptureGraphBuilder2 captureGraphBuilder = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();    
IMediaControl mediaControl = (IMediaControl) this.graphBuilder; 
IBaseFilter renderFilter = (IBaseFilter) new VideoMixingRenderer9(); 

hr = this.captureGraphBuilder.SetFiltergraph(this.graphBuilder); 
DsError.ThrowExceptionForHR(hr); 

IBaseFilter sourceFilter = FindCaptureDevice(); 

hr = this.graphBuilder.AddFilter(sourceFilter, "Video Capture");       
DsError.ThrowExceptionForHR(hr); 

SetCaptureResolution(); 

IVMRFilterConfig9 filterConfig = (IVMRFilterConfig9)renderFilter; 

hr = filterConfig.SetNumberOfStreams(1); 
DsError.ThrowExceptionForHR(hr); 

hr = filterConfig.SetRenderingMode(VMR9Mode.Windowless); 
DsError.ThrowExceptionForHR(hr); 

windowlessControl = (IVMRWindowlessControl9)renderFilter; 

hr = this.graphBuilder.AddFilter(renderFilter, "Video Capture"); 
DsError.ThrowExceptionForHR(hr); 

Window window = Window.GetWindow(this); 
var wih = new WindowInteropHelper(window); 
IntPtr hWnd = wih.Handle; 
hr = windowlessControl.SetVideoClippingWindow(hWnd); 
DsError.ThrowExceptionForHR(hr); 

hr = windowlessControl.SetAspectRatioMode(VMR9AspectRatioMode.LetterBox); 
DsError.ThrowExceptionForHR(hr); 

hr = this.captureGraphBuilder.RenderStream(PinCategory.Capture, MediaType.Video, sourceFilter, null, null); 
DsError.ThrowExceptionForHR(hr); 

Marshal.ReleaseComObject(sourceFilter); 

hr = this.mediaControl.Run(); 
DsError.ThrowExceptionForHR(hr); 

這裏是正在發生的圖像(我發的背景綠色,使其更容易看到): WPF & IVMRWindowlessControl9

這是過濾器圖的示意圖: enter image description here

要回答潛在的問題(因爲我有這個問題p ),是的,hWnd正在設置/有一個值 - 所以windowlessControl確實有一個指向窗口的指針。

+0

'SetNumberOfStreams'可能爲時過早,'SetRenderingMode'應該[首先](https://msdn.microsoft.com/en-us/library/windows/desktop/dd407299)。 ActiveMovie窗口表示視頻渲染器未設置。您的有效過濾器圖表可能不是您期望的圖表。請參閱[瞭解您的DirectShow過濾器圖表](http://alax.info/blog/1678)。具體來說,你的有效圖表可能有兩個渲染器。 –

+0

@RomanR。 http://imgur.com/a/wjjm5 - 這是我在應用程序運行時捕獲的過濾器圖形圖像的鏈接。這看起來很正常嗎? –

回答

1

運行過濾器圖形時創建的彈出式窗口「ActiveMovie Window」是視頻渲染器過濾器的一種症狀,插入管道並以默認模式運行,未被配置爲其他UI的一部分:嵌入爲子窗口等。

你扭轉你的圖形闡明瞭這是怎麼回事:

您插入並設置了一個視頻渲染器過濾器,那麼還有另外一個由API添加並連接到您的輸入。雖然嵌入到您的用戶界面是第一個,但它保持空閒,另一個呈現視頻彈出。

的代碼線,給人的問題是:

hr = this.captureGraphBuilder.RenderStream(PinCategory.Capture, 
    MediaType.Video, sourceFilter, null, null); 

的問題是quite typical爲那些誰通過插入視頻渲染器,並期待他們拾起並連接建立圖表,尤其是它有時作品和這樣的代碼片段可能會在網上找到。

MSDN說:

如果pSink參數爲NULL,則該方法嘗試使用默認渲染器。 對於視頻,它使用Video Renderer,對於音頻,它使用DirectSound渲染器。

該調用添加了另一個實例,並且您希望現有的實例已連接。雖然RenderStream是一個強大的調用,並且過濾魔術以使事物連接起來,但很容易導致它以錯誤的方式完成某些事情。

如果您已經有了您的視頻渲染器,則可以在此調用中將其用作接收器參數。或者,您可以避免執行RenderStream並逐步添加您需要的過濾器,以確保所有內容都按照您的期望進行構建。或者,另一種選擇是IFilterGraph2::RenderEx調用,而不是與AM_RENDEREX_RENDERTOEXISTINGRENDERERS標誌:

...的方法試圖在過濾圖中已經使用的渲染器。 它不會向圖中添加新的渲染器。(如果需要,它將添加中間轉換過濾器。)要使方法成功,該圖必須包含適當的渲染器,並且它們必須具有未連接的輸入引腳。

+0

我使用渲染過濾器作爲接收器參數。它似乎創建了預期的圖形,但是,我沒有在窗口中顯示視頻。沒有'ActiveMovie窗口'了,但網絡攝像頭視頻沒有出現在窗口中。 這是我加入渲染濾波器: 'HR = this.captureGraphBuilder.RenderStream(PinCategory.Capture,MediaType.Video,sourceFilter,NULL,renderFilter);' 這是什麼樣的窗口看起來像一個圖像: http://imgur.com/a/ljMPS。 這是新捕獲圖形的圖像:http://imgur.com/a/FiLOU。 –

+1

您是否使用['IVMRWindowlessControl9 :: SetVideoPosition'](https://msdn.microsoft.com/en-us/library/windows/desktop/dd390550)定位渲染器?我在上面的代碼中沒有看到它。此外,你可以更新你的問題(特別是插入圖像) –

+0

優秀。出於某種原因,我認爲'IVMRWindowlessControl9'不需要SetVideoPosition()。但是這個伎倆。所以最終,這是我的濾波器圖形設置不正確以及需要設置視頻位置的組合。 –