]> git.sesse.net Git - ffmpeg/blobdiff - libavfilter/avfilter.c
avfilter: add missing ,
[ffmpeg] / libavfilter / avfilter.c
index 0d76b985abab0b1e31a19fe89144db7033eb39fd..c3336243f15e51bc88b5b168c10ba6c23e0cdaf6 100644 (file)
@@ -456,28 +456,28 @@ static const char *default_filter_name(void *filter_ctx)
 static void *filter_child_next(void *obj, void *prev)
 {
     AVFilterContext *ctx = obj;
-    if (!prev && ctx->filter && ctx->filter->priv_class)
+    if (!prev && ctx->filter && ctx->filter->priv_class && ctx->priv)
         return ctx->priv;
     return NULL;
 }
 
 static const AVClass *filter_child_class_next(const AVClass *prev)
 {
-    AVFilter **filter_ptr = NULL;
+    AVFilter **f = NULL;
 
     /* find the filter that corresponds to prev */
-    while (prev && *(filter_ptr = av_filter_next(filter_ptr)))
-        if ((*filter_ptr)->priv_class == prev)
+    while (prev && *(f = av_filter_next(f)))
+        if ((*f)->priv_class == prev)
             break;
 
     /* could not find filter corresponding to prev */
-    if (prev && !(*filter_ptr))
+    if (prev && !(*f))
         return NULL;
 
     /* find next filter with specific options */
-    while (*(filter_ptr = av_filter_next(filter_ptr)))
-        if ((*filter_ptr)->priv_class)
-            return (*filter_ptr)->priv_class;
+    while (*(f = av_filter_next(f)))
+        if ((*f)->priv_class)
+            return (*f)->priv_class;
     return NULL;
 }
 
@@ -490,11 +490,6 @@ static const AVClass avfilter_class = {
     .child_class_next = filter_child_class_next,
 };
 
-const AVClass *avfilter_get_class(void)
-{
-    return &avfilter_class;
-}
-
 int avfilter_open(AVFilterContext **filter_ctx, AVFilter *filter, const char *inst_name)
 {
     AVFilterContext *ret;
@@ -615,38 +610,98 @@ 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)
+static int process_options(AVFilterContext *ctx, AVDictionary **options,
+                           const char *args)
 {
     const AVOption *o = NULL;
-    const char *p = args;
-    char *val;
+    int ret, count = 0;
+    char *av_uninit(parsed_key), *av_uninit(value);
+    const char *key;
     int offset= -1;
 
-    while (*p) {
+    if (!args)
+        return 0;
+
+    while (*args) {
+        const char *shorthand = NULL;
+
         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) {
+            if (o->type == AV_OPT_TYPE_CONST || o->offset == offset)
+                continue;
+            offset = o->offset;
+            shorthand = o->name;
         }
-        if (o->type == AV_OPT_TYPE_CONST || o->offset == offset)
-            continue;
-        offset = o->offset;
 
-        val = av_get_token(&p, ":");
-        if (!val)
-            return AVERROR(ENOMEM);
+        ret = av_opt_get_key_value(&args, "=", ":",
+                                   shorthand ? AV_OPT_FLAG_IMPLICIT_KEY : 0,
+                                   &parsed_key, &value);
+        if (ret < 0) {
+            if (ret == AVERROR(EINVAL))
+                av_log(ctx, AV_LOG_ERROR, "No option name near '%s'\n", args);
+            else
+                av_log(ctx, AV_LOG_ERROR, "Unable to parse '%s': %s\n", args,
+                       av_err2str(ret));
+            return ret;
+        }
+        if (*args)
+            args++;
+        if (parsed_key) {
+            key = parsed_key;
+            while ((o = av_opt_next(ctx->priv, o))); /* discard all remaining shorthand */
+        } else {
+            key = shorthand;
+        }
 
-        av_dict_set(options, o->name, val, 0);
+        av_log(ctx, AV_LOG_DEBUG, "Setting '%s' to value '%s'\n", key, value);
+        av_dict_set(options, key, value, 0);
+        if ((ret = av_opt_set(ctx->priv, key, value, 0)) < 0) {
+            if (ret == AVERROR_OPTION_NOT_FOUND)
+                av_log(ctx, AV_LOG_ERROR, "Option '%s' not found\n", key);
+            av_free(value);
+            av_free(parsed_key);
+            return ret;
+        }
 
-        av_freep(&val);
-        if (*p)
-            p++;
+        av_free(value);
+        av_free(parsed_key);
+        count++;
     }
+    return count;
+}
+
+// TODO: drop me
+static const char *const filters_left_to_update[] = {
+    "abuffer",
+    "aconvert",
+    "aevalsrc",
+    "amerge",
+    "anullsrc",
+    "aresample",
+    "asendcmd",
+    "asetnsamples",
+    "astreamsync",
+    "atempo",
+    "bbox",
+    "blackdetect",
+    "buffer",
+    "flite",
+    "hue",
+    "mp",
+    "pan",
+    "removelogo",
+    "scale",
+    "sendcmd",
+    "setdar",
+    "setsar",
+};
 
+static int filter_use_deprecated_init(const char *name)
+{
+    int i;
+    for (i = 0; i < FF_ARRAY_ELEMS(filters_left_to_update); i++)
+        if (!strcmp(name, filters_left_to_update[i]))
+            return 1;
     return 0;
 }
 
@@ -655,43 +710,9 @@ int avfilter_init_filter(AVFilterContext *filter, const char *args, void *opaque
     AVDictionary *options = NULL;
     AVDictionaryEntry *e;
     int ret=0;
-    int anton_options =
-        !strcmp(filter->filter->name,  "aformat") ||
-        !strcmp(filter->filter->name,  "blackframe") ||
-        !strcmp(filter->filter->name,  "boxblur"   ) ||
-        !strcmp(filter->filter->name,  "colormatrix") ||
-        !strcmp(filter->filter->name,  "crop"      ) ||
-        !strcmp(filter->filter->name,  "cropdetect") ||
-        !strcmp(filter->filter->name,  "delogo"    ) ||
-        !strcmp(filter->filter->name,  "drawbox"   ) ||
-        !strcmp(filter->filter->name,  "drawtext"  ) ||
-        !strcmp(filter->filter->name,  "ebur128"   ) ||
-        !strcmp(filter->filter->name,  "fade"      ) ||
-        !strcmp(filter->filter->name,  "fieldorder") ||
-        !strcmp(filter->filter->name,  "fps"       ) ||
-        !strcmp(filter->filter->name,  "frei0r"    ) ||
-        !strcmp(filter->filter->name,  "frei0r_src") ||
-        !strcmp(filter->filter->name, "gradfun"    ) ||
-        !strcmp(filter->filter->name, "hqdn3d"     ) ||
-        !strcmp(filter->filter->name, "ocv"        ) ||
-        !strcmp(filter->filter->name, "lut"        ) ||
-        !strcmp(filter->filter->name, "lutyuv"     ) ||
-        !strcmp(filter->filter->name, "lutrgb"     ) ||
-        !strcmp(filter->filter->name, "negate"     ) ||
-        !strcmp(filter->filter->name, "overlay"    ) ||
-        !strcmp(filter->filter->name, "pad"        ) ||
-        !strcmp(filter->filter->name,   "format") ||
-        !strcmp(filter->filter->name, "noformat") ||
-        !strcmp(filter->filter->name, "perms")  ||
-        !strcmp(filter->filter->name, "aperms") ||
-        !strcmp(filter->filter->name, "resample") ||
-        !strcmp(filter->filter->name, "showspectrum") ||
-        !strcmp(filter->filter->name, "silencedetect") ||
-        !strcmp(filter->filter->name, "thumbnail") ||
-//         !strcmp(filter->filter->name, "scale"      ) ||
-        0
-        ;
+    int deprecated_init = filter_use_deprecated_init(filter->filter->name);
 
+    // TODO: remove old shorthand
     if (filter->filter->shorthand) {
         av_assert0(filter->priv);
         av_assert0(filter->filter->priv_class);
@@ -704,7 +725,13 @@ int avfilter_init_filter(AVFilterContext *filter, const char *args, void *opaque
         args = NULL;
     }
 
-    if (anton_options && args && *args && filter->filter->priv_class) {
+    if (!deprecated_init && args && *args) {
+        if (!filter->filter->priv_class) {
+            av_log(filter, AV_LOG_ERROR, "This filter does not take any "
+                   "options, but options were provided: %s.\n", args);
+            return AVERROR(EINVAL);
+        }
+
 #if FF_API_OLD_FILTER_OPTS
         if (!strcmp(filter->filter->name, "scale") &&
             strchr(args, ':') < strchr(args, '=')) {
@@ -727,20 +754,11 @@ int avfilter_init_filter(AVFilterContext *filter, const char *args, void *opaque
                 ret = av_dict_parse_string(&options, p, "=", ":", 0);
             }
             if (ret >= 0)
-                ret = process_unnamed_options(filter, &options, copy);
+                ret = process_options(filter, &options, copy);
             av_freep(&copy);
 
             if (ret < 0)
                 goto fail;
-        } else
-#endif
-
-        if (strchr(args, '=')) {
-            /* assume a list of key1=value1:key2=value2:... */
-            ret = av_dict_parse_string(&options, args, "=", ":", 0);
-            if (ret < 0)
-                goto fail;
-#if FF_API_OLD_FILTER_OPTS
         } else if (!strcmp(filter->filter->name, "format")     ||
                    !strcmp(filter->filter->name, "noformat")   ||
                    !strcmp(filter->filter->name, "frei0r")     ||
@@ -780,20 +798,20 @@ int avfilter_init_filter(AVFilterContext *filter, const char *args, void *opaque
             while ((p = strchr(p, ':')))
                 *p++ = '|';
 
-            ret = process_unnamed_options(filter, &options, copy);
+            ret = process_options(filter, &options, copy);
             av_freep(&copy);
 
             if (ret < 0)
                 goto fail;
 #endif
         } else {
-            ret = process_unnamed_options(filter, &options, args);
+            ret = process_options(filter, &options, args);
             if (ret < 0)
                 goto fail;
         }
     }
 
-    if (anton_options && filter->filter->priv_class) {
+    if (!deprecated_init && 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");
@@ -978,3 +996,8 @@ int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
         return ff_filter_frame_framed(link, frame);
     }
 }
+
+const AVClass *avfilter_get_class(void)
+{
+    return &avfilter_class;
+}