Skip to content

Commit cf1f574

Browse files
committed
lavfi/edge_common: Templatify ff_gaussian_blur and ff_sobel
1 parent 1001bdc commit cf1f574

File tree

5 files changed

+150
-86
lines changed

5 files changed

+150
-86
lines changed

libavfilter/edge_common.c

Lines changed: 6 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -46,33 +46,13 @@ static int get_rounded_direction(int gx, int gy)
4646
return DIRECTION_VERTICAL;
4747
}
4848

49-
// Simple sobel operator to get rounded gradients
50-
void ff_sobel(int w, int h,
51-
uint16_t *dst, int dst_linesize,
52-
int8_t *dir, int dir_linesize,
53-
const uint8_t *src, int src_linesize)
54-
{
55-
int i, j;
56-
57-
for (j = 1; j < h - 1; j++) {
58-
dst += dst_linesize;
59-
dir += dir_linesize;
60-
src += src_linesize;
61-
for (i = 1; i < w - 1; i++) {
62-
const int gx =
63-
-1*src[-src_linesize + i-1] + 1*src[-src_linesize + i+1]
64-
-2*src[ i-1] + 2*src[ i+1]
65-
-1*src[ src_linesize + i-1] + 1*src[ src_linesize + i+1];
66-
const int gy =
67-
-1*src[-src_linesize + i-1] + 1*src[ src_linesize + i-1]
68-
-2*src[-src_linesize + i ] + 2*src[ src_linesize + i ]
69-
-1*src[-src_linesize + i+1] + 1*src[ src_linesize + i+1];
49+
#undef DEPTH
50+
#define DEPTH 8
51+
#include "edge_template.c"
7052

71-
dst[i] = FFABS(gx) + FFABS(gy);
72-
dir[i] = get_rounded_direction(gx, gy);
73-
}
74-
}
75-
}
53+
#undef DEPTH
54+
#define DEPTH 16
55+
#include "edge_template.c"
7656

7757
// Filters rounded gradients to drop all non-maxima
7858
// Expects gradients generated by ff_sobel()
@@ -137,45 +117,3 @@ void ff_double_threshold(int low, int high, int w, int h,
137117
src += src_linesize;
138118
}
139119
}
140-
141-
// Applies gaussian blur, using 5x5 kernels, sigma = 1.4
142-
void ff_gaussian_blur(int w, int h,
143-
uint8_t *dst, int dst_linesize,
144-
const uint8_t *src, int src_linesize)
145-
{
146-
int i, j;
147-
148-
memcpy(dst, src, w); dst += dst_linesize; src += src_linesize;
149-
memcpy(dst, src, w); dst += dst_linesize; src += src_linesize;
150-
for (j = 2; j < h - 2; j++) {
151-
dst[0] = src[0];
152-
dst[1] = src[1];
153-
for (i = 2; i < w - 2; i++) {
154-
/* Gaussian mask of size 5x5 with sigma = 1.4 */
155-
dst[i] = ((src[-2*src_linesize + i-2] + src[2*src_linesize + i-2]) * 2
156-
+ (src[-2*src_linesize + i-1] + src[2*src_linesize + i-1]) * 4
157-
+ (src[-2*src_linesize + i ] + src[2*src_linesize + i ]) * 5
158-
+ (src[-2*src_linesize + i+1] + src[2*src_linesize + i+1]) * 4
159-
+ (src[-2*src_linesize + i+2] + src[2*src_linesize + i+2]) * 2
160-
161-
+ (src[ -src_linesize + i-2] + src[ src_linesize + i-2]) * 4
162-
+ (src[ -src_linesize + i-1] + src[ src_linesize + i-1]) * 9
163-
+ (src[ -src_linesize + i ] + src[ src_linesize + i ]) * 12
164-
+ (src[ -src_linesize + i+1] + src[ src_linesize + i+1]) * 9
165-
+ (src[ -src_linesize + i+2] + src[ src_linesize + i+2]) * 4
166-
167-
+ src[i-2] * 5
168-
+ src[i-1] * 12
169-
+ src[i ] * 15
170-
+ src[i+1] * 12
171-
+ src[i+2] * 5) / 159;
172-
}
173-
dst[i ] = src[i ];
174-
dst[i + 1] = src[i + 1];
175-
176-
dst += dst_linesize;
177-
src += src_linesize;
178-
}
179-
memcpy(dst, src, w); dst += dst_linesize; src += src_linesize;
180-
memcpy(dst, src, w);
181-
}

libavfilter/edge_common.h

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,14 @@ enum AVRoundedDirection {
4848
* @param src data pointers to source image
4949
* @param src_linesize linesizes for the source image
5050
*/
51-
void ff_sobel(int w, int h,
52-
uint16_t *dst, int dst_linesize,
53-
int8_t *dir, int dir_linesize,
54-
const uint8_t *src, int src_linesize);
51+
#define PROTO_SOBEL(depth) \
52+
void ff_sobel_##depth(int w, int h, \
53+
uint16_t *dst, int dst_linesize, \
54+
int8_t *dir, int dir_linesize, \
55+
const uint8_t *src, int src_linesize, int src_stride);
56+
57+
PROTO_SOBEL(8)
58+
PROTO_SOBEL(16)
5559

5660
/**
5761
* Filters rounded gradients to drop all non-maxima pixels in the magnitude image
@@ -100,8 +104,12 @@ void ff_double_threshold(int low, int high, int w, int h,
100104
* @param src data pointers to source image
101105
* @param src_linesize linesizes for the source image
102106
*/
103-
void ff_gaussian_blur(int w, int h,
104-
uint8_t *dst, int dst_linesize,
105-
const uint8_t *src, int src_linesize);
107+
#define PROTO_GAUSSIAN_BLUR(depth) \
108+
void ff_gaussian_blur_##depth(int w, int h, \
109+
uint8_t *dst, int dst_linesize, \
110+
const uint8_t *src, int src_linesize, int src_stride);
111+
112+
PROTO_GAUSSIAN_BLUR(8)
113+
PROTO_GAUSSIAN_BLUR(16)
106114

107115
#endif

libavfilter/edge_template.c

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/*
2+
* Copyright (c) 2022 Thilo Borgmann <thilo.borgmann _at_ mail.de>
3+
*
4+
* This file is part of FFmpeg.
5+
*
6+
* FFmpeg is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 2.1 of the License, or (at your option) any later version.
10+
*
11+
* FFmpeg is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public
17+
* License along with FFmpeg; if not, write to the Free Software
18+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19+
* Redistribution and use in source and binary forms, with or without modification,
20+
* are permitted provided that the following conditions are met:
21+
*/
22+
23+
#include "libavutil/avassert.h"
24+
#include "avfilter.h"
25+
#include "formats.h"
26+
#include "internal.h"
27+
#include "video.h"
28+
29+
#undef pixel
30+
#if DEPTH == 8
31+
#define pixel uint8_t
32+
#else
33+
#define pixel uint16_t
34+
#endif
35+
36+
#undef fn
37+
#undef fn2
38+
#undef fn3
39+
#define fn3(a,b) ff_##a##_##b
40+
#define fn2(a,b) fn3(a,b)
41+
#define fn(a) fn2(a, DEPTH)
42+
43+
void fn(sobel)(int w, int h,
44+
uint16_t *dst, int dst_linesize,
45+
int8_t *dir, int dir_linesize,
46+
const uint8_t *src, int src_linesize, int src_stride)
47+
{
48+
pixel *srcp = (pixel *)src;
49+
50+
src_stride /= sizeof(pixel);
51+
src_linesize /= sizeof(pixel);
52+
dst_linesize /= sizeof(pixel);
53+
54+
for (int j = 1; j < h - 1; j++) {
55+
dst += dst_linesize;
56+
dir += dir_linesize;
57+
srcp += src_linesize;
58+
for (int i = 1; i < w - 1; i++) {
59+
const int gx =
60+
-1*srcp[-src_linesize + (i-1)*src_stride] + 1*srcp[-src_linesize + (i+1)*src_stride]
61+
-2*srcp[ (i-1)*src_stride] + 2*srcp[ (i+1)*src_stride]
62+
-1*srcp[ src_linesize + (i-1)*src_stride] + 1*srcp[ src_linesize + (i+1)*src_stride];
63+
const int gy =
64+
-1*srcp[-src_linesize + (i-1)*src_stride] + 1*srcp[ src_linesize + (i-1)*src_stride]
65+
-2*srcp[-src_linesize + (i )*src_stride] + 2*srcp[ src_linesize + (i )*src_stride]
66+
-1*srcp[-src_linesize + (i+1)*src_stride] + 1*srcp[ src_linesize + (i+1)*src_stride];
67+
68+
dst[i] = FFABS(gx) + FFABS(gy);
69+
dir[i] = get_rounded_direction(gx, gy);
70+
}
71+
}
72+
}
73+
74+
void fn(gaussian_blur)(int w, int h,
75+
uint8_t *dst, int dst_linesize,
76+
const uint8_t *src, int src_linesize, int src_stride)
77+
{
78+
pixel *srcp = (pixel *)src;
79+
pixel *dstp = (pixel *)dst;
80+
81+
src_stride /= sizeof(pixel);
82+
src_linesize /= sizeof(pixel);
83+
dst_linesize /= sizeof(pixel);
84+
85+
memcpy(dstp, srcp, w*sizeof(pixel)); dstp += dst_linesize; srcp += src_linesize;
86+
memcpy(dstp, srcp, w*sizeof(pixel)); dstp += dst_linesize; srcp += src_linesize;
87+
for (int j = 2; j < h - 2; j++) {
88+
dstp[0] = srcp[(0)*src_stride];
89+
dstp[1] = srcp[(1)*src_stride];
90+
for (int i = 2; i < w - 2; i++) {
91+
/* Gaussian mask of size 5x5 with sigma = 1.4 */
92+
dstp[i] = ((srcp[-2*src_linesize + (i-2)*src_stride] + srcp[2*src_linesize + (i-2)*src_stride]) * 2
93+
+ (srcp[-2*src_linesize + (i-1)*src_stride] + srcp[2*src_linesize + (i-1)*src_stride]) * 4
94+
+ (srcp[-2*src_linesize + (i )*src_stride] + srcp[2*src_linesize + (i )*src_stride]) * 5
95+
+ (srcp[-2*src_linesize + (i+1)*src_stride] + srcp[2*src_linesize + (i+1)*src_stride]) * 4
96+
+ (srcp[-2*src_linesize + (i+2)*src_stride] + srcp[2*src_linesize + (i+2)*src_stride]) * 2
97+
98+
+ (srcp[ -src_linesize + (i-2)*src_stride] + srcp[ src_linesize + (i-2)*src_stride]) * 4
99+
+ (srcp[ -src_linesize + (i-1)*src_stride] + srcp[ src_linesize + (i-1)*src_stride]) * 9
100+
+ (srcp[ -src_linesize + (i )*src_stride] + srcp[ src_linesize + (i )*src_stride]) * 12
101+
+ (srcp[ -src_linesize + (i+1)*src_stride] + srcp[ src_linesize + (i+1)*src_stride]) * 9
102+
+ (srcp[ -src_linesize + (i+2)*src_stride] + srcp[ src_linesize + (i+2)*src_stride]) * 4
103+
104+
+ srcp[(i-2)*src_stride] * 5
105+
+ srcp[(i-1)*src_stride] * 12
106+
+ srcp[(i )*src_stride] * 15
107+
+ srcp[(i+1)*src_stride] * 12
108+
+ srcp[(i+2)*src_stride] * 5) / 159;
109+
}
110+
dstp[w - 2] = srcp[(w - 2)*src_stride];
111+
dstp[w - 1] = srcp[(w - 1)*src_stride];
112+
113+
dstp += dst_linesize;
114+
srcp += src_linesize;
115+
}
116+
memcpy(dstp, srcp, w*sizeof(pixel)); dstp += dst_linesize; srcp += src_linesize;
117+
memcpy(dstp, srcp, w*sizeof(pixel));
118+
}

libavfilter/vf_blurdetect.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -283,12 +283,12 @@ static int blurdetect_filter_frame(AVFilterLink *inlink, AVFrame *in)
283283
nplanes++;
284284

285285
// gaussian filter to reduce noise
286-
ff_gaussian_blur(w, h,
287-
filterbuf, w,
288-
in->data[plane], in->linesize[plane]);
286+
ff_gaussian_blur_8(w, h,
287+
filterbuf, w,
288+
in->data[plane], in->linesize[plane], 1);
289289

290290
// compute the 16-bits gradients and directions for the next step
291-
ff_sobel(w, h, gradients, w, directions, w, filterbuf, w);
291+
ff_sobel_8(w, h, gradients, w, directions, w, filterbuf, w, 1);
292292

293293
// non_maximum_suppression() will actually keep & clip what's necessary and
294294
// ignore the rest, so we need a clean output buffer

libavfilter/vf_edgedetect.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -191,15 +191,15 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
191191
}
192192

193193
/* gaussian filter to reduce noise */
194-
ff_gaussian_blur(width, height,
195-
tmpbuf, width,
196-
in->data[p], in->linesize[p]);
194+
ff_gaussian_blur_8(width, height,
195+
tmpbuf, width,
196+
in->data[p], in->linesize[p], 1);
197197

198198
/* compute the 16-bits gradients and directions for the next step */
199-
ff_sobel(width, height,
200-
gradients, width,
201-
directions,width,
202-
tmpbuf, width);
199+
ff_sobel_8(width, height,
200+
gradients, width,
201+
directions,width,
202+
tmpbuf, width, 1);
203203

204204
/* non_maximum_suppression() will actually keep & clip what's necessary and
205205
* ignore the rest, so we need a clean output buffer */

0 commit comments

Comments
 (0)