From 571e207c3ae411b7b74ed18bb6a98388ee6047a8 Mon Sep 17 00:00:00 2001 From: Seppo Ingalsuo Date: Wed, 7 Jun 2023 14:08:37 +0300 Subject: [PATCH] Audio: Module adapter: Add a new simple copy function This patch adds a simplified version of simple copy for module adapter clients with one source and one sink. The overhead of discovering multiple source and sink buffers is avoided. The module_adapter_bind() and module_adapter_unbind() functions are changed to detect multiple sources or sinks condition to control the used simple copy function. Signed-off-by: Seppo Ingalsuo --- src/audio/module_adapter/module_adapter.c | 98 +++++++++++++++++++ .../sof/audio/module_adapter/module/generic.h | 9 ++ 2 files changed, 107 insertions(+) diff --git a/src/audio/module_adapter/module_adapter.c b/src/audio/module_adapter/module_adapter.c index fc0705ab9861..5a47a9a229df 100644 --- a/src/audio/module_adapter/module_adapter.c +++ b/src/audio/module_adapter/module_adapter.c @@ -245,6 +245,20 @@ int module_adapter_prepare(struct comp_dev *dev) return -EINVAL; } + /* Check if simple copy client has only one source and one sink buffer to use a + * simplified copy function. The multi_source_or_sink is set later to true + * if module_adapter_bind() indicates multiple sources. + */ + if (mod->simple_copy && mod->num_input_buffers == 1 && mod->num_output_buffers == 1) { + mod->source = list_first_item(&dev->bsource_list, struct comp_buffer, sink_list); + mod->sink = sink; + mod->multi_source_or_sink = false; + } else { + mod->source = NULL; + mod->sink = NULL; + mod->multi_source_or_sink = true; + } + /* allocate memory for input buffers */ if (mod->num_input_buffers) { mod->input_buffers = @@ -825,6 +839,56 @@ static int module_adapter_simple_copy(struct comp_dev *dev) return ret; } +static int module_adapter_simple_copy_1to1(struct processing_module *mod) +{ + struct comp_buffer __sparse_cache *source_c; + struct comp_buffer __sparse_cache *sink_c; + struct comp_dev *dev = mod->dev; + uint32_t frames; + int ret; + + source_c = buffer_acquire(mod->source); + sink_c = buffer_acquire(mod->sink); + frames = audio_stream_avail_frames_aligned(&source_c->stream, &sink_c->stream); + mod->input_buffers[0].size = frames; + mod->input_buffers[0].consumed = 0; + mod->input_buffers[0].data = &source_c->stream; + mod->output_buffers[0].size = 0; + mod->output_buffers[0].data = &sink_c->stream; + if (!mod->skip_src_buffer_invalidate) /* TODO: add mod->is_multi_core && */ + buffer_stream_invalidate(source_c, + frames * audio_stream_frame_bytes(&source_c->stream)); + + ret = module_process(mod, mod->input_buffers, 1, mod->output_buffers, 1); + if (ret) { + if (ret != -ENOSPC && ret != -ENODATA) { + comp_err(dev, "module_adapter_simple_copy_1to1(), process failed: %d", ret); + goto out; + } + + ret = 0; + } + + /* consume from input buffer */ + mod->total_data_consumed += mod->input_buffers[0].consumed; + if (mod->input_buffers[0].consumed) + audio_stream_consume(&source_c->stream, mod->input_buffers[0].consumed); + + /* produce data into all active output buffers */ + mod->total_data_produced += mod->output_buffers[0].size; + if (!mod->skip_sink_buffer_writeback) /* TODO: add mod->is_multi_core && */ + buffer_stream_writeback(sink_c, mod->output_buffers[0].size); + + if (mod->output_buffers[0].size) + audio_stream_produce(&sink_c->stream, mod->output_buffers[0].size); + +out: + /* release all buffers */ + buffer_release(sink_c); + buffer_release(source_c); + return ret; +} + int module_adapter_copy(struct comp_dev *dev) { struct processing_module *mod = comp_get_drvdata(dev); @@ -838,6 +902,9 @@ int module_adapter_copy(struct comp_dev *dev) comp_dbg(dev, "module_adapter_copy(): start"); + if (!mod->multi_source_or_sink) + return module_adapter_simple_copy_1to1(mod); + if (mod->simple_copy) return module_adapter_simple_copy(dev); @@ -1275,6 +1342,25 @@ int module_adapter_get_attribute(struct comp_dev *dev, uint32_t type, void *valu return 0; } +static bool module_adapter_multi_sink_source_check(struct comp_dev *dev) +{ + struct list_item *blist; + int num_sources = 0; + int num_sinks = 0; + + list_for_item(blist, &dev->bsource_list) + num_sources++; + + list_for_item(blist, &dev->bsink_list) + num_sinks++; + + comp_dbg(dev, "num_sources=%d num_sinks=%d", num_sources, num_sinks); + if (num_sources > 1 || num_sinks > 1) + return true; + else + return false; +} + int module_adapter_bind(struct comp_dev *dev, void *data) { struct module_source_info __sparse_cache *mod_source_info; @@ -1319,6 +1405,12 @@ int module_adapter_bind(struct comp_dev *dev, void *data) /* set the source dev pointer */ mod_source_info->sources[source_index] = source_dev; + /* Disable 1 source 1 sink simple copy mode if multiple source buffers */ + if (module_adapter_multi_sink_source_check(dev)) { + comp_dbg(dev, "module_adapter_bind(), multi_sink_or_source = true"); + mod->multi_source_or_sink = true; + } + module_source_info_release(mod_source_info); return 0; @@ -1353,6 +1445,12 @@ int module_adapter_unbind(struct comp_dev *dev, void *data) if (source_index >= 0) mod_source_info->sources[source_index] = NULL; + /* Re-enable 1 source 1 sink simple copy mode if single source buffer */ + if (mod->simple_copy && !module_adapter_multi_sink_source_check(dev)) { + comp_dbg(dev, "module_adapter_bind(), multi_sink_or_source = false"); + mod->multi_source_or_sink = false; + } + module_source_info_release(mod_source_info); return 0; diff --git a/src/include/sof/audio/module_adapter/module/generic.h b/src/include/sof/audio/module_adapter/module/generic.h index f0bc0a4c539c..111d0c89391e 100644 --- a/src/include/sof/audio/module_adapter/module/generic.h +++ b/src/include/sof/audio/module_adapter/module/generic.h @@ -184,6 +184,10 @@ struct processing_module { struct output_stream_buffer *output_buffers; uint32_t num_input_buffers; /**< number of input buffers */ uint32_t num_output_buffers; /**< number of output buffers */ + + struct comp_buffer *source; + struct comp_buffer *sink; + /* * flag set by a module that produces period_bytes every copy. It can be used by modules * that support 1:1, 1:N, N:1 sources:sinks configuration. @@ -208,6 +212,11 @@ struct processing_module { */ bool skip_src_buffer_invalidate; + /* False for module with one sink and one source to simplify copy operations. True if + * multiple source or sink buffers. + */ + bool multi_source_or_sink; + /* table containing the list of connected sources */ struct module_source_info *source_info;