[FFmpeg-devel] [PATCH 3/4] Add setpts filter, ported from the libavfilter soc repo.

Stefano Sabatini stefano.sabatini-lala
Sun Oct 31 01:30:31 CEST 2010


---
 doc/filters.texi         |   66 ++++++++++++++++++
 libavfilter/Makefile     |    1 +
 libavfilter/allfilters.c |    1 +
 libavfilter/vf_setpts.c  |  170 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 238 insertions(+), 0 deletions(-)
 create mode 100644 libavfilter/vf_setpts.c

diff --git a/doc/filters.texi b/doc/filters.texi
index 157f621..19c4d29 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -502,6 +502,72 @@ settb=2*intb
 settb=AVTB
 @end example
 
+ at section setpts
+
+Change the PTS (presentation timestamp) of the input video frames.
+
+Accept in input an expression evaluated through the eval API, which
+can contain the following constants:
+
+ at table @option
+ at item PTS
+the presentation timestamp in input
+
+ at item PI
+Greek PI
+
+ at item PHI
+golden ratio
+
+ at item E
+Euler number
+
+ at item TBNUM, TBDEN
+input timebase numerator and denomimator
+
+ at item N
+the count of the input frame, starting from 0.
+
+ at item STARTPTS
+the PTS of the first video frame
+
+ at item INTERLACED
+tell if the current frame is interlaced
+
+ at item NOPTS
+1 if the input timestamp is undefined, 0 otherwise
+
+ at item POS
+original position in the file of the frame, or undefined if undefined
+for the current frame
+
+ at item PREV_INPTS
+previous input PTS
+
+ at item PREV_OUTPTS
+previous output PTS
+
+ at end table
+
+Some examples follow:
+
+ at example
+# start counting PTS from zero
+setpts=PTS-STARTPTS
+
+# fast motion
+setpts=0.5*PTS
+
+# slow motion
+setpts=2.0*PTS
+
+# fixed rate 25 fps
+setpts=N/(25*TB)
+
+# fixed rate 25 fps with some jitter
+setpts='1/(25*TB) * (N + 0.05 * sin(N*2*PI/25))'
+ at end example
+
 @section slicify
 
 Pass the images of input video on to next video filter as multiple
diff --git a/libavfilter/Makefile b/libavfilter/Makefile
index 38d2762..9dc92be 100644
--- a/libavfilter/Makefile
+++ b/libavfilter/Makefile
@@ -37,6 +37,7 @@ OBJS-$(CONFIG_PIXDESCTEST_FILTER)            += vf_pixdesctest.o
 OBJS-$(CONFIG_PIXELASPECT_FILTER)            += vf_aspect.o
 OBJS-$(CONFIG_SCALE_FILTER)                  += vf_scale.o
 OBJS-$(CONFIG_SETTB_FILTER)                  += vf_settb.o
+OBJS-$(CONFIG_SETPTS_FILTER)                 += vf_setpts.o
 OBJS-$(CONFIG_SLICIFY_FILTER)                += vf_slicify.o
 OBJS-$(CONFIG_TRANSPOSE_FILTER)              += vf_transpose.o
 OBJS-$(CONFIG_UNSHARP_FILTER)                += vf_unsharp.o
diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c
index bade1dd..8ba0b62 100644
--- a/libavfilter/allfilters.c
+++ b/libavfilter/allfilters.c
@@ -57,6 +57,7 @@ void avfilter_register_all(void)
     REGISTER_FILTER (PIXELASPECT, pixelaspect, vf);
     REGISTER_FILTER (SCALE,       scale,       vf);
     REGISTER_FILTER (SETTB,       settb,       vf);
+    REGISTER_FILTER (SETPTS,      setpts,      vf);
     REGISTER_FILTER (SLICIFY,     slicify,     vf);
     REGISTER_FILTER (TRANSPOSE,   transpose,   vf);
     REGISTER_FILTER (UNSHARP,     unsharp,     vf);
diff --git a/libavfilter/vf_setpts.c b/libavfilter/vf_setpts.c
new file mode 100644
index 0000000..e0a9609
--- /dev/null
+++ b/libavfilter/vf_setpts.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2010 Stefano Sabatini
+ * Copyright (C) 2008 Victor Paesa
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * video presentation timestamp (PTS) modification filter
+ */
+
+#define DEBUG
+
+#include "libavutil/eval.h"
+#include "avfilter.h"
+
+static const char *var_names[] = {
+    "E",           ///< Euler number
+    "INTERLACED",  ///< tell if the current frame is interlaced
+    "N",           ///< frame number (starting at zero)
+    "NOPTS",       ///< 1 if the input value is undefined, 0 otherwise
+    "PHI",         ///< golden ratio
+    "PI",          ///< greek pi
+    "POS",         ///< original position in the file of the frame
+    "PREV_INPTS",  ///< previous  input PTS
+    "PREV_OUTPTS", ///< previous output PTS
+    "PTS",         ///< original pts in the file of the frame
+    "START_PTS",   ///< PTS at start of movie
+    "TB",          ///< timebase
+    "TBNUM",       ///< timebase numerator
+    "TBDEN",       ///< timebase denominator
+    NULL
+};
+
+enum var_name {
+    VAR_E,
+    VAR_INTERLACED,
+    VAR_N,
+    VAR_NOPTS,
+    VAR_PHI,
+    VAR_PI,
+    VAR_POS,
+    VAR_PREV_INPTS,
+    VAR_PREV_OUTPTS,
+    VAR_PTS,
+    VAR_START_PTS,
+    VAR_TB,
+    VAR_TBNUM,
+    VAR_TBDEN,
+    VAR_VARS_NB
+};
+
+typedef struct {
+    AVExpr *expr;
+    double var_values[VAR_VARS_NB];
+} SetPTSContext;
+
+static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
+{
+    SetPTSContext *setpts = ctx->priv;
+    int ret;
+
+    if ((ret = av_parse_expr(&setpts->expr, args ? args : "PTS",
+                             var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) {
+        av_log(ctx, AV_LOG_ERROR, "Error while parsing expression '%s'\n", args);
+        return ret;
+    }
+
+    setpts->var_values[VAR_E          ] = M_E;
+    setpts->var_values[VAR_N          ] = 0.0;
+    setpts->var_values[VAR_NOPTS      ] = NAN;
+    setpts->var_values[VAR_PHI        ] = M_PHI;
+    setpts->var_values[VAR_PI         ] = M_PI;
+    setpts->var_values[VAR_PREV_INPTS ] = NAN;
+    setpts->var_values[VAR_PREV_OUTPTS] = NAN;
+    setpts->var_values[VAR_START_PTS  ] = NAN;
+    return 0;
+}
+
+static int config_input(AVFilterLink *inlink)
+{
+    SetPTSContext *setpts = inlink->dst->priv;
+
+    setpts->var_values[VAR_TB]    = (double)inlink->time_base.num/inlink->time_base.den;
+    setpts->var_values[VAR_TBNUM] = inlink->time_base.num;
+    setpts->var_values[VAR_TBDEN] = inlink->time_base.den;
+
+    av_log(inlink->src, AV_LOG_INFO, "TB:%f TBNUM:%d TBDEN:%d\n",
+           setpts->var_values[VAR_TB], inlink->time_base.num, inlink->time_base.den);
+    return 0;
+}
+
+#define D2TS(d)  (isnan(d) ? AV_NOPTS_VALUE : (int64_t)(d))
+#define TS2D(ts) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts))
+
+static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
+{
+    SetPTSContext *setpts = inlink->dst->priv;
+    double d;
+    AVFilterBufferRef *outpicref = avfilter_ref_buffer(inpicref, ~0);
+
+    if (isnan(setpts->var_values[VAR_START_PTS]))
+        setpts->var_values[VAR_START_PTS] = TS2D(inpicref->pts);
+
+    setpts->var_values[VAR_INTERLACED] = inpicref->video->interlaced;
+    setpts->var_values[VAR_NOPTS     ] = inpicref->pts == AV_NOPTS_VALUE;
+    setpts->var_values[VAR_PTS       ] = TS2D(inpicref->pts);
+    setpts->var_values[VAR_POS       ] = inpicref->pos == -1 ? NAN : inpicref->pos;
+
+    d = av_eval_expr(setpts->expr, setpts->var_values, NULL);
+    outpicref->pts = D2TS(d);
+
+#ifdef DEBUG
+    av_log(inlink->dst, AV_LOG_DEBUG,
+           "n:%"PRId64" interlaced:%d pos:%d pts:%"PRId64" t:%f -> pts:%"PRId64" t:%f\n",
+           (int64_t)setpts->var_values[VAR_N],
+           (int)setpts->var_values[VAR_INTERLACED],
+           (int)setpts->var_values[VAR_POS],
+           inpicref ->pts,
+           (double)inpicref->pts * inlink->time_base.num / inlink->time_base.den,
+           outpicref->pts,
+           (double)outpicref->pts * inlink->time_base.num / inlink->time_base.den);
+#endif
+
+    setpts->var_values[VAR_N] += 1.0;
+    setpts->var_values[VAR_PREV_INPTS ] = TS2D(inpicref ->pts);
+    setpts->var_values[VAR_PREV_OUTPTS] = TS2D(outpicref->pts);
+    avfilter_start_frame(inlink->dst->outputs[0], outpicref);
+}
+
+static av_cold void uninit(AVFilterContext *ctx)
+{
+    SetPTSContext *setpts = ctx->priv;
+    av_free_expr(setpts->expr);
+    setpts->expr = NULL;
+}
+
+AVFilter avfilter_vf_setpts = {
+    .name      = "setpts",
+    .description = NULL_IF_CONFIG_SMALL("Set PTS for the output video frame."),
+    .init      = init,
+    .uninit    = uninit,
+
+    .priv_size = sizeof(SetPTSContext),
+
+    .inputs    = (AVFilterPad[]) {{ .name             = "default",
+                                    .type             = AVMEDIA_TYPE_VIDEO,
+                                    .get_video_buffer = avfilter_null_get_video_buffer,
+                                    .config_props     = config_input,
+                                    .start_frame      = start_frame, },
+                                  { .name = NULL }},
+    .outputs   = (AVFilterPad[]) {{ .name             = "default",
+                                    .type             = AVMEDIA_TYPE_VIDEO, },
+                                  { .name = NULL}},
+};
-- 
1.7.1




More information about the ffmpeg-devel mailing list