[FFmpeg-devel] [PATCH 1/3] avutil/eval: Add av_expr_count_func() similar to av_expr_count_vars()

Michael Niedermayer michael at niedermayer.cc
Tue Dec 17 12:18:51 EET 2019


On Tue, Dec 17, 2019 at 01:50:37AM +0100, Marton Balint wrote:
> 
> 
> On Tue, 17 Dec 2019, Michael Niedermayer wrote:
> 
> >On Sun, Dec 15, 2019 at 01:59:23PM +0100, Marton Balint wrote:
> >>
> >>
> >>On Fri, 6 Dec 2019, Michael Niedermayer wrote:
> >>
> >>>Signed-off-by: Michael Niedermayer <michael at niedermayer.cc>
> >>>---
> >>>libavutil/eval.c | 28 ++++++++++++++++++++--------
> >>>libavutil/eval.h | 11 +++++++++++
> >>>2 files changed, 31 insertions(+), 8 deletions(-)
> >>>
> >>>diff --git a/libavutil/eval.c b/libavutil/eval.c
> >>>index 62d2ae938b..d527f6a9d0 100644
> >>>--- a/libavutil/eval.c
> >>>+++ b/libavutil/eval.c
> >>>@@ -166,8 +166,8 @@ struct AVExpr {
> >>>       e_sgn,
> >>>   } type;
> >>>   double value; // is sign in other types
> >>>+    int const_index;
> >>>   union {
> >>>-        int const_index;
> >>>       double (*func0)(double);
> >>>       double (*func1)(void *, double);
> >>>       double (*func2)(void *, double, double);
> >>>@@ -185,7 +185,7 @@ static double eval_expr(Parser *p, AVExpr *e)
> >>>{
> >>>   switch (e->type) {
> >>>       case e_value:  return e->value;
> >>>-        case e_const:  return e->value * p->const_values[e->a.const_index];
> >>>+        case e_const:  return e->value * p->const_values[e->const_index];
> >>>       case e_func0:  return e->value * e->a.func0(eval_expr(p, e->param[0]));
> >>>       case e_func1:  return e->value * e->a.func1(p->opaque, eval_expr(p, e->param[0]));
> >>>       case e_func2:  return e->value * e->a.func2(p->opaque, eval_expr(p, e->param[0]), eval_expr(p, e->param[1]));
> >>>@@ -367,7 +367,7 @@ static int parse_primary(AVExpr **e, Parser *p)
> >>>       if (strmatch(p->s, p->const_names[i])) {
> >>>           p->s+= strlen(p->const_names[i]);
> >>>           d->type = e_const;
> >>>-            d->a.const_index = i;
> >>>+            d->const_index = i;
> >>>           *e = d;
> >>>           return 0;
> >>>       }
> >>>@@ -478,6 +478,7 @@ static int parse_primary(AVExpr **e, Parser *p)
> >>>           if (strmatch(next, p->func1_names[i])) {
> >>>               d->a.func1 = p->funcs1[i];
> >>>               d->type = e_func1;
> >>>+                d->const_index = i;
> >>>               *e = d;
> >>>               return 0;
> >>>           }
> >>>@@ -487,6 +488,7 @@ static int parse_primary(AVExpr **e, Parser *p)
> >>>           if (strmatch(next, p->func2_names[i])) {
> >>>               d->a.func2 = p->funcs2[i];
> >>>               d->type = e_func2;
> >>>+                d->const_index = i;
> >>>               *e = d;
> >>>               return 0;
> >>>           }
> >>>@@ -735,22 +737,32 @@ end:
> >>>   return ret;
> >>>}
> >>>
> >>>-int av_expr_count_vars(AVExpr *e, unsigned *counter, int size)
> >>>+static int expr_count(AVExpr *e, unsigned *counter, int size, int type)
> >>>{
> >>>   int i;
> >>>
> >>>   if (!e || !counter || !size)
> >>>       return AVERROR(EINVAL);
> >>>
> >>>-    for (i = 0; e->type != e_const && i < 3 && e->param[i]; i++)
> >>>-        av_expr_count_vars(e->param[i], counter, size);
> >>>+    for (i = 0; e->type != type && i < 3 && e->param[i]; i++)
> >>>+        expr_count(e->param[i], counter, size, type);
> >>>
> >>>-    if (e->type == e_const && e->a.const_index < size)
> >>>-        counter[e->a.const_index]++;
> >>>+    if (e->type == type && e->const_index < size)
> >>>+        counter[e->const_index]++;
> >>>
> >>>   return 0;
> >>>}
> >>>
> >>>+int av_expr_count_vars(AVExpr *e, unsigned *counter, int size)
> >>>+{
> >>>+    return expr_count(e, counter, size, e_const);
> >>>+}
> >>>+
> >>>+int av_expr_count_func(AVExpr *e, unsigned *counter, int size, int arg)
> >>>+{
> >>>+    return expr_count(e, counter, size, ((int[]){e_const, e_func1, e_func2})[arg]);
> >>>+}
> >>>+
> >>>double av_expr_eval(AVExpr *e, const double *const_values, void *opaque)
> >>>{
> >>>   Parser p = { 0 };
> >>>diff --git a/libavutil/eval.h b/libavutil/eval.h
> >>>index 9bdb10cca2..688c523fbe 100644
> >>>--- a/libavutil/eval.h
> >>>+++ b/libavutil/eval.h
> >>>@@ -96,6 +96,17 @@ double av_expr_eval(AVExpr *e, const double *const_values, void *opaque);
> >>>*/
> >>>int av_expr_count_vars(AVExpr *e, unsigned *counter, int size);
> >>>
> >>>+/**
> >>>+ * Track the presence of functions and their number of occurrences in a parsed expression
> >>>+ *
> >>>+ * @param counter a zero-initialized array where the count of each function will be stored
> >>>+ * @param size size of array
> >>>+ * @param arg number of arguments the counted functions have
> >>>+ * @return 0 on success, a negative value indicates that no expression or array was passed
> >>>+ * or size was zero
> >>>+ */
> >>>+int av_expr_count_func(AVExpr *e, unsigned *counter, int size, int arg);
> >>>+
> >>
> >>In order to define a function like this in public API you should change the
> >>functions list enum in eval.c to become public API as well. Otherwise the
> >>user would not know which function has which identifier. Also the number of
> >>functions should also become public API.
> >
> >The user would know which function is the i-th function in the array which
> >the user passed to the expression evaluator.
> >It indeed would not work with built in functions, thats the same though with
> >the constants counted by av_expr_count_vars()
> 
> I missed that only the user functions are counted. I guess it is fine then
> from an API perspective, but please emphasize this in the docs.

will chnage the docs as in:
@@ -97,9 +97,12 @@ double av_expr_eval(AVExpr *e, const double *const_values, void *opaque);
 int av_expr_count_vars(AVExpr *e, unsigned *counter, int size);
 
 /**
- * Track the presence of functions and their number of occurrences in a parsed expression
+ * Track the presence of user provided functions and their number of occurrences
+ * in a parsed expression.
  *
  * @param counter a zero-initialized array where the count of each function will be stored
+ *                if you passed 5 functions with 2 arguments to av_expr_parse()
+ *                then for arg=2 this will use upto 5 entries.
  * @param size size of array
  * @param arg number of arguments the counted functions have
  * @return 0 on success, a negative value indicates that no expression or array was passed

thx

[...]

-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Democracy is the form of government in which you can choose your dictator
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: not available
URL: <https://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20191217/aa89f093/attachment.sig>


More information about the ffmpeg-devel mailing list