FFmpeg: libavfilter/vf_fps.c Source File
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 * Copyright 2018 Calvin Walton <calvin.walton@kepstin.ca>
6 *
7 * This file is part of FFmpeg.
8 *
9 * FFmpeg is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (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 GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with FFmpeg; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24 /**
25 * @file
26 * a filter enforcing given constant framerate
27 */
28
30 #include <stdint.h>
31
40
45 };
46
48 "source_fps",
49 "ntsc",
50 "pal",
51 "film",
52 "ntsc_film",
54 };
55
63 };
64
65 static const double ntsc_fps = 30000.0 / 1001.0;
69
72
73 double start_time;
///< pts, in seconds, of the expected first frame
74
75 char *
framerate;
///< expression that defines the target framerate
76 int rounding;
///< AVRounding method for timestamps
77 int eof_action;
///< action performed for last frame in FIFO
78
79 /* Set during outlink configuration */
82
83 /* Runtime state */
84 int status;
///< buffered input status
86
90
92
93 /* statistics */
97 int dup;
///< number of frames duplicated
98 int drop;
///< number of framed dropped
100
101 #define OFFSET(x) offsetof(FPSContext, x)
102 #define V AV_OPT_FLAG_VIDEO_PARAM
103 #define F AV_OPT_FLAG_FILTERING_PARAM
117 };
118
120
122 {
124
127
128 return 0;
129 }
130
131 /* Remove the first frame from the buffer, returning it */
133 {
135
136 /* Must only be called when there are frames in the buffer */
138
140 s->frames[0] =
s->frames[1];
143
144 /* Update statistics counters */
145 s->frames_out +=
s->cur_frame_out;
146 if (
s->cur_frame_out > 1) {
148 frame->pts,
s->cur_frame_out - 1);
149 s->dup +=
s->cur_frame_out - 1;
150 }
else if (
s->cur_frame_out == 0) {
154 }
155 s->cur_frame_out = 0;
156
158 }
159
161 {
163
165
166 while (
s->frames_count > 0) {
169 }
171
173 "%d frames duplicated.\n",
s->frames_in,
s->frames_out,
s->drop,
s->dup);
174 }
175
177 {
183
184 double var_values[
VARS_NB], res;
186
197
200
201 /* Calculate the input and output pts offsets for start_time */
204 if (first_pts < INT64_MIN || first_pts > INT64_MAX) {
208 }
213 s->next_pts =
s->out_pts_off;
215 s->in_pts_off,
s->out_pts_off,
s->start_time);
216 }
217
222 }
223
225
226 return 0;
227 }
228
229 /* Read a frame from the input and save it in the buffer */
231 {
235
236 /* Must only be called when we have buffer room available */
238
240 /* Caller must have run ff_inlink_check_available_frame first */
244
245 /* Convert frame pts to output timebase.
246 * The dance with offsets is required to match the rounding behaviour of the
247 * previous version of the fps filter when using the start_time option. */
252
255
257 s->frames[
s->frames_count++] =
frame;
259
260 return 1;
261 }
262
263 /* Write a frame to the output */
265 {
267
268 av_assert1(
s->frames_count == 2 || (
s->status &&
s->frames_count == 1));
269
270 /* We haven't yet determined the pts of the first frame */
273 s->next_pts =
s->frames[0]->pts;
275 } else {
277 "timestamp.\n");
281 return 0;
282 }
283 }
284
285 /* There are two conditions where we want to drop a frame:
286 * - If we have two buffered frames and the second frame is acceptable
287 * as the next output frame, then drop the first buffered frame.
288 * - If we have status (EOF) set, drop frames when we hit the
289 * status timestamp. */
290 if ((
s->frames_count == 2 &&
s->frames[1]->pts <=
s->next_pts) ||
291 (
s->status &&
s->status_pts <=
s->next_pts)) {
292
296 return 0;
297
298 /* Output a copy of the first buffered frame */
299 } else {
303 // Make sure Closed Captions will not be duplicated
305 frame->pts =
s->next_pts++;
307
309 s->frames[0]->pts,
frame->pts);
313 }
314 }
315
316 /* Convert status_pts to outlink timebase */
318 {
322
324 }
325
327 {
331
335
337
338 /* No buffered status: normal operation */
340
341 /* Read available input frames if we have room */
346 }
347
348 /* We do not yet have enough frames to produce output */
349 if (
s->frames_count < 2) {
350 /* Check if we've hit EOF (or otherwise that an error status is set) */
354
356 /* If someone wants us to output, we'd better ask for more input */
358 return 0;
359 }
360 }
361 }
362
363 /* Buffered frames are available, so generate an output frame */
364 if (
s->frames_count > 0) {
366 /* Couldn't generate a frame, so schedule us to perform another step */
370 }
371
372 /* No frames left, so forward the status */
373 if (
s->status &&
s->frames_count == 0) {
375 return 0;
376 }
377
379 }
380
382 {
386 },
387 };
388
392 .p.priv_class = &fps_class,
400 };
@ AV_ROUND_UP
Round toward +infinity.
#define AV_LOG_WARNING
Something somehow does not look correct.
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 ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
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
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
#define FILTER_INPUTS(array)
This structure describes decoded (raw) audio or video data.
@ AV_ROUND_ZERO
Round toward zero.
#define AV_LOG_VERBOSE
Detailed information.
static const double ntsc_fps
static const char *const var_names[]
const char * name
Filter name.
static const double pal_fps
static av_cold int init(AVFilterContext *ctx)
A link between two filters.
#define FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink)
Forward the status on an output link to an input link.
static int config_props(AVFilterLink *outlink)
int ff_inoutlink_check_flow(AVFilterLink *inlink, AVFilterLink *outlink)
Check for flow control between input and output.
Link properties exposed to filter code, but not external callers.
static av_cold void uninit(AVFilterContext *ctx)
int ff_inlink_consume_frame(AVFilterLink *link, AVFrame **rframe)
Take a frame from the link's FIFO and update the link's stats.
void ff_ccfifo_uninit(CCFifo *ccf)
Free all memory allocated in a CCFifo and clear the context.
A filter pad used for either input or output.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
static void update_eof_pts(AVFilterContext *ctx, FPSContext *s, AVFilterLink *inlink, AVFilterLink *outlink, int64_t status_pts)
const AVFilterPad ff_video_default_filterpad[1]
An AVFilterPad array whose only entry has name "default" and is of type AVMEDIA_TYPE_VIDEO.
int ff_ccfifo_inject(CCFifo *ccf, AVFrame *frame)
Insert CC data from the FIFO into an AVFrame (as side data)
static void ff_outlink_set_status(AVFilterLink *link, int status, int64_t pts)
Set the status field of a link from the source filter.
int eof_action
action performed for last frame in FIFO
int frames_in
number of frames on input
@ AV_OPT_TYPE_DOUBLE
Underlying C type is double.
static double av_q2d(AVRational a)
Convert an AVRational to a double.
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
AVFrame * av_frame_clone(const AVFrame *src)
Create a new frame that references the same data as src.
int frames_count
number of buffered frames
@ AV_ROUND_NEAR_INF
Round to nearest and halfway cases away from zero.
#define FILTER_OUTPUTS(array)
@ AV_ROUND_PASS_MINMAX
Flag telling rescaling functions to pass INT64_MIN/MAX through unchanged, avoiding special cases for ...
static int write_frame(AVFilterContext *ctx, FPSContext *s, AVFilterLink *outlink, int *again)
int64_t out_pts_off
output frame pts offset for start_time handling
static const double ntsc_film_fps
Describe the class of an AVClass context structure.
static const AVFilterPad avfilter_vf_fps_outputs[]
int ff_ccfifo_extract(CCFifo *ccf, AVFrame *frame)
Extract CC data from an AVFrame.
int64_t status_pts
buffered input status timestamp
AVFrame * frames[2]
buffered frames
int ff_inlink_acknowledge_status(AVFilterLink *link, int *rstatus, int64_t *rpts)
Test and acknowledge the change of status on the link.
static FilterLink * ff_filter_link(AVFilterLink *link)
@ AV_ROUND_DOWN
Round toward -infinity.
int status
buffered input status
static int read_frame(AVFilterContext *ctx, FPSContext *s, AVFilterLink *inlink, AVFilterLink *outlink)
int ff_inlink_check_available_frame(AVFilterLink *link)
Test if a frame is available on the link.
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
int av_expr_parse_and_eval(double *d, const char *s, const char *const *const_names, const double *const_values, const char *const *func1_names, double(*const *funcs1)(void *, double), const char *const *func2_names, double(*const *funcs2)(void *, double, double), void *opaque, int log_offset, void *log_ctx)
Parse and evaluate an expression.
static int64_t start_time
#define AV_NOPTS_VALUE
Undefined timestamp value.
AVFilterContext * src
source filter
int64_t next_pts
pts of the next frame to output
FF_FILTER_FORWARD_WANTED(outlink, inlink)
int drop
number of framed dropped
static AVFrame * shift_frame(AVFilterContext *ctx, FPSContext *s)
char * framerate
expression that defines the target framerate
#define AV_TIME_BASE
Internal time base represented as integer.
@ AV_ROUND_INF
Round away from zero.
CCFifo cc_fifo
closed captions
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
AVRational av_d2q(double d, int max)
Convert a double precision floating point number to a rational.
static av_always_inline AVRational av_inv_q(AVRational q)
Invert a rational.
const char * name
Pad name.
int ff_ccfifo_init(CCFifo *ccf, AVRational framerate, void *log_ctx)
Initialize a CCFifo.
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 the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
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 again
@ AV_OPT_TYPE_INT
Underlying C type is int.
#define AVFILTER_FLAG_METADATA_ONLY
The filter is a "metadata" filter - it does not modify the frame data in any way.
int64_t in_pts_off
input frame pts offset for start_time handling
static const double film_fps
AVRational time_base
Define the time base used by the PTS of the frames/samples which will pass through this link.
int dup
number of frames duplicated
AVFilter p
The public AVFilter.
double start_time
pts, in seconds, of the expected first frame
AVFILTER_DEFINE_CLASS(fps)
static int activate(AVFilterContext *ctx)
static const AVOption fps_options[]
int cur_frame_out
number of times current frame has been output
AVRational frame_rate
Frame rate of the stream on the link, or 1/0 if unknown or variable.
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
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.
int frames_out
number of frames on output
int rounding
AVRounding method for timestamps.
void ff_filter_set_ready(AVFilterContext *filter, unsigned priority)
Mark a filter ready and schedule it for activation.
Generated on Wed Nov 19 2025 19:22:57 for FFmpeg by
doxygen
1.8.17