1. 程式人生 > >WebRTC手記之本地音訊採集

WebRTC手記之本地音訊採集

上一篇博文介紹了本地視訊採集,這一篇就介紹下音訊採集流程,也是先介紹WebRTC原生的音訊採集,再介紹Chromium原始碼對它的定製。

1. WebRTC原生音訊採集

先介紹一下WebRTC中與音訊採集貌似相關的介面概念:

結構上看起來是不是和視訊Track的結構類似?不過前面提過,如果你以對稱的思維,在此結構中找出與視訊track相似的採集源和輸出源,那就肯定無功而返了,LocalAudioSource對AudioSourceInterface的實現就是一個空實現,沒有了音訊源,那音訊處理介面AudioProcessorInterface和輸出介面AudioRenderer都成了無米之炊了。這些介面先擺在這,可能類似於AudioCapturer的框架正在實現的途中,也可能這些介面有別的用處,比如遠端音訊流的抽象等,這裡就暫且擱置,先記下有這回事吧。這裡只談WebRTC本地音訊的採集處理。前面介紹音視訊介面的時候也提到的,本地音訊的採集由AudioDeviceModule介面統一封裝:

AudioDeviceModule是個大而全的介面,恨不得將所有音訊相關的介面都封裝在裡面(實際也差不多了),具體包括:列舉音訊採集裝置(Record)和播放裝置(Playout)、設定當前的採集裝置/播放裝置、開始/停止音訊的採集/播放、設定音訊增益控制開關(AGC)等。AudioTransport是個關鍵的對外介面,負責音訊資料的傳入(呼叫NeedMorePlayData方法,供Playout使用)和輸出(呼叫RecordedDataIsAvailable方法,資料由Record採集操作產生)。

AudioDeviceModuleImpl實現了AudioDeviceModule介面,建立的時候呼叫CreatePlatformSpecificObjects方法建立平臺相關的AudioDeviceGeneric介面實現。該介面抽象了音訊的採集和播放邏輯,在Windows平臺下有兩種實現方案:

  •   AudioDeviceWindowsWave實現的是傳統的Windows Wave APIs方案。
  •  AudioDeviceWindowsCore實現的是Vista之後才支援的Windows Core Audio APIs方案。

此外,AudioDeviceModuleImpl還維護了一個AudioDeviceBuffer物件來管理音訊資料的緩衝區,由它直接與對外介面AudioTransport互動。比如:

  •  當AudioDeviceWindowsWave或者AudioDeviceWindowsCore需要播放音訊資料的時候,會呼叫AudioDeviceBuffer的RequestPlayoutData方法請求播放資料,然後通過GetPlayoutData方法來獲取剛請求到的資料。AudioDeviceBuffer的RequestPlayoutData就是呼叫AudioTransport介面的NeedMorePlayData方法來請求待播放的音訊流資料。
  •  當AudioDeviceWindowsWave或者AudioDeviceWindowsCore採集到音訊資料後,會呼叫AudioDeviceBuffer的SetRecordedBuffer方法將採集到的音訊資料傳遞進去,然後呼叫DeliverRecordedData方法來派發出去,該派發方法就是通過呼叫AudioTransport介面的RecordedDataIsAvailable來實現。

總之,音訊採集模組處處都透露出大而全的結構設計。如果可以,真的應該細化一下概念設計,比如將音訊採集和音訊播放邏輯分離、音訊輸入和輸出的介面拆分等等,那樣才能談得上結構設計。

2. Chromium對WebRTC的音訊採集適配

根據WebRTC的本地音訊介面設計,Chromium提供了一個WebRtcAudioDeviceImpl類來實現AudioDeviceModule介面,該類物件由PeerConnectionDependencyFactory負責建立和維護,結構如下:

如圖所示,WebRtcAudioDeviceImpl摒棄了原生的AudioDeviceModuleImpl實現中大而全的設計,而是將音訊採集和音訊渲染邏輯分開,分別對應於WebRtcAudioCapturer和WebRtcAudioRenderer。WebRtcAudioRenderer通過WebRtcAudioRendererSource介面的RenderData方法向WebRtcAudioDeviceImpl請求音訊流資料來渲染,WebRtcAudioDeviceImpl將該請求轉發給前面提到的對外互動介面AudioTransport。WebRtcAudioCapturer封裝音訊採集邏輯,它將採集到的資料通過WebRtcLocalAudioTrack物件所持有的PeerConnectionAudioSink介面派發出去,WebRtcAudioDeviceImpl正是實現了該介面來接收音訊採集資料,然後也是通過AudioTransport介面往外傳遞。至於WebRtcAudioCapturer物件的持有者MediaStreamAudioSource和WebMediaStreamTrack,這裡暫時有個概念就行,它們是Chromium對HTML5媒體流的實現介面。接下來仔細分析一下WebRtcAudioCapturer和WebRtcAudioRenderer兩個關鍵類,毋庸置疑,它們都涉及到了特定平臺實現,而且在Chromium中還跨越了Render和Browser程序。和介紹Chromium視訊採集的模式一樣,由於不是本文重點,這裡只列出結構圖,不打算詳解,如果你有開發上的需要,可以照著該結構圖細看原始碼。

這是WebRtcAudioCapturer採集音訊資料的結構,牽涉到跨程序通訊,結構還是非常複雜的。WebRtcAudioRenderer的結構就不準備介紹了,因為Chromium的這塊設計非常具備對稱性,基本上圖中類命名中的Input改成Output就差不多是WebRtcAudioRenderer的架構了。