WebRTC音頻引擎實(shí)現(xiàn)分析

WebRTC的音頻引擎作為兩大基礎(chǔ)多媒體引擎之一,實(shí)現(xiàn)了音頻數(shù)據(jù)的采集、前處理、編碼、發(fā)送、接收、解碼、混音、后處理、播放等一系列處理流程。本文在深入分析WebRTC源代碼的基礎(chǔ)上,學(xué)習(xí)并總結(jié)其音頻引擎的實(shí)現(xiàn)框架和細(xì)節(jié)。

1. WebRTC音頻引擎整體架構(gòu)

WebRTC音頻引擎的實(shí)現(xiàn)代碼主要分布在如下幾個(gè)源碼目錄中:

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音頻引擎的整體架構(gòu)如圖1所示。

圖1 WebRTC音頻引擎的整體架構(gòu).png

從整個(gè)WebRTC框架結(jié)構(gòu)來看,音頻引擎和和視頻引擎都位于比較底層的位置,負(fù)責(zé)音視頻數(shù)據(jù)的采集、編解碼、渲染播放等工作。音視頻引擎的上一層是多媒體引擎WebRtcMediaEngine2,是對底層音視頻引擎VideoEngine的進(jìn)一步高層抽象,由WebRtcVoiceEngine對VoiceEngine進(jìn)行封裝,WebRtcVideoEngine2對VideoEngine進(jìn)行封裝。

在內(nèi)部實(shí)現(xiàn)上,音頻引擎VoiceEngineImpl通過一系列對象來實(shí)現(xiàn)音頻處理,包括VoEAudioProcessingImpl、VoECodecImpl、VoENetworkImpl等等,每個(gè)對象負(fù)責(zé)具體某方面功能,例如VoEAudioProcessingImpl負(fù)責(zé)調(diào)用底層AudioProcessing模塊對音頻數(shù)據(jù)進(jìn)行預(yù)處理。在這些功能對象中,比較重要的有VoEBaseImpl、SharedData和Channel。其中VoEBaseImpl是連接音頻設(shè)備AudioDevice和音頻引擎VoiceEngineImpl的紐帶,是音頻數(shù)據(jù)流水線上的重要一站;SharedData是一個(gè)聚合類,持有一系列重要對象;Channel則代表一路音頻數(shù)據(jù),負(fù)責(zé)大部分對該路數(shù)據(jù)的重要操作,包括音頻數(shù)據(jù)的前處理、編解碼、發(fā)送和接收、后處理、混音等等。

從功能依賴上講,VoiceEngineImpl依賴五個(gè)重要的底層功能模塊:音頻數(shù)據(jù)采集和播放AudioDeviceModule 、音頻數(shù)據(jù)預(yù)處理AudioProcessing、音頻數(shù)據(jù)編解碼AudioCodingModule、接收端音頻數(shù)據(jù)緩沖區(qū)NetEq、接收端混音AudioConferenceMixer。此外音頻數(shù)據(jù)編解碼還依賴一系列音頻編解碼器如G711、G722、Opus等等。在發(fā)送端,音頻數(shù)據(jù)由AudioDevice采集得到,經(jīng)過AudioProcessing預(yù)處理后,到達(dá)AudioCodingModule進(jìn)行編碼,然后由RTPRTCP模塊發(fā)送到網(wǎng)絡(luò)。在接收端,音頻數(shù)據(jù)經(jīng)過RTPRTCP模塊接收后到達(dá)AudioCodingModule,存儲(chǔ)在NetEq中進(jìn)行抖動(dòng)控制和錯(cuò)誤消除,然后解碼。解碼后的數(shù)據(jù)經(jīng)過AudioConferenceMixer進(jìn)行混音,最終發(fā)送到AudioDeviceModule進(jìn)行播放。

2. WebRTC音頻引擎重要數(shù)據(jù)結(jié)構(gòu)

本節(jié)在第一節(jié)的基礎(chǔ)上,靜態(tài)分析WebRTC音頻引擎實(shí)現(xiàn)上的一些重要數(shù)據(jù)結(jié)構(gòu)。為了便于理解,采用從高層到底層的順序進(jìn)行分析。

WebRtcMediaEngine2在MediaEngine層對底層的音視頻引擎進(jìn)行封裝,分別是WebRtcVoiceEngine和WebRtcVideoEngine2。而WebRtcVoiceEngine則封裝了音頻引擎層的VoiceEngineImpl對象。VoiceEngineImpl以多繼承方式聚集一系列接口,包括SharedData、VoEAudioProcessingImpl、VoECodecImpl、VoENetworkImpl、VoEBaseImpl等等。

SharedData是一個(gè)聚合類,內(nèi)部包括ChannelManager、AudioDeviceModule、OutputMixer、TransmitMixer、AudioProcess等對象,大部分關(guān)于VoiceEngineImpl的操作最終都會(huì)經(jīng)過SharedData委托給內(nèi)部對象。在創(chuàng)建SharedData對象時(shí),其構(gòu)造函數(shù)會(huì)創(chuàng)建一個(gè)名為“VoiceProcessThread”的線程,該線程用以處理音頻引擎的周期性事務(wù)。

VoEBaseImpl是連接底層音頻采集播放模塊AudioDeviceModule和音頻引擎內(nèi)部音頻通道Channel的重要紐帶。它實(shí)現(xiàn)三個(gè)接口:VoEBase負(fù)責(zé)創(chuàng)建Channel、啟動(dòng)/停止音頻數(shù)據(jù)的發(fā)送/接收;AudioTransport負(fù)責(zé)AudioDeviceModule模塊和Channel之間數(shù)據(jù)傳送,包括采集后的音頻數(shù)據(jù)發(fā)送到Channel進(jìn)行編碼、從Channel拉取解碼后的音頻數(shù)據(jù)進(jìn)行播放;AudioDeviceObserver負(fù)責(zé)把AudioDeviceModule工作過程中出現(xiàn)的錯(cuò)誤和警告向上層報(bào)告。

Channel是對一路音頻數(shù)據(jù)及其處理過程的抽象,是VoiceEngineImpl中最重要的底層實(shí)現(xiàn)類,其繼承并實(shí)現(xiàn)RtpData、RtpFeedback、FileCallback、Transport、PacketizationCallback、ACMVADCallback、MixerParticipant等多個(gè)接口,分別負(fù)責(zé)音頻數(shù)據(jù)編碼后回掉、發(fā)送到網(wǎng)絡(luò)、接收后存儲(chǔ)到NetEq緩沖區(qū)、播放前混音等一些列重要操作。在類內(nèi)部, Channel包含的重要成員對象包括RtpReceiver、RtpRtcpModule、AudioCodingModule、CodecManager、OutputMixer、TransmitMixer、ProcessThread、AudioDeviceModule、VoiceEngineObserver、Transport、AudioProcessing、PacketRouter等等。

AudioDeviceModule模塊負(fù)責(zé)音頻數(shù)據(jù)的采集和播放,是音頻數(shù)據(jù)的發(fā)源地和目的地。其內(nèi)部主要包含三個(gè)對象:AudioDeviceModule、AudioDeviceGeneric和AudioDeviceBuffer。AudioDeviceModule是對外接口類,負(fù)責(zé)對AudioDevice和AudioDeviceBuffer進(jìn)行管理、設(shè)置和對音頻數(shù)據(jù)進(jìn)行傳遞。AudioDevice是平臺(tái)相關(guān)的音頻設(shè)備,它管理音頻采集設(shè)備和播放設(shè)備,包括初始化、設(shè)置音頻采集設(shè)備和播放設(shè)備、開始/停止設(shè)備、控制設(shè)備音量、設(shè)置設(shè)備的音頻數(shù)據(jù)緩沖區(qū),等等。在初始化階段,AudioDevice創(chuàng)建采集線程和播放線程,用來執(zhí)行采集任務(wù)和播放任務(wù)。AudioDeviceBuffer是音頻數(shù)據(jù)緩沖區(qū),負(fù)責(zé)臨時(shí)存儲(chǔ)和傳遞音頻數(shù)據(jù)。

AudioCodingModule模塊負(fù)責(zé)音頻數(shù)據(jù)的編解碼,它由音頻引擎層的Channel持有并調(diào)用。在內(nèi)部,AudioCodingModul包含如下重要對象:AcmReceiver、AudioEncoder、AudioDecoder和NetEq,其中AcmReceiver負(fù)責(zé)接收音頻數(shù)據(jù)并存儲(chǔ)到NetEq中,NetEq負(fù)責(zé)音頻數(shù)據(jù)的抖動(dòng)消除和錯(cuò)誤隱藏,AudioEncoder負(fù)責(zé)音頻數(shù)據(jù)編碼,AudioDecoder負(fù)責(zé)音頻數(shù)據(jù)解碼。WebRTC支持一系列音頻編解碼器,包括CNG、G711、G722、ilbc、isac、opus等等。數(shù)據(jù)編碼完成后通過AudioPacketizationCallback接口回調(diào)到Channel進(jìn)行下一步發(fā)送工作,數(shù)據(jù)解碼完成后由Channel拉取進(jìn)行下一步播放工作。

Audio Processing模塊實(shí)現(xiàn)音頻數(shù)據(jù)的預(yù)處理操作,包括聲學(xué)回聲消除AEC、自動(dòng)增益控制AGC、噪聲抑制NS、語音活動(dòng)檢測VAD,等等。AudioProcessing聚合一系列子模塊實(shí)現(xiàn)各種音頻處理算法,其重要的對外接口由兩個(gè):ProcessStream()和ProcessReverseStream(),前者負(fù)責(zé)采集后編碼前的音頻數(shù)據(jù)的前處理,后者播放前解碼后的音頻數(shù)據(jù)的后處理。

TransmitMixer用于發(fā)送端混音。OutputMixer用于接收端混音。OutputMixer在內(nèi)部使用AudioConferenceMixer負(fù)責(zé)解碼后音頻數(shù)據(jù)的混音操作。

3. WebRTC音頻引擎數(shù)據(jù)流分析

本節(jié)在前兩節(jié)分析的基礎(chǔ)上,動(dòng)態(tài)分析WebRTC音頻引擎的數(shù)據(jù)流,包括音頻數(shù)據(jù)的采集、前處理、編碼、發(fā)送、接收、緩存、解碼、混音、后處理、播放。如圖2所示。

圖2 WebRTC音頻引擎數(shù)據(jù)流.png
3.1 音頻引擎創(chuàng)建及初始化

音頻引擎的創(chuàng)建及初始化流程如圖3所示:

圖3 WebRTC音頻引擎創(chuàng)建及初始化.png

WebRTC音頻引擎的創(chuàng)建從PeerConnectionFactory對象的創(chuàng)建及初始化開始,這個(gè)過程由WebRTC的應(yīng)用程序發(fā)起,并在signal線程在進(jìn)行,最終調(diào)用CreateMediaEngine_w()轉(zhuǎn)到worker線程。在worker線程中,先創(chuàng)建WebRtcMediaEngine2,進(jìn)而WebRtcVoiceEngine,最終創(chuàng)建VoiceEngineImpl。而最重要的初始化操作則VoEBaseImpl的Init()函數(shù)中完成。

3.2 音頻數(shù)據(jù)的采集和編碼

音頻數(shù)據(jù)的采集是平臺(tái)相關(guān)的,在此以Windows平臺(tái)為例,整個(gè)采集和編碼過程如圖4所示:

圖4 音頻數(shù)據(jù)的采集和編碼.png

在Windows 7平臺(tái)上,WebRTC默認(rèn)使用Windows Core接口采集和播放音頻數(shù)據(jù)。采集線程叫做webrtc_core_audio_capture_thread,線程入口是AudioDeviceWindowCore的CaptureAudio函數(shù)。該函數(shù)從麥克風(fēng)中采集到音頻數(shù)據(jù)后,存儲(chǔ)到AudioDeviceBuffer中,并調(diào)用DeliverRecordedData()把音頻數(shù)據(jù)向上推送到VoEBaseImpl對象中。VoEBaseImpl對象調(diào)用ProcessRecordedDataWithAPM()函數(shù)進(jìn)行處理,首先創(chuàng)建AudioFrame對象并進(jìn)行前處理,然后進(jìn)行解復(fù)合和混音,最后數(shù)據(jù)到達(dá)Channel進(jìn)行編碼和發(fā)送。

在Channel對象中,編碼任務(wù)委托給AudioCodingModule對象,首先從AudioFrame中獲取10ms的音頻數(shù)據(jù),然后調(diào)用具體的編碼器如Opus進(jìn)行編碼。編碼后的數(shù)據(jù)通過AudioPacketizationCallback接口的SendData()回到Channel對象進(jìn)行下一步的RTP打包和發(fā)送過程。

3.3 音頻數(shù)據(jù)的發(fā)送

音頻數(shù)據(jù)在AudioCodingModule編碼完成后,通過回調(diào)接口回到Channel對象進(jìn)行下一步的RTP打包和發(fā)送過程,如圖5所示。

圖5 音頻數(shù)據(jù)的發(fā)送.png

Channel調(diào)用把數(shù)據(jù)發(fā)送給RtpRtcp模塊,后者經(jīng)過一系列的調(diào)用進(jìn)行RTP打包后到達(dá)RtpSender對象。如果沒有配置平滑發(fā)送線程PacedSender,則RtpSender直接調(diào)用SendPacketToNetwork()把數(shù)據(jù)發(fā)送到network線程。否則數(shù)據(jù)會(huì)先存儲(chǔ)到PacedSender線程中,再由后者進(jìn)行平滑發(fā)送,最終數(shù)據(jù)發(fā)送到network線程。

3.4 音頻數(shù)據(jù)的接收

network線程從網(wǎng)絡(luò)接收到音頻數(shù)據(jù)后,交給worker線程進(jìn)行下一步接收。Worker線程的工作流程如圖6所示。

圖6 音頻數(shù)據(jù)的接收.png

worker線程在收到網(wǎng)絡(luò)數(shù)據(jù)后,通過BaseChannel的OnPacketReceived()接口向下傳遞,到達(dá)MediaEngine層的WebRtcVoiceMediaChannel,然后繼續(xù)向下經(jīng)過Call和AudioReceiveStream到達(dá)Channel的ReceivedRTPPacket()接口。Channel把數(shù)據(jù)推送到RtpRtcp模塊進(jìn)行RTP解包操作,得到純音頻數(shù)據(jù),然后再經(jīng)過Channel的OnReceivedPaylaodData()接口把數(shù)據(jù)推送到AudioCodingModule模塊,最終經(jīng)過AcmReceiver把數(shù)據(jù)存儲(chǔ)在NetEq中,進(jìn)行抖動(dòng)消除和錯(cuò)誤隱藏等操作。

3.5 音頻數(shù)據(jù)的解碼和播放

worker線程把接收到的音頻數(shù)據(jù)存儲(chǔ)到NetEq后,為播放線程提供數(shù)據(jù)源。播放線程具體負(fù)責(zé)音頻數(shù)據(jù)解碼和播放操作。Windows Core接口的播放線程名稱為webrtc_core_audio_render_thread,其工作流程如圖7所示。

圖7 音頻數(shù)據(jù)的解碼和播放.png

AudioDeviceWindowsCore設(shè)備向AudioDeviceBuffer請求音頻數(shù)據(jù),后者進(jìn)一步向VoeBaseImpl請求數(shù)據(jù),接下來主要操作都在GetPlayoutData()中進(jìn)行:1)在AudioConferenceMixer中對所有活動(dòng)Channel中的音頻數(shù)據(jù)進(jìn)行混音,每個(gè)Channel都作為混音的參與者。這包括獲取解碼后的音頻數(shù)據(jù)(從AudioCodingModule模塊中解碼音頻數(shù)據(jù)并返回)、對音頻數(shù)據(jù)進(jìn)行混音、得到最終音頻數(shù)據(jù)并返回給OutputMixer。2)OutputMixer對混音后的音頻數(shù)據(jù)執(zhí)行AudioProcessing后處理操作。3)對后處理操作后的音頻數(shù)據(jù)進(jìn)行再混合和再采樣。最終OutputMixer拿到最終的音頻數(shù)據(jù),交給VoEBaseImpl,并進(jìn)一步向下交給AudioDeviceBuffer。AudioDeviceBuffer則把數(shù)據(jù)交給AudioDeviceWindowsCore進(jìn)行播放操作。

至此,我們完整分析了音頻數(shù)據(jù)從采集到播放的全部過程。

4. 總結(jié)

本文在深入分析WebRTC關(guān)于音頻引擎實(shí)現(xiàn)代碼的基礎(chǔ)上,首先給出了WebRTC音頻引擎的整體框架,然后靜態(tài)分析了其實(shí)現(xiàn)上的若干重要對象,最后完整分析了音頻數(shù)據(jù)從采集到播放的完整流動(dòng)過程。通過本文,對WebRTC有了更深入的認(rèn)識(shí)和體會(huì),為未來進(jìn)一步學(xué)習(xí)打下堅(jiān)實(shí)基礎(chǔ)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者。

友情鏈接更多精彩內(nèi)容