FFmpeg  4.0
vf_telecine.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012 Rudolf Polzer
3  * Copyright (c) 2013 Paul B Mahol
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 /**
23  * @file telecine filter, heavily based from mpv-player:TOOLS/vf_dlopen/telecine.c by
24  * Rudolf Polzer.
25  */
26 
27 #include "libavutil/avstring.h"
28 #include "libavutil/imgutils.h"
29 #include "libavutil/opt.h"
30 #include "libavutil/pixdesc.h"
31 #include "avfilter.h"
32 #include "formats.h"
33 #include "internal.h"
34 #include "video.h"
35 
36 typedef struct TelecineContext {
37  const AVClass *class;
39  char *pattern;
40  unsigned int pattern_pos;
41  int64_t start_time;
42 
45  int out_cnt;
46  int occupied;
47 
48  int nb_planes;
49  int planeheight[4];
50  int stride[4];
51 
55 
56 #define OFFSET(x) offsetof(TelecineContext, x)
57 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
58 
59 static const AVOption telecine_options[] = {
60  {"first_field", "select first field", OFFSET(first_field), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "field"},
61  {"top", "select top field first", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "field"},
62  {"t", "select top field first", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "field"},
63  {"bottom", "select bottom field first", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "field"},
64  {"b", "select bottom field first", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "field"},
65  {"pattern", "pattern that describe for how many fields a frame is to be displayed", OFFSET(pattern), AV_OPT_TYPE_STRING, {.str="23"}, 0, 0, FLAGS},
66  {NULL}
67 };
68 
69 AVFILTER_DEFINE_CLASS(telecine);
70 
72 {
73  TelecineContext *s = ctx->priv;
74  const char *p;
75  int max = 0;
76 
77  if (!strlen(s->pattern)) {
78  av_log(ctx, AV_LOG_ERROR, "No pattern provided.\n");
79  return AVERROR_INVALIDDATA;
80  }
81 
82  for (p = s->pattern; *p; p++) {
83  if (!av_isdigit(*p)) {
84  av_log(ctx, AV_LOG_ERROR, "Provided pattern includes non-numeric characters.\n");
85  return AVERROR_INVALIDDATA;
86  }
87 
88  max = FFMAX(*p - '0', max);
89  s->pts.num += 2;
90  s->pts.den += *p - '0';
91  }
92 
94 
95  s->out_cnt = (max + 1) / 2;
96  av_log(ctx, AV_LOG_INFO, "Telecine pattern %s yields up to %d frames per frame, pts advance factor: %d/%d\n",
97  s->pattern, s->out_cnt, s->pts.num, s->pts.den);
98 
99  return 0;
100 }
101 
103 {
105  int fmt, ret;
106 
107  for (fmt = 0; av_pix_fmt_desc_get(fmt); fmt++) {
109  if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL ||
110  desc->flags & AV_PIX_FMT_FLAG_PAL ||
111  desc->flags & AV_PIX_FMT_FLAG_BITSTREAM) &&
112  (ret = ff_add_format(&pix_fmts, fmt)) < 0)
113  return ret;
114  }
115 
116  return ff_set_common_formats(ctx, pix_fmts);
117 }
118 
119 static int config_input(AVFilterLink *inlink)
120 {
121  TelecineContext *s = inlink->dst->priv;
123  int i, ret;
124 
125  s->temp = ff_get_video_buffer(inlink, inlink->w, inlink->h);
126  if (!s->temp)
127  return AVERROR(ENOMEM);
128  for (i = 0; i < s->out_cnt; i++) {
129  s->frame[i] = ff_get_video_buffer(inlink, inlink->w, inlink->h);
130  if (!s->frame[i])
131  return AVERROR(ENOMEM);
132  }
133 
134  if ((ret = av_image_fill_linesizes(s->stride, inlink->format, inlink->w)) < 0)
135  return ret;
136 
137  s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
138  s->planeheight[0] = s->planeheight[3] = inlink->h;
139 
141 
142  return 0;
143 }
144 
145 static int config_output(AVFilterLink *outlink)
146 {
147  AVFilterContext *ctx = outlink->src;
148  TelecineContext *s = ctx->priv;
149  const AVFilterLink *inlink = ctx->inputs[0];
150  AVRational fps = inlink->frame_rate;
151 
152  if (!fps.num || !fps.den) {
153  av_log(ctx, AV_LOG_ERROR, "The input needs a constant frame rate; "
154  "current rate of %d/%d is invalid\n", fps.num, fps.den);
155  return AVERROR(EINVAL);
156  }
157  fps = av_mul_q(fps, av_inv_q(s->pts));
158  av_log(ctx, AV_LOG_VERBOSE, "FPS: %d/%d -> %d/%d\n",
159  inlink->frame_rate.num, inlink->frame_rate.den, fps.num, fps.den);
160 
161  outlink->frame_rate = fps;
162  outlink->time_base = av_mul_q(inlink->time_base, s->pts);
163  av_log(ctx, AV_LOG_VERBOSE, "TB: %d/%d -> %d/%d\n",
164  inlink->time_base.num, inlink->time_base.den, outlink->time_base.num, outlink->time_base.den);
165 
166  s->ts_unit = av_inv_q(av_mul_q(fps, outlink->time_base));
167 
168  return 0;
169 }
170 
171 static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
172 {
173  AVFilterContext *ctx = inlink->dst;
174  AVFilterLink *outlink = ctx->outputs[0];
175  TelecineContext *s = ctx->priv;
176  int i, len, ret = 0, nout = 0;
177 
178  if (s->start_time == AV_NOPTS_VALUE)
179  s->start_time = inpicref->pts;
180 
181  len = s->pattern[s->pattern_pos] - '0';
182 
183  s->pattern_pos++;
184  if (!s->pattern[s->pattern_pos])
185  s->pattern_pos = 0;
186 
187  if (!len) { // do not output any field from this frame
188  av_frame_free(&inpicref);
189  return 0;
190  }
191 
192  if (s->occupied) {
193  av_frame_make_writable(s->frame[nout]);
194  for (i = 0; i < s->nb_planes; i++) {
195  // fill in the EARLIER field from the buffered pic
196  av_image_copy_plane(s->frame[nout]->data[i] + s->frame[nout]->linesize[i] * s->first_field,
197  s->frame[nout]->linesize[i] * 2,
198  s->temp->data[i] + s->temp->linesize[i] * s->first_field,
199  s->temp->linesize[i] * 2,
200  s->stride[i],
201  (s->planeheight[i] - s->first_field + 1) / 2);
202  // fill in the LATER field from the new pic
203  av_image_copy_plane(s->frame[nout]->data[i] + s->frame[nout]->linesize[i] * !s->first_field,
204  s->frame[nout]->linesize[i] * 2,
205  inpicref->data[i] + inpicref->linesize[i] * !s->first_field,
206  inpicref->linesize[i] * 2,
207  s->stride[i],
208  (s->planeheight[i] - !s->first_field + 1) / 2);
209  }
210  nout++;
211  len--;
212  s->occupied = 0;
213  }
214 
215  while (len >= 2) {
216  // output THIS image as-is
217  av_frame_make_writable(s->frame[nout]);
218  for (i = 0; i < s->nb_planes; i++)
219  av_image_copy_plane(s->frame[nout]->data[i], s->frame[nout]->linesize[i],
220  inpicref->data[i], inpicref->linesize[i],
221  s->stride[i],
222  s->planeheight[i]);
223  nout++;
224  len -= 2;
225  }
226 
227  if (len >= 1) {
228  // copy THIS image to the buffer, we need it later
229  for (i = 0; i < s->nb_planes; i++)
230  av_image_copy_plane(s->temp->data[i], s->temp->linesize[i],
231  inpicref->data[i], inpicref->linesize[i],
232  s->stride[i],
233  s->planeheight[i]);
234  s->occupied = 1;
235  }
236 
237  for (i = 0; i < nout; i++) {
238  AVFrame *frame = av_frame_clone(s->frame[i]);
239 
240  if (!frame) {
241  av_frame_free(&inpicref);
242  return AVERROR(ENOMEM);
243  }
244 
245  av_frame_copy_props(frame, inpicref);
246  frame->pts = ((s->start_time == AV_NOPTS_VALUE) ? 0 : s->start_time) +
247  av_rescale(outlink->frame_count_in, s->ts_unit.num,
248  s->ts_unit.den);
249  ret = ff_filter_frame(outlink, frame);
250  }
251  av_frame_free(&inpicref);
252 
253  return ret;
254 }
255 
257 {
258  TelecineContext *s = ctx->priv;
259  int i;
260 
261  av_frame_free(&s->temp);
262  for (i = 0; i < s->out_cnt; i++)
263  av_frame_free(&s->frame[i]);
264 }
265 
266 static const AVFilterPad telecine_inputs[] = {
267  {
268  .name = "default",
269  .type = AVMEDIA_TYPE_VIDEO,
270  .filter_frame = filter_frame,
271  .config_props = config_input,
272  },
273  { NULL }
274 };
275 
276 static const AVFilterPad telecine_outputs[] = {
277  {
278  .name = "default",
279  .type = AVMEDIA_TYPE_VIDEO,
280  .config_props = config_output,
281  },
282  { NULL }
283 };
284 
286  .name = "telecine",
287  .description = NULL_IF_CONFIG_SMALL("Apply a telecine pattern."),
288  .priv_size = sizeof(TelecineContext),
289  .priv_class = &telecine_class,
290  .init = init,
291  .uninit = uninit,
293  .inputs = telecine_inputs,
294  .outputs = telecine_outputs,
295 };
#define AV_PIX_FMT_FLAG_PAL
Pixel format has a palette in data[1], values are indexes in this palette.
Definition: pixdesc.h:132
#define NULL
Definition: coverity.c:32
const char * s
Definition: avisynth_c.h:768
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
static av_const int av_isdigit(int c)
Locale-independent conversion of ASCII isdigit.
Definition: avstring.h:206
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2363
This structure describes decoded (raw) audio or video data.
Definition: frame.h:218
AVOption.
Definition: opt.h:246
const char * fmt
Definition: avisynth_c.h:769
misc image utilities
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2403
Main libavfilter public API header.
const char * desc
Definition: nvenc.c:65
int num
Numerator.
Definition: rational.h:59
static int config_input(AVFilterLink *inlink)
Definition: vf_telecine.c:119
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
AVRational ts_unit
Definition: vf_telecine.c:44
const char * name
Pad name.
Definition: internal.h:60
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:346
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1080
#define av_cold
Definition: attributes.h:82
AVOptions.
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:311
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:192
int planeheight[4]
Definition: vf_telecine.c:49
#define av_log(a,...)
static const AVFilterPad telecine_outputs[]
Definition: vf_telecine.c:276
A filter pad used for either input or output.
Definition: internal.h:54
AVRational pts
Definition: vf_telecine.c:43
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.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:568
static int config_output(AVFilterLink *outlink)
Definition: vf_telecine.c:145
uint8_t log2_chroma_h
Amount to shift the luma height right to find the chroma height.
Definition: pixdesc.h:101
static av_cold int init(AVFilterContext *ctx)
Definition: vf_telecine.c:71
#define AVERROR(e)
Definition: error.h:43
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:202
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
int64_t start_time
Definition: vf_telecine.c:41
void * priv
private data for use by the filter
Definition: avfilter.h:353
#define OFFSET(x)
Definition: vf_telecine.c:56
#define AV_PIX_FMT_FLAG_HWACCEL
Pixel format is an HW accelerated format.
Definition: pixdesc.h:140
int ff_add_format(AVFilterFormats **avff, int64_t fmt)
Add fmt to the list of media formats contained in *avff.
Definition: formats.c:337
#define FFMAX(a, b)
Definition: common.h:94
uint64_t flags
Combination of AV_PIX_FMT_FLAG_...
Definition: pixdesc.h:106
int64_t av_rescale(int64_t a, int64_t b, int64_t c)
Rescale a 64-bit integer with rounding to nearest.
Definition: mathematics.c:129
#define FLAGS
Definition: vf_telecine.c:57
AVFrame * temp
Definition: vf_telecine.c:53
AVFormatContext * ctx
Definition: movenc.c:48
unsigned int pattern_pos
Definition: vf_telecine.c:40
AVFILTER_DEFINE_CLASS(telecine)
static const AVFilterPad inputs[]
Definition: af_acontrast.c:193
AVFrame * av_frame_clone(const AVFrame *src)
Create a new frame that references the same data as src.
Definition: frame.c:538
static const AVFilterPad outputs[]
Definition: af_acontrast.c:203
#define AV_LOG_INFO
Standard information.
Definition: log.h:187
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:249
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:81
Describe the class of an AVClass context structure.
Definition: log.h:67
Filter definition.
Definition: avfilter.h:144
int av_image_fill_linesizes(int linesizes[4], enum AVPixelFormat pix_fmt, int width)
Fill plane linesizes for an image with pixel format pix_fmt and width width.
Definition: imgutils.c:89
Rational number (pair of numerator and denominator).
Definition: rational.h:58
const char * name
Filter name.
Definition: avfilter.h:148
AVFrame * frame[5]
Definition: vf_telecine.c:52
#define AV_PIX_FMT_FLAG_BITSTREAM
All values of a component are bit-wise packed end to end.
Definition: pixdesc.h:136
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:350
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:266
int av_frame_make_writable(AVFrame *frame)
Ensure that the frame data is writable, avoiding data copy if possible.
Definition: frame.c:609
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:232
static av_always_inline AVRational av_inv_q(AVRational q)
Invert a rational.
Definition: rational.h:159
static const AVOption telecine_options[]
Definition: vf_telecine.c:59
static const AVFilterPad telecine_inputs[]
Definition: vf_telecine.c:266
int den
Denominator.
Definition: rational.h:60
int len
static av_cold void uninit(AVFilterContext *ctx)
Definition: vf_telecine.c:256
A list of supported formats for one end of a filter link.
Definition: formats.h:64
static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
Definition: vf_telecine.c:171
An instance of a filter.
Definition: avfilter.h:338
AVRational av_mul_q(AVRational b, AVRational c)
Multiply two rationals.
Definition: rational.c:80
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:338
AVFilter ff_vf_telecine
Definition: vf_telecine.c:285
internal API functions
static int query_formats(AVFilterContext *ctx)
Definition: vf_telecine.c:102
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:652
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:58