|
@@ -160,7 +160,7 @@ void show_help_options(const OptionDef *options, const char *msg, int req_flags,
|
|
|
first = 0;
|
|
|
}
|
|
|
av_strlcpy(buf, po->name, sizeof(buf));
|
|
|
- if (po->flags & HAS_ARG) {
|
|
|
+ if (po->argname) {
|
|
|
av_strlcat(buf, " ", sizeof(buf));
|
|
|
av_strlcat(buf, po->argname, sizeof(buf));
|
|
|
}
|
|
@@ -806,6 +806,65 @@ int show_formats(const char *opt, const char *arg)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+#define PRINT_CODEC_SUPPORTED(codec, field, type, list_name, term, get_name) \
|
|
|
+ if (codec->field) { \
|
|
|
+ const type *p = c->field; \
|
|
|
+ \
|
|
|
+ printf(" Supported " list_name ":"); \
|
|
|
+ while (*p != term) { \
|
|
|
+ get_name(*p); \
|
|
|
+ printf(" %s", name); \
|
|
|
+ p++; \
|
|
|
+ } \
|
|
|
+ printf("\n"); \
|
|
|
+ } \
|
|
|
+
|
|
|
+static void print_codec(const AVCodec *c)
|
|
|
+{
|
|
|
+ int encoder = av_codec_is_encoder(c);
|
|
|
+
|
|
|
+ printf("%s %s [%s]:\n", encoder ? "Encoder" : "Decoder", c->name,
|
|
|
+ c->long_name ? c->long_name : "");
|
|
|
+
|
|
|
+ if (c->type == AVMEDIA_TYPE_VIDEO) {
|
|
|
+ printf(" Threading capabilities: ");
|
|
|
+ switch (c->capabilities & (CODEC_CAP_FRAME_THREADS |
|
|
|
+ CODEC_CAP_SLICE_THREADS)) {
|
|
|
+ case CODEC_CAP_FRAME_THREADS |
|
|
|
+ CODEC_CAP_SLICE_THREADS: printf("frame and slice"); break;
|
|
|
+ case CODEC_CAP_FRAME_THREADS: printf("frame"); break;
|
|
|
+ case CODEC_CAP_SLICE_THREADS: printf("slice"); break;
|
|
|
+ default: printf("no"); break;
|
|
|
+ }
|
|
|
+ printf("\n");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (c->supported_framerates) {
|
|
|
+ const AVRational *fps = c->supported_framerates;
|
|
|
+
|
|
|
+ printf(" Supported framerates:");
|
|
|
+ while (fps->num) {
|
|
|
+ printf(" %d/%d", fps->num, fps->den);
|
|
|
+ fps++;
|
|
|
+ }
|
|
|
+ printf("\n");
|
|
|
+ }
|
|
|
+ PRINT_CODEC_SUPPORTED(c, pix_fmts, enum PixelFormat, "pixel formats",
|
|
|
+ PIX_FMT_NONE, GET_PIX_FMT_NAME);
|
|
|
+ PRINT_CODEC_SUPPORTED(c, supported_samplerates, int, "sample rates", 0,
|
|
|
+ GET_SAMPLE_RATE_NAME);
|
|
|
+ PRINT_CODEC_SUPPORTED(c, sample_fmts, enum AVSampleFormat, "sample formats",
|
|
|
+ AV_SAMPLE_FMT_NONE, GET_SAMPLE_FMT_NAME);
|
|
|
+ PRINT_CODEC_SUPPORTED(c, channel_layouts, uint64_t, "channel layouts",
|
|
|
+ 0, GET_CH_LAYOUT_DESC);
|
|
|
+
|
|
|
+ if (c->priv_class) {
|
|
|
+ show_help_children(c->priv_class,
|
|
|
+ AV_OPT_FLAG_ENCODING_PARAM |
|
|
|
+ AV_OPT_FLAG_DECODING_PARAM);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static char get_media_type_char(enum AVMediaType type)
|
|
|
{
|
|
|
switch (type) {
|
|
@@ -1034,6 +1093,120 @@ int show_sample_fmts(const char *opt, const char *arg)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static void show_help_codec(const char *name, int encoder)
|
|
|
+{
|
|
|
+ const AVCodecDescriptor *desc;
|
|
|
+ const AVCodec *codec;
|
|
|
+
|
|
|
+ if (!name) {
|
|
|
+ av_log(NULL, AV_LOG_ERROR, "No codec name specified.\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ codec = encoder ? avcodec_find_encoder_by_name(name) :
|
|
|
+ avcodec_find_decoder_by_name(name);
|
|
|
+
|
|
|
+ if (codec)
|
|
|
+ print_codec(codec);
|
|
|
+ else if ((desc = avcodec_descriptor_get_by_name(name))) {
|
|
|
+ int printed = 0;
|
|
|
+
|
|
|
+ while ((codec = next_codec_for_id(desc->id, codec, encoder))) {
|
|
|
+ printed = 1;
|
|
|
+ print_codec(codec);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!printed) {
|
|
|
+ av_log(NULL, AV_LOG_ERROR, "Codec '%s' is known to FFmpeg, "
|
|
|
+ "but no %s for it are available. FFmpeg might need to be "
|
|
|
+ "recompiled with additional external libraries.\n",
|
|
|
+ name, encoder ? "encoders" : "decoders");
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ av_log(NULL, AV_LOG_ERROR, "Codec '%s' is not recognized by FFmpeg.\n",
|
|
|
+ name);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void show_help_demuxer(const char *name)
|
|
|
+{
|
|
|
+ const AVInputFormat *fmt = av_find_input_format(name);
|
|
|
+
|
|
|
+ if (!fmt) {
|
|
|
+ av_log(NULL, AV_LOG_ERROR, "Unknown format '%s'.\n", name);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ printf("Demuxer %s [%s]:\n", fmt->name, fmt->long_name);
|
|
|
+
|
|
|
+ if (fmt->extensions)
|
|
|
+ printf(" Common extensions: %s.\n", fmt->extensions);
|
|
|
+
|
|
|
+ if (fmt->priv_class)
|
|
|
+ show_help_children(fmt->priv_class, AV_OPT_FLAG_DECODING_PARAM);
|
|
|
+}
|
|
|
+
|
|
|
+static void show_help_muxer(const char *name)
|
|
|
+{
|
|
|
+ const AVCodecDescriptor *desc;
|
|
|
+ const AVOutputFormat *fmt = av_guess_format(name, NULL, NULL);
|
|
|
+
|
|
|
+ if (!fmt) {
|
|
|
+ av_log(NULL, AV_LOG_ERROR, "Unknown format '%s'.\n", name);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ printf("Muxer %s [%s]:\n", fmt->name, fmt->long_name);
|
|
|
+
|
|
|
+ if (fmt->extensions)
|
|
|
+ printf(" Common extensions: %s.\n", fmt->extensions);
|
|
|
+ if (fmt->mime_type)
|
|
|
+ printf(" Mime type: %s.\n", fmt->mime_type);
|
|
|
+ if (fmt->video_codec != AV_CODEC_ID_NONE &&
|
|
|
+ (desc = avcodec_descriptor_get(fmt->video_codec))) {
|
|
|
+ printf(" Default video codec: %s.\n", desc->name);
|
|
|
+ }
|
|
|
+ if (fmt->audio_codec != AV_CODEC_ID_NONE &&
|
|
|
+ (desc = avcodec_descriptor_get(fmt->audio_codec))) {
|
|
|
+ printf(" Default audio codec: %s.\n", desc->name);
|
|
|
+ }
|
|
|
+ if (fmt->subtitle_codec != AV_CODEC_ID_NONE &&
|
|
|
+ (desc = avcodec_descriptor_get(fmt->subtitle_codec))) {
|
|
|
+ printf(" Default subtitle codec: %s.\n", desc->name);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (fmt->priv_class)
|
|
|
+ show_help_children(fmt->priv_class, AV_OPT_FLAG_ENCODING_PARAM);
|
|
|
+}
|
|
|
+
|
|
|
+int show_help(const char *opt, const char *arg)
|
|
|
+{
|
|
|
+ char *topic, *par;
|
|
|
+ av_log_set_callback(log_callback_help);
|
|
|
+
|
|
|
+ topic = av_strdup(arg ? arg : "");
|
|
|
+ par = strchr(topic, '=');
|
|
|
+ if (par)
|
|
|
+ *par++ = 0;
|
|
|
+
|
|
|
+ if (!*topic) {
|
|
|
+ show_help_default(topic, par);
|
|
|
+ } else if (!strcmp(topic, "decoder")) {
|
|
|
+ show_help_codec(par, 0);
|
|
|
+ } else if (!strcmp(topic, "encoder")) {
|
|
|
+ show_help_codec(par, 1);
|
|
|
+ } else if (!strcmp(topic, "demuxer")) {
|
|
|
+ show_help_demuxer(par);
|
|
|
+ } else if (!strcmp(topic, "muxer")) {
|
|
|
+ show_help_muxer(par);
|
|
|
+ } else {
|
|
|
+ show_help_default(topic, par);
|
|
|
+ }
|
|
|
+
|
|
|
+ av_freep(&topic);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
int read_yesno(void)
|
|
|
{
|
|
|
int c = getchar();
|