]> git.sesse.net Git - ffmpeg/blobdiff - libavutil/opt.c
Merge commit '481a3667495425db9fdffb653292b6460fb68208'
[ffmpeg] / libavutil / opt.c
index 693e846cddc25836a503da3b623034541de2c8e8..fec840bf71826b8ec985406891cf3bb0361820bb 100644 (file)
@@ -206,44 +206,47 @@ static int set_string_number(void *obj, void *target_obj, const AVOption *o, con
         }
 
         {
-            const AVOption *o_named;
+            const AVOption *o_named = av_opt_find(target_obj, i ? buf : val, o->unit, 0, 0);
             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;
+            if (o_named && o_named->type == AV_OPT_TYPE_CONST)
+                d = DEFAULT_NUMVAL(o_named);
+            else {
+                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  ] = 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, i ? buf : val, 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_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, i ? buf : val, 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) {
@@ -677,6 +680,24 @@ const char *av_get_string(void *obj, const char *name, const AVOption **o_out, c
 }
 #endif
 
+int av_opt_set_dict_val(void *obj, const char *name, const AVDictionary *val, int search_flags)
+{
+    void *target_obj;
+    AVDictionary **dst;
+    const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
+
+    if (!o || !target_obj)
+        return AVERROR_OPTION_NOT_FOUND;
+    if (o->flags & AV_OPT_FLAG_READONLY)
+        return AVERROR(EINVAL);
+
+    dst = (AVDictionary **)(((uint8_t *)target_obj) + o->offset);
+    av_dict_free(dst);
+    av_dict_copy(dst, val, 0);
+
+    return 0;
+}
+
 int av_opt_get(void *obj, const char *name, int search_flags, uint8_t **out_val)
 {
     void *dst, *target_obj;
@@ -924,6 +945,23 @@ int av_opt_get_channel_layout(void *obj, const char *name, int search_flags, int
     return 0;
 }
 
+int av_opt_get_dict_val(void *obj, const char *name, int search_flags, AVDictionary **out_val)
+{
+    void *target_obj;
+    AVDictionary *src;
+    const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
+
+    if (!o || !target_obj)
+        return AVERROR_OPTION_NOT_FOUND;
+    if (o->type != AV_OPT_TYPE_DICT)
+        return AVERROR(EINVAL);
+
+    src = *(AVDictionary **)(((uint8_t *)target_obj) + o->offset);
+    av_dict_copy(out_val, src, 0);
+
+    return 0;
+}
+
 int av_opt_flag_is_set(void *obj, const char *field_name, const char *flag_name)
 {
     const AVOption *field = av_opt_find(obj, field_name, NULL, 0, 0);
@@ -1217,7 +1255,8 @@ void av_opt_set_defaults2(void *s, int mask, int flags)
                     write_number(s, opt, dst, 1, 1, opt->default_val.i64);
                 break;
             case AV_OPT_TYPE_BINARY:
-                /* Cannot set default for binary */
+            case AV_OPT_TYPE_DICT:
+                /* Cannot set defaults for these types */
             break;
             default:
                 av_log(s, AV_LOG_DEBUG, "AVOption type %d of option %s not implemented yet\n", opt->type, opt->name);
@@ -1411,9 +1450,21 @@ int av_opt_set_from_string(void *ctx, const char *opts,
 void av_opt_free(void *obj)
 {
     const AVOption *o = NULL;
-    while ((o = av_opt_next(obj, o)))
-        if (o->type == AV_OPT_TYPE_STRING || o->type == AV_OPT_TYPE_BINARY)
+    while ((o = av_opt_next(obj, o))) {
+        switch (o->type) {
+        case AV_OPT_TYPE_STRING:
+        case AV_OPT_TYPE_BINARY:
             av_freep((uint8_t *)obj + o->offset);
+            break;
+
+        case AV_OPT_TYPE_DICT:
+            av_dict_free((AVDictionary **)(((uint8_t *)obj) + o->offset));
+            break;
+
+        default:
+            break;
+        }
+    }
 }
 
 int av_opt_set_dict2(void *obj, AVDictionary **options, int search_flags)