解析5G时代音视频 WebRTC音频引擎实现分析

前言

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所示。

解析5G时代音视频 WebRTC音频引擎实现分析

图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所示。

解析5G时代音视频 WebRTC音频引擎实现分析

图2 WebRTC音频引擎数据流.png

3.1 音频引擎创建及初始化

音频引擎的创建及初始化流程如图3所示:

解析5G时代音视频 WebRTC音频引擎实现分析

图3 WebRTC音频引擎创建及初始化.png

WebRTC音频引擎的创建从PeerConnectionFactory对象的创建及初始化开始,这个过程由WebRTC的应用程序发起,并在signal线程在进行,最终调用CreateMediaEngine_w()转到worker线程。在worker线程中,先创建WebRtcMediaEngine2,进而WebRtcVoiceEngine,最终创建VoiceEngineImpl。而最重要的初始化操作则VoEBaseImpl的Init()函数中完成。

3.2 音频数据的采集和编码

音频数据的采集是平台相关的,在此以Windows平台为例,整个采集和编码过程如图4所示:

解析5G时代音视频 WebRTC音频引擎实现分析

图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所示。

解析5G时代音视频 WebRTC音频引擎实现分析

图5 音频数据的发送.png

Channel调用把数据发送给RtpRtcp模块,后者经过一系列的调用进行RTP打包后到达RtpSender对象。如果没有配置平滑发送线程PacedSender,则RtpSender直接调用SendPacketToNetwork()把数据发送到network线程。否则数据会先存储到PacedSender线程中,再由后者进行平滑发送,最终数据发送到network线程。

3.4 音频数据的接收

network线程从网络接收到音频数据后,交给worker线程进行下一步接收。Worker线程的工作流程如图6所示。

解析5G时代音视频 WebRTC音频引擎实现分析

图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所示。

解析5G时代音视频 WebRTC音频引擎实现分析

图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有了更深入的认识和体会,为未来进一步学习打下坚实基础。

猜你喜欢

转载自blog.csdn.net/qq_42302962/article/details/106281096