demux: Support inactive cross-pipeline sinks

It may happen that a demux is configured to write to a buffer in a
stopped pipeline (consider echo cancellation when the mic is not in
use: the output reference stream has nowhere to go).  This doesn't
work in the tree currently; the general pipeline design is to try to
turn on pipes that are required, but that's incomplete for the case
(again, echo cancellation) where the pipelines are oriented in
different directions and in any case is undesirable as a microphone
stream shouldn't be required to be active for playback to work.

Instead, detect the situation at PRE_START time, configure the output
buffers overrun_permitted (as there may not be a reader), and drop the
unconfigured streams dynamically at process() time, as the target
pipeline may be started up at arbitrary moments.  When it starts,
we'll begin emitting output at the first process callback as desired.

Signed-off-by: Andy Ross <andyross@google.com>
This commit is contained in:
Andy Ross 2023-11-28 18:17:04 -08:00 committed by Kai Vehmanen
parent ddf70fa033
commit 33ef5f6a7d
1 changed files with 32 additions and 3 deletions

View File

@ -270,9 +270,12 @@ static int demux_process(struct processing_module *mod,
/* produce output, one sink at a time */
for (i = 0; i < num_output_buffers; i++) {
if (sinks_stream[i]) {
demux_prepare_active_look_up(cd, sinks_stream[i],
input_buffers[0].data, look_ups[i]);
cd->demux(dev, sinks_stream[i], input_buffers[0].data, frames, &cd->active_lookup);
cd->demux(dev, sinks_stream[i], input_buffers[0].data,
frames, &cd->active_lookup);
}
mod->output_buffers[i].size = sink_bytes;
}
@ -453,6 +456,31 @@ static int mux_set_config(struct processing_module *mod, uint32_t config_id,
fragment, fragment_size);
}
static int demux_trigger(struct processing_module *mod, int cmd)
{
struct list_item *li;
struct comp_buffer *b;
/* Check for cross-pipeline sinks: in general foreign
* pipelines won't be started synchronously with ours (it's
* under control of host software), so output can't be
* guaranteed not to overflow. Always set the
* overrun_permitted flag. These sink components are assumed
* responsible for flushing/synchronizing the stream
* themselves.
*/
if (cmd == COMP_TRIGGER_PRE_START) {
list_for_item(li, &mod->dev->bsink_list) {
b = container_of(li, struct comp_buffer, source_list);
if (b->sink->pipeline != mod->dev->pipeline)
audio_stream_set_overrun(&b->stream, true);
}
}
return module_adapter_set_state(mod, mod->dev, cmd);
}
static const struct module_interface mux_interface = {
.init = mux_init,
.set_configuration = mux_set_config,
@ -472,6 +500,7 @@ static const struct module_interface demux_interface = {
.get_configuration = mux_get_config,
.prepare = mux_prepare,
.process_audio_stream = demux_process,
.trigger = demux_trigger,
.reset = mux_reset,
.free = mux_free,
};