FFmpeg
Loading...
Searching...
No Matches
setpts.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2010 Stefano Sabatini
3 * Copyright (c) 2008 Victor Paesa
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
24 * video presentation timestamp (PTS) modification filter
25 */
26
27#include "config_components.h"
28
29#include <inttypes.h>
30
31#include "libavutil/eval.h"
32#include "libavutil/internal.h"
34#include "libavutil/opt.h"
35#include "libavutil/time.h"
36#include "audio.h"
37#include "avfilter.h"
38#include "filters.h"
39#include "video.h"
40
41static const char *const var_names[] = {
42 "FRAME_RATE", ///< defined only for constant frame-rate video
43 "INTERLACED", ///< tell if the current frame is interlaced
44 "N", ///< frame / sample number (starting at zero)
45 "NB_CONSUMED_SAMPLES", ///< number of samples consumed by the filter (only audio)
46 "NB_SAMPLES", ///< number of samples in the current frame (only audio)
47 "PREV_INPTS", ///< previous input PTS
48 "PREV_INT", ///< previous input time in seconds
49 "PREV_OUTPTS", ///< previous output PTS
50 "PREV_OUTT", ///< previous output time in seconds
51 "PTS", ///< original pts in the file of the frame
52 "SAMPLE_RATE", ///< sample rate (only audio)
53 "STARTPTS", ///< PTS at start of movie
54 "STARTT", ///< time at start of movie
55 "T", ///< original time in the file of the frame
56 "TB", ///< timebase
57 "RTCTIME", ///< wallclock (RTC) time in microseconds
58 "RTCSTART", ///< wallclock (RTC) time at the start of the movie in microseconds
59 "S", // Number of samples in the current frame
60 "SR", // Audio sample rate
61 "FR", ///< defined only for constant frame-rate video
62 "T_CHANGE", ///< time of first frame after latest command was applied
63 NULL
64};
65
90
99
100#define V(name_) \
101 setpts->var_values[VAR_##name_]
102
104{
105 SetPTSContext *setpts = ctx->priv;
106 int ret;
107
108 if ((ret = av_expr_parse(&setpts->expr, setpts->expr_str,
109 var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) {
110 av_log(ctx, AV_LOG_ERROR, "Error while parsing expression '%s'\n", setpts->expr_str);
111 return ret;
112 }
113
114 V(N) = 0.0;
115 V(S) = 0.0;
116 V(PREV_INPTS) = NAN;
117 V(PREV_INT) = NAN;
118 V(PREV_OUTPTS) = NAN;
119 V(PREV_OUTT) = NAN;
120 V(STARTPTS) = NAN;
121 V(STARTT) = NAN;
122 V(T_CHANGE) = NAN;
123 return 0;
124}
125
126static int config_input(AVFilterLink *inlink)
127{
128 FilterLink *l = ff_filter_link(inlink);
129 AVFilterContext *ctx = inlink->dst;
130 SetPTSContext *setpts = ctx->priv;
131
132 setpts->type = inlink->type;
133 V(TB) = av_q2d(inlink->time_base);
134 V(RTCSTART) = av_gettime();
135
136 V(SR) = V(SAMPLE_RATE) =
137 setpts->type == AVMEDIA_TYPE_AUDIO ? inlink->sample_rate : NAN;
138
139 V(FRAME_RATE) = V(FR) =
140 l->frame_rate.num && l->frame_rate.den ?
141 av_q2d(l->frame_rate) : NAN;
142
143 av_log(inlink->src, AV_LOG_VERBOSE, "TB:%f FRAME_RATE:%f SAMPLE_RATE:%f\n",
144 V(TB), V(FRAME_RATE), V(SAMPLE_RATE));
145 return 0;
146}
147
149{
150 FilterLink *l = ff_filter_link(outlink);
151 SetPTSContext *s = outlink->src->priv;
152
153 if (s->strip_fps)
154 l->frame_rate = (AVRational){ 1, 0 };
155
156 return 0;
157}
158
159#define BUF_SIZE 64
160
161static inline char *double2int64str(char *buf, double v)
162{
163 if (isnan(v)) snprintf(buf, BUF_SIZE, "nan");
164 else snprintf(buf, BUF_SIZE, "%"PRId64, (int64_t)v);
165 return buf;
166}
167
168static double eval_pts(SetPTSContext *setpts, AVFilterLink *inlink, AVFrame *frame, int64_t pts)
169{
170 if (isnan(V(STARTPTS))) {
171 V(STARTPTS) = TS2D(pts);
172 V(STARTT ) = TS2T(pts, inlink->time_base);
173 }
174 if (isnan(V(T_CHANGE))) {
175 V(T_CHANGE) = TS2T(pts, inlink->time_base);
176 }
177 V(PTS ) = TS2D(pts);
178 V(T ) = TS2T(pts, inlink->time_base);
179 V(RTCTIME ) = av_gettime();
180
181 if (frame) {
182 if (inlink->type == AVMEDIA_TYPE_VIDEO) {
184 } else if (inlink->type == AVMEDIA_TYPE_AUDIO) {
185 V(S) = frame->nb_samples;
186 V(NB_SAMPLES) = frame->nb_samples;
187 }
188 }
189
190 return av_expr_eval(setpts->expr, setpts->var_values, NULL);
191}
192#define d2istr(v) double2int64str((char[BUF_SIZE]){0}, v)
193
195{
196 SetPTSContext *setpts = inlink->dst->priv;
197 int64_t in_pts = frame->pts;
198 double d;
199
200 d = eval_pts(setpts, inlink, frame, frame->pts);
201 frame->pts = D2TS(d);
202 if (setpts->strip_fps)
203 frame->duration = 0;
204
205 av_log(inlink->dst, AV_LOG_TRACE,
206 "N:%"PRId64" PTS:%s T:%f",
207 (int64_t)V(N), d2istr(V(PTS)), V(T));
208 switch (inlink->type) {
210 av_log(inlink->dst, AV_LOG_TRACE, " INTERLACED:%"PRId64,
212 break;
214 av_log(inlink->dst, AV_LOG_TRACE, " NB_SAMPLES:%"PRId64" NB_CONSUMED_SAMPLES:%"PRId64,
215 (int64_t)V(NB_SAMPLES),
216 (int64_t)V(NB_CONSUMED_SAMPLES));
217 break;
218 }
219 av_log(inlink->dst, AV_LOG_TRACE, " -> PTS:%s T:%f\n", d2istr(d), TS2T(d, inlink->time_base));
220
221 if (inlink->type == AVMEDIA_TYPE_VIDEO) {
222 V(N) += 1.0;
223 } else {
224 V(N) += frame->nb_samples;
225 }
226
227 V(PREV_INPTS ) = TS2D(in_pts);
228 V(PREV_INT ) = TS2T(in_pts, inlink->time_base);
229 V(PREV_OUTPTS) = TS2D(frame->pts);
230 V(PREV_OUTT) = TS2T(frame->pts, inlink->time_base);
231 if (setpts->type == AVMEDIA_TYPE_AUDIO) {
232 V(NB_CONSUMED_SAMPLES) += frame->nb_samples;
233 }
234 return ff_filter_frame(inlink->dst->outputs[0], frame);
235}
236
238{
239 SetPTSContext *setpts = ctx->priv;
240 AVFilterLink *inlink = ctx->inputs[0];
241 AVFilterLink *outlink = ctx->outputs[0];
242 AVFrame *in;
243 int status;
244 int64_t pts;
245 int ret;
246
247 FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
248
249 ret = ff_inlink_consume_frame(inlink, &in);
250 if (ret < 0)
251 return ret;
252 if (ret > 0)
253 return filter_frame(inlink, in);
254
255 if (ff_inlink_acknowledge_status(inlink, &status, &pts)) {
256 double d = eval_pts(setpts, inlink, NULL, pts);
257
258 av_log(ctx, AV_LOG_TRACE, "N:EOF PTS:%s T:%f -> PTS:%s T:%f\n",
259 d2istr(V(PTS)), V(T), d2istr(d), TS2T(d, inlink->time_base));
260 ff_outlink_set_status(outlink, status, D2TS(d));
261 return 0;
262 }
263
264 FF_FILTER_FORWARD_WANTED(outlink, inlink);
265
266 return FFERROR_NOT_READY;
267}
268
270{
271 SetPTSContext *setpts = ctx->priv;
272 av_expr_free(setpts->expr);
273 setpts->expr = NULL;
274}
275
276static int process_command(AVFilterContext *ctx, const char *cmd, const char *arg,
277 char *res, int res_len, int flags)
278{
279 SetPTSContext *setpts = ctx->priv;
280 AVExpr *new_expr;
281 int ret;
282
283 ret = ff_filter_process_command(ctx, cmd, arg, res, res_len, flags);
284
285 if (ret < 0)
286 return ret;
287
288 if (!strcmp(cmd, "expr")) {
289 ret = av_expr_parse(&new_expr, arg, var_names, NULL, NULL, NULL, NULL, 0, ctx);
290 // Only free and replace previous expression if new one succeeds,
291 // otherwise defensively keep everything intact even if reporting an error.
292 if (ret < 0) {
293 av_log(ctx, AV_LOG_ERROR, "Error while parsing expression '%s'\n", arg);
294 } else {
295 av_expr_free(setpts->expr);
296 setpts->expr = new_expr;
297 V(T_CHANGE) = NAN;
298 }
299 } else {
300 ret = AVERROR(EINVAL);
301 }
302
303 return ret;
304}
305#undef V
306
307#define OFFSET(x) offsetof(SetPTSContext, x)
308#define V AV_OPT_FLAG_VIDEO_PARAM
309#define A AV_OPT_FLAG_AUDIO_PARAM
310#define R AV_OPT_FLAG_RUNTIME_PARAM
311#define F AV_OPT_FLAG_FILTERING_PARAM
312
313#if CONFIG_SETPTS_FILTER
314static const AVOption setpts_options[] = {
315 { "expr", "Expression determining the frame timestamp", OFFSET(expr_str), AV_OPT_TYPE_STRING, { .str = "PTS" }, .flags = V|F|R },
316 { "strip_fps", "Unset framerate metadata", OFFSET(strip_fps), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = V|F },
317 { NULL }
318};
320
321static const AVFilterPad avfilter_vf_setpts_inputs[] = {
322 {
323 .name = "default",
324 .type = AVMEDIA_TYPE_VIDEO,
325 .config_props = config_input,
326 },
327};
328
329static const AVFilterPad outputs_video[] = {
330 {
331 .name = "default",
332 .type = AVMEDIA_TYPE_VIDEO,
333 .config_props = config_output_video,
334 },
335};
336
337const FFFilter ff_vf_setpts = {
338 .p.name = "setpts",
339 .p.description = NULL_IF_CONFIG_SMALL("Set PTS for the output video frame."),
341
342 .p.priv_class = &setpts_class,
343
344 .init = init,
345 .activate = activate,
346 .uninit = uninit,
347 .process_command = process_command,
348
349 .priv_size = sizeof(SetPTSContext),
350
351 FILTER_INPUTS(avfilter_vf_setpts_inputs),
352 FILTER_OUTPUTS(outputs_video),
353};
354#endif /* CONFIG_SETPTS_FILTER */
355
356#if CONFIG_ASETPTS_FILTER
357
358static const AVOption asetpts_options[] = {
359 { "expr", "Expression determining the frame timestamp", OFFSET(expr_str), AV_OPT_TYPE_STRING, { .str = "PTS" }, .flags = A|F|R },
360 { NULL }
361};
362AVFILTER_DEFINE_CLASS(asetpts);
363
364static const AVFilterPad asetpts_inputs[] = {
365 {
366 .name = "default",
367 .type = AVMEDIA_TYPE_AUDIO,
368 .config_props = config_input,
369 },
370};
371
372const FFFilter ff_af_asetpts = {
373 .p.name = "asetpts",
374 .p.description = NULL_IF_CONFIG_SMALL("Set PTS for the output audio frame."),
375 .p.priv_class = &asetpts_class,
377 .init = init,
378 .activate = activate,
379 .uninit = uninit,
380 .process_command = process_command,
381 .priv_size = sizeof(SetPTSContext),
382 FILTER_INPUTS(asetpts_inputs),
384};
385#endif /* CONFIG_ASETPTS_FILTER */
#define INTERLACED
Definition a64multienc.c:40
@ VAR_T
Definition aeval.c:53
@ VAR_S
Definition aeval.c:54
static int config_input(AVFilterLink *inlink)
static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, char *res, int res_len, int flags)
@ VAR_SAMPLE_RATE
Definition af_afftfilt.c:57
#define N
Definition af_mcompand.c:54
@ VAR_NB_SAMPLES
Definition af_volume.h:49
@ VAR_NB_CONSUMED_SAMPLES
Definition af_volume.h:48
@ VAR_STARTT
Definition af_volume.h:53
const FFFilter ff_vf_setpts
const FFFilter ff_af_asetpts
static AVFormatContext * ctx
#define T(x)
Definition vpx_arith.h:29
#define A(x)
Definition vpx_arith.h:28
const AVFilterPad ff_audio_default_filterpad[1]
An AVFilterPad array whose only entry has name "default" and is of type AVMEDIA_TYPE_AUDIO.
Definition audio.c:34
#define V
Definition avdct.c:32
int ff_inlink_acknowledge_status(AVFilterLink *link, int *rstatus, int64_t *rpts)
Test and acknowledge the change of status on the link.
Definition avfilter.c:1467
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition avfilter.c:1068
int ff_filter_process_command(AVFilterContext *ctx, const char *cmd, const char *arg, char *res, int res_len, int flags)
Generic processing of user supplied commands that are set in the same way as the filter options.
Definition avfilter.c:906
int ff_inlink_consume_frame(AVFilterLink *link, AVFrame **rframe)
Take a frame from the link's FIFO and update the link's stats.
Definition avfilter.c:1520
Main libavfilter public API header.
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define s(width, name)
Definition cbs_vp9.c:198
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
static AVFrame * frame
#define F(x)
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
void av_expr_free(AVExpr *e)
Free a parsed expression previously created with av_expr_parse().
Definition eval.c:368
double av_expr_eval(AVExpr *e, const double *const_values, void *opaque)
Evaluate a previously parsed expression.
Definition eval.c:824
int av_expr_parse(AVExpr **expr, const char *s, const char *const *const_names, const char *const *func1_names, double(*const *funcs1)(void *, double), const char *const *func2_names, double(*const *funcs2)(void *, double, double), int log_offset, void *log_ctx)
Parse an expression.
Definition eval.c:735
simple arithmetic expression evaluator
#define S(s, c, i)
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
Definition opt.h:326
@ 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...
Definition opt.h:275
#define AVFILTER_FLAG_METADATA_ONLY
The filter is a "metadata" filter - it does not modify the frame data in any way.
Definition avfilter.h:182
#define AVERROR(e)
Definition error.h:45
#define AV_FRAME_FLAG_INTERLACED
A flag to mark frames whose content is interlaced.
Definition frame.h:695
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
Definition log.h:236
#define AV_LOG_VERBOSE
Detailed information.
Definition log.h:226
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
static double av_q2d(AVRational a)
Convert an AVRational to a double.
Definition rational.h:104
AVMediaType
Definition avutil.h:198
@ AVMEDIA_TYPE_AUDIO
Definition avutil.h:201
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
#define R
Definition huffyuv.h:44
static av_cold void uninit(AVBitStreamFilterContext *ctx)
static int activate(AVBitStreamFilterContext *ctx)
const char * arg
Definition jacosubdec.c:65
#define TS2D(ts)
Definition filters.h:482
#define FILTER_INPUTS(array)
Definition filters.h:264
#define FILTER_OUTPUTS(array)
Definition filters.h:265
#define D2TS(d)
Definition filters.h:481
#define FF_FILTER_FORWARD_WANTED(outlink, inlink)
Forward the frame_wanted_out flag from an output link to an input link.
Definition filters.h:694
#define TS2T(ts, tb)
Definition filters.h:483
static void ff_outlink_set_status(AVFilterLink *link, int status, int64_t pts)
Set the status field of a link from the source filter.
Definition filters.h:629
#define FFERROR_NOT_READY
Filters implementation helper functions and internal structures.
Definition filters.h:34
#define FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink)
Forward the status on an output link to an input link.
Definition filters.h:639
static FilterLink * ff_filter_link(AVFilterLink *link)
Definition filters.h:199
#define AVFILTER_DEFINE_CLASS(fname)
Definition filters.h:478
#define av_cold
Definition attributes.h:117
common internal API header
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition internal.h:88
#define isnan(x)
Definition libm.h:342
#define NAN
var_name
Definition noise.c:46
@ VAR_STARTPTS
Definition noise.c:52
@ VAR_PTS
Definition noise.c:49
@ VAR_TB
Definition noise.c:48
@ VAR_N
Definition noise.c:47
@ VAR_VARS_NB
Definition noise.c:59
static const char *const var_names[]
Definition noise.c:30
AVOptions.
#define TB(i)
Definition prosumer.c:202
static int process_command(AVFilterContext *ctx, const char *cmd, const char *arg, char *res, int res_len, int flags)
Definition setpts.c:276
@ VAR_INTERLACED
Definition setpts.c:68
@ VAR_PREV_INT
Definition setpts.c:73
@ VAR_FRAME_RATE
Definition setpts.c:67
@ VAR_FR
Definition setpts.c:86
@ VAR_VARS_NB
Definition setpts.c:88
@ VAR_PREV_OUTT
Definition setpts.c:75
@ VAR_T_CHANGE
Definition setpts.c:87
@ VAR_RTCSTART
Definition setpts.c:83
@ VAR_RTCTIME
Definition setpts.c:82
static int config_input(AVFilterLink *inlink)
Definition setpts.c:126
static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
Definition setpts.c:194
#define BUF_SIZE
Definition setpts.c:159
static char * double2int64str(char *buf, double v)
Definition setpts.c:161
static int config_output_video(AVFilterLink *outlink)
Definition setpts.c:148
#define V(name_)
Definition setpts.c:100
#define d2istr(v)
Definition setpts.c:192
static double eval_pts(SetPTSContext *setpts, AVFilterLink *inlink, AVFrame *frame, int64_t pts)
Definition setpts.c:168
static int activate(AVFilterContext *ctx)
Definition setpts.c:237
static av_cold void uninit(AVFilterContext *ctx)
Definition setpts.c:269
#define OFFSET(x)
Definition setpts.c:307
@ VAR_PREV_OUTPTS
Definition setts.c:64
@ VAR_SR
Definition setts.c:77
@ VAR_PREV_INPTS
Definition setts.c:61
#define snprintf
Definition snprintf.h:34
Describe the class of an AVClass context structure.
Definition log.h:76
Definition eval.c:171
An instance of a filter.
Definition avfilter.h:273
void * priv
private data for use by the filter
Definition avfilter.h:288
AVFilterLink ** outputs
array of pointers to output links
Definition avfilter.h:285
A filter pad used for either input or output.
Definition filters.h:40
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
AVOption.
Definition opt.h:428
Rational number (pair of numerator and denominator).
Definition rational.h:58
int num
Numerator.
Definition rational.h:59
int den
Denominator.
Definition rational.h:60
enum AVMediaType type
Definition setpts.c:97
char * expr_str
Definition setpts.c:93
AVExpr * expr
Definition setpts.c:94
double var_values[VAR_VARS_NB]
Definition setpts.c:96
int strip_fps
Definition setpts.c:95
#define av_log(a,...)
int64_t av_gettime(void)
Get the current time in microseconds.
Definition time.c:40
static int64_t pts