Android Audio System 之二:AudioFlinger

原创 2010年10月19日 19:01:00

引言

    AudioFlinger是Android音频系统的两大服务之一,另一个服务是AudioPolicyService,这两大服务都在系统启动时有MediaSever加载,加载的代码位于:frameworks/base/media/mediaserver/main_mediaserver.cpp。AudioPolicyService的相关内容请参考另一编文章:《Android Audio System 之三: AudioPolicyService 和 AudioPolicyManager 》

http://blog.csdn.net/DroidPhone/archive/2010/10/18/5949280.aspx

 

    本文主要介绍AudioFlinger,AudioFlinger向下访问AudioHardware,实现输出音频数据,控制音频参数。同时,AudioFlinger向上通过IAudioFinger接口提供服务。所以,AudioFlinger在Android的音频系统框架中起着承上启下的作用,地位相当重要。AudioFlinger的相关代码主要在:frameworks/base/libs/audioflinger,也有部分相关的代码在frameworks/base/media/libmedia里。

AudioFlinger的类结构

下面的图示描述了AudioFlinger类的内部结构和关系:

 

                                                             图一   AudioFlinger的类结构

不知道各位是否和我一样,第一次看到AudioFlinger类的定义的时候都很郁闷--这个类实在是庞大和臃肿,可是当你理清他的关系以后,你会觉得相当合理。下面我们一一展开讨论。

  • IAudioFlinger接口

    这是AudioFlinger向外提供服务的接口,例如openOutput,openInput,createTrack,openRecord等等,应用程序或者其他service通过ServiceManager可以获得该接口。该接口通过继承BnAudioFlinger得到。

  • ThreadBase

    在AudioFlinger中,Android为每一个放音/录音设备均创建一个处理线程,负责音频数据的I/O和合成,ThreadBase是这些线程的基类,所有的播放和录音线程都派生自ThreadBase

  • TrackBase

    应用程序每创建一个音轨(AudioTrack/AudioRecord),在AudioFlinger中都会创建一个对应的Track实例,TrackBase就是这些Track的基类,他的派生类有:

  •  
    • PlaybackTread::Track    // 用于普通播放,对应于应用层的AudioTrack
    • PlaybackThread::OutputTrack    // 用于多重设备输出,当蓝牙播放开启时使用
    • RecordThread::RecordTrack    // 用于录音,对应于应用层的AudioRecord
  • 播放

    默认的播放线程是MixerThread,它由AudioPolicyManager创建,在AudioPolicyManager的构造函数中,有以下代码:

最终会进入AudioFlinger的openOut函数:

可以看到,创建好的线程会把该线程和它的Id保存在AudioFlinger的成员变量mPlaybackThreads中,mPlaybackThreads是一个Vector,AudioFlinger创建的线程都会保存在里面,最后,openOutput返回该线程的Id,该Id也就是所谓的audio_io_handle_t,AudioFlinger的调用者这能看到这个audio_io_handle_t,当需要访问时传入该audio_io_handle_t,AudioFlinger会通过mPlaybackThreads,得到该线程的指针。

    要播放声音,应用程序首先要通过IAudioFlinger接口,调用createTrack(),关于createTrack的流程,可以参看我的另一篇文章:

          http://blog.csdn.net/DroidPhone/archive/2010/10/14/5941344.aspx

createTrack会调用PlaybackThread类的createTrack_l函数:

再跟入createTrack_l函数中,可以看到创建了PlaybackThread::Track类,然后加入播放线程的track列表mTracks中。

在createTrack的最后,创建了TrackHandle类并返回,TrackHandle继承了IAudioTrack接口,以后,createTrack的调用者可以通过IAudioTrack接口与AudioFlinger中对应的Track实例交互。

 最后,在系统运行时,AudioFlinger中的线程和Track的结构大致如下图所示:它会拥有多个工作线程,每个线程拥有多个Track。

                                          图二     AudioFlinger的线程结构

播放线程实际上是MixerThread的一个实例,MixerThread的threadLoop()中,会把该线程中的各个Track进行混合,必要时还要进行ReSample(重采样)的动作,转换为统一的采样率(44.1K),然后通过音频系统的AudioHardware层输出音频数据。

  • 录音

     录音的流程和放音差不多,只不过数据流动的方向相反,录音线程变成RecordThread,Track变成了RecordTrack,openRecord返回RecordHandle,详细的暂且不表。

  • DuplicatingThread

    AudioFlinger中有一个特殊的线程类:DuplicatingThread,从图一可以知道,它是MixerThread的子类。当系统中有两个设备要同时输出时,DuplicatingThread将被创建,通过IAudioFlinger的openDuplicateOutput方法创建DuplicatingThread。

    创建 DuplicatingThread时,传入2个需要同时输出的目标线程Id,openDuplicateOutput先从mPlaybackThreads中根据Id取得相应输出线程的实例,然后为每个线程创建一个虚拟的AudioTrack----OutputTrack,然后把这个虚拟的AudioTrack加入到目标线程的mTracks列表中,DuplicatingThread在它的threadLoop()中,把Mixer好的数据同时写入两个虚拟的OutputTrack中,因为这两个OutputTrack已经加入到目标线程的mTracks列表,所以,两个目标线程会同时输出DuplicatingThread的声音。

    实际上,创建DuplicatingThread的工作是有AudioPolicyService中的AudioPolicyManager里发起的。主要是当蓝牙耳机和本机输出都开启时,AudioPolicyManager会做出以下动作:

  • 首先打开(或创建)蓝牙输出线程A2dpOutput
  • 以HardwareOutput和A2dpOutput作为参数,调用openDuplicateOutput,创建DuplicatingThread
  • 把属于STRATEGY_MEDIA类型的Track移到A2dpOutput中
  • 把属于STRATEGY_DTMF类型的Track移到A2dpOutput中
  • 把属于STRATEGY_SONIFICATION类型的Track移到DuplicateOutput中

结果是,音乐和DTMF只会在蓝牙耳机中输出,而按键音和铃声等提示音会同时在本机和蓝牙耳机中输出。

                                                                           图三  本机播放时的Thread和Track

 

 

 

 

 

 

 

 

 

                                                                        图四   蓝牙播放时的Thread和Track

 

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Android中的Audio播放:控制Audio输出通道切换

田海立@csdn2012-04-03 Audio 输出通道有很多,Speaker、headset、bluetooth A2DP等。通话或播放音乐等使用Audio输出过程中,可能发生Audio输出通道的...
  • thl789
  • thl789
  • 2012-04-03 14:22
  • 22076

Android 7.0 Audio: AudioFlinger介绍和初始

对于AF的分析,先看其所在层的位置以及相关的交互类,       之前的版本,AF在Main_MediaServer.cpp里面启动,在android N,AF在main_audioserver.c...

深入剖析Android音频之AudioPolicyService

AudioPolicyService是策略的制定者,比如什么时候打开音频接口设备、某种Stream类型的音频对应什么设备等等。而AudioFlinger则是策略的执行者,例如具体如何与音频设备通信,如...

ASP.NET中应用Excel:(2)释放对象

我们访问的Excel对象是COM对象。对于COM对象(也包括接口),每次对于对象的引用(在C++中这一操作对应于ComCreateObject和QueryInterface)都会增加该对象的引用计数,...
  • igame
  • igame
  • 2008-06-26 15:41
  • 1052

Android的Audio系统

Android的Audio 系统第一部分 Audio系统综述第二部分 Audio系统和上层接口第三部分 Audio的硬件抽象层第一部分 Audio系统综述Audio系统在Android中负责音频方面的...
  • gowyz
  • gowyz
  • 2010-11-18 16:08
  • 21817

Android系统Choreographer机制实现过程

在Android4.1之后增加了Choreographer机制,用于同Vsync机制配合,实现统一调度界面绘图. Choreographer构造过程 frameworks\base\core\ja...

Android Audio System

第7章 Android的Audio系统 本章介绍Android的音频系统内容,主要是音频的输入/输出环节,不涉及编解码的内容(音频系统从驱动程序、本地框架到Java框架都具有内 容)。本章介绍Aud...

Android的Audio系统详解

目录 Audio系统详解 1       Audio的Framework层功能及用法大全     1.1      ...

android audio概念大全

1.audio stream  type(10类audio stream类型) 这些类型代表了android系统中所有的声音种类,通过不同的stream标志,可以精确的控制这些audio strea...

字符串+ 聚合函数?

存在一个表 表名:t_example字段:meetingid,     joiner类型:varchar(10),    varchar(10)数据:1000      ...
  • qvyyy
  • qvyyy
  • 2007-06-11 13:59
  • 816
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)