[FFmpeg-devel] [PATCH 2/5] fftools/cmdutils: Print filter input/output formats in help output

Soft Works softworkz at hotmail.com
Wed Oct 13 07:49:57 EEST 2021


Exmaple command: ffmpeg -h filters=overlay

Output:

Filter overlay
  Overlay a video source on top of the input.
    slice threading supported
    Inputs:
       #0: main (video) [yuv420p, yuvj420p, yuva420p, nv12, nv21]
       #1: overlay (video) [yuva420p]
    Outputs:
       #0: default (video) [yuv420p, yuvj420p, yuva420p, nv12, nv21]
overlay AVOptions:
  x [...]

Signed-off-by: softworkz <softworkz at hotmail.com>
---
 fftools/cmdutils.c | 89 +++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 84 insertions(+), 5 deletions(-)

diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c
index aa706c33ab..a112998574 100644
--- a/fftools/cmdutils.c
+++ b/fftools/cmdutils.c
@@ -33,6 +33,7 @@
 #include "compat/va_copy.h"
 #include "libavformat/avformat.h"
 #include "libavfilter/avfilter.h"
+#include <libavfilter/formats.h>
 #include "libavdevice/avdevice.h"
 #include "libswscale/swscale.h"
 #include "libswresample/swresample.h"
@@ -1922,11 +1923,38 @@ static void show_help_muxer(const char *name)
 }
 
 #if CONFIG_AVFILTER
+static void print_link_formats(enum AVMediaType mediaType, AVFilterFormats* formats)
+{
+    if (formats == NULL)
+        return;
+
+    printf(" [");
+
+    for (unsigned i = 0; i < formats->nb_formats; i++) {
+        if (formats->formats[i] >= 0) {
+            if (i > 0)
+                printf(", ");
+            if (mediaType == AVMEDIA_TYPE_VIDEO) {
+                printf("%s", av_get_pix_fmt_name(formats->formats[i]));
+            } else if (mediaType == AVMEDIA_TYPE_AUDIO) {
+                printf("%s", av_get_sample_fmt_name(formats->formats[i]));
+            // TODO: Uncomment once subtitle filtering is added
+            ////} else if (mediaType == AVMEDIA_TYPE_SUBTITLE) {
+            ////    printf("%s", av_get_subtitle_fmt_name(formats->formats[i]));
+            }
+        }
+    }
+
+    printf("]");
+}
+
 static void show_help_filter(const char *name)
 {
 #if CONFIG_AVFILTER
     const AVFilter *f = avfilter_get_by_name(name);
-    int i, count;
+    unsigned i, count;
+    int got_formats = 0;
+    AVFilterContext *filter_context;
 
     if (!name) {
         av_log(NULL, AV_LOG_ERROR, "No filter name specified.\n");
@@ -1943,12 +1971,50 @@ static void show_help_filter(const char *name)
     if (f->flags & AVFILTER_FLAG_SLICE_THREADS)
         printf("    slice threading supported\n");
 
+    filter_context = avfilter_alloc(f, "filter");
+    if (!filter_context) {
+        av_log(NULL, AV_LOG_ERROR, "Failed create filtercontext\n");
+        return;
+    }
+
+    if (filter_context->nb_outputs == 0) {
+        filter_context->outputs= av_calloc(1, sizeof(AVFilterLink*));
+        filter_context->outputs[0] = (AVFilterLink *)av_mallocz(sizeof(AVFilterLink));
+    }
+
+    if (filter_context->nb_inputs == 0) {
+        filter_context->inputs= av_calloc(1, sizeof(AVFilterLink*));
+        filter_context->inputs[0] = (AVFilterLink *)av_mallocz(sizeof(AVFilterLink));
+    }
+
+    for (i = 0; i < filter_context->nb_inputs; i++)
+        filter_context->inputs[i] = (AVFilterLink *)av_mallocz(sizeof(AVFilterLink));
+    
+    for (i = 0; i < filter_context->nb_outputs; i++)
+        filter_context->outputs[i] = (AVFilterLink *)av_mallocz(sizeof(AVFilterLink));
+
+    if (filter_context->filter->nb_inputs)
+        filter_context->inputs[0]->type = avfilter_pad_get_type(f->inputs, 0);
+
+    if (filter_context->filter->nb_outputs)
+        filter_context->outputs[0]->type = avfilter_pad_get_type(f->outputs, 0);
+
+    if (filter_context->nb_inputs > 0 || filter_context->nb_outputs > 0)
+        got_formats = !avfilter_query_formats(filter_context);
+
     printf("    Inputs:\n");
     count = avfilter_filter_pad_count(f, 0);
     for (i = 0; i < count; i++) {
-        printf("       #%d: %s (%s)\n", i, avfilter_pad_get_name(f->inputs, i),
-               media_type_string(avfilter_pad_get_type(f->inputs, i)));
+        const enum AVMediaType media_type = avfilter_pad_get_type(f->inputs, i);
+
+        printf("       #%d: %s (%s)", i, avfilter_pad_get_name(f->inputs, i),
+               media_type_string(media_type));
+
+        if (got_formats && (i < filter_context->nb_inputs))
+            print_link_formats(media_type, filter_context->inputs[i]->outcfg.formats);
+        printf("\n");
     }
+
     if (f->flags & AVFILTER_FLAG_DYNAMIC_INPUTS)
         printf("        dynamic (depending on the options)\n");
     else if (!count)
@@ -1957,8 +2023,13 @@ static void show_help_filter(const char *name)
     printf("    Outputs:\n");
     count = avfilter_filter_pad_count(f, 1);
     for (i = 0; i < count; i++) {
-        printf("       #%d: %s (%s)\n", i, avfilter_pad_get_name(f->outputs, i),
-               media_type_string(avfilter_pad_get_type(f->outputs, i)));
+        const enum AVMediaType media_type = avfilter_pad_get_type(f->outputs, i);
+        printf("       #%d: %s (%s)", i, avfilter_pad_get_name(f->outputs, i),
+               media_type_string(media_type));
+ 
+        if (got_formats && i < filter_context->nb_outputs)
+            print_link_formats(media_type, filter_context->outputs[i]->incfg.formats);
+        printf("\n");
     }
     if (f->flags & AVFILTER_FLAG_DYNAMIC_OUTPUTS)
         printf("        dynamic (depending on the options)\n");
@@ -1970,6 +2041,14 @@ static void show_help_filter(const char *name)
                                           AV_OPT_FLAG_AUDIO_PARAM);
     if (f->flags & AVFILTER_FLAG_SUPPORT_TIMELINE)
         printf("This filter has support for timeline through the 'enable' option.\n");
+
+    if (filter_context->nb_inputs == 0)
+        filter_context->nb_inputs = 1;
+    if (filter_context->nb_outputs == 0)
+        filter_context->nb_outputs = 1;
+
+    avfilter_free(filter_context);
+
 #else
     av_log(NULL, AV_LOG_ERROR, "Build without libavfilter; "
            "can not to satisfy request\n");
-- 
2.30.2.windows.1



More information about the ffmpeg-devel mailing list