Android audio中的AUDIO_OUTPUT_FLAG_NON_BLOCKING

什么是AUDIO_OUTPUT_FLAG_NON_BLOCKING

如字面意思,非阻塞式写入,在以下文件中也有相关定义。

AudioOutputFlags.aidl

/**

* Write operations must return as fast as possible instead of

* being blocked until all provided data has been consumed.

*/

NON_BLOCKING = 5,

平时通过alsa调用pcm_write一般都采用的是阻塞式。但在Offload模式下,通常需要使用非阻塞式。

为什么需要非阻塞式:

1. 延长 CPU 睡眠时间

这是大缓冲区最主要的原因。
普通模式(PCM) :缓冲区通常很小(比如 20ms~40ms)。这意味着 CPU 每隔几十毫秒就必须醒来一次,往缓冲区里填数据。CPU 频繁地在"工作"和"睡眠"之间切换,无法进入深度的省电状态(Deep Sleep States)。
Offload 模式 :通过使用非常大的缓冲区(通常可以容纳 1秒到数秒 的音频数据),CPU 可以一次性把大量的压缩数据(如 MP3, AAC)"推"给 DSP。

结果:数据推完后,CPU 就可以彻底"躺平"睡大觉。在接下来的 2 秒钟里,CPU 都不需要处理音频,只有低功耗的 DSP 在工作。这种长周期的睡眠能显著降低功耗。

2. 压缩数据的高效率

压缩音频数据的"密度"比原始 PCM 数据大得多。

同样的 128KB 空间:

* 如果存 PCM(44.1kHz, 16bit, 双声道),只能支撑约 0.7 秒。

* 如果存 MP3(128kbps 比特率),可以支撑约 8 秒。

因为 Offload 传输的是压缩数据,大缓冲区配合高压缩比,使得 CPU 每次"醒来"填满缓冲区后,获得的"收益"(播放时长)极大,数据需要消耗的时间也相当长,如果一直阻塞等待消耗完,十分浪费CPU资源。

如何实现非阻塞式:

1.配置文件

在AudioPolicyConfiguration.xml中Offload模式下(AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)同时配置AUDIO_OUTPUT_FLAG_NON_BLOCKING.

2.flag检测

在audio HAL层检测flag是否包含AUDIO_OUTPUT_FLAG_NON_BLOCKING,如若包含,创建对应的StreamOut,并且保存回调函数接口(callback)

3.修改write()

在write函数下实现非阻塞写入:如果有空间,写入数据,返回写入字节数。如果没空间,立即返回-EAGAIN 或 0,不要调用 `usleep` 或等待信号量。

4. 异步回调:

HAL 内部维护一个线程处理实际的硬件写入。当硬件消费了数据,空出缓冲区时,调用 `IStreamOutCallback->onWriteReady()`。当 AudioFlinger 层收到 `onWriteReady` 回调时,`AudioFlinger::PlaybackThread` 或`AudioFlinger::OffloadThread` 会被唤醒。它会重新调用 `mStream->write()`。

非阻塞模式通常还伴随着 `drain()` 操作。当数据写完时,Framework 会调用 `drain(AUDIO_DRAIN_ALL)`。HAL 在硬件播放完成后,需要回调 `IStreamOutCallback->onDrainReady()`。

其它要点:

pause与resume

状态同步:当调用 `pause` 时,HAL 应该立即停止向硬件推送数据,但不能丢弃已在硬件缓冲区中的数据。

Resume 的瞬时性:调用 `resume` 后,硬件应立即从暂停的位置恢复播放。

在非阻塞模式下,`pause` 之后不应触发数据请求回调。如果正在进行 `drain` 操作时执行 `pause`,`drain` 的完成回调通常会被挂起,直到 `resume`。

drain

这是非阻塞模式下最复杂的操作。它的目的是确保所有已写入缓冲区的音频数据都被完整播放。

异步特性:在非阻塞模式下,`drain()` 操作必须是非阻塞的。HAL 接收到指令后开始播放剩余数据,并在播放完成后发送 `AUDIO_DRAIN_READY` 回调。

类型:

`DRAIN_ALL`: 等待所有数据播放完。

`DRAIN_EARLY_NOTIFY`: 在数据接近播放完时提前通知(常用于下一曲等无缝切换)。

在 `drain` 过程中,如果收到 `flush` 或 `stop` 指令,必须取消 `drain` 等待。

在 `drain` 完成前,不要关闭 Stream。

测试验证

在应用层快速写入大量数据,检验是否立即返回,返回写入数据长度或0

相关推荐
东莞市奥普新音频技术有限公司1 天前
国产音频分析仪怎么选?从性能参数、测试软件到自动化能力
人工智能·科技·测试工具·自动化·音视频·音频
k4m7v2pz2 天前
ESP32-S3 + I2S 麦克风实时音频流静音问题排查:从网络到AGC的谬误溯源
rust·音频·esp32·agc·实时监听·静音排查
~央千澈~12 天前
从“拟声”到“生成”:AI音效背后的技术原理·优雅草AI音乐·AI音乐技术研究
大数据·人工智能·ai·音频
我是海飞13 天前
杰理JL703N SSD1306 OLED(128x64) 点阵屏移植说明
单片机·算法·嵌入式·音频·杰理
林澈在路上17 天前
可以用自己声音写歌的软件哪款好用 实测对比
大数据·人工智能·aigc·音视频·音频
鲟迹18 天前
测量不同平台UAC RMS曲线的方法
音视频·音频
提升汽车音响好物19 天前
2026广州新能源汽车蔚来ES8音响升级施工记录:多单元系统如何重新安排车内声场
汽车·音频
林澈在路上22 天前
2026 主流 AI 写歌 APP 全面测评|零基础原创歌曲工具选购指南
大数据·人工智能·aigc·音视频·音频
哦***723 天前
鸿蒙小知识 | 华为耳机双击没法暂停音乐?
华为·音频·harmonyos
星核0penstarry25 天前
从 Dialog-RSN-1 看语音 Agent 走向:企业如何评估音频原生模型与 API 服务
人工智能·音视频·音频·api