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. +@item ldp(idx) +Load the persistent variable loaded in register @var{idx}, which was +filled with the @code{stp} function. + +@item stp(idx, val) +Store the value @var{val} in the persistent register with index +@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 +@item +Remove timestamp gaps greater than 60 seconds, and avoid non +monotically increasing timestamps setting an arbitrary constant frame +duration of 0.05 seconds: +@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))' +@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 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel