diff mbox

[FFmpeg-devel,01/13] avutil/opt: add full support for AV_OPT_TYPE_DICT

Message ID 20191225214314.15879-1-cus@passwd.hu
State Accepted
Commit 5edacc46099725f59ac81bdbff991b0daf4b3a7c
Headers show

Commit Message

Marton Balint Dec. 25, 2019, 9:43 p.m. UTC
Now it is possible to set them from a string, to serialize them and to use a
default value.

Signed-off-by: Marton Balint <cus@passwd.hu>
---
 libavutil/opt.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++-----
 libavutil/opt.h | 10 +++++++---
 2 files changed, 53 insertions(+), 8 deletions(-)

Comments

Michael Niedermayer Dec. 26, 2019, 7:47 p.m. UTC | #1
On Wed, Dec 25, 2019 at 10:43:02PM +0100, Marton Balint wrote:
> Now it is possible to set them from a string, to serialize them and to use a
> default value.
> 
> Signed-off-by: Marton Balint <cus@passwd.hu>
> ---
>  libavutil/opt.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++-----
>  libavutil/opt.h | 10 +++++++---
>  2 files changed, 53 insertions(+), 8 deletions(-)

nice patch

thanks

[...]
Marton Balint Dec. 27, 2019, 8:59 p.m. UTC | #2
On Thu, 26 Dec 2019, Michael Niedermayer wrote:

> On Wed, Dec 25, 2019 at 10:43:02PM +0100, Marton Balint wrote:
>> Now it is possible to set them from a string, to serialize them and to use a
>> default value.
>>
>> Signed-off-by: Marton Balint <cus@passwd.hu>
>> ---
>>  libavutil/opt.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++-----
>>  libavutil/opt.h | 10 +++++++---
>>  2 files changed, 53 insertions(+), 8 deletions(-)
>
> nice patch

Thanks, applied patches 1-3. Will wait a few days more for the rest.

Thanks,
Marton
Marton Balint Jan. 1, 2020, 9:46 p.m. UTC | #3
On Fri, 27 Dec 2019, Marton Balint wrote:

>
>
> On Thu, 26 Dec 2019, Michael Niedermayer wrote:
>
>> On Wed, Dec 25, 2019 at 10:43:02PM +0100, Marton Balint wrote:
>>> Now it is possible to set them from a string, to serialize them and to use 
> a
>>> default value.
>>>
>>> Signed-off-by: Marton Balint <cus@passwd.hu>
>>> ---
>>>  libavutil/opt.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++-----
>>>  libavutil/opt.h | 10 +++++++---
>>>  2 files changed, 53 insertions(+), 8 deletions(-)
>>
>> nice patch
>
> Thanks, applied patches 1-3. Will wait a few days more for the rest.

Applied the rest.

Regard,
Marton
diff mbox

Patch

diff --git a/libavutil/opt.c b/libavutil/opt.c
index 9081a593a1..60161d4a80 100644
--- a/libavutil/opt.c
+++ b/libavutil/opt.c
@@ -446,6 +446,22 @@  static int set_string_sample_fmt(void *obj, const AVOption *o, const char *val,
                           AV_SAMPLE_FMT_NB, av_get_sample_fmt, "sample format");
 }
 
+static int set_string_dict(void *obj, const AVOption *o, const char *val, uint8_t **dst)
+{
+    AVDictionary *options = NULL;
+
+    if (val) {
+        int ret = av_dict_parse_string(&options, val, "=", ":", 0);
+        if (ret < 0)
+            return ret;
+    }
+
+    av_dict_free((AVDictionary **)dst);
+    *dst = (uint8_t *)options;
+
+    return 0;
+}
+
 int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
 {
     int ret = 0;
@@ -527,6 +543,8 @@  int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
             return ret;
         }
         break;
+    case AV_OPT_TYPE_DICT:
+        return set_string_dict(obj, o, val, dst);
     }
 
     av_log(obj, AV_LOG_ERROR, "Invalid option type.\n");
@@ -855,6 +873,12 @@  int av_opt_get(void *obj, const char *name, int search_flags, uint8_t **out_val)
         i64 = *(int64_t *)dst;
         ret = snprintf(buf, sizeof(buf), "0x%"PRIx64, i64);
         break;
+    case AV_OPT_TYPE_DICT:
+        if (!*(AVDictionary **)dst && (search_flags & AV_OPT_ALLOW_NULL)) {
+            *out_val = NULL;
+            return 0;
+        }
+        return av_dict_get_string(*(AVDictionary **)dst, (char **)out_val, '=', ':');
     default:
         return AVERROR(EINVAL);
     }
@@ -1174,6 +1198,9 @@  static void opt_list(void *obj, void *av_log_obj, const char *unit,
             case AV_OPT_TYPE_BINARY:
                 av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<binary>");
                 break;
+            case AV_OPT_TYPE_DICT:
+                av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<dictionary>");
+                break;
             case AV_OPT_TYPE_IMAGE_SIZE:
                 av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<image_size>");
                 break;
@@ -1247,6 +1274,7 @@  static void opt_list(void *obj, void *av_log_obj, const char *unit,
                 !((opt->type == AV_OPT_TYPE_COLOR      ||
                    opt->type == AV_OPT_TYPE_IMAGE_SIZE ||
                    opt->type == AV_OPT_TYPE_STRING     ||
+                   opt->type == AV_OPT_TYPE_DICT       ||
                    opt->type == AV_OPT_TYPE_VIDEO_RATE) &&
                   !opt->default_val.str)) {
             av_log(av_log_obj, AV_LOG_INFO, " (default ");
@@ -1297,6 +1325,7 @@  static void opt_list(void *obj, void *av_log_obj, const char *unit,
             case AV_OPT_TYPE_COLOR:
             case AV_OPT_TYPE_IMAGE_SIZE:
             case AV_OPT_TYPE_STRING:
+            case AV_OPT_TYPE_DICT:
             case AV_OPT_TYPE_VIDEO_RATE:
                 av_log(av_log_obj, AV_LOG_INFO, "\"%s\"", opt->default_val.str);
                 break;
@@ -1386,8 +1415,8 @@  void av_opt_set_defaults2(void *s, int mask, int flags)
                 set_string_binary(s, opt, opt->default_val.str, dst);
                 break;
             case AV_OPT_TYPE_DICT:
-                /* Cannot set defaults for these types */
-            break;
+                set_string_dict(s, opt, opt->default_val.str, dst);
+                break;
         default:
             av_log(s, AV_LOG_DEBUG, "AVOption type %d of option %s not implemented yet\n",
                    opt->type, opt->name);
@@ -1971,9 +2000,21 @@  int av_opt_is_set_to_default(void *obj, const AVOption *o)
         av_free(tmp.data);
         return ret;
     }
-    case AV_OPT_TYPE_DICT:
-        /* Binary and dict have not default support yet. Any pointer is not default. */
-        return !!(*(void **)dst);
+    case AV_OPT_TYPE_DICT: {
+        AVDictionary *dict1 = NULL;
+        AVDictionary *dict2 = *(AVDictionary **)dst;
+        AVDictionaryEntry *en1 = NULL;
+        AVDictionaryEntry *en2 = NULL;
+        ret = av_dict_parse_string(&dict1, o->default_val.str, "=", ":", 0);
+        if (ret < 0)
+            return ret;
+        do {
+            en1 = av_dict_get(dict1, "", en1, AV_DICT_IGNORE_SUFFIX);
+            en2 = av_dict_get(dict2, "", en2, AV_DICT_IGNORE_SUFFIX);
+        } while (en1 && en2 && !strcmp(en1->key, en2->key) && !strcmp(en1->value, en2->value));
+        av_dict_free(&dict1);
+        return (!en1 && !en2);
+    }
     case AV_OPT_TYPE_IMAGE_SIZE:
         if (!o->default_val.str || !strcmp(o->default_val.str, "none"))
             w = h = 0;
diff --git a/libavutil/opt.h b/libavutil/opt.h
index bc98ab104d..1969c984dd 100644
--- a/libavutil/opt.h
+++ b/libavutil/opt.h
@@ -670,6 +670,9 @@  const AVClass *av_opt_child_class_next(const AVClass *parent, const AVClass *pre
  * scalars or named flags separated by '+' or '-'. Prefixing a flag
  * with '+' causes it to be set without affecting the other flags;
  * similarly, '-' unsets a flag.
+ * If the field is of a dictionary type, it has to be a ':' separated list of
+ * key=value parameters. Values containing ':' special characters must be
+ * escaped.
  * @param search_flags flags passed to av_opt_find2. I.e. if AV_OPT_SEARCH_CHILDREN
  * is passed here, then the option may be set on a child of obj.
  *
@@ -730,9 +733,10 @@  int av_opt_set_dict_val(void *obj, const char *name, const AVDictionary *val, in
 /**
  * @note the returned string will be av_malloc()ed and must be av_free()ed by the caller
  *
- * @note if AV_OPT_ALLOW_NULL is set in search_flags in av_opt_get, and the option has
- * AV_OPT_TYPE_STRING or AV_OPT_TYPE_BINARY and is set to NULL, *out_val will be set
- * to NULL instead of an allocated empty string.
+ * @note if AV_OPT_ALLOW_NULL is set in search_flags in av_opt_get, and the
+ * option is of type AV_OPT_TYPE_STRING, AV_OPT_TYPE_BINARY or AV_OPT_TYPE_DICT
+ * and is set to NULL, *out_val will be set to NULL instead of an allocated
+ * empty string.
  */
 int av_opt_get         (void *obj, const char *name, int search_flags, uint8_t   **out_val);
 int av_opt_get_int     (void *obj, const char *name, int search_flags, int64_t    *out_val);