[FFmpeg-devel] [PATCH] lavfi: dump debug graph when merging failed.

Nicolas George george at nsup.org
Thu Nov 28 15:02:43 CET 2013


Signed-off-by: Nicolas George <george at nsup.org>
---
 libavfilter/avfiltergraph.c |   4 +-
 libavfilter/graphdump.c     | 182 ++++++++++++++++++++++++++++++++++++++++++++
 libavfilter/internal.h      |   5 ++
 3 files changed, 190 insertions(+), 1 deletion(-)


Note: this is somewhat redundant with the avfilter_graph_dump() API, but not
so much: must of avfilter_graph_dump()'s code comes from an attempt at
ASCII-art dump, that actually gives quite bad results, while most of this
code deals with format negotiation lists.


diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c
index 1fb83c4..a11cdeb 100644
--- a/libavfilter/avfiltergraph.c
+++ b/libavfilter/avfiltergraph.c
@@ -1098,8 +1098,10 @@ static int graph_config_formats(AVFilterGraph *graph, AVClass *log_ctx)
     swap_samplerates(graph);
     swap_channel_layouts(graph);
 
-    if ((ret = pick_formats(graph)) < 0)
+    if ((ret = pick_formats(graph)) < 0) {
+        ff_dump_graph_debug(graph);
         return ret;
+    }
 
     return 0;
 }
diff --git a/libavfilter/graphdump.c b/libavfilter/graphdump.c
index 1b59321..6795a2f 100644
--- a/libavfilter/graphdump.c
+++ b/libavfilter/graphdump.c
@@ -26,6 +26,8 @@
 #include "libavutil/pixdesc.h"
 #include "avfilter.h"
 #include "avfiltergraph.h"
+#include "formats.h"
+#include "internal.h"
 
 static int print_link_prop(AVBPrint *buf, AVFilterLink *link)
 {
@@ -162,3 +164,183 @@ char *avfilter_graph_dump(AVFilterGraph *graph, const char *options)
     av_bprint_finalize(&buf, &dump);
     return dump;
 }
+
+static int ddump_find_ref(AVBPrint *bp, AVFilterGraph *graph,
+                          void *ref, void *self,
+                          size_t off_in, size_t off_out)
+{
+    unsigned i, j;
+
+    if (ref == self)
+        return 0;
+    for (i = 0; i < graph->nb_filters; i++) {
+        AVFilterContext *f = graph->filters[i];
+        for (j = 0; j < f->nb_inputs; j++) {
+            if (ref == (char *)f->inputs[j] + off_out) {
+                av_bprintf(bp, "{ same as i%d:%d }", i, j);
+                return 1;
+            }
+        }
+        for (j = 0; j < f->nb_outputs; j++) {
+            if (ref == (char *)f->outputs[j] + off_in) {
+                av_bprintf(bp, "{ same as o%d:%d }", i, j);
+                return 1;
+            }
+        }
+    }
+    return 0;
+}
+
+static void ddump_pixel_format(AVBPrint *bp, AVFilterGraph *graph,
+                               enum AVPixelFormat fmt,
+                               AVFilterFormats **fmtsp)
+{
+    AVFilterFormats *fmts = *fmtsp;
+    unsigned i;
+
+    if (fmts) {
+        if (!ddump_find_ref(bp, graph, fmts->refs[0], fmtsp,
+                            offsetof(AVFilterLink,  in_formats),
+                            offsetof(AVFilterLink, out_formats))) {
+            for (i = 0; i < fmts->nb_formats; i++)
+                av_bprintf(bp, " %c %s", i ? '|' : '{',
+                           av_get_pix_fmt_name(fmts->formats[i]));
+            av_bprintf(bp, " }");
+        }
+    } else {
+        av_bprintf(bp, "%s", av_get_pix_fmt_name(fmt));
+    }
+}
+
+static void ddump_sample_format(AVBPrint *bp, AVFilterGraph *graph,
+                                enum AVSampleFormat fmt,
+                                AVFilterFormats **fmtsp)
+{
+    AVFilterFormats *fmts = *fmtsp;
+    unsigned i;
+
+    if (fmts) {
+        if (!ddump_find_ref(bp, graph, fmts->refs[0], fmtsp,
+                            offsetof(AVFilterLink,  in_formats),
+                            offsetof(AVFilterLink, out_formats))) {
+            for (i = 0; i < fmts->nb_formats; i++)
+                av_bprintf(bp, " %c %s", i ? '|' : '{',
+                           av_get_sample_fmt_name(fmts->formats[i]));
+            av_bprintf(bp, " }");
+        }
+    } else {
+        av_bprintf(bp, "%s", av_get_sample_fmt_name(fmt));
+    }
+}
+
+static void ddump_sample_freq(AVBPrint *bp, AVFilterGraph *graph,
+                              int rate, AVFilterFormats **ratesp)
+{
+    AVFilterFormats *rates = *ratesp;
+    unsigned i;
+
+    if (rates) {
+        if (!ddump_find_ref(bp, graph, rates->refs[0], ratesp,
+                            offsetof(AVFilterLink,  in_samplerates),
+                            offsetof(AVFilterLink, out_samplerates))) {
+            for (i = 0; i < rates->nb_formats; i++)
+                av_bprintf(bp, " %c %d", i ? '|' : '{',
+                           rates->formats[i]);
+            av_bprintf(bp, " }");
+        }
+    } else {
+        av_bprintf(bp, "%d Hz", rate);
+    }
+}
+
+static void ddump_channels(AVBPrint *bp, AVFilterGraph *graph,
+                           unsigned channels, uint64_t layout,
+                           AVFilterChannelLayouts **layoutsp)
+{
+    AVFilterChannelLayouts *layouts = *layoutsp;
+    unsigned i;
+    uint64_t l;
+
+    if (layouts) {
+        if (ddump_find_ref(bp, graph, layouts->refs[0], layoutsp,
+                           offsetof(AVFilterLink,  in_channel_layouts),
+                           offsetof(AVFilterLink, out_channel_layouts))) {
+            /* nothing */
+        } else if (layouts->all_counts) {
+            av_bprintf(bp, "{ all layouts and counts }");
+        } else if (layouts->all_layouts) {
+            av_bprintf(bp, "{ all layouts }");
+        } else {
+            for (i = 0; i < layouts->nb_channel_layouts; i++) {
+                av_bprintf(bp, "%s", i ? " | " : " { ");
+                l = layouts->channel_layouts[i];
+                if (FF_LAYOUT2COUNT(l))
+                    av_bprintf(bp, "%dc", FF_LAYOUT2COUNT(l));
+                else
+                    av_bprint_channel_layout(bp, 0, l);
+            }
+            av_bprintf(bp, " }");
+        }
+    } else {
+        av_bprint_channel_layout(bp, channels, layout);
+    }
+}
+
+static void ddump_link(AVFilterGraph *graph, unsigned filter_idx,
+                       int out, unsigned pad_idx)
+{
+    AVFilterContext *f = graph->filters[filter_idx];
+    AVFilterLink *l = (out ? f->outputs : f->inputs)[pad_idx];
+    AVFilterContext *remote = out ? l->dst : l->src;
+    unsigned remote_idx;
+    AVBPrint bp;
+
+    for (remote_idx = 0; remote_idx < graph->nb_filters; remote_idx++)
+        if (graph->filters[remote_idx] == remote)
+            break;
+    av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
+    av_bprintf(&bp, "%c%d:%d %s", out ? 'o' : 'i', filter_idx, pad_idx,
+               out ? "->" : "<-");
+    if (remote_idx < graph->nb_filters)
+        av_bprintf(&bp, "%c%d:%d", out ? 'i' : 'o', remote_idx,
+                   out ? FF_OUTLINK_IDX(l) : FF_INLINK_IDX(l));
+    else
+        av_bprintf(&bp, "?");
+    av_bprintf(&bp, " ");
+    switch (l->type) {
+    case AVMEDIA_TYPE_VIDEO:
+        ddump_pixel_format(&bp, graph, l->format,
+                           out ? &l->in_formats : &l->out_formats);
+        break;
+    case AVMEDIA_TYPE_AUDIO:
+        ddump_sample_format(&bp, graph, l->format,
+                            out ? &l->in_formats : &l->out_formats);
+        av_bprintf(&bp, " / ");
+        ddump_sample_freq(&bp, graph, l->sample_rate,
+                          out ? &l->in_samplerates : &l->out_samplerates);
+        av_bprintf(&bp, " / ");
+        ddump_channels(&bp, graph, l->channels, l->channel_layout,
+                       out ? &l-> in_channel_layouts : &l->out_channel_layouts);
+        break;
+    default:
+        av_bprintf(&bp, " unknown format");
+        break;
+    }
+    av_log(graph, AV_LOG_DEBUG, "  %s\n", bp.str);
+    av_bprint_finalize(&bp, NULL);
+}
+
+void ff_dump_graph_debug(AVFilterGraph *graph)
+{
+    unsigned i, j;
+
+    for (i = 0; i < graph->nb_filters; i++) {
+        AVFilterContext *f = graph->filters[i];
+        av_log(graph, AV_LOG_DEBUG, "%d: %s \"%s\"\n", i, f->filter->name, f->name);
+        for (j = 0; j < f->nb_inputs; j++)
+            ddump_link(graph, i, 0, j);
+        for (j = 0; j < f->nb_outputs; j++)
+            ddump_link(graph, i, 1, j);
+    }
+}
+
diff --git a/libavfilter/internal.h b/libavfilter/internal.h
index 5e19698..a71557b 100644
--- a/libavfilter/internal.h
+++ b/libavfilter/internal.h
@@ -366,4 +366,9 @@ AVFilterContext *ff_filter_alloc(const AVFilter *filter, const char *inst_name);
  */
 void ff_filter_graph_remove_filter(AVFilterGraph *graph, AVFilterContext *filter);
 
+/**
+ * Dump a graph internal properties to debug log.
+ */
+void ff_dump_graph_debug(AVFilterGraph *graph);
+
 #endif /* AVFILTER_INTERNAL_H */
-- 
1.8.4.3



More information about the ffmpeg-devel mailing list