PR #22605 opened by Zhao Zhili (quink) URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22605 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22605.patch
libvidstab's vsTransformPrepare() takes different internal code paths for in-place (src == dest) vs. separate-buffer operation. Its persistent state (srcMalloced, destbuf) becomes inconsistent when the two modes are mixed across frames, producing incorrect stabilization output. Whether a given frame is writable depends on pipeline scheduling and frame reference management, which can change between FFmpeg versions. Since FFmpeg 8.1, changes in the scheduler caused some frames to arrive as non-writable, leading to alternation between in-place and separate-buffer paths that triggered the inconsistency. Fix this by always calling av_frame_make_writable() to ensure frames are writable, so we consistently take the in-place path. Fix #22595 Signed-off-by: Zhao Zhili <[email protected]> >From 6b63a5daa0deae99b419df1f7bdb870d3273b1eb Mon Sep 17 00:00:00 2001 From: Zhao Zhili <[email protected]> Date: Wed, 25 Mar 2026 00:35:19 +0800 Subject: [PATCH] avfilter/vidstabtransform: always use in-place transform path libvidstab's vsTransformPrepare() takes different internal code paths for in-place (src == dest) vs. separate-buffer operation. Its persistent state (srcMalloced, destbuf) becomes inconsistent when the two modes are mixed across frames, producing incorrect stabilization output. Whether a given frame is writable depends on pipeline scheduling and frame reference management, which can change between FFmpeg versions. Since FFmpeg 8.1, changes in the scheduler caused some frames to arrive as non-writable, leading to alternation between in-place and separate-buffer paths that triggered the inconsistency. Fix this by always calling av_frame_make_writable() to ensure frames are writable, so we consistently take the in-place path. Fix #22595 Signed-off-by: Zhao Zhili <[email protected]> --- libavfilter/vf_vidstabtransform.c | 39 ++++++++++++------------------- 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/libavfilter/vf_vidstabtransform.c b/libavfilter/vf_vidstabtransform.c index 55a5c9960d..abf652aa05 100644 --- a/libavfilter/vf_vidstabtransform.c +++ b/libavfilter/vf_vidstabtransform.c @@ -232,45 +232,36 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) VSTransformData* td = &(tc->td); AVFilterLink *outlink = inlink->dst->outputs[0]; - int direct = 0; AVFrame *out; VSFrame inframe; int plane; + int ret; - if (av_frame_is_writable(in)) { - direct = 1; - out = in; - } else { - out = ff_get_video_buffer(outlink, outlink->w, outlink->h); - if (!out) { - av_frame_free(&in); - return AVERROR(ENOMEM); - } - av_frame_copy_props(out, in); + /* libvidstab's vsTransformPrepare() takes different internal code paths + * for in-place (src == dest) vs. separate-buffer operation, and its + * persistent state (srcMalloced, destbuf) becomes inconsistent when the + * two modes are mixed across frames. Whether a frame is writable depends + * on pipeline scheduling, so alternation between the paths is not + * deterministic. Always ensure the frame is writable so we consistently + * take the in-place path, avoiding the inconsistency. + */ + ret = av_frame_make_writable(in); + if (ret < 0) { + av_frame_free(&in); + return ret; } + out = in; for (plane = 0; plane < vsTransformGetSrcFrameInfo(td)->planes; plane++) { inframe.data[plane] = in->data[plane]; inframe.linesize[plane] = in->linesize[plane]; } - if (direct) { - vsTransformPrepare(td, &inframe, &inframe); - } else { // separate frames - VSFrame outframe; - for (plane = 0; plane < vsTransformGetDestFrameInfo(td)->planes; plane++) { - outframe.data[plane] = out->data[plane]; - outframe.linesize[plane] = out->linesize[plane]; - } - vsTransformPrepare(td, &inframe, &outframe); - } + vsTransformPrepare(td, &inframe, &inframe); vsDoTransform(td, vsGetNextTransform(td, &tc->trans)); vsTransformFinish(td); - if (!direct) - av_frame_free(&in); - return ff_filter_frame(outlink, out); } -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
