diff --git a/inc/mpp_rc_defs.h b/inc/mpp_rc_defs.h index 73a513fc..2f02c7c8 100644 --- a/inc/mpp_rc_defs.h +++ b/inc/mpp_rc_defs.h @@ -43,7 +43,18 @@ typedef union EncFrmStatus_u { * 1 - do not write the reconstructed frame pixel to memory */ RK_U32 non_recn : 1; - RK_U32 reserved0 : 2; + + /* + * 0 - normal frame and normal dpb management + * 1 - save recon frame as first pass extra frame. Used in two pass mode + */ + RK_U32 save_pass1 : 1; + + /* + * 0 - use normal input source frame as input + * 1 - use the previously stored first pass recon frame as input frame + */ + RK_U32 use_pass1 : 1; /* reference status flag */ /* diff --git a/mpp/base/inc/mpp_enc_refs.h b/mpp/base/inc/mpp_enc_refs.h index caaecff9..2e8e8a11 100644 --- a/mpp/base/inc/mpp_enc_refs.h +++ b/mpp/base/inc/mpp_enc_refs.h @@ -75,6 +75,11 @@ MPP_RET mpp_enc_refs_dryrun(MppEncRefs refs); MPP_RET mpp_enc_refs_stash(MppEncRefs refs); MPP_RET mpp_enc_refs_rollback(MppEncRefs refs); +/* two-pass encoding functions */ +/* check next frame is intra or not */ +RK_S32 mpp_enc_refs_next_frm_is_intra(MppEncRefs refs); +MPP_RET mpp_enc_refs_get_cpb_pass1(MppEncRefs refs, EncCpbStatus *status); + #define dump_frm(frm) _dump_frm(frm, __FUNCTION__, __LINE__) void _dump_frm(EncFrmStatus *frm, const char *func, RK_S32 line); diff --git a/mpp/base/mpp_enc_refs.cpp b/mpp/base/mpp_enc_refs.cpp index dd66ba9c..86e2a9ca 100644 --- a/mpp/base/mpp_enc_refs.cpp +++ b/mpp/base/mpp_enc_refs.cpp @@ -757,6 +757,7 @@ MPP_RET mpp_enc_refs_get_cpb(MppEncRefs refs, EncCpbStatus *status) RefsCnt *lt_cfg = cpb->lt_cnter; RK_S32 set_to_lt = 0; RK_S32 cleanup_cpb = 0; + RK_S32 prev_frm_is_pass1 = frm->save_pass1; RK_S32 i; /* step 1. check igop from cfg_set and force idr for usr_cfg */ @@ -868,6 +869,10 @@ MPP_RET mpp_enc_refs_get_cpb(MppEncRefs refs, EncCpbStatus *status) } else ref->val = 0; + /* step 5. check use previous pass one frame as input */ + if (prev_frm_is_pass1) + frm->use_pass1 = 1; + if (enc_refs_debug & MPP_ENC_REFS_DBG_FRM) { mpp_log_f("frm status:\n"); dump_frm(frm); @@ -891,6 +896,93 @@ MPP_RET mpp_enc_refs_get_cpb(MppEncRefs refs, EncCpbStatus *status) return MPP_OK; } +RK_S32 mpp_enc_refs_next_frm_is_intra(MppEncRefs refs) +{ + 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; + EncVirtualCpb *cpb = &p->cpb; + MppEncRefFrmUsrCfg *usr_cfg = &p->usr_cfg; + RK_S32 is_intra = 0; + + if (p->changed & ENC_REFS_IGOP_CHANGED) + is_intra = 1; + + if (p->igop && cpb->seq_idx >= p->igop) + is_intra = 1; + + if (usr_cfg->force_flag & ENC_FORCE_IDR) + is_intra = 1; + + if (!cpb->frm_idx) + is_intra = 0; + + enc_refs_dbg_func("leave %p\n", refs); + + return is_intra; +} + +MPP_RET mpp_enc_refs_get_cpb_pass1(MppEncRefs refs, EncCpbStatus *status) +{ + 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; + EncVirtualCpb *cpb = &p->cpb; + EncFrmStatus *frm = &status->curr; + EncFrmStatus *ref = &status->refr; + + frm->valid = 1; + frm->save_pass1 = 1; + frm->is_non_ref = 1; + frm->is_lt_ref = 0; + frm->temporal_id = 0; + frm->ref_mode = REF_TO_PREV_REF_FRM; + frm->ref_arg = 0; + frm->non_recn = 0; + + /* step 4. try find ref by the ref_mode */ + EncFrmStatus *ref_found = get_ref_from_cpb(cpb, frm); + if (ref_found) { + RK_S32 cpb_idx = check_ref_cpb_pos(cpb, ref_found); + + mpp_assert(cpb_idx >= 0); + cpb->list0[0].val = ref->val; + ref->val = ref_found->val; + } else + ref->val = 0; + + if (enc_refs_debug & MPP_ENC_REFS_DBG_FRM) { + mpp_log_f("frm status:\n"); + dump_frm(frm); + mpp_log_f("ref status:\n"); + dump_frm(ref); + } + + /* step 5. generate cpb init */ + memset(status->init, 0, sizeof(status->init)); + save_cpb_status(cpb, status->init); + // TODO: cpb_init must be the same to cpb_final + + /* step 6. store frame according to status */ + store_ref_to_cpb(cpb, frm); + + /* step 7. generate cpb final */ + memset(status->final, 0, sizeof(status->final)); + save_cpb_status(cpb, status->final); + + enc_refs_dbg_func("leave %p\n", refs); + return MPP_OK; +} MPP_RET mpp_enc_refs_stash(MppEncRefs refs) { if (NULL == refs) { diff --git a/mpp/codec/enc/h265/h265e_api.c b/mpp/codec/enc/h265/h265e_api.c index f980fb06..3559fdc4 100644 --- a/mpp/codec/enc/h265/h265e_api.c +++ b/mpp/codec/enc/h265/h265e_api.c @@ -54,7 +54,6 @@ static MPP_RET h265e_init(void *ctx, EncImplCfg *ctrlCfg) p->cfg = ctrlCfg->cfg; memset(&p->syntax, 0, sizeof(p->syntax)); - ctrlCfg->task_count = 1; p->extra_info = mpp_calloc(H265eExtraInfo, 1); diff --git a/mpp/codec/enc/jpeg/jpege_api_v2.c b/mpp/codec/enc/jpeg/jpege_api_v2.c index e8b0b1ab..e2730773 100644 --- a/mpp/codec/enc/jpeg/jpege_api_v2.c +++ b/mpp/codec/enc/jpeg/jpege_api_v2.c @@ -75,7 +75,6 @@ static MPP_RET jpege_init_v2(void *ctx, EncImplCfg *cfg) p->cfg = cfg->cfg; mpp_assert(cfg->coding = MPP_VIDEO_CodingMJPEG); - cfg->task_count = 1; { /* init default rc config */ diff --git a/mpp/codec/inc/enc_impl_api.h b/mpp/codec/inc/enc_impl_api.h index 40f53510..9bc54d39 100644 --- a/mpp/codec/inc/enc_impl_api.h +++ b/mpp/codec/inc/enc_impl_api.h @@ -32,9 +32,6 @@ typedef struct EncImplCfg_t { MppClientType type; MppEncCfgSet *cfg; MppEncRefs refs; - - // output - RK_S32 task_count; } EncImplCfg; /* diff --git a/mpp/codec/inc/mpp_enc_impl.h b/mpp/codec/inc/mpp_enc_impl.h index 2058eb83..6783537d 100644 --- a/mpp/codec/inc/mpp_enc_impl.h +++ b/mpp/codec/inc/mpp_enc_impl.h @@ -125,6 +125,10 @@ typedef struct MppEncImpl_t { MppEncRefs refs; MppEncRefFrmUsrCfg frm_cfg; + /* two-pass deflicker parameters */ + RK_U32 support_hw_deflicker; + EncRcTaskInfo rc_info_prev; + /* Encoder configure set */ MppEncCfgSet cfg; } MppEncImpl; diff --git a/mpp/codec/mpp_enc_impl.cpp b/mpp/codec/mpp_enc_impl.cpp index b22c1335..4a33cbb1 100644 --- a/mpp/codec/mpp_enc_impl.cpp +++ b/mpp/codec/mpp_enc_impl.cpp @@ -1201,6 +1201,74 @@ static MPP_RET mpp_enc_check_pkt_buf(MppEncImpl *enc) return MPP_OK; } +static MPP_RET mpp_enc_proc_two_pass(Mpp *mpp, EncTask *task) +{ + MppEncImpl *enc = (MppEncImpl *)mpp->mEnc; + MPP_RET ret = MPP_OK; + + if (mpp_enc_refs_next_frm_is_intra(enc->refs)) { + EncRcTask *rc_task = &enc->rc_task; + EncFrmStatus frm_bak = rc_task->frm; + EncRcTaskInfo rc_info = rc_task->info; + EncCpbStatus *cpb = &rc_task->cpb; + EncFrmStatus *frm = &rc_task->frm; + HalEncTask *hal_task = &task->info; + EncImpl impl = enc->impl; + MppEncHal hal = enc->enc_hal; + MppPacket packet = hal_task->packet; + RK_S32 task_len = hal_task->length; + RK_S32 hw_len = hal_task->hw_length; + RK_S32 pkt_len = mpp_packet_get_length(packet); + + enc_dbg_detail("task %d two pass mode enter\n", frm->seq_idx); + rc_task->info = enc->rc_info_prev; + + enc_dbg_detail("task %d enc proc dpb\n", frm->seq_idx); + mpp_enc_refs_get_cpb_pass1(enc->refs, cpb); + + enc_dbg_frm_status("frm %d start ***********************************\n", cpb->curr.seq_idx); + ENC_RUN_FUNC2(enc_impl_proc_dpb, impl, hal_task, mpp, ret); + + enc_dbg_detail("task %d enc proc hal\n", frm->seq_idx); + ENC_RUN_FUNC2(enc_impl_proc_hal, impl, hal_task, mpp, ret); + + enc_dbg_detail("task %d hal get task\n", frm->seq_idx); + ENC_RUN_FUNC2(mpp_enc_hal_get_task, hal, hal_task, mpp, ret); + + enc_dbg_detail("task %d hal generate reg\n", frm->seq_idx); + ENC_RUN_FUNC2(mpp_enc_hal_gen_regs, hal, hal_task, mpp, ret); + + enc_dbg_detail("task %d hal start\n", frm->seq_idx); + ENC_RUN_FUNC2(mpp_enc_hal_start, hal, hal_task, mpp, ret); + + enc_dbg_detail("task %d hal wait\n", frm->seq_idx); + ENC_RUN_FUNC2(mpp_enc_hal_wait, hal, hal_task, mpp, ret); + + enc_dbg_detail("task %d hal ret task\n", frm->seq_idx); + ENC_RUN_FUNC2(mpp_enc_hal_ret_task, hal, hal_task, mpp, ret); + + //recover status & packet + mpp_packet_set_length(packet, pkt_len); + hal_task->hw_length = hw_len; + hal_task->length = task_len; + + *frm = frm_bak; + rc_task->info = rc_info; + + enc_dbg_detail("task %d two pass mode leave\n", frm->seq_idx); + } +TASK_DONE: + return ret; +} + +static void mpp_enc_rc_info_backup(MppEncImpl *enc) +{ + if (!enc->support_hw_deflicker || !enc->cfg.rc.debreath_en) + return; + + enc->rc_info_prev = enc->rc_task.info; +} + static MPP_RET mpp_enc_normal(Mpp *mpp, EncTask *task) { MppEncImpl *enc = (MppEncImpl *)mpp->mEnc; @@ -1215,6 +1283,12 @@ static MPP_RET mpp_enc_normal(Mpp *mpp, EncTask *task) MppPacket packet = hal_task->packet; MPP_RET ret = MPP_OK; + if (enc->support_hw_deflicker && enc->cfg.rc.debreath_en) { + ret = mpp_enc_proc_two_pass(mpp, task); + if (ret) + return ret; + } + enc_dbg_detail("task %d enc proc dpb\n", frm->seq_idx); mpp_enc_refs_get_cpb(enc->refs, cpb); @@ -1923,6 +1997,7 @@ TASK_DONE: mpp_task_meta_set_frame(enc->task_in, KEY_INPUT_FRAME, enc->frame); mpp_port_enqueue(enc->input, enc->task_in); + mpp_enc_rc_info_backup(enc); reset_enc_task(enc); task->status.val = 0; diff --git a/mpp/codec/mpp_enc_v2.cpp b/mpp/codec/mpp_enc_v2.cpp index 01b3192c..4b445f9e 100644 --- a/mpp/codec/mpp_enc_v2.cpp +++ b/mpp/codec/mpp_enc_v2.cpp @@ -68,12 +68,12 @@ MPP_RET mpp_enc_init_v2(MppEnc *enc, MppEncInitCfg *cfg) enc_hal_cfg.cfg = &p->cfg; enc_hal_cfg.type = VPU_CLIENT_BUTT; enc_hal_cfg.dev = NULL; + enc_hal_cfg.cap_recn_out = 0; ctrl_cfg.coding = coding; ctrl_cfg.type = VPU_CLIENT_BUTT; ctrl_cfg.cfg = &p->cfg; ctrl_cfg.refs = p->refs; - ctrl_cfg.task_count = 2; ret = mpp_enc_hal_init(&enc_hal, &enc_hal_cfg); if (ret) { @@ -82,7 +82,6 @@ MPP_RET mpp_enc_init_v2(MppEnc *enc, MppEncInitCfg *cfg) } ctrl_cfg.type = enc_hal_cfg.type; - ctrl_cfg.task_count = -1; ret = enc_impl_init(&impl, &ctrl_cfg); if (ret) { @@ -107,6 +106,9 @@ MPP_RET mpp_enc_init_v2(MppEnc *enc, MppEncInitCfg *cfg) p->rc_cfg_size = SZ_1K; p->rc_cfg_info = mpp_calloc_size(char, p->rc_cfg_size); + if (enc_hal_cfg.cap_recn_out) + p->support_hw_deflicker = 1; + { // create header packet storage size_t size = SZ_1K; diff --git a/mpp/codec/rc/rc_ctx.h b/mpp/codec/rc/rc_ctx.h index 4b577f3f..71042cf9 100644 --- a/mpp/codec/rc/rc_ctx.h +++ b/mpp/codec/rc/rc_ctx.h @@ -21,7 +21,6 @@ typedef struct RcModelV2Ctx_t { RcCfg usr_cfg; - EncRcTaskInfo hal_cfg; RK_U32 frame_type; RK_U32 last_frame_type; diff --git a/mpp/codec/rc/rc_model_v2.c b/mpp/codec/rc/rc_model_v2.c index b0e6213a..d4ad4b0c 100644 --- a/mpp/codec/rc/rc_model_v2.c +++ b/mpp/codec/rc/rc_model_v2.c @@ -474,10 +474,10 @@ MPP_RET calc_next_i_ratio(RcModelV2Ctx *ctx) MPP_RET calc_debreath_qp(RcModelV2Ctx *ctx) { rc_dbg_func("enter %p\n", ctx); - RK_S32 qp_start_sum = 0; - RK_U8 idx2 = ctx->pre_iblk4_prop >> 5; - RK_S32 new_start_qp = 0; RcDebreathCfg *debreath_cfg = &ctx->usr_cfg.debreath_cfg; + RK_S32 qp_start_sum = 0; + RK_S32 new_start_qp = 0; + RK_U8 idx2 = MPP_MIN(ctx->pre_iblk4_prop >> 5, (RK_S32)sizeof(intra_qp_map) - 1); static RK_S8 strength_map[36] = { 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, @@ -485,7 +485,7 @@ MPP_RET calc_debreath_qp(RcModelV2Ctx *ctx) 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12 }; - qp_start_sum = ctx->gop_qp_sum / ctx->gop_frm_cnt; + qp_start_sum = MPP_MIN(ctx->gop_qp_sum / ctx->gop_frm_cnt, (RK_S32)sizeof(strength_map) - 1); rc_dbg_qp("i start_qp %d, qp_start_sum = %d, intra_lv4_prop %d", ctx->start_qp, qp_start_sum, ctx->pre_iblk4_prop); @@ -496,8 +496,7 @@ MPP_RET calc_debreath_qp(RcModelV2Ctx *ctx) else new_start_qp = qp_start_sum; - ctx->start_qp = new_start_qp; - ctx->start_qp = mpp_clip(ctx->start_qp, 20, 51); + ctx->start_qp = mpp_clip(new_start_qp, ctx->usr_cfg.min_i_quality, ctx->usr_cfg.max_i_quality); rc_dbg_func("leave %p\n", ctx); return MPP_OK; @@ -1264,11 +1263,6 @@ MPP_RET rc_model_v2_start(void *ctx, EncRcTask *task) info->quality_min = usr_cfg->min_quality; } - if (frm->is_idr) { - p->gop_frm_cnt = 0; - p->gop_qp_sum = 0; - } - 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); @@ -1407,9 +1401,13 @@ MPP_RET rc_model_v2_hal_start(void *ctx, EncRcTask *task) if (!p->reenc_cnt) { p->cur_scale_qp = qp_scale; - if (p->usr_cfg.debreath_cfg.enable) + if (p->usr_cfg.debreath_cfg.enable) { calc_debreath_qp(ctx); + } } + + p->gop_frm_cnt = 0; + p->gop_qp_sum = 0; } else { qp_scale = mpp_clip(qp_scale, (info->quality_min << 6), (info->quality_max << 6)); p->cur_scale_qp = qp_scale; diff --git a/mpp/hal/inc/mpp_enc_hal.h b/mpp/hal/inc/mpp_enc_hal.h index 8885bd72..b4b8eb3f 100644 --- a/mpp/hal/inc/mpp_enc_hal.h +++ b/mpp/hal/inc/mpp_enc_hal.h @@ -29,6 +29,7 @@ typedef struct MppEncHalCfg_t { // output from enc_impl MppClientType type; MppDev dev; + RK_S32 cap_recn_out; } MppEncHalCfg; typedef struct MppEncHalApi_t { diff --git a/mpp/hal/rkenc/h264e/hal_h264e_vepu580.c b/mpp/hal/rkenc/h264e/hal_h264e_vepu580.c index 4914f4e5..1bf2f9af 100644 --- a/mpp/hal/rkenc/h264e/hal_h264e_vepu580.c +++ b/mpp/hal/rkenc/h264e/hal_h264e_vepu580.c @@ -49,6 +49,7 @@ typedef struct HalH264eVepu580Ctx_t { RK_S32 pixel_buf_size; RK_S32 thumb_buf_size; RK_S32 max_buf_cnt; + MppDevRegOffCfgs *offsets; /* external line buffer over 4K */ MppBufferGroup ext_line_buf_grp; @@ -77,6 +78,9 @@ typedef struct HalH264eVepu580Ctx_t { /* finetune */ void *tune; + /* two-pass deflicker */ + MppBuffer buf_pass1; + /* register */ HalVepu580RegSet regs_set; } HalH264eVepu580Ctx; @@ -146,6 +150,16 @@ static MPP_RET hal_h264e_vepu580_deinit(void *hal) p->hw_recn = NULL; } + if (p->offsets) { + mpp_dev_multi_offset_deinit(p->offsets); + p->offsets = NULL; + } + + if (p->buf_pass1) { + mpp_buffer_put(p->buf_pass1); + p->buf_pass1 = NULL; + } + if (p->tune) { vepu580_h264e_tune_deinit(p->tune); p->tune = NULL; @@ -198,9 +212,13 @@ static MPP_RET hal_h264e_vepu580_init(void *hal, MppEncHalCfg *cfg) memcpy(hw->aq_step_i, h264_I_aq_step_default, sizeof(hw->aq_step_i)); memcpy(hw->aq_step_p, h264_P_aq_step_default, sizeof(hw->aq_step_p)); } + mpp_dev_multi_offset_init(&p->offsets, 24); + p->osd_cfg.reg_cfg = p->offsets; p->tune = vepu580_h264e_tune_init(p); + cfg->cap_recn_out = 1; + DONE: if (ret) hal_h264e_vepu580_deinit(hal); @@ -558,6 +576,71 @@ static MPP_RET setup_vepu580_prep(HalVepu580RegSet *regs, MppEncPrepCfg *prep) return ret; } +static MPP_RET vepu580_h264e_save_pass1_patch(HalVepu580RegSet *regs, HalH264eVepu580Ctx *ctx) +{ + RK_S32 width_align = MPP_ALIGN(ctx->cfg->prep.width, 16); + RK_S32 height_align = MPP_ALIGN(ctx->cfg->prep.height, 16); + + if (NULL == ctx->buf_pass1) { + mpp_buffer_get(NULL, &ctx->buf_pass1, width_align * height_align * 3 / 2); + if (!ctx->buf_pass1) { + mpp_err("buf_pass1 malloc fail, debreath invaild"); + return MPP_NOK; + } + } + + regs->reg_base.enc_pic.cur_frm_ref = 1; + regs->reg_base.rfpw_h_addr = mpp_buffer_get_fd(ctx->buf_pass1); + regs->reg_base.rfpw_b_addr = regs->reg_base.rfpw_h_addr; + regs->reg_base.enc_pic.rec_fbc_dis = 1; + mpp_dev_multi_offset_update(ctx->offsets, 164, width_align * height_align); + + return MPP_OK; +} + +static MPP_RET vepu580_h264e_use_pass1_patch(HalVepu580RegSet *regs, HalH264eVepu580Ctx *ctx) +{ + MppEncPrepCfg *prep = &ctx->cfg->prep; + RK_S32 hor_stride = MPP_ALIGN(prep->width, 16); + RK_S32 ver_stride = MPP_ALIGN(prep->height, 16); + RK_S32 frame_size = hor_stride * ver_stride; + RK_S32 fd_in = mpp_buffer_get_fd(ctx->buf_pass1); + RK_S32 y_stride; + RK_S32 c_stride; + + hal_h264e_dbg_func("enter\n"); + + regs->reg_base.src_fmt.src_cfmt = VEPU541_FMT_YUV420SP; + regs->reg_base.src_fmt.alpha_swap = 0; + regs->reg_base.src_fmt.rbuv_swap = 0; + regs->reg_base.src_fmt.out_fmt = 1; + + y_stride = MPP_ALIGN(prep->width, 16); + c_stride = y_stride; + + regs->reg_base.src_proc.afbcd_en = 0; + regs->reg_base.src_strd0.src_strd0 = y_stride; + regs->reg_base.src_strd1.src_strd1 = c_stride; + + regs->reg_base.src_proc.src_mirr = 0; + regs->reg_base.src_proc.src_rot = 0; + regs->reg_base.src_proc.txa_en = 0; + + regs->reg_base.pic_ofst.pic_ofst_y = 0; + regs->reg_base.pic_ofst.pic_ofst_x = 0; + + + regs->reg_base.adr_src0 = fd_in; + regs->reg_base.adr_src1 = fd_in; + regs->reg_base.adr_src2 = fd_in; + + mpp_dev_multi_offset_update(ctx->offsets, 161, frame_size); + mpp_dev_multi_offset_update(ctx->offsets, 162, frame_size); + + hal_h264e_dbg_func("leave\n"); + return MPP_OK; +} + static void setup_vepu580_codec(HalVepu580RegSet *regs, H264eSps *sps, H264ePps *pps, H264eSlice *slice) { @@ -1056,7 +1139,7 @@ static void setup_vepu580_rc_base(HalVepu580RegSet *regs, H264eSps *sps, hal_h264e_dbg_func("leave\n"); } -static void setup_vepu580_io_buf(HalVepu580RegSet *regs, MppDev dev, +static void setup_vepu580_io_buf(HalVepu580RegSet *regs, MppDevRegOffCfgs *offsets, HalEncTask *task) { MppFrame frm = task->frame; @@ -1131,23 +1214,10 @@ static void setup_vepu580_io_buf(HalVepu580RegSet *regs, MppDev dev, } } - MppDevRegOffsetCfg trans_cfg; - - trans_cfg.reg_idx = 161; - trans_cfg.offset = off_in[0]; - mpp_dev_ioctl(dev, MPP_DEV_REG_OFFSET, &trans_cfg); - - trans_cfg.reg_idx = 162; - trans_cfg.offset = off_in[1]; - mpp_dev_ioctl(dev, MPP_DEV_REG_OFFSET, &trans_cfg); - - trans_cfg.reg_idx = 172; - trans_cfg.offset = siz_out; - mpp_dev_ioctl(dev, MPP_DEV_REG_OFFSET, &trans_cfg); - - trans_cfg.reg_idx = 175; - trans_cfg.offset = off_out; - mpp_dev_ioctl(dev, MPP_DEV_REG_OFFSET, &trans_cfg); + mpp_dev_multi_offset_update(offsets, 161, off_in[0]); + mpp_dev_multi_offset_update(offsets, 162, off_in[1]); + mpp_dev_multi_offset_update(offsets, 172, siz_out); + mpp_dev_multi_offset_update(offsets, 175, off_out); hal_h264e_dbg_func("leave\n"); } @@ -1183,13 +1253,14 @@ static void setup_vepu580_roi(HalVepu580RegSet *regs, HalH264eVepu580Ctx *ctx) hal_h264e_dbg_func("leave\n"); } -static void setup_vepu580_recn_refr(HalVepu580RegSet *regs, MppDev dev, - H264eFrmInfo *frms, HalBufs bufs, - RK_S32 fbc_hdr_size) +static void setup_vepu580_recn_refr(HalH264eVepu580Ctx *ctx, HalVepu580RegSet *regs) { + H264eFrmInfo *frms = ctx->frms; + HalBufs bufs = ctx->hw_recn; + RK_S32 fbc_hdr_size = ctx->pixel_buf_fbc_hdr_size; + HalBuf *curr = hal_bufs_get_buf(bufs, frms->curr_idx); HalBuf *refr = hal_bufs_get_buf(bufs, frms->refr_idx); - MppDevRegOffsetCfg trans_cfg; hal_h264e_dbg_func("enter\n"); @@ -1204,10 +1275,6 @@ static void setup_vepu580_recn_refr(HalVepu580RegSet *regs, MppDev dev, regs->reg_base.rfpw_h_addr = fd; regs->reg_base.rfpw_b_addr = fd; regs->reg_base.dspw_addr = mpp_buffer_get_fd(buf_thumb); - - trans_cfg.reg_idx = 164; - trans_cfg.offset = fbc_hdr_size; - mpp_dev_ioctl(dev, MPP_DEV_REG_OFFSET, &trans_cfg); } if (refr && refr->cnt) { @@ -1221,12 +1288,11 @@ static void setup_vepu580_recn_refr(HalVepu580RegSet *regs, MppDev dev, regs->reg_base.rfpr_h_addr = fd; regs->reg_base.rfpr_b_addr = fd; regs->reg_base.dspr_addr = mpp_buffer_get_fd(buf_thumb); - - trans_cfg.reg_idx = 166; - trans_cfg.offset = fbc_hdr_size; - mpp_dev_ioctl(dev, MPP_DEV_REG_OFFSET, &trans_cfg); } + mpp_dev_multi_offset_update(ctx->offsets, 164, fbc_hdr_size); + mpp_dev_multi_offset_update(ctx->offsets, 166, fbc_hdr_size); + hal_h264e_dbg_func("leave\n"); } @@ -1620,20 +1686,21 @@ static void setup_vepu580_l2(HalVepu580RegSet *regs, H264eSlice *slice, MppEncHw static void setup_vepu580_ext_line_buf(HalVepu580RegSet *regs, HalH264eVepu580Ctx *ctx) { + RK_S32 offset = 0; + if (ctx->ext_line_buf) { - MppDevRegOffsetCfg trans_cfg; RK_S32 fd = mpp_buffer_get_fd(ctx->ext_line_buf); regs->reg_base.ebuft_addr = fd; regs->reg_base.ebufb_addr = fd; - trans_cfg.reg_idx = 182; - trans_cfg.offset = ctx->ext_line_buf_size; - mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_OFFSET, &trans_cfg); + offset = ctx->ext_line_buf_size; } else { regs->reg_base.ebufb_addr = 0; regs->reg_base.ebufb_addr = 0; } + + mpp_dev_multi_offset_update(ctx->offsets, 182, offset); } static MPP_RET hal_h264e_vepu580_gen_regs(void *hal, HalEncTask *task) @@ -1644,6 +1711,8 @@ static MPP_RET hal_h264e_vepu580_gen_regs(void *hal, HalEncTask *task) H264eSps *sps = ctx->sps; H264ePps *pps = ctx->pps; H264eSlice *slice = ctx->slice; + EncRcTask *rc_task = task->rc_task; + EncFrmStatus *frm = &rc_task->frm; MPP_RET ret = MPP_OK; hal_h264e_dbg_func("enter %p\n", hal); @@ -1661,11 +1730,10 @@ static MPP_RET hal_h264e_vepu580_gen_regs(void *hal, HalEncTask *task) setup_vepu580_rdo_pred(regs, sps, pps, slice); setup_vepu580_rdo_cfg(®s->reg_rdo); setup_vepu580_scl_cfg(®s->reg_scl); - setup_vepu580_rc_base(regs, sps, slice, &cfg->hw, task->rc_task); - setup_vepu580_io_buf(regs, ctx->dev, task); + setup_vepu580_rc_base(regs, sps, slice, &cfg->hw, rc_task); + setup_vepu580_io_buf(regs, ctx->offsets, task); setup_vepu580_roi(regs, ctx); - setup_vepu580_recn_refr(regs, ctx->dev, ctx->frms, ctx->hw_recn, - ctx->pixel_buf_fbc_hdr_size); + setup_vepu580_recn_refr(ctx, regs); regs->reg_base.meiw_addr = task->mv_info ? mpp_buffer_get_fd(task->mv_info) : 0; @@ -1680,6 +1748,13 @@ static MPP_RET hal_h264e_vepu580_gen_regs(void *hal, HalEncTask *task) setup_vepu580_ext_line_buf(regs, ctx); vepu580_h264e_tune_reg_patch(ctx->tune); + /* two pass register patch */ + if (frm->save_pass1) + vepu580_h264e_save_pass1_patch(regs, ctx); + + if (frm->use_pass1) + vepu580_h264e_use_pass1_patch(regs, ctx); + mpp_env_get_u32("dump_l1_reg", &dump_l1_reg, 0); if (dump_l1_reg) { @@ -1789,6 +1864,12 @@ static MPP_RET hal_h264e_vepu580_start(void *hal, HalEncTask *task) break; } + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_OFFS, ctx->offsets); + if (ret) { + mpp_err_f("set register offsets failed %d\n", ret); + break; + } + rd_cfg.reg = &ctx->regs_set.reg_st; rd_cfg.size = sizeof(ctx->regs_set.reg_st); rd_cfg.offset = VEPU580_STATUS_OFFSET; @@ -1901,6 +1982,8 @@ static MPP_RET hal_h264e_vepu580_ret_task(void *hal, HalEncTask *task) vepu580_h264e_tune_stat_update(ctx->tune); + mpp_dev_multi_offset_reset(ctx->offsets); + hal_h264e_dbg_func("leave %p\n", hal); return MPP_OK; diff --git a/mpp/hal/rkenc/h265e/hal_h265e_vepu580.c b/mpp/hal/rkenc/h265e/hal_h265e_vepu580.c index 9988b13a..2b12aafa 100644 --- a/mpp/hal/rkenc/h265e/hal_h265e_vepu580.c +++ b/mpp/hal/rkenc/h265e/hal_h265e_vepu580.c @@ -87,6 +87,7 @@ typedef struct H265eV580HalContext_t { MppBufferGroup tile_grp; MppBuffer hw_tile_buf[2]; MppBuffer hw_tile_stream; + MppBuffer buf_pass1; RK_U32 enc_mode; RK_U32 frame_size; @@ -1172,6 +1173,9 @@ MPP_RET hal_h265e_v580_init(void *hal, MppEncHalCfg *cfg) ctx->tile_parall_en = cap->send_cmd > MPP_CMD_SET_SESSION_FD; } + + cfg->cap_recn_out = 1; + hal_h265e_leave(); return ret; } @@ -1211,6 +1215,11 @@ MPP_RET hal_h265e_v580_deinit(void *hal) ctx->tile_grp = NULL; } + if (ctx->buf_pass1) { + mpp_buffer_put(ctx->buf_pass1); + ctx->buf_pass1 = NULL; + } + if (ctx->dev) { mpp_dev_deinit(ctx->dev); ctx->dev = NULL; @@ -1308,18 +1317,14 @@ vepu580_h265_set_patch_info(MppDevRegOffCfgs *cfgs, H265eSyntax_new *syn, } /* input cb addr */ - if (u_offset) { - ret = mpp_dev_multi_offset_update(cfgs, 161, u_offset); - if (ret) - mpp_err_f("set input cb addr offset failed %d\n", ret); - } + ret = mpp_dev_multi_offset_update(cfgs, 161, u_offset); + if (ret) + mpp_err_f("set input cb addr offset failed %d\n", ret); /* input cr addr */ - if (v_offset) { - ret = mpp_dev_multi_offset_update(cfgs, 162, v_offset); - if (ret) - mpp_err_f("set input cr addr offset failed %d\n", ret); - } + ret = mpp_dev_multi_offset_update(cfgs, 162, v_offset); + if (ret) + mpp_err_f("set input cr addr offset failed %d\n", ret); return ret; } @@ -1850,6 +1855,7 @@ void vepu580_h265_set_hw_address(H265eV580HalContext *ctx, hevc_vepu580_base *re if (!syn->sp.non_reference_flag) { regs->reg0163_rfpw_h_addr = mpp_buffer_get_fd(recon_buf->buf[0]); regs->reg0164_rfpw_b_addr = regs->reg0163_rfpw_h_addr; + mpp_dev_multi_offset_update(ctx->reg_cfg, 164, ctx->fbc_header_len); } regs->reg0165_rfpr_h_addr = mpp_buffer_get_fd(ref_buf->buf[0]); @@ -1899,15 +1905,76 @@ void vepu580_h265_set_hw_address(H265eV580HalContext *ctx, hevc_vepu580_base *re mpp_dev_multi_offset_update(ctx->reg_cfg, 175, mpp_packet_get_length(task->packet)); mpp_dev_multi_offset_update(ctx->reg_cfg, 172, mpp_buffer_get_size(enc_task->output)); +} - regs->reg0204_pic_ofst.pic_ofst_y = mpp_frame_get_offset_y(task->frame); - regs->reg0204_pic_ofst.pic_ofst_x = mpp_frame_get_offset_x(task->frame); +static MPP_RET vepu580_h265e_save_pass1_patch(H265eV580RegSet *regs, H265eV580HalContext *ctx, + RK_S32 tiles_enabled_flag) +{ + hevc_vepu580_base *reg_base = ®s->reg_base; + RK_S32 width_align = MPP_ALIGN(ctx->cfg->prep.width, 64); + RK_S32 height_align = MPP_ALIGN(ctx->cfg->prep.height, 64); + + if (NULL == ctx->buf_pass1) { + mpp_buffer_get(NULL, &ctx->buf_pass1, width_align * height_align * 3 / 2); + if (!ctx->buf_pass1) { + mpp_err("buf_pass1 malloc fail, debreath invaild"); + return MPP_NOK; + } + } + + reg_base->reg0192_enc_pic.cur_frm_ref = 1; + reg_base->reg0163_rfpw_h_addr = mpp_buffer_get_fd(ctx->buf_pass1); + reg_base->reg0164_rfpw_b_addr = reg_base->reg0163_rfpw_h_addr; + reg_base->reg0192_enc_pic.rec_fbc_dis = 1; + + if (tiles_enabled_flag) + reg_base->reg0238_synt_pps.lpf_fltr_acrs_til = 0; + + mpp_dev_multi_offset_update(ctx->reg_cfg, 164, width_align * height_align); + + return MPP_OK; +} + +static MPP_RET vepu580_h265e_use_pass1_patch(H265eV580RegSet *regs, H265eV580HalContext *ctx, + H265eSyntax_new *syn) +{ + hevc_vepu580_control_cfg *reg_ctl = ®s->reg_ctl; + hevc_vepu580_base *reg_base = ®s->reg_base; + RK_U32 hor_stride = MPP_ALIGN(syn->pp.pic_width, 64); + RK_U32 ver_stride = MPP_ALIGN(syn->pp.pic_height, 64); + RK_U32 frame_size = hor_stride * ver_stride; + RK_S32 stridey = MPP_ALIGN(syn->pp.pic_width, 64); + VepuFmtCfg *fmt = (VepuFmtCfg *)ctx->input_fmt; + MPP_RET ret = MPP_OK; + + reg_ctl->reg0012_dtrns_map.src_bus_edin = fmt->src_endian; + reg_base->reg0198_src_fmt.src_cfmt = VEPU541_FMT_YUV420SP; + reg_base->reg0198_src_fmt.out_fmt = 1; + reg_base->reg0205_src_strd0.src_strd0 = stridey; + reg_base->reg0206_src_strd1.src_strd1 = stridey; + reg_base->reg0160_adr_src0 = mpp_buffer_get_fd(ctx->buf_pass1); + reg_base->reg0161_adr_src1 = reg_base->reg0160_adr_src0; + reg_base->reg0162_adr_src2 = reg_base->reg0160_adr_src0; + + /* input cb addr */ + ret = mpp_dev_multi_offset_update(ctx->reg_cfg, 161, frame_size); + if (ret) + mpp_err_f("set input cb addr offset failed %d\n", ret); + + /* input cr addr */ + ret = mpp_dev_multi_offset_update(ctx->reg_cfg, 162, frame_size); + if (ret) + mpp_err_f("set input cr addr offset failed %d\n", ret); + + return MPP_OK; } MPP_RET hal_h265e_v580_gen_regs(void *hal, HalEncTask *task) { H265eV580HalContext *ctx = (H265eV580HalContext *)hal; HalEncTask *enc_task = task; + EncRcTask *rc_task = enc_task->rc_task; + EncFrmStatus *frm = &rc_task->frm; H265eSyntax_new *syn = (H265eSyntax_new *)enc_task->syntax.data; H265eV580RegSet *regs = (H265eV580RegSet *)ctx->regs[0]; RK_U32 pic_width_align8, pic_height_align8; @@ -2041,6 +2108,13 @@ MPP_RET hal_h265e_v580_gen_regs(void *hal, HalEncTask *task) vepu580_h265e_tune_reg_patch(ctx->tune); + /* two pass register patch */ + if (frm->save_pass1) + vepu580_h265e_save_pass1_patch(regs, ctx, syn->pp.tiles_enabled_flag); + + if (frm->use_pass1) + vepu580_h265e_use_pass1_patch(regs, ctx, syn); + ctx->frame_num++; hal_h265e_leave(); @@ -2131,11 +2205,14 @@ MPP_RET hal_h265e_v580_start(void *hal, HalEncTask *enc_task) hal_h265e_v580_set_uniform_tile(&hw_regs->reg_base, syn, k); if (k) { - if (!ctx->tile_parall_en) { - RK_U32 offset = mpp_packet_get_length(enc_task->packet); + RK_U32 offset = 0; + if (!ctx->tile_parall_en) { + offset = mpp_packet_get_length(enc_task->packet); offset += stream_len; + reg_base->reg0173_bsbb_addr = mpp_buffer_get_fd(enc_task->output); + mpp_dev_multi_offset_update(ctx->reg_cfg, 175, offset); mpp_dev_multi_offset_update(ctx->reg_cfg, 172, mpp_buffer_get_size(enc_task->output)); } else { @@ -2147,8 +2224,17 @@ MPP_RET hal_h265e_v580_start(void *hal, HalEncTask *enc_task) mpp_dev_multi_offset_update(ctx->reg_cfg, 175, 0); mpp_dev_multi_offset_update(ctx->reg_cfg, 172, mpp_buffer_get_size(ctx->hw_tile_stream)); } - mpp_dev_multi_offset_update(ctx->reg_cfg, 164, ctx->fbc_header_len); - mpp_dev_multi_offset_update(ctx->reg_cfg, 166, ctx->fbc_header_len); + + offset = ctx->fbc_header_len; + + mpp_dev_multi_offset_update(ctx->reg_cfg, 166, offset); + mpp_dev_multi_offset_update(ctx->reg_cfg, 164, offset); + + if (enc_task->rc_task->frm.save_pass1) + vepu580_h265e_save_pass1_patch(hw_regs, ctx, syn->pp.tiles_enabled_flag); + + if (enc_task->rc_task->frm.use_pass1) + vepu580_h265e_use_pass1_patch(hw_regs, ctx, syn); } hal_h265e_v580_send_regs(ctx->dev, hw_regs, reg_out); diff --git a/test/mpi_rc2_test.c b/test/mpi_rc2_test.c index 1e66b783..4664805e 100644 --- a/test/mpi_rc2_test.c +++ b/test/mpi_rc2_test.c @@ -961,11 +961,6 @@ RET: } \ } while (0) -static const char *name_of_gop_mode[] = { - "normal_p", - "smart_p", -}; - static void *rc2_pre_dec_thread(void *param) { MpiRc2TestCtx *ctx = (MpiRc2TestCtx *)param; @@ -1057,16 +1052,19 @@ static MPP_RET mpi_rc_codec(MpiRc2TestCtx *ctx) ctx->frm_idx, elapsed_time / 1000, frame_rate); if (ctx->frm_idx) { - mpp_log("%s: %s: average: bps %d | psnr %5.2f | ssim %5.5f", ctx->enc_cmd->file_input, - name_of_gop_mode[ctx->enc_cmd->gop_mode], + MpiEncTestArgs* enc_cmd = ctx->enc_cmd; + + mpp_log("%s: %s: average: bps %d | psnr %5.2f | ssim %5.5f", + enc_cmd->file_input, enc_cmd->gop_mode ? "smart_p" : "normal_p", 30 * (RK_U32)(ctx->total_bits / ctx->frm_idx), ctx->total_psnrs / ctx->frm_idx, ctx->total_ssims / ctx->frm_idx); if (ctx->file.fp_stat) - fprintf(ctx->file.fp_stat, "%s: %s: average: bps %dk | psnr %5.2f | ssim %5.5f \n", ctx->enc_cmd->file_input, - name_of_gop_mode[ctx->enc_cmd->gop_mode], + fprintf(ctx->file.fp_stat, "%s: %s: average: bps %dk | psnr %5.2f | ssim %5.5f \n", + enc_cmd->file_input, enc_cmd->gop_mode ? "smart_p" : "normal_p", 30 * (RK_U32)(ctx->total_bits / ctx->frm_idx) / 1000, ctx->total_psnrs / ctx->frm_idx, ctx->total_ssims / ctx->frm_idx); } + CHECK_RET(ctx->enc_mpi->reset(ctx->enc_ctx)); CHECK_RET(ctx->dec_mpi_pre->reset(ctx->dec_ctx_pre)); CHECK_RET(ctx->dec_mpi_post->reset(ctx->dec_ctx_post));