转自:http://www.cnblogs.com/fangkm/p/4374668.html

上一篇博文介绍了本地视频采集,这一篇就介绍下音频采集流程,也是先介绍WebRTC原生的音频采集,再介绍Chromium源码对它的定制。

1. WebRTC原生音频采集

先介绍一下WebRTC中与音频采集貌似相关的接口概念:

结构上看起来是不是和视频Track的结构类似?不过前面提过,如果你以对称的思维,在此结构中找出与视频track相似的采集源和输出源,那就肯定无功而返了,LocalAudioSource对AudioSourceInterface的实现就是一个空实现,没有了音频源,那音频处理接口AudioProcessorInterface和输出接口AudioRenderer都成了无米之炊了。这些接口先摆在这,可能类似于AudioCapturer的框架正在实现的途中,也可能这些接口有别的用处,比如远程音频流的抽象等,这里就暂且搁置,先记下有这回事吧。这里只谈WebRTC本地音频的采集处理。前面介绍音视频接口的时候也提到的,本地音频的采集由AudioDeviceModule接口统一封装:

AudioDeviceModule是个大而全的接口,恨不得将所有音频相关的接口都封装在里面(实际也差不多了),具体包括:枚举音频采集设备(Record)和播放设备(Playout)、设置当前的采集设备/播放设备、开始/停止音频的采集/播放、设置音频增益控制开关(AGC)等。AudioTransport是个关键的对外接口,负责音频数据的传入(调用NeedMorePlayData方法,供Playout使用)和输出(调用RecordedDataIsAvailable方法,数据由Record采集操作产生)。

AudioDeviceModuleImpl实现了AudioDeviceModule接口,创建的时候调用CreatePlatformSpecificObjects方法创建平台相关的AudioDeviceGeneric接口实现。该接口抽象了音频的采集和播放逻辑,在Windows平台下有两种实现方案:

  • AudioDeviceWindowsWave实现的是传统的Windows Wave APIs方案。
  • AudioDeviceWindowsCore实现的是Vista之后才支持的Windows Core Audio APIs方案。

此外,AudioDeviceModuleImpl还维护了一个AudioDeviceBuffer对象来管理音频数据的缓冲区,由它直接与对外接口AudioTransport交互。比如:

  • 当AudioDeviceWindowsWave或者AudioDeviceWindowsCore需要播放音频数据的时候,会调用AudioDeviceBuffer的RequestPlayoutData方法请求播放数据,然后通过GetPlayoutData方法来获取刚请求到的数据。AudioDeviceBuffer的RequestPlayoutData就是调用AudioTransport接口的NeedMorePlayData方法来请求待播放的音频流数据。
  • 当AudioDeviceWindowsWave或者AudioDeviceWindowsCore采集到音频数据后,会调用AudioDeviceBuffer的SetRecordedBuffer方法将采集到的音频数据传递进去,然后调用DeliverRecordedData方法来派发出去,该派发方法就是通过调用AudioTransport接口的RecordedDataIsAvailable来实现。

总之,音频采集模块处处都透露出大而全的结构设计。如果可以,真的应该细化一下概念设计,比如将音频采集和音频播放逻辑分离、音频输入和输出的接口拆分等等,那样才能谈得上结构设计。

2. Chromium对WebRTC的音频采集适配

根据WebRTC的本地音频接口设计,Chromium提供了一个WebRtcAudioDeviceImpl类来实现AudioDeviceModule接口,该类对象由PeerConnectionDependencyFactory负责创建和维护,结构如下:

如图所示,WebRtcAudioDeviceImpl摒弃了原生的AudioDeviceModuleImpl实现中大而全的设计,而是将音频采集和音频渲染逻辑分开,分别对应于WebRtcAudioCapturer和WebRtcAudioRenderer。WebRtcAudioRenderer通过WebRtcAudioRendererSource接口的RenderData方法向WebRtcAudioDeviceImpl请求音频流数据来渲染,WebRtcAudioDeviceImpl将该请求转发给前面提到的对外交互接口AudioTransport。WebRtcAudioCapturer封装音频采集逻辑,它将采集到的数据通过WebRtcLocalAudioTrack对象所持有的PeerConnectionAudioSink接口派发出去,WebRtcAudioDeviceImpl正是实现了该接口来接收音频采集数据,然后也是通过AudioTransport接口往外传递。至于WebRtcAudioCapturer对象的持有者MediaStreamAudioSource和WebMediaStreamTrack,这里暂时有个概念就行,它们是Chromium对HTML5媒体流的实现接口。接下来仔细分析一下WebRtcAudioCapturer和WebRtcAudioRenderer两个关键类,毋庸置疑,它们都涉及到了特定平台实现,而且在Chromium中还跨越了Render和Browser进程。和介绍Chromium视频采集的模式一样,由于不是本文重点,这里只列出结构图,不打算详解,如果你有开发上的需要,可以照着该结构图细看源码。

这是WebRtcAudioCapturer采集音频数据的结构,牵涉到跨进程通信,结构还是非常复杂的。WebRtcAudioRenderer的结构就不准备介绍了,因为Chromium的这块设计非常具备对称性,基本上图中类命名中的Input改成Output就差不多是WebRtcAudioRenderer的架构了。

(四)WebRTC手记之本地音频采集的更多相关文章

  1. WebRTC手记之本地音频采集

    转载请注明出处:http://www.cnblogs.com/fangkm/p/4374668.html 上一篇博文介绍了本地视频采集,这一篇就介绍下音频采集流程,也是先介绍WebRTC原生的音频采集 ...

  2. (三)WebRTC手记之本地视频采集

    转自:http://www.cnblogs.com/fangkm/p/4374610.html 前面两篇文章介绍WebRTC的运行流程和使用框架接口,接下来就开始分析本地音视频的采集流程.由于篇幅较大 ...

  3. WebRTC手记之本地视频采集

    转载请注明出处:http://www.cnblogs.com/fangkm/p/4374610.html 前面两篇文章介绍WebRTC的运行流程和使用框架接口,接下来就开始分析本地音视频的采集流程.由 ...

  4. EasyPlayerPro Windows播放器进行本地对讲喊话音频采集功能实现

    需求 在安防行业应用中,除了在本地看到摄像机的视频和进行音频监听外,还有一个重要的功能,那就是对讲. EasyPlayerPro-win为了减轻二次开发者的工作量,将本地音频采集也进行了集成: 功能特 ...

  5. (二)WebRTC手记之框架与接口

    转自:http://www.cnblogs.com/fangkm/p/4370492.html 转载请注明出处:http://www.cnblogs.com/fangkm/p/4370492.html ...

  6. WebRTC手记之框架与接口

    转载请注明出处:http://www.cnblogs.com/fangkm/p/4370492.html 上一篇文章简单地介绍了下WebRTC的协议流程,这一篇就开始介绍框架与接口. 一提到框架,本能 ...

  7. iOS从零开始学习直播之音频1.播放本地音频文件

      现在直播越来越火,俨然已经成为了下一个红海.作为一个资深码农(我只喜欢这样称呼自己,不喜欢别人这样称呼我),我必须赶上时代的潮流,开始研究视频直播.发现视屏直播类的文章上来就讲拉流.推流.采集.美 ...

  8. iOS Dev (20) 用 AVAudioPlayer 播放一个本地音频文件

    iOS Dev (20) 用 AVAudioPlayer 播放一个本地音频文件 作者:CSDN 大锐哥 博客:http://blog.csdn.net/prevention 步骤 第一步:在 Proj ...

  9. iOS Dev (21) 用 AVPlayer 播放一个本地音频文件

    iOS Dev (21) 用 AVPlayer 播放一个本地音频文件 作者:CSDN 大锐哥 博客:http://blog.csdn.net/prevention 前言 这篇文章与上一篇极其相似,要注 ...

随机推荐

  1. Python 列表元素排重uniq

    # -*- coding: gbk -*- def uniq(ls): lsCopy=[e for e in ls] for i in xrange(1,len(ls)): for j in xran ...

  2. 嵌套div中margin-top转移问题的解决办法

    在这两个浏览器中,有两个嵌套关系的div,如果外层div的父元素padding值为0,那么内层div的margin-top或者margin-bottom的值会“转移”给外层div. <!DOCT ...

  3. [20160731][转]JAVA当中变量什么时候需要初始化

    1. 对于类的成员变量,不管程序有没有显式的进行初始化,Java虚拟机都会先自动给它初始化为默认值. 默认值如下:             Boolean      false             ...

  4. Linux下如何移除同时在线的用户

    Linux下移除同时在线的用户太多时,shell操作会变得比较卡,很多时候经常是直接关闭终端导致不正常退出,一般要等上一段时间才会退出,这个时候主动结束用户进程使用户下线是比较好的方式,方法如下: 使 ...

  5. iOS AES加密解密实现方法

    使用方法 先导入头文件 #import "NSData+AES.h" //AES测试 //用来密钥 NSString *key = "; //用来发送的原始数据 NSSt ...

  6. HDU 1693 Eat the Trees(插头DP、棋盘哈密顿回路数)+ URAL 1519 Formula 1(插头DP、棋盘哈密顿单回路数)

    插头DP基础题的样子...输入N,M<=11,以及N*M的01矩阵,0(1)表示有(无)障碍物.输出哈密顿回路(可以多回路)方案数... 看了个ppt,画了下图...感觉还是挺有效的... 参考 ...

  7. C# Arraylist + struct 综合练习 枚举ENUE 递归

    枚举类型 一组常量的组合, 在不制定任何索引的情况下,默认第一个字段从0开始,之后的依次+1 在指定了某个索引的情况下,之后的依次+1 若之前定义的某字段的索引指向了之后的某个默认字段,那么他俩完全相 ...

  8. php面向对象中的静态与抽象,接口

    静态又包括: 普通成员: 普通成员是属于对象的 静态成员: 静态成员是属于类的 关键字:static self关键字:在类里面代表该类,前面不用加$ 在静态方法里面不能调用普通成员 在普通方法里面能够 ...

  9. 核心动画基础动画(CABasicAnimation)关键帧动画

    1.在iOS中核心动画分为几类: 基础动画(CABasicAnimation) 关键帧动画(CAKeyframeAnimation) 动画组(CAAnimationGroup) 转场动画(CATran ...

  10. UI课堂笔记

    2016.7.18 + (UIColor *)blackColor; + (UIColor *)darkGrayColor;   深灰色 + (UIColor *)lightGrayColor;  浅 ...