diff --git a/inc/rk_venc_ref.h b/inc/rk_venc_ref.h index fdb2aa4d..61badf86 100644 --- a/inc/rk_venc_ref.h +++ b/inc/rk_venc_ref.h @@ -226,6 +226,12 @@ MPP_RET mpp_enc_ref_cfg_add_lt_cfg(MppEncRefCfg ref, RK_S32 cnt, MppEncRefLtFrmC MPP_RET mpp_enc_ref_cfg_add_st_cfg(MppEncRefCfg ref, RK_S32 cnt, MppEncRefStFrmCfg *frm); MPP_RET mpp_enc_ref_cfg_check(MppEncRefCfg ref); +/* + * A new reference configure will restart a new gop and clear cpb by default. + * The keep cpb function will let encoder keeps the current cpb status and do NOT + * reset all the reference frame in cpb. + */ +MPP_RET mpp_enc_ref_cfg_set_keep_cpb(MppEncRefCfg ref, RK_S32 keep); MPP_RET mpp_enc_ref_cfg_get_preset(MppEncRefPreset *preset); MPP_RET mpp_enc_ref_cfg_show(MppEncRefCfg ref); diff --git a/mpp/base/inc/mpp_enc_ref.h b/mpp/base/inc/mpp_enc_ref.h index 5e02b8e2..6c0b3978 100644 --- a/mpp/base/inc/mpp_enc_ref.h +++ b/mpp/base/inc/mpp_enc_ref.h @@ -40,6 +40,7 @@ typedef struct MppEncRefCfgImpl_t { RK_U32 debug; /* config from user */ + RK_S32 keep_cpb; RK_S32 max_lt_cfg; RK_S32 max_st_cfg; RK_S32 lt_cfg_cnt; diff --git a/mpp/base/inc/mpp_enc_refs.h b/mpp/base/inc/mpp_enc_refs.h index 58c069c9..1ba29508 100644 --- a/mpp/base/inc/mpp_enc_refs.h +++ b/mpp/base/inc/mpp_enc_refs.h @@ -51,11 +51,15 @@ typedef void* MppEncRefs; extern "C" { #endif -MPP_RET mpp_enc_refs_init(MppEncRefs *refs, MppEncCfgSet *cfg); +MPP_RET mpp_enc_refs_init(MppEncRefs *refs); 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); + +/* return hdr need update or not */ +RK_S32 mpp_enc_refs_update_hdr(MppEncRefs refs); /* get dpb size */ MPP_RET mpp_enc_refs_get_cpb_info(MppEncRefs refs, MppEncCpbInfo *info); diff --git a/mpp/base/mpp_enc_ref.cpp b/mpp/base/mpp_enc_ref.cpp index bac861bf..69f74eaa 100644 --- a/mpp/base/mpp_enc_ref.cpp +++ b/mpp/base/mpp_enc_ref.cpp @@ -313,7 +313,7 @@ MPP_RET mpp_enc_ref_cfg_check(MppEncRefCfg ref) cpb_info->lt_gop = lt_dryrun_length; cpb_info->st_gop = st_dryrun_length - 1; - ret = mpp_enc_refs_init(&refs, NULL); + ret = mpp_enc_refs_init(&refs); ready = (ret) ? 0 : (ready); ret = mpp_enc_refs_set_cfg(refs, ref); ready = (ret) ? 0 : (ready); @@ -334,6 +334,17 @@ MPP_RET mpp_enc_ref_cfg_check(MppEncRefCfg ref) return ready ? MPP_OK : MPP_NOK; } +MPP_RET mpp_enc_ref_cfg_set_keep_cpb(MppEncRefCfg ref, RK_S32 keep) +{ + if (check_is_mpp_enc_ref_cfg(ref)) + return MPP_ERR_VALUE; + + MppEncRefCfgImpl *p = (MppEncRefCfgImpl *)ref; + p->keep_cpb = keep; + + return MPP_OK; +} + MPP_RET mpp_enc_ref_cfg_show(MppEncRefCfg ref) { if (check_is_mpp_enc_ref_cfg(ref)) @@ -412,6 +423,7 @@ static const MppEncRefCfgImpl default_ref_cfg = { .name = module_name, .ready = 1, .debug = 0, + .keep_cpb = 0, .max_lt_cfg = 0, .max_st_cfg = 1, .lt_cfg_cnt = 0, diff --git a/mpp/base/mpp_enc_refs.cpp b/mpp/base/mpp_enc_refs.cpp index 9fe051ec..69abca2d 100644 --- a/mpp/base/mpp_enc_refs.cpp +++ b/mpp/base/mpp_enc_refs.cpp @@ -42,6 +42,10 @@ #define enc_refs_dbg_frm(fmt, ...) _mpp_dbg(enc_refs_debug, MPP_ENC_REFS_DBG_FRM, fmt, ## __VA_ARGS__) #define enc_refs_dbg_size(fmt, ...) _mpp_dbg(enc_refs_debug, MPP_ENC_REFS_DBG_SIZE, fmt, ## __VA_ARGS__) +#define ENC_REFS_REF_CFG_CHANGED (0x00000001) +#define ENC_REFS_USR_CFG_CHANGED (0x00000002) +#define ENC_REFS_IGOP_CHANGED (0x00000004) + typedef struct RefsCnt_t { RK_S32 delay; RK_S32 delay_cnt; @@ -96,12 +100,12 @@ typedef struct EncVirtualCpb_t { } EncVirtualCpb; typedef struct MppEncRefsImpl_t { - MppEncCfgSet *cfg_set; + RK_U32 changed; MppEncRefCfgImpl *ref_cfg; - - RK_S32 igop; - RK_S32 usr_cfg_updated; MppEncRefFrmUsrCfg usr_cfg; + RK_S32 igop; + + RK_S32 hdr_need_update; EncVirtualCpb cpb; EncVirtualCpb cpb_stash; @@ -169,14 +173,14 @@ void _dump_cpb(EncVirtualCpb *cpb, const char *func, RK_S32 line) cpb->st_cfg_pos, cpb->st_cfg_repeat_pos); } -MPP_RET mpp_enc_refs_init(MppEncRefs *refs, MppEncCfgSet *cfg) +MPP_RET mpp_enc_refs_init(MppEncRefs *refs) { if (NULL == refs) { mpp_err_f("invalid NULL input refs\n"); return MPP_ERR_NULL_PTR; } - enc_refs_dbg_func("enter %p cfg %p\n", refs, cfg); + enc_refs_dbg_func("enter %p\n", refs); MppEncRefsImpl *p = mpp_calloc(MppEncRefsImpl, 1); *refs = p; @@ -185,11 +189,9 @@ MPP_RET mpp_enc_refs_init(MppEncRefs *refs, MppEncCfgSet *cfg) return MPP_ERR_NULL_PTR; } - p->cfg_set = cfg; - mpp_env_get_u32("enc_refs_debug", &enc_refs_debug, 0); - enc_refs_dbg_func("leave %p cfg %p\n", p, cfg); + enc_refs_dbg_func("leave %p\n", p); return MPP_OK; } @@ -222,20 +224,17 @@ MPP_RET mpp_enc_refs_set_cfg(MppEncRefs refs, MppEncRefCfg ref_cfg) EncVirtualCpb *cpb = &p->cpb; MppEncRefCfgImpl *cfg = NULL; - if (NULL == ref_cfg) { - if (p->cfg_set) - ref_cfg = p->cfg_set->ref_cfg; - } - if (NULL == ref_cfg) ref_cfg = mpp_enc_ref_default(); cfg = (MppEncRefCfgImpl *)ref_cfg; p->ref_cfg = cfg; + p->changed |= ENC_REFS_REF_CFG_CHANGED; /* clear cpb on setup new cfg */ - memset(cpb, 0, sizeof(*cpb)); + if (!cfg->keep_cpb) + memset(cpb, 0, sizeof(*cpb)); if (cfg->lt_cfg_cnt) { RK_S32 i; @@ -257,6 +256,8 @@ MPP_RET mpp_enc_refs_set_cfg(MppEncRefs refs, MppEncRefCfg ref_cfg) } MppEncCpbInfo *info = &cpb->info; + p->hdr_need_update = (info->dpb_size && info->dpb_size < cfg->cpb_info.dpb_size); + memcpy(info, &cfg->cpb_info, sizeof(cfg->cpb_info)); enc_refs_dbg_flow("ref_cfg cpb size: lt %d st %d max lt_idx %d tid %d\n", @@ -607,8 +608,15 @@ MPP_RET mpp_enc_refs_dryrun(MppEncRefs refs) lt_cfg->cnt++; if (lt_cfg->cnt >= lt_cfg->len) { - lt_cfg->cnt = 0; - lt_cfg->idx++; + if (lt_cfg->len) { + /* when there is loop len loop lt_cfg */ + lt_cfg->cnt = 0; + lt_cfg->idx++; + } else { + /* else just set lt_cfg once */ + lt_cfg->cnt = 1; + lt_cfg->idx = 1; + } } } @@ -632,7 +640,7 @@ MPP_RET mpp_enc_refs_dryrun(MppEncRefs refs) } cleanup_cpb_refs(cpb); - info->max_st_cnt = cpb_st_used_size; + info->max_st_cnt = cpb_st_used_size ? cpb_st_used_size : 1; DONE: info->dpb_size = info->max_lt_cnt + info->max_st_cnt; @@ -654,11 +662,49 @@ MPP_RET mpp_enc_refs_set_usr_cfg(MppEncRefs refs, MppEncRefFrmUsrCfg *cfg) MppEncRefsImpl *p = (MppEncRefsImpl *)refs; memcpy(&p->usr_cfg, cfg, sizeof(p->usr_cfg)); + if (cfg->force_flag) + p->changed |= ENC_REFS_USR_CFG_CHANGED; enc_refs_dbg_func("leave %p\n", refs); return MPP_OK; } +MPP_RET mpp_enc_refs_set_rc_igop(MppEncRefs refs, RK_S32 igop) +{ + 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 (p->igop != igop) { + p->igop = igop; + p->changed |= ENC_REFS_IGOP_CHANGED; + } + + enc_refs_dbg_func("leave %p\n", refs); + return MPP_OK; +} + +RK_S32 mpp_enc_refs_update_hdr(MppEncRefs refs) +{ + if (NULL == refs) { + mpp_err_f("invalid NULL input refs\n"); + return 0; + } + + enc_refs_dbg_func("enter %p\n", refs); + + MppEncRefsImpl *p = (MppEncRefsImpl *)refs; + RK_S32 hdr_need_update = p->hdr_need_update; + + enc_refs_dbg_func("leave %p\n", refs); + return hdr_need_update; +} + MPP_RET mpp_enc_refs_get_cpb_info(MppEncRefs refs, MppEncCpbInfo *info) { if (NULL == refs || NULL == info) { @@ -675,6 +721,18 @@ MPP_RET mpp_enc_refs_get_cpb_info(MppEncRefs refs, MppEncCpbInfo *info) return MPP_OK; } +static RK_S32 get_cpb_st_cfg_pos(EncVirtualCpb *cpb, MppEncRefCfgImpl *cfg) +{ + RK_S32 st_cfg_pos = cpb->st_cfg_pos; + RK_S32 st_cfg_cnt = cfg->st_cfg_cnt; + + /* NOTE: second loop will start from 1 */ + if (st_cfg_pos >= st_cfg_cnt) + st_cfg_pos = (st_cfg_cnt > 1) ? (1) : (0); + + return st_cfg_pos; +} + MPP_RET mpp_enc_refs_get_cpb(MppEncRefs refs, EncCpbStatus *status) { if (NULL == refs) { @@ -685,10 +743,9 @@ MPP_RET mpp_enc_refs_get_cpb(MppEncRefs refs, EncCpbStatus *status) enc_refs_dbg_func("enter %p\n", refs); MppEncRefsImpl *p = (MppEncRefsImpl *)refs; - MppEncCfgSet *cfg_set = p->cfg_set; MppEncRefCfgImpl *cfg = p->ref_cfg; EncVirtualCpb *cpb = &p->cpb; - MppEncRefStFrmCfg *st_cfg = &cfg->st_cfg[cpb->st_cfg_pos]; + MppEncRefStFrmCfg *st_cfg = NULL; MppEncRefFrmUsrCfg *usr_cfg = &p->usr_cfg; EncFrmStatus *frm = &status->curr; EncFrmStatus *ref = &status->refr; @@ -698,10 +755,8 @@ MPP_RET mpp_enc_refs_get_cpb(MppEncRefs refs, EncCpbStatus *status) RK_S32 i; /* step 1. check igop from cfg_set and force idr for usr_cfg */ - if (cfg_set->rc.gop != p->igop) { - p->igop = cfg_set->rc.gop; + if (p->changed & ENC_REFS_IGOP_CHANGED) cleanup_cpb = 1; - } if (p->igop && cpb->seq_idx >= p->igop) cleanup_cpb = 1; @@ -714,27 +769,19 @@ MPP_RET mpp_enc_refs_get_cpb(MppEncRefs refs, EncCpbStatus *status) if (cleanup_cpb) { /* update seq_idx for igop loop and force idr */ cleanup_cpb_refs(cpb); + } else if (p->changed & ENC_REFS_REF_CFG_CHANGED) { + cpb->st_cfg_pos = 0; + cpb->st_cfg_repeat_pos = 0; } + p->changed = 0; + cpb->frm_idx++; + cpb->st_cfg_pos = get_cpb_st_cfg_pos(cpb, cfg); + 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); - /* update st_cfg for st_cfg loop */ - cpb->st_cfg_repeat_pos++; - if (cpb->st_cfg_repeat_pos > st_cfg->repeat) { - cpb->st_cfg_repeat_pos = 0; - cpb->st_cfg_pos++; - - /* NOTE: second loop will start from 1 */ - if (cpb->st_cfg_pos >= cfg->st_cfg_cnt) { - if (cfg->st_cfg_cnt > 1) - cpb->st_cfg_pos = 1; - else - cpb->st_cfg_pos = 0; - } - } - lt_cfg = p->cpb.lt_cnter; /* step 3. updated by lt_cfg */ @@ -753,11 +800,46 @@ MPP_RET mpp_enc_refs_get_cpb(MppEncRefs refs, EncCpbStatus *status) lt_cfg->cnt++; if (lt_cfg->cnt >= lt_cfg->len) { - lt_cfg->cnt = 0; - lt_cfg->idx++; + if (lt_cfg->len) { + /* when there is loop len loop lt_cfg */ + lt_cfg->cnt = 0; + lt_cfg->idx++; + } else { + /* else just set lt_cfg once */ + lt_cfg->cnt = 1; + lt_cfg->idx = 1; + } } } + /* step 4. process force flags and force ref_mode */ + if (usr_cfg->force_flag & ENC_FORCE_LT_REF_IDX) { + frm->is_non_ref = 0; + frm->is_lt_ref = 1; + frm->lt_idx = usr_cfg->force_lt_idx; + /* lt_ref will be forced to tid 0 */ + frm->temporal_id = 0; + + /* reset st_cfg to next loop */ + cpb->st_cfg_repeat_pos = 0; + cpb->st_cfg_pos = 0; + usr_cfg->force_flag &= ~ENC_FORCE_LT_REF_IDX; + } + + if (usr_cfg->force_flag & ENC_FORCE_REF_MODE) { + frm->ref_mode = usr_cfg->force_ref_mode; + frm->ref_arg = usr_cfg->force_ref_arg; + + usr_cfg->force_flag &= ~ENC_FORCE_REF_MODE; + } + + /* update st_cfg for st_cfg loop */ + cpb->st_cfg_repeat_pos++; + if (cpb->st_cfg_repeat_pos > st_cfg->repeat) { + cpb->st_cfg_repeat_pos = 0; + cpb->st_cfg_pos++; + } + /* step 4. try find ref by the ref_mode */ EncFrmStatus *ref_found = get_ref_from_cpb(&p->cpb, frm); if (ref_found) { diff --git a/mpp/codec/mpp_enc_v2.cpp b/mpp/codec/mpp_enc_v2.cpp index 2704f6fb..8de4261f 100644 --- a/mpp/codec/mpp_enc_v2.cpp +++ b/mpp/codec/mpp_enc_v2.cpp @@ -276,10 +276,15 @@ static MPP_RET check_enc_task_wait(MppEncImpl *enc, EncTask *task) static RK_S32 check_codec_to_resend_hdr(MppEncCodecCfg *codec) { MppCodingType coding = codec->coding; + RK_U32 skip_flag = 0; + switch (coding) { case MPP_VIDEO_CodingAVC : { MppEncH264Cfg *h264 = &codec->h264; - if (h264->change & (~MPP_ENC_H264_CFG_CHANGE_QP_LIMIT)) + + skip_flag = MPP_ENC_H264_CFG_CHANGE_QP_LIMIT | MPP_ENC_H264_CFG_CHANGE_MAX_TID; + + if (h264->change & (~skip_flag)) return 1; } break; case MPP_VIDEO_CodingHEVC : { @@ -428,6 +433,15 @@ static RK_S32 check_rc_cfg_update(MpiCmd cmd, MppEncCfgSet *cfg) return 0; } +static RK_S32 check_rc_gop_update(MpiCmd cmd, MppEncCfgSet *cfg) +{ + if (((cmd == MPP_ENC_SET_RC_CFG) || (cmd == MPP_ENC_SET_CFG)) && + (cfg->rc.change & MPP_ENC_RC_CFG_CHANGE_GOP)) + return 1; + + return 0; +} + static void mpp_enc_proc_cfg(MppEncImpl *enc) { switch (enc->cmd) { @@ -525,7 +539,9 @@ static void mpp_enc_proc_cfg(MppEncImpl *enc) mpp_err_f("failed to set ref cfg ret %d\n", ret); *enc->cmd_ret = ret; } - enc->hdr_status.val = 0; + + if (mpp_enc_refs_update_hdr(enc->refs)) + enc->hdr_status.val = 0; } break; case MPP_ENC_SET_OSD_PLT_CFG : { MppEncOSDPltCfg *src = (MppEncOSDPltCfg *)enc->param; @@ -567,6 +583,8 @@ static void mpp_enc_proc_cfg(MppEncImpl *enc) } if (check_rc_cfg_update(enc->cmd, &enc->cfg)) enc->rc_status.rc_api_user_cfg = 1; + if (check_rc_gop_update(enc->cmd, &enc->cfg)) + mpp_enc_refs_set_rc_igop(enc->refs, enc->cfg.rc.gop); } #define RUN_ENC_IMPL_FUNC(func, impl, task, mpp, ret) \ @@ -961,17 +979,19 @@ void *mpp_enc_thread(void *data) hal_task->length = mpp_packet_get_length(packet); mpp_task_meta_get_buffer(task_in, KEY_MOTION_INFO, &hal_task->mv_info); - // 15. setup user_cfg to dpb - if (enc->frm_cfg.force_flag) { - mpp_enc_refs_set_usr_cfg(enc->refs, &enc->frm_cfg); - enc->frm_cfg.force_flag = 0; + /* 14. check frm_meta data force key in input frame and start one frame */ + enc_dbg_detail("task %d enc start\n", frm->seq_idx); + RUN_ENC_IMPL_FUNC(enc_impl_start, impl, hal_task, mpp, ret); + + // 14. setup user_cfg to dpb + if (frm_cfg->force_flag) { + mpp_enc_refs_set_usr_cfg(enc->refs, frm_cfg); + frm_cfg->force_flag = 0; } - // 14. backup dpb - enc_dbg_detail("task %d enc start\n", frm->seq_idx); - task.status.enc_backup = 1; - RUN_ENC_IMPL_FUNC(enc_impl_start, impl, hal_task, mpp, ret); + // 15. backup dpb mpp_enc_refs_stash(enc->refs); + task.status.enc_backup = 1; TASK_REENCODE: // 15. restore and process dpb @@ -1181,7 +1201,7 @@ MPP_RET mpp_enc_init_v2(MppEnc *enc, MppEncInitCfg *cfg) return MPP_ERR_MALLOC; } - ret = mpp_enc_refs_init(&p->refs, &p->cfg); + ret = mpp_enc_refs_init(&p->refs); if (ret) { mpp_err_f("could not init enc refs\n"); goto ERR_RET; diff --git a/mpp/legacy/vpu_api_mlvec.cpp b/mpp/legacy/vpu_api_mlvec.cpp index a7355a27..feeb15c2 100644 --- a/mpp/legacy/vpu_api_mlvec.cpp +++ b/mpp/legacy/vpu_api_mlvec.cpp @@ -463,6 +463,7 @@ MPP_RET vpu_api_mlvec_set_dy_max_tid(VpuApiMlvec ctx, RK_S32 max_tid) ret = mpp_enc_ref_cfg_set_cfg_cnt(ref, lt_cfg_cnt, st_cfg_cnt); ret = mpp_enc_ref_cfg_add_lt_cfg(ref, lt_cfg_cnt, lt_ref); ret = mpp_enc_ref_cfg_add_st_cfg(ref, st_cfg_cnt, st_ref); + ret = mpp_enc_ref_cfg_set_keep_cpb(ref, 1); ret = mpp_enc_ref_cfg_check(ref); ret = mpi->control(mpp_ctx, MPP_ENC_SET_REF_CFG, ref);