mirror of
https://github.com/nyanmisaka/mpp.git
synced 2025-09-26 21:15:53 +08:00

1. Refactor caller parameter on pool functions. 2. Add name on pool init. 3. Add exit leak pool print. Signed-off-by: Herman Chen <herman.chen@rock-chips.com> Change-Id: I39a8a966db895340a9e01ddff3a7894f1ca4b825
779 lines
23 KiB
C
779 lines
23 KiB
C
/*
|
|
*
|
|
* 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 <string.h>
|
|
|
|
#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->p_Vid->dpb_fast_out,
|
|
p_Dec->cfg->base.enable_fast_play);
|
|
H264D_LOG("fast play mode: %d", p_Dec->p_Vid->dpb_fast_out);
|
|
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->p_Vid->dpb_fast_out,
|
|
p_Dec->cfg->base.enable_fast_play);
|
|
H264D_LOG("fast play mode: %d", p_Dec->p_Vid->dpb_fast_out);
|
|
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->p_Vid->dpb_fast_out = (param) ? (*((RK_U32 *)param)) : (1);
|
|
mpp_env_get_u32("force_fast_play_mode", &p_Dec->p_Vid->dpb_fast_out,
|
|
p_Dec->p_Vid->dpb_fast_out);
|
|
H264D_LOG("fast play mode: %d", p_Dec->p_Vid->dpb_fast_out);
|
|
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,
|
|
};
|
|
|