ALSA子系统(五)------XRUN排查

你好!这里是风筝的博客,
欢迎和我一起交流。

什么是XRUN?相信做音频的童鞋都不陌生。
它是缓冲区不足或溢出,X代表不足或溢出。在这两种情况下,都表明系统速度不够快,未能及时处理来自ALSA音频缓冲区的数据,因此丢失了一些数据。当我们以非常小的缓冲区大小运行时,声卡应该非常快地处理传入缓冲区的数据,否则就溢出overrun了。有些芯片无法适应较小的缓冲区大小,因此我们必须增加缓冲区长度以减轻声音芯片的工作量。通常,xruns可以听到爆裂声或爆裂声。

在录音例子中,如果应用程序读取数据不够快,循环缓存区将会被新的数据覆盖。这种数据的丢失被称为"over run".
在回放例子中,如果应用程序写入数据到缓存区中的速度不够快,缓存区将会"饿死"。这样的错误被称为"under run"。
在ALSA文档中,有时将这两种情形统称为"XRUN"。适当地设计应用程序可以最小化XRUN并且可以从中恢复过来。

好在ALSA提供了一种通过proc记录和调试xrun的方法:
Menuconfig配置如下:

Device Drivers  --->  <*> Sound card support  --->  <*>   Advanced Linux Sound Architecture  ---> [*]   Sound Proc FS Support

Device Drivers  --->  <*> Sound card support  --->  <*>   Advanced Linux Sound Architecture  ---> [*]   Debug  --->  [*]     Enable PCM ring buffer overrun/underrun debugging

menuconfig
可能某些内核版本不一定路径完全一样,不过主要记住一个,我们配置里选上这些,目的就是为了使得CONFIG_SND_PCM_XRUN_DEBUG这个配置起效。
实现文件在:sound/core/pcm_lib.c里面:

#ifdef CONFIG_SND_PCM_XRUN_DEBUG

#define xrun_debug(substream, mask) \
                        ((substream)->pstr->xrun_debug & (mask))
#else
#define xrun_debug(substream, mask)     0
#endif

配置好之后重新编译代码,启动系统,如果出现了XRUN,会得到类似这样的打印信息:

audiocodec soc@xxxxxxxx:sound@0:XRUN:pcmC0D0p:0

/proc配置

XRUN主要要靠/proc下配置一些功能来查看信息,在:/proc/asound/card#/pcm0p/xrun_debug
将“#”替换为具体卡号(通常为0)。此proc文件可以启用各种调试工具。

 1   Basic debugging - show xruns in ksyslog interface
 2   Dump stack - dump stack for basic debugging
 4   Jiffies check - compare the position with kernel jiffies (a sort of in-kernel monotonic clock),
     show what's changed when basic debugging is enabled
 8   Dump positions on each period update call
 16  Dump positions on each hardware pointer update call
 32  Enable logging of last 10 ring buffer positions
 64  Show the last 10 ring buffer position only once (when first error situation occured)

要启用更多功能,只需对上述值求和(例如1 + 2 = 3)
一些常用到好的组合如下:

# Enable basic debugging and dump stack
# Usefull to just see, if PCM stream is stopped for a reason (usually wrong audio process timing from scheduler)
 echo 3 > /proc/asound/card0/pcm0p/xrun_debug

上面往xrun_debug写入3,也就是启用基本调试和堆栈功能(Enable basic debugging and dump stack)以及查看PCM流是否由于某种原因而停止(if PCM stream is stopped for a reason)。
还有一些常用到组合配置:

# Enable basic debugging and dump stack, check hardware pointer on the period update
 # Usefull to just see, if PCM stream is stopped for a reason (usually wrong audio process timing from scheduler)
 # And to check the values from driver
 echo 11 > /proc/asound/card0/pcm0p/xrun_debug
 # Enable basic debugging and dump stack, check hardware pointer on all updates
 # Usefull to just see, if PCM stream is stopped for a reason (usually wrong audio process timing from scheduler)
 # And to do the exact check the values from driver
 echo 27 > /proc/asound/card0/pcm0p/xrun_debug
 # Enable basic debugging, do jiffies check and enable one shot dump of last 10 ring buffer positions
 # Usefull, when the position is broken only after some of time (to reduce ksyslog messages)
 echo 101 > /proc/asound/card0/pcm0p/xrun_debug
 # Enable basic debugging, do jiffies check and dump position on each period and hardware pointer update calls
 # Usefull when the lowlevel (specific) hardware driver is somehow broken
 echo 29 > /proc/asound/card0/pcm0p/xrun_debug

不过我这里个人推荐使用:echo 53 > /proc/asound/xxx/pcm0p/xrun_debug

关于proc asoc到更多描述,可以参考我这文章:Proc asound documentation

常见原因分析

根据经验,通常有几种原因出现XRUN:

  • Linux CFS(完全公平的调度程序)
  • 具有 SCHED_FIFO 调度的高优先级线程
  • 优先级倒置
  • 长时间调度延时
  • 长时间运行到中断处理 程序
  • 长时间中断禁用
  • 电源管理
  • 安全内核

大部分情况下xrun都可以先试着调整period size和period count来解决,如果不起作用,还需要根据具体原因来具体分析。
period_size:每次传输的数据长度。值越小,时延越小,cpu占用就越高。
period_count:缓冲区period的个数。缓冲区越大,发生XRUN的机会就越少。

默认情况下,在进入XRUN状态时会停止DMA传输,直到有available空间可写入(overrun时),或者直到有数据写入(underrun时)。
但是用户空间可以通过配置silence_threshold来继续播放缓冲区的重复的音频数据或静音数据(silence_size为填充的大小),当空余空间超过silence threshold时,就hardware buffer 写入silence。
PS:偶尔的系统繁忙导致的这种状态, 重复播放原有的音频数据会显得更平滑,效果更好。

参考AOSP官网和ALSA官网:
音频延迟的促成因素
XRUN Debug

  • 4
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值