Stefano Sabatini: > This is useful to simulate random jitter. > --- > Changelog | 1 + > doc/filters.texi | 10 +++++++++- > libavfilter/setpts.c | 39 +++++++++++++++++++++++++++++++++------ > 3 files changed, 43 insertions(+), 7 deletions(-) > > diff --git a/Changelog b/Changelog > index 424bfc11af..ed01c53264 100644 > --- a/Changelog > +++ b/Changelog > @@ -15,6 +15,7 @@ version <next>: > - tiltandshift filter > - qrencode filter and qrencodesrc source > - quirc filter > +- lavfi/setpts: introduce rand() function in expression > > version 6.1: > - libaribcaption decoder > diff --git a/doc/filters.texi b/doc/filters.texi > index d1f95b9781..1d9a5d6c7d 100644 > --- a/doc/filters.texi > +++ b/doc/filters.texi > @@ -30946,7 +30946,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, FR > @@ -31010,6 +31010,8 @@ The timebase of the input timestamps. > @item T_CHANGE > Time of the first frame after command was applied or time of the first frame > if no commands. > > +@item rand(min, max) > +a random number included between min and max > @end table > > @subsection Examples > @@ -31021,6 +31023,12 @@ Start counting PTS from zero > setpts=PTS-STARTPTS > @end example > > +@item > +Apply a random jitter effect of +/-100 TB units: > +@example > +setpts=PTS+100rand(-100\,100) > +@end example > + > @item > Apply fast motion effect: > @example > diff --git a/libavfilter/setpts.c b/libavfilter/setpts.c > index 88a8d6af86..0f24a900b3 100644 > --- a/libavfilter/setpts.c > +++ b/libavfilter/setpts.c > @@ -32,6 +32,8 @@ > #include "libavutil/internal.h" > #include "libavutil/mathematics.h" > #include "libavutil/opt.h" > +#include "libavutil/lfg.h" > +#include "libavutil/random_seed.h" > #include "libavutil/time.h" > #include "audio.h" > #include "avfilter.h" > @@ -101,18 +103,39 @@ typedef struct SetPTSContext { > AVExpr *expr; > double var_values[VAR_VARS_NB]; > enum AVMediaType type; > + AVLFG lfg; > } SetPTSContext; > > #define V(name_) \ > setpts->var_values[VAR_##name_] > > +static double drand(void *ctx, double min, double max) > +{ > + SetPTSContext *setpts = ((AVFilterContext *)ctx)->priv; > + > + return min + (max-min) / UINT_MAX * av_lfg_get(&setpts->lfg); > +} > + > +typedef double (*eval_func2)(void *, double a, double b); > + > +static const eval_func2 fun2[] = { > + drand, > + NULL > +}; > + > +static const char *const fun2_names[] = { > + "rand" > +}; > + > static av_cold int init(AVFilterContext *ctx) > { > SetPTSContext *setpts = ctx->priv; > int ret; > > + av_lfg_init(&setpts->lfg, av_get_random_seed()); > + > if ((ret = av_expr_parse(&setpts->expr, setpts->expr_str, > - var_names, NULL, NULL, NULL, NULL, 0, ctx)) < > 0) { > + var_names, NULL, NULL, fun2_names, fun2, 0, > ctx)) < 0) { > av_log(ctx, AV_LOG_ERROR, "Error while parsing expression '%s'\n", > setpts->expr_str); > return ret; > } > @@ -126,6 +149,7 @@ static av_cold int init(AVFilterContext *ctx) > V(STARTPTS) = NAN; > V(STARTT) = NAN; > V(T_CHANGE) = NAN; > + > return 0; > } > > @@ -159,8 +183,10 @@ static inline char *double2int64str(char *buf, double v) > return buf; > } > > -static double eval_pts(SetPTSContext *setpts, AVFilterLink *inlink, AVFrame > *frame, int64_t pts) > +static double eval_pts(AVFilterContext *ctx, AVFilterLink *inlink, AVFrame > *frame, int64_t pts) > { > + SetPTSContext *setpts = ctx->priv; > + > if (isnan(V(STARTPTS))) { > V(STARTPTS) = TS2D(pts); > V(STARTT ) = TS2T(pts, inlink->time_base); > @@ -186,17 +212,18 @@ FF_ENABLE_DEPRECATION_WARNINGS > } > } > > - return av_expr_eval(setpts->expr, setpts->var_values, NULL); > + return av_expr_eval(setpts->expr, setpts->var_values, ctx); > } > #define d2istr(v) double2int64str((char[BUF_SIZE]){0}, v) > > static int filter_frame(AVFilterLink *inlink, AVFrame *frame) > { > - SetPTSContext *setpts = inlink->dst->priv; > + AVFilterContext *ctx = inlink->dst; > + SetPTSContext *setpts = ctx->priv; > int64_t in_pts = frame->pts; > double d; > > - d = eval_pts(setpts, inlink, frame, frame->pts); > + d = eval_pts(ctx, inlink, frame, frame->pts); > frame->pts = D2TS(d); > > av_log(inlink->dst, AV_LOG_TRACE, > @@ -250,7 +277,7 @@ static int activate(AVFilterContext *ctx) > return filter_frame(inlink, in); > > if (ff_inlink_acknowledge_status(inlink, &status, &pts)) { > - double d = eval_pts(setpts, inlink, NULL, pts); > + double d = eval_pts(ctx, inlink, NULL, pts); > > av_log(ctx, AV_LOG_TRACE, "N:EOF PTS:%s T:%f -> PTS:%s T:%f\n", > d2istr(V(PTS)), V(T), d2istr(d), TS2T(d, inlink->time_base));
Why is this added here and not in lavu/eval so that it is available with all expressions? - Andreas _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".