diff --git a/mpp/codec/mpp_rc.cpp b/mpp/codec/mpp_rc.cpp index d4e13cf1..1a80c3bf 100644 --- a/mpp/codec/mpp_rc.cpp +++ b/mpp/codec/mpp_rc.cpp @@ -37,58 +37,6 @@ static RK_U32 mpp_rc_debug = 0; -static RK_S32 axb_div_c(RK_S32 a, RK_S32 b, RK_S32 c) -{ - RK_U32 left = 32; - RK_U32 right = 0; - RK_U32 shift; - RK_S32 sign = 1; - RK_S32 tmp; - - if (a == 0 || b == 0) - return 0; - else if ((a * b / b) == a && c != 0) - return (a * b / c); - - if (a < 0) { - sign = -1; - a = -a; - } - if (b < 0) { - sign *= -1; - b = -b; - } - if (c < 0) { - sign *= -1; - c = -c; - } - - if (c == 0) - return 0x7FFFFFFF * sign; - - if (b > a) { - tmp = b; - b = a; - a = tmp; - } - - for (--left; (((RK_U32)a << left) >> left) != (RK_U32)a; --left) - ; - - left--; - - while (((RK_U32)b >> right) > (RK_U32)c) - right++; - - if (right > left) { - return 0x7FFFFFFF * sign; - } else { - shift = left - right; - return (RK_S32)((((RK_U32)a << shift) / - (RK_U32)c * (RK_U32)b) >> shift) * sign; - } -} - MPP_RET mpp_data_init(MppData **data, RK_S32 size) { if (NULL == data || size <= 0) { diff --git a/mpp/hal/rkenc/h264e/hal_h264e_rkv.c b/mpp/hal/rkenc/h264e/hal_h264e_rkv.c index f0b47247..eaba0ab7 100644 --- a/mpp/hal/rkenc/h264e/hal_h264e_rkv.c +++ b/mpp/hal/rkenc/h264e/hal_h264e_rkv.c @@ -2385,8 +2385,8 @@ MPP_RET hal_h264e_rkv_set_rc_regs(h264e_hal_context *ctx, h264e_rkv_reg_set *reg regs->swreg54.rc_qp_mod = 2; //sw_quality_flag; if (syn->frame_type == H264E_RKV_FRAME_I) { - regs->swreg54.rc_fact0 = 16; //sw_quality_factor_0; - regs->swreg54.rc_fact1 = 0; //sw_quality_factor_1; + regs->swreg54.rc_fact0 = 8; //sw_quality_factor_0; + regs->swreg54.rc_fact1 = 8; //sw_quality_factor_1; } else { regs->swreg54.rc_fact0 = 0; //sw_quality_factor_0; regs->swreg54.rc_fact1 = 16; //sw_quality_factor_1; @@ -2742,6 +2742,40 @@ static MPP_RET hal_h264e_rkv_update_hw_cfg(h264e_hal_context *ctx, HalEncTask *t codec->change = 0; } + /* init qp calculate, if outside doesn't set init qp. + * mpp will use bpp to estimates one. + */ + if (hw_cfg->pic_init_qp <= 0) { + RK_S32 qp_tbl[2][9] = { + {27, 44, 72, 119, 192, 314, 453, 653, 0x7FFFFFFF}, + {49, 45, 41, 37, 33, 29, 25, 21, 17}}; + RK_S32 pels = ctx->cfg->prep.width * ctx->cfg->prep.height; + RK_S32 bits_per_pic = axb_div_c(rc->bps_target, + rc->fps_out_denorm, + rc->fps_out_num); + + if (pels) { + RK_S32 upscale = 8000; + if (bits_per_pic > 1000000) + hw_cfg->pic_init_qp = codec->qp_min; + else { + RK_S32 j = -1; + + pels >>= 8; + bits_per_pic >>= 5; + + bits_per_pic *= pels + 250; + bits_per_pic /= 350 + (3 * pels) / 4; + bits_per_pic = axb_div_c(bits_per_pic, upscale, pels << 6); + + while (qp_tbl[0][++j] < bits_per_pic); + + hw_cfg->pic_init_qp = qp_tbl[1][j]; + hw_cfg->qp_prev = hw_cfg->pic_init_qp; + } + } + } + if (NULL == ctx->intra_qs) mpp_linreg_init(&ctx->intra_qs, MPP_MIN(rc->gop, 10), 2); if (NULL == ctx->inter_qs) diff --git a/osal/inc/mpp_common.h b/osal/inc/mpp_common.h index c5345b0e..fbe116db 100644 --- a/osal/inc/mpp_common.h +++ b/osal/inc/mpp_common.h @@ -181,6 +181,8 @@ static __inline RK_U32 mpp_is_32bit() return ((sizeof(void *) == 4) ? (1) : (0)); } +RK_S32 axb_div_c(RK_S32 a, RK_S32 b, RK_S32 c); + #ifdef __cplusplus } #endif diff --git a/osal/mpp_common.cpp b/osal/mpp_common.cpp index 39f2eb4c..08376bff 100644 --- a/osal/mpp_common.cpp +++ b/osal/mpp_common.cpp @@ -55,3 +55,54 @@ RK_S32 mpp_log2_16bit(RK_U32 v) return n; } +RK_S32 axb_div_c(RK_S32 a, RK_S32 b, RK_S32 c) +{ + RK_U32 left = 32; + RK_U32 right = 0; + RK_U32 shift; + RK_S32 sign = 1; + RK_S32 tmp; + + if (a == 0 || b == 0) + return 0; + else if ((a * b / b) == a && c != 0) + return (a * b / c); + + if (a < 0) { + sign = -1; + a = -a; + } + if (b < 0) { + sign *= -1; + b = -b; + } + if (c < 0) { + sign *= -1; + c = -c; + } + + if (c == 0) + return 0x7FFFFFFF * sign; + + if (b > a) { + tmp = b; + b = a; + a = tmp; + } + + for (--left; (((RK_U32)a << left) >> left) != (RK_U32)a; --left) + ; + + left--; + + while (((RK_U32)b >> right) > (RK_U32)c) + right++; + + if (right > left) { + return 0x7FFFFFFF * sign; + } else { + shift = left - right; + return (RK_S32)((((RK_U32)a << shift) / + (RK_U32)c * (RK_U32)b) >> shift) * sign; + } +}