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