[FFmpeg-devel] [PATCH 10/10] Implement av_parse_fraction(), and use it in av_parse_video_rate().

Stefano Sabatini stefano.sabatini-lala
Thu Sep 30 23:50:57 CEST 2010


The new function is useful for parsing framerates, timebases or
generic fractions (not necessarily video frame rates).
---
 libavcore/parseutils.c |   95 ++++++++++++++++++++++++++++++++++++++++--------
 libavcore/parseutils.h |   11 ++++++
 2 files changed, 90 insertions(+), 16 deletions(-)

diff --git a/libavcore/parseutils.c b/libavcore/parseutils.c
index e8ce6cf..5139b91 100644
--- a/libavcore/parseutils.c
+++ b/libavcore/parseutils.c
@@ -24,6 +24,38 @@
 #include "parseutils.h"
 #include "libavutil/avutil.h"
 
+#define WHITESPACES " \n\t"
+
+int av_parse_fraction(AVRational *q, const char *arg)
+{
+    char *tail;
+    char *cp = strchr(arg, '/');
+
+    *q = (AVRational) {0,0};
+    if (!cp)
+        cp = strchr(arg, ':');
+    if (cp) {
+        q->num = strtol(arg, &tail, 10);
+        tail += strspn(tail, WHITESPACES);
+        if (*tail && tail != cp)
+            return AVERROR(EINVAL);
+        if (tail) {
+            q->den = strtol(cp+1, &tail, 10);
+            tail += strspn(tail, WHITESPACES);
+            if (*tail)
+                return AVERROR(EINVAL);
+        } else
+            q->den = 1;
+    } else {
+        /* Finally we give up and parse it as double */
+        *q = av_d2q(strtod(arg, &tail), 1001000);
+        tail += strspn(tail, WHITESPACES);
+        if (*tail)
+            return AVERROR(EINVAL);
+    }
+    return 0;
+}
+
 typedef struct {
     const char *abbr;
     int width, height;
@@ -115,9 +147,8 @@ int av_parse_video_size(int *width_ptr, int *height_ptr, const char *str)
 
 int av_parse_video_rate(AVRational *rate, const char *arg)
 {
-    int i;
+    int i, ret;
     int n = FF_ARRAY_ELEMS(video_rate_abbrs);
-    char *cp;
 
     /* First, we check our abbreviation table */
     for (i = 0; i < n; ++i)
@@ -127,21 +158,53 @@ int av_parse_video_rate(AVRational *rate, const char *arg)
          }
 
     /* Then, we try to parse it as fraction */
-    cp = strchr(arg, '/');
-    if (!cp)
-        cp = strchr(arg, ':');
-    if (cp) {
-        char *cpp;
-        rate->num = strtol(arg, &cpp, 10);
-        if (cpp != arg || cpp == cp)
-            rate->den = strtol(cp+1, &cpp, 10);
-        else
-            rate->num = 0;
-    } else {
-        /* Finally we give up and parse it as double */
-        *rate = av_d2q(strtod(arg, 0), 1001000);
-    }
+    if ((ret = av_parse_fraction(rate, arg)))
+        return ret;
     if (rate->num <= 0 || rate->den <= 0)
         return AVERROR(EINVAL);
     return 0;
 }
+
+#ifdef TEST
+
+#undef printf
+
+int main(void)
+{
+    printf("Testing av_parse_fraction()\n");
+    {
+        int i;
+        const char *fracts[] = {
+            "",
+            "/",
+            "123/0",
+            " 123  /  321",
+            "foo/foo",
+            "foo/1",
+            "1/foo",
+            "0/0",
+            "/0",
+            "1/",
+            "-123/123",
+            "-foo",
+            "123.23",
+            ".23",
+            "-.23",
+            "-0.234",
+            "-0.0000001",
+            " -21332.2324   ",
+        };
+
+        for (i = 0; i < FF_ARRAY_ELEMS(fracts); i++) {
+            int ret;
+            AVRational q;
+            ret = av_parse_fraction(&q, fracts[i]);
+            printf("'%s' -> %d/%d %s\n",
+                   fracts[i], q.num, q.den, ret ? "***error!" : "");
+        }
+    }
+
+    return 0;
+}
+
+#endif /* TEST */
diff --git a/libavcore/parseutils.h b/libavcore/parseutils.h
index ad31ef2..19c0c11 100644
--- a/libavcore/parseutils.h
+++ b/libavcore/parseutils.h
@@ -27,6 +27,17 @@
  */
 
 /**
+ * Parse str as a fraction and store the parsed value in *q.
+ *
+ * @param[in,out] q pointer to an AVRational which will contain the
+ * detected fraction
+ * @param[in] str the string to parse: it has to be a string in the format
+ * rate_num / rate_den, or a float number
+ * @return >= 0 on success, a negative error code otherwise
+ */
+int av_parse_fraction(AVRational *q, const char *arg);
+
+/**
  * Parse str and put in width_ptr and height_ptr the detected values.
  *
  * @param[in,out] width_ptr pointer to the variable which will contain the detected
-- 
1.7.1




More information about the ffmpeg-devel mailing list