ALSA 协处理器加速 API

Jaroslav Kysela <perex@perex.cz>

概述

需要为用户空间公开音频硬件,以加速各种任务,例如采样率转换器、压缩流解码器等。

这是对压缩 ALSA API 的 API 扩展的描述,该扩展能够处理不绑定到实时操作的“任务”,并允许操作的序列化。

要求

主要要求是

  • 用户空间多个任务的序列化,允许在没有用户空间干预的情况下进行多个操作

  • 每个操作的单独缓冲区(输入 + 输出)

  • 使用 mmap 向用户空间公开缓冲区

  • 在任务完成时向用户空间发送信号(标准轮询机制)

设计

引入新的方向 SND_COMPRESS_ACCEL 来标识直通 API。

API 扩展与主压缩 API 共享设备枚举和参数处理。所有其他实时流式 ioctl 都被禁用,并引入了一组新的任务相关 ioctl。直通设备不支持标准的 read/write/mmap I/O 操作。

设备(“流”)状态处理简化为 OPEN/SETUP。所有其他状态在直通模式下均不可用。

数据 I/O 机制使用标准的 dma-buf 接口,具有所有优点,如 mmap、标准 I/O、缓冲区共享等。一个缓冲区用于输入数据,第二个(单独的)缓冲区用于输出数据。每个任务都有单独的 I/O 缓冲区。

对于缓冲参数,片段表示给定设备分配任务的限制。fragment_size 限制给定设备的输入缓冲区大小。输出缓冲区大小由驱动程序确定(可能与输入缓冲区大小不同)。

状态机

直通音频流状态机如下所述

                                     +----------+
                                     |          |
                                     |   OPEN   |
                                     |          |
                                     +----------+
                                           |
                                           |
                                           | compr_set_params()
                                           |
                                           v
       all passthrough task ops      +----------+
+------------------------------------|          |
|                                    |   SETUP  |
|                                    |
|                                    +----------+
|                                          |
+------------------------------------------+

直通操作 (ioctl)

所有操作都使用 stream->device->lock (mutex) 进行保护。

创建

创建一组输入/输出缓冲区。输入缓冲区大小为 fragment_size。分配唯一的 seqno。

硬件驱动程序为输入和输出缓冲区分配内部 ‘struct dma_buf’(使用 ‘dma_buf_export()’ 函数)。这些缓冲区的匿名文件描述符将传递给用户空间。

释放

释放一组输入/输出缓冲区。如果任务处于活动状态,则先执行停止操作。如果 seqno 为零,则对所有任务执行操作。

开始

开始(排队)一个任务。任务启动有两种情况 - 紧随任务创建之后。在这种情况下,origin_seqno 必须为零。第二种情况是重用已经完成的任务。origin_seqno 必须标识要重用的任务。在这两种情况下,都会分配一个新的 seqno 值并返回给用户空间。

先决条件是应用程序用新的源数据填充了输入 dma 缓冲区,并将 input_size 设置为将实际数据大小传递给驱动程序。

保留数据处理的顺序(首先启动的作业必须首先完成)。

如果多个任务需要状态处理(例如,重采样操作),则用户空间可以设置 SND_COMPRESS_TFLG_NEW_STREAM 标志来标记新流数据的开始。保持为新操作分配的缓冲区,而不是使用打开/关闭机制,这很有用。

停止

停止(出列)一个任务。如果 seqno 为零,则对所有任务执行操作。

状态

获取任务状态(活动、已完成)。此外,驱动程序将设置实际输出数据大小(输出缓冲区中的有效区域)。

鸣谢