From 7c1019499602e23141d7ca06fe6df5ea5ab3a240 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 11 Aug 2012 15:23:22 +0200 Subject: [PATCH] cmdutils: refactor -codecs option. Make it print a list of AVCodecDescriptors. Add new -decoders and -encoders options that print lists of decoders and encoders respectively. --- cmdutils.c | 174 ++++++++++++++++++++++------------- cmdutils.h | 12 +++ cmdutils_common_opts.h | 2 + doc/avtools-common-opts.texi | 25 ++--- 4 files changed, 131 insertions(+), 82 deletions(-) diff --git a/cmdutils.c b/cmdutils.c index ae59f7953c..b017490f3f 100644 --- a/cmdutils.c +++ b/cmdutils.c @@ -632,81 +632,123 @@ void show_formats(void) } } +static char get_media_type_char(enum AVMediaType type) +{ + switch (type) { + case AVMEDIA_TYPE_VIDEO: return 'V'; + case AVMEDIA_TYPE_AUDIO: return 'A'; + case AVMEDIA_TYPE_SUBTITLE: return 'S'; + default: return '?'; + } +} + +static const AVCodec *next_codec_for_id(enum AVCodecID id, const AVCodec *prev, + int encoder) +{ + while ((prev = av_codec_next(prev))) { + if (prev->id == id && + (encoder ? av_codec_is_encoder(prev) : av_codec_is_decoder(prev))) + return prev; + } + return NULL; +} + +static void print_codecs_for_id(enum AVCodecID id, int encoder) +{ + const AVCodec *codec = NULL; + + printf(" (%s: ", encoder ? "encoders" : "decoders"); + + while ((codec = next_codec_for_id(id, codec, encoder))) + printf("%s ", codec->name); + + printf(")"); +} + void show_codecs(void) { - AVCodec *p = NULL, *p2; - const char *last_name; + const AVCodecDescriptor *desc = NULL; + printf("Codecs:\n" - " D..... = Decoding supported\n" - " .E.... = Encoding supported\n" - " ..V... = Video codec\n" - " ..A... = Audio codec\n" - " ..S... = Subtitle codec\n" - " ...S.. = Supports draw_horiz_band\n" - " ....D. = Supports direct rendering method 1\n" - " .....T = Supports weird frame truncation\n" - " ------\n"); - last_name= "000"; - for (;;) { - int decode = 0; - int encode = 0; - int cap = 0; - const char *type_str; - - p2 = NULL; - while ((p = av_codec_next(p))) { - if ((p2 == NULL || strcmp(p->name, p2->name) < 0) && - strcmp(p->name, last_name) > 0) { - p2 = p; - decode = encode = cap = 0; + " D... = Decoding supported\n" + " .E.. = Encoding supported\n" + " ..V. = Video codec\n" + " ..A. = Audio codec\n" + " ..S. = Subtitle codec\n" + " ...I = Intra frame-only codec\n" + " -----\n"); + while ((desc = avcodec_descriptor_next(desc))) { + const AVCodec *codec = NULL; + + printf(avcodec_find_decoder(desc->id) ? "D" : "."); + printf(avcodec_find_encoder(desc->id) ? "E" : "."); + + printf("%c", get_media_type_char(desc->type)); + printf((desc->props & AV_CODEC_PROP_INTRA_ONLY) ? "I" : "."); + + printf(" %-20s %s", desc->name, desc->long_name ? desc->long_name : ""); + + /* print decoders/encoders when there's more than one or their + * names are different from codec name */ + while ((codec = next_codec_for_id(desc->id, codec, 0))) { + if (strcmp(codec->name, desc->name)) { + print_codecs_for_id(desc->id, 0); + break; } - if (p2 && strcmp(p->name, p2->name) == 0) { - if (av_codec_is_decoder(p)) - decode = 1; - if (av_codec_is_encoder(p)) - encode = 1; - cap |= p->capabilities; + } + codec = NULL; + while ((codec = next_codec_for_id(desc->id, codec, 1))) { + if (strcmp(codec->name, desc->name)) { + print_codecs_for_id(desc->id, 1); + break; } } - if (p2 == NULL) - break; - last_name = p2->name; - switch (p2->type) { - case AVMEDIA_TYPE_VIDEO: - type_str = "V"; - break; - case AVMEDIA_TYPE_AUDIO: - type_str = "A"; - break; - case AVMEDIA_TYPE_SUBTITLE: - type_str = "S"; - break; - default: - type_str = "?"; - break; - } - printf(" %s%s%s%s%s%s %-15s %s", - decode ? "D" : (/* p2->decoder ? "d" : */ " "), - encode ? "E" : " ", - type_str, - cap & CODEC_CAP_DRAW_HORIZ_BAND ? "S" : " ", - cap & CODEC_CAP_DR1 ? "D" : " ", - cap & CODEC_CAP_TRUNCATED ? "T" : " ", - p2->name, - p2->long_name ? p2->long_name : ""); -#if 0 - if (p2->decoder && decode == 0) - printf(" use %s for decoding", p2->decoder->name); -#endif printf("\n"); } - printf("\n"); - printf("Note, the names of encoders and decoders do not always match, so there are\n" - "several cases where the above table shows encoder only or decoder only entries\n" - "even though both encoding and decoding are supported. For example, the h263\n" - "decoder corresponds to the h263 and h263p encoders, for file formats it is even\n" - "worse.\n"); +} + +static void print_codecs(int encoder) +{ + const AVCodecDescriptor *desc = NULL; + + printf("%s:\n" + " V... = Video\n" + " A... = Audio\n" + " S... = Subtitle\n" + " .F.. = Frame-level multithreading\n" + " ..S. = Slice-level multithreading\n" + " ...X = Codec is experimental\n" + " ---\n", + encoder ? "Encoders" : "Decoders"); + while ((desc = avcodec_descriptor_next(desc))) { + const AVCodec *codec = NULL; + + while ((codec = next_codec_for_id(desc->id, codec, encoder))) { + printf("%c", get_media_type_char(desc->type)); + printf((codec->capabilities & CODEC_CAP_FRAME_THREADS) ? "F" : "."); + printf((codec->capabilities & CODEC_CAP_SLICE_THREADS) ? "S" : "."); + printf((codec->capabilities & CODEC_CAP_EXPERIMENTAL) ? "X" : "."); + + printf(" %-20s %s", codec->name, codec->long_name ? codec->long_name : ""); + if (strcmp(codec->name, desc->name)) + printf(" (codec %s)", desc->name); + + printf("\n"); + } + } +} + +int show_decoders(const char *opt, const char *arg) +{ + print_codecs(0); + return 0; +} + +int show_encoders(const char *opt, const char *arg) +{ + print_codecs(1); + return 0; } void show_bsfs(void) diff --git a/cmdutils.h b/cmdutils.h index f013c2a33f..d787496a36 100644 --- a/cmdutils.h +++ b/cmdutils.h @@ -278,6 +278,18 @@ void show_formats(void); */ void show_codecs(void); +/** + * Print a listing containing all the decoders supported by the + * program. + */ +int show_decoders(const char *opt, const char *arg); + +/** + * Print a listing containing all the encoders supported by the + * program. + */ +int show_encoders(const char *opt, const char *arg); + /** * Print a listing containing all the filters supported by the * program. diff --git a/cmdutils_common_opts.h b/cmdutils_common_opts.h index 1158afab99..d9a09c0c19 100644 --- a/cmdutils_common_opts.h +++ b/cmdutils_common_opts.h @@ -6,6 +6,8 @@ { "version", OPT_EXIT, {(void*)show_version}, "show version" }, { "formats" , OPT_EXIT, {(void*)show_formats }, "show available formats" }, { "codecs" , OPT_EXIT, {(void*)show_codecs }, "show available codecs" }, + { "decoders" , OPT_EXIT, {(void*)show_decoders }, "show available decoders" }, + { "encoders" , OPT_EXIT, {(void*)show_encoders }, "show available encoders" }, { "bsfs" , OPT_EXIT, {(void*)show_bsfs }, "show available bit stream filters" }, { "protocols", OPT_EXIT, {(void*)show_protocols}, "show available protocols" }, { "filters", OPT_EXIT, {(void*)show_filters }, "show available filters" }, diff --git a/doc/avtools-common-opts.texi b/doc/avtools-common-opts.texi index 0be9cf0634..375e4b041c 100644 --- a/doc/avtools-common-opts.texi +++ b/doc/avtools-common-opts.texi @@ -69,23 +69,16 @@ Encoding available @end table @item -codecs -Show available codecs. +Show all codecs known to libavcodec. -The fields preceding the codec names have the following meanings: -@table @samp -@item D -Decoding available -@item E -Encoding available -@item V/A/S -Video/audio/subtitle codec -@item S -Codec supports slices -@item D -Codec supports direct rendering -@item T -Codec can handle input truncated at random locations instead of only at frame boundaries -@end table +Note that the term 'codec' is used throughout this documentation as a shortcut +for what is more correctly called a media bitstream format. + +@item -decoders +Show available decoders. + +@item -encoders +Show all available encoders. @item -bsfs Show available bitstream filters.