轉自:http://www.cnblogs.com/fangkm/p/4374610.html
前面兩篇文章介紹WebRTC的執行流程和使用框架介面,接下來就開始分析本地音視訊的採集流程。由於篇幅較大,視訊採集和音訊採集分成兩篇博文,這裡先分析視訊採集流程。分析的時候先分析WebRTC原生的視訊採集流程,再捎帶提一下Chromium對WebRTC視訊採集的適配,這樣能更好地理解WebRTC的介面設計。
1. WebRTC原生視訊採集
在介紹視訊裝置的採集之前,首先要分析一下WebRTC的DeviceManager結構,因為視訊採集的抽象介面VideoCapturer的WebRTC原生實現就是通過它來建立的。這個類的功能還包括列舉音視訊裝置的相關資訊等。結構如下:
限於篇幅,該UML中沒有標出DeviceManagerInterface介面的所有功能介面,具體包括:獲取音訊輸入/輸出裝置列表、獲取視訊輸入裝置列表、根據裝置資訊建立VideoCapturer視訊採集物件等。由於獲取硬體裝置列表,涉及到平臺相關的呼叫,在Windows平臺下的實現是Win32DeviceManager類(可以呼叫DeviceManagerFactory的靜態方法Create()返回當前平臺相應的DeviceManager物件)。關注一下DeviceWatcher,顧名思義,它的功能在於監控裝置的變化。在Windows平臺下的實現Win32DeviceWatcher通過API函式RegisterDeviceNotification監控視訊類裝置和音訊類裝置的變化。當有監視的型別裝置傳送變化時,會通過DeviceManagerInterface介面的SignalDevicesChange訊號向外投遞通知。最後分析一下建立VideoCapturer的流程。DeviceManager建立VideoCapturer物件時通過VideoDeviceCapturerFactory介面來完成的。VideoDeviceCapturerFactory介面的預設實現是WebRtcVideoDeviceCapturerFactory類,該類建立WebRtcVideoCapturer物件做為VideoCapturer介面的實現。可以理解成WebRtcVideoCapturer就是WebRTC原生的視訊採集的實現,但這種說法不確切,因為視訊採集涉及到跨平臺,沒這麼簡單。下面再細扒一下WebRtcVideoCapturer:
由於平臺相關性,WebRtcVideoCapturer仍然不是視訊採集的真正實現,它建立一個VideoCaptureModule介面物件來完成真正的視訊採集工作。該抽象介面是視訊採集的實現介面,最終在Windows平臺下由VideoCaptureDS(傳統的DirectShow方式)和VideoCaptureMF(Vista之後的Media Foundation API實現方式)來實現採集工作。這裡要說明一下VideoCaptureMF在WebRTC中還是個空架子,還未真正實現,如果讀者對Media Foundation API實現視訊採集感興趣,可以參考Chromium的media庫中VideoCaptureDeviceMFWin類實現。
接下來分析一下VideoSourceInterface和VideoCapturer是如何結合,以及採集由誰驅動開始的。
VideoSource是WebRTC對VideoSourceInterface介面的實現, 它容納一個VideoCapturer物件做為視訊採集源,VideoRenderer是供外部從VideoSource中獲取視訊幀資料。此外VideoSource還依賴ChannelManager物件,使用它所包含的CaptureManager來負責視訊的採集任務。VideoSource在建立的時候就會呼叫 Initialize方法中呼叫ChannelManager的StartVideoCapture方法開始採集視訊資料。CaptureManager內部為每個VideoCapturer物件維護了一個CaptureRenderAdapter,CaptureRenderAdapter在建立的時候將OnVideoFrame成員方法掛接上VideoCapturer的SignalVideoFrame訊號來實時接收採集源傳送過來的視訊幀資料,OnVideoFrame內部將接收到的視訊幀資料分發給向其註冊的VideoRenderer物件(VideoRenderer物件的註冊的流程是VideoSource到ChannelManager,再到CaptureManager,最後註冊到CaptureRenderAdapter與特定的VideoCapturer關聯)。
至此,VideoSourceInterface在WebRTC中的實現已經很清晰了,視訊採集的流程和時機也很明瞭,接下來順便稍等地簡單分析一下WebRTC中VideoTrackInterface介面的實現:
WebRTC建立了一個VideoTrack實現VideoTrackInterface介面,在此之前我一直有個疑問,VideoTrackInterface對外暴露的視訊輸出介面是VideoRendererInterface,而視訊源介面VideoSourceInterface對外暴露的視訊輸出介面是VideoRenderer,兩套介面是如何適配的。看到這裡,我發現原來VideoTrack新建了一個VideoTrackRenderers物件來完成VideoRendererInterface介面到VideoRenderer介面的適配工作。VideoTrackRenderers一方面從VideoRenderer介面派生,這樣就可以將自己通過VideoSourceInterface的AddSink方法掛接進去來接收視訊幀資料,另一方面將接收到的視訊幀資料分發給外部掛接給VideoTrackInterface的VideoRendererInterface介面。
2. Chromium對WebRTC的視訊採集適配
Chromium建立WebRtcVideoCapturerAdapter類來實現VideoCapturer介面,相關結構如下:
Chromium自己也封裝了Track、Source概念,所以當初看這塊的時候腦袋不容易轉彎費了不少心思。WebRtcVideoCapturerAdapter需要接收Chromium的視訊採集模組傳輸過來的幀資料,通過一層層的掛接,最終掛接到MediaStreamVideoSource類中。MediaStreamVideoSource接收到視訊幀資料時,再一層層地通知回來,最終通知到WebRtcVideoCapturerAdapter的OnFrameCaptured方法,該方法內部觸發SignalFrameCaptured訊號。
MediaStreamVideoSource封裝了Chromium視訊採集的入口,這塊結構就複雜了,牽涉到跨程式的架構,如下:
這部分不打算細說,如果細說就很可能混淆到目前為止建立的僅有的一點點概念了,本節主要是介紹的是Chromium對WebRTC視訊採集介面的定製。