vf_fps.c
Go to the documentation of this file.
1 /*
2  * Copyright 2007 Bobby Bingham
3  * Copyright 2012 Robert Nagy <ronag89 gmail com>
4  * Copyright 2012 Anton Khirnov <anton khirnov net>
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 /**
24  * @file
25  * a filter enforcing given constant framerate
26  */
27 
28 #include "libavutil/common.h"
29 #include "libavutil/fifo.h"
30 #include "libavutil/mathematics.h"
31 #include "libavutil/opt.h"
32 #include "libavutil/parseutils.h"
33 
34 #include "avfilter.h"
35 #include "internal.h"
36 #include "video.h"
37 
38 typedef struct FPSContext {
39  const AVClass *class;
40 
41  AVFifoBuffer *fifo; ///< store frames until we get two successive timestamps
42 
43  /* timestamps in input timebase */
44  int64_t first_pts; ///< pts of the first frame that arrived on this filter
45  int64_t pts; ///< pts of the first frame currently in the fifo
46 
47  AVRational framerate; ///< target framerate
48  int rounding; ///< AVRounding method for timestamps
49 
50  /* statistics */
51  int frames_in; ///< number of frames on input
52  int frames_out; ///< number of frames on output
53  int dup; ///< number of frames duplicated
54  int drop; ///< number of framed dropped
55 } FPSContext;
56 
57 #define OFFSET(x) offsetof(FPSContext, x)
58 #define V AV_OPT_FLAG_VIDEO_PARAM
59 #define F AV_OPT_FLAG_FILTERING_PARAM
60 static const AVOption fps_options[] = {
61  { "fps", "A string describing desired output framerate", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, { .str = "25" }, .flags = V|F },
62  { "round", "set rounding method for timestamps", OFFSET(rounding), AV_OPT_TYPE_INT, { .i64 = AV_ROUND_NEAR_INF }, 0, 5, V|F, "round" },
63  { "zero", "round towards 0", OFFSET(rounding), AV_OPT_TYPE_CONST, { .i64 = AV_ROUND_ZERO }, 0, 5, V|F, "round" },
64  { "inf", "round away from 0", OFFSET(rounding), AV_OPT_TYPE_CONST, { .i64 = AV_ROUND_INF }, 0, 5, V|F, "round" },
65  { "down", "round towards -infty", OFFSET(rounding), AV_OPT_TYPE_CONST, { .i64 = AV_ROUND_DOWN }, 0, 5, V|F, "round" },
66  { "up", "round towards +infty", OFFSET(rounding), AV_OPT_TYPE_CONST, { .i64 = AV_ROUND_UP }, 0, 5, V|F, "round" },
67  { "near", "round to nearest", OFFSET(rounding), AV_OPT_TYPE_CONST, { .i64 = AV_ROUND_NEAR_INF }, 0, 5, V|F, "round" },
68  { NULL },
69 };
70 
72 
73 static av_cold int init(AVFilterContext *ctx)
74 {
75  FPSContext *s = ctx->priv;
76 
77  if (!(s->fifo = av_fifo_alloc(2*sizeof(AVFrame*))))
78  return AVERROR(ENOMEM);
79 
80  av_log(ctx, AV_LOG_VERBOSE, "fps=%d/%d\n", s->framerate.num, s->framerate.den);
81  return 0;
82 }
83 
85 {
86  while (av_fifo_size(fifo)) {
87  AVFrame *tmp;
88  av_fifo_generic_read(fifo, &tmp, sizeof(tmp), NULL);
89  av_frame_free(&tmp);
90  }
91 }
92 
93 static av_cold void uninit(AVFilterContext *ctx)
94 {
95  FPSContext *s = ctx->priv;
96  if (s->fifo) {
97  s->drop += av_fifo_size(s->fifo) / sizeof(AVFrame*);
98  flush_fifo(s->fifo);
99  av_fifo_free(s->fifo);
100  }
101 
102  av_log(ctx, AV_LOG_VERBOSE, "%d frames in, %d frames out; %d frames dropped, "
103  "%d frames duplicated.\n", s->frames_in, s->frames_out, s->drop, s->dup);
104 }
105 
107 {
108  FPSContext *s = link->src->priv;
109 
110  link->time_base = av_inv_q(s->framerate);
111  link->frame_rate= s->framerate;
112  link->w = link->src->inputs[0]->w;
113  link->h = link->src->inputs[0]->h;
114  s->pts = AV_NOPTS_VALUE;
115 
116  return 0;
117 }
118 
119 static int request_frame(AVFilterLink *outlink)
120 {
121  AVFilterContext *ctx = outlink->src;
122  FPSContext *s = ctx->priv;
123  int frames_out = s->frames_out;
124  int ret = 0;
125 
126  while (ret >= 0 && s->frames_out == frames_out)
127  ret = ff_request_frame(ctx->inputs[0]);
128 
129  /* flush the fifo */
130  if (ret == AVERROR_EOF && av_fifo_size(s->fifo)) {
131  int i;
132  for (i = 0; av_fifo_size(s->fifo); i++) {
133  AVFrame *buf;
134 
135  av_fifo_generic_read(s->fifo, &buf, sizeof(buf), NULL);
136  buf->pts = av_rescale_q(s->first_pts, ctx->inputs[0]->time_base,
137  outlink->time_base) + s->frames_out;
138 
139  if ((ret = ff_filter_frame(outlink, buf)) < 0)
140  return ret;
141 
142  s->frames_out++;
143  }
144  return 0;
145  }
146 
147  return ret;
148 }
149 
151 {
152  int ret;
153 
154  if (!av_fifo_space(fifo) &&
155  (ret = av_fifo_realloc2(fifo, 2*av_fifo_size(fifo)))) {
156  av_frame_free(&buf);
157  return ret;
158  }
159 
160  av_fifo_generic_write(fifo, &buf, sizeof(buf), NULL);
161  return 0;
162 }
163 
164 static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
165 {
166  AVFilterContext *ctx = inlink->dst;
167  FPSContext *s = ctx->priv;
168  AVFilterLink *outlink = ctx->outputs[0];
169  int64_t delta;
170  int i, ret;
171 
172  s->frames_in++;
173  /* discard frames until we get the first timestamp */
174  if (s->pts == AV_NOPTS_VALUE) {
175  if (buf->pts != AV_NOPTS_VALUE) {
176  ret = write_to_fifo(s->fifo, buf);
177  if (ret < 0)
178  return ret;
179 
180  s->first_pts = s->pts = buf->pts;
181  } else {
182  av_log(ctx, AV_LOG_WARNING, "Discarding initial frame(s) with no "
183  "timestamp.\n");
184  av_frame_free(&buf);
185  s->drop++;
186  }
187  return 0;
188  }
189 
190  /* now wait for the next timestamp */
191  if (buf->pts == AV_NOPTS_VALUE) {
192  return write_to_fifo(s->fifo, buf);
193  }
194 
195  /* number of output frames */
196  delta = av_rescale_q_rnd(buf->pts - s->pts, inlink->time_base,
197  outlink->time_base, s->rounding);
198 
199  if (delta < 1) {
200  /* drop the frame and everything buffered except the first */
201  AVFrame *tmp;
202  int drop = av_fifo_size(s->fifo)/sizeof(AVFrame*);
203 
204  av_log(ctx, AV_LOG_DEBUG, "Dropping %d frame(s).\n", drop);
205  s->drop += drop;
206 
207  av_fifo_generic_read(s->fifo, &tmp, sizeof(tmp), NULL);
208  flush_fifo(s->fifo);
209  ret = write_to_fifo(s->fifo, tmp);
210 
211  av_frame_free(&buf);
212  return ret;
213  }
214 
215  /* can output >= 1 frames */
216  for (i = 0; i < delta; i++) {
217  AVFrame *buf_out;
218  av_fifo_generic_read(s->fifo, &buf_out, sizeof(buf_out), NULL);
219 
220  /* duplicate the frame if needed */
221  if (!av_fifo_size(s->fifo) && i < delta - 1) {
222  AVFrame *dup = av_frame_clone(buf_out);
223 
224  av_log(ctx, AV_LOG_DEBUG, "Duplicating frame.\n");
225  if (dup)
226  ret = write_to_fifo(s->fifo, dup);
227  else
228  ret = AVERROR(ENOMEM);
229 
230  if (ret < 0) {
231  av_frame_free(&buf_out);
232  av_frame_free(&buf);
233  return ret;
234  }
235 
236  s->dup++;
237  }
238 
239  buf_out->pts = av_rescale_q(s->first_pts, inlink->time_base,
240  outlink->time_base) + s->frames_out;
241 
242  if ((ret = ff_filter_frame(outlink, buf_out)) < 0) {
243  av_frame_free(&buf);
244  return ret;
245  }
246 
247  s->frames_out++;
248  }
249  flush_fifo(s->fifo);
250 
251  ret = write_to_fifo(s->fifo, buf);
252  s->pts = s->first_pts + av_rescale_q(s->frames_out, outlink->time_base, inlink->time_base);
253 
254  return ret;
255 }
256 
258  {
259  .name = "default",
260  .type = AVMEDIA_TYPE_VIDEO,
261  .filter_frame = filter_frame,
262  },
263  { NULL }
264 };
265 
267  {
268  .name = "default",
269  .type = AVMEDIA_TYPE_VIDEO,
270  .request_frame = request_frame,
271  .config_props = config_props
272  },
273  { NULL }
274 };
275 
277  .name = "fps",
278  .description = NULL_IF_CONFIG_SMALL("Force constant framerate."),
279 
280  .init = init,
281  .uninit = uninit,
282 
283  .priv_size = sizeof(FPSContext),
284  .priv_class = &fps_class,
285 
286  .inputs = avfilter_vf_fps_inputs,
287  .outputs = avfilter_vf_fps_outputs,
288 };
int frames_out
number of frames on output
Definition: vf_fps.c:52
#define F
Definition: vf_fps.c:59
const char * s
Definition: avisynth_c.h:668
AVFifoBuffer * fifo
store frames until we get two successive timestamps
Definition: vf_fps.c:41
static const AVOption fps_options[]
Definition: vf_fps.c:60
This structure describes decoded (raw) audio or video data.
Definition: frame.h:76
AVOption.
Definition: opt.h:251
static const AVFilterPad outputs[]
Definition: af_ashowinfo.c:117
external API header
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:154
int num
numerator
Definition: rational.h:44
int drop
number of framed dropped
Definition: vf_fps.c:54
int64_t pts
pts of the first frame currently in the fifo
Definition: vf_fps.c:45
int64_t first_pts
pts of the first frame that arrived on this filter
Definition: vf_fps.c:44
int av_fifo_generic_write(AVFifoBuffer *f, void *src, int size, int(*func)(void *, void *, int))
Feed data from a user-supplied callback to an AVFifoBuffer.
const char * name
Pad name.
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:532
AVFilter avfilter_vf_fps
Definition: vf_fps.c:276
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
Round toward +infinity.
Definition: mathematics.h:71
#define av_cold
Definition: attributes.h:78
int frames_in
number of frames on input
Definition: vf_fps.c:51
float delta
AVOptions.
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:159
#define AVERROR_EOF
End of file.
Definition: error.h:55
static av_cold int init(AVFilterContext *ctx)
Definition: vf_fps.c:73
void av_fifo_free(AVFifoBuffer *f)
Free an AVFifoBuffer.
A filter pad used for either input or output.
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:130
int dup
number of frames duplicated
Definition: vf_fps.c:53
static av_cold void uninit(AVFilterContext *ctx)
Definition: vf_fps.c:93
Round away from zero.
Definition: mathematics.h:69
#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
int av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size, void(*func)(void *, void *, int))
Feed data from an AVFifoBuffer to a user-supplied callback.
static const AVFilterPad avfilter_vf_fps_inputs[]
Definition: vf_fps.c:257
Round to nearest and halfway cases away from zero.
Definition: mathematics.h:72
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
static int request_frame(AVFilterLink *outlink)
Definition: vf_fps.c:119
#define V
Definition: vf_fps.c:58
static const AVFilterPad avfilter_vf_fps_outputs[]
Definition: vf_fps.c:266
#define OFFSET(x)
Definition: vf_fps.c:57
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 link
#define AV_LOG_VERBOSE
Definition: log.h:157
int64_t av_rescale_q_rnd(int64_t a, AVRational bq, AVRational cq, enum AVRounding rnd)
Rescale a 64-bit integer by 2 rational numbers with specified rounding.
Definition: mathematics.c:122
Round toward zero.
Definition: mathematics.h:68
ret
Definition: avfilter.c:821
static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
Definition: vf_fps.c:164
AVFrame * av_frame_clone(AVFrame *src)
Create a new frame that references the same data as src.
Definition: frame.c:317
NULL
Definition: eval.c:55
int av_fifo_space(AVFifoBuffer *f)
Return the amount of space in bytes in the AVFifoBuffer, that is the amount of data you can write int...
struct FPSContext FPSContext
int av_fifo_realloc2(AVFifoBuffer *f, unsigned int new_size)
Resize an AVFifoBuffer.
a very simple circular buffer FIFO implementation
void * buf
Definition: avisynth_c.h:594
Describe the class of an AVClass context structure.
Definition: log.h:50
Filter definition.
Definition: avfilter.h:436
synthesis window for stochastic i
rational number numerator/denominator
Definition: rational.h:43
offset must point to AVRational
Definition: opt.h:233
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
misc parsing utilities
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:539
Round toward -infinity.
Definition: mathematics.h:70
static av_always_inline AVRational av_inv_q(AVRational q)
Invert a rational.
Definition: rational.h:122
AVFILTER_DEFINE_CLASS(fps)
int av_fifo_size(AVFifoBuffer *f)
Return the amount of data in bytes in the AVFifoBuffer, that is the amount of data you can read from ...
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:162
common internal and external API header
AVRational framerate
target framerate
Definition: vf_fps.c:47
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:108
int den
denominator
Definition: rational.h:45
int rounding
AVRounding method for timestamps.
Definition: vf_fps.c:48
static int config_props(AVFilterLink *link)
Definition: vf_fps.c:106
AVFifoBuffer * av_fifo_alloc(unsigned int size)
Initialize an AVFifoBuffer.
static int write_to_fifo(AVFifoBuffer *fifo, AVFrame *buf)
Definition: vf_fps.c:150
An instance of a filter.
Definition: avfilter.h:524
int ff_request_frame(AVFilterLink *link)
Request an input frame from the filter at the other end of the link.
Definition: avfilter.c:319
internal API functions
static void flush_fifo(AVFifoBuffer *fifo)
Definition: vf_fps.c:84
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
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:190