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/avassert.h"
#include "libavutil/eval.h" #include "libavutil/eval.h"
#include "libavutil/opt.h" #include "libavutil/opt.h"
#include "drawutils.h"
#include "internal.h" #include "internal.h"
static const char *const var_names[] = { "c", NULL }; 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 int pr_width, pr_height; // width and height to process
float sigma; // used when no expression are st float sigma; // used when no expression are st
float th; // threshold (3*sigma) 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 *cbuf[2][3]; // two planar rgb color buffers
float *weights; // dct coeff are cumulated with overlapping; these values are used for averaging float *weights; // dct coeff are cumulated with overlapping; these values are used for averaging
int p_linesize; // line sizes for color and weights int p_linesize; // line sizes for color and weights
@ -59,6 +57,12 @@ typedef struct DCTdnoizContext {
void (*filter_freq_func)(struct DCTdnoizContext *s, void (*filter_freq_func)(struct DCTdnoizContext *s,
const float *src, int src_linesize, const float *src, int src_linesize,
float *dst, int dst_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; } DCTdnoizContext;
#define MIN_NBITS 3 /* blocksize = 1<<3 = 8 */ #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(8)
DEF_FILTER_FREQ_FUNCS(16) 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) static int config_input(AVFilterLink *inlink)
{ {
AVFilterContext *ctx = inlink->dst; AVFilterContext *ctx = inlink->dst;
DCTdnoizContext *s = ctx->priv; DCTdnoizContext *s = ctx->priv;
int i, x, y, bx, by, linesize, *iweights; int i, x, y, bx, by, linesize, *iweights;
const int bsize = 1 << s->n; 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); switch (inlink->format) {
for (y = 0; y < 3; y++) case AV_PIX_FMT_BGR24:
for (x = 0; x < 3; x++) s->color_decorrelation = color_decorrelation_bgr;
s->color_dct[y][x] = dct_3x3[rgba_map[y]][rgba_map[x]]; 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_width = inlink->w - (inlink->w - bsize) % s->step;
s->pr_height = inlink->h - (inlink->h - 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; return 0;
} }
static void color_decorrelation(float dct3ch[3][3], float **dst, int dst_linesize, #define DCT3X3_0_0 0.5773502691896258f /* 1/sqrt(3) */
const uint8_t *src, int src_linesize, int w, int h) #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; int x, y;
float *dstp_r = dst[0]; 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; const uint8_t *srcp = src;
for (x = 0; x < w; x++) { 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_r[x] = srcp[r] * DCT3X3_0_0 + srcp[g] * DCT3X3_0_1 + srcp[b] * DCT3X3_0_2;
dstp_g[x] = srcp[0] * dct3ch[1][0] + srcp[1] * dct3ch[1][1] + srcp[2] * dct3ch[1][2]; dstp_g[x] = srcp[r] * DCT3X3_1_0 + srcp[b] * DCT3X3_1_2;
dstp_b[x] = srcp[0] * dct3ch[2][0] + srcp[1] * dct3ch[2][1] + srcp[2] * dct3ch[2][2]; dstp_b[x] = srcp[r] * DCT3X3_2_0 + srcp[g] * DCT3X3_2_1 + srcp[b] * DCT3X3_2_2;
srcp += 3; srcp += 3;
} }
src += src_linesize; 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, static av_always_inline void color_correlation(uint8_t *dst, int dst_linesize,
float **src, int src_linesize, int w, int h) float **src, int src_linesize,
int w, int h,
int r, int g, int b)
{ {
int x, y; int x, y;
const float *src_r = src[0]; 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; uint8_t *dstp = dst;
for (x = 0; x < w; x++) { 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[r] = av_clip_uint8(src_r[x] * DCT3X3_0_0 + src_g[x] * DCT3X3_1_0 + src_b[x] * DCT3X3_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[g] = av_clip_uint8(src_r[x] * DCT3X3_0_1 + src_b[x] * DCT3X3_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[b] = av_clip_uint8(src_r[x] * DCT3X3_0_2 + src_g[x] * DCT3X3_1_2 + src_b[x] * DCT3X3_2_2);
dstp += 3; dstp += 3;
} }
dst += dst_linesize; 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, static void filter_plane(AVFilterContext *ctx,
float *dst, int dst_linesize, float *dst, int dst_linesize,
const float *src, int src_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); av_frame_copy_props(out, in);
} }
color_decorrelation(s->color_dct, s->cbuf[0], s->p_linesize, s->color_decorrelation(s->cbuf[0], s->p_linesize,
in->data[0], in->linesize[0], s->pr_width, s->pr_height); in->data[0], in->linesize[0],
s->pr_width, s->pr_height);
for (plane = 0; plane < 3; plane++) for (plane = 0; plane < 3; plane++)
filter_plane(ctx, s->cbuf[1][plane], s->p_linesize, filter_plane(ctx, s->cbuf[1][plane], s->p_linesize,
s->cbuf[0][plane], s->p_linesize, s->cbuf[0][plane], s->p_linesize,
s->pr_width, s->pr_height); s->pr_width, s->pr_height);
color_correlation(s->color_dct, out->data[0], out->linesize[0], s->color_correlation(out->data[0], out->linesize[0],
s->cbuf[1], s->p_linesize, s->pr_width, s->pr_height); s->cbuf[1], s->p_linesize,
s->pr_width, s->pr_height);
if (!direct) { if (!direct) {
int y; int y;