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