1 /*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 /**
20 * @file
21 * misc parsing utilities
22 */
23
25
34
35 #ifdef TEST
36
37 #define av_get_random_seed av_get_random_seed_deterministic
38 static uint32_t av_get_random_seed_deterministic(void);
39
40 #define time(t) 1331972053
41
42 #endif
43
45 int log_offset, void *log_ctx)
46 {
49
50 if (sscanf(str,
"%d:%d%c", &q->
num, &q->
den, &c) != 2) {
51 double d;
54 NULL, log_offset, log_ctx);
55 if (ret < 0)
58 } else {
60 }
61
62 return 0;
63 }
64
69
74
76 { "ntsc", 720, 480 },
77 { "pal", 720, 576 },
78 { "qntsc", 352, 240 }, /* VCD compliant NTSC */
79 { "qpal", 352, 288 }, /* VCD compliant PAL */
80 { "sntsc", 640, 480 }, /* square pixel NTSC */
81 { "spal", 768, 576 }, /* square pixel PAL */
82 { "film", 352, 240 },
83 { "ntsc-film", 352, 240 },
84 { "sqcif", 128, 96 },
85 { "qcif", 176, 144 },
86 { "cif", 352, 288 },
87 { "4cif", 704, 576 },
88 { "16cif", 1408,1152 },
89 { "qqvga", 160, 120 },
90 { "qvga", 320, 240 },
91 { "vga", 640, 480 },
92 { "svga", 800, 600 },
93 { "xga", 1024, 768 },
94 { "uxga", 1600,1200 },
95 { "qxga", 2048,1536 },
96 { "sxga", 1280,1024 },
97 { "qsxga", 2560,2048 },
98 { "hsxga", 5120,4096 },
99 { "wvga", 852, 480 },
100 { "wxga", 1366, 768 },
101 { "wsxga", 1600,1024 },
102 { "wuxga", 1920,1200 },
103 { "woxga", 2560,1600 },
104 { "wqsxga", 3200,2048 },
105 { "wquxga", 3840,2400 },
106 { "whsxga", 6400,4096 },
107 { "whuxga", 7680,4800 },
108 { "cga", 320, 200 },
109 { "ega", 640, 350 },
110 { "hd480", 852, 480 },
111 { "hd720", 1280, 720 },
112 { "hd1080", 1920,1080 },
113 { "2k", 2048,1080 }, /* Digital Cinema System Specification */
114 { "2kflat", 1998,1080 },
115 { "2kscope", 2048, 858 },
116 { "4k", 4096,2160 }, /* Digital Cinema System Specification */
117 { "4kflat", 3996,2160 },
118 { "4kscope", 4096,1716 },
119 { "nhd", 640,360 },
120 { "hqvga", 240,160 },
121 { "wqvga", 400,240 },
122 { "fwqvga", 432,240 },
123 { "hvga", 480,320 },
124 { "qhd", 960,540 },
125 };
126
128 { "ntsc", { 30000, 1001 } },
129 { "pal", { 25, 1 } },
130 { "qntsc", { 30000, 1001 } }, /* VCD compliant NTSC */
131 { "qpal", { 25, 1 } }, /* VCD compliant PAL */
132 { "sntsc", { 30000, 1001 } }, /* square pixel NTSC */
133 { "spal", { 25, 1 } }, /* square pixel PAL */
134 { "film", { 24, 1 } },
135 { "ntsc-film", { 24000, 1001 } },
136 };
137
139 {
140 int i;
142 const char *p;
144
145 for (i = 0; i <
n; i++) {
146 if (!strcmp(video_size_abbrs[i].abbr, str)) {
147 width = video_size_abbrs[i].
width;
149 break;
150 }
151 }
152 if (i == n) {
153 width = strtol(str, (void*)&p, 10);
154 if (*p)
155 p++;
156 height = strtol(p, (
void*)&p, 10);
157
158 /* trailing extraneous data detected, like in 123x345foobar */
159 if (*p)
161 }
162 if (width <= 0 ||
height <= 0)
166 return 0;
167 }
168
170 {
173
174 /* First, we check our abbreviation table */
175 for (i = 0; i <
n; ++i)
176 if (!strcmp(video_rate_abbrs[i].abbr, arg)) {
177 *rate = video_rate_abbrs[i].
rate;
178 return 0;
179 }
180
181 /* Then, we try to parse it as fraction */
184 if (rate->
num <= 0 || rate->
den <= 0)
186 return 0;
187 }
188
190 const char *
name;
///< a string representing the name of the color
193
195 { "AliceBlue", { 0xF0, 0xF8, 0xFF } },
196 { "AntiqueWhite", { 0xFA, 0xEB, 0xD7 } },
197 { "Aqua", { 0x00, 0xFF, 0xFF } },
198 { "Aquamarine", { 0x7F, 0xFF, 0xD4 } },
199 { "Azure", { 0xF0, 0xFF, 0xFF } },
200 { "Beige", { 0xF5, 0xF5, 0xDC } },
201 { "Bisque", { 0xFF, 0xE4, 0xC4 } },
202 { "Black", { 0x00, 0x00, 0x00 } },
203 { "BlanchedAlmond", { 0xFF, 0xEB, 0xCD } },
204 { "Blue", { 0x00, 0x00, 0xFF } },
205 { "BlueViolet", { 0x8A, 0x2B, 0xE2 } },
206 { "Brown", { 0xA5, 0x2A, 0x2A } },
207 { "BurlyWood", { 0xDE, 0xB8, 0x87 } },
208 { "CadetBlue", { 0x5F, 0x9E, 0xA0 } },
209 { "Chartreuse", { 0x7F, 0xFF, 0x00 } },
210 { "Chocolate", { 0xD2, 0x69, 0x1E } },
211 { "Coral", { 0xFF, 0x7F, 0x50 } },
212 { "CornflowerBlue", { 0x64, 0x95, 0xED } },
213 { "Cornsilk", { 0xFF, 0xF8, 0xDC } },
214 { "Crimson", { 0xDC, 0x14, 0x3C } },
215 { "Cyan", { 0x00, 0xFF, 0xFF } },
216 { "DarkBlue", { 0x00, 0x00, 0x8B } },
217 { "DarkCyan", { 0x00, 0x8B, 0x8B } },
218 { "DarkGoldenRod", { 0xB8, 0x86, 0x0B } },
219 { "DarkGray", { 0xA9, 0xA9, 0xA9 } },
220 { "DarkGreen", { 0x00, 0x64, 0x00 } },
221 { "DarkKhaki", { 0xBD, 0xB7, 0x6B } },
222 { "DarkMagenta", { 0x8B, 0x00, 0x8B } },
223 { "DarkOliveGreen", { 0x55, 0x6B, 0x2F } },
224 { "Darkorange", { 0xFF, 0x8C, 0x00 } },
225 { "DarkOrchid", { 0x99, 0x32, 0xCC } },
226 { "DarkRed", { 0x8B, 0x00, 0x00 } },
227 { "DarkSalmon", { 0xE9, 0x96, 0x7A } },
228 { "DarkSeaGreen", { 0x8F, 0xBC, 0x8F } },
229 { "DarkSlateBlue", { 0x48, 0x3D, 0x8B } },
230 { "DarkSlateGray", { 0x2F, 0x4F, 0x4F } },
231 { "DarkTurquoise", { 0x00, 0xCE, 0xD1 } },
232 { "DarkViolet", { 0x94, 0x00, 0xD3 } },
233 { "DeepPink", { 0xFF, 0x14, 0x93 } },
234 { "DeepSkyBlue", { 0x00, 0xBF, 0xFF } },
235 { "DimGray", { 0x69, 0x69, 0x69 } },
236 { "DodgerBlue", { 0x1E, 0x90, 0xFF } },
237 { "FireBrick", { 0xB2, 0x22, 0x22 } },
238 { "FloralWhite", { 0xFF, 0xFA, 0xF0 } },
239 { "ForestGreen", { 0x22, 0x8B, 0x22 } },
240 { "Fuchsia", { 0xFF, 0x00, 0xFF } },
241 { "Gainsboro", { 0xDC, 0xDC, 0xDC } },
242 { "GhostWhite", { 0xF8, 0xF8, 0xFF } },
243 { "Gold", { 0xFF, 0xD7, 0x00 } },
244 { "GoldenRod", { 0xDA, 0xA5, 0x20 } },
245 { "Gray", { 0x80, 0x80, 0x80 } },
246 { "Green", { 0x00, 0x80, 0x00 } },
247 { "GreenYellow", { 0xAD, 0xFF, 0x2F } },
248 { "HoneyDew", { 0xF0, 0xFF, 0xF0 } },
249 { "HotPink", { 0xFF, 0x69, 0xB4 } },
250 { "IndianRed", { 0xCD, 0x5C, 0x5C } },
251 { "Indigo", { 0x4B, 0x00, 0x82 } },
252 { "Ivory", { 0xFF, 0xFF, 0xF0 } },
253 { "Khaki", { 0xF0, 0xE6, 0x8C } },
254 { "Lavender", { 0xE6, 0xE6, 0xFA } },
255 { "LavenderBlush", { 0xFF, 0xF0, 0xF5 } },
256 { "LawnGreen", { 0x7C, 0xFC, 0x00 } },
257 { "LemonChiffon", { 0xFF, 0xFA, 0xCD } },
258 { "LightBlue", { 0xAD, 0xD8, 0xE6 } },
259 { "LightCoral", { 0xF0, 0x80, 0x80 } },
260 { "LightCyan", { 0xE0, 0xFF, 0xFF } },
261 { "LightGoldenRodYellow", { 0xFA, 0xFA, 0xD2 } },
262 { "LightGreen", { 0x90, 0xEE, 0x90 } },
263 { "LightGrey", { 0xD3, 0xD3, 0xD3 } },
264 { "LightPink", { 0xFF, 0xB6, 0xC1 } },
265 { "LightSalmon", { 0xFF, 0xA0, 0x7A } },
266 { "LightSeaGreen", { 0x20, 0xB2, 0xAA } },
267 { "LightSkyBlue", { 0x87, 0xCE, 0xFA } },
268 { "LightSlateGray", { 0x77, 0x88, 0x99 } },
269 { "LightSteelBlue", { 0xB0, 0xC4, 0xDE } },
270 { "LightYellow", { 0xFF, 0xFF, 0xE0 } },
271 { "Lime", { 0x00, 0xFF, 0x00 } },
272 { "LimeGreen", { 0x32, 0xCD, 0x32 } },
273 { "Linen", { 0xFA, 0xF0, 0xE6 } },
274 { "Magenta", { 0xFF, 0x00, 0xFF } },
275 { "Maroon", { 0x80, 0x00, 0x00 } },
276 { "MediumAquaMarine", { 0x66, 0xCD, 0xAA } },
277 { "MediumBlue", { 0x00, 0x00, 0xCD } },
278 { "MediumOrchid", { 0xBA, 0x55, 0xD3 } },
279 { "MediumPurple", { 0x93, 0x70, 0xD8 } },
280 { "MediumSeaGreen", { 0x3C, 0xB3, 0x71 } },
281 { "MediumSlateBlue", { 0x7B, 0x68, 0xEE } },
282 { "MediumSpringGreen", { 0x00, 0xFA, 0x9A } },
283 { "MediumTurquoise", { 0x48, 0xD1, 0xCC } },
284 { "MediumVioletRed", { 0xC7, 0x15, 0x85 } },
285 { "MidnightBlue", { 0x19, 0x19, 0x70 } },
286 { "MintCream", { 0xF5, 0xFF, 0xFA } },
287 { "MistyRose", { 0xFF, 0xE4, 0xE1 } },
288 { "Moccasin", { 0xFF, 0xE4, 0xB5 } },
289 { "NavajoWhite", { 0xFF, 0xDE, 0xAD } },
290 { "Navy", { 0x00, 0x00, 0x80 } },
291 { "OldLace", { 0xFD, 0xF5, 0xE6 } },
292 { "Olive", { 0x80, 0x80, 0x00 } },
293 { "OliveDrab", { 0x6B, 0x8E, 0x23 } },
294 { "Orange", { 0xFF, 0xA5, 0x00 } },
295 { "OrangeRed", { 0xFF, 0x45, 0x00 } },
296 { "Orchid", { 0xDA, 0x70, 0xD6 } },
297 { "PaleGoldenRod", { 0xEE, 0xE8, 0xAA } },
298 { "PaleGreen", { 0x98, 0xFB, 0x98 } },
299 { "PaleTurquoise", { 0xAF, 0xEE, 0xEE } },
300 { "PaleVioletRed", { 0xD8, 0x70, 0x93 } },
301 { "PapayaWhip", { 0xFF, 0xEF, 0xD5 } },
302 { "PeachPuff", { 0xFF, 0xDA, 0xB9 } },
303 { "Peru", { 0xCD, 0x85, 0x3F } },
304 { "Pink", { 0xFF, 0xC0, 0xCB } },
305 { "Plum", { 0xDD, 0xA0, 0xDD } },
306 { "PowderBlue", { 0xB0, 0xE0, 0xE6 } },
307 { "Purple", { 0x80, 0x00, 0x80 } },
308 { "Red", { 0xFF, 0x00, 0x00 } },
309 { "RosyBrown", { 0xBC, 0x8F, 0x8F } },
310 { "RoyalBlue", { 0x41, 0x69, 0xE1 } },
311 { "SaddleBrown", { 0x8B, 0x45, 0x13 } },
312 { "Salmon", { 0xFA, 0x80, 0x72 } },
313 { "SandyBrown", { 0xF4, 0xA4, 0x60 } },
314 { "SeaGreen", { 0x2E, 0x8B, 0x57 } },
315 { "SeaShell", { 0xFF, 0xF5, 0xEE } },
316 { "Sienna", { 0xA0, 0x52, 0x2D } },
317 { "Silver", { 0xC0, 0xC0, 0xC0 } },
318 { "SkyBlue", { 0x87, 0xCE, 0xEB } },
319 { "SlateBlue", { 0x6A, 0x5A, 0xCD } },
320 { "SlateGray", { 0x70, 0x80, 0x90 } },
321 { "Snow", { 0xFF, 0xFA, 0xFA } },
322 { "SpringGreen", { 0x00, 0xFF, 0x7F } },
323 { "SteelBlue", { 0x46, 0x82, 0xB4 } },
324 { "Tan", { 0xD2, 0xB4, 0x8C } },
325 { "Teal", { 0x00, 0x80, 0x80 } },
326 { "Thistle", { 0xD8, 0xBF, 0xD8 } },
327 { "Tomato", { 0xFF, 0x63, 0x47 } },
328 { "Turquoise", { 0x40, 0xE0, 0xD0 } },
329 { "Violet", { 0xEE, 0x82, 0xEE } },
330 { "Wheat", { 0xF5, 0xDE, 0xB3 } },
331 { "White", { 0xFF, 0xFF, 0xFF } },
332 { "WhiteSmoke", { 0xF5, 0xF5, 0xF5 } },
333 { "Yellow", { 0xFF, 0xFF, 0x00 } },
334 { "YellowGreen", { 0x9A, 0xCD, 0x32 } },
335 };
336
338 {
340 }
341
342 #define ALPHA_SEP '@'
343
345 void *log_ctx)
346 {
347 char *tail, color_string2[128];
349 int len, hex_offset = 0;
350
351 if (color_string[0] == '#') {
352 hex_offset = 1;
353 } else if (!strncmp(color_string, "0x", 2))
354 hex_offset = 2;
355
356 if (slen < 0)
357 slen = strlen(color_string);
358 av_strlcpy(color_string2, color_string + hex_offset,
359 FFMIN(slen-hex_offset+1,
sizeof(color_string2)));
360 if ((tail = strchr(color_string2,
ALPHA_SEP)))
361 *tail++ = 0;
362 len = strlen(color_string2);
363 rgba_color[3] = 255;
364
367 rgba_color[0] = rgba >> 24;
368 rgba_color[1] = rgba >> 16;
369 rgba_color[2] = rgba >> 8;
370 rgba_color[3] = rgba;
371 } else if (hex_offset ||
372 strspn(color_string2, "0123456789ABCDEFabcdef") == len) {
373 char *tail;
374 unsigned int rgba = strtoul(color_string2, &tail, 16);
375
376 if (*tail || (len != 6 && len != 8)) {
377 av_log(log_ctx,
AV_LOG_ERROR,
"Invalid 0xRRGGBB[AA] color string: '%s'\n", color_string2);
379 }
380 if (len == 8) {
381 rgba_color[3] = rgba;
382 rgba >>= 8;
383 }
384 rgba_color[0] = rgba >> 16;
385 rgba_color[1] = rgba >> 8;
386 rgba_color[2] = rgba;
387 } else {
388 entry = bsearch(color_string2,
389 color_table,
393 if (!entry) {
396 }
398 }
399
400 if (tail) {
402 const char *alpha_string = tail;
403 if (!strncmp(alpha_string, "0x", 2)) {
404 alpha = strtoul(alpha_string, &tail, 16);
405 } else {
406 double norm_alpha =
strtod(alpha_string, &tail);
407 if (norm_alpha < 0.0 || norm_alpha > 1.0)
408 alpha = 256;
409 else
410 alpha = 255 * norm_alpha;
411 }
412
413 if (tail == alpha_string || *tail || alpha > 255 || alpha < 0) {
415 alpha_string, color_string);
417 }
418 rgba_color[3] =
alpha;
419 }
420
421 return 0;
422 }
423
425 {
427
430
431 color = &color_table[color_idx];
432 if (rgbp)
434
436 }
437
438 /* get a positive number between n_min and n_max, for a maximum length
439 of len_max. Return -1 if error. */
441 int n_min, int n_max, int len_max)
442 {
444 const char *p;
445
446 p = *pp;
447 val = 0;
448 for(i = 0; i < len_max; i++) {
449 c = *p;
451 break;
452 val = (val * 10) + c - '0';
453 p++;
454 }
455 /* no number read ? */
456 if (p == *pp)
457 return -1;
458 if (val < n_min || val > n_max)
459 return -1;
460 *pp = p;
462 }
463
465 {
467
468 for(;;) {
469 /* consume time string until a non whitespace char is found */
472 p++;
473 fmt++;
474 }
475 c = *fmt++;
476 if (c == '0円') {
477 return (char *)p;
478 } else if (c == '%') {
479 c = *fmt++;
480 switch(c) {
481 case 'H':
482 case 'J':
484 if (val == -1)
487 break;
488 case 'M':
490 if (val == -1)
493 break;
494 case 'S':
496 if (val == -1)
499 break;
500 case 'Y':
502 if (val == -1)
504 dt->tm_year = val - 1900;
505 break;
506 case 'm':
508 if (val == -1)
510 dt->tm_mon = val - 1;
511 break;
512 case 'd':
514 if (val == -1)
517 break;
518 case '%':
519 goto match;
520 default:
522 }
523 } else {
524 match:
525 if (c != *p)
527 p++;
528 }
529 }
530 }
531
533 {
534 time_t t;
535
536 int y = tm->tm_year + 1900,
m = tm->tm_mon + 1, d = tm->tm_mday;
537
540 y--;
541 }
542
543 t = 86400LL *
544 (d + (153 *
m - 457) / 5 + 365 * y + y / 4 - y / 100 + y / 400 - 719469);
545
546 t += 3600 * tm->tm_hour + 60 * tm->tm_min + tm->tm_sec;
547
548 return t;
549 }
550
552 {
553 const char *p, *q;
554 int64_t t;
555 time_t now;
556 struct tm dt = { 0 }, tmbuf;
557 int today = 0, negative = 0, microseconds = 0;
558 int i;
559 static const char * const date_fmt[] = {
560 "%Y-%m-%d",
561 "%Y%m%d",
562 };
563 static const char * const time_fmt[] = {
564 "%H:%M:%S",
565 "%H%M%S",
566 };
567
568 p = timestr;
570 *timeval = INT64_MIN;
571 if (!duration) {
572 now = time(0);
573
575 *timeval = (int64_t) now * 1000000;
576 return 0;
577 }
578
579 /* parse the year-month-day part */
582 if (q)
583 break;
584 }
585
586 /* if the year-month-day part is missing, then take the
587 * current year-month-day time */
588 if (!q) {
589 today = 1;
590 q = p;
591 }
592 p = q;
593
594 if (*p == 'T' || *p == 't' || *p == ' ')
595 p++;
596
597 /* parse the hour-minute-second part */
600 if (q)
601 break;
602 }
603 } else {
604 /* parse timestr as a duration */
605 if (p[0] == '-') {
606 negative = 1;
607 ++p;
608 }
609 /* parse timestr as HH:MM:SS */
611 if (!q) {
612 /* parse timestr as MM:SS */
614 dt.tm_hour = 0;
615 }
616 if (!q) {
617 char *o;
618 /* parse timestr as S+ */
619 dt.tm_sec = strtol(p, &o, 10);
620 if (o == p) /* the parsing didn't succeed */
622 dt.tm_min = 0;
623 dt.tm_hour = 0;
624 q = o;
625 }
626 }
627
628 /* Now we have all the fields that we can get */
629 if (!q)
631
632 /* parse the .m... part */
633 if (*q == '.') {
635 q++;
636 for (n = 100000; n >= 1; n /= 10, q++) {
638 break;
639 microseconds += n * (*q - '0');
640 }
642 q++;
643 }
644
645 if (duration) {
646 t = dt.tm_hour * 3600 + dt.tm_min * 60 + dt.tm_sec;
647 } else {
648 int is_utc = *q == 'Z' || *q == 'z';
649 q += is_utc;
650 if (today) { /* fill in today's date */
652 dt2.tm_hour = dt.tm_hour;
653 dt2.tm_min = dt.tm_min;
654 dt2.tm_sec = dt.tm_sec;
655 dt = dt2;
656 }
657 t = is_utc ?
av_timegm(&dt) : mktime(&dt);
658 }
659
660 /* Check that we are at the end of the string */
661 if (*q)
663
664 t *= 1000000;
665 t += microseconds;
666 *timeval = negative ? -t : t;
667 return 0;
668 }
669
671 {
672 const char *p;
674
675 p = info;
676 if (*p == '?')
677 p++;
678 for(;;) {
680 while (*p != '0円' && *p != '=' && *p != '&') {
681 if ((q - tag) < sizeof(tag) - 1)
682 *q++ = *p;
683 p++;
684 }
685 *q = '0円';
687 if (*p == '=') {
688 p++;
689 while (*p != '&' && *p != '0円') {
690 if ((q - arg) < arg_size - 1) {
691 if (*p == '+')
692 *q++ = ' ';
693 else
694 *q++ = *p;
695 }
696 p++;
697 }
698 }
699 *q = '0円';
700 if (!strcmp(tag, tag1))
701 return 1;
702 if (*p != '&')
703 break;
704 p++;
705 }
706 return 0;
707 }
708
709 #ifdef TEST
710
711 static uint32_t randomv =
MKTAG(
'L',
'A',
'V',
'U');
712
713 static uint32_t av_get_random_seed_deterministic(void)
714 {
715 return randomv = randomv * 1664525 + 1013904223;
716 }
717
719 {
720 printf("Testing av_parse_video_rate()\n");
721 {
722 int i;
723 static const char *
const rates[] = {
724 "-inf",
725 "inf",
726 "nan",
727 "123/0",
728 "-123 / 0",
729 "",
730 "/",
731 " 123 / 321",
732 "foo/foo",
733 "foo/1",
734 "1/foo",
735 "0/0",
736 "/0",
737 "1/",
738 "1",
739 "0",
740 "-123/123",
741 "-foo",
742 "123.23",
743 ".23",
744 "-.23",
745 "-0.234",
746 "-0.0000001",
747 " 21332.2324 ",
748 " -21332.2324 ",
749 };
750
755 printf("'%s' -> %d/%d %s\n",
756 rates[i], q.
num, q.
den, ret ?
"ERROR" :
"OK");
757 }
758 }
759
760 printf("\nTesting av_parse_color()\n");
761 {
762 int i;
764 static const char *const color_names[] = {
765 "bikeshed",
766 "RaNdOm",
767 "foo",
768 "red",
769 "Red ",
770 "RED",
771 "Violet",
772 "Yellow",
773 "Red",
774 "0x000000",
775 "0x0000000",
776 "0xff000000",
777 "0x3e34ff",
778 "0x3e34ffaa",
779 "0xffXXee",
780 "0xfoobar",
781 "0xffffeeeeeeee",
782 "#ff0000",
783 "#ffXX00",
784 "ff0000",
785 "ffXX00",
786 "red@foo",
787 "random@10",
788 "0xff0000@1.0",
789 "red@",
790 "red@0xfff",
791 "red@0xf",
792 "red@2",
793 "red@0.1",
794 "red@-1",
795 "red@0.5",
796 "red@1.0",
797 "red@256",
798 "red@10foo",
799 "red@-1.0",
800 "red@-0.0",
801 };
802
804
807 printf("%s -> R(%d) G(%d) B(%d) A(%d)\n",
808 color_names[i], rgba[0], rgba[1], rgba[2], rgba[3]);
809 else
810 printf("%s -> error\n", color_names[i]);
811 }
812 }
813
814 printf("\nTesting av_small_strptime()\n");
815 {
816 int i;
817 struct tm tm = { 0 };
818 struct fmt_timespec_entry {
819 const char *
fmt, *timespec;
820 } fmt_timespec_entries[] = {
821 { "%Y-%m-%d", "2012年12月21日" },
822 { "%Y - %m - %d", "2012年12月21日" },
823 { "%Y-%m-%d %H:%M:%S", "2012年12月21日 20:12:21" },
824 { " %Y - %m - %d %H : %M : %S", " 2012 - 12 - 21 20 : 12 : 21" },
825 };
826
829 char *p;
830 struct fmt_timespec_entry *e = &fmt_timespec_entries[i];
831 printf("fmt:'%s' spec:'%s' -> ", e->fmt, e->timespec);
833 if (p) {
834 printf("%04d-%02d-%2d %02d:%02d:%02d\n",
835 1900+tm.tm_year, tm.tm_mon+1, tm.tm_mday,
836 tm.tm_hour, tm.tm_min, tm.tm_sec);
837 } else {
838 printf("error\n");
839 }
840 }
841 }
842
843 printf("\nTesting av_parse_time()\n");
844 {
845 int i;
846 int64_t tv;
847 time_t tvi;
848 struct tm *tm;
849 static char tzstr[] = "TZ=CET-1";
850 static const char * const time_string[] = {
851 "now",
852 "12:35:46",
853 "2000年12月20日 0:02:47.5z",
854 "2000年12月20日T010247.6",
855 };
856 static const char * const duration_string[] = {
857 "2:34:56.79",
858 "-1:23:45.67",
859 "42.1729",
860 "-1729.42",
861 "12:34",
862 };
863
865 putenv(tzstr);
866 printf("(now is 2012年03月17日 09:14:13 +0100, local time is UTC+1)\n");
868 printf("%-24s -> ", time_string[i]);
870 printf("error\n");
871 } else {
872 tvi = tv / 1000000;
873 tm = gmtime(&tvi);
874 printf("%14"PRIi64".%06d = %04d-%02d-%02dT%02d:%02d:%02dZ\n",
875 tv / 1000000, (int)(tv % 1000000),
876 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
877 tm->tm_hour, tm->tm_min, tm->tm_sec);
878 }
879 }
881 printf("%-24s -> ", duration_string[i]);
883 printf("error\n");
884 } else {
885 printf("%+21"PRIi64"\n", tv);
886 }
887 }
888 }
889
890 return 0;
891 }
892
893 #endif /* TEST */