ALSA 协处理器加速 API

Jaroslav Kysela <perex@perex.cz>

概述

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

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

要求

主要要求是

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

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

  • 使用 mmap 将缓冲区暴露给用户空间

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

设计

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

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

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

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

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

状态机

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

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

直通操作 (ioctls)

所有操作都使用 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 为零,则对所有任务执行操作。

状态

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

致谢