Skip to content

Commit

Permalink
google_rtc_audio_processing: Add trigger handler for pipeline control
Browse files Browse the repository at this point in the history
The reference playback stream for this component is from a different
pipeline in another direction, and SOF does not handle this well or
consistently.  Add a trigger handler to avoid pitfalls:

Drop and ignore commands arriving from the foreign reference pipeline.
They aren't for us.  Traditionally SOF has tried to propagate pipeline
startup to connected pipelines, but this never worked correctly for
opposite-direction connections like this one.  And IPC4 now has
removed (I think) almost all of the cross-pipeline trigger propagation
anyway.

Call into comp_new_state() directly to avoid some IPC3-only logic in
module_adapter_set_state() that would fail pipeline startup if there
were sources that were already active at the time of the PRE_START
command (I guess it was treating this as invalid, because the pipeline
should be off at PRE_START -- but the reference stream is on a
different pipeline and can be on if playback is active!)

The net effect is that this corrects the AEC component lifecycle to
work either with or without an active reference pipeline, though as of
this patch the data-less reference stream will still stall if you try
to open capture without playback already running.

Signed-off-by: Andy Ross <[email protected]>
  • Loading branch information
andyross committed Dec 5, 2023
1 parent 482e83b commit 26d90cc
Showing 1 changed file with 45 additions and 0 deletions.
45 changes: 45 additions & 0 deletions src/audio/google/google_rtc_audio_processing.c
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,50 @@ static int google_rtc_audio_processing_prepare(struct processing_module *mod,
return 0;
}

/* Extracts connected buffer pointers. Clumsy, should cache in comp_data */
static void find_bufs(struct processing_module *mod, struct comp_buffer **mic,
struct comp_buffer **ref, struct comp_buffer **out)
{
struct google_rtc_audio_processing_comp_data *cd = module_get_private_data(mod);
struct list_item *li;
int i = 0;

list_for_item(li, &mod->dev->bsource_list) {
struct comp_buffer *b = container_of(li, struct comp_buffer,
sink_list);
if (i == cd->raw_microphone_source)
*mic = b;
else if (i == cd->aec_reference_source)
*ref = b;
i++;
}

*out = list_first_item(&mod->dev->bsink_list,
struct comp_buffer, source_list);
}

static int trigger_handler(struct processing_module *mod, int cmd)
{
struct comp_buffer *mic, *ref, *out;

find_bufs(mod, &mic, &ref, &out);

/* Ignore and halt propagation if we get a trigger from the
* playback pipeline: not for us.
*/
if (ref->walking)
return PPL_STATUS_PATH_STOP;

/* Note: not module_adapter_set_state(). With IPC4 those are
* identical, but IPC3 has some odd-looking logic that
* validates that no sources are active when receiving a
* PRE_START command, which obviously breaks for our reference
* stream if playback was already running when our pipeline
* started
*/
return comp_set_state(mod->dev, cmd);
}

static int google_rtc_audio_processing_reset(struct processing_module *mod)
{
comp_dbg(mod->dev, "google_rtc_audio_processing_reset()");
Expand Down Expand Up @@ -710,6 +754,7 @@ static struct module_interface google_rtc_audio_processing_interface = {
.prepare = google_rtc_audio_processing_prepare,
.set_configuration = google_rtc_audio_processing_set_config,
.get_configuration = google_rtc_audio_processing_get_config,
.trigger = trigger_handler,
.reset = google_rtc_audio_processing_reset,
};

Expand Down

0 comments on commit 26d90cc

Please sign in to comment.