1 /*
2 * Copyright (c) 2017 Thomas Mundt <tmundt75@gmail.com>
3 * Copyright (c) 2011 Stefano Sabatini
4 * Copyright (c) 2010 Baptiste Coudurier
5 * Copyright (c) 2003 Michael Zucchi <notzed@ximian.com>
6 *
7 * This file is part of FFmpeg.
8 *
9 * FFmpeg is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * FFmpeg is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with FFmpeg if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 */
23
24 /**
25 * @file
26 * temporal field interlace filter, ported from MPlayer/libmpcodecs
27 */
28
37
38 #define OFFSET(x) offsetof(TInterlaceContext, x)
39 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
40
51
59
61 };
62
64
73
75 };
76
78
79 #define FULL_SCALE_YUVJ_FORMATS \
80 AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ440P
81
84 };
85
87 {1, 25},
88 {1, 30},
89 {1001, 30000},
90 };
91
104 };
105
107 ptrdiff_t mref, ptrdiff_t pref, int clip_max)
108 {
109 const uint8_t *srcp_above = srcp + mref;
110 const uint8_t *srcp_below = srcp + pref;
113 // this calculation is an integer representation of
114 // '0.5 * current + 0.25 * above + 0.25 * below'
115 // '1 +' is for rounding.
116 dstp[
i] = (1 + srcp[
i] + srcp[
i] + srcp_above[
i] + srcp_below[
i]) >> 2;
117 }
118 }
119
121 ptrdiff_t mref, ptrdiff_t pref, int clip_max)
122 {
123 uint16_t *dstp = (uint16_t *)dst8;
124 const uint16_t *srcp = (const uint16_t *)src8;
125 const uint16_t *srcp_above = srcp + mref / 2;
126 const uint16_t *srcp_below = srcp + pref / 2;
129 // this calculation is an integer representation of
130 // '0.5 * current + 0.25 * above + 0.25 * below'
131 // '1 +' is for rounding.
135 }
136 }
137
139 ptrdiff_t mref, ptrdiff_t pref, int clip_max)
140 {
141 const uint8_t *srcp_above = srcp + mref;
142 const uint8_t *srcp_below = srcp + pref;
143 const uint8_t *srcp_above2 = srcp + mref * 2;
144 const uint8_t *srcp_below2 = srcp + pref * 2;
145 int i, src_x, src_ab;
147 // this calculation is an integer representation of
148 // '0.75 * current + 0.25 * above + 0.25 * below - 0.125 * above2 - 0.125 * below2'
149 // '4 +' is for rounding.
150 src_x = srcp[
i] << 1;
151 src_ab = srcp_above[
i] + srcp_below[
i];
153 - srcp_above2[
i] - srcp_below2[
i]) >> 3);
154 // Prevent over-sharpening:
155 // dst must not exceed src when the average of above and below
156 // is less than src. And the other way around.
157 if (src_ab > src_x) {
158 if (dstp[
i] < srcp[
i])
160 }
else if (dstp[
i] > srcp[
i])
162 }
163 }
164
166 ptrdiff_t mref, ptrdiff_t pref, int clip_max)
167 {
168 uint16_t *dstp = (uint16_t *)dst8;
169 const uint16_t *srcp = (const uint16_t *)src8;
170 const uint16_t *srcp_above = srcp + mref / 2;
171 const uint16_t *srcp_below = srcp + pref / 2;
172 const uint16_t *srcp_above2 = srcp + mref;
173 const uint16_t *srcp_below2 = srcp + pref;
174 int i, dst_le, src_le, src_x, src_ab;
176 // this calculation is an integer representation of
177 // '0.75 * current + 0.25 * above + 0.25 * below - 0.125 * above2 - 0.125 * below2'
178 // '4 +' is for rounding.
180 src_x = src_le << 1;
182 dst_le =
av_clip((4 + ((src_le + src_x + src_ab) << 1)
185 // Prevent over-sharpening:
186 // dst must not exceed src when the average of above and below
187 // is less than src. And the other way around.
188 if (src_ab > src_x) {
189 if (dst_le < src_le)
191 else
193 } else if (dst_le > src_le) {
195 } else
197 }
198 }
199
201 {
203
209 }
210
212 {
220
221 tinterlace->
vsub =
desc->log2_chroma_h;
228
230 uint8_t black[4] = { 0, 0, 0, 16 };
235 }
237 /* limited range */
240 outlink->
w, outlink->
h, outlink->
format, 16);
245 }
246 /* full range */
249 outlink->
w, outlink->
h, outlink->
format, 16);
254 }
261 }
273 }
274
277 break;
278 }
282
287 else
289 #if ARCH_X86
291 #endif
295 else
297 #if ARCH_X86
299 #endif
300 }
301
306 }
307
312
313 return 0;
314 }
315
316 #define FIELD_UPPER 0
317 #define FIELD_LOWER 1
318 #define FIELD_UPPER_AND_LOWER 2
319
320 /**
321 * Copy picture field from src to dst.
322 *
323 * @param src_field copy from upper, lower field or both
324 * @param interleave leave a padding line between each copied line
325 * @param dst_field copy to upper or lower field,
326 * only meaningful when interleave is selected
327 * @param flags context flags
328 */
329 static inline
331 uint8_t *
dst[4],
int dst_linesize[4],
332 const uint8_t *
src[4],
int src_linesize[4],
336 {
339 int plane, vsub =
desc->log2_chroma_h;
342
343 for (plane = 0; plane <
desc->nb_components; plane++) {
344 int lines = plane == 1 || plane == 2 ?
AV_CEIL_RSHIFT(src_h, vsub) : src_h;
346 uint8_t *dstp =
dst[plane];
347 const uint8_t *srcp =
src[plane];
348 int srcp_linesize = src_linesize[plane] * k;
349 int dstp_linesize = dst_linesize[plane] * (
interleave ? 2 : 1);
350 int clip_max = (1 << tinterlace->
csp->
comp[plane].
depth) - 1;
351
354 srcp += src_linesize[plane];
356 dstp += dst_linesize[plane];
357 // Low-pass filtering is required when creating an interlaced destination from
358 // a progressive source which contains high-frequency vertical detail.
359 // Filtering will reduce interlace 'twitter' and Moire patterning.
362 for (
h = lines;
h > 0;
h--) {
363 ptrdiff_t pref = src_linesize[plane];
364 ptrdiff_t mref = -pref;
365 if (
h >= (lines - x)) mref = 0;
// there is no line above
366 else if (
h <= (1 + x)) pref = 0;
// there is no line below
367
368 tinterlace->
lowpass_line(dstp, cols, srcp, mref, pref, clip_max);
369 dstp += dstp_linesize;
370 srcp += srcp_linesize;
371 }
372 } else {
374 cols *= 2;
376 }
377 }
378 }
379
381 {
389
391 tinterlace->
cur = tinterlace->
next;
392 tinterlace->
next = picref;
393
395
396 cur = tinterlace->
cur;
397 next = tinterlace->
next;
398 /* we need at least two frames */
399 if (!tinterlace->
cur)
400 return 0;
401
402 switch (tinterlace->
mode) {
403 case MODE_MERGEX2:
/* move the odd frame into the upper field of the new image, even into
404 * the lower field, generating a double-height video at same framerate */
405 case MODE_MERGE:
/* move the odd frame into the upper field of the new image, even into
406 * the lower field, generating a double-height video at half framerate */
411 out->height = outlink->
h;
414
415 /* write odd frame lines into the upper field of the new frame */
420 /* write even frame lines into the lower field of the new frame */
427 break;
428
429 case MODE_DROP_ODD:
/* only output even frames, odd frames are dropped; height unchanged, half framerate */
430 case MODE_DROP_EVEN:
/* only output odd frames, even frames are dropped; height unchanged, half framerate */
435 break;
436
437 case MODE_PAD:
/* expand each frame to double height, but pad alternate
438 * lines with black; framerate unchanged */
443 out->height = outlink->
h;
445
448 /* copy upper and lower fields */
453 /* pad with black the other field */
458 break;
459
460 /* interleave upper/lower lines from odd frames with lower/upper lines from even frames,
461 * halving the frame rate and preserving image height */
466 "video is already interlaced, adjusting framerate only\n");
470 out->pts /= 2;
// adjust pts to new framerate
474 }
481 if (tff)
483 else
485
486 /* copy upper/lower field from cur */
492 /* copy lower/upper field from next */
494 (const uint8_t **)next->data, next->linesize,
499 break;
500 case MODE_INTERLACEX2:
/* re-interlace preserving image height, double frame rate */
501 /* output current frame first */
508
513
514 /* output mix of current and next frame */
521 if (tff)
523 else
525
527 out->pts = cur->
pts + next->pts;
528 else
530 /* write current frame second field lines into the second field of the new frame */
536 /* write next frame first field lines into the first field of the new frame */
538 (const uint8_t **)next->data, next->linesize,
542 break;
543 default:
545 }
546
551
553 }
554
556 {
558
561
567
568 return 0;
569 }
570
572 {
576 },
577 };
578
580 {
584 },
585 };
586
588 .
p.
name =
"tinterlace",
590 .p.priv_class = &tinterlace_class,
596 };
597
598
600 .
p.
name =
"interlace",
602 .p.priv_class = &interlace_class,
609 };