diff --git a/inc/mpp_rc_defs.h b/inc/mpp_rc_defs.h index e8cb5b52..d3eb3b18 100644 --- a/inc/mpp_rc_defs.h +++ b/inc/mpp_rc_defs.h @@ -209,6 +209,12 @@ typedef struct EncRcCommonInfo_t { RK_U32 lvl8_intra_num; RK_U32 lvl4_intra_num; + RK_U32 motion_level; + RK_U32 complex_level; + RK_S32 complex_scene; + RK_S32 scene_mode; + RK_S32 last_scene_mode; + RK_S32 reserve[5]; } EncRcTaskInfo; diff --git a/inc/rk_venc_cmd.h b/inc/rk_venc_cmd.h index e83c6a15..3c8d9024 100644 --- a/inc/rk_venc_cmd.h +++ b/inc/rk_venc_cmd.h @@ -239,6 +239,7 @@ typedef enum MppEncRcCfgChange_e { MPP_ENC_RC_CFG_CHANGE_REFRESH = (1 << 27), MPP_ENC_RC_CFG_CHANGE_GOP_REF_CFG = (1 << 28), MPP_ENC_RC_CFG_CHANGE_FQP = (1 << 29), + MPP_ENC_RC_CFG_CHANGE_QPDD = (1 << 30), MPP_ENC_RC_CFG_CHANGE_ALL = (0xFFFFFFFF), } MppEncRcCfgChange; @@ -410,6 +411,7 @@ typedef struct MppEncRcCfg_t { RK_S32 fqp_min_p; RK_S32 fqp_max_i; RK_S32 fqp_max_p; + RK_S32 cu_qp_delta_depth; RK_S32 hier_qp_en; RK_S32 hier_qp_delta[4]; @@ -1427,12 +1429,16 @@ 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) } MppEncFineTuneCfgChange; typedef struct MppEncFineTuneCfg_t { RK_U32 change; MppEncSceneMode scene_mode; + RK_S32 lambda_idx_i; + RK_S32 lambda_idx_p; } MppEncFineTuneCfg; #endif /*__RK_VENC_CMD_H__*/ diff --git a/mpp/base/mpp_enc_cfg.cpp b/mpp/base/mpp_enc_cfg.cpp index 0fbcdea6..c3786312 100644 --- a/mpp/base/mpp_enc_cfg.cpp +++ b/mpp/base/mpp_enc_cfg.cpp @@ -139,6 +139,7 @@ public: ENTRY(rc, fqp_min_p, S32, RK_S32, MPP_ENC_RC_CFG_CHANGE_FQP, rc, fqp_min_p) \ ENTRY(rc, fqp_max_i, S32, RK_S32, MPP_ENC_RC_CFG_CHANGE_FQP, rc, fqp_max_i) \ ENTRY(rc, fqp_max_p, S32, RK_S32, MPP_ENC_RC_CFG_CHANGE_FQP, rc, fqp_max_p) \ + ENTRY(rc, cu_qp_delta_depth, S32, RK_S32, MPP_ENC_RC_CFG_CHANGE_QPDD, rc, cu_qp_delta_depth) \ /* prep config */ \ ENTRY(prep, width, S32, RK_S32, MPP_ENC_PREP_CFG_CHANGE_INPUT, prep, width) \ ENTRY(prep, height, S32, RK_S32, MPP_ENC_PREP_CFG_CHANGE_INPUT, prep, height) \ @@ -255,7 +256,9 @@ public: ENTRY(hw, qbias_p, S32, RK_S32, MPP_ENC_HW_CFG_CHANGE_QBIAS_P, hw, qbias_p) \ 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, scene_mode, S32, MppEncSceneMode, MPP_ENC_TUNE_CFG_CHANGE_SCENE_MODE, tune, scene_mode) \ + 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) static void mpp_enc_cfg_fill(MppTrie trie, MppCfgApi **cfgs) { diff --git a/mpp/base/mpp_trie.cpp b/mpp/base/mpp_trie.cpp index 5f771701..1f024b1e 100644 --- a/mpp/base/mpp_trie.cpp +++ b/mpp/base/mpp_trie.cpp @@ -74,7 +74,7 @@ typedef struct MppTrieNode_t { RK_U16 next_cnt; } MppTrieNode; -typedef struct MppAcImpl_t { +typedef struct MppTrieImpl_t { RK_S32 info_count; RK_S32 info_used; MppTrieInfo *info; @@ -175,7 +175,7 @@ DONE: MPP_RET mpp_trie_deinit(MppTrie trie) { if (NULL == trie) { - mpp_err_f("invalid NULL input trie automation\n"); + mpp_err_f("invalid NULL input trie\n"); return MPP_ERR_NULL_PTR; } diff --git a/mpp/codec/enc/h264/h264e_api_v2.c b/mpp/codec/enc/h264/h264e_api_v2.c index 95c9b722..b717a37b 100644 --- a/mpp/codec/enc/h264/h264e_api_v2.c +++ b/mpp/codec/enc/h264/h264e_api_v2.c @@ -188,6 +188,9 @@ static void init_h264e_cfg_set(MppEncCfgSet *cfg, MppClientType type) rc_cfg->fqp_min_p = INT_MAX; rc_cfg->fqp_max_i = INT_MAX; rc_cfg->fqp_max_p = INT_MAX; + + cfg->tune.lambda_idx_i = 6; + cfg->tune.lambda_idx_p = 6; } static void h264e_add_syntax(H264eCtx *ctx, H264eSyntaxType type, void *p) diff --git a/mpp/codec/enc/h265/h265e_api.c b/mpp/codec/enc/h265/h265e_api.c index d5a60e33..57ed9b64 100644 --- a/mpp/codec/enc/h265/h265e_api.c +++ b/mpp/codec/enc/h265/h265e_api.c @@ -110,6 +110,8 @@ static MPP_RET h265e_init(void *ctx, EncImplCfg *ctrlCfg) h265->merge_cfg.merge_left_flag = 1; h265->merge_cfg.merge_up_flag = 1; p->cfg->tune.scene_mode = MPP_ENC_SCENE_MODE_DEFAULT; + p->cfg->tune.lambda_idx_i = 2; + p->cfg->tune.lambda_idx_p = 4; /* * default prep: @@ -167,7 +169,7 @@ static MPP_RET h265e_init(void *ctx, EncImplCfg *ctrlCfg) rc_cfg->fqp_min_p = INT_MAX; rc_cfg->fqp_max_i = INT_MAX; rc_cfg->fqp_max_p = INT_MAX; - + rc_cfg->cu_qp_delta_depth = 0; INIT_LIST_HEAD(&p->rc_list); h265e_dbg_func("leave ctx %p\n", ctx); diff --git a/mpp/codec/enc/h265/h265e_ps.c b/mpp/codec/enc/h265/h265e_ps.c index cafa8d38..88261d9f 100644 --- a/mpp/codec/enc/h265/h265e_ps.c +++ b/mpp/codec/enc/h265/h265e_ps.c @@ -400,13 +400,14 @@ MPP_RET h265e_set_sps(H265eCtx *ctx, H265eSps *sps, H265eVps *vps) MPP_RET h265e_set_pps(H265eCtx *ctx, H265ePps *pps, H265eSps *sps) { MppEncH265Cfg *codec = &ctx->cfg->codec.h265; + MppEncRcCfg *rc = &ctx->cfg->rc; + pps->m_bConstrainedIntraPred = codec->const_intra_pred; pps->m_PPSId = 0; pps->m_SPSId = 0; pps->m_picInitQPMinus26 = 0; - pps->m_useDQP = 1; - pps->m_maxCuDQPDepth = 0; + pps->m_maxCuDQPDepth = rc->cu_qp_delta_depth; pps->m_minCuDQPSize = (sps->m_maxCUSize >> pps->m_maxCuDQPDepth); pps->m_sps = sps; diff --git a/mpp/codec/mpp_enc_impl.cpp b/mpp/codec/mpp_enc_impl.cpp index 0dfbfa84..24c4ba8b 100644 --- a/mpp/codec/mpp_enc_impl.cpp +++ b/mpp/codec/mpp_enc_impl.cpp @@ -681,6 +681,9 @@ MPP_RET mpp_enc_proc_rc_cfg(MppCodingType coding, MppEncRcCfg *dst, MppEncRcCfg dst->refresh_num = src->refresh_num; } + if (change & MPP_ENC_RC_CFG_CHANGE_QPDD) + dst->cu_qp_delta_depth = src->cu_qp_delta_depth; + // parameter checking if (dst->rc_mode >= MPP_ENC_RC_MODE_BUTT) { mpp_err("invalid rc mode %d should be RC_MODE_VBR or RC_MODE_CBR\n", @@ -864,6 +867,22 @@ MPP_RET mpp_enc_proc_tune_cfg(MppEncFineTuneCfg *dst, MppEncFineTuneCfg *src) 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"); + ret = MPP_ERR_VALUE; + } + + if (change & MPP_ENC_TUNE_CFG_CHANGE_LAMBDA_IDX_P) + 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"); + ret = MPP_ERR_VALUE; + } + dst->change |= change; if (ret) { diff --git a/mpp/hal/rkenc/common/vepu510_common.h b/mpp/hal/rkenc/common/vepu510_common.h index f26f97a6..3a76572b 100644 --- a/mpp/hal/rkenc/common/vepu510_common.h +++ b/mpp/hal/rkenc/common/vepu510_common.h @@ -1103,12 +1103,7 @@ typedef struct Vepu510Status_t { } st_bnum_b16; /* 0x000040a4 reg4137 */ - struct { - RK_U32 rdo_smear_cnt0 : 8; - RK_U32 rdo_smear_cnt1 : 8; - RK_U32 rdo_smear_cnt2 : 8; - RK_U32 rdo_smear_cnt3 : 8; - } st_smear_cnt; + RK_U32 st_smear_cnt_reserved; /* 0x000040a8 reg4138 */ RK_U32 madi16_sum; diff --git a/mpp/hal/rkenc/h264e/hal_h264e_vepu510.c b/mpp/hal/rkenc/h264e/hal_h264e_vepu510.c index d8468311..89378810 100644 --- a/mpp/hal/rkenc/h264e/hal_h264e_vepu510.c +++ b/mpp/hal/rkenc/h264e/hal_h264e_vepu510.c @@ -107,8 +107,13 @@ typedef struct HalH264eVepu510Ctx_t { RK_S32 poll_slice_max; RK_S32 poll_cfg_size; MppDevPollCfg *poll_cfgs; + + void *tune; + RK_S32 smart_en; } HalH264eVepu510Ctx; +#include "hal_h264e_vepu510_tune.c" + static RK_S32 h264_aq_tthd_default[16] = { 0, 0, 0, 0, 3, 3, 5, 5, @@ -213,6 +218,11 @@ static MPP_RET hal_h264e_vepu510_deinit(void *hal) p->buf_pass1 = NULL; } + if (p->tune) { + vepu510_h264e_tune_deinit(p->tune); + p->tune = NULL; + } + hal_h264e_dbg_func("leave %p\n", p); return MPP_OK; @@ -326,6 +336,8 @@ static MPP_RET hal_h264e_vepu510_init(void *hal, MppEncHalCfg *cfg) for (i = 0; i < p->task_cnt; i++) h264e_vepu_stream_amend_init(&p->amend_sets[i]); + p->tune = vepu510_h264e_tune_init(p); + DONE: if (ret) hal_h264e_vepu510_deinit(hal); @@ -1184,7 +1196,6 @@ static void setup_vepu510_sqi(H264eVepu510Sqi *reg) static void setup_vepu510_rc_base(HalVepu510RegSet *regs, HalH264eVepu510Ctx *ctx, EncRcTask *rc_task) { - H264eSps *sps = ctx->sps; H264eSlice *slice = ctx->slice; MppEncCfgSet *cfg = ctx->cfg; @@ -1256,6 +1267,24 @@ static void setup_vepu510_rc_base(HalVepu510RegSet *regs, HalH264eVepu510Ctx *ct reg_frm->common.rc_qp.rc_min_qp = qp_min; reg_frm->common.rc_tgt.ctu_ebit = mb_target_bits_mul_16; + { + /* fixed frame level QP */ + RK_S32 fqp_min, fqp_max; + + if (slice->slice_type == H264_I_SLICE) { + fqp_min = rc->fqp_min_i; + fqp_max = rc->fqp_max_i; + } else { + fqp_min = rc->fqp_min_p; + fqp_max = rc->fqp_max_p; + } + + if ((fqp_min == fqp_max) && (fqp_min >= 1) && (fqp_max <= 51)) { + reg_frm->common.enc_pic.pic_qp = fqp_min; + reg_frm->common.rc_qp.rc_qp_range = 0; + } + } + regs->reg_rc_roi.rc_adj0.qp_adj0 = -2; regs->reg_rc_roi.rc_adj0.qp_adj1 = -1; regs->reg_rc_roi.rc_adj0.qp_adj2 = 0; @@ -1626,31 +1655,59 @@ static void setup_vepu510_me(HalVepu510RegSet *regs) #define H264E_LAMBDA_TAB_SIZE (52 * sizeof(RK_U32)) -static RK_U32 h264e_lambda_default[58] = { - 0x00000003, 0x00000005, 0x00000006, 0x00000007, - 0x00000009, 0x0000000b, 0x0000000e, 0x00000012, - 0x00000016, 0x0000001c, 0x00000024, 0x0000002d, - 0x00000039, 0x00000048, 0x0000005b, 0x00000073, - 0x00000091, 0x000000b6, 0x000000e6, 0x00000122, - 0x0000016d, 0x000001cc, 0x00000244, 0x000002db, - 0x00000399, 0x00000489, 0x000005b6, 0x00000733, - 0x00000912, 0x00000b6d, 0x00000e66, 0x00001224, - 0x000016db, 0x00001ccc, 0x00002449, 0x00002db7, - 0x00003999, 0x00004892, 0x00005b6f, 0x00007333, - 0x00009124, 0x0000b6de, 0x0000e666, 0x00012249, - 0x00016dbc, 0x0001cccc, 0x00024492, 0x0002db79, - 0x00039999, 0x00048924, 0x0005b6f2, 0x00073333, - 0x00091249, 0x000b6de5, 0x000e6666, 0x00122492, - 0x0016dbcb, 0x001ccccc, +static RK_U32 h264e_lambda_default[60] = { + 0x00000005, 0x00000006, 0x00000007, 0x00000009, + 0x0000000b, 0x0000000e, 0x00000012, 0x00000016, + 0x0000001c, 0x00000024, 0x0000002d, 0x00000039, + 0x00000048, 0x0000005b, 0x00000073, 0x00000091, + 0x000000b6, 0x000000e6, 0x00000122, 0x0000016d, + 0x000001cc, 0x00000244, 0x000002db, 0x00000399, + 0x00000489, 0x000005b6, 0x00000733, 0x00000912, + 0x00000b6d, 0x00000e66, 0x00001224, 0x000016db, + 0x00001ccc, 0x00002449, 0x00002db7, 0x00003999, + 0x00004892, 0x00005b6f, 0x00007333, 0x00009124, + 0x0000b6de, 0x0000e666, 0x00012249, 0x00016dbc, + 0x0001cccc, 0x00024492, 0x0002db79, 0x00039999, + 0x00048924, 0x0005b6f2, 0x00073333, 0x00091249, + 0x000b6de5, 0x000e6666, 0x00122492, 0x0016dbcb, + 0x001ccccc, 0x00244924, 0x002db796, 0x00399998, }; -static void setup_vepu510_l2(HalVepu510RegSet *regs, H264eSlice *slice, MppEncHwCfg *hw) +static RK_U32 h264e_lambda_cvr[60] = { + 0x00000009, 0x0000000b, 0x0000000e, 0x00000011, + 0x00000016, 0x0000001b, 0x00000022, 0x0000002b, + 0x00000036, 0x00000045, 0x00000056, 0x0000006d, + 0x00000089, 0x000000ad, 0x000000da, 0x00000112, + 0x00000159, 0x000001b3, 0x00000224, 0x000002b3, + 0x00000366, 0x00000449, 0x00000566, 0x000006cd, + 0x00000891, 0x00000acb, 0x00000d9a, 0x000013c1, + 0x000018e4, 0x00001f5c, 0x00002783, 0x000031c8, + 0x00003eb8, 0x00004f06, 0x00006390, 0x00008e14, + 0x0000b302, 0x0000e18a, 0x00011c29, 0x00016605, + 0x0001c313, 0x00027ae1, 0x00031fe6, 0x0003efcf, + 0x0004f5c3, 0x0006e785, 0x0008b2ef, 0x000af5c3, + 0x000f1e7a, 0x00130c7f, 0x00180000, 0x001e3cf4, + 0x002618fe, 0x00300000, 0x003c79e8, 0x004c31fc, + 0x00600000, 0x0078f3d0, 0x009863f8, 0x0c000000, +}; + +static void +setup_vepu510_l2(HalH264eVepu510Ctx *ctx, H264eSlice *slice, MppEncHwCfg *hw) { + HalVepu510RegSet *regs = ctx->regs_set; + MppEncSceneMode sm = ctx->cfg->tune.scene_mode; + RK_S32 lambda_idx = ctx->cfg->tune.lambda_idx_i; //TODO: lambda_idx_p RK_U32 i; hal_h264e_dbg_func("enter\n"); - memcpy(regs->reg_param.rdo_wgta_qp_grpa_0_51, &h264e_lambda_default[6], H264E_LAMBDA_TAB_SIZE); + if (sm == MPP_ENC_SCENE_MODE_IPC) { + memcpy(regs->reg_param.rdo_wgta_qp_grpa_0_51, + &h264e_lambda_default[lambda_idx], H264E_LAMBDA_TAB_SIZE); + } else { + memcpy(regs->reg_param.rdo_wgta_qp_grpa_0_51, + &h264e_lambda_cvr[lambda_idx], H264E_LAMBDA_TAB_SIZE); + } if (hw->qbias_en) { regs->reg_param.qnt_bias_comb.qnt_f_bias_i = hw->qbias_i; @@ -1950,12 +2007,14 @@ static MPP_RET hal_h264e_vepu510_gen_regs(void *hal, HalEncTask *task) if (frm_status->is_i_refresh) setup_vepu510_intra_refresh(regs, ctx, frm_status->seq_idx % cfg->rc.gop); - setup_vepu510_l2(regs, slice, &cfg->hw); + setup_vepu510_l2(ctx, slice, &cfg->hw); setup_vepu510_ext_line_buf(regs, ctx); if (ctx->roi_data) vepu510_set_roi(&ctx->regs_set->reg_rc_roi.roi_cfg, ctx->roi_data, ctx->cfg->prep.width, ctx->cfg->prep.height); + vepu510_h264e_tune_reg_patch(ctx->tune); + /* two pass register patch */ if (frm->save_pass1) vepu510_h264e_save_pass1_patch(regs, ctx); @@ -2267,6 +2326,8 @@ static MPP_RET hal_h264e_vepu510_ret_task(void * hal, HalEncTask * task) h264e_dpb_hal_end(ctx->dpb, task->flags.refr_idx); } + vepu510_h264e_tune_stat_update(ctx->tune, task); + hal_h264e_dbg_func("leave %p\n", hal); return MPP_OK; diff --git a/mpp/hal/rkenc/h264e/hal_h264e_vepu510_tune.c b/mpp/hal/rkenc/h264e/hal_h264e_vepu510_tune.c new file mode 100644 index 00000000..b476abae --- /dev/null +++ b/mpp/hal/rkenc/h264e/hal_h264e_vepu510_tune.c @@ -0,0 +1,178 @@ +/* + * Copyright 2024 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hal_enc_task.h" +#include "hal_h264e_vepu510_reg.h" + +#define HAL_H264E_DBG_CONTENT (0x00000200) +#define hal_h264e_dbg_content(fmt, ...) hal_h264e_dbg_f(HAL_H264E_DBG_CONTENT, fmt, ## __VA_ARGS__) + +/* + * Please follow the configuration below: + * + * FRAME_CONTENT_ANALYSIS_NUM >= 5 + * MD_WIN_LEN >= 3 + * MD_SHOW_LEN == 4 + */ + +typedef struct HalH264eVepu510Tune_t { + HalH264eVepu510Ctx *ctx; + + RK_S32 pre_madp[2]; + RK_S32 pre_madi[2]; +} HalH264eVepu510Tune; + +static RK_S32 mb_avg_madp_thd[6] = {192, 128, 64, 192, 128, 64}; + +static RK_S32 atr_wgt[4][9] = { + {22, 19, 16, 22, 19, 18, 22, 19, 16}, + {19, 19, 19, 19, 19, 19, 19, 19, 19}, + {22, 19, 16, 22, 19, 18, 22, 19, 16}, + {20, 20, 20, 20, 20, 20, 20, 20, 20}, +}; + +static RK_S32 skip_atf_wgt[4][13] = { + {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}, + {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}, + {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}, + {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}, +}; + +static RK_S32 intra_atf_wgt[4][12] = { + {24, 22, 21, 22, 21, 20, 20, 19, 18, 16, 16, 16}, + {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}, + {22, 21, 20, 21, 20, 19, 20, 19, 18, 16, 16, 16}, + {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}, +}; + +static RK_S32 cime_multi[4][4] = { + {4, 8, 24, 24}, + {4, 7, 20, 20}, + {4, 7, 20, 20}, + {4, 4, 4, 4}, +}; + +static RK_S32 rime_multi[4][3] = { + {4, 32, 128}, + {4, 16, 64}, + {4, 16, 64}, + {4, 4, 4}, +}; + +static HalH264eVepu510Tune *vepu510_h264e_tune_init(HalH264eVepu510Ctx *ctx) +{ + HalH264eVepu510Tune *tune = mpp_malloc(HalH264eVepu510Tune, 1); + + if (NULL == tune) + return tune; + + tune->ctx = ctx; + tune->pre_madi[0] = tune->pre_madi[1] = -1; + tune->pre_madp[0] = tune->pre_madp[1] = -1; + + return tune; +} + +static void vepu510_h264e_tune_deinit(void *tune) +{ + MPP_FREE(tune); +} + +static void vepu510_h264e_tune_reg_patch(void *p) +{ + HalH264eVepu510Tune *tune = (HalH264eVepu510Tune *)p; + + if (NULL == tune) + return; +} + +static void vepu510_h264e_tune_stat_update(void *p, HalEncTask *task) +{ + HalH264eVepu510Tune *tune = (HalH264eVepu510Tune *)p; + + if (NULL == tune) + return; + + EncRcTaskInfo *rc_info = &task->rc_task->info; + HalH264eVepu510Ctx *ctx = tune->ctx; + HalVepu510RegSet *regs = &ctx->regs_sets[task->flags.reg_idx]; + Vepu510Status *st = ®s->reg_st; + RK_U32 mb_w = ctx->sps->pic_width_in_mbs; + RK_U32 mb_h = ctx->sps->pic_height_in_mbs; + RK_U32 b16_num = mb_w * mb_h; + RK_U32 madi_cnt = 0; + + RK_U32 madi_th_cnt0 = st->st_madi_lt_num0.madi_th_lt_cnt0 + + st->st_madi_rt_num0.madi_th_rt_cnt0 + + st->st_madi_lb_num0.madi_th_lb_cnt0 + + st->st_madi_rb_num0.madi_th_rb_cnt0; + RK_U32 madi_th_cnt1 = st->st_madi_lt_num0.madi_th_lt_cnt1 + + st->st_madi_rt_num0.madi_th_rt_cnt1 + + st->st_madi_lb_num0.madi_th_lb_cnt1 + + st->st_madi_rb_num0.madi_th_rb_cnt1; + RK_U32 madi_th_cnt2 = st->st_madi_lt_num1.madi_th_lt_cnt2 + + st->st_madi_rt_num1.madi_th_rt_cnt2 + + st->st_madi_lb_num1.madi_th_lb_cnt2 + + st->st_madi_rb_num1.madi_th_rb_cnt2; + RK_U32 madi_th_cnt3 = st->st_madi_lt_num1.madi_th_lt_cnt3 + + st->st_madi_rt_num1.madi_th_rt_cnt3 + + st->st_madi_lb_num1.madi_th_lb_cnt3 + + st->st_madi_rb_num1.madi_th_rb_cnt3; + RK_U32 madp_th_cnt0 = st->st_madp_lt_num0.madp_th_lt_cnt0 + + st->st_madp_rt_num0.madp_th_rt_cnt0 + + st->st_madp_lb_num0.madp_th_lb_cnt0 + + st->st_madp_rb_num0.madp_th_rb_cnt0; + RK_U32 madp_th_cnt1 = st->st_madp_lt_num0.madp_th_lt_cnt1 + + st->st_madp_rt_num0.madp_th_rt_cnt1 + + st->st_madp_lb_num0.madp_th_lb_cnt1 + + st->st_madp_rb_num0.madp_th_rb_cnt1; + RK_U32 madp_th_cnt2 = st->st_madp_lt_num1.madp_th_lt_cnt2 + + st->st_madp_rt_num1.madp_th_rt_cnt2 + + st->st_madp_lb_num1.madp_th_lb_cnt2 + + st->st_madp_rb_num1.madp_th_rb_cnt2; + RK_U32 madp_th_cnt3 = st->st_madp_lt_num1.madp_th_lt_cnt3 + + st->st_madp_rt_num1.madp_th_rt_cnt3 + + st->st_madp_lb_num1.madp_th_lb_cnt3 + + st->st_madp_rb_num1.madp_th_rb_cnt3; + + madi_cnt = (6 * madi_th_cnt3 + 5 * madi_th_cnt2 + 4 * madi_th_cnt1) >> 2; + rc_info->complex_level = (madi_cnt * 100 > 30 * b16_num) ? 2 : + (madi_cnt * 100 > 13 * b16_num) ? 1 : 0; + + { + RK_U32 md_cnt = 0, motion_level = 0; + + if (ctx->smart_en) + md_cnt = (12 * madp_th_cnt3 + 11 * madp_th_cnt2 + 8 * madp_th_cnt1) >> 2; + else + md_cnt = (24 * madp_th_cnt3 + 22 * madp_th_cnt2 + 17 * madp_th_cnt1) >> 2; + + if (md_cnt * 100 > 15 * b16_num) + motion_level = 200; + else if (md_cnt * 100 > 5 * b16_num) + motion_level = 100; + else if (md_cnt * 100 > (b16_num >> 2)) + motion_level = 1; + else + motion_level = 0; + rc_info->motion_level = motion_level; + } + hal_h264e_dbg_rc("complex_level %d motion_level %d\n", + rc_info->complex_level, rc_info->motion_level); + + (void)madi_th_cnt0; + (void)madp_th_cnt0; +} diff --git a/mpp/hal/rkenc/h265e/hal_h265e_vepu510.c b/mpp/hal/rkenc/h265e/hal_h265e_vepu510.c index bb25c7cc..38a6e04f 100644 --- a/mpp/hal/rkenc/h265e/hal_h265e_vepu510.c +++ b/mpp/hal/rkenc/h265e/hal_h265e_vepu510.c @@ -30,6 +30,7 @@ #include "vepu510_common.h" #define MAX_FRAME_TASK_NUM 2 +#define H265E_LAMBDA_TAB_SIZE (52 * sizeof(RK_U32)) #define hal_h265e_err(fmt, ...) \ do {\ @@ -38,6 +39,7 @@ typedef struct Vepu510H265Fbk_t { RK_U32 hw_status; /* 0:corret, 1:error */ + RK_U32 frame_type; RK_U32 qp_sum; RK_U32 out_strm_size; RK_U32 out_hw_strm_size; @@ -55,6 +57,8 @@ typedef struct Vepu510H265Fbk_t { RK_U32 st_madi; RK_U32 st_mb_num; RK_U32 st_ctu_num; + RK_U32 st_smear_cnt[5]; + RK_S8 tgt_sub_real_lvl[6]; } Vepu510H265Fbk; typedef struct Vepu510H265eFrmCfg_t { @@ -117,6 +121,7 @@ typedef struct H265eV510HalContext_t { RK_S32 prev_idx; Vepu510H265Fbk feedback; + Vepu510H265Fbk last_frame_fb; void *dump_files; RK_U32 frame_cnt_gen_ready; @@ -144,15 +149,21 @@ typedef struct H265eV510HalContext_t { RK_S32 fbc_header_len; RK_U32 title_num; - /* external line buffer over 3K */ - MppBufferGroup ext_line_buf_grp; - RK_S32 ext_line_buf_size; - MppBuffer ext_line_buf; - MppBuffer buf_pass1; - MppBuffer ext_line_bufs[MAX_FRAME_TASK_NUM]; + RK_S32 qpmap_en; + RK_S32 smart_en; + /* external line buffer over 3K */ + MppBufferGroup ext_line_buf_grp; + RK_S32 ext_line_buf_size; + MppBuffer ext_line_buf; + MppBuffer buf_pass1; + MppBuffer ext_line_bufs[MAX_FRAME_TASK_NUM]; + + void *tune; } H265eV510HalContext; +#include "hal_h265e_vepu510_tune.c" + static RK_U32 aq_thd_default[16] = { 0, 0, 0, 0, 3, 3, 5, 5, @@ -167,6 +178,43 @@ static RK_S32 aq_qp_dealt_default[16] = { 4, 5, 6, 8, }; +static RK_U32 rdo_lambda_table_I[60] = { + 0x00000012, 0x00000017, + 0x0000001d, 0x00000024, 0x0000002e, 0x0000003a, + 0x00000049, 0x0000005c, 0x00000074, 0x00000092, + 0x000000b8, 0x000000e8, 0x00000124, 0x00000170, + 0x000001cf, 0x00000248, 0x000002df, 0x0000039f, + 0x0000048f, 0x000005bf, 0x0000073d, 0x0000091f, + 0x00000b7e, 0x00000e7a, 0x0000123d, 0x000016fb, + 0x00001cf4, 0x0000247b, 0x00002df6, 0x000039e9, + 0x000048f6, 0x00005bed, 0x000073d1, 0x000091ec, + 0x0000b7d9, 0x0000e7a2, 0x000123d7, 0x00016fb2, + 0x0001cf44, 0x000247ae, 0x0002df64, 0x00039e89, + 0x00048f5c, 0x0005bec8, 0x00073d12, 0x00091eb8, + 0x000b7d90, 0x000e7a23, 0x00123d71, 0x0016fb20, + 0x001cf446, 0x00247ae1, 0x002df640, 0x0039e88c, + 0x0048f5c3, 0x005bec81, 0x0073d119, 0x0091eb85, + 0x00b7d902, 0x00e7a232 +}; + +static RK_U32 rdo_lambda_table_P[60] = { + 0x0000002c, 0x00000038, 0x00000044, 0x00000058, + 0x00000070, 0x00000089, 0x000000b0, 0x000000e0, + 0x00000112, 0x00000160, 0x000001c0, 0x00000224, + 0x000002c0, 0x00000380, 0x00000448, 0x00000580, + 0x00000700, 0x00000890, 0x00000b00, 0x00000e00, + 0x00001120, 0x00001600, 0x00001c00, 0x00002240, + 0x00002c00, 0x00003800, 0x00004480, 0x00005800, + 0x00007000, 0x00008900, 0x0000b000, 0x0000e000, + 0x00011200, 0x00016000, 0x0001c000, 0x00022400, + 0x0002c000, 0x00038000, 0x00044800, 0x00058000, + 0x00070000, 0x00089000, 0x000b0000, 0x000e0000, + 0x00112000, 0x00160000, 0x001c0000, 0x00224000, + 0x002c0000, 0x00380000, 0x00448000, 0x00580000, + 0x00700000, 0x00890000, 0x00b00000, 0x00e00000, + 0x01120000, 0x01600000, 0x01c00000, 0x02240000, +}; + static void setup_ext_line_bufs(H265eV510HalContext *ctx) { RK_S32 i; @@ -296,15 +344,15 @@ static MPP_RET vepu510_h265_setup_hal_bufs(H265eV510HalContext *ctx) return ret; } -static void vepu510_h265_rdo_cfg(H265eVepu510Sqi *reg) +static void vepu510_h265_rdo_cfg(H265eVepu510Sqi *reg, MppEncSceneMode sm) { rdo_skip_par *p_rdo_skip = NULL; rdo_noskip_par *p_rdo_noskip = NULL; pre_cst_par *p_pre_cst = NULL; - reg->subj_opt_cfg.subj_opt_en = 1; + reg->subj_opt_cfg.subj_opt_en = (sm == MPP_ENC_SCENE_MODE_IPC); reg->subj_opt_cfg.subj_opt_strength = 3; - reg->subj_opt_cfg.aq_subj_en = 1; + reg->subj_opt_cfg.aq_subj_en = (sm == MPP_ENC_SCENE_MODE_IPC); reg->subj_opt_cfg.aq_subj_strength = 4; reg->subj_opt_dpth_thd.common_thre_num_grdn_point_dep0 = 64; reg->subj_opt_dpth_thd.common_thre_num_grdn_point_dep1 = 32; @@ -313,7 +361,7 @@ static void vepu510_h265_rdo_cfg(H265eVepu510Sqi *reg) reg->subj_opt_inrar_coef.common_rdo_cu_intra_r_coef_dep1 = 160; /* anti smear */ - reg->smear_opt_cfg0.anti_smear_en = 1; + reg->smear_opt_cfg0.anti_smear_en = (sm == MPP_ENC_SCENE_MODE_IPC); reg->smear_opt_cfg0.smear_stor_en = 0; reg->smear_opt_cfg0.smear_load_en = 0; reg->smear_opt_cfg0.smear_strength = 3; @@ -370,7 +418,7 @@ static void vepu510_h265_rdo_cfg(H265eVepu510Sqi *reg) reg->smear_madp_cov_thd.smear_thre_qp = 30; /* skin_opt */ - reg->skin_opt_cfg.skin_en = 1; + reg->skin_opt_cfg.skin_en = 0; reg->skin_opt_cfg.skin_strength = 3; reg->skin_opt_cfg.thre_uvsqr16_skin = 128; reg->skin_opt_cfg.skin_thre_cst_best_mad = 1000; @@ -385,7 +433,7 @@ static void vepu510_h265_rdo_cfg(H265eVepu510Sqi *reg) reg->subj_opt_dqp1.skin_thre_qp = 31; /* text_opt */ - reg->block_opt_cfg.block_en = 1; + 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; @@ -393,14 +441,14 @@ static void vepu510_h265_rdo_cfg(H265eVepu510Sqi *reg) 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 = 1; + 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 = 1; + 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; @@ -580,7 +628,7 @@ static void vepu510_h265_rdo_cfg(H265eVepu510Sqi *reg) reg->cudecis_thd3.delta0_thre_str_edge_bgrad32_intra = 0; reg->cudecis_thd3.delta1_thre_str_edge_bgrad32_intra = 0; reg->cudecis_thd3.delta2_thre_str_edge_bgrad32_intra = 7; - reg->cudecis_thd3.delta3_thre_str_edge_bgrad32_intra = 0; + reg->cudecis_thd3.delta3_thre_str_edge_bgrad32_intra = 19; reg->cudecis_thd3.base_thre_mad16_intra = 6; reg->cudecis_thd3.delta0_thre_mad16_intra = 0; @@ -666,25 +714,32 @@ static void vepu510_h265_global_cfg_set(H265eV510HalContext *ctx, H265eV510RegSe 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 lambda_idx = 0; - vepu510_h265_rdo_cfg(reg_sqi); + vepu510_h265_rdo_cfg(reg_sqi, sm); 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; - memcpy(®_param->rdo_wgta_qp_grpa_0_51[0], lamd_moda_qp, sizeof(lamd_moda_qp)); + 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; - memcpy(®_param->rdo_wgta_qp_grpa_0_51[0], lamd_modb_qp, sizeof(lamd_modb_qp)); + lambda_idx = ctx->cfg->tune.lambda_idx_p; + memcpy(®_param->rdo_wgta_qp_grpa_0_51[0], + &rdo_lambda_table_P[lambda_idx], H265E_LAMBDA_TAB_SIZE); } reg_param->qnt_bias_comb.qnt_f_bias_i = 171; @@ -693,52 +748,70 @@ static void vepu510_h265_global_cfg_set(H265eV510HalContext *ctx, H265eV510RegSe reg_param->qnt_bias_comb.qnt_f_bias_i = hw->qbias_i; reg_param->qnt_bias_comb.qnt_f_bias_p = hw->qbias_p; } + /* CIME */ { - /* 0x1760 */ - regs->reg_param.me_sqi_comb.cime_pmv_num = 1; - regs->reg_param.me_sqi_comb.cime_fuse = 1; - regs->reg_param.me_sqi_comb.itp_mode = 0; - regs->reg_param.me_sqi_comb.move_lambda = 2; - regs->reg_param.me_sqi_comb.rime_lvl_mrg = 1; - regs->reg_param.me_sqi_comb.rime_prelvl_en = 3; - regs->reg_param.me_sqi_comb.rime_prersu_en = 3; + reg_param->me_sqi_comb.cime_pmv_num = 1; + reg_param->me_sqi_comb.cime_fuse = 1; + reg_param->me_sqi_comb.itp_mode = 1; + reg_param->me_sqi_comb.move_lambda = (sm == MPP_ENC_SCENE_MODE_IPC) ? 2 : 8; + reg_param->me_sqi_comb.rime_lvl_mrg = 1; + reg_param->me_sqi_comb.rime_prelvl_en = 3; + reg_param->me_sqi_comb.rime_prersu_en = 0; + reg_param->cime_mvd_th_comb.cime_mvd_th0 = 8; + reg_param->cime_mvd_th_comb.cime_mvd_th1 = 20; + reg_param->cime_mvd_th_comb.cime_mvd_th2 = 32; + reg_param->cime_madp_th_comb.cime_madp_th = (sm == MPP_ENC_SCENE_MODE_IPC) ? 16 : 0; - /* 0x1764 */ - regs->reg_param.cime_mvd_th_comb.cime_mvd_th0 = 8; - regs->reg_param.cime_mvd_th_comb.cime_mvd_th1 = 20; - regs->reg_param.cime_mvd_th_comb.cime_mvd_th2 = 32; - - /* 0x1768 */ - regs->reg_param.cime_madp_th_comb.cime_madp_th = 16; - - /* 0x176c */ - regs->reg_param.cime_multi_comb.cime_multi0 = 8; - regs->reg_param.cime_multi_comb.cime_multi1 = 12; - regs->reg_param.cime_multi_comb.cime_multi2 = 16; - regs->reg_param.cime_multi_comb.cime_multi3 = 20; + if (sm == MPP_ENC_SCENE_MODE_IPC) { + reg_param->cime_multi_comb.cime_multi0 = 8; + reg_param->cime_multi_comb.cime_multi1 = 12; + reg_param->cime_multi_comb.cime_multi2 = 16; + reg_param->cime_multi_comb.cime_multi3 = 20; + } else { + reg_param->cime_multi_comb.cime_multi0 = 4; + reg_param->cime_multi_comb.cime_multi1 = 4; + reg_param->cime_multi_comb.cime_multi2 = 4; + reg_param->cime_multi_comb.cime_multi3 = 4; + } } /* RIME && FME */ + if (sm == MPP_ENC_SCENE_MODE_IPC) { + reg_param->rime_mvd_th_comb.rime_mvd_th0 = 1; + reg_param->rime_mvd_th_comb.rime_mvd_th1 = 2; + reg_param->rime_mvd_th_comb.fme_madp_th = 0; + reg_param->rime_madp_th_comb.rime_madp_th0 = 8; + reg_param->rime_madp_th_comb.rime_madp_th1 = 16; + reg_param->rime_multi_comb.rime_multi0 = 4; + reg_param->rime_multi_comb.rime_multi1 = 8; + reg_param->rime_multi_comb.rime_multi2 = 12; + } else { + reg_param->rime_mvd_th_comb.rime_mvd_th0 = 0; + reg_param->rime_mvd_th_comb.rime_mvd_th1 = 0; + reg_param->rime_mvd_th_comb.fme_madp_th = 30; + reg_param->rime_madp_th_comb.rime_madp_th0 = 0; + reg_param->rime_madp_th_comb.rime_madp_th1 = 0; + reg_param->rime_multi_comb.rime_multi0 = 4; + reg_param->rime_multi_comb.rime_multi1 = 4; + reg_param->rime_multi_comb.rime_multi2 = 4; + } + { - /* 0x1770 */ - regs->reg_param.rime_mvd_th_comb.rime_mvd_th0 = 1; - regs->reg_param.rime_mvd_th_comb.rime_mvd_th1 = 2; - regs->reg_param.rime_mvd_th_comb.fme_madp_th = 0; - - /* 0x1774 */ - regs->reg_param.rime_madp_th_comb.rime_madp_th0 = 8; - regs->reg_param.rime_madp_th_comb.rime_madp_th1 = 16; - - /* 0x1778 */ - regs->reg_param.rime_multi_comb.rime_multi0 = 4; - regs->reg_param.rime_multi_comb.rime_multi1 = 8; - regs->reg_param.rime_multi_comb.rime_multi2 = 12; + /* 0x1064 */ + regs->reg_rc_roi.madi_st_thd.madi_th0 = 5; + regs->reg_rc_roi.madi_st_thd.madi_th1 = 12; + regs->reg_rc_roi.madi_st_thd.madi_th2 = 20; + /* 0x1068 */ + regs->reg_rc_roi.madp_st_thd0.madp_th0 = 4 << 4; + regs->reg_rc_roi.madp_st_thd0.madp_th1 = 9 << 4; + /* 0x106C */ + regs->reg_rc_roi.madp_st_thd1.madp_th2 = 15 << 4; /* 0x177C */ - regs->reg_param.cmv_st_th_comb.cmv_th0 = 64; - regs->reg_param.cmv_st_th_comb.cmv_th1 = 96; - regs->reg_param.cmv_st_th_comb.cmv_th2 = 128; + reg_param->cmv_st_th_comb.cmv_th0 = 64; + reg_param->cmv_st_th_comb.cmv_th1 = 96; + reg_param->cmv_st_th_comb.cmv_th2 = 128; } } @@ -798,6 +871,11 @@ MPP_RET hal_h265e_v510_deinit(void *hal) ctx->reg_cfg = NULL; } + if (ctx->tune) { + vepu510_h265e_tune_deinit(ctx->tune); + ctx->tune = NULL; + } + hal_h265e_leave(); return MPP_OK; } @@ -875,6 +953,8 @@ MPP_RET hal_h265e_v510_init(void *hal, MppEncHalCfg *cfg) ctx->output_cb = cfg->output_cb; cfg->cap_recn_out = 1; + ctx->tune = vepu510_h265e_tune_init(ctx); + DONE: if (ret) hal_h265e_v510_deinit(hal); @@ -1019,7 +1099,6 @@ static MPP_RET vepu510_h265_set_rc_regs(H265eV510HalContext *ctx, H265eV510RegSe if (rc->rc_mode == MPP_ENC_RC_MODE_FIXQP) { reg_frm->common.enc_pic.pic_qp = rc_cfg->quality_target; reg_frm->synt_sli1.sli_qp = rc_cfg->quality_target; - reg_frm->common.rc_qp.rc_max_qp = rc_cfg->quality_target; reg_frm->common.rc_qp.rc_min_qp = rc_cfg->quality_target; } else { @@ -1041,6 +1120,25 @@ static MPP_RET vepu510_h265_set_rc_regs(H265eV510HalContext *ctx, H265eV510RegSe reg_frm->common.rc_qp.rc_min_qp = rc_cfg->quality_min; reg_frm->common.rc_tgt.ctu_ebit = ctu_target_bits_mul_16; + { + /* fixed frame qp */ + RK_S32 fqp_min, fqp_max; + + if (ctx->frame_type == INTRA_FRAME) { + fqp_min = rc->fqp_min_i; + fqp_max = rc->fqp_max_i; + } else { + fqp_min = rc->fqp_min_p; + fqp_max = rc->fqp_max_p; + } + + if ((fqp_min == fqp_max) && (fqp_min >= 0) && (fqp_max <= 51)) { + reg_frm->common.enc_pic.pic_qp = fqp_min; + reg_frm->synt_sli1.sli_qp = fqp_min; + reg_frm->common.rc_qp.rc_qp_range = 0; + } + } + reg_rc->rc_dthd_0_8[0] = 2 * negative_bits_thd; reg_rc->rc_dthd_0_8[1] = negative_bits_thd; reg_rc->rc_dthd_0_8[2] = positive_bits_thd; @@ -1230,7 +1328,7 @@ static void vepu510_h265_set_slice_regs(H265eSyntax_new *syn, H265eVepu510Frame regs->synt_sli1.sp_dblk_fltr_dis = syn->sp.sli_dblk_fltr_dis; regs->synt_sli1.dblk_fltr_ovrd_flg = syn->sp.dblk_fltr_ovrd_flg; regs->synt_sli1.sli_cb_qp_ofst = syn->sp.sli_cb_qp_ofst; - regs->synt_sli1.max_mrg_cnd = syn->sp.max_mrg_cnd; + regs->synt_sli1.max_mrg_cnd = 3;//syn->sp.max_mrg_cnd; regs->synt_sli1.col_ref_idx = syn->sp.col_ref_idx; regs->synt_sli1.col_frm_l0_flg = syn->sp.col_frm_l0_flg; @@ -1295,7 +1393,8 @@ static void vepu510_h265_set_me_regs(H265eV510HalContext *ctx, H265eSyntax_new * regs->common.me_cach.colmv_stor_hevc = 1; } - regs->common.me_cach.cime_zero_thre = 1024; + regs->common.me_cach.cime_zero_thre = (ctx->cfg->tune.scene_mode == + MPP_ENC_SCENE_MODE_IPC) ? 1024 : 64; regs->common.me_cach.fme_prefsu_en = 0; } @@ -1567,6 +1666,7 @@ MPP_RET hal_h265e_v510_gen_regs(void *hal, HalEncTask *task) Vepu510ControlCfg *reg_ctl = ®s->reg_ctl; H265eVepu510Frame *reg_frm = ®s->reg_frm; Vepu510RcRoi *reg_klut = ®s->reg_rc_roi; + MppEncSceneMode sm = ctx->cfg->tune.scene_mode; MPP_RET ret = MPP_OK; hal_h265e_enter(); @@ -1633,7 +1733,7 @@ MPP_RET hal_h265e_v510_gen_regs(void *hal, HalEncTask *task) reg_frm->common.src_proc.tile4x4_en = 0; reg_klut->klut_ofst.chrm_klut_ofst = (ctx->frame_type == INTRA_FRAME) ? 6 : - (ctx->cfg->tune.scene_mode == MPP_ENC_SCENE_MODE_IPC ? 9 : 6); + (sm == MPP_ENC_SCENE_MODE_IPC ? 9 : 6); reg_frm->sao_cfg.sao_lambda_multi = 5; @@ -1646,10 +1746,10 @@ MPP_RET hal_h265e_v510_gen_regs(void *hal, HalEncTask *task) reg_frm->rdo_cfg.chrm_spcl = 0; reg_frm->rdo_cfg.cu_inter_e = 0xdb; - reg_frm->rdo_cfg.lambda_qp_use_avg_cu16_flag = 1; + 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 = 1; - reg_frm->rdo_cfg.atr_e = 1; + reg_frm->rdo_cfg.atf_e = (sm == MPP_ENC_SCENE_MODE_IPC); + reg_frm->rdo_cfg.atr_e = (sm == MPP_ENC_SCENE_MODE_IPC); if (syn->pp.num_long_term_ref_pics_sps) { reg_frm->rdo_cfg.ltm_col = 0; @@ -1693,6 +1793,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); /* two pass register patch */ if (frm->save_pass1) @@ -1848,8 +1949,7 @@ static MPP_RET vepu510_h265_set_feedback(H265eV510HalContext *ctx, HalEncTask *e Vepu510H265eFrmCfg *frm = ctx->frms[enc_task->flags.reg_idx]; Vepu510H265Fbk *fb = &frm->feedback; MppEncCfgSet *cfg = ctx->cfg; - RK_S32 mb64_num = ((cfg->prep.width + 63) / 64) * ((cfg->prep.height + 63) / 64); - RK_S32 mb8_num = (mb64_num << 6); + RK_S32 mb8_num = MPP_ALIGN(cfg->prep.width, 8) * MPP_ALIGN(cfg->prep.height, 8) / 64; RK_S32 mb4_num = (mb8_num << 2); H265eV510StatusElem *elem = (H265eV510StatusElem *)frm->regs_ret; RK_U32 hw_status = elem->hw_status; @@ -1902,36 +2002,15 @@ static MPP_RET vepu510_h265_set_feedback(H265eV510HalContext *ctx, HalEncTask *e fb->st_lvl4_intra_num += elem->st.st_pnum_i4.pnum_i4; memcpy(&fb->st_cu_num_qp[0], &elem->st.st_b8_qp, 52 * sizeof(RK_U32)); - hal_rc_ret->bit_real += fb->out_strm_size * 8; - - if (fb->st_mb_num) { - fb->st_madi = fb->st_madi / fb->st_mb_num; - } else { - fb->st_madi = 0; - } - if (fb->st_ctu_num) { - fb->st_madp = fb->st_madp / fb->st_ctu_num; - } else { - fb->st_madp = 0; - } - if (mb4_num > 0) hal_rc_ret->iblk4_prop = ((((fb->st_lvl4_intra_num + fb->st_lvl8_intra_num) << 2) + (fb->st_lvl16_intra_num << 4) + (fb->st_lvl32_intra_num << 6)) << 8) / mb4_num; - if (mb64_num > 0) { - /* - hal_cfg[k].inter_lv8_prop = ((fb->st_lvl8_inter_num + (fb->st_lvl16_inter_num << 2) + - (fb->st_lvl32_inter_num << 4) + - (fb->st_lvl64_inter_num << 6)) << 8) / mb8_num;*/ - + if (mb8_num > 0) { hal_rc_ret->quality_real = fb->qp_sum / mb8_num; - // hal_cfg[k].sse = fb->sse_sum / mb64_num; } - hal_rc_ret->madi = fb->st_madi; - hal_rc_ret->madp = fb->st_madp; hal_h265e_leave(); return MPP_OK; } @@ -2207,8 +2286,9 @@ MPP_RET hal_h265e_v510_ret_task(void *hal, HalEncTask *task) h265e_dpb_hal_end(ctx->dpb, frm->hal_curr_idx); h265e_dpb_hal_end(ctx->dpb, frm->hal_refr_idx); - hal_h265e_dbg_detail("output stream size %d\n", fb->out_strm_size); + vepu510_h265e_tune_stat_update(ctx->tune, enc_task); + hal_h265e_dbg_detail("output stream size %d\n", fb->out_strm_size); hal_h265e_leave(); return MPP_OK; } diff --git a/mpp/hal/rkenc/h265e/hal_h265e_vepu510_tune.c b/mpp/hal/rkenc/h265e/hal_h265e_vepu510_tune.c new file mode 100644 index 00000000..785b7b0d --- /dev/null +++ b/mpp/hal/rkenc/h265e/hal_h265e_vepu510_tune.c @@ -0,0 +1,241 @@ +/* + * Copyright 2024 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hal_enc_task.h" +#include "hal_h265e_vepu510_reg.h" + +typedef struct HalH265eVepu510Tune_t { + H265eV510HalContext *ctx; + + RK_S32 pre_madp[2]; + RK_S32 pre_madi[2]; +} HalH265eVepu510Tune; + +static HalH265eVepu510Tune *vepu510_h265e_tune_init(H265eV510HalContext *ctx) +{ + HalH265eVepu510Tune *tune = mpp_malloc(HalH265eVepu510Tune, 1); + + if (NULL == tune) + return tune; + + tune->ctx = ctx; + tune->pre_madi[0] = tune->pre_madi[1] = -1; + tune->pre_madp[0] = tune->pre_madp[1] = -1; + + return tune; +} + +static void vepu510_h265e_tune_deinit(void *tune) +{ + MPP_FREE(tune); +} + +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; + + 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; + 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_clip.aq16_rnge = 5; + r->aq_clip.aq32_rnge = 5; + r->aq_clip.aq8_rnge = 10; + r->aq_clip.aq16_dif0 = 12; + r->aq_clip.aq16_dif1 = 12; +} + +static void vepu510_h265e_tune_reg_patch(void *p) +{ + HalH265eVepu510Tune *tune = (HalH265eVepu510Tune *)p; + H265eV510HalContext *ctx = NULL; + RK_S32 scene_mode = 0; + (void)ctx; + (void)scene_mode; + + if (NULL == tune) + return; + + vepu510_h265e_tune_aq(tune); +} + +static void vepu510_h265e_tune_stat_update(void *p, HalEncTask *task) +{ + HalH265eVepu510Tune *tune = (HalH265eVepu510Tune *)p; + EncRcTaskInfo *hal_rc_ret = (EncRcTaskInfo *)&task->rc_task->info; + + if (NULL == tune) + return; + + H265eV510HalContext *ctx = tune->ctx;; + RK_S32 task_idx = task->flags.reg_idx; + Vepu510H265eFrmCfg *frm = ctx->frms[task_idx]; + Vepu510H265Fbk *fb = &frm->feedback; + H265eV510RegSet *regs_set = frm->regs_set; + H265eV510StatusElem *elem = frm->regs_ret; + MppEncCfgSet *cfg = ctx->cfg; + RK_U32 b16_num = MPP_ALIGN(cfg->prep.width, 16) * MPP_ALIGN(cfg->prep.height, 16) / 256; + RK_U32 madi_cnt = 0, madp_cnt = 0; + RK_S32 i = 0; + + RK_U32 madi_th_cnt0 = elem->st.st_madi_lt_num0.madi_th_lt_cnt0 + + elem->st.st_madi_rt_num0.madi_th_rt_cnt0 + + elem->st.st_madi_lb_num0.madi_th_lb_cnt0 + + elem->st.st_madi_rb_num0.madi_th_rb_cnt0; + RK_U32 madi_th_cnt1 = elem->st.st_madi_lt_num0.madi_th_lt_cnt1 + + elem->st.st_madi_rt_num0.madi_th_rt_cnt1 + + elem->st.st_madi_lb_num0.madi_th_lb_cnt1 + + elem->st.st_madi_rb_num0.madi_th_rb_cnt1; + RK_U32 madi_th_cnt2 = elem->st.st_madi_lt_num1.madi_th_lt_cnt2 + + elem->st.st_madi_rt_num1.madi_th_rt_cnt2 + + elem->st.st_madi_lb_num1.madi_th_lb_cnt2 + + elem->st.st_madi_rb_num1.madi_th_rb_cnt2; + RK_U32 madi_th_cnt3 = elem->st.st_madi_lt_num1.madi_th_lt_cnt3 + + elem->st.st_madi_rt_num1.madi_th_rt_cnt3 + + elem->st.st_madi_lb_num1.madi_th_lb_cnt3 + + elem->st.st_madi_rb_num1.madi_th_rb_cnt3; + RK_U32 madp_th_cnt0 = elem->st.st_madp_lt_num0.madp_th_lt_cnt0 + + elem->st.st_madp_rt_num0.madp_th_rt_cnt0 + + elem->st.st_madp_lb_num0.madp_th_lb_cnt0 + + elem->st.st_madp_rb_num0.madp_th_rb_cnt0; + RK_U32 madp_th_cnt1 = elem->st.st_madp_lt_num0.madp_th_lt_cnt1 + + elem->st.st_madp_rt_num0.madp_th_rt_cnt1 + + elem->st.st_madp_lb_num0.madp_th_lb_cnt1 + + elem->st.st_madp_rb_num0.madp_th_rb_cnt1; + RK_U32 madp_th_cnt2 = elem->st.st_madp_lt_num1.madp_th_lt_cnt2 + + elem->st.st_madp_rt_num1.madp_th_rt_cnt2 + + elem->st.st_madp_lb_num1.madp_th_lb_cnt2 + + elem->st.st_madp_rb_num1.madp_th_rb_cnt2; + RK_U32 madp_th_cnt3 = elem->st.st_madp_lt_num1.madp_th_lt_cnt3 + + elem->st.st_madp_rt_num1.madp_th_rt_cnt3 + + elem->st.st_madp_lb_num1.madp_th_lb_cnt3 + + elem->st.st_madp_rb_num1.madp_th_rb_cnt3; + + madi_cnt = (6 * madi_th_cnt3 + 5 * madi_th_cnt2 + 4 * madi_th_cnt1) >> 2; + hal_rc_ret->complex_level = (madi_cnt * 100 > 30 * b16_num) ? 2 : + (madi_cnt * 100 > 13 * b16_num) ? 1 : 0; + + { + RK_U32 md_cnt = 0, motion_level = 0; + + if (ctx->smart_en) + md_cnt = (12 * madp_th_cnt3 + 11 * madp_th_cnt2 + 8 * madp_th_cnt1) >> 2; + else + md_cnt = (24 * madp_th_cnt3 + 22 * madp_th_cnt2 + 17 * madp_th_cnt1) >> 2; + + if (md_cnt * 100 > 15 * b16_num) + motion_level = 200; + else if (md_cnt * 100 > 5 * b16_num) + motion_level = 100; + else if (md_cnt * 100 > (b16_num >> 2)) + motion_level = 1; + else + motion_level = 0; + hal_rc_ret->motion_level = motion_level; + } + hal_h265e_dbg_output("complex_level %d motion_level %d\n", + hal_rc_ret->complex_level, hal_rc_ret->motion_level); + + fb->st_madi = madi_th_cnt0 * regs_set->reg_rc_roi.madi_st_thd.madi_th0 + + madi_th_cnt1 * (regs_set->reg_rc_roi.madi_st_thd.madi_th0 + + regs_set->reg_rc_roi.madi_st_thd.madi_th1) / 2 + + madi_th_cnt2 * (regs_set->reg_rc_roi.madi_st_thd.madi_th1 + + regs_set->reg_rc_roi.madi_st_thd.madi_th2) / 2 + + madi_th_cnt3 * regs_set->reg_rc_roi.madi_st_thd.madi_th2; + + madi_cnt = madi_th_cnt0 + madi_th_cnt1 + madi_th_cnt2 + madi_th_cnt3; + if (madi_cnt) + fb->st_madi = fb->st_madi / madi_cnt; + + fb->st_madp = madp_th_cnt0 * regs_set->reg_rc_roi.madp_st_thd0.madp_th0 + + madp_th_cnt1 * (regs_set->reg_rc_roi.madp_st_thd0.madp_th0 + + regs_set->reg_rc_roi.madp_st_thd0.madp_th1) / 2 + + madp_th_cnt2 * (regs_set->reg_rc_roi.madp_st_thd0.madp_th1 + + regs_set->reg_rc_roi.madp_st_thd1.madp_th2) / 2 + + madp_th_cnt3 * regs_set->reg_rc_roi.madp_st_thd1.madp_th2; + + madp_cnt = madp_th_cnt0 + madp_th_cnt1 + madp_th_cnt2 + madp_th_cnt3; + if (madp_cnt) + fb->st_madp = fb->st_madp / madp_cnt; + + fb->st_mb_num += elem->st.st_bnum_b16.num_b16; + fb->frame_type = task->rc_task->frm.is_intra ? INTRA_FRAME : INTER_P_FRAME; + hal_rc_ret->bit_real += fb->out_strm_size * 8; + hal_h265e_dbg_output("bit_real %d quality_real %d\n", + hal_rc_ret->bit_real, hal_rc_ret->quality_real); + + { + /* This code snippet may be unnecessary, but it is kept for rv1103b compatibility. */ + RK_S32 bit_tgt = hal_rc_ret->bit_target; + RK_S32 bit_real = hal_rc_ret->bit_real; + RK_S32 real_lvl = 0; + + memcpy(fb->tgt_sub_real_lvl, ctx->last_frame_fb.tgt_sub_real_lvl, 6 * sizeof(RK_S8)); + for (i = 3; i >= 0; i--) + fb->tgt_sub_real_lvl[i + 1] = fb->tgt_sub_real_lvl[i]; + + if (bit_tgt > bit_real) { + fb->tgt_sub_real_lvl[0] = (bit_tgt > bit_real * 6 / 4) ? 3 : + (bit_tgt > bit_real * 5 / 4) ? 2 : + (bit_tgt > bit_real * 9 / 8) ? 1 : 0; + } else { + fb->tgt_sub_real_lvl[0] = (bit_real > bit_tgt * 2) ? -5 : + (bit_real > bit_tgt * 7 / 4) ? -4 : + (bit_real > bit_tgt * 6 / 4) ? -3 : + (bit_real > bit_tgt * 5 / 4) ? -2 : -1; + } + + for (i = 0; i < 5; i ++) + real_lvl += fb->tgt_sub_real_lvl[i]; + if (task->rc_task->frm.is_intra) + fb->tgt_sub_real_lvl[5] = 0; + + if (real_lvl < -9) + fb->tgt_sub_real_lvl[5] = 2; + else if (real_lvl < -2 && fb->tgt_sub_real_lvl[5] < 2) + fb->tgt_sub_real_lvl[5] = 1; + } + + if (fb->st_mb_num) + fb->st_madi = fb->st_madi / fb->st_mb_num; + else + fb->st_madi = 0; + + if (fb->st_ctu_num) + fb->st_madp = fb->st_madp / fb->st_ctu_num; + else + fb->st_madp = 0; + + hal_rc_ret->madi = fb->st_madi; + hal_rc_ret->madp = fb->st_madp; /* unused ?? */ +} diff --git a/test/mpi_enc_test.c b/test/mpi_enc_test.c index a00a47dd..ef6d447e 100644 --- a/test/mpi_enc_test.c +++ b/test/mpi_enc_test.c @@ -118,6 +118,7 @@ typedef struct { RK_S32 gop_len; RK_S32 vi_len; RK_S32 scene_mode; + RK_S32 cu_qp_delta_depth; RK_S64 first_frm; RK_S64 first_pkt; @@ -178,6 +179,7 @@ MPP_RET test_ctx_init(MpiEncMultiCtxInfo *info) p->fps_out_den = cmd->fps_out_den; 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->mdinfo_size = (MPP_VIDEO_CodingHEVC == cmd->type) ? (MPP_ALIGN(p->hor_stride, 32) >> 5) * (MPP_ALIGN(p->ver_stride, 32) >> 5) * 16 : @@ -315,6 +317,8 @@ MPP_RET test_mpp_enc_cfg_setup(MpiEncMultiCtxInfo *info) if (!p->bps) 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:scene_mode", p->scene_mode); mpp_enc_cfg_set_s32(cfg, "prep:width", p->width); diff --git a/utils/mpi_enc_utils.c b/utils/mpi_enc_utils.c index dd023bc3..db1744c0 100644 --- a/utils/mpi_enc_utils.c +++ b/utils/mpi_enc_utils.c @@ -488,6 +488,19 @@ RK_S32 mpi_enc_opt_sm(void *ctx, const char *next) return 0; } +RK_S32 mpi_enc_opt_qpdd(void *ctx, const char *next) +{ + MpiEncTestArgs *cmd = (MpiEncTestArgs *)ctx; + + if (next) { + cmd->cu_qp_delta_depth = atoi(next); + return 1; + } + + mpp_err("invalid cu_qp_delta_depth\n"); + return 0; +} + RK_S32 mpi_enc_opt_help(void *ctx, const char *next) { (void)ctx; @@ -518,6 +531,7 @@ static MppOptInfo enc_opts[] = { {"ini", "ini file", "encoder extra ini config file", mpi_enc_opt_ini}, {"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}, }; static RK_U32 enc_opt_cnt = MPP_ARRAY_ELEMS(enc_opts); @@ -597,9 +611,7 @@ MPP_RET mpi_enc_test_cmd_update_by_args(MpiEncTestArgs* cmd, int argc, char **ar /* mark option end */ mpp_opt_add(opts, NULL); - ret = mpp_opt_parse(opts, argc, argv); - /* check essential parameter */ if (cmd->type <= MPP_VIDEO_CodingAutoDetect) { mpp_err("invalid type %d\n", cmd->type); diff --git a/utils/mpi_enc_utils.h b/utils/mpi_enc_utils.h index baa133b2..572e22e9 100644 --- a/utils/mpi_enc_utils.h +++ b/utils/mpi_enc_utils.h @@ -77,6 +77,9 @@ typedef struct MpiEncTestArgs_t { /* -sm scene_mode */ RK_S32 scene_mode; + /* -qpdd cu_qp_delta_depth */ + RK_S32 cu_qp_delta_depth; + /* -v q runtime log disable flag */ RK_U32 quiet; /* -v f runtime fps log flag */