Libav
vf_fps.c
Go to the documentation of this file.
1 /*
2  * This file is part of Libav.
3  *
4  * Libav is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * Libav is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with Libav; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
24 #include <float.h>
25 #include <stdint.h>
26 
27 #include "libavutil/common.h"
28 #include "libavutil/fifo.h"
29 #include "libavutil/mathematics.h"
30 #include "libavutil/opt.h"
31 #include "libavutil/parseutils.h"
32 
33 #include "avfilter.h"
34 #include "internal.h"
35 #include "video.h"
36 
37 typedef struct FPSContext {
38  const AVClass *class;
39 
41 
42  /* timestamps in input timebase */
43  int64_t first_pts;
44  int64_t pts;
45 
46  double start_time;
47 
49  char *fps;
50 
51  /* statistics */
52  int frames_in;
53  int frames_out;
54  int dup;
55  int drop;
56 } FPSContext;
57 
58 #define OFFSET(x) offsetof(FPSContext, x)
59 #define V AV_OPT_FLAG_VIDEO_PARAM
60 static const AVOption options[] = {
61  { "fps", "A string describing desired output framerate", OFFSET(fps), AV_OPT_TYPE_STRING, { .str = "25" }, .flags = V },
62  { "start_time", "Assume the first PTS should be this value.", OFFSET(start_time), AV_OPT_TYPE_DOUBLE, { .dbl = DBL_MAX}, -DBL_MAX, DBL_MAX, V },
63  { NULL },
64 };
65 
66 static const AVClass class = {
67  .class_name = "FPS filter",
68  .item_name = av_default_item_name,
69  .option = options,
71 };
72 
74 {
75  FPSContext *s = ctx->priv;
76  int ret;
77 
78  if ((ret = av_parse_video_rate(&s->framerate, s->fps)) < 0) {
79  av_log(ctx, AV_LOG_ERROR, "Error parsing framerate %s.\n", s->fps);
80  return ret;
81  }
82 
83  if (!(s->fifo = av_fifo_alloc(2*sizeof(AVFrame*))))
84  return AVERROR(ENOMEM);
85 
86  s->pts = AV_NOPTS_VALUE;
88 
89  av_log(ctx, AV_LOG_VERBOSE, "fps=%d/%d\n", s->framerate.num, s->framerate.den);
90  return 0;
91 }
92 
94 {
95  while (av_fifo_size(fifo)) {
96  AVFrame *tmp;
97  av_fifo_generic_read(fifo, &tmp, sizeof(tmp), NULL);
98  av_frame_free(&tmp);
99  }
100 }
101 
103 {
104  FPSContext *s = ctx->priv;
105  if (s->fifo) {
106  s->drop += av_fifo_size(s->fifo) / sizeof(AVFrame*);
107  flush_fifo(s->fifo);
108  av_fifo_free(s->fifo);
109  }
110 
111  av_log(ctx, AV_LOG_VERBOSE, "%d frames in, %d frames out; %d frames dropped, "
112  "%d frames duplicated.\n", s->frames_in, s->frames_out, s->drop, s->dup);
113 }
114 
115 static int config_props(AVFilterLink* link)
116 {
117  FPSContext *s = link->src->priv;
118 
119  link->time_base = (AVRational){ s->framerate.den, s->framerate.num };
120  link->frame_rate = s->framerate;
121  link->w = link->src->inputs[0]->w;
122  link->h = link->src->inputs[0]->h;
123 
124  return 0;
125 }
126 
127 static int request_frame(AVFilterLink *outlink)
128 {
129  AVFilterContext *ctx = outlink->src;
130  FPSContext *s = ctx->priv;
131  int frames_out = s->frames_out;
132  int ret = 0;
133 
134  while (ret >= 0 && s->frames_out == frames_out)
135  ret = ff_request_frame(ctx->inputs[0]);
136 
137  /* flush the fifo */
138  if (ret == AVERROR_EOF && av_fifo_size(s->fifo)) {
139  int i;
140  for (i = 0; av_fifo_size(s->fifo); i++) {
141  AVFrame *buf;
142 
143  av_fifo_generic_read(s->fifo, &buf, sizeof(buf), NULL);
144  buf->pts = av_rescale_q(s->first_pts, ctx->inputs[0]->time_base,
145  outlink->time_base) + s->frames_out;
146 
147  if ((ret = ff_filter_frame(outlink, buf)) < 0)
148  return ret;
149 
150  s->frames_out++;
151  }
152  return 0;
153  }
154 
155  return ret;
156 }
157 
159 {
160  int ret;
161 
162  if (!av_fifo_space(fifo) &&
163  (ret = av_fifo_realloc2(fifo, 2*av_fifo_size(fifo)))) {
164  av_frame_free(&buf);
165  return ret;
166  }
167 
168  av_fifo_generic_write(fifo, &buf, sizeof(buf), NULL);
169  return 0;
170 }
171 
172 static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
173 {
174  AVFilterContext *ctx = inlink->dst;
175  FPSContext *s = ctx->priv;
176  AVFilterLink *outlink = ctx->outputs[0];
177  int64_t delta;
178  int i, ret;
179 
180  s->frames_in++;
181  /* discard frames until we get the first timestamp */
182  if (s->pts == AV_NOPTS_VALUE) {
183  if (buf->pts != AV_NOPTS_VALUE) {
184  ret = write_to_fifo(s->fifo, buf);
185  if (ret < 0)
186  return ret;
187 
188  if (s->start_time != DBL_MAX) {
189  double first_pts = s->start_time * AV_TIME_BASE;
190  first_pts = FFMIN(FFMAX(first_pts, INT64_MIN), INT64_MAX);
191  s->first_pts = s->pts = av_rescale_q(first_pts, AV_TIME_BASE_Q,
192  inlink->time_base);
193  av_log(ctx, AV_LOG_VERBOSE, "Set first pts to (in:%"PRId64" out:%"PRId64")\n",
194  s->first_pts, av_rescale_q(first_pts, AV_TIME_BASE_Q,
195  outlink->time_base));
196  } else {
197  s->first_pts = s->pts = buf->pts;
198  }
199  } else {
200  av_log(ctx, AV_LOG_WARNING, "Discarding initial frame(s) with no "
201  "timestamp.\n");
202  av_frame_free(&buf);
203  s->drop++;
204  }
205  return 0;
206  }
207 
208  /* now wait for the next timestamp */
209  if (buf->pts == AV_NOPTS_VALUE) {
210  return write_to_fifo(s->fifo, buf);
211  }
212 
213  /* number of output frames */
214  delta = av_rescale_q(buf->pts - s->pts, inlink->time_base,
215  outlink->time_base);
216 
217  if (delta < 1) {
218  /* drop the frame and everything buffered except the first */
219  AVFrame *tmp;
220  int drop = av_fifo_size(s->fifo)/sizeof(AVFrame*);
221 
222  av_log(ctx, AV_LOG_DEBUG, "Dropping %d frame(s).\n", drop);
223  s->drop += drop;
224 
225  av_fifo_generic_read(s->fifo, &tmp, sizeof(tmp), NULL);
226  flush_fifo(s->fifo);
227  ret = write_to_fifo(s->fifo, tmp);
228 
229  av_frame_free(&buf);
230  return ret;
231  }
232 
233  /* can output >= 1 frames */
234  for (i = 0; i < delta; i++) {
235  AVFrame *buf_out;
236  av_fifo_generic_read(s->fifo, &buf_out, sizeof(buf_out), NULL);
237 
238  /* duplicate the frame if needed */
239  if (!av_fifo_size(s->fifo) && i < delta - 1) {
240  AVFrame *dup = av_frame_clone(buf_out);
241 
242  av_log(ctx, AV_LOG_DEBUG, "Duplicating frame.\n");
243  if (dup)
244  ret = write_to_fifo(s->fifo, dup);
245  else
246  ret = AVERROR(ENOMEM);
247 
248  if (ret < 0) {
249  av_frame_free(&buf_out);
250  av_frame_free(&buf);
251  return ret;
252  }
253 
254  s->dup++;
255  }
256 
257  buf_out->pts = av_rescale_q(s->first_pts, inlink->time_base,
258  outlink->time_base) + s->frames_out;
259 
260  if ((ret = ff_filter_frame(outlink, buf_out)) < 0) {
261  av_frame_free(&buf);
262  return ret;
263  }
264 
265  s->frames_out++;
266  }
267  flush_fifo(s->fifo);
268 
269  ret = write_to_fifo(s->fifo, buf);
270  s->pts = s->first_pts + av_rescale_q(s->frames_out, outlink->time_base, inlink->time_base);
271 
272  return ret;
273 }
274 
276  {
277  .name = "default",
278  .type = AVMEDIA_TYPE_VIDEO,
279  .filter_frame = filter_frame,
280  },
281  { NULL }
282 };
283 
285  {
286  .name = "default",
287  .type = AVMEDIA_TYPE_VIDEO,
288  .request_frame = request_frame,
289  .config_props = config_props
290  },
291  { NULL }
292 };
293 
295  .name = "fps",
296  .description = NULL_IF_CONFIG_SMALL("Force constant framerate"),
297 
298  .init = init,
299  .uninit = uninit,
300 
301  .priv_size = sizeof(FPSContext),
302  .priv_class = &class,
303 
304  .inputs = avfilter_vf_fps_inputs,
305  .outputs = avfilter_vf_fps_outputs,
306 };
int frames_out
number of frames on output
Definition: vf_fps.c:53
AVFifoBuffer * fifo
store frames until we get two successive timestamps
Definition: vf_fps.c:40
AVFilter ff_vf_fps
Definition: vf_fps.c:294
This structure describes decoded (raw) audio or video data.
Definition: frame.h:140
int av_parse_video_rate(AVRational *rate, const char *arg)
Parse str and store the detected values in *rate.
Definition: parseutils.c:127
AVOption.
Definition: opt.h:234
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:130
static const AVFilterPad outputs[]
Definition: af_ashowinfo.c:259
Main libavfilter public API header.
int num
numerator
Definition: rational.h:44
av_log(ac->avr, AV_LOG_TRACE, "%d samples - audio_convert: %s to %s (%s)\, len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt), use_generic ? ac->func_descr_generic :ac->func_descr)
int drop
number of framed dropped
Definition: vf_fps.c:55
int64_t pts
pts of the first frame currently in the fifo
Definition: vf_fps.c:44
int64_t first_pts
pts of the first frame that arrived on this filter
Definition: vf_fps.c:43
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.
Definition: fifo.c:84
const char * name
Pad name.
Definition: internal.h:41
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:39
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:270
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:747
#define av_cold
Definition: attributes.h:66
int frames_in
number of frames on input
Definition: vf_fps.c:52
float delta
AVOptions.
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:211
char * fps
a string describing target framerate
Definition: vf_fps.c:49
#define AVERROR_EOF
End of file.
Definition: error.h:51
static av_cold int init(AVFilterContext *ctx)
Definition: vf_fps.c:73
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:140
void av_fifo_free(AVFifoBuffer *f)
Free an AVFifoBuffer.
Definition: fifo.c:38
A filter pad used for either input or output.
Definition: internal.h:35
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:99
int dup
number of frames duplicated
Definition: vf_fps.c:54
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:124
static av_cold void uninit(AVFilterContext *ctx)
Definition: vf_fps.c:102
#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:80
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:148
void * priv
private data for use by the filter
Definition: avfilter.h:277
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:145
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.
Definition: fifo.c:107
static const AVFilterPad avfilter_vf_fps_inputs[]
Definition: vf_fps.c:275
static int request_frame(AVFilterLink *outlink)
Definition: vf_fps.c:127
#define V
Definition: vf_fps.c:59
static const AVFilterPad avfilter_vf_fps_outputs[]
Definition: vf_fps.c:284
#define FFMAX(a, b)
Definition: common.h:64
#define OFFSET(x)
Definition: vf_fps.c:58
#define AV_TIME_BASE
Internal time base represented as integer.
Definition: avutil.h:241
#define FFMIN(a, b)
Definition: common.h:66
AVFormatContext * ctx
Definition: movenc.c:48
static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
Definition: vf_fps.c:172
LIBAVUTIL_VERSION_INT
Definition: eval.c:55
AVFrame * av_frame_clone(const AVFrame *src)
Create a new frame that references the same data as src.
Definition: frame.c:289
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...
Definition: fifo.c:57
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:247
int av_fifo_realloc2(AVFifoBuffer *f, unsigned int new_size)
Resize an AVFifoBuffer.
Definition: fifo.c:62
av_default_item_name
Definition: dnxhdenc.c:55
a very simple circular buffer FIFO implementation
Describe the class of an AVClass context structure.
Definition: log.h:34
Filter definition.
Definition: avfilter.h:120
static const AVFilterPad inputs[]
Definition: af_ashowinfo.c:248
rational number numerator/denominator
Definition: rational.h:43
const char * name
Filter name.
Definition: avfilter.h:124
misc parsing utilities
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:274
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 ...
Definition: fifo.c:52
common internal and external API header
AVRational framerate
target framerate
Definition: vf_fps.c:48
int den
denominator
Definition: rational.h:45
static const AVOption options[]
Definition: vf_fps.c:60
static int config_props(AVFilterLink *link)
Definition: vf_fps.c:115
AVFifoBuffer * av_fifo_alloc(unsigned int size)
Initialize an AVFifoBuffer.
Definition: fifo.c:25
static int write_to_fifo(AVFifoBuffer *fifo, AVFrame *buf)
Definition: vf_fps.c:158
static uint8_t tmp[8]
Definition: des.c:38
An instance of a filter.
Definition: avfilter.h:262
int ff_request_frame(AVFilterLink *link)
Request an input frame from the filter at the other end of the link.
Definition: avfilter.c:264
internal API functions
static void flush_fifo(AVFifoBuffer *fifo)
Definition: vf_fps.c:93
double start_time
pts, in seconds, of the expected first frame
Definition: vf_fps.c:46
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:235