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

Andrey Utkin andrey.krieger.utkin at gmail.com
Fri Jul 4 11:16:16 CEST 2014


It evaluates expression and outputs it as intever value, using specified
format.
---
 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
+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])) {
+        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;
@@ -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 },
-- 
1.8.3.2



More information about the ffmpeg-devel mailing list