https://blog.csdn.net/innost/article/details/6142812

https://blog.csdn.net/zyuanyun/article/details/60890534

AndioFlinger 作为 Android 的音频系统引擎,重任之一是负责输入输出流设备的管理及音频流数据的处理传输,这是由回放线程(PlaybackThread 及其派生的子类)和录制线程(RecordThread)进行的,我们简单看看回放线程和录制线程类关系:

ThreadBase:PlaybackThread 和 RecordThread 的基类
RecordThread:录制线程类,由 ThreadBase 派生
PlaybackThread:回放线程基类,同由 ThreadBase 派生
MixerThread:混音回放线程类,由 PlaybackThread 派生,负责处理标识为 AUDIO_OUTPUT_FLAG_PRIMARY、AUDIO_OUTPUT_FLAG_FAST、AUDIO_OUTPUT_FLAG_DEEP_BUFFER 的音频流,MixerThread 可以把多个音轨的数据混音后再输出
DirectOutputThread:直输回放线程类,由 PlaybackThread 派生,负责处理标识为 AUDIO_OUTPUT_FLAG_DIRECT 的音频流,这种音频流数据不需要软件混音,直接输出到音频设备即可
DuplicatingThread:复制回放线程类,由 MixerThread 派生,负责复制音频流数据到其他输出设备,使用场景如主声卡设备、蓝牙耳机设备、USB 声卡设备同时输出
OffloadThread:硬解回放线程类,由 DirectOutputThread 派生,负责处理标识为 AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD 的音频流,这种音频流未经软件解码的(一般是 MP3、AAC 等格式的数据),需要输出到硬件解码器,由硬件解码器解码成 PCM 数据
PlaybackThread 中有个极为重要的函数 threadLoop(),当 PlaybackThread 被强引用时,threadLoop() 会真正运行起来进入循环主体,处理音频流数据相关事务

1.threadLoop() 循环的条件是 exitPending() 返回 false,如果想要 PlaybackThread 结束循环,则可以调用 requestExit() 来请求退出;
2.processConfigEvents_l() :处理配置事件;当有配置改变的事件发生时,需要调用 sendConfigEvent_l() 来通知 PlaybackThread,这样 PlaybackThread 才能及时处理配置事件;常见的配置事件是切换音频通路;
检查此时此刻是否符合 standby 条件,比如当前并没有 ACTIVE 状态的 Track(mActiveTracks.size() = 0),那么调用 threadLoop_standby() 关闭音频硬件设备以节省能耗;
3.prepareTracks_l(): 准备音频流和混音器,该函数非常复杂,这里不详细分析了,仅列一下流程要点:
遍历 mActiveTracks,逐个处理 mActiveTracks 上的 Track,检查该 Track 是否为 ACTIVE 状态;
如果 Track 设置是 ACTIVE 状态,则再检查该 Track 的数据是否准备就绪了;
根据音频流的音量值、格式、声道数、音轨的采样率、硬件设备的采样率,配置好混音器参数;
如果 Track 的状态是 PAUSED 或 STOPPED,则把该 Track 添加到 tracksToRemove 向量中;
4.threadLoop_mix():读取所有置了 ACTIVE 状态的音频流数据,混音器开始处理这些数据;
5.threadLoop_write(): 把混音器处理后的数据写到输出流设备;
6.threadLoop_removeTracks(): 把 tracksToRemove 上的所有 Track 从 mActiveTracks 中移除出来;这样下一次循环时就不会处理这些 Track 了。
这里说说 PlaybackThread 与输出流设备的关系:PlaybackThread 实例与输出流设备是一一对应的,比方说 OffloadThread 只会将音频数据输出到 compress_offload 设备中,MixerThread(with FastMixer) 只会将音频数据输出到 low_latency 设备中。

从 Audio HAL 中,我们通常看到如下 4 种输出流设备,分别对应着不同的播放场景:

primary_out:主输出流设备,用于铃声类声音输出,对应着标识为 AUDIO_OUTPUT_FLAG_PRIMARY 的音频流和一个 MixerThread 回放线程实例
low_latency:低延迟输出流设备,用于按键音、游戏背景音等对时延要求高的声音输出,对应着标识为 AUDIO_OUTPUT_FLAG_FAST 的音频流和一个 MixerThread 回放线程实例
deep_buffer:音乐音轨输出流设备,用于音乐等对时延要求不高的声音输出,对应着标识为 AUDIO_OUTPUT_FLAG_DEEP_BUFFER 的音频流和一个 MixerThread 回放线程实例
compress_offload:硬解输出流设备,用于需要硬件解码的数据输出,对应着标识为 AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD 的音频流和一个 OffloadThread 回放线程实例
其中 primary_out 设备是必须声明支持的,而且系统启动时就已经打开 primary_out 设备并创建好对应的 MixerThread 实例。其他类型的输出流设备并非必须声明支持的,主要是看硬件上有无这个能力。

可能有人产生这样的疑问:既然 primary_out 设备一直保持打开,那么能耗岂不是很大?这里阐释一个概念:输出流设备属于逻辑设备,并不是硬件设备。所以即使输出流设备一直保持打开,只要硬件设备不工作,那么就不会影响能耗。那么硬件设备什么时候才会打开呢?答案是 PlaybackThread 将音频数据写入到输出流设备时。

下图简单描述 AudioTrack、PlaybackThread、输出流设备三者的对应关系:

我们可以这么说:输出流设备决定了它对应的 PlaybackThread 是什么类型。怎么理解呢?意思是说:只有支持了该类型的输出流设备,那么该类型的 PlaybackThread 才有可能被创建。举个例子:只有硬件上具备硬件解码器,系统才建立 compress_offload 设备,然后播放 mp3 格式的音乐文件时,才会创建 OffloadThread 把数据输出到 compress_offload 设备上;反之,如果硬件上并不具备硬件解码器,系统则不应该建立 compress_offload 设备,那么播放 mp3 格式的音乐文件时,通过 MixerThread 把数据输出到其他输出流设备上。

那么有无可能出现这种情况:底层并不支持 compress_offload 设备,但偏偏有个标识为 AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD 的音频流送到 AudioFlinger 了呢?这是不可能的。系统启动时,会检查并保存输入输出流设备的支持信息;播放器在播放 mp3 文件时,首先看 compress_offload 设备是否支持了,如果支持,那么不进行软件解码,直接把数据标识为 AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;如果不支持,那么先进行软件解码,然后把解码好的数据标识为 AUDIO_OUTPUT_FLAG_DEEP_BUFFER,前提是 deep_buffer 设备是支持了的;如果 deep_buffer 设备也不支持,那么把数据标识为 AUDIO_OUTPUT_FLAG_PRIMARY。

系统启动时,就已经打开 primary_out、low_latency、deep_buffer 这三种输出流设备,并创建对应的 MixerThread 了;而此时 DirectOutputThread 与 OffloadThread 不会被创建,直到标识为 AUDIO_OUTPUT_FLAG_DIRECT/AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD 的音频流需要输出时,才开始创建 DirectOutputThread/OffloadThread 和打开 direct_out/compress_offload 设备。

openOUtput:

new AudioTrack:

start:

write:

pause:

转载:android audio flinger的更多相关文章

  1. 转载:android audio policy

    Audio policy basic:https://www.cnblogs.com/CoderTian/p/5705742.html Set volume flow:https://blog.csd ...

  2. Android Audio遇到播放无声时的分析

    在Android Audio开发过程中,有遇到播放ringtone时无声,但播放Music可以听到声音,关于无声问题的分析,在此做个笔记,方便以后回顾. 分析方向: 1:在音量控制面板中确认该音频流对 ...

  3. [转载]Android开发者必须深入学习的10个应用开源项目

    [转载]Android开发者必须深入学习的10个应用开源项目 原文地址:Android开发者必须深入学习的10个应用开源项目(http://blog.sina.com.cn/s/blog_7b8a63 ...

  4. Android Audio控制和MediaButton远程控制(音视频控制配合)

    使用过Android系统的朋友应该都知道,Android里面声音是区分好几种情况,每种情况下的音频大小是独立的.也就是说你调节了电话铃声大小不会影响多媒体播放的声音大小.这个涉及了AudioStrea ...

  5. [转载] Android Bander设计与实现 - 设计篇

    本文转载自: http://blog.csdn.net/chenxiancool/article/details/17454593 摘要 Binder是Android系统进程间通信(IPC)方式之一. ...

  6. [转载] Android随笔之——PackageManager详解

    本文转载自: http://www.cnblogs.com/travellife/p/3932823.html 参考:http://www.cnblogs.com/xingfuzzhd/p/33745 ...

  7. [转载] Android动态加载Dex机制解析

    本文转载自: http://blog.csdn.net/wy353208214/article/details/50859422 1.什么是类加载器? 类加载器(class loader)是 Java ...

  8. [转载] Android.Hook框架xposed开发篇

    本文转载自: http://www.52pojie.cn/thread-396793-1-1.html 原帖:http://drops.wooyun.org/tips/7488 作者:瘦蛟舞 官方教程 ...

  9. [转载] Android Studio 上第一个 Xposed 模块

    本文转载自: http://www.open-open.com/lib/view/open1451364108964.html 环境: 已root手机一枚 Android Studio一枚 官方文档参 ...

随机推荐

  1. Linux安装ftp服务-详细步骤

    最近项目中用到了FTP服务器,于是整理了一份在Linux服务器上安装FTP的详细步骤供大家分享. 1.首先连接上自己的Linux服务器.我的Linux是CentOS 6 2.检查Linux服务器上是否 ...

  2. 剑指offer-拓展训练-N皇后的问题-全排列

    /* 题目: N皇后的问题. */ /* 思路: 全排列. 声明一个具有N个元素的数组curr,每个下标i(0>i>n)代表行,每个curr[i]代表列,所以初始化为curr[i] = i ...

  3. linq to sql 比较字符串形式的时间

    where Convert.ToDateTime(t.Date.Trim()).CompareTo(Convert.ToDateTime("2009/9/9")) >= 0 ...

  4. python全栈学习 day02

    pycharm 安装设置: 按照百度百科或者官网介绍下载,安装. 激活步骤 1:改host 2.输入激活信息,注意有效期. python 逻辑运算符://返回的均为bool值 与 and A and ...

  5. 谷歌浏览器chrome应用商店无法打开的解决方法

    解决办法:谷歌访问助手 谷歌访问助手是一款免费的谷歌服务代理插件,不用配置就可以正常访问谷歌的大部分服务,而且速度也很快.下载地址:http://www.cnplugins.com/advsearch ...

  6. Java同步和异步过程中消息语言国际化处理策略

    在Java后端做消息内容的语言国际化处理时可以通过Spring中MessageSource接口的来实现,但是MessageSource接口需要用到Locale对象, 而Locale类又是根据前端传过来 ...

  7. [ERR] Node goodsleep.vip:6379 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.

    解决方案 以前的cluster节点信息 保留 要删除 dump.rdb node.conf集群启动时自动生成文件

  8. 树莓派使用Python使用PiCamera录制视频

    个人博客 地址:https://www.wenhaofan.com/article/20190430144020 代码 在树莓派环境下官方提供了乐酷 PiCamera 让我们可以很方便的操作树莓派连接 ...

  9. Android 判断APP前台,后台运行

    public void checkAppState() { ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVI ...

  10. 2017 ACM-ICPC 亚洲区(乌鲁木齐赛区)网络赛 Banana

    签到题 50的规模,随便搞搞都能过,用stl的string的搜索直接做了 #include <bits/stdc++.h> using namespace std; typedef lon ...