From aa075c2a12407e0b155777cd15e183c0a8e7b293 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 30 Jun 2026 11:58:33 +0200 Subject: [PATCH] filter-graph: add support for multiple handles Make instantiate create all the related handles in one go. When a processing node has 1 in/out, multiple handles are created to support multichannel. By instantiating the handles in one go, the implementation could do some special multichannel support or do some optimizations, like parse the config string only once. --- spa/plugins/filter-graph/audio-plugin.h | 2 +- spa/plugins/filter-graph/filter-graph.c | 14 ++- spa/plugins/filter-graph/plugin_builtin.c | 109 +++++++++++++++++----- spa/plugins/filter-graph/plugin_ebur128.c | 40 +++++--- spa/plugins/filter-graph/plugin_ffmpeg.c | 15 ++- spa/plugins/filter-graph/plugin_ladspa.c | 9 +- spa/plugins/filter-graph/plugin_lv2.c | 15 ++- spa/plugins/filter-graph/plugin_onnx.c | 15 ++- spa/plugins/filter-graph/plugin_sofa.c | 15 ++- 9 files changed, 175 insertions(+), 59 deletions(-) diff --git a/spa/plugins/filter-graph/audio-plugin.h b/spa/plugins/filter-graph/audio-plugin.h index 7f88edf1a..1971135bf 100644 --- a/spa/plugins/filter-graph/audio-plugin.h +++ b/spa/plugins/filter-graph/audio-plugin.h @@ -63,7 +63,7 @@ struct spa_fga_descriptor { struct spa_fga_port *ports; int (*instantiate) (const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc, - uint32_t rate, int index, const char *config, void **hndl); + uint32_t rate, const char *config, uint32_t n_hndl, void *hndl[]); void (*cleanup) (void *instance); diff --git a/spa/plugins/filter-graph/filter-graph.c b/spa/plugins/filter-graph/filter-graph.c index f3259afba..b16e1cf13 100644 --- a/spa/plugins/filter-graph/filter-graph.c +++ b/spa/plugins/filter-graph/filter-graph.c @@ -1682,14 +1682,12 @@ static int impl_activate(void *object, const struct spa_dict *props) d = desc->desc; p = desc->plugin->plugin; - for (i = 0; i < node->n_hndl; i++) { - spa_log_info(impl->log, "instantiate %s %s[%d] rate:%lu", d->name, node->name, i, impl->rate); - errno = EINVAL; - if ((res = d->instantiate(p, d, impl->rate, i, node->config, &node->hndl[i])) < 0) { - spa_log_error(impl->log, "cannot create plugin instance %d rate:%lu: %s", - i, impl->rate, spa_strerror(res)); - goto error; - } + spa_log_info(impl->log, "instantiate %s %s[%d] rate:%lu", d->name, node->name, + node->n_hndl, impl->rate); + if ((res = d->instantiate(p, d, impl->rate, node->config, node->n_hndl, node->hndl)) < 0) { + spa_log_error(impl->log, "cannot create plugin instance %d rate:%lu: %s", + node->n_hndl, impl->rate, spa_strerror(res)); + goto error; } node->control_changed = true; } diff --git a/spa/plugins/filter-graph/plugin_builtin.c b/spa/plugins/filter-graph/plugin_builtin.c index 13f369304..08904a71a 100644 --- a/spa/plugins/filter-graph/plugin_builtin.c +++ b/spa/plugins/filter-graph/plugin_builtin.c @@ -69,22 +69,39 @@ struct builtin { float hold; }; -static int builtin_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor, - uint32_t rate, int index, const char *config, void **hndl) +static int instantiate_helper(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc, + uint32_t rate, const char *config, uint32_t n_hndl, void *hndl[], + int (*instantiate1_func) (const struct spa_fga_plugin *plugin, + const struct spa_fga_descriptor *desc, + uint32_t rate, uint32_t index, const char *config, void **hndl)) +{ + int res; + for (uint32_t i = 0; i < n_hndl; i++) { + if ((res = instantiate1_func(plugin, desc, rate, i, config, &hndl[i])) < 0) + return res; + } + return 0; +} + +static int builtin_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc, + uint32_t rate, const char *config, uint32_t n_hndl, void *hndl[]) { struct plugin *pl = SPA_CONTAINER_OF(plugin, struct plugin, plugin); - struct builtin *impl; - impl = calloc(1, sizeof(*impl)); - if (impl == NULL) - return -errno; + for (uint32_t i = 0; i < n_hndl; i++) { + struct builtin *impl; - impl->plugin = pl; - impl->rate = rate; - impl->dsp = impl->plugin->dsp; - impl->log = impl->plugin->log; + impl = calloc(1, sizeof(*impl)); + if (impl == NULL) + return -errno; - *hndl = impl; + impl->plugin = pl; + impl->rate = rate; + impl->dsp = impl->plugin->dsp; + impl->log = impl->plugin->log; + + hndl[i] = impl; + } return 0; } @@ -336,8 +353,8 @@ static void bq_raw_update(struct builtin *impl, float b0, float b1, float b2, * ] * } */ -static int bq_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor, - uint32_t rate, int index, const char *config, void **hndl) +static int bq_instantiate1(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor, + uint32_t rate, uint32_t index, const char *config, void **hndl) { struct plugin *pl = SPA_CONTAINER_OF(plugin, struct plugin, plugin); struct builtin *impl; @@ -448,6 +465,12 @@ error: return -EINVAL; } +static int bq_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc, + uint32_t rate, const char *config, uint32_t n_hndl, void *hndl[]) +{ + return instantiate_helper(plugin, desc, rate, config, n_hndl, hndl, bq_instantiate1); +} + #define BQ_NUM_PORTS 11 static struct spa_fga_port bq_ports[] = { { .index = 0, @@ -1140,8 +1163,8 @@ error: return res; } -static int convolver_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor, - uint32_t rate, int index, const char *config, void **hndl) +static int convolver_instantiate1(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor, + uint32_t rate, uint32_t index, const char *config, void **hndl) { struct plugin *pl = SPA_CONTAINER_OF(plugin, struct plugin, plugin); struct convolver_impl *impl = NULL; @@ -1225,6 +1248,12 @@ error_errno: return res; } +static int convolver_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc, + uint32_t rate, const char *config, uint32_t n_hndl, void *hndl[]) +{ + return instantiate_helper(plugin, desc, rate, config, n_hndl, hndl, convolver_instantiate1); +} + static void convolver_connect_port(void * Instance, unsigned long Port, void * DataLocation) { @@ -1294,8 +1323,8 @@ static const struct spa_fga_descriptor convolve_desc = { }; /** convolver2 */ -static int convolver2_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor, - uint32_t rate, int index, const char *config, void **hndl) +static int convolver2_instantiate1(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor, + uint32_t rate, uint32_t index, const char *config, void **hndl) { struct plugin *pl = SPA_CONTAINER_OF(plugin, struct plugin, plugin); struct convolver_impl *impl = NULL; @@ -1403,6 +1432,12 @@ error: return -EINVAL; } +static int convolver2_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc, + uint32_t rate, const char *config, uint32_t n_hndl, void *hndl[]) +{ + return instantiate_helper(plugin, desc, rate, config, n_hndl, hndl, convolver2_instantiate1); +} + static void convolver2_run(void * Instance, unsigned long SampleCount) { struct convolver_impl *impl = Instance; @@ -1504,8 +1539,8 @@ static void delay_cleanup(void * Instance) free(impl); } -static int delay_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor, - uint32_t rate, int index, const char *config, void **hndl) +static int delay_instantiate1(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor, + uint32_t rate, uint32_t index, const char *config, void **hndl) { struct plugin *pl = SPA_CONTAINER_OF(plugin, struct plugin, plugin); struct delay_impl *impl; @@ -1573,6 +1608,12 @@ static int delay_instantiate(const struct spa_fga_plugin *plugin, const struct s return 0; } +static int delay_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc, + uint32_t rate, const char *config, uint32_t n_hndl, void *hndl[]) +{ + return instantiate_helper(plugin, desc, rate, config, n_hndl, hndl, delay_instantiate1); +} + static void delay_connect_port(void * Instance, unsigned long Port, void * DataLocation) { @@ -2302,8 +2343,8 @@ static int parse_filters(struct plugin *pl, struct spa_json *iter, int rate, * filtersX = [ ... ] # to load channel X * } */ -static int param_eq_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor, - uint32_t rate, int index, const char *config, void **hndl) +static int param_eq_instantiate1(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor, + uint32_t rate, uint32_t index, const char *config, void **hndl) { struct plugin *pl = SPA_CONTAINER_OF(plugin, struct plugin, plugin); struct spa_json it[3]; @@ -2387,6 +2428,12 @@ error: return -EINVAL; } +static int param_eq_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc, + uint32_t rate, const char *config, uint32_t n_hndl, void *hndl[]) +{ + return instantiate_helper(plugin, desc, rate, config, n_hndl, hndl, param_eq_instantiate1); +} + static void param_eq_connect_port(void * Instance, unsigned long Port, void * DataLocation) { @@ -2666,8 +2713,8 @@ struct dcblock_impl { struct dcblock dc[8]; }; -static int dcblock_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor, - uint32_t rate, int index, const char *config, void **hndl) +static int dcblock_instantiate1(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor, + uint32_t rate, uint32_t index, const char *config, void **hndl) { struct plugin *pl = SPA_CONTAINER_OF(plugin, struct plugin, plugin); struct dcblock_impl *impl; @@ -2684,6 +2731,12 @@ static int dcblock_instantiate(const struct spa_fga_plugin *plugin, const struct return 0; } +static int dcblock_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc, + uint32_t rate, const char *config, uint32_t n_hndl, void *hndl[]) +{ + return instantiate_helper(plugin, desc, rate, config, n_hndl, hndl, dcblock_instantiate1); +} + static void dcblock_run_n(struct dcblock dc[], float *dst[], const float *src[], uint32_t n_src, float R, uint32_t n_samples) { @@ -3267,8 +3320,8 @@ struct busy_impl { float cpu_scale; }; -static int busy_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor, - uint32_t rate, int index, const char *config, void **hndl) +static int busy_instantiate1(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor, + uint32_t rate, uint32_t index, const char *config, void **hndl) { struct plugin *pl = SPA_CONTAINER_OF(plugin, struct plugin, plugin); struct busy_impl *impl; @@ -3320,6 +3373,12 @@ static int busy_instantiate(const struct spa_fga_plugin *plugin, const struct sp return 0; } +static int busy_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc, + uint32_t rate, const char *config, uint32_t n_hndl, void *hndl[]) +{ + return instantiate_helper(plugin, desc, rate, config, n_hndl, hndl, busy_instantiate1); +} + static void busy_run(void * Instance, unsigned long SampleCount) { struct busy_impl *impl = Instance; diff --git a/spa/plugins/filter-graph/plugin_ebur128.c b/spa/plugins/filter-graph/plugin_ebur128.c index 8d7518451..d1680a166 100644 --- a/spa/plugins/filter-graph/plugin_ebur128.c +++ b/spa/plugins/filter-graph/plugin_ebur128.c @@ -68,8 +68,8 @@ struct ebur128_impl { ebur128_state *st[7]; }; -static int ebur128_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor, - uint32_t rate, int index, const char *config, void **hndl) +static int ebur128_instantiate1(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc, + uint32_t rate, uint32_t index, const char *config, void **hndl) { struct plugin *pl = SPA_CONTAINER_OF(plugin, struct plugin, plugin); struct ebur128_impl *impl; @@ -129,6 +129,17 @@ error: return -EINVAL; } +static int ebur128_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc, + uint32_t rate, const char *config, uint32_t n_hndl, void *hndl[]) +{ + int res; + for (uint32_t i = 0; i < n_hndl; i++) { + if ((res = ebur128_instantiate1(plugin, desc, rate, i, config, &hndl[i])) < 0) + return res; + } + return 0; +} + static void ebur128_run(void * Instance, unsigned long SampleCount) { struct ebur128_impl *impl = Instance; @@ -418,21 +429,24 @@ struct lufs2gain_impl { float *port[3]; }; -static int lufs2gain_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor, - uint32_t rate, int index, const char *config, void **hndl) +static int lufs2gain_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc, + uint32_t rate, const char *config, uint32_t n_hndl, void **hndl) { struct plugin *pl = SPA_CONTAINER_OF(plugin, struct plugin, plugin); - struct lufs2gain_impl *impl; - impl = calloc(1, sizeof(*impl)); - if (impl == NULL) - return -errno; + for (uint32_t i = 0; i < n_hndl; i++) { + struct lufs2gain_impl *impl; - impl->plugin = pl; - impl->dsp = pl->dsp; - impl->log = pl->log; - impl->rate = rate; - *hndl = impl; + impl = calloc(1, sizeof(*impl)); + if (impl == NULL) + return -errno; + + impl->plugin = pl; + impl->dsp = pl->dsp; + impl->log = pl->log; + impl->rate = rate; + hndl[i] = impl; + } return 0; } diff --git a/spa/plugins/filter-graph/plugin_ffmpeg.c b/spa/plugins/filter-graph/plugin_ffmpeg.c index f84513450..89b2964e7 100644 --- a/spa/plugins/filter-graph/plugin_ffmpeg.c +++ b/spa/plugins/filter-graph/plugin_ffmpeg.c @@ -84,8 +84,8 @@ static void ffmpeg_cleanup(void *instance) free(i); } -static int ffmpeg_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc, - uint32_t rate, int index, const char *config, void **hndl) +static int ffmpeg_instantiate1(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc, + uint32_t rate, uint32_t index, const char *config, void **hndl) { struct descriptor *d = (struct descriptor *)desc; struct plugin *p = d->p; @@ -186,6 +186,17 @@ error_free: return res; } +static int ffmpeg_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc, + uint32_t rate, const char *config, uint32_t n_hndl, void *hndl[]) +{ + int res; + for (uint32_t i = 0; i < n_hndl; i++) { + if ((res = ffmpeg_instantiate1(plugin, desc, rate, i, config, &hndl[i])) < 0) + return res; + } + return 0; +} + static void ffmpeg_free(const struct spa_fga_descriptor *desc) { struct descriptor *d = (struct descriptor*)desc; diff --git a/spa/plugins/filter-graph/plugin_ladspa.c b/spa/plugins/filter-graph/plugin_ladspa.c index edb8612d4..44f3ec440 100644 --- a/spa/plugins/filter-graph/plugin_ladspa.c +++ b/spa/plugins/filter-graph/plugin_ladspa.c @@ -35,12 +35,13 @@ struct descriptor { }; static int ladspa_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc, - uint32_t rate, int index, const char *config, void **hndl) + uint32_t rate, const char *config, uint32_t n_hndl, void **hndl) { struct descriptor *d = (struct descriptor *)desc; - *hndl = d->d->instantiate(d->d, rate); - if (*hndl == NULL) - return -ENOMEM; + for (uint32_t i = 0; i < n_hndl; i++) { + if ((hndl[i] = d->d->instantiate(d->d, rate)) == NULL) + return -ENOMEM; + } return 0; } diff --git a/spa/plugins/filter-graph/plugin_lv2.c b/spa/plugins/filter-graph/plugin_lv2.c index 283ad8187..14209a7d7 100644 --- a/spa/plugins/filter-graph/plugin_lv2.c +++ b/spa/plugins/filter-graph/plugin_lv2.c @@ -374,8 +374,8 @@ static int log_printf(LV2_Log_Handle handle, LV2_URID type, const char* fmt, ... return ret; } -static int lv2_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc, - uint32_t rate, int index, const char *config, void **hndl) +static int lv2_instantiate1(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc, + uint32_t rate, uint32_t index, const char *config, void **hndl) { struct descriptor *d = (struct descriptor*)desc; struct plugin *p = d->p; @@ -465,6 +465,17 @@ static int lv2_instantiate(const struct spa_fga_plugin *plugin, const struct spa return 0; } +static int lv2_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc, + uint32_t rate, const char *config, uint32_t n_hndl, void *hndl[]) +{ + int res; + for (uint32_t i = 0; i < n_hndl; i++) { + if ((res = lv2_instantiate1(plugin, desc, rate, i, config, &hndl[i])) < 0) + return res; + } + return 0; +} + static void lv2_cleanup(void *instance) { struct instance *i = instance; diff --git a/spa/plugins/filter-graph/plugin_onnx.c b/spa/plugins/filter-graph/plugin_onnx.c index 172979f20..726ab24ed 100644 --- a/spa/plugins/filter-graph/plugin_onnx.c +++ b/spa/plugins/filter-graph/plugin_onnx.c @@ -272,8 +272,8 @@ static int set_value(void *data, enum ONNXTensorElementDataType type, double val * } */ -static int onnx_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc, - uint32_t rate, int index, const char *config, void **hndl) +static int onnx_instantiate1(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc, + uint32_t rate, uint32_t index, const char *config, void **hndl) { struct descriptor *d = (struct descriptor *)desc; struct plugin *p = d->p; @@ -324,6 +324,17 @@ error: return res; } +static int onnx_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc, + uint32_t rate, const char *config, uint32_t n_hndl, void *hndl[]) +{ + int res; + for (uint32_t i = 0; i < n_hndl; i++) { + if ((res = onnx_instantiate1(plugin, desc, rate, i, config, &hndl[i])) < 0) + return res; + } + return 0; +} + static void onnx_cleanup(void *instance) { struct instance *i = instance; diff --git a/spa/plugins/filter-graph/plugin_sofa.c b/spa/plugins/filter-graph/plugin_sofa.c index 26d3fb093..4b3f1cb4f 100644 --- a/spa/plugins/filter-graph/plugin_sofa.c +++ b/spa/plugins/filter-graph/plugin_sofa.c @@ -41,8 +41,8 @@ struct spatializer_impl { struct convolver *conv[3]; }; -static int spatializer_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor, - uint32_t rate, int index, const char *config, void **hndl) +static int spatializer_instantiate1(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor, + uint32_t rate, uint32_t index, const char *config, void **hndl) { struct plugin *pl = SPA_CONTAINER_OF(plugin, struct plugin, plugin); struct spatializer_impl *impl; @@ -234,6 +234,17 @@ error: return res; } +static int spatializer_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc, + uint32_t rate, const char *config, uint32_t n_hndl, void *hndl[]) +{ + int res; + for (uint32_t i = 0; i < n_hndl; i++) { + if ((res = spatializer_instantiate1(plugin, desc, rate, i, config, &hndl[i])) < 0) + return res; + } + return 0; +} + static int do_switch(struct spa_loop *loop, bool async, uint32_t seq, const void *data, size_t size, void *user_data)