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 "libswscale/version.h" | ||
37 | #include "libswresample/swresample.h" | ||
38 | #include "libavutil/avassert.h" | ||
39 | #include "libavutil/avstring.h" | ||
40 | #include "libavutil/channel_layout.h" | ||
41 | #include "libavutil/display.h" | ||
42 | #include "libavutil/getenv_utf8.h" | ||
43 | #include "libavutil/mathematics.h" | ||
44 | #include "libavutil/imgutils.h" | ||
45 | #include "libavutil/libm.h" | ||
46 | #include "libavutil/parseutils.h" | ||
47 | #include "libavutil/eval.h" | ||
48 | #include "libavutil/dict.h" | ||
49 | #include "libavutil/opt.h" | ||
50 | #include "cmdutils.h" | ||
51 | #include "fopen_utf8.h" | ||
52 | #include "opt_common.h" | ||
53 | #ifdef _WIN32 | ||
54 | #include <windows.h> | ||
55 | #include "compat/w32dlfcn.h" | ||
56 | #endif | ||
57 | |||
58 | AVDictionary *sws_dict; | ||
59 | AVDictionary *swr_opts; | ||
60 | AVDictionary *format_opts, *codec_opts; | ||
61 | |||
62 | int hide_banner = 0; | ||
63 | |||
64 | 13430 | void uninit_opts(void) | |
65 | { | ||
66 | 13430 | av_dict_free(&swr_opts); | |
67 | 13430 | av_dict_free(&sws_dict); | |
68 | 13430 | av_dict_free(&format_opts); | |
69 | 13430 | av_dict_free(&codec_opts); | |
70 | 13430 | } | |
71 | |||
72 | ✗ | void log_callback_help(void *ptr, int level, const char *fmt, va_list vl) | |
73 | { | ||
74 | ✗ | vfprintf(stdout, fmt, vl); | |
75 | ✗ | } | |
76 | |||
77 | 6781 | void init_dynload(void) | |
78 | { | ||
79 | #if HAVE_SETDLLDIRECTORY && defined(_WIN32) | ||
80 | /* Calling SetDllDirectory with the empty string (but not NULL) removes the | ||
81 | * current working directory from the DLL search path as a security pre-caution. */ | ||
82 | SetDllDirectory(""); | ||
83 | #endif | ||
84 | 6781 | } | |
85 | |||
86 | 31102 | int parse_number(const char *context, const char *numstr, int type, | |
87 | double min, double max, double *dst) | ||
88 | { | ||
89 | char *tail; | ||
90 | const char *error; | ||
91 | 31102 | double d = av_strtod(numstr, &tail); | |
92 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 31102 times.
|
31102 | if (*tail) |
93 | ✗ | error = "Expected number for %s but found: %s\n"; | |
94 |
2/4✓ Branch 0 taken 31102 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 31102 times.
|
31102 | else if (d < min || d > max) |
95 | ✗ | error = "The value for %s was %s which is not within %f - %f\n"; | |
96 |
3/4✓ Branch 0 taken 30810 times.
✓ Branch 1 taken 292 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 30810 times.
|
31102 | else if (type == OPT_INT64 && (int64_t)d != d) |
97 | ✗ | error = "Expected int64 for %s but found %s\n"; | |
98 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 31102 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
31102 | else if (type == OPT_INT && (int)d != d) |
99 | ✗ | error = "Expected int for %s but found %s\n"; | |
100 | else { | ||
101 | 31102 | *dst = d; | |
102 | 31102 | return 0; | |
103 | } | ||
104 | |||
105 | ✗ | av_log(NULL, AV_LOG_FATAL, error, context, numstr, min, max); | |
106 | ✗ | return AVERROR(EINVAL); | |
107 | } | ||
108 | |||
109 | ✗ | void show_help_options(const OptionDef *options, const char *msg, int req_flags, | |
110 | int rej_flags, int alt_flags) | ||
111 | { | ||
112 | const OptionDef *po; | ||
113 | int first; | ||
114 | |||
115 | ✗ | first = 1; | |
116 | ✗ | for (po = options; po->name; po++) { | |
117 | char buf[128]; | ||
118 | |||
119 | ✗ | if (((po->flags & req_flags) != req_flags) || | |
120 | ✗ | (alt_flags && !(po->flags & alt_flags)) || | |
121 | ✗ | (po->flags & rej_flags)) | |
122 | ✗ | continue; | |
123 | |||
124 | ✗ | if (first) { | |
125 | ✗ | printf("%s\n", msg); | |
126 | ✗ | first = 0; | |
127 | } | ||
128 | ✗ | av_strlcpy(buf, po->name, sizeof(buf)); | |
129 | ✗ | if (po->argname) { | |
130 | ✗ | av_strlcat(buf, " ", sizeof(buf)); | |
131 | ✗ | av_strlcat(buf, po->argname, sizeof(buf)); | |
132 | } | ||
133 | ✗ | printf("-%-17s %s\n", buf, po->help); | |
134 | } | ||
135 | ✗ | printf("\n"); | |
136 | ✗ | } | |
137 | |||
138 | ✗ | void show_help_children(const AVClass *class, int flags) | |
139 | { | ||
140 | ✗ | void *iter = NULL; | |
141 | const AVClass *child; | ||
142 | ✗ | if (class->option) { | |
143 | ✗ | av_opt_show2(&class, NULL, flags, 0); | |
144 | ✗ | printf("\n"); | |
145 | } | ||
146 | |||
147 | ✗ | while (child = av_opt_child_class_iterate(class, &iter)) | |
148 | ✗ | show_help_children(child, flags); | |
149 | ✗ | } | |
150 | |||
151 | 1013792 | static const OptionDef *find_option(const OptionDef *po, const char *name) | |
152 | { | ||
153 |
2/2✓ Branch 0 taken 147543159 times.
✓ Branch 1 taken 578376 times.
|
148121535 | while (po->name) { |
154 | const char *end; | ||
155 |
6/6✓ Branch 1 taken 1025538 times.
✓ Branch 2 taken 146517621 times.
✓ Branch 3 taken 635777 times.
✓ Branch 4 taken 389761 times.
✓ Branch 5 taken 590122 times.
✓ Branch 6 taken 45655 times.
|
147543159 | if (av_strstart(name, po->name, &end) && (!*end || *end == ':')) |
156 | break; | ||
157 | 147107743 | po++; | |
158 | } | ||
159 | 1013792 | return po; | |
160 | } | ||
161 | |||
162 | /* _WIN32 means using the windows libc - cygwin doesn't define that | ||
163 | * by default. HAVE_COMMANDLINETOARGVW is true on cygwin, while | ||
164 | * it doesn't provide the actual command line via GetCommandLineW(). */ | ||
165 | #if HAVE_COMMANDLINETOARGVW && defined(_WIN32) | ||
166 | #include <shellapi.h> | ||
167 | /* Will be leaked on exit */ | ||
168 | static char** win32_argv_utf8 = NULL; | ||
169 | static int win32_argc = 0; | ||
170 | |||
171 | /** | ||
172 | * Prepare command line arguments for executable. | ||
173 | * For Windows - perform wide-char to UTF-8 conversion. | ||
174 | * Input arguments should be main() function arguments. | ||
175 | * @param argc_ptr Arguments number (including executable) | ||
176 | * @param argv_ptr Arguments list. | ||
177 | */ | ||
178 | static void prepare_app_arguments(int *argc_ptr, char ***argv_ptr) | ||
179 | { | ||
180 | char *argstr_flat; | ||
181 | wchar_t **argv_w; | ||
182 | int i, buffsize = 0, offset = 0; | ||
183 | |||
184 | if (win32_argv_utf8) { | ||
185 | *argc_ptr = win32_argc; | ||
186 | *argv_ptr = win32_argv_utf8; | ||
187 | return; | ||
188 | } | ||
189 | |||
190 | win32_argc = 0; | ||
191 | argv_w = CommandLineToArgvW(GetCommandLineW(), &win32_argc); | ||
192 | if (win32_argc <= 0 || !argv_w) | ||
193 | return; | ||
194 | |||
195 | /* determine the UTF-8 buffer size (including NULL-termination symbols) */ | ||
196 | for (i = 0; i < win32_argc; i++) | ||
197 | buffsize += WideCharToMultiByte(CP_UTF8, 0, argv_w[i], -1, | ||
198 | NULL, 0, NULL, NULL); | ||
199 | |||
200 | win32_argv_utf8 = av_mallocz(sizeof(char *) * (win32_argc + 1) + buffsize); | ||
201 | argstr_flat = (char *)win32_argv_utf8 + sizeof(char *) * (win32_argc + 1); | ||
202 | if (!win32_argv_utf8) { | ||
203 | LocalFree(argv_w); | ||
204 | return; | ||
205 | } | ||
206 | |||
207 | for (i = 0; i < win32_argc; i++) { | ||
208 | win32_argv_utf8[i] = &argstr_flat[offset]; | ||
209 | offset += WideCharToMultiByte(CP_UTF8, 0, argv_w[i], -1, | ||
210 | &argstr_flat[offset], | ||
211 | buffsize - offset, NULL, NULL); | ||
212 | } | ||
213 | win32_argv_utf8[i] = NULL; | ||
214 | LocalFree(argv_w); | ||
215 | |||
216 | *argc_ptr = win32_argc; | ||
217 | *argv_ptr = win32_argv_utf8; | ||
218 | } | ||
219 | #else | ||
220 | 6781 | static inline void prepare_app_arguments(int *argc_ptr, char ***argv_ptr) | |
221 | { | ||
222 | /* nothing to do */ | ||
223 | 6781 | } | |
224 | #endif /* HAVE_COMMANDLINETOARGVW */ | ||
225 | |||
226 | 79503 | static int write_option(void *optctx, const OptionDef *po, const char *opt, | |
227 | const char *arg) | ||
228 | { | ||
229 | /* new-style options contain an offset into optctx, old-style address of | ||
230 | * a global var*/ | ||
231 | 159006 | void *dst = po->flags & (OPT_OFFSET | OPT_SPEC) ? | |
232 |
2/2✓ Branch 0 taken 39097 times.
✓ Branch 1 taken 40406 times.
|
79503 | (uint8_t *)optctx + po->u.off : po->u.dst_ptr; |
233 | int *dstcount; | ||
234 | double num; | ||
235 | int ret; | ||
236 | |||
237 |
2/2✓ Branch 0 taken 26979 times.
✓ Branch 1 taken 52524 times.
|
79503 | if (po->flags & OPT_SPEC) { |
238 | 26979 | SpecifierOpt **so = dst; | |
239 | 26979 | char *p = strchr(opt, ':'); | |
240 | char *str; | ||
241 | |||
242 | 26979 | dstcount = (int *)(so + 1); | |
243 | 26979 | ret = grow_array((void**)so, sizeof(**so), dstcount, *dstcount + 1); | |
244 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 26979 times.
|
26979 | if (ret < 0) |
245 | ✗ | return ret; | |
246 | |||
247 |
2/2✓ Branch 0 taken 14328 times.
✓ Branch 1 taken 12651 times.
|
26979 | str = av_strdup(p ? p + 1 : ""); |
248 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 26979 times.
|
26979 | if (!str) |
249 | ✗ | return AVERROR(ENOMEM); | |
250 | 26979 | (*so)[*dstcount - 1].specifier = str; | |
251 | 26979 | dst = &(*so)[*dstcount - 1].u; | |
252 | } | ||
253 | |||
254 |
2/2✓ Branch 0 taken 31675 times.
✓ Branch 1 taken 47828 times.
|
79503 | if (po->flags & OPT_STRING) { |
255 | char *str; | ||
256 | 31675 | str = av_strdup(arg); | |
257 | 31675 | av_freep(dst); | |
258 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 31675 times.
|
31675 | if (!str) |
259 | ✗ | return AVERROR(ENOMEM); | |
260 | 31675 | *(char **)dst = str; | |
261 |
4/4✓ Branch 0 taken 21910 times.
✓ Branch 1 taken 25918 times.
✓ Branch 2 taken 138 times.
✓ Branch 3 taken 21772 times.
|
47828 | } else if (po->flags & OPT_BOOL || po->flags & OPT_INT) { |
262 | 26056 | ret = parse_number(opt, arg, OPT_INT64, INT_MIN, INT_MAX, &num); | |
263 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 26056 times.
|
26056 | if (ret < 0) |
264 | ✗ | return ret; | |
265 | |||
266 | 26056 | *(int *)dst = num; | |
267 |
2/2✓ Branch 0 taken 4754 times.
✓ Branch 1 taken 17018 times.
|
21772 | } else if (po->flags & OPT_INT64) { |
268 | 4754 | ret = parse_number(opt, arg, OPT_INT64, INT64_MIN, INT64_MAX, &num); | |
269 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4754 times.
|
4754 | if (ret < 0) |
270 | ✗ | return ret; | |
271 | |||
272 | 4754 | *(int64_t *)dst = num; | |
273 |
2/2✓ Branch 0 taken 201 times.
✓ Branch 1 taken 16817 times.
|
17018 | } else if (po->flags & OPT_TIME) { |
274 | 201 | ret = av_parse_time(dst, arg, 1); | |
275 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 201 times.
|
201 | if (ret < 0) { |
276 | ✗ | av_log(NULL, AV_LOG_ERROR, "Invalid duration for option %s: %s\n", | |
277 | opt, arg); | ||
278 | ✗ | return ret; | |
279 | } | ||
280 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 16814 times.
|
16817 | } else if (po->flags & OPT_FLOAT) { |
281 | 3 | ret = parse_number(opt, arg, OPT_FLOAT, -INFINITY, INFINITY, &num); | |
282 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (ret < 0) |
283 | ✗ | return ret; | |
284 | |||
285 | 3 | *(float *)dst = num; | |
286 |
2/2✓ Branch 0 taken 289 times.
✓ Branch 1 taken 16525 times.
|
16814 | } else if (po->flags & OPT_DOUBLE) { |
287 | 289 | ret = parse_number(opt, arg, OPT_DOUBLE, -INFINITY, INFINITY, &num); | |
288 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 289 times.
|
289 | if (ret < 0) |
289 | ✗ | return ret; | |
290 | |||
291 | 289 | *(double *)dst = num; | |
292 |
1/2✓ Branch 0 taken 16525 times.
✗ Branch 1 not taken.
|
16525 | } else if (po->u.func_arg) { |
293 | 16525 | int ret = po->u.func_arg(optctx, opt, arg); | |
294 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16525 times.
|
16525 | if (ret < 0) { |
295 | ✗ | av_log(NULL, AV_LOG_ERROR, | |
296 | "Failed to set value '%s' for option '%s': %s\n", | ||
297 | ✗ | arg, opt, av_err2str(ret)); | |
298 | ✗ | return ret; | |
299 | } | ||
300 | } | ||
301 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 79502 times.
|
79503 | if (po->flags & OPT_EXIT) |
302 | 1 | return AVERROR_EXIT; | |
303 | |||
304 | 79502 | return 0; | |
305 | } | ||
306 | |||
307 | 8789 | int parse_option(void *optctx, const char *opt, const char *arg, | |
308 | const OptionDef *options) | ||
309 | { | ||
310 | static const OptionDef opt_avoptions = { | ||
311 | .name = "AVOption passthrough", | ||
312 | .flags = HAS_ARG, | ||
313 | .u.func_arg = opt_default, | ||
314 | }; | ||
315 | |||
316 | const OptionDef *po; | ||
317 | int ret; | ||
318 | |||
319 | 8789 | po = find_option(options, opt); | |
320 |
5/6✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8781 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 7 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
8789 | if (!po->name && opt[0] == 'n' && opt[1] == 'o') { |
321 | /* handle 'no' bool option */ | ||
322 | 1 | po = find_option(options, opt + 2); | |
323 |
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->flags & OPT_BOOL))) |
324 | 1 | arg = "0"; | |
325 |
2/2✓ Branch 0 taken 127 times.
✓ Branch 1 taken 8661 times.
|
8788 | } else if (po->flags & OPT_BOOL) |
326 | 127 | arg = "1"; | |
327 | |||
328 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 8782 times.
|
8789 | if (!po->name) |
329 | 7 | po = &opt_avoptions; | |
330 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8789 times.
|
8789 | if (!po->name) { |
331 | ✗ | av_log(NULL, AV_LOG_ERROR, "Unrecognized option '%s'\n", opt); | |
332 | ✗ | return AVERROR(EINVAL); | |
333 | } | ||
334 |
3/4✓ Branch 0 taken 8560 times.
✓ Branch 1 taken 229 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8560 times.
|
8789 | if (po->flags & HAS_ARG && !arg) { |
335 | ✗ | av_log(NULL, AV_LOG_ERROR, "Missing argument for option '%s'\n", opt); | |
336 | ✗ | return AVERROR(EINVAL); | |
337 | } | ||
338 | |||
339 | 8789 | ret = write_option(optctx, po, opt, arg); | |
340 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8789 times.
|
8789 | if (ret < 0) |
341 | ✗ | return ret; | |
342 | |||
343 | 8789 | return !!(po->flags & HAS_ARG); | |
344 | } | ||
345 | |||
346 | 132 | int parse_options(void *optctx, int argc, char **argv, const OptionDef *options, | |
347 | int (*parse_arg_function)(void *, const char*)) | ||
348 | { | ||
349 | const char *opt; | ||
350 | 132 | int optindex, handleoptions = 1, ret; | |
351 | |||
352 | /* perform system-dependent conversions for arguments list */ | ||
353 | 132 | prepare_app_arguments(&argc, &argv); | |
354 | |||
355 | /* parse options */ | ||
356 | 132 | optindex = 1; | |
357 |
2/2✓ Branch 0 taken 604 times.
✓ Branch 1 taken 132 times.
|
736 | while (optindex < argc) { |
358 | 604 | opt = argv[optindex++]; | |
359 | |||
360 |
4/6✓ Branch 0 taken 604 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 482 times.
✓ Branch 3 taken 122 times.
✓ Branch 4 taken 482 times.
✗ Branch 5 not taken.
|
604 | if (handleoptions && opt[0] == '-' && opt[1] != '\0') { |
361 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 482 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
482 | if (opt[1] == '-' && opt[2] == '\0') { |
362 | ✗ | handleoptions = 0; | |
363 | ✗ | continue; | |
364 | } | ||
365 | 482 | opt++; | |
366 | |||
367 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 482 times.
|
482 | if ((ret = parse_option(optctx, opt, argv[optindex], options)) < 0) |
368 | ✗ | return ret; | |
369 | 482 | optindex += ret; | |
370 | } else { | ||
371 |
1/2✓ Branch 0 taken 122 times.
✗ Branch 1 not taken.
|
122 | if (parse_arg_function) { |
372 | 122 | ret = parse_arg_function(optctx, opt); | |
373 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 122 times.
|
122 | if (ret < 0) |
374 | ✗ | return ret; | |
375 | } | ||
376 | } | ||
377 | } | ||
378 | |||
379 | 132 | return 0; | |
380 | } | ||
381 | |||
382 | 19981 | int parse_optgroup(void *optctx, OptionGroup *g) | |
383 | { | ||
384 | int i, ret; | ||
385 | |||
386 | 19981 | av_log(NULL, AV_LOG_DEBUG, "Parsing a group of options: %s %s.\n", | |
387 | 19981 | g->group_def->name, g->arg); | |
388 | |||
389 |
2/2✓ Branch 0 taken 70714 times.
✓ Branch 1 taken 19980 times.
|
90694 | for (i = 0; i < g->nb_opts; i++) { |
390 | 70714 | Option *o = &g->opts[i]; | |
391 | |||
392 |
2/2✓ Branch 0 taken 39504 times.
✓ Branch 1 taken 31210 times.
|
70714 | if (g->group_def->flags && |
393 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 39504 times.
|
39504 | !(g->group_def->flags & o->opt->flags)) { |
394 | ✗ | av_log(NULL, AV_LOG_ERROR, "Option %s (%s) cannot be applied to " | |
395 | "%s %s -- you are trying to apply an input option to an " | ||
396 | "output file or vice versa. Move this option before the " | ||
397 | ✗ | "file it belongs to.\n", o->key, o->opt->help, | |
398 | ✗ | g->group_def->name, g->arg); | |
399 | ✗ | return AVERROR(EINVAL); | |
400 | } | ||
401 | |||
402 | 70714 | av_log(NULL, AV_LOG_DEBUG, "Applying option %s (%s) with argument %s.\n", | |
403 | 70714 | o->key, o->opt->help, o->val); | |
404 | |||
405 | 70714 | ret = write_option(optctx, o->opt, o->key, o->val); | |
406 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 70713 times.
|
70714 | if (ret < 0) |
407 | 1 | return ret; | |
408 | } | ||
409 | |||
410 | 19980 | av_log(NULL, AV_LOG_DEBUG, "Successfully parsed a group of options.\n"); | |
411 | |||
412 | 19980 | return 0; | |
413 | } | ||
414 | |||
415 | 33905 | int locate_option(int argc, char **argv, const OptionDef *options, | |
416 | const char *optname) | ||
417 | { | ||
418 | const OptionDef *po; | ||
419 | int i; | ||
420 | |||
421 |
2/2✓ Branch 0 taken 767325 times.
✓ Branch 1 taken 33890 times.
|
801215 | for (i = 1; i < argc; i++) { |
422 | 767325 | const char *cur_opt = argv[i]; | |
423 | |||
424 |
2/2✓ Branch 0 taken 21273 times.
✓ Branch 1 taken 746052 times.
|
767325 | if (*cur_opt++ != '-') |
425 | 21273 | continue; | |
426 | |||
427 | 746052 | po = find_option(options, cur_opt); | |
428 |
5/6✓ Branch 0 taken 489612 times.
✓ Branch 1 taken 256440 times.
✓ Branch 2 taken 99520 times.
✓ Branch 3 taken 390092 times.
✓ Branch 4 taken 99520 times.
✗ Branch 5 not taken.
|
746052 | if (!po->name && cur_opt[0] == 'n' && cur_opt[1] == 'o') |
429 | 99520 | po = find_option(options, cur_opt + 2); | |
430 | |||
431 |
3/4✓ Branch 0 taken 390132 times.
✓ Branch 1 taken 355920 times.
✓ Branch 2 taken 390132 times.
✗ Branch 3 not taken.
|
746052 | if ((!po->name && !strcmp(cur_opt, optname)) || |
432 |
4/4✓ Branch 0 taken 355920 times.
✓ Branch 1 taken 390132 times.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 355905 times.
|
746052 | (po->name && !strcmp(optname, po->name))) |
433 | 15 | return i; | |
434 | |||
435 |
4/4✓ Branch 0 taken 355905 times.
✓ Branch 1 taken 390132 times.
✓ Branch 2 taken 225810 times.
✓ Branch 3 taken 130095 times.
|
746037 | if (!po->name || po->flags & HAS_ARG) |
436 | 615942 | i++; | |
437 | } | ||
438 | 33890 | return 0; | |
439 | } | ||
440 | |||
441 | ✗ | static void dump_argument(FILE *report_file, const char *a) | |
442 | { | ||
443 | const unsigned char *p; | ||
444 | |||
445 | ✗ | for (p = a; *p; p++) | |
446 | ✗ | if (!((*p >= '+' && *p <= ':') || (*p >= '@' && *p <= 'Z') || | |
447 | ✗ | *p == '_' || (*p >= 'a' && *p <= 'z'))) | |
448 | break; | ||
449 | ✗ | if (!*p) { | |
450 | ✗ | fputs(a, report_file); | |
451 | ✗ | return; | |
452 | } | ||
453 | ✗ | fputc('"', report_file); | |
454 | ✗ | for (p = a; *p; p++) { | |
455 | ✗ | if (*p == '\\' || *p == '"' || *p == '$' || *p == '`') | |
456 | ✗ | fprintf(report_file, "\\%c", *p); | |
457 | ✗ | else if (*p < ' ' || *p > '~') | |
458 | ✗ | fprintf(report_file, "\\x%02x", *p); | |
459 | else | ||
460 | ✗ | fputc(*p, report_file); | |
461 | } | ||
462 | ✗ | fputc('"', report_file); | |
463 | } | ||
464 | |||
465 | 6781 | static void check_options(const OptionDef *po) | |
466 | { | ||
467 |
2/2✓ Branch 0 taken 1285452 times.
✓ Branch 1 taken 6781 times.
|
1292233 | while (po->name) { |
468 |
2/2✓ Branch 0 taken 199470 times.
✓ Branch 1 taken 1085982 times.
|
1285452 | if (po->flags & OPT_PERFILE) |
469 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 199470 times.
|
199470 | av_assert0(po->flags & (OPT_INPUT | OPT_OUTPUT)); |
470 | 1285452 | po++; | |
471 | } | ||
472 | 6781 | } | |
473 | |||
474 | 6781 | void parse_loglevel(int argc, char **argv, const OptionDef *options) | |
475 | { | ||
476 | 6781 | int idx = locate_option(argc, argv, options, "loglevel"); | |
477 | char *env; | ||
478 | |||
479 | 6781 | check_options(options); | |
480 | |||
481 |
1/2✓ Branch 0 taken 6781 times.
✗ Branch 1 not taken.
|
6781 | if (!idx) |
482 | 6781 | idx = locate_option(argc, argv, options, "v"); | |
483 |
3/4✓ Branch 0 taken 15 times.
✓ Branch 1 taken 6766 times.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
|
6781 | if (idx && argv[idx + 1]) |
484 | 15 | opt_loglevel(NULL, "loglevel", argv[idx + 1]); | |
485 | 6781 | idx = locate_option(argc, argv, options, "report"); | |
486 | 6781 | env = getenv_utf8("FFREPORT"); | |
487 |
2/4✓ Branch 0 taken 6781 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6781 times.
|
6781 | if (env || idx) { |
488 | ✗ | FILE *report_file = NULL; | |
489 | ✗ | init_report(env, &report_file); | |
490 | ✗ | if (report_file) { | |
491 | int i; | ||
492 | ✗ | fprintf(report_file, "Command line:\n"); | |
493 | ✗ | for (i = 0; i < argc; i++) { | |
494 | ✗ | dump_argument(report_file, argv[i]); | |
495 | ✗ | fputc(i < argc - 1 ? ' ' : '\n', report_file); | |
496 | } | ||
497 | ✗ | fflush(report_file); | |
498 | } | ||
499 | } | ||
500 | 6781 | freeenv_utf8(env); | |
501 | 6781 | idx = locate_option(argc, argv, options, "hide_banner"); | |
502 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6781 times.
|
6781 | if (idx) |
503 | ✗ | hide_banner = 1; | |
504 | 6781 | } | |
505 | |||
506 | 241031 | static const AVOption *opt_find(void *obj, const char *name, const char *unit, | |
507 | int opt_flags, int search_flags) | ||
508 | { | ||
509 | 241031 | const AVOption *o = av_opt_find(obj, name, unit, opt_flags, search_flags); | |
510 |
4/4✓ Branch 0 taken 68896 times.
✓ Branch 1 taken 172135 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 68894 times.
|
241031 | if(o && !o->flags) |
511 | 2 | return NULL; | |
512 | 241029 | return o; | |
513 | } | ||
514 | |||
515 | #define FLAGS (o->type == AV_OPT_TYPE_FLAGS && (arg[0]=='-' || arg[0]=='+')) ? AV_DICT_APPEND : 0 | ||
516 | 88723 | int opt_default(void *optctx, const char *opt, const char *arg) | |
517 | { | ||
518 | const AVOption *o; | ||
519 | 88723 | int consumed = 0; | |
520 | char opt_stripped[128]; | ||
521 | const char *p; | ||
522 | 88723 | const AVClass *cc = avcodec_get_class(), *fc = avformat_get_class(); | |
523 | #if CONFIG_SWSCALE | ||
524 | 88723 | const AVClass *sc = sws_get_class(); | |
525 | #endif | ||
526 | #if CONFIG_SWRESAMPLE | ||
527 | 88723 | const AVClass *swr_class = swr_get_class(); | |
528 | #endif | ||
529 | |||
530 |
2/4✓ Branch 0 taken 88723 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 88723 times.
|
88723 | if (!strcmp(opt, "debug") || !strcmp(opt, "fdebug")) |
531 | ✗ | av_log_set_level(AV_LOG_DEBUG); | |
532 | |||
533 |
2/2✓ Branch 0 taken 88711 times.
✓ Branch 1 taken 12 times.
|
88723 | if (!(p = strchr(opt, ':'))) |
534 | 88711 | p = opt + strlen(opt); | |
535 | 88723 | av_strlcpy(opt_stripped, opt, FFMIN(sizeof(opt_stripped), p - opt + 1)); | |
536 | |||
537 |
2/2✓ Branch 1 taken 43612 times.
✓ Branch 2 taken 45111 times.
|
88723 | if ((o = opt_find(&cc, opt_stripped, NULL, 0, |
538 | 43612 | AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ)) || | |
539 |
8/8✓ Branch 0 taken 43609 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 43597 times.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 11902 times.
✓ Branch 5 taken 31695 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 11916 times.
|
55529 | ((opt[0] == 'v' || opt[0] == 'a' || opt[0] == 's') && |
540 | 11917 | (o = opt_find(&cc, opt + 1, NULL, 0, AV_OPT_SEARCH_FAKE_OBJ)))) { | |
541 |
5/6✓ Branch 0 taken 18334 times.
✓ Branch 1 taken 26778 times.
✓ Branch 2 taken 18334 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11847 times.
✓ Branch 5 taken 6487 times.
|
45112 | av_dict_set(&codec_opts, opt, arg, FLAGS); |
542 | 45112 | consumed = 1; | |
543 | } | ||
544 |
2/2✓ Branch 1 taken 11904 times.
✓ Branch 2 taken 76819 times.
|
88723 | if ((o = opt_find(&fc, opt, NULL, 0, |
545 | AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) { | ||
546 |
5/6✓ Branch 0 taken 11703 times.
✓ Branch 1 taken 201 times.
✓ Branch 2 taken 11703 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11695 times.
✓ Branch 5 taken 8 times.
|
11904 | av_dict_set(&format_opts, opt, arg, FLAGS); |
547 |
2/2✓ Branch 0 taken 66 times.
✓ Branch 1 taken 11838 times.
|
11904 | if (consumed) |
548 | 66 | av_log(NULL, AV_LOG_VERBOSE, "Routing option %s to both codec and muxer layer\n", opt); | |
549 | 11904 | consumed = 1; | |
550 | } | ||
551 | #if CONFIG_SWSCALE | ||
552 |
4/4✓ Branch 0 taken 31773 times.
✓ Branch 1 taken 56950 times.
✓ Branch 3 taken 11878 times.
✓ Branch 4 taken 19895 times.
|
88723 | if (!consumed && (o = opt_find(&sc, opt, NULL, 0, |
553 | AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) { | ||
554 |
2/4✓ Branch 0 taken 11878 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11878 times.
✗ Branch 3 not taken.
|
11878 | if (!strcmp(opt, "srcw") || !strcmp(opt, "srch") || |
555 |
2/4✓ Branch 0 taken 11878 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11878 times.
✗ Branch 3 not taken.
|
11878 | !strcmp(opt, "dstw") || !strcmp(opt, "dsth") || |
556 |
2/4✓ Branch 0 taken 11878 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11878 times.
|
11878 | !strcmp(opt, "src_format") || !strcmp(opt, "dst_format")) { |
557 | ✗ | av_log(NULL, AV_LOG_ERROR, "Directly using swscale dimensions/format options is not supported, please use the -s or -pix_fmt options\n"); | |
558 | ✗ | return AVERROR(EINVAL); | |
559 | } | ||
560 |
4/6✓ Branch 0 taken 11878 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11878 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11693 times.
✓ Branch 5 taken 185 times.
|
11878 | av_dict_set(&sws_dict, opt, arg, FLAGS); |
561 | |||
562 | 11878 | consumed = 1; | |
563 | } | ||
564 | #else | ||
565 | if (!consumed && !strcmp(opt, "sws_flags")) { | ||
566 | av_log(NULL, AV_LOG_WARNING, "Ignoring %s %s, due to disabled swscale\n", opt, arg); | ||
567 | consumed = 1; | ||
568 | } | ||
569 | #endif | ||
570 | #if CONFIG_SWRESAMPLE | ||
571 |
3/4✓ Branch 0 taken 19895 times.
✓ Branch 1 taken 68828 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 19895 times.
|
88723 | if (!consumed && (o=opt_find(&swr_class, opt, NULL, 0, |
572 | AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) { | ||
573 | ✗ | av_dict_set(&swr_opts, opt, arg, FLAGS); | |
574 | ✗ | consumed = 1; | |
575 | } | ||
576 | #endif | ||
577 | |||
578 |
2/2✓ Branch 0 taken 68828 times.
✓ Branch 1 taken 19895 times.
|
88723 | if (consumed) |
579 | 68828 | return 0; | |
580 | 19895 | return AVERROR_OPTION_NOT_FOUND; | |
581 | } | ||
582 | |||
583 | /* | ||
584 | * Check whether given option is a group separator. | ||
585 | * | ||
586 | * @return index of the group definition that matched or -1 if none | ||
587 | */ | ||
588 | 146217 | static int match_group_separator(const OptionGroupDef *groups, int nb_groups, | |
589 | const char *opt) | ||
590 | { | ||
591 | int i; | ||
592 | |||
593 |
2/2✓ Branch 0 taken 292434 times.
✓ Branch 1 taken 139535 times.
|
431969 | for (i = 0; i < nb_groups; i++) { |
594 | 292434 | const OptionGroupDef *p = &groups[i]; | |
595 |
4/4✓ Branch 0 taken 146217 times.
✓ Branch 1 taken 146217 times.
✓ Branch 2 taken 6682 times.
✓ Branch 3 taken 139535 times.
|
292434 | if (p->sep && !strcmp(p->sep, opt)) |
596 | 6682 | return i; | |
597 | } | ||
598 | |||
599 | 139535 | return -1; | |
600 | } | ||
601 | |||
602 | /* | ||
603 | * Finish parsing an option group. | ||
604 | * | ||
605 | * @param group_idx which group definition should this group belong to | ||
606 | * @param arg argument of the group delimiting option | ||
607 | */ | ||
608 | 13332 | static int finish_group(OptionParseContext *octx, int group_idx, | |
609 | const char *arg) | ||
610 | { | ||
611 | 13332 | OptionGroupList *l = &octx->groups[group_idx]; | |
612 | OptionGroup *g; | ||
613 | int ret; | ||
614 | |||
615 | 13332 | ret = GROW_ARRAY(l->groups, l->nb_groups); | |
616 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13332 times.
|
13332 | if (ret < 0) |
617 | ✗ | return ret; | |
618 | |||
619 | 13332 | g = &l->groups[l->nb_groups - 1]; | |
620 | |||
621 | 13332 | *g = octx->cur_group; | |
622 | 13332 | g->arg = arg; | |
623 | 13332 | g->group_def = l->group_def; | |
624 | 13332 | g->sws_dict = sws_dict; | |
625 | 13332 | g->swr_opts = swr_opts; | |
626 | 13332 | g->codec_opts = codec_opts; | |
627 | 13332 | g->format_opts = format_opts; | |
628 | |||
629 | 13332 | codec_opts = NULL; | |
630 | 13332 | format_opts = NULL; | |
631 | 13332 | sws_dict = NULL; | |
632 | 13332 | swr_opts = NULL; | |
633 | |||
634 | 13332 | memset(&octx->cur_group, 0, sizeof(octx->cur_group)); | |
635 | |||
636 | 13332 | return ret; | |
637 | } | ||
638 | |||
639 | /* | ||
640 | * Add an option instance to currently parsed group. | ||
641 | */ | ||
642 | 70714 | static int add_opt(OptionParseContext *octx, const OptionDef *opt, | |
643 | const char *key, const char *val) | ||
644 | { | ||
645 | 70714 | int global = !(opt->flags & (OPT_PERFILE | OPT_SPEC | OPT_OFFSET)); | |
646 |
2/2✓ Branch 0 taken 31210 times.
✓ Branch 1 taken 39504 times.
|
70714 | OptionGroup *g = global ? &octx->global_opts : &octx->cur_group; |
647 | int ret; | ||
648 | |||
649 | 70714 | ret = GROW_ARRAY(g->opts, g->nb_opts); | |
650 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 70714 times.
|
70714 | if (ret < 0) |
651 | ✗ | return ret; | |
652 | |||
653 | 70714 | g->opts[g->nb_opts - 1].opt = opt; | |
654 | 70714 | g->opts[g->nb_opts - 1].key = key; | |
655 | 70714 | g->opts[g->nb_opts - 1].val = val; | |
656 | |||
657 | 70714 | return 0; | |
658 | } | ||
659 | |||
660 | 6649 | static int init_parse_context(OptionParseContext *octx, | |
661 | const OptionGroupDef *groups, int nb_groups) | ||
662 | { | ||
663 | static const OptionGroupDef global_group = { "global" }; | ||
664 | int i; | ||
665 | |||
666 | 6649 | memset(octx, 0, sizeof(*octx)); | |
667 | |||
668 | 6649 | octx->nb_groups = nb_groups; | |
669 | 6649 | octx->groups = av_calloc(octx->nb_groups, sizeof(*octx->groups)); | |
670 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6649 times.
|
6649 | if (!octx->groups) |
671 | ✗ | return AVERROR(ENOMEM); | |
672 | |||
673 |
2/2✓ Branch 0 taken 13298 times.
✓ Branch 1 taken 6649 times.
|
19947 | for (i = 0; i < octx->nb_groups; i++) |
674 | 13298 | octx->groups[i].group_def = &groups[i]; | |
675 | |||
676 | 6649 | octx->global_opts.group_def = &global_group; | |
677 | 6649 | octx->global_opts.arg = ""; | |
678 | |||
679 | 6649 | return 0; | |
680 | } | ||
681 | |||
682 | 6649 | void uninit_parse_context(OptionParseContext *octx) | |
683 | { | ||
684 | int i, j; | ||
685 | |||
686 |
2/2✓ Branch 0 taken 13298 times.
✓ Branch 1 taken 6649 times.
|
19947 | for (i = 0; i < octx->nb_groups; i++) { |
687 | 13298 | OptionGroupList *l = &octx->groups[i]; | |
688 | |||
689 |
2/2✓ Branch 0 taken 13332 times.
✓ Branch 1 taken 13298 times.
|
26630 | for (j = 0; j < l->nb_groups; j++) { |
690 | 13332 | av_freep(&l->groups[j].opts); | |
691 | 13332 | av_dict_free(&l->groups[j].codec_opts); | |
692 | 13332 | av_dict_free(&l->groups[j].format_opts); | |
693 | |||
694 | 13332 | av_dict_free(&l->groups[j].sws_dict); | |
695 | 13332 | av_dict_free(&l->groups[j].swr_opts); | |
696 | } | ||
697 | 13298 | av_freep(&l->groups); | |
698 | } | ||
699 | 6649 | av_freep(&octx->groups); | |
700 | |||
701 | 6649 | av_freep(&octx->cur_group.opts); | |
702 | 6649 | av_freep(&octx->global_opts.opts); | |
703 | |||
704 | 6649 | uninit_opts(); | |
705 | 6649 | } | |
706 | |||
707 | 6649 | int split_commandline(OptionParseContext *octx, int argc, char *argv[], | |
708 | const OptionDef *options, | ||
709 | const OptionGroupDef *groups, int nb_groups) | ||
710 | { | ||
711 | int ret; | ||
712 | 6649 | int optindex = 1; | |
713 | 6649 | int dashdash = -2; | |
714 | |||
715 | /* perform system-dependent conversions for arguments list */ | ||
716 | 6649 | prepare_app_arguments(&argc, &argv); | |
717 | |||
718 | 6649 | ret = init_parse_context(octx, groups, nb_groups); | |
719 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6649 times.
|
6649 | if (ret < 0) |
720 | ✗ | return ret; | |
721 | |||
722 | 6649 | av_log(NULL, AV_LOG_DEBUG, "Splitting the commandline.\n"); | |
723 | |||
724 |
2/2✓ Branch 0 taken 152867 times.
✓ Branch 1 taken 6649 times.
|
159516 | while (optindex < argc) { |
725 | 152867 | const char *opt = argv[optindex++], *arg; | |
726 | const OptionDef *po; | ||
727 | int ret; | ||
728 | |||
729 | 152867 | av_log(NULL, AV_LOG_DEBUG, "Reading option '%s' ...", opt); | |
730 | |||
731 |
3/6✓ Branch 0 taken 148735 times.
✓ Branch 1 taken 4132 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 148735 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
152867 | if (opt[0] == '-' && opt[1] == '-' && !opt[2]) { |
732 | ✗ | dashdash = optindex; | |
733 | ✗ | continue; | |
734 | } | ||
735 | /* unnamed group separators, e.g. output filename */ | ||
736 |
5/6✓ Branch 0 taken 148735 times.
✓ Branch 1 taken 4132 times.
✓ Branch 2 taken 146217 times.
✓ Branch 3 taken 2518 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 146217 times.
|
152867 | if (opt[0] != '-' || !opt[1] || dashdash+1 == optindex) { |
737 | 6650 | ret = finish_group(octx, 0, opt); | |
738 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6650 times.
|
6650 | if (ret < 0) |
739 | ✗ | return ret; | |
740 | |||
741 | 6650 | av_log(NULL, AV_LOG_DEBUG, " matched as %s.\n", groups[0].name); | |
742 | 6650 | continue; | |
743 | } | ||
744 | 146217 | opt++; | |
745 | |||
746 | #define GET_ARG(arg) \ | ||
747 | do { \ | ||
748 | arg = argv[optindex++]; \ | ||
749 | if (!arg) { \ | ||
750 | av_log(NULL, AV_LOG_ERROR, "Missing argument for option '%s'.\n", opt);\ | ||
751 | return AVERROR(EINVAL); \ | ||
752 | } \ | ||
753 | } while (0) | ||
754 | |||
755 | /* named group separators, e.g. -i */ | ||
756 |
2/2✓ Branch 1 taken 6682 times.
✓ Branch 2 taken 139535 times.
|
146217 | if ((ret = match_group_separator(groups, nb_groups, opt)) >= 0) { |
757 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6682 times.
|
6682 | GET_ARG(arg); |
758 | 6682 | ret = finish_group(octx, ret, arg); | |
759 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6682 times.
|
6682 | if (ret < 0) |
760 | ✗ | return ret; | |
761 | |||
762 | 6682 | av_log(NULL, AV_LOG_DEBUG, " matched as %s with argument '%s'.\n", | |
763 | 6682 | groups[ret].name, arg); | |
764 | 6682 | continue; | |
765 | } | ||
766 | |||
767 | /* normal options */ | ||
768 | 139535 | po = find_option(options, opt); | |
769 |
2/2✓ Branch 0 taken 50819 times.
✓ Branch 1 taken 88716 times.
|
139535 | if (po->name) { |
770 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 50818 times.
|
50819 | if (po->flags & OPT_EXIT) { |
771 | /* optional argument, e.g. -h */ | ||
772 | 1 | arg = argv[optindex++]; | |
773 |
2/2✓ Branch 0 taken 44923 times.
✓ Branch 1 taken 5895 times.
|
50818 | } else if (po->flags & HAS_ARG) { |
774 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 44923 times.
|
44923 | GET_ARG(arg); |
775 | } else { | ||
776 | 5895 | arg = "1"; | |
777 | } | ||
778 | |||
779 | 50819 | ret = add_opt(octx, po, opt, arg); | |
780 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 50819 times.
|
50819 | if (ret < 0) |
781 | ✗ | return ret; | |
782 | |||
783 | 50819 | av_log(NULL, AV_LOG_DEBUG, " matched as option '%s' (%s) with " | |
784 | 50819 | "argument '%s'.\n", po->name, po->help, arg); | |
785 | 50819 | continue; | |
786 | } | ||
787 | |||
788 | /* AVOptions */ | ||
789 |
1/2✓ Branch 0 taken 88716 times.
✗ Branch 1 not taken.
|
88716 | if (argv[optindex]) { |
790 | 88716 | ret = opt_default(NULL, opt, argv[optindex]); | |
791 |
2/2✓ Branch 0 taken 68821 times.
✓ Branch 1 taken 19895 times.
|
88716 | if (ret >= 0) { |
792 | 68821 | av_log(NULL, AV_LOG_DEBUG, " matched as AVOption '%s' with " | |
793 | 68821 | "argument '%s'.\n", opt, argv[optindex]); | |
794 | 68821 | optindex++; | |
795 | 68821 | continue; | |
796 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19895 times.
|
19895 | } else if (ret != AVERROR_OPTION_NOT_FOUND) { |
797 | ✗ | av_log(NULL, AV_LOG_ERROR, "Error parsing option '%s' " | |
798 | ✗ | "with argument '%s'.\n", opt, argv[optindex]); | |
799 | ✗ | return ret; | |
800 | } | ||
801 | } | ||
802 | |||
803 | /* boolean -nofoo options */ | ||
804 |
3/6✓ Branch 0 taken 19895 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19895 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 19895 times.
✗ Branch 5 not taken.
|
39790 | if (opt[0] == 'n' && opt[1] == 'o' && |
805 | 19895 | (po = find_option(options, opt + 2)) && | |
806 |
2/4✓ Branch 0 taken 19895 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19895 times.
✗ Branch 3 not taken.
|
19895 | po->name && po->flags & OPT_BOOL) { |
807 | 19895 | ret = add_opt(octx, po, opt, "0"); | |
808 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19895 times.
|
19895 | if (ret < 0) |
809 | ✗ | return ret; | |
810 | |||
811 | 19895 | av_log(NULL, AV_LOG_DEBUG, " matched as option '%s' (%s) with " | |
812 | 19895 | "argument 0.\n", po->name, po->help); | |
813 | 19895 | continue; | |
814 | } | ||
815 | |||
816 | ✗ | av_log(NULL, AV_LOG_ERROR, "Unrecognized option '%s'.\n", opt); | |
817 | ✗ | return AVERROR_OPTION_NOT_FOUND; | |
818 | } | ||
819 | |||
820 |
3/6✓ Branch 0 taken 6649 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6649 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 6649 times.
|
6649 | if (octx->cur_group.nb_opts || codec_opts || format_opts) |
821 | ✗ | av_log(NULL, AV_LOG_WARNING, "Trailing option(s) found in the " | |
822 | "command: may be ignored.\n"); | ||
823 | |||
824 | 6649 | av_log(NULL, AV_LOG_DEBUG, "Finished splitting the commandline.\n"); | |
825 | |||
826 | 6649 | return 0; | |
827 | } | ||
828 | |||
829 | ✗ | void print_error(const char *filename, int err) | |
830 | { | ||
831 | ✗ | av_log(NULL, AV_LOG_ERROR, "%s: %s\n", filename, av_err2str(err)); | |
832 | ✗ | } | |
833 | |||
834 | ✗ | int read_yesno(void) | |
835 | { | ||
836 | ✗ | int c = getchar(); | |
837 | ✗ | int yesno = (av_toupper(c) == 'Y'); | |
838 | |||
839 | ✗ | while (c != '\n' && c != EOF) | |
840 | ✗ | c = getchar(); | |
841 | |||
842 | ✗ | return yesno; | |
843 | } | ||
844 | |||
845 | ✗ | FILE *get_preset_file(char *filename, size_t filename_size, | |
846 | const char *preset_name, int is_path, | ||
847 | const char *codec_name) | ||
848 | { | ||
849 | ✗ | FILE *f = NULL; | |
850 | int i; | ||
851 | #if HAVE_GETMODULEHANDLE && defined(_WIN32) | ||
852 | char *datadir = NULL; | ||
853 | #endif | ||
854 | ✗ | char *env_home = getenv_utf8("HOME"); | |
855 | ✗ | char *env_ffmpeg_datadir = getenv_utf8("FFMPEG_DATADIR"); | |
856 | ✗ | const char *base[3] = { env_ffmpeg_datadir, | |
857 | env_home, /* index=1(HOME) is special: search in a .ffmpeg subfolder */ | ||
858 | FFMPEG_DATADIR, }; | ||
859 | |||
860 | ✗ | if (is_path) { | |
861 | ✗ | av_strlcpy(filename, preset_name, filename_size); | |
862 | ✗ | f = fopen_utf8(filename, "r"); | |
863 | } else { | ||
864 | #if HAVE_GETMODULEHANDLE && defined(_WIN32) | ||
865 | wchar_t *datadir_w = get_module_filename(NULL); | ||
866 | base[2] = NULL; | ||
867 | |||
868 | if (wchartoutf8(datadir_w, &datadir)) | ||
869 | datadir = NULL; | ||
870 | av_free(datadir_w); | ||
871 | |||
872 | if (datadir) | ||
873 | { | ||
874 | char *ls; | ||
875 | for (ls = datadir; *ls; ls++) | ||
876 | if (*ls == '\\') *ls = '/'; | ||
877 | |||
878 | if (ls = strrchr(datadir, '/')) | ||
879 | { | ||
880 | ptrdiff_t datadir_len = ls - datadir; | ||
881 | size_t desired_size = datadir_len + strlen("/ffpresets") + 1; | ||
882 | char *new_datadir = av_realloc_array( | ||
883 | datadir, desired_size, sizeof *datadir); | ||
884 | if (new_datadir) { | ||
885 | datadir = new_datadir; | ||
886 | datadir[datadir_len] = 0; | ||
887 | strncat(datadir, "/ffpresets", desired_size - 1 - datadir_len); | ||
888 | base[2] = datadir; | ||
889 | } | ||
890 | } | ||
891 | } | ||
892 | #endif | ||
893 | ✗ | for (i = 0; i < 3 && !f; i++) { | |
894 | ✗ | if (!base[i]) | |
895 | ✗ | continue; | |
896 | ✗ | snprintf(filename, filename_size, "%s%s/%s.ffpreset", base[i], | |
897 | i != 1 ? "" : "/.ffmpeg", preset_name); | ||
898 | ✗ | f = fopen_utf8(filename, "r"); | |
899 | ✗ | if (!f && codec_name) { | |
900 | ✗ | snprintf(filename, filename_size, | |
901 | "%s%s/%s-%s.ffpreset", | ||
902 | base[i], i != 1 ? "" : "/.ffmpeg", codec_name, | ||
903 | preset_name); | ||
904 | ✗ | f = fopen_utf8(filename, "r"); | |
905 | } | ||
906 | } | ||
907 | } | ||
908 | |||
909 | #if HAVE_GETMODULEHANDLE && defined(_WIN32) | ||
910 | av_free(datadir); | ||
911 | #endif | ||
912 | ✗ | freeenv_utf8(env_ffmpeg_datadir); | |
913 | ✗ | freeenv_utf8(env_home); | |
914 | ✗ | return f; | |
915 | } | ||
916 | |||
917 | 28589 | int check_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec) | |
918 | { | ||
919 | 28589 | int ret = avformat_match_stream_specifier(s, st, spec); | |
920 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 28589 times.
|
28589 | if (ret < 0) |
921 | ✗ | av_log(s, AV_LOG_ERROR, "Invalid stream specifier: %s.\n", spec); | |
922 | 28589 | return ret; | |
923 | } | ||
924 | |||
925 | 21527 | int filter_codec_opts(const AVDictionary *opts, enum AVCodecID codec_id, | |
926 | AVFormatContext *s, AVStream *st, const AVCodec *codec, | ||
927 | AVDictionary **dst) | ||
928 | { | ||
929 | 21527 | AVDictionary *ret = NULL; | |
930 | 21527 | const AVDictionaryEntry *t = NULL; | |
931 | 43054 | int flags = s->oformat ? AV_OPT_FLAG_ENCODING_PARAM | |
932 |
2/2✓ Branch 0 taken 6923 times.
✓ Branch 1 taken 14604 times.
|
21527 | : AV_OPT_FLAG_DECODING_PARAM; |
933 | 21527 | char prefix = 0; | |
934 | 21527 | const AVClass *cc = avcodec_get_class(); | |
935 | |||
936 |
2/2✓ Branch 0 taken 7901 times.
✓ Branch 1 taken 13626 times.
|
21527 | if (!codec) |
937 | 7901 | codec = s->oformat ? avcodec_find_encoder(codec_id) | |
938 |
2/2✓ Branch 0 taken 565 times.
✓ Branch 1 taken 7336 times.
|
7901 | : avcodec_find_decoder(codec_id); |
939 | |||
940 |
4/4✓ Branch 0 taken 16493 times.
✓ Branch 1 taken 4655 times.
✓ Branch 2 taken 240 times.
✓ Branch 3 taken 139 times.
|
21527 | switch (st->codecpar->codec_type) { |
941 | 16493 | case AVMEDIA_TYPE_VIDEO: | |
942 | 16493 | prefix = 'v'; | |
943 | 16493 | flags |= AV_OPT_FLAG_VIDEO_PARAM; | |
944 | 16493 | break; | |
945 | 4655 | case AVMEDIA_TYPE_AUDIO: | |
946 | 4655 | prefix = 'a'; | |
947 | 4655 | flags |= AV_OPT_FLAG_AUDIO_PARAM; | |
948 | 4655 | break; | |
949 | 240 | case AVMEDIA_TYPE_SUBTITLE: | |
950 | 240 | prefix = 's'; | |
951 | 240 | flags |= AV_OPT_FLAG_SUBTITLE_PARAM; | |
952 | 240 | break; | |
953 | } | ||
954 | |||
955 |
2/2✓ Branch 1 taken 62380 times.
✓ Branch 2 taken 21527 times.
|
83907 | while (t = av_dict_iterate(opts, t)) { |
956 | const AVClass *priv_class; | ||
957 | 62380 | char *p = strchr(t->key, ':'); | |
958 | |||
959 | /* check stream specification in opt name */ | ||
960 |
2/2✓ Branch 0 taken 286 times.
✓ Branch 1 taken 62094 times.
|
62380 | if (p) { |
961 | 286 | int err = check_stream_specifier(s, st, p + 1); | |
962 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 286 times.
|
286 | if (err < 0) { |
963 | ✗ | av_dict_free(&ret); | |
964 | ✗ | return err; | |
965 |
2/2✓ Branch 0 taken 77 times.
✓ Branch 1 taken 209 times.
|
286 | } else if (!err) |
966 | 77 | continue; | |
967 | |||
968 | 209 | *p = 0; | |
969 | } | ||
970 | |||
971 |
4/4✓ Branch 1 taken 2329 times.
✓ Branch 2 taken 59974 times.
✓ Branch 3 taken 1992 times.
✓ Branch 4 taken 337 times.
|
62303 | if (av_opt_find(&cc, t->key, NULL, flags, AV_OPT_SEARCH_FAKE_OBJ) || |
972 | 1992 | !codec || | |
973 |
4/4✓ Branch 0 taken 721 times.
✓ Branch 1 taken 1271 times.
✓ Branch 2 taken 320 times.
✓ Branch 3 taken 401 times.
|
2713 | ((priv_class = codec->priv_class) && |
974 | 721 | av_opt_find(&priv_class, t->key, NULL, flags, | |
975 | AV_OPT_SEARCH_FAKE_OBJ))) | ||
976 | 60631 | av_dict_set(&ret, t->key, t->value, 0); | |
977 |
4/4✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1669 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
|
1675 | else if (t->key[0] == prefix && |
978 | 3 | av_opt_find(&cc, t->key + 1, NULL, flags, | |
979 | AV_OPT_SEARCH_FAKE_OBJ)) | ||
980 | 1 | av_dict_set(&ret, t->key + 1, t->value, 0); | |
981 | |||
982 |
2/2✓ Branch 0 taken 209 times.
✓ Branch 1 taken 62094 times.
|
62303 | if (p) |
983 | 209 | *p = ':'; | |
984 | } | ||
985 | |||
986 | 21527 | *dst = ret; | |
987 | 21527 | return 0; | |
988 | } | ||
989 | |||
990 | 6812 | int setup_find_stream_info_opts(AVFormatContext *s, | |
991 | AVDictionary *codec_opts, | ||
992 | AVDictionary ***dst) | ||
993 | { | ||
994 | int ret; | ||
995 | AVDictionary **opts; | ||
996 | |||
997 | 6812 | *dst = NULL; | |
998 | |||
999 |
2/2✓ Branch 0 taken 84 times.
✓ Branch 1 taken 6728 times.
|
6812 | if (!s->nb_streams) |
1000 | 84 | return 0; | |
1001 | |||
1002 | 6728 | opts = av_calloc(s->nb_streams, sizeof(*opts)); | |
1003 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6728 times.
|
6728 | if (!opts) |
1004 | ✗ | return AVERROR(ENOMEM); | |
1005 | |||
1006 |
2/2✓ Branch 0 taken 7241 times.
✓ Branch 1 taken 6728 times.
|
13969 | for (int i = 0; i < s->nb_streams; i++) { |
1007 | 7241 | ret = filter_codec_opts(codec_opts, s->streams[i]->codecpar->codec_id, | |
1008 | 7241 | s, s->streams[i], NULL, &opts[i]); | |
1009 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7241 times.
|
7241 | if (ret < 0) |
1010 | ✗ | goto fail; | |
1011 | } | ||
1012 | 6728 | *dst = opts; | |
1013 | 6728 | return 0; | |
1014 | ✗ | fail: | |
1015 | ✗ | for (int i = 0; i < s->nb_streams; i++) | |
1016 | ✗ | av_dict_free(&opts[i]); | |
1017 | ✗ | av_freep(&opts); | |
1018 | ✗ | return ret; | |
1019 | } | ||
1020 | |||
1021 | 118189 | int grow_array(void **array, int elem_size, int *size, int new_size) | |
1022 | { | ||
1023 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 118189 times.
|
118189 | if (new_size >= INT_MAX / elem_size) { |
1024 | ✗ | av_log(NULL, AV_LOG_ERROR, "Array too big.\n"); | |
1025 | ✗ | return AVERROR(ERANGE); | |
1026 | } | ||
1027 |
1/2✓ Branch 0 taken 118189 times.
✗ Branch 1 not taken.
|
118189 | if (*size < new_size) { |
1028 | 118189 | uint8_t *tmp = av_realloc_array(*array, new_size, elem_size); | |
1029 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 118189 times.
|
118189 | if (!tmp) |
1030 | ✗ | return AVERROR(ENOMEM); | |
1031 | 118189 | memset(tmp + *size*elem_size, 0, (new_size-*size) * elem_size); | |
1032 | 118189 | *size = new_size; | |
1033 | 118189 | *array = tmp; | |
1034 | 118189 | return 0; | |
1035 | } | ||
1036 | ✗ | return 0; | |
1037 | } | ||
1038 | |||
1039 | 46326 | void *allocate_array_elem(void *ptr, size_t elem_size, int *nb_elems) | |
1040 | { | ||
1041 | void *new_elem; | ||
1042 | |||
1043 |
2/4✓ Branch 1 taken 46326 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 46326 times.
|
92652 | if (!(new_elem = av_mallocz(elem_size)) || |
1044 | 46326 | av_dynarray_add_nofree(ptr, nb_elems, new_elem) < 0) | |
1045 | ✗ | return NULL; | |
1046 | 46326 | return new_elem; | |
1047 | } | ||
1048 | |||
1049 | 5133 | double get_rotation(const int32_t *displaymatrix) | |
1050 | { | ||
1051 | 5133 | double theta = 0; | |
1052 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5132 times.
|
5133 | if (displaymatrix) |
1053 | 1 | theta = -round(av_display_rotation_get((int32_t*) displaymatrix)); | |
1054 | |||
1055 | 5133 | theta -= 360*floor(theta/360 + 0.9/360); | |
1056 | |||
1057 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5133 times.
|
5133 | if (fabs(theta - 90*round(theta/90)) > 2) |
1058 | ✗ | av_log(NULL, AV_LOG_WARNING, "Odd rotation angle.\n" | |
1059 | "If you want to help, upload a sample " | ||
1060 | "of this file to https://streams.videolan.org/upload/ " | ||
1061 | "and contact the ffmpeg-devel mailing list. (ffmpeg-devel@ffmpeg.org)"); | ||
1062 | |||
1063 | 5133 | return theta; | |
1064 | } | ||
1065 |