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