Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pipeline2.0 STEP2 - move hybrid buffering logic from comp_buffer to audio_buffer and partially place comp_buffer on top of audio_buffer #9299

Merged
merged 6 commits into from
Sep 2, 2024
6 changes: 4 additions & 2 deletions src/audio/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@ if(NOT CONFIG_COMP_MODULE_SHARED_LIBRARY_BUILD)
add_local_sources(sof
host-legacy.c
component.c
buffer.c
source_api_helper.c
sink_api_helper.c
sink_source_utils.c
audio_stream.c
channel_map.c
)

add_subdirectory(buffers)

if(CONFIG_COMP_BLOB)
add_local_sources(sof data_blob.c)
endif()
Expand Down Expand Up @@ -128,7 +129,8 @@ endif()
add_local_sources(sof
component.c
data_blob.c
buffer.c
buffers/comp_buffer.c
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can do this in the next PR if needed (as CI is good), but does it make sense to rename like other similar files to legacy-buffer.c ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

legacy-buffer.c
looks as a good idea
also struct comp_buffer ==> struct legacy_buffer
it will be a clear sign that an API is depreciated

buffers/audio_buffer.c
source_api_helper.c
sink_api_helper.c
sink_source_utils.c
Expand Down
181 changes: 0 additions & 181 deletions src/audio/audio_stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,67 +9,6 @@
#include <sof/audio/audio_buffer.h>
#include <sof/audio/buffer.h>

static size_t audio_stream_get_free_size(struct sof_sink *sink)
{
struct audio_stream *audio_stream = container_of(sink, struct audio_stream, _sink_api);

return audio_stream_get_free_bytes(audio_stream);
}

static int audio_stream_get_buffer(struct sof_sink *sink, size_t req_size,
void **data_ptr, void **buffer_start, size_t *buffer_size)
{
struct audio_stream *audio_stream = container_of(sink, struct audio_stream, _sink_api);

if (req_size > audio_stream_get_free_size(sink))
return -ENODATA;

/* get circular buffer parameters */
*data_ptr = audio_stream->w_ptr;
*buffer_start = audio_stream->addr;
*buffer_size = audio_stream->size;
return 0;
}

static int audio_stream_commit_buffer(struct sof_sink *sink, size_t commit_size)
{
struct audio_stream *audio_stream = container_of(sink, struct audio_stream, _sink_api);
struct comp_buffer *buffer = container_of(audio_stream, struct comp_buffer, stream);

if (commit_size) {
buffer_stream_writeback(buffer, commit_size);
audio_stream_produce(audio_stream, commit_size);
}

return 0;
}

static size_t audio_stream_get_data_available(struct sof_source *source)
{
struct audio_stream *audio_stream = container_of(source, struct audio_stream, _source_api);

return audio_stream_get_avail_bytes(audio_stream);
}

static int audio_stream_get_data(struct sof_source *source, size_t req_size,
void const **data_ptr, void const **buffer_start,
size_t *buffer_size)
{
struct audio_stream *audio_stream = container_of(source, struct audio_stream, _source_api);
struct comp_buffer *buffer = container_of(audio_stream, struct comp_buffer, stream);

if (req_size > audio_stream_get_data_available(source))
return -ENODATA;

buffer_stream_invalidate(buffer, req_size);

/* get circular buffer parameters */
*data_ptr = audio_stream->r_ptr;
*buffer_start = audio_stream->addr;
*buffer_size = audio_stream->size;
return 0;
}

static uint32_t audio_stream_frame_align_get(const uint32_t byte_align,
const uint32_t frame_align_req,
uint32_t frame_size)
Expand Down Expand Up @@ -105,132 +44,12 @@ void audio_stream_set_align(const uint32_t byte_align,
audio_stream_recalc_align(stream);
}
EXPORT_SYMBOL(audio_stream_set_align);

static int audio_stream_release_data(struct sof_source *source, size_t free_size)
{
struct audio_stream *audio_stream = container_of(source, struct audio_stream, _source_api);

if (free_size)
audio_stream_consume(audio_stream, free_size);

return 0;
}

static int audio_stream_set_ipc_params_source(struct sof_source *source,
struct sof_ipc_stream_params *params,
bool force_update)
{
struct audio_stream *audio_stream = container_of(source, struct audio_stream, _source_api);
struct comp_buffer *buffer = container_of(audio_stream, struct comp_buffer, stream);

return buffer_set_params(buffer, params, force_update);
}

static int audio_stream_set_ipc_params_sink(struct sof_sink *sink,
struct sof_ipc_stream_params *params,
bool force_update)
{
struct audio_stream *audio_stream = container_of(sink, struct audio_stream, _sink_api);
struct comp_buffer *buffer = container_of(audio_stream, struct comp_buffer, stream);

return buffer_set_params(buffer, params, force_update);
}

static int audio_stream_source_set_alignment_constants(struct sof_source *source,
const uint32_t byte_align,
const uint32_t frame_align_req)
{
struct audio_stream *audio_stream = container_of(source, struct audio_stream, _source_api);

audio_stream_set_align(byte_align, frame_align_req, audio_stream);

return 0;
}

static int audio_stream_sink_set_alignment_constants(struct sof_sink *sink,
const uint32_t byte_align,
const uint32_t frame_align_req)
{
struct audio_stream *audio_stream = container_of(sink, struct audio_stream, _sink_api);

audio_stream_set_align(byte_align, frame_align_req, audio_stream);

return 0;
}

static int source_format_set(struct sof_source *source)
{
struct audio_stream *s = container_of(source, struct audio_stream, _source_api);

audio_stream_recalc_align(s);
return 0;
}

static int sink_format_set(struct sof_sink *sink)
{
struct audio_stream *s = container_of(sink, struct audio_stream, _sink_api);

audio_stream_recalc_align(s);
return 0;
}

static const struct source_ops audio_stream_source_ops = {
.get_data_available = audio_stream_get_data_available,
.get_data = audio_stream_get_data,
.release_data = audio_stream_release_data,
.audio_set_ipc_params = audio_stream_set_ipc_params_source,
.on_audio_format_set = source_format_set,
.set_alignment_constants = audio_stream_source_set_alignment_constants
};

static const struct sink_ops audio_stream_sink_ops = {
.get_free_size = audio_stream_get_free_size,
.get_buffer = audio_stream_get_buffer,
.commit_buffer = audio_stream_commit_buffer,
.audio_set_ipc_params = audio_stream_set_ipc_params_sink,
.on_audio_format_set = sink_format_set,
.set_alignment_constants = audio_stream_sink_set_alignment_constants
};

void audio_stream_init(struct audio_stream *audio_stream, void *buff_addr, uint32_t size)
{
audio_stream->size = size;
audio_stream->addr = buff_addr;
audio_stream->end_addr = (char *)audio_stream->addr + size;

audio_stream_set_align(1, 1, audio_stream);
source_init(audio_stream_get_source(audio_stream), &audio_stream_source_ops,
&audio_stream->runtime_stream_params);
sink_init(audio_stream_get_sink(audio_stream), &audio_stream_sink_ops,
&audio_stream->runtime_stream_params);
audio_stream_reset(audio_stream);
}

/* get a handler to source API */
#if CONFIG_PIPELINE_2_0
struct sof_source *audio_stream_get_source(struct audio_stream *audio_stream)
{
return audio_stream->secondary_buffer_source ?
audio_buffer_get_source(audio_stream->secondary_buffer_source) :
&audio_stream->_source_api;
}

struct sof_sink *audio_stream_get_sink(struct audio_stream *audio_stream)
{
return audio_stream->secondary_buffer_sink ?
audio_buffer_get_sink(audio_stream->secondary_buffer_sink) :
&audio_stream->_sink_api;
}

#else /* CONFIG_PIPELINE_2_0 */

struct sof_source *audio_stream_get_source(struct audio_stream *audio_stream)
{
return &audio_stream->_source_api;
}

struct sof_sink *audio_stream_get_sink(struct audio_stream *audio_stream)
{
return &audio_stream->_sink_api;
}
#endif /* CONFIG_PIPELINE_2_0 */
8 changes: 8 additions & 0 deletions src/audio/buffers/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# SPDX-License-Identifier: BSD-3-Clause

add_local_sources(sof audio_buffer.c)
add_local_sources(sof comp_buffer.c)

if(CONFIG_PIPELINE_2_0)
add_local_sources(sof ring_buffer.c)
endif()
97 changes: 97 additions & 0 deletions src/audio/buffers/audio_buffer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// SPDX-License-Identifier: BSD-3-Clause
//
// Copyright(c) 2024 Intel Corporation. All rights reserved.
//
// Author: Marcin Szkudlinski <[email protected]>

#include <stdint.h>
#include <stddef.h>
#include <errno.h>
#include <rtos/alloc.h>
#include <sof/audio/audio_buffer.h>
#include <sof/audio/sink_api.h>
#include <sof/audio/source_api.h>
#include <sof/audio/sink_source_utils.h>

#if CONFIG_PIPELINE_2_0

int audio_buffer_attach_secondary_buffer(struct sof_audio_buffer *buffer, bool at_input,
struct sof_audio_buffer *secondary_buffer)
{
if (buffer->secondary_buffer_sink || buffer->secondary_buffer_source)
return -EINVAL;

/* secondary buffer must share audio params with the primary buffer */
secondary_buffer->audio_stream_params = buffer->audio_stream_params;
/* for performance reasons pointers to params are also kept in sink/src structures */
secondary_buffer->_sink_api.audio_stream_params = buffer->audio_stream_params;
secondary_buffer->_source_api.audio_stream_params = buffer->audio_stream_params;
Copy link
Collaborator

@lyakh lyakh Sep 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this seems to make 3 copies of stream parameters, so now we have 4 of them on the total? This seems really redundant. Is this a temporary situation until buffers are migrated to the new API? Maybe make one of them where it finally should be and use pointers at all other locations? TBH I'm a bit confused about the roadmap of the migration, how far we're into it and what is still left to do. @marcinszkudlinski maybe you could make a "feature" to explain the steps made so far, the current configuration (what types of buffers we currently have, what copying is done, etc.) and the roadmap?


if (at_input)
buffer->secondary_buffer_sink = secondary_buffer;
else
buffer->secondary_buffer_source = secondary_buffer;

return 0;
}

int audio_buffer_sync_secondary_buffer(struct sof_audio_buffer *buffer, size_t limit)
{
int err;

struct sof_source *data_src;
struct sof_sink *data_dst;

if (buffer->secondary_buffer_sink) {
/*
* audio_buffer sink API is shadowed, that means there's a secondary_buffer
* at data input
* get data from secondary_buffer (use source API)
* copy to primary buffer (use sink API)
* note! can't use audio_buffer_get_sink because it will provide a shadowed
* sink handler (to a secondary buffer).
*/
data_src = audio_buffer_get_source(buffer->secondary_buffer_sink);
data_dst = &buffer->_sink_api; /* primary buffer's sink API */
} else if (buffer->secondary_buffer_source) {
/*
* comp_buffer source API is shadowed, that means there's a secondary_buffer
* at data output
* get data from comp_buffer (use source API)
* copy to secondary_buffer (use sink API)
*/
data_src = &buffer->_source_api;
data_dst = audio_buffer_get_sink(buffer->secondary_buffer_source);

} else {
return -EINVAL;
}

/*
* keep data_available and free_size in local variables to avoid check_time/use_time
* race in MIN macro
*/
size_t data_available = source_get_data_available(data_src);
size_t free_size = sink_get_free_size(data_dst);
size_t to_copy = MIN(MIN(data_available, free_size), limit);

err = source_to_sink_copy(data_src, data_dst, true, to_copy);
return err;
}

#endif /* CONFIG_PIPELINE_2_0 */

void audio_buffer_free(struct sof_audio_buffer *buffer)
{
if (!buffer)
return;

CORE_CHECK_STRUCT(buffer);
#if CONFIG_PIPELINE_2_0
audio_buffer_free(buffer->secondary_buffer_sink);
audio_buffer_free(buffer->secondary_buffer_source);
#endif /* CONFIG_PIPELINE_2_0 */
if (buffer->ops->free)
buffer->ops->free(buffer);
rfree(buffer);
}
Loading