[FFmpeg-devel] [PATCH 1/3] avutil/eval: Add av_expr_count_func() similar to av_expr_count_vars()
Michael Niedermayer
michael at niedermayer.cc
Fri Dec 27 23:56:00 EET 2019
On Tue, Dec 17, 2019 at 11:18:51AM +0100, Michael Niedermayer wrote:
> 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
will apply with these changes
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
Avoid a single point of failure, be that a person or equipment.
-------------- 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/20191227/a84a369e/attachment.sig>
More information about the ffmpeg-devel
mailing list