[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