[FFmpeg-devel] [PATCH 1/9] lavu/opt: introduce av_opt_is_set_to_default()

Stefano Sabatini stefasab at gmail.com
Tue Nov 11 15:45:57 CET 2014


On date Tuesday 2014-11-11 08:31:23 +0100, Lukasz Marek encoded:
> 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.luki2 at 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);

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

> +        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

> +        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.

> +    }
> +    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

> +        break;
> +    }

> +    return AVERROR_PATCHWELCOME;

unreachable code, probably an assert is better here

> +}
> +
> +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);

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));

> +                printf("option not 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.

... 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.

drop capitalization and ending point for incomplete sentences

> + * @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_*.

ditto

[...]
-- 
FFmpeg = Frightening and Furious Murdering Ponderous Entertaining Gnome


More information about the ffmpeg-devel mailing list