diff options
author | Anton Khirnov | 2011-07-29 15:21:51 +0200 |
---|---|---|
committer | Anton Khirnov | 2011-08-12 19:10:22 +0200 |
commit | 8d2e4a7e687b7fdbb939e236399cf774dc7bead6 (patch) | |
tree | b5df07f2cf2d499a9b7c31ce4f9fa564cdeb7451 | |
parent | 3d4f0dab79ccc8b1a662de440a789ec00b428963 (diff) |
avconv: change semantics of -map
New syntax contains an optional stream type, allowing to refer to n-th
stream of specific type.
Omitting stream number now maps all streams of the given type.
-rw-r--r-- | avconv.c | 106 | ||||
-rw-r--r-- | doc/avconv.texi | 47 |
2 files changed, 111 insertions, 42 deletions
@@ -79,6 +79,7 @@ const int program_birth_year = 2000; /* select an input stream for an output stream */ typedef struct StreamMap { + int disabled; /** 1 is this mapping is disabled by a negative map */ int file_index; int stream_index; int sync_file_index; @@ -2780,27 +2781,82 @@ static int opt_codec_tag(const char *opt, const char *arg) static int opt_map(const char *opt, const char *arg) { - StreamMap *m; - char *p; + StreamMap *m = NULL; + int i, negative = 0, file_idx; + int sync_file_idx = -1, sync_stream_idx; + char *p, *sync; + char *map; + + if (*arg == '-') { + negative = 1; + arg++; + } + map = av_strdup(arg); + + /* parse sync stream first, just pick first matching stream */ + if (sync = strchr(map, ',')) { + *sync = 0; + sync_file_idx = strtol(sync + 1, &sync, 0); + if (sync_file_idx >= nb_input_files || sync_file_idx < 0) { + av_log(NULL, AV_LOG_ERROR, "Invalid sync file index: %d.\n", sync_file_idx); + exit_program(1); + } + if (*sync) + sync++; + for (i = 0; i < input_files[sync_file_idx].ctx->nb_streams; i++) + if (check_stream_specifier(input_files[sync_file_idx].ctx, + input_files[sync_file_idx].ctx->streams[i], sync) == 1) { + sync_stream_idx = i; + break; + } + if (i == input_files[sync_file_idx].ctx->nb_streams) { + av_log(NULL, AV_LOG_ERROR, "Sync stream specification in map %s does not " + "match any streams.\n", arg); + exit_program(1); + } + } - stream_maps = grow_array(stream_maps, sizeof(*stream_maps), &nb_stream_maps, nb_stream_maps + 1); - m = &stream_maps[nb_stream_maps-1]; - m->file_index = strtol(arg, &p, 0); - if (*p) - p++; + file_idx = strtol(map, &p, 0); + if (file_idx >= nb_input_files || file_idx < 0) { + av_log(NULL, AV_LOG_ERROR, "Invalid input file index: %d.\n", file_idx); + exit_program(1); + } + if (negative) + /* disable some already defined maps */ + for (i = 0; i < nb_stream_maps; i++) { + m = &stream_maps[i]; + if (check_stream_specifier(input_files[m->file_index].ctx, + input_files[m->file_index].ctx->streams[m->stream_index], + *p == ':' ? p + 1 : p) > 0) + m->disabled = 1; + } + else + for (i = 0; i < input_files[file_idx].ctx->nb_streams; i++) { + if (check_stream_specifier(input_files[file_idx].ctx, input_files[file_idx].ctx->streams[i], + *p == ':' ? p + 1 : p) <= 0) + continue; + stream_maps = grow_array(stream_maps, sizeof(*stream_maps), &nb_stream_maps, nb_stream_maps + 1); + m = &stream_maps[nb_stream_maps - 1]; - m->stream_index = strtol(p, &p, 0); - if (*p) { - p++; - m->sync_file_index = strtol(p, &p, 0); - if (*p) - p++; - m->sync_stream_index = strtol(p, &p, 0); - } else { - m->sync_file_index = m->file_index; - m->sync_stream_index = m->stream_index; + m->file_index = file_idx; + m->stream_index = i; + + if (sync_file_idx >= 0) { + m->sync_file_index = sync_file_idx; + m->sync_stream_index = sync_stream_idx; + } else { + m->sync_file_index = file_idx; + m->sync_stream_index = i; + } + } + + if (!m) { + av_log(NULL, AV_LOG_ERROR, "Stream map '%s' matches no streams.\n", arg); + exit_program(1); } + + av_freep(&map); return 0; } @@ -3514,21 +3570,9 @@ static void opt_output_file(const char *filename) } else { for (i = 0; i < nb_stream_maps; i++) { StreamMap *map = &stream_maps[i]; - int fi = map->file_index; - int si = map->stream_index; - if (fi < 0 || fi >= nb_input_files || - si < 0 || si >= input_files[fi].ctx->nb_streams) { - av_log(NULL, AV_LOG_ERROR, "Input stream #%d.%d does not exist.\n", fi, si); - exit_program(1); - } - fi = map->sync_file_index; - si = map->sync_stream_index; - if (fi < 0 || fi >= nb_input_files || - si < 0 || si >= input_files[fi].ctx->nb_streams) { - av_log(NULL, AV_LOG_ERROR, "Sync stream #%d.%d does not exist.\n", fi, si); - exit_program(1); - } + if (map->disabled) + continue; ist = &input_streams[input_files[map->file_index].ist_index + map->stream_index]; switch (ist->st->codec->codec_type) { diff --git a/doc/avconv.texi b/doc/avconv.texi index d325b1d14f..d9d20137aa 100644 --- a/doc/avconv.texi +++ b/doc/avconv.texi @@ -634,35 +634,60 @@ Synchronize read on input. @section Advanced options @table @option -@item -map @var{input_file_id}.@var{input_stream_id}[:@var{sync_file_id}.@var{sync_stream_id}] +@item -map [-]@var{input_file_id}[:@var{input_stream_type}][:@var{input_stream_id}][,@var{sync_file_id}[:@var{sync_stream_type}][:@var{sync_stream_id}]] -Designate an input stream as a source for the output file. Each input +Designate one or more input streams as a source for the output file. Each input stream is identified by the input file index @var{input_file_id} and the input stream index @var{input_stream_id} within the input -file. Both indexes start at 0. If specified, -@var{sync_file_id}.@var{sync_stream_id} sets which input stream +file. Both indices start at 0. If specified, +@var{sync_file_id}:@var{sync_stream_id} sets which input stream is used as a presentation sync reference. +If @var{input_stream_type} is specified -- 'v' for video, 'a' for audio, 's' for +subtitle and 'd' for data -- then @var{input_stream_id} counts only the streams +of this type. Same for @var{sync_stream_type}. + +@var{input_stream_id} may be omitted, in which case all streams of the given +type are mapped (or all streams in the file, if no type is specified). + The first @code{-map} option on the command line specifies the source for output stream 0, the second @code{-map} option specifies the source for output stream 1, etc. +A @code{-} character before the stream identifier creates a "negative" mapping. +It disables matching streams from already created mappings. + +For example, to map ALL streams from the first input file to output +@example +av -i INPUT -map 0 output +@end example + For example, if you have two audio streams in the first input file, -these streams are identified by "0.0" and "0.1". You can use +these streams are identified by "0:0" and "0:1". You can use @code{-map} to select which streams to place in an output file. For example: @example -avconv -i INPUT -map 0.1 out.wav +avconv -i INPUT -map 0:1 out.wav @end example -will map the input stream in @file{INPUT} identified by "0.1" to +will map the input stream in @file{INPUT} identified by "0:1" to the (single) output stream in @file{out.wav}. For example, to select the stream with index 2 from input file -@file{a.mov} (specified by the identifier "0.2"), and stream with -index 6 from input @file{b.mov} (specified by the identifier "1.6"), +@file{a.mov} (specified by the identifier "0:2"), and stream with +index 6 from input @file{b.mov} (specified by the identifier "1:6"), and copy them to the output file @file{out.mov}: @example -avconv -i a.mov -i b.mov -vcodec copy -acodec copy -map 0.2 -map 1.6 out.mov +avconv -i a.mov -i b.mov -vcodec copy -acodec copy -map 0:2 -map 1:6 out.mov +@end example + +To select all video and the third audio stream from an input file: +@example +avconv -i INPUT -map 0:v -map 0:a:2 OUTPUT +@end example + +To map all the streams except the second audio, use negative mappings +@example +avconv -i INPUT -map 0 -map -0:a:1 OUTPUT @end example Note that using this option disables the default mappings for this output file. @@ -943,7 +968,7 @@ You can encode to several formats at the same time and define a mapping from input stream to output streams: @example -avconv -i /tmp/a.wav -ab 64k /tmp/a.mp2 -ab 128k /tmp/b.mp2 -map 0:0 -map 0:0 +avconv -i /tmp/a.wav -map 0:a -ab 64k /tmp/a.mp2 -map 0:a -ab 128k /tmp/b.mp2 @end example Converts a.wav to a.mp2 at 64 kbits and to b.mp2 at 128 kbits. '-map |