2 * Copyright (c) 2010 Stefano Sabatini
3 * Copyright (c) 2008 Victor Paesa
5 * This file is part of Libav.
7 * Libav 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.
12 * Libav 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.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with Libav; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 * video presentation timestamp (PTS) modification filter
29 #include "libavutil/eval.h"
30 #include "libavutil/internal.h"
31 #include "libavutil/mathematics.h"
32 #include "libavutil/time.h"
37 static const char *const var_names
[] = {
38 "E", ///< Euler number
39 "INTERLACED", ///< tell if the current frame is interlaced
40 "N", ///< frame number (starting at zero)
41 "PHI", ///< golden ratio
43 "POS", ///< original position in the file of the frame
44 "PREV_INPTS", ///< previous input PTS
45 "PREV_OUTPTS", ///< previous output PTS
46 "PTS", ///< original pts in the file of the frame
47 "STARTPTS", ///< PTS at start of movie
49 "RTCTIME", ///< wallclock (RTC) time in micro seconds
50 "RTCSTART", ///< wallclock (RTC) time at the start of the movie in micro seconds
73 double var_values
[VAR_VARS_NB
];
76 static av_cold
int init(AVFilterContext
*ctx
, const char *args
)
78 SetPTSContext
*setpts
= ctx
->priv
;
81 if ((ret
= av_expr_parse(&setpts
->expr
, args
? args
: "PTS",
82 var_names
, NULL
, NULL
, NULL
, NULL
, 0, ctx
)) < 0) {
83 av_log(ctx
, AV_LOG_ERROR
, "Error while parsing expression '%s'\n", args
);
87 setpts
->var_values
[VAR_E
] = M_E
;
88 setpts
->var_values
[VAR_N
] = 0.0;
89 setpts
->var_values
[VAR_PHI
] = M_PHI
;
90 setpts
->var_values
[VAR_PI
] = M_PI
;
91 setpts
->var_values
[VAR_PREV_INPTS
] = NAN
;
92 setpts
->var_values
[VAR_PREV_OUTPTS
] = NAN
;
93 setpts
->var_values
[VAR_STARTPTS
] = NAN
;
97 static int config_input(AVFilterLink
*inlink
)
99 SetPTSContext
*setpts
= inlink
->dst
->priv
;
101 setpts
->var_values
[VAR_TB
] = av_q2d(inlink
->time_base
);
102 setpts
->var_values
[VAR_RTCSTART
] = av_gettime();
104 av_log(inlink
->src
, AV_LOG_VERBOSE
, "TB:%f\n", setpts
->var_values
[VAR_TB
]);
108 #define D2TS(d) (isnan(d) ? AV_NOPTS_VALUE : (int64_t)(d))
109 #define TS2D(ts) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts))
111 static int filter_frame(AVFilterLink
*inlink
, AVFilterBufferRef
*frame
)
113 SetPTSContext
*setpts
= inlink
->dst
->priv
;
114 int64_t in_pts
= frame
->pts
;
117 if (isnan(setpts
->var_values
[VAR_STARTPTS
]))
118 setpts
->var_values
[VAR_STARTPTS
] = TS2D(frame
->pts
);
120 setpts
->var_values
[VAR_INTERLACED
] = frame
->video
->interlaced
;
121 setpts
->var_values
[VAR_PTS
] = TS2D(frame
->pts
);
122 setpts
->var_values
[VAR_POS
] = frame
->pos
== -1 ? NAN
: frame
->pos
;
123 setpts
->var_values
[VAR_RTCTIME
] = av_gettime();
125 d
= av_expr_eval(setpts
->expr
, setpts
->var_values
, NULL
);
126 frame
->pts
= D2TS(d
);
129 av_log(inlink
->dst
, AV_LOG_DEBUG
,
130 "n:%"PRId64
" interlaced:%d pos:%"PRId64
" pts:%"PRId64
" t:%f -> pts:%"PRId64
" t:%f\n",
131 (int64_t)setpts
->var_values
[VAR_N
],
132 (int)setpts
->var_values
[VAR_INTERLACED
],
133 frame
->pos
, in_pts
, in_pts
* av_q2d(inlink
->time_base
),
134 frame
->pts
, frame
->pts
* av_q2d(inlink
->time_base
));
138 setpts
->var_values
[VAR_N
] += 1.0;
139 setpts
->var_values
[VAR_PREV_INPTS
] = TS2D(in_pts
);
140 setpts
->var_values
[VAR_PREV_OUTPTS
] = TS2D(frame
->pts
);
141 return ff_filter_frame(inlink
->dst
->outputs
[0], frame
);
144 static av_cold
void uninit(AVFilterContext
*ctx
)
146 SetPTSContext
*setpts
= ctx
->priv
;
147 av_expr_free(setpts
->expr
);
151 static const AVFilterPad avfilter_vf_setpts_inputs
[] = {
154 .type
= AVMEDIA_TYPE_VIDEO
,
155 .get_video_buffer
= ff_null_get_video_buffer
,
156 .config_props
= config_input
,
157 .filter_frame
= filter_frame
,
162 static const AVFilterPad avfilter_vf_setpts_outputs
[] = {
165 .type
= AVMEDIA_TYPE_VIDEO
,
170 AVFilter avfilter_vf_setpts
= {
172 .description
= NULL_IF_CONFIG_SMALL("Set PTS for the output video frame."),
176 .priv_size
= sizeof(SetPTSContext
),
178 .inputs
= avfilter_vf_setpts_inputs
,
179 .outputs
= avfilter_vf_setpts_outputs
,