[libav-devel] [PATCH] filtergraph: Select the best pixel format

Luca Barbato lu_zero at gentoo.org
Mon Aug 10 03:18:34 CEST 2015


Give priority to pixel formats closer to the input.

Signed-off-by: Luca Barbato <lu_zero at gentoo.org>
---

This iteration implements scoring all the components (so yuv444 and yuv420 won't
get the same score) and I kept the bias towards same rgb and same alpha since
non-alpha -> alpha is plainly wasteful.

 libavfilter/avfiltergraph.c | 97 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 97 insertions(+)

diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c
index 0fc385c..fd43ff3 100644
--- a/libavfilter/avfiltergraph.c
+++ b/libavfilter/avfiltergraph.c
@@ -31,6 +31,7 @@
 #include "libavutil/internal.h"
 #include "libavutil/log.h"
 #include "libavutil/opt.h"
+#include "libavutil/pixdesc.h"

 #include "avfilter.h"
 #include "formats.h"
@@ -742,6 +743,100 @@ static int pick_formats(AVFilterGraph *graph)
     return 0;
 }

+#define same_flag(d1, d2, flag) \
+    !(!!(d1->flags & flag) ^ !!(d2->flags & flag))
+
+static int find_best_pix_fmt_match(AVFilterLink *outlink,
+                                   const AVPixFmtDescriptor *in_desc,
+                                   int in_format)
+{
+    int j;
+    int best_idx = -1, best_score = INT_MIN;
+
+    for (j = 0; j < outlink->in_formats->nb_formats; j++) {
+        int format                     = outlink->in_formats->formats[j];
+        const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(format);
+        int i, nb_components;
+        int same_alpha = same_flag(desc, in_desc, AV_PIX_FMT_FLAG_ALPHA);
+        int same_rgb   = same_flag(desc, in_desc, AV_PIX_FMT_FLAG_RGB);
+        int score      = 0;
+
+        nb_components = FFMIN(desc->nb_components, in_desc->nb_components);
+        for (i = 0; i < nb_components; i++) {
+            int bpc    = desc->comp[i].depth_minus1;
+            int in_bpc = in_desc->comp[i].depth_minus1;
+            if (bpc < in_bpc)
+                score += bpc - in_bpc;
+        }
+
+        score += -10 * abs(desc->nb_components -
+                           in_desc->nb_components);
+
+        if (same_alpha && same_rgb) {
+            score += 2;
+        } else if (desc->flags & AV_PIX_FMT_FLAG_ALPHA) {
+            if (same_alpha)
+                score += 1;
+        } else {
+            if (same_rgb)
+                score += 1;
+        }
+
+        if (score > best_score) {
+            best_score = score;
+            best_idx   = j;
+        }
+    }
+
+    return best_idx;
+}
+
+static void swap_pix_fmts_on_filter(AVFilterContext *filter)
+{
+    AVFilterLink *link = NULL;
+    const AVPixFmtDescriptor *desc;
+    int format;
+    int i;
+
+    for (i = 0; i < filter->nb_inputs; i++) {
+        link = filter->inputs[i];
+
+        if (link->type == AVMEDIA_TYPE_VIDEO &&
+            link->out_formats->nb_formats == 1)
+            break;
+    }
+    if (i == filter->nb_inputs)
+        return;
+
+    format = link->out_formats->formats[0];
+    desc   = av_pix_fmt_desc_get(format);
+
+    for (i = 0; i < filter->nb_outputs; i++) {
+        AVFilterLink *outlink = filter->outputs[i];
+        int best_idx;
+
+        if (outlink->type != AVMEDIA_TYPE_VIDEO ||
+            outlink->in_formats->nb_formats < 2)
+            continue;
+
+        best_idx = find_best_pix_fmt_match(outlink, desc, format);
+
+        if (best_idx > -1)
+            FFSWAP(int, outlink->in_formats->formats[0],
+                   outlink->in_formats->formats[best_idx]);
+    }
+}
+
+static void swap_pix_fmts(AVFilterGraph *graph)
+{
+    int i;
+
+    for (i = 0; i < graph->nb_filters; i++) {
+        swap_pix_fmts_on_filter(graph->filters[i]);
+    }
+}
+
+
 /**
  * Configure the formats of all the links in the graph.
  */
@@ -763,6 +858,8 @@ static int graph_config_formats(AVFilterGraph *graph, AVClass *log_ctx)
     swap_sample_fmts(graph);
     swap_samplerates(graph);
     swap_channel_layouts(graph);
+    /* for video filters, ensure the best format is selected */
+    swap_pix_fmts(graph);

     if ((ret = pick_formats(graph)) < 0)
         return ret;
--
1.9.0



More information about the libav-devel mailing list