00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00024 #include <sys/time.h>
00025 #include <time.h>
00026
00027 #include "avstring.h"
00028 #include "avutil.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 { "LightGrey", { 0xD3, 0xD3, 0xD3 } },
00254 { "LightGreen", { 0x90, 0xEE, 0x90 } },
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
00451 static const char *small_strptime(const char *p, const char *fmt, struct tm *dt)
00452 {
00453 int c, val;
00454
00455 for(;;) {
00456 c = *fmt++;
00457 if (c == '\0') {
00458 return p;
00459 } else if (c == '%') {
00460 c = *fmt++;
00461 switch(c) {
00462 case 'H':
00463 val = date_get_num(&p, 0, 23, 2);
00464 if (val == -1)
00465 return NULL;
00466 dt->tm_hour = val;
00467 break;
00468 case 'M':
00469 val = date_get_num(&p, 0, 59, 2);
00470 if (val == -1)
00471 return NULL;
00472 dt->tm_min = val;
00473 break;
00474 case 'S':
00475 val = date_get_num(&p, 0, 59, 2);
00476 if (val == -1)
00477 return NULL;
00478 dt->tm_sec = val;
00479 break;
00480 case 'Y':
00481 val = date_get_num(&p, 0, 9999, 4);
00482 if (val == -1)
00483 return NULL;
00484 dt->tm_year = val - 1900;
00485 break;
00486 case 'm':
00487 val = date_get_num(&p, 1, 12, 2);
00488 if (val == -1)
00489 return NULL;
00490 dt->tm_mon = val - 1;
00491 break;
00492 case 'd':
00493 val = date_get_num(&p, 1, 31, 2);
00494 if (val == -1)
00495 return NULL;
00496 dt->tm_mday = val;
00497 break;
00498 case '%':
00499 goto match;
00500 default:
00501 return NULL;
00502 }
00503 } else {
00504 match:
00505 if (c != *p)
00506 return NULL;
00507 p++;
00508 }
00509 }
00510 }
00511
00512 time_t av_timegm(struct tm *tm)
00513 {
00514 time_t t;
00515
00516 int y = tm->tm_year + 1900, m = tm->tm_mon + 1, d = tm->tm_mday;
00517
00518 if (m < 3) {
00519 m += 12;
00520 y--;
00521 }
00522
00523 t = 86400 *
00524 (d + (153 * m - 457) / 5 + 365 * y + y / 4 - y / 100 + y / 400 - 719469);
00525
00526 t += 3600 * tm->tm_hour + 60 * tm->tm_min + tm->tm_sec;
00527
00528 return t;
00529 }
00530
00531 int av_parse_time(int64_t *timeval, const char *timestr, int duration)
00532 {
00533 const char *p, *q;
00534 int64_t t;
00535 time_t now;
00536 struct tm dt = { 0 };
00537 int today = 0, negative = 0, microseconds = 0;
00538 int i;
00539 static const char * const date_fmt[] = {
00540 "%Y-%m-%d",
00541 "%Y%m%d",
00542 };
00543 static const char * const time_fmt[] = {
00544 "%H:%M:%S",
00545 "%H%M%S",
00546 };
00547
00548 p = timestr;
00549 q = NULL;
00550 *timeval = INT64_MIN;
00551 if (!duration) {
00552 now = time(0);
00553
00554 if (!av_strcasecmp(timestr, "now")) {
00555 *timeval = (int64_t) now * 1000000;
00556 return 0;
00557 }
00558
00559
00560 for (i = 0; i < FF_ARRAY_ELEMS(date_fmt); i++) {
00561 q = small_strptime(p, date_fmt[i], &dt);
00562 if (q)
00563 break;
00564 }
00565
00566
00567
00568 if (!q) {
00569 today = 1;
00570 q = p;
00571 }
00572 p = q;
00573
00574 if (*p == 'T' || *p == 't' || *p == ' ')
00575 p++;
00576
00577
00578 for (i = 0; i < FF_ARRAY_ELEMS(time_fmt); i++) {
00579 q = small_strptime(p, time_fmt[i], &dt);
00580 if (q)
00581 break;
00582 }
00583 } else {
00584
00585 if (p[0] == '-') {
00586 negative = 1;
00587 ++p;
00588 }
00589
00590 q = small_strptime(p, time_fmt[0], &dt);
00591 if (!q) {
00592
00593 dt.tm_sec = strtol(p, (void *)&q, 10);
00594 if (q == p)
00595 return AVERROR(EINVAL);
00596 dt.tm_min = 0;
00597 dt.tm_hour = 0;
00598 }
00599 }
00600
00601
00602 if (!q)
00603 return AVERROR(EINVAL);
00604
00605
00606 if (*q == '.') {
00607 int n;
00608 q++;
00609 for (n = 100000; n >= 1; n /= 10, q++) {
00610 if (!isdigit(*q))
00611 break;
00612 microseconds += n * (*q - '0');
00613 }
00614 }
00615
00616 if (duration) {
00617 t = dt.tm_hour * 3600 + dt.tm_min * 60 + dt.tm_sec;
00618 } else {
00619 int is_utc = *q == 'Z' || *q == 'z';
00620 q += is_utc;
00621 if (today) {
00622 struct tm dt2 = is_utc ? *gmtime(&now) : *localtime(&now);
00623 dt2.tm_hour = dt.tm_hour;
00624 dt2.tm_min = dt.tm_min;
00625 dt2.tm_sec = dt.tm_sec;
00626 dt = dt2;
00627 }
00628 t = is_utc ? av_timegm(&dt) : mktime(&dt);
00629 }
00630
00631
00632 if (*q)
00633 return AVERROR(EINVAL);
00634
00635 t *= 1000000;
00636 t += microseconds;
00637 *timeval = negative ? -t : t;
00638 return 0;
00639 }
00640
00641 int av_find_info_tag(char *arg, int arg_size, const char *tag1, const char *info)
00642 {
00643 const char *p;
00644 char tag[128], *q;
00645
00646 p = info;
00647 if (*p == '?')
00648 p++;
00649 for(;;) {
00650 q = tag;
00651 while (*p != '\0' && *p != '=' && *p != '&') {
00652 if ((q - tag) < sizeof(tag) - 1)
00653 *q++ = *p;
00654 p++;
00655 }
00656 *q = '\0';
00657 q = arg;
00658 if (*p == '=') {
00659 p++;
00660 while (*p != '&' && *p != '\0') {
00661 if ((q - arg) < arg_size - 1) {
00662 if (*p == '+')
00663 *q++ = ' ';
00664 else
00665 *q++ = *p;
00666 }
00667 p++;
00668 }
00669 }
00670 *q = '\0';
00671 if (!strcmp(tag, tag1))
00672 return 1;
00673 if (*p != '&')
00674 break;
00675 p++;
00676 }
00677 return 0;
00678 }
00679
00680 #ifdef TEST
00681
00682 static uint32_t random = MKTAG('L','A','V','U');
00683
00684 static uint32_t av_get_random_seed_deterministic(void)
00685 {
00686 return random = random * 1664525 + 1013904223;
00687 }
00688
00689 #undef printf
00690
00691 int main(void)
00692 {
00693 printf("Testing av_parse_video_rate()\n");
00694 {
00695 int i;
00696 const char *rates[] = {
00697 "-inf",
00698 "inf",
00699 "nan",
00700 "123/0",
00701 "-123 / 0",
00702 "",
00703 "/",
00704 " 123 / 321",
00705 "foo/foo",
00706 "foo/1",
00707 "1/foo",
00708 "0/0",
00709 "/0",
00710 "1/",
00711 "1",
00712 "0",
00713 "-123/123",
00714 "-foo",
00715 "123.23",
00716 ".23",
00717 "-.23",
00718 "-0.234",
00719 "-0.0000001",
00720 " 21332.2324 ",
00721 " -21332.2324 ",
00722 };
00723
00724 for (i = 0; i < FF_ARRAY_ELEMS(rates); i++) {
00725 int ret;
00726 char err[1024];
00727 AVRational q = (AVRational){0, 0};
00728 ret = av_parse_video_rate(&q, rates[i]);
00729 av_strerror(ret, err, sizeof(err));
00730 printf("'%s' -> %d/%d ret:%s\n",
00731 rates[i], q.num, q.den, err);
00732 }
00733 }
00734
00735 printf("\nTesting av_parse_color()\n");
00736 {
00737 int i;
00738 uint8_t rgba[4];
00739 const char *color_names[] = {
00740 "bikeshed",
00741 "RaNdOm",
00742 "foo",
00743 "red",
00744 "Red ",
00745 "RED",
00746 "Violet",
00747 "Yellow",
00748 "Red",
00749 "0x000000",
00750 "0x0000000",
00751 "0xff000000",
00752 "0x3e34ff",
00753 "0x3e34ffaa",
00754 "0xffXXee",
00755 "0xfoobar",
00756 "0xffffeeeeeeee",
00757 "#ff0000",
00758 "#ffXX00",
00759 "ff0000",
00760 "ffXX00",
00761 "red@foo",
00762 "random@10",
00763 "0xff0000@1.0",
00764 "red@",
00765 "red@0xfff",
00766 "red@0xf",
00767 "red@2",
00768 "red@0.1",
00769 "red@-1",
00770 "red@0.5",
00771 "red@1.0",
00772 "red@256",
00773 "red@10foo",
00774 "red@-1.0",
00775 "red@-0.0",
00776 };
00777
00778 av_log_set_level(AV_LOG_DEBUG);
00779
00780 for (i = 0; i < FF_ARRAY_ELEMS(color_names); i++) {
00781 if (av_parse_color(rgba, color_names[i], -1, NULL) >= 0)
00782 printf("%s -> R(%d) G(%d) B(%d) A(%d)\n", color_names[i], rgba[0], rgba[1], rgba[2], rgba[3]);
00783 else
00784 printf("%s -> error\n", color_names[i]);
00785 }
00786 }
00787
00788 printf("\nTesting av_parse_time()\n");
00789 {
00790 int i;
00791 int64_t tv;
00792 time_t tvi;
00793 struct tm *tm;
00794 static char tzstr[] = "TZ=CET-1";
00795 const char *time_string[] = {
00796 "now",
00797 "12:35:46",
00798 "2000-12-20 0:02:47.5z",
00799 "2000-12-20T010247.6",
00800 };
00801 const char *duration_string[] = {
00802 "2:34:56.79",
00803 "-1:23:45.67",
00804 "42.1729",
00805 "-1729.42",
00806 "12:34",
00807 };
00808
00809 av_log_set_level(AV_LOG_DEBUG);
00810 putenv(tzstr);
00811 printf("(now is 2012-03-17 09:14:13 +0100, local time is UTC+1)\n");
00812 for (i = 0; i < FF_ARRAY_ELEMS(time_string); i++) {
00813 printf("%-24s -> ", time_string[i]);
00814 if (av_parse_time(&tv, time_string[i], 0)) {
00815 printf("error\n");
00816 } else {
00817 tvi = tv / 1000000;
00818 tm = gmtime(&tvi);
00819 printf("%14"PRIi64".%06d = %04d-%02d-%02dT%02d:%02d:%02dZ\n",
00820 tv / 1000000, (int)(tv % 1000000),
00821 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
00822 tm->tm_hour, tm->tm_min, tm->tm_sec);
00823 }
00824 }
00825 for (i = 0; i < FF_ARRAY_ELEMS(duration_string); i++) {
00826 printf("%-24s -> ", duration_string[i]);
00827 if (av_parse_time(&tv, duration_string[i], 1)) {
00828 printf("error\n");
00829 } else {
00830 printf("%+21"PRIi64"\n", tv);
00831 }
00832 }
00833 }
00834
00835 return 0;
00836 }
00837
00838 #endif