parseutils.c
Go to the documentation of this file.
1 /*
2  * This file is part of Libav.
3  *
4  * Libav 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  * Libav 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 Libav; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
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 "parseutils.h"
33 
34 typedef struct {
35  const char *abbr;
36  int width, height;
38 
39 typedef struct {
40  const char *abbr;
43 
44 static const VideoSizeAbbr video_size_abbrs[] = {
45  { "ntsc", 720, 480 },
46  { "pal", 720, 576 },
47  { "qntsc", 352, 240 }, /* VCD compliant NTSC */
48  { "qpal", 352, 288 }, /* VCD compliant PAL */
49  { "sntsc", 640, 480 }, /* square pixel NTSC */
50  { "spal", 768, 576 }, /* square pixel PAL */
51  { "film", 352, 240 },
52  { "ntsc-film", 352, 240 },
53  { "sqcif", 128, 96 },
54  { "qcif", 176, 144 },
55  { "cif", 352, 288 },
56  { "4cif", 704, 576 },
57  { "16cif", 1408,1152 },
58  { "qqvga", 160, 120 },
59  { "qvga", 320, 240 },
60  { "vga", 640, 480 },
61  { "svga", 800, 600 },
62  { "xga", 1024, 768 },
63  { "uxga", 1600,1200 },
64  { "qxga", 2048,1536 },
65  { "sxga", 1280,1024 },
66  { "qsxga", 2560,2048 },
67  { "hsxga", 5120,4096 },
68  { "wvga", 852, 480 },
69  { "wxga", 1366, 768 },
70  { "wsxga", 1600,1024 },
71  { "wuxga", 1920,1200 },
72  { "woxga", 2560,1600 },
73  { "wqsxga", 3200,2048 },
74  { "wquxga", 3840,2400 },
75  { "whsxga", 6400,4096 },
76  { "whuxga", 7680,4800 },
77  { "cga", 320, 200 },
78  { "ega", 640, 350 },
79  { "hd480", 852, 480 },
80  { "hd720", 1280, 720 },
81  { "hd1080", 1920,1080 },
82 };
83 
85  { "ntsc", { 30000, 1001 } },
86  { "pal", { 25, 1 } },
87  { "qntsc", { 30000, 1001 } }, /* VCD compliant NTSC */
88  { "qpal", { 25, 1 } }, /* VCD compliant PAL */
89  { "sntsc", { 30000, 1001 } }, /* square pixel NTSC */
90  { "spal", { 25, 1 } }, /* square pixel PAL */
91  { "film", { 24, 1 } },
92  { "ntsc-film", { 24000, 1001 } },
93 };
94 
95 int av_parse_video_size(int *width_ptr, int *height_ptr, const char *str)
96 {
97  int i;
98  int n = FF_ARRAY_ELEMS(video_size_abbrs);
99  char *p;
100  int width = 0, height = 0;
101 
102  for (i = 0; i < n; i++) {
103  if (!strcmp(video_size_abbrs[i].abbr, str)) {
104  width = video_size_abbrs[i].width;
105  height = video_size_abbrs[i].height;
106  break;
107  }
108  }
109  if (i == n) {
110  width = strtol(str, &p, 10);
111  if (*p)
112  p++;
113  height = strtol(p, &p, 10);
114  }
115  if (width <= 0 || height <= 0)
116  return AVERROR(EINVAL);
117  *width_ptr = width;
118  *height_ptr = height;
119  return 0;
120 }
121 
122 int av_parse_video_rate(AVRational *rate, const char *arg)
123 {
124  int i, ret;
125  int n = FF_ARRAY_ELEMS(video_rate_abbrs);
126  double res;
127 
128  /* First, we check our abbreviation table */
129  for (i = 0; i < n; ++i)
130  if (!strcmp(video_rate_abbrs[i].abbr, arg)) {
131  *rate = video_rate_abbrs[i].rate;
132  return 0;
133  }
134 
135  /* Then, we try to parse it as fraction */
136  if ((ret = av_expr_parse_and_eval(&res, arg, NULL, NULL, NULL, NULL, NULL, NULL,
137  NULL, 0, NULL)) < 0)
138  return ret;
139  *rate = av_d2q(res, 1001000);
140  if (rate->num <= 0 || rate->den <= 0)
141  return AVERROR(EINVAL);
142  return 0;
143 }
144 
145 typedef struct {
146  const char *name;
147  uint8_t rgb_color[3];
148 } ColorEntry;
149 
151  { "AliceBlue", { 0xF0, 0xF8, 0xFF } },
152  { "AntiqueWhite", { 0xFA, 0xEB, 0xD7 } },
153  { "Aqua", { 0x00, 0xFF, 0xFF } },
154  { "Aquamarine", { 0x7F, 0xFF, 0xD4 } },
155  { "Azure", { 0xF0, 0xFF, 0xFF } },
156  { "Beige", { 0xF5, 0xF5, 0xDC } },
157  { "Bisque", { 0xFF, 0xE4, 0xC4 } },
158  { "Black", { 0x00, 0x00, 0x00 } },
159  { "BlanchedAlmond", { 0xFF, 0xEB, 0xCD } },
160  { "Blue", { 0x00, 0x00, 0xFF } },
161  { "BlueViolet", { 0x8A, 0x2B, 0xE2 } },
162  { "Brown", { 0xA5, 0x2A, 0x2A } },
163  { "BurlyWood", { 0xDE, 0xB8, 0x87 } },
164  { "CadetBlue", { 0x5F, 0x9E, 0xA0 } },
165  { "Chartreuse", { 0x7F, 0xFF, 0x00 } },
166  { "Chocolate", { 0xD2, 0x69, 0x1E } },
167  { "Coral", { 0xFF, 0x7F, 0x50 } },
168  { "CornflowerBlue", { 0x64, 0x95, 0xED } },
169  { "Cornsilk", { 0xFF, 0xF8, 0xDC } },
170  { "Crimson", { 0xDC, 0x14, 0x3C } },
171  { "Cyan", { 0x00, 0xFF, 0xFF } },
172  { "DarkBlue", { 0x00, 0x00, 0x8B } },
173  { "DarkCyan", { 0x00, 0x8B, 0x8B } },
174  { "DarkGoldenRod", { 0xB8, 0x86, 0x0B } },
175  { "DarkGray", { 0xA9, 0xA9, 0xA9 } },
176  { "DarkGreen", { 0x00, 0x64, 0x00 } },
177  { "DarkKhaki", { 0xBD, 0xB7, 0x6B } },
178  { "DarkMagenta", { 0x8B, 0x00, 0x8B } },
179  { "DarkOliveGreen", { 0x55, 0x6B, 0x2F } },
180  { "Darkorange", { 0xFF, 0x8C, 0x00 } },
181  { "DarkOrchid", { 0x99, 0x32, 0xCC } },
182  { "DarkRed", { 0x8B, 0x00, 0x00 } },
183  { "DarkSalmon", { 0xE9, 0x96, 0x7A } },
184  { "DarkSeaGreen", { 0x8F, 0xBC, 0x8F } },
185  { "DarkSlateBlue", { 0x48, 0x3D, 0x8B } },
186  { "DarkSlateGray", { 0x2F, 0x4F, 0x4F } },
187  { "DarkTurquoise", { 0x00, 0xCE, 0xD1 } },
188  { "DarkViolet", { 0x94, 0x00, 0xD3 } },
189  { "DeepPink", { 0xFF, 0x14, 0x93 } },
190  { "DeepSkyBlue", { 0x00, 0xBF, 0xFF } },
191  { "DimGray", { 0x69, 0x69, 0x69 } },
192  { "DodgerBlue", { 0x1E, 0x90, 0xFF } },
193  { "FireBrick", { 0xB2, 0x22, 0x22 } },
194  { "FloralWhite", { 0xFF, 0xFA, 0xF0 } },
195  { "ForestGreen", { 0x22, 0x8B, 0x22 } },
196  { "Fuchsia", { 0xFF, 0x00, 0xFF } },
197  { "Gainsboro", { 0xDC, 0xDC, 0xDC } },
198  { "GhostWhite", { 0xF8, 0xF8, 0xFF } },
199  { "Gold", { 0xFF, 0xD7, 0x00 } },
200  { "GoldenRod", { 0xDA, 0xA5, 0x20 } },
201  { "Gray", { 0x80, 0x80, 0x80 } },
202  { "Green", { 0x00, 0x80, 0x00 } },
203  { "GreenYellow", { 0xAD, 0xFF, 0x2F } },
204  { "HoneyDew", { 0xF0, 0xFF, 0xF0 } },
205  { "HotPink", { 0xFF, 0x69, 0xB4 } },
206  { "IndianRed", { 0xCD, 0x5C, 0x5C } },
207  { "Indigo", { 0x4B, 0x00, 0x82 } },
208  { "Ivory", { 0xFF, 0xFF, 0xF0 } },
209  { "Khaki", { 0xF0, 0xE6, 0x8C } },
210  { "Lavender", { 0xE6, 0xE6, 0xFA } },
211  { "LavenderBlush", { 0xFF, 0xF0, 0xF5 } },
212  { "LawnGreen", { 0x7C, 0xFC, 0x00 } },
213  { "LemonChiffon", { 0xFF, 0xFA, 0xCD } },
214  { "LightBlue", { 0xAD, 0xD8, 0xE6 } },
215  { "LightCoral", { 0xF0, 0x80, 0x80 } },
216  { "LightCyan", { 0xE0, 0xFF, 0xFF } },
217  { "LightGoldenRodYellow", { 0xFA, 0xFA, 0xD2 } },
218  { "LightGrey", { 0xD3, 0xD3, 0xD3 } },
219  { "LightGreen", { 0x90, 0xEE, 0x90 } },
220  { "LightPink", { 0xFF, 0xB6, 0xC1 } },
221  { "LightSalmon", { 0xFF, 0xA0, 0x7A } },
222  { "LightSeaGreen", { 0x20, 0xB2, 0xAA } },
223  { "LightSkyBlue", { 0x87, 0xCE, 0xFA } },
224  { "LightSlateGray", { 0x77, 0x88, 0x99 } },
225  { "LightSteelBlue", { 0xB0, 0xC4, 0xDE } },
226  { "LightYellow", { 0xFF, 0xFF, 0xE0 } },
227  { "Lime", { 0x00, 0xFF, 0x00 } },
228  { "LimeGreen", { 0x32, 0xCD, 0x32 } },
229  { "Linen", { 0xFA, 0xF0, 0xE6 } },
230  { "Magenta", { 0xFF, 0x00, 0xFF } },
231  { "Maroon", { 0x80, 0x00, 0x00 } },
232  { "MediumAquaMarine", { 0x66, 0xCD, 0xAA } },
233  { "MediumBlue", { 0x00, 0x00, 0xCD } },
234  { "MediumOrchid", { 0xBA, 0x55, 0xD3 } },
235  { "MediumPurple", { 0x93, 0x70, 0xD8 } },
236  { "MediumSeaGreen", { 0x3C, 0xB3, 0x71 } },
237  { "MediumSlateBlue", { 0x7B, 0x68, 0xEE } },
238  { "MediumSpringGreen", { 0x00, 0xFA, 0x9A } },
239  { "MediumTurquoise", { 0x48, 0xD1, 0xCC } },
240  { "MediumVioletRed", { 0xC7, 0x15, 0x85 } },
241  { "MidnightBlue", { 0x19, 0x19, 0x70 } },
242  { "MintCream", { 0xF5, 0xFF, 0xFA } },
243  { "MistyRose", { 0xFF, 0xE4, 0xE1 } },
244  { "Moccasin", { 0xFF, 0xE4, 0xB5 } },
245  { "NavajoWhite", { 0xFF, 0xDE, 0xAD } },
246  { "Navy", { 0x00, 0x00, 0x80 } },
247  { "OldLace", { 0xFD, 0xF5, 0xE6 } },
248  { "Olive", { 0x80, 0x80, 0x00 } },
249  { "OliveDrab", { 0x6B, 0x8E, 0x23 } },
250  { "Orange", { 0xFF, 0xA5, 0x00 } },
251  { "OrangeRed", { 0xFF, 0x45, 0x00 } },
252  { "Orchid", { 0xDA, 0x70, 0xD6 } },
253  { "PaleGoldenRod", { 0xEE, 0xE8, 0xAA } },
254  { "PaleGreen", { 0x98, 0xFB, 0x98 } },
255  { "PaleTurquoise", { 0xAF, 0xEE, 0xEE } },
256  { "PaleVioletRed", { 0xD8, 0x70, 0x93 } },
257  { "PapayaWhip", { 0xFF, 0xEF, 0xD5 } },
258  { "PeachPuff", { 0xFF, 0xDA, 0xB9 } },
259  { "Peru", { 0xCD, 0x85, 0x3F } },
260  { "Pink", { 0xFF, 0xC0, 0xCB } },
261  { "Plum", { 0xDD, 0xA0, 0xDD } },
262  { "PowderBlue", { 0xB0, 0xE0, 0xE6 } },
263  { "Purple", { 0x80, 0x00, 0x80 } },
264  { "Red", { 0xFF, 0x00, 0x00 } },
265  { "RosyBrown", { 0xBC, 0x8F, 0x8F } },
266  { "RoyalBlue", { 0x41, 0x69, 0xE1 } },
267  { "SaddleBrown", { 0x8B, 0x45, 0x13 } },
268  { "Salmon", { 0xFA, 0x80, 0x72 } },
269  { "SandyBrown", { 0xF4, 0xA4, 0x60 } },
270  { "SeaGreen", { 0x2E, 0x8B, 0x57 } },
271  { "SeaShell", { 0xFF, 0xF5, 0xEE } },
272  { "Sienna", { 0xA0, 0x52, 0x2D } },
273  { "Silver", { 0xC0, 0xC0, 0xC0 } },
274  { "SkyBlue", { 0x87, 0xCE, 0xEB } },
275  { "SlateBlue", { 0x6A, 0x5A, 0xCD } },
276  { "SlateGray", { 0x70, 0x80, 0x90 } },
277  { "Snow", { 0xFF, 0xFA, 0xFA } },
278  { "SpringGreen", { 0x00, 0xFF, 0x7F } },
279  { "SteelBlue", { 0x46, 0x82, 0xB4 } },
280  { "Tan", { 0xD2, 0xB4, 0x8C } },
281  { "Teal", { 0x00, 0x80, 0x80 } },
282  { "Thistle", { 0xD8, 0xBF, 0xD8 } },
283  { "Tomato", { 0xFF, 0x63, 0x47 } },
284  { "Turquoise", { 0x40, 0xE0, 0xD0 } },
285  { "Violet", { 0xEE, 0x82, 0xEE } },
286  { "Wheat", { 0xF5, 0xDE, 0xB3 } },
287  { "White", { 0xFF, 0xFF, 0xFF } },
288  { "WhiteSmoke", { 0xF5, 0xF5, 0xF5 } },
289  { "Yellow", { 0xFF, 0xFF, 0x00 } },
290  { "YellowGreen", { 0x9A, 0xCD, 0x32 } },
291 };
292 
293 static int color_table_compare(const void *lhs, const void *rhs)
294 {
295  return av_strcasecmp(lhs, ((const ColorEntry *)rhs)->name);
296 }
297 
298 #define ALPHA_SEP '@'
299 
300 int av_parse_color(uint8_t *rgba_color, const char *color_string, int slen,
301  void *log_ctx)
302 {
303  char *tail, color_string2[128];
304  const ColorEntry *entry;
305  int len, hex_offset = 0;
306 
307  if (color_string[0] == '#') {
308  hex_offset = 1;
309  } else if (!strncmp(color_string, "0x", 2))
310  hex_offset = 2;
311 
312  if (slen < 0)
313  slen = strlen(color_string);
314  av_strlcpy(color_string2, color_string + hex_offset,
315  FFMIN(slen-hex_offset+1, sizeof(color_string2)));
316  if ((tail = strchr(color_string2, ALPHA_SEP)))
317  *tail++ = 0;
318  len = strlen(color_string2);
319  rgba_color[3] = 255;
320 
321  if (!av_strcasecmp(color_string2, "random") || !av_strcasecmp(color_string2, "bikeshed")) {
322  int rgba = av_get_random_seed();
323  rgba_color[0] = rgba >> 24;
324  rgba_color[1] = rgba >> 16;
325  rgba_color[2] = rgba >> 8;
326  rgba_color[3] = rgba;
327  } else if (hex_offset ||
328  strspn(color_string2, "0123456789ABCDEFabcdef") == len) {
329  char *tail;
330  unsigned int rgba = strtoul(color_string2, &tail, 16);
331 
332  if (*tail || (len != 6 && len != 8)) {
333  av_log(log_ctx, AV_LOG_ERROR, "Invalid 0xRRGGBB[AA] color string: '%s'\n", color_string2);
334  return AVERROR(EINVAL);
335  }
336  if (len == 8) {
337  rgba_color[3] = rgba;
338  rgba >>= 8;
339  }
340  rgba_color[0] = rgba >> 16;
341  rgba_color[1] = rgba >> 8;
342  rgba_color[2] = rgba;
343  } else {
344  entry = bsearch(color_string2,
345  color_table,
346  FF_ARRAY_ELEMS(color_table),
347  sizeof(ColorEntry),
349  if (!entry) {
350  av_log(log_ctx, AV_LOG_ERROR, "Cannot find color '%s'\n", color_string2);
351  return AVERROR(EINVAL);
352  }
353  memcpy(rgba_color, entry->rgb_color, 3);
354  }
355 
356  if (tail) {
357  double alpha;
358  const char *alpha_string = tail;
359  if (!strncmp(alpha_string, "0x", 2)) {
360  alpha = strtoul(alpha_string, &tail, 16);
361  } else {
362  alpha = 255 * strtod(alpha_string, &tail);
363  }
364 
365  if (tail == alpha_string || *tail || alpha > 255 || alpha < 0) {
366  av_log(log_ctx, AV_LOG_ERROR, "Invalid alpha value specifier '%s' in '%s'\n",
367  alpha_string, color_string);
368  return AVERROR(EINVAL);
369  }
370  rgba_color[3] = alpha;
371  }
372 
373  return 0;
374 }
375 
376 /* get a positive number between n_min and n_max, for a maximum length
377  of len_max. Return -1 if error. */
378 static int date_get_num(const char **pp,
379  int n_min, int n_max, int len_max)
380 {
381  int i, val, c;
382  const char *p;
383 
384  p = *pp;
385  val = 0;
386  for(i = 0; i < len_max; i++) {
387  c = *p;
388  if (!isdigit(c))
389  break;
390  val = (val * 10) + c - '0';
391  p++;
392  }
393  /* no number read ? */
394  if (p == *pp)
395  return -1;
396  if (val < n_min || val > n_max)
397  return -1;
398  *pp = p;
399  return val;
400 }
401 
402 static const char *small_strptime(const char *p, const char *fmt, struct tm *dt)
403 {
404  int c, val;
405 
406  for(;;) {
407  c = *fmt++;
408  if (c == '\0') {
409  return p;
410  } else if (c == '%') {
411  c = *fmt++;
412  switch(c) {
413  case 'H':
414  val = date_get_num(&p, 0, 23, 2);
415  if (val == -1)
416  return NULL;
417  dt->tm_hour = val;
418  break;
419  case 'M':
420  val = date_get_num(&p, 0, 59, 2);
421  if (val == -1)
422  return NULL;
423  dt->tm_min = val;
424  break;
425  case 'S':
426  val = date_get_num(&p, 0, 59, 2);
427  if (val == -1)
428  return NULL;
429  dt->tm_sec = val;
430  break;
431  case 'Y':
432  val = date_get_num(&p, 0, 9999, 4);
433  if (val == -1)
434  return NULL;
435  dt->tm_year = val - 1900;
436  break;
437  case 'm':
438  val = date_get_num(&p, 1, 12, 2);
439  if (val == -1)
440  return NULL;
441  dt->tm_mon = val - 1;
442  break;
443  case 'd':
444  val = date_get_num(&p, 1, 31, 2);
445  if (val == -1)
446  return NULL;
447  dt->tm_mday = val;
448  break;
449  case '%':
450  goto match;
451  default:
452  return NULL;
453  }
454  } else {
455  match:
456  if (c != *p)
457  return NULL;
458  p++;
459  }
460  }
461 }
462 
463 time_t av_timegm(struct tm *tm)
464 {
465  time_t t;
466 
467  int y = tm->tm_year + 1900, m = tm->tm_mon + 1, d = tm->tm_mday;
468 
469  if (m < 3) {
470  m += 12;
471  y--;
472  }
473 
474  t = 86400 *
475  (d + (153 * m - 457) / 5 + 365 * y + y / 4 - y / 100 + y / 400 - 719469);
476 
477  t += 3600 * tm->tm_hour + 60 * tm->tm_min + tm->tm_sec;
478 
479  return t;
480 }
481 
482 int av_parse_time(int64_t *timeval, const char *timestr, int duration)
483 {
484  const char *p;
485  int64_t t;
486  struct tm dt = { 0 };
487  int i;
488  static const char * const date_fmt[] = {
489  "%Y-%m-%d",
490  "%Y%m%d",
491  };
492  static const char * const time_fmt[] = {
493  "%H:%M:%S",
494  "%H%M%S",
495  };
496  const char *q;
497  int is_utc, len;
498  char lastch;
499  int negative = 0;
500 
501  time_t now = time(0);
502 
503  len = strlen(timestr);
504  if (len > 0)
505  lastch = timestr[len - 1];
506  else
507  lastch = '\0';
508  is_utc = (lastch == 'z' || lastch == 'Z');
509 
510  p = timestr;
511  q = NULL;
512  if (!duration) {
513  if (!av_strncasecmp(timestr, "now", len)) {
514  *timeval = (int64_t) now * 1000000;
515  return 0;
516  }
517 
518  /* parse the year-month-day part */
519  for (i = 0; i < FF_ARRAY_ELEMS(date_fmt); i++) {
520  q = small_strptime(p, date_fmt[i], &dt);
521  if (q) {
522  break;
523  }
524  }
525 
526  /* if the year-month-day part is missing, then take the
527  * current year-month-day time */
528  if (!q) {
529  if (is_utc) {
530  dt = *gmtime(&now);
531  } else {
532  dt = *localtime(&now);
533  }
534  dt.tm_hour = dt.tm_min = dt.tm_sec = 0;
535  } else {
536  p = q;
537  }
538 
539  if (*p == 'T' || *p == 't' || *p == ' ')
540  p++;
541 
542  /* parse the hour-minute-second part */
543  for (i = 0; i < FF_ARRAY_ELEMS(time_fmt); i++) {
544  q = small_strptime(p, time_fmt[i], &dt);
545  if (q) {
546  break;
547  }
548  }
549  } else {
550  /* parse timestr as a duration */
551  if (p[0] == '-') {
552  negative = 1;
553  ++p;
554  }
555  /* parse timestr as HH:MM:SS */
556  q = small_strptime(p, time_fmt[0], &dt);
557  if (!q) {
558  /* parse timestr as S+ */
559  dt.tm_sec = strtol(p, (char **)&q, 10);
560  if (q == p) {
561  /* the parsing didn't succeed */
562  *timeval = INT64_MIN;
563  return AVERROR(EINVAL);
564  }
565  dt.tm_min = 0;
566  dt.tm_hour = 0;
567  }
568  }
569 
570  /* Now we have all the fields that we can get */
571  if (!q) {
572  *timeval = INT64_MIN;
573  return AVERROR(EINVAL);
574  }
575 
576  if (duration) {
577  t = dt.tm_hour * 3600 + dt.tm_min * 60 + dt.tm_sec;
578  } else {
579  dt.tm_isdst = -1; /* unknown */
580  if (is_utc) {
581  t = av_timegm(&dt);
582  } else {
583  t = mktime(&dt);
584  }
585  }
586 
587  t *= 1000000;
588 
589  /* parse the .m... part */
590  if (*q == '.') {
591  int val, n;
592  q++;
593  for (val = 0, n = 100000; n >= 1; n /= 10, q++) {
594  if (!isdigit(*q))
595  break;
596  val += n * (*q - '0');
597  }
598  t += val;
599  }
600  *timeval = negative ? -t : t;
601  return 0;
602 }
603 
604 int av_find_info_tag(char *arg, int arg_size, const char *tag1, const char *info)
605 {
606  const char *p;
607  char tag[128], *q;
608 
609  p = info;
610  if (*p == '?')
611  p++;
612  for(;;) {
613  q = tag;
614  while (*p != '\0' && *p != '=' && *p != '&') {
615  if ((q - tag) < sizeof(tag) - 1)
616  *q++ = *p;
617  p++;
618  }
619  *q = '\0';
620  q = arg;
621  if (*p == '=') {
622  p++;
623  while (*p != '&' && *p != '\0') {
624  if ((q - arg) < arg_size - 1) {
625  if (*p == '+')
626  *q++ = ' ';
627  else
628  *q++ = *p;
629  }
630  p++;
631  }
632  }
633  *q = '\0';
634  if (!strcmp(tag, tag1))
635  return 1;
636  if (*p != '&')
637  break;
638  p++;
639  }
640  return 0;
641 }
642 
643 #ifdef TEST
644 
645 int main(void)
646 {
647  printf("Testing av_parse_video_rate()\n");
648  {
649  int i;
650  static const char *const rates[] = {
651  "-inf",
652  "inf",
653  "nan",
654  "123/0",
655  "-123 / 0",
656  "",
657  "/",
658  " 123 / 321",
659  "foo/foo",
660  "foo/1",
661  "1/foo",
662  "0/0",
663  "/0",
664  "1/",
665  "1",
666  "0",
667  "-123/123",
668  "-foo",
669  "123.23",
670  ".23",
671  "-.23",
672  "-0.234",
673  "-0.0000001",
674  " 21332.2324 ",
675  " -21332.2324 ",
676  };
677 
678  for (i = 0; i < FF_ARRAY_ELEMS(rates); i++) {
679  int ret;
680  AVRational q = { 0, 0 };
681  ret = av_parse_video_rate(&q, rates[i]);
682  printf("'%s' -> %d/%d %s\n",
683  rates[i], q.num, q.den, ret ? "ERROR" : "OK");
684  }
685  }
686 
687  printf("\nTesting av_parse_color()\n");
688  {
689  int i;
690  uint8_t rgba[4];
691  static const char *const color_names[] = {
692  "foo",
693  "red",
694  "Red ",
695  "RED",
696  "Violet",
697  "Yellow",
698  "Red",
699  "0x000000",
700  "0x0000000",
701  "0xff000000",
702  "0x3e34ff",
703  "0x3e34ffaa",
704  "0xffXXee",
705  "0xfoobar",
706  "0xffffeeeeeeee",
707  "#ff0000",
708  "#ffXX00",
709  "ff0000",
710  "ffXX00",
711  "red@foo",
712  "random@10",
713  "0xff0000@1.0",
714  "red@",
715  "red@0xfff",
716  "red@0xf",
717  "red@2",
718  "red@0.1",
719  "red@-1",
720  "red@0.5",
721  "red@1.0",
722  "red@256",
723  "red@10foo",
724  "red@-1.0",
725  "red@-0.0",
726  };
727 
729 
730  for (i = 0; i < FF_ARRAY_ELEMS(color_names); i++) {
731  if (av_parse_color(rgba, color_names[i], -1, NULL) >= 0)
732  printf("%s -> R(%d) G(%d) B(%d) A(%d)\n",
733  color_names[i], rgba[0], rgba[1], rgba[2], rgba[3]);
734  }
735  }
736 
737  return 0;
738 }
739 
740 #endif /* TEST */
time_t av_timegm(struct tm *tm)
Convert the decomposed UTC time in tm to a time_t value.
Definition: parseutils.c:463
const char * name
a string representing the name of the color
Definition: parseutils.c:146
int av_parse_video_rate(AVRational *rate, const char *arg)
Parse str and store the detected values in *rate.
Definition: parseutils.c:122
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:95
const char * abbr
Definition: parseutils.c:35
static ColorEntry color_table[]
Definition: parseutils.c:150
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:482
const char * abbr
Definition: parseutils.c:40
#define ALPHA_SEP
Definition: parseutils.c:298
int num
numerator
Definition: rational.h:44
int av_strncasecmp(const char *a, const char *b, size_t n)
Locale-independent case-insensitive compare.
Definition: avstring.c:150
external API header
static int64_t duration
Definition: avplay.c:249
uint8_t
AVRational rate
Definition: parseutils.c:41
const char * name
double strtod(const char *, char **)
uint32_t tag
Definition: movenc.c:802
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:604
uint8_t rgb_color[3]
RGB values for the color.
Definition: parseutils.c:147
static float t
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:300
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:548
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:146
int main(int argc, char **argv)
Definition: avconv.c:2372
void av_log_set_level(int level)
Definition: log.c:168
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:67
AVRational av_d2q(double d, int max)
Convert a double precision floating point number to a rational.
Definition: rational.c:106
int av_strcasecmp(const char *a, const char *b)
Definition: avstring.c:140
static int color_table_compare(const void *lhs, const void *rhs)
Definition: parseutils.c:293
NULL
Definition: eval.c:52
static int width
Definition: utils.c:156
static const VideoRateAbbr video_rate_abbrs[]
Definition: parseutils.c:84
static int date_get_num(const char **pp, int n_min, int n_max, int len_max)
Definition: parseutils.c:378
rational number numerator/denominator
Definition: rational.h:43
misc parsing utilities
static const char * small_strptime(const char *p, const char *fmt, struct tm *dt)
Definition: parseutils.c:402
int height
Definition: gxfenc.c:72
static const VideoSizeAbbr video_size_abbrs[]
Definition: parseutils.c:44
common internal and external API header
int den
denominator
Definition: rational.h:45
int len
uint32_t av_get_random_seed(void)
Get random data.
Definition: random_seed.c:85
simple arithmetic expression evaluator