module-echo-cancel: allow per stream AUDIO_POSITION settings

Keep per stream audio info. We copy the global rate and format to
everything but allow for the channel positions to be overwritten
per stream. Invalid channel positions will revert to the default
again.

With a taget.object, this makes it possible to link the echo cancel
stream to specific pro audio sink ports.

Fixes #2939
This commit is contained in:
Wim Taymans 2023-01-16 15:11:02 +01:00
parent e86acd8930
commit 68d9c33078

View file

@ -177,10 +177,12 @@ struct impl {
struct pw_properties *capture_props;
struct pw_stream *capture;
struct spa_hook capture_listener;
struct spa_audio_info_raw capture_info;
struct pw_properties *source_props;
struct pw_stream *source;
struct spa_hook source_listener;
struct spa_audio_info_raw source_info;
void *rec_buffer[SPA_AUDIO_MAX_CHANNELS];
uint32_t rec_ringsize;
@ -189,6 +191,7 @@ struct impl {
struct pw_properties *playback_props;
struct pw_stream *playback;
struct spa_hook playback_listener;
struct spa_audio_info_raw playback_info;
struct pw_properties *sink_props;
struct pw_stream *sink;
@ -197,6 +200,7 @@ struct impl {
uint32_t play_ringsize;
struct spa_ringbuffer play_ring;
struct spa_ringbuffer play_delayed_ring;
struct spa_audio_info_raw sink_info;
void *out_buffer[SPA_AUDIO_MAX_CHANNELS];
uint32_t out_ringsize;
@ -826,7 +830,7 @@ static int setup_streams(struct impl *impl)
spa_pod_dynamic_builder_init(&b, NULL, 0, 4096);
offsets[n_params++] = b.b.state.offset;
spa_format_audio_raw_build(&b.b, SPA_PARAM_EnumFormat, &impl->info);
spa_format_audio_raw_build(&b.b, SPA_PARAM_EnumFormat, &impl->capture_info);
int nbr_of_external_props = spa_audio_aec_enum_props(impl->aec, 0, NULL);
if (nbr_of_external_props > 0) {
@ -837,9 +841,8 @@ static int setup_streams(struct impl *impl)
get_props_param(impl, &b.b);
}
for (i = 0; i < n_params; i++) {
for (i = 0; i < n_params; i++)
params[i] = spa_pod_builder_deref(&b.b, offsets[i]);
}
if ((res = pw_stream_connect(impl->capture,
PW_DIRECTION_INPUT,
@ -852,6 +855,12 @@ static int setup_streams(struct impl *impl)
return res;
}
offsets[0] = b.b.state.offset;
spa_format_audio_raw_build(&b.b, SPA_PARAM_EnumFormat, &impl->source_info);
for (i = 0; i < n_params; i++)
params[i] = spa_pod_builder_deref(&b.b, offsets[i]);
if ((res = pw_stream_connect(impl->source,
PW_DIRECTION_OUTPUT,
PW_ID_ANY,
@ -862,6 +871,12 @@ static int setup_streams(struct impl *impl)
return res;
}
offsets[0] = b.b.state.offset;
spa_format_audio_raw_build(&b.b, SPA_PARAM_EnumFormat, &impl->sink_info);
for (i = 0; i < n_params; i++)
params[i] = spa_pod_builder_deref(&b.b, offsets[i]);
if ((res = pw_stream_connect(impl->sink,
PW_DIRECTION_INPUT,
PW_ID_ANY,
@ -873,6 +888,12 @@ static int setup_streams(struct impl *impl)
return res;
}
offsets[0] = b.b.state.offset;
spa_format_audio_raw_build(&b.b, SPA_PARAM_EnumFormat, &impl->playback_info);
for (i = 0; i < n_params; i++)
params[i] = spa_pod_builder_deref(&b.b, offsets[i]);
if (impl->playback != NULL && (res = pw_stream_connect(impl->playback,
PW_DIRECTION_OUTPUT,
PW_ID_ANY,
@ -1104,6 +1125,11 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args)
parse_audio_info(props, &impl->info);
impl->capture_info = impl->info;
impl->source_info = impl->info;
impl->sink_info = impl->info;
impl->playback_info = impl->info;
if ((str = pw_properties_get(props, "capture.props")) != NULL)
pw_properties_update_string(impl->capture_props, str, strlen(str));
if ((str = pw_properties_get(props, "source.props")) != NULL)
@ -1257,6 +1283,24 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args)
copy_props(impl, props, SPA_KEY_AUDIO_POSITION);
copy_props(impl, props, "resample.prefill");
if ((str = pw_properties_get(impl->capture_props, SPA_KEY_AUDIO_POSITION)) != NULL)
parse_position(&impl->capture_info, str, strlen(str));
if ((str = pw_properties_get(impl->source_props, SPA_KEY_AUDIO_POSITION)) != NULL)
parse_position(&impl->source_info, str, strlen(str));
if ((str = pw_properties_get(impl->sink_props, SPA_KEY_AUDIO_POSITION)) != NULL)
parse_position(&impl->sink_info, str, strlen(str));
if ((str = pw_properties_get(impl->playback_props, SPA_KEY_AUDIO_POSITION)) != NULL)
parse_position(&impl->playback_info, str, strlen(str));
if (impl->capture_info.channels != impl->info.channels)
impl->capture_info = impl->info;
if (impl->source_info.channels != impl->info.channels)
impl->source_info = impl->info;
if (impl->sink_info.channels != impl->info.channels)
impl->sink_info = impl->info;
if (impl->playback_info.channels != impl->info.channels)
impl->playback_info = impl->info;
impl->max_buffer_size = pw_properties_get_uint32(props,"buffer.max_size", MAX_BUFSIZE_MS);
if ((str = pw_properties_get(props, "buffer.play_delay")) != NULL) {