[FFmpeg-devel] [PATCH] parseutils: add av_parse_number() function and children, and use them in the ff* tools

Stefano Sabatini stefano.sabatini-lala at poste.it
Tue May 24 20:19:37 CEST 2011


---
 cmdutils.c             |   44 +++++++++------------------
 cmdutils.h             |   15 ---------
 ffmpeg.c               |   36 ++++++++++------------
 ffplay.c               |   21 +++++--------
 libavutil/parseutils.c |   76 ++++++++++++++++++++++++++++++++++++++++++++++++
 libavutil/parseutils.h |   26 ++++++++++++++++
 6 files changed, 141 insertions(+), 77 deletions(-)

diff --git a/cmdutils.c b/cmdutils.c
index ed06092..4900764 100644
--- a/cmdutils.c
+++ b/cmdutils.c
@@ -92,25 +92,6 @@ void log_callback_help(void* ptr, int level, const char* fmt, va_list vl)
     vfprintf(stdout, fmt, vl);
 }
 
-double parse_number_or_die(const char *context, const char *numstr, int type, double min, double max)
-{
-    char *tail;
-    const char *error;
-    double d = av_strtod(numstr, &tail);
-    if (*tail)
-        error= "Expected number for %s but found: %s\n";
-    else if (d < min || d > max)
-        error= "The value for %s was %s which is not within %f - %f\n";
-    else if(type == OPT_INT64 && (int64_t)d != d)
-        error= "Expected int64 for %s but found %s\n";
-    else if (type == OPT_INT && (int)d != d)
-        error= "Expected int for %s but found %s\n";
-    else
-        return d;
-    fprintf(stderr, error, context, numstr, min, max);
-    exit(1);
-}
-
 int64_t parse_time_or_die(const char *context, const char *timestr, int is_duration)
 {
     int64_t us;
@@ -219,7 +200,7 @@ void parse_options(int argc, char **argv, const OptionDef *options,
                    void (* parse_arg_function)(const char*))
 {
     const char *opt, *arg;
-    int optindex, handleoptions=1;
+    int ret = 0, optindex, handleoptions=1;
     const OptionDef *po;
 
     /* perform system-dependent conversions for arguments list */
@@ -267,18 +248,20 @@ unknown_opt:
             } else if (po->flags & OPT_BOOL) {
                 *po->u.int_arg = bool_val;
             } else if (po->flags & OPT_INT) {
-                *po->u.int_arg = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX);
+                ret = av_parse_int(po->u.int_arg, arg, INT_MIN, INT_MAX, 0, NULL);
             } else if (po->flags & OPT_INT64) {
-                *po->u.int64_arg = parse_number_or_die(opt, arg, OPT_INT64, INT64_MIN, INT64_MAX);
+                ret = av_parse_int64(po->u.int64_arg, arg, INT64_MIN, INT64_MAX, 0, NULL);
             } else if (po->flags & OPT_FLOAT) {
-                *po->u.float_arg = parse_number_or_die(opt, arg, OPT_FLOAT, -INFINITY, INFINITY);
+                ret = av_parse_float(po->u.float_arg, arg, -INFINITY, INFINITY, 0, NULL);
             } else if (po->flags & OPT_DUMMY) {
                 /* Do nothing for this option */
             } else {
-                if (po->u.func_arg(opt, arg) < 0) {
-                    fprintf(stderr, "%s: failed to set value '%s' for option '%s'\n", argv[0], arg, opt);
-                    exit(1);
-                }
+                ret = po->u.func_arg(opt, arg);
+            }
+
+            if (ret < 0) {
+                fprintf(stderr, "%s: failed to set value '%s' for option '%s'\n", argv[0], arg, opt);
+                exit(1);
             }
             if(po->flags & OPT_EXIT)
                 exit(0);
@@ -399,8 +382,11 @@ int opt_loglevel(const char *opt, const char *arg)
 int opt_timelimit(const char *opt, const char *arg)
 {
 #if HAVE_SETRLIMIT
-    int lim = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
-    struct rlimit rl = { lim, lim + 1 };
+    int lim;
+    struct rlimit rl;
+    if (av_parse_int(&lim, arg, 0, INT_MAX, 0, NULL) < 0)
+        return AVERROR(EINVAL);
+    rl = (struct rlimit){ lim, lim + 1 };
     if (setrlimit(RLIMIT_CPU, &rl))
         perror("setrlimit");
 #else
diff --git a/cmdutils.h b/cmdutils.h
index eea4401..304735f 100644
--- a/cmdutils.h
+++ b/cmdutils.h
@@ -78,21 +78,6 @@ int opt_loglevel(const char *opt, const char *arg);
 int opt_timelimit(const char *opt, const char *arg);
 
 /**
- * Parse a string and return its corresponding value as a double.
- * Exit from the application if the string cannot be correctly
- * parsed or the corresponding value is invalid.
- *
- * @param context the context of the value to be set (e.g. the
- * corresponding commandline option name)
- * @param numstr the string to be parsed
- * @param type the type (OPT_INT64 or OPT_FLOAT) as which the
- * string should be parsed
- * @param min the minimum valid accepted value
- * @param max the maximum valid accepted value
- */
-double parse_number_or_die(const char *context, const char *numstr, int type, double min, double max);
-
-/**
  * Parse a string specifying a time and return its corresponding
  * value as a number of microseconds. Exit from the application if
  * the string cannot be correctly parsed.
diff --git a/ffmpeg.c b/ffmpeg.c
index 6597d61..484a7ba 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -2865,14 +2865,12 @@ static int opt_video_rc_override_string(const char *opt, const char *arg)
 
 static int opt_me_threshold(const char *opt, const char *arg)
 {
-    me_threshold = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX);
-    return 0;
+    return av_parse_int(&me_threshold, arg, INT_MIN, INT_MAX, 0, NULL);
 }
 
 static int opt_verbose(const char *opt, const char *arg)
 {
-    verbose = parse_number_or_die(opt, arg, OPT_INT64, -10, 10);
-    return 0;
+    return av_parse_int(&verbose, arg, -10, 10, 0, NULL);
 }
 
 static int opt_frame_rate(const char *opt, const char *arg)
@@ -2973,7 +2971,8 @@ static int opt_metadata(const char *opt, const char *arg)
 
 static int opt_qscale(const char *opt, const char *arg)
 {
-    video_qscale = parse_number_or_die(opt, arg, OPT_FLOAT, 0, 255);
+    if (av_parse_float(&video_qscale, arg, 0, 255, 0, NULL) < 0)
+        return AVERROR(EINVAL);
     if (video_qscale <= 0 || video_qscale > 255) {
         fprintf(stderr, "qscale must be > 0.0 and <= 255\n");
         return AVERROR(EINVAL);
@@ -2983,14 +2982,15 @@ static int opt_qscale(const char *opt, const char *arg)
 
 static int opt_top_field_first(const char *opt, const char *arg)
 {
-    top_field_first = parse_number_or_die(opt, arg, OPT_INT, 0, 1);
-    opt_default(opt, arg);
-    return 0;
+    if (av_parse_int(&top_field_first, arg, 0, 1, 0, NULL) < 0)
+        return AVERROR(EINVAL);
+    return opt_default(opt, arg);
 }
 
 static int opt_thread_count(const char *opt, const char *arg)
 {
-    thread_count= parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
+    if (av_parse_int(&thread_count, arg, 0, INT_MAX, 0, NULL) < 0)
+        return AVERROR(EINVAL);
 #if !HAVE_THREADS
     if (verbose >= 0)
         fprintf(stderr, "Warning: not compiled with thread support, using thread emulation\n");
@@ -3018,20 +3018,17 @@ static int opt_audio_sample_fmt(const char *opt, const char *arg)
 
 static int opt_audio_rate(const char *opt, const char *arg)
 {
-    audio_sample_rate = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
-    return 0;
+    return av_parse_int(&audio_sample_rate, arg, 0, INT_MAX, 0, NULL);
 }
 
 static int opt_audio_channels(const char *opt, const char *arg)
 {
-    audio_channels = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
-    return 0;
+    return av_parse_int(&audio_channels, arg, 0, INT_MAX, 0, NULL);
 }
 
 static int opt_video_channel(const char *opt, const char *arg)
 {
-    video_channel = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
-    return 0;
+    return av_parse_int(&video_channel, arg, 0, INT_MAX, 0, NULL);
 }
 
 static int opt_video_standard(const char *opt, const char *arg)
@@ -3878,10 +3875,10 @@ static int opt_streamid(const char *opt, const char *arg)
         ffmpeg_exit(1);
     }
     *p++ = '\0';
-    idx = parse_number_or_die(opt, idx_str, OPT_INT, 0, MAX_STREAMS-1);
+    if (av_parse_int(&idx, idx_str, 0, MAX_STREAMS-1, 0, NULL) < 0)
+        return AVERROR(EINVAL);
     streamid_map = grow_array(streamid_map, sizeof(*streamid_map), &nb_streamid_map, idx+1);
-    streamid_map[idx] = parse_number_or_die(opt, p, OPT_INT, 0, INT_MAX);
-    return 0;
+    return av_parse_int(&streamid_map[idx], p, 0, INT_MAX, 0, NULL);
 }
 
 static void opt_output_file(const char *filename)
@@ -4013,8 +4010,7 @@ static void opt_output_file(const char *filename)
 /* same option as mencoder */
 static int opt_pass(const char *opt, const char *arg)
 {
-    do_pass = parse_number_or_die(opt, arg, OPT_INT, 1, 2);
-    return 0;
+    return av_parse_int(&do_pass, arg, 1, 2, 0, NULL);
 }
 
 static int64_t getutime(void)
diff --git a/ffplay.c b/ffplay.c
index 66ee836..febffa2 100644
--- a/ffplay.c
+++ b/ffplay.c
@@ -2892,14 +2892,12 @@ static int opt_frame_size(const char *opt, const char *arg)
 
 static int opt_width(const char *opt, const char *arg)
 {
-    screen_width = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX);
-    return 0;
+    return av_parse_int(&screen_width, arg, 1, INT_MAX, 0, NULL);
 }
 
 static int opt_height(const char *opt, const char *arg)
 {
-    screen_height = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX);
-    return 0;
+    return av_parse_int(&screen_height, arg, 1, INT_MAX, 0, NULL);
 }
 
 static int opt_format(const char *opt, const char *arg)
@@ -2948,32 +2946,29 @@ static int opt_duration(const char *opt, const char *arg)
 static int opt_debug(const char *opt, const char *arg)
 {
     av_log_set_level(99);
-    debug = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
-    return 0;
+    return av_parse_int(&debug, arg, 0, INT_MAX, 0, NULL);
 }
 
 static int opt_vismv(const char *opt, const char *arg)
 {
-    debug_mv = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX);
-    return 0;
+    return av_parse_int(&debug_mv, arg, INT_MIN, INT_MAX, 0, NULL);
 }
 
 static int opt_thread_count(const char *opt, const char *arg)
 {
-    thread_count= parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
 #if !HAVE_THREADS
     fprintf(stderr, "Warning: not compiled with thread support, using thread emulation\n");
 #endif
-    return 0;
+    return av_parse_int(&thread_count, arg, 0, INT_MAX, 0, NULL);
 }
 
 static int opt_show_mode(const char *opt, const char *arg)
 {
     show_mode = !strcmp(arg, "video") ? SHOW_MODE_VIDEO :
                 !strcmp(arg, "waves") ? SHOW_MODE_WAVES :
-                !strcmp(arg, "rdft" ) ? SHOW_MODE_RDFT  :
-                parse_number_or_die(opt, arg, OPT_INT, 0, SHOW_MODE_NB-1);
-    return 0;
+                !strcmp(arg, "rdft" ) ? SHOW_MODE_RDFT  : SHOW_MODE_NONE;
+    return show_mode == SHOW_MODE_NONE ?
+        av_parse_int(&show_mode, arg, 0, SHOW_MODE_NB-1, 0, NULL) : 0;
 }
 
 static const OptionDef options[] = {
diff --git a/libavutil/parseutils.c b/libavutil/parseutils.c
index d67d31b..987e937 100644
--- a/libavutil/parseutils.c
+++ b/libavutil/parseutils.c
@@ -30,6 +30,82 @@
 #include "libavutil/avstring.h"
 #include "libavutil/random_seed.h"
 
+typedef struct ParseUtils {
+    const AVClass *class;
+    int   log_offset;
+    void *log_ctx;
+} ParseUtils;
+
+static const AVClass parseutils_class = {
+    "PARSEUTILS", av_default_item_name, NULL, LIBAVUTIL_VERSION_INT,
+    offsetof(ParseUtils, log_offset), offsetof(ParseUtils, log_ctx)
+};
+
+int av_parse_number(double *res, const char *numstr, enum AVParseNumberType type,
+                    double min, double max,
+                    int log_offset, void *log_ctx)
+{
+    ParseUtils parseutils = { &parseutils_class, log_offset, log_ctx };
+
+    char *tail;
+    double d = av_strtod(numstr, &tail);
+    if ((unsigned)type >= AV_PARSE_NUM_TYPE_NB) {
+        av_log(&parseutils, AV_LOG_ERROR, "Unknown parse number type '%d'\n", type);
+    } else if (*tail) {
+        av_log(&parseutils, AV_LOG_ERROR, "Expected number but found '%s'\n", numstr);
+    } else if (d < min || d > max) {
+        av_log(&parseutils, AV_LOG_ERROR,
+               "The numeric value for '%s' is %f, which is not within the inclusive interval %f - %f\n",
+               numstr, d, min, max);
+    } else if (type == AV_PARSE_NUM_TYPE_INT64 && (int64_t)d != d) {
+        av_log(&parseutils, AV_LOG_ERROR,
+               "Expected int64 but found %s\n", numstr);
+    } else if (type == AV_PARSE_NUM_TYPE_INT && (int)d != d) {
+        av_log(&parseutils, AV_LOG_ERROR,
+               "Expected int but found %s\n", numstr);
+    } else {                    /* float and double */
+        *res = d;
+        return 0;
+    }
+
+    return AVERROR(EINVAL);
+}
+
+int av_parse_int(int *res, const char *numstr, int min, int max, int log_offset, void *log_ctx)
+{
+    double d;
+    int ret = av_parse_number(&d, numstr, AV_PARSE_NUM_TYPE_INT, min, max, log_offset, log_ctx);
+    if (ret < 0)
+        return ret;
+    *res = d;
+    return 0;
+}
+
+int av_parse_int64(int64_t *res, const char *numstr, int64_t min, int64_t max, int log_offset, void *log_ctx)
+{
+    double d;
+    int ret = av_parse_number(&d, numstr, AV_PARSE_NUM_TYPE_INT64, min, max, log_offset, log_ctx);
+    if (ret < 0)
+        return ret;
+    *res = d;
+    return 0;
+}
+
+int av_parse_float(float *res, const char *numstr, float min, float max, int log_offset, void *log_ctx)
+{
+    double d;
+    int ret = av_parse_number(&d, numstr, AV_PARSE_NUM_TYPE_FLOAT, min, max,log_offset, log_ctx);
+    if (ret < 0)
+        return ret;
+    *res = d;
+    return 0;
+}
+
+int av_parse_double(double *res, const char *numstr, double min, double max, int log_offset, void *log_ctx)
+{
+    return av_parse_number(res, numstr, AV_PARSE_NUM_TYPE_DOUBLE, min, max, log_offset, log_ctx);
+}
+
 typedef struct {
     const char *abbr;
     int width, height;
diff --git a/libavutil/parseutils.h b/libavutil/parseutils.h
index c3986af..ab7a8b3 100644
--- a/libavutil/parseutils.h
+++ b/libavutil/parseutils.h
@@ -26,6 +26,32 @@
  * misc parsing utilities
  */
 
+enum AVParseNumberType {
+    AV_PARSE_NUM_TYPE_INT,
+    AV_PARSE_NUM_TYPE_INT64,
+    AV_PARSE_NUM_TYPE_FLOAT,
+    AV_PARSE_NUM_TYPE_DOUBLE,
+    AV_PARSE_NUM_TYPE_NB
+};
+
+/**
+ * Parse a string and return its corresponding value as a double.
+ *
+ * @param res pointer where to put the resulting parsed value
+ * @param numstr the string to be parsed
+ * @param type the type of the number to get
+ * @param min the minimum valid accepted value
+ * @param max the maximum valid accepted value
+ * @return >=0 in case of success, a negative AVERROR code in case of failure
+ */
+int av_parse_number(double *res, const char *numstr, enum AVParseNumberType type,
+                    double min, double max, int log_offset, void *log_ctx);
+
+int av_parse_int   (int     *res, const char *numstr, int     min, int     max, int log_offset, void *log_ctx);
+int av_parse_int64 (int64_t *res, const char *numstr, int64_t min, int64_t max, int log_offset, void *log_ctx);
+int av_parse_float (float   *res, const char *numstr, float   min, float   max, int log_offset, void *log_ctx);
+int av_parse_double(double  *res, const char *numstr, double  min, double  max, int log_offset, void *log_ctx);
+
 /**
  * Parse str and put in width_ptr and height_ptr the detected values.
  *
-- 
1.7.2.3



More information about the ffmpeg-devel mailing list