Commit | Line | Data |
---|---|---|
01310af2 FB |
1 | /* |
2 | * Various utilities for command line tools | |
3 | * Copyright (c) 2000-2003 Fabrice Bellard | |
4 | * | |
2912e87a | 5 | * This file is part of Libav. |
b78e7197 | 6 | * |
2912e87a | 7 | * Libav is free software; you can redistribute it and/or |
01310af2 FB |
8 | * modify it under the terms of the GNU Lesser General Public |
9 | * License as published by the Free Software Foundation; either | |
b78e7197 | 10 | * version 2.1 of the License, or (at your option) any later version. |
01310af2 | 11 | * |
2912e87a | 12 | * Libav is distributed in the hope that it will be useful, |
01310af2 FB |
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 | |
2912e87a | 18 | * License along with Libav; if not, write to the Free Software |
5509bffa | 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
01310af2 | 20 | */ |
364a9607 | 21 | |
0f4e8165 RB |
22 | #include <string.h> |
23 | #include <stdlib.h> | |
24 | #include <errno.h> | |
7c84b8bc | 25 | #include <math.h> |
0f4e8165 | 26 | |
2cd39dbf DP |
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 | ||
63d026b1 | 31 | #include "config.h" |
245976da DB |
32 | #include "libavformat/avformat.h" |
33 | #include "libavfilter/avfilter.h" | |
34 | #include "libavdevice/avdevice.h" | |
db6d50c7 | 35 | #include "libswscale/swscale.h" |
1981deaf | 36 | #include "libpostproc/postprocess.h" |
245976da | 37 | #include "libavutil/avstring.h" |
f6c7375a | 38 | #include "libavutil/parseutils.h" |
9cb5c760 | 39 | #include "libavutil/pixdesc.h" |
25e25617 | 40 | #include "libavutil/eval.h" |
9ba38229 | 41 | #include "libavutil/dict.h" |
41d0eb1c | 42 | #include "libavutil/opt.h" |
01310af2 | 43 | #include "cmdutils.h" |
86074ed1 | 44 | #include "version.h" |
da2dc39e | 45 | #if CONFIG_NETWORK |
245976da | 46 | #include "libavformat/network.h" |
da2dc39e | 47 | #endif |
ffcc6e24 MR |
48 | #if HAVE_SYS_RESOURCE_H |
49 | #include <sys/resource.h> | |
50 | #endif | |
01310af2 | 51 | |
85663ef3 | 52 | struct SwsContext *sws_opts; |
8c8eab8b | 53 | AVDictionary *format_opts, *codec_opts; |
086ab001 | 54 | |
3568853f | 55 | static const int this_year = 2011; |
ef4c0bb1 | 56 | |
a5c33faa RD |
57 | void init_opts(void) |
58 | { | |
be4876ea | 59 | #if CONFIG_SWSCALE |
a5c33faa | 60 | sws_opts = sws_getContext(16, 16, 0, 16, 16, 0, SWS_BICUBIC, NULL, NULL, NULL); |
be4876ea | 61 | #endif |
a5c33faa RD |
62 | } |
63 | ||
64 | void uninit_opts(void) | |
65 | { | |
be4876ea | 66 | #if CONFIG_SWSCALE |
faf8d3dd RB |
67 | sws_freeContext(sws_opts); |
68 | sws_opts = NULL; | |
be4876ea | 69 | #endif |
9ba38229 | 70 | av_dict_free(&format_opts); |
8c8eab8b | 71 | av_dict_free(&codec_opts); |
a5c33faa RD |
72 | } |
73 | ||
1790d3b3 SS |
74 | void log_callback_help(void* ptr, int level, const char* fmt, va_list vl) |
75 | { | |
76 | vfprintf(stdout, fmt, vl); | |
77 | } | |
78 | ||
086ab001 MN |
79 | double parse_number_or_die(const char *context, const char *numstr, int type, double min, double max) |
80 | { | |
81 | char *tail; | |
82 | const char *error; | |
25e25617 | 83 | double d = av_strtod(numstr, &tail); |
086ab001 MN |
84 | if (*tail) |
85 | error= "Expected number for %s but found: %s\n"; | |
86 | else if (d < min || d > max) | |
87 | error= "The value for %s was %s which is not within %f - %f\n"; | |
88 | else if(type == OPT_INT64 && (int64_t)d != d) | |
89 | error= "Expected int64 for %s but found %s\n"; | |
3372ec32 SS |
90 | else if (type == OPT_INT && (int)d != d) |
91 | error= "Expected int for %s but found %s\n"; | |
086ab001 MN |
92 | else |
93 | return d; | |
1c5e9551 | 94 | av_log(NULL, AV_LOG_FATAL, error, context, numstr, min, max); |
dad09ff9 AK |
95 | exit_program(1); |
96 | return 0; | |
086ab001 MN |
97 | } |
98 | ||
7542157d SS |
99 | int64_t parse_time_or_die(const char *context, const char *timestr, int is_duration) |
100 | { | |
f6c7375a SS |
101 | int64_t us; |
102 | if (av_parse_time(&us, timestr, is_duration) < 0) { | |
1c5e9551 AK |
103 | av_log(NULL, AV_LOG_FATAL, "Invalid %s specification for %s: %s\n", |
104 | is_duration ? "duration" : "date", context, timestr); | |
dad09ff9 | 105 | exit_program(1); |
7542157d SS |
106 | } |
107 | return us; | |
108 | } | |
109 | ||
02d504a7 | 110 | void show_help_options(const OptionDef *options, const char *msg, int mask, int value) |
01310af2 FB |
111 | { |
112 | const OptionDef *po; | |
02d504a7 | 113 | int first; |
01310af2 | 114 | |
02d504a7 FB |
115 | first = 1; |
116 | for(po = options; po->name != NULL; po++) { | |
117 | char buf[64]; | |
118 | if ((po->flags & mask) == value) { | |
119 | if (first) { | |
120 | printf("%s", msg); | |
121 | first = 0; | |
122 | } | |
f7d78f36 | 123 | av_strlcpy(buf, po->name, sizeof(buf)); |
02d504a7 | 124 | if (po->flags & HAS_ARG) { |
f7d78f36 MR |
125 | av_strlcat(buf, " ", sizeof(buf)); |
126 | av_strlcat(buf, po->argname, sizeof(buf)); | |
01310af2 | 127 | } |
02d504a7 | 128 | printf("-%-17s %s\n", buf, po->help); |
01310af2 FB |
129 | } |
130 | } | |
131 | } | |
132 | ||
fccfc475 | 133 | static const OptionDef* find_option(const OptionDef *po, const char *name){ |
d70e5122 AK |
134 | const char *p = strchr(name, ':'); |
135 | int len = p ? p - name : strlen(name); | |
136 | ||
8bbf6db9 | 137 | while (po->name != NULL) { |
d70e5122 | 138 | if (!strncmp(name, po->name, len) && strlen(po->name) == len) |
8bbf6db9 MN |
139 | break; |
140 | po++; | |
141 | } | |
142 | return po; | |
143 | } | |
144 | ||
b1ac139d | 145 | #if defined(_WIN32) && !defined(__MINGW32CE__) |
ba9327ea | 146 | #include <windows.h> |
b1ac139d KG |
147 | /* Will be leaked on exit */ |
148 | static char** win32_argv_utf8 = NULL; | |
149 | static int win32_argc = 0; | |
150 | ||
151 | /** | |
152 | * Prepare command line arguments for executable. | |
153 | * For Windows - perform wide-char to UTF-8 conversion. | |
154 | * Input arguments should be main() function arguments. | |
155 | * @param argc_ptr Arguments number (including executable) | |
156 | * @param argv_ptr Arguments list. | |
157 | */ | |
158 | static void prepare_app_arguments(int *argc_ptr, char ***argv_ptr) | |
159 | { | |
160 | char *argstr_flat; | |
161 | wchar_t **argv_w; | |
162 | int i, buffsize = 0, offset = 0; | |
163 | ||
164 | if (win32_argv_utf8) { | |
165 | *argc_ptr = win32_argc; | |
166 | *argv_ptr = win32_argv_utf8; | |
167 | return; | |
168 | } | |
169 | ||
170 | win32_argc = 0; | |
171 | argv_w = CommandLineToArgvW(GetCommandLineW(), &win32_argc); | |
172 | if (win32_argc <= 0 || !argv_w) | |
173 | return; | |
174 | ||
175 | /* determine the UTF-8 buffer size (including NULL-termination symbols) */ | |
176 | for (i = 0; i < win32_argc; i++) | |
177 | buffsize += WideCharToMultiByte(CP_UTF8, 0, argv_w[i], -1, | |
178 | NULL, 0, NULL, NULL); | |
179 | ||
180 | win32_argv_utf8 = av_mallocz(sizeof(char*) * (win32_argc + 1) + buffsize); | |
181 | argstr_flat = (char*)win32_argv_utf8 + sizeof(char*) * (win32_argc + 1); | |
182 | if (win32_argv_utf8 == NULL) { | |
183 | LocalFree(argv_w); | |
184 | return; | |
185 | } | |
186 | ||
187 | for (i = 0; i < win32_argc; i++) { | |
188 | win32_argv_utf8[i] = &argstr_flat[offset]; | |
189 | offset += WideCharToMultiByte(CP_UTF8, 0, argv_w[i], -1, | |
190 | &argstr_flat[offset], | |
191 | buffsize - offset, NULL, NULL); | |
192 | } | |
193 | win32_argv_utf8[i] = NULL; | |
194 | LocalFree(argv_w); | |
195 | ||
196 | *argc_ptr = win32_argc; | |
197 | *argv_ptr = win32_argv_utf8; | |
198 | } | |
199 | #else | |
200 | static inline void prepare_app_arguments(int *argc_ptr, char ***argv_ptr) | |
201 | { | |
202 | /* nothing to do */ | |
203 | } | |
204 | #endif /* WIN32 && !__MINGW32CE__ */ | |
205 | ||
2f8e586d AK |
206 | int parse_option(void *optctx, const char *opt, const char *arg, const OptionDef *options) |
207 | { | |
208 | const OptionDef *po; | |
209 | int bool_val = 1; | |
6361c5e1 | 210 | int *dstcount; |
2f8e586d AK |
211 | void *dst; |
212 | ||
213 | po = find_option(options, opt); | |
214 | if (!po->name && opt[0] == 'n' && opt[1] == 'o') { | |
215 | /* handle 'no' bool option */ | |
216 | po = find_option(options, opt + 2); | |
217 | if (!(po->name && (po->flags & OPT_BOOL))) | |
218 | goto unknown_opt; | |
219 | bool_val = 0; | |
220 | } | |
221 | if (!po->name) | |
222 | po = find_option(options, "default"); | |
223 | if (!po->name) { | |
224 | unknown_opt: | |
225 | av_log(NULL, AV_LOG_ERROR, "Unrecognized option '%s'\n", opt); | |
226 | return AVERROR(EINVAL); | |
227 | } | |
228 | if (po->flags & HAS_ARG && !arg) { | |
229 | av_log(NULL, AV_LOG_ERROR, "Missing argument for option '%s'\n", opt); | |
230 | return AVERROR(EINVAL); | |
231 | } | |
232 | ||
233 | /* new-style options contain an offset into optctx, old-style address of | |
234 | * a global var*/ | |
6361c5e1 AK |
235 | dst = po->flags & (OPT_OFFSET|OPT_SPEC) ? (uint8_t*)optctx + po->u.off : po->u.dst_ptr; |
236 | ||
237 | if (po->flags & OPT_SPEC) { | |
238 | SpecifierOpt **so = dst; | |
239 | char *p = strchr(opt, ':'); | |
240 | ||
241 | dstcount = (int*)(so + 1); | |
242 | *so = grow_array(*so, sizeof(**so), dstcount, *dstcount + 1); | |
243 | (*so)[*dstcount - 1].specifier = av_strdup(p ? p + 1 : ""); | |
244 | dst = &(*so)[*dstcount - 1].u; | |
245 | } | |
2f8e586d AK |
246 | |
247 | if (po->flags & OPT_STRING) { | |
248 | char *str; | |
249 | str = av_strdup(arg); | |
250 | *(char**)dst = str; | |
251 | } else if (po->flags & OPT_BOOL) { | |
252 | *(int*)dst = bool_val; | |
253 | } else if (po->flags & OPT_INT) { | |
254 | *(int*)dst = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX); | |
255 | } else if (po->flags & OPT_INT64) { | |
256 | *(int64_t*)dst = parse_number_or_die(opt, arg, OPT_INT64, INT64_MIN, INT64_MAX); | |
6b779ccc AK |
257 | } else if (po->flags & OPT_TIME) { |
258 | *(int64_t*)dst = parse_time_or_die(opt, arg, 1); | |
2f8e586d AK |
259 | } else if (po->flags & OPT_FLOAT) { |
260 | *(float*)dst = parse_number_or_die(opt, arg, OPT_FLOAT, -INFINITY, INFINITY); | |
33f75d72 AK |
261 | } else if (po->flags & OPT_DOUBLE) { |
262 | *(double*)dst = parse_number_or_die(opt, arg, OPT_DOUBLE, -INFINITY, INFINITY); | |
2f8e586d AK |
263 | } else if (po->u.func_arg) { |
264 | int ret = po->flags & OPT_FUNC2 ? po->u.func2_arg(optctx, opt, arg) : | |
265 | po->u.func_arg(opt, arg); | |
266 | if (ret < 0) { | |
267 | av_log(NULL, AV_LOG_ERROR, "Failed to set value '%s' for option '%s'\n", arg, opt); | |
268 | return ret; | |
269 | } | |
270 | } | |
271 | if (po->flags & OPT_EXIT) | |
272 | exit_program(0); | |
273 | return !!(po->flags & HAS_ARG); | |
274 | } | |
275 | ||
7cc8d638 AK |
276 | void parse_options(void *optctx, int argc, char **argv, const OptionDef *options, |
277 | void (* parse_arg_function)(void *, const char*)) | |
01310af2 | 278 | { |
2f8e586d AK |
279 | const char *opt; |
280 | int optindex, handleoptions = 1, ret; | |
01310af2 | 281 | |
b1ac139d KG |
282 | /* perform system-dependent conversions for arguments list */ |
283 | prepare_app_arguments(&argc, &argv); | |
284 | ||
01310af2 FB |
285 | /* parse options */ |
286 | optindex = 1; | |
287 | while (optindex < argc) { | |
288 | opt = argv[optindex++]; | |
115329f1 | 289 | |
84bf226b | 290 | if (handleoptions && opt[0] == '-' && opt[1] != '\0') { |
3749076c SS |
291 | if (opt[1] == '-' && opt[2] == '\0') { |
292 | handleoptions = 0; | |
293 | continue; | |
294 | } | |
c3c78324 | 295 | opt++; |
2f8e586d AK |
296 | |
297 | if ((ret = parse_option(optctx, opt, argv[optindex], options)) < 0) | |
dad09ff9 | 298 | exit_program(1); |
2f8e586d | 299 | optindex += ret; |
01310af2 | 300 | } else { |
60a9966e | 301 | if (parse_arg_function) |
7cc8d638 | 302 | parse_arg_function(optctx, opt); |
01310af2 FB |
303 | } |
304 | } | |
305 | } | |
306 | ||
182cbe43 AK |
307 | /* |
308 | * Return index of option opt in argv or 0 if not found. | |
309 | */ | |
310 | static int locate_option(int argc, char **argv, const OptionDef *options, const char *optname) | |
311 | { | |
312 | const OptionDef *po; | |
313 | int i; | |
314 | ||
315 | for (i = 1; i < argc; i++) { | |
316 | const char *cur_opt = argv[i]; | |
317 | ||
318 | if (*cur_opt++ != '-') | |
319 | continue; | |
320 | ||
321 | po = find_option(options, cur_opt); | |
322 | if (!po->name && cur_opt[0] == 'n' && cur_opt[1] == 'o') | |
323 | po = find_option(options, cur_opt + 2); | |
324 | ||
325 | if ((!po->name && !strcmp(cur_opt, optname)) || | |
326 | (po->name && !strcmp(optname, po->name))) | |
327 | return i; | |
328 | ||
329 | if (!po || po->flags & HAS_ARG) | |
330 | i++; | |
331 | } | |
332 | return 0; | |
333 | } | |
334 | ||
335 | void parse_loglevel(int argc, char **argv, const OptionDef *options) | |
336 | { | |
337 | int idx = locate_option(argc, argv, options, "loglevel"); | |
338 | if (idx && argv[idx + 1]) | |
339 | opt_loglevel("loglevel", argv[idx + 1]); | |
340 | } | |
341 | ||
9ba38229 | 342 | #define FLAGS (o->type == FF_OPT_TYPE_FLAGS) ? AV_DICT_APPEND : 0 |
35d2e4e5 | 343 | int opt_default(const char *opt, const char *arg) |
9ba38229 AK |
344 | { |
345 | const AVOption *o; | |
d4863fc1 AK |
346 | char opt_stripped[128]; |
347 | const char *p; | |
20c21f8b | 348 | const AVClass *cc = avcodec_get_class(), *fc = avformat_get_class(), *sc = sws_get_class(); |
d4863fc1 AK |
349 | |
350 | if (!(p = strchr(opt, ':'))) | |
351 | p = opt + strlen(opt); | |
352 | av_strlcpy(opt_stripped, opt, FFMIN(sizeof(opt_stripped), p - opt + 1)); | |
353 | ||
20c21f8b | 354 | if ((o = av_opt_find(&cc, opt_stripped, NULL, 0, AV_OPT_SEARCH_CHILDREN|AV_OPT_SEARCH_FAKE_OBJ)) || |
8c8eab8b | 355 | ((opt[0] == 'v' || opt[0] == 'a' || opt[0] == 's') && |
20c21f8b | 356 | (o = av_opt_find(&cc, opt+1, NULL, 0, AV_OPT_SEARCH_FAKE_OBJ)))) |
8c8eab8b | 357 | av_dict_set(&codec_opts, opt, arg, FLAGS); |
20c21f8b | 358 | else if ((o = av_opt_find(&fc, opt, NULL, 0, AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) |
9ba38229 | 359 | av_dict_set(&format_opts, opt, arg, FLAGS); |
20c21f8b | 360 | else if ((o = av_opt_find(&sc, opt, NULL, 0, AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) { |
9ba38229 AK |
361 | // XXX we only support sws_flags, not arbitrary sws options |
362 | int ret = av_set_string3(sws_opts, opt, arg, 1, NULL); | |
363 | if (ret < 0) { | |
364 | av_log(NULL, AV_LOG_ERROR, "Error setting option %s.\n", opt); | |
365 | return ret; | |
366 | } | |
367 | } | |
368 | ||
9ba38229 AK |
369 | if (o) |
370 | return 0; | |
1c5e9551 | 371 | av_log(NULL, AV_LOG_ERROR, "Unrecognized option '%s'\n", opt); |
9ba38229 AK |
372 | return AVERROR_OPTION_NOT_FOUND; |
373 | } | |
374 | ||
4c97a6fa SS |
375 | int opt_loglevel(const char *opt, const char *arg) |
376 | { | |
da4c2dab | 377 | const struct { const char *name; int level; } log_levels[] = { |
4c97a6fa SS |
378 | { "quiet" , AV_LOG_QUIET }, |
379 | { "panic" , AV_LOG_PANIC }, | |
380 | { "fatal" , AV_LOG_FATAL }, | |
381 | { "error" , AV_LOG_ERROR }, | |
382 | { "warning", AV_LOG_WARNING }, | |
383 | { "info" , AV_LOG_INFO }, | |
384 | { "verbose", AV_LOG_VERBOSE }, | |
385 | { "debug" , AV_LOG_DEBUG }, | |
386 | }; | |
387 | char *tail; | |
388 | int level; | |
389 | int i; | |
390 | ||
391 | for (i = 0; i < FF_ARRAY_ELEMS(log_levels); i++) { | |
392 | if (!strcmp(log_levels[i].name, arg)) { | |
393 | av_log_set_level(log_levels[i].level); | |
394 | return 0; | |
395 | } | |
396 | } | |
397 | ||
398 | level = strtol(arg, &tail, 10); | |
399 | if (*tail) { | |
1c5e9551 AK |
400 | av_log(NULL, AV_LOG_FATAL, "Invalid loglevel \"%s\". " |
401 | "Possible levels are numbers or:\n", arg); | |
4c97a6fa | 402 | for (i = 0; i < FF_ARRAY_ELEMS(log_levels); i++) |
1c5e9551 | 403 | av_log(NULL, AV_LOG_FATAL, "\"%s\"\n", log_levels[i].name); |
dad09ff9 | 404 | exit_program(1); |
4c97a6fa SS |
405 | } |
406 | av_log_set_level(level); | |
407 | return 0; | |
408 | } | |
409 | ||
ffcc6e24 MR |
410 | int opt_timelimit(const char *opt, const char *arg) |
411 | { | |
0104b608 | 412 | #if HAVE_SETRLIMIT |
ffcc6e24 MR |
413 | int lim = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX); |
414 | struct rlimit rl = { lim, lim + 1 }; | |
415 | if (setrlimit(RLIMIT_CPU, &rl)) | |
416 | perror("setrlimit"); | |
417 | #else | |
1c5e9551 | 418 | av_log(NULL, AV_LOG_WARNING, "-%s not implemented on this OS\n", opt); |
ffcc6e24 MR |
419 | #endif |
420 | return 0; | |
421 | } | |
422 | ||
01310af2 FB |
423 | void print_error(const char *filename, int err) |
424 | { | |
7a5bdd79 | 425 | char errbuf[128]; |
735ef67b | 426 | const char *errbuf_ptr = errbuf; |
7a5bdd79 | 427 | |
9e94bd3e SS |
428 | if (av_strerror(err, errbuf, sizeof(errbuf)) < 0) |
429 | errbuf_ptr = strerror(AVUNERROR(err)); | |
1c5e9551 | 430 | av_log(NULL, AV_LOG_ERROR, "%s: %s\n", filename, errbuf_ptr); |
01310af2 | 431 | } |
f35917b2 | 432 | |
d101e731 SS |
433 | static int warned_cfg = 0; |
434 | ||
208749a0 SS |
435 | #define INDENT 1 |
436 | #define SHOW_VERSION 2 | |
d101e731 | 437 | #define SHOW_CONFIG 4 |
208749a0 | 438 | |
1c5e9551 | 439 | #define PRINT_LIB_INFO(libname, LIBNAME, flags, level) \ |
5116571d | 440 | if (CONFIG_##LIBNAME) { \ |
65dd2ded | 441 | const char *indent = flags & INDENT? " " : ""; \ |
208749a0 | 442 | if (flags & SHOW_VERSION) { \ |
b6525b4b | 443 | unsigned int version = libname##_version(); \ |
1c5e9551 AK |
444 | av_log(NULL, level, "%slib%-9s %2d.%3d.%2d / %2d.%3d.%2d\n",\ |
445 | indent, #libname, \ | |
446 | LIB##LIBNAME##_VERSION_MAJOR, \ | |
447 | LIB##LIBNAME##_VERSION_MINOR, \ | |
448 | LIB##LIBNAME##_VERSION_MICRO, \ | |
449 | version >> 16, version >> 8 & 0xff, version & 0xff); \ | |
208749a0 | 450 | } \ |
d101e731 SS |
451 | if (flags & SHOW_CONFIG) { \ |
452 | const char *cfg = libname##_configuration(); \ | |
29ba0911 | 453 | if (strcmp(LIBAV_CONFIGURATION, cfg)) { \ |
d101e731 | 454 | if (!warned_cfg) { \ |
1c5e9551 | 455 | av_log(NULL, level, \ |
d101e731 | 456 | "%sWARNING: library configuration mismatch\n", \ |
65dd2ded | 457 | indent); \ |
d101e731 SS |
458 | warned_cfg = 1; \ |
459 | } \ | |
1c5e9551 | 460 | av_log(NULL, level, "%s%-11s configuration: %s\n", \ |
65dd2ded | 461 | indent, #libname, cfg); \ |
d101e731 SS |
462 | } \ |
463 | } \ | |
208749a0 | 464 | } \ |
9a109272 | 465 | |
1c5e9551 | 466 | static void print_all_libs_info(int flags, int level) |
9a109272 | 467 | { |
1c5e9551 AK |
468 | PRINT_LIB_INFO(avutil, AVUTIL, flags, level); |
469 | PRINT_LIB_INFO(avcodec, AVCODEC, flags, level); | |
470 | PRINT_LIB_INFO(avformat, AVFORMAT, flags, level); | |
471 | PRINT_LIB_INFO(avdevice, AVDEVICE, flags, level); | |
472 | PRINT_LIB_INFO(avfilter, AVFILTER, flags, level); | |
473 | PRINT_LIB_INFO(swscale, SWSCALE, flags, level); | |
474 | PRINT_LIB_INFO(postproc, POSTPROC, flags, level); | |
9a109272 SS |
475 | } |
476 | ||
ea9c581f | 477 | void show_banner(void) |
86074ed1 | 478 | { |
1c5e9551 AK |
479 | av_log(NULL, AV_LOG_INFO, "%s version " LIBAV_VERSION ", Copyright (c) %d-%d the Libav developers\n", |
480 | program_name, program_birth_year, this_year); | |
481 | av_log(NULL, AV_LOG_INFO, " built on %s %s with %s %s\n", | |
482 | __DATE__, __TIME__, CC_TYPE, CC_VERSION); | |
483 | av_log(NULL, AV_LOG_VERBOSE, " configuration: " LIBAV_CONFIGURATION "\n"); | |
484 | print_all_libs_info(INDENT|SHOW_CONFIG, AV_LOG_VERBOSE); | |
485 | print_all_libs_info(INDENT|SHOW_VERSION, AV_LOG_VERBOSE); | |
86074ed1 SS |
486 | } |
487 | ||
64555bd9 | 488 | void show_version(void) { |
1c5e9551 | 489 | av_log_set_callback(log_callback_help); |
a03be6e1 | 490 | printf("%s " LIBAV_VERSION "\n", program_name); |
1c5e9551 | 491 | print_all_libs_info(SHOW_VERSION, AV_LOG_INFO); |
86074ed1 SS |
492 | } |
493 | ||
f35917b2 SS |
494 | void show_license(void) |
495 | { | |
7ead693b | 496 | printf( |
3bf28f9d | 497 | #if CONFIG_NONFREE |
304ba23a SS |
498 | "This version of %s has nonfree parts compiled in.\n" |
499 | "Therefore it is not legally redistributable.\n", | |
500 | program_name | |
9cad0e4e DB |
501 | #elif CONFIG_GPLV3 |
502 | "%s is free software; you can redistribute it and/or modify\n" | |
503 | "it under the terms of the GNU General Public License as published by\n" | |
504 | "the Free Software Foundation; either version 3 of the License, or\n" | |
505 | "(at your option) any later version.\n" | |
506 | "\n" | |
507 | "%s is distributed in the hope that it will be useful,\n" | |
508 | "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" | |
509 | "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" | |
510 | "GNU General Public License for more details.\n" | |
511 | "\n" | |
512 | "You should have received a copy of the GNU General Public License\n" | |
513 | "along with %s. If not, see <http://www.gnu.org/licenses/>.\n", | |
514 | program_name, program_name, program_name | |
7ead693b | 515 | #elif CONFIG_GPL |
304ba23a | 516 | "%s is free software; you can redistribute it and/or modify\n" |
f35917b2 SS |
517 | "it under the terms of the GNU General Public License as published by\n" |
518 | "the Free Software Foundation; either version 2 of the License, or\n" | |
519 | "(at your option) any later version.\n" | |
520 | "\n" | |
304ba23a | 521 | "%s is distributed in the hope that it will be useful,\n" |
f35917b2 SS |
522 | "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" |
523 | "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" | |
524 | "GNU General Public License for more details.\n" | |
525 | "\n" | |
526 | "You should have received a copy of the GNU General Public License\n" | |
304ba23a SS |
527 | "along with %s; if not, write to the Free Software\n" |
528 | "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n", | |
529 | program_name, program_name, program_name | |
9cad0e4e DB |
530 | #elif CONFIG_LGPLV3 |
531 | "%s is free software; you can redistribute it and/or modify\n" | |
532 | "it under the terms of the GNU Lesser General Public License as published by\n" | |
533 | "the Free Software Foundation; either version 3 of the License, or\n" | |
534 | "(at your option) any later version.\n" | |
535 | "\n" | |
536 | "%s is distributed in the hope that it will be useful,\n" | |
537 | "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" | |
538 | "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" | |
539 | "GNU Lesser General Public License for more details.\n" | |
540 | "\n" | |
541 | "You should have received a copy of the GNU Lesser General Public License\n" | |
542 | "along with %s. If not, see <http://www.gnu.org/licenses/>.\n", | |
543 | program_name, program_name, program_name | |
f35917b2 | 544 | #else |
304ba23a | 545 | "%s is free software; you can redistribute it and/or\n" |
f35917b2 SS |
546 | "modify it under the terms of the GNU Lesser General Public\n" |
547 | "License as published by the Free Software Foundation; either\n" | |
548 | "version 2.1 of the License, or (at your option) any later version.\n" | |
549 | "\n" | |
304ba23a | 550 | "%s is distributed in the hope that it will be useful,\n" |
f35917b2 SS |
551 | "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" |
552 | "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" | |
553 | "Lesser General Public License for more details.\n" | |
554 | "\n" | |
555 | "You should have received a copy of the GNU Lesser General Public\n" | |
304ba23a SS |
556 | "License along with %s; if not, write to the Free Software\n" |
557 | "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n", | |
558 | program_name, program_name, program_name | |
f35917b2 | 559 | #endif |
3bf28f9d | 560 | ); |
f35917b2 | 561 | } |
ba9880c1 SS |
562 | |
563 | void show_formats(void) | |
564 | { | |
565 | AVInputFormat *ifmt=NULL; | |
566 | AVOutputFormat *ofmt=NULL; | |
ba9880c1 SS |
567 | const char *last_name; |
568 | ||
5a8597a0 WZ |
569 | printf( |
570 | "File formats:\n" | |
571 | " D. = Demuxing supported\n" | |
572 | " .E = Muxing supported\n" | |
573 | " --\n"); | |
ba9880c1 SS |
574 | last_name= "000"; |
575 | for(;;){ | |
576 | int decode=0; | |
577 | int encode=0; | |
578 | const char *name=NULL; | |
579 | const char *long_name=NULL; | |
580 | ||
581 | while((ofmt= av_oformat_next(ofmt))) { | |
582 | if((name == NULL || strcmp(ofmt->name, name)<0) && | |
583 | strcmp(ofmt->name, last_name)>0){ | |
584 | name= ofmt->name; | |
585 | long_name= ofmt->long_name; | |
586 | encode=1; | |
587 | } | |
588 | } | |
589 | while((ifmt= av_iformat_next(ifmt))) { | |
590 | if((name == NULL || strcmp(ifmt->name, name)<0) && | |
591 | strcmp(ifmt->name, last_name)>0){ | |
592 | name= ifmt->name; | |
593 | long_name= ifmt->long_name; | |
594 | encode=0; | |
595 | } | |
596 | if(name && strcmp(ifmt->name, name)==0) | |
597 | decode=1; | |
598 | } | |
599 | if(name==NULL) | |
600 | break; | |
601 | last_name= name; | |
602 | ||
603 | printf( | |
604 | " %s%s %-15s %s\n", | |
605 | decode ? "D":" ", | |
606 | encode ? "E":" ", | |
607 | name, | |
608 | long_name ? long_name:" "); | |
609 | } | |
8447f0bd | 610 | } |
ba9880c1 | 611 | |
8447f0bd MN |
612 | void show_codecs(void) |
613 | { | |
614 | AVCodec *p=NULL, *p2; | |
615 | const char *last_name; | |
5a8597a0 WZ |
616 | printf( |
617 | "Codecs:\n" | |
618 | " D..... = Decoding supported\n" | |
619 | " .E.... = Encoding supported\n" | |
620 | " ..V... = Video codec\n" | |
621 | " ..A... = Audio codec\n" | |
622 | " ..S... = Subtitle codec\n" | |
623 | " ...S.. = Supports draw_horiz_band\n" | |
624 | " ....D. = Supports direct rendering method 1\n" | |
625 | " .....T = Supports weird frame truncation\n" | |
626 | " ------\n"); | |
ba9880c1 SS |
627 | last_name= "000"; |
628 | for(;;){ | |
629 | int decode=0; | |
630 | int encode=0; | |
631 | int cap=0; | |
632 | const char *type_str; | |
633 | ||
634 | p2=NULL; | |
635 | while((p= av_codec_next(p))) { | |
636 | if((p2==NULL || strcmp(p->name, p2->name)<0) && | |
637 | strcmp(p->name, last_name)>0){ | |
638 | p2= p; | |
639 | decode= encode= cap=0; | |
640 | } | |
641 | if(p2 && strcmp(p->name, p2->name)==0){ | |
642 | if(p->decode) decode=1; | |
643 | if(p->encode) encode=1; | |
644 | cap |= p->capabilities; | |
645 | } | |
646 | } | |
647 | if(p2==NULL) | |
648 | break; | |
649 | last_name= p2->name; | |
650 | ||
651 | switch(p2->type) { | |
72415b2a | 652 | case AVMEDIA_TYPE_VIDEO: |
ba9880c1 SS |
653 | type_str = "V"; |
654 | break; | |
72415b2a | 655 | case AVMEDIA_TYPE_AUDIO: |
ba9880c1 SS |
656 | type_str = "A"; |
657 | break; | |
72415b2a | 658 | case AVMEDIA_TYPE_SUBTITLE: |
ba9880c1 SS |
659 | type_str = "S"; |
660 | break; | |
661 | default: | |
662 | type_str = "?"; | |
663 | break; | |
664 | } | |
665 | printf( | |
666 | " %s%s%s%s%s%s %-15s %s", | |
667 | decode ? "D": (/*p2->decoder ? "d":*/" "), | |
668 | encode ? "E":" ", | |
669 | type_str, | |
670 | cap & CODEC_CAP_DRAW_HORIZ_BAND ? "S":" ", | |
671 | cap & CODEC_CAP_DR1 ? "D":" ", | |
672 | cap & CODEC_CAP_TRUNCATED ? "T":" ", | |
673 | p2->name, | |
674 | p2->long_name ? p2->long_name : ""); | |
675 | /* if(p2->decoder && decode==0) | |
676 | printf(" use %s for decoding", p2->decoder->name);*/ | |
677 | printf("\n"); | |
678 | } | |
679 | printf("\n"); | |
8447f0bd MN |
680 | printf( |
681 | "Note, the names of encoders and decoders do not always match, so there are\n" | |
682 | "several cases where the above table shows encoder only or decoder only entries\n" | |
683 | "even though both encoding and decoding are supported. For example, the h263\n" | |
684 | "decoder corresponds to the h263 and h263p encoders, for file formats it is even\n" | |
685 | "worse.\n"); | |
686 | } | |
687 | ||
688 | void show_bsfs(void) | |
689 | { | |
690 | AVBitStreamFilter *bsf=NULL; | |
ba9880c1 SS |
691 | |
692 | printf("Bitstream filters:\n"); | |
693 | while((bsf = av_bitstream_filter_next(bsf))) | |
2091b27b | 694 | printf("%s\n", bsf->name); |
ba9880c1 | 695 | printf("\n"); |
8447f0bd MN |
696 | } |
697 | ||
698 | void show_protocols(void) | |
699 | { | |
cdc6a87f AK |
700 | void *opaque = NULL; |
701 | const char *name; | |
ba9880c1 | 702 | |
2ee5c789 | 703 | printf("Supported file protocols:\n" |
cdc6a87f AK |
704 | "Input:\n"); |
705 | while ((name = avio_enum_protocols(&opaque, 0))) | |
706 | printf("%s\n", name); | |
707 | printf("Output:\n"); | |
708 | while ((name = avio_enum_protocols(&opaque, 1))) | |
709 | printf("%s\n", name); | |
ba9880c1 | 710 | } |
090b61b2 | 711 | |
62d75662 SS |
712 | void show_filters(void) |
713 | { | |
78638628 | 714 | AVFilter av_unused(**filter) = NULL; |
62d75662 SS |
715 | |
716 | printf("Filters:\n"); | |
663c2edf | 717 | #if CONFIG_AVFILTER |
62d75662 SS |
718 | while ((filter = av_filter_next(filter)) && *filter) |
719 | printf("%-16s %s\n", (*filter)->name, (*filter)->description); | |
663c2edf | 720 | #endif |
62d75662 SS |
721 | } |
722 | ||
3f7bb426 SS |
723 | void show_pix_fmts(void) |
724 | { | |
9cb5c760 SS |
725 | enum PixelFormat pix_fmt; |
726 | ||
727 | printf( | |
728 | "Pixel formats:\n" | |
729 | "I.... = Supported Input format for conversion\n" | |
730 | ".O... = Supported Output format for conversion\n" | |
731 | "..H.. = Hardware accelerated format\n" | |
732 | "...P. = Paletted format\n" | |
733 | "....B = Bitstream format\n" | |
734 | "FLAGS NAME NB_COMPONENTS BITS_PER_PIXEL\n" | |
735 | "-----\n"); | |
736 | ||
e24db3e3 MR |
737 | #if !CONFIG_SWSCALE |
738 | # define sws_isSupportedInput(x) 0 | |
739 | # define sws_isSupportedOutput(x) 0 | |
740 | #endif | |
741 | ||
9cb5c760 SS |
742 | for (pix_fmt = 0; pix_fmt < PIX_FMT_NB; pix_fmt++) { |
743 | const AVPixFmtDescriptor *pix_desc = &av_pix_fmt_descriptors[pix_fmt]; | |
744 | printf("%c%c%c%c%c %-16s %d %2d\n", | |
745 | sws_isSupportedInput (pix_fmt) ? 'I' : '.', | |
746 | sws_isSupportedOutput(pix_fmt) ? 'O' : '.', | |
747 | pix_desc->flags & PIX_FMT_HWACCEL ? 'H' : '.', | |
748 | pix_desc->flags & PIX_FMT_PAL ? 'P' : '.', | |
749 | pix_desc->flags & PIX_FMT_BITSTREAM ? 'B' : '.', | |
750 | pix_desc->name, | |
751 | pix_desc->nb_components, | |
752 | av_get_bits_per_pixel(pix_desc)); | |
753 | } | |
3f7bb426 SS |
754 | } |
755 | ||
05bffc12 AK |
756 | int show_sample_fmts(const char *opt, const char *arg) |
757 | { | |
758 | int i; | |
759 | char fmt_str[128]; | |
760 | for (i = -1; i < AV_SAMPLE_FMT_NB; i++) | |
761 | printf("%s\n", av_get_sample_fmt_string(fmt_str, sizeof(fmt_str), i)); | |
762 | return 0; | |
763 | } | |
764 | ||
090b61b2 SS |
765 | int read_yesno(void) |
766 | { | |
767 | int c = getchar(); | |
768 | int yesno = (toupper(c) == 'Y'); | |
769 | ||
770 | while (c != '\n' && c != EOF) | |
771 | c = getchar(); | |
772 | ||
773 | return yesno; | |
774 | } | |
458b062d SS |
775 | |
776 | int read_file(const char *filename, char **bufptr, size_t *size) | |
777 | { | |
c56e9e05 | 778 | FILE *f = fopen(filename, "rb"); |
458b062d SS |
779 | |
780 | if (!f) { | |
1c5e9551 | 781 | av_log(NULL, AV_LOG_ERROR, "Cannot read file '%s': %s\n", filename, strerror(errno)); |
458b062d SS |
782 | return AVERROR(errno); |
783 | } | |
784 | fseek(f, 0, SEEK_END); | |
785 | *size = ftell(f); | |
786 | fseek(f, 0, SEEK_SET); | |
787 | *bufptr = av_malloc(*size + 1); | |
788 | if (!*bufptr) { | |
1c5e9551 | 789 | av_log(NULL, AV_LOG_ERROR, "Could not allocate file buffer\n"); |
458b062d SS |
790 | fclose(f); |
791 | return AVERROR(ENOMEM); | |
792 | } | |
793 | fread(*bufptr, 1, *size, f); | |
794 | (*bufptr)[*size++] = '\0'; | |
795 | ||
796 | fclose(f); | |
797 | return 0; | |
798 | } | |
7a8bfa5d AS |
799 | |
800 | void init_pts_correction(PtsCorrectionContext *ctx) | |
801 | { | |
802 | ctx->num_faulty_pts = ctx->num_faulty_dts = 0; | |
803 | ctx->last_pts = ctx->last_dts = INT64_MIN; | |
804 | } | |
805 | ||
806 | int64_t guess_correct_pts(PtsCorrectionContext *ctx, int64_t reordered_pts, int64_t dts) | |
807 | { | |
808 | int64_t pts = AV_NOPTS_VALUE; | |
809 | ||
810 | if (dts != AV_NOPTS_VALUE) { | |
811 | ctx->num_faulty_dts += dts <= ctx->last_dts; | |
812 | ctx->last_dts = dts; | |
813 | } | |
814 | if (reordered_pts != AV_NOPTS_VALUE) { | |
815 | ctx->num_faulty_pts += reordered_pts <= ctx->last_pts; | |
816 | ctx->last_pts = reordered_pts; | |
817 | } | |
01d46198 | 818 | if ((ctx->num_faulty_pts<=ctx->num_faulty_dts || dts == AV_NOPTS_VALUE) |
7a8bfa5d AS |
819 | && reordered_pts != AV_NOPTS_VALUE) |
820 | pts = reordered_pts; | |
821 | else | |
822 | pts = dts; | |
823 | ||
824 | return pts; | |
825 | } | |
f7ead94c | 826 | |
6e872935 SS |
827 | FILE *get_preset_file(char *filename, size_t filename_size, |
828 | const char *preset_name, int is_path, const char *codec_name) | |
829 | { | |
830 | FILE *f = NULL; | |
831 | int i; | |
6291d7e4 | 832 | const char *base[3]= { getenv("AVCONV_DATADIR"), |
6e872935 | 833 | getenv("HOME"), |
6291d7e4 | 834 | AVCONV_DATADIR, |
6e872935 SS |
835 | }; |
836 | ||
837 | if (is_path) { | |
838 | av_strlcpy(filename, preset_name, filename_size); | |
839 | f = fopen(filename, "r"); | |
840 | } else { | |
841 | for (i = 0; i < 3 && !f; i++) { | |
842 | if (!base[i]) | |
843 | continue; | |
6291d7e4 | 844 | snprintf(filename, filename_size, "%s%s/%s.ffpreset", base[i], i != 1 ? "" : "/.avconv", preset_name); |
6e872935 SS |
845 | f = fopen(filename, "r"); |
846 | if (!f && codec_name) { | |
847 | snprintf(filename, filename_size, | |
6291d7e4 | 848 | "%s%s/%s-%s.ffpreset", base[i], i != 1 ? "" : "/.avconv", codec_name, preset_name); |
6e872935 SS |
849 | f = fopen(filename, "r"); |
850 | } | |
851 | } | |
852 | } | |
853 | ||
854 | return f; | |
855 | } | |
856 | ||
d4863fc1 AK |
857 | int check_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec) |
858 | { | |
859 | if (*spec <= '9' && *spec >= '0') /* opt:index */ | |
860 | return strtol(spec, NULL, 0) == st->index; | |
3ccd1580 | 861 | else if (*spec == 'v' || *spec == 'a' || *spec == 's' || *spec == 'd' || *spec == 't') { /* opt:[vasdt] */ |
d4863fc1 AK |
862 | enum AVMediaType type; |
863 | ||
864 | switch (*spec++) { | |
865 | case 'v': type = AVMEDIA_TYPE_VIDEO; break; | |
866 | case 'a': type = AVMEDIA_TYPE_AUDIO; break; | |
867 | case 's': type = AVMEDIA_TYPE_SUBTITLE; break; | |
868 | case 'd': type = AVMEDIA_TYPE_DATA; break; | |
3ccd1580 | 869 | case 't': type = AVMEDIA_TYPE_ATTACHMENT; break; |
d4863fc1 AK |
870 | } |
871 | if (type != st->codec->codec_type) | |
872 | return 0; | |
873 | if (*spec++ == ':') { /* possibly followed by :index */ | |
874 | int i, index = strtol(spec, NULL, 0); | |
875 | for (i = 0; i < s->nb_streams; i++) | |
876 | if (s->streams[i]->codec->codec_type == type && index-- == 0) | |
877 | return i == st->index; | |
878 | return 0; | |
879 | } | |
880 | return 1; | |
2c474ddb AK |
881 | } else if (*spec == 'p' && *(spec + 1) == ':') { |
882 | int prog_id, i, j; | |
883 | char *endptr; | |
884 | spec += 2; | |
885 | prog_id = strtol(spec, &endptr, 0); | |
886 | for (i = 0; i < s->nb_programs; i++) { | |
887 | if (s->programs[i]->id != prog_id) | |
888 | continue; | |
889 | ||
890 | if (*endptr++ == ':') { | |
891 | int stream_idx = strtol(endptr, NULL, 0); | |
892 | return (stream_idx >= 0 && stream_idx < s->programs[i]->nb_stream_indexes && | |
893 | st->index == s->programs[i]->stream_index[stream_idx]); | |
894 | } | |
895 | ||
896 | for (j = 0; j < s->programs[i]->nb_stream_indexes; j++) | |
897 | if (st->index == s->programs[i]->stream_index[j]) | |
898 | return 1; | |
899 | } | |
900 | return 0; | |
d4863fc1 AK |
901 | } else if (!*spec) /* empty specifier, matches everything */ |
902 | return 1; | |
903 | ||
904 | av_log(s, AV_LOG_ERROR, "Invalid stream specifier: %s.\n", spec); | |
905 | return AVERROR(EINVAL); | |
906 | } | |
907 | ||
908 | AVDictionary *filter_codec_opts(AVDictionary *opts, enum CodecID codec_id, AVFormatContext *s, AVStream *st) | |
8c8eab8b AK |
909 | { |
910 | AVDictionary *ret = NULL; | |
911 | AVDictionaryEntry *t = NULL; | |
d4863fc1 AK |
912 | AVCodec *codec = s->oformat ? avcodec_find_encoder(codec_id) : avcodec_find_decoder(codec_id); |
913 | int flags = s->oformat ? AV_OPT_FLAG_ENCODING_PARAM : AV_OPT_FLAG_DECODING_PARAM; | |
8c8eab8b | 914 | char prefix = 0; |
20c21f8b | 915 | const AVClass *cc = avcodec_get_class(); |
8c8eab8b AK |
916 | |
917 | if (!codec) | |
918 | return NULL; | |
919 | ||
920 | switch (codec->type) { | |
921 | case AVMEDIA_TYPE_VIDEO: prefix = 'v'; flags |= AV_OPT_FLAG_VIDEO_PARAM; break; | |
922 | case AVMEDIA_TYPE_AUDIO: prefix = 'a'; flags |= AV_OPT_FLAG_AUDIO_PARAM; break; | |
923 | case AVMEDIA_TYPE_SUBTITLE: prefix = 's'; flags |= AV_OPT_FLAG_SUBTITLE_PARAM; break; | |
924 | } | |
925 | ||
926 | while (t = av_dict_get(opts, "", t, AV_DICT_IGNORE_SUFFIX)) { | |
d4863fc1 AK |
927 | char *p = strchr(t->key, ':'); |
928 | ||
929 | /* check stream specification in opt name */ | |
930 | if (p) | |
931 | switch (check_stream_specifier(s, st, p + 1)) { | |
932 | case 1: *p = 0; break; | |
933 | case 0: continue; | |
934 | default: return NULL; | |
935 | } | |
936 | ||
20c21f8b AK |
937 | if (av_opt_find(&cc, t->key, NULL, flags, AV_OPT_SEARCH_FAKE_OBJ) || |
938 | (codec && codec->priv_class && av_opt_find(&codec->priv_class, t->key, NULL, flags, AV_OPT_SEARCH_FAKE_OBJ))) | |
8c8eab8b | 939 | av_dict_set(&ret, t->key, t->value, 0); |
20c21f8b | 940 | else if (t->key[0] == prefix && av_opt_find(&cc, t->key+1, NULL, flags, AV_OPT_SEARCH_FAKE_OBJ)) |
8c8eab8b | 941 | av_dict_set(&ret, t->key+1, t->value, 0); |
d4863fc1 AK |
942 | |
943 | if (p) | |
944 | *p = ':'; | |
8c8eab8b AK |
945 | } |
946 | return ret; | |
947 | } | |
948 | ||
8ec19f84 | 949 | AVDictionary **setup_find_stream_info_opts(AVFormatContext *s, AVDictionary *codec_opts) |
3009f521 AK |
950 | { |
951 | int i; | |
952 | AVDictionary **opts; | |
953 | ||
954 | if (!s->nb_streams) | |
955 | return NULL; | |
956 | opts = av_mallocz(s->nb_streams * sizeof(*opts)); | |
957 | if (!opts) { | |
958 | av_log(NULL, AV_LOG_ERROR, "Could not alloc memory for stream options.\n"); | |
959 | return NULL; | |
960 | } | |
961 | for (i = 0; i < s->nb_streams; i++) | |
d4863fc1 | 962 | opts[i] = filter_codec_opts(codec_opts, s->streams[i]->codec->codec_id, s, s->streams[i]); |
3009f521 AK |
963 | return opts; |
964 | } | |
965 | ||
f7ead94c SS |
966 | #if CONFIG_AVFILTER |
967 | ||
968 | static int ffsink_init(AVFilterContext *ctx, const char *args, void *opaque) | |
969 | { | |
970 | FFSinkContext *priv = ctx->priv; | |
971 | ||
972 | if (!opaque) | |
973 | return AVERROR(EINVAL); | |
974 | *priv = *(FFSinkContext *)opaque; | |
975 | ||
976 | return 0; | |
977 | } | |
978 | ||
979 | static void null_end_frame(AVFilterLink *inlink) { } | |
980 | ||
981 | static int ffsink_query_formats(AVFilterContext *ctx) | |
982 | { | |
983 | FFSinkContext *priv = ctx->priv; | |
984 | enum PixelFormat pix_fmts[] = { priv->pix_fmt, PIX_FMT_NONE }; | |
985 | ||
986 | avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts)); | |
987 | return 0; | |
988 | } | |
989 | ||
990 | AVFilter ffsink = { | |
991 | .name = "ffsink", | |
992 | .priv_size = sizeof(FFSinkContext), | |
993 | .init = ffsink_init, | |
994 | ||
995 | .query_formats = ffsink_query_formats, | |
996 | ||
997 | .inputs = (AVFilterPad[]) {{ .name = "default", | |
998 | .type = AVMEDIA_TYPE_VIDEO, | |
999 | .end_frame = null_end_frame, | |
1000 | .min_perms = AV_PERM_READ, }, | |
1001 | { .name = NULL }}, | |
1002 | .outputs = (AVFilterPad[]) {{ .name = NULL }}, | |
1003 | }; | |
1004 | ||
ff0652e5 SS |
1005 | int get_filtered_video_frame(AVFilterContext *ctx, AVFrame *frame, |
1006 | AVFilterBufferRef **picref_ptr, AVRational *tb) | |
1007 | { | |
1008 | int ret; | |
1009 | AVFilterBufferRef *picref; | |
1010 | ||
1011 | if ((ret = avfilter_request_frame(ctx->inputs[0])) < 0) | |
1012 | return ret; | |
1013 | if (!(picref = ctx->inputs[0]->cur_buf)) | |
1014 | return AVERROR(ENOENT); | |
1015 | *picref_ptr = picref; | |
1016 | ctx->inputs[0]->cur_buf = NULL; | |
1017 | *tb = ctx->inputs[0]->time_base; | |
1018 | ||
1019 | memcpy(frame->data, picref->data, sizeof(frame->data)); | |
1020 | memcpy(frame->linesize, picref->linesize, sizeof(frame->linesize)); | |
1021 | frame->interlaced_frame = picref->video->interlaced; | |
1022 | frame->top_field_first = picref->video->top_field_first; | |
10d39405 RPM |
1023 | frame->key_frame = picref->video->key_frame; |
1024 | frame->pict_type = picref->video->pict_type; | |
ff0652e5 SS |
1025 | |
1026 | return 1; | |
1027 | } | |
1028 | ||
e1b10155 JG |
1029 | #endif /* CONFIG_AVFILTER */ |
1030 | ||
cac651c8 AK |
1031 | void *grow_array(void *array, int elem_size, int *size, int new_size) |
1032 | { | |
1033 | if (new_size >= INT_MAX / elem_size) { | |
1034 | av_log(NULL, AV_LOG_ERROR, "Array too big.\n"); | |
1035 | exit_program(1); | |
1036 | } | |
1037 | if (*size < new_size) { | |
1038 | uint8_t *tmp = av_realloc(array, new_size*elem_size); | |
1039 | if (!tmp) { | |
1040 | av_log(NULL, AV_LOG_ERROR, "Could not alloc buffer.\n"); | |
1041 | exit_program(1); | |
1042 | } | |
1043 | memset(tmp + *size*elem_size, 0, (new_size-*size) * elem_size); | |
1044 | *size = new_size; | |
1045 | return tmp; | |
1046 | } | |
1047 | return array; | |
1048 | } |