yes On Thu, Feb 19, 2026 at 12:06 AM Dana Feng via ffmpeg-devel < [email protected]> wrote:
> Ah got it, thank you! Do I just create a pull request? > > -----Original Message----- > From: hassan hany via ffmpeg-devel <[email protected]> > Sent: Wednesday, February 18, 2026 5:00 PM > To: FFmpeg development discussions and patches <[email protected]> > Cc: hassan hany <[email protected]> > Subject: [FFmpeg-devel] Re: [PATCH] lavfi/mpdecimate: fix three bugs in > keep_count logic > > Hi dana > you probably want to submit this to https://code.ffmpeg.org/ since thats > where FFmpeg development happens nowadays (yes I am aware the readme says > you should submit patches to the ML but its outdated) > > On Wed, Feb 18, 2026 at 11:55 PM Dana Feng via ffmpeg-devel < > [email protected]> wrote: > > > Hello! Just following up on this. > > > > From: Dana Feng > > Sent: Friday, February 6, 2026 4:38 PM > > To: '[email protected]' <[email protected]> > > Subject: [PATCH] lavfi/mpdecimate: fix three bugs in keep_count logic > > > > Fix the following issues with the keep option: > > > > 1. No similarity check during keep period: The code returned early > > during the keep period without checking if the frame was actually > > similar to the reference. > > > > 2. keep_count doesn't reset on different frames: The counter should > > track "consecutive similar frames," but when a different frame > > arrived mid-count, keep_count didn't reset to 0. It only reset > > after going negative (after a drop), causing the counter to > > accumulate across non-consecutive similar frames and drop frames > > earlier than expected. > > > > 3. Reference frame drift: When similar frames were kept due to > > keep_count, they became the new reference. Over time, tiny > > differences (sensor noise, compression artifacts) accumulated. > > Frame N got compared to frame N-1 instead of the last different > > frame, allowing gradual scene changes to slip through undetected. > > > > Now decimate_frame() checks similarity first, then applies keep_count > > logic, returning distinct values: > > 1 = drop (similar, over keep threshold) > > 0 = keep (different frame) - updates reference, resets keep_count > > -1 = keep (similar, under keep threshold) - preserves reference > > > > Signed-off-by: Dana Feng [email protected]<mailto:[email protected]> > > --- > > libavfilter/vf_mpdecimate.c | 49 +++++++++++++++++++++++++------------ > > 1 file changed, 34 insertions(+), 15 deletions(-) > > > > diff --git a/libavfilter/vf_mpdecimate.c b/libavfilter/vf_mpdecimate.c > > index 0fc95556b7..5b1654f671 100644 > > --- a/libavfilter/vf_mpdecimate.c > > +++ b/libavfilter/vf_mpdecimate.c > > @@ -109,19 +109,18 @@ static int diff_planes(AVFilterContext *ctx, > > /** > > * Tell if the frame should be decimated, for example if it is no much > > * different with respect to the reference frame ref. > > + * > > + * @return 1 if frame should be dropped (similar, over keep threshold), > > + * 0 if frame should be kept (different), > > + * -1 if frame should be kept (similar, under keep threshold) > > */ > > static int decimate_frame(AVFilterContext *ctx, > > AVFrame *cur, AVFrame *ref) { > > DecimateContext *decimate = ctx->priv; > > + int is_similar; > > int plane; > > > > - if (decimate->max_keep_count > 0 && > > - decimate->keep_count > -1 && > > - decimate->keep_count < decimate->max_keep_count) { > > - decimate->keep_count++; > > - return 0; > > - } > > if (decimate->max_drop_count > 0 && > > decimate->drop_count >= decimate->max_drop_count) > > return 0; > > @@ -129,6 +128,7 @@ static int decimate_frame(AVFilterContext *ctx, > > (decimate->drop_count-1) > decimate->max_drop_count) > > return 0; > > > > + is_similar = 1; > > for (plane = 0; ref->data[plane] && ref->linesize[plane]; plane++) { > > /* use 8x8 SAD even on subsampled planes. The blocks won't > > match up with > > * luma blocks, but hopefully nobody is depending on this to > > catch @@ -141,8 +141,21 @@ static int decimate_frame(AVFilterContext > *ctx, > > cur->data[plane], cur->linesize[plane], > > ref->data[plane], ref->linesize[plane], > > AV_CEIL_RSHIFT(ref->width, hsub), > > - AV_CEIL_RSHIFT(ref->height, vsub))) > > - return 0; > > + AV_CEIL_RSHIFT(ref->height, vsub))) { > > + is_similar = 0; > > + break; > > + } > > + } > > + > > + if (!is_similar) > > + return 0; /* Frame is different - keep it */ > > + > > + /* Frame is similar - apply keep_count logic */ > > + if (decimate->max_keep_count > 0 && > > + decimate->keep_count > -1 && > > + decimate->keep_count < decimate->max_keep_count) { > > + decimate->keep_count++; > > + return -1; /* Similar but under keep threshold - keep > > + without > > updating ref */ > > } > > > > return 1; > > @@ -200,29 +213,35 @@ static int filter_frame(AVFilterLink *inlink, > > AVFrame *cur) > > DecimateContext *decimate = inlink->dst->priv; > > AVFilterLink *outlink = inlink->dst->outputs[0]; > > int ret; > > + int result = decimate->ref ? decimate_frame(inlink->dst, cur, > > decimate->ref) : 0; > > > > - if (decimate->ref && decimate_frame(inlink->dst, cur, > decimate->ref)) > > { > > + if (result == 1) { > > + /* Drop: similar frame, over keep threshold */ > > decimate->drop_count = FFMAX(1, decimate->drop_count+1); > > - decimate->keep_count = -1; // do not keep any more frames until > > non-similar frames are detected > > + decimate->keep_count = -1; > > + } else if (result == -1) { > > + /* Keep: similar frame, under keep threshold - don't update ref > */ > > + decimate->drop_count = FFMIN(-1, decimate->drop_count-1); > > + if ((ret = ff_filter_frame(outlink, cur)) < 0) > > + return ret; > > } else { > > + /* Keep: different frame - update ref and reset keep_count */ > > av_frame_free(&decimate->ref); > > decimate->ref = cur; > > decimate->drop_count = FFMIN(-1, decimate->drop_count-1); > > - if (decimate->keep_count < 0) // re-enable counting similar > > frames to ignore before dropping > > - decimate->keep_count = 0; > > - > > + decimate->keep_count = 0; > > if ((ret = ff_filter_frame(outlink, av_frame_clone(cur))) < 0) > > return ret; > > } > > > > av_log(inlink->dst, AV_LOG_DEBUG, > > "%s pts:%s pts_time:%s drop_count:%d keep_count:%d\n", > > - decimate->drop_count > 0 ? "drop" : "keep", > > + result > 0 ? "drop" : "keep", > > av_ts2str(cur->pts), av_ts2timestr(cur->pts, > > &inlink->time_base), > > decimate->drop_count, > > decimate->keep_count); > > > > - if (decimate->drop_count > 0) > > + if (result > 0) > > av_frame_free(&cur); > > > > return 0; > > -- > > 2.39.5 > > _______________________________________________ > > ffmpeg-devel mailing list -- [email protected] To unsubscribe > > send an email to [email protected] > > > _______________________________________________ > ffmpeg-devel mailing list -- [email protected] To unsubscribe send > an email to [email protected] > _______________________________________________ > ffmpeg-devel mailing list -- [email protected] > To unsubscribe send an email to [email protected] > _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
