[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 <herman.chen@rock-chips.com>
Change-Id: I7d0e87d19fc5b24808cda6b2b1bdaa1e60d091f6
This commit is contained in:
Herman Chen
2022-12-26 18:23:32 +08:00
committed by Yandong Lin
parent 4cbe378674
commit 1e2260727a
4 changed files with 192 additions and 76 deletions

View File

@@ -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" {

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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 = &regs->common;
HalBuf *mv_buf = NULL;
Vdpu382H264dRegCtx *ctx = (Vdpu382H264dRegCtx *)p_hal->reg_ctx;
// memset(regs, 0, sizeof(Vdpu382H264dRegSet));
memset(&regs->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(&regs->common, &regs->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 = &regs->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 = &reg_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, &param);
}
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;
}