[FFmpeg-devel] [PATCH 2/2] Make ff_parse_expr() and ff_parse_and_eval_expr() return an int containing an error code.

Stefano Sabatini stefano.sabatini-lala
Thu May 20 02:08:46 CEST 2010


Allow these functions to convey to the calling application the reason
of the failure, which is not always due to a parsing error but for
example it may depend on a memory problem.
---
 libavcodec/eval.c        |   44 ++++++++++++++++++++++++++------------------
 libavcodec/eval.h        |   17 ++++++++++++-----
 libavcodec/opt.c         |    6 +++---
 libavcodec/ratecontrol.c |    8 ++++----
 4 files changed, 45 insertions(+), 30 deletions(-)

diff --git a/libavcodec/eval.c b/libavcodec/eval.c
index c1bb42d..727acbf 100644
--- a/libavcodec/eval.c
+++ b/libavcodec/eval.c
@@ -373,19 +373,20 @@ static int verify_expr(AVExpr * e) {
     }
 }
 
-AVExpr *ff_parse_expr(const char *s,
+int ff_parse_expr(AVExpr **expr, const char *s,
                       const char * const *const_name,
                       const char * const *func1_name, double (* const *func1)(void *, double),
                       const char * const *func2_name, double (* const *func2)(void *, double, double),
                       int log_offset, void *log_ctx)
 {
     Parser p;
-    AVExpr *e = NULL;
     char *w = av_malloc(strlen(s) + 1);
     char *wp = w;
+    int res = 0;
+    *expr = NULL;
 
     if (!w)
-        goto end;
+        return AVERROR(ENOMEM);
 
     while (*s)
         if (!isspace(*s++)) *wp++ = s[-1];
@@ -402,14 +403,14 @@ AVExpr *ff_parse_expr(const char *s,
     p.log_offset = log_offset;
     p.log_ctx    = log_ctx;
 
-    e = parse_expr(&p);
-    if (!verify_expr(e)) {
-        ff_free_expr(e);
-        e = NULL;
+    *expr = parse_expr(&p);
+    if (!verify_expr(*expr)) {
+        ff_free_expr(*expr);
+        *expr = NULL;
+        res = AVERROR(EINVAL);
     }
-end:
     av_free(w);
-    return e;
+    return res;
 }
 
 double ff_eval_expr(AVExpr * e, const double *const_value, void *opaque) {
@@ -420,18 +421,22 @@ double ff_eval_expr(AVExpr * e, const double *const_value, void *opaque) {
     return eval_expr(&p, e);
 }
 
-double ff_parse_and_eval_expr(const char *s,
+int ff_parse_and_eval_expr(double *d, const char *s,
                               const char * const *const_name, const double *const_value,
                               const char * const *func1_name, double (* const *func1)(void *, double),
                               const char * const *func2_name, double (* const *func2)(void *, double, double),
                               void *opaque, int log_offset, void *log_ctx)
 {
-    AVExpr *e = ff_parse_expr(s, const_name, func1_name, func1, func2_name, func2, log_offset, log_ctx);
-    double d;
-    if (!e) return NAN;
-    d = ff_eval_expr(e, const_value, opaque);
+    AVExpr *e = NULL;
+    int res = ff_parse_expr(&e, s, const_name, func1_name, func1, func2_name, func2, log_offset, log_ctx);
+
+    if (res < 0) {
+        *d = NAN;
+        return res;
+    }
+    *d = ff_eval_expr(e, const_value, opaque);
     ff_free_expr(e);
-    return d;
+    return isnan(*d) ? AVERROR(EINVAL) : 0;
 }
 
 #ifdef TEST
@@ -448,12 +453,15 @@ static const char *const_names[]={
 };
 int main(void){
     int i;
-    printf("%f == 12.7\n", ff_parse_and_eval_expr("1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, NULL));
-    printf("%f == 0.931322575\n", ff_parse_and_eval_expr("80G/80Gi", const_names, const_values, NULL, NULL, NULL, NULL, NULL, NULL));
+    double d;
+    ff_parse_and_eval_expr(&d, "1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, NULL);
+    printf("%f == 12.7\n", d);
+    ff_parse_and_eval_expr(&d, "80G/80Gi", const_names, const_values, NULL, NULL, NULL, NULL, NULL, NULL);
+    printf("%f == 0.931322575\n", d);
 
     for(i=0; i<1050; i++){
         START_TIMER
-            ff_parse_and_eval_expr("1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, NULL);
+            ff_parse_and_eval_expr(&d, "1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, NULL);
         STOP_TIMER("ff_parse_and_eval_expr")
     }
     return 0;
diff --git a/libavcodec/eval.h b/libavcodec/eval.h
index d0004b1..0efacbb 100644
--- a/libavcodec/eval.h
+++ b/libavcodec/eval.h
@@ -32,6 +32,8 @@ typedef struct AVExpr AVExpr;
  * Parses and evaluates an expression.
  * Note, this is significantly slower than ff_eval_expr().
  *
+ * @param res a pointer to a double where is put the result value of
+ * the expression, or NAN in case of invalid expression
  * @param s expression as a zero terminated string for example "1+2^3+5*5+sin(2/3)"
  * @param const_name NULL terminated array of zero terminated strings of constant identifers for example {"PI", "E", 0}
  * @param const_value a zero terminated array of values for the identifers from const_name
@@ -41,9 +43,10 @@ typedef struct AVExpr AVExpr;
  * @param func2 NULL terminated array of function pointers for functions which take 2 arguments
  * @param opaque a pointer which will be passed to all functions from func1 and func2
  * @param log_ctx parent logging context
- * @return the value of the expression
+ * @return 0 in case of success, a negative value corresponding to an
+ * AVERROR code otherwise
  */
-double ff_parse_and_eval_expr(const char *s,
+int ff_parse_and_eval_expr(double *res, const char *s,
                               const char * const *const_name, const double *const_value,
                               const char * const *func1_name, double (* const *func1)(void *, double),
                               const char * const *func2_name, double (* const *func2)(void *, double, double),
@@ -52,6 +55,10 @@ double ff_parse_and_eval_expr(const char *s,
 /**
  * Parses an expression.
  *
+ * @param expr a pointer where is put an AVExpr containing the parsed
+ * value in case of successfull parsing, or NULL otherwise.
+ * The pointed to AVExpr must be freed with ff_free_expr() by the user
+ * when it is not needed anymore.
  * @param s expression as a zero terminated string for example "1+2^3+5*5+sin(2/3)"
  * @param const_name NULL terminated array of zero terminated strings of constant identifers for example {"PI", "E", 0}
  * @param func1_name NULL terminated array of zero terminated strings of func1 identifers
@@ -59,10 +66,10 @@ double ff_parse_and_eval_expr(const char *s,
  * @param func2_name NULL terminated array of zero terminated strings of func2 identifers
  * @param func2 NULL terminated array of function pointers for functions which take 2 arguments
  * @param log_ctx parent logging context
- * @return AVExpr which must be freed with ff_free_expr() by the user when it is not needed anymore
- *         NULL if anything went wrong
+ * @return 0 in case of success, a negative value corresponding to an
+ * AVERROR code otherwise
  */
-AVExpr *ff_parse_expr(const char *s,
+int ff_parse_expr(AVExpr **expr, const char *s,
                       const char * const *const_name,
                       const char * const *func1_name, double (* const *func1)(void *, double),
                       const char * const *func2_name, double (* const *func2)(void *, double, double),
diff --git a/libavcodec/opt.c b/libavcodec/opt.c
index 24696e1..8473d90 100644
--- a/libavcodec/opt.c
+++ b/libavcodec/opt.c
@@ -165,10 +165,10 @@ int av_set_string3(void *obj, const char *name, const char *val, int alloc, cons
                 else if(!strcmp(buf, "none"   )) d= 0;
                 else if(!strcmp(buf, "all"    )) d= ~0;
                 else {
-                    d = ff_parse_and_eval_expr(buf, const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, obj);
-                    if (isnan(d)){
+                    int res = ff_parse_and_eval_expr(&d, buf, const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, obj);
+                    if (res < 0) {
                         av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\"\n", val);
-                    return AVERROR(EINVAL);
+                        return res;
                     }
                 }
             }
diff --git a/libavcodec/ratecontrol.c b/libavcodec/ratecontrol.c
index fe6e4b0..375815a 100644
--- a/libavcodec/ratecontrol.c
+++ b/libavcodec/ratecontrol.c
@@ -66,7 +66,7 @@ static inline double bits2qp(RateControlEntry *rce, double bits){
 int ff_rate_control_init(MpegEncContext *s)
 {
     RateControlContext *rcc= &s->rc_context;
-    int i;
+    int i, res;
     static const char * const const_names[]={
         "PI",
         "E",
@@ -106,10 +106,10 @@ int ff_rate_control_init(MpegEncContext *s)
     };
     emms_c();
 
-    rcc->rc_eq_eval = ff_parse_expr(s->avctx->rc_eq ? s->avctx->rc_eq : "tex^qComp", const_names, func1_names, func1, NULL, NULL, 0, s->avctx);
-    if (!rcc->rc_eq_eval) {
+    res = ff_parse_expr(&rcc->rc_eq_eval, s->avctx->rc_eq ? s->avctx->rc_eq : "tex^qComp", const_names, func1_names, func1, NULL, NULL, 0, s->avctx);
+    if (res < 0) {
         av_log(s->avctx, AV_LOG_ERROR, "Error parsing rc_eq \"%s\"\n", s->avctx->rc_eq);
-        return -1;
+        return res;
     }
 
     for(i=0; i<5; i++){
-- 
1.7.1




More information about the ffmpeg-devel mailing list