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