From 167c7dd9cf02b091ed49d202c36512d63d62d67b Mon Sep 17 00:00:00 2001 From: "sayon.chen" Date: Wed, 1 Nov 2017 17:17:32 +0800 Subject: [PATCH] [rkvenc] modfiy ratecontrol to be more smooth 1. use max min qp to limit qp range 2. open aq mode used adaptive aq prop according inter.p 3. open frame ratecontrol on re-encoding 4. modify bits_per_intra equal ctx->bits_per_pic * 3 5. limit target_bit larger then zero Change-Id: I71c5b2747ba4e89b5121093a7b110a2a8af20e02 Signed-off-by: sayon.chen --- mpp/codec/enc/h264/src/h264e_api.c | 6 +++ mpp/codec/inc/mpp_rc.h | 3 ++ mpp/codec/mpp_rc.cpp | 19 ++++++- mpp/hal/rkenc/h264e/hal_h264e_rkv.c | 82 +++++++++++++++++++++-------- mpp/hal/rkenc/h264e/hal_h264e_rkv.h | 10 +++- 5 files changed, 93 insertions(+), 27 deletions(-) diff --git a/mpp/codec/enc/h264/src/h264e_api.c b/mpp/codec/enc/h264/src/h264e_api.c index 10d565ea..61913570 100644 --- a/mpp/codec/enc/h264/src/h264e_api.c +++ b/mpp/codec/enc/h264/src/h264e_api.c @@ -165,6 +165,12 @@ MPP_RET h264e_encode(void *ctx, HalEncTask *task) p->idr_request--; mpp_rc_bits_allocation(p->rc, rc_syn); + if (rc_syn->bit_target <= 0) { + int mb_width = ((cfg->prep.width + 15) & (~15)) >> 4; + int mb_height = ((cfg->prep.height + 15) & (~15)) >> 4; + /* When there is no bit to allocate set bit_target as total mb count */ + rc_syn->bit_target = mb_width * mb_height; + } mpp_rc_record_param(&p->rc_list, p->rc, rc_syn); task->syntax.data = &p->syntax; diff --git a/mpp/codec/inc/mpp_rc.h b/mpp/codec/inc/mpp_rc.h index 7f11e184..827c4a51 100644 --- a/mpp/codec/inc/mpp_rc.h +++ b/mpp/codec/inc/mpp_rc.h @@ -192,6 +192,8 @@ typedef struct MppRateControl_s { /* start from ONE */ RK_U32 frm_cnt; RK_S32 real_bps; + RK_S32 prev_aq_prop_offset; + } MppRateControl; /* @@ -206,6 +208,7 @@ typedef struct RcSyntax_s { RK_S32 bit_target; RK_S32 bit_max; RK_S32 bit_min; + RK_S32 aq_prop_offset; /* head node of rc parameter list */ struct list_head *rc_head; diff --git a/mpp/codec/mpp_rc.cpp b/mpp/codec/mpp_rc.cpp index a0da4ed5..18afdb68 100644 --- a/mpp/codec/mpp_rc.cpp +++ b/mpp/codec/mpp_rc.cpp @@ -369,7 +369,7 @@ MPP_RET mpp_rc_update_user_cfg(MppRateControl *ctx, MppEncRcCfg *cfg, RK_S32 for mpp_env_get_u32("intra_rate", &intra_to_inter_rate, 3); ctx->intra_to_inter_rate = intra_to_inter_rate; ctx->bits_per_inter = ctx->bits_per_pic; - ctx->bits_per_intra = ctx->bps_target * 2 / 3; + ctx->bits_per_intra = ctx->bits_per_pic * 3; ctx->bits_per_inter -= ctx->bits_per_intra / (ctx->fps_out - 1); } } @@ -459,6 +459,20 @@ MPP_RET mpp_rc_bits_allocation(MppRateControl *ctx, RcSyntax *rc_syn) mpp_rc_dbg_rc("RC: rc ctx %p inter pid diff %d target %d\n", ctx, diff_bit, ctx->bits_target); + + if (ctx->pid_inter.p > ctx->bits_per_inter * 1 / 2) { + ctx->prev_aq_prop_offset -= 4; + } else if (ctx->pid_inter.p > ctx->bits_per_inter * 1 / 3) { + ctx->prev_aq_prop_offset -= 3; + } else if (ctx->pid_inter.p > ctx->bits_per_inter * 1 / 6) { + ctx->prev_aq_prop_offset -= 2; + } else if (ctx->pid_inter.p > ctx->bits_per_inter * 1 / 10) { + ctx->prev_aq_prop_offset -= 1; + } + + if (ctx->bits_target > ctx->bits_per_inter * 11 / 12 && ctx->prev_aq_prop_offset < 0) { + ctx->prev_aq_prop_offset += 1; + } } } } break; @@ -481,7 +495,8 @@ MPP_RET mpp_rc_bits_allocation(MppRateControl *ctx, RcSyntax *rc_syn) mpp_rc_dbg_rc("after adjustment, target bits %d\n", ctx->bits_target); } } - + ctx->prev_aq_prop_offset = mpp_clip(ctx->prev_aq_prop_offset, -8, 0); + rc_syn->aq_prop_offset = ctx->prev_aq_prop_offset; rc_syn->bit_target = ctx->bits_target; /* step 2: calc min and max bits */ diff --git a/mpp/hal/rkenc/h264e/hal_h264e_rkv.c b/mpp/hal/rkenc/h264e/hal_h264e_rkv.c index 91232165..05edd02a 100644 --- a/mpp/hal/rkenc/h264e/hal_h264e_rkv.c +++ b/mpp/hal/rkenc/h264e/hal_h264e_rkv.c @@ -79,11 +79,24 @@ static H264eRkvMbRcMcfg mb_rc_m_cfg[H264E_MB_RC_M_NUM] = { {16, 1, 0, 1}, // mode = 0 {8, 1, 1, 2}, // mode = 1 {4, 1, 1, 4}, // mode = 2 - {2, 1, 1, 4}, // mode = 3 - {0, 1, 1, 2}, // mode = 4 + {8, 2, 1, 10}, // mode = 3 + {8, 1.8, 1, 10}, // mode = 4 {0, 0, 1, 15}, // mode = 5 }; +static H264eRkvMbRcQRcfg mb_rc_qr_cfg[9] = { + /*qp min offset to qp hdr, qp_range */ + {8, 0, 10}, //qp 0 - 5 + {8, 0, 10}, //qp 6 - 11 + {6, 0, 8 }, //qp 12 - 17 + {6, 0, 8 }, //qp 18 - 23 + {4, 0, 6 }, //qp 24 - 29 + {4, 0, 5 }, //qp 30 - 35 + {0, 4, 6 }, //qp 36 - 41 + {0, 2, 8 }, //qp 42 - 45 + {0, 2, 5 }, //qp 46 - 51 +}; + static H264eRkvMbRcQcfg mb_rc_q_cfg[MPP_ENC_RC_QUALITY_BUTT] = { /* qp_min, qp_max */ {31, 51}, // worst @@ -1848,6 +1861,31 @@ static MPP_RET h264e_rkv_set_rc_regs(H264eHalContext *ctx, H264eRkvRegSet *regs, syn->qp_min = q_cfg.qp_min; syn->qp_max = q_cfg.qp_max; } + } else { + if (ctx->frame_cnt > 1 && ctx->hw_cfg.frame_type != H264E_RKV_FRAME_I) { + H264eRkvMbRcQRcfg qr_cfg = mb_rc_qr_cfg[syn->qp / 6]; + if (syn->qp > 45) { + qr_cfg = mb_rc_qr_cfg[48 / 6]; + } + if (qr_cfg.qp_min_offset) + syn->qp_min = (RK_U32)MPP_MAX(syn->qp_min, (RK_S32)(syn->qp - qr_cfg.qp_min_offset)); + else + syn->qp_min = (RK_U32)MPP_MAX(syn->qp_min, (RK_S32)(syn->qp - qr_cfg.qp_range)); + + if (qr_cfg.qp_max_offset) + syn->qp_max = (RK_U32)MPP_MIN(syn->qp_max, (RK_S32)(syn->qp + qr_cfg.qp_max_offset)); + else + syn->qp_max = (RK_U32)MPP_MIN(syn->qp_max, (RK_S32)(syn->qp + qr_cfg.qp_range)); + + m_cfg.qp_range = qr_cfg.qp_range; + ctx->qp_scale = 1; + if (rc_syn->aq_prop_offset) { + m_cfg.aq_prop = mpp_clip((m_cfg.aq_prop + rc_syn->aq_prop_offset), 0, m_cfg.aq_prop); + } + } else if (ctx->hw_cfg.frame_type == H264E_RKV_FRAME_I) { + syn->qp_min = (RK_U32)MPP_MAX(10, syn->qp_min); + syn->qp_max = (RK_U32)MPP_MIN(37, syn->qp_max); + } } regs->swreg10.pic_qp = syn->qp; @@ -1870,11 +1908,11 @@ static MPP_RET h264e_rkv_set_rc_regs(H264eHalContext *ctx, H264eRkvRegSet *regs, if (regs->swreg54.rc_max_qp < regs->swreg54.rc_min_qp) MPP_SWAP(RK_U32, regs->swreg54.rc_max_qp, regs->swreg54.rc_min_qp); } - if (regs->swreg46.rc_mode) { //checkpoint rc open RK_U32 target = mb_target_size * m_cfg.mb_num; regs->swreg54.rc_qp_range = m_cfg.qp_range * ctx->qp_scale; + regs->swreg46.rc_ctu_num = m_cfg.mb_num; regs->swreg55.ctu_ebits = mb_target_size_mul_16; @@ -1882,21 +1920,21 @@ static MPP_RET h264e_rkv_set_rc_regs(H264eHalContext *ctx, H264eRkvRegSet *regs, regs->swreg47.bits_error1 = (RK_S32)((pow(0.88, 3) - 1) * (double)target); regs->swreg48.bits_error2 = (RK_S32)((pow(0.88, 2) - 1) * (double)target); regs->swreg48.bits_error3 = (RK_S32)((pow(0.88, 1) - 1) * (double)target); - regs->swreg49.bits_error4 = (RK_S32)((pow(1.12, 1) - 1) * (double)target); - regs->swreg49.bits_error5 = (RK_S32)((pow(1.12, 2) - 1) * (double)target); - regs->swreg50.bits_error6 = (RK_S32)((pow(1.12, 3) - 1) * (double)target); - regs->swreg50.bits_error7 = (RK_S32)((pow(1.12, 4) - 1) * (double)target); - regs->swreg51.bits_error8 = (RK_S32)((pow(1.12, 5) - 1) * (double)target); + regs->swreg49.bits_error4 = (RK_S32)((pow(1.12, 2) - 1) * (double)target); + regs->swreg49.bits_error5 = (RK_S32)((pow(1.12, 3) - 1) * (double)target); + regs->swreg50.bits_error6 = (RK_S32)((pow(1.12, 4) - 1) * (double)target); + regs->swreg50.bits_error7 = (RK_S32)((pow(2, 4) - 1) * (double)target); + regs->swreg51.bits_error8 = (RK_S32)((pow(2, 5) - 1) * (double)target); regs->swreg52.qp_adjust0 = -4; regs->swreg52.qp_adjust1 = -3; regs->swreg52.qp_adjust2 = -2; regs->swreg52.qp_adjust3 = -1; - regs->swreg52.qp_adjust4 = 0; - regs->swreg52.qp_adjust5 = 1; - regs->swreg53.qp_adjust6 = 2; - regs->swreg53.qp_adjust7 = 3; - regs->swreg53.qp_adjust8 = 4; + regs->swreg52.qp_adjust4 = 1; + regs->swreg52.qp_adjust5 = 2; + regs->swreg53.qp_adjust6 = 3; + regs->swreg53.qp_adjust7 = 4; + regs->swreg53.qp_adjust8 = 8; } regs->swreg62.sli_beta_ofst = 0; @@ -2256,12 +2294,10 @@ h264e_rkv_update_hw_cfg(H264eHalContext *ctx, HalEncTask *task, /* limit QP by qp_step */ if (ctx->frame_cnt > 1) { - hw_cfg->qp_min = mpp_clip(hw_cfg->qp_min, - hw_cfg->qp_prev - codec->qp_max_step, - hw_cfg->qp_prev - codec->qp_max_step / 2); - hw_cfg->qp_max = mpp_clip(hw_cfg->qp_max, - hw_cfg->qp_prev + codec->qp_max_step / 2, - hw_cfg->qp_prev + codec->qp_max_step); + + hw_cfg->qp_min = codec->qp_min; + hw_cfg->qp_max = codec->qp_max; + hw_cfg->qp = mpp_clip(hw_cfg->qp, hw_cfg->qp_prev - codec->qp_max_step, hw_cfg->qp_prev + codec->qp_max_step); @@ -2365,7 +2401,8 @@ MPP_RET hal_h264e_rkv_gen_regs(void *hal, HalTaskInfo *task) h264e_rkv_nal_start(extra_info, H264E_NAL_SEI, H264E_NAL_PRIORITY_DISPOSABLE); h264e_rkv_sei_encode(ctx, rc_syn); h264e_rkv_nal_end(extra_info); - rc_syn->bit_target -= extra_info->nal[0].i_payload; // take off SEI size + if (rc_syn->bit_target > extra_info->nal[0].i_payload) + rc_syn->bit_target -= extra_info->nal[0].i_payload; // take off SEI size } if (ctx->enc_mode == 2 || ctx->enc_mode == 3) { //link table mode @@ -2595,7 +2632,6 @@ MPP_RET hal_h264e_rkv_gen_regs(void *hal, HalTaskInfo *task) regs->swreg56.vlc_lmt = (sps->i_profile_idc < H264_PROFILE_HIGH && !pps->b_cabac); regs->swreg56.rdo_mark = 0; - { RK_U32 i_nal_type = 0, i_nal_ref_idc = 0; @@ -2962,12 +2998,12 @@ MPP_RET hal_h264e_rkv_wait(void *hal, HalTaskInfo *task) h264e_hal_dbg(H264E_DBG_DETAIL, "re-encode for first frame overflow ...\n"); fb->qp_sum = new_qp * num_mb; - h264e_rkv_resend(ctx, 0); + h264e_rkv_resend(ctx, 1); } else { /* The first and second frame, that is the first I and P frame, * is re-encoded for getting appropriate QP for target bits. */ - h264e_rkv_resend(ctx, 0); + h264e_rkv_resend(ctx, 1); } h264e_rkv_set_feedback(ctx, reg_out, enc_task); } else if ((RK_S32)frame_cnt < rc->fps_out_num / rc->fps_out_denorm && diff --git a/mpp/hal/rkenc/h264e/hal_h264e_rkv.h b/mpp/hal/rkenc/h264e/hal_h264e_rkv.h index 05b91819..ec33995d 100644 --- a/mpp/hal/rkenc/h264e/hal_h264e_rkv.h +++ b/mpp/hal/rkenc/h264e/hal_h264e_rkv.h @@ -892,9 +892,9 @@ typedef struct H264eRkvIoctlOutput_t { /* mode cfg */ typedef struct H264eRkvMbRcMcfg_t { - RK_U32 aq_prop; //0~16, 0:only enable aq, 16:only enable checkpoint + RK_S32 aq_prop; //0~16, 0:only enable aq, 16:only enable checkpoint - RK_U32 aq_strength; //0~3 + double aq_strength; //0~3 RK_U32 mb_num; RK_U32 qp_range; //0~15 @@ -906,6 +906,12 @@ typedef struct H264eRkvMbRcQcfg_t { RK_U32 qp_max; } H264eRkvMbRcQcfg; +typedef struct H264eRkvMbRcQRcfg_t { + RK_U32 qp_min_offset; + RK_U32 qp_max_offset; + RK_U32 qp_range; +} H264eRkvMbRcQRcfg; + #define RK_H264E_NUM_REGS ((RK_S32)(sizeof(H264eRkvRegSet)/4)) MPP_RET hal_h264e_rkv_init (void *hal, MppHalCfg *cfg);