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