前言
5G時代的到來 音視訊的崛起 多少又真正了解音視訊的開發呢?想學習轉行?卻還在為技術擔憂嗎?
音視訊學習大綱
小編分享一篇webrtc視訊解析
音視訊開發第十八講|CC++程式員進入網際網路公司的捷徑-WebRTC開發|流媒體|音視訊開發|
更多音視訊開發、c/c++ Linux伺服器高階知識、電子書籍、視訊等等可以點選連結加入群聊【linux背景服務架構交流】
WebRTC的音頻引擎作為兩大基礎多媒體引擎之一,實作了音頻資料的采集、前處理、編碼、發送、接收、解碼、混音、後處理、播放等一系列處理流程。本文在深入分析WebRTC源代碼的基礎上,學習并總結其音頻引擎的實作架構和細節。
1. WebRTC音頻引擎整體架構
WebRTC音頻引擎的實作代碼主要分布在如下幾個源碼目錄中:
webrtc/audio
webrtc/common_audio
webrtc/media/engine
webrtc/voice_engine
webrtc/module/audio_coding
webrtc/module/audio_conference_mixer
webrtc/module/audio_device
webrtc/module/audio_processing
WebRTC音頻引擎的整體架構如圖1所示。
圖1 WebRTC音頻引擎的整體架構.png
從整個WebRTC架構結構來看,音頻引擎和和視訊引擎都位于比較底層的位置,負責音視訊資料的采集、編解碼、渲染播放等工作。音視訊引擎的上一層是多媒體引擎WebRtcMediaEngine2,是對底層音視訊引擎VideoEngine的進一步高層抽象,由WebRtcVoiceEngine對VoiceEngine進行封裝,WebRtcVideoEngine2對VideoEngine進行封裝。
在内部實作上,音頻引擎VoiceEngineImpl通過一系列對象來實作音頻處理,包括VoEAudioProcessingImpl、VoECodecImpl、VoENetworkImpl等等,每個對象負責具體某方面功能,例如VoEAudioProcessingImpl負責調用底層AudioProcessing子產品對音頻資料進行預處理。在這些功能對象中,比較重要的有VoEBaseImpl、SharedData和Channel。其中VoEBaseImpl是連接配接音頻裝置AudioDevice和音頻引擎VoiceEngineImpl的紐帶,是音頻資料流水線上的重要一站;SharedData是一個聚合類,持有一系列重要對象;Channel則代表一路音頻資料,負責大部分對該路資料的重要操作,包括音頻資料的前處理、編解碼、發送和接收、後處理、混音等等。
從功能依賴上講,VoiceEngineImpl依賴五個重要的底層功能子產品:音頻資料采集和播放AudioDeviceModule 、音頻資料預處理AudioProcessing、音頻資料編解碼AudioCodingModule、接收端音頻資料緩沖區NetEq、接收端混音AudioConferenceMixer。此外音頻資料編解碼還依賴一系列音頻編解碼器如G711、G722、Opus等等。在發送端,音頻資料由AudioDevice采集得到,經過AudioProcessing預處理後,到達AudioCodingModule進行編碼,然後由RTPRTCP子產品發送到網絡。在接收端,音頻資料經過RTPRTCP子產品接收後到達AudioCodingModule,存儲在NetEq中進行抖動控制和錯誤消除,然後解碼。解碼後的資料經過AudioConferenceMixer進行混音,最終發送到AudioDeviceModule進行播放。
2. WebRTC音頻引擎重要資料結構
本節在第一節的基礎上,靜态分析WebRTC音頻引擎實作上的一些重要資料結構。為了便于了解,采用從高層到底層的順序進行分析。
WebRtcMediaEngine2在MediaEngine層對底層的音視訊引擎進行封裝,分别是WebRtcVoiceEngine和WebRtcVideoEngine2。而WebRtcVoiceEngine則封裝了音頻引擎層的VoiceEngineImpl對象。VoiceEngineImpl以多繼承方式聚集一系列接口,包括SharedData、VoEAudioProcessingImpl、VoECodecImpl、VoENetworkImpl、VoEBaseImpl等等。
SharedData是一個聚合類,内部包括ChannelManager、AudioDeviceModule、OutputMixer、TransmitMixer、AudioProcess等對象,大部分關于VoiceEngineImpl的操作最終都會經過SharedData委托給内部對象。在建立SharedData對象時,其構造函數會建立一個名為“VoiceProcessThread”的線程,該線程用以處理音頻引擎的周期性事務。
VoEBaseImpl是連接配接底層音頻采集播放子產品AudioDeviceModule和音頻引擎内部音頻通道Channel的重要紐帶。它實作三個接口:VoEBase負責建立Channel、啟動/停止音頻資料的發送/接收;AudioTransport負責AudioDeviceModule子產品和Channel之間資料傳送,包括采集後的音頻資料發送到Channel進行編碼、從Channel拉取解碼後的音頻資料進行播放;AudioDeviceObserver負責把AudioDeviceModule工作過程中出現的錯誤和警告向上層報告。
Channel是對一路音頻資料及其處理過程的抽象,是VoiceEngineImpl中最重要的底層實作類,其繼承并實作RtpData、RtpFeedback、FileCallback、Transport、PacketizationCallback、ACMVADCallback、MixerParticipant等多個接口,分别負責音頻資料編碼後回掉、發送到網絡、接收後存儲到NetEq緩沖區、播放前混音等一些列重要操作。在類内部, Channel包含的重要成員對象包括RtpReceiver、RtpRtcpModule、AudioCodingModule、CodecManager、OutputMixer、TransmitMixer、ProcessThread、AudioDeviceModule、VoiceEngineObserver、Transport、AudioProcessing、PacketRouter等等。
AudioDeviceModule子產品負責音頻資料的采集和播放,是音頻資料的發源地和目的地。其内部主要包含三個對象:AudioDeviceModule、AudioDeviceGeneric和AudioDeviceBuffer。AudioDeviceModule是對外接口類,負責對AudioDevice和AudioDeviceBuffer進行管理、設定和對音頻資料進行傳遞。AudioDevice是平台相關的音頻裝置,它管理音頻采集裝置和播放裝置,包括初始化、設定音頻采集裝置和播放裝置、開始/停止裝置、控制裝置音量、設定裝置的音頻資料緩沖區,等等。在初始化階段,AudioDevice建立采集線程和播放線程,用來執行采集任務和播放任務。AudioDeviceBuffer是音頻資料緩沖區,負責臨時存儲和傳遞音頻資料。
AudioCodingModule子產品負責音頻資料的編解碼,它由音頻引擎層的Channel持有并調用。在内部,AudioCodingModul包含如下重要對象:AcmReceiver、AudioEncoder、AudioDecoder和NetEq,其中AcmReceiver負責接收音頻資料并存儲到NetEq中,NetEq負責音頻資料的抖動消除和錯誤隐藏,AudioEncoder負責音頻資料編碼,AudioDecoder負責音頻資料解碼。WebRTC支援一系列音頻編解碼器,包括CNG、G711、G722、ilbc、isac、opus等等。資料編碼完成後通過AudioPacketizationCallback接口回調到Channel進行下一步發送工作,資料解碼完成後由Channel拉取進行下一步播放工作。
Audio Processing子產品實作音頻資料的預處理操作,包括聲學回聲消除AEC、自動增益控制AGC、噪聲抑制NS、語音活動檢測VAD,等等。AudioProcessing聚合一系列子子產品實作各種音頻處理算法,其重要的對外接口由兩個:ProcessStream()和ProcessReverseStream(),前者負責采集後編碼前的音頻資料的前處理,後者播放前解碼後的音頻資料的後處理。
TransmitMixer用于發送端混音。OutputMixer用于接收端混音。OutputMixer在内部使用AudioConferenceMixer負責解碼後音頻資料的混音操作。
3. WebRTC音頻引擎資料流分析
本節在前兩節分析的基礎上,動态分析WebRTC音頻引擎的資料流,包括音頻資料的采集、前處理、編碼、發送、接收、緩存、解碼、混音、後處理、播放。如圖2所示。
圖2 WebRTC音頻引擎資料流.png
3.1 音頻引擎建立及初始化
音頻引擎的建立及初始化流程如圖3所示:
圖3 WebRTC音頻引擎建立及初始化.png
WebRTC音頻引擎的建立從PeerConnectionFactory對象的建立及初始化開始,這個過程由WebRTC的應用程式發起,并在signal線程在進行,最終調用CreateMediaEngine_w()轉到worker線程。在worker線程中,先建立WebRtcMediaEngine2,進而WebRtcVoiceEngine,最終建立VoiceEngineImpl。而最重要的初始化操作則VoEBaseImpl的Init()函數中完成。
3.2 音頻資料的采集和編碼
音頻資料的采集是平台相關的,在此以Windows平台為例,整個采集和編碼過程如圖4所示:
圖4 音頻資料的采集和編碼.png
在Windows 7平台上,WebRTC預設使用Windows Core接口采集和播放音頻資料。采集線程叫做webrtc_core_audio_capture_thread,線程入口是AudioDeviceWindowCore的CaptureAudio函數。該函數從麥克風中采集到音頻資料後,存儲到AudioDeviceBuffer中,并調用DeliverRecordedData()把音頻資料向上推送到VoEBaseImpl對象中。VoEBaseImpl對象調用ProcessRecordedDataWithAPM()函數進行處理,首先建立AudioFrame對象并進行前處理,然後進行解複合和混音,最後資料到達Channel進行編碼和發送。
在Channel對象中,編碼任務委托給AudioCodingModule對象,首先從AudioFrame中擷取10ms的音頻資料,然後調用具體的編碼器如Opus進行編碼。編碼後的資料通過AudioPacketizationCallback接口的SendData()回到Channel對象進行下一步的RTP打包和發送過程。
3.3 音頻資料的發送
音頻資料在AudioCodingModule編碼完成後,通過回調接口回到Channel對象進行下一步的RTP打包和發送過程,如圖5所示。
圖5 音頻資料的發送.png
Channel調用把資料發送給RtpRtcp子產品,後者經過一系列的調用進行RTP打包後到達RtpSender對象。如果沒有配置平滑發送線程PacedSender,則RtpSender直接調用SendPacketToNetwork()把資料發送到network線程。否則資料會先存儲到PacedSender線程中,再由後者進行平滑發送,最終資料發送到network線程。
3.4 音頻資料的接收
network線程從網絡接收到音頻資料後,交給worker線程進行下一步接收。Worker線程的工作流程如圖6所示。
圖6 音頻資料的接收.png
worker線程在收到網絡資料後,通過BaseChannel的OnPacketReceived()接口向下傳遞,到達MediaEngine層的WebRtcVoiceMediaChannel,然後繼續向下經過Call和AudioReceiveStream到達Channel的ReceivedRTPPacket()接口。Channel把資料推送到RtpRtcp子產品進行RTP解包操作,得到純音頻資料,然後再經過Channel的OnReceivedPaylaodData()接口把資料推送到AudioCodingModule子產品,最終經過AcmReceiver把資料存儲在NetEq中,進行抖動消除和錯誤隐藏等操作。
3.5 音頻資料的解碼和播放
worker線程把接收到的音頻資料存儲到NetEq後,為播放線程提供資料源。播放線程具體負責音頻資料解碼和播放操作。Windows Core接口的播放線程名稱為webrtc_core_audio_render_thread,其工作流程如圖7所示。
圖7 音頻資料的解碼和播放.png
AudioDeviceWindowsCore裝置向AudioDeviceBuffer請求音頻資料,後者進一步向VoeBaseImpl請求資料,接下來主要操作都在GetPlayoutData()中進行:1)在AudioConferenceMixer中對所有活動Channel中的音頻資料進行混音,每個Channel都作為混音的參與者。這包括擷取解碼後的音頻資料(從AudioCodingModule子產品中解碼音頻資料并傳回)、對音頻資料進行混音、得到最終音頻資料并傳回給OutputMixer。2)OutputMixer對混音後的音頻資料執行AudioProcessing後處理操作。3)對後處理操作後的音頻資料進行再混合和再采樣。最終OutputMixer拿到最終的音頻資料,交給VoEBaseImpl,并進一步向下交給AudioDeviceBuffer。AudioDeviceBuffer則把資料交給AudioDeviceWindowsCore進行播放操作。
至此,我們完整分析了音頻資料從采集到播放的全部過程。
4. 總結
本文在深入分析WebRTC關于音頻引擎實作代碼的基礎上,首先給出了WebRTC音頻引擎的整體架構,然後靜态分析了其實作上的若幹重要對象,最後完整分析了音頻資料從采集到播放的完整流動過程。通過本文,對WebRTC有了更深入的認識和體會,為未來進一步學習打下堅實基礎。