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

Reply via email to