diff --git a/inc/mpp_meta.h b/inc/mpp_meta.h index b0335515..4da2eb5b 100644 --- a/inc/mpp_meta.h +++ b/inc/mpp_meta.h @@ -80,6 +80,7 @@ typedef enum MppMetaKey_e { KEY_LONG_REF_IDX = FOURCC_META('l', 't', 'i', 'd'), KEY_ENC_AVERAGE_QP = FOURCC_META('a', 'v', 'g', 'q'), KEY_ENC_START_QP = FOURCC_META('s', 't', 'r', 'q'), + KEY_ENC_BPS_RT = FOURCC_META('r', 't', 'b', 'r'), /* realtime bps */ KEY_ROI_DATA = FOURCC_META('r', 'o', 'i', ' '), KEY_OSD_DATA = FOURCC_META('o', 's', 'd', ' '), KEY_OSD_DATA2 = FOURCC_META('o', 's', 'd', '2'), diff --git a/inc/mpp_rc_api.h b/inc/mpp_rc_api.h index 05e2e979..838e0b82 100644 --- a/inc/mpp_rc_api.h +++ b/inc/mpp_rc_api.h @@ -50,6 +50,7 @@ typedef enum RcMode_e { RC_CBR, RC_FIXQP, RC_AVBR, + RC_SMT, RC_CVBR, RC_QVBR, RC_LEARNING, diff --git a/inc/mpp_rc_defs.h b/inc/mpp_rc_defs.h index d3eb3b18..9eb93f01 100644 --- a/inc/mpp_rc_defs.h +++ b/inc/mpp_rc_defs.h @@ -215,7 +215,10 @@ typedef struct EncRcCommonInfo_t { RK_S32 scene_mode; RK_S32 last_scene_mode; - RK_S32 reserve[5]; + /* rc stats info: real time bits */ + RK_S32 rt_bits; + + RK_S32 reserve[4]; } EncRcTaskInfo; typedef struct EncRcTask_s { diff --git a/inc/rk_venc_cmd.h b/inc/rk_venc_cmd.h index 3c8d9024..70d963dd 100644 --- a/inc/rk_venc_cmd.h +++ b/inc/rk_venc_cmd.h @@ -1428,15 +1428,21 @@ typedef enum MppEncSceneMode_e { typedef enum MppEncFineTuneCfgChange_e { /* change on scene mode */ - MPP_ENC_TUNE_CFG_CHANGE_SCENE_MODE = (1 << 0), - MPP_ENC_TUNE_CFG_CHANGE_LAMBDA_IDX_I = (1 << 5), - MPP_ENC_TUNE_CFG_CHANGE_LAMBDA_IDX_P = (1 << 6) + MPP_ENC_TUNE_CFG_CHANGE_SCENE_MODE = (1 << 0), + MPP_ENC_TUNE_CFG_CHANGE_DEBLUR_EN = (1 << 1), + MPP_ENC_TUNE_CFG_CHANGE_DEBLUR_STR = (1 << 2), + MPP_ENC_TUNE_CFG_CHANGE_ANTI_FLICKER_STR = (1 << 3), + MPP_ENC_TUNE_CFG_CHANGE_LAMBDA_IDX_I = (1 << 5), + MPP_ENC_TUNE_CFG_CHANGE_LAMBDA_IDX_P = (1 << 6) } MppEncFineTuneCfgChange; typedef struct MppEncFineTuneCfg_t { RK_U32 change; MppEncSceneMode scene_mode; + RK_S32 deblur_en; /* qpmap_en */ + RK_S32 deblur_str; /* deblur strength */ + RK_S32 anti_flicker_str; RK_S32 lambda_idx_i; RK_S32 lambda_idx_p; } MppEncFineTuneCfg; diff --git a/inc/rk_venc_rc.h b/inc/rk_venc_rc.h index b03289c1..8321b0d9 100644 --- a/inc/rk_venc_rc.h +++ b/inc/rk_venc_rc.h @@ -28,6 +28,7 @@ typedef enum MppEncRcMode_e { MPP_ENC_RC_MODE_CBR, MPP_ENC_RC_MODE_FIXQP, MPP_ENC_RC_MODE_AVBR, + MPP_ENC_RC_MODE_SMTRC, MPP_ENC_RC_MODE_BUTT } MppEncRcMode; diff --git a/mpp/base/mpp_2str.c b/mpp/base/mpp_2str.c index 06e0c91f..08df849c 100644 --- a/mpp/base/mpp_2str.c +++ b/mpp/base/mpp_2str.c @@ -72,6 +72,7 @@ const char *strof_rc_mode(MppEncRcMode rc_mode) "cbr", "fixqp", "avbr", + "smtrc" }; if (rc_mode >= MPP_ENC_RC_MODE_VBR && rc_mode < MPP_ENC_RC_MODE_BUTT) diff --git a/mpp/base/mpp_enc_cfg.cpp b/mpp/base/mpp_enc_cfg.cpp index c3786312..457d4303 100644 --- a/mpp/base/mpp_enc_cfg.cpp +++ b/mpp/base/mpp_enc_cfg.cpp @@ -257,6 +257,9 @@ public: ENTRY(hw, qbias_en, S32, RK_S32, MPP_ENC_HW_CFG_CHANGE_QBIAS_EN, hw, qbias_en) \ /* quality fine tuning config */ \ ENTRY(tune, scene_mode, S32, MppEncSceneMode, MPP_ENC_TUNE_CFG_CHANGE_SCENE_MODE, tune, scene_mode) \ + ENTRY(tune, deblur_en, S32, RK_S32, MPP_ENC_TUNE_CFG_CHANGE_DEBLUR_EN, tune, deblur_en) \ + ENTRY(tune, deblur_str, S32, RK_S32, MPP_ENC_TUNE_CFG_CHANGE_DEBLUR_STR, tune, deblur_str) \ + ENTRY(tune, anti_flicker_str,S32, RK_S32, MPP_ENC_TUNE_CFG_CHANGE_ANTI_FLICKER_STR,tune, anti_flicker_str) \ ENTRY(tune, lambda_idx_i, S32, RK_S32, MPP_ENC_TUNE_CFG_CHANGE_LAMBDA_IDX_I, tune, lambda_idx_i) \ ENTRY(tune, lambda_idx_p, S32, RK_S32, MPP_ENC_TUNE_CFG_CHANGE_LAMBDA_IDX_P, tune, lambda_idx_p) diff --git a/mpp/base/mpp_meta.cpp b/mpp/base/mpp_meta.cpp index 192e5656..2cd1bfae 100644 --- a/mpp/base/mpp_meta.cpp +++ b/mpp/base/mpp_meta.cpp @@ -56,6 +56,7 @@ static MppMetaDef meta_defs[] = { { KEY_LONG_REF_IDX, TYPE_S32, }, { KEY_ENC_AVERAGE_QP, TYPE_S32, }, { KEY_ENC_START_QP, TYPE_S32, }, + { KEY_ENC_BPS_RT, TYPE_S32, }, { KEY_ROI_DATA, TYPE_PTR, }, { KEY_ROI_DATA2, TYPE_PTR, }, diff --git a/mpp/codec/enc/h265/h265e_api.c b/mpp/codec/enc/h265/h265e_api.c index 57ed9b64..5de1e93e 100644 --- a/mpp/codec/enc/h265/h265e_api.c +++ b/mpp/codec/enc/h265/h265e_api.c @@ -112,6 +112,7 @@ static MPP_RET h265e_init(void *ctx, EncImplCfg *ctrlCfg) p->cfg->tune.scene_mode = MPP_ENC_SCENE_MODE_DEFAULT; p->cfg->tune.lambda_idx_i = 2; p->cfg->tune.lambda_idx_p = 4; + p->cfg->tune.anti_flicker_str = 2; /* * default prep: diff --git a/mpp/codec/inc/mpp_rc.h b/mpp/codec/inc/mpp_rc.h index 59f7c78d..bbe6e71c 100644 --- a/mpp/codec/inc/mpp_rc.h +++ b/mpp/codec/inc/mpp_rc.h @@ -128,7 +128,7 @@ RK_S32 mpp_data_avg(MppData *p, RK_S32 len, RK_S32 num, RK_S32 denom); void mpp_pid_reset(MppPIDCtx *p); void mpp_pid_set_param(MppPIDCtx *p, RK_S32 coef_p, RK_S32 coef_i, RK_S32 coef_d, RK_S32 div, RK_S32 len); -void mpp_pid_update(MppPIDCtx *p, RK_S32 val); +void mpp_pid_update(MppPIDCtx *p, RK_S32 val, RK_S32 is_reset); RK_S32 mpp_pid_calc(MppPIDCtx *ctx); #ifdef __cplusplus diff --git a/mpp/codec/mpp_enc_impl.cpp b/mpp/codec/mpp_enc_impl.cpp index 24c4ba8b..04987400 100644 --- a/mpp/codec/mpp_enc_impl.cpp +++ b/mpp/codec/mpp_enc_impl.cpp @@ -862,16 +862,35 @@ MPP_RET mpp_enc_proc_tune_cfg(MppEncFineTuneCfg *dst, MppEncFineTuneCfg *src) if (dst->scene_mode < MPP_ENC_SCENE_MODE_DEFAULT || dst->scene_mode >= MPP_ENC_SCENE_MODE_BUTT) { - mpp_err("invalid scene mode %d not in range [%d:%d]\n", dst->scene_mode, + mpp_err("invalid scene mode %d not in range [%d, %d]\n", dst->scene_mode, MPP_ENC_SCENE_MODE_DEFAULT, MPP_ENC_SCENE_MODE_BUTT - 1); ret = MPP_ERR_VALUE; } + if (change & MPP_ENC_TUNE_CFG_CHANGE_DEBLUR_EN) + dst->deblur_en = src->deblur_en; + + if (change & MPP_ENC_TUNE_CFG_CHANGE_DEBLUR_STR) + dst->deblur_str = src->deblur_str; + + if (dst->deblur_str < 0 || dst->deblur_str > 7) { + mpp_err("invalid deblur strength not in range [0, 7]\n"); + ret = MPP_ERR_VALUE; + } + + if (change & MPP_ENC_TUNE_CFG_CHANGE_ANTI_FLICKER_STR) + dst->anti_flicker_str = src->anti_flicker_str; + + if (dst->anti_flicker_str < 0 || dst->anti_flicker_str > 3) { + mpp_err("invalid anti_flicker_str not in range [0 : 3]\n"); + ret = MPP_ERR_VALUE; + } + if (change & MPP_ENC_TUNE_CFG_CHANGE_LAMBDA_IDX_I) dst->lambda_idx_i = src->lambda_idx_i; if (dst->lambda_idx_i < 0 || dst->lambda_idx_i > 8) { - mpp_err("invalid lambda idx i not in range [0 : 8]\n"); + mpp_err("invalid lambda idx i not in range [0, 8]\n"); ret = MPP_ERR_VALUE; } @@ -879,7 +898,7 @@ MPP_RET mpp_enc_proc_tune_cfg(MppEncFineTuneCfg *dst, MppEncFineTuneCfg *src) dst->lambda_idx_p = src->lambda_idx_p; if (dst->lambda_idx_p < 0 || dst->lambda_idx_p > 8) { - mpp_err("invalid lambda idx i not in range [0 : 8]\n"); + mpp_err("invalid lambda idx i not in range [0, 8]\n"); ret = MPP_ERR_VALUE; } @@ -1152,6 +1171,7 @@ static const char *name_of_rc_mode[] = { "cbr", "fixqp", "avbr", + "smtrc" }; static void update_rc_cfg_log(MppEncImpl *impl, const char* fmt, ...) @@ -1237,6 +1257,9 @@ static void set_rc_cfg(RcCfg *cfg, MppEncCfgSet *cfg_set) case MPP_ENC_RC_MODE_FIXQP: { cfg->mode = RC_FIXQP; } break; + case MPP_ENC_RC_MODE_SMTRC: { + cfg->mode = RC_SMT; + } break; default : { cfg->mode = RC_AVBR; } break; @@ -2253,6 +2276,7 @@ static MPP_RET set_enc_info_to_packet(MppEncImpl *enc, HalEncTask *hal_task) /* frame type */ mpp_meta_set_s32(meta, KEY_OUTPUT_INTRA, frm->is_intra); mpp_meta_set_s32(meta, KEY_OUTPUT_PSKIP, frm->force_pskip || is_pskip); + mpp_meta_set_s32(meta, KEY_ENC_BPS_RT, rc_task->info.rt_bits); if (rc_task->info.frame_type == INTER_VI_FRAME) mpp_meta_set_s32(meta, KEY_ENC_USE_LTR, rc_task->cpb.refr.lt_idx); diff --git a/mpp/codec/mpp_rc.cpp b/mpp/codec/mpp_rc.cpp index 1b200aa1..4305e228 100644 --- a/mpp/codec/mpp_rc.cpp +++ b/mpp/codec/mpp_rc.cpp @@ -155,7 +155,7 @@ void mpp_pid_set_param(MppPIDCtx *ctx, RK_S32 coef_p, RK_S32 coef_i, RK_S32 coef ctx, coef_p, coef_i, coef_d, div, len); } -void mpp_pid_update(MppPIDCtx *ctx, RK_S32 val) +void mpp_pid_update(MppPIDCtx *ctx, RK_S32 val, RK_S32 is_reset) { mpp_rc_dbg_rc("RC: pid ctx %p update val %d\n", ctx, val); mpp_rc_dbg_rc("RC: pid ctx %p before update P %d I %d D %d\n", ctx, ctx->p, ctx->i, ctx->d); @@ -169,7 +169,7 @@ void mpp_pid_update(MppPIDCtx *ctx, RK_S32 val) /* * pid control is a short time control, it needs periodically reset */ - if (ctx->count >= ctx->len) + if (is_reset && ctx->count >= ctx->len) mpp_pid_reset(ctx); } diff --git a/mpp/codec/rc/rc_model_v2.c b/mpp/codec/rc/rc_model_v2.c index 5ee41ad3..86dde8b4 100644 --- a/mpp/codec/rc/rc_model_v2.c +++ b/mpp/codec/rc/rc_model_v2.c @@ -1705,6 +1705,7 @@ MPP_RET rc_model_v2_end(void *ctx, EncRcTask *task) if (usr_cfg->mode == RC_FIXQP) goto DONE; + cfg->rt_bits = p->ins_bps; p->last_inst_bps = p->ins_bps; p->first_frm_flg = 0; diff --git a/mpp/codec/rc/rc_model_v2_smt.c b/mpp/codec/rc/rc_model_v2_smt.c index 583997c9..deb7cd7b 100644 --- a/mpp/codec/rc/rc_model_v2_smt.c +++ b/mpp/codec/rc/rc_model_v2_smt.c @@ -28,151 +28,69 @@ #include "rc_model_v2_smt.h" #include "mpp_rc.h" -#define MAD_THDI 20 -#define LIMIT_QP_MORE_MOVE 30 -#define ENOUGH_QP 33 #define LOW_QP 34 -#define LOW_QP_level0 34 -#define LOW_QP_level1 34 -#define LOW_LOW_QP 38 -#define LOW_PRE_DIFF_BIT_USE -20000 - -extern RK_S32 tab_lnx[64]; +#define LOW_LOW_QP 35 typedef struct RcModelV2SmtCtx_t { - RcCfg usr_cfg; - EncRcTaskInfo hal_cfg; - RK_U32 frame_type; - RK_U32 last_frame_type; - RK_S64 gop_total_bits; - RK_U32 bit_per_frame; - MppDataV2 *i_bit; - RK_U32 i_sumbits; - RK_U32 i_scale; - MppDataV2 *idr_bit; - RK_U32 idr_sumbits; - RK_U32 idr_scale; - MppDataV2 *p_bit; - RK_U32 p_sumbits; - RK_U32 p_scale; - MppDataV2 *pre_p_bit; - RK_S32 target_bps; - RK_S32 pre_target_bits; - RK_S32 pre_real_bits; - RK_S32 frm_bits_thr; - RK_S32 ins_bps; - RK_S32 last_inst_bps; - RK_U32 water_level_thr; - MppDataV2 *stat_bits; - MppDataV2 *stat_rate; - RK_S32 stat_watl_thrd; - RK_S32 stat_watl; - RK_S32 stat_last_watl; - RK_S32 next_i_ratio; // scale 64 - RK_S32 next_ratio; // scale 64 - RK_S32 pre_i_qp; - RK_S32 pre_p_qp; - RK_S32 scale_qp; // scale 64 - MppDataV2 *means_qp; - RK_S64 frm_num; - RK_S32 reenc_cnt; - RK_S32 codec_type; // 264: 0 ; 265: 1 - RK_S32 qp_min; - RK_S32 qp_max; - RK_S32 qp_step; - MppEncGopMode gop_mode; - RK_S32 window_len; - RK_S32 intra_to_inter_rate; - RK_S32 acc_intra_bits_in_fps; - RK_S32 acc_inter_bits_in_fps; - RK_S32 acc_total_bits; - RK_S64 acc_total_count; - RK_S64 acc_intra_count; - RK_S64 acc_inter_count; - RK_S32 last_fps_bits; - RK_S32 pre_gop_left_bit; - MppData *qp_p; - MppData *sse_p; - MppData *intra; - MppData *inter; - MppData *gop_bits; - MppData *intra_percent; - MppPIDCtx pid_fps; - RK_S32 bps_target_low_rate; - RK_S32 bps_target_high_rate; - RK_S32 bits_target_low_rate; - RK_S32 bits_target_high_rate; - RK_S32 bits_per_pic_low_rate; - RK_S32 bits_per_intra_low_rate; - RK_S32 bits_per_inter_low_rate; - RK_S32 bits_per_pic_high_rate; - RK_S32 bits_per_intra_high_rate; - RK_S32 bits_per_inter_high_rate; - RK_S32 pre_diff_bit_low_rate; - RK_S32 pre_diff_bit_high_rate; - RK_S32 gop_min; - MppPIDCtx pid_intra_low_rate; - MppPIDCtx pid_intra_high_rate; - MppPIDCtx pid_inter_low_rate; - MppPIDCtx pid_inter_high_rate; - RK_S32 bits_one_gop[1000]; - RK_S32 bits_one_gop_use_flag; - RK_S32 bits_one_gop_sum; - RK_S32 delta_bits_per_frame; - RK_S32 frame_cnt_in_gop; - RK_S32 bits_target_use; - RK_S32 qp_out; - RK_S32 qp_prev_out; - RK_S32 qp_preavg; - RK_S32 intra_prerealbit; - RK_S32 intra_preqp; - RK_S32 intra_presse; - RK_S32 intra_premadi; - RK_U32 st_madi; + RcCfg usr_cfg; + RK_U32 frame_type; + RK_U32 last_frame_type; + RK_U32 first_frm_flg; + RK_S64 frm_num; + RK_S32 qp_min; + RK_S32 qp_max; + MppEncGopMode gop_mode; + RK_S64 acc_intra_count; + RK_S64 acc_inter_count; + RK_S32 last_fps_bits; + RK_S32 pre_gop_left_bit; + MppData *qp_p; + MppDataV2 *motion_level; + MppDataV2 *complex_level; + MppDataV2 *stat_bits; + MppDataV2 *rt_bits; /* real time bits */ + MppPIDCtx pid_fps; + RK_S64 count_real_bit; + RK_S64 count_pred_bit; + RK_S64 count_frame; + RK_S64 fixed_i_pred_bit; + RK_S64 fixed_p_pred_bit; + RK_S32 change_bit_flag; + + RK_S32 bits_tgt_lower; /* bits target lower limit */ + RK_S32 bits_tgt_upper; /* bits target upper limit */ + RK_S32 bits_per_lower_i; /* bits per intra frame in low rate */ + RK_S32 bits_per_upper_i; /* bits per intra frame in high rate */ + RK_S32 bits_per_lower_p; /* bits per P frame in low rate */ + RK_S32 bits_per_upper_p; /* bits per P frame in high rate */ + + RK_S32 pre_diff_bit_lower; + RK_S32 pre_diff_bit_upper; + RK_S32 igop; + MppPIDCtx pid_lower_i; + MppPIDCtx pid_upper_i; + MppPIDCtx pid_lower_all; + MppPIDCtx pid_upper_all; + MppDataV2 *pid_lower_p; + MppDataV2 *pid_upper_p; + RK_S32 qp_out; + RK_S32 qp_prev_out; + RK_S32 pre_real_bit_i; /* real bit of last intra frame */ + RK_S32 pre_qp_i; /* qp of last intra frame */ + RK_S32 gop_qp_sum; + RK_S32 gop_frm_cnt; + RK_S32 pre_iblk4_prop; + RK_S32 reenc_cnt; + RK_U32 drop_cnt; + RK_S32 on_drop; + RK_S32 on_pskip; } RcModelV2SmtCtx; -typedef struct InfoList_t { - RK_U16 flag; // 1 - valid 0 - unvaild - RK_U16 up_left[2]; // 0 - y idx 1 - x idx - RK_U16 down_right[2]; // 0 - y idx 1 - x idx -} InfoList; - -typedef struct RoiInfo_t { - RK_U16 flag; // 1 - valid 0 - unvaild - RK_U16 is_move; // 1 - is motion 0 - is motionless - RK_U16 up_left[2]; // 0 - y idx 1 - x idx - RK_U16 down_right[2]; // 0 - y idx 1 - x idx -} RoiInfo; - -static RK_U32 cal_mv_info(InfoList* info) -{ - RK_S32 k, i, j; - RK_S32 mb_sta_x, mb_sta_y; - RK_S32 mb_end_x, mb_end_y; - RK_U32 move_num = 0; - - if (info == NULL) - return 0; - - for (k = 0; k < 4096; k++) { - if (info[k].flag == 0) - break; - - mb_sta_y = info[k].up_left[0] / 16; - mb_sta_x = info[k].up_left[1] / 16; - mb_end_y = info[k].down_right[0] / 16; - mb_end_x = info[k].down_right[1] / 16; - - for (j = mb_sta_y; j <= mb_end_y; j++) { - for (i = mb_sta_x; i <= mb_end_x; i++) { - - move_num++; - } - } - } - - return move_num; -} +//rc_container_bitrate_thd2 +// static RK_S32 rc_ctnr_qp_thd1[6] = {51, 42, 42, 51, 38, 38}; +// static RK_S32 rc_ctnr_qp_thd2[6] = {51, 44, 44, 51, 40, 40}; +// static RK_S32 rc_ctnr_br_thd1[6] = {100, 110, 110, 100, 110, 110}; +// static RK_S32 rc_ctnr_br_thd2[6] = {100, 120, 120, 100, 125, 125}; MPP_RET bits_model_smt_deinit(RcModelV2SmtCtx *ctx) { @@ -183,50 +101,14 @@ MPP_RET bits_model_smt_deinit(RcModelV2SmtCtx *ctx) ctx->qp_p = NULL; } - if (ctx->sse_p) { - mpp_data_deinit(ctx->sse_p); - ctx->sse_p = NULL; + if (ctx->motion_level != NULL) { + mpp_data_deinit_v2(ctx->motion_level); + ctx->motion_level = NULL; } - if (ctx->intra) { - mpp_data_deinit(ctx->intra); - ctx->intra = NULL; - } - - if (ctx->inter) { - mpp_data_deinit(ctx->inter); - ctx->inter = NULL; - } - - if (ctx->gop_bits) { - mpp_data_deinit(ctx->gop_bits); - ctx->gop_bits = NULL; - } - - if (ctx->intra_percent) { - mpp_data_deinit(ctx->intra_percent); - ctx->intra_percent = NULL; - } - - - if (ctx->i_bit != NULL) { - mpp_data_deinit_v2(ctx->i_bit); - ctx->i_bit = NULL; - } - - if (ctx->p_bit != NULL) { - mpp_data_deinit_v2(ctx->p_bit); - ctx->p_bit = NULL; - } - - if (ctx->pre_p_bit != NULL) { - mpp_data_deinit_v2(ctx->pre_p_bit); - ctx->pre_p_bit = NULL; - } - - if (ctx->stat_rate != NULL) { - mpp_data_deinit_v2(ctx->stat_rate); - ctx->stat_rate = NULL; + if (ctx->complex_level != NULL) { + mpp_data_deinit_v2(ctx->complex_level); + ctx->complex_level = NULL; } if (ctx->stat_bits != NULL) { @@ -234,6 +116,21 @@ MPP_RET bits_model_smt_deinit(RcModelV2SmtCtx *ctx) ctx->stat_bits = NULL; } + if (ctx->rt_bits != NULL) { + mpp_data_deinit_v2(ctx->rt_bits); + ctx->rt_bits = NULL; + } + + if (ctx->pid_lower_p != NULL) { + mpp_data_deinit_v2(ctx->pid_lower_p); + ctx->pid_lower_p = NULL; + } + + if (ctx->pid_upper_p != NULL) { + mpp_data_deinit_v2(ctx->pid_upper_p); + ctx->pid_upper_p = NULL; + } + rc_dbg_func("leave %p\n", ctx); return MPP_OK; } @@ -242,107 +139,114 @@ MPP_RET bits_model_smt_init(RcModelV2SmtCtx *ctx) { RK_S32 gop_len = ctx->usr_cfg.igop; RcFpsCfg *fps = &ctx->usr_cfg.fps; + RK_S32 mad_len = 10; + RK_S32 ave_bits_lower = 0, ave_bits_uppper = 0; + RK_S32 bits_lower_i, bits_upper_i; + RK_S32 bits_lower_p, bits_upper_p; + RK_S32 bit_ratio[5] = { 7, 8, 9, 10, 11 }; + RK_S32 nfps = fps->fps_out_num / fps->fps_out_denom; + RK_S32 win_len = mpp_clip(MPP_MAX3(gop_len, nfps, 10), 1, nfps); + RK_S32 rt_stat_len = fps->fps_out_num / fps->fps_out_denom; /* real time stat len */ + RK_S32 stat_len = fps->fps_out_num * ctx->usr_cfg.stats_time / fps->fps_out_denom; + stat_len = stat_len ? stat_len : (fps->fps_out_num * 8 / fps->fps_out_denom); rc_dbg_func("enter %p\n", ctx); ctx->frm_num = 0; + ctx->first_frm_flg = 1; + ctx->gop_frm_cnt = 0; + ctx->gop_qp_sum = 0; // smt - ctx->frame_cnt_in_gop = 0; - ctx->bits_one_gop_use_flag = 0; - ctx->gop_min = gop_len; - - ctx->qp_min = 18; + ctx->igop = gop_len; + ctx->qp_min = 10; ctx->qp_max = 51; - ctx->qp_step = 4; - if (gop_len < fps->fps_out_num) - ctx->window_len = fps->fps_out_num; - else - ctx->window_len = gop_len; + if (ctx->motion_level) + mpp_data_deinit_v2(ctx->motion_level); + mpp_data_init_v2(&ctx->motion_level, mad_len, 0); - if (ctx->window_len < 10) - ctx->window_len = 10; + if (ctx->complex_level) + mpp_data_deinit_v2(ctx->complex_level); + mpp_data_init_v2(&ctx->complex_level, mad_len, 0); - if (ctx->window_len > fps->fps_out_num) - ctx->window_len = fps->fps_out_num; + if (ctx->pid_lower_p) + mpp_data_deinit_v2(ctx->pid_lower_p); + mpp_data_init_v2(&ctx->pid_lower_p, stat_len, 0); - if (ctx->intra) - mpp_data_deinit(ctx->intra); - mpp_data_init(&ctx->intra, gop_len); - - if (ctx->inter) - mpp_data_deinit(ctx->inter); - mpp_data_init(&ctx->inter, fps->fps_out_num); /* need test */ - - if (ctx->gop_bits) - mpp_data_deinit(ctx->gop_bits); - mpp_data_init(&ctx->gop_bits, gop_len); - - if (ctx->intra_percent) - mpp_data_deinit(ctx->intra_percent); - mpp_data_init(&ctx->intra_percent, gop_len); + if (ctx->pid_upper_p) + mpp_data_deinit_v2(ctx->pid_upper_p); + mpp_data_init_v2(&ctx->pid_upper_p, stat_len, 0); mpp_pid_reset(&ctx->pid_fps); - mpp_pid_reset(&ctx->pid_intra_low_rate); - mpp_pid_reset(&ctx->pid_intra_high_rate); - mpp_pid_reset(&ctx->pid_inter_low_rate); - mpp_pid_reset(&ctx->pid_inter_high_rate); + mpp_pid_reset(&ctx->pid_lower_i); + mpp_pid_reset(&ctx->pid_upper_i); + mpp_pid_reset(&ctx->pid_lower_all); + mpp_pid_reset(&ctx->pid_upper_all); - mpp_pid_set_param(&ctx->pid_fps, 4, 6, 0, 100, ctx->window_len); - mpp_pid_set_param(&ctx->pid_intra_low_rate, 4, 6, 0, 100, ctx->window_len); - mpp_pid_set_param(&ctx->pid_intra_high_rate, 4, 6, 0, 100, ctx->window_len); - mpp_pid_set_param(&ctx->pid_inter_low_rate, 4, 6, 0, 100, ctx->window_len); - mpp_pid_set_param(&ctx->pid_inter_high_rate, 4, 6, 0, 100, ctx->window_len); + mpp_pid_set_param(&ctx->pid_fps, 4, 6, 0, 90, win_len); + mpp_pid_set_param(&ctx->pid_lower_i, 4, 6, 0, 100, win_len); + mpp_pid_set_param(&ctx->pid_upper_i, 4, 6, 0, 100, win_len); + mpp_pid_set_param(&ctx->pid_lower_all, 4, 6, 0, 100, gop_len); + mpp_pid_set_param(&ctx->pid_upper_all, 4, 6, 0, 100, gop_len); - ctx->bps_target_low_rate = ctx->usr_cfg.bps_min; - ctx->bps_target_high_rate = ctx->usr_cfg.bps_max; - ctx->bits_per_pic_low_rate = axb_div_c(ctx->bps_target_low_rate, fps->fps_out_denom, fps->fps_out_num); - ctx->bits_per_pic_high_rate = axb_div_c(ctx->bps_target_high_rate, fps->fps_out_denom, fps->fps_out_num); + ave_bits_lower = axb_div_c(ctx->usr_cfg.bps_min, fps->fps_out_denom, fps->fps_out_num); + ave_bits_uppper = axb_div_c(ctx->usr_cfg.bps_max, fps->fps_out_denom, fps->fps_out_num); - ctx->acc_intra_bits_in_fps = 0; - ctx->acc_inter_bits_in_fps = 0; - ctx->acc_total_bits = 0; ctx->acc_intra_count = 0; ctx->acc_inter_count = 0; ctx->last_fps_bits = 0; - RK_S32 avg_low_rate = ctx->bits_per_pic_low_rate; - RK_S32 avg_high_rate = ctx->bits_per_pic_high_rate; - if (gop_len == 0) { ctx->gop_mode = MPP_GOP_ALL_INTER; - ctx->bits_per_inter_low_rate = avg_low_rate; - ctx->bits_per_intra_low_rate = avg_low_rate * 10; - ctx->bits_per_inter_high_rate = avg_high_rate; - ctx->bits_per_intra_high_rate = avg_high_rate * 10; + bits_lower_p = ave_bits_lower; + bits_lower_i = ave_bits_lower * 10; + bits_upper_p = ave_bits_uppper; + bits_upper_i = ave_bits_uppper * 10; } else if (gop_len == 1) { ctx->gop_mode = MPP_GOP_ALL_INTRA; - ctx->bits_per_inter_low_rate = 0; - ctx->bits_per_intra_low_rate = avg_low_rate; - ctx->bits_per_inter_high_rate = 0; - ctx->bits_per_intra_high_rate = avg_high_rate; - ctx->intra_to_inter_rate = 0; - } else if (gop_len < ctx->window_len) { + bits_lower_p = 0; + bits_lower_i = ave_bits_lower; + bits_upper_p = 0; + bits_upper_i = ave_bits_uppper; + /* disable debreath on all intra case */ + if (ctx->usr_cfg.debreath_cfg.enable) + ctx->usr_cfg.debreath_cfg.enable = 0; + } else if (gop_len < win_len) { ctx->gop_mode = MPP_GOP_SMALL; - ctx->intra_to_inter_rate = gop_len + 1; - - ctx->bits_per_inter_low_rate = avg_low_rate / 2; - ctx->bits_per_intra_low_rate = ctx->bits_per_inter_low_rate * ctx->intra_to_inter_rate; - ctx->bits_per_inter_high_rate = avg_high_rate / 2; - ctx->bits_per_intra_high_rate = ctx->bits_per_inter_high_rate * ctx->intra_to_inter_rate; + bits_lower_p = ave_bits_lower >> 1; + bits_lower_i = bits_lower_p * (gop_len + 1); + bits_upper_p = ave_bits_uppper >> 1; + bits_upper_i = bits_upper_p * (gop_len + 1); } else { + RK_S32 g = gop_len; + RK_S32 idx = g <= 50 ? 0 : (g <= 100 ? 1 : (g <= 200 ? 2 : (g <= 300 ? 3 : 4))); + ctx->gop_mode = MPP_GOP_LARGE; - ctx->intra_to_inter_rate = gop_len + 1; - - ctx->bits_per_intra_low_rate = ctx->bits_per_pic_low_rate * (2.0 * log((float)gop_len)); - ctx->bits_per_inter_low_rate = ctx->bits_per_pic_low_rate; - ctx->bits_per_inter_low_rate -= ctx->bits_per_intra_low_rate / (fps->fps_out_num - 1); - - ctx->bits_per_intra_high_rate = ctx->bits_per_pic_high_rate * (2.0 * log((float)gop_len)); - ctx->bits_per_inter_high_rate = ctx->bits_per_pic_high_rate; - ctx->bits_per_inter_high_rate -= ctx->bits_per_intra_high_rate / (fps->fps_out_num - 1); + bits_lower_i = ave_bits_lower * bit_ratio[idx] / 2; + bits_upper_i = ave_bits_uppper * bit_ratio[idx] / 2; + bits_lower_p = ave_bits_lower - bits_lower_i / (nfps - 1); + bits_upper_p = ave_bits_uppper - bits_upper_i / (nfps - 1); + ctx->fixed_i_pred_bit = (ctx->usr_cfg.bps_max / nfps * 8) / 8; + ctx->fixed_p_pred_bit = ((ctx->usr_cfg.bps_max * g / nfps - ctx->fixed_i_pred_bit) / (g - 1)) / 8; } + ctx->bits_per_lower_i = bits_lower_i; + ctx->bits_per_upper_i = bits_upper_i; + ctx->bits_per_lower_p = bits_lower_p; + ctx->bits_per_upper_p = bits_upper_p; + + rc_dbg_rc("bits_per_lower_i %d, bits_per_upper_i %d, " + "bits_per_lower_p %d, bits_per_upper_p %d\n", + bits_lower_i, bits_upper_i, bits_lower_p, bits_upper_p); + + if (ctx->stat_bits) + mpp_data_deinit_v2(ctx->stat_bits); + mpp_data_init_v2(&ctx->stat_bits, stat_len, bits_upper_p); + + if (ctx->rt_bits) + mpp_data_deinit_v2(ctx->rt_bits); + mpp_data_init_v2(&ctx->rt_bits, rt_stat_len, bits_upper_p); + rc_dbg_func("leave %p\n", ctx); return MPP_OK; } @@ -350,59 +254,56 @@ MPP_RET bits_model_smt_init(RcModelV2SmtCtx *ctx) MPP_RET bits_model_update_smt(RcModelV2SmtCtx *ctx, RK_S32 real_bit) { rc_dbg_func("enter %p\n", ctx); - // smt - RK_S32 gop_len = ctx->usr_cfg.igop; RcFpsCfg *fps = &ctx->usr_cfg.fps; + RK_S32 bps_target_tmp = 0; + RK_S32 mod = 0; - ctx->pre_diff_bit_low_rate = ctx->bits_target_low_rate - real_bit; - ctx->pre_diff_bit_high_rate = ctx->bits_target_high_rate - real_bit; - ctx->bits_one_gop[ctx->frame_cnt_in_gop % 1000] = real_bit; - ctx->frame_cnt_in_gop++; + rc_dbg_func("enter %p\n", ctx); - if (ctx->frame_cnt_in_gop == gop_len) { - ctx->frame_cnt_in_gop = 0; - ctx->bits_one_gop_use_flag = 1; - ctx->bits_one_gop_sum = 0; - RK_S32 i = 0; - RK_S32 gop_len_save = gop_len; - if (gop_len > 1000) { - gop_len_save = 1000; - } - for (i = 0; i < gop_len_save; i++) - ctx->bits_one_gop_sum += ctx->bits_one_gop[i]; + mpp_data_update_v2(ctx->stat_bits, real_bit); + ctx->pre_diff_bit_lower = ctx->bits_tgt_lower - real_bit; + ctx->pre_diff_bit_upper = ctx->bits_tgt_upper - real_bit; - ctx->delta_bits_per_frame = ctx->bps_target_high_rate / (fps->fps_out_num) - ctx->bits_one_gop_sum / gop_len_save; + ctx->count_real_bit = ctx->count_real_bit + real_bit / 8; + if (ctx->frame_type == INTRA_FRAME) { + ctx->count_pred_bit = ctx->count_pred_bit + ctx->fixed_i_pred_bit; + } else { + ctx->count_pred_bit = ctx->count_pred_bit + ctx->fixed_p_pred_bit; + } + ctx->count_frame ++; + if (ctx->count_real_bit > 72057594037927935 || ctx->count_pred_bit > 72057594037927935) { + ctx->count_real_bit = 0; + ctx->count_pred_bit = 0; + } + + if (ctx->change_bit_flag == 1) { + real_bit = real_bit * 8 / 10; } if (ctx->frame_type == INTRA_FRAME) { ctx->acc_intra_count++; - ctx->acc_intra_bits_in_fps += real_bit; - mpp_data_update(ctx->intra, real_bit); - mpp_data_update(ctx->gop_bits, real_bit); - mpp_pid_update(&ctx->pid_intra_low_rate, real_bit - ctx->bits_target_low_rate); - mpp_pid_update(&ctx->pid_intra_high_rate, real_bit - ctx->bits_target_high_rate); + mpp_pid_update(&ctx->pid_lower_i, real_bit - ctx->bits_tgt_lower, 1); + mpp_pid_update(&ctx->pid_upper_i, real_bit - ctx->bits_tgt_upper, 1); } else { ctx->acc_inter_count++; - ctx->acc_inter_bits_in_fps += real_bit; - mpp_data_update(ctx->inter, real_bit); - mpp_data_update(ctx->gop_bits, real_bit); - mpp_pid_update(&ctx->pid_inter_low_rate, real_bit - ctx->bits_target_low_rate); - mpp_pid_update(&ctx->pid_inter_high_rate, real_bit - ctx->bits_target_high_rate); + mpp_data_update_v2(ctx->pid_lower_p, real_bit - ctx->bits_tgt_lower); + mpp_data_update_v2(ctx->pid_upper_p, real_bit - ctx->bits_tgt_upper); } + mpp_pid_update(&ctx->pid_lower_all, real_bit - ctx->bits_tgt_lower, 1); + mpp_pid_update(&ctx->pid_upper_all, real_bit - ctx->bits_tgt_upper, 1); - ctx->acc_total_count++; ctx->last_fps_bits += real_bit; /* new fps start */ - if ((ctx->acc_intra_count + ctx->acc_inter_count) % fps->fps_out_num == 0) { - RK_S32 bps_target_temp = (ctx->bps_target_low_rate + ctx->bps_target_high_rate) / 2; - if (bps_target_temp > (ctx->last_fps_bits * 2 / 3)) - mpp_pid_update(&ctx->pid_fps, bps_target_temp - ctx->last_fps_bits); + mod = ctx->acc_intra_count + ctx->acc_inter_count; + mod = mod % fps->fps_out_num; + if (0 == mod) { + bps_target_tmp = (ctx->usr_cfg.bps_min + ctx->usr_cfg.bps_max) >> 1; + if (bps_target_tmp * 3 > (ctx->last_fps_bits * 2)) + mpp_pid_update(&ctx->pid_fps, bps_target_tmp - ctx->last_fps_bits, 0); else { - bps_target_temp = ctx->bps_target_low_rate * 0.4 + ctx->bps_target_high_rate * 0.6; - mpp_pid_update(&ctx->pid_fps, bps_target_temp - ctx->last_fps_bits); + bps_target_tmp = ctx->usr_cfg.bps_min * 4 / 10 + ctx->usr_cfg.bps_max * 6 / 10; + mpp_pid_update(&ctx->pid_fps, bps_target_tmp - ctx->last_fps_bits, 0); } - ctx->acc_intra_bits_in_fps = 0; - ctx->acc_inter_bits_in_fps = 0; ctx->last_fps_bits = 0; } @@ -414,202 +315,12 @@ MPP_RET bits_model_update_smt(RcModelV2SmtCtx *ctx, RK_S32 real_bit) return MPP_OK; } -MPP_RET reenc_calc_cbr_ratio_smt(RcModelV2SmtCtx *ctx, EncRcTaskInfo *cfg) -{ - RK_S32 stat_time = ctx->usr_cfg.stats_time; - RK_S32 last_ins_bps = mpp_data_sum_v2(ctx->stat_bits) / stat_time; - RK_S32 ins_bps = (last_ins_bps * stat_time - mpp_data_get_pre_val_v2(ctx->stat_bits, -1) + cfg->bit_real) / stat_time; - RK_S32 real_bit = cfg->bit_real; - RK_S32 target_bit = cfg->bit_target; - RK_S32 target_bps = ctx->target_bps; - RK_S32 water_level = 0; - RK_S32 idx1, idx2; - RK_S32 i_flag = 0; - RK_S32 bit_diff_ratio, ins_ratio, bps_ratio, wl_ratio; - - rc_dbg_func("enter %p\n", ctx); - - i_flag = (ctx->frame_type == INTRA_FRAME); - - if (real_bit + ctx->stat_watl > ctx->stat_watl_thrd) - water_level = ctx->stat_watl_thrd - ctx->bit_per_frame; - else - water_level = real_bit + ctx->stat_watl_thrd - ctx->bit_per_frame; - - if (water_level < ctx->stat_last_watl) { - water_level = ctx->stat_last_watl; - } - - if (target_bit > real_bit) - bit_diff_ratio = 32 * (real_bit - target_bit) / target_bit; - else - bit_diff_ratio = 32 * (real_bit - target_bit) / real_bit; - - idx1 = ins_bps / (target_bps >> 5); - idx2 = last_ins_bps / (target_bps >> 5); - - idx1 = mpp_clip(idx1, 0, 63); - idx2 = mpp_clip(idx2, 0, 63); - ins_ratio = tab_lnx[idx1] - tab_lnx[idx2]; - - bps_ratio = 96 * (ins_bps - target_bps) / target_bps; - wl_ratio = 32 * (water_level - (ctx->water_level_thr >> 3)) / (ctx->water_level_thr >> 3); - if (last_ins_bps < ins_bps && target_bps != last_ins_bps) { - ins_ratio = 6 * ins_ratio; - ins_ratio = mpp_clip(ins_ratio, -192, 256); - } else { - if (i_flag) { - ins_ratio = 3 * ins_ratio; - ins_ratio = mpp_clip(ins_ratio, -192, 256); - } else { - ins_ratio = 0; - } - } - if (bit_diff_ratio >= 256) - bit_diff_ratio = 256; - - if (bps_ratio >= 32) - bps_ratio = 32; - - if (wl_ratio >= 32) - wl_ratio = 32; - - if (bit_diff_ratio < -128) - ins_ratio = ins_ratio - 128; - else - ins_ratio = ins_ratio + bit_diff_ratio; - - if (bps_ratio < -32) - ins_ratio = ins_ratio - 32; - else - ins_ratio = ins_ratio + bps_ratio; - - if (wl_ratio < -32) - wl_ratio = ins_ratio - 32; - else - wl_ratio = ins_ratio + wl_ratio; - - ctx->next_ratio = wl_ratio; - - rc_dbg_func("leave %p\n", ctx); - return MPP_OK; -} - -MPP_RET reenc_calc_vbr_ratio_smt(RcModelV2SmtCtx *ctx, EncRcTaskInfo *cfg) -{ - RK_S32 stat_time = ctx->usr_cfg.stats_time; - RK_S32 last_ins_bps = mpp_data_sum_v2(ctx->stat_bits) / stat_time; - RK_S32 ins_bps = (last_ins_bps * stat_time - mpp_data_get_pre_val_v2(ctx->stat_bits, -1) - + cfg->bit_real) / stat_time; - RK_S32 bps_change = ctx->target_bps; - RK_S32 max_bps_target = ctx->usr_cfg.bps_max; - RK_S32 real_bit = cfg->bit_real; - RK_S32 target_bit = cfg->bit_target; - RK_S32 idx1, idx2; - RK_S32 bit_diff_ratio, ins_ratio, bps_ratio; - - rc_dbg_func("enter %p\n", ctx); - - if (target_bit <= real_bit) - bit_diff_ratio = 32 * (real_bit - target_bit) / target_bit; - else - bit_diff_ratio = 32 * (real_bit - target_bit) / real_bit; - - idx1 = ins_bps / (max_bps_target >> 5); - idx2 = last_ins_bps / (max_bps_target >> 5); - idx1 = mpp_clip(idx1, 0, 63); - idx2 = mpp_clip(idx2, 0, 63); - if (last_ins_bps < ins_bps && bps_change < ins_bps) { - ins_ratio = 6 * (tab_lnx[idx1] - tab_lnx[idx2]); - ins_ratio = mpp_clip(ins_ratio, -192, 256); - } else { - ins_ratio = 0; - } - - bps_ratio = 96 * (ins_bps - bps_change) / bps_change; - - if (bit_diff_ratio >= 256) - bit_diff_ratio = 256; - if (bps_ratio >= 32) - bps_ratio = 32; - - if (bit_diff_ratio < -128) - ins_ratio = ins_ratio - 128; - else - ins_ratio = bit_diff_ratio + ins_ratio; - - if (bps_ratio < -32) - ins_ratio = ins_ratio - 32; - else - ins_ratio = ins_ratio + bps_ratio; - - ctx->next_ratio = ins_ratio; - rc_dbg_func("leave %p\n", ctx); - return MPP_OK; -} - -MPP_RET check_re_enc_smt(RcModelV2SmtCtx *ctx, EncRcTaskInfo *cfg) -{ - return MPP_OK; - - RK_S32 frame_type = ctx->frame_type; - RK_S32 i_flag = 0; - RK_S32 big_flag = 0; - RK_S32 stat_time = ctx->usr_cfg.stats_time; - RK_S32 last_ins_bps = mpp_data_sum_v2(ctx->stat_bits) / stat_time; - RK_S32 ins_bps = (last_ins_bps * stat_time - mpp_data_get_pre_val_v2(ctx->stat_bits, -1) - + cfg->bit_real) / stat_time; - RK_S32 target_bps; - RK_S32 flag1 = 0; - RK_S32 flag2 = 0; - - rc_dbg_func("enter %p\n", ctx); - - if (ctx->usr_cfg.mode == RC_CBR) - target_bps = ctx->usr_cfg.bps_target; - else - target_bps = ctx->usr_cfg.bps_max; - - if (ctx->reenc_cnt >= ctx->usr_cfg.max_reencode_times) { - return MPP_OK; - } - - i_flag = (frame_type == INTRA_FRAME); - if (!i_flag && cfg->bit_real > 3 * cfg->bit_target) { - big_flag = 1; - } - - if (i_flag && cfg->bit_real > 3 * cfg->bit_target / 2) { - big_flag = 1; - } - - if (ctx->usr_cfg.mode == RC_CBR) { - flag1 = target_bps / 20 < ins_bps - last_ins_bps; - if (target_bps + target_bps / 10 < ins_bps || - target_bps - target_bps / 10 > ins_bps) { - flag2 = 1; - } - } else { - flag1 = target_bps - (target_bps >> 3) < ins_bps; - flag2 = target_bps / 20 < ins_bps - last_ins_bps; - } - - if (!(big_flag && flag1 && flag2)) { - return MPP_OK; - } - - rc_dbg_func("leave %p\n", ctx); - return MPP_OK; -} - - MPP_RET rc_model_v2_smt_h265_init(void *ctx, RcCfg *cfg) { RcModelV2SmtCtx *p = (RcModelV2SmtCtx*)ctx; rc_dbg_func("enter %p\n", ctx); - p->codec_type = 1; memcpy(&p->usr_cfg, cfg, sizeof(RcCfg)); bits_model_smt_init(p); @@ -623,7 +334,6 @@ MPP_RET rc_model_v2_smt_h264_init(void *ctx, RcCfg *cfg) rc_dbg_func("enter %p\n", ctx); - p->codec_type = 0; memcpy(&p->usr_cfg, cfg, sizeof(RcCfg)); bits_model_smt_init(p); @@ -641,351 +351,670 @@ MPP_RET rc_model_v2_smt_deinit(void *ctx) return MPP_OK; } -MPP_RET rc_model_v2_smt_start(void *ctx, EncRcTask *task) +static void set_coef(void *ctx, RK_S32 *coef, RK_S32 val) { RcModelV2SmtCtx *p = (RcModelV2SmtCtx*)ctx; + RK_S32 cplx_lvl_0 = mpp_data_get_pre_val_v2(p->complex_level, 0); + RK_S32 cplx_lvl_1 = mpp_data_get_pre_val_v2(p->complex_level, 1); + RK_S32 cplx_lvl_sum = mpp_data_sum_v2(p->complex_level); + + if (cplx_lvl_sum == 0) + *coef = val + 0; + else if (cplx_lvl_sum == 1) { + if (cplx_lvl_0 == 0) + *coef = val + 10; + else + *coef = val + 25; + } else if (cplx_lvl_sum == 2) { + if (cplx_lvl_0 == 0) + *coef = val + 25; + else + *coef = val + 35; + } else if (cplx_lvl_sum == 3) { + if (cplx_lvl_0 == 0) + *coef = val + 35; + else + *coef = val + 51; + } else if (cplx_lvl_sum >= 4 && cplx_lvl_sum <= 6) { + if (cplx_lvl_0 == 0) { + if (cplx_lvl_1 == 0) + *coef = val + 35; + else + *coef = val + 51; + } else + *coef = val + 64; + } else if (cplx_lvl_sum >= 7 && cplx_lvl_sum <= 9) { + if (cplx_lvl_0 == 0) { + if (cplx_lvl_1 == 0) + *coef = val + 64; + else + *coef = val + 72; + } else + *coef = val + 72; + } else + *coef = val + 80; +} + +static RK_U32 mb_num[9] = { + 0, 200, 700, 1200, 2000, 4000, 8000, 16000, 20000 +}; + +static RK_U32 tab_bit[9] = { + 3780, 3570, 3150, 2940, 2730, 3780, 2100, 1680, 2100 +}; + +static RK_U8 qscale2qp[96] = { + 15, 15, 15, 15, 15, 16, 18, 20, 21, 22, 23, + 24, 25, 25, 26, 27, 28, 28, 29, 29, 30, 30, + 30, 31, 31, 32, 32, 33, 33, 33, 34, 34, 34, + 34, 35, 35, 35, 36, 36, 36, 36, 36, 37, 37, + 37, 37, 38, 38, 38, 38, 38, 39, 39, 39, 39, + 39, 39, 40, 40, 40, 40, 41, 41, 41, 41, 41, + 41, 41, 42, 42, 42, 42, 42, 42, 42, 42, 43, + 43, 43, 43, 43, 43, 43, 43, 44, 44, 44, 44, + 44, 44, 44, 44, 45, 45, 45, 45, +}; + +static RK_U8 inter_pqp0[52] = { + 1, 1, 1, 1, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 17, 18, 19, 20, 21, + 21, 21, 22, 23, 24, 25, 26, 26, + 27, 28, 28, 29, 29, 29, 30, 31, + 31, 32, 32, 33, 33, 34, 35, 35, + 35, 36, 36, 36 +}; + +static RK_U8 inter_pqp1[52] = { + 1, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 20, 21, 22, + 23, 24, 25, 26, 26, 27, 28, 29, + 29, 30, 31, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 42, + 42, 43, 43, 44 +}; + +static RK_U8 intra_pqp0[3][52] = { + { + 1, 1, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, + 23, 23, 24, 25, 26, 27, 27, 28, + 28, 29, 30, 31, 32, 32, 33, 34, + 34, 34, 35, 35, 36, 36, 36, 36, + 37, 37, 37, 38 + }, + + { + 1, 1, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 17, 18, 18, 19, 19, + 20, 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 32, 33, 34, + 34, 34, 35, 35, 36, 36, 36, 36, + 37, 37, 37, 38 + }, + + { + 1, 1, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, + 14, 15, 15, 16, 16, 17, 17, 18, + 16, 16, 16, 17, 18, 19, 20, 21, + 23, 24, 26, 28, 30, 31, 32, 33, + 34, 34, 35, 35, 36, 36, 36, 36, + 37, 37, 37, 38 + }, +}; + +static RK_U8 intra_pqp1[52] = { + 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, + 51, 51, 51, 51 +}; + +static RK_S32 cal_smt_first_i_start_qp(RK_S32 target_bit, RK_U32 total_mb) +{ + RK_S32 cnt = 0; + RK_S32 index; + RK_S32 i; + + for (i = 0; i < 8; i++) { + if (mb_num[i] > total_mb) + break; + cnt++; + } + + index = (total_mb * tab_bit[cnt] - 350) / target_bit; // qscale + index = mpp_clip(index, 4, 95); + + return qscale2qp[index]; +} + +static MPP_RET calc_smt_debreath_qp(RcModelV2SmtCtx * ctx) +{ + RK_S32 fm_qp_sum = 0; + RK_S32 new_fm_qp = 0; + RcDebreathCfg *debreath_cfg = &ctx->usr_cfg.debreath_cfg; + RK_S32 dealt_qp = 0; + RK_S32 gop_qp_sum = ctx->gop_qp_sum; + RK_S32 gop_frm_cnt = ctx->gop_frm_cnt; + static RK_S8 intra_qp_map[8] = { + 0, 0, 1, 1, 2, 2, 2, 2, + }; + RK_U8 idx2 = MPP_MIN(ctx->pre_iblk4_prop >> 5, (RK_S32)sizeof(intra_qp_map) - 1); + + static RK_S8 strength_map[36] = { + 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, + 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, + 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12 + }; + + rc_dbg_func("enter %p\n", ctx); + + fm_qp_sum = MPP_MIN(gop_qp_sum / gop_frm_cnt, (RK_S32)sizeof(strength_map) - 1); + + rc_dbg_qp("i qp_out %d, qp_start_sum = %d, intra_lv4_prop %d", + ctx->qp_out, fm_qp_sum, ctx->pre_iblk4_prop); + + dealt_qp = strength_map[debreath_cfg->strength] - intra_qp_map[idx2]; + if (fm_qp_sum > dealt_qp) + new_fm_qp = fm_qp_sum - dealt_qp; + else + new_fm_qp = fm_qp_sum; + + ctx->qp_out = mpp_clip(new_fm_qp, ctx->usr_cfg.min_i_quality, ctx->usr_cfg.max_i_quality); + ctx->gop_frm_cnt = 0; + ctx->gop_qp_sum = 0; + rc_dbg_func("leave %p\n", ctx); + return MPP_OK; +} + +static MPP_RET smt_start_prepare(void *ctx, EncRcTask *task) +{ + EncFrmStatus *frm = &task->frm; + RcModelV2SmtCtx *p = (RcModelV2SmtCtx *) ctx; + EncRcTaskInfo *info = &task->info; + RcFpsCfg *fps = &p->usr_cfg.fps; + RK_S32 fps_out = fps->fps_out_num / fps->fps_out_denom; + RK_S32 b_min = p->usr_cfg.bps_min; + RK_S32 b_max = p->usr_cfg.bps_max; + RK_S32 bits_lower, bits_upper; + + p->frame_type = frm->is_intra ? INTRA_FRAME : INTER_P_FRAME; + if (frm->ref_mode == REF_TO_PREV_INTRA) + p->frame_type = INTER_VI_FRAME; + + switch (p->gop_mode) { + case MPP_GOP_ALL_INTER: { + if (p->frame_type == INTRA_FRAME) { + bits_lower = p->bits_per_lower_i; + bits_upper = p->bits_per_upper_i; + } else { + bits_lower = p->bits_per_lower_p - mpp_data_mean_v2(p->pid_lower_p); + bits_upper = p->bits_per_upper_p - mpp_data_mean_v2(p->pid_upper_p); + } + } break; + case MPP_GOP_ALL_INTRA: { + bits_lower = p->bits_per_lower_i - mpp_pid_calc(&p->pid_lower_i); + bits_upper = p->bits_per_upper_i - mpp_pid_calc(&p->pid_upper_i); + } break; + default: { + if (p->frame_type == INTRA_FRAME) { + RK_S32 diff_bit = mpp_pid_calc(&p->pid_fps); + + p->pre_gop_left_bit = p->pid_fps.i - diff_bit; + mpp_pid_reset(&p->pid_fps); + if (p->acc_intra_count) { + bits_lower = (p->bits_per_lower_i + diff_bit); + bits_upper = (p->bits_per_upper_i + diff_bit); + } else { + bits_lower = p->bits_per_lower_i - mpp_pid_calc(&p->pid_lower_i); + bits_upper = p->bits_per_upper_i - mpp_pid_calc(&p->pid_upper_i); + } + } else { + if (p->last_frame_type == INTRA_FRAME) { + RK_S32 bits_prev_i = p->pre_real_bit_i; + + bits_lower = p->bits_per_lower_p + = (b_min * p->igop / fps_out - bits_prev_i + + p->pre_gop_left_bit) / (p->igop - 1); + + bits_upper = p->bits_per_upper_p + = (b_max * p->igop / fps_out - bits_prev_i + + p->pre_gop_left_bit) / (p->igop - 1); + + } else { + RK_S32 diff_bit_lr = mpp_data_mean_v2(p->pid_lower_p); + RK_S32 diff_bit_hr = mpp_data_mean_v2(p->pid_upper_p); + RK_S32 lr = axb_div_c(b_min, fps->fps_out_denom, fps->fps_out_num); + RK_S32 hr = axb_div_c(b_max, fps->fps_out_denom, fps->fps_out_num); + + bits_lower = p->bits_per_lower_p - diff_bit_lr; + if (bits_lower > 2 * lr) + bits_lower = 2 * lr; + + bits_upper = p->bits_per_upper_p - diff_bit_hr; + if (bits_upper > 2 * hr) + bits_upper = 2 * hr; + } + + } + } break; + } + + p->bits_tgt_lower = bits_lower; + p->bits_tgt_upper = bits_upper; + info->bit_max = (bits_lower + bits_upper) / 2; + if (info->bit_max < 100) + info->bit_max = 100; + + if (NULL == p->qp_p) { + RK_S32 nfps = fps_out < 15 ? 4 * fps_out : (fps_out < 25 ? 3 * fps_out : 2 * fps_out); + mpp_data_init(&p->qp_p, mpp_clip(MPP_MAX(p->igop, nfps), 20, 50)); + } + + rc_dbg_rc("bits_tgt_lower %d, bits_tgt_upper %d, bit_max %d, qp_out %d", + p->bits_tgt_lower, p->bits_tgt_upper, info->bit_max, p->qp_out); + + return MPP_OK; +} + +static RK_S32 smt_calc_coef(void *ctx) +{ + RcModelV2SmtCtx *p = (RcModelV2SmtCtx *) ctx; + RK_S32 coef = 1024; + RK_S32 coef2 = 512; + RK_S32 md_lvl_sum = mpp_data_sum_v2(p->motion_level); + RK_S32 md_lvl_0 = mpp_data_get_pre_val_v2(p->motion_level, 0); + RK_S32 md_lvl_1 = mpp_data_get_pre_val_v2(p->motion_level, 1); + + if (md_lvl_sum < 100) + set_coef(ctx, &coef, 0); + else if (md_lvl_sum < 200) { + if (md_lvl_0 < 100) + set_coef(ctx, &coef, 102); + else + set_coef(ctx, &coef, 154); + } else if (md_lvl_sum < 300) { + if (md_lvl_0 < 100) + set_coef(ctx, &coef, 154); + else if (md_lvl_0 == 100) { + if (md_lvl_1 < 100) + set_coef(ctx, &coef, 205); + else if (md_lvl_1 == 100) + set_coef(ctx, &coef, 256); + else + set_coef(ctx, &coef, 307); + } else + set_coef(ctx, &coef, 307); + } else if (md_lvl_sum < 600) { + if (md_lvl_0 < 100) { + if (md_lvl_1 < 100) + set_coef(ctx, &coef, 307); + else if (md_lvl_1 == 100) + set_coef(ctx, &coef, 358); + else + set_coef(ctx, &coef, 410); + } else if (md_lvl_0 == 100) { + if (md_lvl_1 < 100) + set_coef(ctx, &coef, 358); + else if (md_lvl_1 == 100) + set_coef(ctx, &coef, 410); + else + set_coef(ctx, &coef, 461); + } else + set_coef(ctx, &coef, 461); + } else if (md_lvl_sum < 900) { + if (md_lvl_0 < 100) { + if (md_lvl_1 < 100) + set_coef(ctx, &coef, 410); + else if (md_lvl_1 == 100) + set_coef(ctx, &coef, 461); + else + set_coef(ctx, &coef, 512); + } else if (md_lvl_0 == 100) { + if (md_lvl_1 < 100) + set_coef(ctx, &coef, 512); + else if (md_lvl_1 == 100) + set_coef(ctx, &coef, 563); + else + set_coef(ctx, &coef, 614); + } else + set_coef(ctx, &coef, 614); + } else if (md_lvl_sum < 1500) + set_coef(ctx, &coef, 666); + else if (md_lvl_sum < 1900) + set_coef(ctx, &coef, 768); + else + set_coef(ctx, &coef, 900); + + if (coef > 1024) + coef = 1024; + + if (coef >= 900) + coef2 = 1024; + else if (coef >= 307) // 0.7~0.3 --> 1.0~0.5 + coef2 = 512 + (coef - 307) * (1024 - 512) / (717 - 307); + else // 0.3~0.0 --> 0.5~0.0 + coef2 = 0 + coef * (512 - 0) / (307 - 0); + if (coef2 >= 1024) + coef2 = 1024; + + return coef2; +} + +MPP_RET rc_model_v2_smt_start(void *ctx, EncRcTask * task) +{ + RcModelV2SmtCtx *p = (RcModelV2SmtCtx *) ctx; EncFrmStatus *frm = &task->frm; EncRcTaskInfo *info = &task->info; RcFpsCfg *fps = &p->usr_cfg.fps; - RK_U32 md_ctu_cnt = 0; - void *ptr = NULL; + RK_S32 qp_add = 0, qp_add_p = 0, qp_minus = 0; + RK_S32 bit_target_use = 0; + RK_S32 avg_bps = (p->usr_cfg.bps_min + p->usr_cfg.bps_max) / 2; + RK_S32 fps_out = fps->fps_out_num / fps->fps_out_denom; + RK_S32 avg_pqp = 0; + RK_S32 prev_pqp = p->qp_prev_out; + RK_S32 fm_min_iqp = p->usr_cfg.fqp_min_i; + RK_S32 fm_min_pqp = p->usr_cfg.fqp_min_p; + RK_S32 fm_max_iqp = p->usr_cfg.fqp_max_i; + RK_S32 fm_max_pqp = p->usr_cfg.fqp_max_p; + RK_S32 md_lvl_sum = mpp_data_sum_v2(p->motion_level); + RK_S32 md_lvl_0 = mpp_data_get_pre_val_v2(p->motion_level, 0); + RK_S32 cplx_lvl_sum = mpp_data_sum_v2(p->complex_level); if (frm->reencode) return MPP_OK; - if (mpp_frame_has_meta(task->frame)) { - MppMeta meta = mpp_frame_get_meta(task->frame); - - mpp_meta_get_ptr(meta, KEY_MV_LIST, &ptr); - } - - md_ctu_cnt = cal_mv_info(ptr); - - if (frm->is_intra) { - p->frame_type = INTRA_FRAME; - p->acc_total_count = 0; - p->acc_intra_bits_in_fps = 0; - } else { - p->frame_type = INTER_P_FRAME; - } - - switch (p->gop_mode) { - case MPP_GOP_ALL_INTER : { - if (p->frame_type == INTRA_FRAME) { - p->bits_target_low_rate = p->bits_per_intra_low_rate; - p->bits_target_high_rate = p->bits_per_intra_high_rate; - } else { - p->bits_target_low_rate = p->bits_per_inter_low_rate - - mpp_pid_calc(&p->pid_inter_low_rate); - p->bits_target_high_rate = p->bits_per_inter_high_rate - - mpp_pid_calc(&p->pid_inter_high_rate); - } - } break; - case MPP_GOP_ALL_INTRA : { - p->bits_target_low_rate = p->bits_per_intra_low_rate - - mpp_pid_calc(&p->pid_intra_low_rate); - p->bits_target_high_rate = p->bits_per_intra_high_rate - - mpp_pid_calc(&p->pid_intra_high_rate); - } break; - default : { - if (p->frame_type == INTRA_FRAME) { - //float intra_percent = 0.0; - RK_S32 diff_bit = mpp_pid_calc(&p->pid_fps); - /* only affected by last gop */ - p->pre_gop_left_bit = p->pid_fps.i - diff_bit; - - mpp_pid_reset(&p->pid_fps); - - if (p->acc_intra_count) { - p->bits_target_low_rate = (p->bits_per_intra_low_rate + diff_bit); - p->bits_target_high_rate = (p->bits_per_intra_high_rate + diff_bit); - } else { - p->bits_target_low_rate = p->bits_per_intra_low_rate - - mpp_pid_calc(&p->pid_intra_low_rate); - p->bits_target_high_rate = p->bits_per_intra_high_rate - - mpp_pid_calc(&p->pid_intra_high_rate); - } - } else { - if (p->last_frame_type == INTRA_FRAME) { - RK_S32 diff_bit = mpp_pid_calc(&p->pid_fps); - /* - * case - inter frame after intra frame - * update inter target bits with compensation of previous intra frame - */ - RK_S32 bits_prev_intra = mpp_data_avg(p->intra, 1, 1, 1); - - p->bits_per_inter_low_rate = (p->bps_target_low_rate * - (p->gop_min * 1.0 / fps->fps_out_num) - - bits_prev_intra + diff_bit + p->pre_gop_left_bit) / - (p->gop_min - 1); - p->bits_target_low_rate = p->bits_per_inter_low_rate; - p->bits_per_inter_high_rate = (p->bps_target_high_rate * - (p->gop_min * 1.0 / fps->fps_out_num) - - bits_prev_intra + diff_bit + p->pre_gop_left_bit) / - (p->gop_min - 1); - p->bits_target_high_rate = p->bits_per_inter_high_rate; - } else { - RK_S32 diff_bit_low_rate = mpp_pid_calc(&p->pid_inter_low_rate); - p->bits_target_low_rate = p->bits_per_inter_low_rate - diff_bit_low_rate; - if (p->bits_target_low_rate > p->bits_per_pic_low_rate * 2) { - p->bits_target_low_rate = 2 * p->bits_per_pic_low_rate; - p->pid_inter_low_rate.i = p->pid_inter_low_rate.i / 2; - } - RK_S32 diff_bit_high_rate = mpp_pid_calc(&p->pid_inter_high_rate); - p->bits_target_high_rate = p->bits_per_inter_high_rate - diff_bit_high_rate; - - if (p->bits_target_high_rate > p->bits_per_pic_high_rate * 2) { - p->bits_target_high_rate = 2 * p->bits_per_pic_high_rate; - p->pid_inter_high_rate.i = p->pid_inter_high_rate.i / 2; - } - } - - } - } break; - - } - - if (NULL == p->qp_p) - mpp_data_init(&p->qp_p, MPP_MIN(p->gop_min, 15)); - if (NULL == p->sse_p) - mpp_data_init(&p->sse_p, MPP_MIN(p->gop_min, 15)); - - RK_S32 madi = p->hal_cfg.madi; + smt_start_prepare(ctx, task); + bit_target_use = info->bit_max; + avg_pqp = mpp_data_avg(p->qp_p, -1, 1, 1); if (p->frm_num == 0) { - RK_S32 bits_target_use = 0; - bits_target_use = (p->bits_target_high_rate - p->bits_target_low_rate) * 1 * 0.5 - + p->bits_target_low_rate; - p->bits_target_use = bits_target_use; - bits_target_use = bits_target_use * ((1920 * 1080 * 1000) - / (p->usr_cfg.width * p->usr_cfg.height)) / 1000; - p->qp_out = 95 - 10.0 * log((float)(bits_target_use / 1000)); + RK_S32 mb_w = MPP_ALIGN(p->usr_cfg.width, 16) / 16; + RK_S32 mb_h = MPP_ALIGN(p->usr_cfg.height, 16) / 16; + RK_S32 ratio = mpp_clip(fps_out / 10 + 1, 1, 3); + RK_S32 qp_out_f0 = 0; + if (p->usr_cfg.init_quality < 0) { + qp_out_f0 = cal_smt_first_i_start_qp(p->bits_tgt_upper * ratio, mb_w * mb_h); + qp_out_f0 = (fm_min_iqp > 31) ? mpp_clip(qp_out_f0, fm_min_iqp, p->qp_max) : + mpp_clip(qp_out_f0, 31, p->qp_max); + } else + qp_out_f0 = p->usr_cfg.init_quality; - if (p->qp_out < 27) { - p->qp_out = 27; - } - p->qp_out = mpp_clip(p->qp_out, p->qp_min, p->qp_max); - p->qp_preavg = 0; + p->qp_out = qp_out_f0; + p->count_real_bit = 0; + p->count_pred_bit = 0; + p->count_frame = 0; + rc_dbg_rc("first frame init_quality %d bits_tgt_upper %d " + "mb_w %d mb_h %d ratio %d qp_out %d\n", + p->usr_cfg.init_quality, p->bits_tgt_upper, + mb_w, mb_h, ratio, p->qp_out); } + p->change_bit_flag = 0; if (p->frame_type == INTRA_FRAME) { if (p->frm_num > 0) { - p->qp_out = mpp_data_avg(p->qp_p, -1, 1, 1) - 3; - RK_S32 sse = mpp_data_avg(p->sse_p, 1, 1, 1) + 1; - RK_S32 bit_target_use = (p->bits_target_low_rate + p->bits_target_high_rate) / 2; - RK_S32 qp_add = 0; + RK_S32 avg_qp = mpp_clip(avg_pqp, p->qp_min, p->qp_max); + RK_S32 prev_iqp = p->pre_qp_i; + RK_S32 pre_bits_i = p->pre_real_bit_i; + RK_S32 qp_out_i = 0; - if (bit_target_use < 100) - bit_target_use = 100; - - if (sse < p->intra_presse) { - if (bit_target_use <= p->intra_prerealbit) { - p->qp_out = p->intra_preqp; - } else { - if (madi >= MAD_THDI) { - p->qp_out = p->intra_preqp - 1; - } else { - if (p->intra_preqp - p->qp_out >= 4) { - p->qp_out = p->intra_preqp - (madi <= 12 ? 4 : 3); - } - } - } - } else if (sse > p->intra_presse && p->qp_out < p->intra_preqp) { - if (p->intra_preqp - p->qp_out >= 3) - p->qp_out = p->intra_preqp - 2; + if (bit_target_use <= pre_bits_i) { + qp_out_i = (bit_target_use * 5 < pre_bits_i) ? prev_iqp + 3 : + (bit_target_use * 2 < pre_bits_i) ? prev_iqp + 2 : + (bit_target_use * 3 < pre_bits_i * 2) ? prev_iqp + 1 : prev_iqp; } else { - RK_S32 ratio = (RK_S32)((float)sse / (float)p->intra_presse + 0.5); - if (ratio <= 2) { - p->qp_out = p->intra_preqp; - } else if (ratio <= 4) { - p->qp_out = mpp_clip(p->qp_out, p->intra_preqp - 1, p->intra_preqp + 1); - } else { - p->qp_out = mpp_clip(p->qp_out, p->intra_preqp - 2, p->intra_preqp + 2); - } + qp_out_i = (pre_bits_i * 3 < bit_target_use) ? prev_iqp - 3 : + (pre_bits_i * 2 < bit_target_use) ? prev_iqp - 2 : + (pre_bits_i * 3 < bit_target_use * 2) ? prev_iqp - 1 : prev_iqp; } - if (p->qp_prev_out < 25) { - qp_add = 4; - } else if (p->qp_prev_out < 27) { - qp_add = 2; - } else if (p->qp_prev_out < 29) { - qp_add = 1; - } - p->qp_out = mpp_clip(p->qp_out, p->qp_prev_out - 4, p->qp_prev_out + qp_add); - p->bits_target_use = (p->bits_target_low_rate + p->bits_target_high_rate) / 2; - if (p->bits_target_use < 100) - p->bits_target_use = 100; + if (!p->reenc_cnt && p->usr_cfg.debreath_cfg.enable) + calc_smt_debreath_qp(p); + + qp_out_i = mpp_clip(qp_out_i, inter_pqp0[avg_qp], inter_pqp1[avg_qp]); + qp_out_i = mpp_clip(qp_out_i, inter_pqp0[prev_pqp], inter_pqp1[prev_pqp]); + if (qp_out_i > 27) + p->qp_out = mpp_clip(qp_out_i, intra_pqp0[0][prev_iqp], intra_pqp1[prev_iqp]); + else if (qp_out_i > 22) + p->qp_out = mpp_clip(qp_out_i, intra_pqp0[1][prev_iqp], intra_pqp1[prev_iqp]); + else + p->qp_out = mpp_clip(qp_out_i, intra_pqp0[2][prev_iqp], intra_pqp1[prev_iqp]); + + if (p->pre_gop_left_bit < 0) { + if (abs(p->pre_gop_left_bit) * 5 > avg_bps * (p->igop / fps_out)) + p->qp_out = mpp_clip(p->qp_out, 20, 51); + else if (abs(p->pre_gop_left_bit) * 20 > avg_bps * (p->igop / fps_out)) + p->qp_out = mpp_clip(p->qp_out, 15, 51); + } } } else { - p->bits_target_use = (p->bits_target_low_rate + p->bits_target_high_rate) / 2; - p->qp_out = p->qp_preavg; + if (p->last_frame_type == INTRA_FRAME) + p->qp_out = prev_pqp + (prev_pqp < 33 ? 3 : (prev_pqp < 35 ? 2 : 1)); + else { + RK_S32 bits_tgt_use = 0; + RK_S32 pre_diff_bit_use = 0; + RK_S32 coef = smt_calc_coef(ctx); + RK_S32 m_tbr = p->bits_tgt_upper - p->bits_tgt_lower; + RK_S32 m_dbr = p->pre_diff_bit_upper - p->pre_diff_bit_lower; + RK_S32 diff_bit = (p->pid_lower_all.i + p->pid_upper_all.i) >> 1; + RK_S32 qp_out = p->qp_out; - if (p->last_frame_type == INTRA_FRAME) { - RK_S32 qp_add = 0; - if (p->qp_prev_out < 25) { - qp_add = 2; - } else if (p->qp_prev_out < 29) { - qp_add = 1; - } - p->qp_out = mpp_clip(p->qp_out, p->qp_prev_out + qp_add, p->qp_prev_out + 4 + qp_add); - p->bits_target_use = (p->bits_target_low_rate + p->bits_target_high_rate) / 2; - if (p->bits_target_use < 100) - p->bits_target_use = 100; - } else { - MppFrame frame = task->frame; - RK_S32 width = mpp_frame_get_width(frame); - RK_S32 height = mpp_frame_get_height(frame); - float coef = (float)md_ctu_cnt / (MPP_ALIGN(width, 16) / 16 * MPP_ALIGN(height, 16) / 16); - float coef2 = 0.5; + bits_tgt_use = (m_tbr * coef + p->bits_tgt_lower * 1024) >> 10; + pre_diff_bit_use = (m_dbr * coef + p->pre_diff_bit_lower * 1024) >> 10; + if (bits_tgt_use < 100) + bits_tgt_use = 100; - if (coef >= 0.7) - coef2 = 1.0; - else if (coef >= 0.3) // 0.7~0.3 --> 1.0~0.5 - coef2 = 0.5 + (coef - 0.3) * (1.0 - 0.5) / (0.7 - 0.3); - else // 0.3~0.0 --> 0.5~0.0 - coef2 = 0.0 + coef * (0.5 - 0.0) / (0.3 - 0.0); - - RK_S32 bits_target_use = p->bits_target_low_rate; // bits_target_high_rate - RK_S32 pre_diff_bit_use = p->pre_diff_bit_low_rate; // pre_diff_bit_high_rate - - bits_target_use = (p->bits_target_high_rate - p->bits_target_low_rate) * 1 * coef2 - + p->bits_target_low_rate; - pre_diff_bit_use = (p->pre_diff_bit_high_rate - p->pre_diff_bit_low_rate) * 1 * coef2 - + p->pre_diff_bit_low_rate; - - if (bits_target_use < 100) - bits_target_use = 100; - - p->bits_target_use = bits_target_use; - if (abs(pre_diff_bit_use) <= bits_target_use * 3 / 100) { - p->qp_out = p->qp_prev_out - 1; - } else if (pre_diff_bit_use > bits_target_use * 3 / 100) { - if (pre_diff_bit_use >= bits_target_use) { - p->qp_out = (p->qp_out >= 30 && madi < MAD_THDI) ? p->qp_prev_out - 4 : p->qp_prev_out - 3; - } else if (pre_diff_bit_use >= bits_target_use * 1 / 4) { - p->qp_out = (p->qp_out >= 30 && madi < MAD_THDI) ? p->qp_prev_out - 3 : p->qp_prev_out - 2; - } else if (pre_diff_bit_use > bits_target_use * 1 / 10) { - p->qp_out = (madi < MAD_THDI) ? p->qp_prev_out - 2 : p->qp_prev_out - 1; - } else { - p->qp_out = p->qp_prev_out - 1; - } + if (abs(pre_diff_bit_use) * 100 <= bits_tgt_use * 3) + qp_out = prev_pqp - 1; + else if (pre_diff_bit_use * 100 > bits_tgt_use * 3) { + if (pre_diff_bit_use >= bits_tgt_use) + qp_out = qp_out >= 30 ? prev_pqp - 4 : prev_pqp - 3; + else if (pre_diff_bit_use * 4 >= bits_tgt_use * 1) + qp_out = qp_out >= 30 ? prev_pqp - 3 : prev_pqp - 2; + else if (pre_diff_bit_use * 10 > bits_tgt_use * 1) + qp_out = prev_pqp - 2; + else + qp_out = prev_pqp - 1; } else { + RK_S32 qp_add_tmp = 1; + if (prev_pqp >= 36) + qp_add_tmp = 0; pre_diff_bit_use = abs(pre_diff_bit_use); - RK_S32 weight = (madi < MAD_THDI ? 1 : 3); - if (pre_diff_bit_use >= 2 * weight * bits_target_use) { - p->qp_out = p->qp_prev_out + 3 ; - } else if (pre_diff_bit_use >= bits_target_use * 2 * weight / 3) { - p->qp_out = p->qp_prev_out + 2 ; - } else if (pre_diff_bit_use > bits_target_use * weight / 5) { - p->qp_out = p->qp_prev_out + 1; - } else { - p->qp_out = p->qp_prev_out; - } + qp_out = (pre_diff_bit_use >= 2 * bits_tgt_use) ? prev_pqp + 2 + qp_add_tmp : + (pre_diff_bit_use * 3 >= bits_tgt_use * 2) ? prev_pqp + 1 + qp_add_tmp : + (pre_diff_bit_use * 5 > bits_tgt_use) ? prev_pqp + 1 : prev_pqp; } - p->qp_out = mpp_clip(p->qp_out, p->qp_min, p->qp_max); + qp_out = mpp_clip(qp_out, p->qp_min, p->qp_max); + pre_diff_bit_use = (m_dbr * coef + p->pre_diff_bit_lower * 1024) >> 10; + bits_tgt_use = avg_bps / fps_out; + bits_tgt_use = -bits_tgt_use / 5; + if (qp_out > LOW_QP) { + coef += pre_diff_bit_use <= 2 * bits_tgt_use ? 205 : + ((pre_diff_bit_use <= bits_tgt_use) ? 102 : 51); + if (coef >= 1024 || qp_out > LOW_LOW_QP) + coef = 1024; + pre_diff_bit_use = (m_dbr * coef + p->pre_diff_bit_lower * 1024) >> 10; + bits_tgt_use = (m_tbr * coef + p->bits_tgt_lower * 1024) >> 10; + if (bits_tgt_use < 100) + bits_tgt_use = 100; - pre_diff_bit_use = (p->pre_diff_bit_high_rate - p->pre_diff_bit_low_rate) * 1 * coef2 + p->pre_diff_bit_low_rate; - RK_S32 low_pre_diff_bit_use = LOW_PRE_DIFF_BIT_USE; - low_pre_diff_bit_use = (p->bps_target_low_rate + p->bps_target_high_rate) / 2 / fps->fps_out_num; - low_pre_diff_bit_use = -low_pre_diff_bit_use / 5; - - RK_S32 frame_low_qp; - - if (p->codec_type == 1) { - if (madi >= MAD_THDI) - frame_low_qp = LOW_QP_level1; - else - frame_low_qp = LOW_QP_level0; - } else { - frame_low_qp = LOW_QP; - } - - if (p->qp_out > frame_low_qp) { - if (pre_diff_bit_use <= 2 * low_pre_diff_bit_use) - coef2 += 0.5; - else if (pre_diff_bit_use <= low_pre_diff_bit_use) - coef2 += 0.2; - else - coef2 += 0.1; - - if (coef2 >= 1.0) - coef2 = 1.0; - - if (p->qp_out > LOW_LOW_QP) - coef2 = 1.0; - - if (coef2 == 1.0 && p->qp_prev_out > frame_low_qp) { - float delta_coef = 0; - if (p->bits_one_gop_use_flag == 1 && p->delta_bits_per_frame > 0) { - delta_coef = ((float)p->delta_bits_per_frame) / ((float)p->bits_per_inter_high_rate - p->bits_per_inter_low_rate); - - if (delta_coef >= 0.5) - delta_coef = 0.5; - else if (delta_coef >= 0.3) - delta_coef = 0.3; - - if (p->qp_prev_out > (frame_low_qp + 1)) - delta_coef += 0.1; - - coef2 += delta_coef; - } - } - - bits_target_use = (p->bits_target_high_rate - p->bits_target_low_rate) * 1 * coef2 + p->bits_target_low_rate; - pre_diff_bit_use = (p->pre_diff_bit_high_rate - p->pre_diff_bit_low_rate) * 1 * coef2 + p->pre_diff_bit_low_rate; - if (bits_target_use < 100) - bits_target_use = 100; - - p->bits_target_use = bits_target_use; - if (abs(pre_diff_bit_use) <= bits_target_use * 3 / 100) { - p->qp_out = p->qp_prev_out ; - } else if (pre_diff_bit_use > bits_target_use * 3 / 100) { - if (pre_diff_bit_use >= bits_target_use) { - p->qp_out = (p->qp_out >= 30 && madi < MAD_THDI) ? p->qp_prev_out - 3 : p->qp_prev_out - 2; - } else if (pre_diff_bit_use >= bits_target_use * 1 / 4) { - p->qp_out = (p->qp_out >= 30 && madi < MAD_THDI) ? p->qp_prev_out - 2 : p->qp_prev_out - 1; - } else if (pre_diff_bit_use > bits_target_use * 1 / 10) { - p->qp_out = (madi < MAD_THDI) ? p->qp_prev_out - 1 : p->qp_prev_out; - } else { - p->qp_out = p->qp_prev_out; - } + if (abs(pre_diff_bit_use) * 100 <= bits_tgt_use * 3) + qp_out = prev_pqp; + else if (pre_diff_bit_use * 100 > bits_tgt_use * 3) { + if (pre_diff_bit_use >= bits_tgt_use) + qp_out = qp_out >= 30 ? prev_pqp - 3 : prev_pqp - 2; + else if (pre_diff_bit_use * 4 >= bits_tgt_use * 1) + qp_out = qp_out >= 30 ? prev_pqp - 2 : prev_pqp - 1; + else if (pre_diff_bit_use * 10 > bits_tgt_use * 1) + qp_out = prev_pqp - 1; + else + qp_out = prev_pqp; } else { pre_diff_bit_use = abs(pre_diff_bit_use); - RK_S32 weight = (madi < MAD_THDI ? 0 : 2); - if (pre_diff_bit_use >= 2 * weight * bits_target_use) { - p->qp_out = p->qp_prev_out + 1 ; - } else if (pre_diff_bit_use >= bits_target_use * 2 * weight / 3) { - p->qp_out = p->qp_prev_out + 1 ; - } else if (pre_diff_bit_use > bits_target_use * weight / 5) { - p->qp_out = p->qp_prev_out; - } else { - p->qp_out = p->qp_prev_out; - } + qp_out = prev_pqp + (pre_diff_bit_use * 3 >= bits_tgt_use * 2 ? 1 : 0); } - - p->qp_out = mpp_clip(p->qp_out, p->qp_min, p->qp_max); } + qp_out = mpp_clip(qp_out, p->qp_min, p->qp_max); + //TODO: Add rc_container(20240516) + // if (p->usr_cfg.rc_container) { + // RK_S32 cnt = p->usr_cfg.scene_mode * 3 + p->usr_cfg.rc_container; + // if (p->count_real_bit < p->count_pred_bit * rc_ctnr_br_thd1[cnt] / 100) { + // if (qp_out > rc_ctnr_qp_thd1[cnt]) { + // p->change_bit_flag = 1; + // } - if (p->qp_out < LIMIT_QP_MORE_MOVE && coef >= 0.2) - p->qp_out = LIMIT_QP_MORE_MOVE; + // qp_out = mpp_clip(qp_out, 10, rc_ctnr_qp_thd1[cnt]); + // } else if (p->count_real_bit < p->count_pred_bit * rc_ctnr_br_thd2[cnt] / 100) { + // if (qp_out > rc_ctnr_qp_thd2[cnt]) { + // p->change_bit_flag = 1; + // } + // qp_out = mpp_clip(qp_out, 10, rc_ctnr_qp_thd2[cnt]); + // } + // } + + qp_add = qp_out > 36 ? 1 : (qp_out > 33 ? 2 : (qp_out > 30 ? 3 : 4)); + qp_minus = qp_out > 40 ? 4 : (qp_out > 36 ? 3 : (qp_out > 33 ? 2 : 1)); + p->qp_out = mpp_clip(qp_out, prev_pqp - qp_minus, prev_pqp + qp_add); + if (diff_bit > 0) { + if (avg_bps * 5 > avg_bps) + p->qp_out = mpp_clip(p->qp_out, 25, 51); + else if (avg_bps * 20 > avg_bps) + p->qp_out = mpp_clip(p->qp_out, 21, 51); + } } } - if (p->frm_num >= 1) { - p->qp_out = mpp_clip(p->qp_out, p->qp_prev_out - 3, p->qp_prev_out + p->qp_step); + qp_add = 4; + qp_add_p = 4; + if (md_lvl_sum >= 700 || md_lvl_0 == 200) { + qp_add = 6; + qp_add_p = 5; + } else if (md_lvl_sum >= 400 || md_lvl_0 == 100) { + qp_add = 5; + qp_add_p = 4; + } + if (cplx_lvl_sum >= 12) { + qp_add++; + qp_add_p++; } - info->bit_target = p->bits_target_use; + if (p->frame_type == INTRA_FRAME) + p->qp_out = mpp_clip(p->qp_out, fm_min_iqp + qp_add, fm_max_iqp); + else if (p->frame_type == INTER_VI_FRAME) { + p->qp_out -= 1; + p->qp_out = mpp_clip(p->qp_out, fm_min_pqp + qp_add - 1, fm_max_pqp); + } else + p->qp_out = mpp_clip(p->qp_out, fm_min_pqp + qp_add_p, fm_max_pqp); + + p->qp_out = mpp_clip(p->qp_out, p->qp_min, p->qp_max); info->quality_target = p->qp_out; + + info->complex_scene = 0; + if (p->frame_type == INTER_P_FRAME && avg_pqp >= fm_max_pqp - 1 && + p->qp_out == fm_max_pqp && p->qp_prev_out == fm_max_pqp) + info->complex_scene = 1; + info->quality_max = p->usr_cfg.max_quality; info->quality_min = p->usr_cfg.min_quality; + + rc_dbg_rc("frame %lld quality [%d : %d : %d] complex_scene %d\n", + p->frm_num, info->quality_min, info->quality_target, + info->quality_max, info->complex_scene); + p->frm_num++; p->reenc_cnt = 0; rc_dbg_func("leave %p\n", ctx); return MPP_OK; } +MPP_RET check_super_frame_smt(RcModelV2SmtCtx *ctx, EncRcTaskInfo *cfg) +{ + MPP_RET ret = MPP_OK; + RK_S32 frame_type = ctx->frame_type; + RK_U32 bits_thr = 0; + RcCfg *usr_cfg = &ctx->usr_cfg; + + rc_dbg_func("enter %p\n", ctx); + if (usr_cfg->super_cfg.super_mode) { + bits_thr = usr_cfg->super_cfg.super_p_thd; + if (frame_type == INTRA_FRAME) + bits_thr = usr_cfg->super_cfg.super_i_thd; + + if ((RK_U32)cfg->bit_real >= bits_thr) { + if (usr_cfg->super_cfg.super_mode == MPP_ENC_RC_SUPER_FRM_DROP) { + rc_dbg_rc("super frame drop current frame"); + usr_cfg->drop_mode = MPP_ENC_RC_DROP_FRM_NORMAL; + usr_cfg->drop_gap = 0; + } + ret = MPP_NOK; + } + } + rc_dbg_func("leave %p\n", ctx); + return ret; +} + +MPP_RET check_re_enc_smt(RcModelV2SmtCtx *ctx, EncRcTaskInfo *cfg) +{ + RcCfg *usr_cfg = &ctx->usr_cfg; + RK_S32 frame_type = ctx->frame_type; + RK_S32 bit_thr = 0; + RK_S32 stat_time = usr_cfg->stats_time; + RK_S32 last_ins_bps = mpp_data_sum_v2(ctx->stat_bits) / stat_time; + RK_S32 ins_bps = (last_ins_bps * stat_time - mpp_data_get_pre_val_v2(ctx->stat_bits, -1) + + cfg->bit_real) / stat_time; + RK_S32 bps; + RK_S32 ret = MPP_OK; + + rc_dbg_func("enter %p\n", ctx); + rc_dbg_rc("reenc check target_bps %d last_ins_bps %d ins_bps %d", + usr_cfg->bps_target, last_ins_bps, ins_bps); + + if (ctx->reenc_cnt >= usr_cfg->max_reencode_times) + return MPP_OK; + + if (check_super_frame_smt(ctx, cfg)) + return MPP_NOK; + + if (usr_cfg->debreath_cfg.enable && !ctx->first_frm_flg) + return MPP_OK; + + rc_dbg_drop("drop mode %d frame_type %d\n", usr_cfg->drop_mode, frame_type); + if (usr_cfg->drop_mode && frame_type == INTER_P_FRAME) { + bit_thr = (RK_S32)(usr_cfg->bps_max * (100 + usr_cfg->drop_thd) / (float)100); + rc_dbg_drop("drop mode %d check max_bps %d bit_thr %d ins_bps %d", + usr_cfg->drop_mode, usr_cfg->bps_target, bit_thr, ins_bps); + return (ins_bps > bit_thr) ? MPP_NOK : MPP_OK; + } + + switch (frame_type) { + case INTRA_FRAME: + bit_thr = 3 * cfg->bit_max / 2; + break; + case INTER_P_FRAME: + bit_thr = 3 * cfg->bit_max; + break; + default: + break; + } + + if (cfg->bit_real > bit_thr) { + bps = usr_cfg->bps_max; + if ((bps - (bps >> 3) < ins_bps) && (bps / 20 < ins_bps - last_ins_bps)) + ret = MPP_NOK; + } + + rc_dbg_func("leave %p ret %d\n", ctx, ret); + return ret; +} + MPP_RET rc_model_v2_smt_check_reenc(void *ctx, EncRcTask *task) { RcModelV2SmtCtx *p = (RcModelV2SmtCtx *)ctx; @@ -998,79 +1027,97 @@ MPP_RET rc_model_v2_smt_check_reenc(void *ctx, EncRcTask *task) frm->reencode = 0; if ((usr_cfg->mode == RC_FIXQP) || - (task->force.force_flag & ENC_RC_FORCE_QP)) + (task->force.force_flag & ENC_RC_FORCE_QP) || + p->on_drop || p->on_pskip) return MPP_OK; if (check_re_enc_smt(p, cfg)) { - if (p->usr_cfg.mode == RC_CBR) { - reenc_calc_cbr_ratio_smt(p, cfg); - } else { - reenc_calc_vbr_ratio_smt(p, cfg); - } - if (p->next_ratio != 0 && cfg->quality_target < cfg->quality_max) { - p->reenc_cnt++; + MppEncRcDropFrmMode drop_mode = usr_cfg->drop_mode; + + if (frm->is_intra) + drop_mode = MPP_ENC_RC_DROP_FRM_DISABLED; + + if (usr_cfg->drop_gap && p->drop_cnt >= usr_cfg->drop_gap) + drop_mode = MPP_ENC_RC_DROP_FRM_DISABLED; + + rc_dbg_drop("reenc drop_mode %d drop_cnt %d\n", drop_mode, p->drop_cnt); + + switch (drop_mode) { + case MPP_ENC_RC_DROP_FRM_NORMAL : { + frm->drop = 1; frm->reencode = 1; + p->on_drop = 1; + p->drop_cnt++; + rc_dbg_drop("drop\n"); + } break; + case MPP_ENC_RC_DROP_FRM_PSKIP : { + frm->force_pskip = 1; + frm->reencode = 1; + p->on_pskip = 1; + p->drop_cnt++; + rc_dbg_drop("force_pskip\n"); + } break; + case MPP_ENC_RC_DROP_FRM_DISABLED : + default : { + RK_S32 bits_thr = usr_cfg->super_cfg.super_p_thd; + if (p->frame_type == INTRA_FRAME) + bits_thr = usr_cfg->super_cfg.super_i_thd; + + if (cfg->bit_real > bits_thr * 2) + cfg->quality_target += 3; + else if (cfg->bit_real > bits_thr * 3 / 2) + cfg->quality_target += 2; + else if (cfg->bit_real > bits_thr) + cfg->quality_target ++; + + if (cfg->quality_target < cfg->quality_max) { + p->reenc_cnt++; + frm->reencode = 1; + } + p->drop_cnt = 0; + } break; } } - rc_dbg_func("leave %p\n", ctx); + return MPP_OK; } -MPP_RET rc_model_v2_smt_end(void *ctx, EncRcTask *task) +MPP_RET rc_model_v2_smt_end(void *ctx, EncRcTask * task) { - RcModelV2SmtCtx *p = (RcModelV2SmtCtx *)ctx; - EncRcTaskInfo *cfg = (EncRcTaskInfo *)&task->info; - MppFrame frame = task->frame; - RK_S32 width = mpp_frame_get_width(frame); - RK_S32 height = mpp_frame_get_height(frame); + RcModelV2SmtCtx *p = (RcModelV2SmtCtx *) ctx; + EncRcTaskInfo *cfg = (EncRcTaskInfo *) & task->info; RK_S32 bit_real = cfg->bit_real; - RK_S32 madi = cfg->madi; - RK_S32 cu64_num = (MPP_ALIGN(width, 64) / 64 * MPP_ALIGN(height, 64) / 64) ; - RK_U64 sse_dat = cfg->madp * cu64_num; - RK_U32 qp_sum; - double avg_qp = 0.0; - RK_S32 avg_sse = 1; rc_dbg_func("enter ctx %p cfg %p\n", ctx, cfg); + rc_dbg_rc("motion_level %u, complex_level %u\n", cfg->motion_level, cfg->complex_level); - if (p->codec_type == 1) - qp_sum = cfg->quality_real / 64; // 265 - else - qp_sum = cfg->quality_real / 16; // 264 + mpp_data_update_v2(p->rt_bits, bit_real); + cfg->rt_bits = mpp_data_sum_v2(p->rt_bits); + rc_dbg_rc("frame %lld real_bit %d real time bits %d\n", + p->frm_num - 1, bit_real, cfg->rt_bits); - avg_qp = qp_sum; - avg_sse = (RK_S32)sqrt((double)(sse_dat)); - p->qp_preavg = (RK_S32)(avg_qp + 0.5); - if (p->frame_type == INTER_P_FRAME) { - if (madi >= MAD_THDI) { - avg_qp = p->qp_out; - } + mpp_data_update_v2(p->motion_level, cfg->motion_level); + mpp_data_update_v2(p->complex_level, cfg->complex_level); + p->first_frm_flg = 0; + + if (p->frame_type == INTER_P_FRAME || p->gop_mode == MPP_GOP_ALL_INTRA) + mpp_data_update(p->qp_p, p->qp_out); + else { + p->pre_qp_i = p->qp_out; + p->pre_real_bit_i = bit_real; } - if (p->frame_type == INTER_P_FRAME || p->gop_mode == MPP_GOP_ALL_INTRA) { - mpp_data_update(p->qp_p, avg_qp); - mpp_data_update(p->sse_p, avg_sse); - } else { - p->intra_preqp = p->qp_out; - p->intra_presse = avg_sse; - p->intra_premadi = madi; - p->intra_prerealbit = bit_real; - } - - p->st_madi = cfg->madi; - rc_dbg_rc("bits_mode_update real_bit %d", bit_real); bits_model_update_smt(p, bit_real); - p->pre_target_bits = cfg->bit_target; - p->pre_real_bits = bit_real; p->qp_prev_out = p->qp_out; - p->last_inst_bps = p->ins_bps; p->last_frame_type = p->frame_type; + p->pre_iblk4_prop = cfg->iblk4_prop; + p->gop_frm_cnt++; + p->gop_qp_sum += p->qp_out; rc_dbg_func("leave %p\n", ctx); return MPP_OK; } - MPP_RET rc_model_v2_smt_hal_start(void *ctx, EncRcTask *task) { rc_dbg_func("smt_hal_start enter ctx %p task %p\n", ctx, task); @@ -1084,7 +1131,6 @@ MPP_RET rc_model_v2_smt_hal_end(void *ctx, EncRcTask *task) return MPP_OK; } - const RcImplApi smt_h264e = { "smart", MPP_VIDEO_CodingAVC, diff --git a/mpp/hal/rkenc/common/vepu510_common.h b/mpp/hal/rkenc/common/vepu510_common.h index 3a76572b..6d3125ef 100644 --- a/mpp/hal/rkenc/common/vepu510_common.h +++ b/mpp/hal/rkenc/common/vepu510_common.h @@ -823,33 +823,33 @@ typedef struct Vepu510RcRoi_t { /* 0x00001054 reg1045 */ struct { - RK_U32 aq_stp_s0 : 5; - RK_U32 aq_stp_0t1 : 5; - RK_U32 aq_stp_1t2 : 5; - RK_U32 aq_stp_2t3 : 5; - RK_U32 aq_stp_3t4 : 5; - RK_U32 aq_stp_4t5 : 5; - RK_U32 reserved : 2; + RK_S32 aq_stp_s0 : 5; + RK_S32 aq_stp_0t1 : 5; + RK_S32 aq_stp_1t2 : 5; + RK_S32 aq_stp_2t3 : 5; + RK_S32 aq_stp_3t4 : 5; + RK_S32 aq_stp_4t5 : 5; + RK_S32 reserved : 2; } aq_stp0; /* 0x00001058 reg1046 */ struct { - RK_U32 aq_stp_5t6 : 5; - RK_U32 aq_stp_6t7 : 5; - RK_U32 aq_stp_7t8 : 5; - RK_U32 aq_stp_8t9 : 5; - RK_U32 aq_stp_9t10 : 5; - RK_U32 aq_stp_10t11 : 5; - RK_U32 reserved : 2; + RK_S32 aq_stp_5t6 : 5; + RK_S32 aq_stp_6t7 : 5; + RK_S32 aq_stp_7t8 : 5; + RK_S32 aq_stp_8t9 : 5; + RK_S32 aq_stp_9t10 : 5; + RK_S32 aq_stp_10t11 : 5; + RK_S32 reserved : 2; } aq_stp1; /* 0x0000105c reg1047 */ struct { - RK_U32 aq_stp_11t12 : 5; - RK_U32 aq_stp_12t13 : 5; - RK_U32 aq_stp_13t14 : 5; - RK_U32 aq_stp_14t15 : 5; - RK_U32 aq_stp_b15 : 5; + RK_S32 aq_stp_11t12 : 5; + RK_S32 aq_stp_12t13 : 5; + RK_S32 aq_stp_13t14 : 5; + RK_S32 aq_stp_14t15 : 5; + RK_S32 aq_stp_b15 : 5; RK_U32 reserved : 7; } aq_stp2; @@ -2174,6 +2174,23 @@ typedef struct Vepu510Dbg_t { RK_U32 jpeg_fcyc; } Vepu510Dbg; +/* ROI block configuration */ +typedef struct Vepu510H264RoiBlkCfg { + RK_U32 qp_adju : 8; + RK_U32 mdc_adju_inter : 4; + RK_U32 mdc_adju_skip : 4; + RK_U32 mdc_adju_intra : 4; + RK_U32 reserved : 12; +} Vepu510H264RoiBlkCfg; + +typedef struct Vepu510H265RoiBlkCfg { + RK_U32 qp_adju : 8; + RK_U32 reserved : 12; + RK_U32 mdc_adju_inter : 4; + RK_U32 mdc_adju_skip : 4; + RK_U32 mdc_adju_intra : 4; +} Vepu510H265RoiBlkCfg; + #ifdef __cplusplus extern "C" { #endif diff --git a/mpp/hal/rkenc/h264e/hal_h264e_vepu510.c b/mpp/hal/rkenc/h264e/hal_h264e_vepu510.c index 89378810..906a5ef6 100644 --- a/mpp/hal/rkenc/h264e/hal_h264e_vepu510.c +++ b/mpp/hal/rkenc/h264e/hal_h264e_vepu510.c @@ -402,7 +402,7 @@ static void setup_hal_bufs(HalH264eVepu510Ctx *ctx) (ctx->pixel_buf_size != pixel_buf_size) || (ctx->thumb_buf_size != thumb_buf_size) || (new_max_cnt > old_max_cnt)) { - size_t sizes[2]; + size_t sizes[3]; hal_h264e_dbg_detail("frame size %d -> %d max count %d -> %d\n", ctx->pixel_buf_size, pixel_buf_size, @@ -412,9 +412,11 @@ static void setup_hal_bufs(HalH264eVepu510Ctx *ctx) sizes[0] = pixel_buf_size; /* thumb buffer */ sizes[1] = thumb_buf_size; + /* smear buffer */ + sizes[2] = MPP_ALIGN(aligned_w / 64, 16) * MPP_ALIGN(aligned_h / 16, 16); new_max_cnt = MPP_MAX(new_max_cnt, old_max_cnt); - hal_bufs_setup(ctx->hw_recn, new_max_cnt, 2, sizes); + hal_bufs_setup(ctx->hw_recn, new_max_cnt, MPP_ARRAY_ELEMS(sizes), sizes); ctx->pixel_buf_fbc_hdr_size = pixel_buf_fbc_hdr_size; ctx->pixel_buf_fbc_bdy_size = pixel_buf_fbc_bdy_size; @@ -1261,12 +1263,17 @@ static void setup_vepu510_rc_base(HalVepu510RegSet *regs, HalH264eVepu510Ctx *ct reg_frm->common.rc_cfg.aq_en = 1; reg_frm->common.rc_cfg.rc_ctu_num = mb_w; - reg_frm->common.rc_qp.rc_qp_range = (slice->slice_type == H264_I_SLICE) ? - hw->qp_delta_row_i : hw->qp_delta_row; reg_frm->common.rc_qp.rc_max_qp = qp_max; reg_frm->common.rc_qp.rc_min_qp = qp_min; reg_frm->common.rc_tgt.ctu_ebit = mb_target_bits_mul_16; + if (rc->rc_mode == MPP_ENC_RC_MODE_SMTRC) { + reg_frm->common.rc_qp.rc_qp_range = 0; + } else { + reg_frm->common.rc_qp.rc_qp_range = (slice->slice_type == H264_I_SLICE) ? + hw->qp_delta_row_i : hw->qp_delta_row; + } + { /* fixed frame level QP */ RK_S32 fqp_min, fqp_max; @@ -1544,6 +1551,7 @@ static void setup_vepu510_recn_refr(HalH264eVepu510Ctx *ctx, HalVepu510RegSet *r if (curr && curr->cnt) { MppBuffer buf_pixel = curr->buf[0]; MppBuffer buf_thumb = curr->buf[1]; + MppBuffer buf_smear = curr->buf[2]; RK_S32 fd = mpp_buffer_get_fd(buf_pixel); mpp_assert(buf_pixel); @@ -1552,11 +1560,13 @@ static void setup_vepu510_recn_refr(HalH264eVepu510Ctx *ctx, HalVepu510RegSet *r reg_frm->common.rfpw_h_addr = fd; reg_frm->common.rfpw_b_addr = fd; reg_frm->common.dspw_addr = mpp_buffer_get_fd(buf_thumb); + reg_frm->common.adr_smear_wr = mpp_buffer_get_fd(buf_smear); } if (refr && refr->cnt) { MppBuffer buf_pixel = refr->buf[0]; MppBuffer buf_thumb = refr->buf[1]; + MppBuffer buf_smear = curr->buf[2]; RK_S32 fd = mpp_buffer_get_fd(buf_pixel); mpp_assert(buf_pixel); @@ -1565,6 +1575,7 @@ static void setup_vepu510_recn_refr(HalH264eVepu510Ctx *ctx, HalVepu510RegSet *r reg_frm->common.rfpr_h_addr = fd; reg_frm->common.rfpr_b_addr = fd; reg_frm->common.dspr_addr = mpp_buffer_get_fd(buf_thumb); + reg_frm->common.adr_smear_rd = mpp_buffer_get_fd(buf_smear); } mpp_dev_multi_offset_update(ctx->offsets, 164, fbc_hdr_size); mpp_dev_multi_offset_update(ctx->offsets, 166, fbc_hdr_size); diff --git a/mpp/hal/rkenc/h265e/hal_h265e_vepu510.c b/mpp/hal/rkenc/h265e/hal_h265e_vepu510.c index 38a6e04f..1624bb6c 100644 --- a/mpp/hal/rkenc/h265e/hal_h265e_vepu510.c +++ b/mpp/hal/rkenc/h265e/hal_h265e_vepu510.c @@ -84,10 +84,10 @@ typedef struct Vepu510H265eFrmCfg_t { Vepu541OsdCfg osd_cfg; void *roi_data; - /* gdr roi cfg */ - MppBuffer roi_base_cfg_buf; + /* roi buffer for qpmap or gdr */ + MppBuffer roir_buf; + RK_S32 roir_buf_size; void *roi_base_cfg_sw_buf; - RK_S32 roi_base_buf_size; /* variable length cfg */ MppDevRegOffCfgs *reg_cfg; @@ -110,7 +110,7 @@ typedef struct H265eV510HalContext_t { MppCbCtx *output_cb; /* @frame_cnt starts from ZERO */ - RK_U32 frame_count; + RK_S32 frame_count; /* frame parallel info */ RK_S32 task_cnt; @@ -128,8 +128,7 @@ typedef struct H265eV510HalContext_t { RK_S32 frame_type; RK_S32 last_frame_type; - /* @frame_cnt starts from ZERO */ - RK_U32 frame_cnt; + MppBufferGroup roi_grp; void *roi_data; MppEncCfgSet *cfg; MppDevRegOffCfgs *reg_cfg; @@ -164,19 +163,27 @@ typedef struct H265eV510HalContext_t { #include "hal_h265e_vepu510_tune.c" -static RK_U32 aq_thd_default[16] = { - 0, 0, 0, 0, - 3, 3, 5, 5, - 8, 8, 8, 15, - 15, 20, 25, 25 -}; +static RK_S32 atf_b32_skip_thd2[4] = {15, 15, 15, 200}; +static RK_S32 atf_b32_skip_thd3[4] = {72, 72, 72, 1000}; +static RK_S32 atf_b32_skip_wgt0[4] = {16, 20, 20, 16}; +static RK_S32 atf_b32_skip_wgt3[4] = {16, 16, 16, 17}; +static RK_S32 atf_b16_skip_thd2[4] = {15, 15, 15, 200}; +static RK_S32 atf_b16_skip_thd3[4] = {25, 25, 25, 1000}; +static RK_S32 atf_b16_skip_wgt0[4] = {16, 20, 20, 16}; +static RK_S32 atf_b16_skip_wgt3[4] = {16, 16, 16, 17}; +static RK_S32 atf_b32_intra_thd0[4] = {20, 20, 20, 24}; +static RK_S32 atf_b32_intra_thd1[4] = {40, 40, 40, 48}; +static RK_S32 atf_b32_intra_thd2[4] = {60, 72, 72, 96}; +static RK_S32 atf_b32_intra_wgt0[4] = {16, 22, 27, 28}; +static RK_S32 atf_b32_intra_wgt1[4] = {16, 20, 25, 26}; +static RK_S32 atf_b32_intra_wgt2[4] = {16, 18, 20, 24}; +static RK_S32 atf_b16_intra_thd0[4] = {20, 20, 20, 24}; +static RK_S32 atf_b16_intra_thd1[4] = {40, 40, 40, 48}; +static RK_S32 atf_b16_intra_thd2[4] = {60, 72, 72, 96}; +static RK_S32 atf_b16_intra_wgt0[4] = {16, 22, 27, 28}; +static RK_S32 atf_b16_intra_wgt1[4] = {16, 20, 25, 26}; +static RK_S32 atf_b16_intra_wgt2[4] = {16, 18, 20, 24}; -static RK_S32 aq_qp_dealt_default[16] = { - -8, -7, -6, -5, - -4, -3, -2, -1, - 0, 1, 2, 3, - 4, 5, 6, 8, -}; static RK_U32 rdo_lambda_table_I[60] = { 0x00000012, 0x00000017, @@ -321,7 +328,9 @@ static MPP_RET vepu510_h265_setup_hal_bufs(H265eV510HalContext *ctx) } if (frame_size > ctx->frame_size || new_max_cnt > old_max_cnt) { - size_t size[3] = {0}; + size_t size[4] = {0}; + RK_S32 ctu_w = (prep->width + 31) / 32; + RK_S32 ctu_h = (prep->height + 31) / 32; hal_bufs_deinit(ctx->dpb_bufs); hal_bufs_init(&ctx->dpb_bufs); @@ -330,12 +339,14 @@ static MPP_RET vepu510_h265_setup_hal_bufs(H265eV510HalContext *ctx) size[0] = ctx->fbc_header_len + ((mb_wd64 * mb_h64) << 12) * 3 / 2; //fbc_h + fbc_b size[1] = (mb_wd64 * mb_h64 << 8); size[2] = MPP_ALIGN(mb_wd64 * mb_h64 * 16 * 4, 256) * 16; + /* smear bufs */ + size[3] = MPP_ALIGN(ctu_w, 16) * MPP_ALIGN(ctu_h, 16); new_max_cnt = MPP_MAX(new_max_cnt, old_max_cnt); hal_h265e_dbg_detail("frame size %d -> %d max count %d -> %d\n", ctx->frame_size, frame_size, old_max_cnt, new_max_cnt); - hal_bufs_setup(ctx->dpb_bufs, new_max_cnt, 3, size); + hal_bufs_setup(ctx->dpb_bufs, new_max_cnt, MPP_ARRAY_ELEMS(size), size); ctx->frame_size = frame_size; ctx->max_buf_cnt = new_max_cnt; @@ -344,13 +355,220 @@ static MPP_RET vepu510_h265_setup_hal_bufs(H265eV510HalContext *ctx) return ret; } -static void vepu510_h265_rdo_cfg(H265eVepu510Sqi *reg, MppEncSceneMode sm) +static void vepu510_h265_set_atr_regs(H265eVepu510Sqi *reg_sqi, MppEncSceneMode sm, int atr_level) { - rdo_skip_par *p_rdo_skip = NULL; - rdo_noskip_par *p_rdo_noskip = NULL; - pre_cst_par *p_pre_cst = NULL; + // atr_level 0~3 + // 0 close + // 1 weak + // 2 medium + // 3 strong + H265eVepu510Sqi *reg = reg_sqi; + (void)sm; + if (atr_level == 0) { + reg->block_opt_cfg.block_en = 0; + reg->cmplx_opt_cfg.cmplx_en = 0; + reg->line_opt_cfg.line_en = 0; + } else { + reg->block_opt_cfg.block_en = 0; + reg->cmplx_opt_cfg.cmplx_en = 0; + reg->line_opt_cfg.line_en = 1; + } - reg->subj_opt_cfg.subj_opt_en = (sm == MPP_ENC_SCENE_MODE_IPC); + if (atr_level == 3) { + reg->block_opt_cfg.block_thre_cst_best_mad = 1000; + reg->block_opt_cfg.block_thre_cst_best_grdn_blk = 39; + reg->block_opt_cfg.thre_num_grdnt_point_cmplx = 3; + reg->block_opt_cfg.block_delta_qp_flag = 3; + + reg->cmplx_opt_cfg.cmplx_thre_cst_best_mad_dep0 = 4000; + reg->cmplx_opt_cfg.cmplx_thre_cst_best_mad_dep1 = 2000; + + reg->cmplx_bst_mad_thd.cmplx_thre_cst_best_mad_dep2 = 200; + reg->cmplx_bst_mad_thd.cmplx_thre_cst_best_grdn_blk_dep0 = 977; + + reg->cmplx_bst_grdn_thd.cmplx_thre_cst_best_grdn_blk_dep1 = 0; + reg->cmplx_bst_grdn_thd.cmplx_thre_cst_best_grdn_blk_dep2 = 488; + + reg->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep0 = 4; + reg->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep1 = 30;//20 + reg->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep2 = 30;//20 + reg->line_opt_cfg.line_thre_ratio_best_grdn_blk_dep0 = 7;//7 + reg->line_opt_cfg.line_thre_ratio_best_grdn_blk_dep1 = 6;//8 + + reg->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep0 = 1; + reg->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep1 = 50; + reg->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep2 = 50; + + reg->subj_opt_dqp0.line_thre_qp = 20; + reg->subj_opt_dqp0.block_strength = 4; + reg->subj_opt_dqp0.block_thre_qp = 30; + reg->subj_opt_dqp0.cmplx_strength = 4; + reg->subj_opt_dqp0.cmplx_thre_qp = 34; + reg->subj_opt_dqp0.cmplx_thre_max_grdn_blk = 32; + } else if (atr_level == 2) { + reg->block_opt_cfg.block_thre_cst_best_mad = 1000; + reg->block_opt_cfg.block_thre_cst_best_grdn_blk = 39; + reg->block_opt_cfg.thre_num_grdnt_point_cmplx = 3; + reg->block_opt_cfg.block_delta_qp_flag = 3; + + reg->cmplx_opt_cfg.cmplx_thre_cst_best_mad_dep0 = 4000; + reg->cmplx_opt_cfg.cmplx_thre_cst_best_mad_dep1 = 2000; + + reg->cmplx_bst_mad_thd.cmplx_thre_cst_best_mad_dep2 = 200; + reg->cmplx_bst_mad_thd.cmplx_thre_cst_best_grdn_blk_dep0 = 977; + + reg->cmplx_bst_grdn_thd.cmplx_thre_cst_best_grdn_blk_dep1 = 0; + reg->cmplx_bst_grdn_thd.cmplx_thre_cst_best_grdn_blk_dep2 = 488; + + reg->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep0 = 3; + reg->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep1 = 20; + reg->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep2 = 20; + reg->line_opt_cfg.line_thre_ratio_best_grdn_blk_dep0 = 7; + reg->line_opt_cfg.line_thre_ratio_best_grdn_blk_dep1 = 8; + + reg->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep0 = 1; + reg->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep1 = 60; + reg->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep2 = 60; + + reg->subj_opt_dqp0.line_thre_qp = 25; + reg->subj_opt_dqp0.block_strength = 4; + reg->subj_opt_dqp0.block_thre_qp = 30; + reg->subj_opt_dqp0.cmplx_strength = 4; + reg->subj_opt_dqp0.cmplx_thre_qp = 34; + reg->subj_opt_dqp0.cmplx_thre_max_grdn_blk = 32; + } else { + reg->block_opt_cfg.block_thre_cst_best_mad = 1000; + reg->block_opt_cfg.block_thre_cst_best_grdn_blk = 39; + reg->block_opt_cfg.thre_num_grdnt_point_cmplx = 3; + reg->block_opt_cfg.block_delta_qp_flag = 3; + + reg->cmplx_opt_cfg.cmplx_thre_cst_best_mad_dep0 = 6000; + reg->cmplx_opt_cfg.cmplx_thre_cst_best_mad_dep1 = 2000; + + reg->cmplx_bst_mad_thd.cmplx_thre_cst_best_mad_dep2 = 300; + reg->cmplx_bst_mad_thd.cmplx_thre_cst_best_grdn_blk_dep0 = 1280; + + reg->cmplx_bst_grdn_thd.cmplx_thre_cst_best_grdn_blk_dep1 = 0; + reg->cmplx_bst_grdn_thd.cmplx_thre_cst_best_grdn_blk_dep2 = 512; + + reg->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep0 = 3; + reg->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep1 = 20; + reg->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep2 = 20; + reg->line_opt_cfg.line_thre_ratio_best_grdn_blk_dep0 = 7; + reg->line_opt_cfg.line_thre_ratio_best_grdn_blk_dep1 = 8; + + reg->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep0 = 1; + reg->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep1 = 70; + reg->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep2 = 70; + + reg->subj_opt_dqp0.line_thre_qp = 30; + reg->subj_opt_dqp0.block_strength = 4; + reg->subj_opt_dqp0.block_thre_qp = 30; + reg->subj_opt_dqp0.cmplx_strength = 4; + reg->subj_opt_dqp0.cmplx_thre_qp = 34; + reg->subj_opt_dqp0.cmplx_thre_max_grdn_blk = 32; + } +} + +static void vepu510_h265_set_anti_blur_regs(H265eVepu510Sqi *reg_sqi, int anti_blur_en) +{ + H265eVepu510Sqi *reg = reg_sqi; + + reg->subj_anti_blur_thd.anti_blur_en = anti_blur_en; + reg->subj_anti_blur_thd.blur_low_madi_thd = 5; + reg->subj_anti_blur_thd.blur_high_madi_thd = 27; + reg->subj_anti_blur_thd.blur_low_cnt_thd = 0; + reg->subj_anti_blur_thd.blur_hight_cnt_thd = 0; + reg->subj_anti_blur_thd.blur_sum_cnt_thd = 5; + + reg->subj_anti_blur_sao.blur_motion_thd = 32; + reg->subj_anti_blur_sao.sao_ofst_thd_eo_luma = 2; + reg->subj_anti_blur_sao.sao_ofst_thd_bo_luma = 4; + reg->subj_anti_blur_sao.sao_ofst_thd_eo_chroma = 2; + reg->subj_anti_blur_sao.sao_ofst_thd_bo_chroma = 4; +} + +static void vepu510_h265_set_anti_stripe_regs(H265eVepu510Sqi *reg_sqi) +{ + pre_cst_par* pre_i32 = (pre_cst_par*)®_sqi->preintra32_cst; + pre_cst_par* pre_i16 = (pre_cst_par*)®_sqi->preintra16_cst; + + pre_i32->cst_madi_thd0.madi_thd0 = 5; + pre_i32->cst_madi_thd0.madi_thd1 = 15; + pre_i32->cst_madi_thd0.madi_thd2 = 5; + pre_i32->cst_madi_thd0.madi_thd3 = 3; + pre_i32->cst_madi_thd1.madi_thd4 = 3; + pre_i32->cst_madi_thd1.madi_thd5 = 6; + pre_i32->cst_madi_thd1.madi_thd6 = 7; + pre_i32->cst_madi_thd1.madi_thd7 = 5; + pre_i32->cst_madi_thd2.madi_thd8 = 10; + pre_i32->cst_madi_thd2.madi_thd9 = 5; + pre_i32->cst_madi_thd2.madi_thd10 = 7; + pre_i32->cst_madi_thd2.madi_thd11 = 5; + pre_i32->cst_madi_thd3.madi_thd12 = 7; + pre_i32->cst_madi_thd3.madi_thd13 = 5; + pre_i32->cst_madi_thd3.mode_th = 5; + + pre_i32->cst_wgt0.wgt0 = 20; + pre_i32->cst_wgt0.wgt1 = 18; + pre_i32->cst_wgt0.wgt2 = 19; + pre_i32->cst_wgt0.wgt3 = 18; + pre_i32->cst_wgt1.wgt4 = 12; + pre_i32->cst_wgt1.wgt5 = 6; + pre_i32->cst_wgt1.wgt6 = 13; + pre_i32->cst_wgt1.wgt7 = 9; + pre_i32->cst_wgt2.wgt8 = 12; + pre_i32->cst_wgt2.wgt9 = 6; + pre_i32->cst_wgt2.wgt10 = 13; + pre_i32->cst_wgt2.wgt11 = 9; + pre_i32->cst_wgt3.wgt12 = 18; + pre_i32->cst_wgt3.wgt13 = 17; + pre_i32->cst_wgt3.wgt14 = 17; + + pre_i16->cst_madi_thd0.madi_thd0 = 5; + pre_i16->cst_madi_thd0.madi_thd1 = 15; + pre_i16->cst_madi_thd0.madi_thd2 = 5; + pre_i16->cst_madi_thd0.madi_thd3 = 3; + pre_i16->cst_madi_thd1.madi_thd4 = 3; + pre_i16->cst_madi_thd1.madi_thd5 = 6; + pre_i16->cst_madi_thd1.madi_thd6 = 7; + pre_i16->cst_madi_thd1.madi_thd7 = 5; + pre_i16->cst_madi_thd2.madi_thd8 = 10; + pre_i16->cst_madi_thd2.madi_thd9 = 5; + pre_i16->cst_madi_thd2.madi_thd10 = 7; + pre_i16->cst_madi_thd2.madi_thd11 = 5; + pre_i16->cst_madi_thd3.madi_thd12 = 7; + pre_i16->cst_madi_thd3.madi_thd13 = 5; + pre_i16->cst_madi_thd3.mode_th = 5; + + pre_i16->cst_wgt0.wgt0 = 20; + pre_i16->cst_wgt0.wgt1 = 18; + pre_i16->cst_wgt0.wgt2 = 19; + pre_i16->cst_wgt0.wgt3 = 18; + pre_i16->cst_wgt1.wgt4 = 12; + pre_i16->cst_wgt1.wgt5 = 6; + pre_i16->cst_wgt1.wgt6 = 13; + pre_i16->cst_wgt1.wgt7 = 9; + pre_i16->cst_wgt2.wgt8 = 12; + pre_i16->cst_wgt2.wgt9 = 6; + pre_i16->cst_wgt2.wgt10 = 13; + pre_i16->cst_wgt2.wgt11 = 9; + pre_i16->cst_wgt3.wgt12 = 18; + pre_i16->cst_wgt3.wgt13 = 17; + pre_i16->cst_wgt3.wgt14 = 17; + + pre_i32->cst_madi_thd3.qp_thd = 28; + pre_i32->cst_wgt3.lambda_mv_bit_0 = 5; // lv32 + pre_i32->cst_wgt3.lambda_mv_bit_1 = 4; // lv16 + pre_i16->cst_wgt3.lambda_mv_bit_0 = 4; // lv8 + pre_i16->cst_wgt3.lambda_mv_bit_1 = 3; // lv4 + + pre_i32->cst_wgt3.anti_strp_e = 1; +} + +static void vepu510_h265_rdo_cfg(H265eV510HalContext *ctx, H265eVepu510Sqi *reg, MppEncSceneMode sm) +{ + reg->subj_opt_cfg.subj_opt_en = 1;//(sm == MPP_ENC_SCENE_MODE_IPC); reg->subj_opt_cfg.subj_opt_strength = 3; reg->subj_opt_cfg.aq_subj_en = (sm == MPP_ENC_SCENE_MODE_IPC); reg->subj_opt_cfg.aq_subj_strength = 4; @@ -433,167 +651,9 @@ static void vepu510_h265_rdo_cfg(H265eVepu510Sqi *reg, MppEncSceneMode sm) reg->subj_opt_dqp1.skin_thre_qp = 31; /* text_opt */ - reg->block_opt_cfg.block_en = (sm == MPP_ENC_SCENE_MODE_IPC); - reg->block_opt_cfg.block_thre_cst_best_mad = 1000; - reg->block_opt_cfg.block_thre_cst_best_grdn_blk = 39; - reg->block_opt_cfg.thre_num_grdnt_point_cmplx = 3; - reg->block_opt_cfg.block_delta_qp_flag = 3; - - reg->cmplx_opt_cfg.cmplx_thre_cst_best_mad_dep0 = 4000; - reg->cmplx_opt_cfg.cmplx_thre_cst_best_mad_dep1 = 2000; - reg->cmplx_opt_cfg.cmplx_en = (sm == MPP_ENC_SCENE_MODE_IPC); - reg->cmplx_bst_mad_thd.cmplx_thre_cst_best_mad_dep2 = 200; - reg->cmplx_bst_mad_thd.cmplx_thre_cst_best_grdn_blk_dep0 = 977; - - reg->cmplx_bst_grdn_thd.cmplx_thre_cst_best_grdn_blk_dep1 = 0; - reg->cmplx_bst_grdn_thd.cmplx_thre_cst_best_grdn_blk_dep2 = 488; - - reg->line_opt_cfg.line_en = (sm == MPP_ENC_SCENE_MODE_IPC); - reg->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep0 = 3; - reg->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep1 = 20; - reg->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep2 = 20; - reg->line_opt_cfg.line_thre_ratio_best_grdn_blk_dep0 = 8; - reg->line_opt_cfg.line_thre_ratio_best_grdn_blk_dep1 = 8; - - reg->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep0 = 1; - reg->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep1 = 78; - reg->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep2 = 78; - - reg->subj_opt_dqp0.line_thre_qp = 34; - reg->subj_opt_dqp0.block_strength = 4; - reg->subj_opt_dqp0.block_thre_qp = 30; - reg->subj_opt_dqp0.cmplx_strength = 4; - reg->subj_opt_dqp0.cmplx_thre_qp = 34; - reg->subj_opt_dqp0.cmplx_thre_max_grdn_blk = 32; reg->subj_opt_dqp1.bndry_rdo_cu_intra_r_coef_dep0 = 240; reg->subj_opt_dqp1.bndry_rdo_cu_intra_r_coef_dep1 = 224; - p_rdo_skip = ®->rdo_b32_skip; - p_rdo_skip->atf_thd0.madp_thd0 = 5 ; - p_rdo_skip->atf_thd0.madp_thd1 = 10 ; - p_rdo_skip->atf_thd1.madp_thd2 = 15 ; - p_rdo_skip->atf_thd1.madp_thd3 = 72 ; - p_rdo_skip->atf_wgt0.wgt0 = 20 ; - p_rdo_skip->atf_wgt0.wgt1 = 16 ; - p_rdo_skip->atf_wgt0.wgt2 = 16 ; - p_rdo_skip->atf_wgt0.wgt3 = 16 ; - - p_rdo_noskip = ®->rdo_b32_inter; - p_rdo_noskip->ratf_thd0.madp_thd0 = 20; - p_rdo_noskip->ratf_thd0.madp_thd1 = 40; - p_rdo_noskip->ratf_thd1.madp_thd2 = 72; - p_rdo_noskip->atf_wgt.wgt0 = 16; - p_rdo_noskip->atf_wgt.wgt1 = 16; - p_rdo_noskip->atf_wgt.wgt2 = 16; - - p_rdo_noskip = ®->rdo_b32_intra; - p_rdo_noskip->ratf_thd0.madp_thd0 = 20; - p_rdo_noskip->ratf_thd0.madp_thd1 = 40; - p_rdo_noskip->ratf_thd1.madp_thd2 = 72; - p_rdo_noskip->atf_wgt.wgt0 = 27; - p_rdo_noskip->atf_wgt.wgt1 = 25; - p_rdo_noskip->atf_wgt.wgt2 = 20; - - p_rdo_skip = ®->rdo_b16_skip; - p_rdo_skip->atf_thd0.madp_thd0 = 1 ; - p_rdo_skip->atf_thd0.madp_thd1 = 10 ; - p_rdo_skip->atf_thd1.madp_thd2 = 15 ; - p_rdo_skip->atf_thd1.madp_thd3 = 25 ; - p_rdo_skip->atf_wgt0.wgt0 = 20 ; - p_rdo_skip->atf_wgt0.wgt1 = 16 ; - p_rdo_skip->atf_wgt0.wgt2 = 16 ; - p_rdo_skip->atf_wgt0.wgt3 = 16 ; - p_rdo_skip->atf_wgt1.wgt4 = 16 ; - - p_rdo_noskip = ®->rdo_b16_inter; - p_rdo_noskip->ratf_thd0.madp_thd0 = 20; - p_rdo_noskip->ratf_thd0.madp_thd1 = 40; - p_rdo_noskip->ratf_thd1.madp_thd2 = 72; - p_rdo_noskip->atf_wgt.wgt0 = 16; - p_rdo_noskip->atf_wgt.wgt1 = 16; - p_rdo_noskip->atf_wgt.wgt2 = 16; - p_rdo_noskip->atf_wgt.wgt3 = 16; - - p_rdo_noskip = ®->rdo_b16_intra; - p_rdo_noskip->ratf_thd0.madp_thd0 = 20; - p_rdo_noskip->ratf_thd0.madp_thd1 = 40; - p_rdo_noskip->ratf_thd1.madp_thd2 = 72; - p_rdo_noskip->atf_wgt.wgt0 = 27; - p_rdo_noskip->atf_wgt.wgt1 = 25; - p_rdo_noskip->atf_wgt.wgt2 = 20; - p_rdo_noskip->atf_wgt.wgt3 = 16; - - p_pre_cst = ®->preintra32_cst; - p_pre_cst->cst_madi_thd0.madi_thd0 = 5; - p_pre_cst->cst_madi_thd0.madi_thd1 = 15; - p_pre_cst->cst_madi_thd0.madi_thd2 = 5; - p_pre_cst->cst_madi_thd0.madi_thd3 = 3; - p_pre_cst->cst_madi_thd1.madi_thd4 = 3; - p_pre_cst->cst_madi_thd1.madi_thd5 = 6; - p_pre_cst->cst_madi_thd1.madi_thd6 = 7; - p_pre_cst->cst_madi_thd1.madi_thd7 = 5; - p_pre_cst->cst_madi_thd2.madi_thd8 = 10; - p_pre_cst->cst_madi_thd2.madi_thd9 = 5; - p_pre_cst->cst_madi_thd2.madi_thd10 = 7; - p_pre_cst->cst_madi_thd2.madi_thd11 = 5; - p_pre_cst->cst_madi_thd3.madi_thd12 = 10; - p_pre_cst->cst_madi_thd3.madi_thd13 = 5; - - p_pre_cst->cst_wgt0.wgt0 = 20; - p_pre_cst->cst_wgt0.wgt1 = 18; - p_pre_cst->cst_wgt0.wgt2 = 19; - p_pre_cst->cst_wgt0.wgt3 = 18; - p_pre_cst->cst_wgt1.wgt4 = 12; - p_pre_cst->cst_wgt1.wgt5 = 6; - p_pre_cst->cst_wgt1.wgt6 = 13; - p_pre_cst->cst_wgt1.wgt7 = 9; - p_pre_cst->cst_wgt2.wgt8 = 12; - p_pre_cst->cst_wgt2.wgt9 = 6; - p_pre_cst->cst_wgt2.wgt10 = 13; - p_pre_cst->cst_wgt2.wgt11 = 9; - p_pre_cst->cst_wgt3.wgt12 = 18; - p_pre_cst->cst_wgt3.wgt13 = 17; - p_pre_cst->cst_wgt3.wgt14 = 17; - p_pre_cst->cst_wgt3.lambda_mv_bit_0 = 5; - p_pre_cst->cst_wgt3.lambda_mv_bit_1 = 4; - p_pre_cst->cst_wgt3.anti_strp_e = 0; - p_pre_cst->cst_madi_thd3.mode_th = 5; - p_pre_cst->cst_madi_thd3.qp_thd = 28; - - p_pre_cst = ®->preintra16_cst; - p_pre_cst->cst_madi_thd0.madi_thd0 = 5; - p_pre_cst->cst_madi_thd0.madi_thd1 = 15; - p_pre_cst->cst_madi_thd0.madi_thd2 = 5; - p_pre_cst->cst_madi_thd0.madi_thd3 = 3; - p_pre_cst->cst_madi_thd1.madi_thd4 = 3; - p_pre_cst->cst_madi_thd1.madi_thd5 = 6; - p_pre_cst->cst_madi_thd1.madi_thd6 = 5; - p_pre_cst->cst_madi_thd1.madi_thd7 = 5; - p_pre_cst->cst_madi_thd2.madi_thd8 = 7; - p_pre_cst->cst_madi_thd2.madi_thd9 = 5; - p_pre_cst->cst_madi_thd2.madi_thd10 = 5; - p_pre_cst->cst_madi_thd2.madi_thd11 = 5; - p_pre_cst->cst_madi_thd3.madi_thd12 = 7; - p_pre_cst->cst_madi_thd3.madi_thd13 = 5; - p_pre_cst->cst_wgt0.wgt0 = 20; - p_pre_cst->cst_wgt0.wgt1 = 18; - p_pre_cst->cst_wgt0.wgt2 = 19; - p_pre_cst->cst_wgt0.wgt3 = 18; - p_pre_cst->cst_wgt1.wgt4 = 12; - p_pre_cst->cst_wgt1.wgt5 = 6; - p_pre_cst->cst_wgt1.wgt6 = 13; - p_pre_cst->cst_wgt1.wgt7 = 9; - p_pre_cst->cst_wgt2.wgt8 = 12; - p_pre_cst->cst_wgt2.wgt9 = 6; - p_pre_cst->cst_wgt2.wgt10 = 13; - p_pre_cst->cst_wgt2.wgt11 = 9; - p_pre_cst->cst_wgt3.wgt12 = 18; - p_pre_cst->cst_wgt3.wgt13 = 17; - p_pre_cst->cst_wgt3.wgt14 = 17; - p_pre_cst->cst_wgt3.lambda_mv_bit_0 = 4; - p_pre_cst->cst_wgt3.lambda_mv_bit_1 = 3; - p_pre_cst->cst_madi_thd3.mode_th = 5; - /* 0x00002100 reg2112 */ reg->cudecis_thd0.base_thre_rough_mad32_intra = 9; reg->cudecis_thd0.delta0_thre_rough_mad32_intra = 10; @@ -705,37 +765,99 @@ static void vepu510_h265_rdo_cfg(H265eVepu510Sqi *reg, MppEncSceneMode sm) reg->cudecis_thd11.delta5_thre_mad_fme_ratio_inter = 4; reg->cudecis_thd11.delta6_thre_mad_fme_ratio_inter = 4; reg->cudecis_thd11.delta7_thre_mad_fme_ratio_inter = 4; + + vepu510_h265_set_anti_stripe_regs(reg); + if (ctx->frame_type == INTRA_FRAME) + vepu510_h265_set_atr_regs(reg, sm, 3); + else + vepu510_h265_set_atr_regs(reg, sm, 0); + + if (ctx->frame_type == INTRA_FRAME) + vepu510_h265_set_anti_blur_regs(reg, 0); + else + vepu510_h265_set_anti_blur_regs(reg, 1); +} + +static void vepu510_h265_atf_cfg(H265eVepu510Sqi *reg, RK_S32 atf_str) +{ + rdo_skip_par *p_rdo_skip = NULL; + rdo_noskip_par *p_rdo_noskip = NULL; + + p_rdo_skip = ®->rdo_b32_skip; + p_rdo_skip->atf_thd0.madp_thd0 = 5 ; + p_rdo_skip->atf_thd0.madp_thd1 = 10 ; + p_rdo_skip->atf_thd1.madp_thd2 = atf_b32_skip_thd2[atf_str]; + p_rdo_skip->atf_thd1.madp_thd3 = atf_b32_skip_thd3[atf_str]; + p_rdo_skip->atf_wgt0.wgt0 = atf_b32_skip_wgt0[atf_str]; + p_rdo_skip->atf_wgt0.wgt1 = 16 ; + p_rdo_skip->atf_wgt0.wgt2 = 16 ; + p_rdo_skip->atf_wgt0.wgt3 = atf_b32_skip_wgt3[atf_str]; + + p_rdo_noskip = ®->rdo_b32_inter; + p_rdo_noskip->ratf_thd0.madp_thd0 = 20; + p_rdo_noskip->ratf_thd0.madp_thd1 = 40; + p_rdo_noskip->ratf_thd1.madp_thd2 = 72; + p_rdo_noskip->atf_wgt.wgt0 = 16; + p_rdo_noskip->atf_wgt.wgt1 = 16; + p_rdo_noskip->atf_wgt.wgt2 = 16; + + p_rdo_noskip = ®->rdo_b32_intra; + p_rdo_noskip->ratf_thd0.madp_thd0 = atf_b32_intra_thd0[atf_str]; + p_rdo_noskip->ratf_thd0.madp_thd1 = atf_b32_intra_thd1[atf_str]; + p_rdo_noskip->ratf_thd1.madp_thd2 = atf_b32_intra_thd2[atf_str]; + p_rdo_noskip->atf_wgt.wgt0 = atf_b32_intra_wgt0[atf_str]; + p_rdo_noskip->atf_wgt.wgt1 = atf_b32_intra_wgt1[atf_str]; + p_rdo_noskip->atf_wgt.wgt2 = atf_b32_intra_wgt2[atf_str]; + + p_rdo_skip = ®->rdo_b16_skip; + p_rdo_skip->atf_thd0.madp_thd0 = 1 ; + p_rdo_skip->atf_thd0.madp_thd1 = 10 ; + p_rdo_skip->atf_thd1.madp_thd2 = atf_b16_skip_thd2[atf_str]; + p_rdo_skip->atf_thd1.madp_thd3 = atf_b16_skip_thd3[atf_str]; + p_rdo_skip->atf_wgt0.wgt0 = atf_b16_skip_wgt0[atf_str]; + p_rdo_skip->atf_wgt0.wgt1 = 16 ; + p_rdo_skip->atf_wgt0.wgt2 = 16 ; + p_rdo_skip->atf_wgt0.wgt3 = atf_b16_skip_wgt3[atf_str]; + p_rdo_skip->atf_wgt1.wgt4 = 16 ; + + p_rdo_noskip = ®->rdo_b16_inter; + p_rdo_noskip->ratf_thd0.madp_thd0 = 20; + p_rdo_noskip->ratf_thd0.madp_thd1 = 40; + p_rdo_noskip->ratf_thd1.madp_thd2 = 72; + p_rdo_noskip->atf_wgt.wgt0 = 16; + p_rdo_noskip->atf_wgt.wgt1 = 16; + p_rdo_noskip->atf_wgt.wgt2 = 16; + p_rdo_noskip->atf_wgt.wgt3 = 16; + + p_rdo_noskip = ®->rdo_b16_intra; + p_rdo_noskip->ratf_thd0.madp_thd0 = atf_b16_intra_thd0[atf_str]; + p_rdo_noskip->ratf_thd0.madp_thd1 = atf_b16_intra_thd1[atf_str]; + p_rdo_noskip->ratf_thd1.madp_thd2 = atf_b16_intra_thd2[atf_str]; + p_rdo_noskip->atf_wgt.wgt0 = atf_b16_intra_wgt0[atf_str]; + p_rdo_noskip->atf_wgt.wgt1 = atf_b16_intra_wgt1[atf_str]; + p_rdo_noskip->atf_wgt.wgt2 = atf_b16_intra_wgt2[atf_str]; + p_rdo_noskip->atf_wgt.wgt3 = 16; } static void vepu510_h265_global_cfg_set(H265eV510HalContext *ctx, H265eV510RegSet *regs) { MppEncHwCfg *hw = &ctx->cfg->hw; - RK_U32 i; - Vepu510RcRoi *rc_regs = ®s->reg_rc_roi; H265eVepu510Param *reg_param = ®s->reg_param; H265eVepu510Sqi *reg_sqi = ®s->reg_sqi; MppEncSceneMode sm = ctx->cfg->tune.scene_mode; + RK_S32 atf_str = ctx->cfg->tune.anti_flicker_str; RK_S32 lambda_idx = 0; - vepu510_h265_rdo_cfg(reg_sqi, sm); + vepu510_h265_rdo_cfg(ctx, reg_sqi, sm); + vepu510_h265_atf_cfg(reg_sqi, atf_str); memcpy(®_param->pprd_lamb_satd_0_51[0], lamd_satd_qp_510, sizeof(lamd_satd_qp)); if (ctx->frame_type == INTRA_FRAME) { - RK_U8 *thd = (RK_U8 *)&rc_regs->aq_tthd0; - for (i = 0; i < MPP_ARRAY_ELEMS(aq_thd_default); i++) { - thd[i] = hw->aq_thrd_i[i]; - } - reg_param->iprd_lamb_satd_ofst.lambda_satd_offset = 11; lambda_idx = ctx->cfg->tune.lambda_idx_i; memcpy(®_param->rdo_wgta_qp_grpa_0_51[0], &rdo_lambda_table_I[lambda_idx], H265E_LAMBDA_TAB_SIZE); } else { - RK_U8 *thd = (RK_U8 *)&rc_regs->aq_tthd0; - for (i = 0; i < MPP_ARRAY_ELEMS(aq_thd_default); i++) { - thd[i] = hw->aq_thrd_p[i]; - } - reg_param->iprd_lamb_satd_ofst.lambda_satd_offset = 11; lambda_idx = ctx->cfg->tune.lambda_idx_p; memcpy(®_param->rdo_wgta_qp_grpa_0_51[0], @@ -747,6 +869,8 @@ static void vepu510_h265_global_cfg_set(H265eV510HalContext *ctx, H265eV510RegSe if (hw->qbias_en) { reg_param->qnt_bias_comb.qnt_f_bias_i = hw->qbias_i; reg_param->qnt_bias_comb.qnt_f_bias_p = hw->qbias_p; + } else if (ctx->smart_en) { + reg_param->qnt_bias_comb.qnt_f_bias_i = 144; } /* CIME */ @@ -831,10 +955,10 @@ MPP_RET hal_h265e_v510_deinit(void *hal) if (!frm) continue; - if (frm->roi_base_cfg_buf) { - mpp_buffer_put(frm->roi_base_cfg_buf); - frm->roi_base_cfg_buf = NULL; - frm->roi_base_buf_size = 0; + if (frm->roir_buf) { + mpp_buffer_put(frm->roir_buf); + frm->roir_buf = NULL; + frm->roir_buf_size = 0; } MPP_FREE(frm->roi_base_cfg_sw_buf); @@ -871,6 +995,11 @@ MPP_RET hal_h265e_v510_deinit(void *hal) ctx->reg_cfg = NULL; } + if (ctx->roi_grp) { + mpp_buffer_group_put(ctx->roi_grp); + ctx->roi_grp = NULL; + } + if (ctx->tune) { vepu510_h265e_tune_deinit(ctx->tune); ctx->tune = NULL; @@ -907,7 +1036,7 @@ MPP_RET hal_h265e_v510_init(void *hal, MppEncHalCfg *cfg) ctx->cfg = cfg->cfg; hal_bufs_init(&ctx->dpb_bufs); - ctx->frame_cnt = 0; + ctx->frame_count = -1; ctx->frame_cnt_gen_ready = 0; ctx->enc_mode = 1; cfg->cap_recn_out = 1; @@ -931,11 +1060,6 @@ MPP_RET hal_h265e_v510_init(void *hal, MppEncHalCfg *cfg) hw->qbias_p = 85; hw->qbias_en = 0; - memcpy(hw->aq_thrd_i, aq_thd_default, sizeof(hw->aq_thrd_i)); - memcpy(hw->aq_thrd_p, aq_thd_default, sizeof(hw->aq_thrd_p)); - memcpy(hw->aq_step_i, aq_qp_dealt_default, sizeof(hw->aq_step_i)); - memcpy(hw->aq_step_p, aq_qp_dealt_default, sizeof(hw->aq_step_p)); - for (j = 0; j < MPP_ARRAY_ELEMS(hw->mode_bias); j++) hw->mode_bias[j] = 8; } @@ -1114,12 +1238,18 @@ static MPP_RET vepu510_h265_set_rc_regs(H265eV510HalContext *ctx, H265eV510RegSe reg_frm->common.rc_cfg.rc_en = 1; reg_frm->common.rc_cfg.aq_en = 1; reg_frm->common.rc_cfg.rc_ctu_num = mb_wd32; - reg_frm->common.rc_qp.rc_qp_range = (ctx->frame_type == INTRA_FRAME) ? - hw->qp_delta_row_i : hw->qp_delta_row; + reg_frm->common.rc_qp.rc_max_qp = rc_cfg->quality_max; reg_frm->common.rc_qp.rc_min_qp = rc_cfg->quality_min; reg_frm->common.rc_tgt.ctu_ebit = ctu_target_bits_mul_16; + if (ctx->smart_en) { + reg_frm->common.rc_qp.rc_qp_range = 0; + } else { + reg_frm->common.rc_qp.rc_qp_range = (ctx->frame_type == INTRA_FRAME) ? + hw->qp_delta_row_i : hw->qp_delta_row; + } + { /* fixed frame qp */ RK_S32 fqp_min, fqp_max; @@ -1430,10 +1560,10 @@ void vepu510_h265_set_hw_address(H265eV510HalContext *ctx, H265eVepu510Frame *re mpp_dev_multi_offset_update(ctx->reg_cfg, 166, ctx->fbc_header_len); if (md_info_buf) { - regs->common.enc_pic.mei_stor = 1; + regs->common.enc_pic.mei_stor = 1; regs->common.meiw_addr = mpp_buffer_get_fd(md_info_buf); } else { - regs->common.enc_pic.mei_stor = 0; + regs->common.enc_pic.mei_stor = 0; regs->common.meiw_addr = 0; } @@ -1453,6 +1583,10 @@ void vepu510_h265_set_hw_address(H265eV510HalContext *ctx, H265eVepu510Frame *re regs->common.pic_ofst.pic_ofst_y = mpp_frame_get_offset_y(task->frame); regs->common.pic_ofst.pic_ofst_x = mpp_frame_get_offset_x(task->frame); + + /* smear bufs */ + regs->common.adr_smear_rd = mpp_buffer_get_fd(ref_buf->buf[3]); + regs->common.adr_smear_wr = mpp_buffer_get_fd(recon_buf->buf[3]); } static MPP_RET vepu510_h265e_save_pass1_patch(H265eV510RegSet *regs, H265eV510HalContext *ctx, @@ -1676,8 +1810,8 @@ MPP_RET hal_h265e_v510_gen_regs(void *hal, HalEncTask *task) pic_h32 = (syn->pp.pic_height + 31) / 32; hal_h265e_dbg_simple("frame %d | type %d | start gen regs", - ctx->frame_cnt, ctx->frame_type); - + ctx->frame_count, ctx->frame_type); + vepu510_h265e_tune_aq_prepare(ctx->tune); memset(regs, 0, sizeof(H265eV510RegSet)); reg_ctl->enc_strt.lkt_num = 0; @@ -1748,7 +1882,7 @@ MPP_RET hal_h265e_v510_gen_regs(void *hal, HalEncTask *task) reg_frm->rdo_cfg.cu_inter_e = 0xdb; reg_frm->rdo_cfg.lambda_qp_use_avg_cu16_flag = (sm == MPP_ENC_SCENE_MODE_IPC); reg_frm->rdo_cfg.yuvskip_calc_en = 1; - reg_frm->rdo_cfg.atf_e = (sm == MPP_ENC_SCENE_MODE_IPC); + reg_frm->rdo_cfg.atf_e = 1; reg_frm->rdo_cfg.atr_e = (sm == MPP_ENC_SCENE_MODE_IPC); if (syn->pp.num_long_term_ref_pics_sps) { @@ -1793,7 +1927,7 @@ MPP_RET hal_h265e_v510_gen_regs(void *hal, HalEncTask *task) ctx->cfg->prep.width, ctx->cfg->prep.height); /*paramet cfg*/ vepu510_h265_global_cfg_set(ctx, regs); - vepu510_h265e_tune_reg_patch(ctx->tune); + vepu510_h265e_tune_reg_patch(ctx->tune, task); /* two pass register patch */ if (frm->save_pass1) @@ -2211,6 +2345,8 @@ MPP_RET hal_h265e_v510_get_task(void *hal, HalEncTask *task) ctx->syn = (H265eSyntax_new *)task->syntax.data; ctx->dpb = (H265eDpb*)ctx->syn->dpb; + ctx->smart_en = (ctx->cfg->rc.rc_mode == MPP_ENC_RC_MODE_SMTRC); + ctx->qpmap_en = ctx->cfg->tune.deblur_en; if (vepu510_h265_setup_hal_bufs(ctx)) { hal_h265e_err("vepu541_h265_allocate_buffers failed, free buffers and return\n"); @@ -2219,7 +2355,6 @@ MPP_RET hal_h265e_v510_get_task(void *hal, HalEncTask *task) } ctx->last_frame_type = ctx->frame_type; - frm_cfg = ctx->frms[task_idx]; ctx->frm = frm_cfg; @@ -2228,6 +2363,7 @@ MPP_RET hal_h265e_v510_get_task(void *hal, HalEncTask *task) } else { ctx->frame_type = INTER_P_FRAME; } + if (!frm_status->reencode && mpp_frame_has_meta(task->frame)) { MppMeta meta = mpp_frame_get_meta(frame); diff --git a/mpp/hal/rkenc/h265e/hal_h265e_vepu510_tune.c b/mpp/hal/rkenc/h265e/hal_h265e_vepu510_tune.c index 785b7b0d..aa6cee07 100644 --- a/mpp/hal/rkenc/h265e/hal_h265e_vepu510_tune.c +++ b/mpp/hal/rkenc/h265e/hal_h265e_vepu510_tune.c @@ -18,15 +18,48 @@ #include "hal_h265e_vepu510_reg.h" typedef struct HalH265eVepu510Tune_t { - H265eV510HalContext *ctx; + H265eV510HalContext *ctx; - RK_S32 pre_madp[2]; - RK_S32 pre_madi[2]; + RK_U8 *qm_mv_buf; /* qpmap move flag buffer */ + RK_U32 qm_mv_buf_size; + + RK_S32 pre_madp[2]; + RK_S32 pre_madi[2]; } HalH265eVepu510Tune; +static RK_U32 aq_thd_default[16] = { + 0, 0, 0, 0, 3, 3, 5, 5, + 8, 8, 8, 15, 15, 20, 25, 25 +}; + +static RK_S32 aq_qp_delta_default[16] = { + -8, -7, -6, -5, -4, -3, -2, -1, + 1, 2, 3, 4, 5, 6, 7, 8 +}; + +static RK_U32 aq_thd_smt_I[16] = { + 1, 2, 3, 3, 3, 3, 5, 5, + 8, 8, 8, 13, 15, 20, 25, 25 +}; + +static RK_S32 aq_qp_delta_smt_I[16] = { + -8, -7, -6, -5, -4, -3, -2, -1, + 0, 1, 2, 3, 5, 7, 8, 9 +}; + +static RK_U32 aq_thd_smt_P[16] = { + 0, 0, 0, 0, 3, 3, 5, 5, + 8, 8, 8, 15, 15, 20, 25, 25 +}; + +static RK_S32 aq_qp_delta_smt_P[16] = { + -8, -7, -6, -5, -4, -3, -2, -1, + 0, 1, 2, 3, 4, 6, 7, 9 +}; + static HalH265eVepu510Tune *vepu510_h265e_tune_init(H265eV510HalContext *ctx) { - HalH265eVepu510Tune *tune = mpp_malloc(HalH265eVepu510Tune, 1); + HalH265eVepu510Tune *tune = mpp_calloc(HalH265eVepu510Tune, 1); if (NULL == tune) return tune; @@ -40,33 +73,72 @@ static HalH265eVepu510Tune *vepu510_h265e_tune_init(H265eV510HalContext *ctx) static void vepu510_h265e_tune_deinit(void *tune) { + HalH265eVepu510Tune *t = (HalH265eVepu510Tune *)tune; + + MPP_FREE(t->qm_mv_buf); MPP_FREE(tune); } +static void vepu510_h265e_tune_aq_prepare(HalH265eVepu510Tune *tune) +{ + if (tune == NULL) { + return; + } + + H265eV510HalContext *ctx = tune->ctx; + MppEncHwCfg *hw = &ctx->cfg->hw; + + if (ctx->smart_en) { + memcpy(hw->aq_thrd_i, aq_thd_smt_I, sizeof(hw->aq_thrd_i)); + memcpy(hw->aq_thrd_p, aq_thd_smt_P, sizeof(hw->aq_thrd_p)); + memcpy(hw->aq_step_i, aq_qp_delta_smt_I, sizeof(hw->aq_step_i)); + memcpy(hw->aq_step_p, aq_qp_delta_smt_P, sizeof(hw->aq_step_p)); + } else { + memcpy(hw->aq_thrd_i, aq_thd_default, sizeof(hw->aq_thrd_i)); + memcpy(hw->aq_thrd_p, aq_thd_default, sizeof(hw->aq_thrd_p)); + memcpy(hw->aq_step_i, aq_qp_delta_default, sizeof(hw->aq_step_i)); + memcpy(hw->aq_step_p, aq_qp_delta_default, sizeof(hw->aq_step_p)); + } +} + static void vepu510_h265e_tune_aq(HalH265eVepu510Tune *tune) { H265eV510HalContext *ctx = tune->ctx; Vepu510H265eFrmCfg *frm_cfg = ctx->frm; H265eV510RegSet *regs = frm_cfg->regs_set; Vepu510RcRoi *r = ®s->reg_rc_roi; + MppEncHwCfg *hw = &ctx->cfg->hw; + RK_U32 i = 0; + RK_S32 aq_step[16]; - r->aq_stp0.aq_stp_s0 = -8; - r->aq_stp0.aq_stp_0t1 = -7; - r->aq_stp0.aq_stp_1t2 = -6; - r->aq_stp0.aq_stp_2t3 = -5; - r->aq_stp0.aq_stp_3t4 = -4; - r->aq_stp0.aq_stp_4t5 = -3; - r->aq_stp1.aq_stp_5t6 = -2; - r->aq_stp1.aq_stp_6t7 = -1; + RK_U8 *thd = (RK_U8 *)&r->aq_tthd0; + for (i = 0; i < MPP_ARRAY_ELEMS(aq_thd_default); i++) { + if (ctx->frame_type == INTRA_FRAME) { + thd[i] = hw->aq_thrd_i[i]; + aq_step[i] = hw->aq_step_i[i] & 0x1F; + } else { + thd[i] = hw->aq_thrd_p[i]; + aq_step[i] = hw->aq_step_p[i] & 0x1F; + } + } + + r->aq_stp0.aq_stp_s0 = aq_step[0]; + r->aq_stp0.aq_stp_0t1 = aq_step[1]; + r->aq_stp0.aq_stp_1t2 = aq_step[2]; + r->aq_stp0.aq_stp_2t3 = aq_step[3]; + r->aq_stp0.aq_stp_3t4 = aq_step[4]; + r->aq_stp0.aq_stp_4t5 = aq_step[5]; + r->aq_stp1.aq_stp_5t6 = aq_step[6]; + r->aq_stp1.aq_stp_6t7 = aq_step[7]; r->aq_stp1.aq_stp_7t8 = 0; - r->aq_stp1.aq_stp_8t9 = 1; - r->aq_stp1.aq_stp_9t10 = 2; - r->aq_stp1.aq_stp_10t11 = 3; - r->aq_stp2.aq_stp_11t12 = 4; - r->aq_stp2.aq_stp_12t13 = 5; - r->aq_stp2.aq_stp_13t14 = 6; - r->aq_stp2.aq_stp_14t15 = 7; - r->aq_stp2.aq_stp_b15 = 8; + r->aq_stp1.aq_stp_8t9 = aq_step[8]; + r->aq_stp1.aq_stp_9t10 = aq_step[9]; + r->aq_stp1.aq_stp_10t11 = aq_step[10]; + r->aq_stp2.aq_stp_11t12 = aq_step[11]; + r->aq_stp2.aq_stp_12t13 = aq_step[12]; + r->aq_stp2.aq_stp_13t14 = aq_step[13]; + r->aq_stp2.aq_stp_14t15 = aq_step[14]; + r->aq_stp2.aq_stp_b15 = aq_step[15]; r->aq_clip.aq16_rnge = 5; r->aq_clip.aq32_rnge = 5; @@ -75,13 +147,9 @@ static void vepu510_h265e_tune_aq(HalH265eVepu510Tune *tune) r->aq_clip.aq16_dif1 = 12; } -static void vepu510_h265e_tune_reg_patch(void *p) +static void vepu510_h265e_tune_reg_patch(void *p, HalEncTask *task) { HalH265eVepu510Tune *tune = (HalH265eVepu510Tune *)p; - H265eV510HalContext *ctx = NULL; - RK_S32 scene_mode = 0; - (void)ctx; - (void)scene_mode; if (NULL == tune) return; @@ -238,4 +306,4 @@ static void vepu510_h265e_tune_stat_update(void *p, HalEncTask *task) hal_rc_ret->madi = fb->st_madi; hal_rc_ret->madp = fb->st_madp; /* unused ?? */ -} +} \ No newline at end of file diff --git a/test/mpi_enc_test.c b/test/mpi_enc_test.c index ef6d447e..05393197 100644 --- a/test/mpi_enc_test.c +++ b/test/mpi_enc_test.c @@ -119,6 +119,7 @@ typedef struct { RK_S32 vi_len; RK_S32 scene_mode; RK_S32 cu_qp_delta_depth; + RK_S32 anti_flicker_str; RK_S64 first_frm; RK_S64 first_pkt; @@ -180,6 +181,7 @@ MPP_RET test_ctx_init(MpiEncMultiCtxInfo *info) p->fps_out_num = cmd->fps_out_num; p->scene_mode = cmd->scene_mode; p->cu_qp_delta_depth = cmd->cu_qp_delta_depth; + p->anti_flicker_str = cmd->anti_flicker_str; p->mdinfo_size = (MPP_VIDEO_CodingHEVC == cmd->type) ? (MPP_ALIGN(p->hor_stride, 32) >> 5) * (MPP_ALIGN(p->ver_stride, 32) >> 5) * 16 : @@ -318,8 +320,11 @@ MPP_RET test_mpp_enc_cfg_setup(MpiEncMultiCtxInfo *info) p->bps = p->width * p->height / 8 * (p->fps_out_num / p->fps_out_den); mpp_enc_cfg_set_s32(cfg, "rc:cu_qp_delta_depth", p->cu_qp_delta_depth); + mpp_enc_cfg_set_s32(cfg, "tune:anti_flicker_str", p->anti_flicker_str); mpp_enc_cfg_set_s32(cfg, "tune:scene_mode", p->scene_mode); + mpp_enc_cfg_set_s32(cfg, "tune:deblur_en", cmd->deblur_en); + mpp_enc_cfg_set_s32(cfg, "tune:deblur_str", cmd->deblur_str); mpp_enc_cfg_set_s32(cfg, "prep:width", p->width); mpp_enc_cfg_set_s32(cfg, "prep:height", p->height); @@ -387,7 +392,8 @@ MPP_RET test_mpp_enc_cfg_setup(MpiEncMultiCtxInfo *info) } break; case MPP_ENC_RC_MODE_CBR : case MPP_ENC_RC_MODE_VBR : - case MPP_ENC_RC_MODE_AVBR : { + case MPP_ENC_RC_MODE_AVBR : + case MPP_ENC_RC_MODE_SMTRC : { mpp_enc_cfg_set_s32(cfg, "rc:qp_init", cmd->qp_init ? cmd->qp_init : -1); mpp_enc_cfg_set_s32(cfg, "rc:qp_max", cmd->qp_max ? cmd->qp_max : 51); mpp_enc_cfg_set_s32(cfg, "rc:qp_min", cmd->qp_min ? cmd->qp_min : 10); @@ -508,6 +514,19 @@ MPP_RET test_mpp_enc_cfg_setup(MpiEncMultiCtxInfo *info) goto RET; } + if (cmd->type == MPP_VIDEO_CodingAVC || cmd->type == MPP_VIDEO_CodingHEVC) { + RcApiBrief rc_api_brief; + rc_api_brief.type = cmd->type; + rc_api_brief.name = (cmd->rc_mode == MPP_ENC_RC_MODE_SMTRC) ? + "smart" : "default"; + + ret = mpi->control(ctx, MPP_ENC_SET_RC_API_CURRENT, &rc_api_brief); + if (ret) { + mpp_err("mpi control enc set rc api failed ret %d\n", ret); + goto RET; + } + } + if (ref) mpp_enc_ref_cfg_deinit(&ref); @@ -607,7 +626,7 @@ MPP_RET test_mpp_run(MpiEncMultiCtxInfo *info) if (ret == MPP_NOK || feof(p->fp_input)) { p->frm_eos = 1; - if (p->frame_num < 0 || p->frame_count < p->frame_num) { + if (p->frame_num < 0) { clearerr(p->fp_input); rewind(p->fp_input); p->frm_eos = 0; @@ -818,7 +837,7 @@ MPP_RET test_mpp_run(MpiEncMultiCtxInfo *info) meta = mpp_packet_get_meta(packet); RK_S32 temporal_id = 0; RK_S32 lt_idx = -1; - RK_S32 avg_qp = -1; + RK_S32 avg_qp = -1, bps_rt = -1; RK_S32 use_lt_idx = -1; if (MPP_OK == mpp_meta_get_s32(meta, KEY_TEMPORAL_ID, &temporal_id)) @@ -833,6 +852,10 @@ MPP_RET test_mpp_run(MpiEncMultiCtxInfo *info) log_len += snprintf(log_buf + log_len, log_size - log_len, " qp %2d", avg_qp); + if (MPP_OK == mpp_meta_get_s32(meta, KEY_ENC_BPS_RT, &bps_rt)) + log_len += snprintf(log_buf + log_len, log_size - log_len, + " bps_rt %d", bps_rt); + if (MPP_OK == mpp_meta_get_s32(meta, KEY_ENC_USE_LTR, &use_lt_idx)) log_len += snprintf(log_buf + log_len, log_size - log_len, " vi"); } diff --git a/utils/mpi_enc_utils.c b/utils/mpi_enc_utils.c index db1744c0..e72d1fb8 100644 --- a/utils/mpi_enc_utils.c +++ b/utils/mpi_enc_utils.c @@ -292,7 +292,7 @@ RK_S32 mpi_enc_opt_rc(void *ctx, const char *next) } mpp_err("invalid rate control usage -rc rc_mode\n"); - mpp_err("rc_mode 0:vbr 1:cbr 2:avbr 3:cvbr 4:fixqp\n"); + mpp_err("rc_mode 0:vbr 1:cbr 2:fixqp 3:avbr 4:smtrc\n"); return 0; } @@ -501,6 +501,32 @@ RK_S32 mpi_enc_opt_qpdd(void *ctx, const char *next) return 0; } +RK_S32 mpi_enc_opt_dbe(void *ctx, const char *next) +{ + MpiEncTestArgs *cmd = (MpiEncTestArgs *)ctx; + + if (next) { + cmd->deblur_en = atoi(next); + return 1; + } + + mpp_err("invalid deblur en\n"); + return 0; +} + +RK_S32 mpi_enc_opt_dbs(void *ctx, const char *next) +{ + MpiEncTestArgs *cmd = (MpiEncTestArgs *)ctx; + + if (next) { + cmd->deblur_str = atoi(next); + return 1; + } + + mpp_err("invalid deblur str\n"); + return 0; +} + RK_S32 mpi_enc_opt_help(void *ctx, const char *next) { (void)ctx; @@ -508,6 +534,19 @@ RK_S32 mpi_enc_opt_help(void *ctx, const char *next) return -1; } +RK_S32 mpi_enc_opt_atf(void *ctx, const char *next) +{ + MpiEncTestArgs *cmd = (MpiEncTestArgs *)ctx; + + if (next) { + cmd->anti_flicker_str = atoi(next); + return 1; + } + + mpp_err("invalid cu_qp_delta_depth\n"); + return 0; +} + static MppOptInfo enc_opts[] = { {"i", "input_file", "input frame file", mpi_enc_opt_i}, {"o", "output_file", "output encoded bitstream file", mpi_enc_opt_o}, @@ -532,6 +571,9 @@ static MppOptInfo enc_opts[] = { {"slt", "slt file", "slt verify data file", mpi_enc_opt_slt}, {"sm", "scene mode", "scene_mode, 0:default 1:ipc", mpi_enc_opt_sm}, {"qpdd", "cu_qp_delta_depth", "cu_qp_delta_depth, 0:1:2", mpi_enc_opt_qpdd}, + {"dbe", "deblur enable", "deblur_en or qpmap_en, 0:close 1:open", mpi_enc_opt_dbe}, + {"dbs", "deblur strength", "deblur_str 0~3: hw + sw scheme; 4~7: hw scheme", mpi_enc_opt_dbs}, + {"atf", "anti_flicker_str", "anti_flicker_str, 0:off 1 2 3", mpi_enc_opt_atf}, }; static RK_U32 enc_opt_cnt = MPP_ARRAY_ELEMS(enc_opts); diff --git a/utils/mpi_enc_utils.h b/utils/mpi_enc_utils.h index 572e22e9..5905fc59 100644 --- a/utils/mpi_enc_utils.h +++ b/utils/mpi_enc_utils.h @@ -79,6 +79,13 @@ typedef struct MpiEncTestArgs_t { /* -qpdd cu_qp_delta_depth */ RK_S32 cu_qp_delta_depth; + RK_S32 anti_flicker_str; + + /* -dbe deblur enable flag + * -dbs deblur strength + */ + RK_S32 deblur_en; + RK_S32 deblur_str; /* -v q runtime log disable flag */ RK_U32 quiet;