Skip to content

Commit b0b5fda

Browse files
buf: add secondary buffer support to struct audio_buffer
secondary buffer mechanism is a feature independent of a buffer implementation, therefore it should be located in a base class for all buffers this commit intentionally is not removing the same feature from comp_buffer nor trying to use it anywhere Signed-off-by: Marcin Szkudlinski <marcin.szkudlinski@intel.com>
1 parent 5b6625b commit b0b5fda

5 files changed

Lines changed: 236 additions & 13 deletions

File tree

src/audio/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ add_local_sources(sof
129129
component.c
130130
data_blob.c
131131
buffer.c
132+
buffers/audio_buffer.c
132133
source_api_helper.c
133134
sink_api_helper.c
134135
sink_source_utils.c

src/audio/buffers/audio_buffer.c

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
// SPDX-License-Identifier: BSD-3-Clause
2+
//
3+
// Copyright(c) 2024 Intel Corporation. All rights reserved.
4+
//
5+
// Author: Marcin Szkudlinski <marcin.szkudlinski@intel.com>
6+
7+
#include <stdint.h>
8+
#include <stddef.h>
9+
#include <errno.h>
10+
#include <rtos/alloc.h>
11+
#include <sof/audio/audio_buffer.h>
12+
#include <sof/audio/sink_api.h>
13+
#include <sof/audio/source_api.h>
14+
#include <sof/audio/sink_source_utils.h>
15+
16+
#if CONFIG_PIPELINE_2_0
17+
18+
int audio_buffer_attach_secondary_buffer(struct sof_audio_buffer *buffer, bool at_input,
19+
struct sof_audio_buffer *secondary_buffer)
20+
{
21+
if (buffer->secondary_buffer_sink || buffer->secondary_buffer_source)
22+
return -EINVAL;
23+
24+
/* secondary buffer must share audio params with the primary buffer */
25+
secondary_buffer->audio_stream_params = buffer->audio_stream_params;
26+
/* for performance reasons pointers to params are also kept in sink/src structures */
27+
secondary_buffer->_sink_api.audio_stream_params = buffer->audio_stream_params;
28+
secondary_buffer->_source_api.audio_stream_params = buffer->audio_stream_params;
29+
30+
if (at_input)
31+
buffer->secondary_buffer_sink = secondary_buffer;
32+
else
33+
buffer->secondary_buffer_source = secondary_buffer;
34+
35+
return 0;
36+
}
37+
38+
int audio_buffer_sync_secondary_buffer(struct sof_audio_buffer *buffer, size_t limit)
39+
{
40+
int err;
41+
42+
struct sof_source *data_src;
43+
struct sof_sink *data_dst;
44+
45+
if (buffer->secondary_buffer_sink) {
46+
/*
47+
* audio_buffer sink API is shadowed, that means there's a secondary_buffer
48+
* at data input
49+
* get data from secondary_buffer (use source API)
50+
* copy to primary buffer (use sink API)
51+
* note! can't use audio_buffer_get_sink because it will provide a shadowed
52+
* sink handler (to a secondary buffer).
53+
*/
54+
data_src = audio_buffer_get_source(buffer->secondary_buffer_sink);
55+
data_dst = &buffer->_sink_api; /* primary buffer's sink API */
56+
} else if (buffer->secondary_buffer_source) {
57+
/*
58+
* comp_buffer source API is shadowed, that means there's a secondary_buffer
59+
* at data output
60+
* get data from comp_buffer (use source API)
61+
* copy to secondary_buffer (use sink API)
62+
*/
63+
data_src = &buffer->_source_api;
64+
data_dst = audio_buffer_get_sink(buffer->secondary_buffer_source);
65+
66+
} else {
67+
return -EINVAL;
68+
}
69+
70+
/*
71+
* keep data_available and free_size in local variables to avoid check_time/use_time
72+
* race in MIN macro
73+
*/
74+
size_t data_available = source_get_data_available(data_src);
75+
size_t free_size = sink_get_free_size(data_dst);
76+
size_t to_copy = MIN(MIN(data_available, free_size), limit);
77+
78+
err = source_to_sink_copy(data_src, data_dst, true, to_copy);
79+
return err;
80+
}
81+
82+
#endif /* CONFIG_PIPELINE_2_0 */
83+
84+
void audio_buffer_free(struct sof_audio_buffer *buffer)
85+
{
86+
if (!buffer)
87+
return;
88+
89+
CORE_CHECK_STRUCT(buffer);
90+
#if CONFIG_PIPELINE_2_0
91+
audio_buffer_free(buffer->secondary_buffer_sink);
92+
audio_buffer_free(buffer->secondary_buffer_source);
93+
#endif /* CONFIG_PIPELINE_2_0 */
94+
if (buffer->free)
95+
buffer->free(buffer);
96+
rfree(buffer);
97+
}

src/audio/source_api_helper.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Copyright(c) 2023 Intel Corporation. All rights reserved.
44
*/
55

6+
#include <sof/audio/sink_api.h>
67
#include <sof/audio/source_api.h>
78
#include <sof/audio/audio_stream.h>
89

src/include/sof/audio/audio_buffer.h

Lines changed: 136 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@
99
#include <sof/common.h>
1010
#include <ipc/topology.h>
1111
#include <sof/coherent.h>
12+
#include <sof/audio/sink_api.h>
13+
#include <sof/audio/source_api.h>
1214

1315
#define BUFFER_TYPE_LEGACY_BUFFER 1
14-
#define BUFFER_TYPE_LEGACY_RING_HYBRID 2
15-
#define BUFFER_TYPE_RING_BUFFER 3
16+
#define BUFFER_TYPE_RING_BUFFER 2
1617

1718
/* base class for all buffers, all buffers must inherit from it */
1819
struct sof_audio_buffer {
@@ -21,8 +22,34 @@ struct sof_audio_buffer {
2122
/* type of the buffer BUFFER_TYPE_* */
2223
uint32_t buffer_type;
2324

24-
/* runtime stream params */
25-
struct sof_audio_stream_params audio_stream_params;
25+
#if CONFIG_PIPELINE_2_0
26+
/**
27+
* sink API of an additional buffer
28+
* of any type at data input
29+
*
30+
* to be removed when hybrid buffers are no longer needed
31+
*/
32+
struct sof_audio_buffer *secondary_buffer_sink;
33+
34+
/**
35+
* source API of an additional buffer
36+
* at data output
37+
*/
38+
struct sof_audio_buffer *secondary_buffer_source;
39+
40+
#endif /* CONFIG_PIPELINE_2_0 */
41+
42+
/* effective runtime stream params
43+
* before pipelin2.0 is ready, stream params may be kept in audio_stream structure
44+
* also for hybrid buffering audio params need to be shared between primary and secondary
45+
* buffers
46+
*
47+
* So currently only a pointer to effective stream params is here.
48+
* Note that the same pointer MUST be set in source and sink api (kept there for
49+
* performance reasons)
50+
*/
51+
struct sof_audio_stream_params *audio_stream_params;
52+
2653

2754
/* private: */
2855
struct sof_source _source_api; /**< src api handler */
@@ -36,6 +63,77 @@ struct sof_audio_buffer {
3663
void (*free)(struct sof_audio_buffer *buffer);
3764
};
3865

66+
#if CONFIG_PIPELINE_2_0
67+
/*
68+
* attach a secondary buffer (any type) before buffer (when at_input == true) or behind a buffer
69+
*
70+
* before buffer (at_input == true):
71+
* 2.0 mod ==> (sink_API) secondary buffer ==>
72+
* ==> comp_buffer (audio_stream or source API) ==> 1.0 mod
73+
*
74+
* after buffer (at_input == false):
75+
* 1.0 mod ==> (audio_stream or sink API) ==> comp_buffer ==>
76+
* ==> secondary buffer(source API) == 2.0 mod
77+
*
78+
* If a secondary buffer is attached, it replaces source or sink interface of audio_stream
79+
* allowing the module connected to it using all properties of secondary buffer (like
80+
* lockless cross-core connection in case of ring_buffer etc.) keeping legacy interface
81+
* to other modules
82+
*
83+
* buffer_sync_secondary_buffer must be called every 1 ms to move data to/from
84+
* secondary buffer to comp_buffer
85+
*
86+
* @param buffer pointer to a buffer
87+
* @param at_input true indicates that a secondary buffer is located at data input, replacing
88+
* sink API of audio_stream
89+
* false indicates that a secondary buffer is located at data output, replacing
90+
* source API of audio_stream
91+
* @param secondary_buffer pointer to a buffer to be attached
92+
*
93+
* to be removed when hybrid buffers are no longer needed
94+
*/
95+
int audio_buffer_attach_secondary_buffer(struct sof_audio_buffer *buffer, bool at_input,
96+
struct sof_audio_buffer *secondary_buffer);
97+
98+
/*
99+
* move data from/to secondary buffer, must be called periodically as described above
100+
*
101+
* @param buffer pointer to a buffer
102+
* @param limit data copy limit. Indicates maximum amount of data that will be moved from/to
103+
* secondary buffer in an operation
104+
*
105+
* to be removed when hybrid buffers are no longer needed
106+
*/
107+
int audio_buffer_sync_secondary_buffer(struct sof_audio_buffer *buffer, size_t limit);
108+
109+
/**
110+
* @brief return a handler to sink API of audio_buffer.
111+
* the handler may be used by helper functions defined in sink_api.h
112+
*/
113+
static inline
114+
struct sof_sink *audio_buffer_get_sink(struct sof_audio_buffer *buffer)
115+
{
116+
CORE_CHECK_STRUCT(buffer);
117+
return buffer->secondary_buffer_sink ?
118+
audio_buffer_get_sink(buffer->secondary_buffer_sink) :
119+
&buffer->_sink_api;
120+
}
121+
122+
/**
123+
* @brief return a handler to source API of audio_buffer
124+
* the handler may be used by helper functions defined in source_api.h
125+
*/
126+
static inline
127+
struct sof_source *audio_buffer_get_source(struct sof_audio_buffer *buffer)
128+
{
129+
CORE_CHECK_STRUCT(buffer);
130+
return buffer->secondary_buffer_source ?
131+
audio_buffer_get_source(buffer->secondary_buffer_source) :
132+
&buffer->_source_api;
133+
}
134+
135+
#else /* CONFIG_PIPELINE_2_0 */
136+
39137
/**
40138
* @brief return a handler to sink API of audio_buffer.
41139
* the handler may be used by helper functions defined in sink_api.h
@@ -58,6 +156,17 @@ struct sof_source *audio_buffer_get_source(struct sof_audio_buffer *buffer)
58156
return &buffer->_source_api;
59157
}
60158

159+
#endif /* CONFIG_PIPELINE_2_0 */
160+
161+
/**
162+
* @brief return a handler to stream params structure
163+
*/
164+
static inline
165+
struct sof_audio_stream_params *audio_buffer_get_stream_params(struct sof_audio_buffer *buffer)
166+
{
167+
return buffer->audio_stream_params;
168+
}
169+
61170
/**
62171
* @brief return a pointer to struct sof_audio_buffer from sink pointer
63172
* NOTE! ensure that sink is really provided by sof_audio_buffer
@@ -79,18 +188,32 @@ static inline struct sof_audio_buffer *sof_audo_buffer_from_source(struct sof_so
79188
}
80189

81190
/**
82-
* @brief free buffer and all allocated resources
191+
* @brief initialize audio buffer structures
192+
*
193+
* @param buffer pointer to the audio_buffer
194+
* @param buffer_type a type of the buffer, BUFFER_TYPE_*
195+
* @param is_shared indicates if the buffer will be shared between cores
196+
* @param source_ops pointer to virtual methods table for source API
197+
* @param sink_ops pointer to virtual methods table for sink API
198+
* @param audio_stream_params pointer to audio stream (currently kept in buffer implementation)
83199
*/
84200
static inline
85-
void audio_buffer_free(struct sof_audio_buffer *buffer)
201+
void audio_buffer_init(struct sof_audio_buffer *buffer, uint32_t buffer_type, bool is_shared,
202+
const struct source_ops *source_ops, const struct sink_ops *sink_ops,
203+
struct sof_audio_stream_params *audio_stream_params)
86204
{
87-
if (!buffer)
88-
return;
89-
90-
CORE_CHECK_STRUCT(buffer);
91-
if (buffer->free)
92-
buffer->free(buffer);
93-
rfree(buffer);
205+
CORE_CHECK_STRUCT_INIT(&buffer, is_shared);
206+
buffer->buffer_type = buffer_type;
207+
buffer->audio_stream_params = audio_stream_params;
208+
source_init(audio_buffer_get_source(buffer), source_ops,
209+
audio_buffer_get_stream_params(buffer));
210+
sink_init(audio_buffer_get_sink(buffer), sink_ops,
211+
audio_buffer_get_stream_params(buffer));
94212
}
95213

214+
/**
215+
* @brief free buffer and all allocated resources
216+
*/
217+
void audio_buffer_free(struct sof_audio_buffer *buffer);
218+
96219
#endif /* __SOF_AUDIO_BUFFER__ */

zephyr/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,7 @@ zephyr_library_sources(
413413
# SOF mandatory audio processing
414414
${SOF_AUDIO_PATH}/channel_map.c
415415
${SOF_AUDIO_PATH}/buffer.c
416+
${SOF_AUDIO_PATH}/buffers/audio_buffer.c
416417
${SOF_AUDIO_PATH}/source_api_helper.c
417418
${SOF_AUDIO_PATH}/sink_api_helper.c
418419
${SOF_AUDIO_PATH}/sink_source_utils.c

0 commit comments

Comments
 (0)