avfilter/dctdnoiz: make color [de]correlation less clumsy

This has no impact on overall performance, since the block DCT taking
most of the time anyway.
This commit is contained in:
Clément Bœsch 2014-08-08 19:44:40 +02:00
parent 94494dab91
commit aaf82dc0fa

View 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;