[h264d_dpb]: Fix h264 video flicker issue

When the poc of the idr frame is 0, the subsequent frames with poc<0 are
discarded, which will cause the screen to flicker.
Add parameters in mpp as switches for immediate output of idr frames.

Change-Id: I522334dd1e81fc6aeeb60e71404f3a7071a5ecae
Signed-off-by: Hongjin Li <vic.hong@rock-chips.com>
This commit is contained in:
Hongjin Li
2022-02-23 15:56:24 +08:00
committed by Herman Chen
parent 22caf3f1f8
commit 98ac9b259b
6 changed files with 27 additions and 10 deletions

View File

@@ -100,6 +100,7 @@ typedef enum {
MPP_DEC_SET_DISABLE_ERROR, /* When set it will disable sw/hw error (H.264 / H.265) */ MPP_DEC_SET_DISABLE_ERROR, /* When set it will disable sw/hw error (H.264 / H.265) */
MPP_DEC_SET_IMMEDIATE_OUT, MPP_DEC_SET_IMMEDIATE_OUT,
MPP_DEC_SET_ENABLE_DEINTERLACE, /* MPP enable deinterlace by default. Vpuapi can disable it */ MPP_DEC_SET_ENABLE_DEINTERLACE, /* MPP enable deinterlace by default. Vpuapi can disable it */
MPP_DEC_SET_DISABLE_FAST_PLAY, /* disable idr output immediately */
MPP_DEC_CMD_QUERY = CMD_MODULE_CODEC | CMD_CTX_ID_DEC | CMD_DEC_QUERY, MPP_DEC_CMD_QUERY = CMD_MODULE_CODEC | CMD_CTX_ID_DEC | CMD_DEC_QUERY,
/* query decoder runtime information for decode stage */ /* query decoder runtime information for decode stage */

View File

@@ -162,6 +162,7 @@ static const char *dec_cfg_func_names[] = {
ENTRY(base, sort_pts, U32, RK_U32, MPP_DEC_CFG_CHANGE_SORT_PTS, base, sort_pts) \ ENTRY(base, sort_pts, U32, RK_U32, MPP_DEC_CFG_CHANGE_SORT_PTS, base, sort_pts) \
ENTRY(base, disable_error, U32, RK_U32, MPP_DEC_CFG_CHANGE_DISABLE_ERROR, base, disable_error) \ ENTRY(base, disable_error, U32, RK_U32, MPP_DEC_CFG_CHANGE_DISABLE_ERROR, base, disable_error) \
ENTRY(base, enable_vproc, U32, RK_U32, MPP_DEC_CFG_CHANGE_ENABLE_VPROC, base, enable_vproc) \ ENTRY(base, enable_vproc, U32, RK_U32, MPP_DEC_CFG_CHANGE_ENABLE_VPROC, base, enable_vproc) \
ENTRY(base, disable_fast_play, U32, RK_U32, MPP_DEC_CFG_CHANGE_DISABLE_FAST_PLAY, base, disable_fast_play) \
ENTRY(cb, pkt_rdy_cb, PTR, MppExtCbFunc, MPP_DEC_CB_CFG_CHANGE_PKT_RDY, cb, pkt_rdy_cb) \ ENTRY(cb, pkt_rdy_cb, PTR, MppExtCbFunc, MPP_DEC_CB_CFG_CHANGE_PKT_RDY, cb, pkt_rdy_cb) \
ENTRY(cb, pkt_rdy_ctx, PTR, MppExtCbCtx, MPP_DEC_CB_CFG_CHANGE_PKT_RDY, cb, pkt_rdy_ctx) \ ENTRY(cb, pkt_rdy_ctx, PTR, MppExtCbCtx, MPP_DEC_CB_CFG_CHANGE_PKT_RDY, cb, pkt_rdy_ctx) \
ENTRY(cb, pkt_rdy_cmd, S32, RK_S32, MPP_DEC_CB_CFG_CHANGE_PKT_RDY, cb, pkt_rdy_cmd) \ ENTRY(cb, pkt_rdy_cmd, S32, RK_S32, MPP_DEC_CB_CFG_CHANGE_PKT_RDY, cb, pkt_rdy_cmd) \

View File

@@ -873,7 +873,8 @@ static void write_picture(H264_StorePic_t *p, H264dVideoCtx_t *p_Vid)
} }
} }
//!< discard less than first i frame poc //!< discard less than first i frame poc
if ((p_err->i_slice_no < 2) && (p->poc < p_err->first_iframe_poc)) { if ((p_err->i_slice_no < 2) && (p->poc < p_err->first_iframe_poc) &&
(!p_Vid->p_Dec->cfg->base.disable_fast_play)) {
if (p_err->used_ref_flag) { if (p_err->used_ref_flag) {
mpp_frame_set_errinfo(mframe, MPP_FRAME_ERR_UNKNOW); mpp_frame_set_errinfo(mframe, MPP_FRAME_ERR_UNKNOW);
} else { } else {
@@ -1254,20 +1255,22 @@ static MPP_RET scan_dpb_output(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p)
H264_FrameStore_t *fs = p_Dpb->fs[p_Dpb->used_size - 1]; H264_FrameStore_t *fs = p_Dpb->fs[p_Dpb->used_size - 1];
if (fs->is_used == 3) { if (fs->is_used == 3) {
RK_S32 min_poc = 0, min_pos = 0;
RK_S32 poc_inc = fs->poc - p_Dpb->last_output_poc;
H264dErrCtx_t *p_err = &p_Dpb->p_Vid->p_Dec->errctx; H264dErrCtx_t *p_err = &p_Dpb->p_Vid->p_Dec->errctx;
RK_S32 min_poc = 0;
if ((p_Dpb->last_output_poc > INT_MIN) && abs(poc_inc) & 0x1) { RK_S32 min_pos = 0;
p_Dpb->poc_interval = 1; RK_S32 poc_inc = 0;
}
if (p_Dpb->p_Vid->p_Dec->cfg->base.fast_out || if (p_Dpb->p_Vid->p_Dec->cfg->base.fast_out ||
(p_err->i_slice_no < 2 && p_Dpb->last_output_poc == INT_MIN)) { (!p_Dpb->p_Vid->p_Dec->cfg->base.disable_fast_play &&
p_err->i_slice_no < 2 && p_Dpb->last_output_poc == INT_MIN)) {
FUN_CHECK(ret = write_stored_frame(p_Dpb->p_Vid, p_Dpb, fs)); FUN_CHECK(ret = write_stored_frame(p_Dpb->p_Vid, p_Dpb, fs));
} else { } else {
while ((p_Dpb->last_output_poc > INT_MIN) while ((p_Dpb->last_output_poc > INT_MIN)
&& (get_smallest_poc(p_Dpb, &min_poc, &min_pos))) { && (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) { 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])); FUN_CHECK(ret = write_stored_frame(p_Dpb->p_Vid, p_Dpb, p_Dpb->fs[min_pos]));
} else { } else {

View File

@@ -438,7 +438,8 @@ MPP_RET mpp_dec_proc_cfg(MppDecImpl *dec, MpiCmd cmd, void *param)
case MPP_DEC_SET_IMMEDIATE_OUT : case MPP_DEC_SET_IMMEDIATE_OUT :
case MPP_DEC_SET_OUTPUT_FORMAT : case MPP_DEC_SET_OUTPUT_FORMAT :
case MPP_DEC_SET_DISABLE_ERROR : case MPP_DEC_SET_DISABLE_ERROR :
case MPP_DEC_SET_ENABLE_DEINTERLACE : { case MPP_DEC_SET_ENABLE_DEINTERLACE :
case MPP_DEC_SET_DISABLE_FAST_PLAY : {
ret = mpp_dec_set_cfg_by_cmd(&dec->cfg, cmd, param); ret = mpp_dec_set_cfg_by_cmd(&dec->cfg, cmd, param);
dec->cfg.base.change = 0; dec->cfg.base.change = 0;
} break; } break;
@@ -1614,6 +1615,9 @@ MPP_RET mpp_dec_set_cfg(MppDecCfgSet *dst, MppDecCfgSet *src)
if (change & MPP_DEC_CFG_CHANGE_ENABLE_VPROC) if (change & MPP_DEC_CFG_CHANGE_ENABLE_VPROC)
dst_base->enable_vproc = src_base->enable_vproc; dst_base->enable_vproc = src_base->enable_vproc;
if (change & MPP_DEC_CFG_CHANGE_DISABLE_FAST_PLAY)
dst_base->disable_fast_play = src_base->disable_fast_play;
dst_base->change = change; dst_base->change = change;
src_base->change = 0; src_base->change = 0;
} }
@@ -2098,6 +2102,11 @@ MPP_RET mpp_dec_set_cfg_by_cmd(MppDecCfgSet *set, MpiCmd cmd, void *param)
cfg->change |= MPP_DEC_CFG_CHANGE_ENABLE_VPROC; cfg->change |= MPP_DEC_CFG_CHANGE_ENABLE_VPROC;
dec_dbg_func("enable dec_vproc %d\n", cfg->enable_vproc); dec_dbg_func("enable dec_vproc %d\n", cfg->enable_vproc);
} break; } break;
case MPP_DEC_SET_DISABLE_FAST_PLAY : {
cfg->disable_fast_play = (param) ? (*((RK_U32 *)param)) : (0);
cfg->change |= MPP_DEC_CFG_CHANGE_DISABLE_FAST_PLAY;
dec_dbg_func("disable idr immediately output %d\n", cfg->disable_fast_play);
} break;
default : { default : {
mpp_err_f("unsupported cfg update cmd %x\n", cmd); mpp_err_f("unsupported cfg update cmd %x\n", cmd);
ret = MPP_NOK; ret = MPP_NOK;

View File

@@ -34,6 +34,7 @@ typedef enum MppDecCfgChange_e {
MPP_DEC_CFG_CHANGE_SORT_PTS = (1 << 13), MPP_DEC_CFG_CHANGE_SORT_PTS = (1 << 13),
MPP_DEC_CFG_CHANGE_DISABLE_ERROR = (1 << 14), MPP_DEC_CFG_CHANGE_DISABLE_ERROR = (1 << 14),
MPP_DEC_CFG_CHANGE_ENABLE_VPROC = (1 << 15), MPP_DEC_CFG_CHANGE_ENABLE_VPROC = (1 << 15),
MPP_DEC_CFG_CHANGE_DISABLE_FAST_PLAY = (1 << 16),
MPP_DEC_CFG_CHANGE_ALL = (0xFFFFFFFF), MPP_DEC_CFG_CHANGE_ALL = (0xFFFFFFFF),
} MppDecCfgChange; } MppDecCfgChange;
@@ -54,6 +55,7 @@ typedef struct MppDecBaseCfg_t {
RK_U32 sort_pts; RK_U32 sort_pts;
RK_U32 disable_error; RK_U32 disable_error;
RK_U32 enable_vproc; RK_U32 enable_vproc;
RK_U32 disable_fast_play;
} MppDecBaseCfg; } MppDecBaseCfg;
typedef enum MppDecCbCfgChange_e { typedef enum MppDecCbCfgChange_e {

View File

@@ -1066,7 +1066,8 @@ MPP_RET Mpp::control_dec(MpiCmd cmd, MppParam param)
case MPP_DEC_SET_PARSER_FAST_MODE : case MPP_DEC_SET_PARSER_FAST_MODE :
case MPP_DEC_SET_IMMEDIATE_OUT : case MPP_DEC_SET_IMMEDIATE_OUT :
case MPP_DEC_SET_DISABLE_ERROR : case MPP_DEC_SET_DISABLE_ERROR :
case MPP_DEC_SET_ENABLE_DEINTERLACE : { case MPP_DEC_SET_ENABLE_DEINTERLACE :
case MPP_DEC_SET_DISABLE_FAST_PLAY : {
/* /*
* These control may be set before mpp_init * These control may be set before mpp_init
* When this case happen record the config and wait for decoder init * When this case happen record the config and wait for decoder init