← Documents Documentation/sound/designs/compress-offload.rst GitHub 원문 ↗

Linux 6.18.37 · Sound

ALSA Compress-Offload API

가변 compressed audio를 DSP에 offload하는 ALSA API의 capability·parameter·timestamp routine, stream 상태 머신, gapless metadata와 미지원 범위를 설명합니다.

Source pathDocumentation/sound/designs/compress-offload.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약·해설

compress-offload.rst:1-329

가변 compressed audio를 DSP에 offload하는 ALSA API의 capability·parameter·timestamp routine, stream 상태 머신, gapless metadata와 미지원 범위를 설명합니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 =========================
2 ALSA Compress-Offload API
3 =========================
4
5 Pierre-Louis.Bossart <pierre-louis.bossart@linux.intel.com>
6
7 Vinod Koul <vinod.koul@linux.intel.com>
8
9
10 Overview
11 ========
12 Since its early days, the ALSA API was defined with PCM support or
13 constant bitrates payloads such as IEC61937 in mind. Arguments and
14 returned values in frames are the norm, making it a challenge to
15 extend the existing API to compressed data streams.
16
17 In recent years, audio digital signal processors (DSP) were integrated
18 in system-on-chip designs, and DSPs are also integrated in audio
19 codecs. Processing compressed data on such DSPs results in a dramatic
20 reduction of power consumption compared to host-based
21 processing. Support for such hardware has not been very good in Linux,
22 mostly because of a lack of a generic API available in the mainline
23 kernel.
24
25 Rather than requiring a compatibility break with an API change of the
26 ALSA PCM interface, a new 'Compressed Data' API is introduced to
27 provide a control and data-streaming interface for audio DSPs.
28
29 The design of this API was inspired by the 2-year experience with the
30 Intel Moorestown SOC, with many corrections required to upstream the
31 API in the mainline kernel instead of the staging tree and make it
32 usable by others.
33
34
35 Requirements
36 ============
37 The main requirements are:
38
39 - separation between byte counts and time. Compressed formats may have
40 a header per file, per frame, or no header at all. The payload size
41 may vary from frame-to-frame. As a result, it is not possible to
42 estimate reliably the duration of audio buffers when handling
43 compressed data. Dedicated mechanisms are required to allow for
44 reliable audio-video synchronization, which requires precise
45 reporting of the number of samples rendered at any given time.
46
47 - Handling of multiple formats. PCM data only requires a specification
48 of the sampling rate, number of channels and bits per sample. In
49 contrast, compressed data comes in a variety of formats. Audio DSPs
50 may also provide support for a limited number of audio encoders and
51 decoders embedded in firmware, or may support more choices through
52 dynamic download of libraries.
53
54 - Focus on main formats. This API provides support for the most
55 popular formats used for audio and video capture and playback. It is
56 likely that as audio compression technology advances, new formats
57 will be added.
58
59 - Handling of multiple configurations. Even for a given format like
60 AAC, some implementations may support AAC multichannel but HE-AAC
61 stereo. Likewise WMA10 level M3 may require too much memory and cpu
62 cycles. The new API needs to provide a generic way of listing these
63 formats.
64
65 - Rendering/Grabbing only. This API does not provide any means of
66 hardware acceleration, where PCM samples are provided back to
67 user-space for additional processing. This API focuses instead on
68 streaming compressed data to a DSP, with the assumption that the
69 decoded samples are routed to a physical output or logical back-end.
70
71 - Complexity hiding. Existing user-space multimedia frameworks all
72 have existing enums/structures for each compressed format. This new
73 API assumes the existence of a platform-specific compatibility layer
74 to expose, translate and make use of the capabilities of the audio
75 DSP, eg. Android HAL or PulseAudio sinks. By construction, regular
76 applications are not supposed to make use of this API.
77
78
79 Design
80 ======
81 The new API shares a number of concepts with the PCM API for flow
82 control. Start, pause, resume, drain and stop commands have the same
83 semantics no matter what the content is.
84
85 The concept of memory ring buffer divided in a set of fragments is
86 borrowed from the ALSA PCM API. However, only sizes in bytes can be
87 specified.
88
89 Seeks/trick modes are assumed to be handled by the host.
90
91 The notion of rewinds/forwards is not supported. Data committed to the
92 ring buffer cannot be invalidated, except when dropping all buffers.
93
94 The Compressed Data API does not make any assumptions on how the data
95 is transmitted to the audio DSP. DMA transfers from main memory to an
96 embedded audio cluster or to a SPI interface for external DSPs are
97 possible. As in the ALSA PCM case, a core set of routines is exposed;
98 each driver implementer will have to write support for a set of
99 mandatory routines and possibly make use of optional ones.
100
101 The main additions are
102
103 get_caps
104 This routine returns the list of audio formats supported. Querying the
105 codecs on a capture stream will return encoders, decoders will be
106 listed for playback streams.
107
108 get_codec_caps
109 For each codec, this routine returns a list of
110 capabilities. The intent is to make sure all the capabilities
111 correspond to valid settings, and to minimize the risks of
112 configuration failures. For example, for a complex codec such as AAC,
113 the number of channels supported may depend on a specific profile. If
114 the capabilities were exposed with a single descriptor, it may happen
115 that a specific combination of profiles/channels/formats may not be
116 supported. Likewise, embedded DSPs have limited memory and cpu cycles,
117 it is likely that some implementations make the list of capabilities
118 dynamic and dependent on existing workloads. In addition to codec
119 settings, this routine returns the minimum buffer size handled by the
120 implementation. This information can be a function of the DMA buffer
121 sizes, the number of bytes required to synchronize, etc, and can be
122 used by userspace to define how much needs to be written in the ring
123 buffer before playback can start.
124
125 set_params
126 This routine sets the configuration chosen for a specific codec. The
127 most important field in the parameters is the codec type; in most
128 cases decoders will ignore other fields, while encoders will strictly
129 comply to the settings
130
131 get_params
132 This routines returns the actual settings used by the DSP. Changes to
133 the settings should remain the exception.
134
135 get_timestamp
136 The timestamp becomes a multiple field structure. It lists the number
137 of bytes transferred, the number of samples processed and the number
138 of samples rendered/grabbed. All these values can be used to determine
139 the average bitrate, figure out if the ring buffer needs to be
140 refilled or the delay due to decoding/encoding/io on the DSP.
141
142 Note that the list of codecs/profiles/modes was derived from the
143 OpenMAX AL specification instead of reinventing the wheel.
144 Modifications include:
145 - Addition of FLAC and IEC formats
146 - Merge of encoder/decoder capabilities
147 - Profiles/modes listed as bitmasks to make descriptors more compact
148 - Addition of set_params for decoders (missing in OpenMAX AL)
149 - Addition of AMR/AMR-WB encoding modes (missing in OpenMAX AL)
150 - Addition of format information for WMA
151 - Addition of encoding options when required (derived from OpenMAX IL)
152 - Addition of rateControlSupported (missing in OpenMAX AL)
153
154 State Machine
155 =============
156
157 The compressed audio stream state machine is described below ::
158
159 +----------+
160 | |
161 | OPEN |
162 | |
163 +----------+
164 |
165 |
166 | compr_set_params()
167 |
168 v
169 compr_free() +----------+
170 +------------------------------------| |
171 | | SETUP |
172 | +-------------------------| |<-------------------------+
173 | | compr_write() +----------+ |
174 | | ^ |
175 | | | compr_drain_notify() |
176 | | | or |
177 | | | compr_stop() |
178 | | | |
179 | | +----------+ |
180 | | | | |
181 | | | DRAIN | |
182 | | | | |
183 | | +----------+ |
184 | | ^ |
185 | | | |
186 | | | compr_drain() |
187 | | | |
188 | v | |
189 | +----------+ +----------+ |
190 | | | compr_start() | | compr_stop() |
191 | | PREPARE |------------------->| RUNNING |--------------------------+
192 | | | | | |
193 | +----------+ +----------+ |
194 | | | ^ |
195 | |compr_free() | | |
196 | | compr_pause() | | compr_resume() |
197 | | | | |
198 | v v | |
199 | +----------+ +----------+ |
200 | | | | | compr_stop() |
201 +--->| FREE | | PAUSE |---------------------------+
202 | | | |
203 +----------+ +----------+
204
205
206 Gapless Playback
207 ================
208 When playing thru an album, the decoders have the ability to skip the encoder
209 delay and padding and directly move from one track content to another. The end
210 user can perceive this as gapless playback as we don't have silence while
211 switching from one track to another
212
213 Also, there might be low-intensity noises due to encoding. Perfect gapless is
214 difficult to reach with all types of compressed data, but works fine with most
215 music content. The decoder needs to know the encoder delay and encoder padding.
216 So we need to pass this to DSP. This metadata is extracted from ID3/MP4 headers
217 and are not present by default in the bitstream, hence the need for a new
218 interface to pass this information to the DSP. Also DSP and userspace needs to
219 switch from one track to another and start using data for second track.
220
221 The main additions are:
222
223 set_metadata
224 This routine sets the encoder delay and encoder padding. This can be used by
225 decoder to strip the silence. This needs to be set before the data in the track
226 is written.
227
228 set_next_track
229 This routine tells DSP that metadata and write operation sent after this would
230 correspond to subsequent track
231
232 partial drain
233 This is called when end of file is reached. The userspace can inform DSP that
234 EOF is reached and now DSP can start skipping padding delay. Also next write
235 data would belong to next track
236
237 Sequence flow for gapless would be:
238 - Open
239 - Get caps / codec caps
240 - Set params
241 - Set metadata of the first track
242 - Fill data of the first track
243 - Trigger start
244 - User-space finished sending all,
245 - Indicate next track data by sending set_next_track
246 - Set metadata of the next track
247 - then call partial_drain to flush most of buffer in DSP
248 - Fill data of the next track
249 - DSP switches to second track
250
251 (note: order for partial_drain and write for next track can be reversed as well)
252
253 Gapless Playback SM
254 ===================
255
256 For Gapless, we move from running state to partial drain and back, along
257 with setting of meta_data and signalling for next track ::
258
259
260 +----------+
261 compr_drain_notify() | |
262 +------------------------>| RUNNING |
263 | | |
264 | +----------+
265 | |
266 | |
267 | | compr_next_track()
268 | |
269 | V
270 | +----------+
271 | compr_set_params() | |
272 | +-----------|NEXT_TRACK|
273 | | | |
274 | | +--+-------+
275 | | | |
276 | +--------------+ |
277 | |
278 | | compr_partial_drain()
279 | |
280 | V
281 | +----------+
282 | | |
283 +------------------------ | PARTIAL_ |
284 | DRAIN |
285 +----------+
286
287 Not supported
288 =============
289 - Support for VoIP/circuit-switched calls is not the target of this
290 API. Support for dynamic bit-rate changes would require a tight
291 coupling between the DSP and the host stack, limiting power savings.
292
293 - Packet-loss concealment is not supported. This would require an
294 additional interface to let the decoder synthesize data when frames
295 are lost during transmission. This may be added in the future.
296
297 - Volume control/routing is not handled by this API. Devices exposing a
298 compressed data interface will be considered as regular ALSA devices;
299 volume changes and routing information will be provided with regular
300 ALSA kcontrols.
301
302 - Embedded audio effects. Such effects should be enabled in the same
303 manner, no matter if the input was PCM or compressed.
304
305 - multichannel IEC encoding. Unclear if this is required.
306
307 - Encoding/decoding acceleration is not supported as mentioned
308 above. It is possible to route the output of a decoder to a capture
309 stream, or even implement transcoding capabilities. This routing
310 would be enabled with ALSA kcontrols.
311
312 - Audio policy/resource management. This API does not provide any
313 hooks to query the utilization of the audio DSP, nor any preemption
314 mechanisms.
315
316 - No notion of underrun/overrun. Since the bytes written are compressed
317 in nature and data written/read doesn't translate directly to
318 rendered output in time, this does not deal with underrun/overrun and
319 maybe dealt in user-library
320
321
322 Credits
323 =======
324 - Mark Brown and Liam Girdwood for discussions on the need for this API
325 - Harsha Priya for her work on intel_sst compressed API
326 - Rakesh Ughreja for valuable feedback
327 - Sing Nallasellan, Sikkandar Madar and Prasanna Samaga for
328 demonstrating and quantifying the benefits of audio offload on a
329 real platform.
330

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

배경과 Compressed Data API

1-32

저자는 Pierre-Louis Bossart(`pierre-louis.bossart@linux.intel.com`)와 Vinod Koul(`vinod.koul@linux.intel.com`)이다.

초기 ALSA API는 PCM이나 IEC61937 같은 고정 bitrate payload를 염두에 두고 정의됐다. 인수와 반환값을 frame 단위로 표현하는 것이 일반적이어서 기존 API를 compressed data stream으로 확장하기 어려웠다.

최근에는 audio DSP가 SoC와 audio codec에 통합됐다. Compressed data를 이런 DSP에서 처리하면 host에서 처리할 때보다 전력 소비를 크게 줄일 수 있지만, mainline kernel에 범용 API가 없어 Linux 지원은 충분하지 못했다.

ALSA PCM interface를 변경해 호환성을 깨는 대신, audio DSP를 제어하고 data를 streaming하는 새 `Compressed Data` API를 도입한다. 이 설계는 Intel Moorestown SoC에서 2년간 쌓은 경험을 바탕으로 하며 staging tree가 아닌 mainline에 올리고 다른 플랫폼도 사용할 수 있도록 많은 수정을 거쳤다.

Compressed Data API 도입 배경
PCM·고정 bitrate 중심 ALSA가변 compressed stream 표현 곤란PCM ABI 호환성 유지별도 Compressed Data APIaudio DSP에서 저전력 처리

기존 frame 중심 PCM ABI를 유지하면서 DSP offload 경로를 추가한다.

=========================
ALSA Compress-Offload API
=========================

Pierre-Louis.Bossart <pierre-louis.bossart@linux.intel.com>

Vinod Koul <vinod.koul@linux.intel.com>


Overview
========
Since its early days, the ALSA API was defined with PCM support or
constant bitrates payloads such as IEC61937 in mind. Arguments and
returned values in frames are the norm, making it a challenge to
extend the existing API to compressed data streams.

In recent years, audio digital signal processors (DSP) were integrated
in system-on-chip designs, and DSPs are also integrated in audio
codecs. Processing compressed data on such DSPs results in a dramatic
reduction of power consumption compared to host-based
processing. Support for such hardware has not been very good in Linux,
mostly because of a lack of a generic API available in the mainline
kernel.

Rather than requiring a compatibility break with an API change of the
ALSA PCM interface, a new 'Compressed Data' API is introduced to
provide a control and data-streaming interface for audio DSPs.

The design of this API was inspired by the 2-year experience with the
Intel Moorestown SOC, with many corrections required to upstream the
API in the mainline kernel instead of the staging tree and make it
usable by others.

API 요구사항과 적용 범위

33-77

Compressed format은 파일마다, frame마다 header가 있거나 header가 전혀 없을 수 있고 payload 크기도 frame마다 달라질 수 있다. 따라서 byte 수만으로 audio buffer 재생 시간을 신뢰성 있게 계산할 수 없다. 정확한 audio-video 동기화를 위해서는 특정 시점까지 실제로 render한 sample 수를 정밀하게 보고하는 별도 mechanism이 필요하다.

PCM은 sampling rate, channel 수, sample당 bit 수만 지정하면 되지만 compressed data에는 다양한 format과 설정이 있다. Audio DSP firmware가 일부 encoder·decoder만 내장할 수도 있고 library를 동적으로 내려받아 더 많은 선택지를 제공할 수도 있다. API는 capture와 playback에서 널리 쓰이는 주요 audio·video format을 우선 지원하며 기술 발전에 따라 새 format을 추가할 수 있어야 한다.

같은 format 안에서도 지원 조합이 다를 수 있다. 예를 들어 한 구현이 AAC multichannel은 지원하지만 HE-AAC는 stereo만 지원할 수 있고, WMA10 level M3는 memory와 CPU cycle을 너무 많이 요구할 수 있다. API는 이런 format과 configuration의 유효한 조합을 일반적인 방식으로 열거해야 한다.

이 API는 rendering/grabbing에 집중한다. Decode한 PCM sample을 추가 처리용으로 사용자 공간에 돌려주는 hardware acceleration interface가 아니다. Compressed data를 DSP로 보내고 decode 결과를 물리 출력 또는 논리 back-end로 route한다고 가정한다.

사용자 공간 multimedia framework는 이미 각 compressed format의 enum과 structure를 갖고 있다. 새 API는 Android HAL이나 PulseAudio sink 같은 플랫폼별 compatibility layer가 DSP capability를 노출·변환·사용한다고 가정한다. 일반 응용 프로그램이 API를 직접 쓰도록 설계하지 않았다.

Compress-Offload 요구사항
요구핵심 내용
Byte와 시간 분리rendered sample 수로 정확한 A/V 동기화
여러 formatfirmware 내장 또는 동적 library의 encoder/decoder
주요 format 우선capture/playback의 널리 쓰는 형식, 추후 확장
여러 configurationprofile·channel·mode의 유효 조합 열거
Rendering/GrabbingDSP 출력 또는 logical back-end로 route
복잡성 은닉Android HAL·PulseAudio 같은 compatibility layer 사용

가변 compressed stream과 플랫폼 차이를 처리하는 설계 조건이다.



Requirements
============
The main requirements are:

- separation between byte counts and time. Compressed formats may have
  a header per file, per frame, or no header at all. The payload size
  may vary from frame-to-frame. As a result, it is not possible to
  estimate reliably the duration of audio buffers when handling
  compressed data. Dedicated mechanisms are required to allow for
  reliable audio-video synchronization, which requires precise
  reporting of the number of samples rendered at any given time.

- Handling of multiple formats. PCM data only requires a specification
  of the sampling rate, number of channels and bits per sample. In
  contrast, compressed data comes in a variety of formats. Audio DSPs
  may also provide support for a limited number of audio encoders and
  decoders embedded in firmware, or may support more choices through
  dynamic download of libraries.

- Focus on main formats. This API provides support for the most
  popular formats used for audio and video capture and playback. It is
  likely that as audio compression technology advances, new formats
  will be added.

- Handling of multiple configurations. Even for a given format like
  AAC, some implementations may support AAC multichannel but HE-AAC
  stereo. Likewise WMA10 level M3 may require too much memory and cpu
  cycles. The new API needs to provide a generic way of listing these
  formats.

- Rendering/Grabbing only. This API does not provide any means of
  hardware acceleration, where PCM samples are provided back to
  user-space for additional processing. This API focuses instead on
  streaming compressed data to a DSP, with the assumption that the
  decoded samples are routed to a physical output or logical back-end.

- Complexity hiding. Existing user-space multimedia frameworks all
  have existing enums/structures for each compressed format. This new
  API assumes the existence of a platform-specific compatibility layer
  to expose, translate and make use of the capabilities of the audio
  DSP, eg. Android HAL or PulseAudio sinks. By construction, regular
  applications are not supposed to make use of this API.

Flow control, ring buffer와 driver 경계

78-100

새 API는 flow control에서 PCM API의 여러 개념을 공유한다. Content 종류와 관계없이 start, pause, resume, drain, stop 명령은 같은 의미를 가진다.

여러 fragment로 나눈 memory ring buffer 개념도 ALSA PCM API에서 가져오지만 크기는 byte 단위로만 지정한다. Seek와 trick mode는 host가 처리한다고 가정한다. Rewind와 forward 개념은 지원하지 않으며, ring buffer에 commit한 data는 모든 buffer를 drop하는 경우를 제외하고 무효화할 수 없다.

Compressed Data API는 main memory에서 embedded audio cluster로 DMA 전송하거나 외부 DSP의 SPI interface로 보내는 등 DSP 전달 방식을 가정하지 않는다. ALSA PCM처럼 core routine 집합을 제공하고 각 driver 작성자가 mandatory routine을 구현하며 필요하면 optional routine을 사용한다.

Compressed Data flow 설계
항목규칙
명령 의미start, pause, resume, drain, stop은 PCM과 동일
Ring bufferfragment 집합, 크기는 byte만 사용
Seek/trickhost가 처리
Rewind/forward지원하지 않음
Committed data전체 buffer drop 외에는 무효화 불가
DSP transportDMA, SPI 등 driver 구현에 독립적

PCM과 공유하는 개념과 compressed 전용 제약이다.


Design
======
The new API shares a number of concepts with the PCM API for flow
control. Start, pause, resume, drain and stop commands have the same
semantics no matter what the content is.

The concept of memory ring buffer divided in a set of fragments is
borrowed from the ALSA PCM API. However, only sizes in bytes can be
specified.

Seeks/trick modes are assumed to be handled by the host.

The notion of rewinds/forwards is not supported. Data committed to the
ring buffer cannot be invalidated, except when dropping all buffers.

The Compressed Data API does not make any assumptions on how the data
is transmitted to the audio DSP. DMA transfers from main memory to an
embedded audio cluster or to a SPI interface for external DSPs are
possible. As in the ALSA PCM case, a core set of routines is exposed;
each driver implementer will have to write support for a set of
mandatory routines and possibly make use of optional ones.

Capability·parameter·timestamp routine

101-153

`get_caps`는 지원 audio format 목록을 반환한다. Capture stream에서 codec을 조회하면 encoder를 반환하고 playback stream에서는 decoder를 열거한다.

`get_codec_caps`는 codec별 capability 목록을 반환한다. 모든 항목이 실제로 유효한 설정 조합이 되게 하여 configuration 실패 위험을 줄이는 것이 목적이다. AAC처럼 channel 수가 profile에 따라 달라지는 codec을 단일 descriptor로 표현하면 지원하지 않는 profile/channel/format 조합이 만들어질 수 있다. Embedded DSP의 memory와 CPU cycle도 제한적이므로 capability 목록은 현재 workload에 따라 동적으로 달라질 수 있다.

`get_codec_caps`는 codec 설정 외에도 구현이 처리하는 최소 buffer 크기를 반환한다. 이 값은 DMA buffer 크기나 동기화에 필요한 byte 수 등에 따라 달라질 수 있으며, 사용자 공간이 playback 시작 전에 ring buffer에 써야 하는 최소 data 양을 정하는 데 사용한다.

`set_params`는 특정 codec에 선택한 구성을 설정한다. 가장 중요한 field는 codec type이다. 대부분의 decoder는 다른 field를 무시하지만 encoder는 설정을 엄격히 따른다. `get_params`는 DSP가 실제로 사용하는 설정을 반환하며 설정 변경은 예외적인 경우로 남아야 한다.

`get_timestamp`는 여러 field를 가진 structure를 반환한다. 전송한 byte 수, 처리한 sample 수, render하거나 grab한 sample 수가 포함된다. 이 값을 이용해 평균 bitrate, ring buffer refill 필요 여부, DSP의 decoding·encoding·I/O delay를 계산할 수 있다.

Compress-Offload 주요 routine
Routine반환 / 동작
get_capscapture encoder 또는 playback decoder format 목록
get_codec_caps유효 capability 조합과 최소 buffer 크기
set_params선택한 codec 구성 설정
get_paramsDSP가 실제 사용하는 설정
get_timestamp전송 byte, 처리 sample, rendered/grabbed sample

Capability 조회부터 실행 설정과 진행량 측정까지의 역할이다.

Codec, profile, mode 목록은 새로 만들지 않고 OpenMAX AL 명세에서 가져왔다. 다만 ALSA 사용을 위해 FLAC·IEC format 추가, encoder/decoder capability 병합, compact descriptor를 위한 profile/mode bitmask, OpenMAX AL에 없던 decoder `set_params`와 AMR/AMR-WB encoding mode, WMA format 정보, 필요 시 OpenMAX IL에서 가져온 encoding option, `rateControlSupported`를 추가했다.

OpenMAX AL 기반 수정사항
수정내용
FormatFLAC와 IEC 추가
Capabilityencoder/decoder 병합
Descriptorprofile/mode를 bitmask로 표현
Decoderset_params 추가
AMRAMR/AMR-WB encoding mode 추가
WMAformat 정보 추가
Encoding option필요 시 OpenMAX IL에서 파생
Rate controlrateControlSupported 추가

ALSA API에 맞게 보완한 항목이다.

The main additions are

get_caps
  This routine returns the list of audio formats supported. Querying the
  codecs on a capture stream will return encoders, decoders will be
  listed for playback streams.

get_codec_caps
  For each codec, this routine returns a list of
  capabilities. The intent is to make sure all the capabilities
  correspond to valid settings, and to minimize the risks of
  configuration failures. For example, for a complex codec such as AAC,
  the number of channels supported may depend on a specific profile. If
  the capabilities were exposed with a single descriptor, it may happen
  that a specific combination of profiles/channels/formats may not be
  supported. Likewise, embedded DSPs have limited memory and cpu cycles,
  it is likely that some implementations make the list of capabilities
  dynamic and dependent on existing workloads. In addition to codec
  settings, this routine returns the minimum buffer size handled by the
  implementation. This information can be a function of the DMA buffer
  sizes, the number of bytes required to synchronize, etc, and can be
  used by userspace to define how much needs to be written in the ring
  buffer before playback can start.

set_params
  This routine sets the configuration chosen for a specific codec. The
  most important field in the parameters is the codec type; in most
  cases decoders will ignore other fields, while encoders will strictly
  comply to the settings

get_params
  This routines returns the actual settings used by the DSP. Changes to
  the settings should remain the exception.

get_timestamp
  The timestamp becomes a multiple field structure. It lists the number
  of bytes transferred, the number of samples processed and the number
  of samples rendered/grabbed. All these values can be used to determine
  the average bitrate, figure out if the ring buffer needs to be
  refilled or the delay due to decoding/encoding/io on the DSP.

Note that the list of codecs/profiles/modes was derived from the
OpenMAX AL specification instead of reinventing the wheel.
Modifications include:
- Addition of FLAC and IEC formats
- Merge of encoder/decoder capabilities
- Profiles/modes listed as bitmasks to make descriptors more compact
- Addition of set_params for decoders (missing in OpenMAX AL)
- Addition of AMR/AMR-WB encoding modes (missing in OpenMAX AL)
- Addition of format information for WMA
- Addition of encoding options when required (derived from OpenMAX IL)
- Addition of rateControlSupported (missing in OpenMAX AL)

Compressed stream 상태 머신

154-205

Stream은 `OPEN`에서 `compr_set_params()`를 호출해 `SETUP`으로 간다. `SETUP`에서 `compr_write()`로 data를 넣으면 `PREPARE`, `compr_start()`로 `RUNNING`이 된다.

`RUNNING`에서 `compr_pause()`는 `PAUSE`로 전이하고 `compr_resume()`은 다시 `RUNNING`으로 돌아간다. `compr_drain()`은 `DRAIN`으로 이동하며 `compr_drain_notify()` 또는 `compr_stop()` 뒤 `SETUP`으로 돌아간다. `RUNNING`이나 `PAUSE`에서 `compr_stop()`을 호출해도 `SETUP`으로 복귀한다.

`SETUP` 또는 `PREPARE`에서 `compr_free()`를 호출하면 `FREE`가 된다. 원문의 ASCII 상태 머신을 다음 전이로 재구성했다.

Compressed audio stream 상태
OPENcompr_set_params()SETUP
SETUPcompr_write()PREPARE
PREPAREcompr_start()RUNNING
RUNNINGcompr_pause()PAUSE
PAUSEcompr_resume()RUNNING
RUNNINGcompr_drain()DRAIN
DRAINcompr_drain_notify() 또는 compr_stop()SETUP
RUNNINGcompr_stop()SETUP
PAUSEcompr_stop()SETUP
SETUP 또는 PREPAREcompr_free()FREE

모든 명령과 목적 상태를 보존한 상태 전이다.

State Machine
=============

The compressed audio stream state machine is described below ::

                                        +----------+
                                        |          |
                                        |   OPEN   |
                                        |          |
                                        +----------+
                                             |
                                             |
                                             | compr_set_params()
                                             |
                                             v
         compr_free()                  +----------+
  +------------------------------------|          |
  |                                    |   SETUP  |
  |          +-------------------------|          |<-------------------------+
  |          |       compr_write()     +----------+                          |
  |          |                              ^                                |
  |          |                              | compr_drain_notify()           |
  |          |                              |        or                      |
  |          |                              |     compr_stop()               |
  |          |                              |                                |
  |          |                         +----------+                          |
  |          |                         |          |                          |
  |          |                         |   DRAIN  |                          |
  |          |                         |          |                          |
  |          |                         +----------+                          |
  |          |                              ^                                |
  |          |                              |                                |
  |          |                              | compr_drain()                  |
  |          |                              |                                |
  |          v                              |                                |
  |    +----------+                    +----------+                          |
  |    |          |    compr_start()   |          |        compr_stop()      |
  |    | PREPARE  |------------------->|  RUNNING |--------------------------+
  |    |          |                    |          |                          |
  |    +----------+                    +----------+                          |
  |          |                            |    ^                             |
  |          |compr_free()                |    |                             |
  |          |              compr_pause() |    | compr_resume()              |
  |          |                            |    |                             |
  |          v                            v    |                             |
  |    +----------+                   +----------+                           |
  |    |          |                   |          |         compr_stop()      |
  +--->|   FREE   |                   |  PAUSE   |---------------------------+
       |          |                   |          |
       +----------+                   +----------+

Gapless playback metadata와 실행 순서

206-252

Album을 연속 재생할 때 decoder는 encoder delay와 padding을 건너뛰고 한 track의 content에서 다음 track으로 바로 넘어갈 수 있다. 전환 중 무음이 없어 사용자는 gapless playback으로 인식한다. Encoding 때문에 작은 noise가 생길 수 있어 모든 compressed data에서 완벽한 gapless를 보장하기는 어렵지만 대부분의 음악에서는 잘 동작한다.

Decoder가 무음을 제거하려면 encoder delay와 padding을 알아야 한다. 이 metadata는 ID3/MP4 header에서 추출되며 기본 bitstream에는 없으므로 DSP에 전달할 새 interface가 필요하다. DSP와 사용자 공간은 다음 track data를 사용하도록 전환 시점도 맞춰야 한다.

`set_metadata`는 encoder delay와 padding을 설정하며 해당 track data를 쓰기 전에 호출해야 한다. `set_next_track`은 이후에 보내는 metadata와 write operation이 다음 track에 해당한다고 DSP에 알린다. `partial drain`은 EOF에서 DSP에 종료를 알려 padding을 건너뛰게 하고 이후 write data가 다음 track임을 나타낸다.

Gapless sequence는 open, capability 조회, parameter 설정, 첫 track metadata와 data 전송, start, 첫 track 전송 완료, `set_next_track`, 다음 track metadata, `partial_drain`, 다음 track data 전송, DSP의 track 전환 순서다. 다음 track write와 `partial_drain`의 순서는 서로 바꿀 수도 있다.

Gapless playback 순서
OpenGet caps / codec capsSet params첫 track metadata첫 track dataTrigger start
첫 track 전송 완료set_next_track다음 track metadatapartial_drain다음 track dataDSP가 두 번째 track으로 전환
허용되는 변형다음 track write와 partial_drain 순서 교환 가능

Metadata와 다음 track 표시를 포함한 사용자 공간·DSP 협력 흐름이다.

Gapless Playback
================
When playing thru an album, the decoders have the ability to skip the encoder
delay and padding and directly move from one track content to another. The end
user can perceive this as gapless playback as we don't have silence while
switching from one track to another

Also, there might be low-intensity noises due to encoding. Perfect gapless is
difficult to reach with all types of compressed data, but works fine with most
music content. The decoder needs to know the encoder delay and encoder padding.
So we need to pass this to DSP. This metadata is extracted from ID3/MP4 headers
and are not present by default in the bitstream, hence the need for a new
interface to pass this information to the DSP. Also DSP and userspace needs to
switch from one track to another and start using data for second track.

The main additions are:

set_metadata
  This routine sets the encoder delay and encoder padding. This can be used by
  decoder to strip the silence. This needs to be set before the data in the track
  is written.

set_next_track
  This routine tells DSP that metadata and write operation sent after this would
  correspond to subsequent track

partial drain
  This is called when end of file is reached. The userspace can inform DSP that
  EOF is reached and now DSP can start skipping padding delay. Also next write
  data would belong to next track

Sequence flow for gapless would be:
- Open
- Get caps / codec caps
- Set params
- Set metadata of the first track
- Fill data of the first track
- Trigger start
- User-space finished sending all,
- Indicate next track data by sending set_next_track
- Set metadata of the next track
- then call partial_drain to flush most of buffer in DSP
- Fill data of the next track
- DSP switches to second track

(note: order for partial_drain and write for next track can be reversed as well)

Gapless 상태 머신

253-286

Gapless playback에서는 `RUNNING`에서 `compr_next_track()`으로 `NEXT_TRACK`에 들어간다. 이 상태에서 `compr_set_params()`로 다음 track parameter를 설정할 수 있으며 `compr_partial_drain()`을 호출하면 `PARTIAL_DRAIN`으로 이동한다. DSP가 부분 drain을 마쳐 `compr_drain_notify()`를 알리면 다시 `RUNNING`으로 돌아가 다음 track을 재생한다.

Gapless playback 상태
RUNNINGcompr_next_track()NEXT_TRACK
NEXT_TRACKcompr_set_params()NEXT_TRACK
NEXT_TRACKcompr_partial_drain()PARTIAL_DRAIN
PARTIAL_DRAINcompr_drain_notify()RUNNING

원문의 ASCII 상태 머신을 같은 순환 구조로 재구성했다.

Gapless Playback SM
===================

For Gapless, we move from running state to partial drain and back, along
with setting of meta_data and signalling for next track ::


                                        +----------+
                compr_drain_notify()    |          |
              +------------------------>|  RUNNING |
              |                         |          |
              |                         +----------+
              |                              |
              |                              |
              |                              | compr_next_track()
              |                              |
              |                              V
              |                         +----------+
              |    compr_set_params()   |          |
              |             +-----------|NEXT_TRACK|
              |             |           |          |
              |             |           +--+-------+
              |             |              | |
              |             +--------------+ |
              |                              |
              |                              | compr_partial_drain()
              |                              |
              |                              V
              |                         +----------+
              |                         |          |
              +------------------------ | PARTIAL_ |
                                        |  DRAIN   |
                                        +----------+

지원하지 않는 기능

287-321

VoIP와 circuit-switched call은 이 API의 대상이 아니다. Dynamic bitrate 변경은 DSP와 host stack의 긴밀한 결합이 필요해 전력 절감 효과를 제한한다.

Packet-loss concealment도 지원하지 않는다. 전송 중 frame 손실 시 decoder가 data를 합성하도록 알리는 추가 interface가 필요하며 향후 추가될 수 있다.

Volume control과 routing은 이 API가 처리하지 않는다. Compressed data interface를 제공하는 장치도 일반 ALSA 장치로 보고, volume과 route 정보는 일반 ALSA kcontrol로 제공한다. Embedded audio effect도 input이 PCM인지 compressed인지와 무관하게 같은 방식으로 활성화해야 한다. Multichannel IEC encoding은 필요성 자체가 명확하지 않다.

앞서 언급한 encoding/decoding acceleration은 지원하지 않는다. Decoder 출력을 capture stream으로 route하거나 transcoding을 구현할 수는 있으며 이 routing도 ALSA kcontrol로 활성화한다.

Audio policy와 resource management도 범위 밖이다. DSP 사용률을 조회하거나 작업을 preempt하는 hook이 없다. Compressed byte의 write/read 양은 시간상의 실제 출력과 직접 대응하지 않으므로 underrun/overrun 개념도 다루지 않으며 사용자 library에서 처리할 수 있다.

Compress-Offload 미지원 범위
기능처리 방침
VoIP / circuit-switched대상 아님, dynamic bitrate 결합 비용 큼
Packet-loss concealment추가 decoder interface 필요, 향후 가능
Volume / routing일반 ALSA kcontrol
Embedded effectsPCM과 compressed에 같은 방식 적용
Multichannel IEC encoding필요 여부 불명확
Encoding/decoding acceleration직접 지원 안 함, routing은 kcontrol
Policy/resource managementDSP 사용률·preemption hook 없음
Underrun/overrunAPI에서 다루지 않으며 user library 후보

API 밖에서 처리하거나 향후 확장이 필요한 기능이다.

Not supported
=============
- Support for VoIP/circuit-switched calls is not the target of this
  API. Support for dynamic bit-rate changes would require a tight
  coupling between the DSP and the host stack, limiting power savings.

- Packet-loss concealment is not supported. This would require an
  additional interface to let the decoder synthesize data when frames
  are lost during transmission. This may be added in the future.

- Volume control/routing is not handled by this API. Devices exposing a
  compressed data interface will be considered as regular ALSA devices;
  volume changes and routing information will be provided with regular
  ALSA kcontrols.

- Embedded audio effects. Such effects should be enabled in the same
  manner, no matter if the input was PCM or compressed.

- multichannel IEC encoding. Unclear if this is required.

- Encoding/decoding acceleration is not supported as mentioned
  above. It is possible to route the output of a decoder to a capture
  stream, or even implement transcoding capabilities. This routing
  would be enabled with ALSA kcontrols.

- Audio policy/resource management. This API does not provide any
  hooks to query the utilization of the audio DSP, nor any preemption
  mechanisms.

- No notion of underrun/overrun. Since the bytes written are compressed
  in nature and data written/read doesn't translate directly to
  rendered output in time, this does not deal with underrun/overrun and
  maybe dealt in user-library

기여자

322-329

Mark Brown과 Liam Girdwood는 API 필요성 논의에 기여했다. Harsha Priya는 `intel_sst` compressed API를 작업했고 Rakesh Ughreja는 중요한 피드백을 제공했다. Sing Nallasellan, Sikkandar Madar, Prasanna Samaga는 실제 플랫폼에서 audio offload 효과를 입증하고 정량화했다.

Credits
=======
- Mark Brown and Liam Girdwood for discussions on the need for this API
- Harsha Priya for her work on intel_sst compressed API
- Rakesh Ughreja for valuable feedback
- Sing Nallasellan, Sikkandar Madar and Prasanna Samaga for
  demonstrating and quantifying the benefits of audio offload on a
  real platform.