From bd5aa46c5182c91a5ae724d21e10cd131bbbda1c Mon Sep 17 00:00:00 2001 From: Johnson Ding Date: Wed, 13 Jul 2022 16:28:45 +0800 Subject: [PATCH] [avs2d]: Optimise dec result when player seeking Change-Id: I92565bb05956276f0f626f9293d70e8b38211209 Signed-off-by: Johnson Ding --- mpp/codec/dec/avs2/avs2d_api.c | 66 +++++++++++++++++++++++------ mpp/codec/dec/avs2/avs2d_dpb.c | 31 ++++++++------ mpp/codec/dec/avs2/avs2d_parse.c | 2 +- mpp/hal/rkdec/avs2d/hal_avs2d_rkv.c | 64 +++++++++++++++++++++++++--- 4 files changed, 131 insertions(+), 32 deletions(-) diff --git a/mpp/codec/dec/avs2/avs2d_api.c b/mpp/codec/dec/avs2/avs2d_api.c index be50d148..f4a79088 100644 --- a/mpp/codec/dec/avs2/avs2d_api.c +++ b/mpp/codec/dec/avs2/avs2d_api.c @@ -230,7 +230,6 @@ MPP_RET avs2d_parse(void *decoder, HalDecTask *task) AVS2D_PARSE_TRACE("In."); task->valid = 0; - // memset(task->refer, -1, sizeof(task->refer)); avs2d_parse_stream(p_dec, task); if (task->valid) { @@ -252,28 +251,69 @@ MPP_RET avs2d_callback(void *decoder, void *info) { MPP_RET ret = MPP_ERR_UNKNOW; Avs2dCtx_t *p_dec = (Avs2dCtx_t *)decoder; + Avs2dFrameMgr_t *mgr = &p_dec->frm_mgr; DecCbHalDone *ctx = (DecCbHalDone *)info; - MppFrame mframe = NULL; HalDecTask *task_dec = (HalDecTask *)ctx->task; + MppFrame mframe = NULL; + MppFrame ref_frm = NULL; + RK_U32 i = 0; + RK_U32 error = 0; + RK_U32 discard = 0; + RK_U32 ref_used_flag = 0; AVS2D_PARSE_TRACE("In."); mpp_buf_slot_get_prop(p_dec->frame_slots, task_dec->output, SLOT_FRAME_PTR, &mframe); - AVS2D_DBG(AVS2D_DBG_CALLBACK, "frame poc %d, ref=%d, dpberr=%d, harderr=%d\n", - mpp_frame_get_poc(mframe), - task_dec->flags.used_for_ref, task_dec->flags.ref_err, ctx->hard_err); + if (!mframe) { + ret = MPP_ERR_UNKNOW; + AVS2D_DBG(AVS2D_DBG_CALLBACK, "[CALLBACK]: failed to get frame\n"); + goto __FAILED; + } - if (mframe) { - if (ctx->hard_err || task_dec->flags.ref_err) { - if (task_dec->flags.used_for_ref) { - mpp_frame_set_errinfo(mframe, 1); - } else { - mpp_frame_set_discard(mframe, 1); - } + if (ctx->hard_err || task_dec->flags.ref_err) { + if (task_dec->flags.used_for_ref) { + error = 1; + } else { + discard = 1; + } + } else { + if (task_dec->flags.ref_miss & task_dec->flags.ref_used) { + discard = 1; + AVS2D_DBG(AVS2D_DBG_CALLBACK, "[CALLBACK]: fake ref used, miss 0x%x used 0x%x\n", + task_dec->flags.ref_miss, task_dec->flags.ref_used); } } + + for (i = 0; i < AVS2_MAX_REFS; i++) { + if (!mgr->refs[i] || !mgr->refs[i]->frame || mgr->refs[i]->slot_idx < 0) + continue; + + mpp_buf_slot_get_prop(p_dec->frame_slots, mgr->refs[i]->slot_idx, SLOT_FRAME_PTR, &ref_frm); + if (!ref_frm) + continue; + + ref_used_flag = (task_dec->flags.ref_used >> i) & 1; + //TODO: In fast mode, ref list isn't kept sync with task flag.ref_used + AVS2D_DBG(AVS2D_DBG_CALLBACK, "[CALLBACK]: ref_frm poc %d, err %d, dis %d, ref_used %d\n", + mpp_frame_get_poc(ref_frm), mpp_frame_get_errinfo(ref_frm), + mpp_frame_get_discard(ref_frm), ref_used_flag); + + if (ref_used_flag) { + discard |= mpp_frame_get_discard(ref_frm); + error |= mpp_frame_get_errinfo(ref_frm); + } + } + + mpp_frame_set_errinfo(mframe, error); + mpp_frame_set_discard(mframe, discard); + + AVS2D_DBG(AVS2D_DBG_CALLBACK, "[CALLBACK]: frame poc %d, ref=%d, dpberr=%d, harderr=%d, err:dis=%d:%d\n", + mpp_frame_get_poc(mframe), task_dec->flags.used_for_ref, task_dec->flags.ref_err, + ctx->hard_err, error, discard); + +__FAILED: AVS2D_PARSE_TRACE("Out."); - return ret = MPP_OK; + return ret; } const ParserApi api_avs2d_parser = { diff --git a/mpp/codec/dec/avs2/avs2d_dpb.c b/mpp/codec/dec/avs2/avs2d_dpb.c index c9e62a49..80458f6f 100644 --- a/mpp/codec/dec/avs2/avs2d_dpb.c +++ b/mpp/codec/dec/avs2/avs2d_dpb.c @@ -485,6 +485,7 @@ static Avs2dFrame_t *dpb_alloc_frame(Avs2dCtx_t *p_dec, HalDecTask *task) mpp_frame_set_pts(mframe, mpp_packet_get_pts(task->input_packet)); mpp_frame_set_dts(mframe, mpp_packet_get_dts(task->input_packet)); mpp_frame_set_errinfo(mframe, 0); + mpp_frame_set_discard(mframe, 0); mpp_frame_set_poc(mframe, frm->poi); if (p_dec->got_exh) { mpp_frame_set_color_primaries(mframe, exh->color_primaries); @@ -638,26 +639,26 @@ static MPP_RET dpb_set_frame_refs(Avs2dCtx_t *p_dec, Avs2dFrameMgr_t *mgr, HalDe (void) task; avs2d_dbg_dpb("In."); - for (i = 0; i < AVS2_MAX_REFS; i++) { - mgr->refs[i] = NULL; - } + memset(mgr->refs, 0, sizeof(mgr->refs)); p_cur = mgr->cur_frm; mgr->num_of_ref = 0; p_rps = &mgr->cur_rps; num_of_ref = p_rps->num_of_ref; + task->flags.ref_miss = 0; for (i = 0; i < num_of_ref; i++) { doi_of_ref = p_cur->doi - p_rps->ref_pic[i]; p = find_ref_frame(mgr, doi_of_ref); if (!p) { - mpp_frame_set_discard(p_cur->frame, 1); + task->flags.ref_miss |= 1 << i; avs2d_dbg_dpb("Missing ref doi %d", doi_of_ref); } else { mgr->refs[mgr->num_of_ref] = p; - mgr->num_of_ref++; mpp_buf_slot_set_flag(p_dec->frame_slots, p->slot_idx, SLOT_CODEC_USE); mpp_buf_slot_set_flag(p_dec->frame_slots, p->slot_idx, SLOT_HAL_INPUT); } + + mgr->num_of_ref++; } if (mgr->num_of_ref < 1 && !p_cur->intra_frame_flag) { @@ -668,7 +669,7 @@ static MPP_RET dpb_set_frame_refs(Avs2dCtx_t *p_dec, Avs2dFrameMgr_t *mgr, HalDe error_flag = 1; } else if (mgr->scene_ref != mgr->refs[0] || mgr->num_of_ref > 1) { AVS2D_DBG(AVS2D_DBG_ERROR, "Error reference frame(doi %lld ~ %lld) for S.\n", - mgr->scene_ref->doi, mgr->refs[0]->doi); + mgr->scene_ref->doi, mgr->refs[0] ? mgr->refs[0]->doi : -1); mgr->num_of_ref = 1; mgr->refs[mgr->num_of_ref - 1] = mgr->scene_ref; } @@ -681,7 +682,8 @@ static MPP_RET dpb_set_frame_refs(Avs2dCtx_t *p_dec, Avs2dFrameMgr_t *mgr, HalDe mgr->refs[mgr->num_of_ref - 1] = mgr->scene_ref; } } else if (p_cur->picture_type == B_PICTURE && - (mgr->num_of_ref != 2 || mgr->refs[0]->poi <= p_cur->poi || mgr->refs[1]->poi >= p_cur->poi)) { + (mgr->num_of_ref != 2 || (mgr->refs[0] && mgr->refs[0]->poi <= p_cur->poi) || + (mgr->refs[1] && mgr->refs[1]->poi >= p_cur->poi))) { error_flag = 1; } @@ -740,13 +742,18 @@ MPP_RET avs2d_dpb_insert(Avs2dCtx_t *p_dec, HalDecTask *task) //!< set task refers ret = dpb_set_frame_refs(p_dec, mgr, task); - if (ret != MPP_OK) { - task->flags.ref_err |= mpp_frame_get_errinfo(mgr->cur_frm); - } + if (ret) + task->flags.ref_err = 0; for (i = 0; i < mgr->num_of_ref; i++) { - task->refer[i] = mgr->refs[i]->slot_idx; - avs2d_dbg_dpb("task refer[%d] slot_idx %d doi %d poi %d", i, task->refer[i], mgr->refs[i]->doi, mgr->refs[i]->poi); + task->refer[i] = mgr->refs[i] ? mgr->refs[i]->slot_idx : -1; + if (mgr->refs[i]) { + task->refer[i] = mgr->refs[i]->slot_idx; + avs2d_dbg_dpb("task refer[%d] slot_idx %d doi %d poi %d", i, task->refer[i], mgr->refs[i]->doi, mgr->refs[i]->poi); + } else { + task->refer[i] = -1; + avs2d_dbg_dpb("task refer[%d] missing ref\n", i); + } } //!< update dpb by rps diff --git a/mpp/codec/dec/avs2/avs2d_parse.c b/mpp/codec/dec/avs2/avs2d_parse.c index 154ca873..b033b8e7 100644 --- a/mpp/codec/dec/avs2/avs2d_parse.c +++ b/mpp/codec/dec/avs2/avs2d_parse.c @@ -325,7 +325,7 @@ MPP_RET avs2d_fill_parameters(Avs2dCtx_t *p_dec, Avs2dSyntax_t *syntax) refp->ref_pic_num = mgr->num_of_ref; memset(refp->ref_poc_list, -1, sizeof(refp->ref_poc_list)); for (i = 0; i < mgr->num_of_ref; i++) { - refp->ref_poc_list[i] = mgr->refs[i]->poi; + refp->ref_poc_list[i] = mgr->refs[i] ? mgr->refs[i]->poi : -1; } //!< picture alf params diff --git a/mpp/hal/rkdec/avs2d/hal_avs2d_rkv.c b/mpp/hal/rkdec/avs2d/hal_avs2d_rkv.c index 6a9fb792..ef0df144 100644 --- a/mpp/hal/rkdec/avs2d/hal_avs2d_rkv.c +++ b/mpp/hal/rkdec/avs2d/hal_avs2d_rkv.c @@ -315,6 +315,7 @@ static void hal_avs2d_rcb_info_update(void *hal, Vdpu34xAvs2dRegSet *hw_regs) static MPP_RET fill_registers(Avs2dHalCtx_t *p_hal, Vdpu34xAvs2dRegSet *p_regs, HalTaskInfo *task) { + MPP_RET ret = MPP_OK; RK_U32 i; MppFrame mframe = NULL; Avs2dSyntax_t *syntax = &p_hal->syntax; @@ -372,14 +373,30 @@ static MPP_RET fill_registers(Avs2dHalCtx_t *p_hal, Vdpu34xAvs2dRegSet *p_regs, // set reference { RK_U64 ref_flag = 0; + RK_S32 valid_slot = -1; AVS2D_HAL_TRACE("num of ref %d", refp->ref_pic_num); + for (i = 0; i < refp->ref_pic_num; i++) { + if (task_dec->refer[i] < 0) + continue; + + valid_slot = i; + break; + } + for (i = 0; i < MAX_REF_NUM; i++) { if (i < refp->ref_pic_num) { MppFrame frame_ref = NULL; - mpp_buf_slot_get_prop(p_hal->frame_slots, task_dec->refer[i], SLOT_FRAME_PTR, &frame_ref); + RK_S32 slot_idx = task_dec->refer[i] < 0 ? valid_slot : task_dec->refer[i]; + + if (slot_idx < 0) { + AVS2D_HAL_TRACE("missing ref, could not found valid ref"); + return ret = MPP_ERR_UNKNOW; + } + + mpp_buf_slot_get_prop(p_hal->frame_slots, slot_idx, SLOT_FRAME_PTR, &frame_ref); if (frame_ref) { RK_U32 frm_flag = 1 << 3; @@ -392,14 +409,14 @@ static MPP_RET fill_registers(Avs2dHalCtx_t *p_hal, Vdpu34xAvs2dRegSet *p_regs, ref_flag |= frm_flag << (i * 8); - p_regs->avs2d_addr.ref_base[i] = get_frame_fd(p_hal, task_dec->refer[i]); - mv_buf = hal_bufs_get_buf(p_hal->cmv_bufs, task_dec->refer[i]); + p_regs->avs2d_addr.ref_base[i] = get_frame_fd(p_hal, slot_idx); + mv_buf = hal_bufs_get_buf(p_hal->cmv_bufs, slot_idx); p_regs->avs2d_addr.colmv_base[i] = mpp_buffer_get_fd(mv_buf->buf[0]); p_regs->avs2d_param.reg67_098_ref_poc[i] = mpp_frame_get_poc(frame_ref); AVS2D_HAL_TRACE("ref_base[%d] index=%d, fd = %d, colmv %d, poc %d", - i, task_dec->refer[i], p_regs->avs2d_addr.ref_base[i], + i, slot_idx, p_regs->avs2d_addr.ref_base[i], p_regs->avs2d_addr.colmv_base[i], p_regs->avs2d_param.reg67_098_ref_poc[i]); } } @@ -418,7 +435,7 @@ static MPP_RET fill_registers(Avs2dHalCtx_t *p_hal, Vdpu34xAvs2dRegSet *p_regs, common->reg016_str_len = MPP_ALIGN(mpp_packet_get_length(task_dec->input_packet), 16) + 64; } - return MPP_OK; + return ret; } MPP_RET hal_avs2d_rkv_deinit(void *hal) @@ -624,7 +641,10 @@ MPP_RET hal_avs2d_rkv_gen_regs(void *hal, HalTaskInfo *task) prepare_header(p_hal, reg_ctx->shph_dat, sizeof(reg_ctx->shph_dat)); prepare_scalist(p_hal, reg_ctx->scalist_dat, sizeof(reg_ctx->scalist_dat)); - fill_registers(p_hal, regs, task); + ret = fill_registers(p_hal, regs, task); + + if (ret) + goto __RETURN; { memcpy(reg_ctx->bufs_ptr + reg_ctx->shph_offset, reg_ctx->shph_dat, sizeof(reg_ctx->shph_dat)); @@ -686,6 +706,9 @@ MPP_RET hal_avs2d_rkv_gen_regs(void *hal, HalTaskInfo *task) } vdpu34x_setup_statistic(®s->common, ®s->statistic); + /* enable reference frame usage feedback */ + regs->statistic.reg265.perf_cnt0_sel = 42; + regs->statistic.reg266_perf_cnt0 = 0; __RETURN: AVS2D_HAL_TRACE("Out. ret %d", ret); @@ -859,6 +882,26 @@ MPP_RET hal_avs2d_rkv_start(void *hal, HalTaskInfo *task) break; } + rd_cfg.reg = ®s->avs2d_param; + rd_cfg.size = sizeof(regs->avs2d_param); + rd_cfg.offset = OFFSET_CODEC_PARAMS_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + rd_cfg.reg = ®s->statistic; + rd_cfg.size = sizeof(regs->statistic); + rd_cfg.offset = OFFSET_STATISTIC_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + if (avs2d_hal_debug & AVS2D_HAL_DBG_REG) { memset(reg_ctx->reg_out, 0, sizeof(reg_ctx->reg_out)); rd_cfg.reg = reg_ctx->reg_out; @@ -1042,6 +1085,15 @@ MPP_RET hal_avs2d_rkv_wait(void *hal, HalTaskInfo *task) else param.hard_err = 0; + task->dec.flags.ref_used = p_regs->statistic.reg266_perf_cnt0; + + if (task->dec.flags.ref_miss) { + RK_U32 ref_hw_usage = p_regs->statistic.reg266_perf_cnt0; + + AVS2D_HAL_TRACE("hal frame %d ref miss %x hard_err %d hw_usage %x", p_hal->frame_no, + task->dec.flags.ref_miss, param.hard_err, ref_hw_usage); + } + AVS2D_HAL_TRACE("hal frame %d hard_err= %d", p_hal->frame_no, param.hard_err); mpp_callback(p_hal->dec_cb, ¶m);