WebRTC音频 03 - 实时通信框架

WebRTC音频01 - 设备管理
WebRTC音频 02 - Windows平台设备管理

WebRTC音频 03 - 实时通信框架(本文)
WebRTC音频 04 - 关键类
WebRTC音频 05 - 音频采集编码

一、前言:

前面介绍了音频设备管理,并且以windows平台为例子,介绍了ADM相关的类,以及必须用到的重要API,本文我们分析下,在一个音视频呼叫过程中,音频是如何参与其中的,都有哪些成员参与其中。

二、呼叫时序图:

先回顾下总体呼叫流程,由大到小分析,避免看半天代码不知道自己在哪儿!

可以看出,呼叫过程中,先要创建非常重要的类PeerConnection,接着进行媒体协商,最后选择进行p2p或者turn这条路;我们现在要分析,这个过程中音频要做哪些事,这件事分别是在上面总流程的哪个位置。

三、音频数据流转:

我们先猜想下,整个过程中应该做什么?是不是下图这样?

标注红色的就是我们关心的。

四、具体到每个音频模块

  • 初始化阶段(图中粉色线):

    1. 这个流程之前分析过,从Session层开始创建一个会话,就会创建一个PeerConnection,然后就是创建音频引擎,接着创建ADM;
    2. adm创建过程中会创建AudioDeviceModuleGeneric的具体对象(windows平台就是AudioDeviceWindowsCore,下文本人全都写AudioDeviceModuleGeneric,就代表AudioDeviceWindowsCore);
  • 数据发送阶段(图中绿色线):

    1. AudioDeviceModuleGeneric对象从麦克风采集到数据,并送给AudioDeviceBuffer,等待发送;
    2. 交给AudioTransport模块处理;(这里面主要是经过 AudioProcess 模块进行3A处理)
    3. 交给Call模块的 AudioSendStream;
    4. 交给ACM模块的Encoder进行编码;
    5. 交给网络模块Transport进行发送;
  • 数据接收阶段(图中蓝色线):

    1. 从网络模块接收数据,送给Call模块的队列Queue进行缓存;
    2. 慢慢交给AudioReceiveStream进行处理;
    3. 交给ACM模块的Decoder进行解码;
    4. 解码之后交给在AudioReceiveStream模块继续缓存起来;(因为音频播放有一个单独的线程,扬声器会定时来缓存里面取,而不是我们主动送)
  • 数据播放阶段(图中黑色线):

    1. AudioDeviceModuleGeneric对象调用AudioDeviceBuffer相关接口获取数据;
    2. 调用AudioTransport相关接口获取数据(这里面主要是混音模块Mixer,可能同时获得1路或者多路音频,混成1路);
    3. AudioTransport调用1个或者多个AudioReceiveStream中分别取出一定长度的PCM数据;(webrtc就是10ms)
    4. 上面三步完成了调用之后,数据就会按照AudioReceiveStream->AudioTransport(mixer)->AudioDeviceBuffer->AudioDeviceModuleGeneric对象,最终通过扬声器播放出来;

总结:

  1. Call模块是每个session一个;
  2. ADM和AudioTransport里面的AudioProcess、Mixer都是全局唯一的,因为Mixer这种是瞬间处理的,不保存数据,因此,所有的Call模块共用同一个;
  3. 使用AudioState(可以理解成引擎层的上下文)管理AudioTransport和ADM虽然增加了一层,但是对于上层使用媒体引擎的人来说就非常简单了,我只需要和AudioState打交道;

五、类图:

关键模块类图如下:

  • adm_:就是AudioDeviceModule,对音视频设备进行管理,比如,从麦克风采集音频,让扬声器播放数据;

  • encoder_factory_:音频编码器工厂,创建编码器时候使用;

  • decoder_factory_:音频解码器工厂;

  • audio_mixer_:音频混音器,比如将多路输入流混成一路,送给扬声器播放;

  • apm_:专门用来处理3A问题;

  • audio_state_:表面看是音频状态管理,实则为音频流的管理;

  • send_codecs:音频编码器管理;

  • recv_codecs:音频解码器管理;

  • channels:WebRtcMediaVoiceChannel的集合;一个对应SDP中一个m行;

六、关键类对象创建时机:

在我们开始呼叫音视频通话时候,点击PeerConnectionClient弹出的connect按钮时候,会调用Conductor::InitializePeerConnection(),先看看引擎的初始化时机:

然后再看看PeerConnectionFactory::Create再调用 ConnectionContext::Create,而ConnectionContext::Create之后主要干了下面几件事情:

备注:

  1. 发现扬声器和麦克风ADM这一层逻辑基本一致。

  2. 并且adm和AudioDeviceWindowsCore中间还有个传话筒AudioDeviceModuleImpl我没有画出来,就是转手调用AudioDeviceWindowsCore而已。

  3. 向adm注册一个回调 audio_state()->audio_transport,用于接收将来产生的音视频数据;

  4. 创建PeerConnectionFactory之前已经创建了四个编解码器的Factory;

  5. 构造Denpendenices的时候,就实例化了一个APM模块,并进行了初始化;

  6. 我们前面构造的MediaEngineDependencies是PeerConnectionFactoryDependencies的一个成员,使用media_engine保存;(里面主要是三大线程、call_factory、media_engine(看后面代码,这个主要是接收MediaDependecies的));

  7. 然后是创建音视频引擎;

  8. 引擎创建好之后,对引擎做一些必要的初始化CreateModularPeerConnectionFactory:

    1. 对pc_factory进行初始化;
      1. BasicNetworkManager:主要是管理网卡的;
      2. BasicPacketSocketFactory:也就是Socekt工厂,主要创建各种各样的socket;
      3. 创建ChannelManager(它是连接编解码器的),同时会调用Init,里面会调用media_engine->Init来初始化之前创建的媒体引擎;

七、总结:

本文主要是介绍了音频各个模块在整个呼叫过程中所处的角色,以及何时创建(创建时机)、创建的什么样(类图);主要从总体分析,如果要具体到每个类,后续会根据业务场景再做分析,比如:采集过程中用到哪几个类,具体调用哪个函数等等,关注我,不迷路!

扫描关注,最早拿到一手资源:

相关推荐
全域观察2 小时前
如何复制只读模式下的腾讯文档
人工智能·新媒体运营·媒体·内容运营·程序员创富
简鹿办公6 小时前
如何提取某站 MV 视频中的音乐为 MP3 音频
音视频·简鹿视频格式转换器·视频提取mp3音频
yufengxinpian6 小时前
集成了高性能ARM Cortex-M0+处理器的一款SimpleLink 2.4 GHz无线模块-RF-BM-2340B1
单片机·嵌入式硬件·音视频·智能硬件
runing_an_min7 小时前
ffmpeg视频滤镜:替换部分帧-freezeframes
ffmpeg·音视频·freezeframes
runing_an_min10 小时前
ffmpeg视频滤镜:提取缩略图-framestep
ffmpeg·音视频·framestep
小曲曲10 小时前
接口上传视频和oss直传视频到阿里云组件
javascript·阿里云·音视频
安静读书13 小时前
Python解析视频FPS(帧率)、分辨率信息
python·opencv·音视频
佑华硬盘拷贝机13 小时前
音频档案批量拷贝:专业SD拷贝机解决方案
音视频
EasyNVR13 小时前
NVR管理平台EasyNVR多个NVR同时管理:全方位安防监控视频融合云平台方案
安全·音视频·监控·视频监控
xcLeigh20 小时前
HTML5超酷响应式视频背景动画特效(六种风格,附源码)
前端·音视频·html5