forked from thesofproject/sof
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsink_api.h
More file actions
362 lines (314 loc) · 11.7 KB
/
sink_api.h
File metadata and controls
362 lines (314 loc) · 11.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
/* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright(c) 2023 Intel Corporation. All rights reserved.
*
*/
#ifndef __MODULE_AUDIO_SINK_API_H__
#define __MODULE_AUDIO_SINK_API_H__
#include <errno.h>
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "audio_stream.h"
#include "format.h"
/**
* this is a definition of API to sink of audio data
*
* THE SINK is any component that can store data somehow and provide a buffer to be filled
* with data at request. The sink API does not define how the data will be processed/used
*
* The user - a module - sees this API as a destination it must send data to
* The IMPLEMENTATION - audio_stream, DP Queue - sees this as a producer that
* PROVIDES data for processing
*
* Examples of components that should expose SINK api
* - /dev/null
* all the data stored in sink buffer are just simply discarded
* - I2S sender
* Data stored in sink buffer will be sent to the external world
* - a memory ring buffer
* data stored in the buffer will be sent to another module (usually using source API, but it
* does not matter in fact).
*
* The main advantage of using sink API instead of just taking pointers to the buffers is that
* the buffer may be prepared at the moment the data producer is requesting it. i.e.
* - cache may be written back/invalidated if necessary
* - data may be moved to make linear space
* - part of the buffer may be locked to prevent reading
* etc.etc. it depends on implementation of the data sink
*
* NOTE: the module should get a complete portion of space it needs for processing, fill it
* than release. The reason is - the depending on the implementation, the calls may be
* expensive - may involve some data moving in memory, cache writebacks, etc.
*
*/
/* forward def */
struct sof_sink;
struct sof_audio_stream_params;
struct sof_ipc_stream_params;
struct processing_module;
/**
* this is a definition of internals of sink API
*
* The clients of stream API should use access functions provided below!
*
*/
struct sink_ops {
/**
* see comment of sink_get_free_size()
*/
size_t (*get_free_size)(struct sof_sink *sink);
/**
* see comment of sink_get_buffer()
*/
int (*get_buffer)(struct sof_sink *sink, size_t req_size,
void **data_ptr, void **buffer_start, size_t *buffer_size);
/**
* see comment of sink_commit_buffer()
*/
int (*commit_buffer)(struct sof_sink *sink, size_t commit_size);
/**
* get latest feeding time for this sink, result is a number of microseconds since "NOW"
* where "now" means a start of last LL cycle, as described in zephyr_dp_schedule.c
*/
uint32_t (*get_lft)(struct sof_sink *sink);
/**
* OPTIONAL: Notification to the sink implementation about changes in audio format
*
* Once any of *audio_stream_params elements changes, the implementation of
* sink may need to perform some extra operations.
* This callback will be called immediately after any change
*
* @retval 0 if success, negative if new parameters are not supported
*/
int (*on_audio_format_set)(struct sof_sink *sink);
/**
* OPTIONAL
* see sink_set_params comments
*/
int (*audio_set_ipc_params)(struct sof_sink *sink,
struct sof_ipc_stream_params *params, bool force_update);
/**
* OPTIONAL
* see comment for sink_set_alignment_constants
*/
int (*set_alignment_constants)(struct sof_sink *sink,
const uint32_t byte_align,
const uint32_t frame_align_req);
/**
* OPTIONAL
* events called when a module is starting / finishing using of the API
* on the core that the module and API will executed on
*/
int (*on_bind)(struct sof_sink *sink, struct processing_module *module);
int (*on_unbind)(struct sof_sink *sink);
};
/** internals of sink API. NOT TO BE MODIFIED OUTSIDE OF sink_api.c */
struct sof_sink {
const struct sink_ops *ops; /** operations interface */
size_t requested_write_frag_size; /** keeps number of bytes requested by get_buffer() */
size_t num_of_bytes_processed; /** processed bytes counter */
size_t min_free_space; /** minimum buffer space required by the module using sink
* it is module's OBS as declared in module bind IPC
*/
struct processing_module *bound_module; /* a pointer module that is using sink API */
struct sof_audio_stream_params *audio_stream_params; /** pointer to audio params */
};
/**
*
* Public functions
*
*/
/**
* Retrieves size of free space available in sink (in bytes)
* return number of free bytes in buffer available to immediate filling
*/
static inline size_t sink_get_free_size(struct sof_sink *sink)
{
return sink->ops->get_free_size(sink);
}
static inline enum sof_ipc_frame sink_get_frm_fmt(struct sof_sink *sink)
{
return sink->audio_stream_params->frame_fmt;
}
static inline uint32_t sink_get_channels(struct sof_sink *sink)
{
return sink->audio_stream_params->channels;
}
/** get size of a single audio frame (in bytes) */
size_t sink_get_frame_bytes(struct sof_sink *sink);
/**
* Retrieves size of free space available in sink (in frames)
* return number of free frames in buffer available to immediate filling
*/
size_t sink_get_free_frames(struct sof_sink *sink);
/**
* Get a circular buffer to operate on (to write).
*
* Retrieves a fragment of circular data to be used by the caller
* After calling get_buffer, the space for data is guaranteed to be available
* for exclusive use on the caller core through provided pointer
* if the provided pointers are cached, it is guaranteed that the caller may safely use it without
* any additional cache operations
* The caller MUST take care of data circularity based on provided pointers
*
* @param sink a handler to sink
* @param [in] req_size requested size of space
* @param [out] data_ptr a pointer to the space will be provided there
* @param [out] buffer_start pointer to circular buffer start
* @param [out] buffer_size size of circular buffer
*
* @retval -ENODATA if req_size is bigger than free space
*
*/
int sink_get_buffer(struct sof_sink *sink, size_t req_size, void **data_ptr, void **buffer_start,
size_t *buffer_size);
/**
* Get a circular buffer to operate on (to write).
*
* Same as sink_get_buffer() except that the size of circular buffer is returned as
* 16 bit samples count. The returned samples count simplifies pointer arithmetic in a
* samples process function. The data pointers are int16_t type.
*
* @param sink a handler to sink
* @param [in] req_size requested size of space
* @param [out] data_ptr a pointer to the space will be provided there
* @param [out] buffer_start pointer to circular buffer start
* @param [out] buffer_samples number of s16 samples total in circular buffer
*
* @retval -ENODATA if req_size is bigger than free space
*
*/
int sink_get_buffer_s16(struct sof_sink *sink, size_t req_size, int16_t **data_ptr,
int16_t **buffer_start, int *buffer_samples);
/**
* Get a circular buffer to operate on (to write).
*
* Same as sink_get_buffer() except that the size of circular buffer is returned as
* 32 bit samples count. The returned samples count simplifies pointer arithmetic in a
* samples process function. The data pointers are int32_t type.
*
* @param sink a handler to sink
* @param [in] req_size requested size of space
* @param [out] data_ptr a pointer to the space will be provided there
* @param [out] buffer_start pointer to circular buffer start
* @param [out] buffer_samples number of s32 samples total in circular buffer
*
* @retval -ENODATA if req_size is bigger than free space
*
*/
int sink_get_buffer_s32(struct sof_sink *sink, size_t req_size, int32_t **data_ptr,
int32_t **buffer_start, int *buffer_samples);
/**
* Commits that the buffer previously obtained by get_buffer is filled with data
* and ready to be used
*
* @param sink a handler to sink
* @param commit_size amount of data that the caller declares as valid
* if commit_size is bigger than the amount of data obtained before by get_buffer(), only
* the amount obtained before will be committed. That means - if somebody obtained a buffer,
* filled it with data and wants to commit it in whole, it may simple call
* commit_buffer with commit_size==MAXINT
* @return proper error code (0 on success)
*/
int sink_commit_buffer(struct sof_sink *sink, size_t commit_size);
/** set of functions for retrieve audio parameters */
int sink_set_frm_fmt(struct sof_sink *sink, enum sof_ipc_frame frame_fmt);
static inline enum sof_ipc_frame sink_get_valid_fmt(struct sof_sink *sink)
{
return sink->audio_stream_params->valid_sample_fmt;
}
static inline uint32_t sink_get_rate(struct sof_sink *sink)
{
return sink->audio_stream_params->rate;
}
static inline uint32_t sink_get_buffer_fmt(struct sof_sink *sink)
{
return sink->audio_stream_params->buffer_fmt;
}
/**
* initial set of audio parameters, provided in sof_ipc_stream_params
*
* @param sink a handler to sink
* @param params the set of parameters
* @param force_update tells the implementation that the params should override actual settings
* @return 0 if success
*/
int sink_set_params(struct sof_sink *sink, struct sof_ipc_stream_params *params, bool force_update);
/**
* Set frame_align_shift and frame_align of stream according to byte_align and
* frame_align_req alignment requirement. Once the channel number,frame size
* are determined, the frame_align and frame_align_shift are determined too.
* these two feature will be used in audio_stream_get_avail_frames_aligned
* to calculate the available frames. it should be called in component prepare
* or param functions only once before stream copy. if someone forgets to call
* this first, there would be unexampled error such as nothing is copied at all.
*
* @param sink a handler to sink
* @param byte_align Processing byte alignment requirement.
* @param frame_align_req Processing frames alignment requirement.
*
* @return 0 if success
*/
int sink_set_alignment_constants(struct sof_sink *sink,
const uint32_t byte_align,
const uint32_t frame_align_req);
int sink_set_valid_fmt(struct sof_sink *sink, enum sof_ipc_frame valid_sample_fmt);
int sink_set_rate(struct sof_sink *sink, unsigned int rate);
int sink_set_channels(struct sof_sink *sink, unsigned int channels);
int sink_set_buffer_fmt(struct sof_sink *sink, uint32_t buffer_fmt);
int sink_set_overrun(struct sof_sink *sink, bool overrun_permitted);
int sink_set_params(struct sof_sink *sink, struct sof_ipc_stream_params *params, bool force_update);
static inline size_t sink_get_min_free_space(struct sof_sink *sink)
{
return sink->min_free_space;
}
static inline uint32_t sink_get_id(struct sof_sink *sink)
{
return sink->audio_stream_params->id;
}
static inline uint32_t sink_get_pipeline_id(struct sof_sink *sink)
{
return sink->audio_stream_params->pipeline_id;
}
/**
* @brief hook to be called when a module connects to the API
*
* NOTE! it MUST be called at core that a module is bound to
*/
static inline int sink_bind(struct sof_sink *sink, struct processing_module *module)
{
int ret = 0;
if (sink->bound_module)
return -EBUSY;
if (sink->ops->on_bind)
ret = sink->ops->on_bind(sink, module);
if (!ret)
sink->bound_module = module;
return ret;
}
/**
* @brief hook to be called when a module disconnects from the API
*
* NOTE! it MUST be called at core that a module is bound to
*/
static inline int sink_unbind(struct sof_sink *sink)
{
int ret = 0;
if (!sink->bound_module)
return -EINVAL;
if (sink->ops->on_unbind)
ret = sink->ops->on_unbind(sink);
if (!ret)
sink->bound_module = NULL;
return ret;
}
static inline struct processing_module *sink_get_bound_module(struct sof_sink *sink)
{
return sink->bound_module;
}
static inline uint32_t sink_get_last_feeding_time(struct sof_sink *sink)
{
return sink->ops->get_lft(sink);
}
#endif /* __MODULE_AUDIO_SINK_API_H__ */