diff --git a/doc/APIchanges b/doc/APIchanges index d6e4decdf3..9a1d2ebab0 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -13,6 +13,12 @@ libavutil: 2011-04-18 API changes, most recent first: +2012-02-06 - xxxxxxx - lavu 51.38.100 + Add av_parse_ratio() function to parseutils.h. + +2012-02-06 - xxxxxxx - lavu 51.38.100 + Add AV_LOG_MAX_OFFSET macro to log.h. + 2012-02-02 - xxxxxxx - lavu 51.37.100 Add public timecode helpers. diff --git a/ffmpeg.c b/ffmpeg.c index 3241bcbff7..ac667af3b3 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -3141,30 +3141,6 @@ static int opt_pad(const char *opt, const char *arg) return -1; } -static double parse_frame_aspect_ratio(const char *arg) -{ - int x = 0, y = 0; - double ar = 0; - const char *p; - char *end; - - p = strchr(arg, ':'); - if (p) { - x = strtol(arg, &end, 10); - if (end == p) - y = strtol(end + 1, &end, 10); - if (x > 0 && y > 0) - ar = (double)x / (double)y; - } else - ar = strtod(arg, NULL); - - if (!ar) { - av_log(NULL, AV_LOG_FATAL, "Incorrect aspect ratio specification.\n"); - exit_program(1); - } - return ar; -} - static int opt_video_channel(const char *opt, const char *arg) { av_log(NULL, AV_LOG_WARNING, "This option is deprecated, use -channel.\n"); @@ -3986,8 +3962,15 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc) } MATCH_PER_STREAM_OPT(frame_aspect_ratios, str, frame_aspect_ratio, oc, st); - if (frame_aspect_ratio) - ost->frame_aspect_ratio = parse_frame_aspect_ratio(frame_aspect_ratio); + if (frame_aspect_ratio) { + AVRational q; + if (av_parse_ratio(&q, frame_aspect_ratio, 255, 0, NULL) < 0 || + q.num <= 0 || q.den <= 0) { + av_log(NULL, AV_LOG_FATAL, "Invalid aspect ratio: %s\n", frame_aspect_ratio); + exit_program(1); + } + ost->frame_aspect_ratio = av_q2d(q); + } video_enc->bits_per_raw_sample = frame_bits_per_raw_sample; MATCH_PER_STREAM_OPT(frame_pix_fmts, str, frame_pix_fmt, oc, st); diff --git a/libavfilter/vf_aspect.c b/libavfilter/vf_aspect.c index f92ed1f231..cced6bde8e 100644 --- a/libavfilter/vf_aspect.c +++ b/libavfilter/vf_aspect.c @@ -24,6 +24,7 @@ */ #include "libavutil/mathematics.h" +#include "libavutil/parseutils.h" #include "avfilter.h" typedef struct { @@ -33,32 +34,18 @@ typedef struct { static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) { AspectContext *aspect = ctx->priv; - double ratio; - int64_t gcd; - char c = 0; + int ret; if (args) { - if (sscanf(args, "%d:%d%c", &aspect->aspect.num, &aspect->aspect.den, &c) != 2) - if (sscanf(args, "%lf%c", &ratio, &c) == 1) - aspect->aspect = av_d2q(ratio, 100); - - if (c || aspect->aspect.num <= 0 || aspect->aspect.den <= 0) { + if ((ret = av_parse_ratio(&aspect->aspect, args, 100, 0, ctx)) < 0 || + aspect->aspect.num < 0 || aspect->aspect.den <= 0) { av_log(ctx, AV_LOG_ERROR, "Invalid string '%s' for aspect ratio.\n", args); - return AVERROR(EINVAL); + return ret; } - gcd = av_gcd(FFABS(aspect->aspect.num), FFABS(aspect->aspect.den)); - if (gcd) { - aspect->aspect.num /= gcd; - aspect->aspect.den /= gcd; - } + av_log(ctx, AV_LOG_INFO, "a:%d/%d\n", aspect->aspect.num, aspect->aspect.den); } - - if (aspect->aspect.den == 0) - aspect->aspect = (AVRational) {0, 1}; - - av_log(ctx, AV_LOG_INFO, "a:%d/%d\n", aspect->aspect.num, aspect->aspect.den); return 0; } diff --git a/libavutil/avutil.h b/libavutil/avutil.h index 5d574e8851..c8427fd0bf 100644 --- a/libavutil/avutil.h +++ b/libavutil/avutil.h @@ -154,7 +154,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 51 -#define LIBAVUTIL_VERSION_MINOR 37 +#define LIBAVUTIL_VERSION_MINOR 38 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ diff --git a/libavutil/log.h b/libavutil/log.h index 02a0e1ac8c..26c806f644 100644 --- a/libavutil/log.h +++ b/libavutil/log.h @@ -124,6 +124,8 @@ typedef struct AVClass { */ #define AV_LOG_DEBUG 48 +#define AV_LOG_MAX_OFFSET (AV_LOG_DEBUG - AV_LOG_QUIET) + /** * Send the specified message to the log if the level is less than or equal * to the current av_log_level. By default, all logging messages are sent to diff --git a/libavutil/parseutils.c b/libavutil/parseutils.c index 2649e3b2bc..802931dd2e 100644 --- a/libavutil/parseutils.c +++ b/libavutil/parseutils.c @@ -31,6 +31,32 @@ #include "random_seed.h" #include "parseutils.h" +int av_parse_ratio(AVRational *q, const char *str, int max, + int log_offset, void *log_ctx) +{ + char c; + int ret; + int64_t gcd; + + if (sscanf(str, "%d:%d%c", &q->num, &q->den, &c) != 2) { + double d; + ret = av_expr_parse_and_eval(&d, str, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, log_offset, log_ctx); + if (ret < 0) + return ret; + *q = av_d2q(d, max); + } + + gcd = av_gcd(FFABS(q->num), FFABS(q->den)); + if (gcd) { + q->num /= gcd; + q->den /= gcd; + } + + return 0; +} + typedef struct { const char *abbr; int width, height; @@ -124,7 +150,6 @@ int av_parse_video_rate(AVRational *rate, const char *arg) { int i, ret; int n = FF_ARRAY_ELEMS(video_rate_abbrs); - double res; /* First, we check our abbreviation table */ for (i = 0; i < n; ++i) @@ -134,10 +159,8 @@ int av_parse_video_rate(AVRational *rate, const char *arg) } /* Then, we try to parse it as fraction */ - if ((ret = av_expr_parse_and_eval(&res, arg, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, 0, NULL)) < 0) + if ((ret = av_parse_ratio_quiet(rate, arg, 1001000)) < 0) return ret; - *rate = av_d2q(res, 1001000); if (rate->num <= 0 || rate->den <= 0) return AVERROR(EINVAL); return 0; diff --git a/libavutil/parseutils.h b/libavutil/parseutils.h index 2a74a060f2..a545652d9e 100644 --- a/libavutil/parseutils.h +++ b/libavutil/parseutils.h @@ -28,6 +28,30 @@ * misc parsing utilities */ +/** + * Parse str and store the parsed ratio in q. + * + * Note that a ratio with infinite (1/0) or negative value is + * considered valid, so you should check on the returned value if you + * want to exclude those values. + * + * The undefined value can be expressed using the "0:0" string. + * + * @param[in,out] q pointer to the AVRational which will contain the ratio + * @param[in] str the string to parse: it has to be a string in the format + * num:den, a float number or an expression + * @param[in] max the maximum allowed numerator and denominator + * @param[in] log_offset log level offset which is applied to the log + * level of log_ctx + * @param[in] log_ctx parent logging context + * @return >= 0 on success, a negative error code otherwise + */ +int av_parse_ratio(AVRational *q, const char *str, int max, + int log_offset, void *log_ctx); + +#define av_parse_ratio_quiet(rate, str, max) \ + av_parse_ratio(rate, str, max, AV_LOG_MAX_OFFSET, NULL) + /** * Parse str and put in width_ptr and height_ptr the detected values. *