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 { "nhd", 640,360 },
119 { "hqvga", 240,160 },
120 { "wqvga", 400,240 },
121 { "fwqvga", 432,240 },
122 { "hvga", 480,320 },
123 { "qhd", 960,540 },
124 };
125
127 { "ntsc", { 30000, 1001 } },
128 { "pal", { 25, 1 } },
129 { "qntsc", { 30000, 1001 } }, /* VCD compliant NTSC */
130 { "qpal", { 25, 1 } }, /* VCD compliant PAL */
131 { "sntsc", { 30000, 1001 } }, /* square pixel NTSC */
132 { "spal", { 25, 1 } }, /* square pixel PAL */
133 { "film", { 24, 1 } },
134 { "ntsc-film", { 24000, 1001 } },
135 };
136
138 {
139 int i;
141 const char *p;
143
144 for (i = 0; i <
n; i++) {
145 if (!strcmp(video_size_abbrs[i].abbr, str)) {
146 width = video_size_abbrs[i].
width;
148 break;
149 }
150 }
151 if (i == n) {
152 width = strtol(str, (void*)&p, 10);
153 if (*p)
154 p++;
155 height = strtol(p, (
void*)&p, 10);
156
157 /* trailing extraneous data detected, like in 123x345foobar */
158 if (*p)
160 }
161 if (width <= 0 ||
height <= 0)
165 return 0;
166 }
167
169 {
172
173 /* First, we check our abbreviation table */
174 for (i = 0; i <
n; ++i)
175 if (!strcmp(video_rate_abbrs[i].abbr, arg)) {
176 *rate = video_rate_abbrs[i].
rate;
177 return 0;
178 }
179
180 /* Then, we try to parse it as fraction */
183 if (rate->
num <= 0 || rate->
den <= 0)
185 return 0;
186 }
187
189 const char *
name;
///< a string representing the name of the color
190 uint8_t rgb_color[3];
///< RGB values for the color
192
194 { "AliceBlue", { 0xF0, 0xF8, 0xFF } },
195 { "AntiqueWhite", { 0xFA, 0xEB, 0xD7 } },
196 { "Aqua", { 0x00, 0xFF, 0xFF } },
197 { "Aquamarine", { 0x7F, 0xFF, 0xD4 } },
198 { "Azure", { 0xF0, 0xFF, 0xFF } },
199 { "Beige", { 0xF5, 0xF5, 0xDC } },
200 { "Bisque", { 0xFF, 0xE4, 0xC4 } },
201 { "Black", { 0x00, 0x00, 0x00 } },
202 { "BlanchedAlmond", { 0xFF, 0xEB, 0xCD } },
203 { "Blue", { 0x00, 0x00, 0xFF } },
204 { "BlueViolet", { 0x8A, 0x2B, 0xE2 } },
205 { "Brown", { 0xA5, 0x2A, 0x2A } },
206 { "BurlyWood", { 0xDE, 0xB8, 0x87 } },
207 { "CadetBlue", { 0x5F, 0x9E, 0xA0 } },
208 { "Chartreuse", { 0x7F, 0xFF, 0x00 } },
209 { "Chocolate", { 0xD2, 0x69, 0x1E } },
210 { "Coral", { 0xFF, 0x7F, 0x50 } },
211 { "CornflowerBlue", { 0x64, 0x95, 0xED } },
212 { "Cornsilk", { 0xFF, 0xF8, 0xDC } },
213 { "Crimson", { 0xDC, 0x14, 0x3C } },
214 { "Cyan", { 0x00, 0xFF, 0xFF } },
215 { "DarkBlue", { 0x00, 0x00, 0x8B } },
216 { "DarkCyan", { 0x00, 0x8B, 0x8B } },
217 { "DarkGoldenRod", { 0xB8, 0x86, 0x0B } },
218 { "DarkGray", { 0xA9, 0xA9, 0xA9 } },
219 { "DarkGreen", { 0x00, 0x64, 0x00 } },
220 { "DarkKhaki", { 0xBD, 0xB7, 0x6B } },
221 { "DarkMagenta", { 0x8B, 0x00, 0x8B } },
222 { "DarkOliveGreen", { 0x55, 0x6B, 0x2F } },
223 { "Darkorange", { 0xFF, 0x8C, 0x00 } },
224 { "DarkOrchid", { 0x99, 0x32, 0xCC } },
225 { "DarkRed", { 0x8B, 0x00, 0x00 } },
226 { "DarkSalmon", { 0xE9, 0x96, 0x7A } },
227 { "DarkSeaGreen", { 0x8F, 0xBC, 0x8F } },
228 { "DarkSlateBlue", { 0x48, 0x3D, 0x8B } },
229 { "DarkSlateGray", { 0x2F, 0x4F, 0x4F } },
230 { "DarkTurquoise", { 0x00, 0xCE, 0xD1 } },
231 { "DarkViolet", { 0x94, 0x00, 0xD3 } },
232 { "DeepPink", { 0xFF, 0x14, 0x93 } },
233 { "DeepSkyBlue", { 0x00, 0xBF, 0xFF } },
234 { "DimGray", { 0x69, 0x69, 0x69 } },
235 { "DodgerBlue", { 0x1E, 0x90, 0xFF } },
236 { "FireBrick", { 0xB2, 0x22, 0x22 } },
237 { "FloralWhite", { 0xFF, 0xFA, 0xF0 } },
238 { "ForestGreen", { 0x22, 0x8B, 0x22 } },
239 { "Fuchsia", { 0xFF, 0x00, 0xFF } },
240 { "Gainsboro", { 0xDC, 0xDC, 0xDC } },
241 { "GhostWhite", { 0xF8, 0xF8, 0xFF } },
242 { "Gold", { 0xFF, 0xD7, 0x00 } },
243 { "GoldenRod", { 0xDA, 0xA5, 0x20 } },
244 { "Gray", { 0x80, 0x80, 0x80 } },
245 { "Green", { 0x00, 0x80, 0x00 } },
246 { "GreenYellow", { 0xAD, 0xFF, 0x2F } },
247 { "HoneyDew", { 0xF0, 0xFF, 0xF0 } },
248 { "HotPink", { 0xFF, 0x69, 0xB4 } },
249 { "IndianRed", { 0xCD, 0x5C, 0x5C } },
250 { "Indigo", { 0x4B, 0x00, 0x82 } },
251 { "Ivory", { 0xFF, 0xFF, 0xF0 } },
252 { "Khaki", { 0xF0, 0xE6, 0x8C } },
253 { "Lavender", { 0xE6, 0xE6, 0xFA } },
254 { "LavenderBlush", { 0xFF, 0xF0, 0xF5 } },
255 { "LawnGreen", { 0x7C, 0xFC, 0x00 } },
256 { "LemonChiffon", { 0xFF, 0xFA, 0xCD } },
257 { "LightBlue", { 0xAD, 0xD8, 0xE6 } },
258 { "LightCoral", { 0xF0, 0x80, 0x80 } },
259 { "LightCyan", { 0xE0, 0xFF, 0xFF } },
260 { "LightGoldenRodYellow", { 0xFA, 0xFA, 0xD2 } },
261 { "LightGreen", { 0x90, 0xEE, 0x90 } },
262 { "LightGrey", { 0xD3, 0xD3, 0xD3 } },
263 { "LightPink", { 0xFF, 0xB6, 0xC1 } },
264 { "LightSalmon", { 0xFF, 0xA0, 0x7A } },
265 { "LightSeaGreen", { 0x20, 0xB2, 0xAA } },
266 { "LightSkyBlue", { 0x87, 0xCE, 0xFA } },
267 { "LightSlateGray", { 0x77, 0x88, 0x99 } },
268 { "LightSteelBlue", { 0xB0, 0xC4, 0xDE } },
269 { "LightYellow", { 0xFF, 0xFF, 0xE0 } },
270 { "Lime", { 0x00, 0xFF, 0x00 } },
271 { "LimeGreen", { 0x32, 0xCD, 0x32 } },
272 { "Linen", { 0xFA, 0xF0, 0xE6 } },
273 { "Magenta", { 0xFF, 0x00, 0xFF } },
274 { "Maroon", { 0x80, 0x00, 0x00 } },
275 { "MediumAquaMarine", { 0x66, 0xCD, 0xAA } },
276 { "MediumBlue", { 0x00, 0x00, 0xCD } },
277 { "MediumOrchid", { 0xBA, 0x55, 0xD3 } },
278 { "MediumPurple", { 0x93, 0x70, 0xD8 } },
279 { "MediumSeaGreen", { 0x3C, 0xB3, 0x71 } },
280 { "MediumSlateBlue", { 0x7B, 0x68, 0xEE } },
281 { "MediumSpringGreen", { 0x00, 0xFA, 0x9A } },
282 { "MediumTurquoise", { 0x48, 0xD1, 0xCC } },
283 { "MediumVioletRed", { 0xC7, 0x15, 0x85 } },
284 { "MidnightBlue", { 0x19, 0x19, 0x70 } },
285 { "MintCream", { 0xF5, 0xFF, 0xFA } },
286 { "MistyRose", { 0xFF, 0xE4, 0xE1 } },
287 { "Moccasin", { 0xFF, 0xE4, 0xB5 } },
288 { "NavajoWhite", { 0xFF, 0xDE, 0xAD } },
289 { "Navy", { 0x00, 0x00, 0x80 } },
290 { "OldLace", { 0xFD, 0xF5, 0xE6 } },
291 { "Olive", { 0x80, 0x80, 0x00 } },
292 { "OliveDrab", { 0x6B, 0x8E, 0x23 } },
293 { "Orange", { 0xFF, 0xA5, 0x00 } },
294 { "OrangeRed", { 0xFF, 0x45, 0x00 } },
295 { "Orchid", { 0xDA, 0x70, 0xD6 } },
296 { "PaleGoldenRod", { 0xEE, 0xE8, 0xAA } },
297 { "PaleGreen", { 0x98, 0xFB, 0x98 } },
298 { "PaleTurquoise", { 0xAF, 0xEE, 0xEE } },
299 { "PaleVioletRed", { 0xD8, 0x70, 0x93 } },
300 { "PapayaWhip", { 0xFF, 0xEF, 0xD5 } },
301 { "PeachPuff", { 0xFF, 0xDA, 0xB9 } },
302 { "Peru", { 0xCD, 0x85, 0x3F } },
303 { "Pink", { 0xFF, 0xC0, 0xCB } },
304 { "Plum", { 0xDD, 0xA0, 0xDD } },
305 { "PowderBlue", { 0xB0, 0xE0, 0xE6 } },
306 { "Purple", { 0x80, 0x00, 0x80 } },
307 { "Red", { 0xFF, 0x00, 0x00 } },
308 { "RosyBrown", { 0xBC, 0x8F, 0x8F } },
309 { "RoyalBlue", { 0x41, 0x69, 0xE1 } },
310 { "SaddleBrown", { 0x8B, 0x45, 0x13 } },
311 { "Salmon", { 0xFA, 0x80, 0x72 } },
312 { "SandyBrown", { 0xF4, 0xA4, 0x60 } },
313 { "SeaGreen", { 0x2E, 0x8B, 0x57 } },
314 { "SeaShell", { 0xFF, 0xF5, 0xEE } },
315 { "Sienna", { 0xA0, 0x52, 0x2D } },
316 { "Silver", { 0xC0, 0xC0, 0xC0 } },
317 { "SkyBlue", { 0x87, 0xCE, 0xEB } },
318 { "SlateBlue", { 0x6A, 0x5A, 0xCD } },
319 { "SlateGray", { 0x70, 0x80, 0x90 } },
320 { "Snow", { 0xFF, 0xFA, 0xFA } },
321 { "SpringGreen", { 0x00, 0xFF, 0x7F } },
322 { "SteelBlue", { 0x46, 0x82, 0xB4 } },
323 { "Tan", { 0xD2, 0xB4, 0x8C } },
324 { "Teal", { 0x00, 0x80, 0x80 } },
325 { "Thistle", { 0xD8, 0xBF, 0xD8 } },
326 { "Tomato", { 0xFF, 0x63, 0x47 } },
327 { "Turquoise", { 0x40, 0xE0, 0xD0 } },
328 { "Violet", { 0xEE, 0x82, 0xEE } },
329 { "Wheat", { 0xF5, 0xDE, 0xB3 } },
330 { "White", { 0xFF, 0xFF, 0xFF } },
331 { "WhiteSmoke", { 0xF5, 0xF5, 0xF5 } },
332 { "Yellow", { 0xFF, 0xFF, 0x00 } },
333 { "YellowGreen", { 0x9A, 0xCD, 0x32 } },
334 };
335
337 {
339 }
340
341 #define ALPHA_SEP '@'
342
344 void *log_ctx)
345 {
346 char *tail, color_string2[128];
348 int len, hex_offset = 0;
349
350 if (color_string[0] == '#') {
351 hex_offset = 1;
352 } else if (!strncmp(color_string, "0x", 2))
353 hex_offset = 2;
354
355 if (slen < 0)
356 slen = strlen(color_string);
357 av_strlcpy(color_string2, color_string + hex_offset,
358 FFMIN(slen-hex_offset+1,
sizeof(color_string2)));
359 if ((tail = strchr(color_string2,
ALPHA_SEP)))
360 *tail++ = 0;
361 len = strlen(color_string2);
362 rgba_color[3] = 255;
363
366 rgba_color[0] = rgba >> 24;
367 rgba_color[1] = rgba >> 16;
368 rgba_color[2] = rgba >> 8;
369 rgba_color[3] = rgba;
370 } else if (hex_offset ||
371 strspn(color_string2, "0123456789ABCDEFabcdef") == len) {
372 char *tail;
373 unsigned int rgba = strtoul(color_string2, &tail, 16);
374
375 if (*tail || (len != 6 && len != 8)) {
376 av_log(log_ctx,
AV_LOG_ERROR,
"Invalid 0xRRGGBB[AA] color string: '%s'\n", color_string2);
378 }
379 if (len == 8) {
380 rgba_color[3] = rgba;
381 rgba >>= 8;
382 }
383 rgba_color[0] = rgba >> 16;
384 rgba_color[1] = rgba >> 8;
385 rgba_color[2] = rgba;
386 } else {
387 entry = bsearch(color_string2,
388 color_table,
392 if (!entry) {
395 }
397 }
398
399 if (tail) {
401 const char *alpha_string = tail;
402 if (!strncmp(alpha_string, "0x", 2)) {
403 alpha = strtoul(alpha_string, &tail, 16);
404 } else {
405 double norm_alpha =
strtod(alpha_string, &tail);
406 if (norm_alpha < 0.0 || norm_alpha > 1.0)
407 alpha = 256;
408 else
409 alpha = 255 * norm_alpha;
410 }
411
412 if (tail == alpha_string || *tail || alpha > 255 || alpha < 0) {
414 alpha_string, color_string);
416 }
417 rgba_color[3] =
alpha;
418 }
419
420 return 0;
421 }
422
424 {
426
428 return NULL;
429
430 color = &color_table[color_idx];
431 if (rgbp)
433
435 }
436
437 /* get a positive number between n_min and n_max, for a maximum length
438 of len_max. Return -1 if error. */
440 int n_min, int n_max, int len_max)
441 {
443 const char *p;
444
445 p = *pp;
446 val = 0;
447 for(i = 0; i < len_max; i++) {
448 c = *p;
450 break;
451 val = (val * 10) + c - '0';
452 p++;
453 }
454 /* no number read ? */
455 if (p == *pp)
456 return -1;
457 if (val < n_min || val > n_max)
458 return -1;
459 *pp = p;
461 }
462
464 {
466
467 for(;;) {
468 /* consume time string until a non whitespace char is found */
471 p++;
472 fmt++;
473 }
474 c = *fmt++;
475 if (c == '0円') {
476 return (char *)p;
477 } else if (c == '%') {
478 c = *fmt++;
479 switch(c) {
480 case 'H':
481 case 'J':
483 if (val == -1)
484 return NULL;
486 break;
487 case 'M':
489 if (val == -1)
490 return NULL;
492 break;
493 case 'S':
495 if (val == -1)
496 return NULL;
498 break;
499 case 'Y':
501 if (val == -1)
502 return NULL;
503 dt->tm_year = val - 1900;
504 break;
505 case 'm':
507 if (val == -1)
508 return NULL;
509 dt->tm_mon = val - 1;
510 break;
511 case 'd':
513 if (val == -1)
514 return NULL;
516 break;
517 case '%':
518 goto match;
519 default:
520 return NULL;
521 }
522 } else {
523 match:
524 if (c != *p)
525 return NULL;
526 p++;
527 }
528 }
529 }
530
532 {
533 time_t t;
534
535 int y = tm->tm_year + 1900,
m = tm->tm_mon + 1, d = tm->tm_mday;
536
539 y--;
540 }
541
542 t = 86400LL *
543 (d + (153 *
m - 457) / 5 + 365 * y + y / 4 - y / 100 + y / 400 - 719469);
544
545 t += 3600 * tm->tm_hour + 60 * tm->tm_min + tm->tm_sec;
546
547 return t;
548 }
549
551 {
552 const char *p, *q;
553 int64_t t;
554 time_t now;
555 struct tm dt = { 0 };
556 int today = 0, negative = 0, microseconds = 0;
557 int i;
558 static const char * const date_fmt[] = {
559 "%Y-%m-%d",
560 "%Y%m%d",
561 };
562 static const char * const time_fmt[] = {
563 "%H:%M:%S",
564 "%H%M%S",
565 };
566
567 p = timestr;
568 q = NULL;
569 *timeval = INT64_MIN;
570 if (!duration) {
571 now = time(0);
572
574 *timeval = (int64_t) now * 1000000;
575 return 0;
576 }
577
578 /* parse the year-month-day part */
581 if (q)
582 break;
583 }
584
585 /* if the year-month-day part is missing, then take the
586 * current year-month-day time */
587 if (!q) {
588 today = 1;
589 q = p;
590 }
591 p = q;
592
593 if (*p == 'T' || *p == 't' || *p == ' ')
594 p++;
595
596 /* parse the hour-minute-second part */
599 if (q)
600 break;
601 }
602 } else {
603 /* parse timestr as a duration */
604 if (p[0] == '-') {
605 negative = 1;
606 ++p;
607 }
608 /* parse timestr as HH:MM:SS */
610 if (!q) {
611 /* parse timestr as MM:SS */
613 dt.tm_hour = 0;
614 }
615 if (!q) {
616 char *o;
617 /* parse timestr as S+ */
618 dt.tm_sec = strtol(p, &o, 10);
619 if (o == p) /* the parsing didn't succeed */
621 dt.tm_min = 0;
622 dt.tm_hour = 0;
623 q = o;
624 }
625 }
626
627 /* Now we have all the fields that we can get */
628 if (!q)
630
631 /* parse the .m... part */
632 if (*q == '.') {
634 q++;
635 for (n = 100000; n >= 1; n /= 10, q++) {
637 break;
638 microseconds += n * (*q - '0');
639 }
641 q++;
642 }
643
644 if (duration) {
645 t = dt.tm_hour * 3600 + dt.tm_min * 60 + dt.tm_sec;
646 } else {
647 int is_utc = *q == 'Z' || *q == 'z';
648 q += is_utc;
649 if (today) { /* fill in today's date */
650 struct tm dt2 = is_utc ? *gmtime(&now) : *localtime(&now);
651 dt2.tm_hour = dt.tm_hour;
652 dt2.tm_min = dt.tm_min;
653 dt2.tm_sec = dt.tm_sec;
654 dt = dt2;
655 }
656 t = is_utc ?
av_timegm(&dt) : mktime(&dt);
657 }
658
659 /* Check that we are at the end of the string */
660 if (*q)
662
663 t *= 1000000;
664 t += microseconds;
665 *timeval = negative ? -t : t;
666 return 0;
667 }
668
670 {
671 const char *p;
673
674 p = info;
675 if (*p == '?')
676 p++;
677 for(;;) {
679 while (*p != '0円' && *p != '=' && *p != '&') {
680 if ((q - tag) < sizeof(tag) - 1)
681 *q++ = *p;
682 p++;
683 }
684 *q = '0円';
686 if (*p == '=') {
687 p++;
688 while (*p != '&' && *p != '0円') {
689 if ((q - arg) < arg_size - 1) {
690 if (*p == '+')
691 *q++ = ' ';
692 else
693 *q++ = *p;
694 }
695 p++;
696 }
697 }
698 *q = '0円';
699 if (!strcmp(tag, tag1))
700 return 1;
701 if (*p != '&')
702 break;
703 p++;
704 }
705 return 0;
706 }
707
708 #ifdef TEST
709
710 static uint32_t randomv =
MKTAG(
'L',
'A',
'V',
'U');
711
712 static uint32_t av_get_random_seed_deterministic(void)
713 {
714 return randomv = randomv * 1664525 + 1013904223;
715 }
716
718 {
719 printf("Testing av_parse_video_rate()\n");
720 {
721 int i;
722 static const char *
const rates[] = {
723 "-inf",
724 "inf",
725 "nan",
726 "123/0",
727 "-123 / 0",
728 "",
729 "/",
730 " 123 / 321",
731 "foo/foo",
732 "foo/1",
733 "1/foo",
734 "0/0",
735 "/0",
736 "1/",
737 "1",
738 "0",
739 "-123/123",
740 "-foo",
741 "123.23",
742 ".23",
743 "-.23",
744 "-0.234",
745 "-0.0000001",
746 " 21332.2324 ",
747 " -21332.2324 ",
748 };
749
754 printf("'%s' -> %d/%d %s\n",
755 rates[i], q.
num, q.
den, ret ?
"ERROR" :
"OK");
756 }
757 }
758
759 printf("\nTesting av_parse_color()\n");
760 {
761 int i;
763 static const char *const color_names[] = {
764 "bikeshed",
765 "RaNdOm",
766 "foo",
767 "red",
768 "Red ",
769 "RED",
770 "Violet",
771 "Yellow",
772 "Red",
773 "0x000000",
774 "0x0000000",
775 "0xff000000",
776 "0x3e34ff",
777 "0x3e34ffaa",
778 "0xffXXee",
779 "0xfoobar",
780 "0xffffeeeeeeee",
781 "#ff0000",
782 "#ffXX00",
783 "ff0000",
784 "ffXX00",
785 "red@foo",
786 "random@10",
787 "0xff0000@1.0",
788 "red@",
789 "red@0xfff",
790 "red@0xf",
791 "red@2",
792 "red@0.1",
793 "red@-1",
794 "red@0.5",
795 "red@1.0",
796 "red@256",
797 "red@10foo",
798 "red@-1.0",
799 "red@-0.0",
800 };
801
803
806 printf("%s -> R(%d) G(%d) B(%d) A(%d)\n",
807 color_names[i], rgba[0], rgba[1], rgba[2], rgba[3]);
808 else
809 printf("%s -> error\n", color_names[i]);
810 }
811 }
812
813 printf("\nTesting av_small_strptime()\n");
814 {
815 int i;
816 struct tm tm = { 0 };
817 struct fmt_timespec_entry {
818 const char *
fmt, *timespec;
819 } fmt_timespec_entries[] = {
820 { "%Y-%m-%d", "2012年12月21日" },
821 { "%Y - %m - %d", "2012年12月21日" },
822 { "%Y-%m-%d %H:%M:%S", "2012年12月21日 20:12:21" },
823 { " %Y - %m - %d %H : %M : %S", " 2012 - 12 - 21 20 : 12 : 21" },
824 };
825
828 char *p;
829 struct fmt_timespec_entry *e = &fmt_timespec_entries[i];
830 printf("fmt:'%s' spec:'%s' -> ", e->fmt, e->timespec);
832 if (p) {
833 printf("%04d-%02d-%2d %02d:%02d:%02d\n",
834 1900+tm.tm_year, tm.tm_mon+1, tm.tm_mday,
835 tm.tm_hour, tm.tm_min, tm.tm_sec);
836 } else {
837 printf("error\n");
838 }
839 }
840 }
841
842 printf("\nTesting av_parse_time()\n");
843 {
844 int i;
845 int64_t tv;
846 time_t tvi;
847 struct tm *tm;
848 static char tzstr[] = "TZ=CET-1";
849 static const char * const time_string[] = {
850 "now",
851 "12:35:46",
852 "2000年12月20日 0:02:47.5z",
853 "2000年12月20日T010247.6",
854 };
855 static const char * const duration_string[] = {
856 "2:34:56.79",
857 "-1:23:45.67",
858 "42.1729",
859 "-1729.42",
860 "12:34",
861 };
862
864 putenv(tzstr);
865 printf("(now is 2012年03月17日 09:14:13 +0100, local time is UTC+1)\n");
867 printf("%-24s -> ", time_string[i]);
869 printf("error\n");
870 } else {
871 tvi = tv / 1000000;
872 tm = gmtime(&tvi);
873 printf("%14"PRIi64".%06d = %04d-%02d-%02dT%02d:%02d:%02dZ\n",
874 tv / 1000000, (int)(tv % 1000000),
875 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
876 tm->tm_hour, tm->tm_min, tm->tm_sec);
877 }
878 }
880 printf("%-24s -> ", duration_string[i]);
882 printf("error\n");
883 } else {
884 printf("%+21"PRIi64"\n", tv);
885 }
886 }
887 }
888
889 return 0;
890 }
891
892 #endif /* TEST */