From 9e3b5b8a261f179b6bf39bba3ed59dce472ef84a Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 8 Aug 2024 09:34:00 +0200 Subject: [PATCH] fftools/ffmpeg: switch -map parsing to new stream specifier API Makes optional map handling less hacky, fixes combining optional maps with metadata matching on tags/values containing the '?' character/ Forward errors from stream specifier parsing, previously the code would ignore them. --- fftools/ffmpeg_opt.c | 54 ++++++++++++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index f6df6ae952..3cbf0795ac 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -427,22 +427,20 @@ static int opt_map(void *optctx, const char *opt, const char *arg) { OptionsContext *o = optctx; StreamMap *m = NULL; + StreamSpecifier ss; int i, negative = 0, file_idx, disabled = 0; - int ret; - char *map, *p; - char *allow_unused; + int ret, allow_unused = 0; + + memset(&ss, 0, sizeof(ss)); if (*arg == '-') { negative = 1; arg++; } - map = av_strdup(arg); - if (!map) - return AVERROR(ENOMEM); - if (map[0] == '[') { + if (arg[0] == '[') { /* this mapping refers to lavfi output */ - const char *c = map + 1; + const char *c = arg + 1; ret = GROW_ARRAY(o->stream_maps, o->nb_stream_maps); if (ret < 0) @@ -451,33 +449,55 @@ static int opt_map(void *optctx, const char *opt, const char *arg) m = &o->stream_maps[o->nb_stream_maps - 1]; m->linklabel = av_get_token(&c, "]"); if (!m->linklabel) { - av_log(NULL, AV_LOG_ERROR, "Invalid output link label: %s.\n", map); + av_log(NULL, AV_LOG_ERROR, "Invalid output link label: %s.\n", arg); ret = AVERROR(EINVAL); goto fail; } } else { - if (allow_unused = strchr(map, '?')) - *allow_unused = 0; - file_idx = strtol(map, &p, 0); + char *endptr; + + file_idx = strtol(arg, &endptr, 0); if (file_idx >= nb_input_files || file_idx < 0) { av_log(NULL, AV_LOG_FATAL, "Invalid input file index: %d.\n", file_idx); ret = AVERROR(EINVAL); goto fail; } + arg = endptr; + + ret = stream_specifier_parse(&ss, *arg == ':' ? arg + 1 : arg, 1, NULL); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Invalid stream specifier: %s\n", arg); + goto fail; + } + + if (ss.remainder) { + if (!strcmp(ss.remainder, "?")) + allow_unused = 1; + else { + av_log(NULL, AV_LOG_ERROR, "Trailing garbage after stream specifier: %s\n", + ss.remainder); + ret = AVERROR(EINVAL); + goto fail; + } + } + if (negative) /* disable some already defined maps */ for (i = 0; i < o->nb_stream_maps; i++) { m = &o->stream_maps[i]; if (file_idx == m->file_index && - check_stream_specifier(input_files[m->file_index]->ctx, + stream_specifier_match(&ss, + input_files[m->file_index]->ctx, input_files[m->file_index]->ctx->streams[m->stream_index], - *p == ':' ? p + 1 : p) > 0) + NULL)) m->disabled = 1; } else for (i = 0; i < input_files[file_idx]->nb_streams; i++) { - if (check_stream_specifier(input_files[file_idx]->ctx, input_files[file_idx]->ctx->streams[i], - *p == ':' ? p + 1 : p) <= 0) + if (!stream_specifier_match(&ss, + input_files[file_idx]->ctx, + input_files[file_idx]->ctx->streams[i], + NULL)) continue; if (input_files[file_idx]->streams[i]->user_set_discard == AVDISCARD_ALL) { disabled = 1; @@ -511,7 +531,7 @@ static int opt_map(void *optctx, const char *opt, const char *arg) } ret = 0; fail: - av_freep(&map); + stream_specifier_uninit(&ss); return ret; }