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 | 13669 | void uninit_opts(void) | |
63 | { | ||
64 | 13669 | av_dict_free(&swr_opts); | |
65 | 13669 | av_dict_free(&sws_dict); | |
66 | 13669 | av_dict_free(&format_opts); | |
67 | 13669 | av_dict_free(&codec_opts); | |
68 | 13669 | } | |
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 | 6909 | 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 | 6909 | } | |
83 | |||
84 | 31565 | 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 | 31565 | double d = av_strtod(numstr, &tail); | |
90 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 31565 times.
|
31565 | if (*tail) |
91 | ✗ | error = "Expected number for %s but found: %s\n"; | |
92 |
2/4✓ Branch 0 taken 31565 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 31565 times.
|
31565 | 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 31273 times.
✓ Branch 1 taken 292 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 31273 times.
|
31565 | 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 31565 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
31565 | else if (type == OPT_TYPE_INT && (int)d != d) |
97 | ✗ | error = "Expected int for %s but found %s\n"; | |
98 | else { | ||
99 | 31565 | *dst = d; | |
100 | 31565 | 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 | 1032673 | static const OptionDef *find_option(const OptionDef *po, const char *name) | |
154 | { | ||
155 |
2/2✓ Branch 0 taken 318 times.
✓ Branch 1 taken 1032355 times.
|
1032673 | if (*name == '/') |
156 | 318 | name++; | |
157 | |||
158 |
2/2✓ Branch 0 taken 147698533 times.
✓ Branch 1 taken 586636 times.
|
148285169 | while (po->name) { |
159 | const char *end; | ||
160 |
6/6✓ Branch 1 taken 1046913 times.
✓ Branch 2 taken 146651620 times.
✓ Branch 3 taken 647427 times.
✓ Branch 4 taken 399486 times.
✓ Branch 5 taken 600876 times.
✓ Branch 6 taken 46551 times.
|
147698533 | if (av_strstart(name, po->name, &end) && (!*end || *end == ':')) |
161 | break; | ||
162 | 147252496 | po++; | |
163 | } | ||
164 | 1032673 | 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 | 6909 | static inline void prepare_app_arguments(int *argc_ptr, char ***argv_ptr) | |
226 | { | ||
227 | /* nothing to do */ | ||
228 | 6909 | } | |
229 | #endif /* HAVE_COMMANDLINETOARGVW */ | ||
230 | |||
231 | 432430 | static int opt_has_arg(const OptionDef *o) | |
232 | { | ||
233 |
2/2✓ Branch 0 taken 137967 times.
✓ Branch 1 taken 294463 times.
|
432430 | if (o->type == OPT_TYPE_BOOL) |
234 | 137967 | return 0; | |
235 |
2/2✓ Branch 0 taken 98851 times.
✓ Branch 1 taken 195612 times.
|
294463 | if (o->type == OPT_TYPE_FUNC) |
236 | 98851 | return !!(o->flags & OPT_FUNC_ARG); | |
237 | 195612 | return 1; | |
238 | } | ||
239 | |||
240 | 81037 | 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 | 162074 | void *dst = po->flags & OPT_FLAG_OFFSET ? | |
246 |
2/2✓ Branch 0 taken 40344 times.
✓ Branch 1 taken 40693 times.
|
81037 | (uint8_t *)optctx + po->u.off : po->u.dst_ptr; |
247 | 81037 | char *arg_allocated = NULL; | |
248 | |||
249 | 81037 | SpecifierOptList *sol = NULL; | |
250 | double num; | ||
251 | 81037 | int ret = 0; | |
252 | |||
253 |
2/2✓ Branch 0 taken 53 times.
✓ Branch 1 taken 80984 times.
|
81037 | if (*opt == '/') { |
254 | 53 | opt++; | |
255 | |||
256 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
|
53 | if (po->type == OPT_TYPE_BOOL) { |
257 | ✗ | av_log(NULL, AV_LOG_FATAL, | |
258 | "Requested to load an argument from file for a bool option '%s'\n", | ||
259 | ✗ | po->name); | |
260 | ✗ | return AVERROR(EINVAL); | |
261 | } | ||
262 | |||
263 | 53 | arg_allocated = file_read(arg); | |
264 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
|
53 | if (!arg_allocated) { |
265 | ✗ | av_log(NULL, AV_LOG_FATAL, | |
266 | "Error reading the value for option '%s' from file: %s\n", | ||
267 | opt, arg); | ||
268 | ✗ | return AVERROR(EINVAL); | |
269 | } | ||
270 | |||
271 | 53 | arg = arg_allocated; | |
272 | } | ||
273 | |||
274 |
2/2✓ Branch 0 taken 27997 times.
✓ Branch 1 taken 53040 times.
|
81037 | if (po->flags & OPT_FLAG_SPEC) { |
275 | 27997 | char *p = strchr(opt, ':'); | |
276 | char *str; | ||
277 | |||
278 | 27997 | sol = dst; | |
279 | 27997 | ret = GROW_ARRAY(sol->opt, sol->nb_opt); | |
280 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 27997 times.
|
27997 | if (ret < 0) |
281 | ✗ | goto finish; | |
282 | |||
283 |
2/2✓ Branch 0 taken 14639 times.
✓ Branch 1 taken 13358 times.
|
27997 | str = av_strdup(p ? p + 1 : ""); |
284 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 27997 times.
|
27997 | if (!str) { |
285 | ✗ | ret = AVERROR(ENOMEM); | |
286 | ✗ | goto finish; | |
287 | } | ||
288 | 27997 | sol->opt[sol->nb_opt - 1].specifier = str; | |
289 | 27997 | dst = &sol->opt[sol->nb_opt - 1].u; | |
290 | } | ||
291 | |||
292 |
2/2✓ Branch 0 taken 32817 times.
✓ Branch 1 taken 48220 times.
|
81037 | if (po->type == OPT_TYPE_STRING) { |
293 | char *str; | ||
294 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 32797 times.
|
32817 | if (arg_allocated) { |
295 | 20 | str = arg_allocated; | |
296 | 20 | arg_allocated = NULL; | |
297 | } else | ||
298 | 32797 | str = av_strdup(arg); | |
299 | 32817 | av_freep(dst); | |
300 | |||
301 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32817 times.
|
32817 | if (!str) { |
302 | ✗ | ret = AVERROR(ENOMEM); | |
303 | ✗ | goto finish; | |
304 | } | ||
305 | |||
306 | 32817 | *(char **)dst = str; | |
307 |
4/4✓ Branch 0 taken 21877 times.
✓ Branch 1 taken 26343 times.
✓ Branch 2 taken 128 times.
✓ Branch 3 taken 21749 times.
|
48220 | } else if (po->type == OPT_TYPE_BOOL || po->type == OPT_TYPE_INT) { |
308 | 26471 | ret = parse_number(opt, arg, OPT_TYPE_INT64, INT_MIN, INT_MAX, &num); | |
309 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 26471 times.
|
26471 | if (ret < 0) |
310 | ✗ | goto finish; | |
311 | |||
312 | 26471 | *(int *)dst = num; | |
313 |
2/2✓ Branch 0 taken 4802 times.
✓ Branch 1 taken 16947 times.
|
21749 | } else if (po->type == OPT_TYPE_INT64) { |
314 | 4802 | ret = parse_number(opt, arg, OPT_TYPE_INT64, INT64_MIN, (double)INT64_MAX, &num); | |
315 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4802 times.
|
4802 | if (ret < 0) |
316 | ✗ | goto finish; | |
317 | |||
318 | 4802 | *(int64_t *)dst = num; | |
319 |
2/2✓ Branch 0 taken 215 times.
✓ Branch 1 taken 16732 times.
|
16947 | } else if (po->type == OPT_TYPE_TIME) { |
320 | 215 | ret = av_parse_time(dst, arg, 1); | |
321 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 215 times.
|
215 | if (ret < 0) { |
322 | ✗ | av_log(NULL, AV_LOG_ERROR, "Invalid duration for option %s: %s\n", | |
323 | opt, arg); | ||
324 | ✗ | goto finish; | |
325 | } | ||
326 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 16729 times.
|
16732 | } else if (po->type == OPT_TYPE_FLOAT) { |
327 | 3 | ret = parse_number(opt, arg, OPT_TYPE_FLOAT, -INFINITY, INFINITY, &num); | |
328 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (ret < 0) |
329 | ✗ | goto finish; | |
330 | |||
331 | 3 | *(float *)dst = num; | |
332 |
2/2✓ Branch 0 taken 289 times.
✓ Branch 1 taken 16440 times.
|
16729 | } else if (po->type == OPT_TYPE_DOUBLE) { |
333 | 289 | ret = parse_number(opt, arg, OPT_TYPE_DOUBLE, -INFINITY, INFINITY, &num); | |
334 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 289 times.
|
289 | if (ret < 0) |
335 | ✗ | goto finish; | |
336 | |||
337 | 289 | *(double *)dst = num; | |
338 | } else { | ||
339 |
2/4✓ Branch 0 taken 16440 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 16440 times.
|
16440 | av_assert0(po->type == OPT_TYPE_FUNC && po->u.func_arg); |
340 | |||
341 | 16440 | ret = po->u.func_arg(optctx, opt, arg); | |
342 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16440 times.
|
16440 | if (ret < 0) { |
343 | ✗ | av_log(NULL, AV_LOG_ERROR, | |
344 | "Failed to set value '%s' for option '%s': %s\n", | ||
345 | ✗ | arg, opt, av_err2str(ret)); | |
346 | ✗ | goto finish; | |
347 | } | ||
348 | } | ||
349 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 81036 times.
|
81037 | if (po->flags & OPT_EXIT) { |
350 | 1 | ret = AVERROR_EXIT; | |
351 | 1 | goto finish; | |
352 | } | ||
353 | |||
354 |
2/2✓ Branch 0 taken 53039 times.
✓ Branch 1 taken 27997 times.
|
81036 | if (sol) { |
355 | 27997 | sol->type = po->type; | |
356 |
2/2✓ Branch 0 taken 2393 times.
✓ Branch 1 taken 25604 times.
|
30390 | sol->opt_canon = (po->flags & OPT_HAS_CANON) ? |
357 | 2393 | find_option(defs, po->u1.name_canon) : po; | |
358 | } | ||
359 | |||
360 | 53039 | finish: | |
361 | 81037 | av_freep(&arg_allocated); | |
362 | 81037 | return ret; | |
363 | } | ||
364 | |||
365 | 9023 | int parse_option(void *optctx, const char *opt, const char *arg, | |
366 | const OptionDef *options) | ||
367 | { | ||
368 | static const OptionDef opt_avoptions = { | ||
369 | .name = "AVOption passthrough", | ||
370 | .type = OPT_TYPE_FUNC, | ||
371 | .flags = OPT_FUNC_ARG, | ||
372 | .u.func_arg = opt_default, | ||
373 | }; | ||
374 | |||
375 | const OptionDef *po; | ||
376 | int ret; | ||
377 | |||
378 | 9023 | po = find_option(options, opt); | |
379 |
5/6✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9014 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
9023 | if (!po->name && opt[0] == 'n' && opt[1] == 'o') { |
380 | /* handle 'no' bool option */ | ||
381 | 1 | po = find_option(options, opt + 2); | |
382 |
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)) |
383 | 1 | arg = "0"; | |
384 |
2/2✓ Branch 0 taken 141 times.
✓ Branch 1 taken 8881 times.
|
9022 | } else if (po->type == OPT_TYPE_BOOL) |
385 | 141 | arg = "1"; | |
386 | |||
387 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 9015 times.
|
9023 | if (!po->name) |
388 | 8 | po = &opt_avoptions; | |
389 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9023 times.
|
9023 | if (!po->name) { |
390 | ✗ | av_log(NULL, AV_LOG_ERROR, "Unrecognized option '%s'\n", opt); | |
391 | ✗ | return AVERROR(EINVAL); | |
392 | } | ||
393 |
3/4✓ Branch 1 taken 8776 times.
✓ Branch 2 taken 247 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8776 times.
|
9023 | if (opt_has_arg(po) && !arg) { |
394 | ✗ | av_log(NULL, AV_LOG_ERROR, "Missing argument for option '%s'\n", opt); | |
395 | ✗ | return AVERROR(EINVAL); | |
396 | } | ||
397 | |||
398 | 9023 | ret = write_option(optctx, po, opt, arg, options); | |
399 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9023 times.
|
9023 | if (ret < 0) |
400 | ✗ | return ret; | |
401 | |||
402 | 9023 | return opt_has_arg(po); | |
403 | } | ||
404 | |||
405 | 149 | int parse_options(void *optctx, int argc, char **argv, const OptionDef *options, | |
406 | int (*parse_arg_function)(void *, const char*)) | ||
407 | { | ||
408 | const char *opt; | ||
409 | 149 | int optindex, handleoptions = 1, ret; | |
410 | |||
411 | /* perform system-dependent conversions for arguments list */ | ||
412 | 149 | prepare_app_arguments(&argc, &argv); | |
413 | |||
414 | /* parse options */ | ||
415 | 149 | optindex = 1; | |
416 |
2/2✓ Branch 0 taken 661 times.
✓ Branch 1 taken 149 times.
|
810 | while (optindex < argc) { |
417 | 661 | opt = argv[optindex++]; | |
418 | |||
419 |
4/6✓ Branch 0 taken 661 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 522 times.
✓ Branch 3 taken 139 times.
✓ Branch 4 taken 522 times.
✗ Branch 5 not taken.
|
661 | if (handleoptions && opt[0] == '-' && opt[1] != '\0') { |
420 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 522 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
522 | if (opt[1] == '-' && opt[2] == '\0') { |
421 | ✗ | handleoptions = 0; | |
422 | ✗ | continue; | |
423 | } | ||
424 | 522 | opt++; | |
425 | |||
426 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 522 times.
|
522 | if ((ret = parse_option(optctx, opt, argv[optindex], options)) < 0) |
427 | ✗ | return ret; | |
428 | 522 | optindex += ret; | |
429 | } else { | ||
430 |
1/2✓ Branch 0 taken 139 times.
✗ Branch 1 not taken.
|
139 | if (parse_arg_function) { |
431 | 139 | ret = parse_arg_function(optctx, opt); | |
432 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 139 times.
|
139 | if (ret < 0) |
433 | ✗ | return ret; | |
434 | } | ||
435 | } | ||
436 | } | ||
437 | |||
438 | 149 | return 0; | |
439 | } | ||
440 | |||
441 | 20312 | int parse_optgroup(void *optctx, OptionGroup *g, const OptionDef *defs) | |
442 | { | ||
443 | int i, ret; | ||
444 | |||
445 | 20312 | av_log(NULL, AV_LOG_DEBUG, "Parsing a group of options: %s %s.\n", | |
446 | 20312 | g->group_def->name, g->arg); | |
447 | |||
448 |
2/2✓ Branch 0 taken 72014 times.
✓ Branch 1 taken 20311 times.
|
92325 | for (i = 0; i < g->nb_opts; i++) { |
449 | 72014 | Option *o = &g->opts[i]; | |
450 | |||
451 |
2/2✓ Branch 0 taken 40834 times.
✓ Branch 1 taken 31180 times.
|
72014 | if (g->group_def->flags && |
452 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 40834 times.
|
40834 | !(g->group_def->flags & o->opt->flags)) { |
453 | ✗ | av_log(NULL, AV_LOG_ERROR, "Option %s (%s) cannot be applied to " | |
454 | "%s %s -- you are trying to apply an input option to an " | ||
455 | "output file or vice versa. Move this option before the " | ||
456 | ✗ | "file it belongs to.\n", o->key, o->opt->help, | |
457 | ✗ | g->group_def->name, g->arg); | |
458 | ✗ | return AVERROR(EINVAL); | |
459 | } | ||
460 | |||
461 | 72014 | av_log(NULL, AV_LOG_DEBUG, "Applying option %s (%s) with argument %s.\n", | |
462 | 72014 | o->key, o->opt->help, o->val); | |
463 | |||
464 | 72014 | ret = write_option(optctx, o->opt, o->key, o->val, defs); | |
465 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 72013 times.
|
72014 | if (ret < 0) |
466 | 1 | return ret; | |
467 | } | ||
468 | |||
469 | 20311 | av_log(NULL, AV_LOG_DEBUG, "Successfully parsed a group of options.\n"); | |
470 | |||
471 | 20311 | return 0; | |
472 | } | ||
473 | |||
474 | 34545 | int locate_option(int argc, char **argv, const OptionDef *options, | |
475 | const char *optname) | ||
476 | { | ||
477 | const OptionDef *po; | ||
478 | int i; | ||
479 | |||
480 |
2/2✓ Branch 0 taken 779664 times.
✓ Branch 1 taken 34529 times.
|
814193 | for (i = 1; i < argc; i++) { |
481 | 779664 | const char *cur_opt = argv[i]; | |
482 | |||
483 |
2/2✓ Branch 0 taken 21547 times.
✓ Branch 1 taken 758117 times.
|
779664 | if (*cur_opt++ != '-') |
484 | 21547 | continue; | |
485 | |||
486 | 758117 | po = find_option(options, cur_opt); | |
487 |
5/6✓ Branch 0 taken 496647 times.
✓ Branch 1 taken 261470 times.
✓ Branch 2 taken 101185 times.
✓ Branch 3 taken 395462 times.
✓ Branch 4 taken 101185 times.
✗ Branch 5 not taken.
|
758117 | if (!po->name && cur_opt[0] == 'n' && cur_opt[1] == 'o') |
488 | 101185 | po = find_option(options, cur_opt + 2); | |
489 | |||
490 |
3/4✓ Branch 0 taken 395502 times.
✓ Branch 1 taken 362615 times.
✓ Branch 2 taken 395502 times.
✗ Branch 3 not taken.
|
758117 | if ((!po->name && !strcmp(cur_opt, optname)) || |
491 |
4/4✓ Branch 0 taken 362615 times.
✓ Branch 1 taken 395502 times.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 362599 times.
|
758117 | (po->name && !strcmp(optname, po->name))) |
492 | 16 | return i; | |
493 | |||
494 |
4/4✓ Branch 0 taken 362599 times.
✓ Branch 1 taken 395502 times.
✓ Branch 3 taken 230359 times.
✓ Branch 4 taken 132240 times.
|
758101 | if (!po->name || opt_has_arg(po)) |
495 | 625861 | i++; | |
496 | } | ||
497 | 34529 | return 0; | |
498 | } | ||
499 | |||
500 | ✗ | static void dump_argument(FILE *report_file, const char *a) | |
501 | { | ||
502 | const unsigned char *p; | ||
503 | |||
504 | ✗ | for (p = a; *p; p++) | |
505 | ✗ | if (!((*p >= '+' && *p <= ':') || (*p >= '@' && *p <= 'Z') || | |
506 | ✗ | *p == '_' || (*p >= 'a' && *p <= 'z'))) | |
507 | break; | ||
508 | ✗ | if (!*p) { | |
509 | ✗ | fputs(a, report_file); | |
510 | ✗ | return; | |
511 | } | ||
512 | ✗ | fputc('"', report_file); | |
513 | ✗ | for (p = a; *p; p++) { | |
514 | ✗ | if (*p == '\\' || *p == '"' || *p == '$' || *p == '`') | |
515 | ✗ | fprintf(report_file, "\\%c", *p); | |
516 | ✗ | else if (*p < ' ' || *p > '~') | |
517 | ✗ | fprintf(report_file, "\\x%02x", *p); | |
518 | else | ||
519 | ✗ | fputc(*p, report_file); | |
520 | } | ||
521 | ✗ | fputc('"', report_file); | |
522 | } | ||
523 | |||
524 | 6909 | static void check_options(const OptionDef *po) | |
525 | { | ||
526 |
2/2✓ Branch 0 taken 1287921 times.
✓ Branch 1 taken 6909 times.
|
1294830 | while (po->name) { |
527 |
2/2✓ Branch 0 taken 790920 times.
✓ Branch 1 taken 497001 times.
|
1287921 | if (po->flags & OPT_PERFILE) |
528 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 790920 times.
|
790920 | av_assert0(po->flags & (OPT_INPUT | OPT_OUTPUT | OPT_DECODER)); |
529 | |||
530 |
2/2✓ Branch 0 taken 514599 times.
✓ Branch 1 taken 773322 times.
|
1287921 | if (po->type == OPT_TYPE_FUNC) |
531 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 514599 times.
|
514599 | av_assert0(!(po->flags & (OPT_FLAG_OFFSET | OPT_FLAG_SPEC))); |
532 | |||
533 | // OPT_FUNC_ARG can only be ser for OPT_TYPE_FUNC | ||
534 |
3/4✓ Branch 0 taken 773322 times.
✓ Branch 1 taken 514599 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 773322 times.
|
1287921 | av_assert0((po->type == OPT_TYPE_FUNC) || !(po->flags & OPT_FUNC_ARG)); |
535 | |||
536 | 1287921 | po++; | |
537 | } | ||
538 | 6909 | } | |
539 | |||
540 | 6909 | void parse_loglevel(int argc, char **argv, const OptionDef *options) | |
541 | { | ||
542 | 6909 | int idx = locate_option(argc, argv, options, "loglevel"); | |
543 | char *env; | ||
544 | |||
545 | 6909 | check_options(options); | |
546 | |||
547 |
1/2✓ Branch 0 taken 6909 times.
✗ Branch 1 not taken.
|
6909 | if (!idx) |
548 | 6909 | idx = locate_option(argc, argv, options, "v"); | |
549 |
3/4✓ Branch 0 taken 16 times.
✓ Branch 1 taken 6893 times.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
|
6909 | if (idx && argv[idx + 1]) |
550 | 16 | opt_loglevel(NULL, "loglevel", argv[idx + 1]); | |
551 | 6909 | idx = locate_option(argc, argv, options, "report"); | |
552 | 6909 | env = getenv_utf8("FFREPORT"); | |
553 |
2/4✓ Branch 0 taken 6909 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6909 times.
|
6909 | if (env || idx) { |
554 | ✗ | FILE *report_file = NULL; | |
555 | ✗ | init_report(env, &report_file); | |
556 | ✗ | if (report_file) { | |
557 | int i; | ||
558 | ✗ | fprintf(report_file, "Command line:\n"); | |
559 | ✗ | for (i = 0; i < argc; i++) { | |
560 | ✗ | dump_argument(report_file, argv[i]); | |
561 | ✗ | fputc(i < argc - 1 ? ' ' : '\n', report_file); | |
562 | } | ||
563 | ✗ | fflush(report_file); | |
564 | } | ||
565 | } | ||
566 | 6909 | freeenv_utf8(env); | |
567 | 6909 | idx = locate_option(argc, argv, options, "hide_banner"); | |
568 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6909 times.
|
6909 | if (idx) |
569 | ✗ | hide_banner = 1; | |
570 | 6909 | } | |
571 | |||
572 | 244493 | static const AVOption *opt_find(void *obj, const char *name, const char *unit, | |
573 | int opt_flags, int search_flags) | ||
574 | { | ||
575 | 244493 | const AVOption *o = av_opt_find(obj, name, unit, opt_flags, search_flags); | |
576 |
4/4✓ Branch 0 taken 69819 times.
✓ Branch 1 taken 174674 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 69817 times.
|
244493 | if(o && !o->flags) |
577 | 2 | return NULL; | |
578 | 244491 | return o; | |
579 | } | ||
580 | |||
581 | #define FLAGS (o->type == AV_OPT_TYPE_FLAGS && (arg[0]=='-' || arg[0]=='+')) ? AV_DICT_APPEND : 0 | ||
582 | 89948 | int opt_default(void *optctx, const char *opt, const char *arg) | |
583 | { | ||
584 | const AVOption *o; | ||
585 | 89948 | int consumed = 0; | |
586 | char opt_stripped[128]; | ||
587 | const char *p; | ||
588 | 89948 | const AVClass *cc = avcodec_get_class(), *fc = avformat_get_class(); | |
589 | #if CONFIG_SWSCALE | ||
590 | 89948 | const AVClass *sc = sws_get_class(); | |
591 | #endif | ||
592 | #if CONFIG_SWRESAMPLE | ||
593 | 89948 | const AVClass *swr_class = swr_get_class(); | |
594 | #endif | ||
595 | |||
596 |
2/4✓ Branch 0 taken 89948 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 89948 times.
|
89948 | if (!strcmp(opt, "debug") || !strcmp(opt, "fdebug")) |
597 | ✗ | av_log_set_level(AV_LOG_DEBUG); | |
598 | |||
599 |
2/2✓ Branch 0 taken 89936 times.
✓ Branch 1 taken 12 times.
|
89948 | if (!(p = strchr(opt, ':'))) |
600 | 89936 | p = opt + strlen(opt); | |
601 | 89948 | av_strlcpy(opt_stripped, opt, FFMIN(sizeof(opt_stripped), p - opt + 1)); | |
602 | |||
603 |
2/2✓ Branch 1 taken 44292 times.
✓ Branch 2 taken 45656 times.
|
89948 | if ((o = opt_find(&cc, opt_stripped, NULL, 0, |
604 | 44292 | AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ)) || | |
605 |
8/8✓ Branch 0 taken 44289 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 44277 times.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 12075 times.
✓ Branch 5 taken 32202 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 12089 times.
|
56382 | ((opt[0] == 'v' || opt[0] == 'a' || opt[0] == 's') && |
606 | 12090 | (o = opt_find(&cc, opt + 1, NULL, 0, AV_OPT_SEARCH_FAKE_OBJ)))) { | |
607 |
5/6✓ Branch 0 taken 18450 times.
✓ Branch 1 taken 27207 times.
✓ Branch 2 taken 18450 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12022 times.
✓ Branch 5 taken 6428 times.
|
45657 | av_dict_set(&codec_opts, opt, arg, FLAGS); |
608 | 45657 | consumed = 1; | |
609 | } | ||
610 |
2/2✓ Branch 1 taken 12109 times.
✓ Branch 2 taken 77839 times.
|
89948 | if ((o = opt_find(&fc, opt, NULL, 0, |
611 | AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) { | ||
612 |
5/6✓ Branch 0 taken 11870 times.
✓ Branch 1 taken 239 times.
✓ Branch 2 taken 11870 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11862 times.
✓ Branch 5 taken 8 times.
|
12109 | av_dict_set(&format_opts, opt, arg, FLAGS); |
613 |
2/2✓ Branch 0 taken 97 times.
✓ Branch 1 taken 12012 times.
|
12109 | if (consumed) |
614 | 97 | av_log(NULL, AV_LOG_VERBOSE, "Routing option %s to both codec and muxer layer\n", opt); | |
615 | 12109 | consumed = 1; | |
616 | } | ||
617 | #if CONFIG_SWSCALE | ||
618 |
4/4✓ Branch 0 taken 32279 times.
✓ Branch 1 taken 57669 times.
✓ Branch 3 taken 12051 times.
✓ Branch 4 taken 20228 times.
|
89948 | if (!consumed && (o = opt_find(&sc, opt, NULL, 0, |
619 | AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) { | ||
620 |
2/4✓ Branch 0 taken 12051 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12051 times.
✗ Branch 3 not taken.
|
12051 | if (!strcmp(opt, "srcw") || !strcmp(opt, "srch") || |
621 |
2/4✓ Branch 0 taken 12051 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12051 times.
✗ Branch 3 not taken.
|
12051 | !strcmp(opt, "dstw") || !strcmp(opt, "dsth") || |
622 |
2/4✓ Branch 0 taken 12051 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12051 times.
|
12051 | !strcmp(opt, "src_format") || !strcmp(opt, "dst_format")) { |
623 | ✗ | av_log(NULL, AV_LOG_ERROR, "Directly using swscale dimensions/format options is not supported, please use the -s or -pix_fmt options\n"); | |
624 | ✗ | return AVERROR(EINVAL); | |
625 | } | ||
626 |
4/6✓ Branch 0 taken 12051 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12051 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11866 times.
✓ Branch 5 taken 185 times.
|
12051 | av_dict_set(&sws_dict, opt, arg, FLAGS); |
627 | |||
628 | 12051 | consumed = 1; | |
629 | } | ||
630 | #else | ||
631 | if (!consumed && !strcmp(opt, "sws_flags")) { | ||
632 | av_log(NULL, AV_LOG_WARNING, "Ignoring %s %s, due to disabled swscale\n", opt, arg); | ||
633 | consumed = 1; | ||
634 | } | ||
635 | #endif | ||
636 | #if CONFIG_SWRESAMPLE | ||
637 |
3/4✓ Branch 0 taken 20228 times.
✓ Branch 1 taken 69720 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 20228 times.
|
89948 | if (!consumed && (o=opt_find(&swr_class, opt, NULL, 0, |
638 | AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) { | ||
639 | ✗ | av_dict_set(&swr_opts, opt, arg, FLAGS); | |
640 | ✗ | consumed = 1; | |
641 | } | ||
642 | #endif | ||
643 | |||
644 |
2/2✓ Branch 0 taken 69720 times.
✓ Branch 1 taken 20228 times.
|
89948 | if (consumed) |
645 | 69720 | return 0; | |
646 | 20228 | return AVERROR_OPTION_NOT_FOUND; | |
647 | } | ||
648 | |||
649 | /* | ||
650 | * Check whether given option is a group separator. | ||
651 | * | ||
652 | * @return index of the group definition that matched or -1 if none | ||
653 | */ | ||
654 | 148517 | static int match_group_separator(const OptionGroupDef *groups, int nb_groups, | |
655 | const char *opt) | ||
656 | { | ||
657 | int i; | ||
658 | |||
659 |
2/2✓ Branch 0 taken 438761 times.
✓ Branch 1 taken 141726 times.
|
580487 | for (i = 0; i < nb_groups; i++) { |
660 | 438761 | const OptionGroupDef *p = &groups[i]; | |
661 |
4/4✓ Branch 0 taken 290244 times.
✓ Branch 1 taken 148517 times.
✓ Branch 2 taken 6791 times.
✓ Branch 3 taken 283453 times.
|
438761 | if (p->sep && !strcmp(p->sep, opt)) |
662 | 6791 | return i; | |
663 | } | ||
664 | |||
665 | 141726 | return -1; | |
666 | } | ||
667 | |||
668 | /* | ||
669 | * Finish parsing an option group. | ||
670 | * | ||
671 | * @param group_idx which group definition should this group belong to | ||
672 | * @param arg argument of the group delimiting option | ||
673 | */ | ||
674 | 13552 | static int finish_group(OptionParseContext *octx, int group_idx, | |
675 | const char *arg) | ||
676 | { | ||
677 | 13552 | OptionGroupList *l = &octx->groups[group_idx]; | |
678 | OptionGroup *g; | ||
679 | int ret; | ||
680 | |||
681 | 13552 | ret = GROW_ARRAY(l->groups, l->nb_groups); | |
682 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13552 times.
|
13552 | if (ret < 0) |
683 | ✗ | return ret; | |
684 | |||
685 | 13552 | g = &l->groups[l->nb_groups - 1]; | |
686 | |||
687 | 13552 | *g = octx->cur_group; | |
688 | 13552 | g->arg = arg; | |
689 | 13552 | g->group_def = l->group_def; | |
690 | 13552 | g->sws_dict = sws_dict; | |
691 | 13552 | g->swr_opts = swr_opts; | |
692 | 13552 | g->codec_opts = codec_opts; | |
693 | 13552 | g->format_opts = format_opts; | |
694 | |||
695 | 13552 | codec_opts = NULL; | |
696 | 13552 | format_opts = NULL; | |
697 | 13552 | sws_dict = NULL; | |
698 | 13552 | swr_opts = NULL; | |
699 | |||
700 | 13552 | memset(&octx->cur_group, 0, sizeof(octx->cur_group)); | |
701 | |||
702 | 13552 | return ret; | |
703 | } | ||
704 | |||
705 | /* | ||
706 | * Add an option instance to currently parsed group. | ||
707 | */ | ||
708 | 72014 | static int add_opt(OptionParseContext *octx, const OptionDef *opt, | |
709 | const char *key, const char *val) | ||
710 | { | ||
711 | 72014 | int global = !(opt->flags & OPT_PERFILE); | |
712 |
2/2✓ Branch 0 taken 31180 times.
✓ Branch 1 taken 40834 times.
|
72014 | OptionGroup *g = global ? &octx->global_opts : &octx->cur_group; |
713 | int ret; | ||
714 | |||
715 | 72014 | ret = GROW_ARRAY(g->opts, g->nb_opts); | |
716 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 72014 times.
|
72014 | if (ret < 0) |
717 | ✗ | return ret; | |
718 | |||
719 | 72014 | g->opts[g->nb_opts - 1].opt = opt; | |
720 | 72014 | g->opts[g->nb_opts - 1].key = key; | |
721 | 72014 | g->opts[g->nb_opts - 1].val = val; | |
722 | |||
723 | 72014 | return 0; | |
724 | } | ||
725 | |||
726 | 6760 | static int init_parse_context(OptionParseContext *octx, | |
727 | const OptionGroupDef *groups, int nb_groups) | ||
728 | { | ||
729 | static const OptionGroupDef global_group = { "global" }; | ||
730 | int i; | ||
731 | |||
732 | 6760 | memset(octx, 0, sizeof(*octx)); | |
733 | |||
734 | 6760 | octx->groups = av_calloc(nb_groups, sizeof(*octx->groups)); | |
735 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6760 times.
|
6760 | if (!octx->groups) |
736 | ✗ | return AVERROR(ENOMEM); | |
737 | 6760 | octx->nb_groups = nb_groups; | |
738 | |||
739 |
2/2✓ Branch 0 taken 20280 times.
✓ Branch 1 taken 6760 times.
|
27040 | for (i = 0; i < octx->nb_groups; i++) |
740 | 20280 | octx->groups[i].group_def = &groups[i]; | |
741 | |||
742 | 6760 | octx->global_opts.group_def = &global_group; | |
743 | 6760 | octx->global_opts.arg = ""; | |
744 | |||
745 | 6760 | return 0; | |
746 | } | ||
747 | |||
748 | 6760 | void uninit_parse_context(OptionParseContext *octx) | |
749 | { | ||
750 | int i, j; | ||
751 | |||
752 |
2/2✓ Branch 0 taken 20280 times.
✓ Branch 1 taken 6760 times.
|
27040 | for (i = 0; i < octx->nb_groups; i++) { |
753 | 20280 | OptionGroupList *l = &octx->groups[i]; | |
754 | |||
755 |
2/2✓ Branch 0 taken 13552 times.
✓ Branch 1 taken 20280 times.
|
33832 | for (j = 0; j < l->nb_groups; j++) { |
756 | 13552 | av_freep(&l->groups[j].opts); | |
757 | 13552 | av_dict_free(&l->groups[j].codec_opts); | |
758 | 13552 | av_dict_free(&l->groups[j].format_opts); | |
759 | |||
760 | 13552 | av_dict_free(&l->groups[j].sws_dict); | |
761 | 13552 | av_dict_free(&l->groups[j].swr_opts); | |
762 | } | ||
763 | 20280 | av_freep(&l->groups); | |
764 | } | ||
765 | 6760 | av_freep(&octx->groups); | |
766 | |||
767 | 6760 | av_freep(&octx->cur_group.opts); | |
768 | 6760 | av_freep(&octx->global_opts.opts); | |
769 | |||
770 | 6760 | uninit_opts(); | |
771 | 6760 | } | |
772 | |||
773 | 6760 | int split_commandline(OptionParseContext *octx, int argc, char *argv[], | |
774 | const OptionDef *options, | ||
775 | const OptionGroupDef *groups, int nb_groups) | ||
776 | { | ||
777 | int ret; | ||
778 | 6760 | int optindex = 1; | |
779 | 6760 | int dashdash = -2; | |
780 | |||
781 | /* perform system-dependent conversions for arguments list */ | ||
782 | 6760 | prepare_app_arguments(&argc, &argv); | |
783 | |||
784 | 6760 | ret = init_parse_context(octx, groups, nb_groups); | |
785 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6760 times.
|
6760 | if (ret < 0) |
786 | ✗ | return ret; | |
787 | |||
788 | 6760 | av_log(NULL, AV_LOG_DEBUG, "Splitting the commandline.\n"); | |
789 | |||
790 |
2/2✓ Branch 0 taken 155278 times.
✓ Branch 1 taken 6760 times.
|
162038 | while (optindex < argc) { |
791 | 155278 | const char *opt = argv[optindex++], *arg; | |
792 | const OptionDef *po; | ||
793 | int ret, group_idx; | ||
794 | |||
795 | 155278 | av_log(NULL, AV_LOG_DEBUG, "Reading option '%s' ...", opt); | |
796 | |||
797 |
3/6✓ Branch 0 taken 151109 times.
✓ Branch 1 taken 4169 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 151109 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
155278 | if (opt[0] == '-' && opt[1] == '-' && !opt[2]) { |
798 | ✗ | dashdash = optindex; | |
799 | ✗ | continue; | |
800 | } | ||
801 | /* unnamed group separators, e.g. output filename */ | ||
802 |
5/6✓ Branch 0 taken 151109 times.
✓ Branch 1 taken 4169 times.
✓ Branch 2 taken 148517 times.
✓ Branch 3 taken 2592 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 148517 times.
|
155278 | if (opt[0] != '-' || !opt[1] || dashdash+1 == optindex) { |
803 | 6761 | ret = finish_group(octx, 0, opt); | |
804 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6761 times.
|
6761 | if (ret < 0) |
805 | ✗ | return ret; | |
806 | |||
807 | 6761 | av_log(NULL, AV_LOG_DEBUG, " matched as %s.\n", groups[0].name); | |
808 | 6761 | continue; | |
809 | } | ||
810 | 148517 | opt++; | |
811 | |||
812 | #define GET_ARG(arg) \ | ||
813 | do { \ | ||
814 | arg = argv[optindex++]; \ | ||
815 | if (!arg) { \ | ||
816 | av_log(NULL, AV_LOG_ERROR, "Missing argument for option '%s'.\n", opt);\ | ||
817 | return AVERROR(EINVAL); \ | ||
818 | } \ | ||
819 | } while (0) | ||
820 | |||
821 | /* named group separators, e.g. -i */ | ||
822 | 148517 | group_idx = match_group_separator(groups, nb_groups, opt); | |
823 |
2/2✓ Branch 0 taken 6791 times.
✓ Branch 1 taken 141726 times.
|
148517 | if (group_idx >= 0) { |
824 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6791 times.
|
6791 | GET_ARG(arg); |
825 | 6791 | ret = finish_group(octx, group_idx, arg); | |
826 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6791 times.
|
6791 | if (ret < 0) |
827 | ✗ | return ret; | |
828 | |||
829 | 6791 | av_log(NULL, AV_LOG_DEBUG, " matched as %s with argument '%s'.\n", | |
830 | 6791 | groups[group_idx].name, arg); | |
831 | 6791 | continue; | |
832 | } | ||
833 | |||
834 | /* normal options */ | ||
835 | 141726 | po = find_option(options, opt); | |
836 |
2/2✓ Branch 0 taken 51786 times.
✓ Branch 1 taken 89940 times.
|
141726 | if (po->name) { |
837 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 51785 times.
|
51786 | if (po->flags & OPT_EXIT) { |
838 | /* optional argument, e.g. -h */ | ||
839 | 1 | arg = argv[optindex++]; | |
840 |
2/2✓ Branch 1 taken 45812 times.
✓ Branch 2 taken 5973 times.
|
51785 | } else if (opt_has_arg(po)) { |
841 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 45812 times.
|
45812 | GET_ARG(arg); |
842 | } else { | ||
843 | 5973 | arg = "1"; | |
844 | } | ||
845 | |||
846 | 51786 | ret = add_opt(octx, po, opt, arg); | |
847 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 51786 times.
|
51786 | if (ret < 0) |
848 | ✗ | return ret; | |
849 | |||
850 | 51786 | av_log(NULL, AV_LOG_DEBUG, " matched as option '%s' (%s) with " | |
851 | 51786 | "argument '%s'.\n", po->name, po->help, arg); | |
852 | 51786 | continue; | |
853 | } | ||
854 | |||
855 | /* AVOptions */ | ||
856 |
1/2✓ Branch 0 taken 89940 times.
✗ Branch 1 not taken.
|
89940 | if (argv[optindex]) { |
857 | 89940 | ret = opt_default(NULL, opt, argv[optindex]); | |
858 |
2/2✓ Branch 0 taken 69712 times.
✓ Branch 1 taken 20228 times.
|
89940 | if (ret >= 0) { |
859 | 69712 | av_log(NULL, AV_LOG_DEBUG, " matched as AVOption '%s' with " | |
860 | 69712 | "argument '%s'.\n", opt, argv[optindex]); | |
861 | 69712 | optindex++; | |
862 | 69712 | continue; | |
863 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 20228 times.
|
20228 | } else if (ret != AVERROR_OPTION_NOT_FOUND) { |
864 | ✗ | av_log(NULL, AV_LOG_ERROR, "Error parsing option '%s' " | |
865 | ✗ | "with argument '%s'.\n", opt, argv[optindex]); | |
866 | ✗ | return ret; | |
867 | } | ||
868 | } | ||
869 | |||
870 | /* boolean -nofoo options */ | ||
871 |
3/6✓ Branch 0 taken 20228 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20228 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 20228 times.
✗ Branch 5 not taken.
|
40456 | if (opt[0] == 'n' && opt[1] == 'o' && |
872 | 20228 | (po = find_option(options, opt + 2)) && | |
873 |
2/4✓ Branch 0 taken 20228 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20228 times.
✗ Branch 3 not taken.
|
20228 | po->name && po->type == OPT_TYPE_BOOL) { |
874 | 20228 | ret = add_opt(octx, po, opt, "0"); | |
875 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 20228 times.
|
20228 | if (ret < 0) |
876 | ✗ | return ret; | |
877 | |||
878 | 20228 | av_log(NULL, AV_LOG_DEBUG, " matched as option '%s' (%s) with " | |
879 | 20228 | "argument 0.\n", po->name, po->help); | |
880 | 20228 | continue; | |
881 | } | ||
882 | |||
883 | ✗ | av_log(NULL, AV_LOG_ERROR, "Unrecognized option '%s'.\n", opt); | |
884 | ✗ | return AVERROR_OPTION_NOT_FOUND; | |
885 | } | ||
886 | |||
887 |
3/6✓ Branch 0 taken 6760 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6760 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 6760 times.
|
6760 | if (octx->cur_group.nb_opts || codec_opts || format_opts) |
888 | ✗ | av_log(NULL, AV_LOG_WARNING, "Trailing option(s) found in the " | |
889 | "command: may be ignored.\n"); | ||
890 | |||
891 | 6760 | av_log(NULL, AV_LOG_DEBUG, "Finished splitting the commandline.\n"); | |
892 | |||
893 | 6760 | return 0; | |
894 | } | ||
895 | |||
896 | ✗ | int read_yesno(void) | |
897 | { | ||
898 | ✗ | int c = getchar(); | |
899 | ✗ | int yesno = (av_toupper(c) == 'Y'); | |
900 | |||
901 | ✗ | while (c != '\n' && c != EOF) | |
902 | ✗ | c = getchar(); | |
903 | |||
904 | ✗ | return yesno; | |
905 | } | ||
906 | |||
907 | ✗ | FILE *get_preset_file(char *filename, size_t filename_size, | |
908 | const char *preset_name, int is_path, | ||
909 | const char *codec_name) | ||
910 | { | ||
911 | ✗ | FILE *f = NULL; | |
912 | int i; | ||
913 | #if HAVE_GETMODULEHANDLE && defined(_WIN32) | ||
914 | char *datadir = NULL; | ||
915 | #endif | ||
916 | ✗ | char *env_home = getenv_utf8("HOME"); | |
917 | ✗ | char *env_ffmpeg_datadir = getenv_utf8("FFMPEG_DATADIR"); | |
918 | ✗ | const char *base[3] = { env_ffmpeg_datadir, | |
919 | env_home, /* index=1(HOME) is special: search in a .ffmpeg subfolder */ | ||
920 | FFMPEG_DATADIR, }; | ||
921 | |||
922 | ✗ | if (is_path) { | |
923 | ✗ | av_strlcpy(filename, preset_name, filename_size); | |
924 | ✗ | f = fopen_utf8(filename, "r"); | |
925 | } else { | ||
926 | #if HAVE_GETMODULEHANDLE && defined(_WIN32) | ||
927 | wchar_t *datadir_w = get_module_filename(NULL); | ||
928 | base[2] = NULL; | ||
929 | |||
930 | if (wchartoutf8(datadir_w, &datadir)) | ||
931 | datadir = NULL; | ||
932 | av_free(datadir_w); | ||
933 | |||
934 | if (datadir) | ||
935 | { | ||
936 | char *ls; | ||
937 | for (ls = datadir; *ls; ls++) | ||
938 | if (*ls == '\\') *ls = '/'; | ||
939 | |||
940 | if (ls = strrchr(datadir, '/')) | ||
941 | { | ||
942 | ptrdiff_t datadir_len = ls - datadir; | ||
943 | size_t desired_size = datadir_len + strlen("/ffpresets") + 1; | ||
944 | char *new_datadir = av_realloc_array( | ||
945 | datadir, desired_size, sizeof *datadir); | ||
946 | if (new_datadir) { | ||
947 | datadir = new_datadir; | ||
948 | datadir[datadir_len] = 0; | ||
949 | strncat(datadir, "/ffpresets", desired_size - 1 - datadir_len); | ||
950 | base[2] = datadir; | ||
951 | } | ||
952 | } | ||
953 | } | ||
954 | #endif | ||
955 | ✗ | for (i = 0; i < 3 && !f; i++) { | |
956 | ✗ | if (!base[i]) | |
957 | ✗ | continue; | |
958 | ✗ | snprintf(filename, filename_size, "%s%s/%s.ffpreset", base[i], | |
959 | i != 1 ? "" : "/.ffmpeg", preset_name); | ||
960 | ✗ | f = fopen_utf8(filename, "r"); | |
961 | ✗ | if (!f && codec_name) { | |
962 | ✗ | snprintf(filename, filename_size, | |
963 | "%s%s/%s-%s.ffpreset", | ||
964 | base[i], i != 1 ? "" : "/.ffmpeg", codec_name, | ||
965 | preset_name); | ||
966 | ✗ | f = fopen_utf8(filename, "r"); | |
967 | } | ||
968 | } | ||
969 | } | ||
970 | |||
971 | #if HAVE_GETMODULEHANDLE && defined(_WIN32) | ||
972 | av_free(datadir); | ||
973 | #endif | ||
974 | ✗ | freeenv_utf8(env_ffmpeg_datadir); | |
975 | ✗ | freeenv_utf8(env_home); | |
976 | ✗ | return f; | |
977 | } | ||
978 | |||
979 | 29790 | int check_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec) | |
980 | { | ||
981 | 29790 | int ret = avformat_match_stream_specifier(s, st, spec); | |
982 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 29790 times.
|
29790 | if (ret < 0) |
983 | ✗ | av_log(s, AV_LOG_ERROR, "Invalid stream specifier: %s.\n", spec); | |
984 | 29790 | return ret; | |
985 | } | ||
986 | |||
987 | 22057 | int filter_codec_opts(const AVDictionary *opts, enum AVCodecID codec_id, | |
988 | AVFormatContext *s, AVStream *st, const AVCodec *codec, | ||
989 | AVDictionary **dst) | ||
990 | { | ||
991 | 22057 | AVDictionary *ret = NULL; | |
992 | 22057 | const AVDictionaryEntry *t = NULL; | |
993 | 44114 | int flags = s->oformat ? AV_OPT_FLAG_ENCODING_PARAM | |
994 |
2/2✓ Branch 0 taken 7112 times.
✓ Branch 1 taken 14945 times.
|
22057 | : AV_OPT_FLAG_DECODING_PARAM; |
995 | 22057 | char prefix = 0; | |
996 | 22057 | const AVClass *cc = avcodec_get_class(); | |
997 | |||
998 |
4/4✓ Branch 0 taken 16765 times.
✓ Branch 1 taken 4970 times.
✓ Branch 2 taken 240 times.
✓ Branch 3 taken 82 times.
|
22057 | switch (st->codecpar->codec_type) { |
999 | 16765 | case AVMEDIA_TYPE_VIDEO: | |
1000 | 16765 | prefix = 'v'; | |
1001 | 16765 | flags |= AV_OPT_FLAG_VIDEO_PARAM; | |
1002 | 16765 | break; | |
1003 | 4970 | case AVMEDIA_TYPE_AUDIO: | |
1004 | 4970 | prefix = 'a'; | |
1005 | 4970 | flags |= AV_OPT_FLAG_AUDIO_PARAM; | |
1006 | 4970 | break; | |
1007 | 240 | case AVMEDIA_TYPE_SUBTITLE: | |
1008 | 240 | prefix = 's'; | |
1009 | 240 | flags |= AV_OPT_FLAG_SUBTITLE_PARAM; | |
1010 | 240 | break; | |
1011 | } | ||
1012 | |||
1013 |
2/2✓ Branch 1 taken 63382 times.
✓ Branch 2 taken 22057 times.
|
85439 | while (t = av_dict_iterate(opts, t)) { |
1014 | const AVClass *priv_class; | ||
1015 | 63382 | char *p = strchr(t->key, ':'); | |
1016 | |||
1017 | /* check stream specification in opt name */ | ||
1018 |
2/2✓ Branch 0 taken 286 times.
✓ Branch 1 taken 63096 times.
|
63382 | if (p) { |
1019 | 286 | int err = check_stream_specifier(s, st, p + 1); | |
1020 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 286 times.
|
286 | if (err < 0) { |
1021 | ✗ | av_dict_free(&ret); | |
1022 | ✗ | return err; | |
1023 |
2/2✓ Branch 0 taken 77 times.
✓ Branch 1 taken 209 times.
|
286 | } else if (!err) |
1024 | 77 | continue; | |
1025 | |||
1026 | 209 | *p = 0; | |
1027 | } | ||
1028 | |||
1029 |
4/4✓ Branch 1 taken 2655 times.
✓ Branch 2 taken 60650 times.
✓ Branch 3 taken 1531 times.
✓ Branch 4 taken 1124 times.
|
63305 | if (av_opt_find(&cc, t->key, NULL, flags, AV_OPT_SEARCH_FAKE_OBJ) || |
1030 | 1531 | !codec || | |
1031 |
4/4✓ Branch 0 taken 669 times.
✓ Branch 1 taken 862 times.
✓ Branch 2 taken 307 times.
✓ Branch 3 taken 362 times.
|
2200 | ((priv_class = codec->priv_class) && |
1032 | 669 | av_opt_find(&priv_class, t->key, NULL, flags, | |
1033 | AV_OPT_SEARCH_FAKE_OBJ))) | ||
1034 | 62081 | av_dict_set(&ret, t->key, t->value, 0); | |
1035 |
4/4✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1221 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
|
1227 | else if (t->key[0] == prefix && |
1036 | 3 | av_opt_find(&cc, t->key + 1, NULL, flags, | |
1037 | AV_OPT_SEARCH_FAKE_OBJ)) | ||
1038 | 1 | av_dict_set(&ret, t->key + 1, t->value, 0); | |
1039 | |||
1040 |
2/2✓ Branch 0 taken 209 times.
✓ Branch 1 taken 63096 times.
|
63305 | if (p) |
1041 | 209 | *p = ':'; | |
1042 | } | ||
1043 | |||
1044 | 22057 | *dst = ret; | |
1045 | 22057 | return 0; | |
1046 | } | ||
1047 | |||
1048 | 6937 | int setup_find_stream_info_opts(AVFormatContext *s, | |
1049 | AVDictionary *codec_opts, | ||
1050 | AVDictionary ***dst) | ||
1051 | { | ||
1052 | int ret; | ||
1053 | AVDictionary **opts; | ||
1054 | |||
1055 | 6937 | *dst = NULL; | |
1056 | |||
1057 |
2/2✓ Branch 0 taken 85 times.
✓ Branch 1 taken 6852 times.
|
6937 | if (!s->nb_streams) |
1058 | 85 | return 0; | |
1059 | |||
1060 | 6852 | opts = av_calloc(s->nb_streams, sizeof(*opts)); | |
1061 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6852 times.
|
6852 | if (!opts) |
1062 | ✗ | return AVERROR(ENOMEM); | |
1063 | |||
1064 |
2/2✓ Branch 0 taken 7448 times.
✓ Branch 1 taken 6852 times.
|
14300 | for (int i = 0; i < s->nb_streams; i++) { |
1065 | 7448 | ret = filter_codec_opts(codec_opts, s->streams[i]->codecpar->codec_id, | |
1066 | 7448 | s, s->streams[i], NULL, &opts[i]); | |
1067 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7448 times.
|
7448 | if (ret < 0) |
1068 | ✗ | goto fail; | |
1069 | } | ||
1070 | 6852 | *dst = opts; | |
1071 | 6852 | return 0; | |
1072 | ✗ | fail: | |
1073 | ✗ | for (int i = 0; i < s->nb_streams; i++) | |
1074 | ✗ | av_dict_free(&opts[i]); | |
1075 | ✗ | av_freep(&opts); | |
1076 | ✗ | return ret; | |
1077 | } | ||
1078 | |||
1079 | 200554 | int grow_array(void **array, int elem_size, int *size, int new_size) | |
1080 | { | ||
1081 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 200554 times.
|
200554 | if (new_size >= INT_MAX / elem_size) { |
1082 | ✗ | av_log(NULL, AV_LOG_ERROR, "Array too big.\n"); | |
1083 | ✗ | return AVERROR(ERANGE); | |
1084 | } | ||
1085 |
1/2✓ Branch 0 taken 200554 times.
✗ Branch 1 not taken.
|
200554 | if (*size < new_size) { |
1086 | 200554 | uint8_t *tmp = av_realloc_array(*array, new_size, elem_size); | |
1087 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 200554 times.
|
200554 | if (!tmp) |
1088 | ✗ | return AVERROR(ENOMEM); | |
1089 | 200554 | memset(tmp + *size*elem_size, 0, (new_size-*size) * elem_size); | |
1090 | 200554 | *size = new_size; | |
1091 | 200554 | *array = tmp; | |
1092 | 200554 | return 0; | |
1093 | } | ||
1094 | ✗ | return 0; | |
1095 | } | ||
1096 | |||
1097 | 40797 | void *allocate_array_elem(void *ptr, size_t elem_size, int *nb_elems) | |
1098 | { | ||
1099 | void *new_elem; | ||
1100 | |||
1101 |
2/4✓ Branch 1 taken 40797 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 40797 times.
|
81594 | if (!(new_elem = av_mallocz(elem_size)) || |
1102 | 40797 | av_dynarray_add_nofree(ptr, nb_elems, new_elem) < 0) | |
1103 | ✗ | return NULL; | |
1104 | 40797 | return new_elem; | |
1105 | } | ||
1106 | |||
1107 | 5198 | double get_rotation(const int32_t *displaymatrix) | |
1108 | { | ||
1109 | 5198 | double theta = 0; | |
1110 |
1/2✓ Branch 0 taken 5198 times.
✗ Branch 1 not taken.
|
5198 | if (displaymatrix) |
1111 | 5198 | theta = -round(av_display_rotation_get(displaymatrix)); | |
1112 | |||
1113 | 5198 | theta -= 360*floor(theta/360 + 0.9/360); | |
1114 | |||
1115 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5198 times.
|
5198 | if (fabs(theta - 90*round(theta/90)) > 2) |
1116 | ✗ | av_log(NULL, AV_LOG_WARNING, "Odd rotation angle.\n" | |
1117 | "If you want to help, upload a sample " | ||
1118 | "of this file to https://streams.videolan.org/upload/ " | ||
1119 | "and contact the ffmpeg-devel mailing list. (ffmpeg-devel@ffmpeg.org)"); | ||
1120 | |||
1121 | 5198 | return theta; | |
1122 | } | ||
1123 | |||
1124 | /* read file contents into a string */ | ||
1125 | 57 | char *file_read(const char *filename) | |
1126 | { | ||
1127 | 57 | AVIOContext *pb = NULL; | |
1128 | 57 | int ret = avio_open(&pb, filename, AVIO_FLAG_READ); | |
1129 | AVBPrint bprint; | ||
1130 | char *str; | ||
1131 | |||
1132 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
|
57 | if (ret < 0) { |
1133 | ✗ | av_log(NULL, AV_LOG_ERROR, "Error opening file %s.\n", filename); | |
1134 | ✗ | return NULL; | |
1135 | } | ||
1136 | |||
1137 | 57 | av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED); | |
1138 | 57 | ret = avio_read_to_bprint(pb, &bprint, SIZE_MAX); | |
1139 | 57 | avio_closep(&pb); | |
1140 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
|
57 | if (ret < 0) { |
1141 | ✗ | av_bprint_finalize(&bprint, NULL); | |
1142 | ✗ | return NULL; | |
1143 | } | ||
1144 | 57 | ret = av_bprint_finalize(&bprint, &str); | |
1145 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
|
57 | if (ret < 0) |
1146 | ✗ | return NULL; | |
1147 | 57 | return str; | |
1148 | } | ||
1149 |