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;
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 <= 0 || rate->den <= 0)
197  return AVERROR(EINVAL);
198  return 0;
199 }
200 
201 typedef struct ColorEntry {
202  const char *name; ///< a string representing the name of the color
203  uint8_t rgb_color[3]; ///< RGB values for the color
204 } ColorEntry;
205 
206 static const ColorEntry color_table[] = {
207  { "AliceBlue", { 0xF0, 0xF8, 0xFF } },
208  { "AntiqueWhite", { 0xFA, 0xEB, 0xD7 } },
209  { "Aqua", { 0x00, 0xFF, 0xFF } },
210  { "Aquamarine", { 0x7F, 0xFF, 0xD4 } },
211  { "Azure", { 0xF0, 0xFF, 0xFF } },
212  { "Beige", { 0xF5, 0xF5, 0xDC } },
213  { "Bisque", { 0xFF, 0xE4, 0xC4 } },
214  { "Black", { 0x00, 0x00, 0x00 } },
215  { "BlanchedAlmond", { 0xFF, 0xEB, 0xCD } },
216  { "Blue", { 0x00, 0x00, 0xFF } },
217  { "BlueViolet", { 0x8A, 0x2B, 0xE2 } },
218  { "Brown", { 0xA5, 0x2A, 0x2A } },
219  { "BurlyWood", { 0xDE, 0xB8, 0x87 } },
220  { "CadetBlue", { 0x5F, 0x9E, 0xA0 } },
221  { "Chartreuse", { 0x7F, 0xFF, 0x00 } },
222  { "Chocolate", { 0xD2, 0x69, 0x1E } },
223  { "Coral", { 0xFF, 0x7F, 0x50 } },
224  { "CornflowerBlue", { 0x64, 0x95, 0xED } },
225  { "Cornsilk", { 0xFF, 0xF8, 0xDC } },
226  { "Crimson", { 0xDC, 0x14, 0x3C } },
227  { "Cyan", { 0x00, 0xFF, 0xFF } },
228  { "DarkBlue", { 0x00, 0x00, 0x8B } },
229  { "DarkCyan", { 0x00, 0x8B, 0x8B } },
230  { "DarkGoldenRod", { 0xB8, 0x86, 0x0B } },
231  { "DarkGray", { 0xA9, 0xA9, 0xA9 } },
232  { "DarkGreen", { 0x00, 0x64, 0x00 } },
233  { "DarkKhaki", { 0xBD, 0xB7, 0x6B } },
234  { "DarkMagenta", { 0x8B, 0x00, 0x8B } },
235  { "DarkOliveGreen", { 0x55, 0x6B, 0x2F } },
236  { "Darkorange", { 0xFF, 0x8C, 0x00 } },
237  { "DarkOrchid", { 0x99, 0x32, 0xCC } },
238  { "DarkRed", { 0x8B, 0x00, 0x00 } },
239  { "DarkSalmon", { 0xE9, 0x96, 0x7A } },
240  { "DarkSeaGreen", { 0x8F, 0xBC, 0x8F } },
241  { "DarkSlateBlue", { 0x48, 0x3D, 0x8B } },
242  { "DarkSlateGray", { 0x2F, 0x4F, 0x4F } },
243  { "DarkTurquoise", { 0x00, 0xCE, 0xD1 } },
244  { "DarkViolet", { 0x94, 0x00, 0xD3 } },
245  { "DeepPink", { 0xFF, 0x14, 0x93 } },
246  { "DeepSkyBlue", { 0x00, 0xBF, 0xFF } },
247  { "DimGray", { 0x69, 0x69, 0x69 } },
248  { "DodgerBlue", { 0x1E, 0x90, 0xFF } },
249  { "FireBrick", { 0xB2, 0x22, 0x22 } },
250  { "FloralWhite", { 0xFF, 0xFA, 0xF0 } },
251  { "ForestGreen", { 0x22, 0x8B, 0x22 } },
252  { "Fuchsia", { 0xFF, 0x00, 0xFF } },
253  { "Gainsboro", { 0xDC, 0xDC, 0xDC } },
254  { "GhostWhite", { 0xF8, 0xF8, 0xFF } },
255  { "Gold", { 0xFF, 0xD7, 0x00 } },
256  { "GoldenRod", { 0xDA, 0xA5, 0x20 } },
257  { "Gray", { 0x80, 0x80, 0x80 } },
258  { "Green", { 0x00, 0x80, 0x00 } },
259  { "GreenYellow", { 0xAD, 0xFF, 0x2F } },
260  { "HoneyDew", { 0xF0, 0xFF, 0xF0 } },
261  { "HotPink", { 0xFF, 0x69, 0xB4 } },
262  { "IndianRed", { 0xCD, 0x5C, 0x5C } },
263  { "Indigo", { 0x4B, 0x00, 0x82 } },
264  { "Ivory", { 0xFF, 0xFF, 0xF0 } },
265  { "Khaki", { 0xF0, 0xE6, 0x8C } },
266  { "Lavender", { 0xE6, 0xE6, 0xFA } },
267  { "LavenderBlush", { 0xFF, 0xF0, 0xF5 } },
268  { "LawnGreen", { 0x7C, 0xFC, 0x00 } },
269  { "LemonChiffon", { 0xFF, 0xFA, 0xCD } },
270  { "LightBlue", { 0xAD, 0xD8, 0xE6 } },
271  { "LightCoral", { 0xF0, 0x80, 0x80 } },
272  { "LightCyan", { 0xE0, 0xFF, 0xFF } },
273  { "LightGoldenRodYellow", { 0xFA, 0xFA, 0xD2 } },
274  { "LightGreen", { 0x90, 0xEE, 0x90 } },
275  { "LightGrey", { 0xD3, 0xD3, 0xD3 } },
276  { "LightPink", { 0xFF, 0xB6, 0xC1 } },
277  { "LightSalmon", { 0xFF, 0xA0, 0x7A } },
278  { "LightSeaGreen", { 0x20, 0xB2, 0xAA } },
279  { "LightSkyBlue", { 0x87, 0xCE, 0xFA } },
280  { "LightSlateGray", { 0x77, 0x88, 0x99 } },
281  { "LightSteelBlue", { 0xB0, 0xC4, 0xDE } },
282  { "LightYellow", { 0xFF, 0xFF, 0xE0 } },
283  { "Lime", { 0x00, 0xFF, 0x00 } },
284  { "LimeGreen", { 0x32, 0xCD, 0x32 } },
285  { "Linen", { 0xFA, 0xF0, 0xE6 } },
286  { "Magenta", { 0xFF, 0x00, 0xFF } },
287  { "Maroon", { 0x80, 0x00, 0x00 } },
288  { "MediumAquaMarine", { 0x66, 0xCD, 0xAA } },
289  { "MediumBlue", { 0x00, 0x00, 0xCD } },
290  { "MediumOrchid", { 0xBA, 0x55, 0xD3 } },
291  { "MediumPurple", { 0x93, 0x70, 0xD8 } },
292  { "MediumSeaGreen", { 0x3C, 0xB3, 0x71 } },
293  { "MediumSlateBlue", { 0x7B, 0x68, 0xEE } },
294  { "MediumSpringGreen", { 0x00, 0xFA, 0x9A } },
295  { "MediumTurquoise", { 0x48, 0xD1, 0xCC } },
296  { "MediumVioletRed", { 0xC7, 0x15, 0x85 } },
297  { "MidnightBlue", { 0x19, 0x19, 0x70 } },
298  { "MintCream", { 0xF5, 0xFF, 0xFA } },
299  { "MistyRose", { 0xFF, 0xE4, 0xE1 } },
300  { "Moccasin", { 0xFF, 0xE4, 0xB5 } },
301  { "NavajoWhite", { 0xFF, 0xDE, 0xAD } },
302  { "Navy", { 0x00, 0x00, 0x80 } },
303  { "OldLace", { 0xFD, 0xF5, 0xE6 } },
304  { "Olive", { 0x80, 0x80, 0x00 } },
305  { "OliveDrab", { 0x6B, 0x8E, 0x23 } },
306  { "Orange", { 0xFF, 0xA5, 0x00 } },
307  { "OrangeRed", { 0xFF, 0x45, 0x00 } },
308  { "Orchid", { 0xDA, 0x70, 0xD6 } },
309  { "PaleGoldenRod", { 0xEE, 0xE8, 0xAA } },
310  { "PaleGreen", { 0x98, 0xFB, 0x98 } },
311  { "PaleTurquoise", { 0xAF, 0xEE, 0xEE } },
312  { "PaleVioletRed", { 0xD8, 0x70, 0x93 } },
313  { "PapayaWhip", { 0xFF, 0xEF, 0xD5 } },
314  { "PeachPuff", { 0xFF, 0xDA, 0xB9 } },
315  { "Peru", { 0xCD, 0x85, 0x3F } },
316  { "Pink", { 0xFF, 0xC0, 0xCB } },
317  { "Plum", { 0xDD, 0xA0, 0xDD } },
318  { "PowderBlue", { 0xB0, 0xE0, 0xE6 } },
319  { "Purple", { 0x80, 0x00, 0x80 } },
320  { "Red", { 0xFF, 0x00, 0x00 } },
321  { "RosyBrown", { 0xBC, 0x8F, 0x8F } },
322  { "RoyalBlue", { 0x41, 0x69, 0xE1 } },
323  { "SaddleBrown", { 0x8B, 0x45, 0x13 } },
324  { "Salmon", { 0xFA, 0x80, 0x72 } },
325  { "SandyBrown", { 0xF4, 0xA4, 0x60 } },
326  { "SeaGreen", { 0x2E, 0x8B, 0x57 } },
327  { "SeaShell", { 0xFF, 0xF5, 0xEE } },
328  { "Sienna", { 0xA0, 0x52, 0x2D } },
329  { "Silver", { 0xC0, 0xC0, 0xC0 } },
330  { "SkyBlue", { 0x87, 0xCE, 0xEB } },
331  { "SlateBlue", { 0x6A, 0x5A, 0xCD } },
332  { "SlateGray", { 0x70, 0x80, 0x90 } },
333  { "Snow", { 0xFF, 0xFA, 0xFA } },
334  { "SpringGreen", { 0x00, 0xFF, 0x7F } },
335  { "SteelBlue", { 0x46, 0x82, 0xB4 } },
336  { "Tan", { 0xD2, 0xB4, 0x8C } },
337  { "Teal", { 0x00, 0x80, 0x80 } },
338  { "Thistle", { 0xD8, 0xBF, 0xD8 } },
339  { "Tomato", { 0xFF, 0x63, 0x47 } },
340  { "Turquoise", { 0x40, 0xE0, 0xD0 } },
341  { "Violet", { 0xEE, 0x82, 0xEE } },
342  { "Wheat", { 0xF5, 0xDE, 0xB3 } },
343  { "White", { 0xFF, 0xFF, 0xFF } },
344  { "WhiteSmoke", { 0xF5, 0xF5, 0xF5 } },
345  { "Yellow", { 0xFF, 0xFF, 0x00 } },
346  { "YellowGreen", { 0x9A, 0xCD, 0x32 } },
347 };
348 
349 static int color_table_compare(const void *lhs, const void *rhs)
350 {
351  return av_strcasecmp(lhs, ((const ColorEntry *)rhs)->name);
352 }
353 
354 #define ALPHA_SEP '@'
355 
356 int av_parse_color(uint8_t *rgba_color, const char *color_string, int slen,
357  void *log_ctx)
358 {
359  char *tail, color_string2[128];
360  const ColorEntry *entry;
361  int len, hex_offset = 0;
362 
363  if (color_string[0] == '#') {
364  hex_offset = 1;
365  } else if (!strncmp(color_string, "0x", 2))
366  hex_offset = 2;
367 
368  if (slen < 0)
369  slen = strlen(color_string);
370  av_strlcpy(color_string2, color_string + hex_offset,
371  FFMIN(slen-hex_offset+1, sizeof(color_string2)));
372  if ((tail = strchr(color_string2, ALPHA_SEP)))
373  *tail++ = 0;
374  len = strlen(color_string2);
375  rgba_color[3] = 255;
376 
377  if (!av_strcasecmp(color_string2, "random") || !av_strcasecmp(color_string2, "bikeshed")) {
378  int rgba = av_get_random_seed();
379  rgba_color[0] = rgba >> 24;
380  rgba_color[1] = rgba >> 16;
381  rgba_color[2] = rgba >> 8;
382  rgba_color[3] = rgba;
383  } else if (hex_offset ||
384  strspn(color_string2, "0123456789ABCDEFabcdef") == len) {
385  char *tail;
386  unsigned int rgba = strtoul(color_string2, &tail, 16);
387 
388  if (*tail || (len != 6 && len != 8)) {
389  av_log(log_ctx, AV_LOG_ERROR, "Invalid 0xRRGGBB[AA] color string: '%s'\n", color_string2);
390  return AVERROR(EINVAL);
391  }
392  if (len == 8) {
393  rgba_color[3] = rgba;
394  rgba >>= 8;
395  }
396  rgba_color[0] = rgba >> 16;
397  rgba_color[1] = rgba >> 8;
398  rgba_color[2] = rgba;
399  } else {
400  entry = bsearch(color_string2,
401  color_table,
403  sizeof(ColorEntry),
405  if (!entry) {
406  av_log(log_ctx, AV_LOG_ERROR, "Cannot find color '%s'\n", color_string2);
407  return AVERROR(EINVAL);
408  }
409  memcpy(rgba_color, entry->rgb_color, 3);
410  }
411 
412  if (tail) {
413  double alpha;
414  const char *alpha_string = tail;
415  if (!strncmp(alpha_string, "0x", 2)) {
416  alpha = strtoul(alpha_string, &tail, 16);
417  } else {
418  double norm_alpha = strtod(alpha_string, &tail);
419  if (norm_alpha < 0.0 || norm_alpha > 1.0)
420  alpha = 256;
421  else
422  alpha = 255 * norm_alpha;
423  }
424 
425  if (tail == alpha_string || *tail || alpha > 255 || alpha < 0) {
426  av_log(log_ctx, AV_LOG_ERROR, "Invalid alpha value specifier '%s' in '%s'\n",
427  alpha_string, color_string);
428  return AVERROR(EINVAL);
429  }
430  rgba_color[3] = alpha;
431  }
432 
433  return 0;
434 }
435 
436 const char *av_get_known_color_name(int color_idx, const uint8_t **rgbp)
437 {
438  const ColorEntry *color;
439 
440  if ((unsigned)color_idx >= FF_ARRAY_ELEMS(color_table))
441  return NULL;
442 
443  color = &color_table[color_idx];
444  if (rgbp)
445  *rgbp = color->rgb_color;
446 
447  return color->name;
448 }
449 
450 /* get a positive number between n_min and n_max, for a maximum length
451  of len_max. Return -1 if error. */
452 static int date_get_num(const char **pp,
453  int n_min, int n_max, int len_max)
454 {
455  int i, val, c;
456  const char *p;
457 
458  p = *pp;
459  val = 0;
460  for(i = 0; i < len_max; i++) {
461  c = *p;
462  if (!av_isdigit(c))
463  break;
464  val = (val * 10) + c - '0';
465  p++;
466  }
467  /* no number read ? */
468  if (p == *pp)
469  return -1;
470  if (val < n_min || val > n_max)
471  return -1;
472  *pp = p;
473  return val;
474 }
475 
476 static int date_get_month(const char **pp) {
477  int i = 0;
478  for (; i < 12; i++) {
479  if (!av_strncasecmp(*pp, months[i], 3)) {
480  const char *mo_full = months[i] + 3;
481  int len = strlen(mo_full);
482  *pp += 3;
483  if (len > 0 && !av_strncasecmp(*pp, mo_full, len))
484  *pp += len;
485  return i;
486  }
487  }
488  return -1;
489 }
490 
491 char *av_small_strptime(const char *p, const char *fmt, struct tm *dt)
492 {
493  int c, val;
494 
495  while((c = *fmt++)) {
496  if (c != '%') {
497  if (av_isspace(c))
498  for (; *p && av_isspace(*p); p++);
499  else if (*p != c)
500  return NULL;
501  else p++;
502  continue;
503  }
504 
505  c = *fmt++;
506  switch(c) {
507  case 'H':
508  case 'J':
509  val = date_get_num(&p, 0, c == 'H' ? 23 : INT_MAX, c == 'H' ? 2 : 4);
510 
511  if (val == -1)
512  return NULL;
513  dt->tm_hour = val;
514  break;
515  case 'M':
516  val = date_get_num(&p, 0, 59, 2);
517  if (val == -1)
518  return NULL;
519  dt->tm_min = val;
520  break;
521  case 'S':
522  val = date_get_num(&p, 0, 59, 2);
523  if (val == -1)
524  return NULL;
525  dt->tm_sec = val;
526  break;
527  case 'Y':
528  val = date_get_num(&p, 0, 9999, 4);
529  if (val == -1)
530  return NULL;
531  dt->tm_year = val - 1900;
532  break;
533  case 'm':
534  val = date_get_num(&p, 1, 12, 2);
535  if (val == -1)
536  return NULL;
537  dt->tm_mon = val - 1;
538  break;
539  case 'd':
540  val = date_get_num(&p, 1, 31, 2);
541  if (val == -1)
542  return NULL;
543  dt->tm_mday = val;
544  break;
545  case 'T':
546  p = av_small_strptime(p, "%H:%M:%S", dt);
547  if (!p)
548  return NULL;
549  break;
550  case 'b':
551  case 'B':
552  case 'h':
553  val = date_get_month(&p);
554  if (val == -1)
555  return NULL;
556  dt->tm_mon = val;
557  break;
558  case '%':
559  if (*p++ != '%')
560  return NULL;
561  break;
562  default:
563  return NULL;
564  }
565  }
566 
567  return (char*)p;
568 }
569 
570 time_t av_timegm(struct tm *tm)
571 {
572  time_t t;
573 
574  int y = tm->tm_year + 1900, m = tm->tm_mon + 1, d = tm->tm_mday;
575 
576  if (m < 3) {
577  m += 12;
578  y--;
579  }
580 
581  t = 86400LL *
582  (d + (153 * m - 457) / 5 + 365 * y + y / 4 - y / 100 + y / 400 - 719469);
583 
584  t += 3600 * tm->tm_hour + 60 * tm->tm_min + tm->tm_sec;
585 
586  return t;
587 }
588 
589 int av_parse_time(int64_t *timeval, const char *timestr, int duration)
590 {
591  const char *p, *q;
592  int64_t t, now64;
593  time_t now;
594  struct tm dt = { 0 }, tmbuf;
595  int today = 0, negative = 0, microseconds = 0, suffix = 1000000;
596  int i;
597  static const char * const date_fmt[] = {
598  "%Y - %m - %d",
599  "%Y%m%d",
600  };
601  static const char * const time_fmt[] = {
602  "%H:%M:%S",
603  "%H%M%S",
604  };
605  static const char * const tz_fmt[] = {
606  "%H:%M",
607  "%H%M",
608  "%H",
609  };
610 
611  p = timestr;
612  q = NULL;
613  *timeval = INT64_MIN;
614  if (!duration) {
615  now64 = av_gettime();
616  now = now64 / 1000000;
617 
618  if (!av_strcasecmp(timestr, "now")) {
619  *timeval = now64;
620  return 0;
621  }
622 
623  /* parse the year-month-day part */
624  for (i = 0; i < FF_ARRAY_ELEMS(date_fmt); i++) {
625  q = av_small_strptime(p, date_fmt[i], &dt);
626  if (q)
627  break;
628  }
629 
630  /* if the year-month-day part is missing, then take the
631  * current year-month-day time */
632  if (!q) {
633  today = 1;
634  q = p;
635  }
636  p = q;
637 
638  if (*p == 'T' || *p == 't')
639  p++;
640  else
641  while (av_isspace(*p))
642  p++;
643 
644  /* parse the hour-minute-second part */
645  for (i = 0; i < FF_ARRAY_ELEMS(time_fmt); i++) {
646  q = av_small_strptime(p, time_fmt[i], &dt);
647  if (q)
648  break;
649  }
650  } else {
651  /* parse timestr as a duration */
652  if (p[0] == '-') {
653  negative = 1;
654  ++p;
655  }
656  /* parse timestr as HH:MM:SS */
657  q = av_small_strptime(p, "%J:%M:%S", &dt);
658  if (!q) {
659  /* parse timestr as MM:SS */
660  q = av_small_strptime(p, "%M:%S", &dt);
661  dt.tm_hour = 0;
662  }
663  if (!q) {
664  char *o;
665  /* parse timestr as S+ */
666  errno = 0;
667  t = strtoll(p, &o, 10);
668  if (o == p) /* the parsing didn't succeed */
669  return AVERROR(EINVAL);
670  if (errno == ERANGE)
671  return AVERROR(ERANGE);
672  q = o;
673  } else {
674  t = dt.tm_hour * 3600 + dt.tm_min * 60 + dt.tm_sec;
675  }
676  }
677 
678  /* Now we have all the fields that we can get */
679  if (!q)
680  return AVERROR(EINVAL);
681 
682  /* parse the .m... part */
683  if (*q == '.') {
684  int n;
685  q++;
686  for (n = 100000; n >= 1; n /= 10, q++) {
687  if (!av_isdigit(*q))
688  break;
689  microseconds += n * (*q - '0');
690  }
691  while (av_isdigit(*q))
692  q++;
693  }
694 
695  if (duration) {
696  if (q[0] == 'm' && q[1] == 's') {
697  suffix = 1000;
698  microseconds /= 1000;
699  q += 2;
700  } else if (q[0] == 'u' && q[1] == 's') {
701  suffix = 1;
702  microseconds = 0;
703  q += 2;
704  } else if (*q == 's')
705  q++;
706  } else {
707  int is_utc = *q == 'Z' || *q == 'z';
708  int tzoffset = 0;
709  q += is_utc;
710  if (!today && !is_utc && (*q == '+' || *q == '-')) {
711  struct tm tz = { 0 };
712  int sign = (*q == '+' ? -1 : 1);
713  q++;
714  p = q;
715  for (i = 0; i < FF_ARRAY_ELEMS(tz_fmt); i++) {
716  q = av_small_strptime(p, tz_fmt[i], &tz);
717  if (q)
718  break;
719  }
720  if (!q)
721  return AVERROR(EINVAL);
722  tzoffset = sign * (tz.tm_hour * 60 + tz.tm_min) * 60;
723  is_utc = 1;
724  }
725  if (today) { /* fill in today's date */
726  struct tm dt2 = is_utc ? *gmtime_r(&now, &tmbuf) : *localtime_r(&now, &tmbuf);
727  dt2.tm_hour = dt.tm_hour;
728  dt2.tm_min = dt.tm_min;
729  dt2.tm_sec = dt.tm_sec;
730  dt = dt2;
731  }
732  dt.tm_isdst = is_utc ? 0 : -1;
733  t = is_utc ? av_timegm(&dt) : mktime(&dt);
734  t += tzoffset;
735  }
736 
737  /* Check that we are at the end of the string */
738  if (*q)
739  return AVERROR(EINVAL);
740 
741  if (INT64_MAX / suffix < t || t < INT64_MIN / suffix)
742  return AVERROR(ERANGE);
743  t *= suffix;
744  if (INT64_MAX - microseconds < t)
745  return AVERROR(ERANGE);
746  t += microseconds;
747  if (t == INT64_MIN && negative)
748  return AVERROR(ERANGE);
749  *timeval = negative ? -t : t;
750  return 0;
751 }
752 
753 int av_find_info_tag(char *arg, int arg_size, const char *tag1, const char *info)
754 {
755  const char *p;
756  char tag[128], *q;
757 
758  p = info;
759  if (*p == '?')
760  p++;
761  for(;;) {
762  q = tag;
763  while (*p != '\0' && *p != '=' && *p != '&') {
764  if ((q - tag) < sizeof(tag) - 1)
765  *q++ = *p;
766  p++;
767  }
768  *q = '\0';
769  q = arg;
770  if (*p == '=') {
771  p++;
772  while (*p != '&' && *p != '\0') {
773  if ((q - arg) < arg_size - 1) {
774  if (*p == '+')
775  *q++ = ' ';
776  else
777  *q++ = *p;
778  }
779  p++;
780  }
781  }
782  *q = '\0';
783  if (!strcmp(tag, tag1))
784  return 1;
785  if (*p != '&')
786  break;
787  p++;
788  }
789  return 0;
790 }
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:349
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
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:753
color
Definition: vf_paletteuse.c:511
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:356
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:452
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:78
av_timegm
time_t av_timegm(struct tm *tm)
Convert the decomposed UTC time in tm to a time_t value.
Definition: parseutils.c:570
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:180
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
duration
int64_t duration
Definition: movenc.c:64
color_table
static const ColorEntry color_table[]
Definition: parseutils.c:206
width
#define width
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:42
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:589
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:804
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
height
#define height
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:40
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:255
ALPHA_SEP
#define ALPHA_SEP
Definition: parseutils.c:354
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:476
len
int len
Definition: vorbis_enc_data.h:426
tag
uint32_t tag
Definition: movenc.c:1786
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:491
suffix
const char * suffix
Definition: checkasm.c:252
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:436
alpha
static const int16_t alpha[]
Definition: ilbcdata.h:55
d
d
Definition: ffmpeg_filter.c:425
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
ColorEntry::name
const char * name
a string representing the name of the color
Definition: xpmdec.c:41