天天看點

WPF中在攝像頭視訊上疊加控件的解決方案

原文: WPF中在攝像頭視訊上疊加控件的解決方案

一、視訊呈現

  前段時間,在一個wpf的項目中需要實時顯示ip攝像頭,對此的解決方案想必大家都應該知道很多。在winform中,我們可以将一個控件(一般用panel或者pictruebox)的句柄丢給攝像頭的sdk以實作該功能,而在wpf中我們同樣可以使用該方案快速實作。

  我們以海康平台為例,海康的sdk就需要我們傳遞一個控件的句柄,winform中可以直接使用控件的handle屬性來擷取句柄,而在wpf中我們則有兩種方法:

  1、将WindowsFormsHost作為容器在内部嵌套一個winform控件,比如panel,這樣的話就和winform中一樣了;

  2、直接使用    ((HwndSource)PresentationSource.FromVisual(你的wpf元素)).Handle;  擷取句柄;

二、疊加控件

  簡單的視訊展示使用一中的方案就可以解決,但我接手的項目是一個将攝像頭視訊用以AR處理的程式,界面上需要展示很多圖示和資訊欄,最重要的是整個主程式的大背景就是實時的攝像頭畫面,除此之外還有各種子視窗,子視窗中也要用到視訊,這樣就必然涉及到在視訊畫面上疊加控件的難題。  

  1、使用Microsoft.DwayneNeed

  之是以說是難題,是微軟也在試圖解決卻也沒有給出真正完美的解決方案。這個難題就是著名的空域問題(airspace issues)。這裡有一份園友的随筆連結,主要介紹的是微軟目前的解決方案:http://www.cnblogs.com/sela/p/4948102.html,這套方案在我實際使用中雖然可以正常的在視訊上疊加控件,但在上方拖動控件則非常卡頓,通常的情況就是滑鼠已經移動到了右側,被拖控件還在左側依依不舍,即便是release版本也無濟于事,這套方案最終流産。 

  

  2、将視訊流轉碼,使用d3d渲染為ImageSource

  此方案比較麻煩,需要自己控制轉碼過程,這裡有一篇關于此方案的文章連結:http://blog.csdn.net/yangyy9611/article/details/17464133,我這裡準備了一份demo(非本人編寫):https://pan.baidu.com/s/1eSABfma,以下是demo運作的截圖:

WPF中在攝像頭視訊上疊加控件的解決方案

  大緻的原理就是利用sdk的回調機制逐幀擷取碼流,再使用direct進行渲染;

  此方案除了代碼量相對多點之外還存在和1中同樣的問題,控件拖動時依然卡頓,各位園友不知有何好的解決辦法呢。

  3、最終的解決方案

  在1和2都達不到理想中的要求時,我突然意識到一個問題,為什麼會出現空域問題?那是因為winform和wpf的渲染方式不同,如果将他們統一,問題是不是解決了?隻能說解決了一半,如果需要疊加的控件是規規矩矩的矩形,換句話說,不需要透明通道的那些控件,則完全可以使用這套方案,但是像那些有圓角的控件還需要另外想辦法,我們先說前者吧,簡單的代碼如下:

<wfi:WindowsFormsHost>
    <wf:Panel/>
</wfi:WindowsFormsHost>
<wfi:WindowsFormsHost Width="114" Height="152">
  <ElementHost>
    <Border Width="114" Height="152"/>
  </ElementHost>
</wfi:WindowsFormsHost>      

  其實就是在 WindowsFormsHost再套一個ElementHost,現在無論是視訊的panel還是在其上方的border控件由于都被WindowsFormsHost所包含,是以border在渲染時不會被覆寫到底層了。

  下面再談談我個人認為最難的不規則控件的疊加方式,如果你能在wpf應用中通過代碼讓WindowsFormsHost背景透明,那麼你不需要再繼續往下看了,請你聯系我,我認為這才是最好的解決方案,而接下來我要說的方案可能會讓你們不屑,甚至嘲笑。

  我的辦法很簡單,就是使用兩個視窗,底部視窗單獨顯示視訊,并設定為主視窗,頂部視窗設定AllowsTransparency="True",ShowInTaskbar="False",在顯示頂部視窗時使用showdialog而不是show,這樣能夠保證使用者永遠在頂部視窗上操作,到不了視訊視窗。針對子視窗的情況,雖然可以用popup來模拟上述過程,但popup也有很多問題,他預設是置頂的,有時會給使用者帶來困惑,比如兩個子視窗重疊時,明明帶視訊的那個視窗在底部,但由于其中的視訊部分使用的是popup來展示的,它居然會顯示在頂層視窗之上,完美實作了視窗洗牌的特效,除此之外你還需要通過特殊的偏移量才能控制popup的位置,鑒于此,我建議你單獨定制一個專門用來彈出資訊的窗體,再将包含視訊的控件作為子元素傳入其中。

  最終的解決方案是結合這三種,由于主界面是個實時視訊大背景,是以任何拖動的操作都不該延遲,是以主界面用了3号解決方案,而一些子界面不涉及到在上方拖動的操作,則可以用1号方案,至于2号方案則可以用來相容各大視訊平台,例如有些視訊平台不支援句柄的傳入,則可以使用該方案。

繼續閱讀