mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-02 09:01:50 -05:00
module-echo-cancel: aec-plugin parameters
Make it possible for a aec-plugin to provide props/params through module-echo-cancel and make it possible for a aec-plugin to listen and react to these props/params getting updated. Add method enum_props() that is used under setup_streams() to get props from aec_plugin. Add get_params() and set_params() for updating and getting aec-plugin params under the input/output_param_changed calls and getting params under setup_streams().
This commit is contained in:
parent
2086fa5ad2
commit
b35983eb7e
2 changed files with 112 additions and 14 deletions
|
|
@ -23,6 +23,7 @@
|
|||
*/
|
||||
|
||||
|
||||
#include <spa/pod/builder.h>
|
||||
#include <spa/utils/dict.h>
|
||||
#include <spa/utils/hook.h>
|
||||
#include <spa/param/audio/raw.h>
|
||||
|
|
@ -60,7 +61,7 @@ struct spa_audio_aec_events {
|
|||
};
|
||||
|
||||
struct spa_audio_aec_methods {
|
||||
#define SPA_VERSION_AUDIO_AEC_METHODS 1
|
||||
#define SPA_VERSION_AUDIO_AEC_METHODS 2
|
||||
uint32_t version;
|
||||
|
||||
int (*add_listener) (void *object,
|
||||
|
|
@ -75,6 +76,11 @@ struct spa_audio_aec_methods {
|
|||
int (*activate) (void *object);
|
||||
/* since 0.3.58, version 1:1 */
|
||||
int (*deactivate) (void *object);
|
||||
|
||||
/* version 1:2 */
|
||||
int (*enum_props) (void* object, int index, struct spa_pod_builder* builder);
|
||||
int (*get_params) (void* object, struct spa_pod_builder* builder);
|
||||
int (*set_params) (void *object, const struct spa_pod *args);
|
||||
};
|
||||
|
||||
#define spa_audio_aec_method(o,method,version,...) \
|
||||
|
|
@ -93,6 +99,9 @@ struct spa_audio_aec_methods {
|
|||
#define spa_audio_aec_set_props(o,...) spa_audio_aec_method(o, set_props, 0, __VA_ARGS__)
|
||||
#define spa_audio_aec_activate(o) spa_audio_aec_method(o, activate, 1)
|
||||
#define spa_audio_aec_deactivate(o) spa_audio_aec_method(o, deactivate, 1)
|
||||
#define spa_audio_aec_enum_props(o,...) spa_audio_aec_method(o, enum_props, 2, __VA_ARGS__)
|
||||
#define spa_audio_aec_get_params(o,...) spa_audio_aec_method(o, get_params, 2, __VA_ARGS__)
|
||||
#define spa_audio_aec_set_params(o,...) spa_audio_aec_method(o, set_params, 2, __VA_ARGS__)
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
#include <spa/param/audio/raw.h>
|
||||
#include <spa/param/profiler.h>
|
||||
#include <spa/pod/builder.h>
|
||||
#include <spa/pod/dynamic.h>
|
||||
#include <spa/support/plugin.h>
|
||||
#include <spa/utils/json.h>
|
||||
#include <spa/utils/names.h>
|
||||
|
|
@ -504,14 +505,55 @@ static void input_param_latency_changed(struct impl *impl, const struct spa_pod
|
|||
else
|
||||
pw_stream_update_params(impl->capture, params, 1);
|
||||
}
|
||||
|
||||
static void input_param_changed(void *data, uint32_t id, const struct spa_pod *param)
|
||||
static struct spa_pod* get_props_param(struct impl* impl, struct spa_pod_builder* b)
|
||||
{
|
||||
struct impl *impl = data;
|
||||
if (spa_audio_aec_get_params(impl->aec, NULL) > 0) {
|
||||
struct spa_pod_frame f[2];
|
||||
spa_pod_builder_push_object(
|
||||
b, &f[0], SPA_TYPE_OBJECT_Props, SPA_PARAM_Props);
|
||||
spa_pod_builder_prop(b, SPA_PROP_params, 0);
|
||||
spa_pod_builder_push_struct(b, &f[1]);
|
||||
|
||||
spa_audio_aec_get_params(impl->aec, b);
|
||||
|
||||
spa_pod_builder_pop(b, &f[1]);
|
||||
return spa_pod_builder_pop(b, &f[0]);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void input_param_changed(void *data, uint32_t id, const struct spa_pod* param)
|
||||
{
|
||||
struct spa_pod_object* obj = (struct spa_pod_object*)param;
|
||||
const struct spa_pod_prop* prop;
|
||||
struct impl* impl = data;
|
||||
switch (id) {
|
||||
case SPA_PARAM_Latency:
|
||||
input_param_latency_changed(impl, param);
|
||||
break;
|
||||
case SPA_PARAM_Props:
|
||||
if (param != NULL) {
|
||||
uint8_t buffer[1024];
|
||||
struct spa_pod_dynamic_builder b;
|
||||
const struct spa_pod* params[1];
|
||||
SPA_POD_OBJECT_FOREACH(obj, prop)
|
||||
{
|
||||
if (prop->key == SPA_PROP_params) {
|
||||
spa_audio_aec_set_params(impl->aec, &prop->value);
|
||||
}
|
||||
}
|
||||
|
||||
spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096);
|
||||
params[0] = get_props_param(impl, &b.b);
|
||||
if (params[0]) {
|
||||
pw_stream_update_params(impl->capture, params, 1);
|
||||
pw_stream_update_params(impl->playback, params, 1);
|
||||
}
|
||||
spa_pod_dynamic_builder_clean(&b);
|
||||
} else {
|
||||
pw_log_warn("param is null");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -582,11 +624,34 @@ static void output_param_latency_changed(struct impl *impl, const struct spa_pod
|
|||
|
||||
static void output_param_changed(void *data, uint32_t id, const struct spa_pod *param)
|
||||
{
|
||||
struct spa_pod_object *obj = (struct spa_pod_object *) param;
|
||||
const struct spa_pod_prop *prop;
|
||||
struct impl *impl = data;
|
||||
switch (id) {
|
||||
case SPA_PARAM_Latency:
|
||||
output_param_latency_changed(impl, param);
|
||||
break;
|
||||
case SPA_PARAM_Props:
|
||||
if (param != NULL) {
|
||||
uint8_t buffer[1024];
|
||||
struct spa_pod_dynamic_builder b;
|
||||
const struct spa_pod* params[1];
|
||||
|
||||
SPA_POD_OBJECT_FOREACH(obj, prop)
|
||||
{
|
||||
if (prop->key == SPA_PROP_params) {
|
||||
spa_audio_aec_set_params(impl->aec, &prop->value);
|
||||
}
|
||||
}
|
||||
spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096);
|
||||
params[0] = get_props_param(impl, &b.b);
|
||||
if (params[0] != NULL) {
|
||||
pw_stream_update_params(impl->capture, params, 1);
|
||||
pw_stream_update_params(impl->playback, params, 1);
|
||||
}
|
||||
spa_pod_dynamic_builder_clean(&b);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -685,9 +750,9 @@ static int setup_streams(struct impl *impl)
|
|||
{
|
||||
int res;
|
||||
uint32_t n_params, i;
|
||||
const struct spa_pod *params[1];
|
||||
uint8_t buffer[1024];
|
||||
struct spa_pod_builder b;
|
||||
uint32_t offsets[512];
|
||||
const struct spa_pod *params[512];
|
||||
struct spa_pod_dynamic_builder b;
|
||||
struct pw_properties *props;
|
||||
const char *str;
|
||||
uint32_t index;
|
||||
|
|
@ -771,9 +836,23 @@ static int setup_streams(struct impl *impl)
|
|||
&sink_events, impl);
|
||||
|
||||
n_params = 0;
|
||||
spa_pod_builder_init(&b, buffer, sizeof(buffer));
|
||||
params[n_params++] = spa_format_audio_raw_build(&b, SPA_PARAM_EnumFormat,
|
||||
&impl->info);
|
||||
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);
|
||||
|
||||
int nbr_of_external_props = spa_audio_aec_enum_props(impl->aec, 0, NULL);
|
||||
if (nbr_of_external_props > 0) {
|
||||
for (int i = 0; i < nbr_of_external_props; i++) {
|
||||
offsets[n_params++] = b.b.state.offset;
|
||||
spa_audio_aec_enum_props(impl->aec, i, &b.b);
|
||||
}
|
||||
get_props_param(impl, &b.b);
|
||||
}
|
||||
|
||||
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,
|
||||
|
|
@ -781,24 +860,30 @@ static int setup_streams(struct impl *impl)
|
|||
PW_STREAM_FLAG_AUTOCONNECT |
|
||||
PW_STREAM_FLAG_MAP_BUFFERS |
|
||||
PW_STREAM_FLAG_RT_PROCESS,
|
||||
params, n_params)) < 0)
|
||||
params, n_params)) < 0) {
|
||||
spa_pod_dynamic_builder_clean(&b);
|
||||
return res;
|
||||
}
|
||||
|
||||
if ((res = pw_stream_connect(impl->source,
|
||||
PW_DIRECTION_OUTPUT,
|
||||
PW_ID_ANY,
|
||||
PW_STREAM_FLAG_MAP_BUFFERS |
|
||||
PW_STREAM_FLAG_RT_PROCESS,
|
||||
params, n_params)) < 0)
|
||||
params, n_params)) < 0) {
|
||||
spa_pod_dynamic_builder_clean(&b);
|
||||
return res;
|
||||
}
|
||||
|
||||
if ((res = pw_stream_connect(impl->sink,
|
||||
PW_DIRECTION_INPUT,
|
||||
PW_ID_ANY,
|
||||
PW_STREAM_FLAG_MAP_BUFFERS |
|
||||
PW_STREAM_FLAG_RT_PROCESS,
|
||||
params, n_params)) < 0)
|
||||
params, n_params)) < 0) {
|
||||
spa_pod_dynamic_builder_clean(&b);
|
||||
return res;
|
||||
}
|
||||
|
||||
if ((res = pw_stream_connect(impl->playback,
|
||||
PW_DIRECTION_OUTPUT,
|
||||
|
|
@ -806,8 +891,12 @@ static int setup_streams(struct impl *impl)
|
|||
PW_STREAM_FLAG_AUTOCONNECT |
|
||||
PW_STREAM_FLAG_MAP_BUFFERS |
|
||||
PW_STREAM_FLAG_RT_PROCESS,
|
||||
params, n_params)) < 0)
|
||||
params, n_params)) < 0) {
|
||||
spa_pod_dynamic_builder_clean(&b);
|
||||
return res;
|
||||
}
|
||||
|
||||
spa_pod_dynamic_builder_clean(&b);
|
||||
|
||||
impl->rec_ringsize = sizeof(float) * impl->max_buffer_size * impl->info.rate / 1000;
|
||||
impl->play_ringsize = sizeof(float) * ((impl->max_buffer_size * impl->info.rate / 1000) + impl->buffer_delay);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue