filter-graph: handle allocation errors and do cleanup

Make sure clean up everything on error.
This commit is contained in:
Wim Taymans 2026-05-05 12:53:10 +02:00
parent 9972df2614
commit 7bfc820ae8
4 changed files with 76 additions and 30 deletions

View file

@ -76,6 +76,14 @@ static void layout_from_name(AVChannelLayout *layout, const char *name)
av_channel_layout_from_string(layout, "FC"); av_channel_layout_from_string(layout, "FC");
} }
static void ffmpeg_cleanup(void *instance)
{
struct instance *i = instance;
avfilter_graph_free(&i->filter_graph);
av_frame_free(&i->frame);
free(i);
}
static void *ffmpeg_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc, static void *ffmpeg_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc,
unsigned long SampleRate, int index, const char *config) unsigned long SampleRate, int index, const char *config)
{ {
@ -99,21 +107,21 @@ static void *ffmpeg_instantiate(const struct spa_fga_plugin *plugin, const struc
i->filter_graph = avfilter_graph_alloc(); i->filter_graph = avfilter_graph_alloc();
if (i->filter_graph == NULL) { if (i->filter_graph == NULL) {
errno = ENOMEM; errno = ENOMEM;
return NULL; goto error_free;
} }
res = avfilter_graph_parse2(i->filter_graph, d->desc.name, &in, &out); res = avfilter_graph_parse2(i->filter_graph, d->desc.name, &in, &out);
if (res < 0) { if (res < 0) {
spa_log_error(p->log, "can parse filter graph %s", d->desc.name); spa_log_error(p->log, "can parse filter graph %s", d->desc.name);
errno = EINVAL; errno = EINVAL;
return NULL; goto error_free;
} }
for (n_fp = 0, fp = in; fp != NULL; fp = fp->next, n_fp++) { for (n_fp = 0, fp = in; fp != NULL; fp = fp->next, n_fp++) {
ctx = avfilter_graph_alloc_filter(i->filter_graph, d->buffersrc, "src"); ctx = avfilter_graph_alloc_filter(i->filter_graph, d->buffersrc, "src");
if (ctx == NULL) { if (ctx == NULL) {
spa_log_error(p->log, "can't alloc buffersrc"); spa_log_error(p->log, "can't alloc buffersrc");
return NULL; goto error_free;
} }
av_channel_layout_describe(&d->layout[n_fp], channel, sizeof(channel)); av_channel_layout_describe(&d->layout[n_fp], channel, sizeof(channel));
@ -132,7 +140,7 @@ static void *ffmpeg_instantiate(const struct spa_fga_plugin *plugin, const struc
cnv = avfilter_graph_alloc_filter(i->filter_graph, d->format, "format"); cnv = avfilter_graph_alloc_filter(i->filter_graph, d->format, "format");
if (cnv == NULL) { if (cnv == NULL) {
spa_log_error(p->log, "can't alloc format"); spa_log_error(p->log, "can't alloc format");
return NULL; goto error_free;
} }
av_channel_layout_describe(&d->layout[n_fp], channel, sizeof(channel)); av_channel_layout_describe(&d->layout[n_fp], channel, sizeof(channel));
@ -148,7 +156,7 @@ static void *ffmpeg_instantiate(const struct spa_fga_plugin *plugin, const struc
ctx = avfilter_graph_alloc_filter(i->filter_graph, d->buffersink, "sink"); ctx = avfilter_graph_alloc_filter(i->filter_graph, d->buffersink, "sink");
if (ctx == NULL) { if (ctx == NULL) {
spa_log_error(p->log, "can't alloc buffersink"); spa_log_error(p->log, "can't alloc buffersink");
return NULL; goto error_free;
} }
avfilter_init_str(ctx, NULL); avfilter_init_str(ctx, NULL);
avfilter_link(cnv, 0, ctx, 0); avfilter_link(cnv, 0, ctx, 0);
@ -159,6 +167,8 @@ static void *ffmpeg_instantiate(const struct spa_fga_plugin *plugin, const struc
avfilter_graph_config(i->filter_graph, NULL); avfilter_graph_config(i->filter_graph, NULL);
i->frame = av_frame_alloc(); i->frame = av_frame_alloc();
if (i->frame == NULL)
goto error_free;
#if 0 #if 0
char *dump = avfilter_graph_dump(i->filter_graph, NULL); char *dump = avfilter_graph_dump(i->filter_graph, NULL);
@ -166,14 +176,10 @@ static void *ffmpeg_instantiate(const struct spa_fga_plugin *plugin, const struc
free(dump); free(dump);
#endif #endif
return i; return i;
}
static void ffmpeg_cleanup(void *instance) error_free:
{ ffmpeg_cleanup(i);
struct instance *i = instance; return NULL;
avfilter_graph_free(&i->filter_graph);
av_frame_free(&i->frame);
free(i);
} }
static void ffmpeg_free(const struct spa_fga_descriptor *desc) static void ffmpeg_free(const struct spa_fga_descriptor *desc)
@ -181,10 +187,12 @@ static void ffmpeg_free(const struct spa_fga_descriptor *desc)
struct descriptor *d = (struct descriptor*)desc; struct descriptor *d = (struct descriptor*)desc;
uint32_t i; uint32_t i;
avfilter_graph_free(&d->filter_graph); avfilter_graph_free(&d->filter_graph);
if (d->desc.ports) {
for (i = 0; i < d->desc.n_ports; i++) for (i = 0; i < d->desc.n_ports; i++)
free((void*)d->desc.ports[i].name); free((void*)d->desc.ports[i].name);
free((char*)d->desc.name);
free(d->desc.ports); free(d->desc.ports);
}
free((char*)d->desc.name);
free(d); free(d);
} }
@ -270,14 +278,14 @@ static const struct spa_fga_descriptor *ffmpeg_plugin_make_desc(void *plugin, co
desc->filter_graph = avfilter_graph_alloc(); desc->filter_graph = avfilter_graph_alloc();
if (desc->filter_graph == NULL) { if (desc->filter_graph == NULL) {
errno = ENOMEM; errno = ENOMEM;
return NULL; goto error_free_desc;
} }
res = avfilter_graph_parse2(desc->filter_graph, name, &in, &out); res = avfilter_graph_parse2(desc->filter_graph, name, &in, &out);
if (res < 0) { if (res < 0) {
spa_log_error(p->log, "can parse filter graph %s", name); spa_log_error(p->log, "can parse filter graph %s", name);
errno = EINVAL; errno = EINVAL;
return NULL; goto error_free_desc;
} }
desc->desc.n_ports = 0; desc->desc.n_ports = 0;
@ -300,13 +308,13 @@ static const struct spa_fga_descriptor *ffmpeg_plugin_make_desc(void *plugin, co
spa_log_error(p->log, "%p: too many in/out ports %d > %d", desc, spa_log_error(p->log, "%p: too many in/out ports %d > %d", desc,
n_fp, MAX_CTX); n_fp, MAX_CTX);
errno = ENOSPC; errno = ENOSPC;
return NULL; goto error_free_desc;
} }
if (desc->desc.n_ports >= MAX_PORTS) { if (desc->desc.n_ports >= MAX_PORTS) {
spa_log_error(p->log, "%p: too many ports %d > %d", desc, spa_log_error(p->log, "%p: too many ports %d > %d", desc,
desc->desc.n_ports, MAX_PORTS); desc->desc.n_ports, MAX_PORTS);
errno = ENOSPC; errno = ENOSPC;
return NULL; goto error_free_desc;
} }
desc->desc.instantiate = ffmpeg_instantiate; desc->desc.instantiate = ffmpeg_instantiate;
@ -316,9 +324,13 @@ static const struct spa_fga_descriptor *ffmpeg_plugin_make_desc(void *plugin, co
desc->desc.run = ffmpeg_run; desc->desc.run = ffmpeg_run;
desc->desc.name = strdup(name); desc->desc.name = strdup(name);
if (desc->desc.name == NULL)
goto error_free_desc;
desc->desc.flags = 0; desc->desc.flags = 0;
desc->desc.ports = calloc(desc->desc.n_ports, sizeof(struct spa_fga_port)); desc->desc.ports = calloc(desc->desc.n_ports, sizeof(struct spa_fga_port));
if (desc->desc.ports == NULL)
goto error_free_desc;
for (n_fp = 0, n_p = 0, fp = in; fp != NULL; fp = fp->next, n_fp++) { for (n_fp = 0, n_p = 0, fp = in; fp != NULL; fp = fp->next, n_fp++) {
for (j = 0; j < desc->layout[n_fp].nb_channels; j++, n_p++) { for (j = 0; j < desc->layout[n_fp].nb_channels; j++, n_p++) {
@ -327,6 +339,8 @@ static const struct spa_fga_descriptor *ffmpeg_plugin_make_desc(void *plugin, co
desc->desc.ports[n_p].name = spa_aprintf("%s", fp->name); desc->desc.ports[n_p].name = spa_aprintf("%s", fp->name);
else else
desc->desc.ports[n_p].name = spa_aprintf("%s_%d", fp->name, j); desc->desc.ports[n_p].name = spa_aprintf("%s_%d", fp->name, j);
if (desc->desc.ports[n_p].name == NULL)
goto error_free_desc;
desc->desc.ports[n_p].flags = SPA_FGA_PORT_INPUT | SPA_FGA_PORT_AUDIO; desc->desc.ports[n_p].flags = SPA_FGA_PORT_INPUT | SPA_FGA_PORT_AUDIO;
} }
} }
@ -337,11 +351,15 @@ static const struct spa_fga_descriptor *ffmpeg_plugin_make_desc(void *plugin, co
desc->desc.ports[n_p].name = spa_aprintf("%s", fp->name); desc->desc.ports[n_p].name = spa_aprintf("%s", fp->name);
else else
desc->desc.ports[n_p].name = spa_aprintf("%s_%d", fp->name, j); desc->desc.ports[n_p].name = spa_aprintf("%s_%d", fp->name, j);
if (desc->desc.ports[n_p].name == NULL)
goto error_free_desc;
desc->desc.ports[n_p].flags = SPA_FGA_PORT_OUTPUT | SPA_FGA_PORT_AUDIO; desc->desc.ports[n_p].flags = SPA_FGA_PORT_OUTPUT | SPA_FGA_PORT_AUDIO;
} }
} }
desc->desc.ports[n_p].index = n_p; desc->desc.ports[n_p].index = n_p;
desc->desc.ports[n_p].name = strdup("latency"); desc->desc.ports[n_p].name = strdup("latency");
if (desc->desc.ports[n_p].name == NULL)
goto error_free_desc;
desc->desc.ports[n_p].flags = SPA_FGA_PORT_OUTPUT | SPA_FGA_PORT_CONTROL; desc->desc.ports[n_p].flags = SPA_FGA_PORT_OUTPUT | SPA_FGA_PORT_CONTROL;
desc->desc.ports[n_p].hint = SPA_FGA_HINT_LATENCY; desc->desc.ports[n_p].hint = SPA_FGA_HINT_LATENCY;
desc->latency_idx = n_p++; desc->latency_idx = n_p++;
@ -349,8 +367,14 @@ static const struct spa_fga_descriptor *ffmpeg_plugin_make_desc(void *plugin, co
desc->buffersrc = avfilter_get_by_name("abuffer"); desc->buffersrc = avfilter_get_by_name("abuffer");
desc->buffersink = avfilter_get_by_name("abuffersink"); desc->buffersink = avfilter_get_by_name("abuffersink");
desc->format = avfilter_get_by_name("aformat"); desc->format = avfilter_get_by_name("aformat");
if (desc->buffersrc == NULL || desc->buffersink == NULL || desc->format == NULL)
goto error_free_desc;
return &desc->desc; return &desc->desc;
error_free_desc:
ffmpeg_free(&desc->desc);
return NULL;
} }
static struct spa_fga_plugin_methods impl_plugin = { static struct spa_fga_plugin_methods impl_plugin = {

View file

@ -503,10 +503,12 @@ static void lv2_free(const struct spa_fga_descriptor *desc)
{ {
struct descriptor *d = (struct descriptor*)desc; struct descriptor *d = (struct descriptor*)desc;
uint32_t i; uint32_t i;
if (d->desc.ports) {
for (i = 0; i < d->desc.n_ports; i++) for (i = 0; i < d->desc.n_ports; i++)
free((void*)d->desc.ports[i].name); free((void*)d->desc.ports[i].name);
free((char*)d->desc.name);
free(d->desc.ports); free(d->desc.ports);
}
free((char*)d->desc.name);
free(d); free(d);
} }
@ -535,18 +537,18 @@ static const struct spa_fga_descriptor *lv2_plugin_make_desc(void *plugin, const
desc->desc.free = lv2_free; desc->desc.free = lv2_free;
desc->desc.name = strdup(name); desc->desc.name = strdup(name);
if (desc->desc.name == NULL)
goto error_free;
desc->desc.flags = 0; desc->desc.flags = 0;
desc->desc.n_ports = lilv_plugin_get_num_ports(p->p); desc->desc.n_ports = lilv_plugin_get_num_ports(p->p);
if (desc->desc.n_ports > MAX_PORTS) { if (desc->desc.n_ports > MAX_PORTS)
free(desc); goto error_free;
return NULL;
}
desc->desc.ports = calloc(desc->desc.n_ports, sizeof(struct spa_fga_port)); desc->desc.ports = calloc(desc->desc.n_ports, sizeof(struct spa_fga_port));
if (desc->desc.ports == NULL) { if (desc->desc.ports == NULL)
free(desc); goto error_free;
return NULL;
}
mins = alloca(desc->desc.n_ports * sizeof(float)); mins = alloca(desc->desc.n_ports * sizeof(float));
maxes = alloca(desc->desc.n_ports * sizeof(float)); maxes = alloca(desc->desc.n_ports * sizeof(float));
@ -564,6 +566,8 @@ static const struct spa_fga_descriptor *lv2_plugin_make_desc(void *plugin, const
fp->index = i; fp->index = i;
fp->name = strdup(lilv_node_as_string(symbol)); fp->name = strdup(lilv_node_as_string(symbol));
if (fp->name == NULL)
goto error_free;
fp->flags = 0; fp->flags = 0;
if (lilv_port_is_a(p->p, port, c->lv2_InputPort)) if (lilv_port_is_a(p->p, port, c->lv2_InputPort))
@ -597,6 +601,10 @@ static const struct spa_fga_descriptor *lv2_plugin_make_desc(void *plugin, const
fp->min = -FLT_MAX; fp->min = -FLT_MAX;
} }
return &desc->desc; return &desc->desc;
error_free:
lv2_free(&desc->desc);
return NULL;
} }
static struct spa_fga_plugin_methods impl_plugin = { static struct spa_fga_plugin_methods impl_plugin = {

View file

@ -475,6 +475,8 @@ static const struct spa_fga_descriptor *onnx_plugin_make_desc(void *plugin, cons
desc->desc.run = onnx_run; desc->desc.run = onnx_run;
desc->desc.name = strdup(name); desc->desc.name = strdup(name);
if (desc->desc.name == NULL)
goto error;
desc->desc.flags = 0; desc->desc.flags = 0;
spa_log_info(p->log, "onnx: loading model %s", path); spa_log_info(p->log, "onnx: loading model %s", path);
@ -568,6 +570,8 @@ static const struct spa_fga_descriptor *onnx_plugin_make_desc(void *plugin, cons
} }
desc->desc.ports = calloc(desc->n_tensors, sizeof(struct spa_fga_port)); desc->desc.ports = calloc(desc->n_tensors, sizeof(struct spa_fga_port));
if (desc->desc.ports == NULL)
goto error;
desc->desc.n_ports = 0; desc->desc.n_ports = 0;
/* make ports */ /* make ports */

View file

@ -211,10 +211,14 @@ static void * spatializer_instantiate(const struct spa_fga_plugin *plugin, const
impl->tmp[0] = calloc(impl->plugin->quantum_limit, sizeof(float)); impl->tmp[0] = calloc(impl->plugin->quantum_limit, sizeof(float));
impl->tmp[1] = calloc(impl->plugin->quantum_limit, sizeof(float)); impl->tmp[1] = calloc(impl->plugin->quantum_limit, sizeof(float));
if (impl->tmp[0] == NULL || impl->tmp[1] == NULL)
goto error;
impl->rate = SampleRate; impl->rate = SampleRate;
return impl; return impl;
error: error:
free(impl->tmp[0]);
free(impl->tmp[1]);
if (impl->sofa) if (impl->sofa)
mysofa_close_cached(impl->sofa); mysofa_close_cached(impl->sofa);
free(impl); free(impl);
@ -247,6 +251,12 @@ static void spatializer_reload(void * Instance)
float coords[3]; float coords[3];
struct convolver_ir ir[2]; struct convolver_ir ir[2];
if (left_ir == NULL || right_ir == NULL) {
free(left_ir);
free(right_ir);
return;
}
for (uint8_t i = 0; i < 3; i++) for (uint8_t i = 0; i < 3; i++)
coords[i] = impl->port[3 + i][0]; coords[i] = impl->port[3 + i][0];