[h264_dpb]: add fast play once

fast once can be controlled by cmake cmd:
-DENABLE_FASTPLAY_ONCE=ON

Change-Id: Id0073ef8356acec700030b98b417d4f6999bf894
Signed-off-by: Hongjin Li <vic.hong@rock-chips.com>
This commit is contained in:
Hongjin Li
2022-11-28 10:31:44 +08:00
committed by Herman Chen
parent 219b81cf8b
commit 520980b83b
6 changed files with 106 additions and 24 deletions

View File

@@ -265,7 +265,11 @@ void mpp_dec_cfg_set_default(MppDecCfgSet *cfg)
cfg->base.coding = MPP_VIDEO_CodingUnused;
cfg->base.hw_type = -1;
cfg->base.fast_parse = 1;
cfg->base.enable_fast_play = 1;
#ifdef ENABLE_FASTPLAY_ONCE
cfg->base.enable_fast_play = MPP_ENABLE_FAST_PLAY_ONCE;
#else
cfg->base.enable_fast_play = MPP_ENABLE_FAST_PLAY;
#endif
}
MPP_RET mpp_dec_cfg_init(MppDecCfg *cfg)

View File

@@ -344,6 +344,8 @@ MPP_RET h264d_init(void *decoder, ParserCfg *init)
FUN_CHECK(ret = init_vid_ctx(p_Dec->p_Vid));
FUN_CHECK(ret = init_dec_ctx(p_Dec));
p_Dec->immediate_out = p_Dec->cfg->base.fast_out;
p_Dec->p_Vid->dpb_fast_out = p_Dec->cfg->base.enable_fast_play;
p_Dec->p_Vid->dpb_first_fast_played = 0;
__RETURN:
return ret = MPP_OK;
__FAILED:
@@ -439,6 +441,8 @@ MPP_RET h264d_reset(void *decoder)
p_Dec->dxva_ctx->strm_offset = 0;
p_Dec->dxva_ctx->slice_count = 0;
p_Dec->last_frame_slot_idx = -1;
p_Dec->p_Vid->dpb_fast_out = p_Dec->cfg->base.enable_fast_play;
p_Dec->p_Vid->dpb_first_fast_played = 0;
__RETURN:
return ret = MPP_OK;
@@ -480,9 +484,16 @@ __FAILED:
*/
MPP_RET h264d_control(void *decoder, MpiCmd cmd_type, void *param)
{
(void) decoder;
(void) cmd_type;
(void) param;
H264_DecCtx_t *p_Dec = (H264_DecCtx_t *)decoder;
switch (cmd_type) {
case MPP_DEC_SET_ENABLE_FAST_PLAY:
p_Dec->p_Vid->dpb_fast_out = (param) ? (*((RK_U32 *)param)) : (1);
break;
default:
break;
}
return MPP_OK;
}

View File

@@ -867,7 +867,7 @@ static void write_picture(H264_StorePic_t *p, H264dVideoCtx_t *p_Vid)
if (p_err->used_ref_flag && p_err->first_iframe_is_output) {
mpp_frame_set_errinfo(mframe, MPP_FRAME_ERR_UNKNOW);
} else {
if (p_Vid->p_Dec->cfg->base.enable_fast_play)
if (p_Vid->dpb_fast_out)
mpp_frame_set_discard(mframe, MPP_FRAME_ERR_UNKNOW);
}
}
@@ -1302,6 +1302,63 @@ __FAILED:
return ret;
}
static MPP_RET output_dpb_normal(H264_DpbBuf_t *p_Dpb)
{
MPP_RET ret = MPP_NOK;
RK_S32 min_poc = 0;
RK_S32 min_pos = 0;
RK_S32 poc_inc = 0;
while ((p_Dpb->last_output_poc > INT_MIN)
&& (get_smallest_poc(p_Dpb, &min_poc, &min_pos))) {
poc_inc = min_poc - p_Dpb->last_output_poc;
if ((p_Dpb->last_output_poc > INT_MIN) && (abs(poc_inc) & 0x1))
p_Dpb->poc_interval = 1;
if ((min_poc - p_Dpb->last_output_poc) <= p_Dpb->poc_interval) {
FUN_CHECK(ret = write_stored_frame(p_Dpb->p_Vid, p_Dpb, p_Dpb->fs[min_pos]));
} else {
break;
}
}
while (!remove_unused_frame_from_dpb(p_Dpb));
return MPP_OK;
__FAILED:
return ret;
}
static MPP_RET output_dpb_fastplay(H264_DpbBuf_t *p_Dpb, H264_FrameStore_t *fs, RK_U32 is_i_frm)
{
MPP_RET ret = MPP_NOK;
if ((p_Dpb->p_Vid->dpb_fast_out && is_i_frm)) {
FUN_CHECK(ret = write_stored_frame(p_Dpb->p_Vid, p_Dpb, fs));
} else
output_dpb_normal(p_Dpb);
return MPP_OK;
__FAILED:
return ret;
}
static MPP_RET output_dpb_fastplay_once(H264_DpbBuf_t *p_Dpb, H264_FrameStore_t *fs, RK_U32 is_i_frm)
{
MPP_RET ret = MPP_NOK;
if (p_Dpb->p_Vid->dpb_fast_out && is_i_frm && !p_Dpb->p_Vid->dpb_first_fast_played) {
FUN_CHECK(ret = write_stored_frame(p_Dpb->p_Vid, p_Dpb, fs));
p_Dpb->p_Vid->dpb_first_fast_played = 1;
} else {
// disable fast play once in the second gop
if (p_Dpb->p_Vid->dpb_fast_out && is_i_frm && p_Dpb->p_Vid->dpb_first_fast_played) {
p_Dpb->p_Vid->dpb_fast_out = MPP_DISABLE_FAST_PLAY;
}
output_dpb_normal(p_Dpb);
}
return MPP_OK;
__FAILED:
return ret;
}
static MPP_RET scan_dpb_output(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p)
{
MPP_RET ret = MPP_NOK;
@@ -1309,28 +1366,24 @@ static MPP_RET scan_dpb_output(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p)
if (fs->is_used == 3) {
H264dErrCtx_t *p_err = &p_Dpb->p_Vid->p_Dec->errctx;
RK_S32 min_poc = 0;
RK_S32 min_pos = 0;
RK_S32 poc_inc = 0;
RK_U32 is_i_frm = p_err->i_slice_no < 2 && p_Dpb->last_output_poc == INT_MIN;
if (p_Dpb->p_Vid->p_Dec->cfg->base.fast_out ||
(p_Dpb->p_Vid->p_Dec->cfg->base.enable_fast_play &&
p_err->i_slice_no < 2 && p_Dpb->last_output_poc == INT_MIN)) {
if (p_Dpb->p_Vid->p_Dec->cfg->base.fast_out)
FUN_CHECK(ret = write_stored_frame(p_Dpb->p_Vid, p_Dpb, fs));
} else {
while ((p_Dpb->last_output_poc > INT_MIN)
&& (get_smallest_poc(p_Dpb, &min_poc, &min_pos))) {
poc_inc = min_poc - p_Dpb->last_output_poc;
if ((p_Dpb->last_output_poc > INT_MIN) && (abs(poc_inc) & 0x1))
p_Dpb->poc_interval = 1;
if ((min_poc - p_Dpb->last_output_poc) <= p_Dpb->poc_interval) {
H264D_WARNNING("write_stored_frame, line %d", __LINE__);
FUN_CHECK(ret = write_stored_frame(p_Dpb->p_Vid, p_Dpb, p_Dpb->fs[min_pos]));
} else {
break;
}
else {
switch (p_Dpb->p_Vid->p_Dec->cfg->base.enable_fast_play) {
case MPP_DISABLE_FAST_PLAY:
FUN_CHECK(ret = output_dpb_normal(p_Dpb));
break;
case MPP_ENABLE_FAST_PLAY:
FUN_CHECK(ret = output_dpb_fastplay(p_Dpb, fs, is_i_frm));
break;
case MPP_ENABLE_FAST_PLAY_ONCE:
FUN_CHECK(ret = output_dpb_fastplay_once(p_Dpb, fs, is_i_frm));
break;
default:
H264D_ERR("unsupport output mode");
}
while (!remove_unused_frame_from_dpb(p_Dpb));
}
if (is_i_frm)

View File

@@ -1045,6 +1045,9 @@ typedef struct h264d_video_ctx_t {
MppMemPool pic_st;
//!< spspps data update
RK_U32 spspps_update;
RK_U32 dpb_fast_out;
RK_U32 dpb_first_fast_played;
} H264dVideoCtx_t;
typedef struct h264d_mem_t {

View File

@@ -37,6 +37,10 @@ if( ENABLE_H264D )
set(HAL_H264D hal_h264d)
add_definitions(-DHAVE_H264D)
endif()
option(ENABLE_FASTPLAY_ONCE "Enable h.264 decoder fast play once" OFF)
if( ENABLE_FASTPLAY_ONCE )
add_definitions(-DENABLE_FASTPLAY_ONCE)
endif()
# H.265 decoder
option(ENABLE_H265D "Enable h.265 decoder" ON)

View File

@@ -50,6 +50,13 @@ typedef enum MppVprocMode_e {
MPP_VPROC_MODE_ALL = (0xFFFFFFFF),
} MppVprocMode;
typedef enum FastPlayMode_e {
MPP_DISABLE_FAST_PLAY,
MPP_ENABLE_FAST_PLAY,
// first gop fast play when poc include negative value, otherwise enable fast play all time
MPP_ENABLE_FAST_PLAY_ONCE,
} FastPlayMode;
typedef struct MppDecBaseCfg_t {
RK_U64 change;