Browse code

lavu: introduce av_parse_ratio() and use it in ffmpeg and lavfi/aspect

Factorize code and provide ratio parsing consistency.

Stefano Sabatini authored on 2012/01/17 23:25:14
Showing 7 changed files
... ...
@@ -13,6 +13,12 @@ libavutil:   2011-04-18
13 13
 
14 14
 API changes, most recent first:
15 15
 
16
+2012-02-06 - xxxxxxx - lavu 51.38.100
17
+  Add av_parse_ratio() function to parseutils.h.
18
+
19
+2012-02-06 - xxxxxxx - lavu 51.38.100
20
+  Add AV_LOG_MAX_OFFSET macro to log.h.
21
+
16 22
 2012-02-02 - xxxxxxx - lavu 51.37.100
17 23
   Add public timecode helpers.
18 24
 
... ...
@@ -3141,30 +3141,6 @@ static int opt_pad(const char *opt, const char *arg)
3141 3141
     return -1;
3142 3142
 }
3143 3143
 
3144
-static double parse_frame_aspect_ratio(const char *arg)
3145
-{
3146
-    int x = 0, y = 0;
3147
-    double ar = 0;
3148
-    const char *p;
3149
-    char *end;
3150
-
3151
-    p = strchr(arg, ':');
3152
-    if (p) {
3153
-        x = strtol(arg, &end, 10);
3154
-        if (end == p)
3155
-            y = strtol(end + 1, &end, 10);
3156
-        if (x > 0 && y > 0)
3157
-            ar = (double)x / (double)y;
3158
-    } else
3159
-        ar = strtod(arg, NULL);
3160
-
3161
-    if (!ar) {
3162
-        av_log(NULL, AV_LOG_FATAL, "Incorrect aspect ratio specification.\n");
3163
-        exit_program(1);
3164
-    }
3165
-    return ar;
3166
-}
3167
-
3168 3144
 static int opt_video_channel(const char *opt, const char *arg)
3169 3145
 {
3170 3146
     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)
3986 3986
         }
3987 3987
 
3988 3988
         MATCH_PER_STREAM_OPT(frame_aspect_ratios, str, frame_aspect_ratio, oc, st);
3989
-        if (frame_aspect_ratio)
3990
-            ost->frame_aspect_ratio = parse_frame_aspect_ratio(frame_aspect_ratio);
3989
+        if (frame_aspect_ratio) {
3990
+            AVRational q;
3991
+            if (av_parse_ratio(&q, frame_aspect_ratio, 255, 0, NULL) < 0 ||
3992
+                q.num <= 0 || q.den <= 0) {
3993
+                av_log(NULL, AV_LOG_FATAL, "Invalid aspect ratio: %s\n", frame_aspect_ratio);
3994
+                exit_program(1);
3995
+            }
3996
+            ost->frame_aspect_ratio = av_q2d(q);
3997
+        }
3991 3998
 
3992 3999
         video_enc->bits_per_raw_sample = frame_bits_per_raw_sample;
3993 4000
         MATCH_PER_STREAM_OPT(frame_pix_fmts, str, frame_pix_fmt, oc, st);
... ...
@@ -24,6 +24,7 @@
24 24
  */
25 25
 
26 26
 #include "libavutil/mathematics.h"
27
+#include "libavutil/parseutils.h"
27 28
 #include "avfilter.h"
28 29
 
29 30
 typedef struct {
... ...
@@ -33,32 +34,18 @@ typedef struct {
33 33
 static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
34 34
 {
35 35
     AspectContext *aspect = ctx->priv;
36
-    double  ratio;
37
-    int64_t gcd;
38
-    char c = 0;
36
+    int ret;
39 37
 
40 38
     if (args) {
41
-        if (sscanf(args, "%d:%d%c", &aspect->aspect.num, &aspect->aspect.den, &c) != 2)
42
-            if (sscanf(args, "%lf%c", &ratio, &c) == 1)
43
-                aspect->aspect = av_d2q(ratio, 100);
44
-
45
-        if (c || aspect->aspect.num <= 0 || aspect->aspect.den <= 0) {
39
+        if ((ret = av_parse_ratio(&aspect->aspect, args, 100, 0, ctx)) < 0 ||
40
+            aspect->aspect.num < 0 || aspect->aspect.den <= 0) {
46 41
             av_log(ctx, AV_LOG_ERROR,
47 42
                    "Invalid string '%s' for aspect ratio.\n", args);
48
-            return AVERROR(EINVAL);
43
+            return ret;
49 44
         }
50 45
 
51
-        gcd = av_gcd(FFABS(aspect->aspect.num), FFABS(aspect->aspect.den));
52
-        if (gcd) {
53
-            aspect->aspect.num /= gcd;
54
-            aspect->aspect.den /= gcd;
55
-        }
46
+        av_log(ctx, AV_LOG_INFO, "a:%d/%d\n", aspect->aspect.num, aspect->aspect.den);
56 47
     }
57
-
58
-    if (aspect->aspect.den == 0)
59
-        aspect->aspect = (AVRational) {0, 1};
60
-
61
-    av_log(ctx, AV_LOG_INFO, "a:%d/%d\n", aspect->aspect.num, aspect->aspect.den);
62 48
     return 0;
63 49
 }
64 50
 
... ...
@@ -154,7 +154,7 @@
154 154
  */
155 155
 
156 156
 #define LIBAVUTIL_VERSION_MAJOR 51
157
-#define LIBAVUTIL_VERSION_MINOR 37
157
+#define LIBAVUTIL_VERSION_MINOR 38
158 158
 #define LIBAVUTIL_VERSION_MICRO 100
159 159
 
160 160
 #define LIBAVUTIL_VERSION_INT   AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
... ...
@@ -124,6 +124,8 @@ typedef struct AVClass {
124 124
  */
125 125
 #define AV_LOG_DEBUG    48
126 126
 
127
+#define AV_LOG_MAX_OFFSET (AV_LOG_DEBUG - AV_LOG_QUIET)
128
+
127 129
 /**
128 130
  * Send the specified message to the log if the level is less than or equal
129 131
  * to the current av_log_level. By default, all logging messages are sent to
... ...
@@ -31,6 +31,32 @@
31 31
 #include "random_seed.h"
32 32
 #include "parseutils.h"
33 33
 
34
+int av_parse_ratio(AVRational *q, const char *str, int max,
35
+                   int log_offset, void *log_ctx)
36
+{
37
+    char c;
38
+    int ret;
39
+    int64_t gcd;
40
+
41
+    if (sscanf(str, "%d:%d%c", &q->num, &q->den, &c) != 2) {
42
+        double d;
43
+        ret = av_expr_parse_and_eval(&d, str, NULL, NULL,
44
+                                     NULL, NULL, NULL, NULL,
45
+                                     NULL, log_offset, log_ctx);
46
+        if (ret < 0)
47
+            return ret;
48
+        *q = av_d2q(d, max);
49
+    }
50
+
51
+    gcd = av_gcd(FFABS(q->num), FFABS(q->den));
52
+    if (gcd) {
53
+        q->num /= gcd;
54
+        q->den /= gcd;
55
+    }
56
+
57
+    return 0;
58
+}
59
+
34 60
 typedef struct {
35 61
     const char *abbr;
36 62
     int width, height;
... ...
@@ -124,7 +150,6 @@ int av_parse_video_rate(AVRational *rate, const char *arg)
124 124
 {
125 125
     int i, ret;
126 126
     int n = FF_ARRAY_ELEMS(video_rate_abbrs);
127
-    double res;
128 127
 
129 128
     /* First, we check our abbreviation table */
130 129
     for (i = 0; i < n; ++i)
... ...
@@ -134,10 +159,8 @@ int av_parse_video_rate(AVRational *rate, const char *arg)
134 134
         }
135 135
 
136 136
     /* Then, we try to parse it as fraction */
137
-    if ((ret = av_expr_parse_and_eval(&res, arg, NULL, NULL, NULL, NULL, NULL, NULL,
138
-                                      NULL, 0, NULL)) < 0)
137
+    if ((ret = av_parse_ratio_quiet(rate, arg, 1001000)) < 0)
139 138
         return ret;
140
-    *rate = av_d2q(res, 1001000);
141 139
     if (rate->num <= 0 || rate->den <= 0)
142 140
         return AVERROR(EINVAL);
143 141
     return 0;
... ...
@@ -29,6 +29,30 @@
29 29
  */
30 30
 
31 31
 /**
32
+ * Parse str and store the parsed ratio in q.
33
+ *
34
+ * Note that a ratio with infinite (1/0) or negative value is
35
+ * considered valid, so you should check on the returned value if you
36
+ * want to exclude those values.
37
+ *
38
+ * The undefined value can be expressed using the "0:0" string.
39
+ *
40
+ * @param[in,out] q pointer to the AVRational which will contain the ratio
41
+ * @param[in] str the string to parse: it has to be a string in the format
42
+ * num:den, a float number or an expression
43
+ * @param[in] max the maximum allowed numerator and denominator
44
+ * @param[in] log_offset log level offset which is applied to the log
45
+ * level of log_ctx
46
+ * @param[in] log_ctx parent logging context
47
+ * @return >= 0 on success, a negative error code otherwise
48
+ */
49
+int av_parse_ratio(AVRational *q, const char *str, int max,
50
+                   int log_offset, void *log_ctx);
51
+
52
+#define av_parse_ratio_quiet(rate, str, max) \
53
+    av_parse_ratio(rate, str, max, AV_LOG_MAX_OFFSET, NULL)
54
+
55
+/**
32 56
  * Parse str and put in width_ptr and height_ptr the detected values.
33 57
  *
34 58
  * @param[in,out] width_ptr pointer to the variable which will contain the detected