PR #25477 opened by Kilian (lusoris)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25477
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25477.patch

This patch addresses GCC 14.4.0 and 16.2.1 -Wstack-usage diagnostics against 
-Wstack-usage=122880 in libavcodec/ffv1enc.c, with slice storage declared in 
libavcodec/ffv1.h.

Result: warnings in this file go from 1 to 0 with GCC 14.4.0 and with GCC 
16.2.1.

What the patch does:

- `avcodec/ffv1enc: move float remap scratch to slice state`: allocates 
multiplier and score tables once per slice for 32-bit remapping, adds an 
allocation failure path and frees the tables on close; score resets remain per 
optimizer iteration.

Behaviour change: per-slice heap allocations can fail; remap calculations are 
unchanged when allocation succeeds.

Base: FFmpeg master 46f23be8b1.

Testing:

- GCC 14.4.0 (`--enable-gpl --enable-vulkan`) and GCC 16.2.1 (`--enable-gpl 
--enable-vulkan --enable-vaapi --enable-libdrm --enable-nvenc`), targets all, 
alltools, examples, testprogs and checkasm: master 46f23be8b1 shows 1 
-Wstack-usage warning in libavcodec/ffv1enc.c with each compiler; with this 
patch there are none and no new ones.
- FATE with GCC 16.2.1: 31 tests whose name contains `ffv1` ran, and all 31 
pass on master and with this patch. The 11 `ffv1` `vsynth_lena` tests were left 
out of this run because my local FATE sample copy has no lena image.

Split out of #25111 so that each part reaches the reviewers for its area.



>From f442ad6c8438de6966b99cdfe81f4c99d2f5924a Mon Sep 17 00:00:00 2001
From: lusoris <[email protected]>
Date: Thu, 15 Oct 2026 22:06:35 +0200
Subject: [PATCH] avcodec/ffv1enc: move float remap scratch to slice state

GCC 14.4.0 and 16.2.1 report -Wstack-usage against FFmpeg's default
-Wstack-usage=122880 limit. The float remap multiplier and score tables
occupy large automatic arrays. Allocate them once per slice for 32-bit
remapping and free them on close. Keep the score table reset for each
optimizer iteration, leaving remap calculations unchanged when
allocation succeeds.

Signed-off-by: lusoris <[email protected]>
---
 libavcodec/ffv1.h    |  7 +++++++
 libavcodec/ffv1enc.c | 13 +++++++++++--
 2 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/libavcodec/ffv1.h b/libavcodec/ffv1.h
index 012b92ec212..614a00a1c38 100644
--- a/libavcodec/ffv1.h
+++ b/libavcodec/ffv1.h
@@ -68,6 +68,12 @@ typedef struct PlaneContext {
     VlcState *vlc_state;
 } PlaneContext;
 
+typedef struct FFV1FloatRemapState {
+    /* Large encoder scratch reused by every frame of a slice. */
+    int mul[11][1025];
+    float score[1025][23];
+} FFV1FloatRemapState;
+
 #define MAX_SLICES 1024
 
 typedef struct FFV1SliceContext {
@@ -104,6 +110,7 @@ typedef struct FFV1SliceContext {
         struct {
             uint64_t rc_stat[256][2];
             uint64_t (*rc_stat2[MAX_QUANT_TABLES])[32][2];
+            FFV1FloatRemapState *float_remap_state;
         };
     };
     int remap_count[4];
diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c
index 1d18f10f05f..5ba7e08638c 100644
--- a/libavcodec/ffv1enc.c
+++ b/libavcodec/ffv1enc.c
@@ -1072,6 +1072,11 @@ static av_cold int encode_init_internal(AVCodecContext 
*avctx)
         }
         av_assert0(s->remap_mode >= 0);
         if (s->remap_mode) {
+            if (s->bits_per_raw_sample == 32) {
+                sc->float_remap_state = 
av_malloc(sizeof(*sc->float_remap_state));
+                if (!sc->float_remap_state)
+                    return AVERROR(ENOMEM);
+            }
             for (int p = 0; p < 1 + 2*s->chroma_planes + s->transparency ; 
p++) {
                 if (s->bits_per_raw_sample == 32) {
                     sc->unit[p] = av_malloc_array(sc->slice_width, 
sc->slice_height * sizeof(**sc->unit));
@@ -1520,19 +1525,21 @@ static void encode_float32_remap(FFV1Context *f, 
FFV1SliceContext *sc,
     const int bruteforce_count    = ((int[]){  0,  0,  0,  1,  1,   
1})[f->remap_optimizer];
     const int stair_mode          = ((int[]){  0,  0,  0,  1,  0,   
0})[f->remap_optimizer];
     const int magic_log2          = ((int[]){  1,  1,  1,  1,  0,   
0})[f->remap_optimizer];
+    int (*const mul_all)[1025] = sc->float_remap_state->mul;
+    float (*const score_tab_all)[23] = sc->float_remap_state->score;
 
     for (int p= 0; p < 1 + 2*f->chroma_planes + f->transparency; p++) {
         int best_log2_mul_count = 0;
         float score_sum[11] = {0};
-        int mul_all[11][1025];
 
         for (int log2_mul_count= 0; log2_mul_count <= max_log2_mul_count; 
log2_mul_count += log2_mul_count_step) {
-            float score_tab_all[1025][23] = {0};
             int64_t last_val = -1;
             int *mul_tab = mul_all[log2_mul_count];
             int last_mul_index = -1;
             int mul_count = 1 << log2_mul_count;
 
+            memset(score_tab_all, 0, 1025 * sizeof(*score_tab_all));
+
             score_sum[log2_mul_count] = 2 * log2_mul_count;
             if (magic_log2)
                 score_sum[log2_mul_count] = av_float2int((float)mul_count * 
mul_count);
@@ -1605,6 +1612,7 @@ static void encode_float32_remap(FFV1Context *f, 
FFV1SliceContext *sc,
 
         encode_float32_remap_segment(sc, p, 1<<best_log2_mul_count, 
mul_all[best_log2_mul_count], 1, 1);
     }
+
 }
 
 static int encode_float32_rgb_frame(FFV1Context *f, FFV1SliceContext *sc,
@@ -2051,6 +2059,7 @@ static av_cold int encode_close(AVCodecContext *avctx)
             av_freep(&sc->unit[p]);
             av_freep(&sc->bitmap[p]);
         }
+        av_freep(&sc->float_remap_state);
     }
 
     av_freep(&avctx->stats_out);
-- 
2.54.0

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

Reply via email to