---
avengine.c | 4 ++--
avplay.c | 2 +-
cmdutils.c | 42 +++++++++++++++++++++++++++++++++++++-----
cmdutils.h | 2 +-
doc/fftools-common-opts.texi | 17 +++++++++++++++++
ffmpeg.c | 4 ++--
6 files changed, 60 insertions(+), 11 deletions(-)
diff --git a/avengine.c b/avengine.c
index 603f990..68e19a4 100644
--- a/avengine.c
+++ b/avengine.c
@@ -675,7 +675,7 @@ static OutputStream *new_output_stream(AVFormatContext *oc,
int file_idx, AVCode
ost->st = st;
ost->enc = codec;
if (codec)
- ost->opts = filter_codec_opts(codec_opts, codec->id, 1);
+ ost->opts = filter_codec_opts(codec_opts, codec->id, oc, idx);
avcodec_get_context_defaults3(st->codec, codec);
@@ -3198,7 +3198,7 @@ static int opt_input_file(const char *opt, const char
*filename)
ist->st = st;
ist->file_index = nb_input_files;
ist->discard = 1;
- ist->opts = filter_codec_opts(codec_opts, ist->st->codec->codec_id, 0);
+ ist->opts = filter_codec_opts(codec_opts, ist->st->codec->codec_id,
ic, i);
if (i < nb_ts_scale)
ist->ts_scale = ts_scale[i];
diff --git a/avplay.c b/avplay.c
index c1e70d1..9f3defd 100644
--- a/avplay.c
+++ b/avplay.c
@@ -2134,7 +2134,7 @@ static int stream_component_open(VideoState *is, int
stream_index)
return -1;
avctx = ic->streams[stream_index]->codec;
- opts = filter_codec_opts(codec_opts, avctx->codec_id, 0);
+ opts = filter_codec_opts(codec_opts, avctx->codec_id, ic, stream_index);
/* prepare audio output */
if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) {
diff --git a/cmdutils.c b/cmdutils.c
index b83caca..42be7db 100644
--- a/cmdutils.c
+++ b/cmdutils.c
@@ -286,7 +286,14 @@ unknown_opt:
int opt_default(const char *opt, const char *arg)
{
const AVOption *o;
- if ((o = av_opt_find(avcodec_opts[0], opt, NULL, 0,
AV_OPT_SEARCH_CHILDREN)) ||
+ char opt_stripped[128];
+ const char *p;
+
+ if (!(p = strchr(opt, ':')))
+ p = opt + strlen(opt);
+ av_strlcpy(opt_stripped, opt, FFMIN(sizeof(opt_stripped), p - opt + 1));
+
+ if ((o = av_opt_find(avcodec_opts[0], opt_stripped, NULL, 0,
AV_OPT_SEARCH_CHILDREN)) ||
((opt[0] == 'v' || opt[0] == 'a' || opt[0] == 's') &&
(o = av_opt_find(avcodec_opts[0], opt+1, NULL, 0, 0))))
av_dict_set(&codec_opts, opt, arg, FLAGS);
@@ -779,12 +786,12 @@ FILE *get_preset_file(char *filename, size_t
filename_size,
return f;
}
-AVDictionary *filter_codec_opts(AVDictionary *opts, enum CodecID codec_id, int
encoder)
+AVDictionary *filter_codec_opts(AVDictionary *opts, enum CodecID codec_id,
AVFormatContext *s, int stream_idx)
{
AVDictionary *ret = NULL;
AVDictionaryEntry *t = NULL;
- AVCodec *codec = encoder ? avcodec_find_encoder(codec_id) :
avcodec_find_decoder(codec_id);
- int flags = encoder ? AV_OPT_FLAG_ENCODING_PARAM :
AV_OPT_FLAG_DECODING_PARAM;
+ AVCodec *codec = s->oformat ? avcodec_find_encoder(codec_id) :
avcodec_find_decoder(codec_id);
+ int flags = s->oformat ? AV_OPT_FLAG_ENCODING_PARAM :
AV_OPT_FLAG_DECODING_PARAM;
char prefix = 0;
if (!codec)
@@ -797,6 +804,31 @@ AVDictionary *filter_codec_opts(AVDictionary *opts, enum
CodecID codec_id, int e
}
while (t = av_dict_get(opts, "", t, AV_DICT_IGNORE_SUFFIX)) {
+ char *p = strchr(t->key, ':');
+ int idx = -1, i;
+
+ /* check stream specification in opt name */
+ if (p && *(p + 1)) {
+ *p++ = 0;
+
+ if (*p <= '9' && *p >= '0') { /* Either
opt:stream number */
+ if (strtol(p, NULL, 10) != stream_idx)
+ continue;
+ } else if (*p == 'v' || *p == 'a' || *p == 's') { /* or
opt:[vas] */
+ if (*p++ != prefix)
+ continue;
+ if (*p++ == ':') { /* possibly
followed by :stream number */
+ idx = strtol(p, NULL, 10);
+ for (i = 0; i <= stream_idx; i++)
+ if (s->streams[i]->codec->codec_type ==
s->streams[stream_idx]->codec->codec_type)
+ idx--;
+ if (idx)
+ continue;
+ }
+ } else
+ av_log(NULL, AV_LOG_ERROR, "Invalid stream specification %s in
option %s.\n", p, t->key);
+ }
+
if (av_opt_find(avcodec_opts[0], t->key, NULL, flags, 0) ||
(codec && codec->priv_class && av_opt_find(&codec->priv_class,
t->key, NULL, flags, 0)))
av_dict_set(&ret, t->key, t->value, 0);
@@ -819,7 +851,7 @@ AVDictionary **setup_find_stream_info_opts(AVFormatContext
*s, AVDictionary *cod
return NULL;
}
for (i = 0; i < s->nb_streams; i++)
- opts[i] = filter_codec_opts(codec_opts,
s->streams[i]->codec->codec_id, 0);
+ opts[i] = filter_codec_opts(codec_opts,
s->streams[i]->codec->codec_id, s, i);
return opts;
}
diff --git a/cmdutils.h b/cmdutils.h
index 7769194..ea2f85f 100644
--- a/cmdutils.h
+++ b/cmdutils.h
@@ -157,7 +157,7 @@ void parse_options(int argc, char **argv, const OptionDef
*options,
* @param encoder if non-zero the codec is an encoder, otherwise is a decoder
* @return a pointer to the created dictionary
*/
-AVDictionary *filter_codec_opts(AVDictionary *opts, enum CodecID codec_id, int
encoder);
+AVDictionary *filter_codec_opts(AVDictionary *opts, enum CodecID codec_id,
AVFormatContext *s, int stream_idx);
/**
* Setup AVCodecContext options for avformat_find_stream_info().
diff --git a/doc/fftools-common-opts.texi b/doc/fftools-common-opts.texi
index ba91b87..8ffc329 100644
--- a/doc/fftools-common-opts.texi
+++ b/doc/fftools-common-opts.texi
@@ -114,5 +114,22 @@ muxer:
ffmpeg -i input.flac -id3v2_version 3 out.mp3
@end example
+You can precisely specify which stream(s) should the codec AVOption apply to by
+appending a stream specifier of the form
+@option{[:@var{stream_type}][:@var{stream_index}]} to the option name.
+@var{stream_type} is 'v' for video, 'a' for audio and 's' for subtitle streams.
+@var{stream_index} is a global stream index when @var{stream_type} isn't
+given, otherwise it counts streams of the given type only. As always, the index
+is zero-based. For example
+@example
+-foo -- applies to all applicable streams
+-foo:v -- applies to all video streams
+-foo:a:2 -- applies to the third audio stream
+-foo:0 -- applies to the first stream
+@end example
+
Note -nooption syntax cannot be used for boolean AVOptions, use -option
0/-option 1.
+
+Note2 old undocumented way of specifying per-stream AVOptions by prepending
+v/a/s to the options name is now obsolete and will be removed soon.
diff --git a/ffmpeg.c b/ffmpeg.c
index fda5bc8..702642f 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -683,7 +683,7 @@ static OutputStream *new_output_stream(AVFormatContext *oc,
int file_idx, AVCode
ost->st = st;
ost->enc = codec;
if (codec)
- ost->opts = filter_codec_opts(codec_opts, codec->id, 1);
+ ost->opts = filter_codec_opts(codec_opts, codec->id, oc, idx);
avcodec_get_context_defaults3(st->codec, codec);
@@ -3293,7 +3293,7 @@ static int opt_input_file(const char *opt, const char
*filename)
ist->st = st;
ist->file_index = nb_input_files;
ist->discard = 1;
- ist->opts = filter_codec_opts(codec_opts, ist->st->codec->codec_id, 0);
+ ist->opts = filter_codec_opts(codec_opts, ist->st->codec->codec_id,
ic, i);
if (i < nb_ts_scale)
ist->ts_scale = ts_scale[i];
--
1.7.5.4
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel