XRUN是缓冲区不足或溢出,X代表不足或溢出。在这两种情况下,都表明系统速度不够快,未能及时处理来自ALSA音频缓冲区的数据,因此丢失了一些数据。当我们以非常小的缓冲区大小运行时,声卡应该非常快地处理传入缓冲区的数据,否则就溢出overrun了。有些芯片无法适应较小的缓冲区大小,因此我们必须增加缓冲区长度以减轻声音芯片的工作量。通常,xruns可以听到爆裂声或爆裂声。
在录音例子中,如果应用程序读取数据不够快,循环缓存区将会被新的数据覆盖。这种数据的丢失被称为"over run" 在回放例子中,如果应用程序写入数据到缓存区中的速度不够快,缓存区将会"饿死"。这样的错误被称为"under run"
/Proc
ALSA提供了一种通过proc记录和调试xrun的方法:
1 | Device Drivers ---> <*> Sound card support ---> <*> Advanced Linux Sound Architecture ---> [*] Sound Proc FS Support |
/proc/asound/card#/pcm0p/xrun_debug
将“#”替换为card number。该proc文件可以启用各种调试工具。必须在内核中启用 CONFIG_SND_PCM_XRUN_DEBUG、CONFIG_SND_VERBOSE_PROCFS、CONFIG_SND_DEBUG 选项(如果 xrun_debug proc 文件存在 - 该功能已启用)
1 | 1 Basic debugging - show xruns in ksyslog interface |
To enable more features just do sum values of above (for example 1+2=3).
Some good value combinations:
1 | # Enable basic debugging and dump stack |
1 | # Enable basic debugging and dump stack, check hardware pointer on the period update |
1 | # Enable basic debugging and dump stack, check hardware pointer on all updates |
1 | # Enable basic debugging, do jiffies check and enable one shot dump of last 10 ring buffer positions |
1 | # Enable basic debugging, do jiffies check and dump position on each period and hardware pointer update calls |
默认情况下,在进入XRUN状态时会停止DMA传输,直到有available空间可写入(overrun时),或者直到有数据写入(underrun时)。 但是用户空间可以通过配置silence_threshold来继续播放缓冲区的重复的音频数据或静音数据(silence_size为填充的大小),当空余空间超过silence threshold时,就hardware buffer 写入silence。
常见原因
- Linux CFS(完全公平的调度程序)
- 具有 SCHED_FIFO 调度的高优先级线程
- 优先级倒置
- 长时间调度延迟
- 长时间运行的中断处理程序
- 长时间中断禁用
- 电源管理
- 安全内核
参考文献
https://source.android.com/docs/core/audio/latency/contrib?hl=zh-cn
https://www.alsa-project.org/wiki/XRUN_Debug