avutil/opt: Support general expressions involving AVOption constants in set_string_nu...
authorMichael Niedermayer <michaelni@gmx.at>
Mon, 21 Jul 2014 14:00:08 +0000 (16:00 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Mon, 21 Jul 2014 15:00:37 +0000 (17:00 +0200)
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
libavutil/opt.c

index 9ea4aa5..40c944d 100644 (file)
@@ -129,18 +129,6 @@ static int write_number(void *obj, const AVOption *o, void *dst, double num, int
     return 0;
 }
 
-static const double const_values[] = {
-    M_PI,
-    M_E,
-    0
-};
-
-static const char * const const_names[] = {
-    "PI",
-    "E",
-    0
-};
-
 static int hexchar2int(char c) {
     if (c >= '0' && c <= '9') return c - '0';
     if (c >= 'a' && c <= 'f') return c - 'a' + 10;
@@ -220,21 +208,44 @@ static int set_string_number(void *obj, void *target_obj, const AVOption *o, con
         buf[i] = 0;
 
         {
-            const AVOption *o_named = av_opt_find(target_obj, buf, o->unit, 0, 0);
-            if (o_named && o_named->type == AV_OPT_TYPE_CONST)
-                d = DEFAULT_NUMVAL(o_named);
-            else if (!strcmp(buf, "default")) d = DEFAULT_NUMVAL(o);
-            else if (!strcmp(buf, "max"    )) d = o->max;
-            else if (!strcmp(buf, "min"    )) d = o->min;
-            else if (!strcmp(buf, "none"   )) d = 0;
-            else if (!strcmp(buf, "all"    )) d = ~0;
-            else {
-                int res = av_expr_parse_and_eval(&d, buf, const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, obj);
-                if (res < 0) {
-                    av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\"\n", val);
-                    return res;
+            const AVOption *o_named;
+            int res;
+            int ci = 0;
+            double const_values[64];
+            const char * const_names[64];
+
+            if (o->unit) {
+                for (o_named = NULL; o_named = av_opt_next(target_obj, o_named); ) {
+                    if (o_named->type == AV_OPT_TYPE_CONST &&
+                        o_named->unit &&
+                        !strcmp(o_named->unit, o->unit)) {
+                        if (ci + 6 >= FF_ARRAY_ELEMS(const_values)) {
+                            av_log(obj, AV_LOG_ERROR, "const_values array too small for %s\n", o->unit);
+                            return AVERROR_PATCHWELCOME;
+                        }
+                        const_names [ci  ] = o_named->name;
+                        const_values[ci++] = DEFAULT_NUMVAL(o_named);
+                    }
                 }
             }
+            const_names [ci  ] = "default";
+            const_values[ci++] = DEFAULT_NUMVAL(o);
+            const_names [ci  ] = "max";
+            const_values[ci++] = o->max;
+            const_names [ci  ] = "min";
+            const_values[ci++] = o->min;
+            const_names [ci  ] = "none";
+            const_values[ci++] = 0;
+            const_names [ci  ] = "all";
+            const_values[ci++] = ~0;
+            const_names [ci] = NULL;
+            const_values[ci] = 0;
+
+            res = av_expr_parse_and_eval(&d, buf, const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, obj);
+            if (res < 0) {
+                av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\"\n", val);
+                return res;
+            }
         }
         if (o->type == AV_OPT_TYPE_FLAGS) {
             read_number(o, dst, NULL, NULL, &intnum);