Commit dec87454 authored by Andrey Utkin's avatar Andrey Utkin Committed by Stefano Sabatini

lavfi/drawtext: add expansion function eif()

It evaluates expression and outputs it as integer value, using specified
format.

Address trac ticket #3699.
Signed-off-by: 's avatarStefano Sabatini <stefasab@gmail.com>
parent f3e886c7
......@@ -3911,6 +3911,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.
@item eif
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.
......
......@@ -31,7 +31,7 @@
#define LIBAVFILTER_VERSION_MAJOR 4
#define LIBAVFILTER_VERSION_MINOR 11
#define LIBAVFILTER_VERSION_MICRO 100
#define LIBAVFILTER_VERSION_MICRO 101
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
LIBAVFILTER_VERSION_MINOR, \
......
......@@ -37,6 +37,7 @@
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fenv.h>
#if CONFIG_LIBFONTCONFIG
#include <fontconfig/fontconfig.h>
......@@ -908,6 +909,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])) {
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);
}
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;
......@@ -916,6 +977,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 },
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment