Mercurial > hg > pmhd
comparison ffmpeg/cmdutils.c @ 10:6840f77b83aa
commit
author | Yading Song <yading.song@eecs.qmul.ac.uk> |
---|---|
date | Sun, 21 Apr 2013 10:55:35 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
9:ed610a0bbf83 | 10:6840f77b83aa |
---|---|
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 <stdlib.h> | |
24 #include <errno.h> | |
25 #include <math.h> | |
26 | |
27 /* Include only the enabled headers since some compilers (namely, Sun | |
28 Studio) will not omit unused inline functions and create undefined | |
29 references to libraries that are not being built. */ | |
30 | |
31 #include "config.h" | |
32 #include "compat/va_copy.h" | |
33 #include "libavformat/avformat.h" | |
34 #include "libavfilter/avfilter.h" | |
35 #include "libavdevice/avdevice.h" | |
36 #include "libavresample/avresample.h" | |
37 #include "libswscale/swscale.h" | |
38 #include "libswresample/swresample.h" | |
39 #include "libpostproc/postprocess.h" | |
40 #include "libavutil/avassert.h" | |
41 #include "libavutil/avstring.h" | |
42 #include "libavutil/bprint.h" | |
43 #include "libavutil/mathematics.h" | |
44 #include "libavutil/imgutils.h" | |
45 #include "libavutil/parseutils.h" | |
46 #include "libavutil/pixdesc.h" | |
47 #include "libavutil/eval.h" | |
48 #include "libavutil/dict.h" | |
49 #include "libavutil/opt.h" | |
50 #include "cmdutils.h" | |
51 #include "version.h" | |
52 #if CONFIG_NETWORK | |
53 #include "libavformat/network.h" | |
54 #endif | |
55 #if HAVE_SYS_RESOURCE_H | |
56 #include <sys/time.h> | |
57 #include <sys/resource.h> | |
58 #endif | |
59 #if CONFIG_OPENCL | |
60 #include "libavutil/opencl.h" | |
61 #endif | |
62 | |
63 | |
64 static int init_report(const char *env); | |
65 | |
66 struct SwsContext *sws_opts; | |
67 AVDictionary *swr_opts; | |
68 AVDictionary *format_opts, *codec_opts, *resample_opts; | |
69 | |
70 const int this_year = 2013; | |
71 | |
72 static FILE *report_file; | |
73 | |
74 void init_opts(void) | |
75 { | |
76 | |
77 if(CONFIG_SWSCALE) | |
78 sws_opts = sws_getContext(16, 16, 0, 16, 16, 0, SWS_BICUBIC, | |
79 NULL, NULL, NULL); | |
80 } | |
81 | |
82 void uninit_opts(void) | |
83 { | |
84 #if CONFIG_SWSCALE | |
85 sws_freeContext(sws_opts); | |
86 sws_opts = NULL; | |
87 #endif | |
88 | |
89 av_dict_free(&swr_opts); | |
90 av_dict_free(&format_opts); | |
91 av_dict_free(&codec_opts); | |
92 av_dict_free(&resample_opts); | |
93 } | |
94 | |
95 void log_callback_help(void *ptr, int level, const char *fmt, va_list vl) | |
96 { | |
97 vfprintf(stdout, fmt, vl); | |
98 } | |
99 | |
100 static void log_callback_report(void *ptr, int level, const char *fmt, va_list vl) | |
101 { | |
102 va_list vl2; | |
103 char line[1024]; | |
104 static int print_prefix = 1; | |
105 | |
106 va_copy(vl2, vl); | |
107 av_log_default_callback(ptr, level, fmt, vl); | |
108 av_log_format_line(ptr, level, fmt, vl2, line, sizeof(line), &print_prefix); | |
109 va_end(vl2); | |
110 fputs(line, report_file); | |
111 fflush(report_file); | |
112 } | |
113 | |
114 double parse_number_or_die(const char *context, const char *numstr, int type, | |
115 double min, double max) | |
116 { | |
117 char *tail; | |
118 const char *error; | |
119 double d = av_strtod(numstr, &tail); | |
120 if (*tail) | |
121 error = "Expected number for %s but found: %s\n"; | |
122 else if (d < min || d > max) | |
123 error = "The value for %s was %s which is not within %f - %f\n"; | |
124 else if (type == OPT_INT64 && (int64_t)d != d) | |
125 error = "Expected int64 for %s but found %s\n"; | |
126 else if (type == OPT_INT && (int)d != d) | |
127 error = "Expected int for %s but found %s\n"; | |
128 else | |
129 return d; | |
130 av_log(NULL, AV_LOG_FATAL, error, context, numstr, min, max); | |
131 exit(1); | |
132 return 0; | |
133 } | |
134 | |
135 int64_t parse_time_or_die(const char *context, const char *timestr, | |
136 int is_duration) | |
137 { | |
138 int64_t us; | |
139 if (av_parse_time(&us, timestr, is_duration) < 0) { | |
140 av_log(NULL, AV_LOG_FATAL, "Invalid %s specification for %s: %s\n", | |
141 is_duration ? "duration" : "date", context, timestr); | |
142 exit(1); | |
143 } | |
144 return us; | |
145 } | |
146 | |
147 void show_help_options(const OptionDef *options, const char *msg, int req_flags, | |
148 int rej_flags, int alt_flags) | |
149 { | |
150 const OptionDef *po; | |
151 int first; | |
152 | |
153 first = 1; | |
154 for (po = options; po->name != NULL; po++) { | |
155 char buf[64]; | |
156 | |
157 if (((po->flags & req_flags) != req_flags) || | |
158 (alt_flags && !(po->flags & alt_flags)) || | |
159 (po->flags & rej_flags)) | |
160 continue; | |
161 | |
162 if (first) { | |
163 printf("%s\n", msg); | |
164 first = 0; | |
165 } | |
166 av_strlcpy(buf, po->name, sizeof(buf)); | |
167 if (po->argname) { | |
168 av_strlcat(buf, " ", sizeof(buf)); | |
169 av_strlcat(buf, po->argname, sizeof(buf)); | |
170 } | |
171 printf("-%-17s %s\n", buf, po->help); | |
172 } | |
173 printf("\n"); | |
174 } | |
175 | |
176 void show_help_children(const AVClass *class, int flags) | |
177 { | |
178 const AVClass *child = NULL; | |
179 if (class->option) { | |
180 av_opt_show2(&class, NULL, flags, 0); | |
181 printf("\n"); | |
182 } | |
183 | |
184 while (child = av_opt_child_class_next(class, child)) | |
185 show_help_children(child, flags); | |
186 } | |
187 | |
188 static const OptionDef *find_option(const OptionDef *po, const char *name) | |
189 { | |
190 const char *p = strchr(name, ':'); | |
191 int len = p ? p - name : strlen(name); | |
192 | |
193 while (po->name != NULL) { | |
194 if (!strncmp(name, po->name, len) && strlen(po->name) == len) | |
195 break; | |
196 po++; | |
197 } | |
198 return po; | |
199 } | |
200 | |
201 #if HAVE_COMMANDLINETOARGVW | |
202 #include <windows.h> | |
203 #include <shellapi.h> | |
204 /* Will be leaked on exit */ | |
205 static char** win32_argv_utf8 = NULL; | |
206 static int win32_argc = 0; | |
207 | |
208 /** | |
209 * Prepare command line arguments for executable. | |
210 * For Windows - perform wide-char to UTF-8 conversion. | |
211 * Input arguments should be main() function arguments. | |
212 * @param argc_ptr Arguments number (including executable) | |
213 * @param argv_ptr Arguments list. | |
214 */ | |
215 static void prepare_app_arguments(int *argc_ptr, char ***argv_ptr) | |
216 { | |
217 char *argstr_flat; | |
218 wchar_t **argv_w; | |
219 int i, buffsize = 0, offset = 0; | |
220 | |
221 if (win32_argv_utf8) { | |
222 *argc_ptr = win32_argc; | |
223 *argv_ptr = win32_argv_utf8; | |
224 return; | |
225 } | |
226 | |
227 win32_argc = 0; | |
228 argv_w = CommandLineToArgvW(GetCommandLineW(), &win32_argc); | |
229 if (win32_argc <= 0 || !argv_w) | |
230 return; | |
231 | |
232 /* determine the UTF-8 buffer size (including NULL-termination symbols) */ | |
233 for (i = 0; i < win32_argc; i++) | |
234 buffsize += WideCharToMultiByte(CP_UTF8, 0, argv_w[i], -1, | |
235 NULL, 0, NULL, NULL); | |
236 | |
237 win32_argv_utf8 = av_mallocz(sizeof(char *) * (win32_argc + 1) + buffsize); | |
238 argstr_flat = (char *)win32_argv_utf8 + sizeof(char *) * (win32_argc + 1); | |
239 if (win32_argv_utf8 == NULL) { | |
240 LocalFree(argv_w); | |
241 return; | |
242 } | |
243 | |
244 for (i = 0; i < win32_argc; i++) { | |
245 win32_argv_utf8[i] = &argstr_flat[offset]; | |
246 offset += WideCharToMultiByte(CP_UTF8, 0, argv_w[i], -1, | |
247 &argstr_flat[offset], | |
248 buffsize - offset, NULL, NULL); | |
249 } | |
250 win32_argv_utf8[i] = NULL; | |
251 LocalFree(argv_w); | |
252 | |
253 *argc_ptr = win32_argc; | |
254 *argv_ptr = win32_argv_utf8; | |
255 } | |
256 #else | |
257 static inline void prepare_app_arguments(int *argc_ptr, char ***argv_ptr) | |
258 { | |
259 /* nothing to do */ | |
260 } | |
261 #endif /* HAVE_COMMANDLINETOARGVW */ | |
262 | |
263 static int write_option(void *optctx, const OptionDef *po, const char *opt, | |
264 const char *arg) | |
265 { | |
266 /* new-style options contain an offset into optctx, old-style address of | |
267 * a global var*/ | |
268 void *dst = po->flags & (OPT_OFFSET | OPT_SPEC) ? | |
269 (uint8_t *)optctx + po->u.off : po->u.dst_ptr; | |
270 int *dstcount; | |
271 | |
272 if (po->flags & OPT_SPEC) { | |
273 SpecifierOpt **so = dst; | |
274 char *p = strchr(opt, ':'); | |
275 | |
276 dstcount = (int *)(so + 1); | |
277 *so = grow_array(*so, sizeof(**so), dstcount, *dstcount + 1); | |
278 (*so)[*dstcount - 1].specifier = av_strdup(p ? p + 1 : ""); | |
279 dst = &(*so)[*dstcount - 1].u; | |
280 } | |
281 | |
282 if (po->flags & OPT_STRING) { | |
283 char *str; | |
284 str = av_strdup(arg); | |
285 av_freep(dst); | |
286 *(char **)dst = str; | |
287 } else if (po->flags & OPT_BOOL || po->flags & OPT_INT) { | |
288 *(int *)dst = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX); | |
289 } else if (po->flags & OPT_INT64) { | |
290 *(int64_t *)dst = parse_number_or_die(opt, arg, OPT_INT64, INT64_MIN, INT64_MAX); | |
291 } else if (po->flags & OPT_TIME) { | |
292 *(int64_t *)dst = parse_time_or_die(opt, arg, 1); | |
293 } else if (po->flags & OPT_FLOAT) { | |
294 *(float *)dst = parse_number_or_die(opt, arg, OPT_FLOAT, -INFINITY, INFINITY); | |
295 } else if (po->flags & OPT_DOUBLE) { | |
296 *(double *)dst = parse_number_or_die(opt, arg, OPT_DOUBLE, -INFINITY, INFINITY); | |
297 } else if (po->u.func_arg) { | |
298 int ret = po->u.func_arg(optctx, opt, arg); | |
299 if (ret < 0) { | |
300 av_log(NULL, AV_LOG_ERROR, | |
301 "Failed to set value '%s' for option '%s': %s\n", | |
302 arg, opt, av_err2str(ret)); | |
303 return ret; | |
304 } | |
305 } | |
306 if (po->flags & OPT_EXIT) | |
307 exit(0); | |
308 | |
309 return 0; | |
310 } | |
311 | |
312 int parse_option(void *optctx, const char *opt, const char *arg, | |
313 const OptionDef *options) | |
314 { | |
315 const OptionDef *po; | |
316 int ret; | |
317 | |
318 po = find_option(options, opt); | |
319 if (!po->name && opt[0] == 'n' && opt[1] == 'o') { | |
320 /* handle 'no' bool option */ | |
321 po = find_option(options, opt + 2); | |
322 if ((po->name && (po->flags & OPT_BOOL))) | |
323 arg = "0"; | |
324 } else if (po->flags & OPT_BOOL) | |
325 arg = "1"; | |
326 | |
327 if (!po->name) | |
328 po = find_option(options, "default"); | |
329 if (!po->name) { | |
330 av_log(NULL, AV_LOG_ERROR, "Unrecognized option '%s'\n", opt); | |
331 return AVERROR(EINVAL); | |
332 } | |
333 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 ret = write_option(optctx, po, opt, arg); | |
339 if (ret < 0) | |
340 return ret; | |
341 | |
342 return !!(po->flags & HAS_ARG); | |
343 } | |
344 | |
345 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 int optindex, handleoptions = 1, ret; | |
350 | |
351 /* perform system-dependent conversions for arguments list */ | |
352 prepare_app_arguments(&argc, &argv); | |
353 | |
354 /* parse options */ | |
355 optindex = 1; | |
356 while (optindex < argc) { | |
357 opt = argv[optindex++]; | |
358 | |
359 if (handleoptions && opt[0] == '-' && opt[1] != '\0') { | |
360 if (opt[1] == '-' && opt[2] == '\0') { | |
361 handleoptions = 0; | |
362 continue; | |
363 } | |
364 opt++; | |
365 | |
366 if ((ret = parse_option(optctx, opt, argv[optindex], options)) < 0) | |
367 exit(1); | |
368 optindex += ret; | |
369 } else { | |
370 if (parse_arg_function) | |
371 parse_arg_function(optctx, opt); | |
372 } | |
373 } | |
374 } | |
375 | |
376 int parse_optgroup(void *optctx, OptionGroup *g) | |
377 { | |
378 int i, ret; | |
379 | |
380 av_log(NULL, AV_LOG_DEBUG, "Parsing a group of options: %s %s.\n", | |
381 g->group_def->name, g->arg); | |
382 | |
383 for (i = 0; i < g->nb_opts; i++) { | |
384 Option *o = &g->opts[i]; | |
385 | |
386 if (g->group_def->flags && | |
387 !(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 av_log(NULL, AV_LOG_DEBUG, "Applying option %s (%s) with argument %s.\n", | |
397 o->key, o->opt->help, o->val); | |
398 | |
399 ret = write_option(optctx, o->opt, o->key, o->val); | |
400 if (ret < 0) | |
401 return ret; | |
402 } | |
403 | |
404 av_log(NULL, AV_LOG_DEBUG, "Successfully parsed a group of options.\n"); | |
405 | |
406 return 0; | |
407 } | |
408 | |
409 int locate_option(int argc, char **argv, const OptionDef *options, | |
410 const char *optname) | |
411 { | |
412 const OptionDef *po; | |
413 int i; | |
414 | |
415 for (i = 1; i < argc; i++) { | |
416 const char *cur_opt = argv[i]; | |
417 | |
418 if (*cur_opt++ != '-') | |
419 continue; | |
420 | |
421 po = find_option(options, cur_opt); | |
422 if (!po->name && cur_opt[0] == 'n' && cur_opt[1] == 'o') | |
423 po = find_option(options, cur_opt + 2); | |
424 | |
425 if ((!po->name && !strcmp(cur_opt, optname)) || | |
426 (po->name && !strcmp(optname, po->name))) | |
427 return i; | |
428 | |
429 if (po->flags & HAS_ARG) | |
430 i++; | |
431 } | |
432 return 0; | |
433 } | |
434 | |
435 static void dump_argument(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 void parse_loglevel(int argc, char **argv, const OptionDef *options) | |
460 { | |
461 int idx = locate_option(argc, argv, options, "loglevel"); | |
462 const char *env; | |
463 if (!idx) | |
464 idx = locate_option(argc, argv, options, "v"); | |
465 if (idx && argv[idx + 1]) | |
466 opt_loglevel(NULL, "loglevel", argv[idx + 1]); | |
467 idx = locate_option(argc, argv, options, "report"); | |
468 if ((env = getenv("FFREPORT")) || idx) { | |
469 init_report(env); | |
470 if (report_file) { | |
471 int i; | |
472 fprintf(report_file, "Command line:\n"); | |
473 for (i = 0; i < argc; i++) { | |
474 dump_argument(argv[i]); | |
475 fputc(i < argc - 1 ? ' ' : '\n', report_file); | |
476 } | |
477 fflush(report_file); | |
478 } | |
479 } | |
480 } | |
481 | |
482 #define FLAGS (o->type == AV_OPT_TYPE_FLAGS) ? AV_DICT_APPEND : 0 | |
483 int opt_default(void *optctx, const char *opt, const char *arg) | |
484 { | |
485 const AVOption *o; | |
486 int consumed = 0; | |
487 char opt_stripped[128]; | |
488 const char *p; | |
489 const AVClass *cc = avcodec_get_class(), *fc = avformat_get_class(); | |
490 #if CONFIG_AVRESAMPLE | |
491 const AVClass *rc = avresample_get_class(); | |
492 #endif | |
493 const AVClass *sc, *swr_class; | |
494 | |
495 if (!strcmp(opt, "debug") || !strcmp(opt, "fdebug")) | |
496 av_log_set_level(AV_LOG_DEBUG); | |
497 | |
498 if (!(p = strchr(opt, ':'))) | |
499 p = opt + strlen(opt); | |
500 av_strlcpy(opt_stripped, opt, FFMIN(sizeof(opt_stripped), p - opt + 1)); | |
501 | |
502 if ((o = av_opt_find(&cc, opt_stripped, NULL, 0, | |
503 AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ)) || | |
504 ((opt[0] == 'v' || opt[0] == 'a' || opt[0] == 's') && | |
505 (o = av_opt_find(&cc, opt + 1, NULL, 0, AV_OPT_SEARCH_FAKE_OBJ)))) { | |
506 av_dict_set(&codec_opts, opt, arg, FLAGS); | |
507 consumed = 1; | |
508 } | |
509 if ((o = av_opt_find(&fc, opt, NULL, 0, | |
510 AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) { | |
511 av_dict_set(&format_opts, opt, arg, FLAGS); | |
512 if (consumed) | |
513 av_log(NULL, AV_LOG_VERBOSE, "Routing option %s to both codec and muxer layer\n", opt); | |
514 consumed = 1; | |
515 } | |
516 #if CONFIG_SWSCALE | |
517 sc = sws_get_class(); | |
518 if (!consumed && av_opt_find(&sc, opt, NULL, 0, | |
519 AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ)) { | |
520 // XXX we only support sws_flags, not arbitrary sws options | |
521 int ret = av_opt_set(sws_opts, opt, arg, 0); | |
522 if (ret < 0) { | |
523 av_log(NULL, AV_LOG_ERROR, "Error setting option %s.\n", opt); | |
524 return ret; | |
525 } | |
526 consumed = 1; | |
527 } | |
528 #endif | |
529 #if CONFIG_SWRESAMPLE | |
530 swr_class = swr_get_class(); | |
531 if (!consumed && (o=av_opt_find(&swr_class, opt, NULL, 0, | |
532 AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) { | |
533 struct SwrContext *swr = swr_alloc(); | |
534 int ret = av_opt_set(swr, opt, arg, 0); | |
535 swr_free(&swr); | |
536 if (ret < 0) { | |
537 av_log(NULL, AV_LOG_ERROR, "Error setting option %s.\n", opt); | |
538 return ret; | |
539 } | |
540 av_dict_set(&swr_opts, opt, arg, FLAGS); | |
541 consumed = 1; | |
542 } | |
543 #endif | |
544 #if CONFIG_AVRESAMPLE | |
545 if ((o=av_opt_find(&rc, opt, NULL, 0, | |
546 AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) { | |
547 av_dict_set(&resample_opts, opt, arg, FLAGS); | |
548 consumed = 1; | |
549 } | |
550 #endif | |
551 | |
552 if (consumed) | |
553 return 0; | |
554 return AVERROR_OPTION_NOT_FOUND; | |
555 } | |
556 | |
557 /* | |
558 * Check whether given option is a group separator. | |
559 * | |
560 * @return index of the group definition that matched or -1 if none | |
561 */ | |
562 static int match_group_separator(const OptionGroupDef *groups, int nb_groups, | |
563 const char *opt) | |
564 { | |
565 int i; | |
566 | |
567 for (i = 0; i < nb_groups; i++) { | |
568 const OptionGroupDef *p = &groups[i]; | |
569 if (p->sep && !strcmp(p->sep, opt)) | |
570 return i; | |
571 } | |
572 | |
573 return -1; | |
574 } | |
575 | |
576 /* | |
577 * Finish parsing an option group. | |
578 * | |
579 * @param group_idx which group definition should this group belong to | |
580 * @param arg argument of the group delimiting option | |
581 */ | |
582 static void finish_group(OptionParseContext *octx, int group_idx, | |
583 const char *arg) | |
584 { | |
585 OptionGroupList *l = &octx->groups[group_idx]; | |
586 OptionGroup *g; | |
587 | |
588 GROW_ARRAY(l->groups, l->nb_groups); | |
589 g = &l->groups[l->nb_groups - 1]; | |
590 | |
591 *g = octx->cur_group; | |
592 g->arg = arg; | |
593 g->group_def = l->group_def; | |
594 #if CONFIG_SWSCALE | |
595 g->sws_opts = sws_opts; | |
596 #endif | |
597 g->swr_opts = swr_opts; | |
598 g->codec_opts = codec_opts; | |
599 g->format_opts = format_opts; | |
600 g->resample_opts = resample_opts; | |
601 | |
602 codec_opts = NULL; | |
603 format_opts = NULL; | |
604 resample_opts = NULL; | |
605 #if CONFIG_SWSCALE | |
606 sws_opts = NULL; | |
607 #endif | |
608 swr_opts = NULL; | |
609 init_opts(); | |
610 | |
611 memset(&octx->cur_group, 0, sizeof(octx->cur_group)); | |
612 } | |
613 | |
614 /* | |
615 * Add an option instance to currently parsed group. | |
616 */ | |
617 static void add_opt(OptionParseContext *octx, const OptionDef *opt, | |
618 const char *key, const char *val) | |
619 { | |
620 int global = !(opt->flags & (OPT_PERFILE | OPT_SPEC | OPT_OFFSET)); | |
621 OptionGroup *g = global ? &octx->global_opts : &octx->cur_group; | |
622 | |
623 GROW_ARRAY(g->opts, g->nb_opts); | |
624 g->opts[g->nb_opts - 1].opt = opt; | |
625 g->opts[g->nb_opts - 1].key = key; | |
626 g->opts[g->nb_opts - 1].val = val; | |
627 } | |
628 | |
629 static void init_parse_context(OptionParseContext *octx, | |
630 const OptionGroupDef *groups, int nb_groups) | |
631 { | |
632 static const OptionGroupDef global_group = { "global" }; | |
633 int i; | |
634 | |
635 memset(octx, 0, sizeof(*octx)); | |
636 | |
637 octx->nb_groups = nb_groups; | |
638 octx->groups = av_mallocz(sizeof(*octx->groups) * octx->nb_groups); | |
639 if (!octx->groups) | |
640 exit(1); | |
641 | |
642 for (i = 0; i < octx->nb_groups; i++) | |
643 octx->groups[i].group_def = &groups[i]; | |
644 | |
645 octx->global_opts.group_def = &global_group; | |
646 octx->global_opts.arg = ""; | |
647 | |
648 init_opts(); | |
649 } | |
650 | |
651 void uninit_parse_context(OptionParseContext *octx) | |
652 { | |
653 int i, j; | |
654 | |
655 for (i = 0; i < octx->nb_groups; i++) { | |
656 OptionGroupList *l = &octx->groups[i]; | |
657 | |
658 for (j = 0; j < l->nb_groups; j++) { | |
659 av_freep(&l->groups[j].opts); | |
660 av_dict_free(&l->groups[j].codec_opts); | |
661 av_dict_free(&l->groups[j].format_opts); | |
662 av_dict_free(&l->groups[j].resample_opts); | |
663 #if CONFIG_SWSCALE | |
664 sws_freeContext(l->groups[j].sws_opts); | |
665 #endif | |
666 av_dict_free(&l->groups[j].swr_opts); | |
667 } | |
668 av_freep(&l->groups); | |
669 } | |
670 av_freep(&octx->groups); | |
671 | |
672 av_freep(&octx->cur_group.opts); | |
673 av_freep(&octx->global_opts.opts); | |
674 | |
675 uninit_opts(); | |
676 } | |
677 | |
678 int split_commandline(OptionParseContext *octx, int argc, char *argv[], | |
679 const OptionDef *options, | |
680 const OptionGroupDef *groups, int nb_groups) | |
681 { | |
682 int optindex = 1; | |
683 int dashdash = -2; | |
684 | |
685 /* perform system-dependent conversions for arguments list */ | |
686 prepare_app_arguments(&argc, &argv); | |
687 | |
688 init_parse_context(octx, groups, nb_groups); | |
689 av_log(NULL, AV_LOG_DEBUG, "Splitting the commandline.\n"); | |
690 | |
691 while (optindex < argc) { | |
692 const char *opt = argv[optindex++], *arg; | |
693 const OptionDef *po; | |
694 int ret; | |
695 | |
696 av_log(NULL, AV_LOG_DEBUG, "Reading option '%s' ...", opt); | |
697 | |
698 if (opt[0] == '-' && opt[1] == '-' && !opt[2]) { | |
699 dashdash = optindex; | |
700 continue; | |
701 } | |
702 /* unnamed group separators, e.g. output filename */ | |
703 if (opt[0] != '-' || !opt[1] || dashdash+1 == optindex) { | |
704 finish_group(octx, 0, opt); | |
705 av_log(NULL, AV_LOG_DEBUG, " matched as %s.\n", groups[0].name); | |
706 continue; | |
707 } | |
708 opt++; | |
709 | |
710 #define GET_ARG(arg) \ | |
711 do { \ | |
712 arg = argv[optindex++]; \ | |
713 if (!arg) { \ | |
714 av_log(NULL, AV_LOG_ERROR, "Missing argument for option '%s'.\n", opt);\ | |
715 return AVERROR(EINVAL); \ | |
716 } \ | |
717 } while (0) | |
718 | |
719 /* named group separators, e.g. -i */ | |
720 if ((ret = match_group_separator(groups, nb_groups, opt)) >= 0) { | |
721 GET_ARG(arg); | |
722 finish_group(octx, ret, arg); | |
723 av_log(NULL, AV_LOG_DEBUG, " matched as %s with argument '%s'.\n", | |
724 groups[ret].name, arg); | |
725 continue; | |
726 } | |
727 | |
728 /* normal options */ | |
729 po = find_option(options, opt); | |
730 if (po->name) { | |
731 if (po->flags & OPT_EXIT) { | |
732 /* optional argument, e.g. -h */ | |
733 arg = argv[optindex++]; | |
734 } else if (po->flags & HAS_ARG) { | |
735 GET_ARG(arg); | |
736 } else { | |
737 arg = "1"; | |
738 } | |
739 | |
740 add_opt(octx, po, opt, arg); | |
741 av_log(NULL, AV_LOG_DEBUG, " matched as option '%s' (%s) with " | |
742 "argument '%s'.\n", po->name, po->help, arg); | |
743 continue; | |
744 } | |
745 | |
746 /* AVOptions */ | |
747 if (argv[optindex]) { | |
748 ret = opt_default(NULL, opt, argv[optindex]); | |
749 if (ret >= 0) { | |
750 av_log(NULL, AV_LOG_DEBUG, " matched as AVOption '%s' with " | |
751 "argument '%s'.\n", opt, argv[optindex]); | |
752 optindex++; | |
753 continue; | |
754 } else if (ret != AVERROR_OPTION_NOT_FOUND) { | |
755 av_log(NULL, AV_LOG_ERROR, "Error parsing option '%s' " | |
756 "with argument '%s'.\n", opt, argv[optindex]); | |
757 return ret; | |
758 } | |
759 } | |
760 | |
761 /* boolean -nofoo options */ | |
762 if (opt[0] == 'n' && opt[1] == 'o' && | |
763 (po = find_option(options, opt + 2)) && | |
764 po->name && po->flags & OPT_BOOL) { | |
765 add_opt(octx, po, opt, "0"); | |
766 av_log(NULL, AV_LOG_DEBUG, " matched as option '%s' (%s) with " | |
767 "argument 0.\n", po->name, po->help); | |
768 continue; | |
769 } | |
770 | |
771 av_log(NULL, AV_LOG_ERROR, "Unrecognized option '%s'.\n", opt); | |
772 return AVERROR_OPTION_NOT_FOUND; | |
773 } | |
774 | |
775 if (octx->cur_group.nb_opts || codec_opts || format_opts || resample_opts) | |
776 av_log(NULL, AV_LOG_WARNING, "Trailing options were found on the " | |
777 "commandline.\n"); | |
778 | |
779 av_log(NULL, AV_LOG_DEBUG, "Finished splitting the commandline.\n"); | |
780 | |
781 return 0; | |
782 } | |
783 | |
784 int opt_loglevel(void *optctx, const char *opt, const char *arg) | |
785 { | |
786 const struct { const char *name; int level; } log_levels[] = { | |
787 { "quiet" , AV_LOG_QUIET }, | |
788 { "panic" , AV_LOG_PANIC }, | |
789 { "fatal" , AV_LOG_FATAL }, | |
790 { "error" , AV_LOG_ERROR }, | |
791 { "warning", AV_LOG_WARNING }, | |
792 { "info" , AV_LOG_INFO }, | |
793 { "verbose", AV_LOG_VERBOSE }, | |
794 { "debug" , AV_LOG_DEBUG }, | |
795 }; | |
796 char *tail; | |
797 int level; | |
798 int i; | |
799 | |
800 tail = strstr(arg, "repeat"); | |
801 av_log_set_flags(tail ? 0 : AV_LOG_SKIP_REPEATED); | |
802 if (tail == arg) | |
803 arg += 6 + (arg[6]=='+'); | |
804 if(tail && !*arg) | |
805 return 0; | |
806 | |
807 for (i = 0; i < FF_ARRAY_ELEMS(log_levels); i++) { | |
808 if (!strcmp(log_levels[i].name, arg)) { | |
809 av_log_set_level(log_levels[i].level); | |
810 return 0; | |
811 } | |
812 } | |
813 | |
814 level = strtol(arg, &tail, 10); | |
815 if (*tail) { | |
816 av_log(NULL, AV_LOG_FATAL, "Invalid loglevel \"%s\". " | |
817 "Possible levels are numbers or:\n", arg); | |
818 for (i = 0; i < FF_ARRAY_ELEMS(log_levels); i++) | |
819 av_log(NULL, AV_LOG_FATAL, "\"%s\"\n", log_levels[i].name); | |
820 exit(1); | |
821 } | |
822 av_log_set_level(level); | |
823 return 0; | |
824 } | |
825 | |
826 static void expand_filename_template(AVBPrint *bp, const char *template, | |
827 struct tm *tm) | |
828 { | |
829 int c; | |
830 | |
831 while ((c = *(template++))) { | |
832 if (c == '%') { | |
833 if (!(c = *(template++))) | |
834 break; | |
835 switch (c) { | |
836 case 'p': | |
837 av_bprintf(bp, "%s", program_name); | |
838 break; | |
839 case 't': | |
840 av_bprintf(bp, "%04d%02d%02d-%02d%02d%02d", | |
841 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, | |
842 tm->tm_hour, tm->tm_min, tm->tm_sec); | |
843 break; | |
844 case '%': | |
845 av_bprint_chars(bp, c, 1); | |
846 break; | |
847 } | |
848 } else { | |
849 av_bprint_chars(bp, c, 1); | |
850 } | |
851 } | |
852 } | |
853 | |
854 static int init_report(const char *env) | |
855 { | |
856 char *filename_template = NULL; | |
857 char *key, *val; | |
858 int ret, count = 0; | |
859 time_t now; | |
860 struct tm *tm; | |
861 AVBPrint filename; | |
862 | |
863 if (report_file) /* already opened */ | |
864 return 0; | |
865 time(&now); | |
866 tm = localtime(&now); | |
867 | |
868 while (env && *env) { | |
869 if ((ret = av_opt_get_key_value(&env, "=", ":", 0, &key, &val)) < 0) { | |
870 if (count) | |
871 av_log(NULL, AV_LOG_ERROR, | |
872 "Failed to parse FFREPORT environment variable: %s\n", | |
873 av_err2str(ret)); | |
874 break; | |
875 } | |
876 if (*env) | |
877 env++; | |
878 count++; | |
879 if (!strcmp(key, "file")) { | |
880 av_free(filename_template); | |
881 filename_template = val; | |
882 val = NULL; | |
883 } else { | |
884 av_log(NULL, AV_LOG_ERROR, "Unknown key '%s' in FFREPORT\n", key); | |
885 } | |
886 av_free(val); | |
887 av_free(key); | |
888 } | |
889 | |
890 av_bprint_init(&filename, 0, 1); | |
891 expand_filename_template(&filename, | |
892 av_x_if_null(filename_template, "%p-%t.log"), tm); | |
893 av_free(filename_template); | |
894 if (!av_bprint_is_complete(&filename)) { | |
895 av_log(NULL, AV_LOG_ERROR, "Out of memory building report file name\n"); | |
896 return AVERROR(ENOMEM); | |
897 } | |
898 | |
899 report_file = fopen(filename.str, "w"); | |
900 if (!report_file) { | |
901 av_log(NULL, AV_LOG_ERROR, "Failed to open report \"%s\": %s\n", | |
902 filename.str, strerror(errno)); | |
903 return AVERROR(errno); | |
904 } | |
905 av_log_set_callback(log_callback_report); | |
906 av_log(NULL, AV_LOG_INFO, | |
907 "%s started on %04d-%02d-%02d at %02d:%02d:%02d\n" | |
908 "Report written to \"%s\"\n", | |
909 program_name, | |
910 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, | |
911 tm->tm_hour, tm->tm_min, tm->tm_sec, | |
912 filename.str); | |
913 av_log_set_level(FFMAX(av_log_get_level(), AV_LOG_VERBOSE)); | |
914 av_bprint_finalize(&filename, NULL); | |
915 return 0; | |
916 } | |
917 | |
918 int opt_report(const char *opt) | |
919 { | |
920 return init_report(NULL); | |
921 } | |
922 | |
923 int opt_max_alloc(void *optctx, const char *opt, const char *arg) | |
924 { | |
925 char *tail; | |
926 size_t max; | |
927 | |
928 max = strtol(arg, &tail, 10); | |
929 if (*tail) { | |
930 av_log(NULL, AV_LOG_FATAL, "Invalid max_alloc \"%s\".\n", arg); | |
931 exit(1); | |
932 } | |
933 av_max_alloc(max); | |
934 return 0; | |
935 } | |
936 | |
937 int opt_cpuflags(void *optctx, const char *opt, const char *arg) | |
938 { | |
939 int ret; | |
940 unsigned flags = av_get_cpu_flags(); | |
941 | |
942 if ((ret = av_parse_cpu_caps(&flags, arg)) < 0) | |
943 return ret; | |
944 | |
945 av_force_cpu_flags(flags); | |
946 return 0; | |
947 } | |
948 | |
949 int opt_timelimit(void *optctx, const char *opt, const char *arg) | |
950 { | |
951 #if HAVE_SETRLIMIT | |
952 int lim = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX); | |
953 struct rlimit rl = { lim, lim + 1 }; | |
954 if (setrlimit(RLIMIT_CPU, &rl)) | |
955 perror("setrlimit"); | |
956 #else | |
957 av_log(NULL, AV_LOG_WARNING, "-%s not implemented on this OS\n", opt); | |
958 #endif | |
959 return 0; | |
960 } | |
961 | |
962 #if CONFIG_OPENCL | |
963 int opt_opencl(void *optctx, const char *opt, const char *arg) | |
964 { | |
965 char *key, *value; | |
966 const char *opts = arg; | |
967 int ret = 0; | |
968 while (*opts) { | |
969 ret = av_opt_get_key_value(&opts, "=", ":", 0, &key, &value); | |
970 if (ret < 0) | |
971 return ret; | |
972 ret = av_opencl_set_option(key, value); | |
973 if (ret < 0) | |
974 return ret; | |
975 if (*opts) | |
976 opts++; | |
977 } | |
978 return ret; | |
979 } | |
980 #endif | |
981 | |
982 void print_error(const char *filename, int err) | |
983 { | |
984 char errbuf[128]; | |
985 const char *errbuf_ptr = errbuf; | |
986 | |
987 if (av_strerror(err, errbuf, sizeof(errbuf)) < 0) | |
988 errbuf_ptr = strerror(AVUNERROR(err)); | |
989 av_log(NULL, AV_LOG_ERROR, "%s: %s\n", filename, errbuf_ptr); | |
990 } | |
991 | |
992 static int warned_cfg = 0; | |
993 | |
994 #define INDENT 1 | |
995 #define SHOW_VERSION 2 | |
996 #define SHOW_CONFIG 4 | |
997 #define SHOW_COPYRIGHT 8 | |
998 | |
999 #define PRINT_LIB_INFO(libname, LIBNAME, flags, level) \ | |
1000 if (CONFIG_##LIBNAME) { \ | |
1001 const char *indent = flags & INDENT? " " : ""; \ | |
1002 if (flags & SHOW_VERSION) { \ | |
1003 unsigned int version = libname##_version(); \ | |
1004 av_log(NULL, level, \ | |
1005 "%slib%-11s %2d.%3d.%3d / %2d.%3d.%3d\n", \ | |
1006 indent, #libname, \ | |
1007 LIB##LIBNAME##_VERSION_MAJOR, \ | |
1008 LIB##LIBNAME##_VERSION_MINOR, \ | |
1009 LIB##LIBNAME##_VERSION_MICRO, \ | |
1010 version >> 16, version >> 8 & 0xff, version & 0xff); \ | |
1011 } \ | |
1012 if (flags & SHOW_CONFIG) { \ | |
1013 const char *cfg = libname##_configuration(); \ | |
1014 if (strcmp(FFMPEG_CONFIGURATION, cfg)) { \ | |
1015 if (!warned_cfg) { \ | |
1016 av_log(NULL, level, \ | |
1017 "%sWARNING: library configuration mismatch\n", \ | |
1018 indent); \ | |
1019 warned_cfg = 1; \ | |
1020 } \ | |
1021 av_log(NULL, level, "%s%-11s configuration: %s\n", \ | |
1022 indent, #libname, cfg); \ | |
1023 } \ | |
1024 } \ | |
1025 } \ | |
1026 | |
1027 static void print_all_libs_info(int flags, int level) | |
1028 { | |
1029 PRINT_LIB_INFO(avutil, AVUTIL, flags, level); | |
1030 PRINT_LIB_INFO(avcodec, AVCODEC, flags, level); | |
1031 PRINT_LIB_INFO(avformat, AVFORMAT, flags, level); | |
1032 PRINT_LIB_INFO(avdevice, AVDEVICE, flags, level); | |
1033 PRINT_LIB_INFO(avfilter, AVFILTER, flags, level); | |
1034 PRINT_LIB_INFO(avresample, AVRESAMPLE, flags, level); | |
1035 PRINT_LIB_INFO(swscale, SWSCALE, flags, level); | |
1036 PRINT_LIB_INFO(swresample,SWRESAMPLE, flags, level); | |
1037 PRINT_LIB_INFO(postproc, POSTPROC, flags, level); | |
1038 } | |
1039 | |
1040 static void print_program_info(int flags, int level) | |
1041 { | |
1042 const char *indent = flags & INDENT? " " : ""; | |
1043 | |
1044 av_log(NULL, level, "%s version " FFMPEG_VERSION, program_name); | |
1045 if (flags & SHOW_COPYRIGHT) | |
1046 av_log(NULL, level, " Copyright (c) %d-%d the FFmpeg developers", | |
1047 program_birth_year, this_year); | |
1048 av_log(NULL, level, "\n"); | |
1049 av_log(NULL, level, "%sbuilt on %s %s with %s\n", | |
1050 indent, __DATE__, __TIME__, CC_IDENT); | |
1051 | |
1052 av_log(NULL, level, "%sconfiguration: " FFMPEG_CONFIGURATION "\n", indent); | |
1053 } | |
1054 | |
1055 void show_banner(int argc, char **argv, const OptionDef *options) | |
1056 { | |
1057 int idx = locate_option(argc, argv, options, "version"); | |
1058 if (idx) | |
1059 return; | |
1060 | |
1061 print_program_info (INDENT|SHOW_COPYRIGHT, AV_LOG_INFO); | |
1062 print_all_libs_info(INDENT|SHOW_CONFIG, AV_LOG_INFO); | |
1063 print_all_libs_info(INDENT|SHOW_VERSION, AV_LOG_INFO); | |
1064 } | |
1065 | |
1066 int show_version(void *optctx, const char *opt, const char *arg) | |
1067 { | |
1068 av_log_set_callback(log_callback_help); | |
1069 print_program_info (0 , AV_LOG_INFO); | |
1070 print_all_libs_info(SHOW_VERSION, AV_LOG_INFO); | |
1071 | |
1072 return 0; | |
1073 } | |
1074 | |
1075 int show_license(void *optctx, const char *opt, const char *arg) | |
1076 { | |
1077 #if CONFIG_NONFREE | |
1078 printf( | |
1079 "This version of %s has nonfree parts compiled in.\n" | |
1080 "Therefore it is not legally redistributable.\n", | |
1081 program_name ); | |
1082 #elif CONFIG_GPLV3 | |
1083 printf( | |
1084 "%s is free software; you can redistribute it and/or modify\n" | |
1085 "it under the terms of the GNU General Public License as published by\n" | |
1086 "the Free Software Foundation; either version 3 of the License, or\n" | |
1087 "(at your option) any later version.\n" | |
1088 "\n" | |
1089 "%s is distributed in the hope that it will be useful,\n" | |
1090 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" | |
1091 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" | |
1092 "GNU General Public License for more details.\n" | |
1093 "\n" | |
1094 "You should have received a copy of the GNU General Public License\n" | |
1095 "along with %s. If not, see <http://www.gnu.org/licenses/>.\n", | |
1096 program_name, program_name, program_name ); | |
1097 #elif CONFIG_GPL | |
1098 printf( | |
1099 "%s is free software; you can redistribute it and/or modify\n" | |
1100 "it under the terms of the GNU General Public License as published by\n" | |
1101 "the Free Software Foundation; either version 2 of the License, or\n" | |
1102 "(at your option) any later version.\n" | |
1103 "\n" | |
1104 "%s is distributed in the hope that it will be useful,\n" | |
1105 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" | |
1106 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" | |
1107 "GNU General Public License for more details.\n" | |
1108 "\n" | |
1109 "You should have received a copy of the GNU General Public License\n" | |
1110 "along with %s; if not, write to the Free Software\n" | |
1111 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n", | |
1112 program_name, program_name, program_name ); | |
1113 #elif CONFIG_LGPLV3 | |
1114 printf( | |
1115 "%s is free software; you can redistribute it and/or modify\n" | |
1116 "it under the terms of the GNU Lesser General Public License as published by\n" | |
1117 "the Free Software Foundation; either version 3 of the License, or\n" | |
1118 "(at your option) any later version.\n" | |
1119 "\n" | |
1120 "%s is distributed in the hope that it will be useful,\n" | |
1121 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" | |
1122 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" | |
1123 "GNU Lesser General Public License for more details.\n" | |
1124 "\n" | |
1125 "You should have received a copy of the GNU Lesser General Public License\n" | |
1126 "along with %s. If not, see <http://www.gnu.org/licenses/>.\n", | |
1127 program_name, program_name, program_name ); | |
1128 #else | |
1129 printf( | |
1130 "%s is free software; you can redistribute it and/or\n" | |
1131 "modify it under the terms of the GNU Lesser General Public\n" | |
1132 "License as published by the Free Software Foundation; either\n" | |
1133 "version 2.1 of the License, or (at your option) any later version.\n" | |
1134 "\n" | |
1135 "%s is distributed in the hope that it will be useful,\n" | |
1136 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" | |
1137 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" | |
1138 "Lesser General Public License for more details.\n" | |
1139 "\n" | |
1140 "You should have received a copy of the GNU Lesser General Public\n" | |
1141 "License along with %s; if not, write to the Free Software\n" | |
1142 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n", | |
1143 program_name, program_name, program_name ); | |
1144 #endif | |
1145 | |
1146 return 0; | |
1147 } | |
1148 | |
1149 int show_formats(void *optctx, const char *opt, const char *arg) | |
1150 { | |
1151 AVInputFormat *ifmt = NULL; | |
1152 AVOutputFormat *ofmt = NULL; | |
1153 const char *last_name; | |
1154 | |
1155 printf("File formats:\n" | |
1156 " D. = Demuxing supported\n" | |
1157 " .E = Muxing supported\n" | |
1158 " --\n"); | |
1159 last_name = "000"; | |
1160 for (;;) { | |
1161 int decode = 0; | |
1162 int encode = 0; | |
1163 const char *name = NULL; | |
1164 const char *long_name = NULL; | |
1165 | |
1166 while ((ofmt = av_oformat_next(ofmt))) { | |
1167 if ((name == NULL || strcmp(ofmt->name, name) < 0) && | |
1168 strcmp(ofmt->name, last_name) > 0) { | |
1169 name = ofmt->name; | |
1170 long_name = ofmt->long_name; | |
1171 encode = 1; | |
1172 } | |
1173 } | |
1174 while ((ifmt = av_iformat_next(ifmt))) { | |
1175 if ((name == NULL || strcmp(ifmt->name, name) < 0) && | |
1176 strcmp(ifmt->name, last_name) > 0) { | |
1177 name = ifmt->name; | |
1178 long_name = ifmt->long_name; | |
1179 encode = 0; | |
1180 } | |
1181 if (name && strcmp(ifmt->name, name) == 0) | |
1182 decode = 1; | |
1183 } | |
1184 if (name == NULL) | |
1185 break; | |
1186 last_name = name; | |
1187 | |
1188 printf(" %s%s %-15s %s\n", | |
1189 decode ? "D" : " ", | |
1190 encode ? "E" : " ", | |
1191 name, | |
1192 long_name ? long_name:" "); | |
1193 } | |
1194 return 0; | |
1195 } | |
1196 | |
1197 #define PRINT_CODEC_SUPPORTED(codec, field, type, list_name, term, get_name) \ | |
1198 if (codec->field) { \ | |
1199 const type *p = codec->field; \ | |
1200 \ | |
1201 printf(" Supported " list_name ":"); \ | |
1202 while (*p != term) { \ | |
1203 get_name(*p); \ | |
1204 printf(" %s", name); \ | |
1205 p++; \ | |
1206 } \ | |
1207 printf("\n"); \ | |
1208 } \ | |
1209 | |
1210 static void print_codec(const AVCodec *c) | |
1211 { | |
1212 int encoder = av_codec_is_encoder(c); | |
1213 | |
1214 printf("%s %s [%s]:\n", encoder ? "Encoder" : "Decoder", c->name, | |
1215 c->long_name ? c->long_name : ""); | |
1216 | |
1217 if (c->type == AVMEDIA_TYPE_VIDEO) { | |
1218 printf(" Threading capabilities: "); | |
1219 switch (c->capabilities & (CODEC_CAP_FRAME_THREADS | | |
1220 CODEC_CAP_SLICE_THREADS)) { | |
1221 case CODEC_CAP_FRAME_THREADS | | |
1222 CODEC_CAP_SLICE_THREADS: printf("frame and slice"); break; | |
1223 case CODEC_CAP_FRAME_THREADS: printf("frame"); break; | |
1224 case CODEC_CAP_SLICE_THREADS: printf("slice"); break; | |
1225 default: printf("no"); break; | |
1226 } | |
1227 printf("\n"); | |
1228 } | |
1229 | |
1230 if (c->supported_framerates) { | |
1231 const AVRational *fps = c->supported_framerates; | |
1232 | |
1233 printf(" Supported framerates:"); | |
1234 while (fps->num) { | |
1235 printf(" %d/%d", fps->num, fps->den); | |
1236 fps++; | |
1237 } | |
1238 printf("\n"); | |
1239 } | |
1240 PRINT_CODEC_SUPPORTED(c, pix_fmts, enum AVPixelFormat, "pixel formats", | |
1241 AV_PIX_FMT_NONE, GET_PIX_FMT_NAME); | |
1242 PRINT_CODEC_SUPPORTED(c, supported_samplerates, int, "sample rates", 0, | |
1243 GET_SAMPLE_RATE_NAME); | |
1244 PRINT_CODEC_SUPPORTED(c, sample_fmts, enum AVSampleFormat, "sample formats", | |
1245 AV_SAMPLE_FMT_NONE, GET_SAMPLE_FMT_NAME); | |
1246 PRINT_CODEC_SUPPORTED(c, channel_layouts, uint64_t, "channel layouts", | |
1247 0, GET_CH_LAYOUT_DESC); | |
1248 | |
1249 if (c->priv_class) { | |
1250 show_help_children(c->priv_class, | |
1251 AV_OPT_FLAG_ENCODING_PARAM | | |
1252 AV_OPT_FLAG_DECODING_PARAM); | |
1253 } | |
1254 } | |
1255 | |
1256 static char get_media_type_char(enum AVMediaType type) | |
1257 { | |
1258 switch (type) { | |
1259 case AVMEDIA_TYPE_VIDEO: return 'V'; | |
1260 case AVMEDIA_TYPE_AUDIO: return 'A'; | |
1261 case AVMEDIA_TYPE_DATA: return 'D'; | |
1262 case AVMEDIA_TYPE_SUBTITLE: return 'S'; | |
1263 case AVMEDIA_TYPE_ATTACHMENT:return 'T'; | |
1264 default: return '?'; | |
1265 } | |
1266 } | |
1267 | |
1268 static const AVCodec *next_codec_for_id(enum AVCodecID id, const AVCodec *prev, | |
1269 int encoder) | |
1270 { | |
1271 while ((prev = av_codec_next(prev))) { | |
1272 if (prev->id == id && | |
1273 (encoder ? av_codec_is_encoder(prev) : av_codec_is_decoder(prev))) | |
1274 return prev; | |
1275 } | |
1276 return NULL; | |
1277 } | |
1278 | |
1279 static int compare_codec_desc(const void *a, const void *b) | |
1280 { | |
1281 const AVCodecDescriptor * const *da = a; | |
1282 const AVCodecDescriptor * const *db = b; | |
1283 | |
1284 return (*da)->type != (*db)->type ? (*da)->type - (*db)->type : | |
1285 strcmp((*da)->name, (*db)->name); | |
1286 } | |
1287 | |
1288 static unsigned get_codecs_sorted(const AVCodecDescriptor ***rcodecs) | |
1289 { | |
1290 const AVCodecDescriptor *desc = NULL; | |
1291 const AVCodecDescriptor **codecs; | |
1292 unsigned nb_codecs = 0, i = 0; | |
1293 | |
1294 while ((desc = avcodec_descriptor_next(desc))) | |
1295 nb_codecs++; | |
1296 if (!(codecs = av_calloc(nb_codecs, sizeof(*codecs)))) { | |
1297 av_log(NULL, AV_LOG_ERROR, "Out of memory\n"); | |
1298 exit(1); | |
1299 } | |
1300 desc = NULL; | |
1301 while ((desc = avcodec_descriptor_next(desc))) | |
1302 codecs[i++] = desc; | |
1303 av_assert0(i == nb_codecs); | |
1304 qsort(codecs, nb_codecs, sizeof(*codecs), compare_codec_desc); | |
1305 *rcodecs = codecs; | |
1306 return nb_codecs; | |
1307 } | |
1308 | |
1309 static void print_codecs_for_id(enum AVCodecID id, int encoder) | |
1310 { | |
1311 const AVCodec *codec = NULL; | |
1312 | |
1313 printf(" (%s: ", encoder ? "encoders" : "decoders"); | |
1314 | |
1315 while ((codec = next_codec_for_id(id, codec, encoder))) | |
1316 printf("%s ", codec->name); | |
1317 | |
1318 printf(")"); | |
1319 } | |
1320 | |
1321 int show_codecs(void *optctx, const char *opt, const char *arg) | |
1322 { | |
1323 const AVCodecDescriptor **codecs; | |
1324 unsigned i, nb_codecs = get_codecs_sorted(&codecs); | |
1325 | |
1326 printf("Codecs:\n" | |
1327 " D..... = Decoding supported\n" | |
1328 " .E.... = Encoding supported\n" | |
1329 " ..V... = Video codec\n" | |
1330 " ..A... = Audio codec\n" | |
1331 " ..S... = Subtitle codec\n" | |
1332 " ...I.. = Intra frame-only codec\n" | |
1333 " ....L. = Lossy compression\n" | |
1334 " .....S = Lossless compression\n" | |
1335 " -------\n"); | |
1336 for (i = 0; i < nb_codecs; i++) { | |
1337 const AVCodecDescriptor *desc = codecs[i]; | |
1338 const AVCodec *codec = NULL; | |
1339 | |
1340 printf(" "); | |
1341 printf(avcodec_find_decoder(desc->id) ? "D" : "."); | |
1342 printf(avcodec_find_encoder(desc->id) ? "E" : "."); | |
1343 | |
1344 printf("%c", get_media_type_char(desc->type)); | |
1345 printf((desc->props & AV_CODEC_PROP_INTRA_ONLY) ? "I" : "."); | |
1346 printf((desc->props & AV_CODEC_PROP_LOSSY) ? "L" : "."); | |
1347 printf((desc->props & AV_CODEC_PROP_LOSSLESS) ? "S" : "."); | |
1348 | |
1349 printf(" %-20s %s", desc->name, desc->long_name ? desc->long_name : ""); | |
1350 | |
1351 /* print decoders/encoders when there's more than one or their | |
1352 * names are different from codec name */ | |
1353 while ((codec = next_codec_for_id(desc->id, codec, 0))) { | |
1354 if (strcmp(codec->name, desc->name)) { | |
1355 print_codecs_for_id(desc->id, 0); | |
1356 break; | |
1357 } | |
1358 } | |
1359 codec = NULL; | |
1360 while ((codec = next_codec_for_id(desc->id, codec, 1))) { | |
1361 if (strcmp(codec->name, desc->name)) { | |
1362 print_codecs_for_id(desc->id, 1); | |
1363 break; | |
1364 } | |
1365 } | |
1366 | |
1367 printf("\n"); | |
1368 } | |
1369 av_free(codecs); | |
1370 return 0; | |
1371 } | |
1372 | |
1373 static void print_codecs(int encoder) | |
1374 { | |
1375 const AVCodecDescriptor **codecs; | |
1376 unsigned i, nb_codecs = get_codecs_sorted(&codecs); | |
1377 | |
1378 printf("%s:\n" | |
1379 " V..... = Video\n" | |
1380 " A..... = Audio\n" | |
1381 " S..... = Subtitle\n" | |
1382 " .F.... = Frame-level multithreading\n" | |
1383 " ..S... = Slice-level multithreading\n" | |
1384 " ...X.. = Codec is experimental\n" | |
1385 " ....B. = Supports draw_horiz_band\n" | |
1386 " .....D = Supports direct rendering method 1\n" | |
1387 " ------\n", | |
1388 encoder ? "Encoders" : "Decoders"); | |
1389 for (i = 0; i < nb_codecs; i++) { | |
1390 const AVCodecDescriptor *desc = codecs[i]; | |
1391 const AVCodec *codec = NULL; | |
1392 | |
1393 while ((codec = next_codec_for_id(desc->id, codec, encoder))) { | |
1394 printf(" %c", get_media_type_char(desc->type)); | |
1395 printf((codec->capabilities & CODEC_CAP_FRAME_THREADS) ? "F" : "."); | |
1396 printf((codec->capabilities & CODEC_CAP_SLICE_THREADS) ? "S" : "."); | |
1397 printf((codec->capabilities & CODEC_CAP_EXPERIMENTAL) ? "X" : "."); | |
1398 printf((codec->capabilities & CODEC_CAP_DRAW_HORIZ_BAND)?"B" : "."); | |
1399 printf((codec->capabilities & CODEC_CAP_DR1) ? "D" : "."); | |
1400 | |
1401 printf(" %-20s %s", codec->name, codec->long_name ? codec->long_name : ""); | |
1402 if (strcmp(codec->name, desc->name)) | |
1403 printf(" (codec %s)", desc->name); | |
1404 | |
1405 printf("\n"); | |
1406 } | |
1407 } | |
1408 av_free(codecs); | |
1409 } | |
1410 | |
1411 int show_decoders(void *optctx, const char *opt, const char *arg) | |
1412 { | |
1413 print_codecs(0); | |
1414 return 0; | |
1415 } | |
1416 | |
1417 int show_encoders(void *optctx, const char *opt, const char *arg) | |
1418 { | |
1419 print_codecs(1); | |
1420 return 0; | |
1421 } | |
1422 | |
1423 int show_bsfs(void *optctx, const char *opt, const char *arg) | |
1424 { | |
1425 AVBitStreamFilter *bsf = NULL; | |
1426 | |
1427 printf("Bitstream filters:\n"); | |
1428 while ((bsf = av_bitstream_filter_next(bsf))) | |
1429 printf("%s\n", bsf->name); | |
1430 printf("\n"); | |
1431 return 0; | |
1432 } | |
1433 | |
1434 int show_protocols(void *optctx, const char *opt, const char *arg) | |
1435 { | |
1436 void *opaque = NULL; | |
1437 const char *name; | |
1438 | |
1439 printf("Supported file protocols:\n" | |
1440 "Input:\n"); | |
1441 while ((name = avio_enum_protocols(&opaque, 0))) | |
1442 printf("%s\n", name); | |
1443 printf("Output:\n"); | |
1444 while ((name = avio_enum_protocols(&opaque, 1))) | |
1445 printf("%s\n", name); | |
1446 return 0; | |
1447 } | |
1448 | |
1449 int show_filters(void *optctx, const char *opt, const char *arg) | |
1450 { | |
1451 const AVFilter av_unused(*filter) = NULL; | |
1452 char descr[64], *descr_cur; | |
1453 int i, j; | |
1454 const AVFilterPad *pad; | |
1455 | |
1456 printf("Filters:\n" | |
1457 " A = Audio input/output\n" | |
1458 " V = Video input/output\n" | |
1459 " N = Dynamic number and/or type of input/output\n" | |
1460 " | = Source or sink filter\n"); | |
1461 #if CONFIG_AVFILTER | |
1462 while ((filter = avfilter_next(filter))) { | |
1463 descr_cur = descr; | |
1464 for (i = 0; i < 2; i++) { | |
1465 if (i) { | |
1466 *(descr_cur++) = '-'; | |
1467 *(descr_cur++) = '>'; | |
1468 } | |
1469 pad = i ? filter->outputs : filter->inputs; | |
1470 for (j = 0; pad && pad[j].name; j++) { | |
1471 if (descr_cur >= descr + sizeof(descr) - 4) | |
1472 break; | |
1473 *(descr_cur++) = get_media_type_char(pad[j].type); | |
1474 } | |
1475 if (!j) | |
1476 *(descr_cur++) = ((!i && (filter->flags & AVFILTER_FLAG_DYNAMIC_INPUTS)) || | |
1477 ( i && (filter->flags & AVFILTER_FLAG_DYNAMIC_OUTPUTS))) ? 'N' : '|'; | |
1478 } | |
1479 *descr_cur = 0; | |
1480 printf("%-16s %-10s %s\n", filter->name, descr, filter->description); | |
1481 } | |
1482 #endif | |
1483 return 0; | |
1484 } | |
1485 | |
1486 int show_pix_fmts(void *optctx, const char *opt, const char *arg) | |
1487 { | |
1488 const AVPixFmtDescriptor *pix_desc = NULL; | |
1489 | |
1490 printf("Pixel formats:\n" | |
1491 "I.... = Supported Input format for conversion\n" | |
1492 ".O... = Supported Output format for conversion\n" | |
1493 "..H.. = Hardware accelerated format\n" | |
1494 "...P. = Paletted format\n" | |
1495 "....B = Bitstream format\n" | |
1496 "FLAGS NAME NB_COMPONENTS BITS_PER_PIXEL\n" | |
1497 "-----\n"); | |
1498 | |
1499 #if !CONFIG_SWSCALE | |
1500 # define sws_isSupportedInput(x) 0 | |
1501 # define sws_isSupportedOutput(x) 0 | |
1502 #endif | |
1503 | |
1504 while ((pix_desc = av_pix_fmt_desc_next(pix_desc))) { | |
1505 enum AVPixelFormat pix_fmt = av_pix_fmt_desc_get_id(pix_desc); | |
1506 printf("%c%c%c%c%c %-16s %d %2d\n", | |
1507 sws_isSupportedInput (pix_fmt) ? 'I' : '.', | |
1508 sws_isSupportedOutput(pix_fmt) ? 'O' : '.', | |
1509 pix_desc->flags & PIX_FMT_HWACCEL ? 'H' : '.', | |
1510 pix_desc->flags & PIX_FMT_PAL ? 'P' : '.', | |
1511 pix_desc->flags & PIX_FMT_BITSTREAM ? 'B' : '.', | |
1512 pix_desc->name, | |
1513 pix_desc->nb_components, | |
1514 av_get_bits_per_pixel(pix_desc)); | |
1515 } | |
1516 return 0; | |
1517 } | |
1518 | |
1519 int show_layouts(void *optctx, const char *opt, const char *arg) | |
1520 { | |
1521 int i = 0; | |
1522 uint64_t layout, j; | |
1523 const char *name, *descr; | |
1524 | |
1525 printf("Individual channels:\n" | |
1526 "NAME DESCRIPTION\n"); | |
1527 for (i = 0; i < 63; i++) { | |
1528 name = av_get_channel_name((uint64_t)1 << i); | |
1529 if (!name) | |
1530 continue; | |
1531 descr = av_get_channel_description((uint64_t)1 << i); | |
1532 printf("%-12s%s\n", name, descr); | |
1533 } | |
1534 printf("\nStandard channel layouts:\n" | |
1535 "NAME DECOMPOSITION\n"); | |
1536 for (i = 0; !av_get_standard_channel_layout(i, &layout, &name); i++) { | |
1537 if (name) { | |
1538 printf("%-12s", name); | |
1539 for (j = 1; j; j <<= 1) | |
1540 if ((layout & j)) | |
1541 printf("%s%s", (layout & (j - 1)) ? "+" : "", av_get_channel_name(j)); | |
1542 printf("\n"); | |
1543 } | |
1544 } | |
1545 return 0; | |
1546 } | |
1547 | |
1548 int show_sample_fmts(void *optctx, const char *opt, const char *arg) | |
1549 { | |
1550 int i; | |
1551 char fmt_str[128]; | |
1552 for (i = -1; i < AV_SAMPLE_FMT_NB; i++) | |
1553 printf("%s\n", av_get_sample_fmt_string(fmt_str, sizeof(fmt_str), i)); | |
1554 return 0; | |
1555 } | |
1556 | |
1557 static void show_help_codec(const char *name, int encoder) | |
1558 { | |
1559 const AVCodecDescriptor *desc; | |
1560 const AVCodec *codec; | |
1561 | |
1562 if (!name) { | |
1563 av_log(NULL, AV_LOG_ERROR, "No codec name specified.\n"); | |
1564 return; | |
1565 } | |
1566 | |
1567 codec = encoder ? avcodec_find_encoder_by_name(name) : | |
1568 avcodec_find_decoder_by_name(name); | |
1569 | |
1570 if (codec) | |
1571 print_codec(codec); | |
1572 else if ((desc = avcodec_descriptor_get_by_name(name))) { | |
1573 int printed = 0; | |
1574 | |
1575 while ((codec = next_codec_for_id(desc->id, codec, encoder))) { | |
1576 printed = 1; | |
1577 print_codec(codec); | |
1578 } | |
1579 | |
1580 if (!printed) { | |
1581 av_log(NULL, AV_LOG_ERROR, "Codec '%s' is known to FFmpeg, " | |
1582 "but no %s for it are available. FFmpeg might need to be " | |
1583 "recompiled with additional external libraries.\n", | |
1584 name, encoder ? "encoders" : "decoders"); | |
1585 } | |
1586 } else { | |
1587 av_log(NULL, AV_LOG_ERROR, "Codec '%s' is not recognized by FFmpeg.\n", | |
1588 name); | |
1589 } | |
1590 } | |
1591 | |
1592 static void show_help_demuxer(const char *name) | |
1593 { | |
1594 const AVInputFormat *fmt = av_find_input_format(name); | |
1595 | |
1596 if (!fmt) { | |
1597 av_log(NULL, AV_LOG_ERROR, "Unknown format '%s'.\n", name); | |
1598 return; | |
1599 } | |
1600 | |
1601 printf("Demuxer %s [%s]:\n", fmt->name, fmt->long_name); | |
1602 | |
1603 if (fmt->extensions) | |
1604 printf(" Common extensions: %s.\n", fmt->extensions); | |
1605 | |
1606 if (fmt->priv_class) | |
1607 show_help_children(fmt->priv_class, AV_OPT_FLAG_DECODING_PARAM); | |
1608 } | |
1609 | |
1610 static void show_help_muxer(const char *name) | |
1611 { | |
1612 const AVCodecDescriptor *desc; | |
1613 const AVOutputFormat *fmt = av_guess_format(name, NULL, NULL); | |
1614 | |
1615 if (!fmt) { | |
1616 av_log(NULL, AV_LOG_ERROR, "Unknown format '%s'.\n", name); | |
1617 return; | |
1618 } | |
1619 | |
1620 printf("Muxer %s [%s]:\n", fmt->name, fmt->long_name); | |
1621 | |
1622 if (fmt->extensions) | |
1623 printf(" Common extensions: %s.\n", fmt->extensions); | |
1624 if (fmt->mime_type) | |
1625 printf(" Mime type: %s.\n", fmt->mime_type); | |
1626 if (fmt->video_codec != AV_CODEC_ID_NONE && | |
1627 (desc = avcodec_descriptor_get(fmt->video_codec))) { | |
1628 printf(" Default video codec: %s.\n", desc->name); | |
1629 } | |
1630 if (fmt->audio_codec != AV_CODEC_ID_NONE && | |
1631 (desc = avcodec_descriptor_get(fmt->audio_codec))) { | |
1632 printf(" Default audio codec: %s.\n", desc->name); | |
1633 } | |
1634 if (fmt->subtitle_codec != AV_CODEC_ID_NONE && | |
1635 (desc = avcodec_descriptor_get(fmt->subtitle_codec))) { | |
1636 printf(" Default subtitle codec: %s.\n", desc->name); | |
1637 } | |
1638 | |
1639 if (fmt->priv_class) | |
1640 show_help_children(fmt->priv_class, AV_OPT_FLAG_ENCODING_PARAM); | |
1641 } | |
1642 | |
1643 #if CONFIG_AVFILTER | |
1644 static void show_help_filter(const char *name) | |
1645 { | |
1646 #if CONFIG_AVFILTER | |
1647 const AVFilter *f = avfilter_get_by_name(name); | |
1648 int i, count; | |
1649 | |
1650 if (!name) { | |
1651 av_log(NULL, AV_LOG_ERROR, "No filter name specified.\n"); | |
1652 return; | |
1653 } else if (!f) { | |
1654 av_log(NULL, AV_LOG_ERROR, "Unknown filter '%s'.\n", name); | |
1655 return; | |
1656 } | |
1657 | |
1658 printf("Filter %s\n", f->name); | |
1659 if (f->description) | |
1660 printf(" %s\n", f->description); | |
1661 printf(" Inputs:\n"); | |
1662 count = avfilter_pad_count(f->inputs); | |
1663 for (i = 0; i < count; i++) { | |
1664 printf(" #%d: %s (%s)\n", i, avfilter_pad_get_name(f->inputs, i), | |
1665 media_type_string(avfilter_pad_get_type(f->inputs, i))); | |
1666 } | |
1667 if (f->flags & AVFILTER_FLAG_DYNAMIC_INPUTS) | |
1668 printf(" dynamic (depending on the options)\n"); | |
1669 else if (!count) | |
1670 printf(" none (source filter)\n"); | |
1671 | |
1672 printf(" Outputs:\n"); | |
1673 count = avfilter_pad_count(f->outputs); | |
1674 for (i = 0; i < count; i++) { | |
1675 printf(" #%d: %s (%s)\n", i, avfilter_pad_get_name(f->outputs, i), | |
1676 media_type_string(avfilter_pad_get_type(f->outputs, i))); | |
1677 } | |
1678 if (f->flags & AVFILTER_FLAG_DYNAMIC_OUTPUTS) | |
1679 printf(" dynamic (depending on the options)\n"); | |
1680 else if (!count) | |
1681 printf(" none (sink filter)\n"); | |
1682 | |
1683 if (f->priv_class) | |
1684 show_help_children(f->priv_class, AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM | | |
1685 AV_OPT_FLAG_AUDIO_PARAM); | |
1686 #else | |
1687 av_log(NULL, AV_LOG_ERROR, "Build without libavfilter; " | |
1688 "can not to satisfy request\n"); | |
1689 #endif | |
1690 } | |
1691 #endif | |
1692 | |
1693 int show_help(void *optctx, const char *opt, const char *arg) | |
1694 { | |
1695 char *topic, *par; | |
1696 av_log_set_callback(log_callback_help); | |
1697 | |
1698 topic = av_strdup(arg ? arg : ""); | |
1699 par = strchr(topic, '='); | |
1700 if (par) | |
1701 *par++ = 0; | |
1702 | |
1703 if (!*topic) { | |
1704 show_help_default(topic, par); | |
1705 } else if (!strcmp(topic, "decoder")) { | |
1706 show_help_codec(par, 0); | |
1707 } else if (!strcmp(topic, "encoder")) { | |
1708 show_help_codec(par, 1); | |
1709 } else if (!strcmp(topic, "demuxer")) { | |
1710 show_help_demuxer(par); | |
1711 } else if (!strcmp(topic, "muxer")) { | |
1712 show_help_muxer(par); | |
1713 #if CONFIG_AVFILTER | |
1714 } else if (!strcmp(topic, "filter")) { | |
1715 show_help_filter(par); | |
1716 #endif | |
1717 } else { | |
1718 show_help_default(topic, par); | |
1719 } | |
1720 | |
1721 av_freep(&topic); | |
1722 return 0; | |
1723 } | |
1724 | |
1725 int read_yesno(void) | |
1726 { | |
1727 int c = getchar(); | |
1728 int yesno = (av_toupper(c) == 'Y'); | |
1729 | |
1730 while (c != '\n' && c != EOF) | |
1731 c = getchar(); | |
1732 | |
1733 return yesno; | |
1734 } | |
1735 | |
1736 int cmdutils_read_file(const char *filename, char **bufptr, size_t *size) | |
1737 { | |
1738 int ret; | |
1739 FILE *f = fopen(filename, "rb"); | |
1740 | |
1741 if (!f) { | |
1742 av_log(NULL, AV_LOG_ERROR, "Cannot read file '%s': %s\n", filename, | |
1743 strerror(errno)); | |
1744 return AVERROR(errno); | |
1745 } | |
1746 fseek(f, 0, SEEK_END); | |
1747 *size = ftell(f); | |
1748 fseek(f, 0, SEEK_SET); | |
1749 if (*size == (size_t)-1) { | |
1750 av_log(NULL, AV_LOG_ERROR, "IO error: %s\n", strerror(errno)); | |
1751 fclose(f); | |
1752 return AVERROR(errno); | |
1753 } | |
1754 *bufptr = av_malloc(*size + 1); | |
1755 if (!*bufptr) { | |
1756 av_log(NULL, AV_LOG_ERROR, "Could not allocate file buffer\n"); | |
1757 fclose(f); | |
1758 return AVERROR(ENOMEM); | |
1759 } | |
1760 ret = fread(*bufptr, 1, *size, f); | |
1761 if (ret < *size) { | |
1762 av_free(*bufptr); | |
1763 if (ferror(f)) { | |
1764 av_log(NULL, AV_LOG_ERROR, "Error while reading file '%s': %s\n", | |
1765 filename, strerror(errno)); | |
1766 ret = AVERROR(errno); | |
1767 } else | |
1768 ret = AVERROR_EOF; | |
1769 } else { | |
1770 ret = 0; | |
1771 (*bufptr)[(*size)++] = '\0'; | |
1772 } | |
1773 | |
1774 fclose(f); | |
1775 return ret; | |
1776 } | |
1777 | |
1778 FILE *get_preset_file(char *filename, size_t filename_size, | |
1779 const char *preset_name, int is_path, | |
1780 const char *codec_name) | |
1781 { | |
1782 FILE *f = NULL; | |
1783 int i; | |
1784 const char *base[3] = { getenv("FFMPEG_DATADIR"), | |
1785 getenv("HOME"), | |
1786 FFMPEG_DATADIR, }; | |
1787 | |
1788 if (is_path) { | |
1789 av_strlcpy(filename, preset_name, filename_size); | |
1790 f = fopen(filename, "r"); | |
1791 } else { | |
1792 #ifdef _WIN32 | |
1793 char datadir[MAX_PATH], *ls; | |
1794 base[2] = NULL; | |
1795 | |
1796 if (GetModuleFileNameA(GetModuleHandleA(NULL), datadir, sizeof(datadir) - 1)) | |
1797 { | |
1798 for (ls = datadir; ls < datadir + strlen(datadir); ls++) | |
1799 if (*ls == '\\') *ls = '/'; | |
1800 | |
1801 if (ls = strrchr(datadir, '/')) | |
1802 { | |
1803 *ls = 0; | |
1804 strncat(datadir, "/ffpresets", sizeof(datadir) - 1 - strlen(datadir)); | |
1805 base[2] = datadir; | |
1806 } | |
1807 } | |
1808 #endif | |
1809 for (i = 0; i < 3 && !f; i++) { | |
1810 if (!base[i]) | |
1811 continue; | |
1812 snprintf(filename, filename_size, "%s%s/%s.ffpreset", base[i], | |
1813 i != 1 ? "" : "/.ffmpeg", preset_name); | |
1814 f = fopen(filename, "r"); | |
1815 if (!f && codec_name) { | |
1816 snprintf(filename, filename_size, | |
1817 "%s%s/%s-%s.ffpreset", | |
1818 base[i], i != 1 ? "" : "/.ffmpeg", codec_name, | |
1819 preset_name); | |
1820 f = fopen(filename, "r"); | |
1821 } | |
1822 } | |
1823 } | |
1824 | |
1825 return f; | |
1826 } | |
1827 | |
1828 int check_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec) | |
1829 { | |
1830 int ret = avformat_match_stream_specifier(s, st, spec); | |
1831 if (ret < 0) | |
1832 av_log(s, AV_LOG_ERROR, "Invalid stream specifier: %s.\n", spec); | |
1833 return ret; | |
1834 } | |
1835 | |
1836 AVDictionary *filter_codec_opts(AVDictionary *opts, enum AVCodecID codec_id, | |
1837 AVFormatContext *s, AVStream *st, AVCodec *codec) | |
1838 { | |
1839 AVDictionary *ret = NULL; | |
1840 AVDictionaryEntry *t = NULL; | |
1841 int flags = s->oformat ? AV_OPT_FLAG_ENCODING_PARAM | |
1842 : AV_OPT_FLAG_DECODING_PARAM; | |
1843 char prefix = 0; | |
1844 const AVClass *cc = avcodec_get_class(); | |
1845 | |
1846 if (!codec) | |
1847 codec = s->oformat ? avcodec_find_encoder(codec_id) | |
1848 : avcodec_find_decoder(codec_id); | |
1849 | |
1850 switch (st->codec->codec_type) { | |
1851 case AVMEDIA_TYPE_VIDEO: | |
1852 prefix = 'v'; | |
1853 flags |= AV_OPT_FLAG_VIDEO_PARAM; | |
1854 break; | |
1855 case AVMEDIA_TYPE_AUDIO: | |
1856 prefix = 'a'; | |
1857 flags |= AV_OPT_FLAG_AUDIO_PARAM; | |
1858 break; | |
1859 case AVMEDIA_TYPE_SUBTITLE: | |
1860 prefix = 's'; | |
1861 flags |= AV_OPT_FLAG_SUBTITLE_PARAM; | |
1862 break; | |
1863 } | |
1864 | |
1865 while (t = av_dict_get(opts, "", t, AV_DICT_IGNORE_SUFFIX)) { | |
1866 char *p = strchr(t->key, ':'); | |
1867 | |
1868 /* check stream specification in opt name */ | |
1869 if (p) | |
1870 switch (check_stream_specifier(s, st, p + 1)) { | |
1871 case 1: *p = 0; break; | |
1872 case 0: continue; | |
1873 default: return NULL; | |
1874 } | |
1875 | |
1876 if (av_opt_find(&cc, t->key, NULL, flags, AV_OPT_SEARCH_FAKE_OBJ) || | |
1877 (codec && codec->priv_class && | |
1878 av_opt_find(&codec->priv_class, t->key, NULL, flags, | |
1879 AV_OPT_SEARCH_FAKE_OBJ))) | |
1880 av_dict_set(&ret, t->key, t->value, 0); | |
1881 else if (t->key[0] == prefix && | |
1882 av_opt_find(&cc, t->key + 1, NULL, flags, | |
1883 AV_OPT_SEARCH_FAKE_OBJ)) | |
1884 av_dict_set(&ret, t->key + 1, t->value, 0); | |
1885 | |
1886 if (p) | |
1887 *p = ':'; | |
1888 } | |
1889 return ret; | |
1890 } | |
1891 | |
1892 AVDictionary **setup_find_stream_info_opts(AVFormatContext *s, | |
1893 AVDictionary *codec_opts) | |
1894 { | |
1895 int i; | |
1896 AVDictionary **opts; | |
1897 | |
1898 if (!s->nb_streams) | |
1899 return NULL; | |
1900 opts = av_mallocz(s->nb_streams * sizeof(*opts)); | |
1901 if (!opts) { | |
1902 av_log(NULL, AV_LOG_ERROR, | |
1903 "Could not alloc memory for stream options.\n"); | |
1904 return NULL; | |
1905 } | |
1906 for (i = 0; i < s->nb_streams; i++) | |
1907 opts[i] = filter_codec_opts(codec_opts, s->streams[i]->codec->codec_id, | |
1908 s, s->streams[i], NULL); | |
1909 return opts; | |
1910 } | |
1911 | |
1912 void *grow_array(void *array, int elem_size, int *size, int new_size) | |
1913 { | |
1914 if (new_size >= INT_MAX / elem_size) { | |
1915 av_log(NULL, AV_LOG_ERROR, "Array too big.\n"); | |
1916 exit(1); | |
1917 } | |
1918 if (*size < new_size) { | |
1919 uint8_t *tmp = av_realloc(array, new_size*elem_size); | |
1920 if (!tmp) { | |
1921 av_log(NULL, AV_LOG_ERROR, "Could not alloc buffer.\n"); | |
1922 exit(1); | |
1923 } | |
1924 memset(tmp + *size*elem_size, 0, (new_size-*size) * elem_size); | |
1925 *size = new_size; | |
1926 return tmp; | |
1927 } | |
1928 return array; | |
1929 } |