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