Browse code

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>

Andrey Utkin authored on 2014/07/04 18:16:16
Showing 3 changed files
... ...
@@ -3911,6 +3911,15 @@ example the text size is not known when evaluating the expression, so
3911 3911
 the constants @var{text_w} and @var{text_h} will have an undefined
3912 3912
 value.
3913 3913
 
3914
+@item eif
3915
+Evaluate the expression's value and output as formatted integer.
3916
+
3917
+First argument is expression to be evaluated, same as for @var{expr} function.
3918
+Second argument specifies output format. Allowed values are 'x', 'X', 'd' and
3919
+'u', they are treated exactly as in printf function.
3920
+Third parameter is optional and sets the number of positions taken by output.
3921
+Effectively this allows to add padding with zeros from the left.
3922
+
3914 3923
 @item gmtime
3915 3924
 The time at which the filter is running, expressed in UTC.
3916 3925
 It can accept an argument: a strftime() format string.
... ...
@@ -31,7 +31,7 @@
31 31
 
32 32
 #define LIBAVFILTER_VERSION_MAJOR   4
33 33
 #define LIBAVFILTER_VERSION_MINOR  11
34
-#define LIBAVFILTER_VERSION_MICRO 100
34
+#define LIBAVFILTER_VERSION_MICRO 101
35 35
 
36 36
 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
37 37
                                                LIBAVFILTER_VERSION_MINOR, \
... ...
@@ -37,6 +37,7 @@
37 37
 #if HAVE_UNISTD_H
38 38
 #include <unistd.h>
39 39
 #endif
40
+#include <fenv.h>
40 41
 
41 42
 #if CONFIG_LIBFONTCONFIG
42 43
 #include <fontconfig/fontconfig.h>
... ...
@@ -908,6 +909,66 @@ static int func_eval_expr(AVFilterContext *ctx, AVBPrint *bp,
908 908
     return ret;
909 909
 }
910 910
 
911
+static int func_eval_expr_int_format(AVFilterContext *ctx, AVBPrint *bp,
912
+                          char *fct, unsigned argc, char **argv, int tag)
913
+{
914
+    DrawTextContext *s = ctx->priv;
915
+    double res;
916
+    int intval;
917
+    int ret;
918
+    unsigned int positions = 0;
919
+    char fmt_str[30] = "%";
920
+
921
+    /*
922
+     * argv[0] expression to be converted to `int`
923
+     * argv[1] format: 'x', 'X', 'd' or 'u'
924
+     * argv[2] positions printed (optional)
925
+     */
926
+
927
+    ret = av_expr_parse_and_eval(&res, argv[0], var_names, s->var_values,
928
+                                 NULL, NULL, fun2_names, fun2,
929
+                                 &s->prng, 0, ctx);
930
+    if (ret < 0) {
931
+        av_log(ctx, AV_LOG_ERROR,
932
+               "Expression '%s' for the expr text expansion function is not valid\n",
933
+               argv[0]);
934
+        return ret;
935
+    }
936
+
937
+    if (!strchr("xXdu", argv[1][0])) {
938
+        av_log(ctx, AV_LOG_ERROR, "Invalid format '%c' specified,"
939
+                " allowed values: 'x', 'X', 'd', 'u'\n", argv[1][0]);
940
+        return AVERROR(EINVAL);
941
+    }
942
+
943
+    if (argc == 3) {
944
+        ret = sscanf(argv[2], "%u", &positions);
945
+        if (ret != 1) {
946
+            av_log(ctx, AV_LOG_ERROR, "eif(): Invalid number of positions"
947
+                    " to print: '%s'\n", argv[2]);
948
+            return AVERROR(EINVAL);
949
+        }
950
+    }
951
+
952
+    feclearexcept(FE_ALL_EXCEPT);
953
+    intval = res;
954
+    if ((ret = fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW))) {
955
+        av_log(ctx, AV_LOG_ERROR, "Conversion of floating-point result to int failed. Control register: 0x%08x. Conversion result: %d\n", ret, intval);
956
+        return AVERROR(EINVAL);
957
+    }
958
+
959
+    if (argc == 3)
960
+        av_strlcatf(fmt_str, sizeof(fmt_str), "0%u", positions);
961
+    av_strlcatf(fmt_str, sizeof(fmt_str), "%c", argv[1][0]);
962
+
963
+    av_log(ctx, AV_LOG_DEBUG, "Formatting value %f (expr '%s') with spec '%s'\n",
964
+            res, argv[0], fmt_str);
965
+
966
+    av_bprintf(bp, fmt_str, intval);
967
+
968
+    return 0;
969
+}
970
+
911 971
 static const struct drawtext_function {
912 972
     const char *name;
913 973
     unsigned argc_min, argc_max;
... ...
@@ -916,6 +977,7 @@ static const struct drawtext_function {
916 916
 } functions[] = {
917 917
     { "expr",      1, 1, 0,   func_eval_expr },
918 918
     { "e",         1, 1, 0,   func_eval_expr },
919
+    { "eif",       2, 3, 0,   func_eval_expr_int_format },
919 920
     { "pict_type", 0, 0, 0,   func_pict_type },
920 921
     { "pts",       0, 2, 0,   func_pts      },
921 922
     { "gmtime",    0, 1, 'G', func_strftime },