[FFmpeg-devel] [PATCH] lavfi/vf_extractplanes: set input formats to reduce conversions.

Nicolas George nicolas.george at normalesup.org
Mon May 6 21:21:19 CEST 2013


Only accept formats that will not require color-space conversion
and with the same bit depth as actually available on input.

Signed-off-by: Nicolas George <nicolas.george at normalesup.org>
---
 libavfilter/vf_extractplanes.c |   67 ++++++++++++++++++++++++++--------------
 1 file changed, 44 insertions(+), 23 deletions(-)


Note tht for some reason, GBRP16?E are not considered valid output formats 
for lsws, so handling RGB in 16 bpp will not work. But that is completely
unrelated.


diff --git a/libavfilter/vf_extractplanes.c b/libavfilter/vf_extractplanes.c
index 028813a..373a789 100644
--- a/libavfilter/vf_extractplanes.c
+++ b/libavfilter/vf_extractplanes.c
@@ -18,6 +18,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include "libavutil/avassert.h"
 #include "libavutil/avstring.h"
 #include "libavutil/imgutils.h"
 #include "libavutil/opt.h"
@@ -33,6 +34,12 @@
 #define PLANE_U 0x20
 #define PLANE_V 0x40
 
+#define FLAG_DEPTH_8     0x10000
+#define FLAG_DEPTH_16LE  0x20000
+#define FLAG_DEPTH_16BE  0x40000
+#define FLAG_DEPTH_OTHER 0x80000
+#define FLAG_DEPTHS      0xF0000
+
 typedef struct {
     const AVClass *class;
     int requested_planes;
@@ -56,6 +63,21 @@ static const AVOption extractplanes_options[] = {
 
 AVFILTER_DEFINE_CLASS(extractplanes);
 
+static unsigned pix_fmt_to_bitmask(enum AVPixelFormat fmt)
+{
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt);
+    unsigned depth = desc->comp[0].depth_minus1 + 1;
+
+    return ((desc->flags & PIX_FMT_RGB) ? PLANE_R|PLANE_G|PLANE_B :
+                                          PLANE_Y |
+                         ((desc->nb_components > 2) ? PLANE_U|PLANE_V : 0)) |
+           ((desc->flags & PIX_FMT_ALPHA) ? PLANE_A : 0) |
+           (depth ==  8 ? FLAG_DEPTH_8 :
+            depth == 16 ? (desc->flags & PIX_FMT_BE) ? FLAG_DEPTH_16BE :
+                                                       FLAG_DEPTH_16LE :
+                          FLAG_DEPTH_OTHER);
+}
+
 static int query_formats(AVFilterContext *ctx)
 {
     static const enum AVPixelFormat in_pixfmts[] = {
@@ -77,42 +99,45 @@ static int query_formats(AVFilterContext *ctx)
         AV_PIX_FMT_GRAY16LE, AV_PIX_FMT_GRAY16BE,
         AV_PIX_FMT_GBRP,
         AV_PIX_FMT_GBRP16LE, AV_PIX_FMT_GBRP16BE,
-        AV_PIX_FMT_NONE,
     };
     static const enum AVPixelFormat out8_pixfmts[] = { AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE };
     static const enum AVPixelFormat out16le_pixfmts[] = { AV_PIX_FMT_GRAY16LE, AV_PIX_FMT_NONE };
     static const enum AVPixelFormat out16be_pixfmts[] = { AV_PIX_FMT_GRAY16BE, AV_PIX_FMT_NONE };
     const enum AVPixelFormat *out_pixfmts;
-    const AVPixFmtDescriptor *desc;
-    AVFilterFormats *avff;
-    int i, depth = 0, be = 0;
+    AVFilterFormats *avff, *in_formats = NULL;
+    unsigned i, fmt_mask, max_fmt_mask = 0;
 
     if (!ctx->inputs[0]->in_formats ||
         !ctx->inputs[0]->in_formats->format_count) {
         return AVERROR(EAGAIN);
     }
 
-    if (!ctx->inputs[0]->out_formats)
-        ff_formats_ref(ff_make_format_list(in_pixfmts), &ctx->inputs[0]->out_formats);
-
     avff = ctx->inputs[0]->in_formats;
-    desc = av_pix_fmt_desc_get(avff->formats[0]);
-    depth = desc->comp[0].depth_minus1;
-    be = desc->flags & PIX_FMT_BE;
-    for (i = 1; i < avff->format_count; i++) {
-        desc = av_pix_fmt_desc_get(avff->formats[i]);
-        if (depth != desc->comp[0].depth_minus1 ||
-            be    != (desc->flags & PIX_FMT_BE)) {
+    for (i = 0; i < avff->format_count; i++) {
+        fmt_mask = pix_fmt_to_bitmask(avff->formats[i]);
+        if ((fmt_mask & ~max_fmt_mask) && (max_fmt_mask & ~fmt_mask))
             return AVERROR(EAGAIN);
-        }
+        max_fmt_mask |= fmt_mask;
     }
 
-    if (depth == 7)
+    if ((max_fmt_mask & FLAG_DEPTH_8)) {
         out_pixfmts = out8_pixfmts;
-    else if (be)
+    } else if ((max_fmt_mask & FLAG_DEPTH_16BE)) {
         out_pixfmts = out16be_pixfmts;
-    else
+    } else if ((max_fmt_mask & FLAG_DEPTH_16BE)) {
         out_pixfmts = out16le_pixfmts;
+    } else {
+        av_log(ctx, AV_LOG_ERROR, "No supported bit depth in input\n");
+        return AVERROR(EINVAL);
+    }
+
+    if (!ctx->inputs[0]->out_formats) {
+        for (i = 0; i < FF_ARRAY_ELEMS(in_pixfmts); i++)
+            if (!(pix_fmt_to_bitmask(in_pixfmts[i]) & ~max_fmt_mask))
+                ff_add_format(&in_formats, in_pixfmts[i]);
+        av_assert0(in_formats);
+        ff_formats_ref(in_formats, &ctx->inputs[0]->out_formats);
+    }
 
     for (i = 0; i < ctx->nb_outputs; i++)
         ff_formats_ref(ff_make_format_list(out_pixfmts), &ctx->outputs[i]->in_formats);
@@ -123,13 +148,9 @@ static int config_input(AVFilterLink *inlink)
 {
     AVFilterContext *ctx = inlink->dst;
     ExtractPlanesContext *e = ctx->priv;
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
     int plane_avail, ret;
 
-    plane_avail = ((desc->flags & PIX_FMT_RGB) ? PLANE_R|PLANE_G|PLANE_B :
-                                                 PLANE_Y |
-                                ((desc->nb_components > 2) ? PLANE_U|PLANE_V : 0)) |
-                  ((desc->flags & PIX_FMT_ALPHA) ? PLANE_A : 0);
+    plane_avail = pix_fmt_to_bitmask(inlink->format) & ~FLAG_DEPTHS;
     if (e->requested_planes & ~plane_avail) {
         av_log(ctx, AV_LOG_ERROR, "Requested planes not available.\n");
         return AVERROR(EINVAL);
-- 
1.7.10.4



More information about the ffmpeg-devel mailing list