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);