libavutil/parseutils.c

Go to the documentation of this file.
00001 /*
00002  * This file is part of FFmpeg.
00003  *
00004  * FFmpeg 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  * FFmpeg 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 FFmpeg; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
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 }, /* 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 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 /* 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 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 /* 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 
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 /* parse the year-month-day part */
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 /* if the year-month-day part is missing, then take the
00541  * current year-month-day time */
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 /* parse the hour-minute-second part */
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 /* parse timestr as a duration */
00565 if (p[0] == '-') {
00566 negative = 1;
00567 ++p;
00568 }
00569 /* parse timestr as HH:MM:SS */
00570 q = small_strptime(p, time_fmt[0], &dt);
00571 if (!q) {
00572 /* parse timestr as S+ */
00573 dt.tm_sec = strtol(p, (void *)&q, 10);
00574 if (q == p) {
00575 /* the parsing didn't succeed */
00576 *timeval = INT64_MIN;
00577 return AVERROR(EINVAL);
00578 }
00579 dt.tm_min = 0;
00580 dt.tm_hour = 0;
00581 }
00582 }
00583 
00584 /* Now we have all the fields that we can get */
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; /* unknown */
00594 if (is_utc) {
00595 t = av_timegm(&dt);
00596 } else {
00597 t = mktime(&dt);
00598 }
00599 }
00600 
00601 t *= 1000000;
00602 
00603 /* parse the .m... part */
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 /* TEST */

Generated on Fri Oct 26 02:46:05 2012 for FFmpeg by doxygen 1.5.8

AltStyle によって変換されたページ (->オリジナル) /