FFmpeg
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 #include "time.h"
35 
36 #ifdef TEST
37 
38 #define av_get_random_seed av_get_random_seed_deterministic
39 static uint32_t av_get_random_seed_deterministic(void);
40 
41 #define av_gettime() 1331972053200000
42 
43 #endif
44 
45 int av_parse_ratio(AVRational *q, const char *str, int max,
46  int log_offset, void *log_ctx)
47 {
48  char c;
49  int ret;
50 
51  if (sscanf(str, "%d:%d%c", &q->num, &q->den, &c) != 2) {
52  double d;
53  ret = av_expr_parse_and_eval(&d, str, NULL, NULL,
54  NULL, NULL, NULL, NULL,
55  NULL, log_offset, log_ctx);
56  if (ret < 0)
57  return ret;
58  *q = av_d2q(d, max);
59  } else {
60  av_reduce(&q->num, &q->den, q->num, q->den, max);
61  }
62 
63  return 0;
64 }
65 
66 typedef struct VideoSizeAbbr {
67  const char *abbr;
68  int width, height;
70 
71 typedef struct VideoRateAbbr {
72  const char *abbr;
75 
76 static const VideoSizeAbbr video_size_abbrs[] = {
77  { "ntsc", 720, 480 },
78  { "pal", 720, 576 },
79  { "qntsc", 352, 240 }, /* VCD compliant NTSC */
80  { "qpal", 352, 288 }, /* VCD compliant PAL */
81  { "sntsc", 640, 480 }, /* square pixel NTSC */
82  { "spal", 768, 576 }, /* square pixel PAL */
83  { "film", 352, 240 },
84  { "ntsc-film", 352, 240 },
85  { "sqcif", 128, 96 },
86  { "qcif", 176, 144 },
87  { "cif", 352, 288 },
88  { "4cif", 704, 576 },
89  { "16cif", 1408,1152 },
90  { "qqvga", 160, 120 },
91  { "qvga", 320, 240 },
92  { "vga", 640, 480 },
93  { "svga", 800, 600 },
94  { "xga", 1024, 768 },
95  { "uxga", 1600,1200 },
96  { "qxga", 2048,1536 },
97  { "sxga", 1280,1024 },
98  { "qsxga", 2560,2048 },
99  { "hsxga", 5120,4096 },
100  { "wvga", 852, 480 },
101  { "wxga", 1366, 768 },
102  { "wsxga", 1600,1024 },
103  { "wuxga", 1920,1200 },
104  { "woxga", 2560,1600 },
105  { "wqhd", 2560,1440 },
106  { "wqsxga", 3200,2048 },
107  { "wquxga", 3840,2400 },
108  { "whsxga", 6400,4096 },
109  { "whuxga", 7680,4800 },
110  { "cga", 320, 200 },
111  { "ega", 640, 350 },
112  { "hd480", 852, 480 },
113  { "hd720", 1280, 720 },
114  { "hd1080", 1920,1080 },
115  { "quadhd", 2560,1440 },
116  { "2k", 2048,1080 }, /* Digital Cinema System Specification */
117  { "2kdci", 2048,1080 },
118  { "2kflat", 1998,1080 },
119  { "2kscope", 2048, 858 },
120  { "4k", 4096,2160 }, /* Digital Cinema System Specification */
121  { "4kdci", 4096,2160 },
122  { "4kflat", 3996,2160 },
123  { "4kscope", 4096,1716 },
124  { "nhd", 640,360 },
125  { "hqvga", 240,160 },
126  { "wqvga", 400,240 },
127  { "fwqvga", 432,240 },
128  { "hvga", 480,320 },
129  { "qhd", 960,540 },
130  { "uhd2160", 3840,2160 },
131  { "uhd4320", 7680,4320 },
132 };
133 
135  { "ntsc", { 30000, 1001 } },
136  { "pal", { 25, 1 } },
137  { "qntsc", { 30000, 1001 } }, /* VCD compliant NTSC */
138  { "qpal", { 25, 1 } }, /* VCD compliant PAL */
139  { "sntsc", { 30000, 1001 } }, /* square pixel NTSC */
140  { "spal", { 25, 1 } }, /* square pixel PAL */
141  { "film", { 24, 1 } },
142  { "ntsc-film", { 24000, 1001 } },
143 };
144 
145 static const char *months[12] = {
146  "january", "february", "march", "april", "may", "june", "july", "august",
147  "september", "october", "november", "december"
148 };
149 
150 int av_parse_video_size(int *width_ptr, int *height_ptr, const char *str)
151 {
152  int i;
154  const char *p;
155  int width = 0, height = 0;
156 
157  for (i = 0; i < n; i++) {
158  if (!strcmp(video_size_abbrs[i].abbr, str)) {
161  break;
162  }
163  }
164  if (i == n) {
165  width = strtol(str, (void*)&p, 10);
166  if (*p)
167  p++;
168  height = strtol(p, (void*)&p, 10);
169 
170  /* trailing extraneous data detected, like in 123x345foobar */
171  if (*p)
172  return AVERROR(EINVAL);
173  }
174  if (width <= 0 || height <= 0)
175  return AVERROR(EINVAL);
176  *width_ptr = width;
177  *height_ptr = height;
178  return 0;
179 }
180 
181 int av_parse_video_rate(AVRational *rate, const char *arg)
182 {
183  int i, ret;
185 
186  /* First, we check our abbreviation table */
187  for (i = 0; i < n; ++i)
188  if (!strcmp(video_rate_abbrs[i].abbr, arg)) {
189  *rate = video_rate_abbrs[i].rate;
190  return 0;
191  }
192 
193  /* Then, we try to parse it as fraction */
194  if ((ret = av_parse_ratio_quiet(rate, arg, 1001000)) < 0)
195  return ret;
196  if (!rate->num || !rate->den)
197  if ((ret = av_parse_ratio_quiet(rate, arg, INT_MAX)) < 0)
198  return ret;
199  if (rate->num <= 0 || rate->den <= 0)
200  return AVERROR(EINVAL);
201  return 0;
202 }
203 
204 typedef struct ColorEntry {
205  const char *name; ///< a string representing the name of the color
206  uint8_t rgb_color[3]; ///< RGB values for the color
207 } ColorEntry;
208 
209 static const ColorEntry color_table[] = {
210  { "AliceBlue", { 0xF0, 0xF8, 0xFF } },
211  { "AntiqueWhite", { 0xFA, 0xEB, 0xD7 } },
212  { "Aqua", { 0x00, 0xFF, 0xFF } },
213  { "Aquamarine", { 0x7F, 0xFF, 0xD4 } },
214  { "Azure", { 0xF0, 0xFF, 0xFF } },
215  { "Beige", { 0xF5, 0xF5, 0xDC } },
216  { "Bisque", { 0xFF, 0xE4, 0xC4 } },
217  { "Black", { 0x00, 0x00, 0x00 } },
218  { "BlanchedAlmond", { 0xFF, 0xEB, 0xCD } },
219  { "Blue", { 0x00, 0x00, 0xFF } },
220  { "BlueViolet", { 0x8A, 0x2B, 0xE2 } },
221  { "Brown", { 0xA5, 0x2A, 0x2A } },
222  { "BurlyWood", { 0xDE, 0xB8, 0x87 } },
223  { "CadetBlue", { 0x5F, 0x9E, 0xA0 } },
224  { "Chartreuse", { 0x7F, 0xFF, 0x00 } },
225  { "Chocolate", { 0xD2, 0x69, 0x1E } },
226  { "Coral", { 0xFF, 0x7F, 0x50 } },
227  { "CornflowerBlue", { 0x64, 0x95, 0xED } },
228  { "Cornsilk", { 0xFF, 0xF8, 0xDC } },
229  { "Crimson", { 0xDC, 0x14, 0x3C } },
230  { "Cyan", { 0x00, 0xFF, 0xFF } },
231  { "DarkBlue", { 0x00, 0x00, 0x8B } },
232  { "DarkCyan", { 0x00, 0x8B, 0x8B } },
233  { "DarkGoldenRod", { 0xB8, 0x86, 0x0B } },
234  { "DarkGray", { 0xA9, 0xA9, 0xA9 } },
235  { "DarkGreen", { 0x00, 0x64, 0x00 } },
236  { "DarkKhaki", { 0xBD, 0xB7, 0x6B } },
237  { "DarkMagenta", { 0x8B, 0x00, 0x8B } },
238  { "DarkOliveGreen", { 0x55, 0x6B, 0x2F } },
239  { "Darkorange", { 0xFF, 0x8C, 0x00 } },
240  { "DarkOrchid", { 0x99, 0x32, 0xCC } },
241  { "DarkRed", { 0x8B, 0x00, 0x00 } },
242  { "DarkSalmon", { 0xE9, 0x96, 0x7A } },
243  { "DarkSeaGreen", { 0x8F, 0xBC, 0x8F } },
244  { "DarkSlateBlue", { 0x48, 0x3D, 0x8B } },
245  { "DarkSlateGray", { 0x2F, 0x4F, 0x4F } },
246  { "DarkTurquoise", { 0x00, 0xCE, 0xD1 } },
247  { "DarkViolet", { 0x94, 0x00, 0xD3 } },
248  { "DeepPink", { 0xFF, 0x14, 0x93 } },
249  { "DeepSkyBlue", { 0x00, 0xBF, 0xFF } },
250  { "DimGray", { 0x69, 0x69, 0x69 } },
251  { "DodgerBlue", { 0x1E, 0x90, 0xFF } },
252  { "FireBrick", { 0xB2, 0x22, 0x22 } },
253  { "FloralWhite", { 0xFF, 0xFA, 0xF0 } },
254  { "ForestGreen", { 0x22, 0x8B, 0x22 } },
255  { "Fuchsia", { 0xFF, 0x00, 0xFF } },
256  { "Gainsboro", { 0xDC, 0xDC, 0xDC } },
257  { "GhostWhite", { 0xF8, 0xF8, 0xFF } },
258  { "Gold", { 0xFF, 0xD7, 0x00 } },
259  { "GoldenRod", { 0xDA, 0xA5, 0x20 } },
260  { "Gray", { 0x80, 0x80, 0x80 } },
261  { "Green", { 0x00, 0x80, 0x00 } },
262  { "GreenYellow", { 0xAD, 0xFF, 0x2F } },
263  { "HoneyDew", { 0xF0, 0xFF, 0xF0 } },
264  { "HotPink", { 0xFF, 0x69, 0xB4 } },
265  { "IndianRed", { 0xCD, 0x5C, 0x5C } },
266  { "Indigo", { 0x4B, 0x00, 0x82 } },
267  { "Ivory", { 0xFF, 0xFF, 0xF0 } },
268  { "Khaki", { 0xF0, 0xE6, 0x8C } },
269  { "Lavender", { 0xE6, 0xE6, 0xFA } },
270  { "LavenderBlush", { 0xFF, 0xF0, 0xF5 } },
271  { "LawnGreen", { 0x7C, 0xFC, 0x00 } },
272  { "LemonChiffon", { 0xFF, 0xFA, 0xCD } },
273  { "LightBlue", { 0xAD, 0xD8, 0xE6 } },
274  { "LightCoral", { 0xF0, 0x80, 0x80 } },
275  { "LightCyan", { 0xE0, 0xFF, 0xFF } },
276  { "LightGoldenRodYellow", { 0xFA, 0xFA, 0xD2 } },
277  { "LightGreen", { 0x90, 0xEE, 0x90 } },
278  { "LightGrey", { 0xD3, 0xD3, 0xD3 } },
279  { "LightPink", { 0xFF, 0xB6, 0xC1 } },
280  { "LightSalmon", { 0xFF, 0xA0, 0x7A } },
281  { "LightSeaGreen", { 0x20, 0xB2, 0xAA } },
282  { "LightSkyBlue", { 0x87, 0xCE, 0xFA } },
283  { "LightSlateGray", { 0x77, 0x88, 0x99 } },
284  { "LightSteelBlue", { 0xB0, 0xC4, 0xDE } },
285  { "LightYellow", { 0xFF, 0xFF, 0xE0 } },
286  { "Lime", { 0x00, 0xFF, 0x00 } },
287  { "LimeGreen", { 0x32, 0xCD, 0x32 } },
288  { "Linen", { 0xFA, 0xF0, 0xE6 } },
289  { "Magenta", { 0xFF, 0x00, 0xFF } },
290  { "Maroon", { 0x80, 0x00, 0x00 } },
291  { "MediumAquaMarine", { 0x66, 0xCD, 0xAA } },
292  { "MediumBlue", { 0x00, 0x00, 0xCD } },
293  { "MediumOrchid", { 0xBA, 0x55, 0xD3 } },
294  { "MediumPurple", { 0x93, 0x70, 0xD8 } },
295  { "MediumSeaGreen", { 0x3C, 0xB3, 0x71 } },
296  { "MediumSlateBlue", { 0x7B, 0x68, 0xEE } },
297  { "MediumSpringGreen", { 0x00, 0xFA, 0x9A } },
298  { "MediumTurquoise", { 0x48, 0xD1, 0xCC } },
299  { "MediumVioletRed", { 0xC7, 0x15, 0x85 } },
300  { "MidnightBlue", { 0x19, 0x19, 0x70 } },
301  { "MintCream", { 0xF5, 0xFF, 0xFA } },
302  { "MistyRose", { 0xFF, 0xE4, 0xE1 } },
303  { "Moccasin", { 0xFF, 0xE4, 0xB5 } },
304  { "NavajoWhite", { 0xFF, 0xDE, 0xAD } },
305  { "Navy", { 0x00, 0x00, 0x80 } },
306  { "OldLace", { 0xFD, 0xF5, 0xE6 } },
307  { "Olive", { 0x80, 0x80, 0x00 } },
308  { "OliveDrab", { 0x6B, 0x8E, 0x23 } },
309  { "Orange", { 0xFF, 0xA5, 0x00 } },
310  { "OrangeRed", { 0xFF, 0x45, 0x00 } },
311  { "Orchid", { 0xDA, 0x70, 0xD6 } },
312  { "PaleGoldenRod", { 0xEE, 0xE8, 0xAA } },
313  { "PaleGreen", { 0x98, 0xFB, 0x98 } },
314  { "PaleTurquoise", { 0xAF, 0xEE, 0xEE } },
315  { "PaleVioletRed", { 0xD8, 0x70, 0x93 } },
316  { "PapayaWhip", { 0xFF, 0xEF, 0xD5 } },
317  { "PeachPuff", { 0xFF, 0xDA, 0xB9 } },
318  { "Peru", { 0xCD, 0x85, 0x3F } },
319  { "Pink", { 0xFF, 0xC0, 0xCB } },
320  { "Plum", { 0xDD, 0xA0, 0xDD } },
321  { "PowderBlue", { 0xB0, 0xE0, 0xE6 } },
322  { "Purple", { 0x80, 0x00, 0x80 } },
323  { "Red", { 0xFF, 0x00, 0x00 } },
324  { "RosyBrown", { 0xBC, 0x8F, 0x8F } },
325  { "RoyalBlue", { 0x41, 0x69, 0xE1 } },
326  { "SaddleBrown", { 0x8B, 0x45, 0x13 } },
327  { "Salmon", { 0xFA, 0x80, 0x72 } },
328  { "SandyBrown", { 0xF4, 0xA4, 0x60 } },
329  { "SeaGreen", { 0x2E, 0x8B, 0x57 } },
330  { "SeaShell", { 0xFF, 0xF5, 0xEE } },
331  { "Sienna", { 0xA0, 0x52, 0x2D } },
332  { "Silver", { 0xC0, 0xC0, 0xC0 } },
333  { "SkyBlue", { 0x87, 0xCE, 0xEB } },
334  { "SlateBlue", { 0x6A, 0x5A, 0xCD } },
335  { "SlateGray", { 0x70, 0x80, 0x90 } },
336  { "Snow", { 0xFF, 0xFA, 0xFA } },
337  { "SpringGreen", { 0x00, 0xFF, 0x7F } },
338  { "SteelBlue", { 0x46, 0x82, 0xB4 } },
339  { "Tan", { 0xD2, 0xB4, 0x8C } },
340  { "Teal", { 0x00, 0x80, 0x80 } },
341  { "Thistle", { 0xD8, 0xBF, 0xD8 } },
342  { "Tomato", { 0xFF, 0x63, 0x47 } },
343  { "Turquoise", { 0x40, 0xE0, 0xD0 } },
344  { "Violet", { 0xEE, 0x82, 0xEE } },
345  { "Wheat", { 0xF5, 0xDE, 0xB3 } },
346  { "White", { 0xFF, 0xFF, 0xFF } },
347  { "WhiteSmoke", { 0xF5, 0xF5, 0xF5 } },
348  { "Yellow", { 0xFF, 0xFF, 0x00 } },
349  { "YellowGreen", { 0x9A, 0xCD, 0x32 } },
350 };
351 
352 static int color_table_compare(const void *lhs, const void *rhs)
353 {
354  return av_strcasecmp(lhs, ((const ColorEntry *)rhs)->name);
355 }
356 
357 #define ALPHA_SEP '@'
358 
359 int av_parse_color(uint8_t *rgba_color, const char *color_string, int slen,
360  void *log_ctx)
361 {
362  char *tail, color_string2[128];
363  const ColorEntry *entry;
364  int len, hex_offset = 0;
365 
366  if (color_string[0] == '#') {
367  hex_offset = 1;
368  } else if (!strncmp(color_string, "0x", 2))
369  hex_offset = 2;
370 
371  if (slen < 0)
372  slen = strlen(color_string);
373  av_strlcpy(color_string2, color_string + hex_offset,
374  FFMIN(slen-hex_offset+1, sizeof(color_string2)));
375  if ((tail = strchr(color_string2, ALPHA_SEP)))
376  *tail++ = 0;
377  len = strlen(color_string2);
378  rgba_color[3] = 255;
379 
380  if (!av_strcasecmp(color_string2, "random") || !av_strcasecmp(color_string2, "bikeshed")) {
381  int rgba = av_get_random_seed();
382  rgba_color[0] = rgba >> 24;
383  rgba_color[1] = rgba >> 16;
384  rgba_color[2] = rgba >> 8;
385  rgba_color[3] = rgba;
386  } else if (hex_offset ||
387  strspn(color_string2, "0123456789ABCDEFabcdef") == len) {
388  char *tail;
389  unsigned int rgba = strtoul(color_string2, &tail, 16);
390 
391  if (*tail || (len != 6 && len != 8)) {
392  av_log(log_ctx, AV_LOG_ERROR, "Invalid 0xRRGGBB[AA] color string: '%s'\n", color_string2);
393  return AVERROR(EINVAL);
394  }
395  if (len == 8) {
396  rgba_color[3] = rgba;
397  rgba >>= 8;
398  }
399  rgba_color[0] = rgba >> 16;
400  rgba_color[1] = rgba >> 8;
401  rgba_color[2] = rgba;
402  } else {
403  entry = bsearch(color_string2,
404  color_table,
406  sizeof(ColorEntry),
408  if (!entry) {
409  av_log(log_ctx, AV_LOG_ERROR, "Cannot find color '%s'\n", color_string2);
410  return AVERROR(EINVAL);
411  }
412  memcpy(rgba_color, entry->rgb_color, 3);
413  }
414 
415  if (tail) {
416  double alpha;
417  const char *alpha_string = tail;
418  if (!strncmp(alpha_string, "0x", 2)) {
419  alpha = strtoul(alpha_string, &tail, 16);
420  } else {
421  double norm_alpha = strtod(alpha_string, &tail);
422  if (norm_alpha < 0.0 || norm_alpha > 1.0)
423  alpha = 256;
424  else
425  alpha = 255 * norm_alpha;
426  }
427 
428  if (tail == alpha_string || *tail || alpha > 255 || alpha < 0) {
429  av_log(log_ctx, AV_LOG_ERROR, "Invalid alpha value specifier '%s' in '%s'\n",
430  alpha_string, color_string);
431  return AVERROR(EINVAL);
432  }
433  rgba_color[3] = alpha;
434  }
435 
436  return 0;
437 }
438 
439 const char *av_get_known_color_name(int color_idx, const uint8_t **rgbp)
440 {
441  const ColorEntry *color;
442 
443  if ((unsigned)color_idx >= FF_ARRAY_ELEMS(color_table))
444  return NULL;
445 
446  color = &color_table[color_idx];
447  if (rgbp)
448  *rgbp = color->rgb_color;
449 
450  return color->name;
451 }
452 
453 /* get a positive number between n_min and n_max, for a maximum length
454  of len_max. Return -1 if error. */
455 static int date_get_num(const char **pp,
456  int n_min, int n_max, int len_max)
457 {
458  int i, val, c;
459  const char *p;
460 
461  p = *pp;
462  val = 0;
463  for(i = 0; i < len_max; i++) {
464  c = *p;
465  if (!av_isdigit(c))
466  break;
467  val = (val * 10) + c - '0';
468  p++;
469  }
470  /* no number read ? */
471  if (p == *pp)
472  return -1;
473  if (val < n_min || val > n_max)
474  return -1;
475  *pp = p;
476  return val;
477 }
478 
479 static int date_get_month(const char **pp) {
480  int i = 0;
481  for (; i < 12; i++) {
482  if (!av_strncasecmp(*pp, months[i], 3)) {
483  const char *mo_full = months[i] + 3;
484  int len = strlen(mo_full);
485  *pp += 3;
486  if (len > 0 && !av_strncasecmp(*pp, mo_full, len))
487  *pp += len;
488  return i;
489  }
490  }
491  return -1;
492 }
493 
494 char *av_small_strptime(const char *p, const char *fmt, struct tm *dt)
495 {
496  int c, val;
497 
498  while((c = *fmt++)) {
499  if (c != '%') {
500  if (av_isspace(c))
501  for (; *p && av_isspace(*p); p++);
502  else if (*p != c)
503  return NULL;
504  else p++;
505  continue;
506  }
507 
508  c = *fmt++;
509  switch(c) {
510  case 'H':
511  case 'J':
512  val = date_get_num(&p, 0, c == 'H' ? 23 : INT_MAX, c == 'H' ? 2 : 4);
513 
514  if (val == -1)
515  return NULL;
516  dt->tm_hour = val;
517  break;
518  case 'M':
519  val = date_get_num(&p, 0, 59, 2);
520  if (val == -1)
521  return NULL;
522  dt->tm_min = val;
523  break;
524  case 'S':
525  val = date_get_num(&p, 0, 59, 2);
526  if (val == -1)
527  return NULL;
528  dt->tm_sec = val;
529  break;
530  case 'Y':
531  val = date_get_num(&p, 0, 9999, 4);
532  if (val == -1)
533  return NULL;
534  dt->tm_year = val - 1900;
535  break;
536  case 'm':
537  val = date_get_num(&p, 1, 12, 2);
538  if (val == -1)
539  return NULL;
540  dt->tm_mon = val - 1;
541  break;
542  case 'd':
543  val = date_get_num(&p, 1, 31, 2);
544  if (val == -1)
545  return NULL;
546  dt->tm_mday = val;
547  break;
548  case 'T':
549  p = av_small_strptime(p, "%H:%M:%S", dt);
550  if (!p)
551  return NULL;
552  break;
553  case 'b':
554  case 'B':
555  case 'h':
556  val = date_get_month(&p);
557  if (val == -1)
558  return NULL;
559  dt->tm_mon = val;
560  break;
561  case '%':
562  if (*p++ != '%')
563  return NULL;
564  break;
565  default:
566  return NULL;
567  }
568  }
569 
570  return (char*)p;
571 }
572 
573 time_t av_timegm(struct tm *tm)
574 {
575  time_t t;
576 
577  int y = tm->tm_year + 1900, m = tm->tm_mon + 1, d = tm->tm_mday;
578 
579  if (m < 3) {
580  m += 12;
581  y--;
582  }
583 
584  t = 86400LL *
585  (d + (153 * m - 457) / 5 + 365 * y + y / 4 - y / 100 + y / 400 - 719469);
586 
587  t += 3600 * tm->tm_hour + 60 * tm->tm_min + tm->tm_sec;
588 
589  return t;
590 }
591 
592 int av_parse_time(int64_t *timeval, const char *timestr, int duration)
593 {
594  const char *p, *q;
595  int64_t t, now64;
596  time_t now;
597  struct tm dt = { 0 }, tmbuf;
598  int today = 0, negative = 0, microseconds = 0, suffix = 1000000;
599  int i;
600  static const char * const date_fmt[] = {
601  "%Y - %m - %d",
602  "%Y%m%d",
603  };
604  static const char * const time_fmt[] = {
605  "%H:%M:%S",
606  "%H%M%S",
607  };
608  static const char * const tz_fmt[] = {
609  "%H:%M",
610  "%H%M",
611  "%H",
612  };
613 
614  p = timestr;
615  q = NULL;
616  *timeval = INT64_MIN;
617  if (!duration) {
618  now64 = av_gettime();
619  now = now64 / 1000000;
620 
621  if (!av_strcasecmp(timestr, "now")) {
622  *timeval = now64;
623  return 0;
624  }
625 
626  /* parse the year-month-day part */
627  for (i = 0; i < FF_ARRAY_ELEMS(date_fmt); i++) {
628  q = av_small_strptime(p, date_fmt[i], &dt);
629  if (q)
630  break;
631  }
632 
633  /* if the year-month-day part is missing, then take the
634  * current year-month-day time */
635  if (!q) {
636  today = 1;
637  q = p;
638  }
639  p = q;
640 
641  if (*p == 'T' || *p == 't')
642  p++;
643  else
644  while (av_isspace(*p))
645  p++;
646 
647  /* parse the hour-minute-second part */
648  for (i = 0; i < FF_ARRAY_ELEMS(time_fmt); i++) {
649  q = av_small_strptime(p, time_fmt[i], &dt);
650  if (q)
651  break;
652  }
653  } else {
654  /* parse timestr as a duration */
655  if (p[0] == '-') {
656  negative = 1;
657  ++p;
658  }
659  /* parse timestr as HH:MM:SS */
660  q = av_small_strptime(p, "%J:%M:%S", &dt);
661  if (!q) {
662  /* parse timestr as MM:SS */
663  q = av_small_strptime(p, "%M:%S", &dt);
664  dt.tm_hour = 0;
665  }
666  if (!q) {
667  char *o;
668  /* parse timestr as S+ */
669  errno = 0;
670  t = strtoll(p, &o, 10);
671  if (o == p) /* the parsing didn't succeed */
672  return AVERROR(EINVAL);
673  if (errno == ERANGE)
674  return AVERROR(ERANGE);
675  q = o;
676  } else {
677  t = dt.tm_hour * 3600 + dt.tm_min * 60 + dt.tm_sec;
678  }
679  }
680 
681  /* Now we have all the fields that we can get */
682  if (!q)
683  return AVERROR(EINVAL);
684 
685  /* parse the .m... part */
686  if (*q == '.') {
687  int n;
688  q++;
689  for (n = 100000; n >= 1; n /= 10, q++) {
690  if (!av_isdigit(*q))
691  break;
692  microseconds += n * (*q - '0');
693  }
694  while (av_isdigit(*q))
695  q++;
696  }
697 
698  if (duration) {
699  if (q[0] == 'm' && q[1] == 's') {
700  suffix = 1000;
701  microseconds /= 1000;
702  q += 2;
703  } else if (q[0] == 'u' && q[1] == 's') {
704  suffix = 1;
705  microseconds = 0;
706  q += 2;
707  } else if (*q == 's')
708  q++;
709  } else {
710  int is_utc = *q == 'Z' || *q == 'z';
711  int tzoffset = 0;
712  q += is_utc;
713  if (!today && !is_utc && (*q == '+' || *q == '-')) {
714  struct tm tz = { 0 };
715  int sign = (*q == '+' ? -1 : 1);
716  q++;
717  p = q;
718  for (i = 0; i < FF_ARRAY_ELEMS(tz_fmt); i++) {
719  q = av_small_strptime(p, tz_fmt[i], &tz);
720  if (q)
721  break;
722  }
723  if (!q)
724  return AVERROR(EINVAL);
725  tzoffset = sign * (tz.tm_hour * 60 + tz.tm_min) * 60;
726  is_utc = 1;
727  }
728  if (today) { /* fill in today's date */
729  struct tm dt2 = is_utc ? *gmtime_r(&now, &tmbuf) : *localtime_r(&now, &tmbuf);
730  dt2.tm_hour = dt.tm_hour;
731  dt2.tm_min = dt.tm_min;
732  dt2.tm_sec = dt.tm_sec;
733  dt = dt2;
734  }
735  dt.tm_isdst = is_utc ? 0 : -1;
736  t = is_utc ? av_timegm(&dt) : mktime(&dt);
737  t += tzoffset;
738  }
739 
740  /* Check that we are at the end of the string */
741  if (*q)
742  return AVERROR(EINVAL);
743 
744  if (INT64_MAX / suffix < t || t < INT64_MIN / suffix)
745  return AVERROR(ERANGE);
746  t *= suffix;
747  if (INT64_MAX - microseconds < t)
748  return AVERROR(ERANGE);
749  t += microseconds;
750  if (t == INT64_MIN && negative)
751  return AVERROR(ERANGE);
752  *timeval = negative ? -t : t;
753  return 0;
754 }
755 
756 int av_find_info_tag(char *arg, int arg_size, const char *tag1, const char *info)
757 {
758  const char *p;
759  char tag[128], *q;
760 
761  p = info;
762  if (*p == '?')
763  p++;
764  for(;;) {
765  q = tag;
766  while (*p != '\0' && *p != '=' && *p != '&') {
767  if ((q - tag) < sizeof(tag) - 1)
768  *q++ = *p;
769  p++;
770  }
771  *q = '\0';
772  q = arg;
773  if (*p == '=') {
774  p++;
775  while (*p != '&' && *p != '\0') {
776  if ((q - arg) < arg_size - 1) {
777  if (*p == '+')
778  *q++ = ' ';
779  else
780  *q++ = *p;
781  }
782  p++;
783  }
784  }
785  *q = '\0';
786  if (!strcmp(tag, tag1))
787  return 1;
788  if (*p != '&')
789  break;
790  p++;
791  }
792  return 0;
793 }
VideoSizeAbbr::height
int height
Definition: parseutils.c:68
color_table_compare
static int color_table_compare(const void *lhs, const void *rhs)
Definition: parseutils.c:352
name
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default minimum maximum flags name is the option name
Definition: writing_filters.txt:88
entry
#define entry
Definition: aom_film_grain_template.c:66
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
av_find_info_tag
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:756
color
Definition: vf_paletteuse.c:513
strtod
double strtod(const char *, char **)
av_parse_color
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:359
int64_t
long long int64_t
Definition: coverity.c:34
av_strcasecmp
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
Definition: avstring.c:207
av_isspace
static av_const int av_isspace(int c)
Locale-independent conversion of ASCII isspace.
Definition: avstring.h:218
video_rate_abbrs
static const VideoRateAbbr video_rate_abbrs[]
Definition: parseutils.c:134
date_get_num
static int date_get_num(const char **pp, int n_min, int n_max, int len_max)
Definition: parseutils.c:455
max
#define max(a, b)
Definition: cuda_runtime.h:33
VideoRateAbbr::rate
AVRational rate
Definition: parseutils.c:73
av_get_random_seed
uint32_t av_get_random_seed(void)
Get a seed to use in conjunction with random functions.
Definition: random_seed.c:167
gmtime_r
#define gmtime_r
Definition: time_internal.h:34
VideoRateAbbr
Definition: parseutils.c:71
val
static double val(void *priv, double ch)
Definition: aeval.c:77
av_timegm
time_t av_timegm(struct tm *tm)
Convert the decomposed UTC time in tm to a time_t value.
Definition: parseutils.c:573
av_reduce
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
VideoSizeAbbr::abbr
const char * abbr
Definition: parseutils.c:67
AVRational::num
int num
Numerator.
Definition: rational.h:59
months
static const char * months[12]
Definition: parseutils.c:145
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:209
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
duration
int64_t duration
Definition: movenc.c:65
color_table
static const ColorEntry color_table[]
Definition: parseutils.c:209
info
MIPS optimizations info
Definition: mips.txt:2
VideoSizeAbbr::width
int width
Definition: parseutils.c:68
video_size_abbrs
static const VideoSizeAbbr video_size_abbrs[]
Definition: parseutils.c:76
arg
const char * arg
Definition: jacosubdec.c:67
time_internal.h
NULL
#define NULL
Definition: coverity.c:32
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
parseutils.h
ColorEntry::rgb_color
uint32_t rgb_color
RGB values for the color.
Definition: xpmdec.c:43
av_parse_time
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:592
time.h
av_parse_ratio
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:45
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
av_strncasecmp
int av_strncasecmp(const char *a, const char *b, size_t n)
Locale-independent case-insensitive compare.
Definition: avstring.c:217
eval.h
av_parse_ratio_quiet
#define av_parse_ratio_quiet(rate, str, max)
Definition: parseutils.h:52
av_expr_parse_and_eval
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:803
height
#define height
Definition: dsp.h:85
localtime_r
#define localtime_r
Definition: time_internal.h:46
color
static const uint32_t color[16+AV_CLASS_CATEGORY_NB]
Definition: log.c:94
av_isdigit
static av_const int av_isdigit(int c)
Locale-independent conversion of ASCII isdigit.
Definition: avstring.h:202
av_parse_video_size
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:150
ColorEntry
Definition: xpmdec.c:41
av_parse_video_rate
int av_parse_video_rate(AVRational *rate, const char *arg)
Parse str and store the detected values in *rate.
Definition: parseutils.c:181
log.h
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
ALPHA_SEP
#define ALPHA_SEP
Definition: parseutils.c:357
av_get_random_seed_deterministic
static uint32_t av_get_random_seed_deterministic(void)
Definition: parseutils.c:31
common.h
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
av_d2q
AVRational av_d2q(double d, int max)
Convert a double precision floating point number to a rational.
Definition: rational.c:106
VideoSizeAbbr
Definition: parseutils.c:66
date_get_month
static int date_get_month(const char **pp)
Definition: parseutils.c:479
len
int len
Definition: vorbis_enc_data.h:426
tag
uint32_t tag
Definition: movenc.c:1879
ret
ret
Definition: filter_design.txt:187
av_small_strptime
char * av_small_strptime(const char *p, const char *fmt, struct tm *dt)
Simplified version of strptime.
Definition: parseutils.c:494
suffix
const char * suffix
Definition: checkasm.c:309
random_seed.h
VideoRateAbbr::abbr
const char * abbr
Definition: parseutils.c:72
AVRational::den
int den
Denominator.
Definition: rational.h:60
av_gettime
int64_t av_gettime(void)
Get the current time in microseconds.
Definition: time.c:39
avutil.h
av_get_known_color_name
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:439
alpha
static const int16_t alpha[]
Definition: ilbcdata.h:55
av_strlcpy
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:85
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
avstring.h
width
#define width
Definition: dsp.h:85
ColorEntry::name
const char * name
a string representing the name of the color
Definition: xpmdec.c:42