[FFmpeg-devel] [PATCH] lavfi/setpts: add stp and ldp functions

Stefano Sabatini stefasab at gmail.com
Tue Sep 9 11:54:44 CEST 2014


TODO: bump micro version
---
 doc/filters.texi     | 18 +++++++++++++++++-
 libavfilter/setpts.c | 33 ++++++++++++++++++++++++++++++---
 2 files changed, 47 insertions(+), 4 deletions(-)

diff --git a/doc/filters.texi b/doc/filters.texi
index bb486ea..4338a3e 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -10528,7 +10528,7 @@ The expression which is evaluated for each frame to construct its timestamp.
 @end table
 
 The expression is evaluated through the eval API and can contain the following
-constants:
+constants and functions:
 
 @table @option
 @item FRAME_RATE
@@ -10589,6 +10589,14 @@ The wallclock (RTC) time at the start of the movie in microseconds.
 @item TB
 The timebase of the input timestamps.
 
+ at item ldp(idx)
+Load the persistent variable loaded in register @var{idx}, which was
+filled with the @code{stp} function.
+
+ at item stp(idx, val)
+Store the value @var{val} in the persistent register with index
+ at var{idx}, which must be a value from 0 to 9. The register can then be
+loaded with @code{ldp}.
 @end table
 
 @subsection Examples
@@ -10642,6 +10650,14 @@ Generate timestamps by counting samples:
 asetpts=N/SR/TB
 @end example
 
+ at item
+Remove timestamp gaps greater than 60 seconds, and avoid non
+monotically increasing timestamps setting an arbitrary constant frame
+duration of 0.05 seconds:
+ at example
+setpts='st(0,(T-PREV_INT));if(gt(ld(0),60),stp(0,PTS-PREV_INPTS));st(1,PTS-ldp(0));if(lte(ld(1),PREV_OUTPTS),PREV_OUTPTS+0.05/TB,ld(1))'
+ at end example
+
 @end itemize
 
 @section settb, asettb
diff --git a/libavfilter/setpts.c b/libavfilter/setpts.c
index 92b07fb..873d987 100644
--- a/libavfilter/setpts.c
+++ b/libavfilter/setpts.c
@@ -84,21 +84,48 @@ enum var_name {
     VAR_VARS_NB
 };
 
+#define PERSISTENT_VARS_NB 10
 typedef struct SetPTSContext {
     const AVClass *class;
     char *expr_str;
     AVExpr *expr;
     double var_values[VAR_VARS_NB];
     enum AVMediaType type;
+    double persistent_vars[PERSISTENT_VARS_NB];
 } SetPTSContext;
 
+static double ldp(void *opaque, double var_idx)
+{
+    SetPTSContext *s = opaque;
+    int var_idxi = var_idx;
+    if ((unsigned)var_idxi >= PERSISTENT_VARS_NB)
+        return NAN;
+    return s->persistent_vars[var_idxi];
+}
+
+static double stp(void *opaque, double var_idx, double val)
+{
+    SetPTSContext *s = opaque;
+    int var_idxi = var_idx;
+    if ((unsigned)var_idxi >= PERSISTENT_VARS_NB)
+        return NAN;
+    s->persistent_vars[var_idxi] = val;
+    return val;
+}
+
+static double (* const funcs1[])(void *, double)         = { (void *)ldp, NULL };
+static double (* const funcs2[])(void *, double, double) = { (void *)stp, NULL };
+
+static const char * const funcs1_names[] = { "ldp", NULL };
+static const char * const funcs2_names[] = { "stp", NULL };
+
 static av_cold int init(AVFilterContext *ctx)
 {
     SetPTSContext *setpts = ctx->priv;
     int ret;
 
-    if ((ret = av_expr_parse(&setpts->expr, setpts->expr_str,
-                             var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) {
+    if ((ret = av_expr_parse(&setpts->expr, setpts->expr_str, var_names,
+                             funcs1_names, funcs1, funcs2_names, funcs2, 0, ctx)) < 0) {
         av_log(ctx, AV_LOG_ERROR, "Error while parsing expression '%s'\n", setpts->expr_str);
         return ret;
     }
@@ -174,7 +201,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
         setpts->var_values[VAR_NB_SAMPLES] = frame->nb_samples;
     }
 
-    d = av_expr_eval(setpts->expr, setpts->var_values, NULL);
+    d = av_expr_eval(setpts->expr, setpts->var_values, setpts);
     frame->pts = D2TS(d);
 
     av_dlog(inlink->dst,
-- 
1.8.3.2



More information about the ffmpeg-devel mailing list