Browse code

Add setpts filter, ported from the libavfilter soc repo.

Originally committed as revision 25655 to svn://svn.ffmpeg.org/ffmpeg/trunk

Stefano Sabatini authored on 2010/11/03 07:29:17
Showing 6 changed files
... ...
@@ -51,6 +51,7 @@ version <next>:
51 51
 - ffmpeg -force_key_frames option added
52 52
 - demuxer for receiving raw rtp:// URLs without an SDP description
53 53
 - single stream LATM/LOAS decoder
54
+- setpts filter added
54 55
 
55 56
 
56 57
 version 0.6:
... ...
@@ -502,6 +502,66 @@ settb=2*intb
502 502
 settb=AVTB
503 503
 @end example
504 504
 
505
+@section setpts
506
+
507
+Change the PTS (presentation timestamp) of the input video frames.
508
+
509
+Accept in input an expression evaluated through the eval API, which
510
+can contain the following constants:
511
+
512
+@table @option
513
+@item PTS
514
+the presentation timestamp in input
515
+
516
+@item PI
517
+Greek PI
518
+
519
+@item PHI
520
+golden ratio
521
+
522
+@item E
523
+Euler number
524
+
525
+@item N
526
+the count of the input frame, starting from 0.
527
+
528
+@item STARTPTS
529
+the PTS of the first video frame
530
+
531
+@item INTERLACED
532
+tell if the current frame is interlaced
533
+
534
+@item POS
535
+original position in the file of the frame, or undefined if undefined
536
+for the current frame
537
+
538
+@item PREV_INPTS
539
+previous input PTS
540
+
541
+@item PREV_OUTPTS
542
+previous output PTS
543
+
544
+@end table
545
+
546
+Some examples follow:
547
+
548
+@example
549
+# start counting PTS from zero
550
+setpts=PTS-STARTPTS
551
+
552
+# fast motion
553
+setpts=0.5*PTS
554
+
555
+# slow motion
556
+setpts=2.0*PTS
557
+
558
+# fixed rate 25 fps
559
+setpts=N/(25*TB)
560
+
561
+# fixed rate 25 fps with some jitter
562
+setpts='1/(25*TB) * (N + 0.05 * sin(N*2*PI/25))'
563
+@end example
564
+
505 565
 @section slicify
506 566
 
507 567
 Pass the images of input video on to next video filter as multiple
... ...
@@ -37,6 +37,7 @@ OBJS-$(CONFIG_PIXDESCTEST_FILTER)            += vf_pixdesctest.o
37 37
 OBJS-$(CONFIG_PIXELASPECT_FILTER)            += vf_aspect.o
38 38
 OBJS-$(CONFIG_SCALE_FILTER)                  += vf_scale.o
39 39
 OBJS-$(CONFIG_SETTB_FILTER)                  += vf_settb.o
40
+OBJS-$(CONFIG_SETPTS_FILTER)                 += vf_setpts.o
40 41
 OBJS-$(CONFIG_SLICIFY_FILTER)                += vf_slicify.o
41 42
 OBJS-$(CONFIG_TRANSPOSE_FILTER)              += vf_transpose.o
42 43
 OBJS-$(CONFIG_UNSHARP_FILTER)                += vf_unsharp.o
... ...
@@ -57,6 +57,7 @@ void avfilter_register_all(void)
57 57
     REGISTER_FILTER (PIXELASPECT, pixelaspect, vf);
58 58
     REGISTER_FILTER (SCALE,       scale,       vf);
59 59
     REGISTER_FILTER (SETTB,       settb,       vf);
60
+    REGISTER_FILTER (SETPTS,      setpts,      vf);
60 61
     REGISTER_FILTER (SLICIFY,     slicify,     vf);
61 62
     REGISTER_FILTER (TRANSPOSE,   transpose,   vf);
62 63
     REGISTER_FILTER (UNSHARP,     unsharp,     vf);
... ...
@@ -25,7 +25,7 @@
25 25
 #include "libavutil/avutil.h"
26 26
 
27 27
 #define LIBAVFILTER_VERSION_MAJOR  1
28
-#define LIBAVFILTER_VERSION_MINOR 53
28
+#define LIBAVFILTER_VERSION_MINOR 54
29 29
 #define LIBAVFILTER_VERSION_MICRO  0
30 30
 
31 31
 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
32 32
new file mode 100644
... ...
@@ -0,0 +1,157 @@
0
+/*
1
+ * Copyright (c) 2010 Stefano Sabatini
2
+ * Copyright (c) 2008 Victor Paesa
3
+ *
4
+ * This file is part of FFmpeg.
5
+ *
6
+ * FFmpeg is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * FFmpeg is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with FFmpeg; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ */
20
+
21
+/**
22
+ * @file
23
+ * video presentation timestamp (PTS) modification filter
24
+ */
25
+
26
+/* #define DEBUG */
27
+
28
+#include "libavutil/eval.h"
29
+#include "avfilter.h"
30
+
31
+static const char *var_names[] = {
32
+    "E",           ///< Euler number
33
+    "INTERLACED",  ///< tell if the current frame is interlaced
34
+    "N",           ///< frame number (starting at zero)
35
+    "PHI",         ///< golden ratio
36
+    "PI",          ///< greek pi
37
+    "POS",         ///< original position in the file of the frame
38
+    "PREV_INPTS",  ///< previous  input PTS
39
+    "PREV_OUTPTS", ///< previous output PTS
40
+    "PTS",         ///< original pts in the file of the frame
41
+    "STARTPTS",   ///< PTS at start of movie
42
+    "TB",          ///< timebase
43
+    NULL
44
+};
45
+
46
+enum var_name {
47
+    VAR_E,
48
+    VAR_INTERLACED,
49
+    VAR_N,
50
+    VAR_PHI,
51
+    VAR_PI,
52
+    VAR_POS,
53
+    VAR_PREV_INPTS,
54
+    VAR_PREV_OUTPTS,
55
+    VAR_PTS,
56
+    VAR_STARTPTS,
57
+    VAR_TB,
58
+    VAR_VARS_NB
59
+};
60
+
61
+typedef struct {
62
+    AVExpr *expr;
63
+    double var_values[VAR_VARS_NB];
64
+} SetPTSContext;
65
+
66
+static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
67
+{
68
+    SetPTSContext *setpts = ctx->priv;
69
+    int ret;
70
+
71
+    if ((ret = av_parse_expr(&setpts->expr, args ? args : "PTS",
72
+                             var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) {
73
+        av_log(ctx, AV_LOG_ERROR, "Error while parsing expression '%s'\n", args);
74
+        return ret;
75
+    }
76
+
77
+    setpts->var_values[VAR_E          ] = M_E;
78
+    setpts->var_values[VAR_N          ] = 0.0;
79
+    setpts->var_values[VAR_PHI        ] = M_PHI;
80
+    setpts->var_values[VAR_PI         ] = M_PI;
81
+    setpts->var_values[VAR_PREV_INPTS ] = NAN;
82
+    setpts->var_values[VAR_PREV_OUTPTS] = NAN;
83
+    setpts->var_values[VAR_STARTPTS   ] = NAN;
84
+    return 0;
85
+}
86
+
87
+static int config_input(AVFilterLink *inlink)
88
+{
89
+    SetPTSContext *setpts = inlink->dst->priv;
90
+
91
+    setpts->var_values[VAR_TB] = av_q2d(inlink->time_base);
92
+
93
+    av_log(inlink->src, AV_LOG_INFO, "TB:%f\n", setpts->var_values[VAR_TB]);
94
+    return 0;
95
+}
96
+
97
+#define D2TS(d)  (isnan(d) ? AV_NOPTS_VALUE : (int64_t)(d))
98
+#define TS2D(ts) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts))
99
+
100
+static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
101
+{
102
+    SetPTSContext *setpts = inlink->dst->priv;
103
+    double d;
104
+    AVFilterBufferRef *outpicref = avfilter_ref_buffer(inpicref, ~0);
105
+
106
+    if (isnan(setpts->var_values[VAR_STARTPTS]))
107
+        setpts->var_values[VAR_STARTPTS] = TS2D(inpicref->pts);
108
+
109
+    setpts->var_values[VAR_INTERLACED] = inpicref->video->interlaced;
110
+    setpts->var_values[VAR_PTS       ] = TS2D(inpicref->pts);
111
+    setpts->var_values[VAR_POS       ] = inpicref->pos == -1 ? NAN : inpicref->pos;
112
+
113
+    d = av_eval_expr(setpts->expr, setpts->var_values, NULL);
114
+    outpicref->pts = D2TS(d);
115
+
116
+#ifdef DEBUG
117
+    av_log(inlink->dst, AV_LOG_DEBUG,
118
+           "n:%"PRId64" interlaced:%d pos:%d pts:%"PRId64" t:%f -> pts:%"PRId64" t:%f\n",
119
+           (int64_t)setpts->var_values[VAR_N],
120
+           (int)setpts->var_values[VAR_INTERLACED],
121
+           (int)setpts->var_values[VAR_POS],
122
+           inpicref ->pts, inpicref ->pts * av_q2d(inlink->time_base),
123
+           outpicref->pts, outpicref->pts * av_q2d(inlink->time_base));
124
+#endif
125
+
126
+    setpts->var_values[VAR_N] += 1.0;
127
+    setpts->var_values[VAR_PREV_INPTS ] = TS2D(inpicref ->pts);
128
+    setpts->var_values[VAR_PREV_OUTPTS] = TS2D(outpicref->pts);
129
+    avfilter_start_frame(inlink->dst->outputs[0], outpicref);
130
+}
131
+
132
+static av_cold void uninit(AVFilterContext *ctx)
133
+{
134
+    SetPTSContext *setpts = ctx->priv;
135
+    av_free_expr(setpts->expr);
136
+    setpts->expr = NULL;
137
+}
138
+
139
+AVFilter avfilter_vf_setpts = {
140
+    .name      = "setpts",
141
+    .description = NULL_IF_CONFIG_SMALL("Set PTS for the output video frame."),
142
+    .init      = init,
143
+    .uninit    = uninit,
144
+
145
+    .priv_size = sizeof(SetPTSContext),
146
+
147
+    .inputs    = (AVFilterPad[]) {{ .name             = "default",
148
+                                    .type             = AVMEDIA_TYPE_VIDEO,
149
+                                    .get_video_buffer = avfilter_null_get_video_buffer,
150
+                                    .config_props     = config_input,
151
+                                    .start_frame      = start_frame, },
152
+                                  { .name = NULL }},
153
+    .outputs   = (AVFilterPad[]) {{ .name             = "default",
154
+                                    .type             = AVMEDIA_TYPE_VIDEO, },
155
+                                  { .name = NULL}},
156
+};