mirror of
https://github.com/nyanmisaka/mpp.git
synced 2025-10-04 16:52:40 +08:00
[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:
@@ -179,6 +179,7 @@ typedef struct RcCfg_s {
|
||||
RcSuperframeCfg super_cfg;
|
||||
RcDebreathCfg debreath_cfg;
|
||||
RcHierQPCfg hier_qp_cfg;
|
||||
RK_U32 refresh_len;
|
||||
} RcCfg;
|
||||
|
||||
/*
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
||||
|
||||
|
@@ -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__*/
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -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) \
|
||||
|
@@ -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)
|
||||
cleanup_cpb = 1;
|
||||
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;
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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) {
|
||||
alloc_bits = total_bits / (i_scale + 16 * (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));
|
||||
|
Reference in New Issue
Block a user