PR #25399 opened by michaelni
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25399
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25399.patch


>From dcf2669ded7358389e3c522e60e86e4c224ea157 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Fri, 23 Oct 2026 17:39:52 +0200
Subject: [PATCH 1/4] avcodec/golomb: read Golomb-Rice codes of up to 32 bits
 in get_ur_golomb()

Add a FATE test that codes such a residual at every bit offset.
---
 libavcodec/golomb.h                      |  4 ++--
 tests/Makefile                           |  1 +
 tests/fate/ffv1.mak                      |  9 +++++++++
 tests/ref/fate/ffv1-golomb-float32-26bit | 15 +++++++++++++++
 4 files changed, 27 insertions(+), 2 deletions(-)
 create mode 100644 tests/fate/ffv1.mak
 create mode 100644 tests/ref/fate/ffv1-golomb-float32-26bit

diff --git a/libavcodec/golomb.h b/libavcodec/golomb.h
index 5169a5a4c09..48b9895ece9 100644
--- a/libavcodec/golomb.h
+++ b/libavcodec/golomb.h
@@ -396,7 +396,7 @@ static inline int get_ur_golomb(GetBitContext *gb, int k, 
int limit,
     }
 #else
     OPEN_READER(re, gb);
-    UPDATE_CACHE(re, gb);
+    UPDATE_CACHE_32(re, gb);
     buf = GET_CACHE(re, gb);
 
     log = av_log2(buf);
@@ -411,7 +411,7 @@ static inline int get_ur_golomb(GetBitContext *gb, int k, 
int limit,
         return buf;
     } else {
         LAST_SKIP_BITS(re, gb, limit);
-        UPDATE_CACHE(re, gb);
+        UPDATE_CACHE_32(re, gb);
 
         buf = SHOW_UBITS(re, gb, esc_len);
 
diff --git a/tests/Makefile b/tests/Makefile
index de71678e5c3..4cdd00dea44 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -197,6 +197,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..5175c8df961
--- /dev/null
+++ b/tests/fate/ffv1.mak
@@ -0,0 +1,9 @@
+FATE_FFV1_FLOAT32-$(call TRANSCODE, FFV1, NUT, LAVFI_INDEV 
WRAPPED_AVFRAME_DECODER COLOR_FILTER FORMAT_FILTER GEQ_FILTER SCALE_FILTER) += \
+    fate-ffv1-golomb-float32-26bit
+
+fate-ffv1-golomb-float32-26bit: CMD = transcode lavfi 
"color=black:s=352x288:r=1:d=8,format=gbrpf32,geq=r=X+Y*W:g=X+Y*W:b=X+W*if(lt(Y\,2*(25+N+floor(N/2)+2*floor(N/7))-4)\,if(mod(Y\,2)\,290-(25+N+floor(N/2)+2*floor(N/7))+(Y-1)/2\,290-2*(25+N+floor(N/2)+2*floor(N/7))+Y/2)\,if(eq(Y\,2*(25+N+floor(N/2)+2*floor(N/7))-4)\,19\,if(lt(Y\,2*(25+N+floor(N/2)+2*floor(N/7))+16)\,Y-2*(25+N+floor(N/2)+2*floor(N/7))+3\,if(lt(Y\,286)\,Y-2*(25+N+floor(N/2)+2*floor(N/7))+4\,Y-(25+N+floor(N/2)+2*floor(N/7))+2))))"
 nut \
+    "-c:v ffv1 -strict experimental -coder 0 -remap_mode 1 -slices 1 -g 1" 
"-pix_fmt gbrpf32le -vf scale"
+
+FATE_FFMPEG += $(FATE_FFV1_FLOAT32-yes)
+fate-ffv1: $(FATE_FFV1_FLOAT32-yes)
+
diff --git a/tests/ref/fate/ffv1-golomb-float32-26bit 
b/tests/ref/fate/ffv1-golomb-float32-26bit
new file mode 100644
index 00000000000..3fe457cdcb5
--- /dev/null
+++ b/tests/ref/fate/ffv1-golomb-float32-26bit
@@ -0,0 +1,15 @@
+451a0326abe6e7a074184d3410eef4ce *tests/data/fate/ffv1-golomb-float32-26bit.nut
+163524 tests/data/fate/ffv1-golomb-float32-26bit.nut
+#tb 0: 1/1
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
+0,          0,          0,        1,  1216512, 0x65029b72
+0,          1,          1,        1,  1216512, 0xc7369b72
+0,          2,          2,        1,  1216512, 0x08bc9b72
+0,          3,          3,        1,  1216512, 0x05e29b72
+0,          4,          4,        1,  1216512, 0x027a9b72
+0,          5,          5,        1,  1216512, 0x4f1a9b72
+0,          6,          6,        1,  1216512, 0xe6829b72
+0,          7,          7,        1,  1216512, 0xc9809b72
-- 
2.54.0


>From 78ad6477d2de10d0c105458212b19d064a2a86f0 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Fri, 23 Oct 2026 17:39:52 +0200
Subject: [PATCH 2/4] avcodec/ffv1dec: clamp k in get_vlc_symbol() at 20
 instead of bits

Add a FATE test with such planes.
---
 libavcodec/ffv1dec.c                    | 6 ++++--
 tests/fate/ffv1.mak                     | 7 ++++++-
 tests/ref/fate/ffv1-golomb-float32-1bit | 8 ++++++++
 3 files changed, 18 insertions(+), 3 deletions(-)
 create mode 100644 tests/ref/fate/ffv1-golomb-float32-1bit

diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index 8de15d24760..c15ae288f6d 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -56,10 +56,12 @@ static inline int get_vlc_symbol(GetBitContext *gb, 
VlcState *const state,
         k++;
         i += i;
     }
-    if (k > bits) {
+    /* get_ur_golomb() reads at most 32 bits, 12 of which the escape limit
+     * reserves for the prefix */
+    if (k > 20) {
         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 = 20;
     }
 
     v = get_sr_golomb(gb, k, 12, bits);
diff --git a/tests/fate/ffv1.mak b/tests/fate/ffv1.mak
index 5175c8df961..71e0639e0d1 100644
--- a/tests/fate/ffv1.mak
+++ b/tests/fate/ffv1.mak
@@ -1,9 +1,14 @@
 FATE_FFV1_FLOAT32-$(call TRANSCODE, FFV1, NUT, LAVFI_INDEV 
WRAPPED_AVFRAME_DECODER COLOR_FILTER FORMAT_FILTER GEQ_FILTER SCALE_FILTER) += \
-    fate-ffv1-golomb-float32-26bit
+    fate-ffv1-golomb-float32-26bit fate-ffv1-golomb-float32-1bit
 
 fate-ffv1-golomb-float32-26bit: CMD = transcode lavfi 
"color=black:s=352x288:r=1:d=8,format=gbrpf32,geq=r=X+Y*W:g=X+Y*W:b=X+W*if(lt(Y\,2*(25+N+floor(N/2)+2*floor(N/7))-4)\,if(mod(Y\,2)\,290-(25+N+floor(N/2)+2*floor(N/7))+(Y-1)/2\,290-2*(25+N+floor(N/2)+2*floor(N/7))+Y/2)\,if(eq(Y\,2*(25+N+floor(N/2)+2*floor(N/7))-4)\,19\,if(lt(Y\,2*(25+N+floor(N/2)+2*floor(N/7))+16)\,Y-2*(25+N+floor(N/2)+2*floor(N/7))+3\,if(lt(Y\,286)\,Y-2*(25+N+floor(N/2)+2*floor(N/7))+4\,Y-(25+N+floor(N/2)+2*floor(N/7))+2))))"
 nut \
     "-c:v ffv1 -strict experimental -coder 0 -remap_mode 1 -slices 1 -g 1" 
"-pix_fmt gbrpf32le -vf scale"
 
+# Planes with 2 distinct values are coded with 1 bit residuals while the
+# Golomb-Rice parameter k starts at 2.
+fate-ffv1-golomb-float32-1bit: CMD = transcode lavfi 
"color=black:s=64x48:r=1:d=1,format=gbrpf32,geq=r=mod(floor(X*Y/7)\,2):g=mod(floor(X*Y/7)\,2):b=mod(floor(X*Y/7)\,2)"
 nut \
+    "-c:v ffv1 -strict experimental -coder 0 -remap_mode 1" "-pix_fmt 
gbrpf32le -vf scale"
+
 FATE_FFMPEG += $(FATE_FFV1_FLOAT32-yes)
 fate-ffv1: $(FATE_FFV1_FLOAT32-yes)
 
diff --git a/tests/ref/fate/ffv1-golomb-float32-1bit 
b/tests/ref/fate/ffv1-golomb-float32-1bit
new file mode 100644
index 00000000000..ddd70d29d4d
--- /dev/null
+++ b/tests/ref/fate/ffv1-golomb-float32-1bit
@@ -0,0 +1,8 @@
+89dee9204df7ed527995102564b73abc *tests/data/fate/ffv1-golomb-float32-1bit.nut
+1402 tests/data/fate/ffv1-golomb-float32-1bit.nut
+#tb 0: 1/1
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x48
+#sar 0: 1/1
+0,          0,          0,        1,    36864, 0x538a6520
-- 
2.54.0


>From 4ef1f3e83379dfc278f024f7b41e136be265dae4 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Fri, 23 Oct 2026 17:39:52 +0200
Subject: [PATCH 3/4] avcodec/ffv1enc: reject 32bit float Golomb-Rice slices
 above 2^18 pixels

The escape code of a Golomb-Rice residual is 12 + bits long and
put_bits() writes at most 31 bits, so bits must stay below 20. The RCT
planes of remapped 32bit floats need log2 of the summed remap counts of
two planes, which a slice of at most 1<<18 pixels keeps within 19 bits.
The default slice size of 360x288 is within that, larger slices requested
with -slices were written with escape codes longer than put_bits()
supports. The assertion on k follows the same limit.
---
 libavcodec/ffv1enc.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c
index 1d18f10f05f..869834c2e8f 100644
--- a/libavcodec/ffv1enc.c
+++ b/libavcodec/ffv1enc.c
@@ -250,7 +250,7 @@ static inline void put_vlc_symbol(PutBitContext *pb, 
VlcState *const state,
         i += i;
     }
 
-    av_assert2(k <= 16);
+    av_assert2(k <= 19);
 
     code = v ^ ((2 * state->drift + state->count) >> 31);
 
@@ -1053,6 +1053,18 @@ static av_cold int encode_init_internal(AVCodecContext 
*avctx)
         if ((ret = ff_ffv1_encode_determine_slices(avctx)) < 0)
             return ret;
 
+        /* The Golomb-Rice escape code is 12 + bits long and put_bits()
+         * writes at most 31 bits, so bits must stay below 20. The RCT
+         * planes of remapped 32bit floats need log2 of the summed remap
+         * counts of two planes, which a slice of at most 1<<18 pixels
+         * keeps within 19 bits. */
+        if (s->ac == AC_GOLOMB_RICE && s->bits_per_raw_sample == 32 &&
+            ((avctx->width  + s->num_h_slices - 1) / s->num_h_slices) *
+            (int64_t)((avctx->height + s->num_v_slices - 1) / s->num_v_slices) 
> 1 << 18) {
+            av_log(avctx, AV_LOG_ERROR, "Slices larger than 262144 pixels are 
not supported with 32bit floats and the Golomb-Rice coder\n");
+            return AVERROR(EINVAL);
+        }
+
         if ((ret = ff_ffv1_write_extradata(avctx)) < 0)
             return ret;
     }
-- 
2.54.0


>From 4964a46cfb3707ea57c011ead764bdd831a6be27 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Fri, 23 Oct 2026 17:39:52 +0200
Subject: [PATCH 4/4] fate/ffv1: test the default slice layout of 32bit float
 frames

The size and checksum of the encoded file pin the slice layout and the
remap coding of a 704x576 float frame, which the 360x288 default slice
limit splits into 2x2 slices.
---
 tests/fate/ffv1.mak                | 7 ++++++-
 tests/ref/fate/ffv1-float32-slices | 8 ++++++++
 2 files changed, 14 insertions(+), 1 deletion(-)
 create mode 100644 tests/ref/fate/ffv1-float32-slices

diff --git a/tests/fate/ffv1.mak b/tests/fate/ffv1.mak
index 71e0639e0d1..d26bb657433 100644
--- a/tests/fate/ffv1.mak
+++ b/tests/fate/ffv1.mak
@@ -1,5 +1,7 @@
 FATE_FFV1_FLOAT32-$(call TRANSCODE, FFV1, NUT, LAVFI_INDEV 
WRAPPED_AVFRAME_DECODER COLOR_FILTER FORMAT_FILTER GEQ_FILTER SCALE_FILTER) += \
     fate-ffv1-golomb-float32-26bit fate-ffv1-golomb-float32-1bit
+FATE_FFV1_FLOAT32-$(call TRANSCODE, FFV1, NUT, LAVFI_INDEV 
WRAPPED_AVFRAME_DECODER TESTSRC_FILTER FORMAT_FILTER SCALE_FILTER) += \
+    fate-ffv1-float32-slices
 
 fate-ffv1-golomb-float32-26bit: CMD = transcode lavfi 
"color=black:s=352x288:r=1:d=8,format=gbrpf32,geq=r=X+Y*W:g=X+Y*W:b=X+W*if(lt(Y\,2*(25+N+floor(N/2)+2*floor(N/7))-4)\,if(mod(Y\,2)\,290-(25+N+floor(N/2)+2*floor(N/7))+(Y-1)/2\,290-2*(25+N+floor(N/2)+2*floor(N/7))+Y/2)\,if(eq(Y\,2*(25+N+floor(N/2)+2*floor(N/7))-4)\,19\,if(lt(Y\,2*(25+N+floor(N/2)+2*floor(N/7))+16)\,Y-2*(25+N+floor(N/2)+2*floor(N/7))+3\,if(lt(Y\,286)\,Y-2*(25+N+floor(N/2)+2*floor(N/7))+4\,Y-(25+N+floor(N/2)+2*floor(N/7))+2))))"
 nut \
     "-c:v ffv1 -strict experimental -coder 0 -remap_mode 1 -slices 1 -g 1" 
"-pix_fmt gbrpf32le -vf scale"
@@ -9,6 +11,9 @@ fate-ffv1-golomb-float32-26bit: CMD = transcode lavfi 
"color=black:s=352x288:r=1
 fate-ffv1-golomb-float32-1bit: CMD = transcode lavfi 
"color=black:s=64x48:r=1:d=1,format=gbrpf32,geq=r=mod(floor(X*Y/7)\,2):g=mod(floor(X*Y/7)\,2):b=mod(floor(X*Y/7)\,2)"
 nut \
     "-c:v ffv1 -strict experimental -coder 0 -remap_mode 1" "-pix_fmt 
gbrpf32le -vf scale"
 
+# Default slice layout of a 32bit float frame larger than 360x288
+fate-ffv1-float32-slices: CMD = transcode lavfi 
"testsrc=size=704x576:r=1:d=1,format=gbrpf32" nut \
+    "-c:v ffv1 -strict experimental" "-pix_fmt gbrpf32le -vf scale"
+
 FATE_FFMPEG += $(FATE_FFV1_FLOAT32-yes)
 fate-ffv1: $(FATE_FFV1_FLOAT32-yes)
-
diff --git a/tests/ref/fate/ffv1-float32-slices 
b/tests/ref/fate/ffv1-float32-slices
new file mode 100644
index 00000000000..084e88a7f7d
--- /dev/null
+++ b/tests/ref/fate/ffv1-float32-slices
@@ -0,0 +1,8 @@
+33045e83befdf2085c63bfaea7c60006 *tests/data/fate/ffv1-float32-slices.nut
+9585 tests/data/fate/ffv1-float32-slices.nut
+#tb 0: 1/1
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 704x576
+#sar 0: 1/1
+0,          0,          0,        1,  4866048, 0x1b0e9bf0
-- 
2.54.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to