/* * * 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 "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 "mpp_dec_cb_param.h" RK_U32 rkv_h264d_parse_debug = 0; 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); mpp_env_get_u32("rkv_h264d_mvc_disable", &p_Inp->mvc_disable, 1); open_stream_file(p_Inp, "/sdcard"); if (rkv_h264d_parse_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); 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); } __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); 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++) { if (p_Vid->subspsSet[i]) recycle_subsps(p_Vid->subspsSet[i]); } for (i = 0; i < MAXSPS; i++) { MPP_FREE(p_Vid->spsSet[i]); MPP_FREE(p_Vid->ppsSet[i]); MPP_FREE(p_Vid->subspsSet[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(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(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)); } 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("rkv_h264d_debug", &rkv_h264d_parse_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; __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); 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)); } 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->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; p_strm->head_offset = 0; p_strm->startcode_found = 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; __RETURN: return ret = MPP_OK; __FAILED: return ret = MPP_NOK; } /*! *********************************************************************** * \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) { (void) decoder; (void) cmd_type; (void) param; 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 || p_Dec->errctx.un_spt_flag) { mpp_packet_set_length(pkt, 0); 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->has_get_eos = 1; if (p_Inp->in_length < 4) { p_Inp->in_buf = NULL; p_Inp->in_length = 0; task->flags.eos = p_Inp->pkt_eos; h264d_flush_dpb_eos(p_Dec); goto __RETURN; } } 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] || pdata[1] || (pdata[2] > 1) || (!pdata[2] && pdata[3] > 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); } 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; } __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_Dec->cfg->base.disable_error && (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; INP_CHECK(ret, !decoder); { MppFrame mframe = NULL; HalDecTask *task_dec = (HalDecTask *)ctx->task; if (task_dec->output >= 0) mpp_buf_slot_get_prop(p_Dec->frame_slots, task_dec->output, SLOT_FRAME_PTR, &mframe); if (mframe) { RK_U32 task_err = task_dec->flags.parse_err || task_dec->flags.ref_err; if (ctx->hard_err || task_err) { if (task_dec->flags.used_for_ref) { mpp_frame_set_errinfo(mframe, MPP_FRAME_ERR_UNKNOW); } else { mpp_frame_set_discard(mframe, MPP_FRAME_ERR_UNKNOW); } } H264D_DBG(H264D_DBG_CALLBACK, "[CALLBACK] g_no=%d, out_idx=%d, dpberr=%d, harderr=%d, ref_flag=%d, errinfo=%d, discard=%d\n", p_Dec->p_Vid->g_framecnt, task_dec->output, task_err, ctx->hard_err, task_dec->flags.used_for_ref, mpp_frame_get_errinfo(mframe), mpp_frame_get_discard(mframe)); } } __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, };