[FFmpeg-devel] [PATCH] eval: add support for a round function

Stefano Sabatini stefano.sabatini-lala at poste.it
Wed Mar 30 22:42:05 CEST 2011


---
 doc/eval.texi    |    9 +++++++++
 libavutil/eval.c |   23 +++++++++++++++++++++--
 2 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/doc/eval.texi b/doc/eval.texi
index 99cd034..b29e61d 100644
--- a/doc/eval.texi
+++ b/doc/eval.texi
@@ -60,6 +60,15 @@ The function returns the loaded value.
 Evaluate expression @var{expr} while the expression @var{cond} is
 non-zero, and returns the value of the last @var{expr} evaluation, or
 NAN if @var{cond} was always false.
+
+ at item round(expr1, expr2)
+Round the value of expression @var{expr1} to a multiple of
+ at var{expr2}.
+
+If the value of @var{expr2} is a positive value, round towards 0, if
+the value of @var{expr2} is negative, round towards infinity. If the
+value of @var{expr2} is 0, or if the values for @var{expr1} or
+ at var{expr2} are too big, return NAN.
 @end table
 
 Note that:
diff --git a/libavutil/eval.c b/libavutil/eval.c
index 0fef97b..7589b39 100644
--- a/libavutil/eval.c
+++ b/libavutil/eval.c
@@ -121,7 +121,7 @@ struct AVExpr {
         e_squish, e_gauss, e_ld, e_isnan,
         e_mod, e_max, e_min, e_eq, e_gt, e_gte,
         e_pow, e_mul, e_div, e_add,
-        e_last, e_st, e_while,
+        e_last, e_st, e_while, e_round,
     } type;
     double value; // is sign in other types
     union {
@@ -167,6 +167,12 @@ static double eval_expr(Parser *p, AVExpr *e)
                 case e_add: return e->value * (d + d2);
                 case e_last:return e->value * d2;
                 case e_st : return e->value * (p->var[av_clip(d, 0, VARS-1)]= d2);
+                case e_round: {
+                    long long int i = llrint(d), i2 = llrint(d2);
+                    if (d > LLONG_MAX || d2 > LLONG_MAX || isnan(d) || isnan(d2) || i2 == 0)
+                        return NAN;
+                    return e->value * (i - i%i2 - (i2 < 0 ? FFSIGN(i) * i2 : 0));
+                }
             }
         }
     }
@@ -276,6 +282,7 @@ static int parse_primary(AVExpr **e, Parser *p)
     else if (strmatch(next, "isnan" )) d->type = e_isnan;
     else if (strmatch(next, "st"    )) d->type = e_st;
     else if (strmatch(next, "while" )) d->type = e_while;
+    else if (strmatch(next, "round" )) d->type = e_round;
     else {
         for (i=0; p->func1_names && p->func1_names[i]; i++) {
             if (strmatch(next, p->func1_names[i])) {
@@ -439,7 +446,9 @@ static int verify_expr(AVExpr *e)
         case e_squish:
         case e_ld:
         case e_gauss:
-        case e_isnan: return verify_expr(e->param[0]);
+        case e_isnan:
+        case e_round:
+            return verify_expr(e->param[0]);
         default: return verify_expr(e->param[0]) && verify_expr(e->param[1]);
     }
 }
@@ -611,6 +620,16 @@ int main(void)
         "st(0, 1); while(lte(ld(0),100), st(1, ld(1)+ld(0)); st(0, ld(0)+1))",
         "isnan(1)",
         "isnan(NAN)",
+        "round(123,   10)",
+        "round(123,  -10)",
+        "round(-123,  10)",
+        "round(-123, -10)",
+        "round(2, 12)",
+        "round(NAN, 2)",
+        "round(123, 0)",
+        "round(-123, 20)",
+        "round(-139, 20)",
+        "round((1+2+3), 3)",
         NULL
     };
 
-- 
1.7.2.3



More information about the ffmpeg-devel mailing list