diff options
Diffstat (limited to 'libavutil/parseutils.c')
-rw-r--r-- | libavutil/parseutils.c | 260 |
1 files changed, 187 insertions, 73 deletions
diff --git a/libavutil/parseutils.c b/libavutil/parseutils.c index f4248114b5..7ca07b37a1 100644 --- a/libavutil/parseutils.c +++ b/libavutil/parseutils.c @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -31,6 +31,37 @@ #include "random_seed.h" #include "time_internal.h" #include "parseutils.h" +#include "time.h" + +#ifdef TEST + +#define av_get_random_seed av_get_random_seed_deterministic +static uint32_t av_get_random_seed_deterministic(void); + +#define av_gettime() 1331972053200000 + +#endif + +int av_parse_ratio(AVRational *q, const char *str, int max, + int log_offset, void *log_ctx) +{ + char c; + int ret; + + 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); + } else { + av_reduce(&q->num, &q->den, q->num, q->den, max); + } + + return 0; +} typedef struct VideoSizeAbbr { const char *abbr; @@ -80,8 +111,20 @@ static const VideoSizeAbbr video_size_abbrs[] = { { "hd480", 852, 480 }, { "hd720", 1280, 720 }, { "hd1080", 1920,1080 }, + { "2k", 2048,1080 }, /* Digital Cinema System Specification */ { "2kdci", 2048,1080 }, + { "2kflat", 1998,1080 }, + { "2kscope", 2048, 858 }, + { "4k", 4096,2160 }, /* Digital Cinema System Specification */ { "4kdci", 4096,2160 }, + { "4kflat", 3996,2160 }, + { "4kscope", 4096,1716 }, + { "nhd", 640,360 }, + { "hqvga", 240,160 }, + { "wqvga", 400,240 }, + { "fwqvga", 432,240 }, + { "hvga", 480,320 }, + { "qhd", 960,540 }, { "uhd2160", 3840,2160 }, { "uhd4320", 7680,4320 }, }; @@ -97,11 +140,16 @@ static const VideoRateAbbr video_rate_abbrs[]= { { "ntsc-film", { 24000, 1001 } }, }; +static const char *months[12] = { + "january", "february", "march", "april", "may", "june", "july", "august", + "september", "october", "november", "december" +}; + int av_parse_video_size(int *width_ptr, int *height_ptr, const char *str) { int i; int n = FF_ARRAY_ELEMS(video_size_abbrs); - char *p; + const char *p; int width = 0, height = 0; for (i = 0; i < n; i++) { @@ -112,10 +160,14 @@ int av_parse_video_size(int *width_ptr, int *height_ptr, const char *str) } } if (i == n) { - width = strtol(str, &p, 10); + width = strtol(str, (void*)&p, 10); if (*p) p++; - height = strtol(p, &p, 10); + height = strtol(p, (void*)&p, 10); + + /* trailing extraneous data detected, like in 123x345foobar */ + if (*p) + return AVERROR(EINVAL); } if (width <= 0 || height <= 0) return AVERROR(EINVAL); @@ -128,7 +180,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) @@ -138,10 +189,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; @@ -152,7 +201,7 @@ typedef struct ColorEntry { uint8_t rgb_color[3]; ///< RGB values for the color } ColorEntry; -static ColorEntry color_table[] = { +static const ColorEntry color_table[] = { { "AliceBlue", { 0xF0, 0xF8, 0xFF } }, { "AntiqueWhite", { 0xFA, 0xEB, 0xD7 } }, { "Aqua", { 0x00, 0xFF, 0xFF } }, @@ -220,8 +269,8 @@ static ColorEntry color_table[] = { { "LightCoral", { 0xF0, 0x80, 0x80 } }, { "LightCyan", { 0xE0, 0xFF, 0xFF } }, { "LightGoldenRodYellow", { 0xFA, 0xFA, 0xD2 } }, - { "LightGrey", { 0xD3, 0xD3, 0xD3 } }, { "LightGreen", { 0x90, 0xEE, 0x90 } }, + { "LightGrey", { 0xD3, 0xD3, 0xD3 } }, { "LightPink", { 0xFF, 0xB6, 0xC1 } }, { "LightSalmon", { 0xFF, 0xA0, 0x7A } }, { "LightSeaGreen", { 0x20, 0xB2, 0xAA } }, @@ -364,7 +413,11 @@ int av_parse_color(uint8_t *rgba_color, const char *color_string, int slen, if (!strncmp(alpha_string, "0x", 2)) { alpha = strtoul(alpha_string, &tail, 16); } else { - alpha = 255 * strtod(alpha_string, &tail); + double norm_alpha = strtod(alpha_string, &tail); + if (norm_alpha < 0.0 || norm_alpha > 1.0) + alpha = 256; + else + alpha = 255 * norm_alpha; } if (tail == alpha_string || *tail || alpha > 255 || alpha < 0) { @@ -378,6 +431,20 @@ int av_parse_color(uint8_t *rgba_color, const char *color_string, int slen, return 0; } +const char *av_get_known_color_name(int color_idx, const uint8_t **rgbp) +{ + const ColorEntry *color; + + if ((unsigned)color_idx >= FF_ARRAY_ELEMS(color_table)) + return NULL; + + color = &color_table[color_idx]; + if (rgbp) + *rgbp = color->rgb_color; + + return color->name; +} + /* get a positive number between n_min and n_max, for a maximum length of len_max. Return -1 if error. */ static int date_get_num(const char **pp, @@ -404,7 +471,22 @@ static int date_get_num(const char **pp, return val; } -const char *av_small_strptime(const char *p, const char *fmt, struct tm *dt) +static int date_get_month(const char **pp) { + int i = 0; + for (; i < 12; i++) { + if (!av_strncasecmp(*pp, months[i], 3)) { + const char *mo_full = months[i] + 3; + int len = strlen(mo_full); + *pp += 3; + if (len > 0 && !av_strncasecmp(*pp, mo_full, len)) + *pp += len; + return i; + } + } + return -1; +} + +char *av_small_strptime(const char *p, const char *fmt, struct tm *dt) { int c, val; @@ -421,7 +503,9 @@ const char *av_small_strptime(const char *p, const char *fmt, struct tm *dt) c = *fmt++; switch(c) { case 'H': - val = date_get_num(&p, 0, 23, 2); + case 'J': + val = date_get_num(&p, 0, c == 'H' ? 23 : INT_MAX, 2); + if (val == -1) return NULL; dt->tm_hour = val; @@ -461,6 +545,14 @@ const char *av_small_strptime(const char *p, const char *fmt, struct tm *dt) if (!p) return NULL; break; + case 'b': + case 'B': + case 'h': + val = date_get_month(&p); + if (val == -1) + return NULL; + dt->tm_mon = val; + break; case '%': if (*p++ != '%') return NULL; @@ -470,7 +562,7 @@ const char *av_small_strptime(const char *p, const char *fmt, struct tm *dt) } } - return p; + return (char*)p; } time_t av_timegm(struct tm *tm) @@ -484,7 +576,7 @@ time_t av_timegm(struct tm *tm) y--; } - t = 86400 * + t = 86400LL * (d + (153 * m - 457) / 5 + 365 * y + y / 4 - y / 100 + y / 400 - 719469); t += 3600 * tm->tm_hour + 60 * tm->tm_min + tm->tm_sec; @@ -494,70 +586,64 @@ time_t av_timegm(struct tm *tm) int av_parse_time(int64_t *timeval, const char *timestr, int duration) { - const char *p; - int64_t t; + const char *p, *q; + int64_t t, now64; + time_t now; struct tm dt = { 0 }, tmbuf; + int today = 0, negative = 0, microseconds = 0; int i; static const char * const date_fmt[] = { - "%Y-%m-%d", + "%Y - %m - %d", "%Y%m%d", }; static const char * const time_fmt[] = { "%H:%M:%S", "%H%M%S", }; - const char *q; - int is_utc, len; - char lastch; - int negative = 0; - - time_t now = time(0); - - len = strlen(timestr); - if (len > 0) - lastch = timestr[len - 1]; - else - lastch = '\0'; - is_utc = (lastch == 'z' || lastch == 'Z'); + static const char * const tz_fmt[] = { + "%H:%M", + "%H%M", + "%H", + }; p = timestr; q = NULL; + *timeval = INT64_MIN; if (!duration) { - if (!av_strncasecmp(timestr, "now", len)) { - *timeval = (int64_t) now * 1000000; + now64 = av_gettime(); + now = now64 / 1000000; + + if (!av_strcasecmp(timestr, "now")) { + *timeval = now64; return 0; } /* parse the year-month-day part */ for (i = 0; i < FF_ARRAY_ELEMS(date_fmt); i++) { q = av_small_strptime(p, date_fmt[i], &dt); - if (q) { + if (q) break; - } } /* if the year-month-day part is missing, then take the * current year-month-day time */ if (!q) { - if (is_utc) { - dt = *gmtime_r(&now, &tmbuf); - } else { - dt = *localtime_r(&now, &tmbuf); - } - dt.tm_hour = dt.tm_min = dt.tm_sec = 0; - } else { - p = q; + today = 1; + q = p; } + p = q; - if (*p == 'T' || *p == 't' || *p == ' ') + if (*p == 'T' || *p == 't') p++; + else + while (av_isspace(*p)) + p++; /* parse the hour-minute-second part */ for (i = 0; i < FF_ARRAY_ELEMS(time_fmt); i++) { q = av_small_strptime(p, time_fmt[i], &dt); - if (q) { + if (q) break; - } } } else { /* parse timestr as a duration */ @@ -566,16 +652,18 @@ int av_parse_time(int64_t *timeval, const char *timestr, int duration) ++p; } /* parse timestr as HH:MM:SS */ - q = av_small_strptime(p, time_fmt[0], &dt); + q = av_small_strptime(p, "%J:%M:%S", &dt); + if (!q) { + /* parse timestr as MM:SS */ + q = av_small_strptime(p, "%M:%S", &dt); + dt.tm_hour = 0; + } if (!q) { char *o; /* parse timestr as S+ */ dt.tm_sec = strtol(p, &o, 10); - if (o == p) { - /* the parsing didn't succeed */ - *timeval = INT64_MIN; + if (o == p) /* the parsing didn't succeed */ return AVERROR(EINVAL); - } dt.tm_min = 0; dt.tm_hour = 0; q = o; @@ -583,35 +671,61 @@ int av_parse_time(int64_t *timeval, const char *timestr, int duration) } /* Now we have all the fields that we can get */ - if (!q) { - *timeval = INT64_MIN; + if (!q) return AVERROR(EINVAL); + + /* parse the .m... part */ + if (*q == '.') { + int n; + q++; + for (n = 100000; n >= 1; n /= 10, q++) { + if (!av_isdigit(*q)) + break; + microseconds += n * (*q - '0'); + } + while (av_isdigit(*q)) + q++; } if (duration) { t = dt.tm_hour * 3600 + dt.tm_min * 60 + dt.tm_sec; } else { - dt.tm_isdst = -1; /* unknown */ - if (is_utc) { - t = av_timegm(&dt); - } else { - t = mktime(&dt); + int is_utc = *q == 'Z' || *q == 'z'; + int tzoffset = 0; + q += is_utc; + if (!today && !is_utc && (*q == '+' || *q == '-')) { + struct tm tz = { 0 }; + int sign = (*q == '+' ? -1 : 1); + q++; + p = q; + for (i = 0; i < FF_ARRAY_ELEMS(tz_fmt); i++) { + q = av_small_strptime(p, tz_fmt[i], &tz); + if (q) + break; + } + if (!q) + return AVERROR(EINVAL); + tzoffset = sign * (tz.tm_hour * 60 + tz.tm_min) * 60; + is_utc = 1; + } + if (today) { /* fill in today's date */ + struct tm dt2 = is_utc ? *gmtime_r(&now, &tmbuf) : *localtime_r(&now, &tmbuf); + dt2.tm_hour = dt.tm_hour; + dt2.tm_min = dt.tm_min; + dt2.tm_sec = dt.tm_sec; + dt = dt2; } + dt.tm_isdst = is_utc ? 0 : -1; + t = is_utc ? av_timegm(&dt) : mktime(&dt); + t += tzoffset; } - t *= 1000000; + /* Check that we are at the end of the string */ + if (*q) + return AVERROR(EINVAL); - /* parse the .m... part */ - if (*q == '.') { - int val, n; - q++; - for (val = 0, n = 100000; n >= 1; n /= 10, q++) { - if (!av_isdigit(*q)) - break; - val += n * (*q - '0'); - } - t += val; - } + t *= 1000000; + t += microseconds; *timeval = negative ? -t : t; return 0; } |