[FFmpeg-devel] [PATCH 2/3] cmdutils: use new iteration APIs

Josh de Kock josh at itanimul.li
Sun Feb 18 19:58:18 EET 2018


---
 fftools/cmdutils.c | 239 +++++++++++++++++++++++++----------------------------
 1 file changed, 112 insertions(+), 127 deletions(-)

diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c
index 0c7d13c..c341f8f 100644
--- a/fftools/cmdutils.c
+++ b/fftools/cmdutils.c
@@ -1250,19 +1250,11 @@ int show_license(void *optctx, const char *opt, const char *arg)
     return 0;
 }
 
-static int is_device(const AVClass *avclass)
-{
-    if (!avclass)
-        return 0;
-    return AV_IS_INPUT_DEVICE(avclass->category) || AV_IS_OUTPUT_DEVICE(avclass->category);
-}
-
 static int show_formats_devices(void *optctx, const char *opt, const char *arg, int device_only, int muxdemuxers)
 {
-    AVInputFormat *ifmt  = NULL;
-    AVOutputFormat *ofmt = NULL;
+    const AVInputFormat *ifmt  = NULL;
+    const AVOutputFormat *ofmt = NULL;
     const char *last_name;
-    int is_dev;
 
     printf("%s\n"
            " D. = Demuxing supported\n"
@@ -1270,46 +1262,38 @@ static int show_formats_devices(void *optctx, const char *opt, const char *arg,
            " --\n", device_only ? "Devices:" : "File formats:");
     last_name = "000";
     for (;;) {
-        int decode = 0;
-        int encode = 0;
+        int is_ifmt = 0;
+        int is_ofmt = 0;
         const char *name      = NULL;
         const char *long_name = NULL;
 
-        if (muxdemuxers !=SHOW_DEMUXERS) {
-            while ((ofmt = av_oformat_next(ofmt))) {
-                is_dev = is_device(ofmt->priv_class);
-                if (!is_dev && device_only)
-                    continue;
-                if ((!name || strcmp(ofmt->name, name) < 0) &&
-                    strcmp(ofmt->name, last_name) > 0) {
-                    name      = ofmt->name;
-                    long_name = ofmt->long_name;
-                    encode    = 1;
-                }
-            }
-        }
-        if (muxdemuxers != SHOW_MUXERS) {
-            while ((ifmt = av_iformat_next(ifmt))) {
-                is_dev = is_device(ifmt->priv_class);
-                if (!is_dev && device_only)
-                    continue;
-                if ((!name || strcmp(ifmt->name, name) < 0) &&
-                    strcmp(ifmt->name, last_name) > 0) {
-                    name      = ifmt->name;
-                    long_name = ifmt->long_name;
-                    encode    = 0;
-                }
-                if (name && strcmp(ifmt->name, name) == 0)
-                    decode = 1;
-            }
-        }
+#define x(func, type, condition) do {                           \
+        void *i = 0;                                            \
+        if (condition) {                                        \
+            while ((type = func(&i))) {                         \
+                if ((!name || strcmp(type->name, name) < 0) &&  \
+                    strcmp(type->name, last_name) > 0) {        \
+                    name      = type->name;                     \
+                    long_name = type->long_name;                \
+                    is_ ## type = 1;                            \
+                }                                               \
+            }                                                   \
+        } } while(0)
+
+        x(av_muxer_iterate, ofmt, muxdemuxers != SHOW_DEMUXERS && !device_only);
+        x(av_demuxer_iterate, ifmt, muxdemuxers != SHOW_MUXERS && !device_only);
+#if CONFIG_AVDEVICE
+        x(av_outdev_iterate, ofmt, muxdemuxers != SHOW_DEMUXERS);
+        x(av_indev_iterate, ifmt, muxdemuxers != SHOW_MUXERS);
+#endif
+#undef x
         if (!name)
             break;
         last_name = name;
 
         printf(" %s%s %-15s %s\n",
-               decode ? "D" : " ",
-               encode ? "E" : " ",
+               is_ifmt ? "D" : " ",
+               is_ofmt ? "E" : " ",
                name,
             long_name ? long_name:" ");
     }
@@ -1439,15 +1423,45 @@ static char get_media_type_char(enum AVMediaType type)
     }
 }
 
-static const AVCodec *next_codec_for_id(enum AVCodecID id, const AVCodec *prev,
-                                        int encoder)
+
+static int compare_codec(const void *a, const void *b)
+{
+    const AVCodec * const *ca = a;
+    const AVCodec * const *cb = b;
+
+    return strcmp((*ca)->name, (*cb)->name);
+}
+
+static unsigned get_codecs_sorted(enum AVCodecID id, const AVCodec ***rcodecs, 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;
+    const AVCodec *codec = NULL;
+    const AVCodec **codecs;
+    unsigned nb_codecs = 0, i = 0;
+    void *opaque = 0;
+
+    while ((codec = av_codec_iterate(&opaque))) {
+        if (codec->id == id &&
+            (encoder ? av_codec_is_encoder(codec) : av_codec_is_decoder(codec)))
+        nb_codecs++;
+    }
+
+    if (!(codecs = av_calloc(nb_codecs, sizeof(*codecs)))) {
+        av_log(NULL, AV_LOG_ERROR, "Out of memory\n");
+        exit_program(1);
+    }
+
+    opaque = 0;
+    while ((codec = av_codec_iterate(&opaque))) {
+        if (codec->id == id &&
+            (encoder ? av_codec_is_encoder(codec) : av_codec_is_decoder(codec)))
+            codecs[i++] = codec;
     }
-    return NULL;
+
+    av_assert0(i == nb_codecs);
+    qsort(codecs, nb_codecs, sizeof(*codecs), compare_codec);
+    *rcodecs = codecs;
+
+    return nb_codecs;
 }
 
 static int compare_codec_desc(const void *a, const void *b)
@@ -1459,7 +1473,7 @@ static int compare_codec_desc(const void *a, const void *b)
            strcmp((*da)->name, (*db)->name);
 }
 
-static unsigned get_codecs_sorted(const AVCodecDescriptor ***rcodecs)
+static unsigned get_codec_descs_sorted(const AVCodecDescriptor ***rcodecs)
 {
     const AVCodecDescriptor *desc = NULL;
     const AVCodecDescriptor **codecs;
@@ -1480,22 +1494,10 @@ static unsigned get_codecs_sorted(const AVCodecDescriptor ***rcodecs)
     return nb_codecs;
 }
 
-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(")");
-}
-
 int show_codecs(void *optctx, const char *opt, const char *arg)
 {
     const AVCodecDescriptor **codecs;
-    unsigned i, nb_codecs = get_codecs_sorted(&codecs);
+    unsigned i, nb_codecs = get_codec_descs_sorted(&codecs);
 
     printf("Codecs:\n"
            " D..... = Decoding supported\n"
@@ -1509,7 +1511,6 @@ int show_codecs(void *optctx, const char *opt, const char *arg)
            " -------\n");
     for (i = 0; i < nb_codecs; i++) {
         const AVCodecDescriptor *desc = codecs[i];
-        const AVCodec *codec = NULL;
 
         if (strstr(desc->name, "_deprecated"))
             continue;
@@ -1525,22 +1526,22 @@ int show_codecs(void *optctx, const char *opt, const char *arg)
 
         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;
+        for (int encoder = 0; encoder < 2; encoder++) {
+            const AVCodec **codec_codecs;
+            const int nb_codec_codecs = get_codecs_sorted(desc->id, &codec_codecs, encoder);
+            if (nb_codec_codecs == 1 && !strcmp(desc->name, codec_codecs[0]->name)) {
+                av_free(codec_codecs);
+                continue;
             }
-        }
-        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 (nb_codec_codecs) {
+                printf(" (%s: ", encoder ? "encoders" : "decoders");
+                for (int j = 0; j < nb_codec_codecs; j++) {
+                    printf("%s ", codec_codecs[j]->name);
+                }
+                printf(")");
             }
+            av_free(codec_codecs);
         }
-
         printf("\n");
     }
     av_free(codecs);
@@ -1550,7 +1551,7 @@ int show_codecs(void *optctx, const char *opt, const char *arg)
 static void print_codecs(int encoder)
 {
     const AVCodecDescriptor **codecs;
-    unsigned i, nb_codecs = get_codecs_sorted(&codecs);
+    unsigned i, nb_codecs = get_codec_descs_sorted(&codecs);
 
     printf("%s:\n"
            " V..... = Video\n"
@@ -1566,8 +1567,11 @@ static void print_codecs(int encoder)
     for (i = 0; i < nb_codecs; i++) {
         const AVCodecDescriptor *desc = codecs[i];
         const AVCodec *codec = NULL;
+        const AVCodec **codec_codecs;
+        const int nb_codec_codecs = get_codecs_sorted(desc->id, &codec_codecs, encoder);
 
-        while ((codec = next_codec_for_id(desc->id, codec, encoder))) {
+        for (int j = 0; j < nb_codec_codecs; j++) {
+            codec = codec_codecs[j];
             printf(" %c", get_media_type_char(desc->type));
             printf((codec->capabilities & AV_CODEC_CAP_FRAME_THREADS) ? "F" : ".");
             printf((codec->capabilities & AV_CODEC_CAP_SLICE_THREADS) ? "S" : ".");
@@ -1581,6 +1585,7 @@ static void print_codecs(int encoder)
 
             printf("\n");
         }
+        av_free(codec_codecs);
     }
     av_free(codecs);
 }
@@ -1628,6 +1633,7 @@ int show_filters(void *optctx, const char *opt, const char *arg)
 {
 #if CONFIG_AVFILTER
     const AVFilter *filter = NULL;
+    void *opaque = 0;
     char descr[64], *descr_cur;
     int i, j;
     const AVFilterPad *pad;
@@ -1640,7 +1646,7 @@ int show_filters(void *optctx, const char *opt, const char *arg)
            "  V = Video input/output\n"
            "  N = Dynamic number and/or type of input/output\n"
            "  | = Source or sink filter\n");
-    while ((filter = avfilter_next(filter))) {
+    while ((filter = av_filter_iterate(&opaque))) {
         descr_cur = descr;
         for (i = 0; i < 2; i++) {
             if (i) {
@@ -1771,19 +1777,17 @@ static void show_help_codec(const char *name, int encoder)
     if (codec)
         print_codec(codec);
     else if ((desc = avcodec_descriptor_get_by_name(name))) {
-        int printed = 0;
+        const AVCodec **codec_codecs;
 
-        while ((codec = next_codec_for_id(desc->id, codec, encoder))) {
-            printed = 1;
-            print_codec(codec);
-        }
-
-        if (!printed) {
+        if (get_codecs_sorted(desc->id, &codec_codecs, encoder)) {
+            print_codec(codec_codecs[0]);
+        } else {
             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");
         }
+        av_free(codec_codecs);
     } else {
         av_log(NULL, AV_LOG_ERROR, "Codec '%s' is not recognized by FFmpeg.\n",
                name);
@@ -2116,7 +2120,7 @@ double get_rotation(AVStream *st)
 }
 
 #if CONFIG_AVDEVICE
-static int print_device_sources(AVInputFormat *fmt, AVDictionary *opts)
+static int print_device_sources(const AVInputFormat *fmt, AVDictionary *opts)
 {
     int ret, i;
     AVDeviceInfoList *device_list = NULL;
@@ -2131,7 +2135,7 @@ static int print_device_sources(AVInputFormat *fmt, AVDictionary *opts)
         goto fail;
     }
 
-    if ((ret = avdevice_list_input_sources(fmt, NULL, opts, &device_list)) < 0) {
+    if ((ret = avdevice_list_input_sources((AVInputFormat*)fmt, NULL, opts, &device_list)) < 0) {
         printf("Cannot list sources.\n");
         goto fail;
     }
@@ -2146,7 +2150,7 @@ static int print_device_sources(AVInputFormat *fmt, AVDictionary *opts)
     return ret;
 }
 
-static int print_device_sinks(AVOutputFormat *fmt, AVDictionary *opts)
+static int print_device_sinks(const AVOutputFormat *fmt, AVDictionary *opts)
 {
     int ret, i;
     AVDeviceInfoList *device_list = NULL;
@@ -2161,7 +2165,7 @@ static int print_device_sinks(AVOutputFormat *fmt, AVDictionary *opts)
         goto fail;
     }
 
-    if ((ret = avdevice_list_output_sinks(fmt, NULL, opts, &device_list)) < 0) {
+    if ((ret = avdevice_list_output_sinks((AVOutputFormat*)fmt, NULL, opts, &device_list)) < 0) {
         printf("Cannot list sinks.\n");
         goto fail;
     }
@@ -2200,7 +2204,8 @@ static int show_sinks_sources_parse_arg(const char *arg, char **dev, AVDictionar
 
 int show_sources(void *optctx, const char *opt, const char *arg)
 {
-    AVInputFormat *fmt = NULL;
+    const AVInputFormat *fmt = NULL;
+    void *i = 0;
     char *dev = NULL;
     AVDictionary *opts = NULL;
     int ret = 0;
@@ -2211,24 +2216,14 @@ int show_sources(void *optctx, const char *opt, const char *arg)
     if ((ret = show_sinks_sources_parse_arg(arg, &dev, &opts)) < 0)
         goto fail;
 
-    do {
-        fmt = av_input_audio_device_next(fmt);
-        if (fmt) {
-            if (!strcmp(fmt->name, "lavfi"))
-                continue; //it's pointless to probe lavfi
-            if (dev && !av_match_name(dev, fmt->name))
-                continue;
-            print_device_sources(fmt, opts);
-        }
-    } while (fmt);
-    do {
-        fmt = av_input_video_device_next(fmt);
-        if (fmt) {
-            if (dev && !av_match_name(dev, fmt->name))
-                continue;
-            print_device_sources(fmt, opts);
-        }
-    } while (fmt);
+    while ((fmt = av_indev_iterate(&i))) {
+        if (!strcmp(fmt->name, "lavfi"))
+            continue; //it's pointless to probe lavfi
+        if (dev && !av_match_name(dev, fmt->name))
+            continue;
+        print_device_sources(fmt, opts);
+    }
+
   fail:
     av_dict_free(&opts);
     av_free(dev);
@@ -2238,7 +2233,8 @@ int show_sources(void *optctx, const char *opt, const char *arg)
 
 int show_sinks(void *optctx, const char *opt, const char *arg)
 {
-    AVOutputFormat *fmt = NULL;
+    const AVOutputFormat *fmt = NULL;
+    void *i = 0;
     char *dev = NULL;
     AVDictionary *opts = NULL;
     int ret = 0;
@@ -2249,22 +2245,11 @@ int show_sinks(void *optctx, const char *opt, const char *arg)
     if ((ret = show_sinks_sources_parse_arg(arg, &dev, &opts)) < 0)
         goto fail;
 
-    do {
-        fmt = av_output_audio_device_next(fmt);
-        if (fmt) {
-            if (dev && !av_match_name(dev, fmt->name))
-                continue;
-            print_device_sinks(fmt, opts);
-        }
-    } while (fmt);
-    do {
-        fmt = av_output_video_device_next(fmt);
-        if (fmt) {
-            if (dev && !av_match_name(dev, fmt->name))
-                continue;
-            print_device_sinks(fmt, opts);
-        }
-    } while (fmt);
+    while ((fmt = av_outdev_iterate(&i))) {
+        if (dev && !av_match_name(dev, fmt->name))
+            continue;
+        print_device_sinks(fmt, opts);
+    }
   fail:
     av_dict_free(&opts);
     av_free(dev);
-- 
2.7.4



More information about the ffmpeg-devel mailing list