当前位置: 首页 > news >正文

Android AAudio介绍及流程分析

AAudio 是 Android 系统提供的一种高性能、低延迟的原生 C API 音频库。

源码下的使用样例及测试程序:

frameworks/av/media/libaaudio/examples/write_sine/

为什么可以做到低延时?

1.使用mmap机制减少拷贝。

在支持的硬件上,AAudio 可以进入 MMAP 模式。
在普通模式下,音频数据需要在应用层、系统音频引擎和硬件驱动之间多次拷贝。而在 MMAP 模式下,数据直接写入一个应用和硬件共享的内存区域。这种方式极大地降低了 CPU 占用和延迟。

AAudio Sharing Mode分为两种:

  • AAUDIO_SHARING_MODE_SHARED
  • AAUDIO_SHARING_MODE_EXCLUSIVE

SHARED模式为默认模式,可以支持多应用程序同时使用,多个客户端播放时会在AAudio Server中进行混音,所以会多出一个缓冲区,这种模式下拥有双重缓冲区,会增加时延。

AAudioStream_setBufferSizeInFrames和AAudioStreamBuilder_setBufferCapacityInFrames ** 主要也是针对AAudio Server中的缓冲区进行设定,capacity最大可设定为32x1024。另一个缓冲区是HAL层创建的“共享内存”。

EXCLUSIVE模式只有一个缓冲区,即HAL层创建的"共享内存",capacity size和burst size是由HAL来决定,但buffer size依然是由上层设定。

2.减小buffer size,降低延时。在确保不发生underrun的情况下,尽量使用最小buffer size。

AAudioStream_getFramesPerBurst每次消耗的数据大小。

AAudioStream_setBufferSizeInFramesringbuffer size,由应用层设置,一般要为burst frames的整数倍,默认是2倍。可以在播放过程中动态调整。

AAudioStreamBuilder_setBufferCapacityInFramesringbuffer size最大限制,由应用层设置,动态调整buffer size时不能超过这个值。

buffer size较小的时候,cpu稍微抖动就会发生underrun出现断音,闲置情况单独使用write_sine播放,使用512的buffer size,不会发生断音,此时延时也最低。


3.使用实时高优先级回调线程取数据

AAudio数据传输有两种模式:

  • Read/Write同步模式
  • callback回调异步模式

write_sine对应的是同步模式,线程优先级低,所以很容易被cpu抖动产生影响,其它进程有操作时,断音明显。

write_sine_callback 对于的是回调模式,AAudio 会在一个专门的高优先级线程中自动调用它,优先级极高且由系统调度,不容易受应用主线程或其他繁忙任务的影响。

分别对比同步模式和异步模式两种情况下线程的状态:

1|RTD1325A16:/ # ps -T -p 5973 -o USER,PID,TID,PRI,RTPRIO,SCHED,PCY,CMD USER PID TID PRI RTPRIO SCH PCY CMD root 5973 5973 19 - 0 fg write_sine_call root 5973 5974 19 - 0 fg binder:5973_1 root 5973 5975 19 - 0 fg binder:5973_2 root 5973 5982 42 2 1 fg AAudio_1 RTD1325A16:/ # ps -T -p 3467 -o USER,PID,TID,PRI,RTPRIO,SCHED,PCY,CMD USER PID TID PRI RTPRIO SCH PCY CMD root 3467 3467 19 - 0 fg write_sine root 3467 3468 19 - 0 fg binder:3467_1 root 3467 3469 19 - 0 fg binder:3467_2

可以看到回调模式下,会多出一个AAudio创建的线程,其优先级(PRI)更高,并且属于实时线程(RTPRIO),调度模式(SCH)为FIFO,普通线程调度模式为NORMAL。

如何配置audio_policy_configuration.xml

<mixPort name="mmap_no_irq_out" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT AUDIO_OUTPUT_FLAG_MMAP_NOIRQ" >
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
samplingRates="44100 48000"
channelMasks="AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_5POINT1"/>
</mixPort>

A good blog for reference.

AA​​​​​​​【Android Audio】AAudio 架构讲解以及实现范例 (附带visio流程图)_aaudio demo-CSDN博客

open流程

shared模式流程会复用exclusive mode,如果只是exclusive mode,会跳过2-10步。

1 Aaudiostreambuilder_openstream 2 AudioStreamInternalPlay::open 这部分 AudioStreamInternalPlay 运行在client进程下。share mode 为AAUDIO_SHARING_MODE_SHARED 3 AudioStreamInternal::open 4 AAudioService::openStream 5 AAudioServiceStreamShared::open 6 AAudioServiceStreamBase::open 7 AAudioEndpointManager::openEndpoint 8 AAudioEndpointManager::openSharedEndpoint 9 AAudioServiceEndpointPlay::open && AAudioMixer::allocate,这里创建第一个缓冲区,同时在构造方法中,创建 AAudioServiceEndpointShared,将 AudioStreamInternalPlay 作为参数传入。 10 AAudioServiceEndpointShared::open 将share mode设置为 AAUDIO_SHARING_MODE_EXCLUSIVE ,再次打开 AudioStreamInternalPlay。 11 AudioStreamInternalPlay::open 此时 AudioStreamInternalPlay 运行在service进程下,share mode 为 AAUDIO_SHARING_MODE_EXCLUSIVE 12 AudioStreamInternal::open 13 AAudioService::openStream 14 AAudioServiceStreamMMAP::open 15 AAudioServiceStreamBase::open 16 AAudioEndpointManager::openEndpoint 17 AAudioEndpointManager::openExclusiveEndpoint 18 AAudioServiceEndpointMMAP::open 19 AAudioServiceEndpointMMAP::openWithConfig 20 MmapStreamInterface::openMmapStream 21 AudioFlinger::openMmapStream && MmapStreamInterface::createMmapBuffer 这里最终到HAL层创建第二个缓冲区

start 流程

与open流程类似,需要注意的是它会在aaudio service中会创建一个混音线程。 AAudioServiceEndpointShared::startStream 第一个请求 sartStream 的时候,创建混音线程 AAudioServiceEndpointShared::startSharingThread_l


write 流程

AAudioStream_write() AudioStreamInternalPlay::write AudioStreamInternalPlay::processDataNow AAudioFlowGraph::process() 写入第一个缓冲区 FIFO RingBuffer AAudioServiceEndpointPlay::callbackLoop 唤起混音线程,处理所有客户端传过来的buffer AAudioMixer::mix AAudioServiceEndpointShared::write AudioStreamInternalPlay::processDataNow AAudioFlowGraph::process() 写入第二个缓冲区,HAL创建的共享缓冲区
http://www.jsqmd.com/news/1306019/

相关文章:

  • C语言printf中%g格式符的深度解析与实战应用
  • 2026年广东压缩海棉源头工厂排行榜:揭秘跨境出海隐形冠军 - 变量人生001
  • 程序员兼职平台全解析:从新手到数字游民的实战指南
  • 5分钟快速修复:RDP Wrapper终极指南解决Windows远程桌面不支持问题
  • 终极美化指南:TranslucentTB让你的Windows任务栏轻松实现透明化
  • 2026椒江思维课机构综合解析:代表性品牌梳理,助力家长科学选择 - 汇聚至此
  • Unity VFX Graph系统架构:从粒子流水线到复杂特效的模块化设计
  • GetQzonehistory终极指南:3步快速备份QQ空间所有历史记录
  • DXVK终极指南:快速解决Intel显卡驱动冲突的3个完整方案
  • 常州水电维修怎么找正规平台?资质报价验收三步筛选(2026) - 家修助手
  • PMP报名入口和培训机构怎么找? - 众智商学院官方
  • G-Helper:华硕笔记本轻量级控制解决方案的技术深度解析
  • 直线拟合三大核心方法:最小二乘法、梯度下降与高斯-牛顿法详解
  • uninstall Oceanbase [ rpm -e oceanbase]
  • C++ switch-case编译错误解析:jump to case label的根源与解决方案
  • DeepSeek V4 Flash 0731 正式版实测:20轮小说、Responses Agent 与四档思考
  • 2026年广东包装内衬海绵OEM工厂推荐:选兴顺兴的三大硬核理由 - 变量人生001
  • 2026年植物支撑杆厂家推荐榜单:花架支撑杆/蔬菜爬藤架/包塑钢管支撑杆,番茄黄瓜豆角葡萄月季通用,稳固防腐户外庭院阳台优选 - 优企名品
  • 阅读笔记:Ocean-OCR:Towards General OCR Application via a Vision-Language Model
  • 番禺家装量身定制怎么选
  • 5分钟快速找回QQ空间全部历史说说的完整指南:GetQzonehistory让青春记忆永不丢失
  • 2026年嘉兴市新时代包装彩印有限公司绿色环保印刷全景白皮书 - 招财兔数字员工
  • 2026年成都代理记账费用是怎样的,受哪些因素影响? - 企业推荐官
  • PotPlayer字幕翻译插件:5分钟实现免费双语观影体验
  • 深入理解javac:从命令行编译到Java项目构建的核心原理与实践
  • Clean disk C
  • 身边同学都拿到大厂 Offer 焦虑爆棚?用信息屏蔽与自我节奏破局「蒸汽求职分享」
  • 深耕青岛本地防水修缮,匠心解决各类建筑渗漏难题 - 国麟测评
  • 娄底市屋顶漏水维修_2026湖南中部湘中明珠漏水维修价格行情与哪家好 - 雨婺虹房屋维修
  • 2026年阿克苏地区AIGC应用工程师怎么报名?中山优才教育报考指南 - 人工智能报名机构推荐