音频出现Xrun(underrun或overrun)的原因与解决办法

【现象】

    音频文件在播放时出现断断续续或类似“爆破”(Pop-Click)杂音的现象,称之为 Xrun(可以是 underrun,也可以是 overrun)。


【相关实例】

    《记一次Android系统下解决音频UnderRun问题的过程》


【原因】

    通常来说,出现 Xrun 问题时原因可能是以下几个之一:

    (1) Linux CFS 调度器导致。因为 CFS 调度器的“公平调度”是较长一段时间的平均表现,在很短的一个窗口时间段内,CFS 也可能会将 CPU 时间片完全分配给一个 nice 值更高的线程而不顾及另一个 nice 值更低的线程。如果这个低 nice 值的线程恰好是音频相关的,就会导致 Xrun 问题。

    (2) 更高优先级的 SCHED_FIFO 线程调度。除了音频线程以外,其它线程也可以使用 SCHED_FIFO 标记,如果这个其它线程的优先级高于音频线程,那么它会被优先调度。这样也会导致 Xrun 问题。

    (3) 优先级反转。所谓的优先级反转是指一个更高优先级的线程需要使用另一个更低优先级线程所持有的资源,而不得不等待低优先级线程在使用完毕后将资源释放掉。如果音频线程恰好是这个高优先级线程,此时也将导致 Xrun 问题。

    (4) 过长的调度延时。

    (5) 顶半部中断处理程序执行时间过长。

    (6) 禁用中断时间过长。

    (7) 电源管理。内核会对芯片的工作电源进行适时地控制以免芯片温度过高而烧毁,这些管理策略可能会暂时挂起芯片中正在进行的工作。如果音频相关的任务因此被挂起,那么就会出现 Xrun 问题。

    (8) 内核安全策略原因。


【解决办法】

    最好的解决办法当然是分析出 Xrun 的问题到底是上面哪个原因导致的,然后对症下药的改动相应的代码以修复问题。但并不是所有人都对内核各部分了如指掌能精确定位到问题代码的位置(我承认至少我还没有那个水平),所以这里有一个类似万金油的办法:增加音频数据的 buffer 大小或 buffer 数量来进行补偿。但这样也会使音频播放/录音的 数据准备时间变长,也就是说会增加音频操作的延迟,算是这种方法的一个副作用。


【参考资料】

    [1] 《Contributors to Audio Latency》(Google站点,需要才能阅读)



你可能感兴趣的:(嵌入式,Linux,Android)