diff --git a/inc/mpp_rc_defs.h b/inc/mpp_rc_defs.h index 2f02c7c8..06a55e05 100644 --- a/inc/mpp_rc_defs.h +++ b/inc/mpp_rc_defs.h @@ -21,6 +21,13 @@ #define MAX_CPB_REFS (8) +typedef enum EncFrmType_e { + INTER_P_FRAME = 0, + INTER_B_FRAME = 1, + INTRA_FRAME = 2, + INTER_VI_FRAME = 3, +} EncFrmType; + /* * EncFrmStatus controls record the encoding frame status and also control * work flow of encoder. It is the communicat channel between encoder implement @@ -163,6 +170,8 @@ typedef struct EncRcForceCfg_t { * hw -> rc / hal bit_real / quality_real / madi / madp */ typedef struct EncRcCommonInfo_t { + EncFrmType frame_type; + /* rc to hal */ RK_S32 bit_target; RK_S32 bit_max; diff --git a/mpp/codec/inc/mpp_rc.h b/mpp/codec/inc/mpp_rc.h index 32e4abd0..5368fd5b 100644 --- a/mpp/codec/inc/mpp_rc.h +++ b/mpp/codec/inc/mpp_rc.h @@ -53,13 +53,6 @@ typedef struct { RK_S32 count; } MppPIDCtx; -typedef enum ENC_FRAME_TYPE_E { - INTER_P_FRAME = 0, - INTER_B_FRAME = 1, - INTRA_FRAME = 2, - INTER_VI_FRAME = 3, -} ENC_FRAME_TYPE; - /* * MppRateControl has three steps work: * @@ -98,7 +91,6 @@ typedef enum RC_PARAM_OPS { typedef struct RecordNode_t { struct list_head list; - ENC_FRAME_TYPE frm_type; /* @frm_cnt starts from ONE */ RK_U32 frm_cnt; RK_U32 bps; diff --git a/mpp/codec/mpp_enc_impl.cpp b/mpp/codec/mpp_enc_impl.cpp index 1bc6ee87..94f942c3 100644 --- a/mpp/codec/mpp_enc_impl.cpp +++ b/mpp/codec/mpp_enc_impl.cpp @@ -2917,6 +2917,11 @@ void *mpp_enc_async_thread(void *data) hal_task_hnd_get_info(hnd, &info); mpp_assert(!info.status.enc_done); + + /* NOTE: update pointer in rc_task */ + info.task.rc_task = &info.rc; + info.task.frm_cfg = &info.usr; + enc_async_wait_task(enc, &info); hal_task_hnd_set_status(hnd, TASK_IDLE); wait.task_hnd = 0; diff --git a/mpp/codec/rc/rc_base.cpp b/mpp/codec/rc/rc_base.cpp index d2c7712d..14926459 100644 --- a/mpp/codec/rc/rc_base.cpp +++ b/mpp/codec/rc/rc_base.cpp @@ -58,10 +58,10 @@ MPP_RET mpp_data_init_v2(MppDataV2 **data, RK_S32 size, RK_S32 value) return MPP_ERR_MALLOC; } p->size = size; - p->len = 0; - p->val = (RK_S32 *)(p + 1); p->pos_r = 0; + p->pos_pw = 0; p->pos_w = 0; + p->pos_ahead = 0; p->sum = 0; *data = p; @@ -79,16 +79,48 @@ void mpp_data_reset_v2(MppDataV2 *p, RK_S32 val) RK_S32 i; RK_S32 *data = p->val; - p->pos_r = p->size; + p->pos_pw = 0; p->pos_w = 0; + p->pos_r = p->size; p->sum = val * p->size; for (i = 0; i < p->size; i++) *data++ = val; } +void mpp_data_preset_v2(MppDataV2 *p, RK_S32 val) +{ + mpp_assert(p); + if (p->pos_r == p->size) { + p->pos_r--; + p->sum -= p->val[p->pos_pw]; + } + mpp_assert(p->pos_r < p->size); + p->val[p->pos_pw] = val; + p->sum += p->val[p->pos_pw]; + p->pos_pw++; + p->pos_r++; + if (p->pos_pw >= p->size) { + p->pos_pw = 0; + } + p->pos_ahead++; +} + void mpp_data_update_v2(MppDataV2 *p, RK_S32 val) { + mpp_assert(p->pos_ahead >= 0 && p->pos_ahead <= 2); + if (p->pos_ahead) { + p->sum += val - p->val[p->pos_w]; + p->val[p->pos_w] = val; + p->pos_w++; + if (p->pos_w >= p->size) + p->pos_w = 0; + + p->pos_ahead--; + + return; + } + mpp_assert(p); if (p->pos_r == p->size) { p->pos_r--; @@ -99,9 +131,8 @@ void mpp_data_update_v2(MppDataV2 *p, RK_S32 val) p->sum += p->val[p->pos_w]; p->pos_w++; p->pos_r++; - if (p->pos_w >= p->size) { + if (p->pos_w >= p->size) p->pos_w = 0; - } } RK_S32 mpp_data_get_pre_val_v2(MppDataV2 *p, RK_S32 idx) @@ -112,6 +143,7 @@ RK_S32 mpp_data_get_pre_val_v2(MppDataV2 *p, RK_S32 idx) mpp_assert(p->pos_w < p->size); mpp_assert(idx < p->size); RK_S32 pos = 0; + pos = p->pos_w - 1; if (pos - idx < 0) { mpp_assert(p->pos_r == p->size); diff --git a/mpp/codec/rc/rc_base.h b/mpp/codec/rc/rc_base.h index 62ea7073..931ff42b 100644 --- a/mpp/codec/rc/rc_base.h +++ b/mpp/codec/rc/rc_base.h @@ -27,11 +27,11 @@ /* * 1. MppData - data statistic struct - * size - max valid data number - * len - valid data number - * pos_r - current data read position - * pos_w - current data write position - * val - buffer array pointer + * size - max valid data number + * pos_pw - current data preset write position + * pos_w - current data write position + * pos_r - current data read position + * val - buffer array pointer * * When statistic length is less than 8 use direct save mode which will move * all the data on each update. @@ -40,43 +40,14 @@ */ typedef struct MppDataV2_t { RK_S32 size; - RK_S32 len; - RK_S32 pos_w; RK_S32 pos_r; - RK_S32 *val; + RK_S32 pos_pw; + RK_S32 pos_w; + RK_S32 pos_ahead; RK_S64 sum; + RK_S32 val[]; } MppDataV2; -typedef struct RecordNodeV2_t { - struct list_head list; - ENC_FRAME_TYPE frm_type; - /* @frm_cnt starts from ONE */ - RK_U32 frm_cnt; - RK_U32 bps; - RK_U32 fps; - RK_S32 gop; - RK_S32 bits_per_pic; - RK_S32 bits_per_intra; - RK_S32 bits_per_inter; - RK_U32 tgt_bits; - RK_U32 bit_min; - RK_U32 bit_max; - RK_U32 real_bits; - RK_S32 acc_intra_bits_in_fps; - RK_S32 acc_inter_bits_in_fps; - RK_S32 last_fps_bits; - float last_intra_percent; - - /* hardware result */ - RK_S32 qp_sum; - RK_S64 sse_sum; - RK_S32 set_qp; - RK_S32 qp_min; - RK_S32 qp_max; - RK_S32 real_qp; - RK_S32 wlen; -} RecordNodeV2; - #ifdef __cplusplus extern "C" { #endif @@ -84,6 +55,7 @@ extern "C" { MPP_RET mpp_data_init_v2(MppDataV2 **p, RK_S32 len, RK_S32 value); void mpp_data_deinit_v2(MppDataV2 *p); void mpp_data_reset_v2(MppDataV2 *p, RK_S32 val); +void mpp_data_preset_v2(MppDataV2 *p, RK_S32 val); void mpp_data_update_v2(MppDataV2 *p, RK_S32 val); RK_S32 mpp_data_sum_v2(MppDataV2 *p); RK_S32 mpp_data_mean_v2(MppDataV2 *p); diff --git a/mpp/codec/rc/rc_ctx.h b/mpp/codec/rc/rc_ctx.h index 71042cf9..c4264c33 100644 --- a/mpp/codec/rc/rc_ctx.h +++ b/mpp/codec/rc/rc_ctx.h @@ -22,7 +22,6 @@ typedef struct RcModelV2Ctx_t { RcCfg usr_cfg; - RK_U32 frame_type; RK_U32 last_frame_type; RK_S64 gop_total_bits; RK_U32 bit_per_frame; @@ -110,7 +109,7 @@ MPP_RET bits_model_init(RcModelV2Ctx *ctx); MPP_RET bits_model_deinit(RcModelV2Ctx *ctx); MPP_RET bits_model_alloc(RcModelV2Ctx *ctx, EncRcTaskInfo *cfg, RK_S64 total_bits); -MPP_RET bits_model_update(RcModelV2Ctx *ctx, RK_S32 real_bit, RK_U32 madi); +MPP_RET bits_model_update(RcModelV2Ctx *ctx, EncRcTaskInfo *cfg); MPP_RET calc_next_i_ratio(RcModelV2Ctx *ctx); MPP_RET check_re_enc(RcModelV2Ctx *ctx, EncRcTaskInfo *cfg); diff --git a/mpp/codec/rc/rc_model_v2.c b/mpp/codec/rc/rc_model_v2.c index 4e147cf8..1e3beb69 100644 --- a/mpp/codec/rc/rc_model_v2.c +++ b/mpp/codec/rc/rc_model_v2.c @@ -255,7 +255,7 @@ void bits_frm_init(RcModelV2Ctx *ctx) RK_S32 moving_judge_update(RcModelV2Ctx *ctx, EncRcTaskInfo *cfg) { - switch (ctx->frame_type) { + switch (cfg->frame_type) { case INTRA_FRAME: { mpp_data_update_v2(ctx->pre_i_bit, cfg->bit_real); mpp_data_update_v2(ctx->pre_i_mean_qp, cfg->quality_real); @@ -285,35 +285,88 @@ void bit_statics_update(RcModelV2Ctx *ctx, RK_U32 real_bit) ctx->avg_gbits = (gop_len - 1) * (RK_S64)mean_pbits + mean_ibits; } -MPP_RET bits_model_update(RcModelV2Ctx *ctx, RK_S32 real_bit, RK_U32 madi) +MPP_RET bits_model_preset(RcModelV2Ctx *ctx, EncRcTaskInfo *info) { RcCfg *usr_cfg = &ctx->usr_cfg; + RK_S32 preset_bit = info->bit_target; + RK_S32 water_level = 0; + + mpp_data_preset_v2(ctx->stat_rate, preset_bit != 0); + mpp_data_preset_v2(ctx->stat_bits, preset_bit); + + ctx->ins_bps = mpp_data_sum_v2(ctx->stat_bits) / usr_cfg->stats_time; + if (preset_bit + ctx->stat_watl > ctx->watl_thrd) + water_level = ctx->watl_thrd - ctx->bit_per_frame; + else + water_level = preset_bit + ctx->stat_watl - ctx->bit_per_frame; + + if (water_level < 0) { + water_level = 0; + } + ctx->stat_watl = water_level; + switch (info->frame_type) { + case INTRA_FRAME : { + mpp_data_preset_v2(ctx->i_bit, preset_bit); + ctx->i_sumbits = mpp_data_sum_v2(ctx->i_bit); + ctx->i_scale = 80 * ctx->i_sumbits / (2 * ctx->p_sumbits); + rc_dbg_rc("i_sumbits %d p_sumbits %d i_scale %d\n", + ctx->i_sumbits, ctx->p_sumbits, ctx->i_scale); + } break; + case INTER_P_FRAME : { + mpp_data_preset_v2(ctx->p_bit, preset_bit); + ctx->p_sumbits = mpp_data_sum_v2(ctx->p_bit); + + /* Avoid div zero when P frame successive drop */ + if (!ctx->p_sumbits) + ctx->p_sumbits = 1; + + ctx->p_scale = 16; + } break; + case INTER_VI_FRAME : { + mpp_data_preset_v2(ctx->vi_bit, preset_bit); + ctx->vi_sumbits = mpp_data_sum_v2(ctx->vi_bit); + ctx->vi_scale = 80 * ctx->vi_sumbits / (2 * ctx->p_sumbits); + /* NOTE: vi_scale may be set to zero. So we should limit the range */ + ctx->vi_scale = mpp_clip(ctx->vi_scale, 16, 320); + } break; + default : { + } break; + } + return MPP_OK; +} + +MPP_RET bits_model_update(RcModelV2Ctx *ctx, EncRcTaskInfo *cfg) +{ + RcCfg *usr_cfg = &ctx->usr_cfg; + RK_S32 real_bit = cfg->bit_real; + RK_U32 madi = cfg->madi; RK_S32 water_level = 0; rc_dbg_func("enter %p\n", ctx); mpp_data_update_v2(ctx->stat_rate, real_bit != 0); mpp_data_update_v2(ctx->stat_bits, real_bit); + ctx->ins_bps = mpp_data_sum_v2(ctx->stat_bits) / usr_cfg->stats_time; if (real_bit + ctx->stat_watl > ctx->watl_thrd) water_level = ctx->watl_thrd - ctx->bit_per_frame; else water_level = real_bit + ctx->stat_watl - ctx->bit_per_frame; - if (water_level < 0) { + if (water_level < 0) water_level = 0; - } + ctx->stat_watl = water_level; - switch (ctx->frame_type) { - case INTRA_FRAME: { + + switch (cfg->frame_type) { + case INTRA_FRAME : { mpp_data_update_v2(ctx->i_bit, real_bit); ctx->i_sumbits = mpp_data_sum_v2(ctx->i_bit); ctx->i_scale = 80 * ctx->i_sumbits / (2 * ctx->p_sumbits); rc_dbg_rc("i_sumbits %d p_sumbits %d i_scale %d\n", ctx->i_sumbits, ctx->p_sumbits, ctx->i_scale); } break; - - case INTER_P_FRAME: { + case INTER_P_FRAME : { mpp_data_update_v2(ctx->p_bit, real_bit); mpp_data_update_v2(ctx->madi, madi); ctx->p_sumbits = mpp_data_sum_v2(ctx->p_bit); @@ -324,7 +377,6 @@ MPP_RET bits_model_update(RcModelV2Ctx *ctx, RK_S32 real_bit, RK_U32 madi) ctx->p_scale = 16; } break; - case INTER_VI_FRAME: { mpp_data_update_v2(ctx->vi_bit, real_bit); ctx->vi_sumbits = mpp_data_sum_v2(ctx->vi_bit); @@ -332,9 +384,8 @@ MPP_RET bits_model_update(RcModelV2Ctx *ctx, RK_S32 real_bit, RK_U32 madi) /* NOTE: vi_scale may be set to zero. So we should limit the range */ ctx->vi_scale = mpp_clip(ctx->vi_scale, 16, 320); } break; - - default: - break; + default : { + } break; } rc_dbg_func("leave %p\n", ctx); @@ -356,7 +407,7 @@ MPP_RET bits_model_alloc(RcModelV2Ctx *ctx, EncRcTaskInfo *cfg, RK_S64 total_bit rc_dbg_func("enter %p\n", ctx); rc_dbg_rc("frame_type %d max_i_prop %d i_scale %d total_bits %lld\n", - ctx->frame_type, max_i_prop, i_scale, total_bits); + cfg->frame_type, max_i_prop, i_scale, total_bits); if (usr_cfg->super_cfg.super_mode) { super_bit_thr = usr_cfg->super_cfg.super_p_thd; } @@ -367,7 +418,7 @@ MPP_RET bits_model_alloc(RcModelV2Ctx *ctx, EncRcTaskInfo *cfg, RK_S64 total_bit if (vi_num > 0) { vi_num = vi_num - 1; } - switch (ctx->frame_type) { + switch (cfg->frame_type) { case INTRA_FRAME: { i_scale = mpp_clip(i_scale, 16, 16000); total_bits = total_bits * i_scale; @@ -398,7 +449,7 @@ MPP_RET bits_model_alloc(RcModelV2Ctx *ctx, EncRcTaskInfo *cfg, RK_S64 total_bit ctx->gop_total_bits, ctx->i_sumbits, ctx->p_sumbits, usr_cfg->vgop, usr_cfg->igop); } } else { - switch (ctx->frame_type) { + switch (cfg->frame_type) { case INTRA_FRAME: { i_scale = mpp_clip(i_scale, 16, 16000); total_bits = total_bits * i_scale; @@ -627,7 +678,7 @@ MPP_RET reenc_calc_cbr_ratio(void *ctx, EncRcTaskInfo *cfg) ins_ratio = 6 * ins_ratio; ins_ratio = mpp_clip(ins_ratio, -192, 256); } else { - if (p->frame_type == INTRA_FRAME) { + if (cfg->frame_type == INTRA_FRAME) { ins_ratio = 3 * ins_ratio; ins_ratio = mpp_clip(ins_ratio, -192, 256); } else { @@ -639,7 +690,7 @@ MPP_RET reenc_calc_cbr_ratio(void *ctx, EncRcTaskInfo *cfg) bps_ratio = mpp_clip(bps_ratio, -32, 32); wl_ratio = mpp_clip(wl_ratio, -32, 32); p->next_ratio = bit_diff_ratio + ins_ratio + bps_ratio + wl_ratio; - if (p->frame_type == INTRA_FRAME && (cfg->madi > 0)) { + if (cfg->frame_type == INTRA_FRAME && (cfg->madi > 0)) { RK_U32 tar_bpp = target_bit / (mb_w * mb_h); float lnb_t = log(tar_bpp); float c = 6.7204, a = -0.1435, b = 0.0438; @@ -653,14 +704,14 @@ MPP_RET reenc_calc_cbr_ratio(void *ctx, EncRcTaskInfo *cfg) return MPP_OK; } -void rc_hier_calc_dealt_qp(RcModelV2Ctx *p) +void rc_hier_calc_dealt_qp(RcModelV2Ctx *p, EncRcTaskInfo *info) { RcHierQPCfg *hier_qp_cfg = &p->usr_cfg.hier_qp_cfg; if (!hier_qp_cfg->hier_qp_en) return; - if (p->frame_type == INTRA_FRAME || p->frame_type == INTER_VI_FRAME) { + if (info->frame_type == INTRA_FRAME || info->frame_type == INTER_VI_FRAME) { p->hier_frm_cnt[3] = 0; p->hier_frm_cnt[2] = 0; p->hier_frm_cnt[1] = 0; @@ -1077,7 +1128,7 @@ MPP_RET bits_mode_reset(RcModelV2Ctx *ctx) MPP_RET check_super_frame(RcModelV2Ctx *ctx, EncRcTaskInfo *cfg) { MPP_RET ret = MPP_OK; - RK_S32 frame_type = ctx->frame_type; + RK_S32 frame_type = cfg->frame_type; RK_U32 bits_thr = 0; RcCfg *usr_cfg = &ctx->usr_cfg; @@ -1104,7 +1155,7 @@ MPP_RET check_super_frame(RcModelV2Ctx *ctx, EncRcTaskInfo *cfg) MPP_RET check_re_enc(RcModelV2Ctx *ctx, EncRcTaskInfo *cfg) { RcCfg *usr_cfg = &ctx->usr_cfg; - RK_S32 frame_type = ctx->frame_type; + RK_S32 frame_type = cfg->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; @@ -1233,11 +1284,10 @@ MPP_RET rc_model_v2_start(void *ctx, EncRcTask *task) return MPP_OK; } - p->frame_type = (frm->is_intra) ? (INTRA_FRAME) : (INTER_P_FRAME); + info->frame_type = (frm->is_intra) ? (INTRA_FRAME) : (INTER_P_FRAME); - if (frm->ref_mode == REF_TO_PREV_INTRA) { - p->frame_type = INTER_VI_FRAME; - } + if (frm->ref_mode == REF_TO_PREV_INTRA) + info->frame_type = INTER_VI_FRAME; p->next_ratio = 0; if (p->last_frame_type == INTRA_FRAME) { @@ -1261,11 +1311,14 @@ MPP_RET rc_model_v2_start(void *ctx, EncRcTask *task) info->quality_min = usr_cfg->min_quality; } + bits_model_preset(p, info); + rc_dbg_rc("seq_idx %d intra %d\n", frm->seq_idx, frm->is_intra); rc_dbg_rc("bitrate [%d : %d : %d]\n", info->bit_min, info->bit_target, info->bit_max); rc_dbg_rc("quality [%d : %d : %d]\n", info->quality_min, info->quality_target, info->quality_max); p->reenc_cnt = 0; + p->last_frame_type = info->frame_type; rc_dbg_func("leave %p\n", ctx); @@ -1418,7 +1471,7 @@ MPP_RET rc_model_v2_hal_start(void *ctx, EncRcTask *task) } if (usr_cfg->hier_qp_cfg.hier_qp_en && !p->reenc_cnt) { - rc_hier_calc_dealt_qp(p); + rc_hier_calc_dealt_qp(p, info); if (p->qp_layer_id) { RK_S32 hier_qp_delta = usr_cfg->hier_qp_cfg.hier_qp_delta[p->qp_layer_id - 1]; @@ -1531,7 +1584,7 @@ MPP_RET rc_model_v2_end(void *ctx, EncRcTask *task) p->last_inst_bps = p->ins_bps; p->first_frm_flg = 0; - bits_model_update(p, cfg->bit_real, cfg->madi); + bits_model_update(p, cfg); if (usr_cfg->mode == RC_AVBR) { moving_judge_update(p, cfg); bit_statics_update(p, cfg->bit_real); @@ -1540,7 +1593,6 @@ MPP_RET rc_model_v2_end(void *ctx, EncRcTask *task) p->gop_frm_cnt++; p->gop_qp_sum += p->start_qp; - p->last_frame_type = p->frame_type; p->pre_mean_qp = cfg->quality_real; p->pre_iblk4_prop = cfg->iblk4_prop; p->scale_qp = p->cur_scale_qp; diff --git a/test/mpi_enc_mt_test.cpp b/test/mpi_enc_mt_test.cpp index db7e7911..cf74398e 100644 --- a/test/mpi_enc_mt_test.cpp +++ b/test/mpi_enc_mt_test.cpp @@ -374,7 +374,7 @@ MPP_RET test_mt_cfg_setup(MpiEncMtCtxInfo *info) case MPP_ENC_RC_MODE_CBR : case MPP_ENC_RC_MODE_VBR : case MPP_ENC_RC_MODE_AVBR : { - mpp_enc_cfg_set_s32(cfg, "rc:qp_init", 26); + mpp_enc_cfg_set_s32(cfg, "rc:qp_init", -1); mpp_enc_cfg_set_s32(cfg, "rc:qp_max", 51); mpp_enc_cfg_set_s32(cfg, "rc:qp_min", 10); mpp_enc_cfg_set_s32(cfg, "rc:qp_max_i", 51);