[FFmpeg-cvslog] avconv: do not silently ignore unused codec AVOptions.

Anton Khirnov git at videolan.org
Tue Mar 12 21:39:31 CET 2013


ffmpeg | branch: master | Anton Khirnov <anton at khirnov.net> | Thu Feb 21 10:58:46 2013 +0100| [e7553f4c781751dc8ff243526caae009fc101921] | committer: Anton Khirnov

avconv: do not silently ignore unused codec AVOptions.

Print an error and abort when the option is of the wrong type (decoding
for output file or vice versa), since this could never be correct for
any input or output configuration.

Print a warning and continue when the option is of the correct type,
just unused, so same commandlines can be reused for different kinds of
input or output files.

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=e7553f4c781751dc8ff243526caae009fc101921
---

 Changelog    |    2 ++
 avconv_opt.c |   89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 91 insertions(+)

diff --git a/Changelog b/Changelog
index 4df4b8d..15c0873 100644
--- a/Changelog
+++ b/Changelog
@@ -5,6 +5,8 @@ version 10:
 - av_strnstr
 - support ID3v2 tags in ASF files
 - reference-counting for AVFrame and AVPacket data
+- avconv now fails when input options are used for output file
+  or vice versa
 
 
 version 9:
diff --git a/avconv_opt.c b/avconv_opt.c
index 1d2a7ef..30fbadf 100644
--- a/avconv_opt.c
+++ b/avconv_opt.c
@@ -119,6 +119,24 @@ static void init_options(OptionsContext *o)
     o->chapters_input_file = INT_MAX;
 }
 
+/* return a copy of the input with the stream specifiers removed from the keys */
+static AVDictionary *strip_specifiers(AVDictionary *dict)
+{
+    AVDictionaryEntry *e = NULL;
+    AVDictionary    *ret = NULL;
+
+    while ((e = av_dict_get(dict, "", e, AV_DICT_IGNORE_SUFFIX))) {
+        char *p = strchr(e->key, ':');
+
+        if (p)
+            *p = 0;
+        av_dict_set(&ret, e->key, e->value, 0);
+        if (p)
+            *p = ':';
+    }
+    return ret;
+}
+
 static double parse_frame_aspect_ratio(const char *arg)
 {
     int x = 0, y = 0;
@@ -553,6 +571,8 @@ static int open_input_file(OptionsContext *o, const char *filename)
     int64_t timestamp;
     uint8_t buf[128];
     AVDictionary **opts;
+    AVDictionary *unused_opts = NULL;
+    AVDictionaryEntry *e = NULL;
     int orig_nb_streams;                     // number of streams before avformat_find_stream_info
 
     if (o->format) {
@@ -666,6 +686,39 @@ static int open_input_file(OptionsContext *o, const char *filename)
     f->nb_streams = ic->nb_streams;
     f->rate_emu   = o->rate_emu;
 
+    /* check if all codec options have been used */
+    unused_opts = strip_specifiers(o->g->codec_opts);
+    for (i = f->ist_index; i < nb_input_streams; i++) {
+        e = NULL;
+        while ((e = av_dict_get(input_streams[i]->opts, "", e,
+                                AV_DICT_IGNORE_SUFFIX)))
+            av_dict_set(&unused_opts, e->key, NULL, 0);
+    }
+
+    e = NULL;
+    while ((e = av_dict_get(unused_opts, "", e, AV_DICT_IGNORE_SUFFIX))) {
+        const AVClass *class = avcodec_get_class();
+        const AVOption *option = av_opt_find(&class, e->key, NULL, 0,
+                                             AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ);
+        if (!option)
+            continue;
+        if (!(option->flags & AV_OPT_FLAG_DECODING_PARAM)) {
+            av_log(NULL, AV_LOG_ERROR, "Codec AVOption %s (%s) specified for "
+                   "input file #%d (%s) is not a decoding option.\n", e->key,
+                   option->help ? option->help : "", nb_input_files - 1,
+                   filename);
+            exit(1);
+        }
+
+        av_log(NULL, AV_LOG_WARNING, "Codec AVOption %s (%s) specified for "
+               "input file #%d (%s) has not been used for any stream. The most "
+               "likely reason is either wrong type (e.g. a video option with "
+               "no video streams) or that it is a private option of some decoder "
+               "which was not actually used for any stream.\n", e->key,
+               option->help ? option->help : "", nb_input_files - 1, filename);
+    }
+    av_dict_free(&unused_opts);
+
     for (i = 0; i < o->nb_dump_attachment; i++) {
         int j;
 
@@ -1179,6 +1232,8 @@ static int open_output_file(OptionsContext *o, const char *filename)
     OutputFile *of;
     OutputStream *ost;
     InputStream  *ist;
+    AVDictionary *unused_opts = NULL;
+    AVDictionaryEntry *e = NULL;
 
     if (configure_complex_filters() < 0) {
         av_log(NULL, AV_LOG_FATAL, "Error configuring filters.\n");
@@ -1384,6 +1439,40 @@ loop_end:
     of->shortest       = o->shortest;
     av_dict_copy(&of->opts, o->g->format_opts, 0);
 
+
+    /* check if all codec options have been used */
+    unused_opts = strip_specifiers(o->g->codec_opts);
+    for (i = of->ost_index; i < nb_output_streams; i++) {
+        e = NULL;
+        while ((e = av_dict_get(output_streams[i]->opts, "", e,
+                                AV_DICT_IGNORE_SUFFIX)))
+            av_dict_set(&unused_opts, e->key, NULL, 0);
+    }
+
+    e = NULL;
+    while ((e = av_dict_get(unused_opts, "", e, AV_DICT_IGNORE_SUFFIX))) {
+        const AVClass *class = avcodec_get_class();
+        const AVOption *option = av_opt_find(&class, e->key, NULL, 0,
+                                             AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ);
+        if (!option)
+            continue;
+        if (!(option->flags & AV_OPT_FLAG_ENCODING_PARAM)) {
+            av_log(NULL, AV_LOG_ERROR, "Codec AVOption %s (%s) specified for "
+                   "output file #%d (%s) is not an encoding option.\n", e->key,
+                   option->help ? option->help : "", nb_output_files - 1,
+                   filename);
+            exit(1);
+        }
+
+        av_log(NULL, AV_LOG_WARNING, "Codec AVOption %s (%s) specified for "
+               "output file #%d (%s) has not been used for any stream. The most "
+               "likely reason is either wrong type (e.g. a video option with "
+               "no video streams) or that it is a private option of some encoder "
+               "which was not actually used for any stream.\n", e->key,
+               option->help ? option->help : "", nb_output_files - 1, filename);
+    }
+    av_dict_free(&unused_opts);
+
     /* check filename in case of an image number is expected */
     if (oc->oformat->flags & AVFMT_NEEDNUMBER) {
         if (!av_filename_number_test(oc->filename)) {



More information about the ffmpeg-cvslog mailing list