00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00024 #include <strings.h>
00025 #include "parseutils.h"
00026 #include "libavutil/avutil.h"
00027 #include "libavutil/eval.h"
00028 #include "libavutil/avstring.h"
00029 #include "libavutil/random_seed.h"
00030
00031 typedef struct {
00032 const char *abbr;
00033 int width, height;
00034 } VideoSizeAbbr;
00035
00036 typedef struct {
00037 const char *abbr;
00038 AVRational rate;
00039 } VideoRateAbbr;
00040
00041 static const VideoSizeAbbr video_size_abbrs[] = {
00042 { "ntsc", 720, 480 },
00043 { "pal", 720, 576 },
00044 { "qntsc", 352, 240 },
00045 { "qpal", 352, 288 },
00046 { "sntsc", 640, 480 },
00047 { "spal", 768, 576 },
00048 { "film", 352, 240 },
00049 { "ntsc-film", 352, 240 },
00050 { "sqcif", 128, 96 },
00051 { "qcif", 176, 144 },
00052 { "cif", 352, 288 },
00053 { "4cif", 704, 576 },
00054 { "16cif", 1408,1152 },
00055 { "qqvga", 160, 120 },
00056 { "qvga", 320, 240 },
00057 { "vga", 640, 480 },
00058 { "svga", 800, 600 },
00059 { "xga", 1024, 768 },
00060 { "uxga", 1600,1200 },
00061 { "qxga", 2048,1536 },
00062 { "sxga", 1280,1024 },
00063 { "qsxga", 2560,2048 },
00064 { "hsxga", 5120,4096 },
00065 { "wvga", 852, 480 },
00066 { "wxga", 1366, 768 },
00067 { "wsxga", 1600,1024 },
00068 { "wuxga", 1920,1200 },
00069 { "woxga", 2560,1600 },
00070 { "wqsxga", 3200,2048 },
00071 { "wquxga", 3840,2400 },
00072 { "whsxga", 6400,4096 },
00073 { "whuxga", 7680,4800 },
00074 { "cga", 320, 200 },
00075 { "ega", 640, 350 },
00076 { "hd480", 852, 480 },
00077 { "hd720", 1280, 720 },
00078 { "hd1080", 1920,1080 },
00079 };
00080
00081 static const VideoRateAbbr video_rate_abbrs[]= {
00082 { "ntsc", { 30000, 1001 } },
00083 { "pal", { 25, 1 } },
00084 { "qntsc", { 30000, 1001 } },
00085 { "qpal", { 25, 1 } },
00086 { "sntsc", { 30000, 1001 } },
00087 { "spal", { 25, 1 } },
00088 { "film", { 24, 1 } },
00089 { "ntsc-film", { 24000, 1001 } },
00090 };
00091
00092 int av_parse_video_size(int *width_ptr, int *height_ptr, const char *str)
00093 {
00094 int i;
00095 int n = FF_ARRAY_ELEMS(video_size_abbrs);
00096 char *p;
00097 int width = 0, height = 0;
00098
00099 for (i = 0; i < n; i++) {
00100 if (!strcmp(video_size_abbrs[i].abbr, str)) {
00101 width = video_size_abbrs[i].width;
00102 height = video_size_abbrs[i].height;
00103 break;
00104 }
00105 }
00106 if (i == n) {
00107 p = str;
00108 width = strtol(p, &p, 10);
00109 if (*p)
00110 p++;
00111 height = strtol(p, &p, 10);
00112 }
00113 if (width <= 0 || height <= 0)
00114 return AVERROR(EINVAL);
00115 *width_ptr = width;
00116 *height_ptr = height;
00117 return 0;
00118 }
00119
00120 int av_parse_video_rate(AVRational *rate, const char *arg)
00121 {
00122 int i, ret;
00123 int n = FF_ARRAY_ELEMS(video_rate_abbrs);
00124 double res;
00125
00126
00127 for (i = 0; i < n; ++i)
00128 if (!strcmp(video_rate_abbrs[i].abbr, arg)) {
00129 *rate = video_rate_abbrs[i].rate;
00130 return 0;
00131 }
00132
00133
00134 if ((ret = av_expr_parse_and_eval(&res, arg, NULL, NULL, NULL, NULL, NULL, NULL,
00135 NULL, 0, NULL)) < 0)
00136 return ret;
00137 *rate = av_d2q(res, 1001000);
00138 if (rate->num <= 0 || rate->den <= 0)
00139 return AVERROR(EINVAL);
00140 return 0;
00141 }
00142
00143 typedef struct {
00144 const char *name;
00145 uint8_t rgb_color[3];
00146 } ColorEntry;
00147
00148 static ColorEntry color_table[] = {
00149 { "AliceBlue", { 0xF0, 0xF8, 0xFF } },
00150 { "AntiqueWhite", { 0xFA, 0xEB, 0xD7 } },
00151 { "Aqua", { 0x00, 0xFF, 0xFF } },
00152 { "Aquamarine", { 0x7F, 0xFF, 0xD4 } },
00153 { "Azure", { 0xF0, 0xFF, 0xFF } },
00154 { "Beige", { 0xF5, 0xF5, 0xDC } },
00155 { "Bisque", { 0xFF, 0xE4, 0xC4 } },
00156 { "Black", { 0x00, 0x00, 0x00 } },
00157 { "BlanchedAlmond", { 0xFF, 0xEB, 0xCD } },
00158 { "Blue", { 0x00, 0x00, 0xFF } },
00159 { "BlueViolet", { 0x8A, 0x2B, 0xE2 } },
00160 { "Brown", { 0xA5, 0x2A, 0x2A } },
00161 { "BurlyWood", { 0xDE, 0xB8, 0x87 } },
00162 { "CadetBlue", { 0x5F, 0x9E, 0xA0 } },
00163 { "Chartreuse", { 0x7F, 0xFF, 0x00 } },
00164 { "Chocolate", { 0xD2, 0x69, 0x1E } },
00165 { "Coral", { 0xFF, 0x7F, 0x50 } },
00166 { "CornflowerBlue", { 0x64, 0x95, 0xED } },
00167 { "Cornsilk", { 0xFF, 0xF8, 0xDC } },
00168 { "Crimson", { 0xDC, 0x14, 0x3C } },
00169 { "Cyan", { 0x00, 0xFF, 0xFF } },
00170 { "DarkBlue", { 0x00, 0x00, 0x8B } },
00171 { "DarkCyan", { 0x00, 0x8B, 0x8B } },
00172 { "DarkGoldenRod", { 0xB8, 0x86, 0x0B } },
00173 { "DarkGray", { 0xA9, 0xA9, 0xA9 } },
00174 { "DarkGreen", { 0x00, 0x64, 0x00 } },
00175 { "DarkKhaki", { 0xBD, 0xB7, 0x6B } },
00176 { "DarkMagenta", { 0x8B, 0x00, 0x8B } },
00177 { "DarkOliveGreen", { 0x55, 0x6B, 0x2F } },
00178 { "Darkorange", { 0xFF, 0x8C, 0x00 } },
00179 { "DarkOrchid", { 0x99, 0x32, 0xCC } },
00180 { "DarkRed", { 0x8B, 0x00, 0x00 } },
00181 { "DarkSalmon", { 0xE9, 0x96, 0x7A } },
00182 { "DarkSeaGreen", { 0x8F, 0xBC, 0x8F } },
00183 { "DarkSlateBlue", { 0x48, 0x3D, 0x8B } },
00184 { "DarkSlateGray", { 0x2F, 0x4F, 0x4F } },
00185 { "DarkTurquoise", { 0x00, 0xCE, 0xD1 } },
00186 { "DarkViolet", { 0x94, 0x00, 0xD3 } },
00187 { "DeepPink", { 0xFF, 0x14, 0x93 } },
00188 { "DeepSkyBlue", { 0x00, 0xBF, 0xFF } },
00189 { "DimGray", { 0x69, 0x69, 0x69 } },
00190 { "DodgerBlue", { 0x1E, 0x90, 0xFF } },
00191 { "FireBrick", { 0xB2, 0x22, 0x22 } },
00192 { "FloralWhite", { 0xFF, 0xFA, 0xF0 } },
00193 { "ForestGreen", { 0x22, 0x8B, 0x22 } },
00194 { "Fuchsia", { 0xFF, 0x00, 0xFF } },
00195 { "Gainsboro", { 0xDC, 0xDC, 0xDC } },
00196 { "GhostWhite", { 0xF8, 0xF8, 0xFF } },
00197 { "Gold", { 0xFF, 0xD7, 0x00 } },
00198 { "GoldenRod", { 0xDA, 0xA5, 0x20 } },
00199 { "Gray", { 0x80, 0x80, 0x80 } },
00200 { "Green", { 0x00, 0x80, 0x00 } },
00201 { "GreenYellow", { 0xAD, 0xFF, 0x2F } },
00202 { "HoneyDew", { 0xF0, 0xFF, 0xF0 } },
00203 { "HotPink", { 0xFF, 0x69, 0xB4 } },
00204 { "IndianRed", { 0xCD, 0x5C, 0x5C } },
00205 { "Indigo", { 0x4B, 0x00, 0x82 } },
00206 { "Ivory", { 0xFF, 0xFF, 0xF0 } },
00207 { "Khaki", { 0xF0, 0xE6, 0x8C } },
00208 { "Lavender", { 0xE6, 0xE6, 0xFA } },
00209 { "LavenderBlush", { 0xFF, 0xF0, 0xF5 } },
00210 { "LawnGreen", { 0x7C, 0xFC, 0x00 } },
00211 { "LemonChiffon", { 0xFF, 0xFA, 0xCD } },
00212 { "LightBlue", { 0xAD, 0xD8, 0xE6 } },
00213 { "LightCoral", { 0xF0, 0x80, 0x80 } },
00214 { "LightCyan", { 0xE0, 0xFF, 0xFF } },
00215 { "LightGoldenRodYellow", { 0xFA, 0xFA, 0xD2 } },
00216 { "LightGrey", { 0xD3, 0xD3, 0xD3 } },
00217 { "LightGreen", { 0x90, 0xEE, 0x90 } },
00218 { "LightPink", { 0xFF, 0xB6, 0xC1 } },
00219 { "LightSalmon", { 0xFF, 0xA0, 0x7A } },
00220 { "LightSeaGreen", { 0x20, 0xB2, 0xAA } },
00221 { "LightSkyBlue", { 0x87, 0xCE, 0xFA } },
00222 { "LightSlateGray", { 0x77, 0x88, 0x99 } },
00223 { "LightSteelBlue", { 0xB0, 0xC4, 0xDE } },
00224 { "LightYellow", { 0xFF, 0xFF, 0xE0 } },
00225 { "Lime", { 0x00, 0xFF, 0x00 } },
00226 { "LimeGreen", { 0x32, 0xCD, 0x32 } },
00227 { "Linen", { 0xFA, 0xF0, 0xE6 } },
00228 { "Magenta", { 0xFF, 0x00, 0xFF } },
00229 { "Maroon", { 0x80, 0x00, 0x00 } },
00230 { "MediumAquaMarine", { 0x66, 0xCD, 0xAA } },
00231 { "MediumBlue", { 0x00, 0x00, 0xCD } },
00232 { "MediumOrchid", { 0xBA, 0x55, 0xD3 } },
00233 { "MediumPurple", { 0x93, 0x70, 0xD8 } },
00234 { "MediumSeaGreen", { 0x3C, 0xB3, 0x71 } },
00235 { "MediumSlateBlue", { 0x7B, 0x68, 0xEE } },
00236 { "MediumSpringGreen", { 0x00, 0xFA, 0x9A } },
00237 { "MediumTurquoise", { 0x48, 0xD1, 0xCC } },
00238 { "MediumVioletRed", { 0xC7, 0x15, 0x85 } },
00239 { "MidnightBlue", { 0x19, 0x19, 0x70 } },
00240 { "MintCream", { 0xF5, 0xFF, 0xFA } },
00241 { "MistyRose", { 0xFF, 0xE4, 0xE1 } },
00242 { "Moccasin", { 0xFF, 0xE4, 0xB5 } },
00243 { "NavajoWhite", { 0xFF, 0xDE, 0xAD } },
00244 { "Navy", { 0x00, 0x00, 0x80 } },
00245 { "OldLace", { 0xFD, 0xF5, 0xE6 } },
00246 { "Olive", { 0x80, 0x80, 0x00 } },
00247 { "OliveDrab", { 0x6B, 0x8E, 0x23 } },
00248 { "Orange", { 0xFF, 0xA5, 0x00 } },
00249 { "OrangeRed", { 0xFF, 0x45, 0x00 } },
00250 { "Orchid", { 0xDA, 0x70, 0xD6 } },
00251 { "PaleGoldenRod", { 0xEE, 0xE8, 0xAA } },
00252 { "PaleGreen", { 0x98, 0xFB, 0x98 } },
00253 { "PaleTurquoise", { 0xAF, 0xEE, 0xEE } },
00254 { "PaleVioletRed", { 0xD8, 0x70, 0x93 } },
00255 { "PapayaWhip", { 0xFF, 0xEF, 0xD5 } },
00256 { "PeachPuff", { 0xFF, 0xDA, 0xB9 } },
00257 { "Peru", { 0xCD, 0x85, 0x3F } },
00258 { "Pink", { 0xFF, 0xC0, 0xCB } },
00259 { "Plum", { 0xDD, 0xA0, 0xDD } },
00260 { "PowderBlue", { 0xB0, 0xE0, 0xE6 } },
00261 { "Purple", { 0x80, 0x00, 0x80 } },
00262 { "Red", { 0xFF, 0x00, 0x00 } },
00263 { "RosyBrown", { 0xBC, 0x8F, 0x8F } },
00264 { "RoyalBlue", { 0x41, 0x69, 0xE1 } },
00265 { "SaddleBrown", { 0x8B, 0x45, 0x13 } },
00266 { "Salmon", { 0xFA, 0x80, 0x72 } },
00267 { "SandyBrown", { 0xF4, 0xA4, 0x60 } },
00268 { "SeaGreen", { 0x2E, 0x8B, 0x57 } },
00269 { "SeaShell", { 0xFF, 0xF5, 0xEE } },
00270 { "Sienna", { 0xA0, 0x52, 0x2D } },
00271 { "Silver", { 0xC0, 0xC0, 0xC0 } },
00272 { "SkyBlue", { 0x87, 0xCE, 0xEB } },
00273 { "SlateBlue", { 0x6A, 0x5A, 0xCD } },
00274 { "SlateGray", { 0x70, 0x80, 0x90 } },
00275 { "Snow", { 0xFF, 0xFA, 0xFA } },
00276 { "SpringGreen", { 0x00, 0xFF, 0x7F } },
00277 { "SteelBlue", { 0x46, 0x82, 0xB4 } },
00278 { "Tan", { 0xD2, 0xB4, 0x8C } },
00279 { "Teal", { 0x00, 0x80, 0x80 } },
00280 { "Thistle", { 0xD8, 0xBF, 0xD8 } },
00281 { "Tomato", { 0xFF, 0x63, 0x47 } },
00282 { "Turquoise", { 0x40, 0xE0, 0xD0 } },
00283 { "Violet", { 0xEE, 0x82, 0xEE } },
00284 { "Wheat", { 0xF5, 0xDE, 0xB3 } },
00285 { "White", { 0xFF, 0xFF, 0xFF } },
00286 { "WhiteSmoke", { 0xF5, 0xF5, 0xF5 } },
00287 { "Yellow", { 0xFF, 0xFF, 0x00 } },
00288 { "YellowGreen", { 0x9A, 0xCD, 0x32 } },
00289 };
00290
00291 static int color_table_compare(const void *lhs, const void *rhs)
00292 {
00293 return strcasecmp(lhs, ((const ColorEntry *)rhs)->name);
00294 }
00295
00296 #define ALPHA_SEP '@'
00297
00298 int av_parse_color(uint8_t *rgba_color, const char *color_string, int slen,
00299 void *log_ctx)
00300 {
00301 char *tail, color_string2[128];
00302 const ColorEntry *entry;
00303 int len, hex_offset = 0;
00304
00305 if (color_string[0] == '#') {
00306 hex_offset = 1;
00307 } else if (!strncmp(color_string, "0x", 2))
00308 hex_offset = 2;
00309
00310 if (slen < 0)
00311 slen = strlen(color_string);
00312 av_strlcpy(color_string2, color_string + hex_offset,
00313 FFMIN(slen-hex_offset+1, sizeof(color_string2)));
00314 if ((tail = strchr(color_string2, ALPHA_SEP)))
00315 *tail++ = 0;
00316 len = strlen(color_string2);
00317 rgba_color[3] = 255;
00318
00319 if (!strcasecmp(color_string2, "random") || !strcasecmp(color_string2, "bikeshed")) {
00320 int rgba = av_get_random_seed();
00321 rgba_color[0] = rgba >> 24;
00322 rgba_color[1] = rgba >> 16;
00323 rgba_color[2] = rgba >> 8;
00324 rgba_color[3] = rgba;
00325 } else if (hex_offset ||
00326 strspn(color_string2, "0123456789ABCDEFabcdef") == len) {
00327 char *tail;
00328 unsigned int rgba = strtoul(color_string2, &tail, 16);
00329
00330 if (*tail || (len != 6 && len != 8)) {
00331 av_log(log_ctx, AV_LOG_ERROR, "Invalid 0xRRGGBB[AA] color string: '%s'\n", color_string2);
00332 return AVERROR(EINVAL);
00333 }
00334 if (len == 8) {
00335 rgba_color[3] = rgba;
00336 rgba >>= 8;
00337 }
00338 rgba_color[0] = rgba >> 16;
00339 rgba_color[1] = rgba >> 8;
00340 rgba_color[2] = rgba;
00341 } else {
00342 entry = bsearch(color_string2,
00343 color_table,
00344 FF_ARRAY_ELEMS(color_table),
00345 sizeof(ColorEntry),
00346 color_table_compare);
00347 if (!entry) {
00348 av_log(log_ctx, AV_LOG_ERROR, "Cannot find color '%s'\n", color_string2);
00349 return AVERROR(EINVAL);
00350 }
00351 memcpy(rgba_color, entry->rgb_color, 3);
00352 }
00353
00354 if (tail) {
00355 unsigned long int alpha;
00356 const char *alpha_string = tail;
00357 if (!strncmp(alpha_string, "0x", 2)) {
00358 alpha = strtoul(alpha_string, &tail, 16);
00359 } else {
00360 alpha = 255 * strtod(alpha_string, &tail);
00361 }
00362
00363 if (tail == alpha_string || *tail || alpha > 255) {
00364 av_log(log_ctx, AV_LOG_ERROR, "Invalid alpha value specifier '%s' in '%s'\n",
00365 alpha_string, color_string);
00366 return AVERROR(EINVAL);
00367 }
00368 rgba_color[3] = alpha;
00369 }
00370
00371 return 0;
00372 }
00373
00374 #ifdef TEST
00375
00376 #undef printf
00377
00378 int main(void)
00379 {
00380 printf("Testing av_parse_video_rate()\n");
00381 {
00382 int i;
00383 const char *rates[] = {
00384 "-inf",
00385 "inf",
00386 "nan",
00387 "123/0",
00388 "-123 / 0",
00389 "",
00390 "/",
00391 " 123 / 321",
00392 "foo/foo",
00393 "foo/1",
00394 "1/foo",
00395 "0/0",
00396 "/0",
00397 "1/",
00398 "1",
00399 "0",
00400 "-123/123",
00401 "-foo",
00402 "123.23",
00403 ".23",
00404 "-.23",
00405 "-0.234",
00406 "-0.0000001",
00407 " 21332.2324 ",
00408 " -21332.2324 ",
00409 };
00410
00411 for (i = 0; i < FF_ARRAY_ELEMS(rates); i++) {
00412 int ret;
00413 AVRational q = (AVRational){0, 0};
00414 ret = av_parse_video_rate(&q, rates[i]),
00415 printf("'%s' -> %d/%d ret:%d\n",
00416 rates[i], q.num, q.den, ret);
00417 }
00418 }
00419
00420 printf("\nTesting av_parse_color()\n");
00421 {
00422 int i;
00423 uint8_t rgba[4];
00424 const char *color_names[] = {
00425 "bikeshed",
00426 "RaNdOm",
00427 "foo",
00428 "red",
00429 "Red ",
00430 "RED",
00431 "Violet",
00432 "Yellow",
00433 "Red",
00434 "0x000000",
00435 "0x0000000",
00436 "0xff000000",
00437 "0x3e34ff",
00438 "0x3e34ffaa",
00439 "0xffXXee",
00440 "0xfoobar",
00441 "0xffffeeeeeeee",
00442 "#ff0000",
00443 "#ffXX00",
00444 "ff0000",
00445 "ffXX00",
00446 "red@foo",
00447 "random@10",
00448 "0xff0000@1.0",
00449 "red@",
00450 "red@0xfff",
00451 "red@0xf",
00452 "red@2",
00453 "red@0.1",
00454 "red@-1",
00455 "red@0.5",
00456 "red@1.0",
00457 "red@256",
00458 "red@10foo",
00459 "red@-1.0",
00460 "red@-0.0",
00461 };
00462
00463 av_log_set_level(AV_LOG_DEBUG);
00464
00465 for (i = 0; i < FF_ARRAY_ELEMS(color_names); i++) {
00466 if (av_parse_color(rgba, color_names[i], -1, NULL) >= 0)
00467 printf("%s -> R(%d) G(%d) B(%d) A(%d)\n", color_names[i], rgba[0], rgba[1], rgba[2], rgba[3]);
00468 }
00469 }
00470
00471 return 0;
00472 }
00473
00474 #endif