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