FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
parseutils.c
Go to the documentation of this file.
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 
24 #include <time.h>
25 
26 #include "avstring.h"
27 #include "avutil.h"
28 #include "common.h"
29 #include "eval.h"
30 #include "log.h"
31 #include "random_seed.h"
32 #include "time_internal.h"
33 #include "parseutils.h"
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 
44 int av_parse_ratio(AVRational *q, const char *str, int max,
45  int log_offset, void *log_ctx)
46 {
47  char c;
48  int ret;
49 
50  if (sscanf(str, "%d:%d%c", &q->num, &q->den, &c) != 2) {
51  double d;
52  ret = av_expr_parse_and_eval(&d, str, NULL, NULL,
53  NULL, NULL, NULL, NULL,
54  NULL, log_offset, log_ctx);
55  if (ret < 0)
56  return ret;
57  *q = av_d2q(d, max);
58  } else {
59  av_reduce(&q->num, &q->den, q->num, q->den, max);
60  }
61 
62  return 0;
63 }
64 
65 typedef struct VideoSizeAbbr {
66  const char *abbr;
67  int width, height;
69 
70 typedef struct VideoRateAbbr {
71  const char *abbr;
74 
75 static const VideoSizeAbbr video_size_abbrs[] = {
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  { "2kdci", 2048,1080 },
115  { "2kflat", 1998,1080 },
116  { "2kscope", 2048, 858 },
117  { "4k", 4096,2160 }, /* Digital Cinema System Specification */
118  { "4kdci", 4096,2160 },
119  { "4kflat", 3996,2160 },
120  { "4kscope", 4096,1716 },
121  { "nhd", 640,360 },
122  { "hqvga", 240,160 },
123  { "wqvga", 400,240 },
124  { "fwqvga", 432,240 },
125  { "hvga", 480,320 },
126  { "qhd", 960,540 },
127  { "uhd2160", 3840,2160 },
128  { "uhd4320", 7680,4320 },
129 };
130 
132  { "ntsc", { 30000, 1001 } },
133  { "pal", { 25, 1 } },
134  { "qntsc", { 30000, 1001 } }, /* VCD compliant NTSC */
135  { "qpal", { 25, 1 } }, /* VCD compliant PAL */
136  { "sntsc", { 30000, 1001 } }, /* square pixel NTSC */
137  { "spal", { 25, 1 } }, /* square pixel PAL */
138  { "film", { 24, 1 } },
139  { "ntsc-film", { 24000, 1001 } },
140 };
141 
142 int av_parse_video_size(int *width_ptr, int *height_ptr, const char *str)
143 {
144  int i;
145  int n = FF_ARRAY_ELEMS(video_size_abbrs);
146  const char *p;
147  int width = 0, height = 0;
148 
149  for (i = 0; i < n; i++) {
150  if (!strcmp(video_size_abbrs[i].abbr, str)) {
151  width = video_size_abbrs[i].width;
152  height = video_size_abbrs[i].height;
153  break;
154  }
155  }
156  if (i == n) {
157  width = strtol(str, (void*)&p, 10);
158  if (*p)
159  p++;
160  height = strtol(p, (void*)&p, 10);
161 
162  /* trailing extraneous data detected, like in 123x345foobar */
163  if (*p)
164  return AVERROR(EINVAL);
165  }
166  if (width <= 0 || height <= 0)
167  return AVERROR(EINVAL);
168  *width_ptr = width;
169  *height_ptr = height;
170  return 0;
171 }
172 
173 int av_parse_video_rate(AVRational *rate, const char *arg)
174 {
175  int i, ret;
176  int n = FF_ARRAY_ELEMS(video_rate_abbrs);
177 
178  /* First, we check our abbreviation table */
179  for (i = 0; i < n; ++i)
180  if (!strcmp(video_rate_abbrs[i].abbr, arg)) {
181  *rate = video_rate_abbrs[i].rate;
182  return 0;
183  }
184 
185  /* Then, we try to parse it as fraction */
186  if ((ret = av_parse_ratio_quiet(rate, arg, 1001000)) < 0)
187  return ret;
188  if (rate->num <= 0 || rate->den <= 0)
189  return AVERROR(EINVAL);
190  return 0;
191 }
192 
193 typedef struct ColorEntry {
194  const char *name; ///< a string representing the name of the color
195  uint8_t rgb_color[3]; ///< RGB values for the color
196 } ColorEntry;
197 
198 static const ColorEntry color_table[] = {
199  { "AliceBlue", { 0xF0, 0xF8, 0xFF } },
200  { "AntiqueWhite", { 0xFA, 0xEB, 0xD7 } },
201  { "Aqua", { 0x00, 0xFF, 0xFF } },
202  { "Aquamarine", { 0x7F, 0xFF, 0xD4 } },
203  { "Azure", { 0xF0, 0xFF, 0xFF } },
204  { "Beige", { 0xF5, 0xF5, 0xDC } },
205  { "Bisque", { 0xFF, 0xE4, 0xC4 } },
206  { "Black", { 0x00, 0x00, 0x00 } },
207  { "BlanchedAlmond", { 0xFF, 0xEB, 0xCD } },
208  { "Blue", { 0x00, 0x00, 0xFF } },
209  { "BlueViolet", { 0x8A, 0x2B, 0xE2 } },
210  { "Brown", { 0xA5, 0x2A, 0x2A } },
211  { "BurlyWood", { 0xDE, 0xB8, 0x87 } },
212  { "CadetBlue", { 0x5F, 0x9E, 0xA0 } },
213  { "Chartreuse", { 0x7F, 0xFF, 0x00 } },
214  { "Chocolate", { 0xD2, 0x69, 0x1E } },
215  { "Coral", { 0xFF, 0x7F, 0x50 } },
216  { "CornflowerBlue", { 0x64, 0x95, 0xED } },
217  { "Cornsilk", { 0xFF, 0xF8, 0xDC } },
218  { "Crimson", { 0xDC, 0x14, 0x3C } },
219  { "Cyan", { 0x00, 0xFF, 0xFF } },
220  { "DarkBlue", { 0x00, 0x00, 0x8B } },
221  { "DarkCyan", { 0x00, 0x8B, 0x8B } },
222  { "DarkGoldenRod", { 0xB8, 0x86, 0x0B } },
223  { "DarkGray", { 0xA9, 0xA9, 0xA9 } },
224  { "DarkGreen", { 0x00, 0x64, 0x00 } },
225  { "DarkKhaki", { 0xBD, 0xB7, 0x6B } },
226  { "DarkMagenta", { 0x8B, 0x00, 0x8B } },
227  { "DarkOliveGreen", { 0x55, 0x6B, 0x2F } },
228  { "Darkorange", { 0xFF, 0x8C, 0x00 } },
229  { "DarkOrchid", { 0x99, 0x32, 0xCC } },
230  { "DarkRed", { 0x8B, 0x00, 0x00 } },
231  { "DarkSalmon", { 0xE9, 0x96, 0x7A } },
232  { "DarkSeaGreen", { 0x8F, 0xBC, 0x8F } },
233  { "DarkSlateBlue", { 0x48, 0x3D, 0x8B } },
234  { "DarkSlateGray", { 0x2F, 0x4F, 0x4F } },
235  { "DarkTurquoise", { 0x00, 0xCE, 0xD1 } },
236  { "DarkViolet", { 0x94, 0x00, 0xD3 } },
237  { "DeepPink", { 0xFF, 0x14, 0x93 } },
238  { "DeepSkyBlue", { 0x00, 0xBF, 0xFF } },
239  { "DimGray", { 0x69, 0x69, 0x69 } },
240  { "DodgerBlue", { 0x1E, 0x90, 0xFF } },
241  { "FireBrick", { 0xB2, 0x22, 0x22 } },
242  { "FloralWhite", { 0xFF, 0xFA, 0xF0 } },
243  { "ForestGreen", { 0x22, 0x8B, 0x22 } },
244  { "Fuchsia", { 0xFF, 0x00, 0xFF } },
245  { "Gainsboro", { 0xDC, 0xDC, 0xDC } },
246  { "GhostWhite", { 0xF8, 0xF8, 0xFF } },
247  { "Gold", { 0xFF, 0xD7, 0x00 } },
248  { "GoldenRod", { 0xDA, 0xA5, 0x20 } },
249  { "Gray", { 0x80, 0x80, 0x80 } },
250  { "Green", { 0x00, 0x80, 0x00 } },
251  { "GreenYellow", { 0xAD, 0xFF, 0x2F } },
252  { "HoneyDew", { 0xF0, 0xFF, 0xF0 } },
253  { "HotPink", { 0xFF, 0x69, 0xB4 } },
254  { "IndianRed", { 0xCD, 0x5C, 0x5C } },
255  { "Indigo", { 0x4B, 0x00, 0x82 } },
256  { "Ivory", { 0xFF, 0xFF, 0xF0 } },
257  { "Khaki", { 0xF0, 0xE6, 0x8C } },
258  { "Lavender", { 0xE6, 0xE6, 0xFA } },
259  { "LavenderBlush", { 0xFF, 0xF0, 0xF5 } },
260  { "LawnGreen", { 0x7C, 0xFC, 0x00 } },
261  { "LemonChiffon", { 0xFF, 0xFA, 0xCD } },
262  { "LightBlue", { 0xAD, 0xD8, 0xE6 } },
263  { "LightCoral", { 0xF0, 0x80, 0x80 } },
264  { "LightCyan", { 0xE0, 0xFF, 0xFF } },
265  { "LightGoldenRodYellow", { 0xFA, 0xFA, 0xD2 } },
266  { "LightGreen", { 0x90, 0xEE, 0x90 } },
267  { "LightGrey", { 0xD3, 0xD3, 0xD3 } },
268  { "LightPink", { 0xFF, 0xB6, 0xC1 } },
269  { "LightSalmon", { 0xFF, 0xA0, 0x7A } },
270  { "LightSeaGreen", { 0x20, 0xB2, 0xAA } },
271  { "LightSkyBlue", { 0x87, 0xCE, 0xFA } },
272  { "LightSlateGray", { 0x77, 0x88, 0x99 } },
273  { "LightSteelBlue", { 0xB0, 0xC4, 0xDE } },
274  { "LightYellow", { 0xFF, 0xFF, 0xE0 } },
275  { "Lime", { 0x00, 0xFF, 0x00 } },
276  { "LimeGreen", { 0x32, 0xCD, 0x32 } },
277  { "Linen", { 0xFA, 0xF0, 0xE6 } },
278  { "Magenta", { 0xFF, 0x00, 0xFF } },
279  { "Maroon", { 0x80, 0x00, 0x00 } },
280  { "MediumAquaMarine", { 0x66, 0xCD, 0xAA } },
281  { "MediumBlue", { 0x00, 0x00, 0xCD } },
282  { "MediumOrchid", { 0xBA, 0x55, 0xD3 } },
283  { "MediumPurple", { 0x93, 0x70, 0xD8 } },
284  { "MediumSeaGreen", { 0x3C, 0xB3, 0x71 } },
285  { "MediumSlateBlue", { 0x7B, 0x68, 0xEE } },
286  { "MediumSpringGreen", { 0x00, 0xFA, 0x9A } },
287  { "MediumTurquoise", { 0x48, 0xD1, 0xCC } },
288  { "MediumVioletRed", { 0xC7, 0x15, 0x85 } },
289  { "MidnightBlue", { 0x19, 0x19, 0x70 } },
290  { "MintCream", { 0xF5, 0xFF, 0xFA } },
291  { "MistyRose", { 0xFF, 0xE4, 0xE1 } },
292  { "Moccasin", { 0xFF, 0xE4, 0xB5 } },
293  { "NavajoWhite", { 0xFF, 0xDE, 0xAD } },
294  { "Navy", { 0x00, 0x00, 0x80 } },
295  { "OldLace", { 0xFD, 0xF5, 0xE6 } },
296  { "Olive", { 0x80, 0x80, 0x00 } },
297  { "OliveDrab", { 0x6B, 0x8E, 0x23 } },
298  { "Orange", { 0xFF, 0xA5, 0x00 } },
299  { "OrangeRed", { 0xFF, 0x45, 0x00 } },
300  { "Orchid", { 0xDA, 0x70, 0xD6 } },
301  { "PaleGoldenRod", { 0xEE, 0xE8, 0xAA } },
302  { "PaleGreen", { 0x98, 0xFB, 0x98 } },
303  { "PaleTurquoise", { 0xAF, 0xEE, 0xEE } },
304  { "PaleVioletRed", { 0xD8, 0x70, 0x93 } },
305  { "PapayaWhip", { 0xFF, 0xEF, 0xD5 } },
306  { "PeachPuff", { 0xFF, 0xDA, 0xB9 } },
307  { "Peru", { 0xCD, 0x85, 0x3F } },
308  { "Pink", { 0xFF, 0xC0, 0xCB } },
309  { "Plum", { 0xDD, 0xA0, 0xDD } },
310  { "PowderBlue", { 0xB0, 0xE0, 0xE6 } },
311  { "Purple", { 0x80, 0x00, 0x80 } },
312  { "Red", { 0xFF, 0x00, 0x00 } },
313  { "RosyBrown", { 0xBC, 0x8F, 0x8F } },
314  { "RoyalBlue", { 0x41, 0x69, 0xE1 } },
315  { "SaddleBrown", { 0x8B, 0x45, 0x13 } },
316  { "Salmon", { 0xFA, 0x80, 0x72 } },
317  { "SandyBrown", { 0xF4, 0xA4, 0x60 } },
318  { "SeaGreen", { 0x2E, 0x8B, 0x57 } },
319  { "SeaShell", { 0xFF, 0xF5, 0xEE } },
320  { "Sienna", { 0xA0, 0x52, 0x2D } },
321  { "Silver", { 0xC0, 0xC0, 0xC0 } },
322  { "SkyBlue", { 0x87, 0xCE, 0xEB } },
323  { "SlateBlue", { 0x6A, 0x5A, 0xCD } },
324  { "SlateGray", { 0x70, 0x80, 0x90 } },
325  { "Snow", { 0xFF, 0xFA, 0xFA } },
326  { "SpringGreen", { 0x00, 0xFF, 0x7F } },
327  { "SteelBlue", { 0x46, 0x82, 0xB4 } },
328  { "Tan", { 0xD2, 0xB4, 0x8C } },
329  { "Teal", { 0x00, 0x80, 0x80 } },
330  { "Thistle", { 0xD8, 0xBF, 0xD8 } },
331  { "Tomato", { 0xFF, 0x63, 0x47 } },
332  { "Turquoise", { 0x40, 0xE0, 0xD0 } },
333  { "Violet", { 0xEE, 0x82, 0xEE } },
334  { "Wheat", { 0xF5, 0xDE, 0xB3 } },
335  { "White", { 0xFF, 0xFF, 0xFF } },
336  { "WhiteSmoke", { 0xF5, 0xF5, 0xF5 } },
337  { "Yellow", { 0xFF, 0xFF, 0x00 } },
338  { "YellowGreen", { 0x9A, 0xCD, 0x32 } },
339 };
340 
341 static int color_table_compare(const void *lhs, const void *rhs)
342 {
343  return av_strcasecmp(lhs, ((const ColorEntry *)rhs)->name);
344 }
345 
346 #define ALPHA_SEP '@'
347 
348 int av_parse_color(uint8_t *rgba_color, const char *color_string, int slen,
349  void *log_ctx)
350 {
351  char *tail, color_string2[128];
352  const ColorEntry *entry;
353  int len, hex_offset = 0;
354 
355  if (color_string[0] == '#') {
356  hex_offset = 1;
357  } else if (!strncmp(color_string, "0x", 2))
358  hex_offset = 2;
359 
360  if (slen < 0)
361  slen = strlen(color_string);
362  av_strlcpy(color_string2, color_string + hex_offset,
363  FFMIN(slen-hex_offset+1, sizeof(color_string2)));
364  if ((tail = strchr(color_string2, ALPHA_SEP)))
365  *tail++ = 0;
366  len = strlen(color_string2);
367  rgba_color[3] = 255;
368 
369  if (!av_strcasecmp(color_string2, "random") || !av_strcasecmp(color_string2, "bikeshed")) {
370  int rgba = av_get_random_seed();
371  rgba_color[0] = rgba >> 24;
372  rgba_color[1] = rgba >> 16;
373  rgba_color[2] = rgba >> 8;
374  rgba_color[3] = rgba;
375  } else if (hex_offset ||
376  strspn(color_string2, "0123456789ABCDEFabcdef") == len) {
377  char *tail;
378  unsigned int rgba = strtoul(color_string2, &tail, 16);
379 
380  if (*tail || (len != 6 && len != 8)) {
381  av_log(log_ctx, AV_LOG_ERROR, "Invalid 0xRRGGBB[AA] color string: '%s'\n", color_string2);
382  return AVERROR(EINVAL);
383  }
384  if (len == 8) {
385  rgba_color[3] = rgba;
386  rgba >>= 8;
387  }
388  rgba_color[0] = rgba >> 16;
389  rgba_color[1] = rgba >> 8;
390  rgba_color[2] = rgba;
391  } else {
392  entry = bsearch(color_string2,
393  color_table,
394  FF_ARRAY_ELEMS(color_table),
395  sizeof(ColorEntry),
397  if (!entry) {
398  av_log(log_ctx, AV_LOG_ERROR, "Cannot find color '%s'\n", color_string2);
399  return AVERROR(EINVAL);
400  }
401  memcpy(rgba_color, entry->rgb_color, 3);
402  }
403 
404  if (tail) {
405  double alpha;
406  const char *alpha_string = tail;
407  if (!strncmp(alpha_string, "0x", 2)) {
408  alpha = strtoul(alpha_string, &tail, 16);
409  } else {
410  double norm_alpha = strtod(alpha_string, &tail);
411  if (norm_alpha < 0.0 || norm_alpha > 1.0)
412  alpha = 256;
413  else
414  alpha = 255 * norm_alpha;
415  }
416 
417  if (tail == alpha_string || *tail || alpha > 255 || alpha < 0) {
418  av_log(log_ctx, AV_LOG_ERROR, "Invalid alpha value specifier '%s' in '%s'\n",
419  alpha_string, color_string);
420  return AVERROR(EINVAL);
421  }
422  rgba_color[3] = alpha;
423  }
424 
425  return 0;
426 }
427 
428 const char *av_get_known_color_name(int color_idx, const uint8_t **rgbp)
429 {
430  const ColorEntry *color;
431 
432  if ((unsigned)color_idx >= FF_ARRAY_ELEMS(color_table))
433  return NULL;
434 
435  color = &color_table[color_idx];
436  if (rgbp)
437  *rgbp = color->rgb_color;
438 
439  return color->name;
440 }
441 
442 /* get a positive number between n_min and n_max, for a maximum length
443  of len_max. Return -1 if error. */
444 static int date_get_num(const char **pp,
445  int n_min, int n_max, int len_max)
446 {
447  int i, val, c;
448  const char *p;
449 
450  p = *pp;
451  val = 0;
452  for(i = 0; i < len_max; i++) {
453  c = *p;
454  if (!av_isdigit(c))
455  break;
456  val = (val * 10) + c - '0';
457  p++;
458  }
459  /* no number read ? */
460  if (p == *pp)
461  return -1;
462  if (val < n_min || val > n_max)
463  return -1;
464  *pp = p;
465  return val;
466 }
467 
468 char *av_small_strptime(const char *p, const char *fmt, struct tm *dt)
469 {
470  int c, val;
471 
472  while((c = *fmt++)) {
473  if (c != '%') {
474  if (av_isspace(c))
475  for (; *p && av_isspace(*p); p++);
476  else if (*p != c)
477  return NULL;
478  else p++;
479  continue;
480  }
481 
482  c = *fmt++;
483  switch(c) {
484  case 'H':
485  case 'J':
486  val = date_get_num(&p, 0, c == 'H' ? 23 : INT_MAX, 2);
487 
488  if (val == -1)
489  return NULL;
490  dt->tm_hour = val;
491  break;
492  case 'M':
493  val = date_get_num(&p, 0, 59, 2);
494  if (val == -1)
495  return NULL;
496  dt->tm_min = val;
497  break;
498  case 'S':
499  val = date_get_num(&p, 0, 59, 2);
500  if (val == -1)
501  return NULL;
502  dt->tm_sec = val;
503  break;
504  case 'Y':
505  val = date_get_num(&p, 0, 9999, 4);
506  if (val == -1)
507  return NULL;
508  dt->tm_year = val - 1900;
509  break;
510  case 'm':
511  val = date_get_num(&p, 1, 12, 2);
512  if (val == -1)
513  return NULL;
514  dt->tm_mon = val - 1;
515  break;
516  case 'd':
517  val = date_get_num(&p, 1, 31, 2);
518  if (val == -1)
519  return NULL;
520  dt->tm_mday = val;
521  break;
522  case 'T':
523  p = av_small_strptime(p, "%H:%M:%S", dt);
524  if (!p)
525  return NULL;
526  break;
527  case '%':
528  if (*p++ != '%')
529  return NULL;
530  break;
531  default:
532  return NULL;
533  }
534  }
535 
536  return (char*)p;
537 }
538 
539 time_t av_timegm(struct tm *tm)
540 {
541  time_t t;
542 
543  int y = tm->tm_year + 1900, m = tm->tm_mon + 1, d = tm->tm_mday;
544 
545  if (m < 3) {
546  m += 12;
547  y--;
548  }
549 
550  t = 86400LL *
551  (d + (153 * m - 457) / 5 + 365 * y + y / 4 - y / 100 + y / 400 - 719469);
552 
553  t += 3600 * tm->tm_hour + 60 * tm->tm_min + tm->tm_sec;
554 
555  return t;
556 }
557 
558 int av_parse_time(int64_t *timeval, const char *timestr, int duration)
559 {
560  const char *p, *q;
561  int64_t t;
562  time_t now;
563  struct tm dt = { 0 }, tmbuf;
564  int today = 0, negative = 0, microseconds = 0;
565  int i;
566  static const char * const date_fmt[] = {
567  "%Y-%m-%d",
568  "%Y%m%d",
569  };
570  static const char * const time_fmt[] = {
571  "%H:%M:%S",
572  "%H%M%S",
573  };
574 
575  p = timestr;
576  q = NULL;
577  *timeval = INT64_MIN;
578  if (!duration) {
579  now = time(0);
580 
581  if (!av_strcasecmp(timestr, "now")) {
582  *timeval = (int64_t) now * 1000000;
583  return 0;
584  }
585 
586  /* parse the year-month-day part */
587  for (i = 0; i < FF_ARRAY_ELEMS(date_fmt); i++) {
588  q = av_small_strptime(p, date_fmt[i], &dt);
589  if (q)
590  break;
591  }
592 
593  /* if the year-month-day part is missing, then take the
594  * current year-month-day time */
595  if (!q) {
596  today = 1;
597  q = p;
598  }
599  p = q;
600 
601  if (*p == 'T' || *p == 't' || *p == ' ')
602  p++;
603 
604  /* parse the hour-minute-second part */
605  for (i = 0; i < FF_ARRAY_ELEMS(time_fmt); i++) {
606  q = av_small_strptime(p, time_fmt[i], &dt);
607  if (q)
608  break;
609  }
610  } else {
611  /* parse timestr as a duration */
612  if (p[0] == '-') {
613  negative = 1;
614  ++p;
615  }
616  /* parse timestr as HH:MM:SS */
617  q = av_small_strptime(p, "%J:%M:%S", &dt);
618  if (!q) {
619  /* parse timestr as MM:SS */
620  q = av_small_strptime(p, "%M:%S", &dt);
621  dt.tm_hour = 0;
622  }
623  if (!q) {
624  char *o;
625  /* parse timestr as S+ */
626  dt.tm_sec = strtol(p, &o, 10);
627  if (o == p) /* the parsing didn't succeed */
628  return AVERROR(EINVAL);
629  dt.tm_min = 0;
630  dt.tm_hour = 0;
631  q = o;
632  }
633  }
634 
635  /* Now we have all the fields that we can get */
636  if (!q)
637  return AVERROR(EINVAL);
638 
639  /* parse the .m... part */
640  if (*q == '.') {
641  int n;
642  q++;
643  for (n = 100000; n >= 1; n /= 10, q++) {
644  if (!av_isdigit(*q))
645  break;
646  microseconds += n * (*q - '0');
647  }
648  while (av_isdigit(*q))
649  q++;
650  }
651 
652  if (duration) {
653  t = dt.tm_hour * 3600 + dt.tm_min * 60 + dt.tm_sec;
654  } else {
655  int is_utc = *q == 'Z' || *q == 'z';
656  q += is_utc;
657  if (today) { /* fill in today's date */
658  struct tm dt2 = is_utc ? *gmtime_r(&now, &tmbuf) : *localtime_r(&now, &tmbuf);
659  dt2.tm_hour = dt.tm_hour;
660  dt2.tm_min = dt.tm_min;
661  dt2.tm_sec = dt.tm_sec;
662  dt = dt2;
663  }
664  t = is_utc ? av_timegm(&dt) : mktime(&dt);
665  }
666 
667  /* Check that we are at the end of the string */
668  if (*q)
669  return AVERROR(EINVAL);
670 
671  t *= 1000000;
672  t += microseconds;
673  *timeval = negative ? -t : t;
674  return 0;
675 }
676 
677 int av_find_info_tag(char *arg, int arg_size, const char *tag1, const char *info)
678 {
679  const char *p;
680  char tag[128], *q;
681 
682  p = info;
683  if (*p == '?')
684  p++;
685  for(;;) {
686  q = tag;
687  while (*p != '\0' && *p != '=' && *p != '&') {
688  if ((q - tag) < sizeof(tag) - 1)
689  *q++ = *p;
690  p++;
691  }
692  *q = '\0';
693  q = arg;
694  if (*p == '=') {
695  p++;
696  while (*p != '&' && *p != '\0') {
697  if ((q - arg) < arg_size - 1) {
698  if (*p == '+')
699  *q++ = ' ';
700  else
701  *q++ = *p;
702  }
703  p++;
704  }
705  }
706  *q = '\0';
707  if (!strcmp(tag, tag1))
708  return 1;
709  if (*p != '&')
710  break;
711  p++;
712  }
713  return 0;
714 }
715 
716 #ifdef TEST
717 
718 static uint32_t randomv = MKTAG('L','A','V','U');
719 
720 static uint32_t av_get_random_seed_deterministic(void)
721 {
722  return randomv = randomv * 1664525 + 1013904223;
723 }
724 
725 int main(void)
726 {
727  printf("Testing av_parse_video_rate()\n");
728  {
729  int i;
730  static const char *const rates[] = {
731  "-inf",
732  "inf",
733  "nan",
734  "123/0",
735  "-123 / 0",
736  "",
737  "/",
738  " 123 / 321",
739  "foo/foo",
740  "foo/1",
741  "1/foo",
742  "0/0",
743  "/0",
744  "1/",
745  "1",
746  "0",
747  "-123/123",
748  "-foo",
749  "123.23",
750  ".23",
751  "-.23",
752  "-0.234",
753  "-0.0000001",
754  " 21332.2324 ",
755  " -21332.2324 ",
756  };
757 
758  for (i = 0; i < FF_ARRAY_ELEMS(rates); i++) {
759  int ret;
760  AVRational q = { 0, 0 };
761  ret = av_parse_video_rate(&q, rates[i]);
762  printf("'%s' -> %d/%d %s\n",
763  rates[i], q.num, q.den, ret ? "ERROR" : "OK");
764  }
765  }
766 
767  printf("\nTesting av_parse_color()\n");
768  {
769  int i;
770  uint8_t rgba[4];
771  static const char *const color_names[] = {
772  "bikeshed",
773  "RaNdOm",
774  "foo",
775  "red",
776  "Red ",
777  "RED",
778  "Violet",
779  "Yellow",
780  "Red",
781  "0x000000",
782  "0x0000000",
783  "0xff000000",
784  "0x3e34ff",
785  "0x3e34ffaa",
786  "0xffXXee",
787  "0xfoobar",
788  "0xffffeeeeeeee",
789  "#ff0000",
790  "#ffXX00",
791  "ff0000",
792  "ffXX00",
793  "red@foo",
794  "random@10",
795  "0xff0000@1.0",
796  "red@",
797  "red@0xfff",
798  "red@0xf",
799  "red@2",
800  "red@0.1",
801  "red@-1",
802  "red@0.5",
803  "red@1.0",
804  "red@256",
805  "red@10foo",
806  "red@-1.0",
807  "red@-0.0",
808  };
809 
811 
812  for (i = 0; i < FF_ARRAY_ELEMS(color_names); i++) {
813  if (av_parse_color(rgba, color_names[i], -1, NULL) >= 0)
814  printf("%s -> R(%d) G(%d) B(%d) A(%d)\n",
815  color_names[i], rgba[0], rgba[1], rgba[2], rgba[3]);
816  else
817  printf("%s -> error\n", color_names[i]);
818  }
819  }
820 
821  printf("\nTesting av_small_strptime()\n");
822  {
823  int i;
824  struct tm tm = { 0 };
825  struct fmt_timespec_entry {
826  const char *fmt, *timespec;
827  } fmt_timespec_entries[] = {
828  { "%Y-%m-%d", "2012-12-21" },
829  { "%Y - %m - %d", "2012-12-21" },
830  { "%Y-%m-%d %H:%M:%S", "2012-12-21 20:12:21" },
831  { " %Y - %m - %d %H : %M : %S", " 2012 - 12 - 21 20 : 12 : 21" },
832  };
833 
835  for (i = 0; i < FF_ARRAY_ELEMS(fmt_timespec_entries); i++) {
836  char *p;
837  struct fmt_timespec_entry *e = &fmt_timespec_entries[i];
838  printf("fmt:'%s' spec:'%s' -> ", e->fmt, e->timespec);
839  p = av_small_strptime(e->timespec, e->fmt, &tm);
840  if (p) {
841  printf("%04d-%02d-%2d %02d:%02d:%02d\n",
842  1900+tm.tm_year, tm.tm_mon+1, tm.tm_mday,
843  tm.tm_hour, tm.tm_min, tm.tm_sec);
844  } else {
845  printf("error\n");
846  }
847  }
848  }
849 
850  printf("\nTesting av_parse_time()\n");
851  {
852  int i;
853  int64_t tv;
854  time_t tvi;
855  struct tm *tm;
856  static char tzstr[] = "TZ=CET-1";
857  static const char * const time_string[] = {
858  "now",
859  "12:35:46",
860  "2000-12-20 0:02:47.5z",
861  "2000-12-20T010247.6",
862  };
863  static const char * const duration_string[] = {
864  "2:34:56.79",
865  "-1:23:45.67",
866  "42.1729",
867  "-1729.42",
868  "12:34",
869  };
870 
872  putenv(tzstr);
873  printf("(now is 2012-03-17 09:14:13 +0100, local time is UTC+1)\n");
874  for (i = 0; i < FF_ARRAY_ELEMS(time_string); i++) {
875  printf("%-24s -> ", time_string[i]);
876  if (av_parse_time(&tv, time_string[i], 0)) {
877  printf("error\n");
878  } else {
879  tvi = tv / 1000000;
880  tm = gmtime(&tvi);
881  printf("%14"PRIi64".%06d = %04d-%02d-%02dT%02d:%02d:%02dZ\n",
882  tv / 1000000, (int)(tv % 1000000),
883  tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
884  tm->tm_hour, tm->tm_min, tm->tm_sec);
885  }
886  }
887  for (i = 0; i < FF_ARRAY_ELEMS(duration_string); i++) {
888  printf("%-24s -> ", duration_string[i]);
889  if (av_parse_time(&tv, duration_string[i], 1)) {
890  printf("error\n");
891  } else {
892  printf("%+21"PRIi64"\n", tv);
893  }
894  }
895  }
896 
897  return 0;
898 }
899 
900 #endif /* TEST */
time_t av_timegm(struct tm *tm)
Convert the decomposed UTC time in tm to a time_t value.
Definition: parseutils.c:539
int av_parse_ratio(AVRational *q, const char *str, int max, int log_offset, void *log_ctx)
Parse str and store the parsed ratio in q.
Definition: parseutils.c:44
const char * name
a string representing the name of the color
Definition: parseutils.c:194
#define NULL
Definition: coverity.c:32
int av_isdigit(int c)
Locale-independent conversion of ASCII isdigit.
Definition: avstring.c:320
const char const char void * val
Definition: avisynth_c.h:634
int av_parse_video_rate(AVRational *rate, const char *arg)
Parse str and store the detected values in *rate.
Definition: parseutils.c:173
int av_parse_video_size(int *width_ptr, int *height_ptr, const char *str)
Parse str and put in width_ptr and height_ptr the detected values.
Definition: parseutils.c:142
const char * fmt
Definition: avisynth_c.h:632
const char * abbr
Definition: parseutils.c:66
int av_parse_time(int64_t *timeval, const char *timestr, int duration)
Parse timestr and return in *time a corresponding number of microseconds.
Definition: parseutils.c:558
void av_log_set_level(int level)
Set the log level.
Definition: log.c:382
const char * abbr
Definition: parseutils.c:71
#define ALPHA_SEP
Definition: parseutils.c:346
int num
numerator
Definition: rational.h:44
external API header
uint8_t
int av_isspace(int c)
Locale-independent conversion of ASCII isspace.
Definition: avstring.c:330
static const uint32_t color[16+AV_CLASS_CATEGORY_NB]
Definition: log.c:94
AVRational rate
Definition: parseutils.c:72
char * av_small_strptime(const char *p, const char *fmt, struct tm *dt)
Simplified version of strptime.
Definition: parseutils.c:468
double strtod(const char *, char **)
uint32_t tag
Definition: movenc.c:1334
int av_find_info_tag(char *arg, int arg_size, const char *tag1, const char *info)
Attempt to find a specific tag in a URL.
Definition: parseutils.c:677
static int64_t duration
Definition: ffplay.c:326
uint8_t rgb_color[3]
RGB values for the color.
Definition: parseutils.c:195
#define av_log(a,...)
unsigned m
Definition: audioconvert.c:187
static const int rates[]
int av_parse_color(uint8_t *rgba_color, const char *color_string, int slen, void *log_ctx)
Put the RGBA values that correspond to color_string in rgba_color.
Definition: parseutils.c:348
int av_expr_parse_and_eval(double *d, const char *s, const char *const *const_names, const double *const_values, const char *const *func1_names, double(*const *funcs1)(void *, double), const char *const *func2_names, double(*const *funcs2)(void *, double, double), void *opaque, int log_offset, void *log_ctx)
Parse and evaluate an expression.
Definition: eval.c:718
static double alpha(void *priv, double x, double y)
Definition: vf_geq.c:99
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
#define AVERROR(e)
Definition: error.h:43
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
const char * arg
Definition: jacosubdec.c:66
size_t av_strlcpy(char *dst, const char *src, size_t size)
Copy the string src to dst, but no more than size - 1 bytes, and null-terminate dst.
Definition: avstring.c:83
static struct tm * gmtime_r(const time_t *clock, struct tm *result)
Definition: time_internal.h:26
const char * av_get_known_color_name(int color_idx, const uint8_t **rgbp)
Get the name of a color from the internal table of hard-coded named colors.
Definition: parseutils.c:428
int av_reduce(int *dst_num, int *dst_den, int64_t num, int64_t den, int64_t max)
Reduce a fraction.
Definition: rational.c:35
AVRational av_d2q(double d, int max)
Convert a double precision floating point number to a rational.
Definition: rational.c:106
#define FFMIN(a, b)
Definition: common.h:81
float y
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
Definition: avstring.c:213
static struct tm * localtime_r(const time_t *clock, struct tm *result)
Definition: time_internal.h:37
int n
Definition: avisynth_c.h:547
#define FF_ARRAY_ELEMS(a)
static int color_table_compare(const void *lhs, const void *rhs)
Definition: parseutils.c:341
static const ColorEntry color_table[]
Definition: parseutils.c:198
static const VideoRateAbbr video_rate_abbrs[]
Definition: parseutils.c:131
static int date_get_num(const char **pp, int n_min, int n_max, int len_max)
Definition: parseutils.c:444
BYTE int const BYTE int int int height
Definition: avisynth_c.h:676
rational number numerator/denominator
Definition: rational.h:43
misc parsing utilities
static const VideoSizeAbbr video_size_abbrs[]
Definition: parseutils.c:75
common internal and external API header
static double c[64]
int den
denominator
Definition: rational.h:45
int len
uint32_t av_get_random_seed(void)
Get a seed to use in conjunction with random functions.
Definition: random_seed.c:109
int main(int argc, char **argv)
Definition: main.c:22
#define MKTAG(a, b, c, d)
Definition: common.h:330
#define av_parse_ratio_quiet(rate, str, max)
Definition: parseutils.h:52
simple arithmetic expression evaluator
const char * name
Definition: opengl_enc.c:103
static int width