[FFmpeg-devel] [PATCH 6/6] fftools/ffmpeg: switch -map parsing to new stream specifier API

Anton Khirnov anton at khirnov.net
Sat Aug 10 20:16:21 EEST 2024


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;
 }
 
-- 
2.43.0



More information about the ffmpeg-devel mailing list