mirror of
https://github.com/nyanmisaka/mpp.git
synced 2025-10-04 16:52:40 +08:00
[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:
@@ -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" {
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user