From: Oleg Afanasyev <oafanasiev@gmail.com> To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org> Subject: [FFmpeg-devel] [PATCH v2] avfilter/setpts: add command support Date: Wed, 10 May 2023 22:58:59 +0100 Message-ID: <CABtgRJux+=nB2oc3Fpa0O93T=RehutA_dGSZXy7wOq7ZG1daiw@mail.gmail.com> (raw) [-- Attachment #1: Type: text/plain, Size: 183 bytes --] Addressed issue with old expr being released regardless of new command succeeding which caused crash on invalid commands. -- ---------------------- with best regards Oleg Afanasyev [-- Attachment #2: 0001-avfilter-setpts-add-command-support.patch --] [-- Type: text/x-patch, Size: 6278 bytes --] From a50bf9e58a0f90d63aba3c84de40f31dc22ebfce Mon Sep 17 00:00:00 2001 From: Oleg <oafanasiev@gmail.com> Date: Sat, 29 Apr 2023 19:56:46 +0100 Subject: [PATCH] avfilter/setpts: add command support Add support for changing expr on the fly. Signed-off-by: Oleg <oafanasiev@gmail.com> --- doc/filters.texi | 7 +++++ libavfilter/setpts.c | 73 +++++++++++++++++++++++++++++++++----------- 2 files changed, 63 insertions(+), 17 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 50e1682144..fbdb1f8ecf 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -29384,6 +29384,9 @@ The wallclock (RTC) time at the start of the movie in microseconds. @item TB 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. + @end table @subsection Examples @@ -29439,6 +29442,10 @@ asetpts=N/SR/TB @end itemize +@subsection Commands + +Both filters support all above options as @ref{commands}. + @section setrange Force color range for the output video frame. diff --git a/libavfilter/setpts.c b/libavfilter/setpts.c index 5bcc0c2dcf..c805a60ee4 100644 --- a/libavfilter/setpts.c +++ b/libavfilter/setpts.c @@ -63,6 +63,7 @@ static const char *const var_names[] = { "S", // Number of samples in the current frame "SR", // Audio sample rate "FR", ///< defined only for constant frame-rate video + "T_CHANGE", ///< time of first frame after latest command was applied NULL }; @@ -90,7 +91,8 @@ enum var_name { VAR_S, VAR_SR, VAR_FR, - VAR_VARS_NB + VAR_T_CHANGE, + VAR_VARS_NB, }; typedef struct SetPTSContext { @@ -120,6 +122,7 @@ static av_cold int init(AVFilterContext *ctx) setpts->var_values[VAR_PREV_OUTT] = NAN; setpts->var_values[VAR_STARTPTS] = NAN; setpts->var_values[VAR_STARTT] = NAN; + setpts->var_values[VAR_T_CHANGE] = NAN; return 0; } @@ -163,6 +166,9 @@ static double eval_pts(SetPTSContext *setpts, AVFilterLink *inlink, AVFrame *fra setpts->var_values[VAR_STARTPTS] = TS2D(pts); setpts->var_values[VAR_STARTT ] = TS2T(pts, inlink->time_base); } + if (isnan(setpts->var_values[VAR_T_CHANGE])) { + setpts->var_values[VAR_T_CHANGE] = TS2T(pts, inlink->time_base); + } setpts->var_values[VAR_PTS ] = TS2D(pts); setpts->var_values[VAR_T ] = TS2T(pts, inlink->time_base); #if FF_API_FRAME_PKT @@ -269,14 +275,45 @@ static av_cold void uninit(AVFilterContext *ctx) setpts->expr = NULL; } +static int process_command(AVFilterContext *ctx, const char *cmd, const char *arg, + char *res, int res_len, int flags) +{ + SetPTSContext *setpts = ctx->priv; + AVExpr *new_expr; + int ret; + + ret = ff_filter_process_command(ctx, cmd, arg, res, res_len, flags); + + if (ret < 0) + return ret; + + if (!strcmp(cmd, "expr")) { + ret = av_expr_parse(&new_expr, arg, var_names, NULL, NULL, NULL, NULL, 0, ctx); + // Only free and replace previous expression if new one succeeds, + // otherwise defensively keep everything intact even if reporting an error. + if (ret < 0) { + av_log(ctx, AV_LOG_ERROR, "Error while parsing expression '%s'\n", arg); + } else { + av_expr_free(setpts->expr); + setpts->expr = new_expr; + setpts->var_values[VAR_T_CHANGE] = NAN; + } + } else { + ret = AVERROR(EINVAL); + } + + return ret; +} + #define OFFSET(x) offsetof(SetPTSContext, x) #define V AV_OPT_FLAG_VIDEO_PARAM #define A AV_OPT_FLAG_AUDIO_PARAM +#define R AV_OPT_FLAG_RUNTIME_PARAM #define F AV_OPT_FLAG_FILTERING_PARAM #if CONFIG_SETPTS_FILTER static const AVOption setpts_options[] = { - { "expr", "Expression determining the frame timestamp", OFFSET(expr_str), AV_OPT_TYPE_STRING, { .str = "PTS" }, .flags = V|F }, + { "expr", "Expression determining the frame timestamp", OFFSET(expr_str), AV_OPT_TYPE_STRING, { .str = "PTS" }, .flags = V|F|R }, { NULL } }; AVFILTER_DEFINE_CLASS(setpts); @@ -297,12 +334,13 @@ static const AVFilterPad avfilter_vf_setpts_outputs[] = { }; const AVFilter ff_vf_setpts = { - .name = "setpts", - .description = NULL_IF_CONFIG_SMALL("Set PTS for the output video frame."), - .init = init, - .activate = activate, - .uninit = uninit, - .flags = AVFILTER_FLAG_METADATA_ONLY, + .name = "setpts", + .description = NULL_IF_CONFIG_SMALL("Set PTS for the output video frame."), + .init = init, + .activate = activate, + .uninit = uninit, + .process_command = process_command, + .flags = AVFILTER_FLAG_METADATA_ONLY, .priv_size = sizeof(SetPTSContext), .priv_class = &setpts_class, @@ -315,7 +353,7 @@ const AVFilter ff_vf_setpts = { #if CONFIG_ASETPTS_FILTER static const AVOption asetpts_options[] = { - { "expr", "Expression determining the frame timestamp", OFFSET(expr_str), AV_OPT_TYPE_STRING, { .str = "PTS" }, .flags = A|F }, + { "expr", "Expression determining the frame timestamp", OFFSET(expr_str), AV_OPT_TYPE_STRING, { .str = "PTS" }, .flags = A|F|R }, { NULL } }; AVFILTER_DEFINE_CLASS(asetpts); @@ -336,14 +374,15 @@ static const AVFilterPad asetpts_outputs[] = { }; const AVFilter ff_af_asetpts = { - .name = "asetpts", - .description = NULL_IF_CONFIG_SMALL("Set PTS for the output audio frame."), - .init = init, - .activate = activate, - .uninit = uninit, - .priv_size = sizeof(SetPTSContext), - .priv_class = &asetpts_class, - .flags = AVFILTER_FLAG_METADATA_ONLY, + .name = "asetpts", + .description = NULL_IF_CONFIG_SMALL("Set PTS for the output audio frame."), + .init = init, + .activate = activate, + .uninit = uninit, + .process_command = process_command, + .priv_size = sizeof(SetPTSContext), + .priv_class = &asetpts_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(asetpts_inputs), FILTER_OUTPUTS(asetpts_outputs), }; -- 2.40.0 [-- Attachment #3: Type: text/plain, Size: 251 bytes --] _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
reply other threads:[~2023-05-10 21:58 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to='CABtgRJux+=nB2oc3Fpa0O93T=RehutA_dGSZXy7wOq7ZG1daiw@mail.gmail.com' \ --to=oafanasiev@gmail.com \ --cc=ffmpeg-devel@ffmpeg.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel This inbox may be cloned and mirrored by anyone: git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \ ffmpegdev@gitmailbox.com public-inbox-index ffmpegdev Example config snippet for mirrors. AGPL code for this site: git clone https://public-inbox.org/public-inbox.git