天天看點

OMCS使用技巧 -- 攝像頭及其動态能力一.枚舉攝像頭二.擷取攝像頭支援的分辨率三.動态切換攝像頭四.動态修改攝像頭的分辨率五.動态調節編碼品質六.控制視訊輸出七.廣播時選擇丢棄視訊幀

      在開發類似視訊聊天的應用時,我們經常需要擷取攝像頭的相關資訊;而在進行視訊聊天時,我們可能還希望有一些動态的能力。比如,在不中斷視訊聊天的情況下,切換一個攝像頭、或者修改攝像頭采集的分辨率或編碼品質等等。OMCS提供了很多有用的特性以支援上述需求。

      我們如何得知目前的計算機有哪些攝像頭了?

      OMCS提供了一個工具類OMCS.Tools.Camera,來幫助我們擷取這些資訊。Camera有個靜态方法GetCameras,用于枚舉目前計算機上的所有攝像頭。 

      CameraInformation封裝了攝像頭的基本資訊,其類圖如下所示:

OMCS使用技巧 -- 攝像頭及其動态能力一.枚舉攝像頭二.擷取攝像頭支援的分辨率三.動态切換攝像頭四.動态修改攝像頭的分辨率五.動态調節編碼品質六.控制視訊輸出七.廣播時選擇丢棄視訊幀

      我們可以将GetCameras方法傳回的清單直接綁定到Combox控件,效果如下所示: 

OMCS使用技巧 -- 攝像頭及其動态能力一.枚舉攝像頭二.擷取攝像頭支援的分辨率三.動态切換攝像頭四.動态修改攝像頭的分辨率五.動态調節編碼品質六.控制視訊輸出七.廣播時選擇丢棄視訊幀

      預設情況下,IMultimediaManager使用的攝像頭的索引為0。如果索引為0的攝像頭不可用,或者,使用者指定使用其它的攝像頭,則可以将指定攝像頭的索引儲存到配置檔案。當用戶端程式啟動時,從配置檔案中讀取該索引值,并将其指派給IMultimediaManager的CameraDeviceIndex屬性。

      當選定了一個攝像頭,我們如何知道該攝像頭支援哪些采集分辨率、支援最高的幀頻是多少了?

      Camera提供了另一個靜态方法GetCameraCapability,來擷取目标攝像頭的能力資訊。  

       CameraCapability類封裝了攝像頭的能力資訊,其類圖如下所示:

OMCS使用技巧 -- 攝像頭及其動态能力一.枚舉攝像頭二.擷取攝像頭支援的分辨率三.動态切換攝像頭四.動态修改攝像頭的分辨率五.動态調節編碼品質六.控制視訊輸出七.廣播時選擇丢棄視訊幀

      我們可以将GetCameraCapability方法傳回的清單直接綁定到Combox控件,效果如下所示: 

OMCS使用技巧 -- 攝像頭及其動态能力一.枚舉攝像頭二.擷取攝像頭支援的分辨率三.動态切換攝像頭四.動态修改攝像頭的分辨率五.動态調節編碼品質六.控制視訊輸出七.廣播時選擇丢棄視訊幀

      下面我們設想一種情況,假設我的電腦上裝有兩個可用的攝像頭, 我正在使用索引為0的攝像頭和我的朋友視訊聊天,某個時刻,我想在不中斷視訊聊天的情況下,切換到索引為1的攝像頭。這種需求就稱為動态切換攝像頭。

       OMCS支援動态切換攝像頭,并且操作相當簡單:我們隻需要将IMultimediaManager的CameraDeviceIndex屬性指派為要切換到的攝像頭的索引即可。

       切換會在OMCS内部自動進行,在很短的時間切換完成後,OMCS會将新攝像頭采集的視訊資料發送給各個guest。  

       還記得QQ視訊聊天有這種能力,我們可以在視訊聊天的時候,選擇使用大視窗模式。這實際上就是使用攝像頭更高的分辨率來采集視訊,比如原始的采集分辨率為320*240,可切換到更高的640*480。

       OMCS支援在不需要任何中斷的情況下,修改正在使用的攝像頭的采集分辨率。操作也是相當簡單:我們隻需要将IMultimediaManager的CameraVideoSize屬性設定為目标分辨率大小即可。當然,如果設定的分辨率不被目前攝像頭所支援,則将抛出NotSupportedException。另外要注意,在編碼品質相同的情況下,視訊的分辨率越高,所輸出的碼流就越大,所要求的帶寬也越大。

        為了避免設定不恰當的分辨率給CameraVideoSize屬性,在指派之前,我們可以通過OMCS.Tools.Camera的靜态方法Support來判斷目标攝像頭是否支援指定的分辨率: 

      在用戶端運作的任何時候,我們都可以通過設定IMultimediaManager的CameraEncodeQuality屬性,來實時調整攝像頭采集的視訊的編碼品質。編碼品質越高(CameraEncodeQuality取值越小),對帶寬的要求就越高;反之亦然。

      當然,正如前面文章所介紹的,如果IMultimediaManager的AutoAdjustCameraEncodeQuality屬性被設定為true,則CameraEncodeQuality将會被OMCS自動調節以優先保證語音的清晰連貫,手動對CameraEncodeQuality的設定就不起作用了。

      如果我們将AutoAdjustCameraEncodeQuality設定為false,并且我們的應用自己能檢測到網絡狀态的實時變化,那麼,我們就可以根據目前的網絡狀态,來手動調整CameraEncodeQuality。

       設想這樣一種情況:我在進行視訊會議時,某個時間出于某種原因,我不想讓與會者看到我的視訊,一段時間後,我又希望恢複原樣。

       從節省帶寬的角度,最好的方式就是在這段時間内不輸出視訊幀。OMCS能簡單地實作這種控制:我們隻需将IMultimediaManager的OutputVideo屬性設定為false,即可關閉視訊幀的輸出。

       下面要設想的場景稍微複雜一點:在視訊會議時,我的視訊會發送給與會的每個人,假設我與每個與會者之間都建立的是P2P通道,視訊幀都經過P2P通道傳送。現在的問題時,每個P2P通道的品質是不一樣的,有的可能很快,有的可能很慢。我們假設到與會者A的通道非常慢,到其他與會者的通道品質都很好。那麼,我們來分析一下在兩種廣播模式下,可能出現的情況。

      在同步廣播模式下,隻有當某個視訊幀在所有的通道上都發送完畢時,才會去發送下一個視訊幀。這樣就會出現因為與A之間的通道緩慢,而導緻其他與會者看到自己的視訊出現卡或不連貫的情況。

      在異步廣播模式下,視訊幀在所有的通道上都是異步發送的,這樣A通道的緩慢不會影響到其它的與會者。OMCS采用的就是這種模式。

      但是,由于通道A的緩慢,生産視訊幀的速度遠大于通道A消費視訊幀的速度,這就導緻了需要使用更多的記憶體來緩存那些來不及發送的視訊幀。就用戶端程序看來,其所占用的記憶體會不斷增加,就像記憶體洩漏一樣。

      如何解決這個問題了?OMCS給出的方案是可以選擇在通道繁忙時丢棄幀。通過将IMultimediaManager的AllowDiscardFrameWhenBroadcast屬性設定為true,便可啟用這種方案。

      AllowDiscardFrameWhenBroadcast被啟用後,當一個新的視訊幀要通過某個P2P通道發送給對應的與會者時,會先檢測一下該P2P通道是否繁忙,如果繁忙,就取消該視訊幀在這個通道上的發送。這樣,就避免了記憶體無線增長的情況。但在這種方案下,那些通道比較慢的與會者,因為丢棄視訊幀的原因,看到别人的視訊可能就會出現馬賽克、卡、不連續的現象。

上一篇: 進駐51CTO

繼續閱讀