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