Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

864 lines (791 sloc) 27.251 kb
/*
* This file is part of FFmpeg.
*
* 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.
*
* 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 FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* misc parsing utilities
*/
#include <time.h>
#include "avstring.h"
#include "avutil.h"
#include "common.h"
#include "eval.h"
#include "log.h"
#include "random_seed.h"
#include "parseutils.h"
#undef time
#ifdef TEST
#define av_get_random_seed av_get_random_seed_deterministic
static uint32_t av_get_random_seed_deterministic(void);
#define time(t) 1331972053
#endif
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 {
const char *abbr;
int width, height;
} VideoSizeAbbr;
typedef struct {
const char *abbr;
AVRational rate;
} VideoRateAbbr;
static const VideoSizeAbbr video_size_abbrs[] = {
{ "ntsc", 720, 480 },
{ "pal", 720, 576 },
{ "qntsc", 352, 240 }, /* VCD compliant NTSC */
{ "qpal", 352, 288 }, /* VCD compliant PAL */
{ "sntsc", 640, 480 }, /* square pixel NTSC */
{ "spal", 768, 576 }, /* square pixel PAL */
{ "film", 352, 240 },
{ "ntsc-film", 352, 240 },
{ "sqcif", 128, 96 },
{ "qcif", 176, 144 },
{ "cif", 352, 288 },
{ "4cif", 704, 576 },
{ "16cif", 1408,1152 },
{ "qqvga", 160, 120 },
{ "qvga", 320, 240 },
{ "vga", 640, 480 },
{ "svga", 800, 600 },
{ "xga", 1024, 768 },
{ "uxga", 1600,1200 },
{ "qxga", 2048,1536 },
{ "sxga", 1280,1024 },
{ "qsxga", 2560,2048 },
{ "hsxga", 5120,4096 },
{ "wvga", 852, 480 },
{ "wxga", 1366, 768 },
{ "wsxga", 1600,1024 },
{ "wuxga", 1920,1200 },
{ "woxga", 2560,1600 },
{ "wqsxga", 3200,2048 },
{ "wquxga", 3840,2400 },
{ "whsxga", 6400,4096 },
{ "whuxga", 7680,4800 },
{ "cga", 320, 200 },
{ "ega", 640, 350 },
{ "hd480", 852, 480 },
{ "hd720", 1280, 720 },
{ "hd1080", 1920,1080 },
};
static const VideoRateAbbr video_rate_abbrs[]= {
{ "ntsc", { 30000, 1001 } },
{ "pal", { 25, 1 } },
{ "qntsc", { 30000, 1001 } }, /* VCD compliant NTSC */
{ "qpal", { 25, 1 } }, /* VCD compliant PAL */
{ "sntsc", { 30000, 1001 } }, /* square pixel NTSC */
{ "spal", { 25, 1 } }, /* square pixel PAL */
{ "film", { 24, 1 } },
{ "ntsc-film", { 24000, 1001 } },
};
int av_parse_video_size(int *width_ptr, int *height_ptr, const char *str)
{
int i;
int n = FF_ARRAY_ELEMS(video_size_abbrs);
const char *p;
int width = 0, height = 0;
for (i = 0; i < n; i++) {
if (!strcmp(video_size_abbrs[i].abbr, str)) {
width = video_size_abbrs[i].width;
height = video_size_abbrs[i].height;
break;
}
}
if (i == n) {
p = str;
width = strtol(p, (void*)&p, 10);
if (*p)
p++;
height = strtol(p, (void*)&p, 10);
}
if (width <= 0 || height <= 0)
return AVERROR(EINVAL);
*width_ptr = width;
*height_ptr = height;
return 0;
}
int av_parse_video_rate(AVRational *rate, const char *arg)
{
int i, ret;
int n = FF_ARRAY_ELEMS(video_rate_abbrs);
/* First, we check our abbreviation table */
for (i = 0; i < n; ++i)
if (!strcmp(video_rate_abbrs[i].abbr, arg)) {
*rate = video_rate_abbrs[i].rate;
return 0;
}
/* Then, we try to parse it as fraction */
if ((ret = av_parse_ratio_quiet(rate, arg, 1001000)) < 0)
return ret;
if (rate->num <= 0 || rate->den <= 0)
return AVERROR(EINVAL);
return 0;
}
typedef struct {
const char *name; ///< a string representing the name of the color
uint8_t rgb_color[3]; ///< RGB values for the color
} ColorEntry;
static const ColorEntry color_table[] = {
{ "AliceBlue", { 0xF0, 0xF8, 0xFF } },
{ "AntiqueWhite", { 0xFA, 0xEB, 0xD7 } },
{ "Aqua", { 0x00, 0xFF, 0xFF } },
{ "Aquamarine", { 0x7F, 0xFF, 0xD4 } },
{ "Azure", { 0xF0, 0xFF, 0xFF } },
{ "Beige", { 0xF5, 0xF5, 0xDC } },
{ "Bisque", { 0xFF, 0xE4, 0xC4 } },
{ "Black", { 0x00, 0x00, 0x00 } },
{ "BlanchedAlmond", { 0xFF, 0xEB, 0xCD } },
{ "Blue", { 0x00, 0x00, 0xFF } },
{ "BlueViolet", { 0x8A, 0x2B, 0xE2 } },
{ "Brown", { 0xA5, 0x2A, 0x2A } },
{ "BurlyWood", { 0xDE, 0xB8, 0x87 } },
{ "CadetBlue", { 0x5F, 0x9E, 0xA0 } },
{ "Chartreuse", { 0x7F, 0xFF, 0x00 } },
{ "Chocolate", { 0xD2, 0x69, 0x1E } },
{ "Coral", { 0xFF, 0x7F, 0x50 } },
{ "CornflowerBlue", { 0x64, 0x95, 0xED } },
{ "Cornsilk", { 0xFF, 0xF8, 0xDC } },
{ "Crimson", { 0xDC, 0x14, 0x3C } },
{ "Cyan", { 0x00, 0xFF, 0xFF } },
{ "DarkBlue", { 0x00, 0x00, 0x8B } },
{ "DarkCyan", { 0x00, 0x8B, 0x8B } },
{ "DarkGoldenRod", { 0xB8, 0x86, 0x0B } },
{ "DarkGray", { 0xA9, 0xA9, 0xA9 } },
{ "DarkGreen", { 0x00, 0x64, 0x00 } },
{ "DarkKhaki", { 0xBD, 0xB7, 0x6B } },
{ "DarkMagenta", { 0x8B, 0x00, 0x8B } },
{ "DarkOliveGreen", { 0x55, 0x6B, 0x2F } },
{ "Darkorange", { 0xFF, 0x8C, 0x00 } },
{ "DarkOrchid", { 0x99, 0x32, 0xCC } },
{ "DarkRed", { 0x8B, 0x00, 0x00 } },
{ "DarkSalmon", { 0xE9, 0x96, 0x7A } },
{ "DarkSeaGreen", { 0x8F, 0xBC, 0x8F } },
{ "DarkSlateBlue", { 0x48, 0x3D, 0x8B } },
{ "DarkSlateGray", { 0x2F, 0x4F, 0x4F } },
{ "DarkTurquoise", { 0x00, 0xCE, 0xD1 } },
{ "DarkViolet", { 0x94, 0x00, 0xD3 } },
{ "DeepPink", { 0xFF, 0x14, 0x93 } },
{ "DeepSkyBlue", { 0x00, 0xBF, 0xFF } },
{ "DimGray", { 0x69, 0x69, 0x69 } },
{ "DodgerBlue", { 0x1E, 0x90, 0xFF } },
{ "FireBrick", { 0xB2, 0x22, 0x22 } },
{ "FloralWhite", { 0xFF, 0xFA, 0xF0 } },
{ "ForestGreen", { 0x22, 0x8B, 0x22 } },
{ "Fuchsia", { 0xFF, 0x00, 0xFF } },
{ "Gainsboro", { 0xDC, 0xDC, 0xDC } },
{ "GhostWhite", { 0xF8, 0xF8, 0xFF } },
{ "Gold", { 0xFF, 0xD7, 0x00 } },
{ "GoldenRod", { 0xDA, 0xA5, 0x20 } },
{ "Gray", { 0x80, 0x80, 0x80 } },
{ "Green", { 0x00, 0x80, 0x00 } },
{ "GreenYellow", { 0xAD, 0xFF, 0x2F } },
{ "HoneyDew", { 0xF0, 0xFF, 0xF0 } },
{ "HotPink", { 0xFF, 0x69, 0xB4 } },
{ "IndianRed", { 0xCD, 0x5C, 0x5C } },
{ "Indigo", { 0x4B, 0x00, 0x82 } },
{ "Ivory", { 0xFF, 0xFF, 0xF0 } },
{ "Khaki", { 0xF0, 0xE6, 0x8C } },
{ "Lavender", { 0xE6, 0xE6, 0xFA } },
{ "LavenderBlush", { 0xFF, 0xF0, 0xF5 } },
{ "LawnGreen", { 0x7C, 0xFC, 0x00 } },
{ "LemonChiffon", { 0xFF, 0xFA, 0xCD } },
{ "LightBlue", { 0xAD, 0xD8, 0xE6 } },
{ "LightCoral", { 0xF0, 0x80, 0x80 } },
{ "LightCyan", { 0xE0, 0xFF, 0xFF } },
{ "LightGoldenRodYellow", { 0xFA, 0xFA, 0xD2 } },
{ "LightGreen", { 0x90, 0xEE, 0x90 } },
{ "LightGrey", { 0xD3, 0xD3, 0xD3 } },
{ "LightPink", { 0xFF, 0xB6, 0xC1 } },
{ "LightSalmon", { 0xFF, 0xA0, 0x7A } },
{ "LightSeaGreen", { 0x20, 0xB2, 0xAA } },
{ "LightSkyBlue", { 0x87, 0xCE, 0xFA } },
{ "LightSlateGray", { 0x77, 0x88, 0x99 } },
{ "LightSteelBlue", { 0xB0, 0xC4, 0xDE } },
{ "LightYellow", { 0xFF, 0xFF, 0xE0 } },
{ "Lime", { 0x00, 0xFF, 0x00 } },
{ "LimeGreen", { 0x32, 0xCD, 0x32 } },
{ "Linen", { 0xFA, 0xF0, 0xE6 } },
{ "Magenta", { 0xFF, 0x00, 0xFF } },
{ "Maroon", { 0x80, 0x00, 0x00 } },
{ "MediumAquaMarine", { 0x66, 0xCD, 0xAA } },
{ "MediumBlue", { 0x00, 0x00, 0xCD } },
{ "MediumOrchid", { 0xBA, 0x55, 0xD3 } },
{ "MediumPurple", { 0x93, 0x70, 0xD8 } },
{ "MediumSeaGreen", { 0x3C, 0xB3, 0x71 } },
{ "MediumSlateBlue", { 0x7B, 0x68, 0xEE } },
{ "MediumSpringGreen", { 0x00, 0xFA, 0x9A } },
{ "MediumTurquoise", { 0x48, 0xD1, 0xCC } },
{ "MediumVioletRed", { 0xC7, 0x15, 0x85 } },
{ "MidnightBlue", { 0x19, 0x19, 0x70 } },
{ "MintCream", { 0xF5, 0xFF, 0xFA } },
{ "MistyRose", { 0xFF, 0xE4, 0xE1 } },
{ "Moccasin", { 0xFF, 0xE4, 0xB5 } },
{ "NavajoWhite", { 0xFF, 0xDE, 0xAD } },
{ "Navy", { 0x00, 0x00, 0x80 } },
{ "OldLace", { 0xFD, 0xF5, 0xE6 } },
{ "Olive", { 0x80, 0x80, 0x00 } },
{ "OliveDrab", { 0x6B, 0x8E, 0x23 } },
{ "Orange", { 0xFF, 0xA5, 0x00 } },
{ "OrangeRed", { 0xFF, 0x45, 0x00 } },
{ "Orchid", { 0xDA, 0x70, 0xD6 } },
{ "PaleGoldenRod", { 0xEE, 0xE8, 0xAA } },
{ "PaleGreen", { 0x98, 0xFB, 0x98 } },
{ "PaleTurquoise", { 0xAF, 0xEE, 0xEE } },
{ "PaleVioletRed", { 0xD8, 0x70, 0x93 } },
{ "PapayaWhip", { 0xFF, 0xEF, 0xD5 } },
{ "PeachPuff", { 0xFF, 0xDA, 0xB9 } },
{ "Peru", { 0xCD, 0x85, 0x3F } },
{ "Pink", { 0xFF, 0xC0, 0xCB } },
{ "Plum", { 0xDD, 0xA0, 0xDD } },
{ "PowderBlue", { 0xB0, 0xE0, 0xE6 } },
{ "Purple", { 0x80, 0x00, 0x80 } },
{ "Red", { 0xFF, 0x00, 0x00 } },
{ "RosyBrown", { 0xBC, 0x8F, 0x8F } },
{ "RoyalBlue", { 0x41, 0x69, 0xE1 } },
{ "SaddleBrown", { 0x8B, 0x45, 0x13 } },
{ "Salmon", { 0xFA, 0x80, 0x72 } },
{ "SandyBrown", { 0xF4, 0xA4, 0x60 } },
{ "SeaGreen", { 0x2E, 0x8B, 0x57 } },
{ "SeaShell", { 0xFF, 0xF5, 0xEE } },
{ "Sienna", { 0xA0, 0x52, 0x2D } },
{ "Silver", { 0xC0, 0xC0, 0xC0 } },
{ "SkyBlue", { 0x87, 0xCE, 0xEB } },
{ "SlateBlue", { 0x6A, 0x5A, 0xCD } },
{ "SlateGray", { 0x70, 0x80, 0x90 } },
{ "Snow", { 0xFF, 0xFA, 0xFA } },
{ "SpringGreen", { 0x00, 0xFF, 0x7F } },
{ "SteelBlue", { 0x46, 0x82, 0xB4 } },
{ "Tan", { 0xD2, 0xB4, 0x8C } },
{ "Teal", { 0x00, 0x80, 0x80 } },
{ "Thistle", { 0xD8, 0xBF, 0xD8 } },
{ "Tomato", { 0xFF, 0x63, 0x47 } },
{ "Turquoise", { 0x40, 0xE0, 0xD0 } },
{ "Violet", { 0xEE, 0x82, 0xEE } },
{ "Wheat", { 0xF5, 0xDE, 0xB3 } },
{ "White", { 0xFF, 0xFF, 0xFF } },
{ "WhiteSmoke", { 0xF5, 0xF5, 0xF5 } },
{ "Yellow", { 0xFF, 0xFF, 0x00 } },
{ "YellowGreen", { 0x9A, 0xCD, 0x32 } },
};
static int color_table_compare(const void *lhs, const void *rhs)
{
return av_strcasecmp(lhs, ((const ColorEntry *)rhs)->name);
}
#define ALPHA_SEP '@'
int av_parse_color(uint8_t *rgba_color, const char *color_string, int slen,
void *log_ctx)
{
char *tail, color_string2[128];
const ColorEntry *entry;
int len, hex_offset = 0;
if (color_string[0] == '#') {
hex_offset = 1;
} else if (!strncmp(color_string, "0x", 2))
hex_offset = 2;
if (slen < 0)
slen = strlen(color_string);
av_strlcpy(color_string2, color_string + hex_offset,
FFMIN(slen-hex_offset+1, sizeof(color_string2)));
if ((tail = strchr(color_string2, ALPHA_SEP)))
*tail++ = 0;
len = strlen(color_string2);
rgba_color[3] = 255;
if (!av_strcasecmp(color_string2, "random") || !av_strcasecmp(color_string2, "bikeshed")) {
int rgba = av_get_random_seed();
rgba_color[0] = rgba >> 24;
rgba_color[1] = rgba >> 16;
rgba_color[2] = rgba >> 8;
rgba_color[3] = rgba;
} else if (hex_offset ||
strspn(color_string2, "0123456789ABCDEFabcdef") == len) {
char *tail;
unsigned int rgba = strtoul(color_string2, &tail, 16);
if (*tail || (len != 6 && len != 8)) {
av_log(log_ctx, AV_LOG_ERROR, "Invalid 0xRRGGBB[AA] color string: '%s'\n", color_string2);
return AVERROR(EINVAL);
}
if (len == 8) {
rgba_color[3] = rgba;
rgba >>= 8;
}
rgba_color[0] = rgba >> 16;
rgba_color[1] = rgba >> 8;
rgba_color[2] = rgba;
} else {
entry = bsearch(color_string2,
color_table,
FF_ARRAY_ELEMS(color_table),
sizeof(ColorEntry),
color_table_compare);
if (!entry) {
av_log(log_ctx, AV_LOG_ERROR, "Cannot find color '%s'\n", color_string2);
return AVERROR(EINVAL);
}
memcpy(rgba_color, entry->rgb_color, 3);
}
if (tail) {
double alpha;
const char *alpha_string = tail;
if (!strncmp(alpha_string, "0x", 2)) {
alpha = strtoul(alpha_string, &tail, 16);
} else {
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) {
av_log(log_ctx, AV_LOG_ERROR, "Invalid alpha value specifier '%s' in '%s'\n",
alpha_string, color_string);
return AVERROR(EINVAL);
}
rgba_color[3] = alpha;
}
return 0;
}
/* 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,
int n_min, int n_max, int len_max)
{
int i, val, c;
const char *p;
p = *pp;
val = 0;
for(i = 0; i < len_max; i++) {
c = *p;
if (!isdigit(c))
break;
val = (val * 10) + c - '0';
p++;
}
/* no number read ? */
if (p == *pp)
return -1;
if (val < n_min || val > n_max)
return -1;
*pp = p;
return val;
}
char *av_small_strptime(const char *p, const char *fmt, struct tm *dt)
{
int c, val;
for(;;) {
/* consume time string until a non whitespace char is found */
while (isspace(*fmt)) {
while (isspace(*p))
p++;
fmt++;
}
c = *fmt++;
if (c == '\0') {
return (char *)p;
} else if (c == '%') {
c = *fmt++;
switch(c) {
case 'H':
val = date_get_num(&p, 0, 23, 2);
if (val == -1)
return NULL;
dt->tm_hour = val;
break;
case 'M':
val = date_get_num(&p, 0, 59, 2);
if (val == -1)
return NULL;
dt->tm_min = val;
break;
case 'S':
val = date_get_num(&p, 0, 59, 2);
if (val == -1)
return NULL;
dt->tm_sec = val;
break;
case 'Y':
val = date_get_num(&p, 0, 9999, 4);
if (val == -1)
return NULL;
dt->tm_year = val - 1900;
break;
case 'm':
val = date_get_num(&p, 1, 12, 2);
if (val == -1)
return NULL;
dt->tm_mon = val - 1;
break;
case 'd':
val = date_get_num(&p, 1, 31, 2);
if (val == -1)
return NULL;
dt->tm_mday = val;
break;
case '%':
goto match;
default:
return NULL;
}
} else {
match:
if (c != *p)
return NULL;
p++;
}
}
}
time_t av_timegm(struct tm *tm)
{
time_t t;
int y = tm->tm_year + 1900, m = tm->tm_mon + 1, d = tm->tm_mday;
if (m < 3) {
m += 12;
y--;
}
t = 86400 *
(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;
return t;
}
int av_parse_time(int64_t *timeval, const char *timestr, int duration)
{
const char *p, *q;
int64_t t;
time_t now;
struct tm dt = { 0 };
int today = 0, negative = 0, microseconds = 0;
int i;
static const char * const date_fmt[] = {
"%Y-%m-%d",
"%Y%m%d",
};
static const char * const time_fmt[] = {
"%H:%M:%S",
"%H%M%S",
};
p = timestr;
q = NULL;
*timeval = INT64_MIN;
if (!duration) {
now = time(0);
if (!av_strcasecmp(timestr, "now")) {
*timeval = (int64_t) now * 1000000;
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)
break;
}
/* if the year-month-day part is missing, then take the
* current year-month-day time */
if (!q) {
today = 1;
q = p;
}
p = q;
if (*p == 'T' || *p == 't' || *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)
break;
}
} else {
/* parse timestr as a duration */
if (p[0] == '-') {
negative = 1;
++p;
}
/* parse timestr as HH:MM:SS */
q = av_small_strptime(p, time_fmt[0], &dt);
if (!q) {
/* parse timestr as S+ */
dt.tm_sec = strtol(p, (void *)&q, 10);
if (q == p) /* the parsing didn't succeed */
return AVERROR(EINVAL);
dt.tm_min = 0;
dt.tm_hour = 0;
}
}
/* Now we have all the fields that we can get */
if (!q)
return AVERROR(EINVAL);
/* parse the .m... part */
if (*q == '.') {
int n;
q++;
for (n = 100000; n >= 1; n /= 10, q++) {
if (!isdigit(*q))
break;
microseconds += n * (*q - '0');
}
while (isdigit(*q))
q++;
}
if (duration) {
t = dt.tm_hour * 3600 + dt.tm_min * 60 + dt.tm_sec;
} else {
int is_utc = *q == 'Z' || *q == 'z';
q += is_utc;
if (today) { /* fill in today's date */
struct tm dt2 = is_utc ? *gmtime(&now) : *localtime(&now);
dt2.tm_hour = dt.tm_hour;
dt2.tm_min = dt.tm_min;
dt2.tm_sec = dt.tm_sec;
dt = dt2;
}
t = is_utc ? av_timegm(&dt) : mktime(&dt);
}
/* Check that we are at the end of the string */
if (*q)
return AVERROR(EINVAL);
t *= 1000000;
t += microseconds;
*timeval = negative ? -t : t;
return 0;
}
int av_find_info_tag(char *arg, int arg_size, const char *tag1, const char *info)
{
const char *p;
char tag[128], *q;
p = info;
if (*p == '?')
p++;
for(;;) {
q = tag;
while (*p != '\0' && *p != '=' && *p != '&') {
if ((q - tag) < sizeof(tag) - 1)
*q++ = *p;
p++;
}
*q = '\0';
q = arg;
if (*p == '=') {
p++;
while (*p != '&' && *p != '\0') {
if ((q - arg) < arg_size - 1) {
if (*p == '+')
*q++ = ' ';
else
*q++ = *p;
}
p++;
}
}
*q = '\0';
if (!strcmp(tag, tag1))
return 1;
if (*p != '&')
break;
p++;
}
return 0;
}
#ifdef TEST
static uint32_t random = MKTAG('L','A','V','U');
static uint32_t av_get_random_seed_deterministic(void)
{
return random = random * 1664525 + 1013904223;
}
#undef printf
int main(void)
{
printf("Testing av_parse_video_rate()\n");
{
int i;
const char *rates[] = {
"-inf",
"inf",
"nan",
"123/0",
"-123 / 0",
"",
"/",
" 123 / 321",
"foo/foo",
"foo/1",
"1/foo",
"0/0",
"/0",
"1/",
"1",
"0",
"-123/123",
"-foo",
"123.23",
".23",
"-.23",
"-0.234",
"-0.0000001",
" 21332.2324 ",
" -21332.2324 ",
};
for (i = 0; i < FF_ARRAY_ELEMS(rates); i++) {
int ret;
AVRational q = (AVRational){0, 0};
ret = av_parse_video_rate(&q, rates[i]);
printf("'%s' -> %d/%d%s\n",
rates[i], q.num, q.den, ret ? " error" : "");
}
}
printf("\nTesting av_parse_color()\n");
{
int i;
uint8_t rgba[4];
const char *color_names[] = {
"bikeshed",
"RaNdOm",
"foo",
"red",
"Red ",
"RED",
"Violet",
"Yellow",
"Red",
"0x000000",
"0x0000000",
"0xff000000",
"0x3e34ff",
"0x3e34ffaa",
"0xffXXee",
"0xfoobar",
"0xffffeeeeeeee",
"#ff0000",
"#ffXX00",
"ff0000",
"ffXX00",
"red@foo",
"random@10",
"0xff0000@1.0",
"red@",
"red@0xfff",
"red@0xf",
"red@2",
"red@0.1",
"red@-1",
"red@0.5",
"red@1.0",
"red@256",
"red@10foo",
"red@-1.0",
"red@-0.0",
};
av_log_set_level(AV_LOG_DEBUG);
for (i = 0; i < FF_ARRAY_ELEMS(color_names); i++) {
if (av_parse_color(rgba, color_names[i], -1, NULL) >= 0)
printf("%s -> R(%d) G(%d) B(%d) A(%d)\n", color_names[i], rgba[0], rgba[1], rgba[2], rgba[3]);
else
printf("%s -> error\n", color_names[i]);
}
}
printf("\nTesting av_small_strptime()\n");
{
int i;
struct tm tm = { 0 };
struct fmt_timespec_entry {
const char *fmt, *timespec;
} fmt_timespec_entries[] = {
{ "%Y-%m-%d", "2012-12-21" },
{ "%Y - %m - %d", "2012-12-21" },
{ "%Y-%m-%d %H:%M:%S", "2012-12-21 20:12:21" },
{ " %Y - %m - %d %H : %M : %S", " 2012 - 12 - 21 20 : 12 : 21" },
};
av_log_set_level(AV_LOG_DEBUG);
for (i = 0; i < FF_ARRAY_ELEMS(fmt_timespec_entries); i++) {
char *p;
struct fmt_timespec_entry *e = &fmt_timespec_entries[i];
printf("fmt:'%s' spec:'%s' -> ", e->fmt, e->timespec);
p = av_small_strptime(e->timespec, e->fmt, &tm);
if (p) {
printf("%04d-%02d-%2d %02d:%02d:%02d\n",
1900+tm.tm_year, tm.tm_mon+1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec);
} else {
printf("error\n");
}
}
}
printf("\nTesting av_parse_time()\n");
{
int i;
int64_t tv;
time_t tvi;
struct tm *tm;
static char tzstr[] = "TZ=CET-1";
const char *time_string[] = {
"now",
"12:35:46",
"2000-12-20 0:02:47.5z",
"2000-12-20T010247.6",
};
const char *duration_string[] = {
"2:34:56.79",
"-1:23:45.67",
"42.1729",
"-1729.42",
"12:34",
};
av_log_set_level(AV_LOG_DEBUG);
putenv(tzstr);
printf("(now is 2012-03-17 09:14:13 +0100, local time is UTC+1)\n");
for (i = 0; i < FF_ARRAY_ELEMS(time_string); i++) {
printf("%-24s -> ", time_string[i]);
if (av_parse_time(&tv, time_string[i], 0)) {
printf("error\n");
} else {
tvi = tv / 1000000;
tm = gmtime(&tvi);
printf("%14"PRIi64".%06d = %04d-%02d-%02dT%02d:%02d:%02dZ\n",
tv / 1000000, (int)(tv % 1000000),
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
}
}
for (i = 0; i < FF_ARRAY_ELEMS(duration_string); i++) {
printf("%-24s -> ", duration_string[i]);
if (av_parse_time(&tv, duration_string[i], 1)) {
printf("error\n");
} else {
printf("%+21"PRIi64"\n", tv);
}
}
}
return 0;
}
#endif /* TEST */
Jump to Line
Something went wrong with that request. Please try again.