• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavfilter/parseutils.c

Go to the documentation of this file.
00001 /*
00002  * copyright (c) 2009 Stefano Sabatini
00003  * This file is part of FFmpeg.
00004  *
00005  * FFmpeg is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Lesser General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2.1 of the License, or (at your option) any later version.
00009  *
00010  * FFmpeg is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Lesser General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public
00016  * License along with FFmpeg; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00018  */
00019 
00025 #include <strings.h>
00026 #include "libavutil/avutil.h"
00027 #include "libavutil/random_seed.h"
00028 #include "parseutils.h"
00029 
00030 #define WHITESPACES " \n\t"
00031 
00032 char *av_get_token(const char **buf, const char *term)
00033 {
00034     char *out = av_malloc(strlen(*buf) + 1);
00035     char *ret= out, *end= out;
00036     const char *p = *buf;
00037     p += strspn(p, WHITESPACES);
00038 
00039     while(*p && !strspn(p, term)) {
00040         char c = *p++;
00041         if(c == '\\' && *p){
00042             *out++ = *p++;
00043             end= out;
00044         }else if(c == '\''){
00045             while(*p && *p != '\'')
00046                 *out++ = *p++;
00047             if(*p){
00048                 p++;
00049                 end= out;
00050             }
00051         }else{
00052             *out++ = c;
00053         }
00054     }
00055 
00056     do{
00057         *out-- = 0;
00058     }while(out >= end && strspn(out, WHITESPACES));
00059 
00060     *buf = p;
00061 
00062     return ret;
00063 }
00064 
00065 typedef struct {
00066     const char *name;            
00067     uint8_t     rgba_color[4];   
00068 } ColorEntry;
00069 
00070 static ColorEntry color_table[] = {
00071     { "AliceBlue",            { 0xF0, 0xF8, 0xFF } },
00072     { "AntiqueWhite",         { 0xFA, 0xEB, 0xD7 } },
00073     { "Aqua",                 { 0x00, 0xFF, 0xFF } },
00074     { "Aquamarine",           { 0x7F, 0xFF, 0xD4 } },
00075     { "Azure",                { 0xF0, 0xFF, 0xFF } },
00076     { "Beige",                { 0xF5, 0xF5, 0xDC } },
00077     { "Bisque",               { 0xFF, 0xE4, 0xC4 } },
00078     { "Black",                { 0x00, 0x00, 0x00 } },
00079     { "BlanchedAlmond",       { 0xFF, 0xEB, 0xCD } },
00080     { "Blue",                 { 0x00, 0x00, 0xFF } },
00081     { "BlueViolet",           { 0x8A, 0x2B, 0xE2 } },
00082     { "Brown",                { 0xA5, 0x2A, 0x2A } },
00083     { "BurlyWood",            { 0xDE, 0xB8, 0x87 } },
00084     { "CadetBlue",            { 0x5F, 0x9E, 0xA0 } },
00085     { "Chartreuse",           { 0x7F, 0xFF, 0x00 } },
00086     { "Chocolate",            { 0xD2, 0x69, 0x1E } },
00087     { "Coral",                { 0xFF, 0x7F, 0x50 } },
00088     { "CornflowerBlue",       { 0x64, 0x95, 0xED } },
00089     { "Cornsilk",             { 0xFF, 0xF8, 0xDC } },
00090     { "Crimson",              { 0xDC, 0x14, 0x3C } },
00091     { "Cyan",                 { 0x00, 0xFF, 0xFF } },
00092     { "DarkBlue",             { 0x00, 0x00, 0x8B } },
00093     { "DarkCyan",             { 0x00, 0x8B, 0x8B } },
00094     { "DarkGoldenRod",        { 0xB8, 0x86, 0x0B } },
00095     { "DarkGray",             { 0xA9, 0xA9, 0xA9 } },
00096     { "DarkGreen",            { 0x00, 0x64, 0x00 } },
00097     { "DarkKhaki",            { 0xBD, 0xB7, 0x6B } },
00098     { "DarkMagenta",          { 0x8B, 0x00, 0x8B } },
00099     { "DarkOliveGreen",       { 0x55, 0x6B, 0x2F } },
00100     { "Darkorange",           { 0xFF, 0x8C, 0x00 } },
00101     { "DarkOrchid",           { 0x99, 0x32, 0xCC } },
00102     { "DarkRed",              { 0x8B, 0x00, 0x00 } },
00103     { "DarkSalmon",           { 0xE9, 0x96, 0x7A } },
00104     { "DarkSeaGreen",         { 0x8F, 0xBC, 0x8F } },
00105     { "DarkSlateBlue",        { 0x48, 0x3D, 0x8B } },
00106     { "DarkSlateGray",        { 0x2F, 0x4F, 0x4F } },
00107     { "DarkTurquoise",        { 0x00, 0xCE, 0xD1 } },
00108     { "DarkViolet",           { 0x94, 0x00, 0xD3 } },
00109     { "DeepPink",             { 0xFF, 0x14, 0x93 } },
00110     { "DeepSkyBlue",          { 0x00, 0xBF, 0xFF } },
00111     { "DimGray",              { 0x69, 0x69, 0x69 } },
00112     { "DodgerBlue",           { 0x1E, 0x90, 0xFF } },
00113     { "FireBrick",            { 0xB2, 0x22, 0x22 } },
00114     { "FloralWhite",          { 0xFF, 0xFA, 0xF0 } },
00115     { "ForestGreen",          { 0x22, 0x8B, 0x22 } },
00116     { "Fuchsia",              { 0xFF, 0x00, 0xFF } },
00117     { "Gainsboro",            { 0xDC, 0xDC, 0xDC } },
00118     { "GhostWhite",           { 0xF8, 0xF8, 0xFF } },
00119     { "Gold",                 { 0xFF, 0xD7, 0x00 } },
00120     { "GoldenRod",            { 0xDA, 0xA5, 0x20 } },
00121     { "Gray",                 { 0x80, 0x80, 0x80 } },
00122     { "Green",                { 0x00, 0x80, 0x00 } },
00123     { "GreenYellow",          { 0xAD, 0xFF, 0x2F } },
00124     { "HoneyDew",             { 0xF0, 0xFF, 0xF0 } },
00125     { "HotPink",              { 0xFF, 0x69, 0xB4 } },
00126     { "IndianRed",            { 0xCD, 0x5C, 0x5C } },
00127     { "Indigo",               { 0x4B, 0x00, 0x82 } },
00128     { "Ivory",                { 0xFF, 0xFF, 0xF0 } },
00129     { "Khaki",                { 0xF0, 0xE6, 0x8C } },
00130     { "Lavender",             { 0xE6, 0xE6, 0xFA } },
00131     { "LavenderBlush",        { 0xFF, 0xF0, 0xF5 } },
00132     { "LawnGreen",            { 0x7C, 0xFC, 0x00 } },
00133     { "LemonChiffon",         { 0xFF, 0xFA, 0xCD } },
00134     { "LightBlue",            { 0xAD, 0xD8, 0xE6 } },
00135     { "LightCoral",           { 0xF0, 0x80, 0x80 } },
00136     { "LightCyan",            { 0xE0, 0xFF, 0xFF } },
00137     { "LightGoldenRodYellow", { 0xFA, 0xFA, 0xD2 } },
00138     { "LightGrey",            { 0xD3, 0xD3, 0xD3 } },
00139     { "LightGreen",           { 0x90, 0xEE, 0x90 } },
00140     { "LightPink",            { 0xFF, 0xB6, 0xC1 } },
00141     { "LightSalmon",          { 0xFF, 0xA0, 0x7A } },
00142     { "LightSeaGreen",        { 0x20, 0xB2, 0xAA } },
00143     { "LightSkyBlue",         { 0x87, 0xCE, 0xFA } },
00144     { "LightSlateGray",       { 0x77, 0x88, 0x99 } },
00145     { "LightSteelBlue",       { 0xB0, 0xC4, 0xDE } },
00146     { "LightYellow",          { 0xFF, 0xFF, 0xE0 } },
00147     { "Lime",                 { 0x00, 0xFF, 0x00 } },
00148     { "LimeGreen",            { 0x32, 0xCD, 0x32 } },
00149     { "Linen",                { 0xFA, 0xF0, 0xE6 } },
00150     { "Magenta",              { 0xFF, 0x00, 0xFF } },
00151     { "Maroon",               { 0x80, 0x00, 0x00 } },
00152     { "MediumAquaMarine",     { 0x66, 0xCD, 0xAA } },
00153     { "MediumBlue",           { 0x00, 0x00, 0xCD } },
00154     { "MediumOrchid",         { 0xBA, 0x55, 0xD3 } },
00155     { "MediumPurple",         { 0x93, 0x70, 0xD8 } },
00156     { "MediumSeaGreen",       { 0x3C, 0xB3, 0x71 } },
00157     { "MediumSlateBlue",      { 0x7B, 0x68, 0xEE } },
00158     { "MediumSpringGreen",    { 0x00, 0xFA, 0x9A } },
00159     { "MediumTurquoise",      { 0x48, 0xD1, 0xCC } },
00160     { "MediumVioletRed",      { 0xC7, 0x15, 0x85 } },
00161     { "MidnightBlue",         { 0x19, 0x19, 0x70 } },
00162     { "MintCream",            { 0xF5, 0xFF, 0xFA } },
00163     { "MistyRose",            { 0xFF, 0xE4, 0xE1 } },
00164     { "Moccasin",             { 0xFF, 0xE4, 0xB5 } },
00165     { "NavajoWhite",          { 0xFF, 0xDE, 0xAD } },
00166     { "Navy",                 { 0x00, 0x00, 0x80 } },
00167     { "OldLace",              { 0xFD, 0xF5, 0xE6 } },
00168     { "Olive",                { 0x80, 0x80, 0x00 } },
00169     { "OliveDrab",            { 0x6B, 0x8E, 0x23 } },
00170     { "Orange",               { 0xFF, 0xA5, 0x00 } },
00171     { "OrangeRed",            { 0xFF, 0x45, 0x00 } },
00172     { "Orchid",               { 0xDA, 0x70, 0xD6 } },
00173     { "PaleGoldenRod",        { 0xEE, 0xE8, 0xAA } },
00174     { "PaleGreen",            { 0x98, 0xFB, 0x98 } },
00175     { "PaleTurquoise",        { 0xAF, 0xEE, 0xEE } },
00176     { "PaleVioletRed",        { 0xD8, 0x70, 0x93 } },
00177     { "PapayaWhip",           { 0xFF, 0xEF, 0xD5 } },
00178     { "PeachPuff",            { 0xFF, 0xDA, 0xB9 } },
00179     { "Peru",                 { 0xCD, 0x85, 0x3F } },
00180     { "Pink",                 { 0xFF, 0xC0, 0xCB } },
00181     { "Plum",                 { 0xDD, 0xA0, 0xDD } },
00182     { "PowderBlue",           { 0xB0, 0xE0, 0xE6 } },
00183     { "Purple",               { 0x80, 0x00, 0x80 } },
00184     { "Red",                  { 0xFF, 0x00, 0x00 } },
00185     { "RosyBrown",            { 0xBC, 0x8F, 0x8F } },
00186     { "RoyalBlue",            { 0x41, 0x69, 0xE1 } },
00187     { "SaddleBrown",          { 0x8B, 0x45, 0x13 } },
00188     { "Salmon",               { 0xFA, 0x80, 0x72 } },
00189     { "SandyBrown",           { 0xF4, 0xA4, 0x60 } },
00190     { "SeaGreen",             { 0x2E, 0x8B, 0x57 } },
00191     { "SeaShell",             { 0xFF, 0xF5, 0xEE } },
00192     { "Sienna",               { 0xA0, 0x52, 0x2D } },
00193     { "Silver",               { 0xC0, 0xC0, 0xC0 } },
00194     { "SkyBlue",              { 0x87, 0xCE, 0xEB } },
00195     { "SlateBlue",            { 0x6A, 0x5A, 0xCD } },
00196     { "SlateGray",            { 0x70, 0x80, 0x90 } },
00197     { "Snow",                 { 0xFF, 0xFA, 0xFA } },
00198     { "SpringGreen",          { 0x00, 0xFF, 0x7F } },
00199     { "SteelBlue",            { 0x46, 0x82, 0xB4 } },
00200     { "Tan",                  { 0xD2, 0xB4, 0x8C } },
00201     { "Teal",                 { 0x00, 0x80, 0x80 } },
00202     { "Thistle",              { 0xD8, 0xBF, 0xD8 } },
00203     { "Tomato",               { 0xFF, 0x63, 0x47 } },
00204     { "Turquoise",            { 0x40, 0xE0, 0xD0 } },
00205     { "Violet",               { 0xEE, 0x82, 0xEE } },
00206     { "Wheat",                { 0xF5, 0xDE, 0xB3 } },
00207     { "White",                { 0xFF, 0xFF, 0xFF } },
00208     { "WhiteSmoke",           { 0xF5, 0xF5, 0xF5 } },
00209     { "Yellow",               { 0xFF, 0xFF, 0x00 } },
00210     { "YellowGreen",          { 0x9A, 0xCD, 0x32 } },
00211 };
00212 
00213 static int color_table_compare(const void *lhs, const void *rhs)
00214 {
00215     return strcasecmp(lhs, ((const ColorEntry *)rhs)->name);
00216 }
00217 
00218 int av_parse_color(uint8_t *rgba_color, const char *color_string, void *log_ctx)
00219 {
00220     if (!strcasecmp(color_string, "random") || !strcasecmp(color_string, "bikeshed")) {
00221         int rgba = ff_random_get_seed();
00222         rgba_color[0] = rgba >> 24;
00223         rgba_color[1] = rgba >> 16;
00224         rgba_color[2] = rgba >> 8;
00225         rgba_color[3] = rgba;
00226     } else
00227     if (!strncmp(color_string, "0x", 2)) {
00228         char *tail;
00229         int len = strlen(color_string);
00230         unsigned int rgba = strtoul(color_string, &tail, 16);
00231 
00232         if (*tail || (len != 8 && len != 10)) {
00233             av_log(log_ctx, AV_LOG_ERROR, "Invalid 0xRRGGBB[AA] color string: '%s'\n", color_string);
00234             return -1;
00235         }
00236         if (len == 10) {
00237             rgba_color[3] = rgba;
00238             rgba >>= 8;
00239         }
00240         rgba_color[0] = rgba >> 16;
00241         rgba_color[1] = rgba >> 8;
00242         rgba_color[2] = rgba;
00243     } else {
00244         const ColorEntry *entry = bsearch(color_string,
00245                                           color_table,
00246                                           FF_ARRAY_ELEMS(color_table),
00247                                           sizeof(ColorEntry),
00248                                           color_table_compare);
00249         if (!entry) {
00250             av_log(log_ctx, AV_LOG_ERROR, "Cannot find color '%s'\n", color_string);
00251             return -1;
00252         }
00253         memcpy(rgba_color, entry->rgba_color, 4);
00254     }
00255 
00256     return 0;
00257 }
00258 
00276 static int parse_key_value_pair(void *ctx, const char **buf,
00277                                 const char *key_val_sep, const char *pairs_sep)
00278 {
00279     char *key = av_get_token(buf, key_val_sep);
00280     char *val;
00281     int ret;
00282 
00283     if (*key && strspn(*buf, key_val_sep)) {
00284         (*buf)++;
00285         val = av_get_token(buf, pairs_sep);
00286     } else {
00287         av_log(ctx, AV_LOG_ERROR, "Missing key or no key/value separator found after key '%s'\n", key);
00288         av_free(key);
00289         return AVERROR(EINVAL);
00290     }
00291 
00292     av_log(ctx, AV_LOG_DEBUG, "Setting value '%s' for key '%s'\n", val, key);
00293 
00294     ret = av_set_string3(ctx, key, val, 1, NULL);
00295     if (ret == AVERROR(ENOENT))
00296         av_log(ctx, AV_LOG_ERROR, "Key '%s' not found.\n", key);
00297 
00298     av_free(key);
00299     av_free(val);
00300     return ret;
00301 }
00302 
00303 int av_set_options_string(void *ctx, const char *opts,
00304                           const char *key_val_sep, const char *pairs_sep)
00305 {
00306     int ret, count = 0;
00307 
00308     while (*opts) {
00309         if ((ret = parse_key_value_pair(ctx, &opts, key_val_sep, pairs_sep)) < 0)
00310             return ret;
00311         count++;
00312 
00313         if (*opts)
00314             opts++;
00315     }
00316 
00317     return count;
00318 }
00319 
00320 #ifdef TEST
00321 
00322 #undef printf
00323 
00324 typedef struct TestContext
00325 {
00326     const AVClass *class;
00327     int num;
00328     int toggle;
00329     char *string;
00330     int flags;
00331     AVRational rational;
00332 } TestContext;
00333 
00334 #define OFFSET(x) offsetof(TestContext, x)
00335 
00336 #define TEST_FLAG_COOL 01
00337 #define TEST_FLAG_LAME 02
00338 #define TEST_FLAG_MU   04
00339 
00340 static const AVOption test_options[]= {
00341 {"num",      "set num",        OFFSET(num),      FF_OPT_TYPE_INT,      0,              0,        100                 },
00342 {"toggle",   "set toggle",     OFFSET(toggle),   FF_OPT_TYPE_INT,      0,              0,        1                   },
00343 {"rational", "set rational",   OFFSET(rational), FF_OPT_TYPE_RATIONAL, 0,              0,        10                  },
00344 {"string",   "set string",     OFFSET(string),   FF_OPT_TYPE_STRING,   0,              CHAR_MIN, CHAR_MAX            },
00345 {"flags",    "set flags",      OFFSET(flags),    FF_OPT_TYPE_FLAGS,    0,              0,        INT_MAX, 0, "flags" },
00346 {"cool",     "set cool flag ", 0,                FF_OPT_TYPE_CONST,    TEST_FLAG_COOL, INT_MIN,  INT_MAX, 0, "flags" },
00347 {"lame",     "set lame flag ", 0,                FF_OPT_TYPE_CONST,    TEST_FLAG_LAME, INT_MIN,  INT_MAX, 0, "flags" },
00348 {"mu",       "set mu flag ",   0,                FF_OPT_TYPE_CONST,    TEST_FLAG_MU,   INT_MIN,  INT_MAX, 0, "flags" },
00349 {NULL},
00350 };
00351 
00352 static const char *test_get_name(void *ctx)
00353 {
00354     return "test";
00355 }
00356 
00357 static const AVClass test_class = {
00358     "TestContext",
00359     test_get_name,
00360     test_options
00361 };
00362 
00363 int main(void)
00364 {
00365     int i;
00366 
00367     const char *strings[] = {
00368         "''",
00369         "",
00370         ":",
00371         "\\",
00372         "'",
00373         "    ''    :",
00374         "    ''  ''  :",
00375         "foo   '' :",
00376         "'foo'",
00377         "foo     ",
00378         "foo\\",
00379         "foo':  blah:blah",
00380         "foo\\:  blah:blah",
00381         "foo\'",
00382         "'foo :  '  :blahblah",
00383         "\\ :blah",
00384         "     foo",
00385         "      foo       ",
00386         "      foo     \\ ",
00387         "foo ':blah",
00388         " foo   bar    :   blahblah",
00389         "\\f\\o\\o",
00390         "'foo : \\ \\  '   : blahblah",
00391         "'\\fo\\o:': blahblah",
00392         "\\'fo\\o\\:':  foo  '  :blahblah"
00393     };
00394 
00395     for (i=0; i < FF_ARRAY_ELEMS(strings); i++) {
00396         const char *p= strings[i];
00397         printf("|%s|", p);
00398         printf(" -> |%s|", av_get_token(&p, ":"));
00399         printf(" + |%s|\n", p);
00400     }
00401 
00402     printf("\nTesting av_parse_color()\n");
00403     {
00404         uint8_t rgba[4];
00405         const char *color_names[] = {
00406             "bikeshed",
00407             "RaNdOm",
00408             "foo",
00409             "red",
00410             "Red ",
00411             "RED",
00412             "Violet",
00413             "Yellow",
00414             "Red",
00415             "0x000000",
00416             "0x0000000",
00417             "0xff000000",
00418             "0x3e34ff",
00419             "0x3e34ffaa",
00420             "0xffXXee",
00421             "0xfoobar",
00422             "0xffffeeeeeeee",
00423         };
00424 
00425         av_log_set_level(AV_LOG_DEBUG);
00426 
00427         for (int i = 0;  i < FF_ARRAY_ELEMS(color_names); i++) {
00428             if (av_parse_color(rgba, color_names[i], NULL) >= 0)
00429                 printf("%s -> R(%d) G(%d) B(%d) A(%d)\n", color_names[i], rgba[0], rgba[1], rgba[2], rgba[3]);
00430         }
00431     }
00432 
00433     printf("\nTesting av_set_options_string()\n");
00434     {
00435         TestContext test_ctx;
00436         const char *options[] = {
00437             "",
00438             ":",
00439             "=",
00440             "foo=:",
00441             ":=foo",
00442             "=foo",
00443             "foo=",
00444             "foo",
00445             "foo=val",
00446             "foo==val",
00447             "toggle=:",
00448             "string=:",
00449             "toggle=1 : foo",
00450             "toggle=100",
00451             "toggle==1",
00452             "flags=+mu-lame : num=42: toggle=0",
00453             "num=42 : string=blahblah",
00454             "rational=0 : rational=1/2 : rational=1/-1",
00455             "rational=-1/0",
00456         };
00457 
00458         test_ctx.class = &test_class;
00459         av_opt_set_defaults2(&test_ctx, 0, 0);
00460         test_ctx.string = av_strdup("default");
00461 
00462         av_log_set_level(AV_LOG_DEBUG);
00463 
00464         for (i=0; i < FF_ARRAY_ELEMS(options); i++) {
00465             av_log(&test_ctx, AV_LOG_DEBUG, "Setting options string '%s'\n", options[i]);
00466             if (av_set_options_string(&test_ctx, options[i], "=", ":") < 0)
00467                 av_log(&test_ctx, AV_LOG_ERROR, "Error setting options string: '%s'\n", options[i]);
00468             printf("\n");
00469         }
00470     }
00471 
00472     return 0;
00473 }
00474 
00475 #endif

Generated on Fri Sep 16 2011 17:17:47 for FFmpeg by  doxygen 1.7.1