PR #25266 opened by Forgejo_Fairy URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25266 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25266.patch
FFV1 v4 remapping can reduce a plane's symbol width to one bit while the initial VLC state selects Rice parameter k = 2. The decoder clamps k to the symbol width, disagreeing with the encoder and silently corrupting the decoded pixels. Apply JUI YU LIN's proposed fix from #24026: cap k at 16, matching the encoder's invariant. This retains shift protection in get_ur_golomb(): with limit = 12, the normal branch has log >= 20, so log - k remains nonnegative. Existing affected streams can then decode correctly without re-encoding. The second commit adapts the author's generated FATE test to use exactly representable float values directly in all three planes, explicit Rice coding, little-endian raw output, and the required filter/decoder dependencies. Both commits preserve the original authorship. Verified on Linux arm64 with GCC 13.3.0, based on master 09f879b0742: - The issue's reproducer gives 19/48 differing samples before the fix and zero afterward. - Built 051e0d7744db and its parent c0f1c3e1857: the same stream fails at the former and decodes correctly at the latter, confirming the regression. - release/8.0, release/8.1, and release/9.0 also reproduce the decoder failure. - Twelve checks across four float formats and three entropy coders decode streams from unpatched master byte-exactly with the fix. - An additional 48 Rice cases across all four formats, three dimensions, and four input patterns pass byte-exactly after the fix, including negative values. - The new FATE test fails without the decoder change and passes with it; its decoded output also matches independently generated input bytes. - All 30 enabled existing FFV1 FATE tests and the new test pass. Full FATE was not run. Fixes #24026. >From d5b44a820dbb53943c952b22eeed94f8b3869dfa Mon Sep 17 00:00:00 2001 From: JUI YU LIN <[email protected]> Date: Thu, 6 Aug 2026 08:12:53 +0800 Subject: [PATCH 1/2] avcodec/ffv1dec: do not clamp the Golomb-Rice k to bits Remapped FFV1 v4 planes can have a one-bit symbol width while the initial VLC state (error_sum = 4, count = 1) selects k = 2. Clamping k to bits in the decoder disagrees with the encoder and corrupts the decoded pixels, including streams already written by released encoders. Bound k by 16, matching put_vlc_symbol(), instead. This retains the shift protection added in 051e0d7744db: with limit = 12, the normal get_ur_golomb() branch has log >= 20, so log - k remains nonnegative. The escape branch does not use k. Fixes: 051e0d7744dbb45f680bbfa72bfead947b11ef2f Fixes: https://code.ffmpeg.org/FFmpeg/FFmpeg/issues/24026 Signed-off-by: JUI YU LIN <[email protected]> Assisted-by: Fairy --- libavcodec/ffv1dec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c index 8de15d24760..f2c0f9fee8b 100644 --- a/libavcodec/ffv1dec.c +++ b/libavcodec/ffv1dec.c @@ -56,10 +56,10 @@ static inline int get_vlc_symbol(GetBitContext *gb, VlcState *const state, k++; i += i; } - if (k > bits) { + if (k > 16) { ff_dlog(NULL, "k-overflow bias:%d error:%d drift:%d count:%d k:%d", state->bias, state->error_sum, state->drift, state->count, k); - k = bits; + k = 16; } v = get_sr_golomb(gb, k, 12, bits); -- 2.54.0 >From 923ddcaa49c938e1a410330d73103521b1f400b6 Mon Sep 17 00:00:00 2001 From: JUI YU LIN <[email protected]> Date: Thu, 6 Aug 2026 08:12:53 +0800 Subject: [PATCH 2/2] tests/fate/ffv1: cover the float Golomb-Rice path Generate a 16x16 checkerboard of two exactly representable float values in every plane. The two-entry remap tables exercise the decoder's Rice parameter when the remapped symbol width is smaller than k. Generate the values directly in the float domain and explicitly select little-endian raw output for a portable reference. Include the scale and wrapped_avframe dependencies required by the lavfi input, and select Rice explicitly so future default changes do not weaken the test. The test fails without the preceding decoder fix and passes with it. Signed-off-by: JUI YU LIN <[email protected]> Assisted-by: Fairy --- tests/Makefile | 1 + tests/fate/ffv1.mak | 7 +++++++ tests/ref/fate/ffv1-float-golomb | 8 ++++++++ 3 files changed, 16 insertions(+) create mode 100644 tests/fate/ffv1.mak create mode 100644 tests/ref/fate/ffv1-float-golomb diff --git a/tests/Makefile b/tests/Makefile index bd83c8df91d..93a8bfc976b 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -189,6 +189,7 @@ include $(SRC_PATH)/tests/fate/astc.mak # Must be included after lavf-video.mak include $(SRC_PATH)/tests/fate/ffmpeg.mak include $(SRC_PATH)/tests/fate/ffprobe.mak +include $(SRC_PATH)/tests/fate/ffv1.mak include $(SRC_PATH)/tests/fate/fifo-muxer.mak include $(SRC_PATH)/tests/fate/filter-audio.mak # Must be included after vcodec.mak diff --git a/tests/fate/ffv1.mak b/tests/fate/ffv1.mak new file mode 100644 index 00000000000..4bda8bc971b --- /dev/null +++ b/tests/fate/ffv1.mak @@ -0,0 +1,7 @@ +# A slice plane holding only two distinct values gets a two entry remap table, +# hence a one bit wide coded symbol, which is where Golomb-Rice used to desync. +FATE_FFV1_FFMPEG-$(call TRANSCODE, FFV1, MATROSKA, WRAPPED_AVFRAME_DECODER COLOR_FILTER FORMAT_FILTER GEQ_FILTER SCALE_FILTER LAVFI_INDEV) += fate-ffv1-float-golomb +fate-ffv1-float-golomb: CMD = transcode lavfi "color=c=black:s=16x16:d=1:r=1,format=gbrpf32,geq=r=if(mod(X+Y\,2)\,1\,0.5):g=if(mod(X+Y\,2)\,1\,0.5):b=if(mod(X+Y\,2)\,1\,0.5)" matroska "-c:v ffv1 -level 4 -strict experimental -slices 1 -coder rice" "-c:v rawvideo -pix_fmt gbrpf32le" + +FATE_FFMPEG += $(FATE_FFV1_FFMPEG-yes) +fate-ffv1: $(FATE_FFV1_FFMPEG-yes) diff --git a/tests/ref/fate/ffv1-float-golomb b/tests/ref/fate/ffv1-float-golomb new file mode 100644 index 00000000000..d4997582867 --- /dev/null +++ b/tests/ref/fate/ffv1-float-golomb @@ -0,0 +1,8 @@ +1b61743c5fe7c9eaedfbd24ba85e8160 *tests/data/fate/ffv1-float-golomb.matroska +759 tests/data/fate/ffv1-float-golomb.matroska +#tb 0: 1/1 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 16x16 +#sar 0: 1/1 +0, 0, 0, 1, 3072, 0xc8e37d0f -- 2.54.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
