From 0f5592cfc73773b895e81ae1ab8404b0ff2dc6b1 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 7 Oct 2024 12:38:43 +0200 Subject: [PATCH] fftools/ffmpeg: supply hw device context to probe-filtergraphs I.e. those that are only used to figure out input/output counts, since some filters might expect a valid hw device in init and refuse to initalize otherwise. This requires complex filtergraphs to be created in a separate step after parsing global options, after all hw devices are guaranteed to exist. --- fftools/ffmpeg_filter.c | 3 ++- fftools/ffmpeg_opt.c | 43 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 4d444c161f..4524a3e535 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -1097,7 +1097,8 @@ int fg_create(FilterGraph **pfg, char *graph_desc, Scheduler *sch) return AVERROR(ENOMEM);; graph->nb_threads = 1; - ret = graph_parse(graph, fgp->graph_desc, &inputs, &outputs, NULL); + ret = graph_parse(graph, fgp->graph_desc, &inputs, &outputs, + hw_device_for_filter()); if (ret < 0) goto fail; diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 052e68e943..9bf0c4f0c4 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -90,6 +90,9 @@ int recast_media = 0; // to func_arg() for global options typedef struct GlobalOptionsContext { Scheduler *sch; + + char **filtergraphs; + int nb_filtergraphs; } GlobalOptionsContext; static void uninit_options(OptionsContext *o) @@ -1157,25 +1160,45 @@ static int opt_audio_qscale(void *optctx, const char *opt, const char *arg) static int opt_filter_complex(void *optctx, const char *opt, const char *arg) { GlobalOptionsContext *go = optctx; - char *graph_desc = av_strdup(arg); + char *graph_desc; + int ret; + + graph_desc = av_strdup(arg); if (!graph_desc) return AVERROR(ENOMEM); - return fg_create(NULL, graph_desc, go->sch); + ret = GROW_ARRAY(go->filtergraphs, go->nb_filtergraphs); + if (ret < 0) { + av_freep(&graph_desc); + return ret; + } + go->filtergraphs[go->nb_filtergraphs - 1] = graph_desc; + + return 0; } #if FFMPEG_OPT_FILTER_SCRIPT static int opt_filter_complex_script(void *optctx, const char *opt, const char *arg) { GlobalOptionsContext *go = optctx; - char *graph_desc = file_read(arg); + char *graph_desc; + int ret; + + graph_desc = file_read(arg); if (!graph_desc) return AVERROR(EINVAL); av_log(NULL, AV_LOG_WARNING, "-%s is deprecated, use -/filter_complex %s instead\n", opt, arg); - return fg_create(NULL, graph_desc, go->sch); + ret = GROW_ARRAY(go->filtergraphs, go->nb_filtergraphs); + if (ret < 0) { + av_freep(&graph_desc); + return ret; + } + go->filtergraphs[go->nb_filtergraphs - 1] = graph_desc; + + return 0; } #endif @@ -1377,6 +1400,14 @@ int ffmpeg_parse_options(int argc, char **argv, Scheduler *sch) /* configure terminal and setup signal handlers */ term_init(); + /* create complex filtergraphs */ + for (int i = 0; i < go.nb_filtergraphs; i++) { + ret = fg_create(NULL, go.filtergraphs[i], sch); + go.filtergraphs[i] = NULL; + if (ret < 0) + goto fail; + } + /* open input files */ ret = open_files(&octx.groups[GROUP_INFILE], "input", sch, ifile_open); if (ret < 0) { @@ -1412,6 +1443,10 @@ int ffmpeg_parse_options(int argc, char **argv, Scheduler *sch) goto fail; fail: + for (int i = 0; i < go.nb_filtergraphs; i++) + av_freep(&go.filtergraphs[i]); + av_freep(&go.filtergraphs); + uninit_parse_context(&octx); if (ret < 0 && ret != AVERROR_EXIT) { av_log(NULL, AV_LOG_FATAL, "Error %s: %s\n",