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: Stefano Sabatini <stefasab@gmail.com>
This commit is contained in:
Andrey Utkin 2014-07-04 12:16:16 +03:00 committed by Stefano Sabatini
parent f3e886c7df
commit dec87454de
3 changed files with 72 additions and 1 deletions

View File

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

View File

@ -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, \

View File

@ -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 },