Libav 0.7.1
|
00001 /* 00002 * This file is part of Libav. 00003 * 00004 * Libav is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2.1 of the License, or (at your option) any later version. 00008 * 00009 * Libav is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Lesser General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public 00015 * License along with Libav; if not, write to the Free Software 00016 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 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 }, /* VCD compliant NTSC */ 00048 { "qpal", 352, 288 }, /* VCD compliant PAL */ 00049 { "sntsc", 640, 480 }, /* square pixel NTSC */ 00050 { "spal", 768, 576 }, /* square pixel PAL */ 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 } }, /* VCD compliant NTSC */ 00088 { "qpal", { 25, 1 } }, /* VCD compliant PAL */ 00089 { "sntsc", { 30000, 1001 } }, /* square pixel NTSC */ 00090 { "spal", { 25, 1 } }, /* square pixel PAL */ 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 /* First, we check our abbreviation table */ 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 /* Then, we try to parse it as fraction */ 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 /* get a positive number between n_min and n_max, for a maximum length 00378 of len_max. Return -1 if error. */ 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 /* no number read ? */ 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 /* small strptime for ffmpeg */ 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 /* parse the year-month-day part */ 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 /* if the year-month-day part is missing, then take the 00535 * current year-month-day time */ 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 /* parse the hour-minute-second part */ 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 /* parse datestr as a duration */ 00559 if (p[0] == '-') { 00560 negative = 1; 00561 ++p; 00562 } 00563 /* parse datestr as HH:MM:SS */ 00564 q = small_strptime(p, time_fmt[0], &dt); 00565 if (!q) { 00566 /* parse datestr as S+ */ 00567 dt.tm_sec = strtol(p, (char **)&q, 10); 00568 if (q == p) { 00569 /* the parsing didn't succeed */ 00570 *timeval = INT64_MIN; 00571 return AVERROR(EINVAL); 00572 } 00573 dt.tm_min = 0; 00574 dt.tm_hour = 0; 00575 } 00576 } 00577 00578 /* Now we have all the fields that we can get */ 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; /* unknown */ 00588 if (is_utc) { 00589 t = mktimegm(&dt); 00590 } else { 00591 t = mktime(&dt); 00592 } 00593 } 00594 00595 t *= 1000000; 00596 00597 /* parse the .m... part */ 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 /* TEST */