Directory: | ../../../ffmpeg/ |
---|---|
File: | src/fftools/cmdutils.c |
Date: | 2022-07-04 00:18:54 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 359 | 486 | 73.9% |
Branches: | 249 | 409 | 60.9% |
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 | 12612 | void uninit_opts(void) | |
65 | { | ||
66 | 12612 | av_dict_free(&swr_opts); | |
67 | 12612 | av_dict_free(&sws_dict); | |
68 | 12612 | av_dict_free(&format_opts); | |
69 | 12612 | av_dict_free(&codec_opts); | |
70 | 12612 | } | |
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 | 6364 | 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 | 6364 | } | |
85 | |||
86 | static void (*program_exit)(int ret); | ||
87 | |||
88 | 6364 | void register_exit(void (*cb)(int ret)) | |
89 | { | ||
90 | 6364 | program_exit = cb; | |
91 | 6364 | } | |
92 | |||
93 | 6249 | void exit_program(int ret) | |
94 | { | ||
95 |
1/2✓ Branch 0 taken 6249 times.
✗ Branch 1 not taken.
|
6249 | if (program_exit) |
96 | 6249 | program_exit(ret); | |
97 | |||
98 | 6249 | exit(ret); | |
99 | } | ||
100 | |||
101 | 29248 | double parse_number_or_die(const char *context, const char *numstr, int type, | |
102 | double min, double max) | ||
103 | { | ||
104 | char *tail; | ||
105 | const char *error; | ||
106 | 29248 | double d = av_strtod(numstr, &tail); | |
107 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 29248 times.
|
29248 | if (*tail) |
108 | ✗ | error = "Expected number for %s but found: %s\n"; | |
109 |
2/4✓ Branch 0 taken 29248 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 29248 times.
|
29248 | else if (d < min || d > max) |
110 | ✗ | error = "The value for %s was %s which is not within %f - %f\n"; | |
111 |
3/4✓ Branch 0 taken 28974 times.
✓ Branch 1 taken 274 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 28974 times.
|
29248 | else if (type == OPT_INT64 && (int64_t)d != d) |
112 | ✗ | error = "Expected int64 for %s but found %s\n"; | |
113 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 29248 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
29248 | else if (type == OPT_INT && (int)d != d) |
114 | ✗ | error = "Expected int for %s but found %s\n"; | |
115 | else | ||
116 | 29248 | return d; | |
117 | ✗ | av_log(NULL, AV_LOG_FATAL, error, context, numstr, min, max); | |
118 | ✗ | exit_program(1); | |
119 | return 0; | ||
120 | } | ||
121 | |||
122 | 188 | int64_t parse_time_or_die(const char *context, const char *timestr, | |
123 | int is_duration) | ||
124 | { | ||
125 | int64_t us; | ||
126 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 188 times.
|
188 | if (av_parse_time(&us, timestr, is_duration) < 0) { |
127 | ✗ | av_log(NULL, AV_LOG_FATAL, "Invalid %s specification for %s: %s\n", | |
128 | is_duration ? "duration" : "date", context, timestr); | ||
129 | ✗ | exit_program(1); | |
130 | } | ||
131 | 188 | return us; | |
132 | } | ||
133 | |||
134 | ✗ | void show_help_options(const OptionDef *options, const char *msg, int req_flags, | |
135 | int rej_flags, int alt_flags) | ||
136 | { | ||
137 | const OptionDef *po; | ||
138 | int first; | ||
139 | |||
140 | ✗ | first = 1; | |
141 | ✗ | for (po = options; po->name; po++) { | |
142 | char buf[128]; | ||
143 | |||
144 | ✗ | if (((po->flags & req_flags) != req_flags) || | |
145 | ✗ | (alt_flags && !(po->flags & alt_flags)) || | |
146 | ✗ | (po->flags & rej_flags)) | |
147 | ✗ | continue; | |
148 | |||
149 | ✗ | if (first) { | |
150 | ✗ | printf("%s\n", msg); | |
151 | ✗ | first = 0; | |
152 | } | ||
153 | ✗ | av_strlcpy(buf, po->name, sizeof(buf)); | |
154 | ✗ | if (po->argname) { | |
155 | ✗ | av_strlcat(buf, " ", sizeof(buf)); | |
156 | ✗ | av_strlcat(buf, po->argname, sizeof(buf)); | |
157 | } | ||
158 | ✗ | printf("-%-17s %s\n", buf, po->help); | |
159 | } | ||
160 | ✗ | printf("\n"); | |
161 | } | ||
162 | |||
163 | ✗ | void show_help_children(const AVClass *class, int flags) | |
164 | { | ||
165 | ✗ | void *iter = NULL; | |
166 | const AVClass *child; | ||
167 | ✗ | if (class->option) { | |
168 | ✗ | av_opt_show2(&class, NULL, flags, 0); | |
169 | ✗ | printf("\n"); | |
170 | } | ||
171 | |||
172 | ✗ | while (child = av_opt_child_class_iterate(class, &iter)) | |
173 | ✗ | show_help_children(child, flags); | |
174 | } | ||
175 | |||
176 | 947363 | static const OptionDef *find_option(const OptionDef *po, const char *name) | |
177 | { | ||
178 |
2/2✓ Branch 0 taken 130393821 times.
✓ Branch 1 taken 538565 times.
|
130932386 | while (po->name) { |
179 | const char *end; | ||
180 |
6/6✓ Branch 1 taken 959460 times.
✓ Branch 2 taken 129434361 times.
✓ Branch 3 taken 593292 times.
✓ Branch 4 taken 366168 times.
✓ Branch 5 taken 550662 times.
✓ Branch 6 taken 42630 times.
|
130393821 | if (av_strstart(name, po->name, &end) && (!*end || *end == ':')) |
181 | break; | ||
182 | 129985023 | po++; | |
183 | } | ||
184 | 947363 | return po; | |
185 | } | ||
186 | |||
187 | /* _WIN32 means using the windows libc - cygwin doesn't define that | ||
188 | * by default. HAVE_COMMANDLINETOARGVW is true on cygwin, while | ||
189 | * it doesn't provide the actual command line via GetCommandLineW(). */ | ||
190 | #if HAVE_COMMANDLINETOARGVW && defined(_WIN32) | ||
191 | #include <shellapi.h> | ||
192 | /* Will be leaked on exit */ | ||
193 | static char** win32_argv_utf8 = NULL; | ||
194 | static int win32_argc = 0; | ||
195 | |||
196 | /** | ||
197 | * Prepare command line arguments for executable. | ||
198 | * For Windows - perform wide-char to UTF-8 conversion. | ||
199 | * Input arguments should be main() function arguments. | ||
200 | * @param argc_ptr Arguments number (including executable) | ||
201 | * @param argv_ptr Arguments list. | ||
202 | */ | ||
203 | static void prepare_app_arguments(int *argc_ptr, char ***argv_ptr) | ||
204 | { | ||
205 | char *argstr_flat; | ||
206 | wchar_t **argv_w; | ||
207 | int i, buffsize = 0, offset = 0; | ||
208 | |||
209 | if (win32_argv_utf8) { | ||
210 | *argc_ptr = win32_argc; | ||
211 | *argv_ptr = win32_argv_utf8; | ||
212 | return; | ||
213 | } | ||
214 | |||
215 | win32_argc = 0; | ||
216 | argv_w = CommandLineToArgvW(GetCommandLineW(), &win32_argc); | ||
217 | if (win32_argc <= 0 || !argv_w) | ||
218 | return; | ||
219 | |||
220 | /* determine the UTF-8 buffer size (including NULL-termination symbols) */ | ||
221 | for (i = 0; i < win32_argc; i++) | ||
222 | buffsize += WideCharToMultiByte(CP_UTF8, 0, argv_w[i], -1, | ||
223 | NULL, 0, NULL, NULL); | ||
224 | |||
225 | win32_argv_utf8 = av_mallocz(sizeof(char *) * (win32_argc + 1) + buffsize); | ||
226 | argstr_flat = (char *)win32_argv_utf8 + sizeof(char *) * (win32_argc + 1); | ||
227 | if (!win32_argv_utf8) { | ||
228 | LocalFree(argv_w); | ||
229 | return; | ||
230 | } | ||
231 | |||
232 | for (i = 0; i < win32_argc; i++) { | ||
233 | win32_argv_utf8[i] = &argstr_flat[offset]; | ||
234 | offset += WideCharToMultiByte(CP_UTF8, 0, argv_w[i], -1, | ||
235 | &argstr_flat[offset], | ||
236 | buffsize - offset, NULL, NULL); | ||
237 | } | ||
238 | win32_argv_utf8[i] = NULL; | ||
239 | LocalFree(argv_w); | ||
240 | |||
241 | *argc_ptr = win32_argc; | ||
242 | *argv_ptr = win32_argv_utf8; | ||
243 | } | ||
244 | #else | ||
245 | 6364 | static inline void prepare_app_arguments(int *argc_ptr, char ***argv_ptr) | |
246 | { | ||
247 | /* nothing to do */ | ||
248 | 6364 | } | |
249 | #endif /* HAVE_COMMANDLINETOARGVW */ | ||
250 | |||
251 | 74683 | static int write_option(void *optctx, const OptionDef *po, const char *opt, | |
252 | const char *arg) | ||
253 | { | ||
254 | /* new-style options contain an offset into optctx, old-style address of | ||
255 | * a global var*/ | ||
256 | 149366 | void *dst = po->flags & (OPT_OFFSET | OPT_SPEC) ? | |
257 |
2/2✓ Branch 0 taken 36767 times.
✓ Branch 1 taken 37916 times.
|
74683 | (uint8_t *)optctx + po->u.off : po->u.dst_ptr; |
258 | int *dstcount; | ||
259 | |||
260 |
2/2✓ Branch 0 taken 25348 times.
✓ Branch 1 taken 49335 times.
|
74683 | if (po->flags & OPT_SPEC) { |
261 | 25348 | SpecifierOpt **so = dst; | |
262 | 25348 | char *p = strchr(opt, ':'); | |
263 | char *str; | ||
264 | |||
265 | 25348 | dstcount = (int *)(so + 1); | |
266 | 25348 | *so = grow_array(*so, sizeof(**so), dstcount, *dstcount + 1); | |
267 |
2/2✓ Branch 0 taken 13448 times.
✓ Branch 1 taken 11900 times.
|
25348 | str = av_strdup(p ? p + 1 : ""); |
268 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 25348 times.
|
25348 | if (!str) |
269 | ✗ | return AVERROR(ENOMEM); | |
270 | 25348 | (*so)[*dstcount - 1].specifier = str; | |
271 | 25348 | dst = &(*so)[*dstcount - 1].u; | |
272 | } | ||
273 | |||
274 |
2/2✓ Branch 0 taken 29705 times.
✓ Branch 1 taken 44978 times.
|
74683 | if (po->flags & OPT_STRING) { |
275 | char *str; | ||
276 | 29705 | str = av_strdup(arg); | |
277 | 29705 | av_freep(dst); | |
278 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 29705 times.
|
29705 | if (!str) |
279 | ✗ | return AVERROR(ENOMEM); | |
280 | 29705 | *(char **)dst = str; | |
281 |
4/4✓ Branch 0 taken 20616 times.
✓ Branch 1 taken 24362 times.
✓ Branch 2 taken 135 times.
✓ Branch 3 taken 20481 times.
|
44978 | } else if (po->flags & OPT_BOOL || po->flags & OPT_INT) { |
282 | 24497 | *(int *)dst = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX); | |
283 |
2/2✓ Branch 0 taken 4477 times.
✓ Branch 1 taken 16004 times.
|
20481 | } else if (po->flags & OPT_INT64) { |
284 | 4477 | *(int64_t *)dst = parse_number_or_die(opt, arg, OPT_INT64, INT64_MIN, INT64_MAX); | |
285 |
2/2✓ Branch 0 taken 186 times.
✓ Branch 1 taken 15818 times.
|
16004 | } else if (po->flags & OPT_TIME) { |
286 | 186 | *(int64_t *)dst = parse_time_or_die(opt, arg, 1); | |
287 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 15817 times.
|
15818 | } else if (po->flags & OPT_FLOAT) { |
288 | 1 | *(float *)dst = parse_number_or_die(opt, arg, OPT_FLOAT, -INFINITY, INFINITY); | |
289 |
2/2✓ Branch 0 taken 273 times.
✓ Branch 1 taken 15544 times.
|
15817 | } else if (po->flags & OPT_DOUBLE) { |
290 | 273 | *(double *)dst = parse_number_or_die(opt, arg, OPT_DOUBLE, -INFINITY, INFINITY); | |
291 |
1/2✓ Branch 0 taken 15544 times.
✗ Branch 1 not taken.
|
15544 | } else if (po->u.func_arg) { |
292 | 15544 | int ret = po->u.func_arg(optctx, opt, arg); | |
293 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15544 times.
|
15544 | if (ret < 0) { |
294 | ✗ | av_log(NULL, AV_LOG_ERROR, | |
295 | "Failed to set value '%s' for option '%s': %s\n", | ||
296 | ✗ | arg, opt, av_err2str(ret)); | |
297 | ✗ | return ret; | |
298 | } | ||
299 | } | ||
300 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 74682 times.
|
74683 | if (po->flags & OPT_EXIT) |
301 | 1 | exit_program(0); | |
302 | |||
303 | 74682 | return 0; | |
304 | } | ||
305 | |||
306 | 8273 | int parse_option(void *optctx, const char *opt, const char *arg, | |
307 | const OptionDef *options) | ||
308 | { | ||
309 | static const OptionDef opt_avoptions = { | ||
310 | .name = "AVOption passthrough", | ||
311 | .flags = HAS_ARG, | ||
312 | .u.func_arg = opt_default, | ||
313 | }; | ||
314 | |||
315 | const OptionDef *po; | ||
316 | int ret; | ||
317 | |||
318 | 8273 | po = find_option(options, opt); | |
319 |
5/6✓ Branch 0 taken 7 times.
✓ Branch 1 taken 8266 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
8273 | if (!po->name && opt[0] == 'n' && opt[1] == 'o') { |
320 | /* handle 'no' bool option */ | ||
321 | 1 | po = find_option(options, opt + 2); | |
322 |
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))) |
323 | 1 | arg = "0"; | |
324 |
2/2✓ Branch 0 taken 110 times.
✓ Branch 1 taken 8162 times.
|
8272 | } else if (po->flags & OPT_BOOL) |
325 | 110 | arg = "1"; | |
326 | |||
327 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 8267 times.
|
8273 | if (!po->name) |
328 | 6 | po = &opt_avoptions; | |
329 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8273 times.
|
8273 | if (!po->name) { |
330 | ✗ | av_log(NULL, AV_LOG_ERROR, "Unrecognized option '%s'\n", opt); | |
331 | ✗ | return AVERROR(EINVAL); | |
332 | } | ||
333 |
3/4✓ Branch 0 taken 8072 times.
✓ Branch 1 taken 201 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8072 times.
|
8273 | if (po->flags & HAS_ARG && !arg) { |
334 | ✗ | av_log(NULL, AV_LOG_ERROR, "Missing argument for option '%s'\n", opt); | |
335 | ✗ | return AVERROR(EINVAL); | |
336 | } | ||
337 | |||
338 | 8273 | ret = write_option(optctx, po, opt, arg); | |
339 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8273 times.
|
8273 | if (ret < 0) |
340 | ✗ | return ret; | |
341 | |||
342 | 8273 | return !!(po->flags & HAS_ARG); | |
343 | } | ||
344 | |||
345 | 115 | void parse_options(void *optctx, int argc, char **argv, const OptionDef *options, | |
346 | void (*parse_arg_function)(void *, const char*)) | ||
347 | { | ||
348 | const char *opt; | ||
349 | 115 | int optindex, handleoptions = 1, ret; | |
350 | |||
351 | /* perform system-dependent conversions for arguments list */ | ||
352 | 115 | prepare_app_arguments(&argc, &argv); | |
353 | |||
354 | /* parse options */ | ||
355 | 115 | optindex = 1; | |
356 |
2/2✓ Branch 0 taken 529 times.
✓ Branch 1 taken 115 times.
|
644 | while (optindex < argc) { |
357 | 529 | opt = argv[optindex++]; | |
358 | |||
359 |
4/6✓ Branch 0 taken 529 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 423 times.
✓ Branch 3 taken 106 times.
✓ Branch 4 taken 423 times.
✗ Branch 5 not taken.
|
529 | if (handleoptions && opt[0] == '-' && opt[1] != '\0') { |
360 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 423 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
423 | if (opt[1] == '-' && opt[2] == '\0') { |
361 | ✗ | handleoptions = 0; | |
362 | ✗ | continue; | |
363 | } | ||
364 | 423 | opt++; | |
365 | |||
366 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 423 times.
|
423 | if ((ret = parse_option(optctx, opt, argv[optindex], options)) < 0) |
367 | ✗ | exit_program(1); | |
368 | 423 | optindex += ret; | |
369 | } else { | ||
370 |
1/2✓ Branch 0 taken 106 times.
✗ Branch 1 not taken.
|
106 | if (parse_arg_function) |
371 | 106 | parse_arg_function(optctx, opt); | |
372 | } | ||
373 | } | ||
374 | 115 | } | |
375 | |||
376 | 18778 | int parse_optgroup(void *optctx, OptionGroup *g) | |
377 | { | ||
378 | int i, ret; | ||
379 | |||
380 | 18778 | av_log(NULL, AV_LOG_DEBUG, "Parsing a group of options: %s %s.\n", | |
381 | 18778 | g->group_def->name, g->arg); | |
382 | |||
383 |
2/2✓ Branch 0 taken 66410 times.
✓ Branch 1 taken 18777 times.
|
85187 | for (i = 0; i < g->nb_opts; i++) { |
384 | 66410 | Option *o = &g->opts[i]; | |
385 | |||
386 |
2/2✓ Branch 0 taken 37131 times.
✓ Branch 1 taken 29279 times.
|
66410 | if (g->group_def->flags && |
387 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 37131 times.
|
37131 | !(g->group_def->flags & o->opt->flags)) { |
388 | ✗ | av_log(NULL, AV_LOG_ERROR, "Option %s (%s) cannot be applied to " | |
389 | "%s %s -- you are trying to apply an input option to an " | ||
390 | "output file or vice versa. Move this option before the " | ||
391 | ✗ | "file it belongs to.\n", o->key, o->opt->help, | |
392 | ✗ | g->group_def->name, g->arg); | |
393 | ✗ | return AVERROR(EINVAL); | |
394 | } | ||
395 | |||
396 | 66410 | av_log(NULL, AV_LOG_DEBUG, "Applying option %s (%s) with argument %s.\n", | |
397 | 66410 | o->key, o->opt->help, o->val); | |
398 | |||
399 | 66410 | ret = write_option(optctx, o->opt, o->key, o->val); | |
400 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 66409 times.
|
66409 | if (ret < 0) |
401 | ✗ | return ret; | |
402 | } | ||
403 | |||
404 | 18777 | av_log(NULL, AV_LOG_DEBUG, "Successfully parsed a group of options.\n"); | |
405 | |||
406 | 18777 | return 0; | |
407 | } | ||
408 | |||
409 | 31820 | int locate_option(int argc, char **argv, const OptionDef *options, | |
410 | const char *optname) | ||
411 | { | ||
412 | const OptionDef *po; | ||
413 | int i; | ||
414 | |||
415 |
2/2✓ Branch 0 taken 716381 times.
✓ Branch 1 taken 31806 times.
|
748187 | for (i = 1; i < argc; i++) { |
416 | 716381 | const char *cur_opt = argv[i]; | |
417 | |||
418 |
2/2✓ Branch 0 taken 19703 times.
✓ Branch 1 taken 696678 times.
|
716381 | if (*cur_opt++ != '-') |
419 | 19703 | continue; | |
420 | |||
421 | 696678 | po = find_option(options, cur_opt); | |
422 |
5/6✓ Branch 0 taken 456027 times.
✓ Branch 1 taken 240651 times.
✓ Branch 2 taken 93495 times.
✓ Branch 3 taken 362532 times.
✓ Branch 4 taken 93495 times.
✗ Branch 5 not taken.
|
696678 | if (!po->name && cur_opt[0] == 'n' && cur_opt[1] == 'o') |
423 | 93495 | po = find_option(options, cur_opt + 2); | |
424 | |||
425 |
3/4✓ Branch 0 taken 362557 times.
✓ Branch 1 taken 334121 times.
✓ Branch 2 taken 362557 times.
✗ Branch 3 not taken.
|
696678 | if ((!po->name && !strcmp(cur_opt, optname)) || |
426 |
4/4✓ Branch 0 taken 334121 times.
✓ Branch 1 taken 362557 times.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 334107 times.
|
696678 | (po->name && !strcmp(optname, po->name))) |
427 | 14 | return i; | |
428 | |||
429 |
4/4✓ Branch 0 taken 334107 times.
✓ Branch 1 taken 362557 times.
✓ Branch 2 taken 211842 times.
✓ Branch 3 taken 122265 times.
|
696664 | if (!po->name || po->flags & HAS_ARG) |
430 | 574399 | i++; | |
431 | } | ||
432 | 31806 | return 0; | |
433 | } | ||
434 | |||
435 | ✗ | static void dump_argument(FILE *report_file, const char *a) | |
436 | { | ||
437 | const unsigned char *p; | ||
438 | |||
439 | ✗ | for (p = a; *p; p++) | |
440 | ✗ | if (!((*p >= '+' && *p <= ':') || (*p >= '@' && *p <= 'Z') || | |
441 | ✗ | *p == '_' || (*p >= 'a' && *p <= 'z'))) | |
442 | break; | ||
443 | ✗ | if (!*p) { | |
444 | ✗ | fputs(a, report_file); | |
445 | ✗ | return; | |
446 | } | ||
447 | ✗ | fputc('"', report_file); | |
448 | ✗ | for (p = a; *p; p++) { | |
449 | ✗ | if (*p == '\\' || *p == '"' || *p == '$' || *p == '`') | |
450 | ✗ | fprintf(report_file, "\\%c", *p); | |
451 | ✗ | else if (*p < ' ' || *p > '~') | |
452 | ✗ | fprintf(report_file, "\\x%02x", *p); | |
453 | else | ||
454 | ✗ | fputc(*p, report_file); | |
455 | } | ||
456 | ✗ | fputc('"', report_file); | |
457 | } | ||
458 | |||
459 | 6364 | static void check_options(const OptionDef *po) | |
460 | { | ||
461 |
2/2✓ Branch 0 taken 1138774 times.
✓ Branch 1 taken 6364 times.
|
1145138 | while (po->name) { |
462 |
2/2✓ Branch 0 taken 193719 times.
✓ Branch 1 taken 945055 times.
|
1138774 | if (po->flags & OPT_PERFILE) |
463 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 193719 times.
|
193719 | av_assert0(po->flags & (OPT_INPUT | OPT_OUTPUT)); |
464 | 1138774 | po++; | |
465 | } | ||
466 | 6364 | } | |
467 | |||
468 | 6364 | void parse_loglevel(int argc, char **argv, const OptionDef *options) | |
469 | { | ||
470 | 6364 | int idx = locate_option(argc, argv, options, "loglevel"); | |
471 | char *env; | ||
472 | |||
473 | 6364 | check_options(options); | |
474 | |||
475 |
1/2✓ Branch 0 taken 6364 times.
✗ Branch 1 not taken.
|
6364 | if (!idx) |
476 | 6364 | idx = locate_option(argc, argv, options, "v"); | |
477 |
3/4✓ Branch 0 taken 14 times.
✓ Branch 1 taken 6350 times.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
|
6364 | if (idx && argv[idx + 1]) |
478 | 14 | opt_loglevel(NULL, "loglevel", argv[idx + 1]); | |
479 | 6364 | idx = locate_option(argc, argv, options, "report"); | |
480 | 6364 | env = getenv_utf8("FFREPORT"); | |
481 |
2/4✓ Branch 0 taken 6364 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6364 times.
|
6364 | if (env || idx) { |
482 | ✗ | FILE *report_file = NULL; | |
483 | ✗ | init_report(env, &report_file); | |
484 | ✗ | if (report_file) { | |
485 | int i; | ||
486 | ✗ | fprintf(report_file, "Command line:\n"); | |
487 | ✗ | for (i = 0; i < argc; i++) { | |
488 | ✗ | dump_argument(report_file, argv[i]); | |
489 | ✗ | fputc(i < argc - 1 ? ' ' : '\n', report_file); | |
490 | } | ||
491 | ✗ | fflush(report_file); | |
492 | } | ||
493 | } | ||
494 | 6364 | freeenv_utf8(env); | |
495 | 6364 | idx = locate_option(argc, argv, options, "hide_banner"); | |
496 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6364 times.
|
6364 | if (idx) |
497 | ✗ | hide_banner = 1; | |
498 | 6364 | } | |
499 | |||
500 | 224419 | static const AVOption *opt_find(void *obj, const char *name, const char *unit, | |
501 | int opt_flags, int search_flags) | ||
502 | { | ||
503 | 224419 | const AVOption *o = av_opt_find(obj, name, unit, opt_flags, search_flags); | |
504 |
4/4✓ Branch 0 taken 63892 times.
✓ Branch 1 taken 160527 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 63890 times.
|
224419 | if(o && !o->flags) |
505 | 2 | return NULL; | |
506 | 224417 | return o; | |
507 | } | ||
508 | |||
509 | #define FLAGS (o->type == AV_OPT_TYPE_FLAGS && (arg[0]=='-' || arg[0]=='+')) ? AV_DICT_APPEND : 0 | ||
510 | 82512 | int opt_default(void *optctx, const char *opt, const char *arg) | |
511 | { | ||
512 | const AVOption *o; | ||
513 | 82512 | int consumed = 0; | |
514 | char opt_stripped[128]; | ||
515 | const char *p; | ||
516 | 82512 | const AVClass *cc = avcodec_get_class(), *fc = avformat_get_class(); | |
517 | #if CONFIG_SWSCALE | ||
518 | 82512 | const AVClass *sc = sws_get_class(); | |
519 | #endif | ||
520 | #if CONFIG_SWRESAMPLE | ||
521 | 82512 | const AVClass *swr_class = swr_get_class(); | |
522 | #endif | ||
523 | |||
524 |
2/4✓ Branch 0 taken 82512 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 82512 times.
|
82512 | if (!strcmp(opt, "debug") || !strcmp(opt, "fdebug")) |
525 | ✗ | av_log_set_level(AV_LOG_DEBUG); | |
526 | |||
527 |
2/2✓ Branch 0 taken 82504 times.
✓ Branch 1 taken 8 times.
|
82512 | if (!(p = strchr(opt, ':'))) |
528 | 82504 | p = opt + strlen(opt); | |
529 | 82512 | av_strlcpy(opt_stripped, opt, FFMIN(sizeof(opt_stripped), p - opt + 1)); | |
530 | |||
531 |
2/2✓ Branch 1 taken 40615 times.
✓ Branch 2 taken 41897 times.
|
82512 | if ((o = opt_find(&cc, opt_stripped, NULL, 0, |
532 | 40615 | AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ)) || | |
533 |
8/8✓ Branch 0 taken 40612 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 40602 times.
✓ Branch 3 taken 10 times.
✓ Branch 4 taken 11007 times.
✓ Branch 5 taken 29595 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 11019 times.
|
51635 | ((opt[0] == 'v' || opt[0] == 'a' || opt[0] == 's') && |
534 | 11020 | (o = opt_find(&cc, opt + 1, NULL, 0, AV_OPT_SEARCH_FAKE_OBJ)))) { | |
535 |
5/6✓ Branch 0 taken 17032 times.
✓ Branch 1 taken 24866 times.
✓ Branch 2 taken 17032 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10944 times.
✓ Branch 5 taken 6088 times.
|
41898 | av_dict_set(&codec_opts, opt, arg, FLAGS); |
536 | 41898 | consumed = 1; | |
537 | } | ||
538 |
2/2✓ Branch 1 taken 11003 times.
✓ Branch 2 taken 71509 times.
|
82512 | if ((o = opt_find(&fc, opt, NULL, 0, |
539 | AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) { | ||
540 |
5/6✓ Branch 0 taken 10809 times.
✓ Branch 1 taken 194 times.
✓ Branch 2 taken 10809 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10798 times.
✓ Branch 5 taken 11 times.
|
11003 | av_dict_set(&format_opts, opt, arg, FLAGS); |
541 |
2/2✓ Branch 0 taken 71 times.
✓ Branch 1 taken 10932 times.
|
11003 | if (consumed) |
542 | 71 | av_log(NULL, AV_LOG_VERBOSE, "Routing option %s to both codec and muxer layer\n", opt); | |
543 | 11003 | consumed = 1; | |
544 | } | ||
545 | #if CONFIG_SWSCALE | ||
546 |
4/4✓ Branch 0 taken 29682 times.
✓ Branch 1 taken 52830 times.
✓ Branch 3 taken 10989 times.
✓ Branch 4 taken 18693 times.
|
82512 | if (!consumed && (o = opt_find(&sc, opt, NULL, 0, |
547 | AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) { | ||
548 |
2/4✓ Branch 0 taken 10989 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10989 times.
✗ Branch 3 not taken.
|
10989 | if (!strcmp(opt, "srcw") || !strcmp(opt, "srch") || |
549 |
2/4✓ Branch 0 taken 10989 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10989 times.
✗ Branch 3 not taken.
|
10989 | !strcmp(opt, "dstw") || !strcmp(opt, "dsth") || |
550 |
2/4✓ Branch 0 taken 10989 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10989 times.
|
10989 | !strcmp(opt, "src_format") || !strcmp(opt, "dst_format")) { |
551 | ✗ | av_log(NULL, AV_LOG_ERROR, "Directly using swscale dimensions/format options is not supported, please use the -s or -pix_fmt options\n"); | |
552 | ✗ | return AVERROR(EINVAL); | |
553 | } | ||
554 |
4/6✓ Branch 0 taken 10989 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10989 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10804 times.
✓ Branch 5 taken 185 times.
|
10989 | av_dict_set(&sws_dict, opt, arg, FLAGS); |
555 | |||
556 | 10989 | consumed = 1; | |
557 | } | ||
558 | #else | ||
559 | if (!consumed && !strcmp(opt, "sws_flags")) { | ||
560 | av_log(NULL, AV_LOG_WARNING, "Ignoring %s %s, due to disabled swscale\n", opt, arg); | ||
561 | consumed = 1; | ||
562 | } | ||
563 | #endif | ||
564 | #if CONFIG_SWRESAMPLE | ||
565 |
3/4✓ Branch 0 taken 18693 times.
✓ Branch 1 taken 63819 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 18693 times.
|
82512 | if (!consumed && (o=opt_find(&swr_class, opt, NULL, 0, |
566 | AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) { | ||
567 | ✗ | av_dict_set(&swr_opts, opt, arg, FLAGS); | |
568 | ✗ | consumed = 1; | |
569 | } | ||
570 | #endif | ||
571 | |||
572 |
2/2✓ Branch 0 taken 63819 times.
✓ Branch 1 taken 18693 times.
|
82512 | if (consumed) |
573 | 63819 | return 0; | |
574 | 18693 | return AVERROR_OPTION_NOT_FOUND; | |
575 | } | ||
576 | |||
577 | /* | ||
578 | * Check whether given option is a group separator. | ||
579 | * | ||
580 | * @return index of the group definition that matched or -1 if none | ||
581 | */ | ||
582 | 136503 | static int match_group_separator(const OptionGroupDef *groups, int nb_groups, | |
583 | const char *opt) | ||
584 | { | ||
585 | int i; | ||
586 | |||
587 |
2/2✓ Branch 0 taken 273006 times.
✓ Branch 1 taken 130223 times.
|
403229 | for (i = 0; i < nb_groups; i++) { |
588 | 273006 | const OptionGroupDef *p = &groups[i]; | |
589 |
4/4✓ Branch 0 taken 136503 times.
✓ Branch 1 taken 136503 times.
✓ Branch 2 taken 6280 times.
✓ Branch 3 taken 130223 times.
|
273006 | if (p->sep && !strcmp(p->sep, opt)) |
590 | 6280 | return i; | |
591 | } | ||
592 | |||
593 | 130223 | return -1; | |
594 | } | ||
595 | |||
596 | /* | ||
597 | * Finish parsing an option group. | ||
598 | * | ||
599 | * @param group_idx which group definition should this group belong to | ||
600 | * @param arg argument of the group delimiting option | ||
601 | */ | ||
602 | 12529 | static void finish_group(OptionParseContext *octx, int group_idx, | |
603 | const char *arg) | ||
604 | { | ||
605 | 12529 | OptionGroupList *l = &octx->groups[group_idx]; | |
606 | OptionGroup *g; | ||
607 | |||
608 | 12529 | GROW_ARRAY(l->groups, l->nb_groups); | |
609 | 12529 | g = &l->groups[l->nb_groups - 1]; | |
610 | |||
611 | 12529 | *g = octx->cur_group; | |
612 | 12529 | g->arg = arg; | |
613 | 12529 | g->group_def = l->group_def; | |
614 | 12529 | g->sws_dict = sws_dict; | |
615 | 12529 | g->swr_opts = swr_opts; | |
616 | 12529 | g->codec_opts = codec_opts; | |
617 | 12529 | g->format_opts = format_opts; | |
618 | |||
619 | 12529 | codec_opts = NULL; | |
620 | 12529 | format_opts = NULL; | |
621 | 12529 | sws_dict = NULL; | |
622 | 12529 | swr_opts = NULL; | |
623 | |||
624 | 12529 | memset(&octx->cur_group, 0, sizeof(octx->cur_group)); | |
625 | 12529 | } | |
626 | |||
627 | /* | ||
628 | * Add an option instance to currently parsed group. | ||
629 | */ | ||
630 | 66410 | static void add_opt(OptionParseContext *octx, const OptionDef *opt, | |
631 | const char *key, const char *val) | ||
632 | { | ||
633 | 66410 | int global = !(opt->flags & (OPT_PERFILE | OPT_SPEC | OPT_OFFSET)); | |
634 |
2/2✓ Branch 0 taken 29279 times.
✓ Branch 1 taken 37131 times.
|
66410 | OptionGroup *g = global ? &octx->global_opts : &octx->cur_group; |
635 | |||
636 | 66410 | GROW_ARRAY(g->opts, g->nb_opts); | |
637 | 66410 | g->opts[g->nb_opts - 1].opt = opt; | |
638 | 66410 | g->opts[g->nb_opts - 1].key = key; | |
639 | 66410 | g->opts[g->nb_opts - 1].val = val; | |
640 | 66410 | } | |
641 | |||
642 | 6249 | static void init_parse_context(OptionParseContext *octx, | |
643 | const OptionGroupDef *groups, int nb_groups) | ||
644 | { | ||
645 | static const OptionGroupDef global_group = { "global" }; | ||
646 | int i; | ||
647 | |||
648 | 6249 | memset(octx, 0, sizeof(*octx)); | |
649 | |||
650 | 6249 | octx->nb_groups = nb_groups; | |
651 | 6249 | octx->groups = av_calloc(octx->nb_groups, sizeof(*octx->groups)); | |
652 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6249 times.
|
6249 | if (!octx->groups) |
653 | ✗ | exit_program(1); | |
654 | |||
655 |
2/2✓ Branch 0 taken 12498 times.
✓ Branch 1 taken 6249 times.
|
18747 | for (i = 0; i < octx->nb_groups; i++) |
656 | 12498 | octx->groups[i].group_def = &groups[i]; | |
657 | |||
658 | 6249 | octx->global_opts.group_def = &global_group; | |
659 | 6249 | octx->global_opts.arg = ""; | |
660 | 6249 | } | |
661 | |||
662 | 6248 | void uninit_parse_context(OptionParseContext *octx) | |
663 | { | ||
664 | int i, j; | ||
665 | |||
666 |
2/2✓ Branch 0 taken 12496 times.
✓ Branch 1 taken 6248 times.
|
18744 | for (i = 0; i < octx->nb_groups; i++) { |
667 | 12496 | OptionGroupList *l = &octx->groups[i]; | |
668 | |||
669 |
2/2✓ Branch 0 taken 12529 times.
✓ Branch 1 taken 12496 times.
|
25025 | for (j = 0; j < l->nb_groups; j++) { |
670 | 12529 | av_freep(&l->groups[j].opts); | |
671 | 12529 | av_dict_free(&l->groups[j].codec_opts); | |
672 | 12529 | av_dict_free(&l->groups[j].format_opts); | |
673 | |||
674 | 12529 | av_dict_free(&l->groups[j].sws_dict); | |
675 | 12529 | av_dict_free(&l->groups[j].swr_opts); | |
676 | } | ||
677 | 12496 | av_freep(&l->groups); | |
678 | } | ||
679 | 6248 | av_freep(&octx->groups); | |
680 | |||
681 | 6248 | av_freep(&octx->cur_group.opts); | |
682 | 6248 | av_freep(&octx->global_opts.opts); | |
683 | |||
684 | 6248 | uninit_opts(); | |
685 | 6248 | } | |
686 | |||
687 | 6249 | int split_commandline(OptionParseContext *octx, int argc, char *argv[], | |
688 | const OptionDef *options, | ||
689 | const OptionGroupDef *groups, int nb_groups) | ||
690 | { | ||
691 | 6249 | int optindex = 1; | |
692 | 6249 | int dashdash = -2; | |
693 | |||
694 | /* perform system-dependent conversions for arguments list */ | ||
695 | 6249 | prepare_app_arguments(&argc, &argv); | |
696 | |||
697 | 6249 | init_parse_context(octx, groups, nb_groups); | |
698 | 6249 | av_log(NULL, AV_LOG_DEBUG, "Splitting the commandline.\n"); | |
699 | |||
700 |
2/2✓ Branch 0 taken 142752 times.
✓ Branch 1 taken 6249 times.
|
149001 | while (optindex < argc) { |
701 | 142752 | const char *opt = argv[optindex++], *arg; | |
702 | const OptionDef *po; | ||
703 | int ret; | ||
704 | |||
705 | 142752 | av_log(NULL, AV_LOG_DEBUG, "Reading option '%s' ...", opt); | |
706 | |||
707 |
3/6✓ Branch 0 taken 138917 times.
✓ Branch 1 taken 3835 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 138917 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
142752 | if (opt[0] == '-' && opt[1] == '-' && !opt[2]) { |
708 | ✗ | dashdash = optindex; | |
709 | ✗ | continue; | |
710 | } | ||
711 | /* unnamed group separators, e.g. output filename */ | ||
712 |
5/6✓ Branch 0 taken 138917 times.
✓ Branch 1 taken 3835 times.
✓ Branch 2 taken 136503 times.
✓ Branch 3 taken 2414 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 136503 times.
|
142752 | if (opt[0] != '-' || !opt[1] || dashdash+1 == optindex) { |
713 | 6249 | finish_group(octx, 0, opt); | |
714 | 6249 | av_log(NULL, AV_LOG_DEBUG, " matched as %s.\n", groups[0].name); | |
715 | 6249 | continue; | |
716 | } | ||
717 | 136503 | opt++; | |
718 | |||
719 | #define GET_ARG(arg) \ | ||
720 | do { \ | ||
721 | arg = argv[optindex++]; \ | ||
722 | if (!arg) { \ | ||
723 | av_log(NULL, AV_LOG_ERROR, "Missing argument for option '%s'.\n", opt);\ | ||
724 | return AVERROR(EINVAL); \ | ||
725 | } \ | ||
726 | } while (0) | ||
727 | |||
728 | /* named group separators, e.g. -i */ | ||
729 |
2/2✓ Branch 1 taken 6280 times.
✓ Branch 2 taken 130223 times.
|
136503 | if ((ret = match_group_separator(groups, nb_groups, opt)) >= 0) { |
730 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6280 times.
|
6280 | GET_ARG(arg); |
731 | 6280 | finish_group(octx, ret, arg); | |
732 | 6280 | av_log(NULL, AV_LOG_DEBUG, " matched as %s with argument '%s'.\n", | |
733 | 6280 | groups[ret].name, arg); | |
734 | 6280 | continue; | |
735 | } | ||
736 | |||
737 | /* normal options */ | ||
738 | 130223 | po = find_option(options, opt); | |
739 |
2/2✓ Branch 0 taken 47717 times.
✓ Branch 1 taken 82506 times.
|
130223 | if (po->name) { |
740 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 47716 times.
|
47717 | if (po->flags & OPT_EXIT) { |
741 | /* optional argument, e.g. -h */ | ||
742 | 1 | arg = argv[optindex++]; | |
743 |
2/2✓ Branch 0 taken 42158 times.
✓ Branch 1 taken 5558 times.
|
47716 | } else if (po->flags & HAS_ARG) { |
744 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 42158 times.
|
42158 | GET_ARG(arg); |
745 | } else { | ||
746 | 5558 | arg = "1"; | |
747 | } | ||
748 | |||
749 | 47717 | add_opt(octx, po, opt, arg); | |
750 | 47717 | av_log(NULL, AV_LOG_DEBUG, " matched as option '%s' (%s) with " | |
751 | 47717 | "argument '%s'.\n", po->name, po->help, arg); | |
752 | 47717 | continue; | |
753 | } | ||
754 | |||
755 | /* AVOptions */ | ||
756 |
1/2✓ Branch 0 taken 82506 times.
✗ Branch 1 not taken.
|
82506 | if (argv[optindex]) { |
757 | 82506 | ret = opt_default(NULL, opt, argv[optindex]); | |
758 |
2/2✓ Branch 0 taken 63813 times.
✓ Branch 1 taken 18693 times.
|
82506 | if (ret >= 0) { |
759 | 63813 | av_log(NULL, AV_LOG_DEBUG, " matched as AVOption '%s' with " | |
760 | 63813 | "argument '%s'.\n", opt, argv[optindex]); | |
761 | 63813 | optindex++; | |
762 | 63813 | continue; | |
763 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18693 times.
|
18693 | } else if (ret != AVERROR_OPTION_NOT_FOUND) { |
764 | ✗ | av_log(NULL, AV_LOG_ERROR, "Error parsing option '%s' " | |
765 | ✗ | "with argument '%s'.\n", opt, argv[optindex]); | |
766 | ✗ | return ret; | |
767 | } | ||
768 | } | ||
769 | |||
770 | /* boolean -nofoo options */ | ||
771 |
3/6✓ Branch 0 taken 18693 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18693 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 18693 times.
✗ Branch 5 not taken.
|
37386 | if (opt[0] == 'n' && opt[1] == 'o' && |
772 | 18693 | (po = find_option(options, opt + 2)) && | |
773 |
2/4✓ Branch 0 taken 18693 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18693 times.
✗ Branch 3 not taken.
|
18693 | po->name && po->flags & OPT_BOOL) { |
774 | 18693 | add_opt(octx, po, opt, "0"); | |
775 | 18693 | av_log(NULL, AV_LOG_DEBUG, " matched as option '%s' (%s) with " | |
776 | 18693 | "argument 0.\n", po->name, po->help); | |
777 | 18693 | continue; | |
778 | } | ||
779 | |||
780 | ✗ | av_log(NULL, AV_LOG_ERROR, "Unrecognized option '%s'.\n", opt); | |
781 | ✗ | return AVERROR_OPTION_NOT_FOUND; | |
782 | } | ||
783 | |||
784 |
3/6✓ Branch 0 taken 6249 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6249 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 6249 times.
|
6249 | if (octx->cur_group.nb_opts || codec_opts || format_opts) |
785 | ✗ | av_log(NULL, AV_LOG_WARNING, "Trailing option(s) found in the " | |
786 | "command: may be ignored.\n"); | ||
787 | |||
788 | 6249 | av_log(NULL, AV_LOG_DEBUG, "Finished splitting the commandline.\n"); | |
789 | |||
790 | 6249 | return 0; | |
791 | } | ||
792 | |||
793 | 71 | void print_error(const char *filename, int err) | |
794 | { | ||
795 | char errbuf[128]; | ||
796 | 71 | const char *errbuf_ptr = errbuf; | |
797 | |||
798 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 71 times.
|
71 | if (av_strerror(err, errbuf, sizeof(errbuf)) < 0) |
799 | ✗ | errbuf_ptr = strerror(AVUNERROR(err)); | |
800 | 71 | av_log(NULL, AV_LOG_ERROR, "%s: %s\n", filename, errbuf_ptr); | |
801 | 71 | } | |
802 | |||
803 | ✗ | int read_yesno(void) | |
804 | { | ||
805 | ✗ | int c = getchar(); | |
806 | ✗ | int yesno = (av_toupper(c) == 'Y'); | |
807 | |||
808 | ✗ | while (c != '\n' && c != EOF) | |
809 | ✗ | c = getchar(); | |
810 | |||
811 | ✗ | return yesno; | |
812 | } | ||
813 | |||
814 | ✗ | FILE *get_preset_file(char *filename, size_t filename_size, | |
815 | const char *preset_name, int is_path, | ||
816 | const char *codec_name) | ||
817 | { | ||
818 | ✗ | FILE *f = NULL; | |
819 | int i; | ||
820 | #if HAVE_GETMODULEHANDLE && defined(_WIN32) | ||
821 | char *datadir = NULL; | ||
822 | #endif | ||
823 | ✗ | char *env_home = getenv_utf8("HOME"); | |
824 | ✗ | char *env_ffmpeg_datadir = getenv_utf8("FFMPEG_DATADIR"); | |
825 | ✗ | const char *base[3] = { env_home, | |
826 | env_ffmpeg_datadir, | ||
827 | FFMPEG_DATADIR, }; | ||
828 | |||
829 | ✗ | if (is_path) { | |
830 | ✗ | av_strlcpy(filename, preset_name, filename_size); | |
831 | ✗ | f = fopen_utf8(filename, "r"); | |
832 | } else { | ||
833 | #if HAVE_GETMODULEHANDLE && defined(_WIN32) | ||
834 | wchar_t *datadir_w = get_module_filename(NULL); | ||
835 | base[2] = NULL; | ||
836 | |||
837 | if (wchartoutf8(datadir_w, &datadir)) | ||
838 | datadir = NULL; | ||
839 | av_free(datadir_w); | ||
840 | |||
841 | if (datadir) | ||
842 | { | ||
843 | char *ls; | ||
844 | for (ls = datadir; *ls; ls++) | ||
845 | if (*ls == '\\') *ls = '/'; | ||
846 | |||
847 | if (ls = strrchr(datadir, '/')) | ||
848 | { | ||
849 | ptrdiff_t datadir_len = ls - datadir; | ||
850 | size_t desired_size = datadir_len + strlen("/ffpresets") + 1; | ||
851 | char *new_datadir = av_realloc_array( | ||
852 | datadir, desired_size, sizeof *datadir); | ||
853 | if (new_datadir) { | ||
854 | datadir = new_datadir; | ||
855 | datadir[datadir_len] = 0; | ||
856 | strncat(datadir, "/ffpresets", desired_size - 1 - datadir_len); | ||
857 | base[2] = datadir; | ||
858 | } | ||
859 | } | ||
860 | } | ||
861 | #endif | ||
862 | ✗ | for (i = 0; i < 3 && !f; i++) { | |
863 | ✗ | if (!base[i]) | |
864 | ✗ | continue; | |
865 | ✗ | snprintf(filename, filename_size, "%s%s/%s.ffpreset", base[i], | |
866 | i != 1 ? "" : "/.ffmpeg", preset_name); | ||
867 | ✗ | f = fopen_utf8(filename, "r"); | |
868 | ✗ | if (!f && codec_name) { | |
869 | ✗ | snprintf(filename, filename_size, | |
870 | "%s%s/%s-%s.ffpreset", | ||
871 | base[i], i != 1 ? "" : "/.ffmpeg", codec_name, | ||
872 | preset_name); | ||
873 | ✗ | f = fopen_utf8(filename, "r"); | |
874 | } | ||
875 | } | ||
876 | } | ||
877 | |||
878 | #if HAVE_GETMODULEHANDLE && defined(_WIN32) | ||
879 | av_free(datadir); | ||
880 | #endif | ||
881 | ✗ | freeenv_utf8(env_ffmpeg_datadir); | |
882 | ✗ | freeenv_utf8(env_home); | |
883 | ✗ | return f; | |
884 | } | ||
885 | |||
886 | 26633 | int check_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec) | |
887 | { | ||
888 | 26633 | int ret = avformat_match_stream_specifier(s, st, spec); | |
889 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 26633 times.
|
26633 | if (ret < 0) |
890 | ✗ | av_log(s, AV_LOG_ERROR, "Invalid stream specifier: %s.\n", spec); | |
891 | 26633 | return ret; | |
892 | } | ||
893 | |||
894 | 20141 | AVDictionary *filter_codec_opts(AVDictionary *opts, enum AVCodecID codec_id, | |
895 | AVFormatContext *s, AVStream *st, const AVCodec *codec) | ||
896 | { | ||
897 | 20141 | AVDictionary *ret = NULL; | |
898 | 20141 | const AVDictionaryEntry *t = NULL; | |
899 | 40282 | int flags = s->oformat ? AV_OPT_FLAG_ENCODING_PARAM | |
900 |
2/2✓ Branch 0 taken 6479 times.
✓ Branch 1 taken 13662 times.
|
20141 | : AV_OPT_FLAG_DECODING_PARAM; |
901 | 20141 | char prefix = 0; | |
902 | 20141 | const AVClass *cc = avcodec_get_class(); | |
903 | |||
904 |
2/2✓ Branch 0 taken 7267 times.
✓ Branch 1 taken 12874 times.
|
20141 | if (!codec) |
905 | 7267 | codec = s->oformat ? avcodec_find_encoder(codec_id) | |
906 |
2/2✓ Branch 0 taken 426 times.
✓ Branch 1 taken 6841 times.
|
7267 | : avcodec_find_decoder(codec_id); |
907 | |||
908 |
4/4✓ Branch 0 taken 15433 times.
✓ Branch 1 taken 4360 times.
✓ Branch 2 taken 208 times.
✓ Branch 3 taken 140 times.
|
20141 | switch (st->codecpar->codec_type) { |
909 | 15433 | case AVMEDIA_TYPE_VIDEO: | |
910 | 15433 | prefix = 'v'; | |
911 | 15433 | flags |= AV_OPT_FLAG_VIDEO_PARAM; | |
912 | 15433 | break; | |
913 | 4360 | case AVMEDIA_TYPE_AUDIO: | |
914 | 4360 | prefix = 'a'; | |
915 | 4360 | flags |= AV_OPT_FLAG_AUDIO_PARAM; | |
916 | 4360 | break; | |
917 | 208 | case AVMEDIA_TYPE_SUBTITLE: | |
918 | 208 | prefix = 's'; | |
919 | 208 | flags |= AV_OPT_FLAG_SUBTITLE_PARAM; | |
920 | 208 | break; | |
921 | } | ||
922 | |||
923 |
2/2✓ Branch 1 taken 57810 times.
✓ Branch 2 taken 20141 times.
|
77951 | while (t = av_dict_get(opts, "", t, AV_DICT_IGNORE_SUFFIX)) { |
924 | const AVClass *priv_class; | ||
925 | 57810 | char *p = strchr(t->key, ':'); | |
926 | |||
927 | /* check stream specification in opt name */ | ||
928 |
2/2✓ Branch 0 taken 248 times.
✓ Branch 1 taken 57562 times.
|
57810 | if (p) |
929 |
2/3✓ Branch 1 taken 199 times.
✓ Branch 2 taken 49 times.
✗ Branch 3 not taken.
|
248 | switch (check_stream_specifier(s, st, p + 1)) { |
930 | 199 | case 1: *p = 0; break; | |
931 | 49 | case 0: continue; | |
932 | ✗ | default: exit_program(1); | |
933 | } | ||
934 | |||
935 |
4/4✓ Branch 1 taken 1941 times.
✓ Branch 2 taken 55820 times.
✓ Branch 3 taken 1710 times.
✓ Branch 4 taken 231 times.
|
57761 | if (av_opt_find(&cc, t->key, NULL, flags, AV_OPT_SEARCH_FAKE_OBJ) || |
936 | 1710 | !codec || | |
937 |
4/4✓ Branch 0 taken 637 times.
✓ Branch 1 taken 1073 times.
✓ Branch 2 taken 306 times.
✓ Branch 3 taken 331 times.
|
2347 | ((priv_class = codec->priv_class) && |
938 | 637 | av_opt_find(&priv_class, t->key, NULL, flags, | |
939 | AV_OPT_SEARCH_FAKE_OBJ))) | ||
940 | 56357 | av_dict_set(&ret, t->key, t->value, 0); | |
941 |
4/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1402 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
|
1406 | else if (t->key[0] == prefix && |
942 | 2 | av_opt_find(&cc, t->key + 1, NULL, flags, | |
943 | AV_OPT_SEARCH_FAKE_OBJ)) | ||
944 | 1 | av_dict_set(&ret, t->key + 1, t->value, 0); | |
945 | |||
946 |
2/2✓ Branch 0 taken 199 times.
✓ Branch 1 taken 57562 times.
|
57761 | if (p) |
947 | 199 | *p = ':'; | |
948 | } | ||
949 | 20141 | return ret; | |
950 | } | ||
951 | |||
952 | 6395 | AVDictionary **setup_find_stream_info_opts(AVFormatContext *s, | |
953 | AVDictionary *codec_opts) | ||
954 | { | ||
955 | int i; | ||
956 | AVDictionary **opts; | ||
957 | |||
958 |
2/2✓ Branch 0 taken 64 times.
✓ Branch 1 taken 6331 times.
|
6395 | if (!s->nb_streams) |
959 | 64 | return NULL; | |
960 | 6331 | opts = av_calloc(s->nb_streams, sizeof(*opts)); | |
961 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6331 times.
|
6331 | if (!opts) { |
962 | ✗ | av_log(NULL, AV_LOG_ERROR, | |
963 | "Could not alloc memory for stream options.\n"); | ||
964 | ✗ | exit_program(1); | |
965 | } | ||
966 |
2/2✓ Branch 0 taken 6781 times.
✓ Branch 1 taken 6331 times.
|
13112 | for (i = 0; i < s->nb_streams; i++) |
967 | 6781 | opts[i] = filter_codec_opts(codec_opts, s->streams[i]->codecpar->codec_id, | |
968 | 6781 | s, s->streams[i], NULL); | |
969 | 6331 | return opts; | |
970 | } | ||
971 | |||
972 | 116409 | void *grow_array(void *array, int elem_size, int *size, int new_size) | |
973 | { | ||
974 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 116409 times.
|
116409 | if (new_size >= INT_MAX / elem_size) { |
975 | ✗ | av_log(NULL, AV_LOG_ERROR, "Array too big.\n"); | |
976 | ✗ | exit_program(1); | |
977 | } | ||
978 |
1/2✓ Branch 0 taken 116409 times.
✗ Branch 1 not taken.
|
116409 | if (*size < new_size) { |
979 | 116409 | uint8_t *tmp = av_realloc_array(array, new_size, elem_size); | |
980 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 116409 times.
|
116409 | if (!tmp) { |
981 | ✗ | av_log(NULL, AV_LOG_ERROR, "Could not alloc buffer.\n"); | |
982 | ✗ | exit_program(1); | |
983 | } | ||
984 | 116409 | memset(tmp + *size*elem_size, 0, (new_size-*size) * elem_size); | |
985 | 116409 | *size = new_size; | |
986 | 116409 | return tmp; | |
987 | } | ||
988 | ✗ | return array; | |
989 | } | ||
990 | |||
991 | 37811 | void *allocate_array_elem(void *ptr, size_t elem_size, int *nb_elems) | |
992 | { | ||
993 | void *new_elem; | ||
994 | |||
995 |
2/4✓ Branch 1 taken 37811 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 37811 times.
|
75622 | if (!(new_elem = av_mallocz(elem_size)) || |
996 | 37811 | av_dynarray_add_nofree(ptr, nb_elems, new_elem) < 0) { | |
997 | ✗ | av_log(NULL, AV_LOG_ERROR, "Could not alloc buffer.\n"); | |
998 | ✗ | exit_program(1); | |
999 | } | ||
1000 | 37811 | return new_elem; | |
1001 | } | ||
1002 | |||
1003 | 4879 | double get_rotation(int32_t *displaymatrix) | |
1004 | { | ||
1005 | 4879 | double theta = 0; | |
1006 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4878 times.
|
4879 | if (displaymatrix) |
1007 | 1 | theta = -round(av_display_rotation_get((int32_t*) displaymatrix)); | |
1008 | |||
1009 | 4879 | theta -= 360*floor(theta/360 + 0.9/360); | |
1010 | |||
1011 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4879 times.
|
4879 | if (fabs(theta - 90*round(theta/90)) > 2) |
1012 | ✗ | av_log(NULL, AV_LOG_WARNING, "Odd rotation angle.\n" | |
1013 | "If you want to help, upload a sample " | ||
1014 | "of this file to https://streams.videolan.org/upload/ " | ||
1015 | "and contact the ffmpeg-devel mailing list. (ffmpeg-devel@ffmpeg.org)"); | ||
1016 | |||
1017 | 4879 | return theta; | |
1018 | } | ||
1019 |