/* * * Copyright 2015 Rockchip Electronics Co. LTD * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define MODULE_TAG "h264d_api" #include #include "mpp_env.h" #include "mpp_platform.h" #include "mpp_packet_impl.h" #include "mpp_frame_impl.h" #include "h264d_api.h" #include "h264d_global.h" #include "h264d_parse.h" #include "h264d_sps.h" #include "h264d_slice.h" #include "h264d_dpb.h" #include "h264d_init.h" #include "h2645d_sei.h" #include "mpp_dec_cb_param.h" RK_U32 h264d_debug = 0; // for mblock 16 coded width align static RK_U32 rkv_mblock_width_align(RK_U32 val) { return MPP_ALIGN(val, 16); } static MPP_RET free_input_ctx(H264dInputCtx_t *p_Inp) { MPP_RET ret = MPP_ERR_UNKNOW; INP_CHECK(ret, !p_Inp); close_stream_file(p_Inp); MPP_FREE(p_Inp->spspps_buf); __RETURN: return ret = MPP_OK; } static MPP_RET init_input_ctx(H264dInputCtx_t *p_Inp, ParserCfg *init) { MPP_RET ret = MPP_ERR_UNKNOW; INP_CHECK(ret, !p_Inp && !init); open_stream_file(p_Inp, "/sdcard"); if (h264d_debug & H264D_DBG_WRITE_ES_EN) { p_Inp->spspps_size = HEAD_BUF_MAX_SIZE; p_Inp->spspps_buf = mpp_malloc_size(RK_U8, p_Inp->spspps_size); MEM_CHECK(ret, p_Inp->spspps_buf); } __RETURN: return ret = MPP_OK; __FAILED: free_input_ctx(p_Inp); return ret; } static MPP_RET free_cur_ctx(H264dCurCtx_t *p_Cur) { RK_U32 i = 0; MPP_RET ret = MPP_ERR_UNKNOW; INP_CHECK(ret, !p_Cur); if (p_Cur) { for (i = 0; i < MAX_NUM_DPB_LAYERS; i++) { MPP_FREE(p_Cur->listP[i]); MPP_FREE(p_Cur->listB[i]); } MPP_FREE(p_Cur->strm.nalu_buf); MPP_FREE(p_Cur->strm.head_buf); MPP_FREE(p_Cur->strm.tmp_buf); for (i = 0; i < MAX_MARKING_TIMES; i++) MPP_FREE(p_Cur->dec_ref_pic_marking_buffer[i]); MPP_FREE(p_Cur->subsps); MPP_FREE(p_Cur->sei); MPP_FREE(p_Cur->hdr_dynamic_meta); } __RETURN: return ret = MPP_OK; } static MPP_RET init_cur_ctx(H264dCurCtx_t *p_Cur) { RK_U32 i = 0; MPP_RET ret = MPP_ERR_UNKNOW; H264dCurStream_t *p_strm = NULL; INP_CHECK(ret, !p_Cur); p_strm = &p_Cur->strm; p_strm->nalu_max_size = NALU_BUF_MAX_SIZE; p_strm->nalu_buf = mpp_malloc_size(RK_U8, p_strm->nalu_max_size); p_strm->head_max_size = HEAD_BUF_MAX_SIZE; p_strm->head_buf = mpp_malloc_size(RK_U8, p_strm->head_max_size); p_strm->tmp_max_size = HEAD_BUF_MAX_SIZE; p_strm->tmp_buf = mpp_malloc_size(RK_U8, p_strm->head_max_size); MEM_CHECK(ret, p_strm->nalu_buf && p_strm->head_buf); p_strm->prefixdata = 0xffffffff; for (i = 0; i < MAX_NUM_DPB_LAYERS; i++) { p_Cur->listP[i] = mpp_malloc_size(H264_StorePic_t*, MAX_LIST_SIZE * sizeof(H264_StorePic_t*)); p_Cur->listB[i] = mpp_malloc_size(H264_StorePic_t*, MAX_LIST_SIZE * sizeof(H264_StorePic_t*)); MEM_CHECK(ret, p_Cur->listP[i] && p_Cur->listB[i]); // +1 for reordering } reset_cur_slice(p_Cur, &p_Cur->slice); __RETURN: return ret = MPP_OK; __FAILED: free_cur_ctx(p_Cur); return ret; } static MPP_RET free_vid_ctx(H264dVideoCtx_t *p_Vid) { RK_U32 i = 0; MPP_RET ret = MPP_ERR_UNKNOW; INP_CHECK(ret, !p_Vid); for (i = 0; i < MAXSPS; i++) { MPP_FREE(p_Vid->spsSet[i]); if (p_Vid->subspsSet[i]) recycle_subsps(p_Vid->subspsSet[i]); MPP_FREE(p_Vid->subspsSet[i]); } for (i = 0; i < MAXPPS; i++) MPP_FREE(p_Vid->ppsSet[i]); for (i = 0; i < MAX_NUM_DPB_LAYERS; i++) { free_dpb(p_Vid->p_Dpb_layer[i]); MPP_FREE(p_Vid->p_Dpb_layer[i]); } free_storable_picture(p_Vid->p_Dec, p_Vid->dec_pic); if (p_Vid->pic_st) { mpp_mem_pool_deinit_f(p_Vid->pic_st); p_Vid->pic_st = NULL; } __RETURN: return ret = MPP_OK; } static MPP_RET init_vid_ctx(H264dVideoCtx_t *p_Vid) { RK_U32 i = 0; MPP_RET ret = MPP_ERR_UNKNOW; INP_CHECK(ret, !p_Vid); for (i = 0; i < MAX_NUM_DPB_LAYERS; i++) { p_Vid->p_Dpb_layer[i] = mpp_calloc(H264_DpbBuf_t, 1); MEM_CHECK(ret, p_Vid->p_Dpb_layer[i]); p_Vid->p_Dpb_layer[i]->layer_id = i; p_Vid->p_Dpb_layer[i]->p_Vid = p_Vid; p_Vid->p_Dpb_layer[i]->init_done = 0; p_Vid->p_Dpb_layer[i]->poc_interval = 2; } //!< init active_sps p_Vid->active_sps = NULL; p_Vid->active_subsps = NULL; p_Vid->active_sps_id[0] = -1; p_Vid->active_sps_id[1] = -1; p_Vid->pic_st = mpp_mem_pool_init_f("h264d_pic_st", sizeof(H264_StorePic_t)); __RETURN: return ret = MPP_OK; __FAILED: free_vid_ctx(p_Vid); return ret; } static MPP_RET free_dxva_ctx(H264dDxvaCtx_t *p_dxva) { MPP_RET ret = MPP_ERR_UNKNOW; INP_CHECK(ret, NULL == p_dxva); MPP_FREE(p_dxva->slice_long); MPP_FREE(p_dxva->bitstream); MPP_FREE(p_dxva->syn.buf); __RETURN: return ret = MPP_OK; } static MPP_RET init_dxva_ctx(H264dDxvaCtx_t *p_dxva) { MPP_RET ret = MPP_ERR_UNKNOW; INP_CHECK(ret, !p_dxva); p_dxva->slice_count = 0; p_dxva->max_slice_size = MAX_SLICE_NUM; p_dxva->max_strm_size = BITSTREAM_MAX_SIZE; p_dxva->slice_long = mpp_calloc(DXVA_Slice_H264_Long, p_dxva->max_slice_size); MEM_CHECK(ret, p_dxva->slice_long); p_dxva->bitstream = mpp_malloc(RK_U8, p_dxva->max_strm_size); p_dxva->syn.buf = mpp_calloc(DXVA2_DecodeBufferDesc, SYNTAX_BUF_SIZE); MEM_CHECK(ret, p_dxva->bitstream && p_dxva->syn.buf); __RETURN: return ret = MPP_OK; __FAILED: return ret; } static MPP_RET free_dec_ctx(H264_DecCtx_t *p_Dec) { MPP_RET ret = MPP_ERR_UNKNOW; INP_CHECK(ret, NULL == p_Dec); if (p_Dec->mem) { free_dxva_ctx(&p_Dec->mem->dxva_ctx); MPP_FREE(p_Dec->mem); } //!< free mpp packet mpp_packet_deinit(&p_Dec->task_pkt); __RETURN: return ret = MPP_OK; } static MPP_RET init_dec_ctx(H264_DecCtx_t *p_Dec) { RK_U32 i = 0; MPP_RET ret = MPP_ERR_UNKNOW; INP_CHECK(ret, !p_Dec); p_Dec->mem = mpp_calloc(H264_DecMem_t, 1); MEM_CHECK(ret, p_Dec->mem); p_Dec->dpb_mark = p_Dec->mem->dpb_mark; //!< for write out, MAX_DPB_SIZE p_Dec->dpb_info = p_Dec->mem->dpb_info; //!< 16 p_Dec->refpic_info_p = p_Dec->mem->refpic_info_p; //!< 32 p_Dec->refpic_info_b[0] = p_Dec->mem->refpic_info_b[0]; //!< [2][32] p_Dec->refpic_info_b[1] = p_Dec->mem->refpic_info_b[1]; //!< [2][32] //!< init dxva memory p_Dec->mem->dxva_ctx.p_Dec = p_Dec; FUN_CHECK(ret = init_dxva_ctx(&p_Dec->mem->dxva_ctx)); p_Dec->dxva_ctx = &p_Dec->mem->dxva_ctx; //!< init Dpb_memory Mark for (i = 0; i < MAX_MARK_SIZE; i++) { reset_dpb_mark(&p_Dec->dpb_mark[i]); p_Dec->dpb_mark[i].mark_idx = i; } mpp_buf_slot_setup(p_Dec->frame_slots, MAX_MARK_SIZE); //!< malloc mpp packet mpp_packet_init(&p_Dec->task_pkt, p_Dec->dxva_ctx->bitstream, p_Dec->dxva_ctx->max_strm_size); MEM_CHECK(ret, p_Dec->task_pkt); //!< set Dec support decoder method p_Dec->spt_decode_mtds = MPP_DEC_BY_FRAME; p_Dec->next_state = SliceSTATE_ResetSlice; p_Dec->nalu_ret = NALU_NULL; p_Dec->have_slice_data = 0; p_Dec->last_frame_slot_idx = -1; memset(&p_Dec->errctx, 0, sizeof(H264dErrCtx_t)); __RETURN: return ret = MPP_OK; __FAILED: free_dec_ctx(p_Dec); return ret; } static MPP_RET h264d_flush_dpb_eos(H264_DecCtx_t *p_Dec) { MPP_RET ret = MPP_ERR_UNKNOW; INP_CHECK(ret, !p_Dec->p_Vid); FUN_CHECK(ret = flush_dpb(p_Dec->p_Vid->p_Dpb_layer[0], 1)); FUN_CHECK(ret = init_dpb(p_Dec->p_Vid, p_Dec->p_Vid->p_Dpb_layer[0], 1)); if (p_Dec->mvc_valid) { // layer_id == 1 FUN_CHECK(ret = flush_dpb(p_Dec->p_Vid->p_Dpb_layer[1], 1)); FUN_CHECK(ret = init_dpb(p_Dec->p_Vid, p_Dec->p_Vid->p_Dpb_layer[1], 2)); FUN_CHECK(ret = check_mvc_dpb(p_Dec->p_Vid, p_Dec->p_Vid->p_Dpb_layer[0], p_Dec->p_Vid->p_Dpb_layer[1])); } flush_dpb_buf_slot(p_Dec); __RETURN: return ret = MPP_OK; __FAILED: return ret = MPP_NOK; } /*! *********************************************************************** * \brief * alloc all buffer *********************************************************************** */ MPP_RET h264d_init(void *decoder, ParserCfg *init) { MPP_RET ret = MPP_ERR_UNKNOW; H264_DecCtx_t *p_Dec = (H264_DecCtx_t *)decoder; INP_CHECK(ret, !p_Dec); memset(p_Dec, 0, sizeof(H264_DecCtx_t)); mpp_env_get_u32("h264d_debug", &h264d_debug, H264D_DBG_ERROR); //!< get init frame_slots and packet_slots p_Dec->frame_slots = init->frame_slots; p_Dec->packet_slots = init->packet_slots; p_Dec->cfg = init->cfg; mpp_frame_init(&p_Dec->curframe); //!< malloc decoder buffer p_Dec->p_Inp = mpp_calloc(H264dInputCtx_t, 1); p_Dec->p_Cur = mpp_calloc(H264dCurCtx_t, 1); p_Dec->p_Vid = mpp_calloc(H264dVideoCtx_t, 1); MEM_CHECK(ret, p_Dec->p_Inp && p_Dec->p_Cur && p_Dec->p_Vid); p_Dec->p_Inp->p_Dec = p_Dec; p_Dec->p_Inp->p_Cur = p_Dec->p_Cur; p_Dec->p_Inp->p_Vid = p_Dec->p_Vid; p_Dec->p_Cur->p_Dec = p_Dec; p_Dec->p_Cur->p_Inp = p_Dec->p_Inp; p_Dec->p_Cur->p_Vid = p_Dec->p_Vid; p_Dec->p_Vid->p_Dec = p_Dec; p_Dec->p_Vid->p_Inp = p_Dec->p_Inp; p_Dec->p_Vid->p_Cur = p_Dec->p_Cur; p_Dec->hw_info = init->hw_info; FUN_CHECK(ret = init_input_ctx(p_Dec->p_Inp, init)); FUN_CHECK(ret = init_cur_ctx(p_Dec->p_Cur)); 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; mpp_env_get_u32("force_fast_play_mode", &p_Dec->cfg->base.enable_fast_play, p_Dec->cfg->base.enable_fast_play); p_Dec->p_Vid->dpb_fast_out = p_Dec->cfg->base.enable_fast_play; H264D_LOG("fast play mode: %d", p_Dec->cfg->base.enable_fast_play); p_Dec->p_Vid->dpb_first_fast_played = 0; mpp_slots_set_prop(p_Dec->frame_slots, SLOTS_WIDTH_ALIGN, rkv_mblock_width_align); __RETURN: return ret = MPP_OK; __FAILED: h264d_deinit(decoder); return ret; } /*! *********************************************************************** * \brief * free all buffer *********************************************************************** */ MPP_RET h264d_deinit(void *decoder) { MPP_RET ret = MPP_ERR_UNKNOW; H264_DecCtx_t *p_Dec = (H264_DecCtx_t *)decoder; INP_CHECK(ret, !decoder); mpp_frame_deinit(&p_Dec->curframe); free_input_ctx(p_Dec->p_Inp); MPP_FREE(p_Dec->p_Inp); free_cur_ctx(p_Dec->p_Cur); MPP_FREE(p_Dec->p_Cur); free_vid_ctx(p_Dec->p_Vid); MPP_FREE(p_Dec->p_Vid); free_dec_ctx(p_Dec); __RETURN: return ret = MPP_OK; } /*! *********************************************************************** * \brief * reset *********************************************************************** */ MPP_RET h264d_reset(void *decoder) { MPP_RET ret = MPP_ERR_UNKNOW; H264_DecCtx_t *p_Dec = (H264_DecCtx_t *)decoder; H264dCurStream_t *p_strm = NULL; INP_CHECK(ret, !decoder); flush_dpb(p_Dec->p_Vid->p_Dpb_layer[0], 1); init_dpb(p_Dec->p_Vid, p_Dec->p_Vid->p_Dpb_layer[0], 1); if (p_Dec->mvc_valid) { // layer_id == 1 flush_dpb(p_Dec->p_Vid->p_Dpb_layer[1], 1); init_dpb(p_Dec->p_Vid, p_Dec->p_Vid->p_Dpb_layer[1], 2); check_mvc_dpb(p_Dec->p_Vid, p_Dec->p_Vid->p_Dpb_layer[0], p_Dec->p_Vid->p_Dpb_layer[1]); } flush_dpb_buf_slot(p_Dec); //!< reset input parameter p_Dec->p_Inp->in_buf = NULL; p_Dec->p_Inp->pkt_eos = 0; p_Dec->p_Inp->task_eos = 0; p_Dec->p_Inp->in_pts = 0; p_Dec->p_Inp->in_dts = 0; p_Dec->p_Inp->has_get_eos = 0; //!< reset video parameter p_Dec->p_Vid->have_outpicture_flag = 0; p_Dec->p_Vid->exit_picture_flag = 0; p_Dec->p_Vid->active_mvc_sps_flag = 0; p_Dec->p_Vid->g_framecnt = 0; p_Dec->p_Vid->dec_pic = NULL; p_Dec->p_Vid->last_pic = NULL; memset(&p_Dec->p_Vid->recovery, 0, sizeof(RecoveryPoint)); memset(&p_Dec->p_Vid->old_pic, 0, sizeof(H264_StorePic_t)); memset(&p_Dec->errctx, 0, sizeof(H264dErrCtx_t)); //!< reset current time stamp p_Dec->p_Cur->last_dts = 0; p_Dec->p_Cur->last_pts = 0; p_Dec->p_Cur->curr_dts = 0; p_Dec->p_Cur->curr_pts = 0; //!< reset current stream p_strm = &p_Dec->p_Cur->strm; p_strm->prefixdata = 0xffffffff; p_strm->nalu_offset = 0; p_strm->nalu_len = 0; if (p_strm->nalu_type != H264_NALU_TYPE_PPS && p_strm->nalu_type != H264_NALU_TYPE_SPS) p_strm->head_offset = 0; p_strm->tmp_offset = 0; p_strm->first_mb_in_slice = 0; p_strm->endcode_found = 0; p_strm->startcode_found = p_Dec->p_Inp->is_nalff; //!< reset decoder parameter p_Dec->next_state = SliceSTATE_ResetSlice; p_Dec->nalu_ret = NALU_NULL; p_Dec->have_slice_data = 0; p_Dec->is_new_frame = 0; p_Dec->is_parser_end = 0; p_Dec->dxva_ctx->strm_offset = 0; p_Dec->dxva_ctx->slice_count = 0; p_Dec->last_frame_slot_idx = -1; mpp_env_get_u32("force_fast_play_mode", &p_Dec->cfg->base.enable_fast_play, p_Dec->cfg->base.enable_fast_play); p_Dec->p_Vid->dpb_fast_out = p_Dec->cfg->base.enable_fast_play; H264D_LOG("fast play mode: %d", p_Dec->cfg->base.enable_fast_play); p_Dec->p_Vid->dpb_first_fast_played = 0; __RETURN: return ret = MPP_OK; } /*! *********************************************************************** * \brief * flush *********************************************************************** */ MPP_RET h264d_flush(void *decoder) { MPP_RET ret = MPP_ERR_UNKNOW; H264_DecCtx_t *p_Dec = (H264_DecCtx_t *)decoder; INP_CHECK(ret, !decoder); INP_CHECK(ret, !p_Dec->p_Inp); INP_CHECK(ret, !p_Dec->p_Vid); FUN_CHECK(ret = output_dpb(p_Dec, p_Dec->p_Vid->p_Dpb_layer[0])); if (p_Dec->mvc_valid) { FUN_CHECK(ret = output_dpb(p_Dec, p_Dec->p_Vid->p_Dpb_layer[1])); } __RETURN: return ret = MPP_OK; __FAILED: return ret = MPP_NOK; } /*! *********************************************************************** * \brief * control/perform *********************************************************************** */ MPP_RET h264d_control(void *decoder, MpiCmd 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->cfg->base.enable_fast_play = (param) ? (*((RK_U32 *)param)) : (1); mpp_env_get_u32("force_fast_play_mode", &p_Dec->cfg->base.enable_fast_play, p_Dec->cfg->base.enable_fast_play); p_Dec->p_Vid->dpb_fast_out = p_Dec->cfg->base.enable_fast_play; H264D_LOG("fast play mode: %d", p_Dec->cfg->base.enable_fast_play); break; case MPP_DEC_SET_MAX_USE_BUFFER_SIZE : p_Dec->p_Inp->max_buf_size = (param) ? (*((RK_U32 *)param)) : (0); break; default: break; } return MPP_OK; } /*! *********************************************************************** * \brief * prepare *********************************************************************** */ #define MAX_STREM_IN_SIZE (10*1024*1024) MPP_RET h264d_prepare(void *decoder, MppPacket pkt, HalDecTask *task) { MPP_RET ret = MPP_ERR_UNKNOW; H264dInputCtx_t *p_Inp = NULL; H264_DecCtx_t *p_Dec = (H264_DecCtx_t *)decoder; INP_CHECK(ret, !decoder && !pkt && !task); p_Inp = p_Dec->p_Inp; if (p_Inp->has_get_eos) { mpp_packet_set_length(pkt, 0); task->flags.eos = mpp_packet_get_eos(pkt); goto __RETURN; } p_Inp->in_pkt = pkt; p_Inp->in_pts = mpp_packet_get_pts(pkt); p_Inp->in_dts = mpp_packet_get_dts(pkt); p_Inp->in_length = mpp_packet_get_length(pkt); p_Inp->pkt_eos = mpp_packet_get_eos(pkt); p_Inp->in_buf = (RK_U8 *)mpp_packet_get_pos(pkt); if (p_Inp->pkt_eos && p_Inp->in_length < 4) { p_Inp->has_get_eos = 1; p_Inp->in_buf = NULL; p_Inp->in_length = 0; mpp_packet_set_length(p_Inp->in_pkt, 0); task->flags.eos = p_Inp->pkt_eos; } if (p_Inp->in_length > MAX_STREM_IN_SIZE) { H264D_ERR("[pkt_in_timeUs] input error, stream too large, pts=%lld, eos=%d, len=%d, pkt_no=%d", p_Inp->in_pts, p_Inp->pkt_eos, p_Inp->in_length, p_Dec->p_Vid->g_framecnt); mpp_packet_set_length(pkt, 0); ret = MPP_NOK; goto __FAILED; } //!< avcC stream if (mpp_packet_get_flag(pkt) & MPP_PACKET_FLAG_EXTRA_DATA) { RK_U8 *pdata = p_Inp->in_buf; p_Inp->is_nalff = (p_Inp->in_length > 3) && (pdata[0] == 1); mpp_log("is_avcC=%d\n", p_Inp->is_nalff); if (p_Inp->is_nalff) { (ret = parse_prepare_avcC_header(p_Inp, p_Dec->p_Cur)); goto __RETURN; } } H264D_DBG(H264D_DBG_INPUT, "[pkt_in_timeUs] is_avcC=%d, in_pts=%lld, pkt_eos=%d, len=%d, pkt_no=%d", p_Inp->is_nalff, p_Inp->in_pts, p_Inp->pkt_eos, p_Inp->in_length, p_Dec->p_Vid->g_framecnt); if (p_Inp->is_nalff) { (ret = parse_prepare_avcC_data(p_Inp, p_Dec->p_Cur)); task->valid = p_Inp->task_valid; //!< prepare valid flag } else { fwrite_stream_to_file(p_Inp, p_Inp->in_buf, (RK_U32)p_Inp->in_length); do { if (p_Dec->cfg->base.split_parse) { ret = parse_prepare(p_Inp, p_Dec->p_Cur); } else { ret = parse_prepare_fast(p_Inp, p_Dec->p_Cur); } task->valid = p_Inp->task_valid; //!< prepare valid flag } while (mpp_packet_get_length(pkt) && !task->valid); } if (p_Inp->in_length < 4) task->flags.eos = p_Inp->pkt_eos; if (task->valid) { memset(p_Dec->dxva_ctx->bitstream + p_Dec->dxva_ctx->strm_offset, 0, MPP_ALIGN(p_Dec->dxva_ctx->strm_offset, 16) - p_Dec->dxva_ctx->strm_offset); mpp_packet_set_data(p_Dec->task_pkt, p_Dec->dxva_ctx->bitstream); mpp_packet_set_length(p_Dec->task_pkt, MPP_ALIGN(p_Dec->dxva_ctx->strm_offset, 16)); mpp_packet_set_size(p_Dec->task_pkt, p_Dec->dxva_ctx->max_strm_size); task->input_packet = p_Dec->task_pkt; } else { task->input_packet = NULL; /* * During split_parse, the empty EOS will endcode and decode the * last complete packet. * When sending EOS in split mode, dpb can not be flushed * before split process. */ if (p_Inp->pkt_eos && p_Inp->in_length < 4) h264d_flush_dpb_eos(p_Dec); } __RETURN: return ret = MPP_OK; __FAILED: return ret; } /*! *********************************************************************** * \brief * parser *********************************************************************** */ MPP_RET h264d_parse(void *decoder, HalDecTask *in_task) { MPP_RET ret = MPP_ERR_UNKNOW; H264_DecCtx_t *p_Dec = (H264_DecCtx_t *)decoder; H264dErrCtx_t *p_err = &p_Dec->errctx; in_task->valid = 0; p_Dec->in_task = in_task; p_err->cur_err_flag = 0; p_err->used_ref_flag = 0; p_Dec->is_parser_end = 0; if (p_Dec->p_Cur->sei) memset(p_Dec->p_Cur->sei, 0, sizeof(*p_Dec->p_Cur->sei)); ret = parse_loop(p_Dec); if (ret) { in_task->flags.parse_err = 1; } if (p_Dec->is_parser_end) { p_Dec->is_parser_end = 0; p_Dec->p_Vid->g_framecnt++; ret = update_dpb(p_Dec); if (ret) { in_task->flags.ref_err = 1; } if (in_task->flags.eos) { h264d_flush_dpb_eos(p_Dec); } } in_task->valid = 1; if (!in_task->flags.parse_err) { in_task->syntax.number = p_Dec->dxva_ctx->syn.num; in_task->syntax.data = (void *)p_Dec->dxva_ctx->syn.buf; in_task->flags.used_for_ref = p_err->used_ref_flag; in_task->flags.ref_err |= (p_err->dpb_err_flag | p_err->cur_err_flag) ? 1 : 0; } return ret; } /*! *********************************************************************** * \brief * callback *********************************************************************** */ MPP_RET h264d_callback(void *decoder, void *errinfo) { MPP_RET ret = MPP_ERR_UNKNOW; H264_DecCtx_t *p_Dec = (H264_DecCtx_t *)decoder; DecCbHalDone *ctx = (DecCbHalDone *)errinfo; HalDecTask *task_dec = (HalDecTask *)ctx->task; RK_U32 task_err = task_dec->flags.parse_err || task_dec->flags.ref_err; RK_U32 ref_used = task_dec->flags.ref_info_valid ? task_dec->flags.ref_used : 0; RK_U32 hw_dec_err = ctx->hard_err; RK_S32 output = task_dec->output; RK_U32 err_mark = 0; MppFrame frame = NULL; INP_CHECK(ret, !decoder); if (output >= 0) mpp_buf_slot_get_prop(p_Dec->frame_slots, output, SLOT_FRAME_PTR, &frame); if (!frame) goto __RETURN; /* check and mark current frame */ if (task_err) { err_mark |= MPP_FRAME_ERR_DEC_INVALID; goto DONE; } if (hw_dec_err) { err_mark |= MPP_FRAME_ERR_DEC_HW_ERR; goto DONE; } if (ref_used) { RK_S32 *refer = task_dec->refer; RK_U32 i; for (i = 0; i < 16; i++) { RK_U32 mask = 1 << i; RK_U32 error = 0; MppFrameImpl *tmp = NULL; /* not used frame or non-refer frame skip */ if (!(ref_used & mask) || (refer[i] < 0)) continue; /* check and mark error for error reference frame */ mpp_buf_slot_get_prop(p_Dec->frame_slots, refer[i], SLOT_FRAME_PTR, &tmp); error = tmp->errinfo; H264D_DBG(H264D_DBG_DPB_REF_ERR, "cur_poc %d frm slot %d refer %d slot %d poc %d errinfo %x\n", mpp_frame_get_poc(frame), output, i, refer[i], tmp->poc, error); if (error) { mpp_log_f("cur_poc %d mark error ref slot %d:%d poc %d err %x\n", mpp_frame_get_poc(frame), i, refer[i], tmp->poc, error); err_mark |= MPP_FRAME_ERR_UNKNOW; break; } } } DONE: if (err_mark) { if (task_dec->flags.used_for_ref) { mpp_frame_set_errinfo(frame, err_mark); } else { mpp_frame_set_discard(frame, err_mark); } } H264D_DBG(H264D_DBG_CALLBACK, "[CALLBACK] g_no %d, out_idx %d, dpberr %d, harderr %d, ref_flag %d, " "errinfo %x, discard %x poc %d view_id %d\n", p_Dec->p_Vid->g_framecnt, output, task_err, ctx->hard_err, task_dec->flags.used_for_ref, mpp_frame_get_errinfo(frame), mpp_frame_get_discard(frame), mpp_frame_get_poc(frame), mpp_frame_get_viewid(frame)); __RETURN: return ret = MPP_OK; } /*! *********************************************************************** * \brief * api struct interface *********************************************************************** */ const ParserApi api_h264d_parser = { .name = "h264d_parse", .coding = MPP_VIDEO_CodingAVC, .ctx_size = sizeof(H264_DecCtx_t), .flag = 0, .init = h264d_init, .deinit = h264d_deinit, .prepare = h264d_prepare, .parse = h264d_parse, .reset = h264d_reset, .flush = h264d_flush, .control = h264d_control, .callback = h264d_callback, };