diff mbox

[FFmpeg-devel,v3,3/7] cmdutils: use new iteration APIs

Message ID 20180319193541.2977-4-josh@itanimul.li
State Superseded
Headers show

Commit Message

Josh Dekker March 19, 2018, 7:35 p.m. UTC
---
 fftools/cmdutils.c | 239 +++++++++++++++++++++++++----------------------------
 1 file changed, 112 insertions(+), 127 deletions(-)

Comments

Nicolas George March 19, 2018, 8:48 p.m. UTC | #1
Josh de Kock (2018-03-19):
> +        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

Nack.

If applications need to do that kind of stunt to enumerate devices, they
will not bother doing it, thus losing features in a few unusual cases
and reducing the testing coverage of lavd by users.

Since indevs and demuxers behave the same way and outdevs and muxers
ditto, the default API need to return them all once.

Regards,
diff mbox

Patch

diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c
index 708a849f51..2da313cc0a 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);
@@ -2132,7 +2136,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;
@@ -2147,7 +2151,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;
     }
@@ -2162,7 +2166,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;
@@ -2177,7 +2181,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;
     }
@@ -2216,7 +2220,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;
@@ -2227,24 +2232,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);
@@ -2254,7 +2249,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;
@@ -2265,22 +2261,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);