From f303ecc412994c73ee4ef059cbedfba796b8006b Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 28 Feb 2025 23:47:52 +0100 Subject: [PATCH 31/40] avcodec/mpegvideo: Move ratecontrol-only options to RateControlContext Signed-off-by: Andreas Rheinhardt --- libavcodec/mpegvideo.h | 11 ----------- libavcodec/mpegvideoenc.h | 13 +++++++------ libavcodec/ratecontrol.c | 25 +++++++++++++------------ libavcodec/ratecontrol.h | 11 +++++++++++ libavcodec/snowenc.c | 2 +- 5 files changed, 32 insertions(+), 30 deletions(-) diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index ac38d112f9..5fef008cc5 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -507,21 +507,10 @@ typedef struct MpegEncContext { me_cmp_func sse_cmp[2]; int (*sum_abs_dctelem)(const int16_t *block); - /** - * ratecontrol qmin qmax limiting method - * 0-> clipping, 1-> use a nice continuous function to limit qscale within qmin/qmax. - */ - float rc_qsquish; - float rc_qmod_amp; - int rc_qmod_freq; - float rc_initial_cplx; - float rc_buffer_aggressivity; float border_masking; int lmin, lmax; int vbv_ignore_qmax; - char *rc_eq; - /* temp buffers for rate control */ float *cplx_tab, *bits_tab; diff --git a/libavcodec/mpegvideoenc.h b/libavcodec/mpegvideoenc.h index 2d7f76c57a..f4e02593e8 100644 --- a/libavcodec/mpegvideoenc.h +++ b/libavcodec/mpegvideoenc.h @@ -81,6 +81,7 @@ { "msad", "Sum of absolute differences, median predicted", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_MEDIAN_SAD }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, .unit = "cmp_func" } #define FF_MPV_OFFSET(x) offsetof(MpegEncContext, x) +#define FF_RC_OFFSET(x) (offsetof(MpegEncContext, rc_context) + offsetof(RateControlContext, x)) #define FF_MPV_OPT_FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM) #define FF_MPV_COMMON_OPTS \ FF_MPV_OPT_CMP_FUNC, \ @@ -99,16 +100,16 @@ FF_MPV_OPT_CMP_FUNC, \ { "error_rate", "Simulate errors in the bitstream to test error concealment.", \ FF_MPV_OFFSET(error_rate), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FF_MPV_OPT_FLAGS },\ {"qsquish", "how to keep quantizer between qmin and qmax (0 = clip, 1 = use differentiable function)", \ - FF_MPV_OFFSET(rc_qsquish), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, 0, 99, FF_MPV_OPT_FLAGS}, \ -{"rc_qmod_amp", "experimental quantizer modulation", FF_MPV_OFFSET(rc_qmod_amp), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, -FLT_MAX, FLT_MAX, FF_MPV_OPT_FLAGS}, \ -{"rc_qmod_freq", "experimental quantizer modulation", FF_MPV_OFFSET(rc_qmod_freq), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS}, \ + FF_RC_OFFSET(qsquish), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, 0, 99, FF_MPV_OPT_FLAGS}, \ +{"rc_qmod_amp", "experimental quantizer modulation", FF_RC_OFFSET(qmod_amp), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, -FLT_MAX, FLT_MAX, FF_MPV_OPT_FLAGS}, \ +{"rc_qmod_freq", "experimental quantizer modulation", FF_RC_OFFSET(qmod_freq), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS}, \ {"rc_eq", "Set rate control equation. When computing the expression, besides the standard functions " \ "defined in the section 'Expression Evaluation', the following functions are available: " \ "bits2qp(bits), qp2bits(qp). Also the following constants are available: iTex pTex tex mv " \ "fCode iCount mcVar var isI isP isB avgQP qComp avgIITex avgPITex avgPPTex avgBPTex avgTex.", \ - FF_MPV_OFFSET(rc_eq), AV_OPT_TYPE_STRING, .flags = FF_MPV_OPT_FLAGS }, \ -{"rc_init_cplx", "initial complexity for 1-pass encoding", FF_MPV_OFFSET(rc_initial_cplx), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, -FLT_MAX, FLT_MAX, FF_MPV_OPT_FLAGS}, \ -{"rc_buf_aggressivity", "currently useless", FF_MPV_OFFSET(rc_buffer_aggressivity), AV_OPT_TYPE_FLOAT, {.dbl = 1.0 }, -FLT_MAX, FLT_MAX, FF_MPV_OPT_FLAGS}, \ + 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 }, \ diff --git a/libavcodec/ratecontrol.c b/libavcodec/ratecontrol.c index 86ec7a3443..f383c433c4 100644 --- a/libavcodec/ratecontrol.c +++ b/libavcodec/ratecontrol.c @@ -182,10 +182,10 @@ static double modify_qscale(MpegEncContext *s, const RateControlEntry *rce, get_qminmax(&qmin, &qmax, s, pict_type); /* modulation */ - if (s->rc_qmod_freq && - frame_num % s->rc_qmod_freq == 0 && + if (rcc->qmod_freq && + frame_num % rcc->qmod_freq == 0 && pict_type == AV_PICTURE_TYPE_P) - q *= s->rc_qmod_amp; + q *= rcc->qmod_amp; /* buffer overflow/underflow protection */ if (buffer_size) { @@ -198,7 +198,7 @@ static double modify_qscale(MpegEncContext *s, const RateControlEntry *rce, d = 1.0; else if (d < 0.0001) d = 0.0001; - q *= pow(d, 1.0 / s->rc_buffer_aggressivity); + q *= pow(d, 1.0 / rcc->buffer_aggressivity); q_limit = bits2qp(rce, FFMAX((min_rate - buffer_size + rcc->buffer_index) * @@ -218,7 +218,7 @@ static double modify_qscale(MpegEncContext *s, const RateControlEntry *rce, d = 1.0; else if (d < 0.0001) d = 0.0001; - q /= pow(d, 1.0 / s->rc_buffer_aggressivity); + q /= pow(d, 1.0 / rcc->buffer_aggressivity); q_limit = bits2qp(rce, FFMAX(rcc->buffer_index * @@ -234,8 +234,8 @@ static double modify_qscale(MpegEncContext *s, const RateControlEntry *rce, } ff_dlog(s, "q:%f max:%f min:%f size:%f index:%f agr:%f\n", q, max_rate, min_rate, buffer_size, rcc->buffer_index, - s->rc_buffer_aggressivity); - if (s->rc_qsquish == 0.0 || qmin == qmax) { + rcc->buffer_aggressivity); + if (rcc->qsquish == 0.0 || qmin == qmax) { if (q < qmin) q = qmin; else if (q > qmax) @@ -295,7 +295,7 @@ static double get_qscale(MpegEncContext *s, RateControlEntry *rce, bits = av_expr_eval(rcc->rc_eq_eval, const_values, rce); if (isnan(bits)) { - av_log(s->avctx, AV_LOG_ERROR, "Error evaluating rc_eq \"%s\"\n", s->rc_eq); + av_log(s->avctx, AV_LOG_ERROR, "Error evaluating rc_eq \"%s\"\n", rcc->rc_eq); return -1; } @@ -541,11 +541,11 @@ av_cold int ff_rate_control_init(MpegEncContext *s) } res = av_expr_parse(&rcc->rc_eq_eval, - s->rc_eq ? s->rc_eq : "tex^qComp", + rcc->rc_eq ? rcc->rc_eq : "tex^qComp", const_names, func1_names, func1, NULL, NULL, 0, s->avctx); if (res < 0) { - av_log(s->avctx, AV_LOG_ERROR, "Error parsing rc_eq \"%s\"\n", s->rc_eq); + av_log(s->avctx, AV_LOG_ERROR, "Error parsing rc_eq \"%s\"\n", rcc->rc_eq); return res; } @@ -649,9 +649,9 @@ av_cold int ff_rate_control_init(MpegEncContext *s) return -1; } /* init stuff with the user specified complexity */ - if (s->rc_initial_cplx) { + if (rcc->initial_cplx) { for (i = 0; i < 60 * 30; i++) { - double bits = s->rc_initial_cplx * (i / 10000.0 + 1.0) * s->mb_num; + double bits = rcc->initial_cplx * (i / 10000.0 + 1.0) * s->mb_num; RateControlEntry rce; if (i % ((s->gop_size + 3) / 4) == 0) @@ -701,6 +701,7 @@ av_cold void ff_rate_control_uninit(RateControlContext *rcc) { emms_c(); + // rc_eq is always managed via an AVOption and therefore not freed here. av_expr_free(rcc->rc_eq_eval); rcc->rc_eq_eval = NULL; av_freep(&rcc->entry); diff --git a/libavcodec/ratecontrol.h b/libavcodec/ratecontrol.h index 4d71a181b5..edeccbc6cd 100644 --- a/libavcodec/ratecontrol.h +++ b/libavcodec/ratecontrol.h @@ -77,6 +77,17 @@ typedef struct RateControlContext{ int frame_count[5]; int last_non_b_pict_type; + /** + * ratecontrol qmin qmax limiting method + * 0-> clipping, 1-> use a nice continuous function to limit qscale within qmin/qmax. + */ + float qsquish; + float qmod_amp; + int qmod_freq; + float initial_cplx; + float buffer_aggressivity; + + char *rc_eq; struct AVExpr *rc_eq_eval; }RateControlContext; diff --git a/libavcodec/snowenc.c b/libavcodec/snowenc.c index 5f539a57df..fe8ffdcdcd 100644 --- a/libavcodec/snowenc.c +++ b/libavcodec/snowenc.c @@ -2118,7 +2118,7 @@ static const AVOption options[] = { "defined in the section 'Expression Evaluation', the following functions are available: " "bits2qp(bits), qp2bits(qp). Also the following constants are available: iTex pTex tex mv " "fCode iCount mcVar var isI isP isB avgQP qComp avgIITex avgPITex avgPPTex avgBPTex avgTex.", - OFFSET(m.rc_eq), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, VE }, + OFFSET(m.rc_context.rc_eq), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, VE }, { NULL }, }; -- 2.45.2