[FFmpeg-cvslog] lavfi: switch to an AVOptions-based system.

Anton Khirnov git at videolan.org
Wed Apr 10 12:55:38 CEST 2013


ffmpeg | branch: master | Anton Khirnov <anton at khirnov.net> | Mon Feb 25 21:21:29 2013 +0100| [b439c992c23f3e0f3832fffd2a34a664b236c525] | committer: Anton Khirnov

lavfi: switch to an AVOptions-based system.

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

 doc/filters.texi       |   21 +++++++++++--
 libavfilter/avfilter.c |   81 +++++++++++++++++++++++++++++++++++++++++++++++-
 libavfilter/avfilter.h |    6 ++++
 libavfilter/version.h  |    3 ++
 4 files changed, 108 insertions(+), 3 deletions(-)

diff --git a/doc/filters.texi b/doc/filters.texi
index 88888c6..d32a261 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -41,8 +41,25 @@ The name of the filter class is optionally followed by a string
 "=@var{arguments}".
 
 @var{arguments} is a string which contains the parameters used to
-initialize the filter instance, and are described in the filter
-descriptions below.
+initialize the filter instance. It may have one of the two allowed forms:
+ at itemize
+
+ at item
+A ':'-separated list of @var{key=value} pairs.
+
+ at item
+A ':'-separated list of @var{value}. In this case, the keys are assumed to be
+the option names in the order they are declared. E.g. the @code{fade} filter
+declares three options in this order -- @option{type}, @option{start_frame} and
+ at option{nb_frames}. Then the parameter list @var{in:0:30} means that the value
+ at var{in} is assigned to the option @option{type}, @var{0} to
+ at option{start_frame} and @var{30} to @option{nb_frames}.
+
+ at end itemize
+
+If the option value itself is a list of items (e.g. the @code{format} filter
+takes a list of pixel formats), the items in the list are usually separated by
+'|'.
 
 The list of arguments can be quoted using the character "'" as initial
 and ending mark, and the character '\' for escaping the characters
diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c
index 4985ce9..93d1855 100644
--- a/libavfilter/avfilter.c
+++ b/libavfilter/avfilter.c
@@ -21,9 +21,11 @@
 
 /* #define DEBUG */
 
+#include "libavutil/avstring.h"
 #include "libavutil/channel_layout.h"
 #include "libavutil/common.h"
 #include "libavutil/imgutils.h"
+#include "libavutil/opt.h"
 #include "libavutil/pixdesc.h"
 #include "libavutil/rational.h"
 #include "libavutil/samplefmt.h"
@@ -346,6 +348,11 @@ int avfilter_open(AVFilterContext **filter_ctx, AVFilter *filter, const char *in
             goto err;
     }
 
+    if (filter->priv_class) {
+        *(const AVClass**)ret->priv = filter->priv_class;
+        av_opt_set_defaults(ret->priv);
+    }
+
     ret->nb_inputs = pad_count(filter->inputs);
     if (ret->nb_inputs ) {
         ret->input_pads   = av_malloc(sizeof(AVFilterPad) * ret->nb_inputs);
@@ -422,6 +429,9 @@ void avfilter_free(AVFilterContext *filter)
         av_freep(&link);
     }
 
+    if (filter->filter->priv_class)
+        av_opt_free(filter->priv);
+
     av_freep(&filter->name);
     av_freep(&filter->input_pads);
     av_freep(&filter->output_pads);
@@ -431,12 +441,81 @@ void avfilter_free(AVFilterContext *filter)
     av_free(filter);
 }
 
+/* process a list of value1:value2:..., each value corresponding
+ * to subsequent AVOption, in the order they are declared */
+static int process_unnamed_options(AVFilterContext *ctx, AVDictionary **options,
+                                   const char *args)
+{
+    const AVOption *o = NULL;
+    const char *p = args;
+    char *val;
+
+    while (*p) {
+        o = av_opt_next(ctx->priv, o);
+        if (!o) {
+            av_log(ctx, AV_LOG_ERROR, "More options provided than "
+                   "this filter supports.\n");
+            return AVERROR(EINVAL);
+        }
+        if (o->type == AV_OPT_TYPE_CONST)
+            continue;
+
+        val = av_get_token(&p, ":");
+        if (!val)
+            return AVERROR(ENOMEM);
+
+        av_dict_set(options, o->name, val, 0);
+
+        av_freep(&val);
+        if (*p)
+            p++;
+    }
+
+    return 0;
+}
+
 int avfilter_init_filter(AVFilterContext *filter, const char *args, void *opaque)
 {
+    AVDictionary *options = NULL;
+    AVDictionaryEntry *e;
     int ret=0;
 
-    if (filter->filter->init)
+    if (args && *args && filter->filter->priv_class) {
+        if (strchr(args, '=')) {
+            /* assume a list of key1=value1:key2=value2:... */
+            ret = av_dict_parse_string(&options, args, "=", ":", 0);
+            if (ret < 0)
+                goto fail;
+        } else {
+            ret = process_unnamed_options(filter, &options, args);
+            if (ret < 0)
+                goto fail;
+        }
+    }
+
+    if (filter->filter->priv_class) {
+        ret = av_opt_set_dict(filter->priv, &options);
+        if (ret < 0) {
+            av_log(filter, AV_LOG_ERROR, "Error applying options to the filter.\n");
+            goto fail;
+        }
+    }
+
+    if (filter->filter->init) {
         ret = filter->filter->init(filter, args);
+        if (ret < 0)
+            goto fail;
+    }
+
+    if ((e = av_dict_get(options, "", NULL, AV_DICT_IGNORE_SUFFIX))) {
+        av_log(filter, AV_LOG_ERROR, "No such option: %s.\n", e->key);
+        ret = AVERROR_OPTION_NOT_FOUND;
+        goto fail;
+    }
+
+fail:
+    av_dict_free(&options);
+
     return ret;
 }
 
diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h
index b3522f8..66f57df 100644
--- a/libavfilter/avfilter.h
+++ b/libavfilter/avfilter.h
@@ -388,6 +388,12 @@ typedef struct AVFilter {
     const AVFilterPad *inputs;  ///< NULL terminated list of inputs. NULL if none
     const AVFilterPad *outputs; ///< NULL terminated list of outputs. NULL if none
 
+    /**
+     * A class for the private data, used to access filter private
+     * AVOptions.
+     */
+    const AVClass *priv_class;
+
     /*****************************************************************
      * All fields below this line are not part of the public API. They
      * may not be used outside of libavfilter and can be changed and
diff --git a/libavfilter/version.h b/libavfilter/version.h
index 1a5ec42..914b7ca 100644
--- a/libavfilter/version.h
+++ b/libavfilter/version.h
@@ -55,5 +55,8 @@
 #ifndef FF_API_AVFILTERBUFFER
 #define FF_API_AVFILTERBUFFER               (LIBAVFILTER_VERSION_MAJOR < 4)
 #endif
+#ifndef FF_API_OLD_FILTER_OPTS
+#define FF_API_OLD_FILTER_OPTS              (LIBAVFILTER_VERSION_MAJOR < 4)
+#endif
 
 #endif /* AVFILTER_VERSION_H */



More information about the ffmpeg-cvslog mailing list