Line | Branch | Exec | Source |
---|---|---|---|
1 | /* | ||
2 | * Various utilities for command line tools | ||
3 | * Copyright (c) 2000-2003 Fabrice Bellard | ||
4 | * | ||
5 | * This file is part of FFmpeg. | ||
6 | * | ||
7 | * FFmpeg is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU Lesser General Public | ||
9 | * License as published by the Free Software Foundation; either | ||
10 | * version 2.1 of the License, or (at your option) any later version. | ||
11 | * | ||
12 | * FFmpeg is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * Lesser General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU Lesser General Public | ||
18 | * License along with FFmpeg; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
20 | */ | ||
21 | |||
22 | #include <string.h> | ||
23 | #include <stdint.h> | ||
24 | #include <stdlib.h> | ||
25 | #include <errno.h> | ||
26 | #include <math.h> | ||
27 | |||
28 | /* Include only the enabled headers since some compilers (namely, Sun | ||
29 | Studio) will not omit unused inline functions and create undefined | ||
30 | references to libraries that are not being built. */ | ||
31 | |||
32 | #include "config.h" | ||
33 | #include "compat/va_copy.h" | ||
34 | #include "libavformat/avformat.h" | ||
35 | #include "libswscale/swscale.h" | ||
36 | #include "libswresample/swresample.h" | ||
37 | #include "libavutil/avassert.h" | ||
38 | #include "libavutil/avstring.h" | ||
39 | #include "libavutil/bprint.h" | ||
40 | #include "libavutil/display.h" | ||
41 | #include "libavutil/getenv_utf8.h" | ||
42 | #include "libavutil/libm.h" | ||
43 | #include "libavutil/mem.h" | ||
44 | #include "libavutil/parseutils.h" | ||
45 | #include "libavutil/eval.h" | ||
46 | #include "libavutil/dict.h" | ||
47 | #include "libavutil/opt.h" | ||
48 | #include "cmdutils.h" | ||
49 | #include "fopen_utf8.h" | ||
50 | #include "opt_common.h" | ||
51 | #ifdef _WIN32 | ||
52 | #include <windows.h> | ||
53 | #include "compat/w32dlfcn.h" | ||
54 | #endif | ||
55 | |||
56 | AVDictionary *sws_dict; | ||
57 | AVDictionary *swr_opts; | ||
58 | AVDictionary *format_opts, *codec_opts; | ||
59 | |||
60 | int hide_banner = 0; | ||
61 | |||
62 | 16888 | void uninit_opts(void) | |
63 | { | ||
64 | 16888 | av_dict_free(&swr_opts); | |
65 | 16888 | av_dict_free(&sws_dict); | |
66 | 16888 | av_dict_free(&format_opts); | |
67 | 16888 | av_dict_free(&codec_opts); | |
68 | 16888 | } | |
69 | |||
70 | ✗ | void log_callback_help(void *ptr, int level, const char *fmt, va_list vl) | |
71 | { | ||
72 | ✗ | vfprintf(stdout, fmt, vl); | |
73 | ✗ | } | |
74 | |||
75 | 8524 | void init_dynload(void) | |
76 | { | ||
77 | #if HAVE_SETDLLDIRECTORY && defined(_WIN32) | ||
78 | /* Calling SetDllDirectory with the empty string (but not NULL) removes the | ||
79 | * current working directory from the DLL search path as a security pre-caution. */ | ||
80 | SetDllDirectory(""); | ||
81 | #endif | ||
82 | 8524 | } | |
83 | |||
84 | 38244 | int parse_number(const char *context, const char *numstr, enum OptionType type, | |
85 | double min, double max, double *dst) | ||
86 | { | ||
87 | char *tail; | ||
88 | const char *error; | ||
89 | 38244 | double d = av_strtod(numstr, &tail); | |
90 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 38244 times.
|
38244 | if (*tail) |
91 | ✗ | error = "Expected number for %s but found: %s\n"; | |
92 |
2/4✓ Branch 0 taken 38244 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 38244 times.
|
38244 | else if (d < min || d > max) |
93 | ✗ | error = "The value for %s was %s which is not within %f - %f\n"; | |
94 |
3/4✓ Branch 0 taken 37951 times.
✓ Branch 1 taken 293 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 37951 times.
|
38244 | else if (type == OPT_TYPE_INT64 && (int64_t)d != d) |
95 | ✗ | error = "Expected int64 for %s but found %s\n"; | |
96 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 38244 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
38244 | else if (type == OPT_TYPE_INT && (int)d != d) |
97 | ✗ | error = "Expected int for %s but found %s\n"; | |
98 | else { | ||
99 | 38244 | *dst = d; | |
100 | 38244 | return 0; | |
101 | } | ||
102 | |||
103 | ✗ | av_log(NULL, AV_LOG_FATAL, error, context, numstr, min, max); | |
104 | ✗ | return AVERROR(EINVAL); | |
105 | } | ||
106 | |||
107 | ✗ | void show_help_options(const OptionDef *options, const char *msg, int req_flags, | |
108 | int rej_flags) | ||
109 | { | ||
110 | const OptionDef *po; | ||
111 | int first; | ||
112 | |||
113 | ✗ | first = 1; | |
114 | ✗ | for (po = options; po->name; po++) { | |
115 | char buf[128]; | ||
116 | |||
117 | ✗ | if (((po->flags & req_flags) != req_flags) || | |
118 | ✗ | (po->flags & rej_flags)) | |
119 | ✗ | continue; | |
120 | |||
121 | ✗ | if (first) { | |
122 | ✗ | printf("%s\n", msg); | |
123 | ✗ | first = 0; | |
124 | } | ||
125 | ✗ | av_strlcpy(buf, po->name, sizeof(buf)); | |
126 | |||
127 | ✗ | if (po->flags & OPT_FLAG_PERSTREAM) | |
128 | ✗ | av_strlcat(buf, "[:<stream_spec>]", sizeof(buf)); | |
129 | ✗ | else if (po->flags & OPT_FLAG_SPEC) | |
130 | ✗ | av_strlcat(buf, "[:<spec>]", sizeof(buf)); | |
131 | |||
132 | ✗ | if (po->argname) | |
133 | ✗ | av_strlcatf(buf, sizeof(buf), " <%s>", po->argname); | |
134 | |||
135 | ✗ | printf("-%-17s %s\n", buf, po->help); | |
136 | } | ||
137 | ✗ | printf("\n"); | |
138 | ✗ | } | |
139 | |||
140 | ✗ | void show_help_children(const AVClass *class, int flags) | |
141 | { | ||
142 | ✗ | void *iter = NULL; | |
143 | const AVClass *child; | ||
144 | ✗ | if (class->option) { | |
145 | ✗ | av_opt_show2(&class, NULL, flags, 0); | |
146 | ✗ | printf("\n"); | |
147 | } | ||
148 | |||
149 | ✗ | while (child = av_opt_child_class_iterate(class, &iter)) | |
150 | ✗ | show_help_children(child, flags); | |
151 | ✗ | } | |
152 | |||
153 | 1292351 | static const OptionDef *find_option(const OptionDef *po, const char *name) | |
154 | { | ||
155 |
2/2✓ Branch 0 taken 378 times.
✓ Branch 1 taken 1291973 times.
|
1292351 | if (*name == '/') |
156 | 378 | name++; | |
157 | |||
158 |
2/2✓ Branch 0 taken 191071745 times.
✓ Branch 1 taken 735607 times.
|
191807352 | while (po->name) { |
159 | const char *end; | ||
160 |
6/6✓ Branch 1 taken 1317911 times.
✓ Branch 2 taken 189753834 times.
✓ Branch 3 taken 812903 times.
✓ Branch 4 taken 505008 times.
✓ Branch 5 taken 761167 times.
✓ Branch 6 taken 51736 times.
|
191071745 | if (av_strstart(name, po->name, &end) && (!*end || *end == ':')) |
161 | break; | ||
162 | 190515001 | po++; | |
163 | } | ||
164 | 1292351 | return po; | |
165 | } | ||
166 | |||
167 | /* _WIN32 means using the windows libc - cygwin doesn't define that | ||
168 | * by default. HAVE_COMMANDLINETOARGVW is true on cygwin, while | ||
169 | * it doesn't provide the actual command line via GetCommandLineW(). */ | ||
170 | #if HAVE_COMMANDLINETOARGVW && defined(_WIN32) | ||
171 | #include <shellapi.h> | ||
172 | /* Will be leaked on exit */ | ||
173 | static char** win32_argv_utf8 = NULL; | ||
174 | static int win32_argc = 0; | ||
175 | |||
176 | /** | ||
177 | * Prepare command line arguments for executable. | ||
178 | * For Windows - perform wide-char to UTF-8 conversion. | ||
179 | * Input arguments should be main() function arguments. | ||
180 | * @param argc_ptr Arguments number (including executable) | ||
181 | * @param argv_ptr Arguments list. | ||
182 | */ | ||
183 | static void prepare_app_arguments(int *argc_ptr, char ***argv_ptr) | ||
184 | { | ||
185 | char *argstr_flat; | ||
186 | wchar_t **argv_w; | ||
187 | int i, buffsize = 0, offset = 0; | ||
188 | |||
189 | if (win32_argv_utf8) { | ||
190 | *argc_ptr = win32_argc; | ||
191 | *argv_ptr = win32_argv_utf8; | ||
192 | return; | ||
193 | } | ||
194 | |||
195 | win32_argc = 0; | ||
196 | argv_w = CommandLineToArgvW(GetCommandLineW(), &win32_argc); | ||
197 | if (win32_argc <= 0 || !argv_w) | ||
198 | return; | ||
199 | |||
200 | /* determine the UTF-8 buffer size (including NULL-termination symbols) */ | ||
201 | for (i = 0; i < win32_argc; i++) | ||
202 | buffsize += WideCharToMultiByte(CP_UTF8, 0, argv_w[i], -1, | ||
203 | NULL, 0, NULL, NULL); | ||
204 | |||
205 | win32_argv_utf8 = av_mallocz(sizeof(char *) * (win32_argc + 1) + buffsize); | ||
206 | argstr_flat = (char *)win32_argv_utf8 + sizeof(char *) * (win32_argc + 1); | ||
207 | if (!win32_argv_utf8) { | ||
208 | LocalFree(argv_w); | ||
209 | return; | ||
210 | } | ||
211 | |||
212 | for (i = 0; i < win32_argc; i++) { | ||
213 | win32_argv_utf8[i] = &argstr_flat[offset]; | ||
214 | offset += WideCharToMultiByte(CP_UTF8, 0, argv_w[i], -1, | ||
215 | &argstr_flat[offset], | ||
216 | buffsize - offset, NULL, NULL); | ||
217 | } | ||
218 | win32_argv_utf8[i] = NULL; | ||
219 | LocalFree(argv_w); | ||
220 | |||
221 | *argc_ptr = win32_argc; | ||
222 | *argv_ptr = win32_argv_utf8; | ||
223 | } | ||
224 | #else | ||
225 | 8524 | static inline void prepare_app_arguments(int *argc_ptr, char ***argv_ptr) | |
226 | { | ||
227 | /* nothing to do */ | ||
228 | 8524 | } | |
229 | #endif /* HAVE_COMMANDLINETOARGVW */ | ||
230 | |||
231 | 539587 | static int opt_has_arg(const OptionDef *o) | |
232 | { | ||
233 |
2/2✓ Branch 0 taken 169561 times.
✓ Branch 1 taken 370026 times.
|
539587 | if (o->type == OPT_TYPE_BOOL) |
234 | 169561 | return 0; | |
235 |
2/2✓ Branch 0 taken 129516 times.
✓ Branch 1 taken 240510 times.
|
370026 | if (o->type == OPT_TYPE_FUNC) |
236 | 129516 | return !!(o->flags & OPT_FUNC_ARG); | |
237 | 240510 | return 1; | |
238 | } | ||
239 | |||
240 | 100511 | static int write_option(void *optctx, const OptionDef *po, const char *opt, | |
241 | const char *arg, const OptionDef *defs) | ||
242 | { | ||
243 | /* new-style options contain an offset into optctx, old-style address of | ||
244 | * a global var*/ | ||
245 | 201022 | void *dst = po->flags & OPT_FLAG_OFFSET ? | |
246 |
2/2✓ Branch 0 taken 48701 times.
✓ Branch 1 taken 51810 times.
|
100511 | (uint8_t *)optctx + po->u.off : po->u.dst_ptr; |
247 | 100511 | char *arg_allocated = NULL; | |
248 | |||
249 | 100511 | enum OptionType so_type = po->type; | |
250 | |||
251 | 100511 | SpecifierOptList *sol = NULL; | |
252 | double num; | ||
253 | 100511 | int ret = 0; | |
254 | |||
255 |
2/2✓ Branch 0 taken 63 times.
✓ Branch 1 taken 100448 times.
|
100511 | if (*opt == '/') { |
256 | 63 | opt++; | |
257 | |||
258 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 63 times.
|
63 | if (!opt_has_arg(po)) { |
259 | ✗ | av_log(NULL, AV_LOG_FATAL, | |
260 | "Requested to load an argument from file for an option '%s'" | ||
261 | " which does not take an argument\n", | ||
262 | ✗ | po->name); | |
263 | ✗ | return AVERROR(EINVAL); | |
264 | } | ||
265 | |||
266 | 63 | arg_allocated = file_read(arg); | |
267 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
|
63 | if (!arg_allocated) { |
268 | ✗ | av_log(NULL, AV_LOG_FATAL, | |
269 | "Error reading the value for option '%s' from file: %s\n", | ||
270 | opt, arg); | ||
271 | ✗ | return AVERROR(EINVAL); | |
272 | } | ||
273 | |||
274 | 63 | arg = arg_allocated; | |
275 | } | ||
276 | |||
277 |
2/2✓ Branch 0 taken 33166 times.
✓ Branch 1 taken 67345 times.
|
100511 | if (po->flags & OPT_FLAG_SPEC) { |
278 | 33166 | char *p = strchr(opt, ':'); | |
279 | char *str; | ||
280 | |||
281 | 33166 | sol = dst; | |
282 | 33166 | ret = GROW_ARRAY(sol->opt, sol->nb_opt); | |
283 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 33166 times.
|
33166 | if (ret < 0) |
284 | ✗ | goto finish; | |
285 | |||
286 |
2/2✓ Branch 0 taken 16539 times.
✓ Branch 1 taken 16627 times.
|
33166 | str = av_strdup(p ? p + 1 : ""); |
287 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 33166 times.
|
33166 | if (!str) { |
288 | ✗ | ret = AVERROR(ENOMEM); | |
289 | ✗ | goto finish; | |
290 | } | ||
291 | 33166 | sol->opt[sol->nb_opt - 1].specifier = str; | |
292 | |||
293 |
2/2✓ Branch 0 taken 32915 times.
✓ Branch 1 taken 251 times.
|
33166 | if (po->flags & OPT_FLAG_PERSTREAM) { |
294 | 32915 | ret = stream_specifier_parse(&sol->opt[sol->nb_opt - 1].stream_spec, | |
295 | str, 0, NULL); | ||
296 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32915 times.
|
32915 | if (ret < 0) |
297 | ✗ | goto finish; | |
298 | } | ||
299 | |||
300 | 33166 | dst = &sol->opt[sol->nb_opt - 1].u; | |
301 | } | ||
302 | |||
303 |
2/2✓ Branch 0 taken 39438 times.
✓ Branch 1 taken 61073 times.
|
100511 | if (po->type == OPT_TYPE_STRING) { |
304 | char *str; | ||
305 |
2/2✓ Branch 0 taken 25 times.
✓ Branch 1 taken 39413 times.
|
39438 | if (arg_allocated) { |
306 | 25 | str = arg_allocated; | |
307 | 25 | arg_allocated = NULL; | |
308 | } else | ||
309 | 39413 | str = av_strdup(arg); | |
310 | 39438 | av_freep(dst); | |
311 | |||
312 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 39438 times.
|
39438 | if (!str) { |
313 | ✗ | ret = AVERROR(ENOMEM); | |
314 | ✗ | goto finish; | |
315 | } | ||
316 | |||
317 | 39438 | *(char **)dst = str; | |
318 |
4/4✓ Branch 0 taken 28665 times.
✓ Branch 1 taken 32408 times.
✓ Branch 2 taken 138 times.
✓ Branch 3 taken 28527 times.
|
61073 | } else if (po->type == OPT_TYPE_BOOL || po->type == OPT_TYPE_INT) { |
319 | 32546 | ret = parse_number(opt, arg, OPT_TYPE_INT64, INT_MIN, INT_MAX, &num); | |
320 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32546 times.
|
32546 | if (ret < 0) |
321 | ✗ | goto finish; | |
322 | |||
323 | 32546 | *(int *)dst = num; | |
324 | 32546 | so_type = OPT_TYPE_INT; | |
325 |
2/2✓ Branch 0 taken 5405 times.
✓ Branch 1 taken 23122 times.
|
28527 | } else if (po->type == OPT_TYPE_INT64) { |
326 | 5405 | ret = parse_number(opt, arg, OPT_TYPE_INT64, INT64_MIN, (double)INT64_MAX, &num); | |
327 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5405 times.
|
5405 | if (ret < 0) |
328 | ✗ | goto finish; | |
329 | |||
330 | 5405 | *(int64_t *)dst = num; | |
331 |
2/2✓ Branch 0 taken 1286 times.
✓ Branch 1 taken 21836 times.
|
23122 | } else if (po->type == OPT_TYPE_TIME) { |
332 | 1286 | ret = av_parse_time(dst, arg, 1); | |
333 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1286 times.
|
1286 | if (ret < 0) { |
334 | ✗ | av_log(NULL, AV_LOG_ERROR, "Invalid duration for option %s: %s\n", | |
335 | opt, arg); | ||
336 | ✗ | goto finish; | |
337 | } | ||
338 | 1286 | so_type = OPT_TYPE_INT64; | |
339 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 21833 times.
|
21836 | } else if (po->type == OPT_TYPE_FLOAT) { |
340 | 3 | ret = parse_number(opt, arg, OPT_TYPE_FLOAT, -INFINITY, INFINITY, &num); | |
341 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (ret < 0) |
342 | ✗ | goto finish; | |
343 | |||
344 | 3 | *(float *)dst = num; | |
345 |
2/2✓ Branch 0 taken 290 times.
✓ Branch 1 taken 21543 times.
|
21833 | } else if (po->type == OPT_TYPE_DOUBLE) { |
346 | 290 | ret = parse_number(opt, arg, OPT_TYPE_DOUBLE, -INFINITY, INFINITY, &num); | |
347 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 290 times.
|
290 | if (ret < 0) |
348 | ✗ | goto finish; | |
349 | |||
350 | 290 | *(double *)dst = num; | |
351 | } else { | ||
352 |
2/4✓ Branch 0 taken 21543 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 21543 times.
|
21543 | av_assert0(po->type == OPT_TYPE_FUNC && po->u.func_arg); |
353 | |||
354 | 21543 | ret = po->u.func_arg(optctx, opt, arg); | |
355 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 21543 times.
|
21543 | if (ret < 0) { |
356 | ✗ | if ((strcmp(opt, "init_hw_device") != 0) || (strcmp(arg, "list") != 0)) { | |
357 | ✗ | av_log(NULL, AV_LOG_ERROR, | |
358 | "Failed to set value '%s' for option '%s': %s\n", | ||
359 | ✗ | arg, opt, av_err2str(ret)); | |
360 | } | ||
361 | ✗ | goto finish; | |
362 | } | ||
363 | } | ||
364 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 100510 times.
|
100511 | if (po->flags & OPT_EXIT) { |
365 | 1 | ret = AVERROR_EXIT; | |
366 | 1 | goto finish; | |
367 | } | ||
368 | |||
369 |
2/2✓ Branch 0 taken 67344 times.
✓ Branch 1 taken 33166 times.
|
100510 | if (sol) { |
370 | 33166 | sol->type = so_type; | |
371 |
2/2✓ Branch 0 taken 2467 times.
✓ Branch 1 taken 30699 times.
|
35633 | sol->opt_canon = (po->flags & OPT_HAS_CANON) ? |
372 | 2467 | find_option(defs, po->u1.name_canon) : po; | |
373 | } | ||
374 | |||
375 | 67344 | finish: | |
376 | 100511 | av_freep(&arg_allocated); | |
377 | 100511 | return ret; | |
378 | } | ||
379 | |||
380 | 10295 | int parse_option(void *optctx, const char *opt, const char *arg, | |
381 | const OptionDef *options) | ||
382 | { | ||
383 | static const OptionDef opt_avoptions = { | ||
384 | .name = "AVOption passthrough", | ||
385 | .type = OPT_TYPE_FUNC, | ||
386 | .flags = OPT_FUNC_ARG, | ||
387 | .u.func_arg = opt_default, | ||
388 | }; | ||
389 | |||
390 | const OptionDef *po; | ||
391 | int ret; | ||
392 | |||
393 | 10295 | po = find_option(options, opt); | |
394 |
5/6✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10285 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
10295 | if (!po->name && opt[0] == 'n' && opt[1] == 'o') { |
395 | /* handle 'no' bool option */ | ||
396 | 1 | po = find_option(options, opt + 2); | |
397 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | if ((po->name && po->type == OPT_TYPE_BOOL)) |
398 | 1 | arg = "0"; | |
399 |
2/2✓ Branch 0 taken 152 times.
✓ Branch 1 taken 10142 times.
|
10294 | } else if (po->type == OPT_TYPE_BOOL) |
400 | 152 | arg = "1"; | |
401 | |||
402 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 10286 times.
|
10295 | if (!po->name) |
403 | 9 | po = &opt_avoptions; | |
404 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10295 times.
|
10295 | if (!po->name) { |
405 | ✗ | av_log(NULL, AV_LOG_ERROR, "Unrecognized option '%s'\n", opt); | |
406 | ✗ | return AVERROR(EINVAL); | |
407 | } | ||
408 |
3/4✓ Branch 1 taken 10035 times.
✓ Branch 2 taken 260 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10035 times.
|
10295 | if (opt_has_arg(po) && !arg) { |
409 | ✗ | av_log(NULL, AV_LOG_ERROR, "Missing argument for option '%s'\n", opt); | |
410 | ✗ | return AVERROR(EINVAL); | |
411 | } | ||
412 | |||
413 | 10295 | ret = write_option(optctx, po, opt, arg, options); | |
414 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10295 times.
|
10295 | if (ret < 0) |
415 | ✗ | return ret; | |
416 | |||
417 | 10295 | return opt_has_arg(po); | |
418 | } | ||
419 | |||
420 | 160 | int parse_options(void *optctx, int argc, char **argv, const OptionDef *options, | |
421 | int (*parse_arg_function)(void *, const char*)) | ||
422 | { | ||
423 | const char *opt; | ||
424 | 160 | int optindex, handleoptions = 1, ret; | |
425 | |||
426 | /* perform system-dependent conversions for arguments list */ | ||
427 | 160 | prepare_app_arguments(&argc, &argv); | |
428 | |||
429 | /* parse options */ | ||
430 | 160 | optindex = 1; | |
431 |
2/2✓ Branch 0 taken 701 times.
✓ Branch 1 taken 160 times.
|
861 | while (optindex < argc) { |
432 | 701 | opt = argv[optindex++]; | |
433 | |||
434 |
4/6✓ Branch 0 taken 701 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 551 times.
✓ Branch 3 taken 150 times.
✓ Branch 4 taken 551 times.
✗ Branch 5 not taken.
|
701 | if (handleoptions && opt[0] == '-' && opt[1] != '\0') { |
435 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 551 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
551 | if (opt[1] == '-' && opt[2] == '\0') { |
436 | ✗ | handleoptions = 0; | |
437 | ✗ | continue; | |
438 | } | ||
439 | 551 | opt++; | |
440 | |||
441 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 551 times.
|
551 | if ((ret = parse_option(optctx, opt, argv[optindex], options)) < 0) |
442 | ✗ | return ret; | |
443 | 551 | optindex += ret; | |
444 | } else { | ||
445 |
1/2✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
|
150 | if (parse_arg_function) { |
446 | 150 | ret = parse_arg_function(optctx, opt); | |
447 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 150 times.
|
150 | if (ret < 0) |
448 | ✗ | return ret; | |
449 | } | ||
450 | } | ||
451 | } | ||
452 | |||
453 | 160 | return 0; | |
454 | } | ||
455 | |||
456 | 24046 | int parse_optgroup(void *optctx, OptionGroup *g, const OptionDef *defs) | |
457 | { | ||
458 | int i, ret; | ||
459 | |||
460 | 24046 | av_log(NULL, AV_LOG_DEBUG, "Parsing a group of options: %s %s.\n", | |
461 | 24046 | g->group_def->name, g->arg); | |
462 | |||
463 |
2/2✓ Branch 0 taken 90216 times.
✓ Branch 1 taken 24045 times.
|
114261 | for (i = 0; i < g->nb_opts; i++) { |
464 | 90216 | Option *o = &g->opts[i]; | |
465 | |||
466 |
2/2✓ Branch 0 taken 49260 times.
✓ Branch 1 taken 40956 times.
|
90216 | if (g->group_def->flags && |
467 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 49260 times.
|
49260 | !(g->group_def->flags & o->opt->flags)) { |
468 | ✗ | av_log(NULL, AV_LOG_ERROR, "Option %s (%s) cannot be applied to " | |
469 | "%s %s -- you are trying to apply an input option to an " | ||
470 | "output file or vice versa. Move this option before the " | ||
471 | ✗ | "file it belongs to.\n", o->key, o->opt->help, | |
472 | ✗ | g->group_def->name, g->arg); | |
473 | ✗ | return AVERROR(EINVAL); | |
474 | } | ||
475 | |||
476 | 90216 | av_log(NULL, AV_LOG_DEBUG, "Applying option %s (%s) with argument %s.\n", | |
477 | 90216 | o->key, o->opt->help, o->val); | |
478 | |||
479 | 90216 | ret = write_option(optctx, o->opt, o->key, o->val, defs); | |
480 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 90215 times.
|
90216 | if (ret < 0) |
481 | 1 | return ret; | |
482 | } | ||
483 | |||
484 | 24045 | av_log(NULL, AV_LOG_DEBUG, "Successfully parsed a group of options.\n"); | |
485 | |||
486 | 24045 | return 0; | |
487 | } | ||
488 | |||
489 | 42620 | int locate_option(int argc, char **argv, const OptionDef *options, | |
490 | const char *optname) | ||
491 | { | ||
492 | const OptionDef *po; | ||
493 | int i; | ||
494 | |||
495 |
2/2✓ Branch 0 taken 990219 times.
✓ Branch 1 taken 42604 times.
|
1032823 | for (i = 1; i < argc; i++) { |
496 | 990219 | const char *cur_opt = argv[i]; | |
497 | |||
498 |
4/4✓ Branch 0 taken 960932 times.
✓ Branch 1 taken 29287 times.
✓ Branch 2 taken 13295 times.
✓ Branch 3 taken 947637 times.
|
990219 | if (!(cur_opt[0] == '-' && cur_opt[1])) |
499 | 42582 | continue; | |
500 | 947637 | cur_opt++; | |
501 | |||
502 | 947637 | po = find_option(options, cur_opt); | |
503 |
5/6✓ Branch 0 taken 619067 times.
✓ Branch 1 taken 328570 times.
✓ Branch 2 taken 125245 times.
✓ Branch 3 taken 493822 times.
✓ Branch 4 taken 125245 times.
✗ Branch 5 not taken.
|
947637 | if (!po->name && cur_opt[0] == 'n' && cur_opt[1] == 'o') |
504 | 125245 | po = find_option(options, cur_opt + 2); | |
505 | |||
506 |
3/4✓ Branch 0 taken 493862 times.
✓ Branch 1 taken 453775 times.
✓ Branch 2 taken 493862 times.
✗ Branch 3 not taken.
|
947637 | if ((!po->name && !strcmp(cur_opt, optname)) || |
507 |
4/4✓ Branch 0 taken 453775 times.
✓ Branch 1 taken 493862 times.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 453759 times.
|
947637 | (po->name && !strcmp(optname, po->name))) |
508 | 16 | return i; | |
509 | |||
510 |
4/4✓ Branch 0 taken 453759 times.
✓ Branch 1 taken 493862 times.
✓ Branch 3 taken 291179 times.
✓ Branch 4 taken 162580 times.
|
947621 | if (!po->name || opt_has_arg(po)) |
511 | 785041 | i++; | |
512 | } | ||
513 | 42604 | return 0; | |
514 | } | ||
515 | |||
516 | ✗ | static void dump_argument(FILE *report_file, const char *a) | |
517 | { | ||
518 | const unsigned char *p; | ||
519 | |||
520 | ✗ | for (p = a; *p; p++) | |
521 | ✗ | if (!((*p >= '+' && *p <= ':') || (*p >= '@' && *p <= 'Z') || | |
522 | ✗ | *p == '_' || (*p >= 'a' && *p <= 'z'))) | |
523 | break; | ||
524 | ✗ | if (!*p) { | |
525 | ✗ | fputs(a, report_file); | |
526 | ✗ | return; | |
527 | } | ||
528 | ✗ | fputc('"', report_file); | |
529 | ✗ | for (p = a; *p; p++) { | |
530 | ✗ | if (*p == '\\' || *p == '"' || *p == '$' || *p == '`') | |
531 | ✗ | fprintf(report_file, "\\%c", *p); | |
532 | ✗ | else if (*p < ' ' || *p > '~') | |
533 | ✗ | fprintf(report_file, "\\x%02x", *p); | |
534 | else | ||
535 | ✗ | fputc(*p, report_file); | |
536 | } | ||
537 | ✗ | fputc('"', report_file); | |
538 | } | ||
539 | |||
540 | 8524 | static void check_options(const OptionDef *po) | |
541 | { | ||
542 |
2/2✓ Branch 0 taken 1650544 times.
✓ Branch 1 taken 8524 times.
|
1659068 | while (po->name) { |
543 |
2/2✓ Branch 0 taken 1003680 times.
✓ Branch 1 taken 646864 times.
|
1650544 | if (po->flags & OPT_PERFILE) |
544 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1003680 times.
|
1003680 | av_assert0(po->flags & (OPT_INPUT | OPT_OUTPUT | OPT_DECODER)); |
545 | |||
546 |
2/2✓ Branch 0 taken 635460 times.
✓ Branch 1 taken 1015084 times.
|
1650544 | if (po->type == OPT_TYPE_FUNC) |
547 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 635460 times.
|
635460 | av_assert0(!(po->flags & (OPT_FLAG_OFFSET | OPT_FLAG_SPEC))); |
548 | |||
549 | // OPT_FUNC_ARG can only be ser for OPT_TYPE_FUNC | ||
550 |
3/4✓ Branch 0 taken 1015084 times.
✓ Branch 1 taken 635460 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1015084 times.
|
1650544 | av_assert0((po->type == OPT_TYPE_FUNC) || !(po->flags & OPT_FUNC_ARG)); |
551 | |||
552 | 1650544 | po++; | |
553 | } | ||
554 | 8524 | } | |
555 | |||
556 | 8524 | void parse_loglevel(int argc, char **argv, const OptionDef *options) | |
557 | { | ||
558 | int idx; | ||
559 | char *env; | ||
560 | |||
561 | 8524 | check_options(options); | |
562 | |||
563 | 8524 | idx = locate_option(argc, argv, options, "loglevel"); | |
564 |
1/2✓ Branch 0 taken 8524 times.
✗ Branch 1 not taken.
|
8524 | if (!idx) |
565 | 8524 | idx = locate_option(argc, argv, options, "v"); | |
566 |
3/4✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8508 times.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
|
8524 | if (idx && argv[idx + 1]) |
567 | 16 | opt_loglevel(NULL, "loglevel", argv[idx + 1]); | |
568 | 8524 | idx = locate_option(argc, argv, options, "report"); | |
569 | 8524 | env = getenv_utf8("FFREPORT"); | |
570 |
2/4✓ Branch 0 taken 8524 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8524 times.
|
8524 | if (env || idx) { |
571 | ✗ | FILE *report_file = NULL; | |
572 | ✗ | init_report(env, &report_file); | |
573 | ✗ | if (report_file) { | |
574 | int i; | ||
575 | ✗ | fprintf(report_file, "Command line:\n"); | |
576 | ✗ | for (i = 0; i < argc; i++) { | |
577 | ✗ | dump_argument(report_file, argv[i]); | |
578 | ✗ | fputc(i < argc - 1 ? ' ' : '\n', report_file); | |
579 | } | ||
580 | ✗ | fflush(report_file); | |
581 | } | ||
582 | } | ||
583 | 8524 | freeenv_utf8(env); | |
584 | 8524 | idx = locate_option(argc, argv, options, "hide_banner"); | |
585 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8524 times.
|
8524 | if (idx) |
586 | ✗ | hide_banner = 1; | |
587 | 8524 | } | |
588 | |||
589 | 314383 | static const AVOption *opt_find(void *obj, const char *name, const char *unit, | |
590 | int opt_flags, int search_flags) | ||
591 | { | ||
592 | 314383 | const AVOption *o = av_opt_find(obj, name, unit, opt_flags, search_flags); | |
593 |
4/4✓ Branch 0 taken 91537 times.
✓ Branch 1 taken 222846 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 91535 times.
|
314383 | if(o && !o->flags) |
594 | 2 | return NULL; | |
595 | 314381 | return o; | |
596 | } | ||
597 | |||
598 | #define FLAGS ((o->type == AV_OPT_TYPE_FLAGS && (arg[0]=='-' || arg[0]=='+')) ? AV_DICT_APPEND : 0) | ||
599 | 116499 | int opt_default(void *optctx, const char *opt, const char *arg) | |
600 | { | ||
601 | const AVOption *o; | ||
602 | 116499 | int consumed = 0; | |
603 | char opt_stripped[128]; | ||
604 | const char *p; | ||
605 | 116499 | const AVClass *cc = avcodec_get_class(), *fc = avformat_get_class(); | |
606 | #if CONFIG_SWSCALE | ||
607 | 116499 | const AVClass *sc = sws_get_class(); | |
608 | #endif | ||
609 | #if CONFIG_SWRESAMPLE | ||
610 | 116499 | const AVClass *swr_class = swr_get_class(); | |
611 | #endif | ||
612 | |||
613 |
2/4✓ Branch 0 taken 116499 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 116499 times.
|
116499 | if (!strcmp(opt, "debug") || !strcmp(opt, "fdebug")) |
614 | ✗ | av_log_set_level(AV_LOG_DEBUG); | |
615 | |||
616 |
2/2✓ Branch 0 taken 116487 times.
✓ Branch 1 taken 12 times.
|
116499 | if (!(p = strchr(opt, ':'))) |
617 | 116487 | p = opt + strlen(opt); | |
618 | 116499 | av_strlcpy(opt_stripped, opt, FFMIN(sizeof(opt_stripped), p - opt + 1)); | |
619 | |||
620 |
2/2✓ Branch 1 taken 56241 times.
✓ Branch 2 taken 60258 times.
|
116499 | if ((o = opt_find(&cc, opt_stripped, NULL, 0, |
621 | 56241 | AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ)) || | |
622 |
8/8✓ Branch 0 taken 56238 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 56226 times.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 15657 times.
✓ Branch 5 taken 40569 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 15671 times.
|
71913 | ((opt[0] == 'v' || opt[0] == 'a' || opt[0] == 's') && |
623 | 15672 | (o = opt_find(&cc, opt + 1, NULL, 0, AV_OPT_SEARCH_FAKE_OBJ)))) { | |
624 |
5/6✓ Branch 0 taken 22671 times.
✓ Branch 1 taken 37588 times.
✓ Branch 2 taken 22671 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15580 times.
✓ Branch 5 taken 7091 times.
|
60259 | av_dict_set(&codec_opts, opt, arg, FLAGS); |
625 | 60259 | consumed = 1; | |
626 | } | ||
627 |
2/2✓ Branch 1 taken 15643 times.
✓ Branch 2 taken 100856 times.
|
116499 | if ((o = opt_find(&fc, opt, NULL, 0, |
628 | AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) { | ||
629 |
5/6✓ Branch 0 taken 15422 times.
✓ Branch 1 taken 221 times.
✓ Branch 2 taken 15422 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15414 times.
✓ Branch 5 taken 8 times.
|
15643 | av_dict_set(&format_opts, opt, arg, FLAGS); |
630 |
2/2✓ Branch 0 taken 76 times.
✓ Branch 1 taken 15567 times.
|
15643 | if (consumed) |
631 | 76 | av_log(NULL, AV_LOG_VERBOSE, "Routing option %s to both codec and muxer layer\n", opt); | |
632 | 15643 | consumed = 1; | |
633 | } | ||
634 | #if CONFIG_SWSCALE | ||
635 |
4/4✓ Branch 0 taken 40673 times.
✓ Branch 1 taken 75826 times.
✓ Branch 3 taken 15633 times.
✓ Branch 4 taken 25040 times.
|
116499 | if (!consumed && (o = opt_find(&sc, opt, NULL, 0, |
636 | AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) { | ||
637 |
2/4✓ Branch 0 taken 15633 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15633 times.
✗ Branch 3 not taken.
|
15633 | if (!strcmp(opt, "srcw") || !strcmp(opt, "srch") || |
638 |
2/4✓ Branch 0 taken 15633 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15633 times.
✗ Branch 3 not taken.
|
15633 | !strcmp(opt, "dstw") || !strcmp(opt, "dsth") || |
639 |
2/4✓ Branch 0 taken 15633 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 15633 times.
|
15633 | !strcmp(opt, "src_format") || !strcmp(opt, "dst_format")) { |
640 | ✗ | av_log(NULL, AV_LOG_ERROR, "Directly using swscale dimensions/format options is not supported, please use the -s or -pix_fmt options\n"); | |
641 | ✗ | return AVERROR(EINVAL); | |
642 | } | ||
643 |
4/6✓ Branch 0 taken 15633 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15633 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15418 times.
✓ Branch 5 taken 215 times.
|
15633 | av_dict_set(&sws_dict, opt, arg, FLAGS); |
644 | |||
645 | 15633 | consumed = 1; | |
646 | } | ||
647 | #else | ||
648 | if (!consumed && !strcmp(opt, "sws_flags")) { | ||
649 | av_log(NULL, AV_LOG_WARNING, "Ignoring %s %s, due to disabled swscale\n", opt, arg); | ||
650 | consumed = 1; | ||
651 | } | ||
652 | #endif | ||
653 | #if CONFIG_SWRESAMPLE | ||
654 |
3/4✓ Branch 0 taken 25040 times.
✓ Branch 1 taken 91459 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 25040 times.
|
116499 | if (!consumed && (o=opt_find(&swr_class, opt, NULL, 0, |
655 | AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) { | ||
656 | ✗ | av_dict_set(&swr_opts, opt, arg, FLAGS); | |
657 | ✗ | consumed = 1; | |
658 | } | ||
659 | #endif | ||
660 | |||
661 |
2/2✓ Branch 0 taken 91459 times.
✓ Branch 1 taken 25040 times.
|
116499 | if (consumed) |
662 | 91459 | return 0; | |
663 | 25040 | return AVERROR_OPTION_NOT_FOUND; | |
664 | } | ||
665 | |||
666 | /* | ||
667 | * Check whether given option is a group separator. | ||
668 | * | ||
669 | * @return index of the group definition that matched or -1 if none | ||
670 | */ | ||
671 | 188981 | static int match_group_separator(const OptionGroupDef *groups, int nb_groups, | |
672 | const char *opt) | ||
673 | { | ||
674 | int i; | ||
675 | |||
676 |
2/2✓ Branch 0 taken 559629 times.
✓ Branch 1 taken 181666 times.
|
741295 | for (i = 0; i < nb_groups; i++) { |
677 | 559629 | const OptionGroupDef *p = &groups[i]; | |
678 |
4/4✓ Branch 0 taken 370648 times.
✓ Branch 1 taken 188981 times.
✓ Branch 2 taken 7315 times.
✓ Branch 3 taken 363333 times.
|
559629 | if (p->sep && !strcmp(p->sep, opt)) |
679 | 7315 | return i; | |
680 | } | ||
681 | |||
682 | 181666 | return -1; | |
683 | } | ||
684 | |||
685 | /* | ||
686 | * Finish parsing an option group. | ||
687 | * | ||
688 | * @param group_idx which group definition should this group belong to | ||
689 | * @param arg argument of the group delimiting option | ||
690 | */ | ||
691 | 15682 | static int finish_group(OptionParseContext *octx, int group_idx, | |
692 | const char *arg) | ||
693 | { | ||
694 | 15682 | OptionGroupList *l = &octx->groups[group_idx]; | |
695 | OptionGroup *g; | ||
696 | int ret; | ||
697 | |||
698 | 15682 | ret = GROW_ARRAY(l->groups, l->nb_groups); | |
699 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15682 times.
|
15682 | if (ret < 0) |
700 | ✗ | return ret; | |
701 | |||
702 | 15682 | g = &l->groups[l->nb_groups - 1]; | |
703 | |||
704 | 15682 | *g = octx->cur_group; | |
705 | 15682 | g->arg = arg; | |
706 | 15682 | g->group_def = l->group_def; | |
707 | 15682 | g->sws_dict = sws_dict; | |
708 | 15682 | g->swr_opts = swr_opts; | |
709 | 15682 | g->codec_opts = codec_opts; | |
710 | 15682 | g->format_opts = format_opts; | |
711 | |||
712 | 15682 | codec_opts = NULL; | |
713 | 15682 | format_opts = NULL; | |
714 | 15682 | sws_dict = NULL; | |
715 | 15682 | swr_opts = NULL; | |
716 | |||
717 | 15682 | memset(&octx->cur_group, 0, sizeof(octx->cur_group)); | |
718 | |||
719 | 15682 | return ret; | |
720 | } | ||
721 | |||
722 | /* | ||
723 | * Add an option instance to currently parsed group. | ||
724 | */ | ||
725 | 90216 | static int add_opt(OptionParseContext *octx, const OptionDef *opt, | |
726 | const char *key, const char *val) | ||
727 | { | ||
728 | 90216 | int global = !(opt->flags & OPT_PERFILE); | |
729 |
2/2✓ Branch 0 taken 40956 times.
✓ Branch 1 taken 49260 times.
|
90216 | OptionGroup *g = global ? &octx->global_opts : &octx->cur_group; |
730 | int ret; | ||
731 | |||
732 | 90216 | ret = GROW_ARRAY(g->opts, g->nb_opts); | |
733 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 90216 times.
|
90216 | if (ret < 0) |
734 | ✗ | return ret; | |
735 | |||
736 | 90216 | g->opts[g->nb_opts - 1].opt = opt; | |
737 | 90216 | g->opts[g->nb_opts - 1].key = key; | |
738 | 90216 | g->opts[g->nb_opts - 1].val = val; | |
739 | |||
740 | 90216 | return 0; | |
741 | } | ||
742 | |||
743 | 8364 | static int init_parse_context(OptionParseContext *octx, | |
744 | const OptionGroupDef *groups, int nb_groups) | ||
745 | { | ||
746 | static const OptionGroupDef global_group = { "global" }; | ||
747 | int i; | ||
748 | |||
749 | 8364 | memset(octx, 0, sizeof(*octx)); | |
750 | |||
751 | 8364 | octx->groups = av_calloc(nb_groups, sizeof(*octx->groups)); | |
752 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8364 times.
|
8364 | if (!octx->groups) |
753 | ✗ | return AVERROR(ENOMEM); | |
754 | 8364 | octx->nb_groups = nb_groups; | |
755 | |||
756 |
2/2✓ Branch 0 taken 25092 times.
✓ Branch 1 taken 8364 times.
|
33456 | for (i = 0; i < octx->nb_groups; i++) |
757 | 25092 | octx->groups[i].group_def = &groups[i]; | |
758 | |||
759 | 8364 | octx->global_opts.group_def = &global_group; | |
760 | 8364 | octx->global_opts.arg = ""; | |
761 | |||
762 | 8364 | return 0; | |
763 | } | ||
764 | |||
765 | 8364 | void uninit_parse_context(OptionParseContext *octx) | |
766 | { | ||
767 | int i, j; | ||
768 | |||
769 |
2/2✓ Branch 0 taken 25092 times.
✓ Branch 1 taken 8364 times.
|
33456 | for (i = 0; i < octx->nb_groups; i++) { |
770 | 25092 | OptionGroupList *l = &octx->groups[i]; | |
771 | |||
772 |
2/2✓ Branch 0 taken 15682 times.
✓ Branch 1 taken 25092 times.
|
40774 | for (j = 0; j < l->nb_groups; j++) { |
773 | 15682 | av_freep(&l->groups[j].opts); | |
774 | 15682 | av_dict_free(&l->groups[j].codec_opts); | |
775 | 15682 | av_dict_free(&l->groups[j].format_opts); | |
776 | |||
777 | 15682 | av_dict_free(&l->groups[j].sws_dict); | |
778 | 15682 | av_dict_free(&l->groups[j].swr_opts); | |
779 | } | ||
780 | 25092 | av_freep(&l->groups); | |
781 | } | ||
782 | 8364 | av_freep(&octx->groups); | |
783 | |||
784 | 8364 | av_freep(&octx->cur_group.opts); | |
785 | 8364 | av_freep(&octx->global_opts.opts); | |
786 | |||
787 | 8364 | uninit_opts(); | |
788 | 8364 | } | |
789 | |||
790 | 8364 | int split_commandline(OptionParseContext *octx, int argc, char *argv[], | |
791 | const OptionDef *options, | ||
792 | const OptionGroupDef *groups, int nb_groups) | ||
793 | { | ||
794 | int ret; | ||
795 | 8364 | int optindex = 1; | |
796 | 8364 | int dashdash = -2; | |
797 | |||
798 | /* perform system-dependent conversions for arguments list */ | ||
799 | 8364 | prepare_app_arguments(&argc, &argv); | |
800 | |||
801 | 8364 | ret = init_parse_context(octx, groups, nb_groups); | |
802 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8364 times.
|
8364 | if (ret < 0) |
803 | ✗ | return ret; | |
804 | |||
805 | 8364 | av_log(NULL, AV_LOG_DEBUG, "Splitting the commandline.\n"); | |
806 | |||
807 |
2/2✓ Branch 0 taken 197348 times.
✓ Branch 1 taken 8364 times.
|
205712 | while (optindex < argc) { |
808 | 197348 | const char *opt = argv[optindex++], *arg; | |
809 | const OptionDef *po; | ||
810 | int group_idx; | ||
811 | |||
812 | 197348 | av_log(NULL, AV_LOG_DEBUG, "Reading option '%s' ...", opt); | |
813 | |||
814 |
3/6✓ Branch 0 taken 191640 times.
✓ Branch 1 taken 5708 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 191640 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
197348 | if (opt[0] == '-' && opt[1] == '-' && !opt[2]) { |
815 | ✗ | dashdash = optindex; | |
816 | ✗ | continue; | |
817 | } | ||
818 | /* unnamed group separators, e.g. output filename */ | ||
819 |
5/6✓ Branch 0 taken 191640 times.
✓ Branch 1 taken 5708 times.
✓ Branch 2 taken 188981 times.
✓ Branch 3 taken 2659 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 188981 times.
|
197348 | if (opt[0] != '-' || !opt[1] || dashdash+1 == optindex) { |
820 | 8367 | ret = finish_group(octx, 0, opt); | |
821 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8367 times.
|
8367 | if (ret < 0) |
822 | ✗ | return ret; | |
823 | |||
824 | 8367 | av_log(NULL, AV_LOG_DEBUG, " matched as %s.\n", groups[0].name); | |
825 | 8367 | continue; | |
826 | } | ||
827 | 188981 | opt++; | |
828 | |||
829 | #define GET_ARG(arg) \ | ||
830 | do { \ | ||
831 | arg = argv[optindex++]; \ | ||
832 | if (!arg) { \ | ||
833 | av_log(NULL, AV_LOG_ERROR, "Missing argument for option '%s'.\n", opt);\ | ||
834 | return AVERROR(EINVAL); \ | ||
835 | } \ | ||
836 | } while (0) | ||
837 | |||
838 | /* named group separators, e.g. -i */ | ||
839 | 188981 | group_idx = match_group_separator(groups, nb_groups, opt); | |
840 |
2/2✓ Branch 0 taken 7315 times.
✓ Branch 1 taken 181666 times.
|
188981 | if (group_idx >= 0) { |
841 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7315 times.
|
7315 | GET_ARG(arg); |
842 | 7315 | ret = finish_group(octx, group_idx, arg); | |
843 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7315 times.
|
7315 | if (ret < 0) |
844 | ✗ | return ret; | |
845 | |||
846 | 7315 | av_log(NULL, AV_LOG_DEBUG, " matched as %s with argument '%s'.\n", | |
847 | 7315 | groups[group_idx].name, arg); | |
848 | 7315 | continue; | |
849 | } | ||
850 | |||
851 | /* normal options */ | ||
852 | 181666 | po = find_option(options, opt); | |
853 |
2/2✓ Branch 0 taken 65176 times.
✓ Branch 1 taken 116490 times.
|
181666 | if (po->name) { |
854 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 65175 times.
|
65176 | if (po->flags & OPT_EXIT) { |
855 | /* optional argument, e.g. -h */ | ||
856 | 1 | arg = argv[optindex++]; | |
857 |
2/2✓ Branch 1 taken 57960 times.
✓ Branch 2 taken 7215 times.
|
65175 | } else if (opt_has_arg(po)) { |
858 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 57960 times.
|
57960 | GET_ARG(arg); |
859 | } else { | ||
860 | 7215 | arg = "1"; | |
861 | } | ||
862 | |||
863 | 65176 | ret = add_opt(octx, po, opt, arg); | |
864 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 65176 times.
|
65176 | if (ret < 0) |
865 | ✗ | return ret; | |
866 | |||
867 | 65176 | av_log(NULL, AV_LOG_DEBUG, " matched as option '%s' (%s) with " | |
868 | 65176 | "argument '%s'.\n", po->name, po->help, arg); | |
869 | 65176 | continue; | |
870 | } | ||
871 | |||
872 | /* AVOptions */ | ||
873 |
1/2✓ Branch 0 taken 116490 times.
✗ Branch 1 not taken.
|
116490 | if (argv[optindex]) { |
874 | 116490 | ret = opt_default(NULL, opt, argv[optindex]); | |
875 |
2/2✓ Branch 0 taken 91450 times.
✓ Branch 1 taken 25040 times.
|
116490 | if (ret >= 0) { |
876 | 91450 | av_log(NULL, AV_LOG_DEBUG, " matched as AVOption '%s' with " | |
877 | 91450 | "argument '%s'.\n", opt, argv[optindex]); | |
878 | 91450 | optindex++; | |
879 | 91450 | continue; | |
880 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 25040 times.
|
25040 | } else if (ret != AVERROR_OPTION_NOT_FOUND) { |
881 | ✗ | av_log(NULL, AV_LOG_ERROR, "Error parsing option '%s' " | |
882 | ✗ | "with argument '%s'.\n", opt, argv[optindex]); | |
883 | ✗ | return ret; | |
884 | } | ||
885 | } | ||
886 | |||
887 | /* boolean -nofoo options */ | ||
888 |
3/6✓ Branch 0 taken 25040 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25040 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 25040 times.
✗ Branch 5 not taken.
|
50080 | if (opt[0] == 'n' && opt[1] == 'o' && |
889 | 25040 | (po = find_option(options, opt + 2)) && | |
890 |
2/4✓ Branch 0 taken 25040 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25040 times.
✗ Branch 3 not taken.
|
25040 | po->name && po->type == OPT_TYPE_BOOL) { |
891 | 25040 | ret = add_opt(octx, po, opt, "0"); | |
892 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 25040 times.
|
25040 | if (ret < 0) |
893 | ✗ | return ret; | |
894 | |||
895 | 25040 | av_log(NULL, AV_LOG_DEBUG, " matched as option '%s' (%s) with " | |
896 | 25040 | "argument 0.\n", po->name, po->help); | |
897 | 25040 | continue; | |
898 | } | ||
899 | |||
900 | ✗ | av_log(NULL, AV_LOG_ERROR, "Unrecognized option '%s'.\n", opt); | |
901 | ✗ | return AVERROR_OPTION_NOT_FOUND; | |
902 | } | ||
903 | |||
904 |
3/6✓ Branch 0 taken 8364 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8364 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8364 times.
|
8364 | if (octx->cur_group.nb_opts || codec_opts || format_opts) |
905 | ✗ | av_log(NULL, AV_LOG_WARNING, "Trailing option(s) found in the " | |
906 | "command: may be ignored.\n"); | ||
907 | |||
908 | 8364 | av_log(NULL, AV_LOG_DEBUG, "Finished splitting the commandline.\n"); | |
909 | |||
910 | 8364 | return 0; | |
911 | } | ||
912 | |||
913 | ✗ | int read_yesno(void) | |
914 | { | ||
915 | ✗ | int c = getchar(); | |
916 | ✗ | int yesno = (av_toupper(c) == 'Y'); | |
917 | |||
918 | ✗ | while (c != '\n' && c != EOF) | |
919 | ✗ | c = getchar(); | |
920 | |||
921 | ✗ | return yesno; | |
922 | } | ||
923 | |||
924 | ✗ | FILE *get_preset_file(char *filename, size_t filename_size, | |
925 | const char *preset_name, int is_path, | ||
926 | const char *codec_name) | ||
927 | { | ||
928 | ✗ | FILE *f = NULL; | |
929 | int i; | ||
930 | #if HAVE_GETMODULEHANDLE && defined(_WIN32) | ||
931 | char *datadir = NULL; | ||
932 | #endif | ||
933 | ✗ | char *env_home = getenv_utf8("HOME"); | |
934 | ✗ | char *env_ffmpeg_datadir = getenv_utf8("FFMPEG_DATADIR"); | |
935 | ✗ | const char *base[3] = { env_ffmpeg_datadir, | |
936 | env_home, /* index=1(HOME) is special: search in a .ffmpeg subfolder */ | ||
937 | FFMPEG_DATADIR, }; | ||
938 | |||
939 | ✗ | if (is_path) { | |
940 | ✗ | av_strlcpy(filename, preset_name, filename_size); | |
941 | ✗ | f = fopen_utf8(filename, "r"); | |
942 | } else { | ||
943 | #if HAVE_GETMODULEHANDLE && defined(_WIN32) | ||
944 | wchar_t *datadir_w = get_module_filename(NULL); | ||
945 | base[2] = NULL; | ||
946 | |||
947 | if (wchartoutf8(datadir_w, &datadir)) | ||
948 | datadir = NULL; | ||
949 | av_free(datadir_w); | ||
950 | |||
951 | if (datadir) | ||
952 | { | ||
953 | char *ls; | ||
954 | for (ls = datadir; *ls; ls++) | ||
955 | if (*ls == '\\') *ls = '/'; | ||
956 | |||
957 | if (ls = strrchr(datadir, '/')) | ||
958 | { | ||
959 | ptrdiff_t datadir_len = ls - datadir; | ||
960 | size_t desired_size = datadir_len + strlen("/ffpresets") + 1; | ||
961 | char *new_datadir = av_realloc_array( | ||
962 | datadir, desired_size, sizeof *datadir); | ||
963 | if (new_datadir) { | ||
964 | datadir = new_datadir; | ||
965 | datadir[datadir_len] = 0; | ||
966 | strncat(datadir, "/ffpresets", desired_size - 1 - datadir_len); | ||
967 | base[2] = datadir; | ||
968 | } | ||
969 | } | ||
970 | } | ||
971 | #endif | ||
972 | ✗ | for (i = 0; i < 3 && !f; i++) { | |
973 | ✗ | if (!base[i]) | |
974 | ✗ | continue; | |
975 | ✗ | snprintf(filename, filename_size, "%s%s/%s.ffpreset", base[i], | |
976 | i != 1 ? "" : "/.ffmpeg", preset_name); | ||
977 | ✗ | f = fopen_utf8(filename, "r"); | |
978 | ✗ | if (!f && codec_name) { | |
979 | ✗ | snprintf(filename, filename_size, | |
980 | "%s%s/%s-%s.ffpreset", | ||
981 | base[i], i != 1 ? "" : "/.ffmpeg", codec_name, | ||
982 | preset_name); | ||
983 | ✗ | f = fopen_utf8(filename, "r"); | |
984 | } | ||
985 | } | ||
986 | } | ||
987 | |||
988 | #if HAVE_GETMODULEHANDLE && defined(_WIN32) | ||
989 | av_free(datadir); | ||
990 | #endif | ||
991 | ✗ | freeenv_utf8(env_ffmpeg_datadir); | |
992 | ✗ | freeenv_utf8(env_home); | |
993 | ✗ | return f; | |
994 | } | ||
995 | |||
996 | 16982 | int cmdutils_isalnum(char c) | |
997 | { | ||
998 |
3/4✓ Branch 0 taken 216 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 41 times.
✓ Branch 3 taken 16941 times.
|
16982 | return (c >= '0' && c <= '9') || |
999 |
5/6✓ Branch 0 taken 216 times.
✓ Branch 1 taken 16766 times.
✓ Branch 2 taken 41 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 40 times.
✓ Branch 5 taken 16942 times.
|
34004 | (c >= 'A' && c <= 'Z') || |
1000 |
1/2✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
|
40 | (c >= 'a' && c <= 'z'); |
1001 | } | ||
1002 | |||
1003 | 33814 | void stream_specifier_uninit(StreamSpecifier *ss) | |
1004 | { | ||
1005 | 33814 | av_freep(&ss->meta_key); | |
1006 | 33814 | av_freep(&ss->meta_val); | |
1007 | 33814 | av_freep(&ss->remainder); | |
1008 | |||
1009 | 33814 | memset(ss, 0, sizeof(*ss)); | |
1010 | 33814 | } | |
1011 | |||
1012 | 33739 | int stream_specifier_parse(StreamSpecifier *ss, const char *spec, | |
1013 | int allow_remainder, void *logctx) | ||
1014 | { | ||
1015 | char *endptr; | ||
1016 | int ret; | ||
1017 | |||
1018 | 33739 | memset(ss, 0, sizeof(*ss)); | |
1019 | |||
1020 | 33739 | ss->idx = -1; | |
1021 | 33739 | ss->media_type = AVMEDIA_TYPE_UNKNOWN; | |
1022 | 33739 | ss->stream_list = STREAM_LIST_ALL; | |
1023 | |||
1024 | 33739 | av_log(logctx, AV_LOG_TRACE, "Parsing stream specifier: %s\n", spec); | |
1025 | |||
1026 |
2/2✓ Branch 0 taken 17351 times.
✓ Branch 1 taken 33332 times.
|
84422 | while (*spec) { |
1027 |
3/4✓ Branch 0 taken 394 times.
✓ Branch 1 taken 16957 times.
✓ Branch 2 taken 394 times.
✗ Branch 3 not taken.
|
17351 | if (*spec <= '9' && *spec >= '0') { /* opt:index */ |
1028 | 394 | ss->idx = strtol(spec, &endptr, 0); | |
1029 | |||
1030 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 394 times.
|
394 | av_assert0(endptr > spec); |
1031 | 394 | spec = endptr; | |
1032 | |||
1033 | 394 | av_log(logctx, AV_LOG_TRACE, | |
1034 | "Parsed index: %d; remainder: %s\n", ss->idx, spec); | ||
1035 | |||
1036 | // this terminates the specifier | ||
1037 | 394 | break; | |
1038 |
6/6✓ Branch 0 taken 1504 times.
✓ Branch 1 taken 15453 times.
✓ Branch 2 taken 46 times.
✓ Branch 3 taken 1458 times.
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 36 times.
|
16957 | } else if ((*spec == 'v' || *spec == 'a' || *spec == 's' || |
1039 |
7/8✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
✓ Branch 6 taken 16937 times.
✓ Branch 7 taken 14 times.
|
16961 | *spec == 'd' || *spec == 't' || *spec == 'V') && |
1040 | 16951 | !cmdutils_isalnum(*(spec + 1))) { /* opt:[vasdtV] */ | |
1041 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16937 times.
|
16937 | if (ss->media_type != AVMEDIA_TYPE_UNKNOWN) { |
1042 | ✗ | av_log(logctx, AV_LOG_ERROR, "Stream type specified multiple times\n"); | |
1043 | ✗ | ret = AVERROR(EINVAL); | |
1044 | ✗ | goto fail; | |
1045 | } | ||
1046 | |||
1047 |
4/7✓ Branch 0 taken 15440 times.
✓ Branch 1 taken 1458 times.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
16937 | switch (*spec++) { |
1048 | 15440 | case 'v': ss->media_type = AVMEDIA_TYPE_VIDEO; break; | |
1049 | 1458 | case 'a': ss->media_type = AVMEDIA_TYPE_AUDIO; break; | |
1050 | 36 | case 's': ss->media_type = AVMEDIA_TYPE_SUBTITLE; break; | |
1051 | ✗ | case 'd': ss->media_type = AVMEDIA_TYPE_DATA; break; | |
1052 | 3 | case 't': ss->media_type = AVMEDIA_TYPE_ATTACHMENT; break; | |
1053 | ✗ | case 'V': ss->media_type = AVMEDIA_TYPE_VIDEO; | |
1054 | ✗ | ss->no_apic = 1; break; | |
1055 | ✗ | default: av_assert0(0); | |
1056 | } | ||
1057 | |||
1058 | 16937 | av_log(logctx, AV_LOG_TRACE, "Parsed media type: %s; remainder: %s\n", | |
1059 | av_get_media_type_string(ss->media_type), spec); | ||
1060 |
3/4✓ Branch 0 taken 6 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
20 | } else if (*spec == 'g' && *(spec + 1) == ':') { |
1061 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (ss->stream_list != STREAM_LIST_ALL) |
1062 | ✗ | goto multiple_stream_lists; | |
1063 | |||
1064 | 6 | spec += 2; | |
1065 |
5/6✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
6 | if (*spec == '#' || (*spec == 'i' && *(spec + 1) == ':')) { |
1066 | 3 | ss->stream_list = STREAM_LIST_GROUP_ID; | |
1067 | |||
1068 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
|
3 | spec += 1 + (*spec == 'i'); |
1069 | } else | ||
1070 | 3 | ss->stream_list = STREAM_LIST_GROUP_IDX; | |
1071 | |||
1072 | 6 | ss->list_id = strtol(spec, &endptr, 0); | |
1073 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (spec == endptr) { |
1074 | ✗ | av_log(logctx, AV_LOG_ERROR, "Expected stream group idx/ID, got: %s\n", spec); | |
1075 | ✗ | ret = AVERROR(EINVAL); | |
1076 | ✗ | goto fail; | |
1077 | } | ||
1078 | 6 | spec = endptr; | |
1079 | |||
1080 | 6 | av_log(logctx, AV_LOG_TRACE, "Parsed stream group %s: %"PRId64"; remainder: %s\n", | |
1081 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
|
6 | ss->stream_list == STREAM_LIST_GROUP_ID ? "ID" : "index", ss->list_id, spec); |
1082 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
14 | } else if (*spec == 'p' && *(spec + 1) == ':') { |
1083 | ✗ | if (ss->stream_list != STREAM_LIST_ALL) | |
1084 | ✗ | goto multiple_stream_lists; | |
1085 | |||
1086 | ✗ | ss->stream_list = STREAM_LIST_PROGRAM; | |
1087 | |||
1088 | ✗ | spec += 2; | |
1089 | ✗ | ss->list_id = strtol(spec, &endptr, 0); | |
1090 | ✗ | if (spec == endptr) { | |
1091 | ✗ | av_log(logctx, AV_LOG_ERROR, "Expected program ID, got: %s\n", spec); | |
1092 | ✗ | ret = AVERROR(EINVAL); | |
1093 | ✗ | goto fail; | |
1094 | } | ||
1095 | ✗ | spec = endptr; | |
1096 | |||
1097 | ✗ | av_log(logctx, AV_LOG_TRACE, | |
1098 | "Parsed program ID: %"PRId64"; remainder: %s\n", ss->list_id, spec); | ||
1099 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 13 times.
|
14 | } else if (!strncmp(spec, "disp:", 5)) { |
1100 | 1 | const AVClass *st_class = av_stream_get_class(); | |
1101 | 1 | const AVOption *o = av_opt_find(&st_class, "disposition", NULL, 0, AV_OPT_SEARCH_FAKE_OBJ); | |
1102 | 1 | char *disp = NULL; | |
1103 | size_t len; | ||
1104 | |||
1105 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | av_assert0(o); |
1106 | |||
1107 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (ss->disposition) { |
1108 | ✗ | av_log(logctx, AV_LOG_ERROR, "Multiple disposition specifiers\n"); | |
1109 | ✗ | ret = AVERROR(EINVAL); | |
1110 | ✗ | goto fail; | |
1111 | } | ||
1112 | |||
1113 | 1 | spec += 5; | |
1114 | |||
1115 | 29 | for (len = 0; cmdutils_isalnum(spec[len]) || | |
1116 |
6/6✓ Branch 0 taken 26 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
|
57 | spec[len] == '_' || spec[len] == '+'; len++) |
1117 | 28 | continue; | |
1118 | |||
1119 | 1 | disp = av_strndup(spec, len); | |
1120 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!disp) { |
1121 | ✗ | ret = AVERROR(ENOMEM); | |
1122 | ✗ | goto fail; | |
1123 | } | ||
1124 | |||
1125 | 1 | ret = av_opt_eval_flags(&st_class, o, disp, &ss->disposition); | |
1126 | 1 | av_freep(&disp); | |
1127 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (ret < 0) { |
1128 | ✗ | av_log(logctx, AV_LOG_ERROR, "Invalid disposition specifier\n"); | |
1129 | ✗ | goto fail; | |
1130 | } | ||
1131 | |||
1132 | 1 | spec += len; | |
1133 | |||
1134 | 1 | av_log(logctx, AV_LOG_TRACE, | |
1135 | "Parsed disposition: 0x%x; remainder: %s\n", ss->disposition, spec); | ||
1136 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
13 | } else if (*spec == '#' || |
1137 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
13 | (*spec == 'i' && *(spec + 1) == ':')) { |
1138 | ✗ | if (ss->stream_list != STREAM_LIST_ALL) | |
1139 | ✗ | goto multiple_stream_lists; | |
1140 | |||
1141 | ✗ | ss->stream_list = STREAM_LIST_STREAM_ID; | |
1142 | |||
1143 | ✗ | spec += 1 + (*spec == 'i'); | |
1144 | ✗ | ss->list_id = strtol(spec, &endptr, 0); | |
1145 | ✗ | if (spec == endptr) { | |
1146 | ✗ | av_log(logctx, AV_LOG_ERROR, "Expected stream ID, got: %s\n", spec); | |
1147 | ✗ | ret = AVERROR(EINVAL); | |
1148 | ✗ | goto fail; | |
1149 | } | ||
1150 | ✗ | spec = endptr; | |
1151 | |||
1152 | ✗ | av_log(logctx, AV_LOG_TRACE, | |
1153 | "Parsed stream ID: %"PRId64"; remainder: %s\n", ss->list_id, spec); | ||
1154 | |||
1155 | // this terminates the specifier | ||
1156 | ✗ | break; | |
1157 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
13 | } else if (*spec == 'm' && *(spec + 1) == ':') { |
1158 | ✗ | av_assert0(!ss->meta_key && !ss->meta_val); | |
1159 | |||
1160 | ✗ | spec += 2; | |
1161 | ✗ | ss->meta_key = av_get_token(&spec, ":"); | |
1162 | ✗ | if (!ss->meta_key) { | |
1163 | ✗ | ret = AVERROR(ENOMEM); | |
1164 | ✗ | goto fail; | |
1165 | } | ||
1166 | ✗ | if (*spec == ':') { | |
1167 | ✗ | spec++; | |
1168 | ✗ | ss->meta_val = av_get_token(&spec, ":"); | |
1169 | ✗ | if (!ss->meta_val) { | |
1170 | ✗ | ret = AVERROR(ENOMEM); | |
1171 | ✗ | goto fail; | |
1172 | } | ||
1173 | } | ||
1174 | |||
1175 | ✗ | av_log(logctx, AV_LOG_TRACE, | |
1176 | "Parsed metadata: %s:%s; remainder: %s", ss->meta_key, | ||
1177 | ✗ | ss->meta_val ? ss->meta_val : "<any value>", spec); | |
1178 | |||
1179 | // this terminates the specifier | ||
1180 | ✗ | break; | |
1181 |
1/6✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
13 | } else if (*spec == 'u' && (*(spec + 1) == '\0' || *(spec + 1) == ':')) { |
1182 | ✗ | ss->usable_only = 1; | |
1183 | ✗ | spec++; | |
1184 | ✗ | av_log(logctx, AV_LOG_ERROR, "Parsed 'usable only'\n"); | |
1185 | |||
1186 | // this terminates the specifier | ||
1187 | ✗ | break; | |
1188 | } else | ||
1189 | break; | ||
1190 | |||
1191 |
2/2✓ Branch 0 taken 175 times.
✓ Branch 1 taken 16769 times.
|
16944 | if (*spec == ':') |
1192 | 175 | spec++; | |
1193 | } | ||
1194 | |||
1195 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 33726 times.
|
33739 | if (*spec) { |
1196 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | if (!allow_remainder) { |
1197 | ✗ | av_log(logctx, AV_LOG_ERROR, | |
1198 | "Trailing garbage at the end of a stream specifier: %s\n", | ||
1199 | spec); | ||
1200 | ✗ | ret = AVERROR(EINVAL); | |
1201 | ✗ | goto fail; | |
1202 | } | ||
1203 | |||
1204 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | if (*spec == ':') |
1205 | ✗ | spec++; | |
1206 | |||
1207 | 13 | ss->remainder = av_strdup(spec); | |
1208 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | if (!ss->remainder) { |
1209 | ✗ | ret = AVERROR(EINVAL); | |
1210 | ✗ | goto fail; | |
1211 | } | ||
1212 | } | ||
1213 | |||
1214 | 33739 | return 0; | |
1215 | |||
1216 | ✗ | multiple_stream_lists: | |
1217 | ✗ | av_log(logctx, AV_LOG_ERROR, | |
1218 | "Cannot combine multiple program/group designators in a " | ||
1219 | "single stream specifier"); | ||
1220 | ✗ | ret = AVERROR(EINVAL); | |
1221 | |||
1222 | ✗ | fail: | |
1223 | ✗ | stream_specifier_uninit(ss); | |
1224 | ✗ | return ret; | |
1225 | } | ||
1226 | |||
1227 | 35528 | unsigned stream_specifier_match(const StreamSpecifier *ss, | |
1228 | const AVFormatContext *s, const AVStream *st, | ||
1229 | void *logctx) | ||
1230 | { | ||
1231 | 35528 | const AVStreamGroup *g = NULL; | |
1232 | 35528 | const AVProgram *p = NULL; | |
1233 | 35528 | int start_stream = 0, nb_streams; | |
1234 | 35528 | int nb_matched = 0; | |
1235 | |||
1236 |
3/6✗ Branch 0 not taken.
✓ Branch 1 taken 35512 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
|
35528 | switch (ss->stream_list) { |
1237 | ✗ | case STREAM_LIST_STREAM_ID: | |
1238 | // <n-th> stream with given ID makes no sense and should be impossible to request | ||
1239 | ✗ | av_assert0(ss->idx < 0); | |
1240 | // return early if we know for sure the stream does not match | ||
1241 | ✗ | if (st->id != ss->list_id) | |
1242 | ✗ | return 0; | |
1243 | ✗ | start_stream = st->index; | |
1244 | ✗ | nb_streams = st->index + 1; | |
1245 | ✗ | break; | |
1246 | 35512 | case STREAM_LIST_ALL: | |
1247 |
2/2✓ Branch 0 taken 34832 times.
✓ Branch 1 taken 680 times.
|
35512 | start_stream = ss->idx >= 0 ? 0 : st->index; |
1248 | 35512 | nb_streams = st->index + 1; | |
1249 | 35512 | break; | |
1250 | ✗ | case STREAM_LIST_PROGRAM: | |
1251 | ✗ | for (unsigned i = 0; i < s->nb_programs; i++) { | |
1252 | ✗ | if (s->programs[i]->id == ss->list_id) { | |
1253 | ✗ | p = s->programs[i]; | |
1254 | ✗ | break; | |
1255 | } | ||
1256 | } | ||
1257 | ✗ | if (!p) { | |
1258 | ✗ | av_log(logctx, AV_LOG_WARNING, "No program with ID %"PRId64" exists," | |
1259 | ✗ | " stream specifier can never match\n", ss->list_id); | |
1260 | ✗ | return 0; | |
1261 | } | ||
1262 | ✗ | nb_streams = p->nb_stream_indexes; | |
1263 | ✗ | break; | |
1264 | 9 | case STREAM_LIST_GROUP_ID: | |
1265 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | for (unsigned i = 0; i < s->nb_stream_groups; i++) { |
1266 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
|
18 | if (ss->list_id == s->stream_groups[i]->id) { |
1267 | 9 | g = s->stream_groups[i]; | |
1268 | 9 | break; | |
1269 | } | ||
1270 | } | ||
1271 | // fall-through | ||
1272 | case STREAM_LIST_GROUP_IDX: | ||
1273 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 9 times.
|
16 | if (ss->stream_list == STREAM_LIST_GROUP_IDX && |
1274 |
2/4✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
7 | ss->list_id >= 0 && ss->list_id < s->nb_stream_groups) |
1275 | 7 | g = s->stream_groups[ss->list_id]; | |
1276 | |||
1277 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
|
16 | if (!g) { |
1278 | ✗ | av_log(logctx, AV_LOG_WARNING, "No stream group with group %s %" | |
1279 | PRId64" exists, stream specifier can never match\n", | ||
1280 | ✗ | ss->stream_list == STREAM_LIST_GROUP_ID ? "ID" : "index", | |
1281 | ✗ | ss->list_id); | |
1282 | ✗ | return 0; | |
1283 | } | ||
1284 | 16 | nb_streams = g->nb_streams; | |
1285 | 16 | break; | |
1286 | ✗ | default: av_assert0(0); | |
1287 | } | ||
1288 | |||
1289 |
2/2✓ Branch 0 taken 36991 times.
✓ Branch 1 taken 458 times.
|
37449 | for (int i = start_stream; i < nb_streams; i++) { |
1290 |
3/4✓ Branch 0 taken 35 times.
✓ Branch 1 taken 36956 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 36956 times.
|
36991 | const AVStream *candidate = s->streams[g ? g->streams[i]->index : |
1291 | ✗ | p ? p->stream_index[i] : i]; | |
1292 | |||
1293 |
2/2✓ Branch 0 taken 21240 times.
✓ Branch 1 taken 15751 times.
|
36991 | if (ss->media_type != AVMEDIA_TYPE_UNKNOWN && |
1294 |
2/2✓ Branch 0 taken 20548 times.
✓ Branch 1 taken 692 times.
|
21240 | (ss->media_type != candidate->codecpar->codec_type || |
1295 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 20548 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
20548 | (ss->no_apic && (candidate->disposition & AV_DISPOSITION_ATTACHED_PIC)))) |
1296 | 692 | continue; | |
1297 | |||
1298 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 36299 times.
|
36299 | if (ss->meta_key) { |
1299 | ✗ | const AVDictionaryEntry *tag = av_dict_get(candidate->metadata, | |
1300 | ✗ | ss->meta_key, NULL, 0); | |
1301 | |||
1302 | ✗ | if (!tag) | |
1303 | ✗ | continue; | |
1304 | ✗ | if (ss->meta_val && strcmp(tag->value, ss->meta_val)) | |
1305 | ✗ | continue; | |
1306 | } | ||
1307 | |||
1308 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 36299 times.
|
36299 | if (ss->usable_only) { |
1309 | ✗ | const AVCodecParameters *par = candidate->codecpar; | |
1310 | |||
1311 | ✗ | switch (par->codec_type) { | |
1312 | ✗ | case AVMEDIA_TYPE_AUDIO: | |
1313 | ✗ | if (!par->sample_rate || !par->ch_layout.nb_channels || | |
1314 | ✗ | par->format == AV_SAMPLE_FMT_NONE) | |
1315 | ✗ | continue; | |
1316 | ✗ | break; | |
1317 | ✗ | case AVMEDIA_TYPE_VIDEO: | |
1318 | ✗ | if (!par->width || !par->height || par->format == AV_PIX_FMT_NONE) | |
1319 | ✗ | continue; | |
1320 | ✗ | break; | |
1321 | ✗ | case AVMEDIA_TYPE_UNKNOWN: | |
1322 | ✗ | continue; | |
1323 | } | ||
1324 | } | ||
1325 | |||
1326 |
2/2✓ Branch 0 taken 55 times.
✓ Branch 1 taken 36244 times.
|
36299 | if (ss->disposition && |
1327 |
2/2✓ Branch 0 taken 44 times.
✓ Branch 1 taken 11 times.
|
55 | (candidate->disposition & ss->disposition) != ss->disposition) |
1328 | 44 | continue; | |
1329 | |||
1330 |
2/2✓ Branch 0 taken 35070 times.
✓ Branch 1 taken 1185 times.
|
36255 | if (st == candidate) |
1331 |
4/4✓ Branch 0 taken 589 times.
✓ Branch 1 taken 34481 times.
✓ Branch 2 taken 181 times.
✓ Branch 3 taken 408 times.
|
35070 | return ss->idx < 0 || ss->idx == nb_matched; |
1332 | |||
1333 | 1185 | nb_matched++; | |
1334 | } | ||
1335 | |||
1336 | 458 | return 0; | |
1337 | } | ||
1338 | |||
1339 | 517 | int check_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec) | |
1340 | { | ||
1341 | StreamSpecifier ss; | ||
1342 | int ret; | ||
1343 | |||
1344 | 517 | ret = stream_specifier_parse(&ss, spec, 0, NULL); | |
1345 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 517 times.
|
517 | if (ret < 0) |
1346 | ✗ | return ret; | |
1347 | |||
1348 | 517 | ret = stream_specifier_match(&ss, s, st, NULL); | |
1349 | 517 | stream_specifier_uninit(&ss); | |
1350 | 517 | return ret; | |
1351 | } | ||
1352 | |||
1353 | 24991 | int filter_codec_opts(const AVDictionary *opts, enum AVCodecID codec_id, | |
1354 | AVFormatContext *s, AVStream *st, const AVCodec *codec, | ||
1355 | AVDictionary **dst, AVDictionary **opts_used) | ||
1356 | { | ||
1357 | 24991 | AVDictionary *ret = NULL; | |
1358 | 24991 | const AVDictionaryEntry *t = NULL; | |
1359 | 49982 | int flags = s->oformat ? AV_OPT_FLAG_ENCODING_PARAM | |
1360 |
2/2✓ Branch 0 taken 8851 times.
✓ Branch 1 taken 16140 times.
|
24991 | : AV_OPT_FLAG_DECODING_PARAM; |
1361 | 24991 | char prefix = 0; | |
1362 | 24991 | const AVClass *cc = avcodec_get_class(); | |
1363 | |||
1364 |
4/4✓ Branch 0 taken 19456 times.
✓ Branch 1 taken 5210 times.
✓ Branch 2 taken 240 times.
✓ Branch 3 taken 85 times.
|
24991 | switch (st->codecpar->codec_type) { |
1365 | 19456 | case AVMEDIA_TYPE_VIDEO: | |
1366 | 19456 | prefix = 'v'; | |
1367 | 19456 | flags |= AV_OPT_FLAG_VIDEO_PARAM; | |
1368 | 19456 | break; | |
1369 | 5210 | case AVMEDIA_TYPE_AUDIO: | |
1370 | 5210 | prefix = 'a'; | |
1371 | 5210 | flags |= AV_OPT_FLAG_AUDIO_PARAM; | |
1372 | 5210 | break; | |
1373 | 240 | case AVMEDIA_TYPE_SUBTITLE: | |
1374 | 240 | prefix = 's'; | |
1375 | 240 | flags |= AV_OPT_FLAG_SUBTITLE_PARAM; | |
1376 | 240 | break; | |
1377 | } | ||
1378 | |||
1379 |
2/2✓ Branch 1 taken 77004 times.
✓ Branch 2 taken 24991 times.
|
101995 | while (t = av_dict_iterate(opts, t)) { |
1380 | const AVClass *priv_class; | ||
1381 | 77004 | char *p = strchr(t->key, ':'); | |
1382 | 77004 | int used = 0; | |
1383 | |||
1384 | /* check stream specification in opt name */ | ||
1385 |
2/2✓ Branch 0 taken 287 times.
✓ Branch 1 taken 76717 times.
|
77004 | if (p) { |
1386 | 287 | int err = check_stream_specifier(s, st, p + 1); | |
1387 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 287 times.
|
287 | if (err < 0) { |
1388 | ✗ | av_dict_free(&ret); | |
1389 | ✗ | return err; | |
1390 |
2/2✓ Branch 0 taken 78 times.
✓ Branch 1 taken 209 times.
|
287 | } else if (!err) |
1391 | 78 | continue; | |
1392 | |||
1393 | 209 | *p = 0; | |
1394 | } | ||
1395 | |||
1396 |
4/4✓ Branch 1 taken 2828 times.
✓ Branch 2 taken 74098 times.
✓ Branch 3 taken 1634 times.
✓ Branch 4 taken 1194 times.
|
76926 | if (av_opt_find(&cc, t->key, NULL, flags, AV_OPT_SEARCH_FAKE_OBJ) || |
1397 | 1634 | !codec || | |
1398 |
4/4✓ Branch 0 taken 765 times.
✓ Branch 1 taken 869 times.
✓ Branch 2 taken 346 times.
✓ Branch 3 taken 419 times.
|
2399 | ((priv_class = codec->priv_class) && |
1399 | 765 | av_opt_find(&priv_class, t->key, NULL, flags, | |
1400 | AV_OPT_SEARCH_FAKE_OBJ))) { | ||
1401 | 75638 | av_dict_set(&ret, t->key, t->value, 0); | |
1402 | 75638 | used = 1; | |
1403 |
4/4✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1285 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
|
1291 | } else if (t->key[0] == prefix && |
1404 | 3 | av_opt_find(&cc, t->key + 1, NULL, flags, | |
1405 | AV_OPT_SEARCH_FAKE_OBJ)) { | ||
1406 | 1 | av_dict_set(&ret, t->key + 1, t->value, 0); | |
1407 | 1 | used = 1; | |
1408 | } | ||
1409 | |||
1410 |
2/2✓ Branch 0 taken 209 times.
✓ Branch 1 taken 76717 times.
|
76926 | if (p) |
1411 | 209 | *p = ':'; | |
1412 | |||
1413 |
4/4✓ Branch 0 taken 75639 times.
✓ Branch 1 taken 1287 times.
✓ Branch 2 taken 50116 times.
✓ Branch 3 taken 25523 times.
|
76926 | if (used && opts_used) |
1414 | 50116 | av_dict_set(opts_used, t->key, "", 0); | |
1415 | } | ||
1416 | |||
1417 | 24991 | *dst = ret; | |
1418 | 24991 | return 0; | |
1419 | } | ||
1420 | |||
1421 | 7472 | int setup_find_stream_info_opts(AVFormatContext *s, | |
1422 | AVDictionary *local_codec_opts, | ||
1423 | AVDictionary ***dst) | ||
1424 | { | ||
1425 | int ret; | ||
1426 | AVDictionary **opts; | ||
1427 | |||
1428 | 7472 | *dst = NULL; | |
1429 | |||
1430 |
2/2✓ Branch 0 taken 90 times.
✓ Branch 1 taken 7382 times.
|
7472 | if (!s->nb_streams) |
1431 | 90 | return 0; | |
1432 | |||
1433 | 7382 | opts = av_calloc(s->nb_streams, sizeof(*opts)); | |
1434 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7382 times.
|
7382 | if (!opts) |
1435 | ✗ | return AVERROR(ENOMEM); | |
1436 | |||
1437 |
2/2✓ Branch 0 taken 8029 times.
✓ Branch 1 taken 7382 times.
|
15411 | for (int i = 0; i < s->nb_streams; i++) { |
1438 | 8029 | ret = filter_codec_opts(local_codec_opts, s->streams[i]->codecpar->codec_id, | |
1439 | 8029 | s, s->streams[i], NULL, &opts[i], NULL); | |
1440 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8029 times.
|
8029 | if (ret < 0) |
1441 | ✗ | goto fail; | |
1442 | } | ||
1443 | 7382 | *dst = opts; | |
1444 | 7382 | return 0; | |
1445 | ✗ | fail: | |
1446 | ✗ | for (int i = 0; i < s->nb_streams; i++) | |
1447 | ✗ | av_dict_free(&opts[i]); | |
1448 | ✗ | av_freep(&opts); | |
1449 | ✗ | return ret; | |
1450 | } | ||
1451 | |||
1452 | 253309 | int grow_array(void **array, int elem_size, int *size, int new_size) | |
1453 | { | ||
1454 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 253309 times.
|
253309 | if (new_size >= INT_MAX / elem_size) { |
1455 | ✗ | av_log(NULL, AV_LOG_ERROR, "Array too big.\n"); | |
1456 | ✗ | return AVERROR(ERANGE); | |
1457 | } | ||
1458 |
1/2✓ Branch 0 taken 253309 times.
✗ Branch 1 not taken.
|
253309 | if (*size < new_size) { |
1459 | 253309 | uint8_t *tmp = av_realloc_array(*array, new_size, elem_size); | |
1460 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 253309 times.
|
253309 | if (!tmp) |
1461 | ✗ | return AVERROR(ENOMEM); | |
1462 | 253309 | memset(tmp + *size*elem_size, 0, (new_size-*size) * elem_size); | |
1463 | 253309 | *size = new_size; | |
1464 | 253309 | *array = tmp; | |
1465 | 253309 | return 0; | |
1466 | } | ||
1467 | ✗ | return 0; | |
1468 | } | ||
1469 | |||
1470 | 47446 | void *allocate_array_elem(void *ptr, size_t elem_size, int *nb_elems) | |
1471 | { | ||
1472 | void *new_elem; | ||
1473 | |||
1474 |
2/4✓ Branch 1 taken 47446 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 47446 times.
|
94892 | if (!(new_elem = av_mallocz(elem_size)) || |
1475 | 47446 | av_dynarray_add_nofree(ptr, nb_elems, new_elem) < 0) | |
1476 | ✗ | return NULL; | |
1477 | 47446 | return new_elem; | |
1478 | } | ||
1479 | |||
1480 | 5705 | double get_rotation(const int32_t *displaymatrix) | |
1481 | { | ||
1482 | 5705 | double theta = 0; | |
1483 |
1/2✓ Branch 0 taken 5705 times.
✗ Branch 1 not taken.
|
5705 | if (displaymatrix) |
1484 | 5705 | theta = -round(av_display_rotation_get(displaymatrix)); | |
1485 | |||
1486 | 5705 | theta -= 360*floor(theta/360 + 0.9/360); | |
1487 | |||
1488 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5705 times.
|
5705 | if (fabs(theta - 90*round(theta/90)) > 2) |
1489 | ✗ | av_log(NULL, AV_LOG_WARNING, "Odd rotation angle.\n" | |
1490 | "If you want to help, upload a sample " | ||
1491 | "of this file to https://streams.videolan.org/upload/ " | ||
1492 | "and contact the ffmpeg-devel mailing list. (ffmpeg-devel@ffmpeg.org)"); | ||
1493 | |||
1494 | 5705 | return theta; | |
1495 | } | ||
1496 | |||
1497 | /* read file contents into a string */ | ||
1498 | 71 | char *file_read(const char *filename) | |
1499 | { | ||
1500 | 71 | AVIOContext *pb = NULL; | |
1501 | 71 | int ret = avio_open(&pb, filename, AVIO_FLAG_READ); | |
1502 | AVBPrint bprint; | ||
1503 | char *str; | ||
1504 | |||
1505 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
|
71 | if (ret < 0) { |
1506 | ✗ | av_log(NULL, AV_LOG_ERROR, "Error opening file %s.\n", filename); | |
1507 | ✗ | return NULL; | |
1508 | } | ||
1509 | |||
1510 | 71 | av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED); | |
1511 | 71 | ret = avio_read_to_bprint(pb, &bprint, SIZE_MAX); | |
1512 | 71 | avio_closep(&pb); | |
1513 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
|
71 | if (ret < 0) { |
1514 | ✗ | av_bprint_finalize(&bprint, NULL); | |
1515 | ✗ | return NULL; | |
1516 | } | ||
1517 | 71 | ret = av_bprint_finalize(&bprint, &str); | |
1518 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
|
71 | if (ret < 0) |
1519 | ✗ | return NULL; | |
1520 | 71 | return str; | |
1521 | } | ||
1522 | |||
1523 | 7314 | void remove_avoptions(AVDictionary **a, AVDictionary *b) | |
1524 | { | ||
1525 | 7314 | const AVDictionaryEntry *t = NULL; | |
1526 | |||
1527 |
2/2✓ Branch 1 taken 24298 times.
✓ Branch 2 taken 7314 times.
|
31612 | while ((t = av_dict_iterate(b, t))) { |
1528 | 24298 | av_dict_set(a, t->key, NULL, AV_DICT_MATCH_CASE); | |
1529 | } | ||
1530 | 7314 | } | |
1531 | |||
1532 | 22359 | int check_avoptions(AVDictionary *m) | |
1533 | { | ||
1534 | 22359 | const AVDictionaryEntry *t = av_dict_iterate(m, NULL); | |
1535 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 22359 times.
|
22359 | if (t) { |
1536 | ✗ | av_log(NULL, AV_LOG_FATAL, "Option %s not found.\n", t->key); | |
1537 | ✗ | return AVERROR_OPTION_NOT_FOUND; | |
1538 | } | ||
1539 | |||
1540 | 22359 | return 0; | |
1541 | } | ||
1542 |