diff mbox

[FFmpeg-devel,1/3] avutil/eval: separate AVExpr state to a new AVExprState struct

Message ID 20191228144625.28804-1-cus@passwd.hu
State New
Headers show

Commit Message

Marton Balint Dec. 28, 2019, 2:46 p.m. UTC
Also add helper functions to allocate and free such a struct, and make it
usable by providing a new av_eval_expr2 function for which you can specify a
custom AVExprState.

Signed-off-by: Marton Balint <cus@passwd.hu>
---
 doc/APIchanges      |  3 +++
 libavutil/eval.c    | 31 +++++++++++++++++++++++++------
 libavutil/eval.h    | 27 +++++++++++++++++++++++++++
 libavutil/version.h |  2 +-
 4 files changed, 56 insertions(+), 7 deletions(-)

Comments

Michael Niedermayer Dec. 29, 2019, 3:26 p.m. UTC | #1
On Sat, Dec 28, 2019 at 03:46:23PM +0100, Marton Balint wrote:
> Also add helper functions to allocate and free such a struct, and make it
> usable by providing a new av_eval_expr2 function for which you can specify a
> custom AVExprState.
> 
> Signed-off-by: Marton Balint <cus@passwd.hu>
> ---
>  doc/APIchanges      |  3 +++
>  libavutil/eval.c    | 31 +++++++++++++++++++++++++------
>  libavutil/eval.h    | 27 +++++++++++++++++++++++++++
>  libavutil/version.h |  2 +-
>  4 files changed, 56 insertions(+), 7 deletions(-)
> 
> diff --git a/doc/APIchanges b/doc/APIchanges
> index 3c24dc6fbc..e4ad364ed9 100644
> --- a/doc/APIchanges
> +++ b/doc/APIchanges
> @@ -15,6 +15,9 @@ libavutil:     2017-10-21
>  
>  API changes, most recent first:
>  
> +2020-01-xx - xxxxxxxxxx - lavu 56.39.100 - eval.h
> +  Add av_expr_eval2, av_expr_state_alloc, av_expr_state_free
> +
>  2019-12-27 - xxxxxxxxxx - lavu 56.38.100 - eval.h
>    Add av_expr_count_func().
>  
> diff --git a/libavutil/eval.c b/libavutil/eval.c
> index d527f6a9d0..86fb634fd8 100644
> --- a/libavutil/eval.c
> +++ b/libavutil/eval.c
> @@ -173,7 +173,11 @@ struct AVExpr {
>          double (*func2)(void *, double, double);
>      } a;
>      struct AVExpr *param[3];
> -    double *var;
> +    AVExprState *state;
> +};
> +
> +struct AVExprState {
> +    double vars[VARS];
>  };
>  
>  static double etime(double v)
> @@ -333,13 +337,23 @@ static double eval_expr(Parser *p, AVExpr *e)
>  
>  static int parse_expr(AVExpr **e, Parser *p);
>  
> +AVExprState *av_expr_state_alloc(void)
> +{
> +    return av_mallocz(sizeof(AVExprState));
> +}
> +
> +void av_expr_state_free(AVExprState **ps)
> +{
> +    av_freep(ps);
> +}
> +
>  void av_expr_free(AVExpr *e)
>  {
>      if (!e) return;
>      av_expr_free(e->param[0]);
>      av_expr_free(e->param[1]);
>      av_expr_free(e->param[2]);
> -    av_freep(&e->var);
> +    av_expr_state_free(&e->state);
>      av_freep(&e);
>  }
>  
> @@ -724,8 +738,8 @@ int av_expr_parse(AVExpr **expr, const char *s,
>          ret = AVERROR(EINVAL);
>          goto end;
>      }
> -    e->var= av_mallocz(sizeof(double) *VARS);
> -    if (!e->var) {
> +    e->state = av_expr_state_alloc();
> +    if (!e->state) {
>          ret = AVERROR(ENOMEM);
>          goto end;
>      }
> @@ -763,16 +777,21 @@ 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)
> +double av_expr_eval2(AVExpr *e, AVExprState *s, const double *const_values, void *opaque)
>  {
>      Parser p = { 0 };
> -    p.var= e->var;
> +    p.var = s ? s->vars : e->state->vars;
>  
>      p.const_values = const_values;
>      p.opaque     = opaque;
>      return eval_expr(&p, e);
>  }
>  
> +double av_expr_eval(AVExpr *e, const double *const_values, void *opaque)
> +{
> +    return av_expr_eval2(e, NULL, const_values, opaque);
> +}
> +
>  int av_expr_parse_and_eval(double *d, const char *s,
>                             const char * const *const_names, const double *const_values,
>                             const char * const *func1_names, double (* const *funcs1)(void *, double),
> diff --git a/libavutil/eval.h b/libavutil/eval.h
> index 068c62cdab..8bd1592f6c 100644
> --- a/libavutil/eval.h
> +++ b/libavutil/eval.h
> @@ -29,6 +29,7 @@
>  #include "avutil.h"
>  
>  typedef struct AVExpr AVExpr;
> +typedef struct AVExprState AVExprState;
>  
>  /**
>   * Parse and evaluate an expression.
> @@ -86,6 +87,22 @@ int av_expr_parse(AVExpr **expr, const char *s,
>   */
>  double av_expr_eval(AVExpr *e, const double *const_values, void *opaque);
>  
> +/**
> + * Evaluate a previously parsed expression using a custom state.
> + *
> + * Some expressions can use stateful functions, like random(), st() and ld().
> + * With this function you can provide your own state to the evaluator instead
> + * of using the internal state of the AVExpr. This makes it possible to use the
> + * same AVExpr in multiple threads each with their own AVExprState avoiding
> + * unprotected concurrent access of the internal AVExpr state.
> + *
> + * @param s the state of the expression, if NULL, the internal state of AVExpr will be used
> + * @param const_values a zero terminated array of values for the identifiers from av_expr_parse() const_names
> + * @param opaque a pointer which will be passed to all functions from funcs1 and funcs2
> + * @return the value of the expression
> + */
> +double av_expr_eval2(AVExpr *e, AVExprState *s, const double *const_values, void *opaque);
> +
>  /**
>   * Track the presence of variables and their number of occurrences in a parsed expression
>   *
> @@ -134,4 +151,14 @@ void av_expr_free(AVExpr *e);
>   */
>  double av_strtod(const char *numstr, char **tail);
>  
> +/**
> + * Allocate a new AVExprState struct
> + */
> +AVExprState *av_expr_state_alloc(void);

maybe this should have a double [] argument so the caller can set the
initial variables (or pass NULL if not)

thx

[...]
Marton Balint Dec. 29, 2019, 3:46 p.m. UTC | #2
On Sun, 29 Dec 2019, Michael Niedermayer wrote:

> On Sat, Dec 28, 2019 at 03:46:23PM +0100, Marton Balint wrote:
>> Also add helper functions to allocate and free such a struct, and make it
>> usable by providing a new av_eval_expr2 function for which you can specify a
>> custom AVExprState.
>>
>> Signed-off-by: Marton Balint <cus@passwd.hu>
>> ---
>>  doc/APIchanges      |  3 +++
>>  libavutil/eval.c    | 31 +++++++++++++++++++++++++------
>>  libavutil/eval.h    | 27 +++++++++++++++++++++++++++
>>  libavutil/version.h |  2 +-
>>  4 files changed, 56 insertions(+), 7 deletions(-)
>>
>> diff --git a/doc/APIchanges b/doc/APIchanges
>> index 3c24dc6fbc..e4ad364ed9 100644
>> --- a/doc/APIchanges
>> +++ b/doc/APIchanges
>> @@ -15,6 +15,9 @@ libavutil:     2017-10-21
>>
>>  API changes, most recent first:
>>
>> +2020-01-xx - xxxxxxxxxx - lavu 56.39.100 - eval.h
>> +  Add av_expr_eval2, av_expr_state_alloc, av_expr_state_free
>> +
>>  2019-12-27 - xxxxxxxxxx - lavu 56.38.100 - eval.h
>>    Add av_expr_count_func().
>>
>> diff --git a/libavutil/eval.c b/libavutil/eval.c
>> index d527f6a9d0..86fb634fd8 100644
>> --- a/libavutil/eval.c
>> +++ b/libavutil/eval.c
>> @@ -173,7 +173,11 @@ struct AVExpr {
>>          double (*func2)(void *, double, double);
>>      } a;
>>      struct AVExpr *param[3];
>> -    double *var;
>> +    AVExprState *state;
>> +};
>> +
>> +struct AVExprState {
>> +    double vars[VARS];
>>  };
>>
>>  static double etime(double v)
>> @@ -333,13 +337,23 @@ static double eval_expr(Parser *p, AVExpr *e)
>>
>>  static int parse_expr(AVExpr **e, Parser *p);
>>
>> +AVExprState *av_expr_state_alloc(void)
>> +{
>> +    return av_mallocz(sizeof(AVExprState));
>> +}
>> +
>> +void av_expr_state_free(AVExprState **ps)
>> +{
>> +    av_freep(ps);
>> +}
>> +
>>  void av_expr_free(AVExpr *e)
>>  {
>>      if (!e) return;
>>      av_expr_free(e->param[0]);
>>      av_expr_free(e->param[1]);
>>      av_expr_free(e->param[2]);
>> -    av_freep(&e->var);
>> +    av_expr_state_free(&e->state);
>>      av_freep(&e);
>>  }
>>
>> @@ -724,8 +738,8 @@ int av_expr_parse(AVExpr **expr, const char *s,
>>          ret = AVERROR(EINVAL);
>>          goto end;
>>      }
>> -    e->var= av_mallocz(sizeof(double) *VARS);
>> -    if (!e->var) {
>> +    e->state = av_expr_state_alloc();
>> +    if (!e->state) {
>>          ret = AVERROR(ENOMEM);
>>          goto end;
>>      }
>> @@ -763,16 +777,21 @@ 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)
>> +double av_expr_eval2(AVExpr *e, AVExprState *s, const double *const_values, void *opaque)
>>  {
>>      Parser p = { 0 };
>> -    p.var= e->var;
>> +    p.var = s ? s->vars : e->state->vars;
>>
>>      p.const_values = const_values;
>>      p.opaque     = opaque;
>>      return eval_expr(&p, e);
>>  }
>>
>> +double av_expr_eval(AVExpr *e, const double *const_values, void *opaque)
>> +{
>> +    return av_expr_eval2(e, NULL, const_values, opaque);
>> +}
>> +
>>  int av_expr_parse_and_eval(double *d, const char *s,
>>                             const char * const *const_names, const double *const_values,
>>                             const char * const *func1_names, double (* const *funcs1)(void *, double),
>> diff --git a/libavutil/eval.h b/libavutil/eval.h
>> index 068c62cdab..8bd1592f6c 100644
>> --- a/libavutil/eval.h
>> +++ b/libavutil/eval.h
>> @@ -29,6 +29,7 @@
>>  #include "avutil.h"
>>
>>  typedef struct AVExpr AVExpr;
>> +typedef struct AVExprState AVExprState;
>>
>>  /**
>>   * Parse and evaluate an expression.
>> @@ -86,6 +87,22 @@ int av_expr_parse(AVExpr **expr, const char *s,
>>   */
>>  double av_expr_eval(AVExpr *e, const double *const_values, void *opaque);
>>
>> +/**
>> + * Evaluate a previously parsed expression using a custom state.
>> + *
>> + * Some expressions can use stateful functions, like random(), st() and ld().
>> + * With this function you can provide your own state to the evaluator instead
>> + * of using the internal state of the AVExpr. This makes it possible to use the
>> + * same AVExpr in multiple threads each with their own AVExprState avoiding
>> + * unprotected concurrent access of the internal AVExpr state.
>> + *
>> + * @param s the state of the expression, if NULL, the internal state of AVExpr will be used
>> + * @param const_values a zero terminated array of values for the identifiers from av_expr_parse() const_names
>> + * @param opaque a pointer which will be passed to all functions from funcs1 and funcs2
>> + * @return the value of the expression
>> + */
>> +double av_expr_eval2(AVExpr *e, AVExprState *s, const double *const_values, void *opaque);
>> +
>>  /**
>>   * Track the presence of variables and their number of occurrences in a parsed expression
>>   *
>> @@ -134,4 +151,14 @@ void av_expr_free(AVExpr *e);
>>   */
>>  double av_strtod(const char *numstr, char **tail);
>>
>> +/**
>> + * Allocate a new AVExprState struct
>> + */
>> +AVExprState *av_expr_state_alloc(void);
>
> maybe this should have a double [] argument so the caller can set the
> initial variables (or pass NULL if not)

Maybe it is better to simply make the AVExprState struct public 
if setting/getting state manually is something we want to support. What do 
you think?

Thanks,
Marton
Michael Niedermayer Dec. 30, 2019, 7:43 p.m. UTC | #3
On Sun, Dec 29, 2019 at 04:46:12PM +0100, Marton Balint wrote:
> 
> 
> On Sun, 29 Dec 2019, Michael Niedermayer wrote:
> 
> >On Sat, Dec 28, 2019 at 03:46:23PM +0100, Marton Balint wrote:
> >>Also add helper functions to allocate and free such a struct, and make it
> >>usable by providing a new av_eval_expr2 function for which you can specify a
> >>custom AVExprState.
> >>
> >>Signed-off-by: Marton Balint <cus@passwd.hu>
> >>---
> >> doc/APIchanges      |  3 +++
> >> libavutil/eval.c    | 31 +++++++++++++++++++++++++------
> >> libavutil/eval.h    | 27 +++++++++++++++++++++++++++
> >> libavutil/version.h |  2 +-
> >> 4 files changed, 56 insertions(+), 7 deletions(-)
> >>
> >>diff --git a/doc/APIchanges b/doc/APIchanges
> >>index 3c24dc6fbc..e4ad364ed9 100644
> >>--- a/doc/APIchanges
> >>+++ b/doc/APIchanges
> >>@@ -15,6 +15,9 @@ libavutil:     2017-10-21
> >>
> >> API changes, most recent first:
> >>
> >>+2020-01-xx - xxxxxxxxxx - lavu 56.39.100 - eval.h
> >>+  Add av_expr_eval2, av_expr_state_alloc, av_expr_state_free
> >>+
> >> 2019-12-27 - xxxxxxxxxx - lavu 56.38.100 - eval.h
> >>   Add av_expr_count_func().
> >>
> >>diff --git a/libavutil/eval.c b/libavutil/eval.c
> >>index d527f6a9d0..86fb634fd8 100644
> >>--- a/libavutil/eval.c
> >>+++ b/libavutil/eval.c
> >>@@ -173,7 +173,11 @@ struct AVExpr {
> >>         double (*func2)(void *, double, double);
> >>     } a;
> >>     struct AVExpr *param[3];
> >>-    double *var;
> >>+    AVExprState *state;
> >>+};
> >>+
> >>+struct AVExprState {
> >>+    double vars[VARS];
> >> };
> >>
> >> static double etime(double v)
> >>@@ -333,13 +337,23 @@ static double eval_expr(Parser *p, AVExpr *e)
> >>
> >> static int parse_expr(AVExpr **e, Parser *p);
> >>
> >>+AVExprState *av_expr_state_alloc(void)
> >>+{
> >>+    return av_mallocz(sizeof(AVExprState));
> >>+}
> >>+
> >>+void av_expr_state_free(AVExprState **ps)
> >>+{
> >>+    av_freep(ps);
> >>+}
> >>+
> >> void av_expr_free(AVExpr *e)
> >> {
> >>     if (!e) return;
> >>     av_expr_free(e->param[0]);
> >>     av_expr_free(e->param[1]);
> >>     av_expr_free(e->param[2]);
> >>-    av_freep(&e->var);
> >>+    av_expr_state_free(&e->state);
> >>     av_freep(&e);
> >> }
> >>
> >>@@ -724,8 +738,8 @@ int av_expr_parse(AVExpr **expr, const char *s,
> >>         ret = AVERROR(EINVAL);
> >>         goto end;
> >>     }
> >>-    e->var= av_mallocz(sizeof(double) *VARS);
> >>-    if (!e->var) {
> >>+    e->state = av_expr_state_alloc();
> >>+    if (!e->state) {
> >>         ret = AVERROR(ENOMEM);
> >>         goto end;
> >>     }
> >>@@ -763,16 +777,21 @@ 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)
> >>+double av_expr_eval2(AVExpr *e, AVExprState *s, const double *const_values, void *opaque)
> >> {
> >>     Parser p = { 0 };
> >>-    p.var= e->var;
> >>+    p.var = s ? s->vars : e->state->vars;
> >>
> >>     p.const_values = const_values;
> >>     p.opaque     = opaque;
> >>     return eval_expr(&p, e);
> >> }
> >>
> >>+double av_expr_eval(AVExpr *e, const double *const_values, void *opaque)
> >>+{
> >>+    return av_expr_eval2(e, NULL, const_values, opaque);
> >>+}
> >>+
> >> int av_expr_parse_and_eval(double *d, const char *s,
> >>                            const char * const *const_names, const double *const_values,
> >>                            const char * const *func1_names, double (* const *funcs1)(void *, double),
> >>diff --git a/libavutil/eval.h b/libavutil/eval.h
> >>index 068c62cdab..8bd1592f6c 100644
> >>--- a/libavutil/eval.h
> >>+++ b/libavutil/eval.h
> >>@@ -29,6 +29,7 @@
> >> #include "avutil.h"
> >>
> >> typedef struct AVExpr AVExpr;
> >>+typedef struct AVExprState AVExprState;
> >>
> >> /**
> >>  * Parse and evaluate an expression.
> >>@@ -86,6 +87,22 @@ int av_expr_parse(AVExpr **expr, const char *s,
> >>  */
> >> double av_expr_eval(AVExpr *e, const double *const_values, void *opaque);
> >>
> >>+/**
> >>+ * Evaluate a previously parsed expression using a custom state.
> >>+ *
> >>+ * Some expressions can use stateful functions, like random(), st() and ld().
> >>+ * With this function you can provide your own state to the evaluator instead
> >>+ * of using the internal state of the AVExpr. This makes it possible to use the
> >>+ * same AVExpr in multiple threads each with their own AVExprState avoiding
> >>+ * unprotected concurrent access of the internal AVExpr state.
> >>+ *
> >>+ * @param s the state of the expression, if NULL, the internal state of AVExpr will be used
> >>+ * @param const_values a zero terminated array of values for the identifiers from av_expr_parse() const_names
> >>+ * @param opaque a pointer which will be passed to all functions from funcs1 and funcs2
> >>+ * @return the value of the expression
> >>+ */
> >>+double av_expr_eval2(AVExpr *e, AVExprState *s, const double *const_values, void *opaque);
> >>+
> >> /**
> >>  * Track the presence of variables and their number of occurrences in a parsed expression
> >>  *
> >>@@ -134,4 +151,14 @@ void av_expr_free(AVExpr *e);
> >>  */
> >> double av_strtod(const char *numstr, char **tail);
> >>
> >>+/**
> >>+ * Allocate a new AVExprState struct
> >>+ */
> >>+AVExprState *av_expr_state_alloc(void);
> >
> >maybe this should have a double [] argument so the caller can set the
> >initial variables (or pass NULL if not)
> 
> Maybe it is better to simply make the AVExprState struct public if
> setting/getting state manually is something we want to support. What do you
> think?

if its still extendible, then it may be a good idea, yes

thx

[...]
diff mbox

Patch

diff --git a/doc/APIchanges b/doc/APIchanges
index 3c24dc6fbc..e4ad364ed9 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -15,6 +15,9 @@  libavutil:     2017-10-21
 
 API changes, most recent first:
 
+2020-01-xx - xxxxxxxxxx - lavu 56.39.100 - eval.h
+  Add av_expr_eval2, av_expr_state_alloc, av_expr_state_free
+
 2019-12-27 - xxxxxxxxxx - lavu 56.38.100 - eval.h
   Add av_expr_count_func().
 
diff --git a/libavutil/eval.c b/libavutil/eval.c
index d527f6a9d0..86fb634fd8 100644
--- a/libavutil/eval.c
+++ b/libavutil/eval.c
@@ -173,7 +173,11 @@  struct AVExpr {
         double (*func2)(void *, double, double);
     } a;
     struct AVExpr *param[3];
-    double *var;
+    AVExprState *state;
+};
+
+struct AVExprState {
+    double vars[VARS];
 };
 
 static double etime(double v)
@@ -333,13 +337,23 @@  static double eval_expr(Parser *p, AVExpr *e)
 
 static int parse_expr(AVExpr **e, Parser *p);
 
+AVExprState *av_expr_state_alloc(void)
+{
+    return av_mallocz(sizeof(AVExprState));
+}
+
+void av_expr_state_free(AVExprState **ps)
+{
+    av_freep(ps);
+}
+
 void av_expr_free(AVExpr *e)
 {
     if (!e) return;
     av_expr_free(e->param[0]);
     av_expr_free(e->param[1]);
     av_expr_free(e->param[2]);
-    av_freep(&e->var);
+    av_expr_state_free(&e->state);
     av_freep(&e);
 }
 
@@ -724,8 +738,8 @@  int av_expr_parse(AVExpr **expr, const char *s,
         ret = AVERROR(EINVAL);
         goto end;
     }
-    e->var= av_mallocz(sizeof(double) *VARS);
-    if (!e->var) {
+    e->state = av_expr_state_alloc();
+    if (!e->state) {
         ret = AVERROR(ENOMEM);
         goto end;
     }
@@ -763,16 +777,21 @@  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)
+double av_expr_eval2(AVExpr *e, AVExprState *s, const double *const_values, void *opaque)
 {
     Parser p = { 0 };
-    p.var= e->var;
+    p.var = s ? s->vars : e->state->vars;
 
     p.const_values = const_values;
     p.opaque     = opaque;
     return eval_expr(&p, e);
 }
 
+double av_expr_eval(AVExpr *e, const double *const_values, void *opaque)
+{
+    return av_expr_eval2(e, NULL, const_values, opaque);
+}
+
 int av_expr_parse_and_eval(double *d, const char *s,
                            const char * const *const_names, const double *const_values,
                            const char * const *func1_names, double (* const *funcs1)(void *, double),
diff --git a/libavutil/eval.h b/libavutil/eval.h
index 068c62cdab..8bd1592f6c 100644
--- a/libavutil/eval.h
+++ b/libavutil/eval.h
@@ -29,6 +29,7 @@ 
 #include "avutil.h"
 
 typedef struct AVExpr AVExpr;
+typedef struct AVExprState AVExprState;
 
 /**
  * Parse and evaluate an expression.
@@ -86,6 +87,22 @@  int av_expr_parse(AVExpr **expr, const char *s,
  */
 double av_expr_eval(AVExpr *e, const double *const_values, void *opaque);
 
+/**
+ * Evaluate a previously parsed expression using a custom state.
+ *
+ * Some expressions can use stateful functions, like random(), st() and ld().
+ * With this function you can provide your own state to the evaluator instead
+ * of using the internal state of the AVExpr. This makes it possible to use the
+ * same AVExpr in multiple threads each with their own AVExprState avoiding
+ * unprotected concurrent access of the internal AVExpr state.
+ *
+ * @param s the state of the expression, if NULL, the internal state of AVExpr will be used
+ * @param const_values a zero terminated array of values for the identifiers from av_expr_parse() const_names
+ * @param opaque a pointer which will be passed to all functions from funcs1 and funcs2
+ * @return the value of the expression
+ */
+double av_expr_eval2(AVExpr *e, AVExprState *s, const double *const_values, void *opaque);
+
 /**
  * Track the presence of variables and their number of occurrences in a parsed expression
  *
@@ -134,4 +151,14 @@  void av_expr_free(AVExpr *e);
  */
 double av_strtod(const char *numstr, char **tail);
 
+/**
+ * Allocate a new AVExprState struct
+ */
+AVExprState *av_expr_state_alloc(void);
+
+/**
+ * Free an allocated AVExprState struct and set its pointer to NULL
+ */
+void av_expr_state_free(AVExprState **ps);
+
 #endif /* AVUTIL_EVAL_H */
diff --git a/libavutil/version.h b/libavutil/version.h
index af8f614aff..2bc1b98615 100644
--- a/libavutil/version.h
+++ b/libavutil/version.h
@@ -79,7 +79,7 @@ 
  */
 
 #define LIBAVUTIL_VERSION_MAJOR  56
-#define LIBAVUTIL_VERSION_MINOR  38
+#define LIBAVUTIL_VERSION_MINOR  39
 #define LIBAVUTIL_VERSION_MICRO 100
 
 #define LIBAVUTIL_VERSION_INT   AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \