On 11.11.2014 15:45, Stefano Sabatini wrote:
+        if (o->default_val.str)
+            av_parse_video_rate(&q, o->default_val.str);

you should check the return value here as well for
consistency. Alternatively you can place an assert().

I dont agree. Assert cannot be placed. Return value is not checked is set_defaults so errors are ignored. It can just leave invalid value. Assert here would terminate an application. In general I think it is not regular case - i doub't there is any option with invalid default - but all the best we can do is to compare set value with the default, not validate the default

+        return !av_cmp_q(*(AVRational*)dst, q);
+    case AV_OPT_TYPE_COLOR: {
+        uint8_t color[4] = {0, 0, 0, 0};
+        if (o->default_val.str)
+            av_parse_color(color, o->default_val.str, -1, NULL);

ditto

The same as above


+        return ((uint8_t *)dst)[0] == color[0] && ((uint8_t *)dst)[1] == color[1] 
&&
+               ((uint8_t *)dst)[2] == color[2] && ((uint8_t *)dst)[3] == 
color[3];

memcmp or maybe a cast to uint32_t, but that's subjective.

Casting would be strict aliasing violation I guess. changed to memcmp, it is more clear.

+    }
+    default:
+        av_log(NULL, AV_LOG_WARNING, "Not supported option type: %d\n", 
o->type);

nit: also state name and value, so that's easier to debug

Added name, value has nothing to do with it. changed NULL to obj.


+        break;
+    }

+    return AVERROR_PATCHWELCOME;

unreachable code, probably an assert is better here

It is reached from default section (there is a break, not a return).


+    printf("\nTesting av_opt_is_set_to_default()\n");
+    {
+        TestContext test_ctx = { 0 };
+        const AVOption *o = NULL;
+        test_ctx.class = &test_class;
+
+        av_log_set_level(AV_LOG_QUIET);
+
+        while (o = av_opt_next(&test_ctx, o)) {

+            if (av_opt_is_set_to_default_by_name(&test_ctx, o->name, 0) <= 0)
+                printf("option not detected as set to default: '%s'\n", 
o->name);
+            else
+                printf("option     detected as set to default: '%s'\n", 
o->name);

probably less verbose for a test:

    ret = av_opt_is_set_to_default_by_name(&test_ctx, o->name, 0);
    printf("name:%s default:%s error:%s", o->name, !!ret, av_err2str(ret));

Changed

Updated patch attached
>From 82677357d1033b384ded053ab0e55c4f02183c7f Mon Sep 17 00:00:00 2001
From: Lukasz Marek <lukasz.m.lu...@gmail.com>
Date: Mon, 10 Nov 2014 22:25:30 +0100
Subject: [PATCH] lavu/opt: introduce av_opt_is_set_to_default()

TODO: bump minor version, update doc/APIchanges

New function allows to check if option is set to its default value

Signed-off-by: Lukasz Marek <lukasz.m.lu...@gmail.com>
---
 libavutil/opt.c    | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 libavutil/opt.h    |  26 +++++++++++
 tests/ref/fate/opt |  40 +++++++++++++++++
 3 files changed, 189 insertions(+)

diff --git a/libavutil/opt.c b/libavutil/opt.c
index 90465b6..d6efb06 100644
--- a/libavutil/opt.c
+++ b/libavutil/opt.c
@@ -1726,6 +1726,109 @@ void av_opt_freep_ranges(AVOptionRanges **rangesp)
     av_freep(rangesp);
 }
 
+int av_opt_is_set_to_default(void *obj, const AVOption *o)
+{
+    int64_t i64;
+    double d, d2;
+    float f;
+    AVRational q;
+    int ret, w, h;
+    char *str;
+    void *dst;
+
+    if (!o || !obj)
+        return AVERROR(EINVAL);
+
+    dst = ((uint8_t*)obj) + o->offset;
+
+    switch (o->type) {
+    case AV_OPT_TYPE_CONST:
+        return 1;
+    case AV_OPT_TYPE_FLAGS:
+    case AV_OPT_TYPE_PIXEL_FMT:
+    case AV_OPT_TYPE_SAMPLE_FMT:
+    case AV_OPT_TYPE_INT:
+    case AV_OPT_TYPE_CHANNEL_LAYOUT:
+    case AV_OPT_TYPE_DURATION:
+    case AV_OPT_TYPE_INT64:
+        read_number(o, dst, NULL, NULL, &i64);
+        return o->default_val.i64 == i64;
+    case AV_OPT_TYPE_STRING:
+        str = *(char **)dst;
+        if (str == o->default_val.str) //2 NULLs
+            return 1;
+        if (!str || !o->default_val.str) //1 NULL
+            return 0;
+        return !strcmp(str, o->default_val.str);
+    case AV_OPT_TYPE_DOUBLE:
+        read_number(o, dst, &d, NULL, NULL);
+        return o->default_val.dbl == d;
+    case AV_OPT_TYPE_FLOAT:
+        read_number(o, dst, &d, NULL, NULL);
+        f = o->default_val.dbl;
+        d2 = f;
+        return d2 == d;
+    case AV_OPT_TYPE_RATIONAL:
+        q = av_d2q(o->default_val.dbl, INT_MAX);
+        return !av_cmp_q(*(AVRational*)dst, q);
+    case AV_OPT_TYPE_BINARY: {
+        struct {
+            uint8_t *data;
+            int size;
+        } tmp = {0};
+        int opt_size = *(int *)((void **)dst + 1);
+        void *opt_ptr = *(void **)dst;
+        if (!opt_ptr && (!o->default_val.str || !strlen(o->default_val.str)))
+            return 1;
+        if (opt_ptr && o->default_val.str && !strlen(o->default_val.str))
+            return 0;
+        if (opt_size != strlen(o->default_val.str) / 2)
+            return 0;
+        ret = set_string_binary(NULL, NULL, o->default_val.str, &tmp.data);
+        if (!ret)
+            ret = !memcmp(opt_ptr, tmp.data, tmp.size);
+        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_IMAGE_SIZE:
+        if (!o->default_val.str || !strcmp(o->default_val.str, "none"))
+            w = h = 0;
+        else if ((ret = av_parse_video_size(&w, &h, o->default_val.str)) < 0)
+            return ret;
+        return (w == *(int *)dst) && (h == *((int *)dst+1));
+    case AV_OPT_TYPE_VIDEO_RATE:
+        q = (AVRational){0, 0};
+        if (o->default_val.str)
+            av_parse_video_rate(&q, o->default_val.str);
+        return !av_cmp_q(*(AVRational*)dst, q);
+    case AV_OPT_TYPE_COLOR: {
+        uint8_t color[4] = {0, 0, 0, 0};
+        if (o->default_val.str)
+            av_parse_color(color, o->default_val.str, -1, NULL);
+        return !memcmp(color, dst, sizeof(color));
+    }
+    default:
+        av_log(obj, AV_LOG_WARNING, "Not supported option type: %d, option name: %s\n", o->type, o->name);
+        break;
+    }
+    return AVERROR_PATCHWELCOME;
+}
+
+int av_opt_is_set_to_default_by_name(void *obj, const char *name, int search_flags)
+{
+    const AVOption *o;
+    void *target;
+    if (!obj)
+        return AVERROR(EINVAL);
+    o = av_opt_find2(obj, name, NULL, 0, search_flags, &target);
+    if (!o)
+        return AVERROR_OPTION_NOT_FOUND;
+    return av_opt_is_set_to_default(target, o);
+}
+
 #ifdef TEST
 
 typedef struct TestContext
@@ -1820,6 +1923,26 @@ int main(void)
         printf("dbl=%.6f\n", test_ctx.dbl);
     }
 
+    printf("\nTesting av_opt_is_set_to_default()\n");
+    {
+        int ret;
+        TestContext test_ctx = { 0 };
+        const AVOption *o = NULL;
+        test_ctx.class = &test_class;
+
+        av_log_set_level(AV_LOG_QUIET);
+
+        while (o = av_opt_next(&test_ctx, o)) {
+            ret = av_opt_is_set_to_default_by_name(&test_ctx, o->name, 0);
+            printf("name:%10s default:%d error:%s\n", o->name, !!ret, ret < 0 ? av_err2str(ret) : "");
+        }
+        av_opt_set_defaults(&test_ctx);
+        while (o = av_opt_next(&test_ctx, o)) {
+            ret = av_opt_is_set_to_default_by_name(&test_ctx, o->name, 0);
+            printf("name:%10s default:%d error:%s\n", o->name, !!ret, ret < 0 ? av_err2str(ret) : "");
+        }
+    }
+
     printf("\nTesting av_set_options_string()\n");
     {
         TestContext test_ctx = { 0 };
diff --git a/libavutil/opt.h b/libavutil/opt.h
index df5a62e..5158067 100644
--- a/libavutil/opt.h
+++ b/libavutil/opt.h
@@ -844,6 +844,32 @@ int av_opt_copy(void *dest, void *src);
 int av_opt_query_ranges_default(AVOptionRanges **, void *obj, const char *key, int flags);
 
 /**
+ * Check if given option is set to its default value.
+ *
+ * Options o must belong to the obj. This function must not be called to check child's options state.
+ * @see av_opt_is_set_to_default_by_name().
+ *
+ * @param obj  AVClass object to check option on
+ * @param o    option to be checked
+ * @return     >0 when option is set to its default,
+ *              0 when option is not set its default,
+ *             <0 on error
+ */
+int av_opt_is_set_to_default(void *obj, const AVOption *o);
+
+/**
+ * Check if given option is set to its default value.
+ *
+ * @param obj          AVClass object to check option on
+ * @param name         option name
+ * @param search_flags combination of AV_OPT_SEARCH_*
+ * @return             >0 when option is set to its default,
+ *                     0 when option is not set its default,
+ *                     <0 on error
+ */
+int av_opt_is_set_to_default_by_name(void *obj, const char *name, int search_flags);
+
+/**
  * @}
  */
 
diff --git a/tests/ref/fate/opt b/tests/ref/fate/opt
index 6523390..7953ce8 100644
--- a/tests/ref/fate/opt
+++ b/tests/ref/fate/opt
@@ -17,6 +17,46 @@ num64=1
 flt=0.333333
 dbl=0.333333
 
+Testing av_opt_is_set_to_default()
+name:       num default:1 error:
+name:    toggle default:0 error:
+name:  rational default:0 error:
+name:    string default:0 error:
+name:     flags default:0 error:
+name:      cool default:1 error:Option not found
+name:      lame default:1 error:Option not found
+name:        mu default:1 error:Option not found
+name:      size default:0 error:
+name:   pix_fmt default:0 error:
+name:sample_fmt default:0 error:
+name:video_rate default:0 error:
+name:  duration default:0 error:
+name:     color default:0 error:
+name:        cl default:0 error:
+name:       bin default:0 error:
+name:     num64 default:0 error:
+name:       flt default:0 error:
+name:       dbl default:0 error:
+name:       num default:1 error:
+name:    toggle default:1 error:
+name:  rational default:1 error:
+name:    string default:1 error:
+name:     flags default:1 error:
+name:      cool default:1 error:Option not found
+name:      lame default:1 error:Option not found
+name:        mu default:1 error:Option not found
+name:      size default:1 error:
+name:   pix_fmt default:1 error:
+name:sample_fmt default:1 error:
+name:video_rate default:1 error:
+name:  duration default:1 error:
+name:     color default:1 error:
+name:        cl default:1 error:
+name:       bin default:1 error:
+name:     num64 default:1 error:
+name:       flt default:1 error:
+name:       dbl default:1 error:
+
 Testing av_set_options_string()
 OK    ''
 Error ':'
-- 
1.9.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Reply via email to