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