vf_interlace.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2003 Michael Zucchi <notzed@ximian.com>
3  * Copyright (c) 2010 Baptiste Coudurier
4  * Copyright (c) 2011 Stefano Sabatini
5  * Copyright (c) 2013 Vittorio Giovara <vittorio.giovara@gmail.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  * progressive to interlaced content filter, inspired by heavy debugging of tinterlace filter
27  */
28 
29 #include "libavutil/common.h"
30 #include "libavutil/opt.h"
31 #include "libavutil/imgutils.h"
32 #include "libavutil/avassert.h"
33 
34 #include "formats.h"
35 #include "avfilter.h"
36 #include "internal.h"
37 #include "video.h"
38 
39 enum ScanMode {
40  MODE_TFF = 0,
41  MODE_BFF = 1,
42 };
43 
44 enum FieldType {
47 };
48 
49 typedef struct {
50  const AVClass *class;
51  enum ScanMode scan; // top or bottom field first scanning
52  int lowpass; // enable or disable low pass filterning
53  AVFrame *cur, *next; // the two frames from which the new one is obtained
54  int got_output; // signal an output frame is reday to request_frame()
56 
57 #define OFFSET(x) offsetof(InterlaceContext, x)
58 #define V AV_OPT_FLAG_VIDEO_PARAM
59 static const AVOption options[] = {
60  { "scan", "scanning mode", OFFSET(scan),
61  AV_OPT_TYPE_INT, {.i64 = MODE_TFF }, 0, 1, .flags = V, .unit = "scan" },
62  { "tff", "top field first", 0,
63  AV_OPT_TYPE_CONST, {.i64 = MODE_TFF }, INT_MIN, INT_MAX, .flags = V, .unit = "scan" },
64  { "bff", "bottom field first", 0,
65  AV_OPT_TYPE_CONST, {.i64 = MODE_BFF }, INT_MIN, INT_MAX, .flags = V, .unit = "scan" },
66  { "lowpass", "enable vertical low-pass filter", OFFSET(lowpass),
67  AV_OPT_TYPE_INT, {.i64 = 1 }, 0, 1, .flags = V },
68  { NULL }
69 };
70 
71 static const AVClass class = {
72  .class_name = "interlace filter",
73  .item_name = av_default_item_name,
74  .option = options,
76 };
77 
78 
79 static const enum AVPixelFormat formats_supported[] = {
84 };
85 
87 {
89  return 0;
90 }
91 
92 static av_cold void uninit(AVFilterContext *ctx)
93 {
94  InterlaceContext *s = ctx->priv;
95 
96  av_frame_free(&s->cur);
97  av_frame_free(&s->next);
98 }
99 
100 static int config_out_props(AVFilterLink *outlink)
101 {
102  AVFilterContext *ctx = outlink->src;
103  AVFilterLink *inlink = outlink->src->inputs[0];
104  InterlaceContext *s = ctx->priv;
105 
106  if (inlink->h < 2) {
107  av_log(ctx, AV_LOG_ERROR, "input video height is too small\n");
108  return AVERROR_INVALIDDATA;
109  }
110  // same input size
111  outlink->w = inlink->w;
112  outlink->h = inlink->h;
113  outlink->time_base = inlink->time_base;
114  outlink->frame_rate = inlink->frame_rate;
115  // half framerate
116  outlink->time_base.num *= 2;
117  outlink->frame_rate.den *= 2;
118 
119  av_log(ctx, AV_LOG_VERBOSE, "%s interlacing %s lowpass filter\n",
120  s->scan == MODE_TFF ? "tff" : "bff", (s->lowpass) ? "with" : "without");
121 
122  return 0;
123 }
124 
125 static void copy_picture_field(AVFrame *src_frame, AVFrame *dst_frame,
126  AVFilterLink *inlink, enum FieldType field_type,
127  int lowpass)
128 {
129  const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
130  int vsub = desc->log2_chroma_h;
131  int plane, i, j;
132 
133  for (plane = 0; plane < desc->nb_components; plane++) {
134  int lines = (plane == 1 || plane == 2) ? inlink->h >> vsub : inlink->h;
135  int linesize = av_image_get_linesize(inlink->format, inlink->w, plane);
136  uint8_t *dstp = dst_frame->data[plane];
137  const uint8_t *srcp = src_frame->data[plane];
138 
139  av_assert0(linesize >= 0);
140 
141  lines /= 2;
142  if (field_type == FIELD_LOWER)
143  srcp += src_frame->linesize[plane];
144  if (field_type == FIELD_LOWER)
145  dstp += dst_frame->linesize[plane];
146  if (lowpass) {
147  int srcp_linesize = src_frame->linesize[plane] * 2;
148  int dstp_linesize = dst_frame->linesize[plane] * 2;
149  for (j = lines; j > 0; j--) {
150  const uint8_t *srcp_above = srcp - src_frame->linesize[plane];
151  const uint8_t *srcp_below = srcp + src_frame->linesize[plane];
152  if (j == lines)
153  srcp_above = srcp; // there is no line above
154  if (j == 1)
155  srcp_below = srcp; // there is no line below
156  for (i = 0; i < linesize; i++) {
157  // this calculation is an integer representation of
158  // '0.5 * current + 0.25 * above + 0.25 + below'
159  // '1 +' is for rounding.
160  dstp[i] = (1 + srcp[i] + srcp[i] + srcp_above[i] + srcp_below[i]) >> 2;
161  }
162  dstp += dstp_linesize;
163  srcp += srcp_linesize;
164  }
165  } else {
166  av_image_copy_plane(dstp, dst_frame->linesize[plane] * 2,
167  srcp, src_frame->linesize[plane] * 2,
168  linesize, lines);
169  }
170  }
171 }
172 
173 static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
174 {
175  AVFilterContext *ctx = inlink->dst;
176  AVFilterLink *outlink = ctx->outputs[0];
177  InterlaceContext *s = ctx->priv;
178  AVFrame *out;
179  int tff, ret;
180 
181  av_frame_free(&s->cur);
182  s->cur = s->next;
183  s->next = buf;
184 
185  /* we need at least two frames */
186  if (!s->cur || !s->next)
187  return 0;
188 
189  tff = (s->scan == MODE_TFF);
190  out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
191  if (!out)
192  return AVERROR(ENOMEM);
193 
194  av_frame_copy_props(out, s->cur);
195  out->interlaced_frame = 1;
196  out->top_field_first = tff;
197  out->pts /= 2; // adjust pts to new framerate
198 
199  /* copy upper/lower field from cur */
200  copy_picture_field(s->cur, out, inlink, tff ? FIELD_UPPER : FIELD_LOWER, s->lowpass);
201  av_frame_free(&s->cur);
202 
203  /* copy lower/upper field from next */
204  copy_picture_field(s->next, out, inlink, tff ? FIELD_LOWER : FIELD_UPPER, s->lowpass);
205  av_frame_free(&s->next);
206 
207  ret = ff_filter_frame(outlink, out);
208  s->got_output = 1;
209 
210  return ret;
211 }
212 
213 static int request_frame(AVFilterLink *outlink)
214 {
215  AVFilterContext *ctx = outlink->src;
216  InterlaceContext *s = ctx->priv;
217  int ret = 0;
218 
219  s->got_output = 0;
220  while (ret >= 0 && !s->got_output)
221  ret = ff_request_frame(ctx->inputs[0]);
222 
223  return ret;
224 }
225 
226 static const AVFilterPad inputs[] = {
227  {
228  .name = "default",
229  .type = AVMEDIA_TYPE_VIDEO,
230  .filter_frame = filter_frame,
231  },
232  { NULL }
233 };
234 
235 static const AVFilterPad outputs[] = {
236  {
237  .name = "default",
238  .type = AVMEDIA_TYPE_VIDEO,
239  .config_props = config_out_props,
240  .request_frame = request_frame,
241  },
242  { NULL }
243 };
244 
246  .name = "interlace",
247  .description = NULL_IF_CONFIG_SMALL("Convert progressive video into interlaced."),
248  .uninit = uninit,
249 
250  .priv_class = &class,
251  .priv_size = sizeof(InterlaceContext),
253 
254  .inputs = inputs,
255  .outputs = outputs,
256 };
257 
int av_image_get_linesize(enum AVPixelFormat pix_fmt, int width, int plane)
Compute the size of an image line with format pix_fmt and width width for the plane plane...
Definition: imgutils.c:73
const char * s
Definition: avisynth_c.h:668
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:424
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:1778
This structure describes decoded (raw) audio or video data.
Definition: frame.h:76
AVOption.
Definition: opt.h:251
av_default_item_name
static const AVFilterPad inputs[]
Definition: vf_interlace.c:226
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:73
misc image utilities
external API header
int num
numerator
Definition: rational.h:44
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition: video.c:143
static const AVOption options[]
Definition: vf_interlace.c:59
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:308
static enum AVPixelFormat formats_supported[]
Definition: vf_interlace.c:79
static int query_formats(AVFilterContext *ctx)
Definition: vf_interlace.c:86
BYTE int const BYTE * srcp
Definition: avisynth_c.h:713
const char * name
Pad name.
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:55
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:532
static int config_out_props(AVFilterLink *outlink)
Definition: vf_interlace.c:100
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
static const AVFilterPad outputs[]
Definition: vf_interlace.c:235
planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
Definition: pixfmt.h:105
uint8_t
it can be given away to ff_start_frame *A reference passed to ff_filter_frame(or the deprecated ff_start_frame) is given away and must no longer be used.*A reference created with avfilter_ref_buffer belongs to the code that created it.*A reference obtained with ff_get_video_buffer or ff_get_audio_buffer belongs to the code that requested it.*A reference given as return value by the get_video_buffer or get_audio_buffer method is given away and must no longer be used.Link reference fields---------------------The AVFilterLink structure has a few AVFilterBufferRef fields.The cur_buf and out_buf were used with the deprecated start_frame/draw_slice/end_frame API and should no longer be used.src_buf
#define av_cold
Definition: attributes.h:78
static int request_frame(AVFilterLink *outlink)
Definition: vf_interlace.c:213
AVOptions.
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:159
planar YUV 4:4:0 full scale (JPEG), deprecated in favor of PIX_FMT_YUV440P and setting color_range ...
Definition: pixfmt.h:104
planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of PIX_FMT_YUV422P and setting color_...
Definition: pixfmt.h:81
int interlaced_frame
The content of the picture is interlaced.
Definition: frame.h:270
void 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:545
A filter pad used for either input or output.
uint8_t log2_chroma_h
Amount to shift the luma height right to find the chroma height.
Definition: pixdesc.h:75
BYTE * dstp
Definition: avisynth_c.h:713
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
void * priv
private data for use by the filter
Definition: avfilter.h:545
simple assert() macros that are a bit more flexible than ISO C assert().
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
FieldType
Definition: vf_field.c:32
AVFrame * next
Definition: vf_interlace.c:53
#define OFFSET(x)
Definition: vf_interlace.c:57
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:72
#define AV_LOG_VERBOSE
Definition: log.h:157
uint8_t nb_components
The number of components each pixel has, (1-4)
Definition: pixdesc.h:57
planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of PIX_FMT_YUV420P and setting color_...
Definition: pixfmt.h:80
ret
Definition: avfilter.c:821
LIBAVUTIL_VERSION_INT
Definition: eval.c:55
NULL
Definition: eval.c:55
static av_cold void uninit(AVFilterContext *ctx)
Definition: vf_interlace.c:92
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:101
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:55
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
void * buf
Definition: avisynth_c.h:594
planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
Definition: pixfmt.h:74
Describe the class of an AVClass context structure.
Definition: log.h:50
Filter definition.
Definition: avfilter.h:436
synthesis window for stochastic i
const char * name
filter name
Definition: avfilter.h:437
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer 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.Buffer references ownership and permissions
ScanMode
Definition: vf_interlace.c:39
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:539
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:87
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:68
Y , 8bpp.
Definition: pixfmt.h:76
static void copy_picture_field(AVFrame *src_frame, AVFrame *dst_frame, AVFilterLink *inlink, enum FieldType field_type, int lowpass)
Definition: vf_interlace.c:125
common internal and external API header
#define V
Definition: vf_interlace.c:58
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:108
planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of PIX_FMT_YUV444P and setting color_...
Definition: pixfmt.h:82
enum ScanMode scan
Definition: vf_interlace.c:51
int den
denominator
Definition: rational.h:45
int top_field_first
If the content is interlaced, is top field displayed first.
Definition: frame.h:275
static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
Definition: vf_interlace.c:173
An instance of a filter.
Definition: avfilter.h:524
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(const int16_t *) pi >> 8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t,*(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t,*(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(const int32_t *) pi >> 24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t,*(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t,*(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31))))#define SET_CONV_FUNC_GROUP(ofmt, ifmt) static void set_generic_function(AudioConvert *ac){}void ff_audio_convert_free(AudioConvert **ac){if(!*ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);}AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map){AudioConvert *ac;int in_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) return NULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method!=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt) > 2){ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc){av_free(ac);return NULL;}return ac;}in_planar=av_sample_fmt_is_planar(in_fmt);out_planar=av_sample_fmt_is_planar(out_fmt);if(in_planar==out_planar){ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar?ac->channels:1;}else if(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;else ac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);return ac;}int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in){int use_generic=1;int len=in->nb_samples;int p;if(ac->dc){av_dlog(ac->avr,"%d samples - audio_convert: %s to %s (dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));return ff_convert_dither(ac-> out
int ff_request_frame(AVFilterLink *link)
Request an input frame from the filter at the other end of the link.
Definition: avfilter.c:319
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:242
AVFilter avfilter_vf_interlace
Definition: vf_interlace.c:245
internal API functions
AVPixelFormat
Pixel format.
Definition: pixfmt.h:66