FFmpeg
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/opt.h"
30 #include "libavutil/imgutils.h"
31 #include "libavutil/avassert.h"
32 #include "avfilter.h"
33 #include "internal.h"
34 #include "tinterlace.h"
35 
36 #define OFFSET(x) offsetof(TInterlaceContext, x)
37 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
38 
39 static const AVOption tinterlace_options[] = {
40  {"mode", "select interlace mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=MODE_MERGE}, 0, MODE_NB-1, FLAGS, "mode"},
41  {"merge", "merge fields", 0, AV_OPT_TYPE_CONST, {.i64=MODE_MERGE}, INT_MIN, INT_MAX, FLAGS, "mode"},
42  {"drop_even", "drop even fields", 0, AV_OPT_TYPE_CONST, {.i64=MODE_DROP_EVEN}, INT_MIN, INT_MAX, FLAGS, "mode"},
43  {"drop_odd", "drop odd fields", 0, AV_OPT_TYPE_CONST, {.i64=MODE_DROP_ODD}, INT_MIN, INT_MAX, FLAGS, "mode"},
44  {"pad", "pad alternate lines with black", 0, AV_OPT_TYPE_CONST, {.i64=MODE_PAD}, INT_MIN, INT_MAX, FLAGS, "mode"},
45  {"interleave_top", "interleave top and bottom fields", 0, AV_OPT_TYPE_CONST, {.i64=MODE_INTERLEAVE_TOP}, INT_MIN, INT_MAX, FLAGS, "mode"},
46  {"interleave_bottom", "interleave bottom and top fields", 0, AV_OPT_TYPE_CONST, {.i64=MODE_INTERLEAVE_BOTTOM}, INT_MIN, INT_MAX, FLAGS, "mode"},
47  {"interlacex2", "interlace fields from two consecutive frames", 0, AV_OPT_TYPE_CONST, {.i64=MODE_INTERLACEX2}, INT_MIN, INT_MAX, FLAGS, "mode"},
48  {"mergex2", "merge fields keeping same frame rate", 0, AV_OPT_TYPE_CONST, {.i64=MODE_MERGEX2}, INT_MIN, INT_MAX, FLAGS, "mode"},
49 
50  {"flags", "set flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, 0, INT_MAX, 0, "flags" },
51  {"low_pass_filter", "enable vertical low-pass filter", 0, AV_OPT_TYPE_CONST, {.i64 = TINTERLACE_FLAG_VLPF}, INT_MIN, INT_MAX, FLAGS, "flags" },
52  {"vlpf", "enable vertical low-pass filter", 0, AV_OPT_TYPE_CONST, {.i64 = TINTERLACE_FLAG_VLPF}, INT_MIN, INT_MAX, FLAGS, "flags" },
53  {"complex_filter", "enable complex vertical low-pass filter", 0, AV_OPT_TYPE_CONST, {.i64 = TINTERLACE_FLAG_CVLPF},INT_MIN, INT_MAX, FLAGS, "flags" },
54  {"cvlpf", "enable complex vertical low-pass filter", 0, AV_OPT_TYPE_CONST, {.i64 = TINTERLACE_FLAG_CVLPF},INT_MIN, INT_MAX, FLAGS, "flags" },
55  {"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, "flags" },
56  {"bypass_il", "bypass already interlaced frames", 0, AV_OPT_TYPE_CONST, {.i64 = TINTERLACE_FLAG_BYPASS_IL}, INT_MIN, INT_MAX, FLAGS, "flags" },
57 
58  {NULL}
59 };
60 
61 AVFILTER_DEFINE_CLASS(tinterlace);
62 
63 static const AVOption interlace_options[] = {
64  { "scan", "scanning mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64 = MODE_TFF}, 0, 1, FLAGS, "mode"},
65  { "tff", "top field first", 0, AV_OPT_TYPE_CONST, {.i64 = MODE_TFF}, INT_MIN, INT_MAX, FLAGS, .unit = "mode"},
66  { "bff", "bottom field first", 0, AV_OPT_TYPE_CONST, {.i64 = MODE_BFF}, INT_MIN, INT_MAX, FLAGS, .unit = "mode"},
67  { "lowpass", "set vertical low-pass filter", OFFSET(lowpass), AV_OPT_TYPE_INT, {.i64 = VLPF_LIN}, 0, 2, FLAGS, "lowpass" },
68  { "off", "disable vertical low-pass filter", 0, AV_OPT_TYPE_CONST, {.i64 = VLPF_OFF}, INT_MIN, INT_MAX, FLAGS, "lowpass" },
69  { "linear", "linear vertical low-pass filter", 0, AV_OPT_TYPE_CONST, {.i64 = VLPF_LIN}, INT_MIN, INT_MAX, FLAGS, "lowpass" },
70  { "complex", "complex vertical low-pass filter", 0, AV_OPT_TYPE_CONST, {.i64 = VLPF_CMP}, INT_MIN, INT_MAX, FLAGS, "lowpass" },
71 
72  { NULL }
73 };
74 
75 AVFILTER_DEFINE_CLASS(interlace);
76 
77 #define FULL_SCALE_YUVJ_FORMATS \
78  AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ440P
79 
80 static const enum AVPixelFormat full_scale_yuvj_pix_fmts[] = {
82 };
83 
84 static const AVRational standard_tbs[] = {
85  {1, 25},
86  {1, 30},
87  {1001, 30000},
88 };
89 
91 {
92  static const enum AVPixelFormat pix_fmts[] = {
104  };
105 
106  AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts);
107  if (!fmts_list)
108  return AVERROR(ENOMEM);
109  return ff_set_common_formats(ctx, fmts_list);
110 }
111 
112 static void lowpass_line_c(uint8_t *dstp, ptrdiff_t width, const uint8_t *srcp,
113  ptrdiff_t mref, ptrdiff_t pref, int clip_max)
114 {
115  const uint8_t *srcp_above = srcp + mref;
116  const uint8_t *srcp_below = srcp + pref;
117  int i;
118  for (i = 0; i < width; i++) {
119  // this calculation is an integer representation of
120  // '0.5 * current + 0.25 * above + 0.25 * below'
121  // '1 +' is for rounding.
122  dstp[i] = (1 + srcp[i] + srcp[i] + srcp_above[i] + srcp_below[i]) >> 2;
123  }
124 }
125 
126 static void lowpass_line_c_16(uint8_t *dst8, ptrdiff_t width, const uint8_t *src8,
127  ptrdiff_t mref, ptrdiff_t pref, int clip_max)
128 {
129  uint16_t *dstp = (uint16_t *)dst8;
130  const uint16_t *srcp = (const uint16_t *)src8;
131  const uint16_t *srcp_above = srcp + mref / 2;
132  const uint16_t *srcp_below = srcp + pref / 2;
133  int i, src_x;
134  for (i = 0; i < width; i++) {
135  // this calculation is an integer representation of
136  // '0.5 * current + 0.25 * above + 0.25 * below'
137  // '1 +' is for rounding.
138  src_x = av_le2ne16(srcp[i]) << 1;
139  dstp[i] = av_le2ne16((1 + src_x + av_le2ne16(srcp_above[i])
140  + av_le2ne16(srcp_below[i])) >> 2);
141  }
142 }
143 
144 static void lowpass_line_complex_c(uint8_t *dstp, ptrdiff_t width, const uint8_t *srcp,
145  ptrdiff_t mref, ptrdiff_t pref, int clip_max)
146 {
147  const uint8_t *srcp_above = srcp + mref;
148  const uint8_t *srcp_below = srcp + pref;
149  const uint8_t *srcp_above2 = srcp + mref * 2;
150  const uint8_t *srcp_below2 = srcp + pref * 2;
151  int i, src_x, src_ab;
152  for (i = 0; i < width; i++) {
153  // this calculation is an integer representation of
154  // '0.75 * current + 0.25 * above + 0.25 * below - 0.125 * above2 - 0.125 * below2'
155  // '4 +' is for rounding.
156  src_x = srcp[i] << 1;
157  src_ab = srcp_above[i] + srcp_below[i];
158  dstp[i] = av_clip_uint8((4 + ((srcp[i] + src_x + src_ab) << 1)
159  - srcp_above2[i] - srcp_below2[i]) >> 3);
160  // Prevent over-sharpening:
161  // dst must not exceed src when the average of above and below
162  // is less than src. And the other way around.
163  if (src_ab > src_x) {
164  if (dstp[i] < srcp[i])
165  dstp[i] = srcp[i];
166  } else if (dstp[i] > srcp[i])
167  dstp[i] = srcp[i];
168  }
169 }
170 
171 static void lowpass_line_complex_c_16(uint8_t *dst8, ptrdiff_t width, const uint8_t *src8,
172  ptrdiff_t mref, ptrdiff_t pref, int clip_max)
173 {
174  uint16_t *dstp = (uint16_t *)dst8;
175  const uint16_t *srcp = (const uint16_t *)src8;
176  const uint16_t *srcp_above = srcp + mref / 2;
177  const uint16_t *srcp_below = srcp + pref / 2;
178  const uint16_t *srcp_above2 = srcp + mref;
179  const uint16_t *srcp_below2 = srcp + pref;
180  int i, dst_le, src_le, src_x, src_ab;
181  for (i = 0; i < width; i++) {
182  // this calculation is an integer representation of
183  // '0.75 * current + 0.25 * above + 0.25 * below - 0.125 * above2 - 0.125 * below2'
184  // '4 +' is for rounding.
185  src_le = av_le2ne16(srcp[i]);
186  src_x = src_le << 1;
187  src_ab = av_le2ne16(srcp_above[i]) + av_le2ne16(srcp_below[i]);
188  dst_le = av_clip((4 + ((src_le + src_x + src_ab) << 1)
189  - av_le2ne16(srcp_above2[i])
190  - av_le2ne16(srcp_below2[i])) >> 3, 0, clip_max);
191  // Prevent over-sharpening:
192  // dst must not exceed src when the average of above and below
193  // is less than src. And the other way around.
194  if (src_ab > src_x) {
195  if (dst_le < src_le)
196  dstp[i] = av_le2ne16(src_le);
197  else
198  dstp[i] = av_le2ne16(dst_le);
199  } else if (dst_le > src_le) {
200  dstp[i] = av_le2ne16(src_le);
201  } else
202  dstp[i] = av_le2ne16(dst_le);
203  }
204 }
205 
207 {
208  TInterlaceContext *tinterlace = ctx->priv;
209 
210  av_frame_free(&tinterlace->cur );
211  av_frame_free(&tinterlace->next);
212  av_freep(&tinterlace->black_data[0]);
213 }
214 
215 static int config_out_props(AVFilterLink *outlink)
216 {
217  AVFilterContext *ctx = outlink->src;
218  AVFilterLink *inlink = outlink->src->inputs[0];
220  TInterlaceContext *tinterlace = ctx->priv;
221  int i;
222 
223  tinterlace->vsub = desc->log2_chroma_h;
224  outlink->w = inlink->w;
225  outlink->h = tinterlace->mode == MODE_MERGE || tinterlace->mode == MODE_PAD || tinterlace->mode == MODE_MERGEX2?
226  inlink->h*2 : inlink->h;
227  if (tinterlace->mode == MODE_MERGE || tinterlace->mode == MODE_PAD || tinterlace->mode == MODE_MERGEX2)
229  av_make_q(2, 1));
230 
231  if (tinterlace->mode == MODE_PAD) {
232  uint8_t black[4] = { 0, 0, 0, 16 };
233  int ret;
234  ff_draw_init(&tinterlace->draw, outlink->format, 0);
235  ff_draw_color(&tinterlace->draw, &tinterlace->color, black);
237  tinterlace->color.comp[0].u8[0] = 0;
238  ret = av_image_alloc(tinterlace->black_data, tinterlace->black_linesize,
239  outlink->w, outlink->h, outlink->format, 16);
240  if (ret < 0)
241  return ret;
242 
243  ff_fill_rectangle(&tinterlace->draw, &tinterlace->color, tinterlace->black_data,
244  tinterlace->black_linesize, 0, 0, outlink->w, outlink->h);
245  }
246  if (tinterlace->flags & (TINTERLACE_FLAG_VLPF | TINTERLACE_FLAG_CVLPF)
247  && !(tinterlace->mode == MODE_INTERLEAVE_TOP
248  || tinterlace->mode == MODE_INTERLEAVE_BOTTOM)) {
249  av_log(ctx, AV_LOG_WARNING, "low_pass_filter flags ignored with mode %d\n",
250  tinterlace->mode);
252  }
253  tinterlace->preout_time_base = inlink->time_base;
254  if (tinterlace->mode == MODE_INTERLACEX2) {
255  tinterlace->preout_time_base.den *= 2;
256  outlink->frame_rate = av_mul_q(inlink->frame_rate, (AVRational){2,1});
257  outlink->time_base = av_mul_q(inlink->time_base , (AVRational){1,2});
258  } else if (tinterlace->mode == MODE_MERGEX2) {
259  outlink->frame_rate = inlink->frame_rate;
260  outlink->time_base = inlink->time_base;
261  } else if (tinterlace->mode != MODE_PAD) {
262  outlink->frame_rate = av_mul_q(inlink->frame_rate, (AVRational){1,2});
263  outlink->time_base = av_mul_q(inlink->time_base , (AVRational){2,1});
264  }
265 
266  for (i = 0; i<FF_ARRAY_ELEMS(standard_tbs); i++){
267  if (!av_cmp_q(standard_tbs[i], outlink->time_base))
268  break;
269  }
270  if (i == FF_ARRAY_ELEMS(standard_tbs) ||
271  (tinterlace->flags & TINTERLACE_FLAG_EXACT_TB))
272  outlink->time_base = tinterlace->preout_time_base;
273 
274  tinterlace->csp = av_pix_fmt_desc_get(outlink->format);
275  if (tinterlace->flags & TINTERLACE_FLAG_CVLPF) {
276  if (tinterlace->csp->comp[0].depth > 8)
278  else
279  tinterlace->lowpass_line = lowpass_line_complex_c;
280  if (ARCH_X86)
281  ff_tinterlace_init_x86(tinterlace);
282  } else if (tinterlace->flags & TINTERLACE_FLAG_VLPF) {
283  if (tinterlace->csp->comp[0].depth > 8)
284  tinterlace->lowpass_line = lowpass_line_c_16;
285  else
286  tinterlace->lowpass_line = lowpass_line_c;
287  if (ARCH_X86)
288  ff_tinterlace_init_x86(tinterlace);
289  }
290 
291  av_log(ctx, AV_LOG_VERBOSE, "mode:%d filter:%s h:%d -> h:%d\n", tinterlace->mode,
292  (tinterlace->flags & TINTERLACE_FLAG_CVLPF) ? "complex" :
293  (tinterlace->flags & TINTERLACE_FLAG_VLPF) ? "linear" : "off",
294  inlink->h, outlink->h);
295 
296  return 0;
297 }
298 
299 #define FIELD_UPPER 0
300 #define FIELD_LOWER 1
301 #define FIELD_UPPER_AND_LOWER 2
302 
303 /**
304  * Copy picture field from src to dst.
305  *
306  * @param src_field copy from upper, lower field or both
307  * @param interleave leave a padding line between each copied line
308  * @param dst_field copy to upper or lower field,
309  * only meaningful when interleave is selected
310  * @param flags context flags
311  */
312 static inline
314  uint8_t *dst[4], int dst_linesize[4],
315  const uint8_t *src[4], int src_linesize[4],
316  enum AVPixelFormat format, int w, int src_h,
317  int src_field, int interleave, int dst_field,
318  int flags)
319 {
321  int hsub = desc->log2_chroma_w;
322  int plane, vsub = desc->log2_chroma_h;
323  int k = src_field == FIELD_UPPER_AND_LOWER ? 1 : 2;
324  int h;
325 
326  for (plane = 0; plane < desc->nb_components; plane++) {
327  int lines = plane == 1 || plane == 2 ? AV_CEIL_RSHIFT(src_h, vsub) : src_h;
328  int cols = plane == 1 || plane == 2 ? AV_CEIL_RSHIFT( w, hsub) : w;
329  uint8_t *dstp = dst[plane];
330  const uint8_t *srcp = src[plane];
331  int srcp_linesize = src_linesize[plane] * k;
332  int dstp_linesize = dst_linesize[plane] * (interleave ? 2 : 1);
333  int clip_max = (1 << tinterlace->csp->comp[plane].depth) - 1;
334 
335  lines = (lines + (src_field == FIELD_UPPER)) / k;
336  if (src_field == FIELD_LOWER)
337  srcp += src_linesize[plane];
338  if (interleave && dst_field == FIELD_LOWER)
339  dstp += dst_linesize[plane];
340  // Low-pass filtering is required when creating an interlaced destination from
341  // a progressive source which contains high-frequency vertical detail.
342  // Filtering will reduce interlace 'twitter' and Moire patterning.
344  int x = !!(flags & TINTERLACE_FLAG_CVLPF);
345  for (h = lines; h > 0; h--) {
346  ptrdiff_t pref = src_linesize[plane];
347  ptrdiff_t mref = -pref;
348  if (h >= (lines - x)) mref = 0; // there is no line above
349  else if (h <= (1 + x)) pref = 0; // there is no line below
350 
351  tinterlace->lowpass_line(dstp, cols, srcp, mref, pref, clip_max);
352  dstp += dstp_linesize;
353  srcp += srcp_linesize;
354  }
355  } else {
356  if (tinterlace->csp->comp[plane].depth > 8)
357  cols *= 2;
358  av_image_copy_plane(dstp, dstp_linesize, srcp, srcp_linesize, cols, lines);
359  }
360  }
361 }
362 
364 {
365  AVFilterContext *ctx = inlink->dst;
366  AVFilterLink *outlink = ctx->outputs[0];
367  TInterlaceContext *tinterlace = ctx->priv;
368  AVFrame *cur, *next, *out;
369  int field, tff, ret;
370 
371  av_frame_free(&tinterlace->cur);
372  tinterlace->cur = tinterlace->next;
373  tinterlace->next = picref;
374 
375  cur = tinterlace->cur;
376  next = tinterlace->next;
377  /* we need at least two frames */
378  if (!tinterlace->cur)
379  return 0;
380 
381  switch (tinterlace->mode) {
382  case MODE_MERGEX2: /* move the odd frame into the upper field of the new image, even into
383  * the lower field, generating a double-height video at same framerate */
384  case MODE_MERGE: /* move the odd frame into the upper field of the new image, even into
385  * the lower field, generating a double-height video at half framerate */
386  out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
387  if (!out)
388  return AVERROR(ENOMEM);
389  av_frame_copy_props(out, cur);
390  out->height = outlink->h;
391  out->interlaced_frame = 1;
392  out->top_field_first = 1;
394 
395  /* write odd frame lines into the upper field of the new frame */
396  copy_picture_field(tinterlace, out->data, out->linesize,
397  (const uint8_t **)cur->data, cur->linesize,
398  inlink->format, inlink->w, inlink->h,
399  FIELD_UPPER_AND_LOWER, 1, tinterlace->mode == MODE_MERGEX2 ? (1 + inlink->frame_count_out) & 1 ? FIELD_LOWER : FIELD_UPPER : FIELD_UPPER, tinterlace->flags);
400  /* write even frame lines into the lower field of the new frame */
401  copy_picture_field(tinterlace, out->data, out->linesize,
402  (const uint8_t **)next->data, next->linesize,
403  inlink->format, inlink->w, inlink->h,
404  FIELD_UPPER_AND_LOWER, 1, tinterlace->mode == MODE_MERGEX2 ? (1 + inlink->frame_count_out) & 1 ? FIELD_UPPER : FIELD_LOWER : FIELD_LOWER, tinterlace->flags);
405  if (tinterlace->mode != MODE_MERGEX2)
406  av_frame_free(&tinterlace->next);
407  break;
408 
409  case MODE_DROP_ODD: /* only output even frames, odd frames are dropped; height unchanged, half framerate */
410  case MODE_DROP_EVEN: /* only output odd frames, even frames are dropped; height unchanged, half framerate */
411  out = av_frame_clone(tinterlace->mode == MODE_DROP_EVEN ? cur : next);
412  if (!out)
413  return AVERROR(ENOMEM);
414  av_frame_free(&tinterlace->next);
415  break;
416 
417  case MODE_PAD: /* expand each frame to double height, but pad alternate
418  * lines with black; framerate unchanged */
419  out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
420  if (!out)
421  return AVERROR(ENOMEM);
422  av_frame_copy_props(out, cur);
423  out->height = outlink->h;
425 
426  field = (1 + outlink->frame_count_in) & 1 ? FIELD_UPPER : FIELD_LOWER;
427  /* copy upper and lower fields */
428  copy_picture_field(tinterlace, out->data, out->linesize,
429  (const uint8_t **)cur->data, cur->linesize,
430  inlink->format, inlink->w, inlink->h,
431  FIELD_UPPER_AND_LOWER, 1, field, tinterlace->flags);
432  /* pad with black the other field */
433  copy_picture_field(tinterlace, out->data, out->linesize,
434  (const uint8_t **)tinterlace->black_data, tinterlace->black_linesize,
435  inlink->format, inlink->w, inlink->h,
436  FIELD_UPPER_AND_LOWER, 1, !field, tinterlace->flags);
437  break;
438 
439  /* interleave upper/lower lines from odd frames with lower/upper lines from even frames,
440  * halving the frame rate and preserving image height */
441  case MODE_INTERLEAVE_TOP: /* top field first */
442  case MODE_INTERLEAVE_BOTTOM: /* bottom field first */
443  if ((tinterlace->flags & TINTERLACE_FLAG_BYPASS_IL) && cur->interlaced_frame) {
444  av_log(ctx, AV_LOG_WARNING,
445  "video is already interlaced, adjusting framerate only\n");
446  out = av_frame_clone(cur);
447  if (!out)
448  return AVERROR(ENOMEM);
449  out->pts /= 2; // adjust pts to new framerate
450  ret = ff_filter_frame(outlink, out);
451  return ret;
452  }
453  tff = tinterlace->mode == MODE_INTERLEAVE_TOP;
454  out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
455  if (!out)
456  return AVERROR(ENOMEM);
457  av_frame_copy_props(out, cur);
458  out->interlaced_frame = 1;
459  out->top_field_first = tff;
460 
461  /* copy upper/lower field from cur */
462  copy_picture_field(tinterlace, out->data, out->linesize,
463  (const uint8_t **)cur->data, cur->linesize,
464  inlink->format, inlink->w, inlink->h,
465  tff ? FIELD_UPPER : FIELD_LOWER, 1, tff ? FIELD_UPPER : FIELD_LOWER,
466  tinterlace->flags);
467  /* copy lower/upper field from next */
468  copy_picture_field(tinterlace, out->data, out->linesize,
469  (const uint8_t **)next->data, next->linesize,
470  inlink->format, inlink->w, inlink->h,
471  tff ? FIELD_LOWER : FIELD_UPPER, 1, tff ? FIELD_LOWER : FIELD_UPPER,
472  tinterlace->flags);
473  av_frame_free(&tinterlace->next);
474  break;
475  case MODE_INTERLACEX2: /* re-interlace preserving image height, double frame rate */
476  /* output current frame first */
477  out = av_frame_clone(cur);
478  if (!out)
479  return AVERROR(ENOMEM);
480  out->interlaced_frame = 1;
481  if (cur->pts != AV_NOPTS_VALUE)
482  out->pts = cur->pts*2;
483 
484  out->pts = av_rescale_q(out->pts, tinterlace->preout_time_base, outlink->time_base);
485  if ((ret = ff_filter_frame(outlink, out)) < 0)
486  return ret;
487 
488  /* output mix of current and next frame */
489  tff = next->top_field_first;
490  out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
491  if (!out)
492  return AVERROR(ENOMEM);
493  av_frame_copy_props(out, next);
494  out->interlaced_frame = 1;
495  out->top_field_first = !tff;
496 
497  if (next->pts != AV_NOPTS_VALUE && cur->pts != AV_NOPTS_VALUE)
498  out->pts = cur->pts + next->pts;
499  else
500  out->pts = AV_NOPTS_VALUE;
501  /* write current frame second field lines into the second field of the new frame */
502  copy_picture_field(tinterlace, out->data, out->linesize,
503  (const uint8_t **)cur->data, cur->linesize,
504  inlink->format, inlink->w, inlink->h,
505  tff ? FIELD_LOWER : FIELD_UPPER, 1, tff ? FIELD_LOWER : FIELD_UPPER,
506  tinterlace->flags);
507  /* write next frame first field lines into the first field of the new frame */
508  copy_picture_field(tinterlace, out->data, out->linesize,
509  (const uint8_t **)next->data, next->linesize,
510  inlink->format, inlink->w, inlink->h,
511  tff ? FIELD_UPPER : FIELD_LOWER, 1, tff ? FIELD_UPPER : FIELD_LOWER,
512  tinterlace->flags);
513  break;
514  default:
515  av_assert0(0);
516  }
517 
518  out->pts = av_rescale_q(out->pts, tinterlace->preout_time_base, outlink->time_base);
519  ret = ff_filter_frame(outlink, out);
520 
521  return ret;
522 }
523 
525 {
526  TInterlaceContext *tinterlace = ctx->priv;
527 
528  if (tinterlace->mode <= MODE_BFF)
529  tinterlace->mode += MODE_INTERLEAVE_TOP;
530 
531  tinterlace->flags |= TINTERLACE_FLAG_BYPASS_IL;
532  if (tinterlace->lowpass == VLPF_LIN)
533  tinterlace->flags |= TINTERLACE_FLAG_VLPF;
534  if (tinterlace->lowpass == VLPF_CMP)
535  tinterlace->flags |= TINTERLACE_FLAG_CVLPF;
536 
537  return 0;
538 }
539 
540 static const AVFilterPad tinterlace_inputs[] = {
541  {
542  .name = "default",
543  .type = AVMEDIA_TYPE_VIDEO,
544  .filter_frame = filter_frame,
545  },
546  { NULL }
547 };
548 
549 static const AVFilterPad tinterlace_outputs[] = {
550  {
551  .name = "default",
552  .type = AVMEDIA_TYPE_VIDEO,
553  .config_props = config_out_props,
554  },
555  { NULL }
556 };
557 
559  .name = "tinterlace",
560  .description = NULL_IF_CONFIG_SMALL("Perform temporal field interlacing."),
561  .priv_size = sizeof(TInterlaceContext),
562  .uninit = uninit,
564  .inputs = tinterlace_inputs,
565  .outputs = tinterlace_outputs,
566  .priv_class = &tinterlace_class,
567 };
568 
569 
571  .name = "interlace",
572  .description = NULL_IF_CONFIG_SMALL("Convert progressive video into interlaced."),
573  .priv_size = sizeof(TInterlaceContext),
574  .init = init_interlace,
575  .uninit = uninit,
577  .inputs = tinterlace_inputs,
578  .outputs = tinterlace_outputs,
579  .priv_class = &interlace_class,
580 };
int lowpass
legacy interlace filter lowpass mode
Definition: tinterlace.h:69
#define NULL
Definition: coverity.c:32
planar YUV 4:4:0,20bpp, (1 Cr & Cb sample per 1x2 Y samples), little-endian
Definition: pixfmt.h:275
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:78
static enum AVPixelFormat full_scale_yuvj_pix_fmts[]
Definition: vf_tinterlace.c:80
static int query_formats(AVFilterContext *ctx)
Definition: vf_tinterlace.c:90
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2573
This structure describes decoded (raw) audio or video data.
Definition: frame.h:308
#define OFFSET(x)
Definition: vf_tinterlace.c:36
AVOption.
Definition: opt.h:248
planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
Definition: pixfmt.h:159
const char * desc
Definition: libsvtav1.c:79
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:71
misc image utilities
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:200
#define TINTERLACE_FLAG_CVLPF
Definition: tinterlace.h:37
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)
Main libavfilter public API header.
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
AVFrame * next
Definition: tinterlace.h:72
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:216
#define FIELD_LOWER
static const AVOption interlace_options[]
Definition: vf_tinterlace.c:63
planar YUV 4:4:4 40bpp, (1 Cr & Cb sample per 1x1 Y & A samples, little-endian)
Definition: pixfmt.h:189
int mode
TInterlaceMode, interlace mode selected.
Definition: tinterlace.h:66
FFDrawContext draw
Definition: tinterlace.h:75
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition: video.c:99
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample format(the sample packing is implied by the sample format) and sample rate.The lists are not just lists
uint8_t log2_chroma_w
Amount to shift the luma width right to find the chroma width.
Definition: pixdesc.h:92
int flags
flags affecting interlacing algorithm
Definition: tinterlace.h:68
AVFilter ff_vf_tinterlace
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:287
#define FULL_SCALE_YUVJ_FORMATS
Definition: vf_tinterlace.c:77
const char * name
Pad name.
Definition: internal.h:60
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:117
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:347
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1091
planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
Definition: pixfmt.h:101
AVComponentDescriptor comp[4]
Parameters that describe how pixels are packed.
Definition: pixdesc.h:117
uint8_t
#define av_cold
Definition: attributes.h:88
AVFilter ff_vf_interlace
static const AVOption tinterlace_options[]
Definition: vf_tinterlace.c:39
temporal field interlace filter, ported from MPlayer/libmpcodecs
AVOptions.
planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
Definition: pixfmt.h:251
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:401
int black_linesize[4]
Definition: tinterlace.h:74
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)
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:210
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)
int interlaced_frame
The content of the picture is interlaced.
Definition: frame.h:455
int ff_fmt_is_in(int fmt, const int *fmts)
Tell if an integer is contained in the provided -1-terminated list of integers.
Definition: formats.c:258
#define av_log(a,...)
A filter pad used for either input or output.
Definition: internal.h:54
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:142
#define src
Definition: vp8dsp.c:254
planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
Definition: pixfmt.h:165
planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples)
Definition: pixfmt.h:176
int ff_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats)
A helper for query_formats() which sets all links to the same list of formats.
Definition: formats.c:588
uint8_t log2_chroma_h
Amount to shift the luma height right to find the chroma height.
Definition: pixdesc.h:101
void ff_tinterlace_init_x86(TInterlaceContext *interlace)
int vsub
chroma vertical subsampling
Definition: tinterlace.h:70
#define TINTERLACE_FLAG_VLPF
Definition: tinterlace.h:36
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:203
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this field
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:153
void * priv
private data for use by the filter
Definition: avfilter.h:354
#define FLAGS
Definition: vf_tinterlace.c:37
void ff_draw_color(FFDrawContext *draw, FFDrawColor *color, const uint8_t rgba[4])
Prepare a color.
Definition: drawutils.c:231
planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
Definition: pixfmt.h:161
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.
simple assert() macros that are a bit more flexible than ISO C assert().
uint8_t u8[16]
Definition: drawutils.h:67
AVFILTER_DEFINE_CLASS(tinterlace)
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:70
static int init_interlace(AVFilterContext *ctx)
uint8_t nb_components
The number of components each pixel has, (1-4)
Definition: pixdesc.h:83
#define FIELD_UPPER
union FFDrawColor::@209 comp[MAX_PLANES]
static av_cold void uninit(AVFilterContext *ctx)
#define width
uint8_t w
Definition: llviddspenc.c:38
AVFormatContext * ctx
Definition: movenc.c:48
planar YUV 4:2:0,18bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
Definition: pixfmt.h:243
static const AVFilterPad tinterlace_outputs[]
#define TINTERLACE_FLAG_BYPASS_IL
Definition: tinterlace.h:39
static int filter_frame(AVFilterLink *inlink, AVFrame *picref)
static const AVRational standard_tbs[]
Definition: vf_tinterlace.c:84
AVFrame * av_frame_clone(const AVFrame *src)
Create a new frame that references the same data as src.
Definition: frame.c:553
static const AVFilterPad outputs[]
Definition: af_acontrast.c:203
#define FF_ARRAY_ELEMS(a)
#define av_le2ne16(x)
Definition: bswap.h:95
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:339
planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples)
Definition: pixfmt.h:177
static AVRational av_make_q(int num, int den)
Create an AVRational.
Definition: rational.h:71
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:81
FFDrawColor color
Definition: tinterlace.h:76
AVRational sample_aspect_ratio
Sample aspect ratio for the video frame, 0/1 if unknown/unspecified.
Definition: frame.h:396
planar YUV 4:4:0,24bpp, (1 Cr & Cb sample per 1x2 Y samples), little-endian
Definition: pixfmt.h:277
uint8_t * black_data[4]
buffer used to fill padded lines
Definition: tinterlace.h:73
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several inputs
planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
Definition: pixfmt.h:72
Filter definition.
Definition: avfilter.h:145
Rational number (pair of numerator and denominator).
Definition: rational.h:58
const char * name
Filter name.
Definition: avfilter.h:149
int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags)
Init a draw context.
Definition: drawutils.c:178
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:351
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:300
AVFrame * cur
Definition: tinterlace.h:71
static const AVFilterPad tinterlace_inputs[]
planar YUV 4:2:2 30bpp, (1 Cr & Cb sample per 2x1 Y & A samples, little-endian)
Definition: pixfmt.h:187
#define flags(name, subs,...)
Definition: cbs_av1.c:560
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:322
The exact code depends on how similar the blocks are and how related they are to the and needs to apply these operations to the correct inlink or outlink if there are several Macros are available to factor that when no extra processing is inlink
static int av_cmp_q(AVRational a, AVRational b)
Compare two rationals.
Definition: rational.h:89
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:66
planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
Definition: pixfmt.h:247
Y , 8bpp.
Definition: pixfmt.h:74
const AVPixFmtDescriptor * csp
Definition: tinterlace.h:77
static int config_out_props(AVFilterLink *outlink)
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
Definition: pixfmt.h:73
int den
Denominator.
Definition: rational.h:60
planar YUV 4:2:0 25bpp, (1 Cr & Cb sample per 2x2 Y & A samples, little-endian)
Definition: pixfmt.h:185
#define TINTERLACE_FLAG_EXACT_TB
Definition: tinterlace.h:38
int top_field_first
If the content is interlaced, is top field displayed first.
Definition: frame.h:460
A list of supported formats for one end of a filter link.
Definition: formats.h:65
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:318
An instance of a filter.
Definition: avfilter.h:339
AVRational av_mul_q(AVRational b, AVRational c)
Multiply two rationals.
Definition: rational.c:80
int height
Definition: frame.h:366
FILE * out
Definition: movenc.c:54
#define av_freep(p)
planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
Definition: pixfmt.h:99
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:373
internal API functions
#define FIELD_UPPER_AND_LOWER
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Frame references ownership and permissions
int depth
Number of bits in the component.
Definition: pixdesc.h:58
AVRational preout_time_base
Definition: tinterlace.h:67
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
mode
Use these values in ebur128_init (or&#39;ed).
Definition: ebur128.h:83
static void hsub(htype *dst, const htype *src, int bins)
Definition: vf_median.c:75
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:671
int i
Definition: input.c:407
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:58