FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavutil/parseutils.c
Date: 2024-12-12 01:08:13
Exec Total Coverage
Lines: 305 329 92.7%
Functions: 12 12 100.0%
Branches: 222 264 84.1%

Line Branch Exec Source
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 8244 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
2/2
✓ Branch 0 taken 8242 times.
✓ Branch 1 taken 2 times.
8244 if (sscanf(str, "%d:%d%c", &q->num, &q->den, &c) != 2) {
52 double d;
53 8242 ret = av_expr_parse_and_eval(&d, str, NULL, NULL,
54 NULL, NULL, NULL, NULL,
55 NULL, log_offset, log_ctx);
56
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 8231 times.
8242 if (ret < 0)
57 11 return ret;
58 8231 *q = av_d2q(d, max);
59 } else {
60 2 av_reduce(&q->num, &q->den, q->num, q->den, max);
61 }
62
63 8233 return 0;
64 }
65
66 typedef struct VideoSizeAbbr {
67 const char *abbr;
68 int width, height;
69 } VideoSizeAbbr;
70
71 typedef struct VideoRateAbbr {
72 const char *abbr;
73 AVRational rate;
74 } VideoRateAbbr;
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
134 static const VideoRateAbbr video_rate_abbrs[]= {
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 6619 int av_parse_video_size(int *width_ptr, int *height_ptr, const char *str)
151 {
152 int i;
153 6619 int n = FF_ARRAY_ELEMS(video_size_abbrs);
154 const char *p;
155 6619 int width = 0, height = 0;
156
157
2/2
✓ Branch 0 taken 362070 times.
✓ Branch 1 taken 6544 times.
368614 for (i = 0; i < n; i++) {
158
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 361995 times.
362070 if (!strcmp(video_size_abbrs[i].abbr, str)) {
159 75 width = video_size_abbrs[i].width;
160 75 height = video_size_abbrs[i].height;
161 75 break;
162 }
163 }
164
2/2
✓ Branch 0 taken 6544 times.
✓ Branch 1 taken 75 times.
6619 if (i == n) {
165 6544 width = strtol(str, (void*)&p, 10);
166
1/2
✓ Branch 0 taken 6544 times.
✗ Branch 1 not taken.
6544 if (*p)
167 6544 p++;
168 6544 height = strtol(p, (void*)&p, 10);
169
170 /* trailing extraneous data detected, like in 123x345foobar */
171
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6543 times.
6544 if (*p)
172 1 return AVERROR(EINVAL);
173 }
174
2/4
✓ Branch 0 taken 6618 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6618 times.
6618 if (width <= 0 || height <= 0)
175 return AVERROR(EINVAL);
176 6618 *width_ptr = width;
177 6618 *height_ptr = height;
178 6618 return 0;
179 }
180
181 8237 int av_parse_video_rate(AVRational *rate, const char *arg)
182 {
183 int i, ret;
184 8237 int n = FF_ARRAY_ELEMS(video_rate_abbrs);
185
186 /* First, we check our abbreviation table */
187
2/2
✓ Branch 0 taken 65890 times.
✓ Branch 1 taken 8236 times.
74126 for (i = 0; i < n; ++i)
188
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 65889 times.
65890 if (!strcmp(video_rate_abbrs[i].abbr, arg)) {
189 1 *rate = video_rate_abbrs[i].rate;
190 1 return 0;
191 }
192
193 /* Then, we try to parse it as fraction */
194
2/2
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 8225 times.
8236 if ((ret = av_parse_ratio_quiet(rate, arg, 1001000)) < 0)
195 11 return ret;
196
4/4
✓ Branch 0 taken 8223 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 8219 times.
8225 if (!rate->num || !rate->den)
197
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if ((ret = av_parse_ratio_quiet(rate, arg, INT_MAX)) < 0)
198 return ret;
199
4/4
✓ Branch 0 taken 8217 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 8215 times.
8225 if (rate->num <= 0 || rate->den <= 0)
200 10 return AVERROR(EINVAL);
201 8215 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 3339 static int color_table_compare(const void *lhs, const void *rhs)
353 {
354 3339 return av_strcasecmp(lhs, ((const ColorEntry *)rhs)->name);
355 }
356
357 #define ALPHA_SEP '@'
358
359 543 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 543 int len, hex_offset = 0;
365
366
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 505 times.
543 if (color_string[0] == '#') {
367 38 hex_offset = 1;
368
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 492 times.
505 } else if (!strncmp(color_string, "0x", 2))
369 13 hex_offset = 2;
370
371
2/2
✓ Branch 0 taken 462 times.
✓ Branch 1 taken 81 times.
543 if (slen < 0)
372 462 slen = strlen(color_string);
373 543 av_strlcpy(color_string2, color_string + hex_offset,
374
1/2
✓ Branch 0 taken 543 times.
✗ Branch 1 not taken.
543 FFMIN(slen-hex_offset+1, sizeof(color_string2)));
375
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 526 times.
543 if ((tail = strchr(color_string2, ALPHA_SEP)))
376 17 *tail++ = 0;
377 543 len = strlen(color_string2);
378 543 rgba_color[3] = 255;
379
380
4/4
✓ Branch 1 taken 541 times.
✓ Branch 2 taken 2 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 540 times.
543 if (!av_strcasecmp(color_string2, "random") || !av_strcasecmp(color_string2, "bikeshed")) {
381 3 int rgba = av_get_random_seed();
382 3 rgba_color[0] = rgba >> 24;
383 3 rgba_color[1] = rgba >> 16;
384 3 rgba_color[2] = rgba >> 8;
385 3 rgba_color[3] = rgba;
386
2/2
✓ Branch 0 taken 489 times.
✓ Branch 1 taken 51 times.
540 } else if (hex_offset ||
387
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 481 times.
489 strspn(color_string2, "0123456789ABCDEFabcdef") == len) {
388 char *tail;
389 59 unsigned int rgba = strtoul(color_string2, &tail, 16);
390
391
6/6
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 49 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 5 times.
59 if (*tail || (len != 6 && len != 8)) {
392 5 av_log(log_ctx, AV_LOG_ERROR, "Invalid 0xRRGGBB[AA] color string: '%s'\n", color_string2);
393 5 return AVERROR(EINVAL);
394 }
395
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 49 times.
54 if (len == 8) {
396 5 rgba_color[3] = rgba;
397 5 rgba >>= 8;
398 }
399 54 rgba_color[0] = rgba >> 16;
400 54 rgba_color[1] = rgba >> 8;
401 54 rgba_color[2] = rgba;
402 } else {
403 481 entry = bsearch(color_string2,
404 color_table,
405 FF_ARRAY_ELEMS(color_table),
406 sizeof(ColorEntry),
407 color_table_compare);
408
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 478 times.
481 if (!entry) {
409 3 av_log(log_ctx, AV_LOG_ERROR, "Cannot find color '%s'\n", color_string2);
410 3 return AVERROR(EINVAL);
411 }
412 478 memcpy(rgba_color, entry->rgb_color, 3);
413 }
414
415
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 518 times.
535 if (tail) {
416 double alpha;
417 17 const char *alpha_string = tail;
418
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 15 times.
17 if (!strncmp(alpha_string, "0x", 2)) {
419 2 alpha = strtoul(alpha_string, &tail, 16);
420 } else {
421 15 double norm_alpha = strtod(alpha_string, &tail);
422
4/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 9 times.
15 if (norm_alpha < 0.0 || norm_alpha > 1.0)
423 6 alpha = 256;
424 else
425 9 alpha = 255 * norm_alpha;
426 }
427
428
7/8
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 8 times.
17 if (tail == alpha_string || *tail || alpha > 255 || alpha < 0) {
429 9 av_log(log_ctx, AV_LOG_ERROR, "Invalid alpha value specifier '%s' in '%s'\n",
430 alpha_string, color_string);
431 9 return AVERROR(EINVAL);
432 }
433 8 rgba_color[3] = alpha;
434 }
435
436 526 return 0;
437 }
438
439 140 const char *av_get_known_color_name(int color_idx, const uint8_t **rgbp)
440 {
441 const ColorEntry *color;
442
443
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
140 if ((unsigned)color_idx >= FF_ARRAY_ELEMS(color_table))
444 return NULL;
445
446 140 color = &color_table[color_idx];
447
1/2
✓ Branch 0 taken 140 times.
✗ Branch 1 not taken.
140 if (rgbp)
448 140 *rgbp = color->rgb_color;
449
450 140 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 3163 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 3163 p = *pp;
462 3163 val = 0;
463
2/2
✓ Branch 0 taken 6589 times.
✓ Branch 1 taken 560 times.
7149 for(i = 0; i < len_max; i++) {
464 6589 c = *p;
465
2/2
✓ Branch 0 taken 2603 times.
✓ Branch 1 taken 3986 times.
6589 if (!av_isdigit(c))
466 2603 break;
467 3986 val = (val * 10) + c - '0';
468 3986 p++;
469 }
470 /* no number read ? */
471
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3159 times.
3163 if (p == *pp)
472 4 return -1;
473
3/4
✓ Branch 0 taken 3159 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3156 times.
3159 if (val < n_min || val > n_max)
474 3 return -1;
475 3156 *pp = p;
476 3156 return val;
477 }
478
479 7 static int date_get_month(const char **pp) {
480 7 int i = 0;
481
2/2
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 1 times.
48 for (; i < 12; i++) {
482
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 41 times.
47 if (!av_strncasecmp(*pp, months[i], 3)) {
483 6 const char *mo_full = months[i] + 3;
484 6 int len = strlen(mo_full);
485 6 *pp += 3;
486
4/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 2 times.
6 if (len > 0 && !av_strncasecmp(*pp, mo_full, len))
487 3 *pp += len;
488 6 return i;
489 }
490 }
491 1 return -1;
492 }
493
494 2850 char *av_small_strptime(const char *p, const char *fmt, struct tm *dt)
495 {
496 int c, val;
497
498
2/2
✓ Branch 0 taken 6274 times.
✓ Branch 1 taken 149 times.
6423 while((c = *fmt++)) {
499
2/2
✓ Branch 0 taken 3104 times.
✓ Branch 1 taken 3170 times.
6274 if (c != '%') {
500
2/2
✓ Branch 0 taken 103 times.
✓ Branch 1 taken 3001 times.
3104 if (av_isspace(c))
501
3/4
✓ Branch 0 taken 203 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 100 times.
✓ Branch 3 taken 103 times.
203 for (; *p && av_isspace(*p); p++);
502
2/2
✓ Branch 0 taken 2693 times.
✓ Branch 1 taken 308 times.
3001 else if (*p != c)
503 2693 return NULL;
504 308 else p++;
505 411 continue;
506 }
507
508 3170 c = *fmt++;
509
7/10
✓ Branch 0 taken 1433 times.
✓ Branch 1 taken 1546 times.
✓ Branch 2 taken 139 times.
✓ Branch 3 taken 19 times.
✓ Branch 4 taken 11 times.
✓ Branch 5 taken 15 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 7 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
3170 switch(c) {
510 1433 case 'H':
511 case 'J':
512
4/4
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 1414 times.
✓ Branch 2 taken 19 times.
✓ Branch 3 taken 1414 times.
1433 val = date_get_num(&p, 0, c == 'H' ? 23 : INT_MAX, c == 'H' ? 2 : 4);
513
514
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1432 times.
1433 if (val == -1)
515 1 return NULL;
516 1432 dt->tm_hour = val;
517 1432 break;
518 1546 case 'M':
519 1546 val = date_get_num(&p, 0, 59, 2);
520
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1541 times.
1546 if (val == -1)
521 5 return NULL;
522 1541 dt->tm_min = val;
523 1541 break;
524 139 case 'S':
525 139 val = date_get_num(&p, 0, 59, 2);
526
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 139 times.
139 if (val == -1)
527 return NULL;
528 139 dt->tm_sec = val;
529 139 break;
530 19 case 'Y':
531 19 val = date_get_num(&p, 0, 9999, 4);
532
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (val == -1)
533 return NULL;
534 19 dt->tm_year = val - 1900;
535 19 break;
536 11 case 'm':
537 11 val = date_get_num(&p, 1, 12, 2);
538
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10 times.
11 if (val == -1)
539 1 return NULL;
540 10 dt->tm_mon = val - 1;
541 10 break;
542 15 case 'd':
543 15 val = date_get_num(&p, 1, 31, 2);
544
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (val == -1)
545 return NULL;
546 15 dt->tm_mday = val;
547 15 break;
548 case 'T':
549 p = av_small_strptime(p, "%H:%M:%S", dt);
550 if (!p)
551 return NULL;
552 break;
553 7 case 'b':
554 case 'B':
555 case 'h':
556 7 val = date_get_month(&p);
557
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
7 if (val == -1)
558 1 return NULL;
559 6 dt->tm_mon = val;
560 6 break;
561 case '%':
562 if (*p++ != '%')
563 return NULL;
564 break;
565 default:
566 return NULL;
567 }
568 }
569
570 149 return (char*)p;
571 }
572
573 24 time_t av_timegm(struct tm *tm)
574 {
575 time_t t;
576
577 24 int y = tm->tm_year + 1900, m = tm->tm_mon + 1, d = tm->tm_mday;
578
579
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22 times.
24 if (m < 3) {
580 2 m += 12;
581 2 y--;
582 }
583
584 24 t = 86400LL *
585 24 (d + (153 * m - 457) / 5 + 365 * y + y / 4 - y / 100 + y / 400 - 719469);
586
587 24 t += 3600 * tm->tm_hour + 60 * tm->tm_min + tm->tm_sec;
588
589 24 return t;
590 }
591
592 1422 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 1422 struct tm dt = { 0 }, tmbuf;
598 1422 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 1422 p = timestr;
615 1422 q = NULL;
616 1422 *timeval = INT64_MIN;
617
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1414 times.
1422 if (!duration) {
618 8 now64 = av_gettime();
619 8 now = now64 / 1000000;
620
621
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 7 times.
8 if (!av_strcasecmp(timestr, "now")) {
622 1 *timeval = now64;
623 1 return 0;
624 }
625
626 /* parse the year-month-day part */
627
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
9 for (i = 0; i < FF_ARRAY_ELEMS(date_fmt); i++) {
628 8 q = av_small_strptime(p, date_fmt[i], &dt);
629
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 if (q)
630 6 break;
631 }
632
633 /* if the year-month-day part is missing, then take the
634 * current year-month-day time */
635
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
7 if (!q) {
636 1 today = 1;
637 1 q = p;
638 }
639 7 p = q;
640
641
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
7 if (*p == 'T' || *p == 't')
642 2 p++;
643 else
644
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 while (av_isspace(*p))
645 5 p++;
646
647 /* parse the hour-minute-second part */
648
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 for (i = 0; i < FF_ARRAY_ELEMS(time_fmt); i++) {
649 8 q = av_small_strptime(p, time_fmt[i], &dt);
650
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1 times.
8 if (q)
651 7 break;
652 }
653 } else {
654 /* parse timestr as a duration */
655
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1411 times.
1414 if (p[0] == '-') {
656 3 negative = 1;
657 3 ++p;
658 }
659 /* parse timestr as HH:MM:SS */
660 1414 q = av_small_strptime(p, "%J:%M:%S", &dt);
661
2/2
✓ Branch 0 taken 1405 times.
✓ Branch 1 taken 9 times.
1414 if (!q) {
662 /* parse timestr as MM:SS */
663 1405 q = av_small_strptime(p, "%M:%S", &dt);
664 1405 dt.tm_hour = 0;
665 }
666
2/2
✓ Branch 0 taken 1289 times.
✓ Branch 1 taken 125 times.
1414 if (!q) {
667 char *o;
668 /* parse timestr as S+ */
669 1289 errno = 0;
670 1289 t = strtoll(p, &o, 10);
671
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1288 times.
1289 if (o == p) /* the parsing didn't succeed */
672 2 return AVERROR(EINVAL);
673
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1287 times.
1288 if (errno == ERANGE)
674 1 return AVERROR(ERANGE);
675 1287 q = o;
676 } else {
677 125 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
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1419 times.
1419 if (!q)
683 return AVERROR(EINVAL);
684
685 /* parse the .m... part */
686
2/2
✓ Branch 0 taken 238 times.
✓ Branch 1 taken 1181 times.
1419 if (*q == '.') {
687 int n;
688 238 q++;
689
2/2
✓ Branch 0 taken 666 times.
✓ Branch 1 taken 6 times.
672 for (n = 100000; n >= 1; n /= 10, q++) {
690
2/2
✓ Branch 0 taken 232 times.
✓ Branch 1 taken 434 times.
666 if (!av_isdigit(*q))
691 232 break;
692 434 microseconds += n * (*q - '0');
693 }
694
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 238 times.
253 while (av_isdigit(*q))
695 15 q++;
696 }
697
698
2/2
✓ Branch 0 taken 1412 times.
✓ Branch 1 taken 7 times.
1419 if (duration) {
699
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1410 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
1412 if (q[0] == 'm' && q[1] == 's') {
700 2 suffix = 1000;
701 2 microseconds /= 1000;
702 2 q += 2;
703
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1409 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1410 } else if (q[0] == 'u' && q[1] == 's') {
704 1 suffix = 1;
705 1 microseconds = 0;
706 1 q += 2;
707
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1404 times.
1409 } else if (*q == 's')
708 5 q++;
709 } else {
710
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 5 times.
7 int is_utc = *q == 'Z' || *q == 'z';
711 7 int tzoffset = 0;
712 7 q += is_utc;
713
8/8
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 2 times.
7 if (!today && !is_utc && (*q == '+' || *q == '-')) {
714 2 struct tm tz = { 0 };
715
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 int sign = (*q == '+' ? -1 : 1);
716 2 q++;
717 2 p = q;
718
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 for (i = 0; i < FF_ARRAY_ELEMS(tz_fmt); i++) {
719 4 q = av_small_strptime(p, tz_fmt[i], &tz);
720
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (q)
721 2 break;
722 }
723
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!q)
724 return AVERROR(EINVAL);
725 2 tzoffset = sign * (tz.tm_hour * 60 + tz.tm_min) * 60;
726 2 is_utc = 1;
727 }
728
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
7 if (today) { /* fill in today's date */
729
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 struct tm dt2 = is_utc ? *gmtime_r(&now, &tmbuf) : *localtime_r(&now, &tmbuf);
730 1 dt2.tm_hour = dt.tm_hour;
731 1 dt2.tm_min = dt.tm_min;
732 1 dt2.tm_sec = dt.tm_sec;
733 1 dt = dt2;
734 }
735
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
7 dt.tm_isdst = is_utc ? 0 : -1;
736
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
7 t = is_utc ? av_timegm(&dt) : mktime(&dt);
737 7 t += tzoffset;
738 }
739
740 /* Check that we are at the end of the string */
741
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1419 times.
1419 if (*q)
742 return AVERROR(EINVAL);
743
744
2/4
✓ Branch 0 taken 1419 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1419 times.
1419 if (INT64_MAX / suffix < t || t < INT64_MIN / suffix)
745 return AVERROR(ERANGE);
746 1419 t *= suffix;
747
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1419 times.
1419 if (INT64_MAX - microseconds < t)
748 return AVERROR(ERANGE);
749 1419 t += microseconds;
750
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1419 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1419 if (t == INT64_MIN && negative)
751 return AVERROR(ERANGE);
752
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1416 times.
1419 *timeval = negative ? -t : t;
753 1419 return 0;
754 }
755
756 7 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 7 p = info;
762
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (*p == '?')
763 7 p++;
764 for(;;) {
765 25 q = tag;
766
4/6
✓ Branch 0 taken 132 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 107 times.
✓ Branch 3 taken 25 times.
✓ Branch 4 taken 107 times.
✗ Branch 5 not taken.
132 while (*p != '\0' && *p != '=' && *p != '&') {
767
1/2
✓ Branch 0 taken 107 times.
✗ Branch 1 not taken.
107 if ((q - tag) < sizeof(tag) - 1)
768 107 *q++ = *p;
769 107 p++;
770 }
771 25 *q = '\0';
772 25 q = arg;
773
1/2
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
25 if (*p == '=') {
774 25 p++;
775
4/4
✓ Branch 0 taken 128 times.
✓ Branch 1 taken 22 times.
✓ Branch 2 taken 125 times.
✓ Branch 3 taken 3 times.
150 while (*p != '&' && *p != '\0') {
776
1/2
✓ Branch 0 taken 125 times.
✗ Branch 1 not taken.
125 if ((q - arg) < arg_size - 1) {
777
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 125 times.
125 if (*p == '+')
778 *q++ = ' ';
779 else
780 125 *q++ = *p;
781 }
782 125 p++;
783 }
784 }
785 25 *q = '\0';
786
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 21 times.
25 if (!strcmp(tag, tag1))
787 4 return 1;
788
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 18 times.
21 if (*p != '&')
789 3 break;
790 18 p++;
791 }
792 3 return 0;
793 }
794