[FFmpeg-devel] [PATCH v2 09/14] avfilter/vf_scale: Honour the AVFilter.init_dict documentation

Nicolas George george at nsup.org
Thu Sep 16 16:07:09 EEST 2021


Andreas Rheinhardt (12021-09-14):
> The documentation states that unrecognized options need to be returned
> (just as av_opt_set_dict() would do). Yet the scale and scale2ref
> filters didn't abide by this: They simply copied all options
> and in case it contained an unrecognized option was among them,
> they would error out later in config_props. This violates the
> documentation of av_filter_init_dict().
> 
> Fix this by only keeping the recognized options and returning
> the unrecognized ones.
> 
> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt at outlook.com>
> ---
>  libavfilter/vf_scale.c | 16 +++++++++++++---
>  1 file changed, 13 insertions(+), 3 deletions(-)
> 
> diff --git a/libavfilter/vf_scale.c b/libavfilter/vf_scale.c
> index a1902a13cf..c31b92b847 100644
> --- a/libavfilter/vf_scale.c
> +++ b/libavfilter/vf_scale.c
> @@ -269,6 +269,8 @@ revert:
>  
>  static av_cold int init_dict(AVFilterContext *ctx, AVDictionary **opts)
>  {
> +    const AVClass *class = sws_get_class();
> +    const AVDictionaryEntry *entry = NULL;
>      ScaleContext *scale = ctx->priv;
>      int ret;
>  
> @@ -312,15 +314,23 @@ static av_cold int init_dict(AVFilterContext *ctx, AVDictionary **opts)
>      scale->flags = 0;
>  
>      if (scale->flags_str && *scale->flags_str) {
> -        const AVClass *class = sws_get_class();
>          const AVOption    *o = av_opt_find(&class, "sws_flags", NULL, 0,
>                                             AV_OPT_SEARCH_FAKE_OBJ);
>          int ret = av_opt_eval_flags(&class, o, scale->flags_str, &scale->flags);
>          if (ret < 0)
>              return ret;
>      }
> -    scale->opts = *opts;
> -    *opts = NULL;
> +    FFSWAP(AVDictionary *, *opts, scale->opts);
> +    /* Now move all the unrecognized options back to opts. */
> +    while (entry = av_dict_get(scale->opts, "", entry, AV_DICT_IGNORE_SUFFIX)) {
> +        if (!av_opt_find(&class, entry->key, NULL, 0, AV_OPT_SEARCH_FAKE_OBJ)) {
> +            if ((ret = av_dict_set(opts, entry->key, entry->value, 0)) < 0 ||
> +                (ret = av_dict_set(&scale->opts, entry->key, NULL, 0)) < 0)
> +                return ret;
> +            /* Removing the entry from scale->opts invalidated entry. */
> +            entry = NULL;
> +        }
> +    }
>  
>      return 0;
>  }

I managed to understand what this code does, but I find it quite
confusing.

First, correct me if I am wrong, but I think the entry parameter to
av_dict_get() is always NULL.

Second, I think if you swap removing the option from scale->opts and
adding it to opts you can avoid strduping the key.

And is entry->value not leaking?

But more importantly, is it not a convoluted implementation that would
be simplified by using preinit like you did for sws?

Regards,

-- 
  Nicolas George
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <https://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20210916/140c504a/attachment.sig>


More information about the ffmpeg-devel mailing list