[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