webrtc发送端-音频采集编码发送

github:https://github.com/bigonelby/webrtcUml/tree/master/latest

webrtc-new-发送端-audio采集编码发送.drawio.png
  1. 这张图介绍了音频发送端采集,编码,发送的流程。整个内容分为8部分,分别为:核心Core;音频采集;AudioUnit;AudioSession;Resample && Process;Send Stream;Encode和Network

  2. 首先看核心Core。万物皆由始,Audio的整个内容的源头是什么呢?可以认为是VoiceEngineInterface,正是引擎层最终构建出完整的音频世界。实现这个Interface的正是大名鼎鼎的WebrtcVoiceEngine。WebrtcVoiceEngine有几个关键的组件,比如AudioDeviceModule,这个组件就是负责音频采集的,我们从这个组件开始看起

  3. 音频采集。刚才已经提到,WebrtcVoiceEngine有一个关键的组件,即AudioDeviceModule。这是一个Module,是一个抽象层,不同的平台有不同的实现。对于iOS而言,实现类是AudioDeviceModuleIOS。当然,这个实现类也不直接接触底层,真正干活的是他的小弟AudioDeviceIOS,这是整个音频采集层的核心。后面我们可以看到这个类起到承上启下的关键作用!我们先看看这个类有若干身份:首先他是一个通用的音频设备,即AudioDeviceGeneric;其次,他还是VoiceProcessingAudioUnitObserver,因此可以接收系统AudioUnit传回来的数据;最后,他还是AudioSessionObserver,这就表示他还可以监听AudioSession的一举一动。在收到AudioUnit的采集或播放数据后,他还会将数据缓存到FineAudioBuffer中,并最终送到AudioDeviceBuffer,最终通过注册的audio_transrpot_cb_将采集数据分发给AudioTransport。至此有个疑问,为何有FineAudioBuffer和AudioDeviceBuffer两个Buffer呢?实际上FineAudioBuffer作为更精细化的buffer,从设备获取的数据可能不足10ms,但是整个webrtc的pipeline里处理的音频数据都是以10ms为frame的。那么如何处理这种不对等呢?自然是引入buffer。因此当FineAudioBuffer积累的数据超过10ms时,就会构建成AudioDeviceBuffer,这样就可以保证完整的10ms数据分发给底层了!

  4. AudioUnit和AudioSession。这两个才是系统级别的api,是真正的打工仔,webrtc通过这两个类控制音频模块。通过VoiceProcessingAudioUnit操纵AudioUnit,顾名思义,关注的是voice process后的i/o。并且会注册回调函数到系统的AudioUnit中。因此当AudioUnit中有采集数据时,就会通过注册好的回调函数OnDeliverRecordedData回调上来,并最终通过observer_将这个信息告知VoiceProcessingAudioUnitObserver,即AudioDeviceIOS。AudioDeviceIOS再通过VoiceProcessingAudioUnit的Render方法,得到真正的采集数据,于是将数据缓存至FineAudioBuffer中,并最终分发出去。除了采集数据,我们还需要一些控制信息,比如音量变化了,Router变化了等等信息,这就需要AVAudioSession了。AudioDeviceIOS通过RTCAudioSession向AVAudioSession中注册感兴趣的事件,通过NSNotificationCenter这个消息大管家注册具体感兴趣的通知,比如AVAudioSessionRouteChangeNotification等。当有相应事件发生时,就会通知给RTCAudioSession,RTCAudioSession进而通过注册的delegate将消息分发,通过RTCNativeAudioSessionDelegateAdapter,最终告知AudioSessionObserver,即AudioDeviceIOS,至此这些关键信息也可以被AudioDeviceIOS捕获。

  5. Resample && Process。上面已经清楚了AudioDeviceIOS确实神通广大,他可以获取采集音频,和音频相关的控制信息的变化,并最终将采集的音频数据打包成10ms的AudioDeviceBuffer,并分发给AudioTransport。接下来,顺理成章的,AudioTransport的实现类AudioTransportImpl收到了来自AudioDeviceIOS的这份大礼,首先会交由PushResampler,如需要,则进行重采样工作,接着有AudioProcessing模块完成音频的3a处理

  6. SendStream。至此,采集数据已经重采样并进行了3a处理,接下来就是分发给注册到AudioTransportImpl的audio_senders_了。这个类是AudioSender,其实现者是AudioSendStream,是在什么时机注册的呢?其实是大管家AudioState会维护一个sending_streams_的map,其value就是AudioSendStream。因此每次新加一个成员,即调用AudioState的AddSendingStream的时候,首先会将新成员管理在sending_streams_这个map中,另外就会调用UpdateAudioTransportWithSendingStreams将所有的AudioSendStream注册到AudioTransport中。因此AudioSendStream可以顺利拿到采集数据,并交给ChannelSendInterface进行接下来的处理

  7. Encode && Network。ChannelSendInterface的实现类即为ChannelSend,顾名思义,他要进行真正的send工作了,在此之前要先进行编码。因此ChannelSend首先将采集数据交给了AudioCodingModule,这个模块是专门负责音频编码的。完成编码工作的是其实现类AudioCodingModelImpl的成员encode_stack_,这是AudioEncoder,负责真正的编码工作。和视频不同的是,这个编码是一个同步的过程,AudioEncoder将生成EncodedInfo对象同步返回。于是AudioCodingModuleImpl在收到这个编码后的信息后,交由packetization_callback_处理,即AudioPacketizationCallback的SendData接口。实现这个接口的还是ChannelSend,你看编码后的数据再次回到了ChannelSend的手中。这样就可以进行下一步的网络发送了。主要有两个步骤,其一是通过rtp_rtcp_检验是否应该发送RTCP数据,如果需要,则通过RTCPSender将相应的RTCP包发送。最后就是通过rtp_sender_audio_即RTPSenderAudio,将数据发送出去即SendAudio。最终构建RtpPacketToSend,并通过RTPSender的EnqueuePackets方法,将包入队列。后面的pacing过程就和video是一样的了,这里就不再赘述了。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容