From 1e2260727ac7b741aa706d4a40d97a62654dafce Mon Sep 17 00:00:00 2001 From: Herman Chen Date: Mon, 26 Dec 2022 18:23:32 +0800 Subject: [PATCH] [h264d]: Add ref miss check 1. Define more decoder frame error level. 2. Setup errInfo according to error type and level Signed-off-by: Herman Chen Change-Id: I7d0e87d19fc5b24808cda6b2b1bdaa1e60d091f6 --- inc/mpp_frame.h | 23 +++- mpp/codec/dec/h264/h264d_api.c | 85 ++++++++++--- mpp/hal/inc/hal_dec_task.h | 7 +- mpp/hal/rkdec/h264d/hal_h264d_vdpu382.c | 153 +++++++++++++++--------- 4 files changed, 192 insertions(+), 76 deletions(-) diff --git a/inc/mpp_frame.h b/inc/mpp_frame.h index 450c515f..b94421c7 100644 --- a/inc/mpp_frame.h +++ b/inc/mpp_frame.h @@ -277,10 +277,29 @@ typedef struct MppFrameHdrDynamicMeta { RK_U8 data[]; } MppFrameHdrDynamicMeta; -typedef enum { +typedef enum MppFrameError { + /* General error not specified */ MPP_FRAME_ERR_UNKNOW = 0x0001, + + /* Critical error for decoder not support error */ MPP_FRAME_ERR_UNSUPPORT = 0x0002, -} MPP_FRAME_ERR; + + /* + * Fatal error for decoder can not parse a valid frame for hardware. + * the pixel data is all invalid. + */ + MPP_FRAME_ERR_DEC_INVALID = 0x0010, + + /* + * Normal error for decoder found hardware error on decoding. + */ + MPP_FRAME_ERR_DEC_HW_ERR = 0x0100, + + /* + * Normal error for decoder found missing reference frame on decoding. + */ + MPP_FRAME_ERR_DEC_MISS_REF = 0x0200, +} MppFrameError; #ifdef __cplusplus extern "C" { diff --git a/mpp/codec/dec/h264/h264d_api.c b/mpp/codec/dec/h264/h264d_api.c index 4d171bd6..36b3b1d7 100644 --- a/mpp/codec/dec/h264/h264d_api.c +++ b/mpp/codec/dec/h264/h264d_api.c @@ -22,6 +22,7 @@ #include "mpp_env.h" #include "mpp_platform.h" #include "mpp_packet_impl.h" +#include "mpp_frame_impl.h" #include "h264d_api.h" #include "h264d_global.h" @@ -653,32 +654,82 @@ MPP_RET h264d_callback(void *decoder, void *errinfo) MPP_RET ret = MPP_ERR_UNKNOW; H264_DecCtx_t *p_Dec = (H264_DecCtx_t *)decoder; DecCbHalDone *ctx = (DecCbHalDone *)errinfo; + HalDecTask *task_dec = (HalDecTask *)ctx->task; + RK_U32 task_err = task_dec->flags.parse_err || task_dec->flags.ref_err; + RK_U32 ref_used = task_dec->flags.ref_info_valid ? task_dec->flags.ref_used : 0; + RK_U32 hw_ref_miss = task_dec->flags.ref_info_valid ? task_dec->flags.ref_miss : 0; + RK_U32 hw_dec_err = ctx->hard_err; + RK_S32 output = task_dec->output; + RK_U32 err_mark = 0; + MppFrame frame = NULL; INP_CHECK(ret, !decoder); - { - MppFrame mframe = NULL; - HalDecTask *task_dec = (HalDecTask *)ctx->task; + if (output >= 0) + mpp_buf_slot_get_prop(p_Dec->frame_slots, output, SLOT_FRAME_PTR, &frame); - if (task_dec->output >= 0) - mpp_buf_slot_get_prop(p_Dec->frame_slots, task_dec->output, SLOT_FRAME_PTR, &mframe); + if (!frame) + goto __RETURN; - if (mframe) { - RK_U32 task_err = task_dec->flags.parse_err || task_dec->flags.ref_err; - if (ctx->hard_err || task_err) { - if (task_dec->flags.used_for_ref) { - mpp_frame_set_errinfo(mframe, MPP_FRAME_ERR_UNKNOW); - } else { - mpp_frame_set_discard(mframe, MPP_FRAME_ERR_UNKNOW); - } + /* check and mark current frame */ + if (task_err) { + err_mark |= MPP_FRAME_ERR_DEC_INVALID; + goto DONE; + } + + if (hw_dec_err) { + err_mark |= MPP_FRAME_ERR_DEC_HW_ERR; + goto DONE; + } + + if (ref_used) { + RK_S32 *refer = task_dec->refer; + RK_U32 i; + + for (i = 0; i < 16; i++) { + RK_U32 mask = 1 << i; + RK_U32 error = 0; + MppFrameImpl *tmp = NULL; + + /* not used frame or non-refer frame skip */ + if (!(ref_used & mask) || (refer[i] < 0)) + continue; + + /* check and mark error for error reference frame */ + mpp_buf_slot_get_prop(p_Dec->frame_slots, refer[i], + SLOT_FRAME_PTR, &tmp); + + error = tmp->errinfo; + H264D_DBG(H264D_DBG_DPB_REF_ERR, + "cur_poc %d frm slot %d refer %d slot %d poc %d errinfo %x\n", + mpp_frame_get_poc(frame), output, i, refer[i], tmp->poc, error); + + if (error) { + mpp_log_f("cur_poc %d mark error ref slot %d:%d poc %d err %x\n", + mpp_frame_get_poc(frame), i, refer[i], tmp->poc, error); + err_mark |= MPP_FRAME_ERR_UNKNOW; + break; } - H264D_DBG(H264D_DBG_CALLBACK, "[CALLBACK] g_no=%d, out_idx=%d, dpberr=%d, harderr=%d, ref_flag=%d, errinfo=%d, discard=%d, poc=%d, view_id=%d\n", - p_Dec->p_Vid->g_framecnt, task_dec->output, task_err, ctx->hard_err, task_dec->flags.used_for_ref, - mpp_frame_get_errinfo(mframe), mpp_frame_get_discard(mframe), - mpp_frame_get_poc(mframe), mpp_frame_get_viewid(mframe)); } } +DONE: + if (err_mark) { + if (task_dec->flags.used_for_ref) { + mpp_frame_set_errinfo(frame, err_mark); + } else { + mpp_frame_set_discard(frame, err_mark); + } + } + + H264D_DBG(H264D_DBG_CALLBACK, + "[CALLBACK] g_no %d, out_idx %d, dpberr %d, harderr %d, ref_flag %d, " + "errinfo %x, discard %x poc %d view_id %d\n", + p_Dec->p_Vid->g_framecnt, output, task_err, ctx->hard_err, + task_dec->flags.used_for_ref, mpp_frame_get_errinfo(frame), + mpp_frame_get_discard(frame), mpp_frame_get_poc(frame), + mpp_frame_get_viewid(frame)); + __RETURN: return ret = MPP_OK; } diff --git a/mpp/hal/inc/hal_dec_task.h b/mpp/hal/inc/hal_dec_task.h index cac2ea58..ca55d886 100644 --- a/mpp/hal/inc/hal_dec_task.h +++ b/mpp/hal/inc/hal_dec_task.h @@ -63,9 +63,10 @@ typedef union HalDecTaskFlag_t { RK_U32 used_for_ref : 1; RK_U32 wait_done : 1; - RK_U32 reserved0 : 2; - RK_U32 ref_miss : 8; - RK_U32 ref_used : 8; + RK_U32 reserved0 : 1; + RK_U32 ref_info_valid : 1; + RK_U32 ref_miss : 16; + RK_U32 ref_used : 16; }; } HalDecTaskFlag; diff --git a/mpp/hal/rkdec/h264d/hal_h264d_vdpu382.c b/mpp/hal/rkdec/h264d/hal_h264d_vdpu382.c index 9e000702..522da06d 100644 --- a/mpp/hal/rkdec/h264d/hal_h264d_vdpu382.c +++ b/mpp/hal/rkdec/h264d/hal_h264d_vdpu382.c @@ -27,6 +27,7 @@ #include "mpp_bitput.h" #include "mpp_device.h" +#include "mpp_frame_impl.h" #include "hal_h264d_global.h" #include "hal_h264d_vdpu382.h" @@ -127,7 +128,8 @@ typedef struct h264d_rkv_buf_t { RK_U32 valid; Vdpu382H264dRegSet *regs; - RK_S32 ref_slot_index[16]; + DXVA_PicEntry_H264 RefFrameList[16]; + DXVA_PicEntry_H264 RefPicList[3][32]; } H264dRkvBuf_t; typedef struct Vdpu382H264dRegCtx_t { @@ -534,7 +536,6 @@ static MPP_RET set_registers(H264dHalCtx_t *p_hal, Vdpu382H264dRegSet *regs, Hal DXVA_PicParams_H264_MVC *pp = p_hal->pp; Vdpu382RegCommon *common = ®s->common; HalBuf *mv_buf = NULL; - Vdpu382H264dRegCtx *ctx = (Vdpu382H264dRegCtx *)p_hal->reg_ctx; // memset(regs, 0, sizeof(Vdpu382H264dRegSet)); memset(®s->h264d_highpoc, 0, sizeof(regs->h264d_highpoc)); @@ -542,6 +543,8 @@ static MPP_RET set_registers(H264dHalCtx_t *p_hal, Vdpu382H264dRegSet *regs, Hal common->reg013.cur_pic_is_idr = p_hal->slice_long->idr_flag; common->reg012.colmv_compress_en = (p_hal->hw_info && p_hal->hw_info->cap_colmv_compress && pp->frame_mbs_only_flag) ? 1 : 0; + common->reg012.info_collect_en = 1; + //!< caculate the yuv_frame_size { MppFrame mframe = NULL; @@ -597,7 +600,8 @@ static MPP_RET set_registers(H264dHalCtx_t *p_hal, Vdpu382H264dRegSet *regs, Hal MppBuffer mbuffer = NULL; RK_U32 min_frame_num = 0; MppFrame mframe = NULL; - RK_S32 *ref_slot_index = ctx->reg_buf[task->dec.reg_index].ref_slot_index; + + task->dec.flags.ref_miss = 0; for (i = 0; i < 15; i++) { RK_U32 field_flag = (pp->RefPicFiledFlags >> i) & 0x01; @@ -614,10 +618,9 @@ static MPP_RET set_registers(H264dHalCtx_t *p_hal, Vdpu382H264dRegSet *regs, Hal if (pp->RefFrameList[i].bPicEntry != 0xff) { ref_index = pp->RefFrameList[i].Index7Bits; near_index = pp->RefFrameList[i].Index7Bits; - if (!common->reg013.cur_pic_is_idr) - ref_slot_index[i] = ref_index; } else { ref_index = (near_index < 0) ? pp->CurrPic.Index7Bits : near_index; + task->dec.flags.ref_miss |= (1 << i); } /* mark 3 to differ from current frame */ if (ref_index == pp->CurrPic.Index7Bits) { @@ -926,37 +929,6 @@ static void hal_h264d_rcb_info_update(void *hal, Vdpu382H264dRegSet *regs) } } -void vdpu382_h264d_check_refinfo(void *hal, HalTaskInfo *task) -{ - H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; - Vdpu382H264dRegCtx *reg_ctx; - - if (!p_hal) - return; - - reg_ctx = (Vdpu382H264dRegCtx *)p_hal->reg_ctx; - if (p_hal->fast_mode) { - RK_S32 *ref_slot_index = reg_ctx->reg_buf[task->dec.reg_index].ref_slot_index; - RK_U32 i; - MppFrame cur_frame = NULL; - MppFrame frame = NULL; - - mpp_buf_slot_get_prop(p_hal->frame_slots, task->dec.output, - SLOT_FRAME_PTR, &cur_frame); - for (i = 0; i < 15; i++) { - if (ref_slot_index[i] >= 0) { - mpp_buf_slot_get_prop(p_hal->frame_slots, ref_slot_index[i], - SLOT_FRAME_PTR, &frame); - if (frame && mpp_frame_get_errinfo(frame)) { - mpp_frame_set_errinfo(cur_frame, 1); - break; - } - } - } - memset(ref_slot_index, -1, 16 * sizeof(RK_S32)); - } -} - static MPP_RET vdpu382_h264d_setup_colmv_buf(void *hal) { MPP_RET ret = MPP_ERR_UNKNOW; @@ -1002,6 +974,7 @@ MPP_RET vdpu382_h264d_gen_regs(void *hal, HalTaskInfo *task) goto __RETURN; } + task->dec.reg_index = 0; if (p_hal->fast_mode) { RK_U32 i = 0; for (i = 0; i < MPP_ARRAY_ELEMS(ctx->reg_buf); i++) { @@ -1084,6 +1057,15 @@ MPP_RET vdpu382_h264d_gen_regs(void *hal, HalTaskInfo *task) regs->common.reg012.scale_down_en = 0; } } + /* back up ref infos */ + { + DXVA_PicParams_H264_MVC *pp = p_hal->pp; + RK_S32 index = task->dec.reg_index; + + memcpy(ctx->reg_buf[index].RefFrameList, pp->RefFrameList, sizeof(pp->RefFrameList)); + memcpy(ctx->reg_buf[index].RefPicList, p_hal->slice_long->RefPicList, + sizeof(p_hal->slice_long->RefPicList)); + } vdpu382_setup_statistic(®s->common, ®s->statistic); __RETURN: @@ -1179,6 +1161,17 @@ MPP_RET vdpu382_h264d_start(void *hal, HalTaskInfo *task) 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 read failed %d\n", ret); + break; + } + /* rcb info for sram */ vdpu382_set_rcbinfo(dev, reg_ctx->rcb_info); /* send request to hardware */ @@ -1193,15 +1186,69 @@ __RETURN: return ret = MPP_OK; } +RK_U32 vdpu382_h264_get_ref_used(void *hal, HalTaskInfo *task) +{ + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + Vdpu382H264dRegCtx *reg_ctx = (Vdpu382H264dRegCtx *)p_hal->reg_ctx; + Vdpu382H264dRegSet *p_regs = p_hal->fast_mode ? + reg_ctx->reg_buf[task->dec.reg_index].regs : + reg_ctx->regs; + RK_U32 hw_ref_used; + RK_U32 ref_used = 0;; + + memcpy(&hw_ref_used, &p_regs->statistic.reg265, sizeof(RK_U32)); + + { + H264dRkvBuf_t *cur_buf = ®_ctx->reg_buf[task->dec.reg_index]; + RK_U32 i, j; + MppFrame cur_frame = NULL; + MppFrameStatus *status; + + mpp_buf_slot_get_prop(p_hal->frame_slots, task->dec.output, + SLOT_FRAME_PTR, &cur_frame); + status = mpp_frame_get_status(cur_frame); + + if (status->is_intra) + return ref_used; + + for (i = 0; i < 32; i++) { + RK_U32 mask = 1 << i; + RK_U32 dpb_idx; + + if (!(hw_ref_used & mask)) + continue; + + if (status->is_b_frame) { + for (j = 1; j < 3; j++) { + dpb_idx = cur_buf->RefPicList[j][i].Index7Bits; + if (cur_buf->RefPicList[j][i].bPicEntry != 0xff && dpb_idx < 16) + ref_used |= (1 << dpb_idx); + } + } else { + j = 1; + dpb_idx = cur_buf->RefPicList[j][i].Index7Bits; + if (cur_buf->RefPicList[j][i].bPicEntry != 0xff && dpb_idx < 16) + ref_used |= (1 << dpb_idx); + } + } + } + H264D_LOG("hw_ref_used 0x%08x ref_used %08x\n", hw_ref_used, ref_used); + + return ref_used; +} + MPP_RET vdpu382_h264d_wait(void *hal, HalTaskInfo *task) { MPP_RET ret = MPP_ERR_UNKNOW; + RK_S32 index = task->dec.reg_index; H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + RK_U32 hw_err = 0; + RK_U32 ref_used = 0; INP_CHECK(ret, NULL == p_hal); Vdpu382H264dRegCtx *reg_ctx = (Vdpu382H264dRegCtx *)p_hal->reg_ctx; Vdpu382H264dRegSet *p_regs = p_hal->fast_mode ? - reg_ctx->reg_buf[task->dec.reg_index].regs : + reg_ctx->reg_buf[index].regs : reg_ctx->regs; if (task->dec.flags.parse_err || @@ -1213,31 +1260,30 @@ MPP_RET vdpu382_h264d_wait(void *hal, HalTaskInfo *task) if (ret) mpp_err_f("poll cmd failed %d\n", ret); + hw_err = p_regs->irq_status.reg224.dec_error_sta || + (!p_regs->irq_status.reg224.dec_rdy_sta) || + p_regs->irq_status.reg224.buf_empty_sta || + p_regs->irq_status.reg226.strmd_error_status || + p_regs->irq_status.reg227.colmv_error_ref_picidx || + p_regs->irq_status.reg226.strmd_detect_error_flag; + + ref_used = vdpu382_h264_get_ref_used(hal, task); + task->dec.flags.ref_info_valid = 1; + task->dec.flags.ref_used = ref_used; + __SKIP_HARD: if (p_hal->dec_cb) { DecCbHalDone param; param.task = (void *)&task->dec; param.regs = (RK_U32 *)p_regs; - - if (p_regs->irq_status.reg224.dec_error_sta || - (!p_regs->irq_status.reg224.dec_rdy_sta) || - p_regs->irq_status.reg224.buf_empty_sta || - p_regs->irq_status.reg226.strmd_error_status || - p_regs->irq_status.reg227.colmv_error_ref_picidx || - p_regs->irq_status.reg226.strmd_detect_error_flag) - param.hard_err = 1; - else { - param.hard_err = 0; - vdpu382_h264d_check_refinfo(hal, task); - } + param.hard_err = hw_err; mpp_callback(p_hal->dec_cb, ¶m); } - memset(&p_regs->irq_status.reg224, 0, sizeof(RK_U32)); - if (p_hal->fast_mode) { - reg_ctx->reg_buf[task->dec.reg_index].valid = 0; - } + + if (p_hal->fast_mode) + reg_ctx->reg_buf[index].valid = 0; (void)task; __RETURN: @@ -1251,7 +1297,6 @@ MPP_RET vdpu382_h264d_reset(void *hal) INP_CHECK(ret, NULL == p_hal); - __RETURN: return ret = MPP_OK; }