avfilter/dctdnoiz: make color [de]correlation less clumsy
authorClément Bœsch <u@pkh.me>
Fri, 8 Aug 2014 17:44:40 +0000 (19:44 +0200)
committerClément Bœsch <u@pkh.me>
Fri, 8 Aug 2014 18:00:13 +0000 (20:00 +0200)
This has no impact on overall performance, since the block DCT taking
most of the time anyway.

libavfilter/vf_dctdnoiz.c

index 1e2d2b7..d9fa39b 100644 (file)
@@ -31,7 +31,6 @@
 #include "libavutil/avassert.h"
 #include "libavutil/eval.h"
 #include "libavutil/opt.h"
-#include "drawutils.h"
 #include "internal.h"
 
 static const char *const var_names[] = { "c", NULL };
@@ -48,7 +47,6 @@ typedef struct DCTdnoizContext {
     int pr_width, pr_height;    // width and height to process
     float sigma;                // used when no expression are st
     float th;                   // threshold (3*sigma)
-    float color_dct[3][3];      // 3x3 DCT for color decorrelation
     float *cbuf[2][3];          // two planar rgb color buffers
     float *weights;             // dct coeff are cumulated with overlapping; these values are used for averaging
     int p_linesize;             // line sizes for color and weights
@@ -59,6 +57,12 @@ typedef struct DCTdnoizContext {
     void (*filter_freq_func)(struct DCTdnoizContext *s,
                              const float *src, int src_linesize,
                              float *dst, int dst_linesize);
+    void (*color_decorrelation)(float **dst, int dst_linesize,
+                                const uint8_t *src, int src_linesize,
+                                int w, int h);
+    void (*color_correlation)(uint8_t *dst, int dst_linesize,
+                              float **src, int src_linesize,
+                              int w, int h);
 } DCTdnoizContext;
 
 #define MIN_NBITS 3 /* blocksize = 1<<3 =  8 */
@@ -392,23 +396,39 @@ static void filter_freq_expr_##bsize(DCTdnoizContext *s,
 DEF_FILTER_FREQ_FUNCS(8)
 DEF_FILTER_FREQ_FUNCS(16)
 
+// TODO: remove
+static void color_decorrelation_rgb(float **dst, int dst_linesize,
+                                    const uint8_t *src, int src_linesize,
+                                    int w, int h);
+static void color_correlation_rgb(uint8_t *dst, int dst_linesize,
+                                  float **src, int src_linesize,
+                                  int w, int h);
+static void color_decorrelation_bgr(float **dst, int dst_linesize,
+                                    const uint8_t *src, int src_linesize,
+                                    int w, int h);
+static void color_correlation_bgr(uint8_t *dst, int dst_linesize,
+                                  float **src, int src_linesize,
+                                  int w, int h);
+
 static int config_input(AVFilterLink *inlink)
 {
     AVFilterContext *ctx = inlink->dst;
     DCTdnoizContext *s = ctx->priv;
     int i, x, y, bx, by, linesize, *iweights;
     const int bsize = 1 << s->n;
-    const float dct_3x3[3][3] = {
-        { 1./sqrt(3),  1./sqrt(3),  1./sqrt(3) },
-        { 1./sqrt(2),           0, -1./sqrt(2) },
-        { 1./sqrt(6), -2./sqrt(6),  1./sqrt(6) },
-    };
-    uint8_t rgba_map[4];
 
-    ff_fill_rgba_map(rgba_map, inlink->format);
-    for (y = 0; y < 3; y++)
-        for (x = 0; x < 3; x++)
-            s->color_dct[y][x] = dct_3x3[rgba_map[y]][rgba_map[x]];
+    switch (inlink->format) {
+    case AV_PIX_FMT_BGR24:
+        s->color_decorrelation = color_decorrelation_bgr;
+        s->color_correlation   = color_correlation_bgr;
+        break;
+    case AV_PIX_FMT_RGB24:
+        s->color_decorrelation = color_decorrelation_rgb;
+        s->color_correlation   = color_correlation_rgb;
+        break;
+    default:
+        av_assert0(0);
+    }
 
     s->pr_width  = inlink->w - (inlink->w - bsize) % s->step;
     s->pr_height = inlink->h - (inlink->h - bsize) % s->step;
@@ -495,8 +515,19 @@ static int query_formats(AVFilterContext *ctx)
     return 0;
 }
 
-static void color_decorrelation(float dct3ch[3][3], float **dst, int dst_linesize,
-                                const uint8_t *src, int src_linesize, int w, int h)
+#define DCT3X3_0_0  0.5773502691896258f /*  1/sqrt(3) */
+#define DCT3X3_0_1  0.5773502691896258f /*  1/sqrt(3) */
+#define DCT3X3_0_2  0.5773502691896258f /*  1/sqrt(3) */
+#define DCT3X3_1_0  0.7071067811865475f /*  1/sqrt(2) */
+#define DCT3X3_1_2 -0.7071067811865475f /* -1/sqrt(2) */
+#define DCT3X3_2_0  0.4082482904638631f /*  1/sqrt(6) */
+#define DCT3X3_2_1 -0.8164965809277261f /* -2/sqrt(6) */
+#define DCT3X3_2_2  0.4082482904638631f /*  1/sqrt(6) */
+
+static av_always_inline void color_decorrelation(float **dst, int dst_linesize,
+                                                 const uint8_t *src, int src_linesize,
+                                                 int w, int h,
+                                                 int r, int g, int b)
 {
     int x, y;
     float *dstp_r = dst[0];
@@ -507,9 +538,9 @@ static void color_decorrelation(float dct3ch[3][3], float **dst, int dst_linesiz
         const uint8_t *srcp = src;
 
         for (x = 0; x < w; x++) {
-            dstp_r[x] = srcp[0] * dct3ch[0][0] + srcp[1] * dct3ch[0][1] + srcp[2] * dct3ch[0][2];
-            dstp_g[x] = srcp[0] * dct3ch[1][0] + srcp[1] * dct3ch[1][1] + srcp[2] * dct3ch[1][2];
-            dstp_b[x] = srcp[0] * dct3ch[2][0] + srcp[1] * dct3ch[2][1] + srcp[2] * dct3ch[2][2];
+            dstp_r[x] = srcp[r] * DCT3X3_0_0 + srcp[g] * DCT3X3_0_1 + srcp[b] * DCT3X3_0_2;
+            dstp_g[x] = srcp[r] * DCT3X3_1_0 +                        srcp[b] * DCT3X3_1_2;
+            dstp_b[x] = srcp[r] * DCT3X3_2_0 + srcp[g] * DCT3X3_2_1 + srcp[b] * DCT3X3_2_2;
             srcp += 3;
         }
         src += src_linesize;
@@ -519,8 +550,10 @@ static void color_decorrelation(float dct3ch[3][3], float **dst, int dst_linesiz
     }
 }
 
-static void color_correlation(float dct3ch[3][3], uint8_t *dst, int dst_linesize,
-                              float **src, int src_linesize, int w, int h)
+static av_always_inline void color_correlation(uint8_t *dst, int dst_linesize,
+                                               float **src, int src_linesize,
+                                               int w, int h,
+                                               int r, int g, int b)
 {
     int x, y;
     const float *src_r = src[0];
@@ -531,9 +564,9 @@ static void color_correlation(float dct3ch[3][3], uint8_t *dst, int dst_linesize
         uint8_t *dstp = dst;
 
         for (x = 0; x < w; x++) {
-            dstp[0] = av_clip_uint8(src_r[x] * dct3ch[0][0] + src_g[x] * dct3ch[1][0] + src_b[x] * dct3ch[2][0]);
-            dstp[1] = av_clip_uint8(src_r[x] * dct3ch[0][1] + src_g[x] * dct3ch[1][1] + src_b[x] * dct3ch[2][1]);
-            dstp[2] = av_clip_uint8(src_r[x] * dct3ch[0][2] + src_g[x] * dct3ch[1][2] + src_b[x] * dct3ch[2][2]);
+            dstp[r] = av_clip_uint8(src_r[x] * DCT3X3_0_0 + src_g[x] * DCT3X3_1_0 + src_b[x] * DCT3X3_2_0);
+            dstp[g] = av_clip_uint8(src_r[x] * DCT3X3_0_1 +                         src_b[x] * DCT3X3_2_1);
+            dstp[b] = av_clip_uint8(src_r[x] * DCT3X3_0_2 + src_g[x] * DCT3X3_1_2 + src_b[x] * DCT3X3_2_2);
             dstp += 3;
         }
         dst += dst_linesize;
@@ -543,6 +576,24 @@ static void color_correlation(float dct3ch[3][3], uint8_t *dst, int dst_linesize
     }
 }
 
+#define DECLARE_COLOR_FUNCS(name, r, g, b)                                          \
+static void color_decorrelation_##name(float **dst, int dst_linesize,               \
+                                       const uint8_t *src, int src_linesize,        \
+                                       int w, int h)                                \
+{                                                                                   \
+    color_decorrelation(dst, dst_linesize, src, src_linesize, w, h, r, g, b);       \
+}                                                                                   \
+                                                                                    \
+static void color_correlation_##name(uint8_t *dst, int dst_linesize,                \
+                                     float **src, int src_linesize,                 \
+                                     int w, int h)                                  \
+{                                                                                   \
+    color_correlation(dst, dst_linesize, src, src_linesize, w, h, r, g, b);         \
+}
+
+DECLARE_COLOR_FUNCS(rgb, 0, 1, 2)
+DECLARE_COLOR_FUNCS(bgr, 2, 1, 0)
+
 static void filter_plane(AVFilterContext *ctx,
                          float *dst, int dst_linesize,
                          const float *src, int src_linesize,
@@ -596,14 +647,16 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
         av_frame_copy_props(out, in);
     }
 
-    color_decorrelation(s->color_dct, s->cbuf[0], s->p_linesize,
-                        in->data[0], in->linesize[0], s->pr_width, s->pr_height);
+    s->color_decorrelation(s->cbuf[0], s->p_linesize,
+                           in->data[0], in->linesize[0],
+                           s->pr_width, s->pr_height);
     for (plane = 0; plane < 3; plane++)
         filter_plane(ctx, s->cbuf[1][plane], s->p_linesize,
                           s->cbuf[0][plane], s->p_linesize,
                           s->pr_width, s->pr_height);
-    color_correlation(s->color_dct, out->data[0], out->linesize[0],
-                      s->cbuf[1], s->p_linesize, s->pr_width, s->pr_height);
+    s->color_correlation(out->data[0], out->linesize[0],
+                         s->cbuf[1], s->p_linesize,
+                         s->pr_width, s->pr_height);
 
     if (!direct) {
         int y;