00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00024 #include <time.h>
00025
00026 #include "avstring.h"
00027 #include "avutil.h"
00028 #include "common.h"
00029 #include "eval.h"
00030 #include "log.h"
00031 #include "random_seed.h"
00032 #include "parseutils.h"
00033
00034 #undef time
00035
00036 #ifdef TEST
00037
00038 #define av_get_random_seed av_get_random_seed_deterministic
00039 static uint32_t av_get_random_seed_deterministic(void);
00040
00041 #define time(t) 1331972053
00042
00043 #endif
00044
00045 int av_parse_ratio(AVRational *q, const char *str, int max,
00046 int log_offset, void *log_ctx)
00047 {
00048 char c;
00049 int ret;
00050 int64_t gcd;
00051
00052 if (sscanf(str, "%d:%d%c", &q->num, &q->den, &c) != 2) {
00053 double d;
00054 ret = av_expr_parse_and_eval(&d, str, NULL, NULL,
00055 NULL, NULL, NULL, NULL,
00056 NULL, log_offset, log_ctx);
00057 if (ret < 0)
00058 return ret;
00059 *q = av_d2q(d, max);
00060 }
00061
00062 gcd = av_gcd(FFABS(q->num), FFABS(q->den));
00063 if (gcd) {
00064 q->num /= gcd;
00065 q->den /= gcd;
00066 }
00067
00068 return 0;
00069 }
00070
00071 typedef struct {
00072 const char *abbr;
00073 int width, height;
00074 } VideoSizeAbbr;
00075
00076 typedef struct {
00077 const char *abbr;
00078 AVRational rate;
00079 } VideoRateAbbr;
00080
00081 static const VideoSizeAbbr video_size_abbrs[] = {
00082 { "ntsc", 720, 480 },
00083 { "pal", 720, 576 },
00084 { "qntsc", 352, 240 },
00085 { "qpal", 352, 288 },
00086 { "sntsc", 640, 480 },
00087 { "spal", 768, 576 },
00088 { "film", 352, 240 },
00089 { "ntsc-film", 352, 240 },
00090 { "sqcif", 128, 96 },
00091 { "qcif", 176, 144 },
00092 { "cif", 352, 288 },
00093 { "4cif", 704, 576 },
00094 { "16cif", 1408,1152 },
00095 { "qqvga", 160, 120 },
00096 { "qvga", 320, 240 },
00097 { "vga", 640, 480 },
00098 { "svga", 800, 600 },
00099 { "xga", 1024, 768 },
00100 { "uxga", 1600,1200 },
00101 { "qxga", 2048,1536 },
00102 { "sxga", 1280,1024 },
00103 { "qsxga", 2560,2048 },
00104 { "hsxga", 5120,4096 },
00105 { "wvga", 852, 480 },
00106 { "wxga", 1366, 768 },
00107 { "wsxga", 1600,1024 },
00108 { "wuxga", 1920,1200 },
00109 { "woxga", 2560,1600 },
00110 { "wqsxga", 3200,2048 },
00111 { "wquxga", 3840,2400 },
00112 { "whsxga", 6400,4096 },
00113 { "whuxga", 7680,4800 },
00114 { "cga", 320, 200 },
00115 { "ega", 640, 350 },
00116 { "hd480", 852, 480 },
00117 { "hd720", 1280, 720 },
00118 { "hd1080", 1920,1080 },
00119 };
00120
00121 static const VideoRateAbbr video_rate_abbrs[]= {
00122 { "ntsc", { 30000, 1001 } },
00123 { "pal", { 25, 1 } },
00124 { "qntsc", { 30000, 1001 } },
00125 { "qpal", { 25, 1 } },
00126 { "sntsc", { 30000, 1001 } },
00127 { "spal", { 25, 1 } },
00128 { "film", { 24, 1 } },
00129 { "ntsc-film", { 24000, 1001 } },
00130 };
00131
00132 int av_parse_video_size(int *width_ptr, int *height_ptr, const char *str)
00133 {
00134 int i;
00135 int n = FF_ARRAY_ELEMS(video_size_abbrs);
00136 const char *p;
00137 int width = 0, height = 0;
00138
00139 for (i = 0; i < n; i++) {
00140 if (!strcmp(video_size_abbrs[i].abbr, str)) {
00141 width = video_size_abbrs[i].width;
00142 height = video_size_abbrs[i].height;
00143 break;
00144 }
00145 }
00146 if (i == n) {
00147 p = str;
00148 width = strtol(p, (void*)&p, 10);
00149 if (*p)
00150 p++;
00151 height = strtol(p, (void*)&p, 10);
00152 }
00153 if (width <= 0 || height <= 0)
00154 return AVERROR(EINVAL);
00155 *width_ptr = width;
00156 *height_ptr = height;
00157 return 0;
00158 }
00159
00160 int av_parse_video_rate(AVRational *rate, const char *arg)
00161 {
00162 int i, ret;
00163 int n = FF_ARRAY_ELEMS(video_rate_abbrs);
00164
00165
00166 for (i = 0; i < n; ++i)
00167 if (!strcmp(video_rate_abbrs[i].abbr, arg)) {
00168 *rate = video_rate_abbrs[i].rate;
00169 return 0;
00170 }
00171
00172
00173 if ((ret = av_parse_ratio_quiet(rate, arg, 1001000)) < 0)
00174 return ret;
00175 if (rate->num <= 0 || rate->den <= 0)
00176 return AVERROR(EINVAL);
00177 return 0;
00178 }
00179
00180 typedef struct {
00181 const char *name;
00182 uint8_t rgb_color[3];
00183 } ColorEntry;
00184
00185 static const ColorEntry color_table[] = {
00186 { "AliceBlue", { 0xF0, 0xF8, 0xFF } },
00187 { "AntiqueWhite", { 0xFA, 0xEB, 0xD7 } },
00188 { "Aqua", { 0x00, 0xFF, 0xFF } },
00189 { "Aquamarine", { 0x7F, 0xFF, 0xD4 } },
00190 { "Azure", { 0xF0, 0xFF, 0xFF } },
00191 { "Beige", { 0xF5, 0xF5, 0xDC } },
00192 { "Bisque", { 0xFF, 0xE4, 0xC4 } },
00193 { "Black", { 0x00, 0x00, 0x00 } },
00194 { "BlanchedAlmond", { 0xFF, 0xEB, 0xCD } },
00195 { "Blue", { 0x00, 0x00, 0xFF } },
00196 { "BlueViolet", { 0x8A, 0x2B, 0xE2 } },
00197 { "Brown", { 0xA5, 0x2A, 0x2A } },
00198 { "BurlyWood", { 0xDE, 0xB8, 0x87 } },
00199 { "CadetBlue", { 0x5F, 0x9E, 0xA0 } },
00200 { "Chartreuse", { 0x7F, 0xFF, 0x00 } },
00201 { "Chocolate", { 0xD2, 0x69, 0x1E } },
00202 { "Coral", { 0xFF, 0x7F, 0x50 } },
00203 { "CornflowerBlue", { 0x64, 0x95, 0xED } },
00204 { "Cornsilk", { 0xFF, 0xF8, 0xDC } },
00205 { "Crimson", { 0xDC, 0x14, 0x3C } },
00206 { "Cyan", { 0x00, 0xFF, 0xFF } },
00207 { "DarkBlue", { 0x00, 0x00, 0x8B } },
00208 { "DarkCyan", { 0x00, 0x8B, 0x8B } },
00209 { "DarkGoldenRod", { 0xB8, 0x86, 0x0B } },
00210 { "DarkGray", { 0xA9, 0xA9, 0xA9 } },
00211 { "DarkGreen", { 0x00, 0x64, 0x00 } },
00212 { "DarkKhaki", { 0xBD, 0xB7, 0x6B } },
00213 { "DarkMagenta", { 0x8B, 0x00, 0x8B } },
00214 { "DarkOliveGreen", { 0x55, 0x6B, 0x2F } },
00215 { "Darkorange", { 0xFF, 0x8C, 0x00 } },
00216 { "DarkOrchid", { 0x99, 0x32, 0xCC } },
00217 { "DarkRed", { 0x8B, 0x00, 0x00 } },
00218 { "DarkSalmon", { 0xE9, 0x96, 0x7A } },
00219 { "DarkSeaGreen", { 0x8F, 0xBC, 0x8F } },
00220 { "DarkSlateBlue", { 0x48, 0x3D, 0x8B } },
00221 { "DarkSlateGray", { 0x2F, 0x4F, 0x4F } },
00222 { "DarkTurquoise", { 0x00, 0xCE, 0xD1 } },
00223 { "DarkViolet", { 0x94, 0x00, 0xD3 } },
00224 { "DeepPink", { 0xFF, 0x14, 0x93 } },
00225 { "DeepSkyBlue", { 0x00, 0xBF, 0xFF } },
00226 { "DimGray", { 0x69, 0x69, 0x69 } },
00227 { "DodgerBlue", { 0x1E, 0x90, 0xFF } },
00228 { "FireBrick", { 0xB2, 0x22, 0x22 } },
00229 { "FloralWhite", { 0xFF, 0xFA, 0xF0 } },
00230 { "ForestGreen", { 0x22, 0x8B, 0x22 } },
00231 { "Fuchsia", { 0xFF, 0x00, 0xFF } },
00232 { "Gainsboro", { 0xDC, 0xDC, 0xDC } },
00233 { "GhostWhite", { 0xF8, 0xF8, 0xFF } },
00234 { "Gold", { 0xFF, 0xD7, 0x00 } },
00235 { "GoldenRod", { 0xDA, 0xA5, 0x20 } },
00236 { "Gray", { 0x80, 0x80, 0x80 } },
00237 { "Green", { 0x00, 0x80, 0x00 } },
00238 { "GreenYellow", { 0xAD, 0xFF, 0x2F } },
00239 { "HoneyDew", { 0xF0, 0xFF, 0xF0 } },
00240 { "HotPink", { 0xFF, 0x69, 0xB4 } },
00241 { "IndianRed", { 0xCD, 0x5C, 0x5C } },
00242 { "Indigo", { 0x4B, 0x00, 0x82 } },
00243 { "Ivory", { 0xFF, 0xFF, 0xF0 } },
00244 { "Khaki", { 0xF0, 0xE6, 0x8C } },
00245 { "Lavender", { 0xE6, 0xE6, 0xFA } },
00246 { "LavenderBlush", { 0xFF, 0xF0, 0xF5 } },
00247 { "LawnGreen", { 0x7C, 0xFC, 0x00 } },
00248 { "LemonChiffon", { 0xFF, 0xFA, 0xCD } },
00249 { "LightBlue", { 0xAD, 0xD8, 0xE6 } },
00250 { "LightCoral", { 0xF0, 0x80, 0x80 } },
00251 { "LightCyan", { 0xE0, 0xFF, 0xFF } },
00252 { "LightGoldenRodYellow", { 0xFA, 0xFA, 0xD2 } },
00253 { "LightGreen", { 0x90, 0xEE, 0x90 } },
00254 { "LightGrey", { 0xD3, 0xD3, 0xD3 } },
00255 { "LightPink", { 0xFF, 0xB6, 0xC1 } },
00256 { "LightSalmon", { 0xFF, 0xA0, 0x7A } },
00257 { "LightSeaGreen", { 0x20, 0xB2, 0xAA } },
00258 { "LightSkyBlue", { 0x87, 0xCE, 0xFA } },
00259 { "LightSlateGray", { 0x77, 0x88, 0x99 } },
00260 { "LightSteelBlue", { 0xB0, 0xC4, 0xDE } },
00261 { "LightYellow", { 0xFF, 0xFF, 0xE0 } },
00262 { "Lime", { 0x00, 0xFF, 0x00 } },
00263 { "LimeGreen", { 0x32, 0xCD, 0x32 } },
00264 { "Linen", { 0xFA, 0xF0, 0xE6 } },
00265 { "Magenta", { 0xFF, 0x00, 0xFF } },
00266 { "Maroon", { 0x80, 0x00, 0x00 } },
00267 { "MediumAquaMarine", { 0x66, 0xCD, 0xAA } },
00268 { "MediumBlue", { 0x00, 0x00, 0xCD } },
00269 { "MediumOrchid", { 0xBA, 0x55, 0xD3 } },
00270 { "MediumPurple", { 0x93, 0x70, 0xD8 } },
00271 { "MediumSeaGreen", { 0x3C, 0xB3, 0x71 } },
00272 { "MediumSlateBlue", { 0x7B, 0x68, 0xEE } },
00273 { "MediumSpringGreen", { 0x00, 0xFA, 0x9A } },
00274 { "MediumTurquoise", { 0x48, 0xD1, 0xCC } },
00275 { "MediumVioletRed", { 0xC7, 0x15, 0x85 } },
00276 { "MidnightBlue", { 0x19, 0x19, 0x70 } },
00277 { "MintCream", { 0xF5, 0xFF, 0xFA } },
00278 { "MistyRose", { 0xFF, 0xE4, 0xE1 } },
00279 { "Moccasin", { 0xFF, 0xE4, 0xB5 } },
00280 { "NavajoWhite", { 0xFF, 0xDE, 0xAD } },
00281 { "Navy", { 0x00, 0x00, 0x80 } },
00282 { "OldLace", { 0xFD, 0xF5, 0xE6 } },
00283 { "Olive", { 0x80, 0x80, 0x00 } },
00284 { "OliveDrab", { 0x6B, 0x8E, 0x23 } },
00285 { "Orange", { 0xFF, 0xA5, 0x00 } },
00286 { "OrangeRed", { 0xFF, 0x45, 0x00 } },
00287 { "Orchid", { 0xDA, 0x70, 0xD6 } },
00288 { "PaleGoldenRod", { 0xEE, 0xE8, 0xAA } },
00289 { "PaleGreen", { 0x98, 0xFB, 0x98 } },
00290 { "PaleTurquoise", { 0xAF, 0xEE, 0xEE } },
00291 { "PaleVioletRed", { 0xD8, 0x70, 0x93 } },
00292 { "PapayaWhip", { 0xFF, 0xEF, 0xD5 } },
00293 { "PeachPuff", { 0xFF, 0xDA, 0xB9 } },
00294 { "Peru", { 0xCD, 0x85, 0x3F } },
00295 { "Pink", { 0xFF, 0xC0, 0xCB } },
00296 { "Plum", { 0xDD, 0xA0, 0xDD } },
00297 { "PowderBlue", { 0xB0, 0xE0, 0xE6 } },
00298 { "Purple", { 0x80, 0x00, 0x80 } },
00299 { "Red", { 0xFF, 0x00, 0x00 } },
00300 { "RosyBrown", { 0xBC, 0x8F, 0x8F } },
00301 { "RoyalBlue", { 0x41, 0x69, 0xE1 } },
00302 { "SaddleBrown", { 0x8B, 0x45, 0x13 } },
00303 { "Salmon", { 0xFA, 0x80, 0x72 } },
00304 { "SandyBrown", { 0xF4, 0xA4, 0x60 } },
00305 { "SeaGreen", { 0x2E, 0x8B, 0x57 } },
00306 { "SeaShell", { 0xFF, 0xF5, 0xEE } },
00307 { "Sienna", { 0xA0, 0x52, 0x2D } },
00308 { "Silver", { 0xC0, 0xC0, 0xC0 } },
00309 { "SkyBlue", { 0x87, 0xCE, 0xEB } },
00310 { "SlateBlue", { 0x6A, 0x5A, 0xCD } },
00311 { "SlateGray", { 0x70, 0x80, 0x90 } },
00312 { "Snow", { 0xFF, 0xFA, 0xFA } },
00313 { "SpringGreen", { 0x00, 0xFF, 0x7F } },
00314 { "SteelBlue", { 0x46, 0x82, 0xB4 } },
00315 { "Tan", { 0xD2, 0xB4, 0x8C } },
00316 { "Teal", { 0x00, 0x80, 0x80 } },
00317 { "Thistle", { 0xD8, 0xBF, 0xD8 } },
00318 { "Tomato", { 0xFF, 0x63, 0x47 } },
00319 { "Turquoise", { 0x40, 0xE0, 0xD0 } },
00320 { "Violet", { 0xEE, 0x82, 0xEE } },
00321 { "Wheat", { 0xF5, 0xDE, 0xB3 } },
00322 { "White", { 0xFF, 0xFF, 0xFF } },
00323 { "WhiteSmoke", { 0xF5, 0xF5, 0xF5 } },
00324 { "Yellow", { 0xFF, 0xFF, 0x00 } },
00325 { "YellowGreen", { 0x9A, 0xCD, 0x32 } },
00326 };
00327
00328 static int color_table_compare(const void *lhs, const void *rhs)
00329 {
00330 return av_strcasecmp(lhs, ((const ColorEntry *)rhs)->name);
00331 }
00332
00333 #define ALPHA_SEP '@'
00334
00335 int av_parse_color(uint8_t *rgba_color, const char *color_string, int slen,
00336 void *log_ctx)
00337 {
00338 char *tail, color_string2[128];
00339 const ColorEntry *entry;
00340 int len, hex_offset = 0;
00341
00342 if (color_string[0] == '#') {
00343 hex_offset = 1;
00344 } else if (!strncmp(color_string, "0x", 2))
00345 hex_offset = 2;
00346
00347 if (slen < 0)
00348 slen = strlen(color_string);
00349 av_strlcpy(color_string2, color_string + hex_offset,
00350 FFMIN(slen-hex_offset+1, sizeof(color_string2)));
00351 if ((tail = strchr(color_string2, ALPHA_SEP)))
00352 *tail++ = 0;
00353 len = strlen(color_string2);
00354 rgba_color[3] = 255;
00355
00356 if (!av_strcasecmp(color_string2, "random") || !av_strcasecmp(color_string2, "bikeshed")) {
00357 int rgba = av_get_random_seed();
00358 rgba_color[0] = rgba >> 24;
00359 rgba_color[1] = rgba >> 16;
00360 rgba_color[2] = rgba >> 8;
00361 rgba_color[3] = rgba;
00362 } else if (hex_offset ||
00363 strspn(color_string2, "0123456789ABCDEFabcdef") == len) {
00364 char *tail;
00365 unsigned int rgba = strtoul(color_string2, &tail, 16);
00366
00367 if (*tail || (len != 6 && len != 8)) {
00368 av_log(log_ctx, AV_LOG_ERROR, "Invalid 0xRRGGBB[AA] color string: '%s'\n", color_string2);
00369 return AVERROR(EINVAL);
00370 }
00371 if (len == 8) {
00372 rgba_color[3] = rgba;
00373 rgba >>= 8;
00374 }
00375 rgba_color[0] = rgba >> 16;
00376 rgba_color[1] = rgba >> 8;
00377 rgba_color[2] = rgba;
00378 } else {
00379 entry = bsearch(color_string2,
00380 color_table,
00381 FF_ARRAY_ELEMS(color_table),
00382 sizeof(ColorEntry),
00383 color_table_compare);
00384 if (!entry) {
00385 av_log(log_ctx, AV_LOG_ERROR, "Cannot find color '%s'\n", color_string2);
00386 return AVERROR(EINVAL);
00387 }
00388 memcpy(rgba_color, entry->rgb_color, 3);
00389 }
00390
00391 if (tail) {
00392 unsigned long int alpha;
00393 const char *alpha_string = tail;
00394 if (!strncmp(alpha_string, "0x", 2)) {
00395 alpha = strtoul(alpha_string, &tail, 16);
00396 } else {
00397 double norm_alpha = strtod(alpha_string, &tail);
00398 if (norm_alpha < 0.0 || norm_alpha > 1.0)
00399 alpha = 256;
00400 else
00401 alpha = 255 * norm_alpha;
00402 }
00403
00404 if (tail == alpha_string || *tail || alpha > 255) {
00405 av_log(log_ctx, AV_LOG_ERROR, "Invalid alpha value specifier '%s' in '%s'\n",
00406 alpha_string, color_string);
00407 return AVERROR(EINVAL);
00408 }
00409 rgba_color[3] = alpha;
00410 }
00411
00412 return 0;
00413 }
00414
00415
00416
00417 static int date_get_num(const char **pp,
00418 int n_min, int n_max, int len_max)
00419 {
00420 int i, val, c;
00421 const char *p;
00422
00423 p = *pp;
00424 val = 0;
00425 for(i = 0; i < len_max; i++) {
00426 c = *p;
00427 if (!isdigit(c))
00428 break;
00429 val = (val * 10) + c - '0';
00430 p++;
00431 }
00432
00433 if (p == *pp)
00434 return -1;
00435 if (val < n_min || val > n_max)
00436 return -1;
00437 *pp = p;
00438 return val;
00439 }
00440
00441 char *av_small_strptime(const char *p, const char *fmt, struct tm *dt)
00442 {
00443 int c, val;
00444
00445 for(;;) {
00446
00447 while (isspace(*fmt)) {
00448 while (isspace(*p))
00449 p++;
00450 fmt++;
00451 }
00452 c = *fmt++;
00453 if (c == '\0') {
00454 return (char *)p;
00455 } else if (c == '%') {
00456 c = *fmt++;
00457 switch(c) {
00458 case 'H':
00459 val = date_get_num(&p, 0, 23, 2);
00460 if (val == -1)
00461 return NULL;
00462 dt->tm_hour = val;
00463 break;
00464 case 'M':
00465 val = date_get_num(&p, 0, 59, 2);
00466 if (val == -1)
00467 return NULL;
00468 dt->tm_min = val;
00469 break;
00470 case 'S':
00471 val = date_get_num(&p, 0, 59, 2);
00472 if (val == -1)
00473 return NULL;
00474 dt->tm_sec = val;
00475 break;
00476 case 'Y':
00477 val = date_get_num(&p, 0, 9999, 4);
00478 if (val == -1)
00479 return NULL;
00480 dt->tm_year = val - 1900;
00481 break;
00482 case 'm':
00483 val = date_get_num(&p, 1, 12, 2);
00484 if (val == -1)
00485 return NULL;
00486 dt->tm_mon = val - 1;
00487 break;
00488 case 'd':
00489 val = date_get_num(&p, 1, 31, 2);
00490 if (val == -1)
00491 return NULL;
00492 dt->tm_mday = val;
00493 break;
00494 case '%':
00495 goto match;
00496 default:
00497 return NULL;
00498 }
00499 } else {
00500 match:
00501 if (c != *p)
00502 return NULL;
00503 p++;
00504 }
00505 }
00506 }
00507
00508 time_t av_timegm(struct tm *tm)
00509 {
00510 time_t t;
00511
00512 int y = tm->tm_year + 1900, m = tm->tm_mon + 1, d = tm->tm_mday;
00513
00514 if (m < 3) {
00515 m += 12;
00516 y--;
00517 }
00518
00519 t = 86400 *
00520 (d + (153 * m - 457) / 5 + 365 * y + y / 4 - y / 100 + y / 400 - 719469);
00521
00522 t += 3600 * tm->tm_hour + 60 * tm->tm_min + tm->tm_sec;
00523
00524 return t;
00525 }
00526
00527 int av_parse_time(int64_t *timeval, const char *timestr, int duration)
00528 {
00529 const char *p, *q;
00530 int64_t t;
00531 time_t now;
00532 struct tm dt = { 0 };
00533 int today = 0, negative = 0, microseconds = 0;
00534 int i;
00535 static const char * const date_fmt[] = {
00536 "%Y-%m-%d",
00537 "%Y%m%d",
00538 };
00539 static const char * const time_fmt[] = {
00540 "%H:%M:%S",
00541 "%H%M%S",
00542 };
00543
00544 p = timestr;
00545 q = NULL;
00546 *timeval = INT64_MIN;
00547 if (!duration) {
00548 now = time(0);
00549
00550 if (!av_strcasecmp(timestr, "now")) {
00551 *timeval = (int64_t) now * 1000000;
00552 return 0;
00553 }
00554
00555
00556 for (i = 0; i < FF_ARRAY_ELEMS(date_fmt); i++) {
00557 q = av_small_strptime(p, date_fmt[i], &dt);
00558 if (q)
00559 break;
00560 }
00561
00562
00563
00564 if (!q) {
00565 today = 1;
00566 q = p;
00567 }
00568 p = q;
00569
00570 if (*p == 'T' || *p == 't' || *p == ' ')
00571 p++;
00572
00573
00574 for (i = 0; i < FF_ARRAY_ELEMS(time_fmt); i++) {
00575 q = av_small_strptime(p, time_fmt[i], &dt);
00576 if (q)
00577 break;
00578 }
00579 } else {
00580
00581 if (p[0] == '-') {
00582 negative = 1;
00583 ++p;
00584 }
00585
00586 q = av_small_strptime(p, time_fmt[0], &dt);
00587 if (!q) {
00588
00589 dt.tm_sec = strtol(p, (void *)&q, 10);
00590 if (q == p)
00591 return AVERROR(EINVAL);
00592 dt.tm_min = 0;
00593 dt.tm_hour = 0;
00594 }
00595 }
00596
00597
00598 if (!q)
00599 return AVERROR(EINVAL);
00600
00601
00602 if (*q == '.') {
00603 int n;
00604 q++;
00605 for (n = 100000; n >= 1; n /= 10, q++) {
00606 if (!isdigit(*q))
00607 break;
00608 microseconds += n * (*q - '0');
00609 }
00610 while (isdigit(*q))
00611 q++;
00612 }
00613
00614 if (duration) {
00615 t = dt.tm_hour * 3600 + dt.tm_min * 60 + dt.tm_sec;
00616 } else {
00617 int is_utc = *q == 'Z' || *q == 'z';
00618 q += is_utc;
00619 if (today) {
00620 struct tm dt2 = is_utc ? *gmtime(&now) : *localtime(&now);
00621 dt2.tm_hour = dt.tm_hour;
00622 dt2.tm_min = dt.tm_min;
00623 dt2.tm_sec = dt.tm_sec;
00624 dt = dt2;
00625 }
00626 t = is_utc ? av_timegm(&dt) : mktime(&dt);
00627 }
00628
00629
00630 if (*q)
00631 return AVERROR(EINVAL);
00632
00633 t *= 1000000;
00634 t += microseconds;
00635 *timeval = negative ? -t : t;
00636 return 0;
00637 }
00638
00639 int av_find_info_tag(char *arg, int arg_size, const char *tag1, const char *info)
00640 {
00641 const char *p;
00642 char tag[128], *q;
00643
00644 p = info;
00645 if (*p == '?')
00646 p++;
00647 for(;;) {
00648 q = tag;
00649 while (*p != '\0' && *p != '=' && *p != '&') {
00650 if ((q - tag) < sizeof(tag) - 1)
00651 *q++ = *p;
00652 p++;
00653 }
00654 *q = '\0';
00655 q = arg;
00656 if (*p == '=') {
00657 p++;
00658 while (*p != '&' && *p != '\0') {
00659 if ((q - arg) < arg_size - 1) {
00660 if (*p == '+')
00661 *q++ = ' ';
00662 else
00663 *q++ = *p;
00664 }
00665 p++;
00666 }
00667 }
00668 *q = '\0';
00669 if (!strcmp(tag, tag1))
00670 return 1;
00671 if (*p != '&')
00672 break;
00673 p++;
00674 }
00675 return 0;
00676 }
00677
00678 #ifdef TEST
00679
00680 static uint32_t random = MKTAG('L','A','V','U');
00681
00682 static uint32_t av_get_random_seed_deterministic(void)
00683 {
00684 return random = random * 1664525 + 1013904223;
00685 }
00686
00687 #undef printf
00688
00689 int main(void)
00690 {
00691 printf("Testing av_parse_video_rate()\n");
00692 {
00693 int i;
00694 const char *rates[] = {
00695 "-inf",
00696 "inf",
00697 "nan",
00698 "123/0",
00699 "-123 / 0",
00700 "",
00701 "/",
00702 " 123 / 321",
00703 "foo/foo",
00704 "foo/1",
00705 "1/foo",
00706 "0/0",
00707 "/0",
00708 "1/",
00709 "1",
00710 "0",
00711 "-123/123",
00712 "-foo",
00713 "123.23",
00714 ".23",
00715 "-.23",
00716 "-0.234",
00717 "-0.0000001",
00718 " 21332.2324 ",
00719 " -21332.2324 ",
00720 };
00721
00722 for (i = 0; i < FF_ARRAY_ELEMS(rates); i++) {
00723 int ret;
00724 AVRational q = (AVRational){0, 0};
00725 ret = av_parse_video_rate(&q, rates[i]);
00726 printf("'%s' -> %d/%d%s\n",
00727 rates[i], q.num, q.den, ret ? " error" : "");
00728 }
00729 }
00730
00731 printf("\nTesting av_parse_color()\n");
00732 {
00733 int i;
00734 uint8_t rgba[4];
00735 const char *color_names[] = {
00736 "bikeshed",
00737 "RaNdOm",
00738 "foo",
00739 "red",
00740 "Red ",
00741 "RED",
00742 "Violet",
00743 "Yellow",
00744 "Red",
00745 "0x000000",
00746 "0x0000000",
00747 "0xff000000",
00748 "0x3e34ff",
00749 "0x3e34ffaa",
00750 "0xffXXee",
00751 "0xfoobar",
00752 "0xffffeeeeeeee",
00753 "#ff0000",
00754 "#ffXX00",
00755 "ff0000",
00756 "ffXX00",
00757 "red@foo",
00758 "random@10",
00759 "0xff0000@1.0",
00760 "red@",
00761 "red@0xfff",
00762 "red@0xf",
00763 "red@2",
00764 "red@0.1",
00765 "red@-1",
00766 "red@0.5",
00767 "red@1.0",
00768 "red@256",
00769 "red@10foo",
00770 "red@-1.0",
00771 "red@-0.0",
00772 };
00773
00774 av_log_set_level(AV_LOG_DEBUG);
00775
00776 for (i = 0; i < FF_ARRAY_ELEMS(color_names); i++) {
00777 if (av_parse_color(rgba, color_names[i], -1, NULL) >= 0)
00778 printf("%s -> R(%d) G(%d) B(%d) A(%d)\n", color_names[i], rgba[0], rgba[1], rgba[2], rgba[3]);
00779 else
00780 printf("%s -> error\n", color_names[i]);
00781 }
00782 }
00783
00784 printf("\nTesting av_small_strptime()\n");
00785 {
00786 int i;
00787 struct tm tm = { 0 };
00788 struct fmt_timespec_entry {
00789 const char *fmt, *timespec;
00790 } fmt_timespec_entries[] = {
00791 { "%Y-%m-%d", "2012-12-21" },
00792 { "%Y - %m - %d", "2012-12-21" },
00793 { "%Y-%m-%d %H:%M:%S", "2012-12-21 20:12:21" },
00794 { " %Y - %m - %d %H : %M : %S", " 2012 - 12 - 21 20 : 12 : 21" },
00795 };
00796
00797 av_log_set_level(AV_LOG_DEBUG);
00798 for (i = 0; i < FF_ARRAY_ELEMS(fmt_timespec_entries); i++) {
00799 char *p;
00800 struct fmt_timespec_entry *e = &fmt_timespec_entries[i];
00801 printf("fmt:'%s' spec:'%s' -> ", e->fmt, e->timespec);
00802 p = av_small_strptime(e->timespec, e->fmt, &tm);
00803 if (p) {
00804 printf("%04d-%02d-%2d %02d:%02d:%02d\n",
00805 1900+tm.tm_year, tm.tm_mon+1, tm.tm_mday,
00806 tm.tm_hour, tm.tm_min, tm.tm_sec);
00807 } else {
00808 printf("error\n");
00809 }
00810 }
00811 }
00812
00813 printf("\nTesting av_parse_time()\n");
00814 {
00815 int i;
00816 int64_t tv;
00817 time_t tvi;
00818 struct tm *tm;
00819 static char tzstr[] = "TZ=CET-1";
00820 const char *time_string[] = {
00821 "now",
00822 "12:35:46",
00823 "2000-12-20 0:02:47.5z",
00824 "2000-12-20T010247.6",
00825 };
00826 const char *duration_string[] = {
00827 "2:34:56.79",
00828 "-1:23:45.67",
00829 "42.1729",
00830 "-1729.42",
00831 "12:34",
00832 };
00833
00834 av_log_set_level(AV_LOG_DEBUG);
00835 putenv(tzstr);
00836 printf("(now is 2012-03-17 09:14:13 +0100, local time is UTC+1)\n");
00837 for (i = 0; i < FF_ARRAY_ELEMS(time_string); i++) {
00838 printf("%-24s -> ", time_string[i]);
00839 if (av_parse_time(&tv, time_string[i], 0)) {
00840 printf("error\n");
00841 } else {
00842 tvi = tv / 1000000;
00843 tm = gmtime(&tvi);
00844 printf("%14"PRIi64".%06d = %04d-%02d-%02dT%02d:%02d:%02dZ\n",
00845 tv / 1000000, (int)(tv % 1000000),
00846 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
00847 tm->tm_hour, tm->tm_min, tm->tm_sec);
00848 }
00849 }
00850 for (i = 0; i < FF_ARRAY_ELEMS(duration_string); i++) {
00851 printf("%-24s -> ", duration_string[i]);
00852 if (av_parse_time(&tv, duration_string[i], 1)) {
00853 printf("error\n");
00854 } else {
00855 printf("%+21"PRIi64"\n", tv);
00856 }
00857 }
00858 }
00859
00860 return 0;
00861 }
00862
00863 #endif