2 * BobWeaver Deinterlacing Filter DSP functions
3 * Copyright (C) 2016 Thomas Mundt <loudmax@yahoo.de>
5 * Based on YADIF (Yet Another Deinterlacing Filter)
6 * Copyright (C) 2006-2011 Michael Niedermayer <michaelni@gmx.at>
7 * 2010 James Darnley <james.darnley@gmail.com>
9 * With use of Weston 3 Field Deinterlacing Filter algorithm
10 * Copyright (C) 2012 British Broadcasting Corporation, All Rights Reserved
11 * Author of de-interlace algorithm: Jim Easterbrook for BBC R&D
12 * Based on the process described by Martin Weston for BBC R&D
14 * This file is part of FFmpeg.
16 * FFmpeg is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU Lesser General Public
18 * License as published by the Free Software Foundation; either
19 * version 2.1 of the License, or (at your option) any later version.
21 * FFmpeg is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 * Lesser General Public License for more details.
26 * You should have received a copy of the GNU Lesser General Public
27 * License along with FFmpeg; if not, write to the Free Software
28 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
37 #include "libavutil/attributes.h"
38 #include "libavutil/common.h"
39 #include "libavutil/macros.h"
42 * Filter coefficients coef_lf and coef_hf taken from BBC PH-2071 (Weston 3 Field Deinterlacer).
43 * Used when there is spatial and temporal interpolation.
44 * Filter coefficients coef_sp are used when there is spatial interpolation only.
45 * Adjusted for matching visual sharpness impression of spatial and temporal interpolation.
47 static const uint16_t coef_lf
[2] = { 4309, 213 };
48 static const uint16_t coef_hf
[3] = { 5570, 3801, 1016 };
49 static const uint16_t coef_sp
[2] = { 5077, 981 };
52 #define FILTER_INTRA() \
53 for (x = 0; x < w; x++) { \
54 interpol = (coef_sp[0] * (cur[mrefs] + cur[prefs]) - coef_sp[1] * (cur[mrefs3] + cur[prefs3])) >> 13; \
55 dst[0] = av_clip(interpol, 0, clip_max); \
62 for (x = 0; x < w; x++) { \
64 int d = (prev2[0] + next2[0]) >> 1; \
66 int temporal_diff0 = FFABS(prev2[0] - next2[0]); \
67 int temporal_diff1 =(FFABS(prev[mrefs] - c) + FFABS(prev[prefs] - e)) >> 1; \
68 int temporal_diff2 =(FFABS(next[mrefs] - c) + FFABS(next[prefs] - e)) >> 1; \
69 int diff = FFMAX3(temporal_diff0 >> 1, temporal_diff1, temporal_diff2); \
75 #define SPAT_CHECK() \
76 int b = ((prev2[mrefs2] + next2[mrefs2]) >> 1) - c; \
77 int f = ((prev2[prefs2] + next2[prefs2]) >> 1) - e; \
80 int max = FFMAX3(de, dc, FFMIN(b, f)); \
81 int min = FFMIN3(de, dc, FFMAX(b, f)); \
82 diff = FFMAX3(diff, min, -max);
84 #define FILTER_LINE() \
86 if (FFABS(c - e) > temporal_diff0) { \
87 interpol = (((coef_hf[0] * (prev2[0] + next2[0]) \
88 - coef_hf[1] * (prev2[mrefs2] + next2[mrefs2] + prev2[prefs2] + next2[prefs2]) \
89 + coef_hf[2] * (prev2[mrefs4] + next2[mrefs4] + prev2[prefs4] + next2[prefs4])) >> 2) \
90 + coef_lf[0] * (c + e) - coef_lf[1] * (cur[mrefs3] + cur[prefs3])) >> 13; \
92 interpol = (coef_sp[0] * (c + e) - coef_sp[1] * (cur[mrefs3] + cur[prefs3])) >> 13; \
95 #define FILTER_EDGE() \
99 interpol = (c + e) >> 1;
102 if (interpol > d + diff) \
103 interpol = d + diff; \
104 else if (interpol < d - diff) \
105 interpol = d - diff; \
107 dst[0] = av_clip(interpol, 0, clip_max); \
118 void ff_bwdif_filter_intra_c(void *dst1
, const void *cur1
, int w
, int prefs
, int mrefs
,
119 int prefs3
, int mrefs3
, int parity
, int clip_max
)
122 const uint8_t *cur
= cur1
;
128 void ff_bwdif_filter_line_c(void *dst1
, const void *prev1
, const void *cur1
, const void *next1
,
129 int w
, int prefs
, int mrefs
, int prefs2
, int mrefs2
,
130 int prefs3
, int mrefs3
, int prefs4
, int mrefs4
,
131 int parity
, int clip_max
)
134 const uint8_t *prev
= prev1
;
135 const uint8_t *cur
= cur1
;
136 const uint8_t *next
= next1
;
137 const uint8_t *prev2
= parity
? prev
: cur
;
138 const uint8_t *next2
= parity
? cur
: next
;
146 void ff_bwdif_filter_edge_c(void *dst1
, const void *prev1
, const void *cur1
, const void *next1
,
147 int w
, int prefs
, int mrefs
, int prefs2
, int mrefs2
,
148 int parity
, int clip_max
, int spat
)
151 const uint8_t *prev
= prev1
;
152 const uint8_t *cur
= cur1
;
153 const uint8_t *next
= next1
;
154 const uint8_t *prev2
= parity
? prev
: cur
;
155 const uint8_t *next2
= parity
? cur
: next
;
163 static void filter_intra_16bit(void *dst1
, const void *cur1
, int w
, int prefs
, int mrefs
,
164 int prefs3
, int mrefs3
, int parity
, int clip_max
)
166 uint16_t *dst
= dst1
;
167 const uint16_t *cur
= cur1
;
173 static void filter_line_c_16bit(void *dst1
, const void *prev1
, const void *cur1
, const void *next1
,
174 int w
, int prefs
, int mrefs
, int prefs2
, int mrefs2
,
175 int prefs3
, int mrefs3
, int prefs4
, int mrefs4
,
176 int parity
, int clip_max
)
178 uint16_t *dst
= dst1
;
179 const uint16_t *prev
= prev1
;
180 const uint16_t *cur
= cur1
;
181 const uint16_t *next
= next1
;
182 const uint16_t *prev2
= parity
? prev
: cur
;
183 const uint16_t *next2
= parity
? cur
: next
;
191 static void filter_edge_16bit(void *dst1
, const void *prev1
, const void *cur1
, const void *next1
,
192 int w
, int prefs
, int mrefs
, int prefs2
, int mrefs2
,
193 int parity
, int clip_max
, int spat
)
195 uint16_t *dst
= dst1
;
196 const uint16_t *prev
= prev1
;
197 const uint16_t *cur
= cur1
;
198 const uint16_t *next
= next1
;
199 const uint16_t *prev2
= parity
? prev
: cur
;
200 const uint16_t *next2
= parity
? cur
: next
;
208 av_cold
void ff_bwdif_init_filter_line(BWDIFDSPContext
*s
, int bit_depth
)
212 s
->filter_intra
= filter_intra_16bit
;
213 s
->filter_line
= filter_line_c_16bit
;
214 s
->filter_edge
= filter_edge_16bit
;
216 s
->filter_intra
= ff_bwdif_filter_intra_c
;
217 s
->filter_line
= ff_bwdif_filter_line_c
;
218 s
->filter_edge
= ff_bwdif_filter_edge_c
;
222 ff_bwdif_init_x86(s
, bit_depth
);
224 ff_bwdif_init_aarch64(s
, bit_depth
);