FFmpegKit Android API 6.0
Loading...
Searching...
No Matches
fftools_opt_common.c
Go to the documentation of this file.
1/*
2 * Option handlers shared between the tools.
3 * Copyright (c) 2022 Taner Sener
4 * Copyright (c) 2023 ARTHENICA LTD
5 *
6 * This file is part of FFmpeg.
7 *
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23/*
24 * This file is the modified version of opt_common.c file living in ffmpeg source code under the fftools folder. We
25 * manually update it each time we depend on a new ffmpeg version. Below you can see the list of changes applied
26 * by us to develop the ffmpeg-kit library.
27 *
28 * ffmpeg-kit changes by ARTHENICA LTD
29 *
30 * 07.2023
31 * --------------------------------------------------------
32 * - time field in report_callback updated as double
33 *
34 * ffmpeg-kit changes by Taner Sener
35 *
36 * 09.2022
37 * --------------------------------------------------------
38 * - printf replaced with av_log statements
39 * - libpostproc references dropped
40 * - fftools_ prefix added to fftools headers
41 * - added __thread modifier to report_file variables and warned_cfg
42 * - log_callback_report updated to forward logs via ffmpegkit_log_callback_function
43 * - extern program_name declared
44 */
45
46#include "config.h"
47
48#include <stdio.h>
49
50#include "fftools_cmdutils.h"
51#include "fftools_opt_common.h"
52
53#include "libavutil/avassert.h"
54#include "libavutil/avstring.h"
55#include "libavutil/bprint.h"
56#include "libavutil/channel_layout.h"
57#include "libavutil/cpu.h"
58#include "libavutil/dict.h"
59#include "libavutil/error.h"
60#include "libavutil/ffversion.h"
61#include "libavutil/log.h"
62#include "libavutil/mem.h"
63#include "libavutil/parseutils.h"
64#include "libavutil/pixdesc.h"
65#include "libavutil/version.h"
66
67#include "libavcodec/avcodec.h"
68#include "libavcodec/bsf.h"
69#include "libavcodec/codec.h"
70#include "libavcodec/codec_desc.h"
71#include "libavcodec/version.h"
72
73#include "libavformat/avformat.h"
74#include "libavformat/version.h"
75
76#include "libavdevice/avdevice.h"
77#include "libavdevice/version.h"
78
79#include "libavfilter/avfilter.h"
80#include "libavfilter/version.h"
81
82#include "libswscale/swscale.h"
83#include "libswscale/version.h"
84
85#include "libswresample/swresample.h"
86#include "libswresample/version.h"
87
92};
93
94static __thread FILE *report_file = NULL;
95static __thread int report_file_level = AV_LOG_DEBUG;
96
97extern void ffmpegkit_log_callback_function(void *ptr, int level, const char* format, va_list vargs);
98extern void (*report_callback)(int, float, float, int64_t, double, double, double);
99extern __thread char *program_name;
100
101int show_license(void *optctx, const char *opt, const char *arg)
102{
103#if CONFIG_NONFREE
104 av_log(NULL, AV_LOG_ERROR,
105 "This version of %s has nonfree parts compiled in.\n"
106 "Therefore it is not legally redistributable.\n",
107 program_name );
108#elif CONFIG_GPLV3
109 av_log(NULL, AV_LOG_ERROR,
110 "%s is free software; you can redistribute it and/or modify\n"
111 "it under the terms of the GNU General Public License as published by\n"
112 "the Free Software Foundation; either version 3 of the License, or\n"
113 "(at your option) any later version.\n"
114 "\n"
115 "%s is distributed in the hope that it will be useful,\n"
116 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
117 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
118 "GNU General Public License for more details.\n"
119 "\n"
120 "You should have received a copy of the GNU General Public License\n"
121 "along with %s. If not, see <http://www.gnu.org/licenses/>.\n",
123#elif CONFIG_GPL
124 av_log(NULL, AV_LOG_ERROR,
125 "%s is free software; you can redistribute it and/or modify\n"
126 "it under the terms of the GNU General Public License as published by\n"
127 "the Free Software Foundation; either version 2 of the License, or\n"
128 "(at your option) any later version.\n"
129 "\n"
130 "%s is distributed in the hope that it will be useful,\n"
131 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
132 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
133 "GNU General Public License for more details.\n"
134 "\n"
135 "You should have received a copy of the GNU General Public License\n"
136 "along with %s; if not, write to the Free Software\n"
137 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n",
139#elif CONFIG_LGPLV3
140 av_log(NULL, AV_LOG_ERROR,
141 "%s is free software; you can redistribute it and/or modify\n"
142 "it under the terms of the GNU Lesser General Public License as published by\n"
143 "the Free Software Foundation; either version 3 of the License, or\n"
144 "(at your option) any later version.\n"
145 "\n"
146 "%s is distributed in the hope that it will be useful,\n"
147 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
148 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
149 "GNU Lesser General Public License for more details.\n"
150 "\n"
151 "You should have received a copy of the GNU Lesser General Public License\n"
152 "along with %s. If not, see <http://www.gnu.org/licenses/>.\n",
154#else
155 av_log(NULL, AV_LOG_ERROR,
156 "%s is free software; you can redistribute it and/or\n"
157 "modify it under the terms of the GNU Lesser General Public\n"
158 "License as published by the Free Software Foundation; either\n"
159 "version 2.1 of the License, or (at your option) any later version.\n"
160 "\n"
161 "%s is distributed in the hope that it will be useful,\n"
162 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
163 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n"
164 "Lesser General Public License for more details.\n"
165 "\n"
166 "You should have received a copy of the GNU Lesser General Public\n"
167 "License along with %s; if not, write to the Free Software\n"
168 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n",
170#endif
171
172 return 0;
173}
174
175__thread int warned_cfg = 0;
176
177#define INDENT 1
178#define SHOW_VERSION 2
179#define SHOW_CONFIG 4
180#define SHOW_COPYRIGHT 8
181
182#define PRINT_LIB_INFO(libname, LIBNAME, flags, level) \
183 if (CONFIG_##LIBNAME) { \
184 const char *indent = flags & INDENT? " " : ""; \
185 if (flags & SHOW_VERSION) { \
186 unsigned int version = libname##_version(); \
187 av_log(NULL, level, \
188 "%slib%-11s %2d.%3d.%3d / %2d.%3d.%3d\n", \
189 indent, #libname, \
190 LIB##LIBNAME##_VERSION_MAJOR, \
191 LIB##LIBNAME##_VERSION_MINOR, \
192 LIB##LIBNAME##_VERSION_MICRO, \
193 AV_VERSION_MAJOR(version), AV_VERSION_MINOR(version),\
194 AV_VERSION_MICRO(version)); \
195 } \
196 if (flags & SHOW_CONFIG) { \
197 const char *cfg = libname##_configuration(); \
198 if (strcmp(FFMPEG_CONFIGURATION, cfg)) { \
199 if (!warned_cfg) { \
200 av_log(NULL, level, \
201 "%sWARNING: library configuration mismatch\n", \
202 indent); \
203 warned_cfg = 1; \
204 } \
205 av_log(NULL, level, "%s%-11s configuration: %s\n", \
206 indent, #libname, cfg); \
207 } \
208 } \
209 } \
210
211static void print_all_libs_info(int flags, int level)
212{
213 PRINT_LIB_INFO(avutil, AVUTIL, flags, level);
214 PRINT_LIB_INFO(avcodec, AVCODEC, flags, level);
215 PRINT_LIB_INFO(avformat, AVFORMAT, flags, level);
216 PRINT_LIB_INFO(avdevice, AVDEVICE, flags, level);
217 PRINT_LIB_INFO(avfilter, AVFILTER, flags, level);
218 PRINT_LIB_INFO(swscale, SWSCALE, flags, level);
219 PRINT_LIB_INFO(swresample, SWRESAMPLE, flags, level);
220}
221
222static void print_program_info(int flags, int level)
223{
224 const char *indent = flags & INDENT? " " : "";
225
226 av_log(NULL, level, "%s version " FFMPEG_VERSION, program_name);
227 if (flags & SHOW_COPYRIGHT)
228 av_log(NULL, level, " Copyright (c) %d-%d the FFmpeg developers",
229 program_birth_year, CONFIG_THIS_YEAR);
230 av_log(NULL, level, "\n");
231 av_log(NULL, level, "%sbuilt with %s\n", indent, CC_IDENT);
232
233 av_log(NULL, level, "%sconfiguration: " FFMPEG_CONFIGURATION "\n", indent);
234}
235
236static void print_buildconf(int flags, int level)
237{
238 const char *indent = flags & INDENT ? " " : "";
239 char str[] = { FFMPEG_CONFIGURATION };
240 char *conflist, *remove_tilde, *splitconf;
241
242 // Change all the ' --' strings to '~--' so that
243 // they can be identified as tokens.
244 while ((conflist = strstr(str, " --")) != NULL) {
245 conflist[0] = '~';
246 }
247
248 // Compensate for the weirdness this would cause
249 // when passing 'pkg-config --static'.
250 while ((remove_tilde = strstr(str, "pkg-config~")) != NULL) {
251 remove_tilde[sizeof("pkg-config~") - 2] = ' ';
252 }
253
254 splitconf = strtok(str, "~");
255 av_log(NULL, level, "\n%sconfiguration:\n", indent);
256 while (splitconf != NULL) {
257 av_log(NULL, level, "%s%s%s\n", indent, indent, splitconf);
258 splitconf = strtok(NULL, "~");
259 }
260}
261
262void show_banner(int argc, char **argv, const OptionDef *options)
263{
264 int idx = locate_option(argc, argv, options, "version");
265 if (hide_banner || idx)
266 return;
267
271}
272
273int show_version(void *optctx, const char *opt, const char *arg)
274{
275 print_program_info (SHOW_COPYRIGHT, AV_LOG_INFO);
276 print_all_libs_info(SHOW_VERSION, AV_LOG_INFO);
277
278 return 0;
279}
280
281int show_buildconf(void *optctx, const char *opt, const char *arg)
282{
283 print_buildconf (INDENT|0, AV_LOG_INFO);
284
285 return 0;
286}
287
288#define PRINT_CODEC_SUPPORTED(codec, field, type, list_name, term, get_name) \
289 if (codec->field) { \
290 const type *p = codec->field; \
291 \
292 av_log(NULL, AV_LOG_ERROR, " Supported " list_name ":"); \
293 while (*p != term) { \
294 get_name(*p); \
295 av_log(NULL, AV_LOG_ERROR, " %s", name); \
296 p++; \
297 } \
298 av_log(NULL, AV_LOG_ERROR, "\n"); \
299 } \
300
301static void print_codec(const AVCodec *c)
302{
303 int encoder = av_codec_is_encoder(c);
304
305 av_log(NULL, AV_LOG_ERROR, "%s %s [%s]:\n", encoder ? "Encoder" : "Decoder", c->name,
306 c->long_name ? c->long_name : "");
307
308 av_log(NULL, AV_LOG_ERROR, " General capabilities: ");
309 if (c->capabilities & AV_CODEC_CAP_DRAW_HORIZ_BAND)
310 av_log(NULL, AV_LOG_ERROR, "horizband ");
311 if (c->capabilities & AV_CODEC_CAP_DR1)
312 av_log(NULL, AV_LOG_ERROR, "dr1 ");
313 if (c->capabilities & AV_CODEC_CAP_DELAY)
314 av_log(NULL, AV_LOG_ERROR, "delay ");
315 if (c->capabilities & AV_CODEC_CAP_SMALL_LAST_FRAME)
316 av_log(NULL, AV_LOG_ERROR, "small ");
317 if (c->capabilities & AV_CODEC_CAP_SUBFRAMES)
318 av_log(NULL, AV_LOG_ERROR, "subframes ");
319 if (c->capabilities & AV_CODEC_CAP_EXPERIMENTAL)
320 av_log(NULL, AV_LOG_ERROR, "exp ");
321 if (c->capabilities & AV_CODEC_CAP_CHANNEL_CONF)
322 av_log(NULL, AV_LOG_ERROR, "chconf ");
323 if (c->capabilities & AV_CODEC_CAP_PARAM_CHANGE)
324 av_log(NULL, AV_LOG_ERROR, "paramchange ");
325 if (c->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE)
326 av_log(NULL, AV_LOG_ERROR, "variable ");
327 if (c->capabilities & (AV_CODEC_CAP_FRAME_THREADS |
328 AV_CODEC_CAP_SLICE_THREADS |
329 AV_CODEC_CAP_OTHER_THREADS))
330 av_log(NULL, AV_LOG_ERROR, "threads ");
331 if (c->capabilities & AV_CODEC_CAP_AVOID_PROBING)
332 av_log(NULL, AV_LOG_ERROR, "avoidprobe ");
333 if (c->capabilities & AV_CODEC_CAP_HARDWARE)
334 av_log(NULL, AV_LOG_ERROR, "hardware ");
335 if (c->capabilities & AV_CODEC_CAP_HYBRID)
336 av_log(NULL, AV_LOG_ERROR, "hybrid ");
337 if (!c->capabilities)
338 av_log(NULL, AV_LOG_ERROR, "none");
339 av_log(NULL, AV_LOG_ERROR, "\n");
340
341 if (c->type == AVMEDIA_TYPE_VIDEO ||
342 c->type == AVMEDIA_TYPE_AUDIO) {
343 av_log(NULL, AV_LOG_ERROR, " Threading capabilities: ");
344 switch (c->capabilities & (AV_CODEC_CAP_FRAME_THREADS |
345 AV_CODEC_CAP_SLICE_THREADS |
346 AV_CODEC_CAP_OTHER_THREADS)) {
347 case AV_CODEC_CAP_FRAME_THREADS |
348 AV_CODEC_CAP_SLICE_THREADS: av_log(NULL, AV_LOG_ERROR, "frame and slice"); break;
349 case AV_CODEC_CAP_FRAME_THREADS: av_log(NULL, AV_LOG_ERROR, "frame"); break;
350 case AV_CODEC_CAP_SLICE_THREADS: av_log(NULL, AV_LOG_ERROR, "slice"); break;
351 case AV_CODEC_CAP_OTHER_THREADS: av_log(NULL, AV_LOG_ERROR, "other"); break;
352 default: av_log(NULL, AV_LOG_ERROR, "none"); break;
353 }
354 av_log(NULL, AV_LOG_ERROR, "\n");
355 }
356
357 if (avcodec_get_hw_config(c, 0)) {
358 av_log(NULL, AV_LOG_ERROR, " Supported hardware devices: ");
359 for (int i = 0;; i++) {
360 const AVCodecHWConfig *config = avcodec_get_hw_config(c, i);
361 if (!config)
362 break;
363 av_log(NULL, AV_LOG_ERROR, "%s ", av_hwdevice_get_type_name(config->device_type));
364 }
365 av_log(NULL, AV_LOG_ERROR, "\n");
366 }
367
368 if (c->supported_framerates) {
369 const AVRational *fps = c->supported_framerates;
370
371 av_log(NULL, AV_LOG_ERROR, " Supported framerates:");
372 while (fps->num) {
373 av_log(NULL, AV_LOG_ERROR, " %d/%d", fps->num, fps->den);
374 fps++;
375 }
376 av_log(NULL, AV_LOG_ERROR, "\n");
377 }
378 PRINT_CODEC_SUPPORTED(c, pix_fmts, enum AVPixelFormat, "pixel formats",
379 AV_PIX_FMT_NONE, GET_PIX_FMT_NAME);
380 PRINT_CODEC_SUPPORTED(c, supported_samplerates, int, "sample rates", 0,
382 PRINT_CODEC_SUPPORTED(c, sample_fmts, enum AVSampleFormat, "sample formats",
383 AV_SAMPLE_FMT_NONE, GET_SAMPLE_FMT_NAME);
384
385 if (c->ch_layouts) {
386 const AVChannelLayout *p = c->ch_layouts;
387
388 av_log(NULL, AV_LOG_ERROR, " Supported channel layouts:");
389 while (p->nb_channels) {
390 char name[128];
391 av_channel_layout_describe(p, name, sizeof(name));
392 av_log(NULL, AV_LOG_ERROR, " %s", name);
393 p++;
394 }
395 av_log(NULL, AV_LOG_ERROR, "\n");
396 }
397
398 if (c->priv_class) {
399 show_help_children(c->priv_class,
400 AV_OPT_FLAG_ENCODING_PARAM |
401 AV_OPT_FLAG_DECODING_PARAM);
402 }
403}
404
405static const AVCodec *next_codec_for_id(enum AVCodecID id, void **iter,
406 int encoder)
407{
408 const AVCodec *c;
409 while ((c = av_codec_iterate(iter))) {
410 if (c->id == id &&
411 (encoder ? av_codec_is_encoder(c) : av_codec_is_decoder(c)))
412 return c;
413 }
414 return NULL;
415}
416
417static void show_help_codec(const char *name, int encoder)
418{
419 const AVCodecDescriptor *desc;
420 const AVCodec *codec;
421
422 if (!name) {
423 av_log(NULL, AV_LOG_ERROR, "No codec name specified.\n");
424 return;
425 }
426
427 codec = encoder ? avcodec_find_encoder_by_name(name) :
428 avcodec_find_decoder_by_name(name);
429
430 if (codec)
431 print_codec(codec);
432 else if ((desc = avcodec_descriptor_get_by_name(name))) {
433 void *iter = NULL;
434 int printed = 0;
435
436 while ((codec = next_codec_for_id(desc->id, &iter, encoder))) {
437 printed = 1;
438 print_codec(codec);
439 }
440
441 if (!printed) {
442 av_log(NULL, AV_LOG_ERROR, "Codec '%s' is known to FFmpeg, "
443 "but no %s for it are available. FFmpeg might need to be "
444 "recompiled with additional external libraries.\n",
445 name, encoder ? "encoders" : "decoders");
446 }
447 } else {
448 av_log(NULL, AV_LOG_ERROR, "Codec '%s' is not recognized by FFmpeg.\n",
449 name);
450 }
451}
452
453static void show_help_demuxer(const char *name)
454{
455 const AVInputFormat *fmt = av_find_input_format(name);
456
457 if (!fmt) {
458 av_log(NULL, AV_LOG_ERROR, "Unknown format '%s'.\n", name);
459 return;
460 }
461
462 av_log(NULL, AV_LOG_ERROR, "Demuxer %s [%s]:\n", fmt->name, fmt->long_name);
463
464 if (fmt->extensions)
465 av_log(NULL, AV_LOG_ERROR, " Common extensions: %s.\n", fmt->extensions);
466
467 if (fmt->priv_class)
468 show_help_children(fmt->priv_class, AV_OPT_FLAG_DECODING_PARAM);
469}
470
471static void show_help_protocol(const char *name)
472{
473 const AVClass *proto_class;
474
475 if (!name) {
476 av_log(NULL, AV_LOG_ERROR, "No protocol name specified.\n");
477 return;
478 }
479
480 proto_class = avio_protocol_get_class(name);
481 if (!proto_class) {
482 av_log(NULL, AV_LOG_ERROR, "Unknown protocol '%s'.\n", name);
483 return;
484 }
485
486 show_help_children(proto_class, AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_ENCODING_PARAM);
487}
488
489static void show_help_muxer(const char *name)
490{
491 const AVCodecDescriptor *desc;
492 const AVOutputFormat *fmt = av_guess_format(name, NULL, NULL);
493
494 if (!fmt) {
495 av_log(NULL, AV_LOG_ERROR, "Unknown format '%s'.\n", name);
496 return;
497 }
498
499 av_log(NULL, AV_LOG_ERROR, "Muxer %s [%s]:\n", fmt->name, fmt->long_name);
500
501 if (fmt->extensions)
502 av_log(NULL, AV_LOG_ERROR, " Common extensions: %s.\n", fmt->extensions);
503 if (fmt->mime_type)
504 av_log(NULL, AV_LOG_ERROR, " Mime type: %s.\n", fmt->mime_type);
505 if (fmt->video_codec != AV_CODEC_ID_NONE &&
506 (desc = avcodec_descriptor_get(fmt->video_codec))) {
507 av_log(NULL, AV_LOG_ERROR, " Default video codec: %s.\n", desc->name);
508 }
509 if (fmt->audio_codec != AV_CODEC_ID_NONE &&
510 (desc = avcodec_descriptor_get(fmt->audio_codec))) {
511 av_log(NULL, AV_LOG_ERROR, " Default audio codec: %s.\n", desc->name);
512 }
513 if (fmt->subtitle_codec != AV_CODEC_ID_NONE &&
514 (desc = avcodec_descriptor_get(fmt->subtitle_codec))) {
515 av_log(NULL, AV_LOG_ERROR, " Default subtitle codec: %s.\n", desc->name);
516 }
517
518 if (fmt->priv_class)
519 show_help_children(fmt->priv_class, AV_OPT_FLAG_ENCODING_PARAM);
520}
521
522#if CONFIG_AVFILTER
523static void show_help_filter(const char *name)
524{
525#if CONFIG_AVFILTER
526 const AVFilter *f = avfilter_get_by_name(name);
527 int i, count;
528
529 if (!name) {
530 av_log(NULL, AV_LOG_ERROR, "No filter name specified.\n");
531 return;
532 } else if (!f) {
533 av_log(NULL, AV_LOG_ERROR, "Unknown filter '%s'.\n", name);
534 return;
535 }
536
537 av_log(NULL, AV_LOG_ERROR, "Filter %s\n", f->name);
538 if (f->description)
539 av_log(NULL, AV_LOG_ERROR, " %s\n", f->description);
540
541 if (f->flags & AVFILTER_FLAG_SLICE_THREADS)
542 av_log(NULL, AV_LOG_ERROR, " slice threading supported\n");
543
544 av_log(NULL, AV_LOG_ERROR, " Inputs:\n");
545 count = avfilter_filter_pad_count(f, 0);
546 for (i = 0; i < count; i++) {
547 av_log(NULL, AV_LOG_ERROR, " #%d: %s (%s)\n", i, avfilter_pad_get_name(f->inputs, i),
548 av_get_media_type_string(avfilter_pad_get_type(f->inputs, i)));
549 }
550 if (f->flags & AVFILTER_FLAG_DYNAMIC_INPUTS)
551 av_log(NULL, AV_LOG_ERROR, " dynamic (depending on the options)\n");
552 else if (!count)
553 av_log(NULL, AV_LOG_ERROR, " none (source filter)\n");
554
555 av_log(NULL, AV_LOG_ERROR, " Outputs:\n");
556 count = avfilter_filter_pad_count(f, 1);
557 for (i = 0; i < count; i++) {
558 av_log(NULL, AV_LOG_ERROR, " #%d: %s (%s)\n", i, avfilter_pad_get_name(f->outputs, i),
559 av_get_media_type_string(avfilter_pad_get_type(f->outputs, i)));
560 }
561 if (f->flags & AVFILTER_FLAG_DYNAMIC_OUTPUTS)
562 av_log(NULL, AV_LOG_ERROR, " dynamic (depending on the options)\n");
563 else if (!count)
564 av_log(NULL, AV_LOG_ERROR, " none (sink filter)\n");
565
566 if (f->priv_class)
567 show_help_children(f->priv_class, AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM |
568 AV_OPT_FLAG_AUDIO_PARAM);
569 if (f->flags & AVFILTER_FLAG_SUPPORT_TIMELINE)
570 av_log(NULL, AV_LOG_ERROR, "This filter has support for timeline through the 'enable' option.\n");
571#else
572 av_log(NULL, AV_LOG_ERROR, "Build without libavfilter; "
573 "can not to satisfy request\n");
574#endif
575}
576#endif
577
578static void show_help_bsf(const char *name)
579{
580 const AVBitStreamFilter *bsf = av_bsf_get_by_name(name);
581
582 if (!name) {
583 av_log(NULL, AV_LOG_ERROR, "No bitstream filter name specified.\n");
584 return;
585 } else if (!bsf) {
586 av_log(NULL, AV_LOG_ERROR, "Unknown bit stream filter '%s'.\n", name);
587 return;
588 }
589
590 av_log(NULL, AV_LOG_ERROR, "Bit stream filter %s\n", bsf->name);
591 PRINT_CODEC_SUPPORTED(bsf, codec_ids, enum AVCodecID, "codecs",
592 AV_CODEC_ID_NONE, GET_CODEC_NAME);
593 if (bsf->priv_class)
594 show_help_children(bsf->priv_class, AV_OPT_FLAG_BSF_PARAM);
595}
596
597int show_help(void *optctx, const char *opt, const char *arg)
598{
599 char *topic, *par;
600
601 topic = av_strdup(arg ? arg : "");
602 if (!topic)
603 return AVERROR(ENOMEM);
604 par = strchr(topic, '=');
605 if (par)
606 *par++ = 0;
607
608 if (!*topic) {
609 if (program_name && !strcmp(program_name, "ffmpeg")) {
610 show_help_default_ffmpeg(topic, par);
611 } else {
612 show_help_default_ffprobe(topic, par);
613 }
614 } else if (!strcmp(topic, "decoder")) {
615 show_help_codec(par, 0);
616 } else if (!strcmp(topic, "encoder")) {
617 show_help_codec(par, 1);
618 } else if (!strcmp(topic, "demuxer")) {
620 } else if (!strcmp(topic, "muxer")) {
621 show_help_muxer(par);
622 } else if (!strcmp(topic, "protocol")) {
624#if CONFIG_AVFILTER
625 } else if (!strcmp(topic, "filter")) {
626 show_help_filter(par);
627#endif
628 } else if (!strcmp(topic, "bsf")) {
629 show_help_bsf(par);
630 } else {
631 if (program_name && !strcmp(program_name, "ffmpeg")) {
632 show_help_default_ffmpeg(topic, par);
633 } else {
634 show_help_default_ffprobe(topic, par);
635 }
636 }
637
638 av_freep(&topic);
639 return 0;
640}
641
642static void print_codecs_for_id(enum AVCodecID id, int encoder)
643{
644 void *iter = NULL;
645 const AVCodec *codec;
646
647 av_log(NULL, AV_LOG_ERROR, " (%s: ", encoder ? "encoders" : "decoders");
648
649 while ((codec = next_codec_for_id(id, &iter, encoder)))
650 av_log(NULL, AV_LOG_ERROR, "%s ", codec->name);
651
652 av_log(NULL, AV_LOG_ERROR, ")");
653}
654
655static int compare_codec_desc(const void *a, const void *b)
656{
657 const AVCodecDescriptor * const *da = a;
658 const AVCodecDescriptor * const *db = b;
659
660 return (*da)->type != (*db)->type ? FFDIFFSIGN((*da)->type, (*db)->type) :
661 strcmp((*da)->name, (*db)->name);
662}
663
664static unsigned get_codecs_sorted(const AVCodecDescriptor ***rcodecs)
665{
666 const AVCodecDescriptor *desc = NULL;
667 const AVCodecDescriptor **codecs;
668 unsigned nb_codecs = 0, i = 0;
669
670 while ((desc = avcodec_descriptor_next(desc)))
671 nb_codecs++;
672 if (!(codecs = av_calloc(nb_codecs, sizeof(*codecs)))) {
673 av_log(NULL, AV_LOG_ERROR, "Out of memory\n");
674 exit_program(1);
675 }
676 desc = NULL;
677 while ((desc = avcodec_descriptor_next(desc)))
678 codecs[i++] = desc;
679 av_assert0(i == nb_codecs);
680 qsort(codecs, nb_codecs, sizeof(*codecs), compare_codec_desc);
681 *rcodecs = codecs;
682 return nb_codecs;
683}
684
685static char get_media_type_char(enum AVMediaType type)
686{
687 switch (type) {
688 case AVMEDIA_TYPE_VIDEO: return 'V';
689 case AVMEDIA_TYPE_AUDIO: return 'A';
690 case AVMEDIA_TYPE_DATA: return 'D';
691 case AVMEDIA_TYPE_SUBTITLE: return 'S';
692 case AVMEDIA_TYPE_ATTACHMENT:return 'T';
693 default: return '?';
694 }
695}
696
697int show_codecs(void *optctx, const char *opt, const char *arg)
698{
699 const AVCodecDescriptor **codecs;
700 unsigned i, nb_codecs = get_codecs_sorted(&codecs);
701
702 av_log(NULL, AV_LOG_ERROR, "Codecs:\n"
703 " D..... = Decoding supported\n"
704 " .E.... = Encoding supported\n"
705 " ..V... = Video codec\n"
706 " ..A... = Audio codec\n"
707 " ..S... = Subtitle codec\n"
708 " ..D... = Data codec\n"
709 " ..T... = Attachment codec\n"
710 " ...I.. = Intra frame-only codec\n"
711 " ....L. = Lossy compression\n"
712 " .....S = Lossless compression\n"
713 " -------\n");
714 for (i = 0; i < nb_codecs; i++) {
715 const AVCodecDescriptor *desc = codecs[i];
716 const AVCodec *codec;
717 void *iter = NULL;
718
719 if (strstr(desc->name, "_deprecated"))
720 continue;
721
722 av_log(NULL, AV_LOG_ERROR, " ");
723 av_log(NULL, AV_LOG_ERROR, avcodec_find_decoder(desc->id) ? "D" : ".");
724 av_log(NULL, AV_LOG_ERROR, avcodec_find_encoder(desc->id) ? "E" : ".");
725
726 av_log(NULL, AV_LOG_ERROR, "%c", get_media_type_char(desc->type));
727 av_log(NULL, AV_LOG_ERROR, (desc->props & AV_CODEC_PROP_INTRA_ONLY) ? "I" : ".");
728 av_log(NULL, AV_LOG_ERROR, (desc->props & AV_CODEC_PROP_LOSSY) ? "L" : ".");
729 av_log(NULL, AV_LOG_ERROR, (desc->props & AV_CODEC_PROP_LOSSLESS) ? "S" : ".");
730
731 av_log(NULL, AV_LOG_ERROR, " %-20s %s", desc->name, desc->long_name ? desc->long_name : "");
732
733 /* print decoders/encoders when there's more than one or their
734 * names are different from codec name */
735 while ((codec = next_codec_for_id(desc->id, &iter, 0))) {
736 if (strcmp(codec->name, desc->name)) {
737 print_codecs_for_id(desc->id, 0);
738 break;
739 }
740 }
741 iter = NULL;
742 while ((codec = next_codec_for_id(desc->id, &iter, 1))) {
743 if (strcmp(codec->name, desc->name)) {
744 print_codecs_for_id(desc->id, 1);
745 break;
746 }
747 }
748
749 av_log(NULL, AV_LOG_ERROR, "\n");
750 }
751 av_free(codecs);
752 return 0;
753}
754
755static void print_codecs(int encoder)
756{
757 const AVCodecDescriptor **codecs;
758 unsigned i, nb_codecs = get_codecs_sorted(&codecs);
759
760 av_log(NULL, AV_LOG_ERROR, "%s:\n"
761 " V..... = Video\n"
762 " A..... = Audio\n"
763 " S..... = Subtitle\n"
764 " .F.... = Frame-level multithreading\n"
765 " ..S... = Slice-level multithreading\n"
766 " ...X.. = Codec is experimental\n"
767 " ....B. = Supports draw_horiz_band\n"
768 " .....D = Supports direct rendering method 1\n"
769 " ------\n",
770 encoder ? "Encoders" : "Decoders");
771 for (i = 0; i < nb_codecs; i++) {
772 const AVCodecDescriptor *desc = codecs[i];
773 const AVCodec *codec;
774 void *iter = NULL;
775
776 while ((codec = next_codec_for_id(desc->id, &iter, encoder))) {
777 av_log(NULL, AV_LOG_ERROR, " %c", get_media_type_char(desc->type));
778 av_log(NULL, AV_LOG_ERROR, (codec->capabilities & AV_CODEC_CAP_FRAME_THREADS) ? "F" : ".");
779 av_log(NULL, AV_LOG_ERROR, (codec->capabilities & AV_CODEC_CAP_SLICE_THREADS) ? "S" : ".");
780 av_log(NULL, AV_LOG_ERROR, (codec->capabilities & AV_CODEC_CAP_EXPERIMENTAL) ? "X" : ".");
781 av_log(NULL, AV_LOG_ERROR, (codec->capabilities & AV_CODEC_CAP_DRAW_HORIZ_BAND)?"B" : ".");
782 av_log(NULL, AV_LOG_ERROR, (codec->capabilities & AV_CODEC_CAP_DR1) ? "D" : ".");
783
784 av_log(NULL, AV_LOG_ERROR, " %-20s %s", codec->name, codec->long_name ? codec->long_name : "");
785 if (strcmp(codec->name, desc->name))
786 av_log(NULL, AV_LOG_ERROR, " (codec %s)", desc->name);
787
788 av_log(NULL, AV_LOG_ERROR, "\n");
789 }
790 }
791 av_free(codecs);
792}
793
794int show_decoders(void *optctx, const char *opt, const char *arg)
795{
796 print_codecs(0);
797 return 0;
798}
799
800int show_encoders(void *optctx, const char *opt, const char *arg)
801{
802 print_codecs(1);
803 return 0;
804}
805
806int show_bsfs(void *optctx, const char *opt, const char *arg)
807{
808 const AVBitStreamFilter *bsf = NULL;
809 void *opaque = NULL;
810
811 av_log(NULL, AV_LOG_ERROR, "Bitstream filters:\n");
812 while ((bsf = av_bsf_iterate(&opaque)))
813 av_log(NULL, AV_LOG_ERROR, "%s\n", bsf->name);
814 av_log(NULL, AV_LOG_ERROR, "\n");
815 return 0;
816}
817
818int show_filters(void *optctx, const char *opt, const char *arg)
819{
820#if CONFIG_AVFILTER
821 const AVFilter *filter = NULL;
822 char descr[64], *descr_cur;
823 void *opaque = NULL;
824 int i, j;
825 const AVFilterPad *pad;
826
827 av_log(NULL, AV_LOG_ERROR, "Filters:\n"
828 " T.. = Timeline support\n"
829 " .S. = Slice threading\n"
830 " ..C = Command support\n"
831 " A = Audio input/output\n"
832 " V = Video input/output\n"
833 " N = Dynamic number and/or type of input/output\n"
834 " | = Source or sink filter\n");
835 while ((filter = av_filter_iterate(&opaque))) {
836 descr_cur = descr;
837 for (i = 0; i < 2; i++) {
838 unsigned nb_pads;
839 if (i) {
840 *(descr_cur++) = '-';
841 *(descr_cur++) = '>';
842 }
843 pad = i ? filter->outputs : filter->inputs;
844 nb_pads = avfilter_filter_pad_count(filter, i);
845 for (j = 0; j < nb_pads; j++) {
846 if (descr_cur >= descr + sizeof(descr) - 4)
847 break;
848 *(descr_cur++) = get_media_type_char(avfilter_pad_get_type(pad, j));
849 }
850 if (!j)
851 *(descr_cur++) = ((!i && (filter->flags & AVFILTER_FLAG_DYNAMIC_INPUTS)) ||
852 ( i && (filter->flags & AVFILTER_FLAG_DYNAMIC_OUTPUTS))) ? 'N' : '|';
853 }
854 *descr_cur = 0;
855 av_log(NULL, AV_LOG_ERROR, " %c%c%c %-17s %-10s %s\n",
856 filter->flags & AVFILTER_FLAG_SUPPORT_TIMELINE ? 'T' : '.',
857 filter->flags & AVFILTER_FLAG_SLICE_THREADS ? 'S' : '.',
858 filter->process_command ? 'C' : '.',
859 filter->name, descr, filter->description);
860 }
861#else
862 av_log(NULL, AV_LOG_ERROR, "No filters available: libavfilter disabled\n");
863#endif
864 return 0;
865}
866
867static int is_device(const AVClass *avclass)
868{
869 if (!avclass)
870 return 0;
871 return AV_IS_INPUT_DEVICE(avclass->category) || AV_IS_OUTPUT_DEVICE(avclass->category);
872}
873
874static int show_formats_devices(void *optctx, const char *opt, const char *arg, int device_only, int muxdemuxers)
875{
876 void *ifmt_opaque = NULL;
877 const AVInputFormat *ifmt = NULL;
878 void *ofmt_opaque = NULL;
879 const AVOutputFormat *ofmt = NULL;
880 const char *last_name;
881 int is_dev;
882
883 av_log(NULL, AV_LOG_ERROR, "%s\n"
884 " D. = Demuxing supported\n"
885 " .E = Muxing supported\n"
886 " --\n", device_only ? "Devices:" : "File formats:");
887 last_name = "000";
888 for (;;) {
889 int decode = 0;
890 int encode = 0;
891 const char *name = NULL;
892 const char *long_name = NULL;
893
894 if (muxdemuxers !=SHOW_DEMUXERS) {
895 ofmt_opaque = NULL;
896 while ((ofmt = av_muxer_iterate(&ofmt_opaque))) {
897 is_dev = is_device(ofmt->priv_class);
898 if (!is_dev && device_only)
899 continue;
900 if ((!name || strcmp(ofmt->name, name) < 0) &&
901 strcmp(ofmt->name, last_name) > 0) {
902 name = ofmt->name;
903 long_name = ofmt->long_name;
904 encode = 1;
905 }
906 }
907 }
908 if (muxdemuxers != SHOW_MUXERS) {
909 ifmt_opaque = NULL;
910 while ((ifmt = av_demuxer_iterate(&ifmt_opaque))) {
911 is_dev = is_device(ifmt->priv_class);
912 if (!is_dev && device_only)
913 continue;
914 if ((!name || strcmp(ifmt->name, name) < 0) &&
915 strcmp(ifmt->name, last_name) > 0) {
916 name = ifmt->name;
917 long_name = ifmt->long_name;
918 encode = 0;
919 }
920 if (name && strcmp(ifmt->name, name) == 0)
921 decode = 1;
922 }
923 }
924 if (!name)
925 break;
926 last_name = name;
927
928 av_log(NULL, AV_LOG_ERROR, " %c%c %-15s %s\n",
929 decode ? 'D' : ' ',
930 encode ? 'E' : ' ',
931 name,
932 long_name ? long_name:" ");
933 }
934 return 0;
935}
936
937int show_formats(void *optctx, const char *opt, const char *arg)
938{
939 return show_formats_devices(optctx, opt, arg, 0, SHOW_DEFAULT);
940}
941
942int show_muxers(void *optctx, const char *opt, const char *arg)
943{
944 return show_formats_devices(optctx, opt, arg, 0, SHOW_MUXERS);
945}
946
947int show_demuxers(void *optctx, const char *opt, const char *arg)
948{
949 return show_formats_devices(optctx, opt, arg, 0, SHOW_DEMUXERS);
950}
951
952int show_devices(void *optctx, const char *opt, const char *arg)
953{
954 return show_formats_devices(optctx, opt, arg, 1, SHOW_DEFAULT);
955}
956
957int show_protocols(void *optctx, const char *opt, const char *arg)
958{
959 void *opaque = NULL;
960 const char *name;
961
962 av_log(NULL, AV_LOG_ERROR, "Supported file protocols:\n"
963 "Input:\n");
964 while ((name = avio_enum_protocols(&opaque, 0)))
965 av_log(NULL, AV_LOG_ERROR, " %s\n", name);
966 av_log(NULL, AV_LOG_ERROR, "Output:\n");
967 while ((name = avio_enum_protocols(&opaque, 1)))
968 av_log(NULL, AV_LOG_ERROR, " %s\n", name);
969 return 0;
970}
971
972int show_colors(void *optctx, const char *opt, const char *arg)
973{
974 const char *name;
975 const uint8_t *rgb;
976 int i;
977
978 av_log(NULL, AV_LOG_ERROR, "%-32s #RRGGBB\n", "name");
979
980 for (i = 0; (name = av_get_known_color_name(i, &rgb)); i++)
981 av_log(NULL, AV_LOG_ERROR, "%-32s #%02x%02x%02x\n", name, rgb[0], rgb[1], rgb[2]);
982
983 return 0;
984}
985
986int show_pix_fmts(void *optctx, const char *opt, const char *arg)
987{
988 const AVPixFmtDescriptor *pix_desc = NULL;
989
990 av_log(NULL, AV_LOG_ERROR, "Pixel formats:\n"
991 "I.... = Supported Input format for conversion\n"
992 ".O... = Supported Output format for conversion\n"
993 "..H.. = Hardware accelerated format\n"
994 "...P. = Paletted format\n"
995 "....B = Bitstream format\n"
996 "FLAGS NAME NB_COMPONENTS BITS_PER_PIXEL BIT_DEPTHS\n"
997 "-----\n");
998
999#if !CONFIG_SWSCALE
1000# define sws_isSupportedInput(x) 0
1001# define sws_isSupportedOutput(x) 0
1002#endif
1003
1004 while ((pix_desc = av_pix_fmt_desc_next(pix_desc))) {
1005 enum AVPixelFormat av_unused pix_fmt = av_pix_fmt_desc_get_id(pix_desc);
1006 av_log(NULL, AV_LOG_ERROR, "%c%c%c%c%c %-16s %d %3d %d",
1007 sws_isSupportedInput (pix_fmt) ? 'I' : '.',
1008 sws_isSupportedOutput(pix_fmt) ? 'O' : '.',
1009 pix_desc->flags & AV_PIX_FMT_FLAG_HWACCEL ? 'H' : '.',
1010 pix_desc->flags & AV_PIX_FMT_FLAG_PAL ? 'P' : '.',
1011 pix_desc->flags & AV_PIX_FMT_FLAG_BITSTREAM ? 'B' : '.',
1012 pix_desc->name,
1013 pix_desc->nb_components,
1014 av_get_bits_per_pixel(pix_desc),
1015 pix_desc->comp[0].depth);
1016
1017 for (unsigned i = 1; i < pix_desc->nb_components; i++)
1018 av_log(NULL, AV_LOG_ERROR, "-%d", pix_desc->comp[i].depth);
1019 av_log(NULL, AV_LOG_ERROR, "\n");
1020 }
1021 return 0;
1022}
1023
1024int show_layouts(void *optctx, const char *opt, const char *arg)
1025{
1026 const AVChannelLayout *ch_layout;
1027 void *iter = NULL;
1028 char buf[128], buf2[128];
1029 int i = 0;
1030
1031 av_log(NULL, AV_LOG_ERROR, "Individual channels:\n"
1032 "NAME DESCRIPTION\n");
1033 for (i = 0; i < 63; i++) {
1034 av_channel_name(buf, sizeof(buf), i);
1035 if (strstr(buf, "USR"))
1036 continue;
1037 av_channel_description(buf2, sizeof(buf2), i);
1038 av_log(NULL, AV_LOG_ERROR, "%-14s %s\n", buf, buf2);
1039 }
1040 av_log(NULL, AV_LOG_ERROR, "\nStandard channel layouts:\n"
1041 "NAME DECOMPOSITION\n");
1042 while ((ch_layout = av_channel_layout_standard(&iter))) {
1043 av_channel_layout_describe(ch_layout, buf, sizeof(buf));
1044 av_log(NULL, AV_LOG_ERROR, "%-14s ", buf);
1045 for (i = 0; i < 63; i++) {
1046 int idx = av_channel_layout_index_from_channel(ch_layout, i);
1047 if (idx >= 0) {
1048 av_channel_name(buf2, sizeof(buf2), i);
1049 av_log(NULL, AV_LOG_ERROR, "%s%s", idx ? "+" : "", buf2);
1050 }
1051 }
1052 av_log(NULL, AV_LOG_ERROR, "\n");
1053 }
1054 return 0;
1055}
1056
1057int show_sample_fmts(void *optctx, const char *opt, const char *arg)
1058{
1059 int i;
1060 char fmt_str[128];
1061 for (i = -1; i < AV_SAMPLE_FMT_NB; i++)
1062 av_log(NULL, AV_LOG_ERROR, "%s\n", av_get_sample_fmt_string(fmt_str, sizeof(fmt_str), i));
1063 return 0;
1064}
1065
1066int show_dispositions(void *optctx, const char *opt, const char *arg)
1067{
1068 for (int i = 0; i < 32; i++) {
1069 const char *str = av_disposition_to_string(1U << i);
1070 if (str)
1071 av_log(NULL, AV_LOG_ERROR, "%s\n", str);
1072 }
1073 return 0;
1074}
1075
1076int opt_cpuflags(void *optctx, const char *opt, const char *arg)
1077{
1078 int ret;
1079 unsigned flags = av_get_cpu_flags();
1080
1081 if ((ret = av_parse_cpu_caps(&flags, arg)) < 0)
1082 return ret;
1083
1084 av_force_cpu_flags(flags);
1085 return 0;
1086}
1087
1088int opt_cpucount(void *optctx, const char *opt, const char *arg)
1089{
1090 int ret;
1091 int count;
1092
1093 static const AVOption opts[] = {
1094 {"count", NULL, 0, AV_OPT_TYPE_INT, { .i64 = -1}, -1, INT_MAX},
1095 {NULL},
1096 };
1097 static const AVClass class = {
1098 .class_name = "cpucount",
1099 .item_name = av_default_item_name,
1100 .option = opts,
1101 .version = LIBAVUTIL_VERSION_INT,
1102 };
1103 const AVClass *pclass = &class;
1104
1105 ret = av_opt_eval_int(&pclass, opts, arg, &count);
1106
1107 if (!ret) {
1108 av_cpu_force_count(count);
1109 }
1110
1111 return ret;
1112}
1113
1114static void expand_filename_template(AVBPrint *bp, const char *template,
1115 struct tm *tm)
1116{
1117 int c;
1118
1119 while ((c = *(template++))) {
1120 if (c == '%') {
1121 if (!(c = *(template++)))
1122 break;
1123 switch (c) {
1124 case 'p':
1125 av_bprintf(bp, "%s", program_name);
1126 break;
1127 case 't':
1128 av_bprintf(bp, "%04d%02d%02d-%02d%02d%02d",
1129 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
1130 tm->tm_hour, tm->tm_min, tm->tm_sec);
1131 break;
1132 case '%':
1133 av_bprint_chars(bp, c, 1);
1134 break;
1135 }
1136 } else {
1137 av_bprint_chars(bp, c, 1);
1138 }
1139 }
1140}
1141
1142static void log_callback_report(void *ptr, int level, const char *fmt, va_list vl)
1143{
1144 va_list vl2;
1145 char line[1024];
1146 static int print_prefix = 1;
1147
1148 va_copy(vl2, vl);
1149 if (report_callback == NULL) {
1150 av_log_default_callback(ptr, level, fmt, vl);
1151 } else {
1152 ffmpegkit_log_callback_function(ptr, level, fmt, vl);
1153 }
1154 av_log_format_line(ptr, level, fmt, vl2, line, sizeof(line), &print_prefix);
1155 va_end(vl2);
1156 if (report_file && report_file_level >= level) {
1157 fputs(line, report_file);
1158 fflush(report_file);
1159 }
1160}
1161
1162int init_report(const char *env, FILE **file)
1163{
1164 char *filename_template = NULL;
1165 char *key, *val;
1166 int ret, count = 0;
1167 int prog_loglevel, envlevel = 0;
1168 time_t now;
1169 struct tm *tm;
1170 AVBPrint filename;
1171
1172 if (report_file) /* already opened */
1173 return 0;
1174 time(&now);
1175 tm = localtime(&now);
1176
1177 while (env && *env) {
1178 if ((ret = av_opt_get_key_value(&env, "=", ":", 0, &key, &val)) < 0) {
1179 if (count)
1180 av_log(NULL, AV_LOG_ERROR,
1181 "Failed to parse FFREPORT environment variable: %s\n",
1182 av_err2str(ret));
1183 break;
1184 }
1185 if (*env)
1186 env++;
1187 count++;
1188 if (!strcmp(key, "file")) {
1189 av_free(filename_template);
1190 filename_template = val;
1191 val = NULL;
1192 } else if (!strcmp(key, "level")) {
1193 char *tail;
1194 report_file_level = strtol(val, &tail, 10);
1195 if (*tail) {
1196 av_log(NULL, AV_LOG_FATAL, "Invalid report file level\n");
1197 exit_program(1);
1198 }
1199 envlevel = 1;
1200 } else {
1201 av_log(NULL, AV_LOG_ERROR, "Unknown key '%s' in FFREPORT\n", key);
1202 }
1203 av_free(val);
1204 av_free(key);
1205 }
1206
1207 av_bprint_init(&filename, 0, AV_BPRINT_SIZE_AUTOMATIC);
1208 expand_filename_template(&filename,
1209 av_x_if_null(filename_template, "%p-%t.log"), tm);
1210 av_free(filename_template);
1211 if (!av_bprint_is_complete(&filename)) {
1212 av_log(NULL, AV_LOG_ERROR, "Out of memory building report file name\n");
1213 return AVERROR(ENOMEM);
1214 }
1215
1216 prog_loglevel = av_log_get_level();
1217 if (!envlevel)
1218 report_file_level = FFMAX(report_file_level, prog_loglevel);
1219
1220 report_file = fopen(filename.str, "w");
1221 if (!report_file) {
1222 int ret = AVERROR(errno);
1223 av_log(NULL, AV_LOG_ERROR, "Failed to open report \"%s\": %s\n",
1224 filename.str, strerror(errno));
1225 return ret;
1226 }
1227 av_log_set_callback(log_callback_report);
1228 av_log(NULL, AV_LOG_INFO,
1229 "%s started on %04d-%02d-%02d at %02d:%02d:%02d\n"
1230 "Report written to \"%s\"\n"
1231 "Log level: %d\n",
1233 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
1234 tm->tm_hour, tm->tm_min, tm->tm_sec,
1235 filename.str, report_file_level);
1236 av_bprint_finalize(&filename, NULL);
1237
1238 if (file)
1239 *file = report_file;
1240
1241 return 0;
1242}
1243
1244int opt_report(void *optctx, const char *opt, const char *arg)
1245{
1246 return init_report(NULL, NULL);
1247}
1248
1249int opt_max_alloc(void *optctx, const char *opt, const char *arg)
1250{
1251 char *tail;
1252 size_t max;
1253
1254 max = strtol(arg, &tail, 10);
1255 if (*tail) {
1256 av_log(NULL, AV_LOG_FATAL, "Invalid max_alloc \"%s\".\n", arg);
1257 exit_program(1);
1258 }
1259 av_max_alloc(max);
1260 return 0;
1261}
1262
1263int opt_loglevel(void *optctx, const char *opt, const char *arg)
1264{
1265 const struct { const char *name; int level; } log_levels[] = {
1266 { "quiet" , AV_LOG_QUIET },
1267 { "panic" , AV_LOG_PANIC },
1268 { "fatal" , AV_LOG_FATAL },
1269 { "error" , AV_LOG_ERROR },
1270 { "warning", AV_LOG_WARNING },
1271 { "info" , AV_LOG_INFO },
1272 { "verbose", AV_LOG_VERBOSE },
1273 { "debug" , AV_LOG_DEBUG },
1274 { "trace" , AV_LOG_TRACE },
1275 };
1276 const char *token;
1277 char *tail;
1278 int flags = av_log_get_flags();
1279 int level = av_log_get_level();
1280 int cmd, i = 0;
1281
1282 av_assert0(arg);
1283 while (*arg) {
1284 token = arg;
1285 if (*token == '+' || *token == '-') {
1286 cmd = *token++;
1287 } else {
1288 cmd = 0;
1289 }
1290 if (!i && !cmd) {
1291 flags = 0; /* missing relative prefix, build absolute value */
1292 }
1293 if (av_strstart(token, "repeat", &arg)) {
1294 if (cmd == '-') {
1295 flags |= AV_LOG_SKIP_REPEATED;
1296 } else {
1297 flags &= ~AV_LOG_SKIP_REPEATED;
1298 }
1299 } else if (av_strstart(token, "level", &arg)) {
1300 if (cmd == '-') {
1301 flags &= ~AV_LOG_PRINT_LEVEL;
1302 } else {
1303 flags |= AV_LOG_PRINT_LEVEL;
1304 }
1305 } else {
1306 break;
1307 }
1308 i++;
1309 }
1310 if (!*arg) {
1311 goto end;
1312 } else if (*arg == '+') {
1313 arg++;
1314 } else if (!i) {
1315 flags = av_log_get_flags(); /* level value without prefix, reset flags */
1316 }
1317
1318 for (i = 0; i < FF_ARRAY_ELEMS(log_levels); i++) {
1319 if (!strcmp(log_levels[i].name, arg)) {
1320 level = log_levels[i].level;
1321 goto end;
1322 }
1323 }
1324
1325 level = strtol(arg, &tail, 10);
1326 if (*tail) {
1327 av_log(NULL, AV_LOG_FATAL, "Invalid loglevel \"%s\". "
1328 "Possible levels are numbers or:\n", arg);
1329 for (i = 0; i < FF_ARRAY_ELEMS(log_levels); i++)
1330 av_log(NULL, AV_LOG_FATAL, "\"%s\"\n", log_levels[i].name);
1331 exit_program(1);
1332 }
1333
1334end:
1335 av_log_set_flags(flags);
1336 av_log_set_level(level);
1337 return 0;
1338}
1339
1340#if CONFIG_AVDEVICE
1341static void print_device_list(const AVDeviceInfoList *device_list)
1342{
1343 // print devices
1344 for (int i = 0; i < device_list->nb_devices; i++) {
1345 const AVDeviceInfo *device = device_list->devices[i];
1346 av_log(NULL, AV_LOG_ERROR, "%c %s [%s] (", device_list->default_device == i ? '*' : ' ',
1347 device->device_name, device->device_description);
1348 if (device->nb_media_types > 0) {
1349 for (int j = 0; j < device->nb_media_types; ++j) {
1350 const char* media_type = av_get_media_type_string(device->media_types[j]);
1351 if (j > 0)
1352 av_log(NULL, AV_LOG_ERROR, ", ");
1353 av_log(NULL, AV_LOG_ERROR, "%s", media_type ? media_type : "unknown");
1354 }
1355 } else {
1356 av_log(NULL, AV_LOG_ERROR, "none");
1357 }
1358 av_log(NULL, AV_LOG_ERROR, ")\n");
1359 }
1360}
1361
1362static int print_device_sources(const AVInputFormat *fmt, AVDictionary *opts)
1363{
1364 int ret;
1365 AVDeviceInfoList *device_list = NULL;
1366
1367 if (!fmt || !fmt->priv_class || !AV_IS_INPUT_DEVICE(fmt->priv_class->category))
1368 return AVERROR(EINVAL);
1369
1370 av_log(NULL, AV_LOG_ERROR, "Auto-detected sources for %s:\n", fmt->name);
1371 if ((ret = avdevice_list_input_sources(fmt, NULL, opts, &device_list)) < 0) {
1372 av_log(NULL, AV_LOG_ERROR, "Cannot list sources: %s\n", av_err2str(ret));
1373 goto fail;
1374 }
1375
1376 print_device_list(device_list);
1377
1378 fail:
1379 avdevice_free_list_devices(&device_list);
1380 return ret;
1381}
1382
1383static int print_device_sinks(const AVOutputFormat *fmt, AVDictionary *opts)
1384{
1385 int ret;
1386 AVDeviceInfoList *device_list = NULL;
1387
1388 if (!fmt || !fmt->priv_class || !AV_IS_OUTPUT_DEVICE(fmt->priv_class->category))
1389 return AVERROR(EINVAL);
1390
1391 av_log(NULL, AV_LOG_ERROR, "Auto-detected sinks for %s:\n", fmt->name);
1392 if ((ret = avdevice_list_output_sinks(fmt, NULL, opts, &device_list)) < 0) {
1393 av_log(NULL, AV_LOG_ERROR, "Cannot list sinks: %s\n", av_err2str(ret));
1394 goto fail;
1395 }
1396
1397 print_device_list(device_list);
1398
1399 fail:
1400 avdevice_free_list_devices(&device_list);
1401 return ret;
1402}
1403
1404static int show_sinks_sources_parse_arg(const char *arg, char **dev, AVDictionary **opts)
1405{
1406 int ret;
1407 if (arg) {
1408 char *opts_str = NULL;
1409 av_assert0(dev && opts);
1410 *dev = av_strdup(arg);
1411 if (!*dev)
1412 return AVERROR(ENOMEM);
1413 if ((opts_str = strchr(*dev, ','))) {
1414 *(opts_str++) = '\0';
1415 if (opts_str[0] && ((ret = av_dict_parse_string(opts, opts_str, "=", ":", 0)) < 0)) {
1416 av_freep(dev);
1417 return ret;
1418 }
1419 }
1420 } else
1421 av_log(NULL, AV_LOG_ERROR, "\nDevice name is not provided.\n"
1422 "You can pass devicename[,opt1=val1[,opt2=val2...]] as an argument.\n\n");
1423 return 0;
1424}
1425
1426int show_sources(void *optctx, const char *opt, const char *arg)
1427{
1428 const AVInputFormat *fmt = NULL;
1429 char *dev = NULL;
1430 AVDictionary *opts = NULL;
1431 int ret = 0;
1432 int error_level = av_log_get_level();
1433
1434 av_log_set_level(AV_LOG_WARNING);
1435
1436 if ((ret = show_sinks_sources_parse_arg(arg, &dev, &opts)) < 0)
1437 goto fail;
1438
1439 do {
1440 fmt = av_input_audio_device_next(fmt);
1441 if (fmt) {
1442 if (!strcmp(fmt->name, "lavfi"))
1443 continue; //it's pointless to probe lavfi
1444 if (dev && !av_match_name(dev, fmt->name))
1445 continue;
1446 print_device_sources(fmt, opts);
1447 }
1448 } while (fmt);
1449 do {
1450 fmt = av_input_video_device_next(fmt);
1451 if (fmt) {
1452 if (dev && !av_match_name(dev, fmt->name))
1453 continue;
1454 print_device_sources(fmt, opts);
1455 }
1456 } while (fmt);
1457 fail:
1458 av_dict_free(&opts);
1459 av_free(dev);
1460 av_log_set_level(error_level);
1461 return ret;
1462}
1463
1464int show_sinks(void *optctx, const char *opt, const char *arg)
1465{
1466 const AVOutputFormat *fmt = NULL;
1467 char *dev = NULL;
1468 AVDictionary *opts = NULL;
1469 int ret = 0;
1470 int error_level = av_log_get_level();
1471
1472 av_log_set_level(AV_LOG_WARNING);
1473
1474 if ((ret = show_sinks_sources_parse_arg(arg, &dev, &opts)) < 0)
1475 goto fail;
1476
1477 do {
1478 fmt = av_output_audio_device_next(fmt);
1479 if (fmt) {
1480 if (dev && !av_match_name(dev, fmt->name))
1481 continue;
1482 print_device_sinks(fmt, opts);
1483 }
1484 } while (fmt);
1485 do {
1486 fmt = av_output_video_device_next(fmt);
1487 if (fmt) {
1488 if (dev && !av_match_name(dev, fmt->name))
1489 continue;
1490 print_device_sinks(fmt, opts);
1491 }
1492 } while (fmt);
1493 fail:
1494 av_dict_free(&opts);
1495 av_free(dev);
1496 av_log_set_level(error_level);
1497 return ret;
1498}
1499#endif /* CONFIG_AVDEVICE */
void exit_program(int ret)
void show_help_children(const AVClass *class, int flags)
int locate_option(int argc, char **argv, const OptionDef *options, const char *optname)
__thread int program_birth_year
__thread int hide_banner
#define GET_SAMPLE_RATE_NAME(rate)
#define GET_CODEC_NAME(id)
#define GET_PIX_FMT_NAME(pix_fmt)
#define GET_SAMPLE_FMT_NAME(sample_fmt)
void show_help_default_ffprobe(const char *opt, const char *arg)
void show_help_default_ffmpeg(const char *opt, const char *arg)
static int decode(InputStream *ist, AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *pkt)
int show_decoders(void *optctx, const char *opt, const char *arg)
int opt_loglevel(void *optctx, const char *opt, const char *arg)
int opt_cpuflags(void *optctx, const char *opt, const char *arg)
void ffmpegkit_log_callback_function(void *ptr, int level, const char *format, va_list vargs)
Definition ffmpegkit.c:446
int show_help(void *optctx, const char *opt, const char *arg)
static void log_callback_report(void *ptr, int level, const char *fmt, va_list vl)
static void show_help_bsf(const char *name)
static void show_help_codec(const char *name, int encoder)
int show_filters(void *optctx, const char *opt, const char *arg)
static void show_help_demuxer(const char *name)
int show_sample_fmts(void *optctx, const char *opt, const char *arg)
#define SHOW_CONFIG
static void print_codecs(int encoder)
show_muxdemuxers
@ SHOW_DEFAULT
@ SHOW_DEMUXERS
@ SHOW_MUXERS
#define SHOW_VERSION
int show_muxers(void *optctx, const char *opt, const char *arg)
#define INDENT
static int compare_codec_desc(const void *a, const void *b)
static __thread int report_file_level
int show_bsfs(void *optctx, const char *opt, const char *arg)
static void print_all_libs_info(int flags, int level)
__thread char * program_name
static void print_buildconf(int flags, int level)
#define PRINT_LIB_INFO(libname, LIBNAME, flags, level)
int show_dispositions(void *optctx, const char *opt, const char *arg)
int show_layouts(void *optctx, const char *opt, const char *arg)
int show_encoders(void *optctx, const char *opt, const char *arg)
int show_version(void *optctx, const char *opt, const char *arg)
static void expand_filename_template(AVBPrint *bp, const char *template, struct tm *tm)
static void show_help_protocol(const char *name)
__thread int warned_cfg
static char get_media_type_char(enum AVMediaType type)
int opt_cpucount(void *optctx, const char *opt, const char *arg)
void show_banner(int argc, char **argv, const OptionDef *options)
static void show_help_muxer(const char *name)
int show_license(void *optctx, const char *opt, const char *arg)
int show_codecs(void *optctx, const char *opt, const char *arg)
int show_buildconf(void *optctx, const char *opt, const char *arg)
static int show_formats_devices(void *optctx, const char *opt, const char *arg, int device_only, int muxdemuxers)
static __thread FILE * report_file
int show_devices(void *optctx, const char *opt, const char *arg)
void(* report_callback)(int, float, float, int64_t, double, double, double)
static void print_program_info(int flags, int level)
static unsigned get_codecs_sorted(const AVCodecDescriptor ***rcodecs)
#define SHOW_COPYRIGHT
int init_report(const char *env, FILE **file)
static void print_codec(const AVCodec *c)
int show_formats(void *optctx, const char *opt, const char *arg)
static const AVCodec * next_codec_for_id(enum AVCodecID id, void **iter, int encoder)
#define sws_isSupportedOutput(x)
static int is_device(const AVClass *avclass)
int show_protocols(void *optctx, const char *opt, const char *arg)
int opt_max_alloc(void *optctx, const char *opt, const char *arg)
int opt_report(void *optctx, const char *opt, const char *arg)
int show_colors(void *optctx, const char *opt, const char *arg)
#define PRINT_CODEC_SUPPORTED(codec, field, type, list_name, term, get_name)
int show_pix_fmts(void *optctx, const char *opt, const char *arg)
int show_demuxers(void *optctx, const char *opt, const char *arg)
#define sws_isSupportedInput(x)
static void print_codecs_for_id(enum AVCodecID id, int encoder)