[enc_gdr]: Platform supports intra refresh

Add parameters required for intra refresh
Add rate control corresponding to intra refresh

Change-Id: I6dbaf70e3c50cd0debf909ded9fb5c4f30df26ec
Signed-off-by: Hongjin Li <vic.hong@rock-chips.com>
This commit is contained in:
Hongjin Li
2022-05-09 17:51:47 +08:00
committed by Herman Chen
parent 6ff45db4e8
commit 0ee683acf3
11 changed files with 169 additions and 8 deletions

View File

@@ -179,6 +179,7 @@ typedef struct RcCfg_s {
RcSuperframeCfg super_cfg;
RcDebreathCfg debreath_cfg;
RcHierQPCfg hier_qp_cfg;
RK_U32 refresh_len;
} RcCfg;
/*

View File

@@ -26,6 +26,7 @@ typedef enum EncFrmType_e {
INTER_B_FRAME = 1,
INTRA_FRAME = 2,
INTER_VI_FRAME = 3,
INTRA_RFH_FRAME = 4,
} EncFrmType;
/*
@@ -131,7 +132,16 @@ typedef union EncFrmStatus_u {
* When true currnet frame is force to encoded as software skip frame
*/
RK_U32 force_pskip : 1;
RK_U32 reserved1 : 3;
/*
* Current frame is intra refresh frame
*/
RK_U32 is_i_refresh : 1;
/*
* Current frame needs add recovery point prefix
*/
RK_U32 is_i_recovery : 1;
RK_U32 reserved1 : 1;
/* reencode times */
RK_U32 reencode_times : 8;

View File

@@ -236,6 +236,7 @@ typedef enum MppEncRcCfgChange_e {
MPP_ENC_RC_CFG_CHANGE_DEBREATH = (1 << 24),
MPP_ENC_RC_CFG_CHANGE_HIER_QP = (1 << 25),
MPP_ENC_RC_CFG_CHANGE_ST_TIME = (1 << 26),
MPP_ENC_RC_CFG_CHANGE_REFRESH = (1 << 27),
MPP_ENC_RC_CFG_CHANGE_ALL = (0xFFFFFFFF),
} MppEncRcCfgChange;
@@ -406,6 +407,11 @@ typedef struct MppEncRcCfg_t {
RK_S32 hier_qp_en;
RK_S32 hier_qp_delta[4];
RK_S32 hier_frame_num[4];
RK_U32 refresh_en;
MppEncRcRefreshMode refresh_mode;
RK_U32 refresh_num;
RK_S32 refresh_length;
} MppEncRcCfg;

View File

@@ -57,4 +57,10 @@ typedef enum MppEncRcGopMode_e {
MPP_ENC_RC_GOP_MODE_BUTT,
} MppEncRcGopMode;
typedef enum MppEncRcIntraRefreshMode_e {
MPP_ENC_RC_INTRA_REFRESH_ROW = 0,
MPP_ENC_RC_INTRA_REFRESH_COL,
MPP_ENC_RC_INTRA_REFRESH_BUTT
} MppEncRcRefreshMode;
#endif /*__RK_VENC_RC_H__*/

View File

@@ -20,6 +20,8 @@
#include "mpp_trie.h"
#include "mpp_enc_cfg.h"
extern RK_U8 uuid_refresh_cfg[16];
typedef struct MppEncCfgImpl_t {
RK_S32 size;
MppEncCfgSet cfg;

View File

@@ -61,6 +61,7 @@ MPP_RET mpp_enc_refs_deinit(MppEncRefs *refs);
MPP_RET mpp_enc_refs_set_cfg(MppEncRefs refs, MppEncRefCfg ref_cfg);
MPP_RET mpp_enc_refs_set_usr_cfg(MppEncRefs refs, MppEncRefFrmUsrCfg *force);
MPP_RET mpp_enc_refs_set_rc_igop(MppEncRefs refs, RK_S32 igop);
MPP_RET mpp_enc_refs_set_refresh_length(MppEncRefs refs, RK_S32 len);
/* return hdr need update or not */
RK_S32 mpp_enc_refs_update_hdr(MppEncRefs refs);

View File

@@ -162,6 +162,9 @@ public:
ENTRY(rc, hier_qp_delta, St, RK_S32 *, MPP_ENC_RC_CFG_CHANGE_HIER_QP, rc, hier_qp_delta) \
ENTRY(rc, hier_frame_num, St, RK_S32 *, MPP_ENC_RC_CFG_CHANGE_HIER_QP, rc, hier_frame_num) \
ENTRY(rc, stats_time, S32, RK_S32, MPP_ENC_RC_CFG_CHANGE_ST_TIME, rc, stats_time) \
ENTRY(rc, refresh_en, U32, RK_U32, MPP_ENC_RC_CFG_CHANGE_REFRESH, rc, refresh_en) \
ENTRY(rc, refresh_mode, U32, MppEncRcRefreshMode, MPP_ENC_RC_CFG_CHANGE_REFRESH, rc, refresh_mode) \
ENTRY(rc, refresh_num, U32, RK_U32, MPP_ENC_RC_CFG_CHANGE_REFRESH, rc, refresh_num) \
/* 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) \

View File

@@ -104,6 +104,7 @@ typedef struct MppEncRefsImpl_t {
MppEncRefCfgImpl *ref_cfg;
MppEncRefFrmUsrCfg usr_cfg;
RK_S32 igop;
RK_U32 refresh_length;
RK_S32 hdr_need_update;
@@ -318,6 +319,22 @@ static void set_st_cfg_to_frm(EncFrmStatus *frm, RK_S32 seq_idx,
dump_frm(frm);
}
static MPP_RET set_frm_refresh_flag(EncFrmStatus *frm, MppEncRefsImpl *p)
{
MPP_RET ret = MPP_OK;
if (!frm || !p)
return ret = MPP_ERR_NULL_PTR;
if (p->refresh_length) {
frm->is_i_refresh = ((frm->seq_idx % p->igop) < p->refresh_length) && p->cpb.seq_cnt > 1;
frm->is_i_recovery = !(frm->seq_idx % p->igop) && p->cpb.seq_cnt > 1;
} else
frm->is_i_refresh = 0;
return ret;
}
static void set_lt_cfg_to_frm(EncFrmStatus *frm, RefsCnt *lt_cfg)
{
frm->is_non_ref = 0;
@@ -339,7 +356,7 @@ static EncFrmStatus *get_ref_from_cpb(EncVirtualCpb *cpb, EncFrmStatus *frm)
MppEncRefMode ref_mode = frm->ref_mode;
RK_S32 ref_arg = frm->ref_arg;
if (frm->is_intra)
if (frm->is_idr)
return NULL;
EncFrmStatus *ref = NULL;
@@ -592,6 +609,7 @@ MPP_RET mpp_enc_refs_dryrun(MppEncRefs refs)
while (repeat-- > 0) {
/* step 1. updated by st_cfg */
set_st_cfg_to_frm(&frm, seq_idx++, st_cfg);
set_frm_refresh_flag(&frm, p);
/* step 2. updated by lt_cfg */
RefsCnt *lt_cfg = &cpb->lt_cnter[0];
@@ -694,6 +712,30 @@ MPP_RET mpp_enc_refs_set_rc_igop(MppEncRefs refs, RK_S32 igop)
return MPP_OK;
}
MPP_RET mpp_enc_refs_set_refresh_length(MppEncRefs refs, RK_S32 len)
{
MPP_RET ret = MPP_OK;
if (NULL == refs) {
mpp_err_f("invalid NULL input refs\n");
return MPP_ERR_VALUE;
}
enc_refs_dbg_func("enter %p\n", refs);
MppEncRefsImpl *p = (MppEncRefsImpl *)refs;
if (len < p->igop) {
p->refresh_length = len;
} else {
p->refresh_length = p->igop;
ret = MPP_ERR_VALUE;
goto RET;
}
enc_refs_dbg_func("leave %p\n", refs);
RET:
return ret;
}
RK_S32 mpp_enc_refs_update_hdr(MppEncRefs refs)
{
if (NULL == refs) {
@@ -764,12 +806,17 @@ MPP_RET mpp_enc_refs_get_cpb(MppEncRefs refs, EncCpbStatus *status)
if (p->changed & ENC_REFS_IGOP_CHANGED)
cleanup_cpb = 1;
if (p->igop && cpb->seq_idx >= p->igop)
if (p->igop && (cpb->seq_idx >= p->igop)) {
if (p->refresh_length) {
p->cpb.seq_cnt = cpb->seq_idx / p->igop + 1;
} else
cleanup_cpb = 1;
}
if (usr_cfg->force_flag & ENC_FORCE_IDR) {
usr_cfg->force_flag &= (~ENC_FORCE_IDR);
cleanup_cpb = 1;
p->cpb.seq_cnt = 0;
}
if (cleanup_cpb) {
@@ -787,6 +834,7 @@ MPP_RET mpp_enc_refs_get_cpb(MppEncRefs refs, EncCpbStatus *status)
st_cfg = &cfg->st_cfg[cpb->st_cfg_pos];
/* step 2. updated by st_cfg */
set_st_cfg_to_frm(frm, cpb->seq_idx++, st_cfg);
set_frm_refresh_flag(frm, p);
lt_cfg = p->cpb.lt_cnter;

View File

@@ -77,6 +77,11 @@ static RK_U8 uuid_debug_info[16] = {
0xa9, 0x06, 0xae, 0x29, 0x94, 0x11, 0xcd, 0x9a
};
RK_U8 uuid_refresh_cfg[16] = {
0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79,
0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x00, 0x00
};
static void reset_hal_enc_task(HalEncTask *task)
{
memset(task, 0, sizeof(*task));
@@ -562,8 +567,16 @@ MPP_RET mpp_enc_proc_rc_cfg(MppCodingType coding, MppEncRcCfg *dst, MppEncRcCfg
dst->fps_out_denorm = src->fps_out_denorm;
}
if (change & MPP_ENC_RC_CFG_CHANGE_GOP)
if (change & MPP_ENC_RC_CFG_CHANGE_GOP) {
/*
* If GOP is changed smaller, disable Intra-Refresh
* and User level should reconfig Intra-Refresh
*/
if (dst->gop < src->gop && dst->refresh_en) {
dst->refresh_en = 0;
}
dst->gop = src->gop;
}
if (change & MPP_ENC_RC_CFG_CHANGE_MAX_REENC)
dst->max_reenc_times = src->max_reenc_times;
@@ -643,6 +656,17 @@ MPP_RET mpp_enc_proc_rc_cfg(MppCodingType coding, MppEncRcCfg *dst, MppEncRcCfg
if (change & MPP_ENC_RC_CFG_CHANGE_ST_TIME)
dst->stats_time = src->stats_time;
if (change & MPP_ENC_RC_CFG_CHANGE_REFRESH) {
if (dst->debreath_en) {
mpp_err_f("Turn off Debreath first.");
ret = MPP_ERR_VALUE;
}
dst->refresh_en = src->refresh_en;
dst->refresh_mode = src->refresh_mode;
// Make sure refresh_num is legal
dst->refresh_num = src->refresh_num;
}
// 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",
@@ -1041,6 +1065,9 @@ MPP_RET mpp_enc_proc_cfg(MppEncImpl *enc, MpiCmd cmd, void *param)
if (check_rc_gop_update(cmd, &enc->cfg))
mpp_enc_refs_set_rc_igop(enc->refs, enc->cfg.rc.gop);
if (enc->cfg.rc.refresh_en)
mpp_enc_refs_set_refresh_length(enc->refs, enc->cfg.rc.refresh_length);
if (check_hal_info_update(cmd))
enc->hal_info_updated = 0;
@@ -1213,6 +1240,8 @@ static void set_rc_cfg(RcCfg *cfg, MppEncCfgSet *cfg_set)
cfg->debreath_cfg.enable = rc->debreath_en;
cfg->debreath_cfg.strength = rc->debre_strength;
cfg->refresh_len = rc->refresh_length;
if (info->st_gop) {
cfg->vgop = info->st_gop;
if (cfg->vgop >= rc->fps_out_num / rc->fps_out_denorm &&
@@ -1514,6 +1543,16 @@ static MPP_RET mpp_enc_normal(Mpp *mpp, EncAsyncTaskInfo *task)
hal_task->length += length;
}
if (!frm->is_idr && frm->is_i_recovery && enc->cfg.rc.refresh_en) {
RK_S32 length = 0;
enc_impl_add_prefix(impl, packet, &length, uuid_refresh_cfg,
&enc->cfg.rc.refresh_length, 0);
hal_task->sei_length += length;
hal_task->length += length;
}
if (mpp_frame_has_meta(frame)) {
update_user_datas(impl, packet, frame, hal_task);
}

View File

@@ -40,12 +40,15 @@ typedef struct RcModelV2Ctx_t {
MppDataV2 *vi_bit;
RK_U32 vi_sumbits;
RK_U32 vi_scale;
RK_U32 i_refresh_scale;
MppDataV2 *p_bit;
RK_U32 p_sumbits;
RK_U32 i_refresh_sumbits;
RK_U32 p_scale;
MppDataV2 *pre_p_bit;
MppDataV2 *pre_i_bit;
MppDataV2 *i_refresh_bit;
MppDataV2 *pre_i_mean_qp;
MppDataV2 *madi;
MppDataV2 *madp;

View File

@@ -202,6 +202,14 @@ MPP_RET bits_model_param_init(RcModelV2Ctx *ctx)
mpp_err("gop_bits init fail gop_len %d", gop_len);
return MPP_ERR_MALLOC;
}
if (ctx->usr_cfg.refresh_len) {
mpp_data_init_v2(&ctx->i_refresh_bit, ctx->usr_cfg.refresh_len, 0);
if (ctx->i_refresh_bit == NULL) {
mpp_err("i_refresh_bit init fail refresh_len %d", ctx->usr_cfg.refresh_len);
return MPP_ERR_MALLOC;
}
}
return MPP_OK;
}
@@ -210,6 +218,7 @@ void bits_frm_init(RcModelV2Ctx *ctx)
RcCfg *usr_cfg = &ctx->usr_cfg;
RK_U32 gop_len = usr_cfg->igop;
RK_U32 p_bit = 0;
RK_U32 refresh_bit = 0;
rc_dbg_func("enter %p\n", ctx);
@@ -225,6 +234,13 @@ void bits_frm_init(RcModelV2Ctx *ctx)
ctx->p_sumbits = 5 * p_bit;
mpp_data_reset_v2(ctx->i_bit, p_bit * ctx->i_scale / 16);
ctx->i_sumbits = 2 * p_bit * ctx->i_scale / 16;
if (usr_cfg->refresh_len) {
ctx->i_refresh_scale = ctx->i_scale / usr_cfg->refresh_len + ctx->p_scale;
refresh_bit = ctx->gop_total_bits * 16 / (ctx->i_refresh_scale * usr_cfg->refresh_len
+ ctx->p_scale * (gop_len - usr_cfg->refresh_len));
mpp_data_reset_v2(ctx->i_refresh_bit, refresh_bit);
ctx->i_refresh_sumbits = usr_cfg->refresh_len * refresh_bit;
}
} break;
case SMART_P: {
RK_U32 vi_num = 0;
@@ -329,6 +345,13 @@ MPP_RET bits_model_preset(RcModelV2Ctx *ctx, EncRcTaskInfo *info)
/* 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;
case INTRA_RFH_FRAME: {
mpp_data_update_v2(ctx->i_refresh_bit, preset_bit);
mpp_data_update_v2(ctx->madi, info->madi);
ctx->i_refresh_sumbits = mpp_data_sum_v2(ctx->i_refresh_bit);
ctx->i_refresh_scale = 80 * ctx->i_refresh_sumbits / (usr_cfg->refresh_len * ctx->p_sumbits);
ctx->i_refresh_scale = mpp_clip(ctx->i_refresh_scale, 16, 64);
} break;
default : {
} break;
}
@@ -384,6 +407,13 @@ MPP_RET bits_model_update(RcModelV2Ctx *ctx, EncRcTaskInfo *cfg)
/* 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;
case INTRA_RFH_FRAME: {
mpp_data_update_v2(ctx->i_refresh_bit, real_bit);
mpp_data_update_v2(ctx->madi, madi);
ctx->i_refresh_sumbits = mpp_data_sum_v2(ctx->i_refresh_bit);
ctx->i_refresh_scale = 80 * ctx->i_refresh_sumbits / (usr_cfg->refresh_len * ctx->p_sumbits);
ctx->i_refresh_scale = mpp_clip(ctx->i_refresh_scale, 16, 64);
} break;
default : {
} break;
}
@@ -426,7 +456,6 @@ MPP_RET bits_model_alloc(RcModelV2Ctx *ctx, EncRcTaskInfo *cfg, RK_S64 total_bit
super_bit_thr = usr_cfg->super_cfg.super_i_thd;
}
} break;
case INTER_P_FRAME: {
i_scale = mpp_clip(i_scale, 16, max_i_prop);
total_bits = total_bits * 16;
@@ -462,11 +491,21 @@ MPP_RET bits_model_alloc(RcModelV2Ctx *ctx, EncRcTaskInfo *cfg, RK_S64 total_bit
i_scale = mpp_clip(i_scale, 16, max_i_prop);
total_bits = total_bits * 16;
} break;
case INTRA_RFH_FRAME: {
i_scale = mpp_clip(i_scale, 16, max_i_prop);
total_bits = total_bits * ctx->i_refresh_scale;
rc_dbg_rc("ctx->i_refresh_scale = %d", ctx->i_refresh_scale);
} break;
default:
break;
}
if (gop_len > 1) {
if (!usr_cfg->refresh_len || cfg->frame_type == INTRA_FRAME)
alloc_bits = total_bits / (i_scale + 16 * (gop_len - 1));
else
alloc_bits = total_bits /
(ctx->i_refresh_scale * usr_cfg->refresh_len +
16 * (gop_len - usr_cfg->refresh_len));
} else {
alloc_bits = total_bits / i_scale;
}
@@ -1289,6 +1328,9 @@ MPP_RET rc_model_v2_start(void *ctx, EncRcTask *task)
if (frm->ref_mode == REF_TO_PREV_INTRA)
info->frame_type = INTER_VI_FRAME;
if (frm->is_i_refresh)
info->frame_type = INTRA_RFH_FRAME;
p->next_ratio = 0;
if (p->last_frame_type == INTRA_FRAME) {
calc_next_i_ratio(p);
@@ -1426,7 +1468,7 @@ MPP_RET rc_model_v2_hal_start(void *ctx, EncRcTask *task)
RK_S32 qp_scale = p->cur_scale_qp + p->next_ratio;
RK_S32 start_qp = 0;
if (frm->is_intra) {
if (frm->is_intra && !frm->is_i_refresh) {
RK_S32 i_quality_delta = usr_cfg->i_quality_delta;
qp_scale = mpp_clip(qp_scale, (info->quality_min << 6), (info->quality_max << 6));