[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