1 /*
2 * Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
3 *
4 * FFmpeg is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with FFmpeg; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19 /**
20 * @file
21 * Motion Compensation Deinterlacer
22 * Ported from MPlayer libmpcodecs/vf_mcdeint.c.
23 *
24 * Known Issues:
25 *
26 * The motion estimation is somewhat at the mercy of the input, if the
27 * input frames are created purely based on spatial interpolation then
28 * for example a thin black line or another random and not
29 * interpolateable pattern will cause problems.
30 * Note: completely ignoring the "unavailable" lines during motion
31 * estimation did not look any better, so the most obvious solution
32 * would be to improve tfields or penalize problematic motion vectors.
33 *
34 * If non iterative ME is used then snow currently ignores the OBMC
35 * window and as a result sometimes creates artifacts.
36 *
37 * Only past frames are used, we should ideally use future frames too,
38 * something like filtering the whole movie in forward and then
39 * backward direction seems like a interesting idea but the current
40 * filter framework is FAR from supporting such things.
41 *
42 * Combining the motion compensated image with the input image also is
43 * not as trivial as it seems, simple blindly taking even lines from
44 * one and odd ones from the other does not work at all as ME/MC
45 * sometimes has nothing in the previous frames which matches the
46 * current. The current algorithm has been found by trial and error
47 * and almost certainly can be improved...
48 */
49
56
63 };
64
68 };
69
77
78 #define OFFSET(x) offsetof(MCDeintContext, x)
79 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
80 #define CONST(name, help, val, unit) { name, help, 0, AV_OPT_TYPE_CONST, {.i64=val}, INT_MIN, INT_MAX, FLAGS, unit }
81
88
92
95 };
96
98
100 {
107
111 }
112
117 enc_ctx->
width = inlink->
w;
130
131 switch (mcdeint->
mode) {
141 }
142
145 if (ret < 0)
147
148 return 0;
149 }
150
152 {
154
158 }
159 }
160
162 {
165 };
166
168
169 return 0;
170 }
171
173 {
178 int x,
y, i,
ret, got_frame = 0;
179
181 if (!outpic) {
184 }
187
189
191 if (ret < 0)
193
195
196 for (i = 0; i < 3; i++) {
197 int is_chroma = !!i;
203
204 for (y = 0; y < h; y++) {
205 if ((y ^ mcdeint->
parity) & 1) {
206 for (x = 0; x < w; x++) {
210
211 if (y > 0 && y < h-1){
212 int is_edge = x < 3 || x > w-4;
213 int diff0 = filp[-fils] - srcp[-srcs];
214 int diff1 = filp[+fils] - srcp[+srcs];
216
217 #define DELTA(j) av_clip(j, -x, w-1-x)
218
219 #define GET_SCORE_EDGE(j)\
220 FFABS(srcp[-srcs+DELTA(-1+(j))] - srcp[+srcs+DELTA(-1-(j))])+\
221 FFABS(srcp[-srcs+DELTA(j) ] - srcp[+srcs+DELTA( -(j))])+\
222 FFABS(srcp[-srcs+DELTA(1+(j)) ] - srcp[+srcs+DELTA( 1-(j))])
223
224 #define GET_SCORE(j)\
225 FFABS(srcp[-srcs-1+(j)] - srcp[+srcs-1-(j)])+\
226 FFABS(srcp[-srcs +(j)] - srcp[+srcs -(j)])+\
227 FFABS(srcp[-srcs+1+(j)] - srcp[+srcs+1-(j)])
228
229 #define CHECK_EDGE(j)\
230 { int score = GET_SCORE_EDGE(j);\
231 if (score < spatial_score){\
232 spatial_score = score;\
233 diff0 = filp[-fils+DELTA(j)] - srcp[-srcs+DELTA(j)];\
234 diff1 = filp[+fils+DELTA(-(j))] - srcp[+srcs+DELTA(-(j))];\
235
236 #define CHECK(j)\
237 { int score = GET_SCORE(j);\
238 if (score < spatial_score){\
239 spatial_score= score;\
240 diff0 = filp[-fils+(j)] - srcp[-srcs+(j)];\
241 diff1 = filp[+fils-(j)] - srcp[+srcs-(j)];\
242
243 if (is_edge) {
247 } else {
249 CHECK(-1) CHECK(-2) }} }}
250 CHECK( 1) CHECK( 2) }} }}
251 }
252
253
254 if (diff0 + diff1 > 0)
261 }
262 }
263 }
264 }
265
267 if (!((
y ^ mcdeint->parity) & 1)) {
268 for (x = 0; x < w; x++) {
269 frame_dec->data[i][x +
y*fils] =
270 outpic ->data[i][x +
y*dsts] =
inpic->data[i][x +
y*srcs];
271 }
272 }
273 }
274 }
275 mcdeint->parity ^= 1;
276
283 }
285 }
286
288 {
293 },
295 };
296
298 {
301 },
303 };
304
313 .priv_class = &mcdeint_class,
314 };