[FFmpeg-devel] [PATCH 1/2] drawtext: add expansion function eif()

Nicolas George george at nsup.org
Sat Jul 5 15:19:14 CEST 2014


Le sextidi 16 messidor, an CCXXII, Andrey Utkin a écrit :
> It evaluates expression and outputs it as intever value, using specified
> format.

I was away from my keyboard for some time and Stefano is about to apply, so
a quick review before I can give it more time.

> ---
>  doc/filters.texi          |  9 +++++++
>  libavfilter/vf_drawtext.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 71 insertions(+)
> 
> diff --git a/doc/filters.texi b/doc/filters.texi
> index a5f6965..3ed28a0 100644
> --- a/doc/filters.texi
> +++ b/doc/filters.texi
> @@ -3867,6 +3867,15 @@ example the text size is not known when evaluating the expression, so
>  the constants @var{text_w} and @var{text_h} will have an undefined
>  value.
>  

> + at item eif

I find the name obscure. Where does it come from?

> +Evaluate the expression's value and output as formatted integer.
> +
> +First argument is expression to be evaluated, same as for @var{expr} function.
> +Second argument specifies output format. Allowed values are 'x', 'X', 'd' and
> +'u', they are treated exactly as in printf function.
> +Third parameter is optional and sets the number of positions taken by output.
> +Effectively this allows to add padding with zeros from the left.
> +
>  @item gmtime
>  The time at which the filter is running, expressed in UTC.
>  It can accept an argument: a strftime() format string.
> diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c
> index adc587e..305e00f 100644
> --- a/libavfilter/vf_drawtext.c
> +++ b/libavfilter/vf_drawtext.c
> @@ -35,6 +35,7 @@
>  #include <sys/stat.h>
>  #include <time.h>
>  #include <unistd.h>
> +#include <fenv.h>
>  
>  #if CONFIG_LIBFONTCONFIG
>  #include <fontconfig/fontconfig.h>
> @@ -800,6 +801,66 @@ static int func_eval_expr(AVFilterContext *ctx, AVBPrint *bp,
>      return ret;
>  }
>  
> +static int func_eval_expr_int_format(AVFilterContext *ctx, AVBPrint *bp,
> +                          char *fct, unsigned argc, char **argv, int tag)
> +{
> +    DrawTextContext *s = ctx->priv;
> +    double res;
> +    int intval;
> +    int ret;
> +    unsigned int positions = 0;
> +    char fmt_str[30] = "%";
> +
> +    /*
> +     * argv[0] expression to be converted to `int`
> +     * argv[1] format: 'x', 'X', 'd' or 'u'
> +     * argv[2] positions printed (optional)
> +     */
> +
> +    ret = av_expr_parse_and_eval(&res, argv[0], var_names, s->var_values,
> +                                 NULL, NULL, fun2_names, fun2,
> +                                 &s->prng, 0, ctx);
> +    if (ret < 0) {
> +        av_log(ctx, AV_LOG_ERROR,
> +               "Expression '%s' for the expr text expansion function is not valid\n",
> +               argv[0]);
> +        return ret;
> +    }
> +

> +    if (!strchr("xXdu", argv[1][0])) {

You should probably check that argv[1][1] is 0.

> +        av_log(ctx, AV_LOG_ERROR, "Invalid format '%c' specified,"
> +                " allowed values: 'x', 'X', 'd', 'u'\n", argv[1][0]);
> +        return AVERROR(EINVAL);
> +    }
> +
> +    if (argc == 3) {

> +        ret = sscanf(argv[2], "%u", &positions);
> +        if (ret != 1) {
> +            av_log(ctx, AV_LOG_ERROR, "eif(): Invalid number of positions"
> +                    " to print: '%s'\n", argv[2]);
> +            return AVERROR(EINVAL);
> +        }
> +    }
> +

> +    feclearexcept(FE_ALL_EXCEPT);
> +    intval = res;
> +    if ((ret = fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW))) {
> +        av_log(ctx, AV_LOG_ERROR, "Conversion of floating-point result to int failed. Control register: 0x%08x. Conversion result: %d\n", ret, intval);
> +        return AVERROR(EINVAL);

Is this portable enough? Anyway, AFAIK, we never do that kind of test in the
code.

> +    }
> +
> +    if (argc == 3)
> +        av_strlcatf(fmt_str, sizeof(fmt_str), "0%u", positions);
> +    av_strlcatf(fmt_str, sizeof(fmt_str), "%c", argv[1][0]);
> +
> +    av_log(ctx, AV_LOG_DEBUG, "Formatting value %f (expr '%s') with spec '%s'\n",
> +            res, argv[0], fmt_str);
> +
> +    av_bprintf(bp, fmt_str, intval);
> +
> +    return 0;
> +}
> +
>  static const struct drawtext_function {
>      const char *name;
>      unsigned argc_min, argc_max;
> @@ -808,6 +869,7 @@ static const struct drawtext_function {
>  } functions[] = {
>      { "expr",      1, 1, 0,   func_eval_expr },
>      { "e",         1, 1, 0,   func_eval_expr },
> +    { "eif",       2, 3, 0,   func_eval_expr_int_format },
>      { "pict_type", 0, 0, 0,   func_pict_type },
>      { "pts",       0, 2, 0,   func_pts      },
>      { "gmtime",    0, 1, 'G', func_strftime },

Regards,

-- 
  Nicolas George
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <https://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20140705/d71d1290/attachment.asc>


More information about the ffmpeg-devel mailing list