TODO: bump minor version, update doc/APIchanges New function allows to check if option is set to its default
Signed-off-by: Lukasz Marek <lukasz.m.lu...@gmail.com> --- libavutil/opt.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++++++++ libavutil/opt.h | 26 +++++++++++ tests/ref/fate/opt | 40 +++++++++++++++++ 3 files changed, 193 insertions(+) diff --git a/libavutil/opt.c b/libavutil/opt.c index f55f1c5..85c9379 100644 --- a/libavutil/opt.c +++ b/libavutil/opt.c @@ -1726,6 +1726,110 @@ 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 ((uint8_t *)dst)[0] == color[0] && ((uint8_t *)dst)[1] == color[1] && + ((uint8_t *)dst)[2] == color[2] && ((uint8_t *)dst)[3] == color[3]; + } + default: + av_log(NULL, AV_LOG_WARNING, "Not supported option type: %d\n", o->type); + 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 +1924,29 @@ int main(void) printf("dbl=%.6f\n", test_ctx.dbl); } + 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); + } + av_opt_set_defaults(&test_ctx); + 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); + } + } + printf("\nTesting av_set_options_string()\n"); { TestContext test_ctx = { 0 }; diff --git a/libavutil/opt.h b/libavutil/opt.h index df5a62e..a3ad7cc 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. + * + * 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. + * + * @param obj AVClass object to check option on. + * @param name Option name. + * @param search_flags A 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 a14c558..21008bc 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() +option detected as set to default: 'num' +option not detected as set to default: 'toggle' +option not detected as set to default: 'rational' +option not detected as set to default: 'string' +option not detected as set to default: 'flags' +option not detected as set to default: 'cool' +option not detected as set to default: 'lame' +option not detected as set to default: 'mu' +option not detected as set to default: 'size' +option not detected as set to default: 'pix_fmt' +option not detected as set to default: 'sample_fmt' +option not detected as set to default: 'video_rate' +option not detected as set to default: 'duration' +option not detected as set to default: 'color' +option not detected as set to default: 'cl' +option not detected as set to default: 'bin' +option not detected as set to default: 'num64' +option not detected as set to default: 'flt' +option not detected as set to default: 'dbl' +option detected as set to default: 'num' +option detected as set to default: 'toggle' +option detected as set to default: 'rational' +option detected as set to default: 'string' +option detected as set to default: 'flags' +option not detected as set to default: 'cool' +option not detected as set to default: 'lame' +option not detected as set to default: 'mu' +option detected as set to default: 'size' +option detected as set to default: 'pix_fmt' +option detected as set to default: 'sample_fmt' +option detected as set to default: 'video_rate' +option detected as set to default: 'duration' +option detected as set to default: 'color' +option detected as set to default: 'cl' +option detected as set to default: 'bin' +option detected as set to default: 'num64' +option detected as set to default: 'flt' +option detected as set to default: 'dbl' + Testing av_set_options_string() OK setting options string: '' Error setting options string: ':' -- 1.9.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel