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

相关推荐
zxy28472253017 小时前
C# 音频倍速播放
c#·音频·naudio·soundtouch·倍速
林澈在路上17 小时前
能做DJ的AI写歌软件推荐:MELO音乐对比Suno v6
大数据·人工智能·github·音视频·音频
提升汽车音响好物3 天前
斯巴鲁森林人音响升级记录:江门汇声的前后声场与低频搭配
汽车·音频
沐禾安信8 天前
抖音的bgm 想保存? 3个音频提取工具,一键分离
音视频·音频·音频转换·视频转换
A133455512 天前
Apple TV 软件推荐:全平台怎么选
android·音频
林澈在路上16 天前
AI翻唱软件哪个好 2026国产AI写歌工具对比推荐
大数据·人工智能·深度学习·github·aigc·音视频·音频
提升汽车音响好物18 天前
宝马音响升级怎么做?东莞虎门杰之声 采用FOCAL 劲浪专车专用进行汽车音响升级
汽车·音频
liuyunshengsir20 天前
基于海光DCU的AI音乐翻唱全流程落地实战
人工智能·大模型·音频·dcu
林澈在路上21 天前
AI做歌用哪个最好 2026国产AI音乐工具评测
大数据·人工智能·aigc·音视频·音频
东莞市奥普新音频技术有限公司22 天前
国产音频分析仪怎么选?从性能参数、测试软件到自动化能力
人工智能·科技·测试工具·自动化·音视频·音频