00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00024 #include <strings.h>
00025 #include <sys/time.h>
00026 #include <time.h>
00027
00028 #include "avstring.h"
00029 #include "avutil.h"
00030 #include "eval.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 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, &p, 10);
00112 if (*p)
00113 p++;
00114 height = strtol(p, &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 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 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 (!strcasecmp(color_string2, "random") || !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
00403
00404 static
00405 const char *small_strptime(const char *p, const char *fmt,
00406 struct tm *dt)
00407 {
00408 int c, val;
00409
00410 for(;;) {
00411 c = *fmt++;
00412 if (c == '\0') {
00413 return p;
00414 } else if (c == '%') {
00415 c = *fmt++;
00416 switch(c) {
00417 case 'H':
00418 val = date_get_num(&p, 0, 23, 2);
00419 if (val == -1)
00420 return NULL;
00421 dt->tm_hour = val;
00422 break;
00423 case 'M':
00424 val = date_get_num(&p, 0, 59, 2);
00425 if (val == -1)
00426 return NULL;
00427 dt->tm_min = val;
00428 break;
00429 case 'S':
00430 val = date_get_num(&p, 0, 59, 2);
00431 if (val == -1)
00432 return NULL;
00433 dt->tm_sec = val;
00434 break;
00435 case 'Y':
00436 val = date_get_num(&p, 0, 9999, 4);
00437 if (val == -1)
00438 return NULL;
00439 dt->tm_year = val - 1900;
00440 break;
00441 case 'm':
00442 val = date_get_num(&p, 1, 12, 2);
00443 if (val == -1)
00444 return NULL;
00445 dt->tm_mon = val - 1;
00446 break;
00447 case 'd':
00448 val = date_get_num(&p, 1, 31, 2);
00449 if (val == -1)
00450 return NULL;
00451 dt->tm_mday = val;
00452 break;
00453 case '%':
00454 goto match;
00455 default:
00456 return NULL;
00457 }
00458 } else {
00459 match:
00460 if (c != *p)
00461 return NULL;
00462 p++;
00463 }
00464 }
00465 return p;
00466 }
00467
00468 static time_t mktimegm(struct tm *tm)
00469 {
00470 time_t t;
00471
00472 int y = tm->tm_year + 1900, m = tm->tm_mon + 1, d = tm->tm_mday;
00473
00474 if (m < 3) {
00475 m += 12;
00476 y--;
00477 }
00478
00479 t = 86400 *
00480 (d + (153 * m - 457) / 5 + 365 * y + y / 4 - y / 100 + y / 400 - 719469);
00481
00482 t += 3600 * tm->tm_hour + 60 * tm->tm_min + tm->tm_sec;
00483
00484 return t;
00485 }
00486
00487 int av_parse_time(int64_t *timeval, const char *datestr, int duration)
00488 {
00489 const char *p;
00490 int64_t t;
00491 struct tm dt;
00492 int i;
00493 static const char * const date_fmt[] = {
00494 "%Y-%m-%d",
00495 "%Y%m%d",
00496 };
00497 static const char * const time_fmt[] = {
00498 "%H:%M:%S",
00499 "%H%M%S",
00500 };
00501 const char *q;
00502 int is_utc, len;
00503 char lastch;
00504 int negative = 0;
00505
00506 #undef time
00507 time_t now = time(0);
00508
00509 len = strlen(datestr);
00510 if (len > 0)
00511 lastch = datestr[len - 1];
00512 else
00513 lastch = '\0';
00514 is_utc = (lastch == 'z' || lastch == 'Z');
00515
00516 memset(&dt, 0, sizeof(dt));
00517
00518 p = datestr;
00519 q = NULL;
00520 if (!duration) {
00521 if (!strncasecmp(datestr, "now", len)) {
00522 *timeval = (int64_t) now * 1000000;
00523 return 0;
00524 }
00525
00526
00527 for (i = 0; i < FF_ARRAY_ELEMS(date_fmt); i++) {
00528 q = small_strptime(p, date_fmt[i], &dt);
00529 if (q) {
00530 break;
00531 }
00532 }
00533
00534
00535
00536 if (!q) {
00537 if (is_utc) {
00538 dt = *gmtime(&now);
00539 } else {
00540 dt = *localtime(&now);
00541 }
00542 dt.tm_hour = dt.tm_min = dt.tm_sec = 0;
00543 } else {
00544 p = q;
00545 }
00546
00547 if (*p == 'T' || *p == 't' || *p == ' ')
00548 p++;
00549
00550
00551 for (i = 0; i < FF_ARRAY_ELEMS(time_fmt); i++) {
00552 q = small_strptime(p, time_fmt[i], &dt);
00553 if (q) {
00554 break;
00555 }
00556 }
00557 } else {
00558
00559 if (p[0] == '-') {
00560 negative = 1;
00561 ++p;
00562 }
00563
00564 q = small_strptime(p, time_fmt[0], &dt);
00565 if (!q) {
00566
00567 dt.tm_sec = strtol(p, (char **)&q, 10);
00568 if (q == p) {
00569
00570 *timeval = INT64_MIN;
00571 return AVERROR(EINVAL);
00572 }
00573 dt.tm_min = 0;
00574 dt.tm_hour = 0;
00575 }
00576 }
00577
00578
00579 if (!q) {
00580 *timeval = INT64_MIN;
00581 return AVERROR(EINVAL);
00582 }
00583
00584 if (duration) {
00585 t = dt.tm_hour * 3600 + dt.tm_min * 60 + dt.tm_sec;
00586 } else {
00587 dt.tm_isdst = -1;
00588 if (is_utc) {
00589 t = mktimegm(&dt);
00590 } else {
00591 t = mktime(&dt);
00592 }
00593 }
00594
00595 t *= 1000000;
00596
00597
00598 if (*q == '.') {
00599 int val, n;
00600 q++;
00601 for (val = 0, n = 100000; n >= 1; n /= 10, q++) {
00602 if (!isdigit(*q))
00603 break;
00604 val += n * (*q - '0');
00605 }
00606 t += val;
00607 }
00608 *timeval = negative ? -t : t;
00609 return 0;
00610 }
00611
00612 int av_find_info_tag(char *arg, int arg_size, const char *tag1, const char *info)
00613 {
00614 const char *p;
00615 char tag[128], *q;
00616
00617 p = info;
00618 if (*p == '?')
00619 p++;
00620 for(;;) {
00621 q = tag;
00622 while (*p != '\0' && *p != '=' && *p != '&') {
00623 if ((q - tag) < sizeof(tag) - 1)
00624 *q++ = *p;
00625 p++;
00626 }
00627 *q = '\0';
00628 q = arg;
00629 if (*p == '=') {
00630 p++;
00631 while (*p != '&' && *p != '\0') {
00632 if ((q - arg) < arg_size - 1) {
00633 if (*p == '+')
00634 *q++ = ' ';
00635 else
00636 *q++ = *p;
00637 }
00638 p++;
00639 }
00640 }
00641 *q = '\0';
00642 if (!strcmp(tag, tag1))
00643 return 1;
00644 if (*p != '&')
00645 break;
00646 p++;
00647 }
00648 return 0;
00649 }
00650
00651 #ifdef TEST
00652
00653 #undef printf
00654
00655 int main(void)
00656 {
00657 printf("Testing av_parse_video_rate()\n");
00658 {
00659 int i;
00660 const char *rates[] = {
00661 "-inf",
00662 "inf",
00663 "nan",
00664 "123/0",
00665 "-123 / 0",
00666 "",
00667 "/",
00668 " 123 / 321",
00669 "foo/foo",
00670 "foo/1",
00671 "1/foo",
00672 "0/0",
00673 "/0",
00674 "1/",
00675 "1",
00676 "0",
00677 "-123/123",
00678 "-foo",
00679 "123.23",
00680 ".23",
00681 "-.23",
00682 "-0.234",
00683 "-0.0000001",
00684 " 21332.2324 ",
00685 " -21332.2324 ",
00686 };
00687
00688 for (i = 0; i < FF_ARRAY_ELEMS(rates); i++) {
00689 int ret;
00690 AVRational q = (AVRational){0, 0};
00691 ret = av_parse_video_rate(&q, rates[i]),
00692 printf("'%s' -> %d/%d ret:%d\n",
00693 rates[i], q.num, q.den, ret);
00694 }
00695 }
00696
00697 printf("\nTesting av_parse_color()\n");
00698 {
00699 int i;
00700 uint8_t rgba[4];
00701 const char *color_names[] = {
00702 "bikeshed",
00703 "RaNdOm",
00704 "foo",
00705 "red",
00706 "Red ",
00707 "RED",
00708 "Violet",
00709 "Yellow",
00710 "Red",
00711 "0x000000",
00712 "0x0000000",
00713 "0xff000000",
00714 "0x3e34ff",
00715 "0x3e34ffaa",
00716 "0xffXXee",
00717 "0xfoobar",
00718 "0xffffeeeeeeee",
00719 "#ff0000",
00720 "#ffXX00",
00721 "ff0000",
00722 "ffXX00",
00723 "red@foo",
00724 "random@10",
00725 "0xff0000@1.0",
00726 "red@",
00727 "red@0xfff",
00728 "red@0xf",
00729 "red@2",
00730 "red@0.1",
00731 "red@-1",
00732 "red@0.5",
00733 "red@1.0",
00734 "red@256",
00735 "red@10foo",
00736 "red@-1.0",
00737 "red@-0.0",
00738 };
00739
00740 av_log_set_level(AV_LOG_DEBUG);
00741
00742 for (i = 0; i < FF_ARRAY_ELEMS(color_names); i++) {
00743 if (av_parse_color(rgba, color_names[i], -1, NULL) >= 0)
00744 printf("%s -> R(%d) G(%d) B(%d) A(%d)\n", color_names[i], rgba[0], rgba[1], rgba[2], rgba[3]);
00745 }
00746 }
00747
00748 return 0;
00749 }
00750
00751 #endif