Skip to content

Commit 95183d2

Browse files
committed
avfilter/vf_atadenoise: add sigma options
1 parent ee1d1c4 commit 95183d2

File tree

4 files changed

+162
-23
lines changed

4 files changed

+162
-23
lines changed

doc/filters.texi

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7096,6 +7096,15 @@ Alternatively can be set to @code{s} serial.
70967096
Parallel can be faster then serial, while other way around is never true.
70977097
Parallel will abort early on first change being greater then thresholds, while serial
70987098
will continue processing other side of frames if they are equal or below thresholds.
7099+
7100+
@item 0s
7101+
@item 1s
7102+
@item 2s
7103+
Set sigma for 1st plane, 2nd plane or 3rd plane. Default is 32767.
7104+
Valid range is from 0 to 32767.
7105+
This options controls weight for each pixel in radius defined by size.
7106+
Default value means every pixel have same weight.
7107+
Setting this option to 0 effectively disables filtering.
70997108
@end table
71007109

71017110
@subsection Commands

libavfilter/atadenoise.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@ enum ATAAlgorithm {
3131
};
3232

3333
typedef struct ATADenoiseDSPContext {
34-
void (*filter_row)(const uint8_t *src, uint8_t *dst,
35-
const uint8_t **srcf,
36-
int w, int mid, int size,
37-
int thra, int thrb);
34+
void (*filter_row[4])(const uint8_t *src, uint8_t *dst,
35+
const uint8_t **srcf,
36+
int w, int mid, int size,
37+
int thra, int thrb, const float *weight);
3838
} ATADenoiseDSPContext;
3939

40-
void ff_atadenoise_init_x86(ATADenoiseDSPContext *dsp, int depth, int algorithm);
40+
void ff_atadenoise_init_x86(ATADenoiseDSPContext *dsp, int depth, int algorithm, const float *sigma);
4141

4242
#endif /* AVFILTER_ATADENOISE_H */

libavfilter/vf_atadenoise.c

Lines changed: 138 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ typedef struct ATADenoiseContext {
4444
const AVClass *class;
4545

4646
float fthra[4], fthrb[4];
47+
float sigma[4];
4748
int thra[4], thrb[4];
4849
int algorithm;
4950

@@ -55,7 +56,8 @@ typedef struct ATADenoiseContext {
5556
struct FFBufQueue q;
5657
void *data[4][SIZE];
5758
int linesize[4][SIZE];
58-
int size, mid;
59+
float weights[4][SIZE];
60+
int size, mid, radius;
5961
int available;
6062

6163
int (*filter_slice)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
@@ -79,6 +81,9 @@ static const AVOption atadenoise_options[] = {
7981
{ "a", "set variant of algorithm", OFFSET(algorithm),AV_OPT_TYPE_INT, {.i64=PARALLEL}, 0, NB_ATAA-1, FLAGS, "a" },
8082
{ "p", "parallel", 0, AV_OPT_TYPE_CONST, {.i64=PARALLEL}, 0, 0, FLAGS, "a" },
8183
{ "s", "serial", 0, AV_OPT_TYPE_CONST, {.i64=SERIAL}, 0, 0, FLAGS, "a" },
84+
{ "0s", "set sigma for 1st plane", OFFSET(sigma[0]), AV_OPT_TYPE_FLOAT, {.dbl=INT16_MAX}, 0, INT16_MAX, FLAGS },
85+
{ "1s", "set sigma for 2nd plane", OFFSET(sigma[1]), AV_OPT_TYPE_FLOAT, {.dbl=INT16_MAX}, 0, INT16_MAX, FLAGS },
86+
{ "2s", "set sigma for 3rd plane", OFFSET(sigma[2]), AV_OPT_TYPE_FLOAT, {.dbl=INT16_MAX}, 0, INT16_MAX, FLAGS },
8287
{ NULL }
8388
};
8489

@@ -129,7 +134,8 @@ static av_cold int init(AVFilterContext *ctx)
129134
av_log(ctx, AV_LOG_WARNING, "size %d is invalid. Must be an odd value, setting it to %d.\n", s->size, s->size|1);
130135
s->size |= 1;
131136
}
132-
s->mid = s->size / 2 + 1;
137+
s->radius = s->size / 2;
138+
s->mid = s->radius + 1;
133139

134140
return 0;
135141
}
@@ -138,11 +144,114 @@ typedef struct ThreadData {
138144
AVFrame *in, *out;
139145
} ThreadData;
140146

147+
#define WFILTER_ROW(type, name) \
148+
static void fweight_row##name(const uint8_t *ssrc, uint8_t *ddst, \
149+
const uint8_t *ssrcf[SIZE], \
150+
int w, int mid, int size, \
151+
int thra, int thrb, const float *weights) \
152+
{ \
153+
const type *src = (const type *)ssrc; \
154+
const type **srcf = (const type **)ssrcf; \
155+
type *dst = (type *)ddst; \
156+
\
157+
for (int x = 0; x < w; x++) { \
158+
const int srcx = src[x]; \
159+
unsigned lsumdiff = 0, rsumdiff = 0; \
160+
unsigned ldiff, rdiff; \
161+
float sum = srcx; \
162+
float wsum = 1.f; \
163+
int l = 0, r = 0; \
164+
int srcjx, srcix; \
165+
\
166+
for (int j = mid - 1, i = mid + 1; j >= 0 && i < size; j--, i++) { \
167+
srcjx = srcf[j][x]; \
168+
\
169+
ldiff = FFABS(srcx - srcjx); \
170+
lsumdiff += ldiff; \
171+
if (ldiff > thra || \
172+
lsumdiff > thrb) \
173+
break; \
174+
l++; \
175+
sum += srcjx * weights[j]; \
176+
wsum += weights[j]; \
177+
\
178+
srcix = srcf[i][x]; \
179+
\
180+
rdiff = FFABS(srcx - srcix); \
181+
rsumdiff += rdiff; \
182+
if (rdiff > thra || \
183+
rsumdiff > thrb) \
184+
break; \
185+
r++; \
186+
sum += srcix * weights[i]; \
187+
wsum += weights[i]; \
188+
} \
189+
\
190+
dst[x] = lrintf(sum / wsum); \
191+
} \
192+
}
193+
194+
WFILTER_ROW(uint8_t, 8)
195+
WFILTER_ROW(uint16_t, 16)
196+
197+
#define WFILTER_ROW_SERIAL(type, name) \
198+
static void fweight_row##name##_serial(const uint8_t *ssrc, uint8_t *ddst, \
199+
const uint8_t *ssrcf[SIZE], \
200+
int w, int mid, int size, \
201+
int thra, int thrb, \
202+
const float *weights) \
203+
{ \
204+
const type *src = (const type *)ssrc; \
205+
const type **srcf = (const type **)ssrcf; \
206+
type *dst = (type *)ddst; \
207+
\
208+
for (int x = 0; x < w; x++) { \
209+
const int srcx = src[x]; \
210+
unsigned lsumdiff = 0, rsumdiff = 0; \
211+
unsigned ldiff, rdiff; \
212+
float sum = srcx; \
213+
float wsum = 1.f; \
214+
int l = 0, r = 0; \
215+
int srcjx, srcix; \
216+
\
217+
for (int j = mid - 1; j >= 0; j--) { \
218+
srcjx = srcf[j][x]; \
219+
\
220+
ldiff = FFABS(srcx - srcjx); \
221+
lsumdiff += ldiff; \
222+
if (ldiff > thra || \
223+
lsumdiff > thrb) \
224+
break; \
225+
l++; \
226+
sum += srcjx * weights[j]; \
227+
wsum += weights[j]; \
228+
} \
229+
\
230+
for (int i = mid + 1; i < size; i++) { \
231+
srcix = srcf[i][x]; \
232+
\
233+
rdiff = FFABS(srcx - srcix); \
234+
rsumdiff += rdiff; \
235+
if (rdiff > thra || \
236+
rsumdiff > thrb) \
237+
break; \
238+
r++; \
239+
sum += srcix * weights[i]; \
240+
wsum += weights[i]; \
241+
} \
242+
\
243+
dst[x] = lrintf(sum / wsum); \
244+
} \
245+
}
246+
247+
WFILTER_ROW_SERIAL(uint8_t, 8)
248+
WFILTER_ROW_SERIAL(uint16_t, 16)
249+
141250
#define FILTER_ROW(type, name) \
142251
static void filter_row##name(const uint8_t *ssrc, uint8_t *ddst, \
143252
const uint8_t *ssrcf[SIZE], \
144253
int w, int mid, int size, \
145-
int thra, int thrb) \
254+
int thra, int thrb, const float *weights) \
146255
{ \
147256
const type *src = (const type *)ssrc; \
148257
const type **srcf = (const type **)ssrcf; \
@@ -189,7 +298,8 @@ FILTER_ROW(uint16_t, 16)
189298
static void filter_row##name##_serial(const uint8_t *ssrc, uint8_t *ddst, \
190299
const uint8_t *ssrcf[SIZE], \
191300
int w, int mid, int size, \
192-
int thra, int thrb) \
301+
int thra, int thrb, \
302+
const float *weights) \
193303
{ \
194304
const type *src = (const type *)ssrc; \
195305
const type **srcf = (const type **)ssrcf; \
@@ -245,6 +355,7 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
245355
int p, y, i;
246356

247357
for (p = 0; p < s->nb_planes; p++) {
358+
const float *weights = s->weights[p];
248359
const int h = s->planeheight[p];
249360
const int w = s->planewidth[p];
250361
const int slice_start = (h * jobnr) / nb_jobs;
@@ -267,7 +378,7 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
267378
srcf[i] = data[i] + slice_start * linesize[i];
268379

269380
for (y = slice_start; y < slice_end; y++) {
270-
s->dsp.filter_row(src, dst, srcf, w, mid, size, thra, thrb);
381+
s->dsp.filter_row[p](src, dst, srcf, w, mid, size, thra, thrb, weights);
271382

272383
dst += out->linesize[p];
273384
src += in->linesize[p];
@@ -296,10 +407,17 @@ static int config_input(AVFilterLink *inlink)
296407

297408
depth = desc->comp[0].depth;
298409
s->filter_slice = filter_slice;
299-
if (depth == 8)
300-
s->dsp.filter_row = s->algorithm == PARALLEL ? filter_row8 : filter_row8_serial;
301-
else
302-
s->dsp.filter_row = s->algorithm == PARALLEL ? filter_row16 : filter_row16_serial;
410+
411+
for (int p = 0; p < s->nb_planes; p++) {
412+
if (depth == 8 && s->sigma[p] == INT16_MAX)
413+
s->dsp.filter_row[p] = s->algorithm == PARALLEL ? filter_row8 : filter_row8_serial;
414+
else if (s->sigma[p] == INT16_MAX)
415+
s->dsp.filter_row[p] = s->algorithm == PARALLEL ? filter_row16 : filter_row16_serial;
416+
else if (depth == 8 && s->sigma[p] < INT16_MAX)
417+
s->dsp.filter_row[p] = s->algorithm == PARALLEL ? fweight_row8 : fweight_row8_serial;
418+
else if (s->sigma[p] < INT16_MAX)
419+
s->dsp.filter_row[p] = s->algorithm == PARALLEL ? fweight_row16 : fweight_row16_serial;
420+
}
303421

304422
s->thra[0] = s->fthra[0] * (1 << depth) - 1;
305423
s->thra[1] = s->fthra[1] * (1 << depth) - 1;
@@ -308,8 +426,18 @@ static int config_input(AVFilterLink *inlink)
308426
s->thrb[1] = s->fthrb[1] * (1 << depth) - 1;
309427
s->thrb[2] = s->fthrb[2] * (1 << depth) - 1;
310428

429+
for (int p = 0; p < s->nb_planes; p++) {
430+
float sigma = s->radius * s->sigma[p];
431+
432+
s->weights[p][s->mid] = 1.f;
433+
for (int n = 1; n <= s->radius; n++) {
434+
s->weights[p][s->radius + n] =
435+
s->weights[p][s->radius - n] = expf(-0.5 * (n + 1) * (n + 1) / (sigma * sigma));
436+
}
437+
}
438+
311439
if (ARCH_X86)
312-
ff_atadenoise_init_x86(&s->dsp, depth, s->algorithm);
440+
ff_atadenoise_init_x86(&s->dsp, depth, s->algorithm, s->sigma);
313441

314442
return 0;
315443
}

libavfilter/x86/vf_atadenoise_init.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,22 +28,24 @@
2828
void ff_atadenoise_filter_row8_sse4(const uint8_t *src, uint8_t *dst,
2929
const uint8_t **srcf,
3030
int w, int mid, int size,
31-
int thra, int thrb);
31+
int thra, int thrb, const float *weights);
3232

3333
void ff_atadenoise_filter_row8_serial_sse4(const uint8_t *src, uint8_t *dst,
3434
const uint8_t **srcf,
3535
int w, int mid, int size,
36-
int thra, int thrb);
36+
int thra, int thrb, const float *weights);
3737

38-
av_cold void ff_atadenoise_init_x86(ATADenoiseDSPContext *dsp, int depth, int algorithm)
38+
av_cold void ff_atadenoise_init_x86(ATADenoiseDSPContext *dsp, int depth, int algorithm, const float *sigma)
3939
{
4040
int cpu_flags = av_get_cpu_flags();
4141

42-
if (ARCH_X86_64 && EXTERNAL_SSE4(cpu_flags) && depth <= 8 && algorithm == PARALLEL) {
43-
dsp->filter_row = ff_atadenoise_filter_row8_sse4;
44-
}
42+
for (int p = 0; p < 4; p++) {
43+
if (ARCH_X86_64 && EXTERNAL_SSE4(cpu_flags) && depth <= 8 && algorithm == PARALLEL && sigma[p] == INT16_MAX) {
44+
dsp->filter_row[p] = ff_atadenoise_filter_row8_sse4;
45+
}
4546

46-
if (ARCH_X86_64 && EXTERNAL_SSE4(cpu_flags) && depth <= 8 && algorithm == SERIAL) {
47-
dsp->filter_row = ff_atadenoise_filter_row8_serial_sse4;
47+
if (ARCH_X86_64 && EXTERNAL_SSE4(cpu_flags) && depth <= 8 && algorithm == SERIAL && sigma[p] == INT16_MAX) {
48+
dsp->filter_row[p] = ff_atadenoise_filter_row8_serial_sse4;
49+
}
4850
}
4951
}

0 commit comments

Comments
 (0)