[h264d]: fix bug: when judge whether is end of frame

1. when had slice data and current nalu is SPS PPS AUD SEI,
thus it can consider that last nalu is the end of frame.
2. when pps is missing, frame data is continue, and use
first_mb_in_slice to judge last nalu is end of frame.

Change-Id: I1ccf3ca415e6b04dcd7fe7fc9c357fd600fa5803
Signed-off-by: leo.ding <leo.ding@rock-chips.com>
This commit is contained in:
leo.ding
2017-06-15 21:29:01 +08:00
committed by Herman Chen
parent ca168b9119
commit ef02ca75ff
3 changed files with 44 additions and 43 deletions

View File

@@ -264,7 +264,7 @@ static MPP_RET init_dec_ctx(H264_DecCtx_t *p_Dec)
p_Dec->spt_decode_mtds = MPP_DEC_BY_FRAME; p_Dec->spt_decode_mtds = MPP_DEC_BY_FRAME;
p_Dec->next_state = SliceSTATE_ResetSlice; p_Dec->next_state = SliceSTATE_ResetSlice;
p_Dec->nalu_ret = NALU_NULL; p_Dec->nalu_ret = NALU_NULL;
p_Dec->is_first_frame = 1; p_Dec->have_slice_data = 0;
p_Dec->last_frame_slot_idx = -1; p_Dec->last_frame_slot_idx = -1;
memset(&p_Dec->errctx, 0, sizeof(H264dErrCtx_t)); memset(&p_Dec->errctx, 0, sizeof(H264dErrCtx_t));
__RETURN: __RETURN:
@@ -422,7 +422,7 @@ MPP_RET h264d_reset(void *decoder)
//!< reset decoder parameter //!< reset decoder parameter
p_Dec->next_state = SliceSTATE_ResetSlice; p_Dec->next_state = SliceSTATE_ResetSlice;
p_Dec->nalu_ret = NALU_NULL; p_Dec->nalu_ret = NALU_NULL;
p_Dec->is_first_frame = 1; p_Dec->have_slice_data = 0;
p_Dec->is_new_frame = 0; p_Dec->is_new_frame = 0;
p_Dec->is_parser_end = 0; p_Dec->is_parser_end = 0;
p_Dec->dxva_ctx->strm_offset = 0; p_Dec->dxva_ctx->strm_offset = 0;

View File

@@ -1132,7 +1132,7 @@ typedef struct h264_dec_ctx_t {
RK_U32 spt_decode_mtds; //!< support decoder methods RK_U32 spt_decode_mtds; //!< support decoder methods
NALU_STATUS nalu_ret; //!< current nalu state NALU_STATUS nalu_ret; //!< current nalu state
SLICE_STATUS next_state; //!< RKV_SLICE_STATUS SLICE_STATUS next_state; //!< RKV_SLICE_STATUS
RK_U8 is_first_frame; RK_U8 have_slice_data;
RK_U8 is_new_frame; RK_U8 is_new_frame;
RK_U8 is_parser_end; RK_U8 is_parser_end;
RK_U8 mvc_valid; RK_U8 mvc_valid;

View File

@@ -369,6 +369,7 @@ static MPP_RET store_cur_nalu(H264dCurCtx_t *p_Cur, H264dCurStream_t *p_strm, H2
p_Inp->spspps_offset = 0; p_Inp->spspps_offset = 0;
} }
} }
return ret = MPP_OK; return ret = MPP_OK;
__FAILED: __FAILED:
return ret; return ret;
@@ -378,52 +379,60 @@ static MPP_RET judge_is_new_frame(H264dCurCtx_t *p_Cur, H264dCurStream_t *p_strm
{ {
MPP_RET ret = MPP_ERR_UNKNOW; MPP_RET ret = MPP_ERR_UNKNOW;
RK_U32 nalu_header_bytes = 0; RK_U32 nalu_header_bytes = 0;
RK_U32 first_mb_in_slice = 0;
BitReadCtx_t *p_bitctx = &p_Cur->bitctx; BitReadCtx_t *p_bitctx = &p_Cur->bitctx;
RK_U32 forbidden_bit = -1;
RK_U32 nal_reference_idc = -1;
RK_U32 svc_extension_flag = -1;
memset(p_bitctx, 0, sizeof(BitReadCtx_t)); memset(p_bitctx, 0, sizeof(BitReadCtx_t));
mpp_set_bitread_ctx(p_bitctx, p_strm->nalu_buf, 4); {
mpp_set_pre_detection(p_bitctx); RK_U32 forbidden_bit = -1;
RK_U32 nal_reference_idc = -1;
RK_U32 svc_extension_flag = -1;
mpp_set_bitread_ctx(p_bitctx, p_strm->nalu_buf, 4);
mpp_set_pre_detection(p_bitctx);
READ_BITS(p_bitctx, 1, &forbidden_bit); READ_BITS(p_bitctx, 1, &forbidden_bit);
ASSERT(forbidden_bit == 0); ASSERT(forbidden_bit == 0);
READ_BITS(p_bitctx, 2, &nal_reference_idc); READ_BITS(p_bitctx, 2, &nal_reference_idc);
READ_BITS(p_bitctx, 5, &p_strm->nalu_type); READ_BITS(p_bitctx, 5, &p_strm->nalu_type);
nalu_header_bytes = 1; nalu_header_bytes = 1;
if ((p_strm->nalu_type == NALU_TYPE_PREFIX) || (p_strm->nalu_type == NALU_TYPE_SLC_EXT)) { if ((p_strm->nalu_type == NALU_TYPE_PREFIX) || (p_strm->nalu_type == NALU_TYPE_SLC_EXT)) {
READ_BITS(p_bitctx, 1, &svc_extension_flag); READ_BITS(p_bitctx, 1, &svc_extension_flag);
if (svc_extension_flag) { if (svc_extension_flag) {
H264D_WARNNING("svc_extension is not supported."); H264D_WARNNING("svc_extension is not supported.");
goto __FAILED; goto __FAILED;
} else { } else {
if (p_strm->nalu_type == NALU_TYPE_SLC_EXT) { if (p_strm->nalu_type == NALU_TYPE_SLC_EXT) {
p_strm->nalu_type = NALU_TYPE_SLICE; p_strm->nalu_type = NALU_TYPE_SLICE;
}
} }
nalu_header_bytes += 3;
} }
nalu_header_bytes += 3;
} }
//-- parse slice if ((p_strm->nalu_len == 1)
if ( p_strm->nalu_type == NALU_TYPE_SLICE || p_strm->nalu_type == NALU_TYPE_IDR) { && (p_strm->nalu_type == NALU_TYPE_SEI
|| p_strm->nalu_type == NALU_TYPE_SPS
|| p_strm->nalu_type == NALU_TYPE_PPS
|| p_strm->nalu_type == NALU_TYPE_AUD)) {
if (p_Cur->p_Dec->have_slice_data) {
p_Cur->p_Dec->is_new_frame = 1;
}
p_Cur->p_Dec->have_slice_data = 0;
} else if ((p_strm->nalu_len > 1)
&& (p_strm->nalu_type == NALU_TYPE_SLICE
|| p_strm->nalu_type == NALU_TYPE_IDR)) {
RK_U32 first_mb_in_slice = 0;
mpp_set_bitread_ctx(p_bitctx, (p_strm->nalu_buf + nalu_header_bytes), 4); // reset mpp_set_bitread_ctx(p_bitctx, (p_strm->nalu_buf + nalu_header_bytes), 4); // reset
mpp_set_pre_detection(p_bitctx); mpp_set_pre_detection(p_bitctx);
READ_UE(p_bitctx, &first_mb_in_slice); READ_UE(p_bitctx, &first_mb_in_slice);
//!< get time stamp
if (first_mb_in_slice == 0) { if (first_mb_in_slice == 0) {
p_Cur->last_dts = p_Cur->curr_dts; p_Cur->last_dts = p_Cur->curr_dts;
p_Cur->last_pts = p_Cur->curr_pts; p_Cur->last_pts = p_Cur->curr_pts;
p_Cur->curr_dts = p_Cur->p_Inp->in_dts; p_Cur->curr_dts = p_Cur->p_Inp->in_dts;
p_Cur->curr_pts = p_Cur->p_Inp->in_pts; p_Cur->curr_pts = p_Cur->p_Inp->in_pts;
if (!p_Cur->p_Dec->is_first_frame) { if (p_Cur->p_Dec->have_slice_data) {
p_Cur->p_Dec->is_new_frame = 1; p_Cur->p_Dec->is_new_frame = 1;
} }
p_Cur->p_Dec->is_first_frame = 0; p_Cur->p_Dec->have_slice_data = 1;
} }
} }
@@ -515,7 +524,6 @@ MPP_RET close_stream_file(H264dInputCtx_t *p_Inp)
MPP_RET parse_prepare(H264dInputCtx_t *p_Inp, H264dCurCtx_t *p_Cur) MPP_RET parse_prepare(H264dInputCtx_t *p_Inp, H264dCurCtx_t *p_Cur)
{ {
MPP_RET ret = MPP_ERR_UNKNOW; MPP_RET ret = MPP_ERR_UNKNOW;
RK_U32 nalu_header_bytes = 0;
H264_DecCtx_t *p_Dec = p_Inp->p_Dec; H264_DecCtx_t *p_Dec = p_Inp->p_Dec;
H264dCurStream_t *p_strm = &p_Cur->strm; H264dCurStream_t *p_strm = &p_Cur->strm;
@@ -546,15 +554,8 @@ MPP_RET parse_prepare(H264dInputCtx_t *p_Inp, H264dCurCtx_t *p_Cur)
FUN_CHECK(ret = realloc_buffer(&p_strm->nalu_buf, &p_strm->nalu_max_size, NALU_BUF_ADD_SIZE)); FUN_CHECK(ret = realloc_buffer(&p_strm->nalu_buf, &p_strm->nalu_max_size, NALU_BUF_ADD_SIZE));
} }
p_strm->nalu_buf[p_strm->nalu_len++] = *p_strm->curdata; p_strm->nalu_buf[p_strm->nalu_len++] = *p_strm->curdata;
if (p_strm->nalu_len == 1) { if ((p_strm->nalu_len == 1)
p_strm->nalu_type = p_strm->nalu_buf[0] & 0x1F; || (p_strm->nalu_len == 5)) {
nalu_header_bytes += 1;
if ((p_strm->nalu_type == NALU_TYPE_PREFIX)
|| (p_strm->nalu_type == NALU_TYPE_SLC_EXT)) {
nalu_header_bytes += 3;
}
}
if (p_strm->nalu_len == (nalu_header_bytes + 4)) {
FUN_CHECK(ret = judge_is_new_frame(p_Cur, p_strm)); FUN_CHECK(ret = judge_is_new_frame(p_Cur, p_strm));
if (p_Cur->p_Dec->is_new_frame) { if (p_Cur->p_Dec->is_new_frame) {
FUN_CHECK(ret = add_empty_nalu(&p_Cur->strm)); FUN_CHECK(ret = add_empty_nalu(&p_Cur->strm));
@@ -784,7 +785,7 @@ MPP_RET parse_prepare_extra_data(H264dInputCtx_t *p_Inp, H264dCurCtx_t *p_Cur)
p_strm->nalu_len = parse_nal_size(p_Inp->nal_size, p_strm->curdata); p_strm->nalu_len = parse_nal_size(p_Inp->nal_size, p_strm->curdata);
if (p_strm->nalu_len <= 0 || p_strm->nalu_len >= p_Inp->in_length) { if (p_strm->nalu_len <= 0 || p_strm->nalu_len >= p_Inp->in_length) {
p_Cur->p_Dec->is_new_frame = 1; p_Cur->p_Dec->is_new_frame = 1;
p_Cur->p_Dec->is_first_frame = 1; p_Cur->p_Dec->have_slice_data = 0;
pkt_impl->length = 0; pkt_impl->length = 0;
p_Inp->in_length = 0; p_Inp->in_length = 0;
p_strm->nalu_len = 0; p_strm->nalu_len = 0;
@@ -815,7 +816,7 @@ MPP_RET parse_prepare_extra_data(H264dInputCtx_t *p_Inp, H264dCurCtx_t *p_Cur)
} }
if (p_Inp->in_length < p_Inp->nal_size) { if (p_Inp->in_length < p_Inp->nal_size) {
p_Cur->p_Dec->is_new_frame = 1; p_Cur->p_Dec->is_new_frame = 1;
p_Cur->p_Dec->is_first_frame = 1; p_Cur->p_Dec->have_slice_data = 0;
pkt_impl->length = 0; pkt_impl->length = 0;
p_Inp->in_length = 0; p_Inp->in_length = 0;
p_strm->nalu_len = 0; p_strm->nalu_len = 0;