[FFmpeg-cvslog] r25635 - in trunk: doc/ffmpeg-doc.texi ffmpeg.c
elenril
subversion
Tue Nov 2 07:01:29 CET 2010
Author: elenril
Date: Tue Nov 2 07:01:28 2010
New Revision: 25635
Log:
ffmpeg.c: extend map_meta_data to allow advanced mappings
i.e. to/from streams/chapters/programs.
Modified:
trunk/doc/ffmpeg-doc.texi
trunk/ffmpeg.c
Modified: trunk/doc/ffmpeg-doc.texi
==============================================================================
--- trunk/doc/ffmpeg-doc.texi Tue Nov 2 04:09:16 2010 (r25634)
+++ trunk/doc/ffmpeg-doc.texi Tue Nov 2 07:01:28 2010 (r25635)
@@ -586,9 +586,19 @@ Set stream mapping from input streams to
Just enumerate the input streams in the order you want them in the output.
@var{sync_stream_id} if specified sets the input stream to sync
against.
- at item -map_meta_data @var{outfile}:@var{infile}
+ at item -map_meta_data @var{outfile}[, at var{metadata}]:@var{infile}[, at var{metadata}]
Set meta data 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
+(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
+global.
+For example to copy metadata from the first stream of the input file to global metadata
+of the output file:
+ at example
+ffmpeg -i in.ogg -map_meta_data 0:0,s0 out.mp3
+ at end example
@item -debug
Print specific debug info.
@item -benchmark
Modified: trunk/ffmpeg.c
==============================================================================
--- trunk/ffmpeg.c Tue Nov 2 04:09:16 2010 (r25634)
+++ trunk/ffmpeg.c Tue Nov 2 07:01:28 2010 (r25635)
@@ -97,8 +97,9 @@ typedef struct AVStreamMap {
* select an input file for an output file
*/
typedef struct AVMetaDataMap {
- int out_file;
- int in_file;
+ int file; //< file index
+ char type; //< type of metadata to copy -- (g)lobal, (s)tream, (c)hapter or (p)rogram
+ int index; //< stream/chapter/program number
} AVMetaDataMap;
static const OptionDef options[];
@@ -125,7 +126,8 @@ static int nb_output_codecs = 0;
static AVStreamMap *stream_maps = NULL;
static int nb_stream_maps;
-static AVMetaDataMap *meta_data_maps = NULL;
+/* first item specifies output metadata, second is input */
+static AVMetaDataMap (*meta_data_maps)[2] = NULL;
static int nb_meta_data_maps;
/* indexed by output file stream index */
@@ -2326,32 +2328,52 @@ static int transcode(AVFormatContext **o
/* set meta data information from input file if required */
for (i=0;i<nb_meta_data_maps;i++) {
- AVFormatContext *out_file;
- AVFormatContext *in_file;
+ AVFormatContext *files[2];
+ AVMetadata **meta[2];
AVMetadataTag *mtag;
+ int j;
- int out_file_index = meta_data_maps[i].out_file;
- int in_file_index = meta_data_maps[i].in_file;
- if (out_file_index < 0 || out_file_index >= nb_output_files) {
- snprintf(error, sizeof(error), "Invalid output file index %d map_meta_data(%d,%d)",
- out_file_index, out_file_index, in_file_index);
- ret = AVERROR(EINVAL);
- goto dump_format;
- }
- if (in_file_index < 0 || in_file_index >= nb_input_files) {
- snprintf(error, sizeof(error), "Invalid input file index %d map_meta_data(%d,%d)",
- in_file_index, out_file_index, in_file_index);
- ret = AVERROR(EINVAL);
- goto dump_format;
+#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;\
}
- out_file = output_files[out_file_index];
- in_file = input_files[in_file_index];
+ int out_file_index = meta_data_maps[i][0].file;
+ int in_file_index = meta_data_maps[i][1].file;
+ 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];
+
+ for (j = 0; j < 2; j++) {
+ AVMetaDataMap *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;
+ }
+ }
mtag=NULL;
- while((mtag=av_metadata_get(in_file->metadata, "", mtag, AV_METADATA_IGNORE_SUFFIX)))
- av_metadata_set2(&out_file->metadata, mtag->key, mtag->value, AV_METADATA_DONT_OVERWRITE);
+ while((mtag=av_metadata_get(*meta[1], "", mtag, AV_METADATA_IGNORE_SUFFIX)))
+ av_metadata_set2(meta[0], mtag->key, mtag->value, AV_METADATA_DONT_OVERWRITE);
}
/* copy chapters from the first input file that has them*/
@@ -2890,20 +2912,44 @@ static void opt_map(const char *arg)
}
}
+static void parse_meta_type(const char *arg, char *type, int *index, char **endptr)
+{
+ *endptr = arg;
+ if (*arg == ',') {
+ *type = *(++arg);
+ switch (*arg) {
+ case 'g':
+ break;
+ case 's':
+ case 'c':
+ case 'p':
+ *index = strtol(++arg, endptr, 0);
+ break;
+ default:
+ fprintf(stderr, "Invalid metadata type %c.\n", *arg);
+ ffmpeg_exit(1);
+ }
+ } else
+ *type = 'g';
+}
+
static void opt_map_meta_data(const char *arg)
{
- AVMetaDataMap *m;
+ AVMetaDataMap *m, *m1;
char *p;
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];
- m->out_file = strtol(arg, &p, 0);
+ m = &meta_data_maps[nb_meta_data_maps - 1][0];
+ m->file = strtol(arg, &p, 0);
+ parse_meta_type(p, &m->type, &m->index, &p);
if (*p)
p++;
- m->in_file = strtol(p, &p, 0);
+ 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);
}
static void opt_input_ts_scale(const char *arg)
@@ -4038,7 +4084,7 @@ static const OptionDef options[] = {
{ "i", HAS_ARG, {(void*)opt_input_file}, "input file name", "filename" },
{ "y", OPT_BOOL, {(void*)&file_overwrite}, "overwrite output files" },
{ "map", HAS_ARG | OPT_EXPERT, {(void*)opt_map}, "set input stream mapping", "file:stream[:syncfile:syncstream]" },
- { "map_meta_data", HAS_ARG | OPT_EXPERT, {(void*)opt_map_meta_data}, "set meta data information of outfile from infile", "outfile:infile" },
+ { "map_meta_data", HAS_ARG | OPT_EXPERT, {(void*)opt_map_meta_data}, "set meta data information of outfile from infile", "outfile[,metadata]:infile[,metadata]" },
{ "t", OPT_FUNC2 | HAS_ARG, {(void*)opt_recording_time}, "record or transcode \"duration\" seconds of audio/video", "duration" },
{ "fs", HAS_ARG | OPT_INT64, {(void*)&limit_filesize}, "set the limit file size in bytes", "limit_size" }, //
{ "ss", OPT_FUNC2 | HAS_ARG, {(void*)opt_start_time}, "set the start time offset", "time_off" },
More information about the ffmpeg-cvslog
mailing list