ffmpeg / libavfilter / vf_setpts.c @ e73127a4
History | View | Annotate | Download (5.13 KB)
1 |
/*
|
---|---|
2 |
* Copyright (c) 2010 Stefano Sabatini
|
3 |
* Copyright (c) 2008 Victor Paesa
|
4 |
*
|
5 |
* This file is part of Libav.
|
6 |
*
|
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.
|
11 |
*
|
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.
|
16 |
*
|
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
|
20 |
*/
|
21 |
|
22 |
/**
|
23 |
* @file
|
24 |
* video presentation timestamp (PTS) modification filter
|
25 |
*/
|
26 |
|
27 |
/* #define DEBUG */
|
28 |
|
29 |
#include "libavutil/eval.h" |
30 |
#include "avfilter.h" |
31 |
|
32 |
static const char *var_names[] = { |
33 |
"E", ///< Euler number |
34 |
"INTERLACED", ///< tell if the current frame is interlaced |
35 |
"N", ///< frame number (starting at zero) |
36 |
"PHI", ///< golden ratio |
37 |
"PI", ///< greek pi |
38 |
"POS", ///< original position in the file of the frame |
39 |
"PREV_INPTS", ///< previous input PTS |
40 |
"PREV_OUTPTS", ///< previous output PTS |
41 |
"PTS", ///< original pts in the file of the frame |
42 |
"STARTPTS", ///< PTS at start of movie |
43 |
"TB", ///< timebase |
44 |
NULL
|
45 |
}; |
46 |
|
47 |
enum var_name {
|
48 |
VAR_E, |
49 |
VAR_INTERLACED, |
50 |
VAR_N, |
51 |
VAR_PHI, |
52 |
VAR_PI, |
53 |
VAR_POS, |
54 |
VAR_PREV_INPTS, |
55 |
VAR_PREV_OUTPTS, |
56 |
VAR_PTS, |
57 |
VAR_STARTPTS, |
58 |
VAR_TB, |
59 |
VAR_VARS_NB |
60 |
}; |
61 |
|
62 |
typedef struct { |
63 |
AVExpr *expr; |
64 |
double var_values[VAR_VARS_NB];
|
65 |
} SetPTSContext; |
66 |
|
67 |
static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) |
68 |
{ |
69 |
SetPTSContext *setpts = ctx->priv; |
70 |
int ret;
|
71 |
|
72 |
if ((ret = av_expr_parse(&setpts->expr, args ? args : "PTS", |
73 |
var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) { |
74 |
av_log(ctx, AV_LOG_ERROR, "Error while parsing expression '%s'\n", args);
|
75 |
return ret;
|
76 |
} |
77 |
|
78 |
setpts->var_values[VAR_E ] = M_E; |
79 |
setpts->var_values[VAR_N ] = 0.0; |
80 |
setpts->var_values[VAR_PHI ] = M_PHI; |
81 |
setpts->var_values[VAR_PI ] = M_PI; |
82 |
setpts->var_values[VAR_PREV_INPTS ] = NAN; |
83 |
setpts->var_values[VAR_PREV_OUTPTS] = NAN; |
84 |
setpts->var_values[VAR_STARTPTS ] = NAN; |
85 |
return 0; |
86 |
} |
87 |
|
88 |
static int config_input(AVFilterLink *inlink) |
89 |
{ |
90 |
SetPTSContext *setpts = inlink->dst->priv; |
91 |
|
92 |
setpts->var_values[VAR_TB] = av_q2d(inlink->time_base); |
93 |
|
94 |
av_log(inlink->src, AV_LOG_INFO, "TB:%f\n", setpts->var_values[VAR_TB]);
|
95 |
return 0; |
96 |
} |
97 |
|
98 |
#define D2TS(d) (isnan(d) ? AV_NOPTS_VALUE : (int64_t)(d))
|
99 |
#define TS2D(ts) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts)) |
100 |
|
101 |
static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref) |
102 |
{ |
103 |
SetPTSContext *setpts = inlink->dst->priv; |
104 |
double d;
|
105 |
AVFilterBufferRef *outpicref = avfilter_ref_buffer(inpicref, ~0);
|
106 |
|
107 |
if (isnan(setpts->var_values[VAR_STARTPTS]))
|
108 |
setpts->var_values[VAR_STARTPTS] = TS2D(inpicref->pts); |
109 |
|
110 |
setpts->var_values[VAR_INTERLACED] = inpicref->video->interlaced; |
111 |
setpts->var_values[VAR_PTS ] = TS2D(inpicref->pts); |
112 |
setpts->var_values[VAR_POS ] = inpicref->pos == -1 ? NAN : inpicref->pos;
|
113 |
|
114 |
d = av_expr_eval(setpts->expr, setpts->var_values, NULL);
|
115 |
outpicref->pts = D2TS(d); |
116 |
|
117 |
#ifdef DEBUG
|
118 |
av_log(inlink->dst, AV_LOG_DEBUG, |
119 |
"n:%"PRId64" interlaced:%d pos:%"PRId64" pts:%"PRId64" t:%f -> pts:%"PRId64" t:%f\n", |
120 |
(int64_t)setpts->var_values[VAR_N], |
121 |
(int)setpts->var_values[VAR_INTERLACED],
|
122 |
inpicref ->pos, |
123 |
inpicref ->pts, inpicref ->pts * av_q2d(inlink->time_base), |
124 |
outpicref->pts, outpicref->pts * av_q2d(inlink->time_base)); |
125 |
#endif
|
126 |
|
127 |
setpts->var_values[VAR_N] += 1.0; |
128 |
setpts->var_values[VAR_PREV_INPTS ] = TS2D(inpicref ->pts); |
129 |
setpts->var_values[VAR_PREV_OUTPTS] = TS2D(outpicref->pts); |
130 |
avfilter_start_frame(inlink->dst->outputs[0], outpicref);
|
131 |
} |
132 |
|
133 |
static av_cold void uninit(AVFilterContext *ctx) |
134 |
{ |
135 |
SetPTSContext *setpts = ctx->priv; |
136 |
av_expr_free(setpts->expr); |
137 |
setpts->expr = NULL;
|
138 |
} |
139 |
|
140 |
AVFilter avfilter_vf_setpts = { |
141 |
.name = "setpts",
|
142 |
.description = NULL_IF_CONFIG_SMALL("Set PTS for the output video frame."),
|
143 |
.init = init, |
144 |
.uninit = uninit, |
145 |
|
146 |
.priv_size = sizeof(SetPTSContext),
|
147 |
|
148 |
.inputs = (AVFilterPad[]) {{ .name = "default",
|
149 |
.type = AVMEDIA_TYPE_VIDEO, |
150 |
.get_video_buffer = avfilter_null_get_video_buffer, |
151 |
.config_props = config_input, |
152 |
.start_frame = start_frame, }, |
153 |
{ .name = NULL }},
|
154 |
.outputs = (AVFilterPad[]) {{ .name = "default",
|
155 |
.type = AVMEDIA_TYPE_VIDEO, }, |
156 |
{ .name = NULL}},
|
157 |
}; |