From f1ee64b9e2b800ff6e4f58efd161b9d3a6bcdefe Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Sun, 2 Mar 2025 04:01:24 +0100
Subject: [PATCH 24/77] avcodec/mpegvideo: Move ratecontrol-adjacent fields to
 MPVMainEncContext

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/mpegvideo.h     |  6 ------
 libavcodec/mpegvideo_enc.c | 40 ++++++++++++++++++++------------------
 libavcodec/mpegvideoenc.h  | 15 ++++++++++----
 libavcodec/ratecontrol.c   | 18 +++++++++--------
 libavcodec/snowenc.c       |  4 ++--
 5 files changed, 44 insertions(+), 39 deletions(-)

diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h
index 3259c1117c..6c71d9bc01 100644
--- a/libavcodec/mpegvideo.h
+++ b/libavcodec/mpegvideo.h
@@ -101,7 +101,6 @@ typedef struct MpegEncContext {
     int h263_flv;     ///< use flv H.263 header
 
     enum AVCodecID codec_id;     /* see AV_CODEC_ID_xxx */
-    int fixed_qscale; ///< fixed qscale if non zero
     int encoding;     ///< true if we are encoding (vs decoding)
     int max_b_frames; ///< max number of B-frames for encoding
     int luma_elim_threshold;
@@ -478,10 +477,6 @@ typedef struct MpegEncContext {
     me_cmp_func sse_cmp[2];
     int (*sum_abs_dctelem)(const int16_t *block);
 
-    float border_masking;
-    int lmin, lmax;
-    int vbv_ignore_qmax;
-
     /// Bitfield containing information which frames to reconstruct.
     int frame_reconstruction_bitfield;
 
@@ -493,7 +488,6 @@ typedef struct MpegEncContext {
 
     int error_rate;
 
-    int scenechange_threshold;
     int noise_reduction;
 
     int intra_penalty;
diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c
index cc3c7a745f..06314dc602 100644
--- a/libavcodec/mpegvideo_enc.c
+++ b/libavcodec/mpegvideo_enc.c
@@ -195,8 +195,10 @@ void ff_convert_matrix(MpegEncContext *s, int (*qmat)[64],
     }
 }
 
-static inline void update_qscale(MpegEncContext *s)
+static inline void update_qscale(MPVMainEncContext *const m)
 {
+    MpegEncContext *const s = &m->s;
+
     if (s->q_scale_type == 1 && 0) {
         int i;
         int bestdiff=INT_MAX;
@@ -205,7 +207,7 @@ static inline void update_qscale(MpegEncContext *s)
         for (i = 0 ; i<FF_ARRAY_ELEMS(ff_mpeg2_non_linear_qscale); i++) {
             int diff = FFABS((ff_mpeg2_non_linear_qscale[i]<<(FF_LAMBDA_SHIFT + 6)) - (int)s->lambda * 139);
             if (ff_mpeg2_non_linear_qscale[i] < s->avctx->qmin ||
-                (ff_mpeg2_non_linear_qscale[i] > s->avctx->qmax && !s->vbv_ignore_qmax))
+                (ff_mpeg2_non_linear_qscale[i] > s->avctx->qmax && !m->vbv_ignore_qmax))
                 continue;
             if (diff < bestdiff) {
                 bestdiff = diff;
@@ -216,7 +218,7 @@ static inline void update_qscale(MpegEncContext *s)
     } else {
         s->qscale = (s->lambda * 139 + FF_LAMBDA_SCALE * 64) >>
                     (FF_LAMBDA_SHIFT + 7);
-        s->qscale = av_clip(s->qscale, s->avctx->qmin, s->vbv_ignore_qmax ? 31 : s->avctx->qmax);
+        s->qscale = av_clip(s->qscale, s->avctx->qmin, m->vbv_ignore_qmax ? 31 : s->avctx->qmax);
     }
 
     s->lambda2 = (s->lambda * s->lambda + FF_LAMBDA_SCALE / 2) >>
@@ -507,16 +509,16 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx)
     }
 
     /* Fixed QSCALE */
-    s->fixed_qscale = !!(avctx->flags & AV_CODEC_FLAG_QSCALE);
+    m->fixed_qscale = !!(avctx->flags & AV_CODEC_FLAG_QSCALE);
 
     s->adaptive_quant = (avctx->lumi_masking ||
                          avctx->dark_masking ||
                          avctx->temporal_cplx_masking ||
                          avctx->spatial_cplx_masking  ||
                          avctx->p_masking      ||
-                         s->border_masking ||
+                         m->border_masking ||
                          (s->mpv_flags & FF_MPV_FLAG_QP_RD)) &&
-                        !s->fixed_qscale;
+                        !m->fixed_qscale;
 
     s->loop_filter = !!(avctx->flags & AV_CODEC_FLAG_LOOP_FILTER);
 
@@ -580,7 +582,7 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx)
         return AVERROR(EINVAL);
     }
 
-    if (!s->fixed_qscale &&
+    if (!m->fixed_qscale &&
         avctx->bit_rate * av_q2d(avctx->time_base) >
             avctx->bit_rate_tolerance) {
         double nbt = avctx->bit_rate * av_q2d(avctx->time_base) * 5;
@@ -675,7 +677,7 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx)
         return AVERROR(EINVAL);
     }
 
-    if (s->scenechange_threshold < 1000000000 &&
+    if (m->scenechange_threshold < 1000000000 &&
         (avctx->flags & AV_CODEC_FLAG_CLOSED_GOP)) {
         av_log(avctx, AV_LOG_ERROR,
                "closed gop with scene change detection are not supported yet, "
@@ -890,9 +892,9 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx)
         s->frame_reconstruction_bitfield = 0;
     }
 
-    if (s->lmin > s->lmax) {
-        av_log(avctx, AV_LOG_WARNING, "Clipping lmin value to %d\n", s->lmax);
-        s->lmin = s->lmax;
+    if (m->lmin > m->lmax) {
+        av_log(avctx, AV_LOG_WARNING, "Clipping lmin value to %d\n", m->lmax);
+        m->lmin = m->lmax;
     }
 
     /* init */
@@ -1876,7 +1878,7 @@ int ff_mpv_encode_picture(AVCodecContext *avctx, AVPacket *pkt,
 
     ff_mpv_unref_picture(&s->cur_pic);
 
-    s->vbv_ignore_qmax = 0;
+    m->vbv_ignore_qmax = 0;
 
     m->picture_in_gop_number++;
 
@@ -1935,7 +1937,7 @@ vbv_retry:
             int min_step = hq ? 1 : (1<<(FF_LAMBDA_SHIFT + 7))/139;
 
             if (put_bits_count(&s->pb) > max_size &&
-                s->lambda < s->lmax) {
+                s->lambda < m->lmax) {
                 m->next_lambda = FFMAX(s->lambda + min_step, s->lambda *
                                        (s->qscale + 1) / s->qscale);
                 if (s->adaptive_quant) {
@@ -1955,7 +1957,7 @@ vbv_retry:
                     s->time_base       = s->last_time_base;
                     s->last_non_b_time = s->time - s->pp_time;
                 }
-                s->vbv_ignore_qmax = 1;
+                m->vbv_ignore_qmax = 1;
                 av_log(avctx, AV_LOG_VERBOSE, "reencoding frame due to VBV\n");
                 goto vbv_retry;
             }
@@ -3616,7 +3618,7 @@ static int estimate_qp(MPVMainEncContext *const m, int dry_run)
     if (m->next_lambda){
         s->cur_pic.ptr->f->quality = m->next_lambda;
         if(!dry_run) m->next_lambda= 0;
-    } else if (!s->fixed_qscale) {
+    } else if (!m->fixed_qscale) {
         int quality = ff_rate_estimate_qscale(m, dry_run);
         s->cur_pic.ptr->f->quality = quality;
         if (s->cur_pic.ptr->f->quality < 0)
@@ -3643,7 +3645,7 @@ static int estimate_qp(MPVMainEncContext *const m, int dry_run)
         //FIXME broken
     }else
         s->lambda = s->cur_pic.ptr->f->quality;
-    update_qscale(s);
+    update_qscale(m);
     return 0;
 }
 
@@ -3700,7 +3702,7 @@ static int encode_picture(MPVMainEncContext *const m, const AVPacket *pkt)
             s->lambda= s->last_lambda_for[s->pict_type];
         else
             s->lambda= s->last_lambda_for[s->last_non_b_pict_type];
-        update_qscale(s);
+        update_qscale(m);
     }
 
     ff_me_init_pic(s);
@@ -3742,7 +3744,7 @@ static int encode_picture(MPVMainEncContext *const m, const AVPacket *pkt)
         for(i=0; i<s->mb_stride*s->mb_height; i++)
             s->mb_type[i]= CANDIDATE_MB_TYPE_INTRA;
 
-        if(!s->fixed_qscale){
+        if (!m->fixed_qscale) {
             /* finding spatial complexity for I-frame rate control */
             s->avctx->execute(s->avctx, mb_var_thread, &s->thread_context[0], NULL, context_count, sizeof(void*));
         }
@@ -3754,7 +3756,7 @@ static int encode_picture(MPVMainEncContext *const m, const AVPacket *pkt)
     s->mb_var_sum    = s->me.   mb_var_sum_temp;
     emms_c();
 
-    if (s->me.scene_change_score > s->scenechange_threshold &&
+    if (s->me.scene_change_score > m->scenechange_threshold &&
         s->pict_type == AV_PICTURE_TYPE_P) {
         s->pict_type= AV_PICTURE_TYPE_I;
         for(i=0; i<s->mb_stride*s->mb_height; i++)
diff --git a/libavcodec/mpegvideoenc.h b/libavcodec/mpegvideoenc.h
index a76d17f63e..1fbe5590df 100644
--- a/libavcodec/mpegvideoenc.h
+++ b/libavcodec/mpegvideoenc.h
@@ -39,6 +39,8 @@
 typedef struct MPVMainEncContext {
     MpegEncContext s;  ///< The main slicecontext
 
+    int scenechange_threshold;
+
     int intra_only;                ///< if true, only intra pictures are generated
     int gop_size;
     int picture_in_gop_number;     ///< 0-> first pic in gop, ...
@@ -61,6 +63,10 @@ typedef struct MPVMainEncContext {
     int b_sensitivity;
     int brd_scale;
 
+    float border_masking;
+    int lmin, lmax;
+    int vbv_ignore_qmax;
+
     /* frame skip options */
     int frame_skip_threshold;
     int frame_skip_factor;
@@ -73,6 +79,7 @@ typedef struct MPVMainEncContext {
     int frame_bits;                ///< bits used for the current frame
     int stuffing_bits;             ///< bits used for stuffing
     int next_lambda;               ///< next lambda used for retrying to encode a frame
+    int fixed_qscale;              ///< fixed qscale if non zero
     RateControlContext rc_context; ///< contains stuff only accessed in ratecontrol.c
 } MPVMainEncContext;
 
@@ -154,14 +161,14 @@ FF_MPV_OPT_CMP_FUNC, \
                                                                     FF_RC_OFFSET(rc_eq), AV_OPT_TYPE_STRING,                           .flags = FF_MPV_OPT_FLAGS },            \
 {"rc_init_cplx", "initial complexity for 1-pass encoding",          FF_RC_OFFSET(initial_cplx), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, -FLT_MAX, FLT_MAX, FF_MPV_OPT_FLAGS},       \
 {"rc_buf_aggressivity", "currently useless",                        FF_RC_OFFSET(buffer_aggressivity), AV_OPT_TYPE_FLOAT, {.dbl = 1.0 }, -FLT_MAX, FLT_MAX, FF_MPV_OPT_FLAGS}, \
-{"border_mask", "increase the quantizer for macroblocks close to borders", FF_MPV_OFFSET(border_masking), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, -FLT_MAX, FLT_MAX, FF_MPV_OPT_FLAGS},    \
-{"lmin", "minimum Lagrange factor (VBR)",                           FF_MPV_OFFSET(lmin), AV_OPT_TYPE_INT, {.i64 =  2*FF_QP2LAMBDA }, 0, INT_MAX, FF_MPV_OPT_FLAGS },            \
-{"lmax", "maximum Lagrange factor (VBR)",                           FF_MPV_OFFSET(lmax), AV_OPT_TYPE_INT, {.i64 = 31*FF_QP2LAMBDA }, 0, INT_MAX, FF_MPV_OPT_FLAGS },            \
+{"border_mask", "increase the quantizer for macroblocks close to borders", FF_MPV_MAIN_OFFSET(border_masking), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, -FLT_MAX, FLT_MAX, FF_MPV_OPT_FLAGS},    \
+{"lmin", "minimum Lagrange factor (VBR)",                           FF_MPV_MAIN_OFFSET(lmin), AV_OPT_TYPE_INT, {.i64 =  2*FF_QP2LAMBDA }, 0, INT_MAX, FF_MPV_OPT_FLAGS },            \
+{"lmax", "maximum Lagrange factor (VBR)",                           FF_MPV_MAIN_OFFSET(lmax), AV_OPT_TYPE_INT, {.i64 = 31*FF_QP2LAMBDA }, 0, INT_MAX, FF_MPV_OPT_FLAGS },            \
 {"skip_threshold", "Frame skip threshold",                          FF_MPV_MAIN_OFFSET(frame_skip_threshold), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \
 {"skip_factor", "Frame skip factor",                                FF_MPV_MAIN_OFFSET(frame_skip_factor), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \
 {"skip_exp", "Frame skip exponent",                                 FF_MPV_MAIN_OFFSET(frame_skip_exp), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \
 {"skip_cmp", "Frame skip compare function",                         FF_MPV_MAIN_OFFSET(frame_skip_cmp), AV_OPT_TYPE_INT, {.i64 = FF_CMP_DCTMAX }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, .unit = "cmp_func" }, \
-{"sc_threshold", "Scene change threshold",                          FF_MPV_OFFSET(scenechange_threshold), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \
+{"sc_threshold", "Scene change threshold",                          FF_MPV_MAIN_OFFSET(scenechange_threshold), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \
 {"noise_reduction", "Noise reduction",                              FF_MPV_OFFSET(noise_reduction), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \
 {"ps", "RTP payload size in bytes",                             FF_MPV_OFFSET(rtp_payload_size), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \
 
diff --git a/libavcodec/ratecontrol.c b/libavcodec/ratecontrol.c
index 4aa358a4e5..f4df67aab0 100644
--- a/libavcodec/ratecontrol.c
+++ b/libavcodec/ratecontrol.c
@@ -142,10 +142,11 @@ static double get_diff_limited_q(MPVMainEncContext *m, const RateControlEntry *r
 /**
  * Get the qmin & qmax for pict_type.
  */
-static void get_qminmax(int *qmin_ret, int *qmax_ret, MpegEncContext *s, int pict_type)
+static void get_qminmax(int *qmin_ret, int *qmax_ret, MPVMainEncContext *const m, int pict_type)
 {
-    int qmin = s->lmin;
-    int qmax = s->lmax;
+    MpegEncContext *const s = &m->s;
+    int qmin = m->lmin;
+    int qmax = m->lmax;
 
     av_assert0(qmin <= qmax);
 
@@ -182,7 +183,7 @@ static double modify_qscale(MPVMainEncContext *const m, const RateControlEntry *
     const int pict_type      = rce->new_pict_type;
     int qmin, qmax;
 
-    get_qminmax(&qmin, &qmax, s, pict_type);
+    get_qminmax(&qmin, &qmax, m, pict_type);
 
     /* modulation */
     if (rcc->qmod_freq &&
@@ -784,15 +785,16 @@ static void update_predictor(Predictor *p, double q, double var, double size)
 }
 
 static void adaptive_quantization(RateControlContext *const rcc,
-                                  MpegEncContext *const s, double q)
+                                  MPVMainEncContext *const m, double q)
 {
+    MpegEncContext *const s = &m->s;
     int i;
     const float lumi_masking         = s->avctx->lumi_masking / (128.0 * 128.0);
     const float dark_masking         = s->avctx->dark_masking / (128.0 * 128.0);
     const float temp_cplx_masking    = s->avctx->temporal_cplx_masking;
     const float spatial_cplx_masking = s->avctx->spatial_cplx_masking;
     const float p_masking            = s->avctx->p_masking;
-    const float border_masking       = s->border_masking;
+    const float border_masking       = m->border_masking;
     float bits_sum                   = 0.0;
     float cplx_sum                   = 0.0;
     float *cplx_tab                  = rcc->cplx_tab;
@@ -932,7 +934,7 @@ float ff_rate_estimate_qscale(MPVMainEncContext *const m, int dry_run)
     const int pict_type = s->pict_type;
     emms_c();
 
-    get_qminmax(&qmin, &qmax, s, pict_type);
+    get_qminmax(&qmin, &qmax, m, pict_type);
 
     fps = get_fps(s->avctx);
     /* update predictors */
@@ -1068,7 +1070,7 @@ float ff_rate_estimate_qscale(MPVMainEncContext *const m, int dry_run)
         q = qmax;
 
     if (s->adaptive_quant)
-        adaptive_quantization(rcc, s, q);
+        adaptive_quantization(rcc, m, q);
     else
         q = (int)(q + 0.5);
 
diff --git a/libavcodec/snowenc.c b/libavcodec/snowenc.c
index 830f6f5096..d974a12f6b 100644
--- a/libavcodec/snowenc.c
+++ b/libavcodec/snowenc.c
@@ -228,8 +228,8 @@ static av_cold int encode_init(AVCodecContext *avctx)
 
     mpv->avctx   = avctx;
     mpv->bit_rate= avctx->bit_rate;
-    mpv->lmin    = avctx->mb_lmin;
-    mpv->lmax    = avctx->mb_lmax;
+    enc->m.lmin  = avctx->mb_lmin;
+    enc->m.lmax  = avctx->mb_lmax;
     mpv->mb_num  = (avctx->width * avctx->height + 255) / 256; // For ratecontrol
 
     mpv->me.temp      =
-- 
2.45.2