ALSA 中的跟踪点

2017/07/02 Takasahi Sakamoto

ALSA PCM 核心中的跟踪点

ALSA PCM 核心向内核跟踪点系统注册 snd_pcm 子系统。该子系统包含两类跟踪点:PCM 缓冲区状态和 PCM 硬件参数处理。当相应的内核配置启用时,这些跟踪点可用。当启用 CONFIG_SND_DEBUG 时,后一类跟踪点可用。如果另外启用 SND_PCM_XRUN_DEBUG,则启用前一类跟踪点。

PCM 缓冲区状态的跟踪点

此类包含四个跟踪点:hwptrapplptrxrunhw_ptr_error

PCM 硬件参数处理的跟踪点

此类包含两个跟踪点:hw_mask_paramhw_interval_param

在 ALSA PCM 核心的设计中,数据传输被抽象为 PCM 子流。应用程序管理 PCM 子流以维护 PCM 帧的数据传输。在开始数据传输之前,应用程序需要配置 PCM 子流。在此过程中,PCM 硬件参数由应用程序和 ALSA PCM 核心之间的交互决定。一旦确定,PCM 子流的运行时将保持这些参数。

这些参数在 struct snd_pcm_hw_params 中描述。此结构包含几种类型的参数。应用程序将首选值设置为这些参数,然后使用 SNDRV_PCM_IOCTL_HW_REFINE 或 SNDRV_PCM_IOCTL_HW_PARAMS 执行 ioctl(2)。前者仅用于优化可用参数集。后者用于实际确定参数。

struct snd_pcm_hw_params 结构具有以下成员

flags

可配置。ALSA PCM 核心和一些驱动程序处理此标志以选择方便的参数或更改其行为。

masks

可配置。此类参数在 struct snd_mask 中描述,并表示掩码值。截至 PCM 协议 v2.0.13,定义了三种类型。

  • SNDRV_PCM_HW_PARAM_ACCESS

  • SNDRV_PCM_HW_PARAM_FORMAT

  • SNDRV_PCM_HW_PARAM_SUBFORMAT

intervals

可配置。此类参数在 struct snd_interval 中描述,并表示具有范围的值。截至 PCM 协议 v2.0.13,定义了十二种类型。

  • SNDRV_PCM_HW_PARAM_SAMPLE_BITS

  • SNDRV_PCM_HW_PARAM_FRAME_BITS

  • SNDRV_PCM_HW_PARAM_CHANNELS

  • SNDRV_PCM_HW_PARAM_RATE

  • SNDRV_PCM_HW_PARAM_PERIOD_TIME

  • SNDRV_PCM_HW_PARAM_PERIOD_SIZE

  • SNDRV_PCM_HW_PARAM_PERIOD_BYTES

  • SNDRV_PCM_HW_PARAM_PERIODS

  • SNDRV_PCM_HW_PARAM_BUFFER_TIME

  • SNDRV_PCM_HW_PARAM_BUFFER_SIZE

  • SNDRV_PCM_HW_PARAM_BUFFER_BYTES

  • SNDRV_PCM_HW_PARAM_TICK_TIME

rmask

可配置。仅在具有 SNDRV_PCM_IOCTL_HW_REFINE 的 ioctl(2) 中进行评估。应用程序可以选择 ALSA PCM 核心可以更改哪些掩码/间隔参数。对于 SNDRV_PCM_IOCTL_HW_PARAMS,将忽略此掩码,并且将更改所有参数。

cmask

只读。从 ioctl(2) 返回后,用户空间中用于 struct snd_pcm_hw_params 的缓冲区包含每个操作的结果。此掩码表示实际更改了哪些掩码/间隔参数。

info

只读。这表示硬件/驱动程序的功能,作为带有 SNDRV_PCM_INFO_XXX 的位标志。通常,应用程序使用 SNDRV_PCM_IOCTL_HW_REFINE 执行 ioctl(2) 以检索此标志,然后确定参数的候选项并使用 SNDRV_PCM_IOCTL_HW_PARAMS 执行 ioctl(2) 以配置 PCM 子流。

msbits

只读。此值表示 PCM 样本 MSB 侧可用的位宽。当 SNDRV_PCM_HW_PARAM_SAMPLE_BITS 的参数被确定为固定数字时,也会根据它计算此值。否则,为零。但此行为取决于驱动程序端的实现。

rate_num

只读。此值表示分数表示法中采样率的分子。基本上,当 SNDRV_PCM_HW_PARAM_RATE 的参数被确定为单个值时,也会根据它计算此值。否则,为零。但此行为取决于驱动程序端的实现。

rate_den

只读。此值表示分数表示法中采样率的分母。基本上,当 SNDRV_PCM_HW_PARAM_RATE 的参数被确定为单个值时,也会根据它计算此值。否则,为零。但此行为取决于驱动程序端的实现。

fifo_size

只读。此值表示硬件串行声音接口中 FIFO 的大小。基本上,每个驱动程序都可以为该参数分配适当的值,但某些驱动程序会故意将其设置为零,并注意硬件设计或数据传输协议。

当应用程序使用 SNDRV_PCM_HW_REFINE 或 SNDRV_PCM_HW_PARAMS 执行 ioctl(2) 时,ALSA PCM 核心会处理 struct snd_pcm_hw_params 的缓冲区。缓冲区中的参数根据 struct snd_pcm_hardware 和运行时的约束规则进行更改。该结构描述了处理的硬件的功能。这些规则描述了根据几个参数确定参数的依赖关系。规则具有回调函数,驱动程序可以注册任意函数来计算目标参数。ALSA PCM 核心默认将一些规则注册到运行时。

只要驱动程序在 struct snd_pcm_ops.open 的回调中准备好两件事,每个驱动程序都可以加入交互。

  1. 在回调中,驱动程序应根据相应硬件的容量,更改运行时中 struct snd_pcm_hardware 类型的成员。

  2. 在同一个回调中,当由于硬件设计导致几个参数具有依赖关系时,驱动程序还应将其他约束规则注册到运行时。

驱动程序可以参考 struct snd_pcm_ops.hw_params 回调中的交互结果,但不应更改内容。

此类中的跟踪点旨在跟踪掩码/间隔参数的更改。当 ALSA PCM 核心更改它们时,会根据更改的参数类型探测 hw_mask_paramhw_interval_param 事件。

ALSA PCM 核心还为每个跟踪点提供了一个漂亮的打印格式。下面是 hw_mask_param 的一个示例。

hw_mask_param: pcmC0D0p 001/023 FORMAT 00000000000000000000001000000044 00000000000000000000001000000044

下面是 hw_interval_param 的一个示例。

hw_interval_param: pcmC0D0p 000/023 BUFFER_SIZE 0 0 [0 4294967295] 0 1 [0 4294967295]

前三个字段是通用的。它们依次表示 ALSA PCM 字符设备的名称、约束规则和更改的参数的名称。约束规则的字段由两个子字段组成:应用的规则的索引和添加到运行时的规则总数。作为例外,索引 000 表示参数由 ALSA PCM 核心更改,与规则无关。

其余字段表示更改前后参数的状态。这些字段根据参数的类型而不同。对于掩码类型的参数,这些字段表示参数内容的十六进制转储。对于间隔类型的参数,这些字段按此顺序表示 struct snd_interval 中 emptyintegeropenminminmaxopenmax 的每个成员的值。

驱动程序中的跟踪点

一些驱动程序具有跟踪点,以方便开发人员。对于它们,请参阅每个文档或实现。