Factorize code and provide ratio parsing consistency.tags/n0.11
| @@ -13,6 +13,12 @@ libavutil: 2011-04-18 | |||||
| API changes, most recent first: | 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 | 2012-02-02 - xxxxxxx - lavu 51.37.100 | ||||
| Add public timecode helpers. | Add public timecode helpers. | ||||
| @@ -3141,30 +3141,6 @@ static int opt_pad(const char *opt, const char *arg) | |||||
| return -1; | 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) | static int opt_video_channel(const char *opt, const char *arg) | ||||
| { | { | ||||
| av_log(NULL, AV_LOG_WARNING, "This option is deprecated, use -channel.\n"); | 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); | 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; | video_enc->bits_per_raw_sample = frame_bits_per_raw_sample; | ||||
| MATCH_PER_STREAM_OPT(frame_pix_fmts, str, frame_pix_fmt, oc, st); | MATCH_PER_STREAM_OPT(frame_pix_fmts, str, frame_pix_fmt, oc, st); | ||||
| @@ -24,6 +24,7 @@ | |||||
| */ | */ | ||||
| #include "libavutil/mathematics.h" | #include "libavutil/mathematics.h" | ||||
| #include "libavutil/parseutils.h" | |||||
| #include "avfilter.h" | #include "avfilter.h" | ||||
| typedef struct { | typedef struct { | ||||
| @@ -33,32 +34,18 @@ typedef struct { | |||||
| static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) | static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) | ||||
| { | { | ||||
| AspectContext *aspect = ctx->priv; | AspectContext *aspect = ctx->priv; | ||||
| double ratio; | |||||
| int64_t gcd; | |||||
| char c = 0; | |||||
| int ret; | |||||
| if (args) { | 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, | av_log(ctx, AV_LOG_ERROR, | ||||
| "Invalid string '%s' for aspect ratio.\n", args); | "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; | return 0; | ||||
| } | } | ||||
| @@ -154,7 +154,7 @@ | |||||
| */ | */ | ||||
| #define LIBAVUTIL_VERSION_MAJOR 51 | #define LIBAVUTIL_VERSION_MAJOR 51 | ||||
| #define LIBAVUTIL_VERSION_MINOR 37 | |||||
| #define LIBAVUTIL_VERSION_MINOR 38 | |||||
| #define LIBAVUTIL_VERSION_MICRO 100 | #define LIBAVUTIL_VERSION_MICRO 100 | ||||
| #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ | #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ | ||||
| @@ -124,6 +124,8 @@ typedef struct AVClass { | |||||
| */ | */ | ||||
| #define AV_LOG_DEBUG 48 | #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 | * 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 | * to the current av_log_level. By default, all logging messages are sent to | ||||
| @@ -31,6 +31,32 @@ | |||||
| #include "random_seed.h" | #include "random_seed.h" | ||||
| #include "parseutils.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 { | typedef struct { | ||||
| const char *abbr; | const char *abbr; | ||||
| int width, height; | int width, height; | ||||
| @@ -124,7 +150,6 @@ int av_parse_video_rate(AVRational *rate, const char *arg) | |||||
| { | { | ||||
| int i, ret; | int i, ret; | ||||
| int n = FF_ARRAY_ELEMS(video_rate_abbrs); | int n = FF_ARRAY_ELEMS(video_rate_abbrs); | ||||
| double res; | |||||
| /* First, we check our abbreviation table */ | /* First, we check our abbreviation table */ | ||||
| for (i = 0; i < n; ++i) | 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 */ | /* 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; | return ret; | ||||
| *rate = av_d2q(res, 1001000); | |||||
| if (rate->num <= 0 || rate->den <= 0) | if (rate->num <= 0 || rate->den <= 0) | ||||
| return AVERROR(EINVAL); | return AVERROR(EINVAL); | ||||
| return 0; | return 0; | ||||
| @@ -28,6 +28,30 @@ | |||||
| * misc parsing utilities | * 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. | * Parse str and put in width_ptr and height_ptr the detected values. | ||||
| * | * | ||||