From 520980b83bf7f29c83f9be1da9aebdc42c35400a Mon Sep 17 00:00:00 2001 From: Hongjin Li Date: Mon, 28 Nov 2022 10:31:44 +0800 Subject: [PATCH] [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 --- mpp/base/mpp_dec_cfg.cpp | 6 +- mpp/codec/dec/h264/h264d_api.c | 17 +++++- mpp/codec/dec/h264/h264d_dpb.c | 93 ++++++++++++++++++++++++------- mpp/codec/dec/h264/h264d_global.h | 3 + mpp/codecs.cmake | 4 ++ mpp/inc/mpp_dec_cfg.h | 7 +++ 6 files changed, 106 insertions(+), 24 deletions(-) diff --git a/mpp/base/mpp_dec_cfg.cpp b/mpp/base/mpp_dec_cfg.cpp index ae49a58a..71d148d9 100644 --- a/mpp/base/mpp_dec_cfg.cpp +++ b/mpp/base/mpp_dec_cfg.cpp @@ -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) diff --git a/mpp/codec/dec/h264/h264d_api.c b/mpp/codec/dec/h264/h264d_api.c index 9b4f7543..27426d34 100644 --- a/mpp/codec/dec/h264/h264d_api.c +++ b/mpp/codec/dec/h264/h264d_api.c @@ -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; } diff --git a/mpp/codec/dec/h264/h264d_dpb.c b/mpp/codec/dec/h264/h264d_dpb.c index 0049a007..44a95f8b 100644 --- a/mpp/codec/dec/h264/h264d_dpb.c +++ b/mpp/codec/dec/h264/h264d_dpb.c @@ -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) diff --git a/mpp/codec/dec/h264/h264d_global.h b/mpp/codec/dec/h264/h264d_global.h index 4ad8981b..54090579 100644 --- a/mpp/codec/dec/h264/h264d_global.h +++ b/mpp/codec/dec/h264/h264d_global.h @@ -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 { diff --git a/mpp/codecs.cmake b/mpp/codecs.cmake index 66a8e84b..7927520f 100644 --- a/mpp/codecs.cmake +++ b/mpp/codecs.cmake @@ -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) diff --git a/mpp/inc/mpp_dec_cfg.h b/mpp/inc/mpp_dec_cfg.h index 9ff524f0..bb54aec4 100644 --- a/mpp/inc/mpp_dec_cfg.h +++ b/mpp/inc/mpp_dec_cfg.h @@ -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;