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]

Reply via email to