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

Marton Balint cus at passwd.hu
Tue Dec 17 02:50:37 EET 2019



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.

Thanks,
Marton


More information about the ffmpeg-devel mailing list