[FFmpeg-cvslog] avconv: make -map_metadata work consistently with the other options

Anton Khirnov git at videolan.org
Sat Aug 13 03:18:02 CEST 2011


ffmpeg | branch: master | Anton Khirnov <anton at khirnov.net> | Fri Jul 29 13:07:27 2011 +0200| [e6e6060c9be60f5eb6c94556ca4c92f76cba0d1f] | committer: Anton Khirnov

avconv: make -map_metadata work consistently with the other options

Before, it took an input and output file index, now it only takes an
input file and applies to the next output file.

Stream/chapter/program specification is now part of the option name and
the delimiter was changed from ',' to ':' to be consistent with the
similar feature for AVOptions.

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=e6e6060c9be60f5eb6c94556ca4c92f76cba0d1f
---

 avconv.c        |  145 ++++++++++++++++++++++++++++---------------------------
 doc/avconv.texi |   14 +++---
 2 files changed, 80 insertions(+), 79 deletions(-)

diff --git a/avconv.c b/avconv.c
index b72b26d..f5ca05a 100644
--- a/avconv.c
+++ b/avconv.c
@@ -2091,10 +2091,6 @@ static int transcode(AVFormatContext **output_files,
         codec = ost->st->codec;
         icodec = ist->st->codec;
 
-        if (metadata_streams_autocopy)
-            av_dict_copy(&ost->st->metadata, ist->st->metadata,
-                         AV_DICT_DONT_OVERWRITE);
-
         ost->st->disposition = ist->st->disposition;
         codec->bits_per_raw_sample= icodec->bits_per_raw_sample;
         codec->chroma_sample_location = icodec->chroma_sample_location;
@@ -2399,63 +2395,6 @@ static int transcode(AVFormatContext **output_files,
         ist->is_start = 1;
     }
 
-    /* set meta data information from input file if required */
-    for (i=0;i<nb_meta_data_maps;i++) {
-        AVFormatContext *files[2];
-        AVDictionary    **meta[2];
-        int j;
-
-#define METADATA_CHECK_INDEX(index, nb_elems, desc)\
-        if ((index) < 0 || (index) >= (nb_elems)) {\
-            snprintf(error, sizeof(error), "Invalid %s index %d while processing metadata maps\n",\
-                     (desc), (index));\
-            ret = AVERROR(EINVAL);\
-            goto dump_format;\
-        }
-
-        int out_file_index = meta_data_maps[i][0].file;
-        int in_file_index = meta_data_maps[i][1].file;
-        if (in_file_index < 0 || out_file_index < 0)
-            continue;
-        METADATA_CHECK_INDEX(out_file_index, nb_output_files, "output file")
-        METADATA_CHECK_INDEX(in_file_index, nb_input_files, "input file")
-
-        files[0] = output_files[out_file_index];
-        files[1] = input_files[in_file_index].ctx;
-
-        for (j = 0; j < 2; j++) {
-            MetadataMap *map = &meta_data_maps[i][j];
-
-            switch (map->type) {
-            case 'g':
-                meta[j] = &files[j]->metadata;
-                break;
-            case 's':
-                METADATA_CHECK_INDEX(map->index, files[j]->nb_streams, "stream")
-                meta[j] = &files[j]->streams[map->index]->metadata;
-                break;
-            case 'c':
-                METADATA_CHECK_INDEX(map->index, files[j]->nb_chapters, "chapter")
-                meta[j] = &files[j]->chapters[map->index]->metadata;
-                break;
-            case 'p':
-                METADATA_CHECK_INDEX(map->index, files[j]->nb_programs, "program")
-                meta[j] = &files[j]->programs[map->index]->metadata;
-                break;
-            }
-        }
-
-        av_dict_copy(meta[0], *meta[1], AV_DICT_DONT_OVERWRITE);
-    }
-
-    /* copy global metadata by default */
-    if (metadata_global_autocopy) {
-
-        for (i = 0; i < nb_output_files; i++)
-            av_dict_copy(&output_files[i]->metadata, input_files[0].ctx->metadata,
-                         AV_DICT_DONT_OVERWRITE);
-    }
-
     /* open files and write file headers */
     for(i=0;i<nb_output_files;i++) {
         os = output_files[i];
@@ -2963,10 +2902,9 @@ static int opt_map(const char *opt, const char *arg)
     return 0;
 }
 
-static void parse_meta_type(char *arg, char *type, int *index, char **endptr)
+static void parse_meta_type(char *arg, char *type, int *index)
 {
-    *endptr = arg;
-    if (*arg == ',') {
+    if (*arg == ':') {
         *type = *(++arg);
         switch (*arg) {
         case 'g':
@@ -2974,7 +2912,8 @@ static void parse_meta_type(char *arg, char *type, int *index, char **endptr)
         case 's':
         case 'c':
         case 'p':
-            *index = strtol(++arg, endptr, 0);
+            if (*(++arg) == ':')
+                *index = strtol(++arg, NULL, 0);
             break;
         default:
             fprintf(stderr, "Invalid metadata type %c.\n", *arg);
@@ -2992,15 +2931,15 @@ static int opt_map_metadata(const char *opt, const char *arg)
     meta_data_maps = grow_array(meta_data_maps, sizeof(*meta_data_maps),
                                 &nb_meta_data_maps, nb_meta_data_maps + 1);
 
-    m = &meta_data_maps[nb_meta_data_maps - 1][0];
+    m = &meta_data_maps[nb_meta_data_maps - 1][1];
     m->file = strtol(arg, &p, 0);
-    parse_meta_type(p, &m->type, &m->index, &p);
-    if (*p)
-        p++;
+    parse_meta_type(p, &m->type, &m->index);
 
-    m1 = &meta_data_maps[nb_meta_data_maps - 1][1];
-    m1->file = strtol(p, &p, 0);
-    parse_meta_type(p, &m1->type, &m1->index, &p);
+    m1 = &meta_data_maps[nb_meta_data_maps - 1][0];
+    if (p = strchr(opt, ':'))
+        parse_meta_type(p, &m1->type, &m1->index);
+    else
+        m1->type = 'g';
 
     if (m->type == 'g' || m1->type == 'g')
         metadata_global_autocopy = 0;
@@ -3777,6 +3716,62 @@ static void opt_output_file(const char *filename)
     if (chapters_input_file >= 0)
         copy_chapters(chapters_input_file, nb_output_files - 1);
 
+    /* copy metadata */
+    for (i = 0; i < nb_meta_data_maps; i++) {
+        AVFormatContext *files[2];
+        AVDictionary    **meta[2];
+        int j;
+
+#define METADATA_CHECK_INDEX(index, nb_elems, desc)\
+        if ((index) < 0 || (index) >= (nb_elems)) {\
+            av_log(NULL, AV_LOG_ERROR, "Invalid %s index %d while processing metadata maps\n",\
+                     (desc), (index));\
+            exit_program(1);\
+        }
+
+        int in_file_index = meta_data_maps[i][1].file;
+        if (in_file_index < 0)
+            continue;
+        METADATA_CHECK_INDEX(in_file_index, nb_input_files, "input file")
+
+        files[0] = oc;
+        files[1] = input_files[in_file_index].ctx;
+
+        for (j = 0; j < 2; j++) {
+            MetadataMap *map = &meta_data_maps[i][j];
+
+            switch (map->type) {
+            case 'g':
+                meta[j] = &files[j]->metadata;
+                break;
+            case 's':
+                METADATA_CHECK_INDEX(map->index, files[j]->nb_streams, "stream")
+                meta[j] = &files[j]->streams[map->index]->metadata;
+                break;
+            case 'c':
+                METADATA_CHECK_INDEX(map->index, files[j]->nb_chapters, "chapter")
+                meta[j] = &files[j]->chapters[map->index]->metadata;
+                break;
+            case 'p':
+                METADATA_CHECK_INDEX(map->index, files[j]->nb_programs, "program")
+                meta[j] = &files[j]->programs[map->index]->metadata;
+                break;
+            }
+        }
+
+        av_dict_copy(meta[0], *meta[1], AV_DICT_DONT_OVERWRITE);
+    }
+
+    /* copy global metadata by default */
+    if (metadata_global_autocopy)
+        av_dict_copy(&oc->metadata, input_files[0].ctx->metadata,
+                     AV_DICT_DONT_OVERWRITE);
+    if (metadata_streams_autocopy)
+        for (i = 0; i < oc->nb_streams; i++) {
+            InputStream *ist = &input_streams[output_streams_for_file[nb_output_files-1][i]->source_index];
+            av_dict_copy(&oc->streams[i]->metadata, ist->st->metadata, AV_DICT_DONT_OVERWRITE);
+        }
+
     frame_rate    = (AVRational){0, 0};
     frame_width   = 0;
     frame_height  = 0;
@@ -3785,6 +3780,12 @@ static void opt_output_file(const char *filename)
     audio_sample_fmt  = AV_SAMPLE_FMT_NONE;
     chapters_input_file = INT_MAX;
 
+    av_freep(&meta_data_maps);
+    nb_meta_data_maps = 0;
+    metadata_global_autocopy   = 1;
+    metadata_streams_autocopy  = 1;
+    metadata_chapters_autocopy = 1;
+
     av_freep(&forced_key_frames);
     uninit_opts();
     init_opts();
diff --git a/doc/avconv.texi b/doc/avconv.texi
index 32808fd..ab1df09 100644
--- a/doc/avconv.texi
+++ b/doc/avconv.texi
@@ -677,16 +677,16 @@ avconv -i a.mov -i b.mov -vcodec copy -acodec copy out.mov -map 0.2 -map 1.6
 To add more streams to the output file, you can use the
 @code{-newaudio}, @code{-newvideo}, @code{-newsubtitle} options.
 
- at item -map_metadata @var{outfile}[, at var{metadata}]:@var{infile}[, at var{metadata}]
-Set metadata information of @var{outfile} from @var{infile}. Note that those
-are file indices (zero-based), not filenames.
-Optional @var{metadata} parameters specify, which metadata to copy - (g)lobal
+ at item -map_metadata[:@var{metadata_type}][:@var{index}] @var{infile}[:@var{metadata_type}][:@var{index}]
+Set metadata information of the next output file from @var{infile}. Note that
+those are file indices (zero-based), not filenames.
+Optional @var{metadata_type} parameters specify, which metadata to copy - (g)lobal
 (i.e. metadata that applies to the whole file), per-(s)tream, per-(c)hapter or
 per-(p)rogram. All metadata specifiers other than global must be followed by the
-stream/chapter/program number. If metadata specifier is omitted, it defaults to
+stream/chapter/program index. If metadata specifier is omitted, it defaults to
 global.
 
-By default, global metadata is copied from the first input file to all output files,
+By default, global metadata is copied from the first input file,
 per-stream and per-chapter metadata is copied along with streams/chapters. These
 default mappings are disabled by creating any mapping of the relevant type. A negative
 file index can be used to create a dummy mapping that just disables automatic copying.
@@ -694,7 +694,7 @@ file index can be used to create a dummy mapping that just disables automatic co
 For example to copy metadata from the first stream of the input file to global metadata
 of the output file:
 @example
-avconv -i in.ogg -map_metadata 0:0,s0 out.mp3
+avconv -i in.ogg -map_metadata 0:s:0 out.mp3
 @end example
 @item -map_chapters @var{input_file_index}
 Copy chapters from input file with index @var{input_file_index} to the next



More information about the ffmpeg-cvslog mailing list