[avs2d]: Fix buffer leak issue

When decoding S picture, reference list with be force to set to only one
left. Slot flag should be cleared for the already marked buffers at
reference list. But decoded picture may not be correct if following AVS2
specification. So for S picture, keep those reference frames found by
doi_of_ref and replace the content of the first reference frame with
scene ref only.

Change-Id: I9f84fdd55acfc9cf9d65deb065ccf97c36de1321
Signed-off-by: Johnson Ding <johnson.ding@rock-chips.com>
This commit is contained in:
Johnson Ding
2022-12-09 14:41:26 +08:00
parent 477a35d4f0
commit a6917d23cb
5 changed files with 27 additions and 15 deletions

View File

@@ -323,9 +323,17 @@ static MPP_RET dpb_remove_frame(Avs2dCtx_t *p_dec, Avs2dFrame_t *p)
MppFrame frame = p->frame;
avs2d_dbg_dpb("In.");
if (p->picture_type == GB_PICTURE || p->invisible) {
MppBuffer buffer = NULL;
mpp_buf_slot_get_prop(p_dec->frame_slots, p->slot_idx, SLOT_BUFFER, &buffer);
mpp_buffer_put(buffer);
}
mpp_buf_slot_clr_flag(p_dec->frame_slots, p->slot_idx, SLOT_CODEC_USE);
avs2d_dbg_dpb("dpb remove frame slot_idx %d, doi %d poi %d, dpb used %d",
p->slot_idx, p->doi, p->poi, mgr->used_size);
memset(p, 0, sizeof(Avs2dFrame_t));
p->frame = frame;
p->slot_idx = NO_VAL;
@@ -467,7 +475,7 @@ static Avs2dFrame_t *dpb_alloc_frame(Avs2dCtx_t *p_dec, HalDecTask *task)
frm->intra_frame_flag = (frm->scene_frame_flag || frm->picture_type == I_PICTURE);
frm->refered_by_scene = frm->scene_frame_flag;
frm->refered_by_others = (frm->picture_type != GB_PICTURE && mgr->cur_rps.refered_by_others);
avs2d_dbg_dpb("frame picture type ref by others %d\n", frm->refered_by_others);
avs2d_dbg_dpb("frame picture type %d, ref by others %d\n", frm->picture_type, frm->refered_by_others);
if (vsh->chroma_format == CHROMA_420 && vsh->bit_depth == 8) {
mpp_frame_set_fmt(mframe, MPP_FMT_YUV420SP);
} else if (vsh->chroma_format == CHROMA_420 && vsh->bit_depth == 10) {
@@ -677,10 +685,10 @@ static MPP_RET dpb_set_frame_refs(Avs2dCtx_t *p_dec, Avs2dFrameMgr_t *mgr, HalDe
if (!mgr->scene_ref) {
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",
AVS2D_DBG(AVS2D_DBG_ERROR, "Error reference frame(doi %ld ~ %ld) for S.\n",
mgr->scene_ref->doi, mgr->refs[0] ? mgr->refs[0]->doi : -1);
mgr->num_of_ref = 1;
replace_ref_flag = 1;
p_dec->syntax.refp.scene_ref_replace_pos = 0;
}
} else if ((p_cur->picture_type == P_PICTURE || p_cur->picture_type == F_PICTURE) &&
p_dec->ph.background_reference_flag) {
@@ -689,6 +697,7 @@ static MPP_RET dpb_set_frame_refs(Avs2dCtx_t *p_dec, Avs2dFrameMgr_t *mgr, HalDe
error_flag = 1;
} else {
replace_ref_flag = 1;
p_dec->syntax.refp.scene_ref_replace_pos = mgr->num_of_ref - 1;
}
} else if (p_cur->picture_type == B_PICTURE &&
(mgr->num_of_ref != 2 || (mgr->refs[0] && mgr->refs[0]->poi <= p_cur->poi) ||
@@ -724,10 +733,8 @@ MPP_RET avs2d_dpb_insert(Avs2dCtx_t *p_dec, HalDecTask *task)
AVS2D_PARSE_TRACE("In.");
if (p_dec->ph.picture_type != GB_PICTURE) {
//!< output frame from dpb
dpb_scan_output_frame(p_dec);
}
//!< output frame from dpb
dpb_scan_output_frame(p_dec);
compute_frame_order_index(p_dec);

View File

@@ -591,6 +591,7 @@ static MPP_RET parse_picture_header_intra(Avs2dCtx_t *p_dec)
BitReadCtx_t *bitctx = &p_dec->bitctx;
Avs2dSeqHeader_t *vsh = &p_dec->vsh;
Avs2dPicHeader_t *ph = &p_dec->ph;
RK_U32 last_pic_out_delay = ph->picture_output_delay;
AVS2D_PARSE_TRACE("In.");
memset(ph, 0, sizeof(Avs2dPicHeader_t));
@@ -627,7 +628,7 @@ static MPP_RET parse_picture_header_intra(Avs2dCtx_t *p_dec)
AVS2D_PARSE_TRACE("temporal_id %d\n", ph->temporal_id);
}
if (vsh->low_delay == 0 && (!ph->background_picture_flag || ph->background_picture_output_flag)) {
if (vsh->low_delay == 0 && !(ph->background_picture_flag && !ph->background_picture_output_flag)) {
READ_UE(bitctx, &ph->picture_output_delay);
AVS2D_PARSE_TRACE("picture_output_delay %d\n", ph->picture_output_delay);
if (ph->picture_output_delay >= 64) {
@@ -636,7 +637,7 @@ static MPP_RET parse_picture_header_intra(Avs2dCtx_t *p_dec)
goto __FAILED;
}
} else {
ph->picture_output_delay = 0;
ph->picture_output_delay = last_pic_out_delay;
}
READ_ONEBIT(bitctx, &predict);
@@ -737,6 +738,7 @@ static MPP_RET parse_picture_header_inter(Avs2dCtx_t *p_dec)
if (vsh->low_delay == 0) {
READ_UE(bitctx, &ph->picture_output_delay);
AVS2D_PARSE_TRACE("picture_output_delay %d\n", ph->picture_output_delay);
if (ph->picture_output_delay >= 64) {
ret = MPP_NOK;
mpp_err_f("invalid picture output delay(%d) intra.\n", ph->picture_output_delay);

View File

@@ -57,6 +57,7 @@ typedef struct _DXVA_RefParams_AVS2 {
RK_S32 ref_poc_list[32];
RK_S32 scene_ref_slot_idx;
RK_S32 scene_ref_enable;
RK_S32 scene_ref_replace_pos;
} RefParams_Avs2d, *LP_RefParams_Avs2d;
typedef struct _DXVA_AlfParams_AVS2 {

View File

@@ -427,14 +427,15 @@ static MPP_RET fill_registers(Avs2dHalCtx_t *p_hal, Vdpu34xAvs2dRegSet *p_regs,
if (p_hal->syntax.refp.scene_ref_enable && p_hal->syntax.refp.scene_ref_slot_idx >= 0) {
MppFrame scene_ref = NULL;
RK_S32 slot_idx = p_hal->syntax.refp.scene_ref_slot_idx;
RK_S32 replace_idx = p_hal->syntax.refp.scene_ref_replace_pos;
mpp_buf_slot_get_prop(p_hal->frame_slots, slot_idx, SLOT_FRAME_PTR, &scene_ref);
if (scene_ref) {
p_regs->avs2d_addr.ref_base[refp->ref_pic_num - 1] = get_frame_fd(p_hal, slot_idx);
p_regs->avs2d_addr.ref_base[replace_idx] = 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[refp->ref_pic_num - 1] = mpp_buffer_get_fd(mv_buf->buf[0]);
p_regs->avs2d_param.reg67_098_ref_poc[refp->ref_pic_num - 1] = mpp_frame_get_poc(scene_ref);
p_regs->avs2d_addr.colmv_base[replace_idx] = mpp_buffer_get_fd(mv_buf->buf[0]);
p_regs->avs2d_param.reg67_098_ref_poc[replace_idx] = mpp_frame_get_poc(scene_ref);
}
}

View File

@@ -429,15 +429,16 @@ static MPP_RET fill_registers(Avs2dHalCtx_t *p_hal, Vdpu382Avs2dRegSet *p_regs,
if (p_hal->syntax.refp.scene_ref_enable && p_hal->syntax.refp.scene_ref_slot_idx >= 0) {
MppFrame scene_ref = NULL;
RK_S32 replace_idx = p_hal->syntax.refp.scene_ref_replace_pos;
RK_S32 slot_idx = p_hal->syntax.refp.scene_ref_slot_idx;
mpp_buf_slot_get_prop(p_hal->frame_slots, slot_idx, SLOT_FRAME_PTR, &scene_ref);
if (scene_ref) {
p_regs->avs2d_addr.ref_base[refp->ref_pic_num - 1] = get_frame_fd(p_hal, slot_idx);
p_regs->avs2d_addr.ref_base[replace_idx] = 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[refp->ref_pic_num - 1] = mpp_buffer_get_fd(mv_buf->buf[0]);
p_regs->avs2d_param.reg67_098_ref_poc[refp->ref_pic_num - 1] = mpp_frame_get_poc(scene_ref);
p_regs->avs2d_addr.colmv_base[replace_idx] = mpp_buffer_get_fd(mv_buf->buf[0]);
p_regs->avs2d_param.reg67_098_ref_poc[replace_idx] = mpp_frame_get_poc(scene_ref);
}
}