织梦CMS - 轻松建站从此开始!

罗索实验室

当前位置: 主页 > 流媒体开发 > 流媒体开发 >

WebRtc VoiceEngine代码解析

落鹤生 发布于 2013-09-01 14:35 点击:次 
WebRtc中VoiceEngine可以完成大部分的VOIP相关人物,包括采集、自动增益、噪声消除、回声抑制、编解码、RTP传输。下边我们通过代码来解析Voe中处理流程
TAG:

WebRtc中VoiceEngine可以完成大部分的VOIP相关人物,包括采集、自动增益、噪声消除、回声抑制、编解码、RTP传输。下边我们通过代码来解析Voe中处理流程;

创建VoiceEngine和VoEBase


[cpp]

  1. VoiceEngine* _vePtr = VoiceEngine::Create(); //创建VoiceEngine   
  2. VoEBase* _veBasePtr = VoEBase::GetInterface(_vePtr);
  3. //创建VoeBase  所有Voe相关操作通过这个共有类   
  4. _veBasePtr->Init();//创建整个Voe处理线程  
  5.  
  6. VoiceEngine* _vePtr = VoiceEngine::Create();//创建VoiceEngine 
  7. //创建VoeBase  所有Voe相关操作通过这个共有类 
  8. VoEBase* _veBasePtr = VoEBase::GetInterface(_vePtr);
  9. _veBasePtr->Init();//创建整个Voe处理线程 

重点就在_veBasePtr->Init()  它会创建voe线程,线程负责采集、数字信号处理、编码、rtp传输。

[cpp]

  1. int VoEBaseImpl::Init(AudioDeviceModule* external_adm,  
  2.                       AudioProcessing* audioproc)  
  3. {  
  4.     _shared->process_thread();   //创建voe线程   
  5.     _shared->process_thread()->Start();  
  6.     _shared->audio_device()->Init();
  7. }
  8.  
  9. int VoEBaseImpl::Init(AudioDeviceModule* external_adm,
  10.                       AudioProcessing* audioproc)
  11. {
  12.     _shared->process_thread();   //创建voe线程
  13.     _shared->process_thread()->Start();
  14.     _shared->audio_device()->Init();
  15. }

audio_device()->Init()重载了int32_t AudioDeviceWindowsWave::Init()(windowns平台),别的平台是别的函数,基本差不多,在这个Init中,创建了 ThreadProcess线程,ThreadProcess线程负责所有的音频流程,从设备获取音频数据包。

[cpp]

  1. bool AudioDeviceWindowsWave::ThreadProcess()  
  2. {  
  3.    while ((nRecordedBytes = RecProc(recTime)) > 0);  
  4. }  
  5.  
  6. bool AudioDeviceWindowsWave::ThreadProcess() 
  7.    while ((nRecordedBytes = RecProc(recTime)) > 0); 

处理过程在RecProc


[cpp]

  1. int32_t AudioDeviceWindowsWave::RecProc(LONGLONG& consumedTime)  
  2. {  
  3.      _ptrAudioBuffer->DeliverRecordedData();  
  4.  
  5. int32_t AudioDeviceWindowsWave::RecProc(LONGLONG& consumedTime) 
  6.      _ptrAudioBuffer->DeliverRecordedData(); 
  7. int32_t AudioDeviceBuffer::DeliverRecordedData()  
  8. {  
  9.      _ptrCbAudioTransport->RecordedDataIsAvailable();  
  10. }  
  11.  
  12. int32_t AudioDeviceBuffer::DeliverRecordedData() 
  13.      _ptrCbAudioTransport->RecordedDataIsAvailable(); 

RecordedDataIsAvailable是虚函数,被VoeBase重载

[cpp]

  1. int32_t VoEBaseImpl::RecordedDataIsAvailable(  
  2.         const void* audioSamples,  
  3.         uint32_t nSamples,  
  4.         uint8_t nBytesPerSample,  
  5.         uint8_t nChannels,  
  6.         uint32_t samplesPerSec,  
  7.         uint32_t totalDelayMS,  
  8.         int32_t clockDrift,  
  9.         uint32_t currentMicLevel,  
  10.         bool keyPressed,  
  11.         uint32_t& newMicLevel)  
  12. {  
  13.      _shared->transmit_mixer()->DemuxAndMix();  
  14.     _shared->transmit_mixer()->EncodeAndSend();  
  15. }  
  16.  
  17. int32_t VoEBaseImpl::RecordedDataIsAvailable( 
  18.         const void* audioSamples, 
  19.         uint32_t nSamples, 
  20.         uint8_t nBytesPerSample, 
  21.         uint8_t nChannels, 
  22.         uint32_t samplesPerSec, 
  23.         uint32_t totalDelayMS, 
  24.         int32_t clockDrift, 
  25.         uint32_t currentMicLevel, 
  26.         bool keyPressed, 
  27.         uint32_t& newMicLevel) 
  28.      _shared->transmit_mixer()->DemuxAndMix(); 
  29.     _shared->transmit_mixer()->EncodeAndSend(); 

DemuxAndMix() 从字面意思是分路与混合,这个函数,主要负责AudioProcess的所有过程,包括Aec,Aecm,AGC,DTMF,遍历所有channel;

[cpp]

  1. TransmitMixer::DemuxAndMix()  
  2. {  
  3.     Channel* channelPtr = sc.GetFirstChannel(iterator);  
  4.     while (channelPtr != NULL)  
  5.     {  
  6.         if (channelPtr->InputIsOnHold())  
  7.         {  
  8.             channelPtr->UpdateLocalTimeStamp();  
  9.         } else if (channelPtr->Sending())  
  10.         {  
  11.             // Demultiplex makes a copy of its input.   
  12.             channelPtr->Demultiplex(_audioFrame);  
  13.             channelPtr->PrepareEncodeAndSend(_audioFrame.sample_rate_hz_);  
  14.         }  
  15.         channelPtr = sc.GetNextChannel(iterator);  
  16.     } 
  17. }  
  18.  
  19. TransmitMixer::DemuxAndMix() 
  20.     Channel* channelPtr = sc.GetFirstChannel(iterator); 
  21.     while (channelPtr != NULL) 
  22.     { 
  23.         if (channelPtr->InputIsOnHold()) 
  24.         { 
  25.             channelPtr->UpdateLocalTimeStamp(); 
  26.         } else if (channelPtr->Sending()) 
  27.         { 
  28.             // Demultiplex makes a copy of its input. 
  29.             channelPtr->Demultiplex(_audioFrame); 
  30.             channelPtr->PrepareEncodeAndSend(_audioFrame.sample_rate_hz_); 
  31.         } 
  32.         channelPtr = sc.GetNextChannel(iterator); 
  33.     } 

Channel::Demutiplex(),基本上没有什么具体任务,就是把audioFrame里边的数据拷贝到channel自身, webrtc是client解决方案,对于client只认为有一个audio source,但可以有多个channel,每个channel中都有audio process,所以需要把数据copy到每个channel.

只有就是数据处理 PrepareEncodeAndSend()

[cpp]

  1. Channel::PrepareEncodeAndSend(int mixingFrequency)  
  2. {  
  3.    if (_inputFilePlaying)  
  4.     {  
  5.         MixOrReplaceAudioWithFile(mixingFrequency);
  6.  //如果使用了voeFile::PlayFileAsMic();则从文件读取10ms数据,并覆盖audio buffer   
  7.     }  
  8.   
  9.     if (_mute)  
  10.     {  
  11.         AudioFrameOperations::Mute(_audioFrame);//当然如果设置mutex,则memset 0    
  12.     }  
  13.    if (_inputExternalMedia)  
  14.    {  
  15.    _inputExternalMediaCallbackPtr->Process();
  16.   //所过设置了ExternalMedia,自己的audio处理过程,就是在这里调用的   
  17.    }  
  18.   InsertInbandDtmfTone();//添加DTMF音频   
  19.  _rtpAudioProc->ProcessStream(&_audioFrame);
  20.  // 真正的GIPS牛逼代码,audio process过程: Aec Aecm AGC    
  21. }  
  22.  
  23. Channel::PrepareEncodeAndSend(int mixingFrequency) 
  24.    if (_inputFilePlaying) 
  25.     { 
  26.         MixOrReplaceAudioWithFile(mixingFrequency);
  27.  //如果使用了voeFile::PlayFileAsMic();则从文件读取10ms数据,并覆盖audio buffer 
  28.     } 
  29.  
  30.     if (_mute) 
  31.     { 
  32.         AudioFrameOperations::Mute(_audioFrame);
  33. //当然如果设置mutex,则memset 0 
  34.     } 
  35.    if (_inputExternalMedia) 
  36.    { 
  37.    _inputExternalMediaCallbackPtr->Process();
  38. //所过设置了ExternalMedia,自己的audio处理过程,就是在这里调用的 
  39.    } 
  40.   InsertInbandDtmfTone(); 
  41.   //添加DTMF音频 
  42.  _rtpAudioProc->ProcessStream(&_audioFrame);
  43.   // 真正的GIPS牛逼代码,audio process过程: Aec Aecm AGC 

int AudioProcessingImpl::ProcessStream(AudioFrame* frame) 就是上述调用的_rtpAudioProc->ProcessStream();

以上是DemuxAndMix()过程,之后就是EncodeAndSend()过程,至此整个voe数据处理流程分析结束;

关于Audio Process则是另外一个大话题;


总结一下几点:

1.  VoeBase提供大部分的对外接口

2. Channel:继承了大部分的音频功能;

(tastesweet)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www1.rosoo.net/a/201309/16733.html]
本文出处:网络 作者:tastesweet
顶一下
(2)
66.7%
踩一下
(1)
33.3%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容