WebRTC源碼分析:音頻模塊結構分析

 

一、概要介紹WebRTC的音頻處理流程,見下圖:

webRTC將音頻會話抽象爲一個通道Channel,譬如A與B進行音頻通話,則A需要建立一個Channel與B進行音頻數據傳輸。上圖中有三個Channel,每個Channel包含編解碼和RTP/RTCP發送功能。

以一個Channel而言,應用程序中將包含三個活動線程,錄音線程,音頻接收線程和播放線程。

1)錄音線程:負責麥克風音頻的採集,見圖中紅色路徑,採集到音頻後,緩存到一定長度,進行音頻處理,主要包括EC,AGC和NS等。然後送到Channel,經過音頻

Codec模塊編碼,封裝成RTP包,通過Socket發送出去;

2)接收線程:見藍色路徑,負責接收遠端發送過來的音頻包,解封RTP包,解碼音頻數據,送入NetEQ模塊緩存。

3)播放線程:負責耳機聲音播放,見綠色路徑。播放線程去OutMixer中獲取要播放的音頻數據,首先依次獲取參與會話的Channel中NetEQ存儲的音頻幀,可以對其做AGC和NS處理;然後混合多個Channel的音頻信號,得到混合音頻,傳遞給AudioProcessing模塊進行遠端分析。最後播放出來。

如下爲本地迴環錄音和播放代碼:

VoiceEngine* ve = VoiceEngine::Create();
VoEBase* base = VoEBase::GetInterface(ve);
base->Init();
int chId = base->CreateChannel();
base->SetSendDestination(chId,3000,"127.0.0.1",4000);
base->SetLocalReceiver(chId,3000,3001,"127.0.0.1");
base->StartPlayout(chId);
base->StartReceive(chId);
base->StartSend(chId);

        //....sleep...wait.....

base->StopSend(chId);

base->StopReveive(chId);

base->StopPlayout(chId);

base->Terminate();

 

本文介紹WebRTC音頻模塊組成和結構,詳細介紹音頻引擎的配置和啓動,相信看完本文後,很多人可以利用WebRTC完成一個音頻通話程序開發。

一、對外接口

      音頻部分的對外主要接口如下,各個接口之間的關係如圖1所示。

1)VoiceEngine:負責引擎的所有接口查詢,存儲共享數據信息ShareData。

2)VoEBase:負責音頻處理的基本操作。

3)VoEAudioProcessing:音頻信號處理接口,設置各個音頻處理項的參數。

4)VoECodec:音頻編解碼接口,提供支持的編解碼器查詢,音頻編解碼設置。

5)VoEHardware:音頻硬件設備接口,負責音頻硬件設備的設置。

         其它的接口還有VoENetEqStats,VoENetwork,VoERTP_RTCP,VoEVideoSync,VoEVolumeControl,VoEFile,VoECallReport,VoEDtmf,VoEMeidaProcess和VoEEncryption。

         WebRTC使用繼承實現接口轉換和查詢,接口之間的數據共享是通過ShareData完成,首先VoiceEngineImpl繼承各個對外接口的實現,所以可以從VoiceEngineImpl很容易獲取其他對外接口。而VoiceEngineImpl本身也繼承ShareData,當從VoiceEngineImpl獲取其他對外接口的同時,隱式的傳遞了ShareData指針,因此各個接口可以很方便的獲取到ShareData的數據信息。因此雖然類與類之間的關係看起來比較混亂,但是使用上比較方便。

         利用VoiceEngine獲取對外接口:VoEInterfaceXX* pInterf = VoEInterfaceXX:GetInterface(pVoiceEngine);

二、模塊組成

主要由五大模塊組成:AudioDeviceModule音頻設備模塊,AudioProcess音頻處理模塊,AudioCodingModule音頻編碼模塊,AudioConferenceMixer混音模塊和RtpRtcp傳輸模塊。

         ShareData用於粘合各個模塊之間的關係,負責管理全局的對象,包括AudioDeviceModule,TransmitMixer,OutputMixer,ChannelManager和AudioProcess。

         錄音流程:AudioDeviceWinCore負責採集音頻數據,傳遞到AudioDeviceBuffer中緩存,AudioDeviceBuffer則將數據送入TransmixMixer,首先交給AudioProcess進行近端音頻處理,完成後分發到各個Channel中,Channel則通過AudioCodingModule進行編碼,編碼後再交付到RtpRtcp中經由RTPSender發送出去。

         接收流程:RTPReceiver負責接收音頻RTP包,接收到RTP包後交給Channel,Channel轉交給AudioCodingModule中的ACMNetEQ模塊,進行解碼緩存。

         播放流程:Channel從ACMNetEQ模塊中取出緩存的解碼音頻數據,如果需要進行遠端數據處理的話,傳遞給AudioProcess處理。最後所有Channel都匯入到OutputMixer中進行混音,混音後再傳遞到AudioProcess進行遠端音頻分析。最後送入AudioDeviceModule中的AudioDevceWinCore播放。

三、配置

1、音頻引擎創建與刪除

         VoiceEngine*pVoeEngine = VoiceEngine::Create();

         VoiceEngine::Delete(pVoeEngine);

2、音頻收發

1)音頻通話鏈路創建

         WebRTC中的Channel,爲一路音頻。作爲網絡語音通信,至少要創建一路音頻Channel。

        Channel沒有提供對外接口,是有VoEBase來管理的,通過索引號來選定對應的Channel。

         VoEBase*base = VoEBase::GetInterface(pVoeEngine);

         int ch0 =base->CreateChannel();

2)網絡端口設置

         音頻通過RTP和RTCP發送出去,RTP和RTCP使用UDP實現,需要配置網絡端口和地址。

         //設置發送給.2機器的3000端口

         base->SetSendDestination(ch0,3000,”192.168.8.2”);

        //在本機的3000端口接收RTP包

        base->SetLocalReceiver(ch0,3000);

3)音頻編碼選擇

         VoECodec負責編解碼的配置。

         VoECodec*codec = VoEBase::GetInterface(pVoeEngine);

         設置Channel的編碼類型之前,要查詢支持的編碼列表。

         CodecInstinst;

         Intnum = codec->NumOfCodecs();

         for(int i=0; i<num; ++i)

        {

              Codec->GetCodec(I,inst);

             //打印編碼信息

        }

       //設置編碼0

       Codec->GetCodec(0,inst);

       Codec->SetSendCodec(ch0,inst);

       WebRTC自動識別編碼類型,因此解碼不需要設置。

4)啓動

         啓動播放:base->StartPlayout(ch0);該操作含義是將通話ch0進行混音輸出。

         啓動接收:base->StartReceive(ch0);開始接收後,每增加一路通話,引擎會將音頻進行混音再輸出。

         啓動發送:base->StartSend(ch0);啓動發送的時候,會檢查是否正在錄音,如果已經開啓錄音,則不再開啓;否則會執行音頻設備錄音操作。

3、音頻處理的配置

         VoEAudioProcessing負責音頻處理的配置。

         VoEAudioProcessing*pAudioProc = VoEAudioProcessing::GetInterface(pVoeEngine);

         //啓動AGC功能

         pAudioProc->SetAgcStatus(true);

4、音頻設備的配置

         VoEHardware接口可以查看錄音和播放設備,可以選擇指定的設備進行音頻通話。

         VoEHardware*pHardware=VoEAudioProcessing::GetInterface(pVoeEngine);

         Int numin =pHardware->GetNumOfRecordingDevices();

         For(int i=0;i<numin; ++i)

        {

             pHardware->GetRecordingDeviceNames(…)

             //打印錄音設備

        }

       //選擇設備0作爲錄音設備

       pHardware->SetRecordingDevice(0);

      播放設備配置類似。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章