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.
This commit is contained in:
Anton Khirnov 2011-07-29 15:21:51 +02:00
parent 3d4f0dab79
commit 8d2e4a7e68
2 changed files with 113 additions and 44 deletions

110
avconv.c
View File

@ -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;
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++;
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;
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);
}
}
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->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) {

View File

@ -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