FFmpeg
Loading...
Searching...
No Matches
vf_tinterlace.c
Go to the documentation of this file.
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
29#include "libavutil/mem.h"
30#include "libavutil/opt.h"
31#include "libavutil/imgutils.h"
32#include "libavutil/avassert.h"
33#include "avfilter.h"
34#include "filters.h"
35#include "tinterlace.h"
36#include "video.h"
37
38#define OFFSET(x) offsetof(TInterlaceContext, x)
39#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
40
41static const AVOption tinterlace_options[] = {
42 {"mode", "select interlace mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=MODE_MERGE}, 0, MODE_NB-1, FLAGS, .unit = "mode"},
43 {"merge", "merge fields", 0, AV_OPT_TYPE_CONST, {.i64=MODE_MERGE}, INT_MIN, INT_MAX, FLAGS, .unit = "mode"},
44 {"drop_even", "drop even fields", 0, AV_OPT_TYPE_CONST, {.i64=MODE_DROP_EVEN}, INT_MIN, INT_MAX, FLAGS, .unit = "mode"},
45 {"drop_odd", "drop odd fields", 0, AV_OPT_TYPE_CONST, {.i64=MODE_DROP_ODD}, INT_MIN, INT_MAX, FLAGS, .unit = "mode"},
46 {"pad", "pad alternate lines with black", 0, AV_OPT_TYPE_CONST, {.i64=MODE_PAD}, INT_MIN, INT_MAX, FLAGS, .unit = "mode"},
47 {"interleave_top", "interleave top and bottom fields", 0, AV_OPT_TYPE_CONST, {.i64=MODE_INTERLEAVE_TOP}, INT_MIN, INT_MAX, FLAGS, .unit = "mode"},
48 {"interleave_bottom", "interleave bottom and top fields", 0, AV_OPT_TYPE_CONST, {.i64=MODE_INTERLEAVE_BOTTOM}, INT_MIN, INT_MAX, FLAGS, .unit = "mode"},
49 {"interlacex2", "interlace fields from two consecutive frames", 0, AV_OPT_TYPE_CONST, {.i64=MODE_INTERLACEX2}, INT_MIN, INT_MAX, FLAGS, .unit = "mode"},
50 {"mergex2", "merge fields keeping same frame rate", 0, AV_OPT_TYPE_CONST, {.i64=MODE_MERGEX2}, INT_MIN, INT_MAX, FLAGS, .unit = "mode"},
51
52 {"flags", "set flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, 0, INT_MAX, 0, .unit = "flags" },
53 {"low_pass_filter", "enable vertical low-pass filter", 0, AV_OPT_TYPE_CONST, {.i64 = TINTERLACE_FLAG_VLPF}, INT_MIN, INT_MAX, FLAGS, .unit = "flags" },
54 {"vlpf", "enable vertical low-pass filter", 0, AV_OPT_TYPE_CONST, {.i64 = TINTERLACE_FLAG_VLPF}, INT_MIN, INT_MAX, FLAGS, .unit = "flags" },
55 {"complex_filter", "enable complex vertical low-pass filter", 0, AV_OPT_TYPE_CONST, {.i64 = TINTERLACE_FLAG_CVLPF},INT_MIN, INT_MAX, FLAGS, .unit = "flags" },
56 {"cvlpf", "enable complex vertical low-pass filter", 0, AV_OPT_TYPE_CONST, {.i64 = TINTERLACE_FLAG_CVLPF},INT_MIN, INT_MAX, FLAGS, .unit = "flags" },
57 {"exact_tb", "force a timebase which can represent timestamps exactly", 0, AV_OPT_TYPE_CONST, {.i64 = TINTERLACE_FLAG_EXACT_TB}, INT_MIN, INT_MAX, FLAGS, .unit = "flags" },
58 {"bypass_il", "bypass already interlaced frames", 0, AV_OPT_TYPE_CONST, {.i64 = TINTERLACE_FLAG_BYPASS_IL}, INT_MIN, INT_MAX, FLAGS, .unit = "flags" },
59
60 {NULL}
61};
62
64
65static const AVOption interlace_options[] = {
66 { "scan", "scanning mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64 = MODE_TFF}, 0, 1, FLAGS, .unit = "mode"},
67 { "tff", "top field first", 0, AV_OPT_TYPE_CONST, {.i64 = MODE_TFF}, INT_MIN, INT_MAX, FLAGS, .unit = "mode"},
68 { "bff", "bottom field first", 0, AV_OPT_TYPE_CONST, {.i64 = MODE_BFF}, INT_MIN, INT_MAX, FLAGS, .unit = "mode"},
69 { "lowpass", "set vertical low-pass filter", OFFSET(lowpass), AV_OPT_TYPE_INT, {.i64 = VLPF_LIN}, 0, 2, FLAGS, .unit = "lowpass" },
70 { "off", "disable vertical low-pass filter", 0, AV_OPT_TYPE_CONST, {.i64 = VLPF_OFF}, INT_MIN, INT_MAX, FLAGS, .unit = "lowpass" },
71 { "linear", "linear vertical low-pass filter", 0, AV_OPT_TYPE_CONST, {.i64 = VLPF_LIN}, INT_MIN, INT_MAX, FLAGS, .unit = "lowpass" },
72 { "complex", "complex vertical low-pass filter", 0, AV_OPT_TYPE_CONST, {.i64 = VLPF_CMP}, INT_MIN, INT_MAX, FLAGS, .unit = "lowpass" },
73
74 { NULL }
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
85
86static const AVRational standard_tbs[] = {
87 {1, 25},
88 {1, 30},
89 {1001, 30000},
90};
91
105
106static void lowpass_line_c(uint8_t *dstp, ptrdiff_t width, const uint8_t *srcp,
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;
111 int i;
112 for (i = 0; i < width; i++) {
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
120static void lowpass_line_c_16(uint8_t *dst8, ptrdiff_t width, const uint8_t *src8,
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;
127 int i, src_x;
128 for (i = 0; i < width; i++) {
129 // this calculation is an integer representation of
130 // '0.5 * current + 0.25 * above + 0.25 * below'
131 // '1 +' is for rounding.
132 src_x = av_le2ne16(srcp[i]) << 1;
133 dstp[i] = av_le2ne16((1 + src_x + av_le2ne16(srcp_above[i])
134 + av_le2ne16(srcp_below[i])) >> 2);
135 }
136}
137
138static void lowpass_line_complex_c(uint8_t *dstp, ptrdiff_t width, const uint8_t *srcp,
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;
146 for (i = 0; i < width; i++) {
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];
152 dstp[i] = av_clip_uint8((4 + ((srcp[i] + src_x + src_ab) << 1)
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])
159 dstp[i] = srcp[i];
160 } else if (dstp[i] > srcp[i])
161 dstp[i] = srcp[i];
162 }
163}
164
165static void lowpass_line_complex_c_16(uint8_t *dst8, ptrdiff_t width, const uint8_t *src8,
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;
175 for (i = 0; i < width; i++) {
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.
179 src_le = av_le2ne16(srcp[i]);
180 src_x = src_le << 1;
181 src_ab = av_le2ne16(srcp_above[i]) + av_le2ne16(srcp_below[i]);
182 dst_le = av_clip((4 + ((src_le + src_x + src_ab) << 1)
183 - av_le2ne16(srcp_above2[i])
184 - av_le2ne16(srcp_below2[i])) >> 3, 0, clip_max);
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)
190 dstp[i] = av_le2ne16(src_le);
191 else
192 dstp[i] = av_le2ne16(dst_le);
193 } else if (dst_le > src_le) {
194 dstp[i] = av_le2ne16(src_le);
195 } else
196 dstp[i] = av_le2ne16(dst_le);
197 }
198}
199
201{
202 TInterlaceContext *tinterlace = ctx->priv;
203
204 av_frame_free(&tinterlace->cur );
205 av_frame_free(&tinterlace->next);
206 av_freep(&tinterlace->black_data[0][0]);
207 av_freep(&tinterlace->black_data[1][0]);
208 ff_ccfifo_uninit(&tinterlace->cc_fifo);
209}
210
211static int config_out_props(AVFilterLink *outlink)
212{
213 AVFilterContext *ctx = outlink->src;
214 AVFilterLink *inlink = outlink->src->inputs[0];
215 FilterLink *il = ff_filter_link(inlink);
216 FilterLink *ol = ff_filter_link(outlink);
218 TInterlaceContext *tinterlace = ctx->priv;
219 int ret, i;
220
221 tinterlace->vsub = desc->log2_chroma_h;
222 outlink->w = inlink->w;
223 outlink->h = tinterlace->mode == MODE_MERGE || tinterlace->mode == MODE_PAD || tinterlace->mode == MODE_MERGEX2?
224 inlink->h*2 : inlink->h;
225 if (tinterlace->mode == MODE_MERGE || tinterlace->mode == MODE_PAD || tinterlace->mode == MODE_MERGEX2)
227 av_make_q(2, 1));
228
229 if (tinterlace->mode == MODE_PAD) {
230 uint8_t black[4] = { 0, 0, 0, 16 };
231 ret = ff_draw_init_from_link(&tinterlace->draw, outlink, 0);
232 if (ret < 0) {
233 av_log(ctx, AV_LOG_ERROR, "Failed to initialize FFDrawContext\n");
234 return ret;
235 }
236 ff_draw_color(&tinterlace->draw, &tinterlace->color, black);
237 /* limited range */
239 ret = av_image_alloc(tinterlace->black_data[0], tinterlace->black_linesize,
240 outlink->w, outlink->h, outlink->format, 16);
241 if (ret < 0)
242 return ret;
243 ff_fill_rectangle(&tinterlace->draw, &tinterlace->color, tinterlace->black_data[0],
244 tinterlace->black_linesize, 0, 0, outlink->w, outlink->h);
245 }
246 /* full range */
247 tinterlace->color.comp[0].u8[0] = 0;
248 ret = av_image_alloc(tinterlace->black_data[1], tinterlace->black_linesize,
249 outlink->w, outlink->h, outlink->format, 16);
250 if (ret < 0)
251 return ret;
252 ff_fill_rectangle(&tinterlace->draw, &tinterlace->color, tinterlace->black_data[1],
253 tinterlace->black_linesize, 0, 0, outlink->w, outlink->h);
254 }
256 && !(tinterlace->mode == MODE_INTERLEAVE_TOP
257 || tinterlace->mode == MODE_INTERLEAVE_BOTTOM)) {
258 av_log(ctx, AV_LOG_WARNING, "low_pass_filter flags ignored with mode %d\n",
259 tinterlace->mode);
261 }
262 tinterlace->preout_time_base = inlink->time_base;
263 if (tinterlace->mode == MODE_INTERLACEX2) {
264 tinterlace->preout_time_base.den *= 2;
265 ol->frame_rate = av_mul_q(il->frame_rate, (AVRational){2,1});
266 outlink->time_base = av_mul_q(inlink->time_base , (AVRational){1,2});
267 } else if (tinterlace->mode == MODE_MERGEX2) {
268 ol->frame_rate = il->frame_rate;
269 outlink->time_base = inlink->time_base;
270 } else if (tinterlace->mode != MODE_PAD) {
271 ol->frame_rate = av_mul_q(il->frame_rate, (AVRational){1,2});
272 outlink->time_base = av_mul_q(inlink->time_base , (AVRational){2,1});
273 }
274
275 for (i = 0; i<FF_ARRAY_ELEMS(standard_tbs); i++){
276 if (!av_cmp_q(standard_tbs[i], outlink->time_base))
277 break;
278 }
279 if (i == FF_ARRAY_ELEMS(standard_tbs) ||
280 (tinterlace->flags & TINTERLACE_FLAG_EXACT_TB))
281 outlink->time_base = tinterlace->preout_time_base;
282
283 tinterlace->csp = av_pix_fmt_desc_get(outlink->format);
284 if (tinterlace->flags & TINTERLACE_FLAG_CVLPF) {
285 if (tinterlace->csp->comp[0].depth > 8)
287 else
289#if ARCH_X86 && HAVE_X86ASM
290 ff_tinterlace_init_x86(tinterlace);
291#endif
292 } else if (tinterlace->flags & TINTERLACE_FLAG_VLPF) {
293 if (tinterlace->csp->comp[0].depth > 8)
294 tinterlace->lowpass_line = lowpass_line_c_16;
295 else
296 tinterlace->lowpass_line = lowpass_line_c;
297#if ARCH_X86 && HAVE_X86ASM
298 ff_tinterlace_init_x86(tinterlace);
299#endif
300 }
301
302 ret = ff_ccfifo_init(&tinterlace->cc_fifo, ol->frame_rate, ctx);
303 if (ret < 0) {
304 av_log(ctx, AV_LOG_ERROR, "Failure to setup CC FIFO queue\n");
305 return ret;
306 }
307
308 av_log(ctx, AV_LOG_VERBOSE, "mode:%d filter:%s h:%d -> h:%d\n", tinterlace->mode,
309 (tinterlace->flags & TINTERLACE_FLAG_CVLPF) ? "complex" :
310 (tinterlace->flags & TINTERLACE_FLAG_VLPF) ? "linear" : "off",
311 inlink->h, outlink->h);
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 */
329static inline
331 uint8_t *dst[4], int dst_linesize[4],
332 const uint8_t *src[4], int src_linesize[4],
333 enum AVPixelFormat format, int w, int src_h,
334 int src_field, int interleave, int dst_field,
335 int flags)
336{
338 int hsub = desc->log2_chroma_w;
339 int plane, vsub = desc->log2_chroma_h;
340 int k = src_field == FIELD_UPPER_AND_LOWER ? 1 : 2;
341 int 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;
345 int cols = plane == 1 || plane == 2 ? AV_CEIL_RSHIFT( w, hsub) : w;
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
352 lines = (lines + (src_field == FIELD_UPPER)) / k;
353 if (src_field == FIELD_LOWER)
354 srcp += src_linesize[plane];
355 if (interleave && dst_field == FIELD_LOWER)
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.
361 int x = !!(flags & TINTERLACE_FLAG_CVLPF);
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 {
373 if (tinterlace->csp->comp[plane].depth > 8)
374 cols *= 2;
375 av_image_copy_plane(dstp, dstp_linesize, srcp, srcp_linesize, cols, lines);
376 }
377 }
378}
379
380static int filter_frame(AVFilterLink *inlink, AVFrame *picref)
381{
382 FilterLink *inl = ff_filter_link(inlink);
383 AVFilterContext *ctx = inlink->dst;
384 AVFilterLink *outlink = ctx->outputs[0];
385 FilterLink *l = ff_filter_link(outlink);
386 TInterlaceContext *tinterlace = ctx->priv;
387 AVFrame *cur, *next, *out;
388 int field, tff, full, ret;
389
390 av_frame_free(&tinterlace->cur);
391 tinterlace->cur = tinterlace->next;
392 tinterlace->next = picref;
393
394 ff_ccfifo_extract(&tinterlace->cc_fifo, picref);
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 */
407 out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
408 if (!out)
409 return AVERROR(ENOMEM);
411 out->height = outlink->h;
413 out->sample_aspect_ratio = av_mul_q(cur->sample_aspect_ratio, av_make_q(2, 1));
414
415 /* write odd frame lines into the upper field of the new frame */
416 copy_picture_field(tinterlace, out->data, out->linesize,
417 (const uint8_t **)cur->data, cur->linesize,
418 inlink->format, inlink->w, inlink->h,
419 FIELD_UPPER_AND_LOWER, 1, tinterlace->mode == MODE_MERGEX2 ? (1 + inl->frame_count_out) & 1 ? FIELD_LOWER : FIELD_UPPER : FIELD_UPPER, tinterlace->flags);
420 /* write even frame lines into the lower field of the new frame */
421 copy_picture_field(tinterlace, out->data, out->linesize,
422 (const uint8_t **)next->data, next->linesize,
423 inlink->format, inlink->w, inlink->h,
424 FIELD_UPPER_AND_LOWER, 1, tinterlace->mode == MODE_MERGEX2 ? (1 + inl->frame_count_out) & 1 ? FIELD_UPPER : FIELD_LOWER : FIELD_LOWER, tinterlace->flags);
425 if (tinterlace->mode != MODE_MERGEX2)
426 av_frame_free(&tinterlace->next);
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 */
431 out = av_frame_clone(tinterlace->mode == MODE_DROP_EVEN ? cur : next);
432 if (!out)
433 return AVERROR(ENOMEM);
434 av_frame_free(&tinterlace->next);
435 break;
436
437 case MODE_PAD: /* expand each frame to double height, but pad alternate
438 * lines with black; framerate unchanged */
439 out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
440 if (!out)
441 return AVERROR(ENOMEM);
443 out->height = outlink->h;
444 out->sample_aspect_ratio = av_mul_q(cur->sample_aspect_ratio, av_make_q(2, 1));
445
446 field = (1 + l->frame_count_in) & 1 ? FIELD_UPPER : FIELD_LOWER;
448 /* copy upper and lower fields */
449 copy_picture_field(tinterlace, out->data, out->linesize,
450 (const uint8_t **)cur->data, cur->linesize,
451 inlink->format, inlink->w, inlink->h,
452 FIELD_UPPER_AND_LOWER, 1, field, tinterlace->flags);
453 /* pad with black the other field */
454 copy_picture_field(tinterlace, out->data, out->linesize,
455 (const uint8_t **)tinterlace->black_data[full], tinterlace->black_linesize,
456 inlink->format, inlink->w, inlink->h,
457 FIELD_UPPER_AND_LOWER, 1, !field, tinterlace->flags);
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 */
462 case MODE_INTERLEAVE_TOP: /* top field first */
463 case MODE_INTERLEAVE_BOTTOM: /* bottom field first */
464 if ((tinterlace->flags & TINTERLACE_FLAG_BYPASS_IL) && (cur->flags & AV_FRAME_FLAG_INTERLACED)) {
466 "video is already interlaced, adjusting framerate only\n");
467 out = av_frame_clone(cur);
468 if (!out)
469 return AVERROR(ENOMEM);
470 out->pts /= 2; // adjust pts to new framerate
471 ff_ccfifo_inject(&tinterlace->cc_fifo, out);
472 ret = ff_filter_frame(outlink, out);
473 return ret;
474 }
475 tff = tinterlace->mode == MODE_INTERLEAVE_TOP;
476 out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
477 if (!out)
478 return AVERROR(ENOMEM);
481 if (tff)
483 else
485
486 /* copy upper/lower field from cur */
487 copy_picture_field(tinterlace, out->data, out->linesize,
488 (const uint8_t **)cur->data, cur->linesize,
489 inlink->format, inlink->w, inlink->h,
491 tinterlace->flags);
492 /* copy lower/upper field from next */
493 copy_picture_field(tinterlace, out->data, out->linesize,
494 (const uint8_t **)next->data, next->linesize,
495 inlink->format, inlink->w, inlink->h,
497 tinterlace->flags);
498 av_frame_free(&tinterlace->next);
499 break;
500 case MODE_INTERLACEX2: /* re-interlace preserving image height, double frame rate */
501 /* output current frame first */
502 out = av_frame_clone(cur);
503 if (!out)
504 return AVERROR(ENOMEM);
506 if (cur->pts != AV_NOPTS_VALUE)
507 out->pts = cur->pts*2;
508
509 out->pts = av_rescale_q(out->pts, tinterlace->preout_time_base, outlink->time_base);
510 ff_ccfifo_inject(&tinterlace->cc_fifo, out);
511 if ((ret = ff_filter_frame(outlink, out)) < 0)
512 return ret;
513
514 /* output mix of current and next frame */
515 tff = !!(next->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST);
516 out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
517 if (!out)
518 return AVERROR(ENOMEM);
521 if (tff)
523 else
525
526 if (next->pts != AV_NOPTS_VALUE && cur->pts != AV_NOPTS_VALUE)
527 out->pts = cur->pts + next->pts;
528 else
529 out->pts = AV_NOPTS_VALUE;
530 /* write current frame second field lines into the second field of the new frame */
531 copy_picture_field(tinterlace, out->data, out->linesize,
532 (const uint8_t **)cur->data, cur->linesize,
533 inlink->format, inlink->w, inlink->h,
535 tinterlace->flags);
536 /* write next frame first field lines into the first field of the new frame */
537 copy_picture_field(tinterlace, out->data, out->linesize,
538 (const uint8_t **)next->data, next->linesize,
539 inlink->format, inlink->w, inlink->h,
541 tinterlace->flags);
542 break;
543 default:
544 av_assert0(0);
545 }
546
547 out->pts = av_rescale_q(out->pts, tinterlace->preout_time_base, outlink->time_base);
548 out->duration = av_rescale_q(1, av_inv_q(l->frame_rate), outlink->time_base);
549 ff_ccfifo_inject(&tinterlace->cc_fifo, out);
550 ret = ff_filter_frame(outlink, out);
551
552 return ret;
553}
554
556{
557 TInterlaceContext *tinterlace = ctx->priv;
558
559 if (tinterlace->mode <= MODE_BFF)
560 tinterlace->mode += MODE_INTERLEAVE_TOP;
561
562 tinterlace->flags |= TINTERLACE_FLAG_BYPASS_IL;
563 if (tinterlace->lowpass == VLPF_LIN)
564 tinterlace->flags |= TINTERLACE_FLAG_VLPF;
565 if (tinterlace->lowpass == VLPF_CMP)
566 tinterlace->flags |= TINTERLACE_FLAG_CVLPF;
567
568 return 0;
569}
570
572 {
573 .name = "default",
574 .type = AVMEDIA_TYPE_VIDEO,
575 .filter_frame = filter_frame,
576 },
577};
578
580 {
581 .name = "default",
582 .type = AVMEDIA_TYPE_VIDEO,
583 .config_props = config_out_props,
584 },
585};
586
588 .p.name = "tinterlace",
589 .p.description = NULL_IF_CONFIG_SMALL("Perform temporal field interlacing."),
590 .p.priv_class = &tinterlace_class,
591 .priv_size = sizeof(TInterlaceContext),
592 .uninit = uninit,
596};
597
598
600 .p.name = "interlace",
601 .p.description = NULL_IF_CONFIG_SMALL("Convert progressive video into interlaced."),
602 .p.priv_class = &interlace_class,
603 .priv_size = sizeof(TInterlaceContext),
605 .uninit = uninit,
609};
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition dsp.h:87
static const char *const format[]
Definition af_aiir.c:444
@ lowpass
Definition af_biquads.c:87
const FFFilter ff_vf_interlace
const FFFilter ff_vf_tinterlace
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition avassert.h:42
@ MODE_NB
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition avfilter.c:1068
Main libavfilter public API header.
#define av_le2ne16(x)
Definition bswap.h:91
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define FLAGS
Definition cmdutils.c:598
#define AV_CEIL_RSHIFT(a, b)
Definition common.h:60
#define av_clip
Definition common.h:100
#define av_clip_uint8
Definition common.h:106
#define NULL
Definition coverity.c:32
static int filter_frame(DBEDecodeContext *s, AVFrame *frame)
Definition dolby_e.c:1067
void ff_draw_color(FFDrawContext *draw, FFDrawColor *color, const uint8_t rgba[4])
Prepare a color.
Definition drawutils.c:179
void ff_fill_rectangle(FFDrawContext *draw, FFDrawColor *color, uint8_t *dst[], int dst_linesize[], int dst_x, int dst_y, int w, int h)
Fill a rectangle with an uniform color.
Definition drawutils.c:258
int ff_draw_init_from_link(FFDrawContext *draw, const AVFilterLink *link, unsigned flags)
Init a draw context, taking the format, colorspace and range from the given filter link.
Definition drawutils.c:168
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
Definition opt.h:298
@ AV_OPT_TYPE_FLAGS
Underlying C type is unsigned int.
Definition opt.h:254
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition opt.h:258
#define AVERROR(e)
Definition error.h:45
#define AV_FRAME_FLAG_INTERLACED
A flag to mark frames whose content is interlaced.
Definition frame.h:695
#define AV_FRAME_FLAG_TOP_FIELD_FIRST
A flag to mark frames where the top field is displayed first if the content is interlaced.
Definition frame.h:700
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition frame.c:64
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition frame.c:599
AVFrame * av_frame_clone(const AVFrame *src)
Create a new frame that references the same data as src.
Definition frame.c:483
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
#define AV_LOG_VERBOSE
Detailed information.
Definition log.h:226
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
AVRational av_mul_q(AVRational b, AVRational c)
Multiply two rationals.
Definition rational.c:80
static AVRational av_make_q(int num, int den)
Create an AVRational.
Definition rational.h:71
static int av_cmp_q(AVRational a, AVRational b)
Compare two rationals.
Definition rational.h:89
static av_always_inline AVRational av_inv_q(AVRational q)
Invert a rational.
Definition rational.h:159
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
void av_image_copy_plane(uint8_t *dst, int dst_linesize, const uint8_t *src, int src_linesize, int bytewidth, int height)
Copy image plane from src to dst.
Definition imgutils.c:374
int av_image_alloc(uint8_t *pointers[4], int linesizes[4], int w, int h, enum AVPixelFormat pix_fmt, int align)
Allocate an image with size w and h and pixel format pix_fmt, and fill pointers and linesizes accordi...
Definition imgutils.c:218
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition avutil.h:247
misc image utilities
static av_cold void uninit(AVBitStreamFilterContext *ctx)
int ff_ccfifo_inject(CCFifo *ccf, AVFrame *frame)
Insert CC data from the FIFO into an AVFrame (as side data)
Definition ccfifo.c:133
int ff_ccfifo_init(CCFifo *ccf, AVRational framerate, void *log_ctx)
Initialize a CCFifo.
Definition ccfifo.c:53
void ff_ccfifo_uninit(CCFifo *ccf)
Free all memory allocated in a CCFifo and clear the context.
Definition ccfifo.c:46
int ff_ccfifo_extract(CCFifo *ccf, AVFrame *frame)
Extract CC data from an AVFrame.
Definition ccfifo.c:183
#define FILTER_INPUTS(array)
Definition filters.h:264
#define FILTER_OUTPUTS(array)
Definition filters.h:265
int ff_pixfmt_is_in(enum AVPixelFormat fmt, const enum AVPixelFormat *fmts)
Tell if a pixel format is contained in the provided AV_PIX_FMT_NONE-terminated list.
Definition formats.c:471
#define FILTER_PIXFMTS_ARRAY(array)
Definition filters.h:244
static FilterLink * ff_filter_link(AVFilterLink *link)
Definition filters.h:199
#define AVFILTER_DEFINE_CLASS(fname)
Definition filters.h:478
#define av_cold
Definition attributes.h:117
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition internal.h:88
static enum AVPixelFormat pix_fmts[]
Definition libkvazaar.c:296
const char * desc
Definition libsvtav1.c:83
uint8_t w
Definition llvidencdsp.c:39
Memory handling functions.
AVOptions.
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3460
@ AVCOL_RANGE_JPEG
Full range content.
Definition pixfmt.h:783
AVPixelFormat
Pixel format.
Definition pixfmt.h:71
@ AV_PIX_FMT_NONE
Definition pixfmt.h:72
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition pixfmt.h:73
@ AV_PIX_FMT_YUV440P
planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
Definition pixfmt.h:106
@ AV_PIX_FMT_YUVA444P10LE
planar YUV 4:4:4 40bpp, (1 Cr & Cb sample per 1x1 Y & A samples, little-endian)
Definition pixfmt.h:186
@ AV_PIX_FMT_YUV422P
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition pixfmt.h:77
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition pixfmt.h:81
@ AV_PIX_FMT_YUVA420P10LE
planar YUV 4:2:0 25bpp, (1 Cr & Cb sample per 2x2 Y & A samples, little-endian)
Definition pixfmt.h:182
@ AV_PIX_FMT_YUVA420P
planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
Definition pixfmt.h:108
@ AV_PIX_FMT_YUVA422P10LE
planar YUV 4:2:2 30bpp, (1 Cr & Cb sample per 2x1 Y & A samples, little-endian)
Definition pixfmt.h:184
@ AV_PIX_FMT_YUV420P10LE
planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
Definition pixfmt.h:156
@ AV_PIX_FMT_YUV410P
planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
Definition pixfmt.h:79
@ AV_PIX_FMT_YUV411P
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
Definition pixfmt.h:80
@ AV_PIX_FMT_YUV422P12LE
planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
Definition pixfmt.h:272
@ AV_PIX_FMT_YUV440P12LE
planar YUV 4:4:0,24bpp, (1 Cr & Cb sample per 1x2 Y samples), little-endian
Definition pixfmt.h:300
@ AV_PIX_FMT_YUV444P
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition pixfmt.h:78
@ AV_PIX_FMT_YUVA444P
planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples)
Definition pixfmt.h:174
@ AV_PIX_FMT_YUV420P12LE
planar YUV 4:2:0,18bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
Definition pixfmt.h:268
@ AV_PIX_FMT_YUV422P10LE
planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
Definition pixfmt.h:158
@ AV_PIX_FMT_YUVA422P
planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples)
Definition pixfmt.h:173
@ AV_PIX_FMT_YUV440P10LE
planar YUV 4:4:0,20bpp, (1 Cr & Cb sample per 1x2 Y samples), little-endian
Definition pixfmt.h:298
@ AV_PIX_FMT_YUV444P10LE
planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
Definition pixfmt.h:162
@ AV_PIX_FMT_YUV444P12LE
planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
Definition pixfmt.h:276
#define FF_ARRAY_ELEMS(a)
int depth
Number of bits in the component.
Definition pixdesc.h:57
An instance of a filter.
Definition avfilter.h:273
AVFilterLink ** inputs
array of pointers to input links
Definition avfilter.h:281
A filter pad used for either input or output.
Definition filters.h:40
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition frame.h:574
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition frame.h:493
int flags
Frame flags, a combination of AV_FRAME_FLAGS.
Definition frame.h:716
AVRational sample_aspect_ratio
Sample aspect ratio for the video frame, 0/1 if unknown/unspecified.
Definition frame.h:569
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Definition frame.h:517
AVOption.
Definition opt.h:428
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition pixdesc.h:69
AVComponentDescriptor comp[4]
Parameters that describe how pixels are packed.
Definition pixdesc.h:105
Rational number (pair of numerator and denominator).
Definition rational.h:58
int den
Denominator.
Definition rational.h:60
union FFDrawColor::@125210232202265035037051142373134026157344251103 comp[MAX_PLANES]
uint8_t u8[16]
Definition drawutils.h:57
AVRational preout_time_base
Definition tinterlace.h:68
int black_linesize[4]
Definition tinterlace.h:75
const AVPixFmtDescriptor * csp
Definition tinterlace.h:78
FFDrawColor color
Definition tinterlace.h:77
uint8_t * black_data[2][4]
buffer used to fill padded lines (limited/full)
Definition tinterlace.h:74
void(* lowpass_line)(uint8_t *dstp, ptrdiff_t width, const uint8_t *srcp, ptrdiff_t mref, ptrdiff_t pref, int clip_max)
Definition tinterlace.h:79
int flags
flags affecting interlacing algorithm
Definition tinterlace.h:69
int lowpass
legacy interlace filter lowpass mode
Definition tinterlace.h:70
int vsub
chroma vertical subsampling
Definition tinterlace.h:71
int mode
TInterlaceMode, interlace mode selected.
Definition tinterlace.h:67
FFDrawContext draw
Definition tinterlace.h:76
Definition swscale.c:71
#define av_freep(p)
#define av_log(a,...)
#define src
Definition vp8dsp.c:248
static FILE * out
Definition movenc.c:55
static AVFormatContext * ctx
Definition movenc.c:49
#define width
Definition dsp.h:89
temporal field interlace filter, ported from MPlayer/libmpcodecs
#define TINTERLACE_FLAG_BYPASS_IL
Definition tinterlace.h:40
#define TINTERLACE_FLAG_EXACT_TB
Definition tinterlace.h:39
void ff_tinterlace_init_x86(TInterlaceContext *interlace)
#define TINTERLACE_FLAG_VLPF
Definition tinterlace.h:37
@ MODE_MERGEX2
Definition tinterlace.h:56
@ MODE_DROP_EVEN
Definition tinterlace.h:50
@ MODE_INTERLEAVE_BOTTOM
Definition tinterlace.h:54
@ MODE_INTERLACEX2
Definition tinterlace.h:55
@ MODE_MERGE
Definition tinterlace.h:49
@ MODE_DROP_ODD
Definition tinterlace.h:51
@ MODE_PAD
Definition tinterlace.h:52
@ MODE_INTERLEAVE_TOP
Definition tinterlace.h:53
@ VLPF_OFF
Definition tinterlace.h:43
@ VLPF_LIN
Definition tinterlace.h:44
@ VLPF_CMP
Definition tinterlace.h:45
#define TINTERLACE_FLAG_CVLPF
Definition tinterlace.h:38
@ MODE_BFF
Definition tinterlace.h:62
@ MODE_TFF
Definition tinterlace.h:61
char full[32]
static int config_out_props(AVFilterLink *outlink)
Definition vf_dejudder.c:79
static void interleave(uint8_t *dst, uint8_t *src, int w, int h, int dst_linesize, int src_linesize, enum FilterMode mode, int swap)
Definition vf_il.c:113
static void hsub(htype *dst, const htype *src, int bins)
Definition vf_median.c:74
static enum AVPixelFormat full_scale_yuvj_pix_fmts[]
static int init_interlace(AVFilterContext *ctx)
#define FULL_SCALE_YUVJ_FORMATS
static void copy_picture_field(TInterlaceContext *tinterlace, uint8_t *dst[4], int dst_linesize[4], const uint8_t *src[4], int src_linesize[4], enum AVPixelFormat format, int w, int src_h, int src_field, int interleave, int dst_field, int flags)
Copy picture field from src to dst.
#define FIELD_UPPER_AND_LOWER
static const AVOption tinterlace_options[]
static void lowpass_line_c(uint8_t *dstp, ptrdiff_t width, const uint8_t *srcp, ptrdiff_t mref, ptrdiff_t pref, int clip_max)
static void lowpass_line_complex_c(uint8_t *dstp, ptrdiff_t width, const uint8_t *srcp, ptrdiff_t mref, ptrdiff_t pref, int clip_max)
static const AVRational standard_tbs[]
static const AVOption interlace_options[]
static void lowpass_line_c_16(uint8_t *dst8, ptrdiff_t width, const uint8_t *src8, ptrdiff_t mref, ptrdiff_t pref, int clip_max)
#define FIELD_LOWER
#define FIELD_UPPER
static av_cold void uninit(AVFilterContext *ctx)
static void lowpass_line_complex_c_16(uint8_t *dst8, ptrdiff_t width, const uint8_t *src8, ptrdiff_t mref, ptrdiff_t pref, int clip_max)
static const AVFilterPad tinterlace_inputs[]
static const AVFilterPad tinterlace_outputs[]
#define OFFSET(x)
static int config_out_props(AVFilterLink *outlink)
static int filter_frame(AVFilterLink *inlink, AVFrame *picref)
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition video.c:89