From 93930b5ef94b72e47a8030faefd56058b29622a7 Mon Sep 17 00:00:00 2001 From: DingWei Date: Sun, 13 Sep 2015 20:16:23 +0000 Subject: [PATCH] add file: parse module and hal module Tips: In his version, h264d_test pass via the way of single pthread. git-svn-id: https://10.10.10.66:8443/svn/MediaProcessPlatform/trunk/mpp@263 6e48237b-75ef-9749-8fc9-41990f28c85a --- mpp/codec/dec/h264/CMakeLists.txt | 20 + mpp/codec/dec/h264/h264d_api.c | 309 +++- mpp/codec/dec/h264/h264d_bitread.c | 40 +- mpp/codec/dec/h264/h264d_bitread.h | 79 +- mpp/codec/dec/h264/h264d_dpb.c | 2332 ++++++++++++++++++++++++ mpp/codec/dec/h264/h264d_dpb.h | 54 + mpp/codec/dec/h264/h264d_fill.c | 426 +++++ mpp/codec/dec/h264/h264d_fill.h | 43 + mpp/codec/dec/h264/h264d_global.h | 72 +- mpp/codec/dec/h264/h264d_init.c | 1389 ++++++++++++++ mpp/codec/dec/h264/h264d_init.h | 39 + mpp/codec/dec/h264/h264d_log.c | 199 +- mpp/codec/dec/h264/h264d_parse.c | 386 +++- mpp/codec/dec/h264/h264d_parse.h | 58 +- mpp/codec/dec/h264/h264d_pps.c | 183 ++ mpp/codec/dec/h264/h264d_pps.h | 39 + mpp/codec/dec/h264/h264d_rwfile.c | 55 +- mpp/codec/dec/h264/h264d_scalist.c | 409 +++++ mpp/codec/dec/h264/h264d_scalist.h | 41 + mpp/codec/dec/h264/h264d_sei.c | 410 +++++ mpp/codec/dec/h264/h264d_sei.h | 37 + mpp/codec/dec/h264/h264d_slice.c | 659 +++++++ mpp/codec/dec/h264/h264d_slice.h | 39 + mpp/codec/dec/h264/h264d_sps.c | 592 ++++++ mpp/codec/dec/h264/h264d_sps.h | 41 + mpp/common/h264d_log.h | 118 +- mpp/common/h264d_syntax.h | 2 +- mpp/hal/inc/hal_h264d_api.h | 305 +--- mpp/hal/rkdec/h264d/CMakeLists.txt | 10 +- mpp/hal/rkdec/h264d/hal_h264d_api.c | 328 +++- mpp/hal/rkdec/h264d/hal_h264d_fifo.c | 205 +++ mpp/hal/rkdec/h264d/hal_h264d_fifo.h | 46 + mpp/hal/rkdec/h264d/hal_h264d_global.h | 65 + mpp/hal/rkdec/h264d/hal_h264d_packet.c | 518 ++++++ mpp/hal/rkdec/h264d/hal_h264d_packet.h | 45 + mpp/hal/rkdec/h264d/hal_h264d_reg.c | 270 +++ mpp/hal/rkdec/h264d/hal_h264d_reg.h | 307 ++++ mpp/test/h264d_test.c | 33 +- 38 files changed, 9427 insertions(+), 776 deletions(-) create mode 100644 mpp/codec/dec/h264/h264d_dpb.c create mode 100644 mpp/codec/dec/h264/h264d_dpb.h create mode 100644 mpp/codec/dec/h264/h264d_fill.c create mode 100644 mpp/codec/dec/h264/h264d_fill.h create mode 100644 mpp/codec/dec/h264/h264d_init.c create mode 100644 mpp/codec/dec/h264/h264d_init.h create mode 100644 mpp/codec/dec/h264/h264d_pps.c create mode 100644 mpp/codec/dec/h264/h264d_pps.h create mode 100644 mpp/codec/dec/h264/h264d_scalist.c create mode 100644 mpp/codec/dec/h264/h264d_scalist.h create mode 100644 mpp/codec/dec/h264/h264d_sei.c create mode 100644 mpp/codec/dec/h264/h264d_sei.h create mode 100644 mpp/codec/dec/h264/h264d_slice.c create mode 100644 mpp/codec/dec/h264/h264d_slice.h create mode 100644 mpp/codec/dec/h264/h264d_sps.c create mode 100644 mpp/codec/dec/h264/h264d_sps.h create mode 100644 mpp/hal/rkdec/h264d/hal_h264d_fifo.c create mode 100644 mpp/hal/rkdec/h264d/hal_h264d_fifo.h create mode 100644 mpp/hal/rkdec/h264d/hal_h264d_global.h create mode 100644 mpp/hal/rkdec/h264d/hal_h264d_packet.c create mode 100644 mpp/hal/rkdec/h264d/hal_h264d_packet.h create mode 100644 mpp/hal/rkdec/h264d/hal_h264d_reg.c create mode 100644 mpp/hal/rkdec/h264d/hal_h264d_reg.h diff --git a/mpp/codec/dec/h264/CMakeLists.txt b/mpp/codec/dec/h264/CMakeLists.txt index a4a60d43..680ec2f3 100644 --- a/mpp/codec/dec/h264/CMakeLists.txt +++ b/mpp/codec/dec/h264/CMakeLists.txt @@ -16,6 +16,16 @@ set(H264D_HDR h264d_global.h h264d_bitread.h h264d_parse.h + h264d_slice.h + h264d_sps.h + h264d_pps.h + h264d_scalist.h + h264d_sei.h + h264d_dpb.h + h264d_init.h + h264d_fill.h + + ) # h264 decoder sourse @@ -25,6 +35,16 @@ set(H264D_SRC h264d_log.c h264d_bitread.c h264d_parse.c + h264d_slice.c + h264d_sps.c + h264d_pps.c + h264d_scalist.c + h264d_sei.c + h264d_dpb.c + h264d_init.c + h264d_fill.c + + ) diff --git a/mpp/codec/dec/h264/h264d_api.c b/mpp/codec/dec/h264/h264d_api.c index 13f5cbcb..ff4bca44 100644 --- a/mpp/codec/dec/h264/h264d_api.c +++ b/mpp/codec/dec/h264/h264d_api.c @@ -23,43 +23,147 @@ #include "h264d_api.h" #include "h264d_global.h" #include "h264d_parse.h" +#include "h264d_sps.h" +#include "h264d_slice.h" +#include "h264d_dpb.h" #define MODULE_TAG "h264d_api" +static void close_log_files(LogEnv_t *env) +{ + FCLOSE(env->fp_syn_parse); + FCLOSE(env->fp_run_parse); +} + +static MPP_RET open_log_files(LogEnv_t *env, LogFlag_t *pflag) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + char fname[128] = { 0 }; + + INP_CHECK(ret, ctx, !pflag->write_en); + //!< runlog file + if (GetBitVal(env->ctrl, LOG_DEBUG_EN)) { + sprintf(fname, "%s/h264d_parse_runlog.dat", env->outpath); + FLE_CHECK(ret, env->fp_run_parse = fopen(fname, "wb")); + } + //!< read syntax + if ( GetBitVal(env->ctrl, LOG_READ_NALU ) + || GetBitVal(env->ctrl, LOG_READ_SPS ) + || GetBitVal(env->ctrl, LOG_READ_SUBSPS) + || GetBitVal(env->ctrl, LOG_READ_PPS ) + || GetBitVal(env->ctrl, LOG_READ_SLICE ) ) { + sprintf(fname, "%s/h264d_read_syntax.dat", env->outpath); + FLE_CHECK(ret, env->fp_syn_parse = fopen(fname, "wb")); + } +__RETURN: + return MPP_OK; + +__FAILED: + return ret; +} + +static MPP_RET logctx_deinit(H264dLogCtx_t *logctx) +{ + close_log_files(&logctx->env); + + return MPP_OK; +} + +static MPP_RET logctx_init(H264dLogCtx_t *logctx, LogCtx_t *logbuf) +{ + RK_U8 i = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + LogCtx_t *pcur = NULL; + + FUN_CHECK(ret = get_logenv(&logctx->env)); + if (logctx->env.help) { + print_env_help(&logctx->env); + } + if (logctx->env.show) { + show_env_flags(&logctx->env); + } + FUN_CHECK(ret = explain_ctrl_flag(logctx->env.ctrl, &logctx->log_flag)); + if ( !logctx->log_flag.debug_en + && !logctx->log_flag.print_en && !logctx->log_flag.write_en ) { + logctx->log_flag.debug_en = 0; + goto __RETURN; + } + logctx->log_flag.level = (1 << logctx->env.level) - 1; + //!< open file + FUN_CHECK(ret = open_log_files(&logctx->env, &logctx->log_flag)); + //!< set logctx + while (i < LOG_MAX) { + if (GetBitVal(logctx->env.ctrl, i)) { + pcur = logctx->parr[i] = &logbuf[i]; + pcur->tag = logctrl_name[i]; + pcur->flag = &logctx->log_flag; + + switch (i) { + case RUN_PARSE: + pcur->fp = logctx->env.fp_run_parse; + break; + break; + case LOG_WRITE_SPSPPS: + case LOG_WRITE_RPS: + case LOG_WRITE_SCANLIST: + case LOG_WRITE_STEAM: + case LOG_WRITE_REG: + pcur->fp = logctx->env.fp_syn_hal; + default: + break; + } + } + i++; + } + +__RETURN: + return ret = MPP_OK; +__FAILED: + logctx->log_flag.debug_en = 0; + logctx_deinit(logctx); + + return ret; +} static MPP_RET free_input_ctx(H264dInputCtx_t *p_Inp) { - INP_CHECK(!p_Inp); + MPP_RET ret = MPP_ERR_UNKNOW; + + INP_CHECK(ret, ctx, !p_Inp); FunctionIn(p_Inp->p_Dec->logctx.parr[RUN_PARSE]); (void)p_Inp; FunctionOut(p_Inp->p_Dec->logctx.parr[RUN_PARSE]); __RETURN: - return MPP_OK; + return ret = MPP_OK; } static MPP_RET init_input_ctx(H264dInputCtx_t *p_Inp, MppParserInitCfg *init) { - INP_CHECK(!p_Inp && !init); + MPP_RET ret = MPP_ERR_UNKNOW; + + INP_CHECK(ret, ctx, !p_Inp && !init); FunctionIn(p_Inp->p_Dec->logctx.parr[RUN_PARSE]); p_Inp->init = *init; FunctionOut(p_Inp->p_Dec->logctx.parr[RUN_PARSE]); __RETURN: - return MPP_OK; + return ret = MPP_OK; } static MPP_RET free_cur_ctx(H264dCurCtx_t *p_Cur) { - RK_U32 i = 0; - INP_CHECK(!p_Cur); + RK_U32 i = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + + INP_CHECK(ret, ctx, !p_Cur); FunctionIn(p_Cur->p_Dec->logctx.parr[RUN_PARSE]); if (p_Cur) { - //rkv_h264d_recycle_slice(p_Cur->slice); + recycle_slice(&p_Cur->slice); for (i = 0; i < 2; i++) { mpp_free(p_Cur->listP[i]); mpp_free(p_Cur->listB[i]); @@ -68,52 +172,70 @@ static MPP_RET free_cur_ctx(H264dCurCtx_t *p_Cur) } FunctionOut(p_Cur->p_Dec->logctx.parr[RUN_PARSE]); __RETURN: - return MPP_OK; + return ret = MPP_OK; } static MPP_RET init_cur_ctx(H264dCurCtx_t *p_Cur) { RK_U32 i = 0; - INP_CHECK(!p_Cur); - FunctionIn(p_Cur->p_Dec->logctx.parr[RUN_PARSE]); + MPP_RET ret = MPP_ERR_UNKNOW; - MEM_CHECK(p_Cur->strm.buf = mpp_malloc_size(RK_U8, NALU_BUF_MAX_SIZE)); + INP_CHECK(ret, ctx, !p_Cur); + FunctionIn(p_Cur->p_Dec->logctx.parr[RUN_PARSE]); + p_Cur->strm.buf = mpp_malloc_size(RK_U8, NALU_BUF_MAX_SIZE); + MEM_CHECK(ret, p_Cur->strm.buf); p_Cur->strm.max_size = NALU_BUF_MAX_SIZE; p_Cur->strm.prefixdata[0] = 0xff; p_Cur->strm.prefixdata[1] = 0xff; p_Cur->strm.prefixdata[2] = 0xff; for (i = 0; i < 2; i++) { - MEM_CHECK(p_Cur->listP[i] = mpp_malloc_size(H264_StorePic_t*, MAX_LIST_SIZE * sizeof(H264_StorePic_t*))); // +1 for reordering - MEM_CHECK(p_Cur->listB[i] = mpp_malloc_size(H264_StorePic_t*, MAX_LIST_SIZE * sizeof(H264_StorePic_t*))); // +1 for reordering + 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 } FunctionOut(p_Cur->p_Dec->logctx.parr[RUN_PARSE]); __RETURN: - return MPP_OK; + return ret = MPP_OK; __FAILED: free_cur_ctx(p_Cur); - return MPP_NOK; + return ret; } static MPP_RET free_vid_ctx(H264dVideoCtx_t *p_Vid) { - RK_U32 i = 0; - INP_CHECK(!p_Vid); - FunctionIn(p_Vid->p_Dec->logctx.parr[RUN_PARSE]); - for (i = 0; i < MAX_NUM_DPB_LAYERS; i++) { - mpp_free(p_Vid->p_Dpb_layer[i]); - } + RK_U32 i = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + + INP_CHECK(ret, ctx, !p_Vid); + FunctionIn(p_Vid->p_Dec->logctx.parr[RUN_PARSE]); + + for (i = 0; i < MAXSPS; i++) + { + recycle_subsps(&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->dec_picture); + //free_frame_store(&p_Vid->out_buffer); + FunctionOut(p_Vid->p_Dec->logctx.parr[RUN_PARSE]); __RETURN: - return MPP_OK; + return ret = MPP_OK; } static MPP_RET init_vid_ctx(H264dVideoCtx_t *p_Vid) { RK_U32 i = 0; - INP_CHECK(!p_Vid); + MPP_RET ret = MPP_ERR_UNKNOW; + + INP_CHECK(ret, ctx, !p_Vid); FunctionIn(p_Vid->p_Dec->logctx.parr[RUN_PARSE]); for (i = 0; i < MAX_NUM_DPB_LAYERS; i++) { - MEM_CHECK(p_Vid->p_Dpb_layer[i] = mpp_calloc(H264_DpbBuf_t, 1)); + 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; @@ -140,81 +262,88 @@ static MPP_RET init_vid_ctx(H264dVideoCtx_t *p_Vid) } FunctionOut(p_Vid->p_Dec->logctx.parr[RUN_PARSE]); __RETURN: - return MPP_OK; + return ret = MPP_OK; __FAILED: free_vid_ctx(p_Vid); - return MPP_NOK; + return ret; } static MPP_RET free_dxva_ctx(H264dDxvaCtx_t *p_dxva) { - INP_CHECK(!p_dxva); + MPP_RET ret = MPP_ERR_UNKNOW; + + INP_CHECK(ret, ctx, NULL == p_dxva); FunctionIn(p_dxva->p_Dec->logctx.parr[RUN_PARSE]); - mpp_free(p_dxva->slice_short); mpp_free(p_dxva->slice_long); mpp_free(p_dxva->bitstream); mpp_free(p_dxva->syn.buf); FunctionOut(p_dxva->p_Dec->logctx.parr[RUN_PARSE]); __RETURN: - return MPP_OK; + return ret = MPP_OK; } static MPP_RET init_dxva_ctx(H264dDxvaCtx_t *p_dxva) { - INP_CHECK(!p_dxva); + MPP_RET ret = MPP_ERR_UNKNOW; + + INP_CHECK(ret, ctx, !p_dxva); FunctionIn(p_dxva->p_Dec->logctx.parr[RUN_PARSE]); p_dxva->max_slice_size = MAX_SLICE_SIZE; - MEM_CHECK(p_dxva->slice_short = mpp_calloc(DXVA_Slice_H264_Short, p_dxva->max_slice_size)); - MEM_CHECK(p_dxva->slice_long = mpp_calloc(DXVA_Slice_H264_Long, p_dxva->max_slice_size)); - p_dxva->max_strm_size = FRAME_BUF_MAX_SIZE; - MEM_CHECK(p_dxva->bitstream = mpp_malloc(RK_U8, p_dxva->max_strm_size)); - MEM_CHECK(p_dxva->syn.buf = mpp_calloc(DXVA2_DecodeBufferDesc, SYNTAX_BUF_SIZE)); - + p_dxva->max_strm_size = FRAME_BUF_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); FunctionOut(p_dxva->p_Dec->logctx.parr[RUN_PARSE]); __RETURN: - return MPP_OK; + return ret = MPP_OK; __FAILED: - return MPP_NOK; + return ret; } static MPP_RET free_dec_ctx(H264_DecCtx_t *p_Dec) { RK_U32 i = 0; - INP_CHECK(!p_Dec); + MPP_RET ret = MPP_ERR_UNKNOW; + + INP_CHECK(ret, ctx, NULL == p_Dec); FunctionIn(p_Dec->logctx.parr[RUN_PARSE]); for (i = 0; i < MAX_TASK_SIZE; i++) { - free_dxva_ctx(&p_Dec->dxva_ctx[i]); + free_dxva_ctx(&p_Dec->mem->dxva_ctx[i]); } mpp_free(p_Dec->mem); FunctionOut(p_Dec->logctx.parr[RUN_PARSE]); __RETURN: - return MPP_OK; + return ret = MPP_OK; } static MPP_RET init_dec_ctx(H264_DecCtx_t *p_Dec) { RK_U32 i = 0; - INP_CHECK(!p_Dec); + MPP_RET ret = MPP_ERR_UNKNOW; + + INP_CHECK(ret, ctx, !p_Dec); FunctionIn(p_Dec->logctx.parr[RUN_PARSE]); - - MEM_CHECK(p_Dec->mem = mpp_calloc(H264_DecMem_t, 1)); - + 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[0] = p_Dec->mem->refpic_info[0]; //!< [2][32] p_Dec->refpic_info[1] = p_Dec->mem->refpic_info[1]; //!< [2][32] - p_Dec->dxva_ctx = p_Dec->mem->dxva_ctx; //!< MAX_TASK_SIZE - - for (i = 0; i < MAX_TASK_SIZE; i++) { - p_Dec->dxva_ctx[i].p_Dec = p_Dec; - FUN_CHECK(init_dxva_ctx(&p_Dec->dxva_ctx[i])); + //!< MAX_TASK_SIZE + for (i = 0; i < MAX_TASK_SIZE; i++) { + p_Dec->mem->dxva_ctx[i].p_Dec = p_Dec; + FUN_CHECK(ret = init_dxva_ctx(&p_Dec->mem->dxva_ctx[i])); } + p_Dec->dxva_idx = 0; + p_Dec->dxva_ctx = p_Dec->mem->dxva_ctx; //!< init Dpb_memory Mark for (i = 0; i < MAX_DPB_SIZE; i++) { p_Dec->dpb_mark[i].index = i; @@ -225,12 +354,12 @@ static MPP_RET init_dec_ctx(H264_DecCtx_t *p_Dec) p_Dec->nalu_ret = NALU_NULL; p_Dec->first_frame_flag = 1; __RETURN: - return MPP_OK; + return ret = MPP_OK; __FAILED: free_dec_ctx(p_Dec); - return MPP_NOK; + return ret; } @@ -245,15 +374,18 @@ __FAILED: MPP_RET h264d_init(void *decoder, MppParserInitCfg *init) { - MPP_RET ret = MPP_NOK; + MPP_RET ret = MPP_ERR_UNKNOW; H264_DecCtx_t *p_Dec = (H264_DecCtx_t *)decoder; - INP_CHECK(!p_Dec); + INP_CHECK(ret, ctx, !p_Dec); // init logctx - FUN_CHECK(ret = h264d_log_init(&p_Dec->logctx, p_Dec->logctxbuf)); + FUN_CHECK(ret = logctx_init(&p_Dec->logctx, p_Dec->logctxbuf)); FunctionIn(p_Dec->logctx.parr[RUN_PARSE]); - MEM_CHECK(p_Dec->p_Inp = mpp_calloc(H264dInputCtx_t, 1)); - MEM_CHECK(p_Dec->p_Cur = mpp_calloc(H264dCurCtx_t, 1)); - MEM_CHECK(p_Dec->p_Vid = mpp_calloc(H264dVideoCtx_t, 1)); + + 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; @@ -273,11 +405,11 @@ MPP_RET h264d_init(void *decoder, MppParserInitCfg *init) FunctionOut(p_Dec->logctx.parr[RUN_PARSE]); __RETURN: - return MPP_OK; + return ret = MPP_OK; __FAILED: h264d_deinit(decoder); - return MPP_NOK; + return ret; } /*! *********************************************************************** @@ -287,9 +419,10 @@ __FAILED: */ MPP_RET h264d_deinit(void *decoder) { + MPP_RET ret = MPP_ERR_UNKNOW; H264_DecCtx_t *p_Dec = (H264_DecCtx_t *)decoder; - INP_CHECK(!decoder); + INP_CHECK(ret, ctx, !decoder); FunctionIn(p_Dec->logctx.parr[RUN_PARSE]); free_input_ctx(p_Dec->p_Inp); @@ -301,9 +434,9 @@ MPP_RET h264d_deinit(void *decoder) free_dec_ctx(p_Dec); FunctionOut(p_Dec->logctx.parr[RUN_PARSE]); - h264d_log_deinit(&p_Dec->logctx); + logctx_deinit(&p_Dec->logctx); __RETURN: - return MPP_OK; + return ret = MPP_OK; } /*! *********************************************************************** @@ -313,11 +446,13 @@ __RETURN: */ MPP_RET h264d_reset(void *decoder) { - INP_CHECK(decoder); + MPP_RET ret = MPP_ERR_UNKNOW; + + INP_CHECK(ret, ctx, decoder); (void)decoder; __RETURN: - return MPP_OK; + return ret = MPP_OK; } /*! @@ -328,11 +463,13 @@ __RETURN: */ MPP_RET h264d_flush(void *decoder) { - INP_CHECK(decoder); + MPP_RET ret = MPP_ERR_UNKNOW; + + INP_CHECK(ret, ctx, decoder); (void)decoder; __RETURN: - return MPP_OK; + return ret = MPP_OK; } /*! @@ -343,7 +480,9 @@ __RETURN: */ MPP_RET h264d_control(void *decoder, RK_S32 cmd_type, void *param) { + MPP_RET ret = MPP_ERR_UNKNOW; + INP_CHECK(ret, ctx, decoder); (void)decoder; @@ -351,7 +490,8 @@ MPP_RET h264d_control(void *decoder, RK_S32 cmd_type, void *param) (void)param; - return MPP_OK; +__RETURN: + return ret = MPP_OK; } /*! @@ -362,28 +502,33 @@ MPP_RET h264d_control(void *decoder, RK_S32 cmd_type, void *param) */ MPP_RET h264d_parse(void *decoder, MppPacket in_pkt, HalDecTask *in_task) { + MPP_RET ret = MPP_ERR_UNKNOW; H264_DecCtx_t *p_Dec = (H264_DecCtx_t *)decoder; MppPacketImpl *pkt = (MppPacketImpl *)in_pkt; - INP_CHECK(!decoder && !in_pkt && !in_task); + + INP_CHECK(ret, ctx, !decoder && !in_pkt && !in_task); FunctionIn(p_Dec->logctx.parr[RUN_PARSE]); + p_Dec->p_Inp->in_buf = (RK_U8 *)pkt->pos; + p_Dec->p_Inp->in_size = &pkt->size; + p_Dec->p_Inp->is_eos = pkt->flag & MPP_PACKET_FLAG_EOS; - - - - - - pkt->size = (pkt->size >= 500) ? (pkt->size - 500) : 0; - - in_task->valid = pkt->size ? 0 : 1; - - - - + FUN_CHECK(ret = parse_loop(p_Dec)); + if (p_Dec->parser_end_flag) + { + in_task->valid = 1; + in_task->syntax.number = p_Dec->dxva_ctx->syn.num; + in_task->syntax.data = (void *)p_Dec->dxva_ctx->syn.buf; + FUN_CHECK(ret = update_dpb(p_Dec)); + p_Dec->dxva_idx = (p_Dec->dxva_idx + 1) % MAX_TASK_SIZE; + p_Dec->dxva_ctx = &p_Dec->mem->dxva_ctx[p_Dec->dxva_idx]; + } FunctionOut(p_Dec->logctx.parr[RUN_PARSE]); __RETURN: - return MPP_OK; + return ret = MPP_OK; +__FAILED: + return ret; } /*! diff --git a/mpp/codec/dec/h264/h264d_bitread.c b/mpp/codec/dec/h264/h264d_bitread.c index b4bf2d13..d7625892 100644 --- a/mpp/codec/dec/h264/h264d_bitread.c +++ b/mpp/codec/dec/h264/h264d_bitread.c @@ -22,9 +22,9 @@ static MPP_RET update_currbyte(BitReadCtx_t *bitctx) { - if (bitctx->bytes_left_ < 1) - return MPP_NOK; + MPP_RET ret = MPP_ERR_UNKNOW; + VAL_CHECK(ret, bitctx->bytes_left_ > 0); // Emulation prevention three-byte detection. // If a sequence of 0x000003 is found, skip (ignore) the last byte (0x03). if (*bitctx->data_ == 0x03 && (bitctx->prev_two_bytes_ & 0xffff) == 0) { @@ -34,19 +34,17 @@ static MPP_RET update_currbyte(BitReadCtx_t *bitctx) ++bitctx->emulation_prevention_bytes_; // Need another full three bytes before we can detect the sequence again. bitctx->prev_two_bytes_ = 0xffff; - - if (bitctx->bytes_left_ < 1) - return MPP_NOK; + VAL_CHECK(ret, bitctx->bytes_left_ > 0); } - // Load a new byte and advance pointers. bitctx->curr_byte_ = *bitctx->data_++ & 0xff; --bitctx->bytes_left_; bitctx->num_remaining_bits_in_curr_byte_ = 8; - bitctx->prev_two_bytes_ = (bitctx->prev_two_bytes_ << 8) | bitctx->curr_byte_; - return MPP_OK; + return ret = MPP_OK; +__FAILED: + return ret; } /*! @@ -60,12 +58,11 @@ static MPP_RET update_currbyte(BitReadCtx_t *bitctx) MPP_RET read_bits(BitReadCtx_t *bitctx, RK_S32 num_bits, RK_S32 *out) { - MPP_RET ret = MPP_NOK; + MPP_RET ret = MPP_ERR_UNKNOW; RK_S32 bits_left = num_bits; *out = 0; - ASSERT(num_bits <= 31); - + VAL_CHECK(ret, num_bits < 32); while (bitctx->num_remaining_bits_in_curr_byte_ < bits_left) { // Take all that's left in current byte, shift to make space for the rest. *out |= (bitctx->curr_byte_ << (bits_left - bitctx->num_remaining_bits_in_curr_byte_)); @@ -79,9 +76,9 @@ MPP_RET read_bits(BitReadCtx_t *bitctx, RK_S32 num_bits, RK_S32 *out) bitctx->num_remaining_bits_in_curr_byte_ -= bits_left; bitctx->used_bits += num_bits; - return MPP_OK; + return ret = MPP_OK; __FAILED: - return ret; + return ret = MPP_ERR_READ_BIT; } /*! *********************************************************************** @@ -101,17 +98,17 @@ MPP_RET read_one_bit(BitReadCtx_t *bitctx, RK_S32 *out) */ MPP_RET read_ue(BitReadCtx_t *bitctx, RK_U32 *val) { - MPP_RET ret = MPP_NOK; RK_S32 num_bits = -1; RK_S32 bit; RK_S32 rest; + MPP_RET ret = MPP_ERR_UNKNOW; // Count the number of contiguous zero bits. do { FUN_CHECK(ret = read_bits(bitctx, 1, &bit)); num_bits++; } while (bit == 0); - VAL_CHECK(num_bits < 32); + VAL_CHECK(ret, num_bits < 32); // Calculate exp-Golomb code value of size num_bits. *val = (1 << num_bits) - 1; @@ -120,9 +117,9 @@ MPP_RET read_ue(BitReadCtx_t *bitctx, RK_U32 *val) *val += rest; } - return MPP_OK; + return ret = MPP_OK; __FAILED: - return ret; + return ret = MPP_ERR_READ_BIT; } /*! *********************************************************************** @@ -132,8 +129,9 @@ __FAILED: */ MPP_RET read_se(BitReadCtx_t *bitctx, RK_S32 *val) { - MPP_RET ret = MPP_NOK; - RK_U32 ue; + RK_U32 ue; + MPP_RET ret = MPP_ERR_UNKNOW; + FUN_CHECK(ret = read_ue(bitctx, &ue)); if (ue % 2 == 0) { // odd @@ -142,9 +140,9 @@ MPP_RET read_se(BitReadCtx_t *bitctx, RK_S32 *val) *val = (RK_S32)((ue >> 1) + 1); } - return MPP_OK; + return ret = MPP_OK; __FAILED: - return ret; + return ret = MPP_ERR_READ_BIT; } /*! diff --git a/mpp/codec/dec/h264/h264d_bitread.h b/mpp/codec/dec/h264/h264d_bitread.h index f1dd8972..83650e24 100644 --- a/mpp/codec/dec/h264/h264d_bitread.h +++ b/mpp/codec/dec/h264/h264d_bitread.h @@ -23,66 +23,59 @@ #include "mpp_err.h" #include "h264d_log.h" +#define __BITREAD_ERR __bitread_error #define WRITE_LOG(bitctx, name)\ do {\ - LogInfo(bitctx->ctx, "%s", name);\ - } while (0) + LogInfo(bitctx->ctx, "%s", name);\ + } while (0) -#define SKIP_BITS(bitctx, num_bits)\ +#define SKIP_BITS(ret, bitctx, num_bits)\ do {\ - RK_S32 _out;\ - MPP_RET ret = MPP_NOK;\ - ret = read_bits(bitctx, num_bits, &_out);\ - LogInfo(bitctx->ctx, "%48s = %10d", "skip", _out);\ - if (ret) { ASSERT(0); goto __FAILED; }\ - } while (0) + RK_S32 _out;\ + ret = read_bits(bitctx, num_bits, &_out);\ + LogInfo(bitctx->ctx, "%48s = %10d", "skip", _out);\ + if (ret) { ASSERT(0); goto __FAILED; }\ + } while (0) -#define READ_BITS(bitctx, num_bits, out, name)\ +#define READ_BITS(ret, bitctx, num_bits, out, name)\ do {\ - RK_S32 _out;\ - MPP_RET ret = MPP_NOK;\ - ret = read_bits(bitctx, num_bits, &_out);\ - LogInfo(bitctx->ctx, "%48s = %10d", name, _out);\ - if (ret) { ASSERT(0); goto __FAILED; }\ - else { *out = _out; }\ - } while (0) + ret = read_bits(bitctx, num_bits, (RK_S32 *)out);\ + LogInfo(bitctx->ctx, "%48s = %10d", name, *out);\ + if (ret) { ASSERT(0); goto __FAILED; }\ + } while (0) - -#define READ_ONEBIT(bitctx, out, name)\ +#define READ_ONEBIT(ret, bitctx, out, name)\ do {\ - RK_S32 _out;\ - MPP_RET ret = MPP_NOK;\ - ret = read_bits(bitctx, 1, &_out);\ - LogInfo(bitctx->ctx, "%48s = %10d", name, _out);\ - if (ret) { ASSERT(0); goto __FAILED; }\ - else { *out = _out; }\ + ret = read_bits(bitctx, 1, (RK_S32 *)out);\ + LogInfo(bitctx->ctx, "%48s = %10d", name, *out);\ + if (ret) { ASSERT(0); goto __FAILED; }\ } while (0) -#define READ_UE(bitctx, out, name)\ +#define READ_UE(ret, bitctx, out, name)\ do {\ - RK_U32 _out;\ - MPP_RET ret = MPP_NOK;\ - ret = read_ue(bitctx, &_out);\ - LogInfo(bitctx->ctx, "%48s = %10d", name, _out);\ - if (ret) { ASSERT(0); goto __FAILED; }\ - else { *out = _out; }\ - } while (0) + ret = read_ue(bitctx, (RK_U32 *)out);\ + LogInfo(bitctx->ctx, "%48s = %10d", name, *out);\ + if (ret) { ASSERT(0); goto __FAILED; }\ + } while (0) -#define READ_SE(bitctx, out, name)\ +#define READ_SE(ret, bitctx, out, name)\ do {\ - RK_S32 _out;\ - MPP_RET ret = MPP_NOK;\ - ret = read_se(bitctx, &_out);\ - LogInfo(bitctx->ctx, "%48s = %10d", name, _out);\ - if (ret) { ASSERT(0); goto __FAILED; }\ - else { *out = _out; }\ - } while (0) - + ret = read_se(bitctx, (RK_S32 *)out);\ + LogInfo(bitctx->ctx, "%48s = %10d", name, *out);\ + if (ret) { ASSERT(0); goto __FAILED; }\ + } while (0) +#define CHECK_RANGE(ret, bitctx, val, _min, _max)\ + do {\ + if ((val) < (_min) || (val) > (_max)) {\ + LogError(bitctx->ctx, "%d[%d,%d]", val, _min, _max);\ + ret = MPP_ERR_VALUE;\ + ASSERT(0); goto __FAILED;\ + } } while (0) typedef struct getbit_ctx_t { @@ -113,7 +106,7 @@ typedef struct getbit_ctx_t { extern "C" { #endif -MPP_RET read_bits(BitReadCtx_t *bitctx, RK_S32 num_bits, RK_S32 *out); +MPP_RET read_bits( BitReadCtx_t *bitctx, RK_S32 num_bits, RK_S32 *out); MPP_RET read_one_bit(BitReadCtx_t *bitctx, RK_S32 *out); MPP_RET read_ue(BitReadCtx_t *bitctx, RK_U32* val); MPP_RET read_se(BitReadCtx_t *bitctx, RK_S32* val); diff --git a/mpp/codec/dec/h264/h264d_dpb.c b/mpp/codec/dec/h264/h264d_dpb.c new file mode 100644 index 00000000..02760350 --- /dev/null +++ b/mpp/codec/dec/h264/h264d_dpb.c @@ -0,0 +1,2332 @@ +/* +* +* 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. +*/ + +#include +#include + +#include "mpp_mem.h" + +#include "h264d_log.h" +#include "h264d_scalist.h" + + +#include "h264d_dpb.h" + + + +#define MODULE_TAG "h264d_dpb" + + + +#define INT_MIN (-2147483647 - 1) /* minimum (signed) int value */ +#define INT_MAX 2147483647 /* maximum (signed) int value */ + +static RK_S32 RoundLog2(RK_S32 iValue) +{ + RK_S32 iRet = 0; + RK_S32 iValue_square = iValue * iValue; + + while ((1 << (iRet + 1)) <= iValue_square){ + ++iRet; + } + iRet = (iRet + 1) >> 1; + + return iRet; +} + +static RK_S32 getDpbSize(H264dVideoCtx_t *p_Vid, H264_SPS_t *active_sps) +{ + RK_S32 size = 0, num_views = 0; + RK_S32 pic_size = (active_sps->pic_width_in_mbs_minus1 + 1) + *(active_sps->pic_height_in_map_units_minus1 + 1) * (active_sps->frame_mbs_only_flag ? 1 : 2) * 384; + + switch (active_sps->level_idc) + { + case 9: + size = 152064; + break; + case 10: + size = 152064; + break; + case 11: + if (!is_prext_profile(active_sps->profile_idc) && (active_sps->constrained_set3_flag == 1)) + size = 152064; + else + size = 345600; + break; + case 12: + size = 912384; + break; + case 13: + size = 912384; + break; + case 20: + size = 912384; + break; + case 21: + size = 1824768; + break; + case 22: + size = 3110400; + break; + case 30: + size = 3110400; + break; + case 31: + size = 6912000; + break; + case 32: + size = 7864320; + break; + case 40: + size = 12582912; + break; + case 41: + size = 12582912; + break; + case 42: + size = 13369344; + break; + case 50: + size = 42393600; + break; + case 51: + size = 70778880; + break; + case 52: + size = 70778880; + break; + default: + ASSERT(0); + break; + } + size /= pic_size; + if (p_Vid->active_mvc_sps_flag && + (p_Vid->profile_idc == MVC_HIGH || p_Vid->profile_idc == STEREO_HIGH)) + { + num_views = p_Vid->active_subsps->num_views_minus1 + 1; + size = min(2 * size, max(1, RoundLog2(num_views)) * 16) / num_views; + } + else + { + size = min(size, 16); + } + + return size; +} + +static RK_S32 get_pic_num_x(H264_StorePic_t *p, RK_S32 difference_of_pic_nums_minus1) +{ + RK_S32 currPicNum; + + if (p->structure == FRAME) + currPicNum = p->frame_num; + else + currPicNum = 2 * p->frame_num + 1; + + return currPicNum - (difference_of_pic_nums_minus1 + 1); +} + +static void unmark_for_reference(H264_FrameStore_t* fs) +{ + if (fs->is_used & 1) + { + if (fs->top_field) + { + fs->top_field->used_for_reference = 0; + } + } + if (fs->is_used & 2) + { + if (fs->bottom_field) + { + fs->bottom_field->used_for_reference = 0; + } + } + if (fs->is_used == 3) + { + if (fs->top_field && fs->bottom_field) + { + fs->top_field->used_for_reference = 0; + fs->bottom_field->used_for_reference = 0; + } + fs->frame->used_for_reference = 0; + } + fs->is_reference = 0; +} + +static RK_U32 is_short_term_reference(H264_FrameStore_t* fs) +{ + if (fs->is_used == 3) // frame + { + if ((fs->frame->used_for_reference) && (!fs->frame->is_long_term)) + { + return 1; + } + } + + if (fs->is_used & 1) // top field + { + if (fs->top_field) + { + if ((fs->top_field->used_for_reference) && (!fs->top_field->is_long_term)) + { + return 1; + } + } + } + + if (fs->is_used & 2) // bottom field + { + if (fs->bottom_field) + { + if ((fs->bottom_field->used_for_reference) && (!fs->bottom_field->is_long_term)) + { + return 1; + } + } + } + return 0; +} + +static RK_U32 is_long_term_reference(H264_FrameStore_t* fs) +{ + + if (fs->is_used == 3) // frame + { + if ((fs->frame->used_for_reference) && (fs->frame->is_long_term)) + { + return 1; + } + } + + if (fs->is_used & 1) // top field + { + if (fs->top_field) + { + if ((fs->top_field->used_for_reference) && (fs->top_field->is_long_term)) + { + return 1; + } + } + } + + if (fs->is_used & 2) // bottom field + { + if (fs->bottom_field) + { + if ((fs->bottom_field->used_for_reference) && (fs->bottom_field->is_long_term)) + { + return 1; + } + } + } + return 0; +} + +static void unmark_for_long_term_reference(H264_FrameStore_t* fs) +{ + if (fs->is_used & 1) + { + if (fs->top_field) + { + fs->top_field->used_for_reference = 0; + fs->top_field->is_long_term = 0; + } + } + if (fs->is_used & 2) + { + if (fs->bottom_field) + { + fs->bottom_field->used_for_reference = 0; + fs->bottom_field->is_long_term = 0; + } + } + if (fs->is_used == 3) + { + if (fs->top_field && fs->bottom_field) + { + fs->top_field->used_for_reference = 0; + fs->top_field->is_long_term = 0; + fs->bottom_field->used_for_reference = 0; + fs->bottom_field->is_long_term = 0; + } + fs->frame->used_for_reference = 0; + fs->frame->is_long_term = 0; + } + + fs->is_reference = 0; + fs->is_long_term = 0; +} + +static void mm_unmark_short_term_for_reference(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p, RK_S32 difference_of_pic_nums_minus1) +{ + RK_S32 picNumX = 0; + RK_U32 i = 0; + + picNumX = get_pic_num_x(p, difference_of_pic_nums_minus1); + + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) + { + if (p->structure == FRAME) + { + if ((p_Dpb->fs_ref[i]->is_reference == 3) && (p_Dpb->fs_ref[i]->is_long_term == 0)) + { + if (p_Dpb->fs_ref[i]->frame->pic_num == picNumX) + { + unmark_for_reference(p_Dpb->fs_ref[i]); + return; + } + } + } + else + { + if ((p_Dpb->fs_ref[i]->is_reference & 1) && (!(p_Dpb->fs_ref[i]->is_long_term & 1))) + { + if (p_Dpb->fs_ref[i]->top_field->pic_num == picNumX) + { + p_Dpb->fs_ref[i]->top_field->used_for_reference = 0; + p_Dpb->fs_ref[i]->is_reference &= 2; + if (p_Dpb->fs_ref[i]->is_used == 3) + { + p_Dpb->fs_ref[i]->frame->used_for_reference = 0; + } + return; + } + } + if ((p_Dpb->fs_ref[i]->is_reference & 2) && (!(p_Dpb->fs_ref[i]->is_long_term & 2))) + { + if (p_Dpb->fs_ref[i]->bottom_field->pic_num == picNumX) + { + p_Dpb->fs_ref[i]->bottom_field->used_for_reference = 0; + p_Dpb->fs_ref[i]->is_reference &= 1; + if (p_Dpb->fs_ref[i]->is_used == 3) + { + p_Dpb->fs_ref[i]->frame->used_for_reference = 0; + } + return; + } + } + } + } +} + +static void mm_unmark_long_term_for_reference(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p, RK_S32 long_term_pic_num) +{ + RK_U32 i = 0; + + for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) + { + if (p->structure == FRAME) + { + if ((p_Dpb->fs_ltref[i]->is_reference == 3) && (p_Dpb->fs_ltref[i]->is_long_term == 3)) + { + if (p_Dpb->fs_ltref[i]->frame->long_term_pic_num == long_term_pic_num) + { + unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); + } + } + } + else + { + if ((p_Dpb->fs_ltref[i]->is_reference & 1) && ((p_Dpb->fs_ltref[i]->is_long_term & 1))) + { + if (p_Dpb->fs_ltref[i]->top_field->long_term_pic_num == long_term_pic_num) + { + p_Dpb->fs_ltref[i]->top_field->used_for_reference = 0; + p_Dpb->fs_ltref[i]->top_field->is_long_term = 0; + p_Dpb->fs_ltref[i]->is_reference &= 2; + p_Dpb->fs_ltref[i]->is_long_term &= 2; + if (p_Dpb->fs_ltref[i]->is_used == 3) + { + p_Dpb->fs_ltref[i]->frame->used_for_reference = 0; + p_Dpb->fs_ltref[i]->frame->is_long_term = 0; + } + return; + } + } + if ((p_Dpb->fs_ltref[i]->is_reference & 2) && ((p_Dpb->fs_ltref[i]->is_long_term & 2))) + { + if (p_Dpb->fs_ltref[i]->bottom_field->long_term_pic_num == long_term_pic_num) + { + p_Dpb->fs_ltref[i]->bottom_field->used_for_reference = 0; + p_Dpb->fs_ltref[i]->bottom_field->is_long_term = 0; + p_Dpb->fs_ltref[i]->is_reference &= 1; + p_Dpb->fs_ltref[i]->is_long_term &= 1; + if (p_Dpb->fs_ltref[i]->is_used == 3) + { + p_Dpb->fs_ltref[i]->frame->used_for_reference = 0; + p_Dpb->fs_ltref[i]->frame->is_long_term = 0; + } + return; + } + } + } + } +} + +static void unmark_long_term_frame_for_reference_by_frame_idx(H264_DpbBuf_t *p_Dpb, RK_S32 long_term_frame_idx) +{ + RK_U32 i = 0; + for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) + { + if (p_Dpb->fs_ltref[i]->long_term_frame_idx == long_term_frame_idx) + { + unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); + } + } +} + +static MPP_RET unmark_long_term_field_for_reference_by_frame_idx(H264_DpbBuf_t *p_Dpb, PictureStructure structure, + RK_S32 long_term_frame_idx, RK_S32 mark_current, RK_U32 curr_frame_num, RK_S32 curr_pic_num) +{ + RK_U8 i = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + H264dVideoCtx_t *p_Vid = p_Dpb->p_Vid; + + VAL_CHECK(ret, structure != FRAME); + if (curr_pic_num < 0) + curr_pic_num += (2 * p_Vid->max_frame_num); + + for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) + { + if (p_Dpb->fs_ltref[i]->long_term_frame_idx == long_term_frame_idx) + { + if (structure == TOP_FIELD) + { + if (p_Dpb->fs_ltref[i]->is_long_term == 3) + { + unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); + } + else + { + if (p_Dpb->fs_ltref[i]->is_long_term == 1) + { + unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); + } + else + { + if (mark_current) + { + if (p_Dpb->last_picture) + { + if ((p_Dpb->last_picture != p_Dpb->fs_ltref[i]) || p_Dpb->last_picture->frame_num != curr_frame_num) + unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); + } + else + { + unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); + } + } + else + { + if ((p_Dpb->fs_ltref[i]->frame_num) != (unsigned)(curr_pic_num >> 1)) + { + unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); + } + } + } + } + } + if (structure == BOTTOM_FIELD) + { + if (p_Dpb->fs_ltref[i]->is_long_term == 3) + { + unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); + } + else + { + if (p_Dpb->fs_ltref[i]->is_long_term == 2) + { + unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); + } + else + { + if (mark_current) + { + if (p_Dpb->last_picture) + { + if ((p_Dpb->last_picture != p_Dpb->fs_ltref[i]) || p_Dpb->last_picture->frame_num != curr_frame_num) + unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); + } + else + { + unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); + } + } + else + { + if ((p_Dpb->fs_ltref[i]->frame_num) != (unsigned)(curr_pic_num >> 1)) + { + unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); + } + } + } + } + } + } + } + return ret = MPP_OK; +__FAILED: + return ret; +} + +static void mark_pic_long_term(H264_DpbBuf_t *p_Dpb, H264_StorePic_t* p, RK_S32 long_term_frame_idx, RK_S32 picNumX) +{ + RK_U32 i = 0; + RK_S32 add_top = 0, add_bottom = 0; + LogCtx_t *runlog = p_Dpb->p_Vid->p_Dec->logctx.parr[RUN_PARSE]; + + if (p->structure == FRAME) + { + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) + { + if (p_Dpb->fs_ref[i]->is_reference == 3) + { + if ((!p_Dpb->fs_ref[i]->frame->is_long_term) && (p_Dpb->fs_ref[i]->frame->pic_num == picNumX)) + { + p_Dpb->fs_ref[i]->long_term_frame_idx = p_Dpb->fs_ref[i]->frame->long_term_frame_idx = long_term_frame_idx; + p_Dpb->fs_ref[i]->frame->long_term_pic_num = long_term_frame_idx; + p_Dpb->fs_ref[i]->frame->is_long_term = 1; + + if (p_Dpb->fs_ref[i]->top_field && p_Dpb->fs_ref[i]->bottom_field) + { + p_Dpb->fs_ref[i]->top_field->long_term_frame_idx = p_Dpb->fs_ref[i]->bottom_field->long_term_frame_idx = long_term_frame_idx; + p_Dpb->fs_ref[i]->top_field->long_term_pic_num = long_term_frame_idx; + p_Dpb->fs_ref[i]->bottom_field->long_term_pic_num = long_term_frame_idx; + p_Dpb->fs_ref[i]->top_field->is_long_term = p_Dpb->fs_ref[i]->bottom_field->is_long_term = 1; + } + p_Dpb->fs_ref[i]->is_long_term = 3; + return; + } + } + } + LogWarnning(runlog, "reference frame for long term marking not found."); + } + else + { + if (p->structure == TOP_FIELD) + { + add_top = 1; + add_bottom = 0; + } + else + { + add_top = 0; + add_bottom = 1; + } + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) + { + if (p_Dpb->fs_ref[i]->is_reference & 1) + { + if ((!p_Dpb->fs_ref[i]->top_field->is_long_term) && (p_Dpb->fs_ref[i]->top_field->pic_num == picNumX)) + { + if ((p_Dpb->fs_ref[i]->is_long_term) && (p_Dpb->fs_ref[i]->long_term_frame_idx != long_term_frame_idx)) + { + LogWarnning(runlog, "assigning long_term_frame_idx different from other field."); + } + p_Dpb->fs_ref[i]->long_term_frame_idx = p_Dpb->fs_ref[i]->top_field->long_term_frame_idx = long_term_frame_idx; + p_Dpb->fs_ref[i]->top_field->long_term_pic_num = 2 * long_term_frame_idx + add_top; + p_Dpb->fs_ref[i]->top_field->is_long_term = 1; + p_Dpb->fs_ref[i]->is_long_term |= 1; + if (p_Dpb->fs_ref[i]->is_long_term == 3) + { + p_Dpb->fs_ref[i]->frame->is_long_term = 1; + p_Dpb->fs_ref[i]->frame->long_term_frame_idx = p_Dpb->fs_ref[i]->frame->long_term_pic_num = long_term_frame_idx; + } + return; + } + } + if (p_Dpb->fs_ref[i]->is_reference & 2) + { + if ((!p_Dpb->fs_ref[i]->bottom_field->is_long_term) && (p_Dpb->fs_ref[i]->bottom_field->pic_num == picNumX)) + { + if ((p_Dpb->fs_ref[i]->is_long_term) && (p_Dpb->fs_ref[i]->long_term_frame_idx != long_term_frame_idx)) + { + LogWarnning(runlog, "assigning long_term_frame_idx different from other field."); + } + + p_Dpb->fs_ref[i]->long_term_frame_idx = p_Dpb->fs_ref[i]->bottom_field->long_term_frame_idx + = long_term_frame_idx; + p_Dpb->fs_ref[i]->bottom_field->long_term_pic_num = 2 * long_term_frame_idx + add_bottom; + p_Dpb->fs_ref[i]->bottom_field->is_long_term = 1; + p_Dpb->fs_ref[i]->is_long_term |= 2; + if (p_Dpb->fs_ref[i]->is_long_term == 3) + { + p_Dpb->fs_ref[i]->frame->is_long_term = 1; + p_Dpb->fs_ref[i]->frame->long_term_frame_idx = p_Dpb->fs_ref[i]->frame->long_term_pic_num = long_term_frame_idx; + } + return; + } + } + } + LogWarnning(runlog, "reference field for long term marking not found."); + } +} + +static MPP_RET mm_assign_long_term_frame_idx(H264_DpbBuf_t *p_Dpb, H264_StorePic_t* p, RK_S32 difference_of_pic_nums_minus1, RK_S32 long_term_frame_idx) +{ + RK_S32 picNumX = 0; + RK_U32 i = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + + picNumX = get_pic_num_x(p, difference_of_pic_nums_minus1); + //!< remove frames/fields with same long_term_frame_idx + if (p->structure == FRAME) + { + unmark_long_term_frame_for_reference_by_frame_idx(p_Dpb, long_term_frame_idx); + } + else + { + PictureStructure structure = FRAME; + + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) + { + if (p_Dpb->fs_ref[i]->is_reference & 1) + { + if (p_Dpb->fs_ref[i]->top_field->pic_num == picNumX) + { + structure = TOP_FIELD; + break; + } + } + if (p_Dpb->fs_ref[i]->is_reference & 2) + { + if (p_Dpb->fs_ref[i]->bottom_field->pic_num == picNumX) + { + structure = BOTTOM_FIELD; + break; + } + } + } + VAL_CHECK(ret,structure != FRAME); + FUN_CHECK(ret = unmark_long_term_field_for_reference_by_frame_idx(p_Dpb, structure, long_term_frame_idx, 0, 0, picNumX)); + } + mark_pic_long_term(p_Dpb, p, long_term_frame_idx, picNumX); + + return ret = MPP_OK; +__FAILED: + ASSERT(0); + return ret; +} + +static void mm_update_max_long_term_frame_idx(H264_DpbBuf_t *p_Dpb, RK_S32 max_long_term_frame_idx_plus1) +{ + RK_U32 i = 0; + + p_Dpb->max_long_term_pic_idx = max_long_term_frame_idx_plus1 - 1; + + // check for invalid frames + for (i = 0; iltref_frames_in_buffer; i++) + { + if (p_Dpb->fs_ltref[i]->long_term_frame_idx > p_Dpb->max_long_term_pic_idx) + { + unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); + } + } +} + +static void mm_unmark_all_short_term_for_reference(H264_DpbBuf_t *p_Dpb) +{ + RK_U32 i = 0; + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) + { + unmark_for_reference(p_Dpb->fs_ref[i]); + } + update_ref_list(p_Dpb); +} + +static void mm_unmark_all_long_term_for_reference(H264_DpbBuf_t *p_Dpb) +{ + mm_update_max_long_term_frame_idx(p_Dpb, 0); +} + +static void mm_mark_current_picture_long_term(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p, RK_S32 long_term_frame_idx) +{ + // remove long term pictures with same long_term_frame_idx + if (p->structure == FRAME) + { + unmark_long_term_frame_for_reference_by_frame_idx(p_Dpb, long_term_frame_idx); + } + else + { + unmark_long_term_field_for_reference_by_frame_idx(p_Dpb, p->structure, long_term_frame_idx, 1, p->pic_num, 0); + } + + p->is_long_term = 1; + p->long_term_frame_idx = long_term_frame_idx; +} + +static void sliding_window_memory_management(H264_DpbBuf_t *p_Dpb, H264_StorePic_t* p) +{ + RK_U32 i = 0; + + // if this is a reference pic with sliding window, unmark first ref frame + if (p_Dpb->ref_frames_in_buffer == max(1, p_Dpb->num_ref_frames) - p_Dpb->ltref_frames_in_buffer) + { + for (i = 0; i < p_Dpb->used_size; i++) + { + if (p_Dpb->fs[i]->is_reference && (!(p_Dpb->fs[i]->is_long_term))) + { + unmark_for_reference(p_Dpb->fs[i]); + update_ref_list(p_Dpb); + break; + } + } + } + (void)p; +} + +static void check_num_ref(H264_DpbBuf_t *p_Dpb) +{ + LogCtx_t *runlog = p_Dpb->p_Vid->p_Dec->logctx.parr[RUN_PARSE]; + + if ((RK_S32)(p_Dpb->ltref_frames_in_buffer + p_Dpb->ref_frames_in_buffer) > max(1, p_Dpb->num_ref_frames)) + { + if ((RK_S32)(p_Dpb->ltref_frames_in_buffer + p_Dpb->ref_frames_in_buffer) > max(1, p_Dpb->num_ref_frames)) + { + sliding_window_memory_management(p_Dpb, NULL); + LogWarnning(runlog, "Max number of reference frames exceeded"); + } + } +} + +static RK_U32 is_used_for_reference(H264_FrameStore_t* fs) +{ + RK_U8 is_used_flag = 0; + + if (fs->is_reference) + { + return is_used_flag = 1; + } + + if (fs->is_used == 3) // frame + { + if (fs->frame->used_for_reference) + { + return is_used_flag = 1; + } + } + + if (fs->is_used & 1) // top field + { + if (fs->top_field) + { + if (fs->top_field->used_for_reference) + { + return is_used_flag = 1; + } + } + } + + if (fs->is_used & 2) // bottom field + { + if (fs->bottom_field) + { + if (fs->bottom_field->used_for_reference) + { + return is_used_flag = 1; + } + } + } + return is_used_flag = 0; +} + +static void free_dpb_memory_index(H264_DpbMark_t *p, RK_S32 structure, RK_U8 layer_id) +{ + if (structure == FRAME) + { + p->top_used = (p->top_used > 0) ? (p->top_used - 1) : 0; + p->bot_used = (p->bot_used > 0) ? (p->bot_used - 1) : 0; + } + else if (structure == TOP_FIELD) + { + p->top_used = (p->top_used > 0) ? (p->top_used - 1) : 0; + } + else if (structure == BOTTOM_FIELD) + { + p->bot_used = (p->bot_used > 0) ? (p->bot_used - 1) : 0; + } + (void)layer_id; +} + +static MPP_RET remove_frame_from_dpb(H264_DpbBuf_t *p_Dpb, RK_S32 pos) +{ + RK_U32 i = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + H264_FrameStore_t* fs = p_Dpb->fs[pos]; + H264_FrameStore_t* tmp = NULL; + LogCtx_t *runlog = p_Dpb->p_Vid->p_Dec->logctx.parr[RUN_PARSE]; + + switch (fs->is_used) + { + case 3: + if (fs->frame) free_storable_picture(fs->frame); + if (fs->top_field) free_storable_picture(fs->top_field); + if (fs->bottom_field) free_storable_picture(fs->bottom_field); + fs->frame = NULL; + fs->top_field = NULL; + fs->bottom_field = NULL; + break; + case 2: + if (fs->bottom_field) free_storable_picture(fs->bottom_field); + fs->bottom_field = NULL; + break; + case 1: + if (fs->top_field) free_storable_picture(fs->top_field); + fs->top_field = NULL; + break; + case 0: + break; + default: + LogError(runlog, "invalid frame store type."); + goto __FAILED; + } + fs->is_used = 0; + fs->is_long_term = 0; + fs->is_reference = 0; + fs->is_orig_reference = 0; + + // move empty framestore to end of buffer + tmp = p_Dpb->fs[pos]; + + for (i = pos; i < p_Dpb->used_size - 1; i++) + { + p_Dpb->fs[i] = p_Dpb->fs[i + 1]; + } + p_Dpb->fs[p_Dpb->used_size - 1] = tmp; + p_Dpb->used_size--; + + return ret = MPP_OK; +__FAILED: + ASSERT(0); + return ret = MPP_NOK; +} + +static MPP_RET remove_unused_frame_from_dpb(H264_DpbBuf_t *p_Dpb) +{ + RK_U32 i = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + // check for frames that were already output and no longer used for reference + for (i = 0; i < p_Dpb->used_size; i++) + { + if (p_Dpb->fs[i]->is_output && (!is_used_for_reference(p_Dpb->fs[i]))) + { + FUN_CHECK(ret = remove_frame_from_dpb(p_Dpb, i)); + return MPP_OK; + } + } +__FAILED: + return ret; +} + +static MPP_RET get_smallest_poc(H264_DpbBuf_t *p_Dpb, RK_S32 *poc, RK_S32 *pos) +{ + RK_U32 i = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + + VAL_CHECK(ret, p_Dpb->used_size > 0); //!< "Cannot determine smallest POC, DPB empty." + *pos = -1; + *poc = INT_MAX; + for (i = 0; i < p_Dpb->used_size; i++) + { + if ((*poc > p_Dpb->fs[i]->poc) && (!p_Dpb->fs[i]->is_output)) + { + *poc = p_Dpb->fs[i]->poc; + *pos = i; + } + } + + return ret = MPP_OK; +__FAILED: + ASSERT(0); + return ret; +} + +static H264_FrameStore_t *alloc_frame_store() +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264_FrameStore_t *f = mpp_calloc(H264_FrameStore_t, 1); + MEM_CHECK(ret, f); + + f->is_used = 0; + f->is_reference = 0; + f->is_long_term = 0; + f->is_orig_reference = 0; + f->is_output = 0; + + f->frame = NULL; + f->top_field = NULL; + f->bottom_field = NULL; + + return f; +__FAILED: + (void)ret; + return NULL; +} + +static MPP_RET dpb_combine_field_yuv(H264dVideoCtx_t *p_Vid, H264_FrameStore_t *fs, RK_U8 combine_flag) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + if (!fs->frame) + { + fs->frame = alloc_storable_picture(p_Vid, FRAME); + MEM_CHECK(ret, fs->frame); + ASSERT(fs->top_field->colmv_no_used_flag == fs->bottom_field->colmv_no_used_flag); + fs->frame->colmv_no_used_flag = fs->top_field->colmv_no_used_flag; + if (combine_flag) + { + ASSERT(fs->top_field->mem_mark->index = fs->bottom_field->mem_mark->index); + fs->frame->mem_malloc_type = fs->top_field->mem_malloc_type; + fs->frame->mem_mark = fs->top_field->mem_mark; + } + else if (fs->is_used == 0x1) // unpaired, have top + { + ASSERT(fs->bottom_field->mem_malloc_type == Mem_UnPaired); + fs->frame->mem_mark = fs->top_field->mem_mark; + } + else if (fs->is_used == 0x02) // unpaired, have bottom + { + ASSERT(fs->top_field->mem_malloc_type == Mem_UnPaired); + fs->frame->mem_mark = fs->bottom_field->mem_mark; + } + else + { + ASSERT(fs->is_used == 0x03); + } + } + fs->poc = fs->frame->poc = fs->frame->frame_poc = min(fs->top_field->poc, fs->bottom_field->poc); + fs->bottom_field->frame_poc = fs->top_field->frame_poc = fs->frame->poc; + fs->bottom_field->top_poc = fs->frame->top_poc = fs->top_field->poc; + fs->top_field->bottom_poc = fs->frame->bottom_poc = fs->bottom_field->poc; + fs->frame->used_for_reference = (fs->top_field->used_for_reference && fs->bottom_field->used_for_reference); + fs->frame->is_long_term = (fs->top_field->is_long_term && fs->bottom_field->is_long_term); + if (fs->frame->is_long_term) + { + fs->frame->long_term_frame_idx = fs->long_term_frame_idx; + } + fs->frame->top_field = fs->top_field; + fs->frame->bottom_field = fs->bottom_field; + fs->frame->frame = fs->frame; + fs->frame->chroma_format_idc = fs->top_field->chroma_format_idc; + + fs->frame->frame_cropping_flag = fs->top_field->frame_cropping_flag; + if (fs->frame->frame_cropping_flag) + { + fs->frame->frame_crop_top_offset = fs->top_field->frame_crop_top_offset; + fs->frame->frame_crop_bottom_offset = fs->top_field->frame_crop_bottom_offset; + fs->frame->frame_crop_left_offset = fs->top_field->frame_crop_left_offset; + fs->frame->frame_crop_right_offset = fs->top_field->frame_crop_right_offset; + } + fs->top_field->frame = fs->bottom_field->frame = fs->frame; + fs->top_field->top_field = fs->top_field; + fs->top_field->bottom_field = fs->bottom_field; + fs->bottom_field->top_field = fs->top_field; + fs->bottom_field->bottom_field = fs->bottom_field; + + fs->frame->is_mmco_5 = fs->top_field->is_mmco_5 || fs->bottom_field->is_mmco_5; + fs->frame->poc_mmco5 = min(fs->top_field->top_poc_mmco5, fs->bottom_field->bot_poc_mmco5); + fs->frame->top_poc_mmco5 = fs->top_field->top_poc_mmco5; + fs->frame->bot_poc_mmco5 = fs->top_field->bot_poc_mmco5; + + return ret = MPP_OK; +__FAILED: + return ret ; +} + +static void write_picture(H264_StorePic_t *p, H264dVideoCtx_t *p_Vid) +{ + (void)p; + (void)p_Vid; +} + +static MPP_RET write_unpaired_field(H264dVideoCtx_t *p_Vid, H264_FrameStore_t *fs) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264_StorePic_t *p = NULL; + + VAL_CHECK(ret, fs->is_used < 3); + if (fs->is_used & 0x01) // we have a top field, construct an empty bottom field + { + p = fs->top_field; + fs->bottom_field = alloc_storable_picture(p_Vid, BOTTOM_FIELD); + MEM_CHECK(ret, fs->bottom_field); + fs->bottom_field->mem_malloc_type = Mem_UnPaired; + fs->bottom_field->chroma_format_idc = p->chroma_format_idc; + FUN_CHECK(ret = dpb_combine_field_yuv(p_Vid, fs, 0)); + fs->frame->view_id = fs->view_id; + write_picture(fs->frame, p_Vid); + } + + if (fs->is_used & 0x02) // we have a bottom field, construct an empty top field + { + p = fs->bottom_field; + fs->top_field = alloc_storable_picture(p_Vid, TOP_FIELD); + MEM_CHECK(ret, fs->top_field); + fs->top_field->mem_malloc_type = Mem_UnPaired; + fs->top_field->chroma_format_idc = p->chroma_format_idc; + fs->top_field->frame_cropping_flag = fs->bottom_field->frame_cropping_flag; + if (fs->top_field->frame_cropping_flag) + { + fs->top_field->frame_crop_top_offset = fs->bottom_field->frame_crop_top_offset; + fs->top_field->frame_crop_bottom_offset = fs->bottom_field->frame_crop_bottom_offset; + fs->top_field->frame_crop_left_offset = fs->bottom_field->frame_crop_left_offset; + fs->top_field->frame_crop_right_offset = fs->bottom_field->frame_crop_right_offset; + } + FUN_CHECK(ret = dpb_combine_field_yuv(p_Vid, fs, 0)); + fs->frame->view_id = fs->view_id; + write_picture(fs->frame, p_Vid); + } + fs->is_used = 3; + + return ret = MPP_OK; +__FAILED: + ASSERT(0); + return ret; +} + +static MPP_RET flush_direct_output(H264dVideoCtx_t *p_Vid) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + FUN_CHECK(ret = write_unpaired_field(p_Vid, &p_Vid->out_buffer)); + free_storable_picture(p_Vid->out_buffer.frame); + p_Vid->out_buffer.frame = NULL; + free_storable_picture(p_Vid->out_buffer.top_field); + p_Vid->out_buffer.top_field = NULL; + free_storable_picture(p_Vid->out_buffer.bottom_field); + p_Vid->out_buffer.bottom_field = NULL; + p_Vid->out_buffer.is_used = 0; + + return ret = MPP_OK; +__FAILED: + ASSERT(0); + return ret; +} + +static MPP_RET write_stored_frame(H264dVideoCtx_t *p_Vid, H264_FrameStore_t *fs) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + //!< make sure no direct output field is pending + FUN_CHECK(ret = flush_direct_output(p_Vid)); + + if (fs->is_used < 3) + { + FUN_CHECK(ret = write_unpaired_field(p_Vid, fs)); + } + else + { + write_picture(fs->frame, p_Vid); + } + + fs->is_output = 1; + + return ret = MPP_OK; +__FAILED: + ASSERT(0); + return ret; +} + +static MPP_RET output_one_frame_from_dpb(H264_DpbBuf_t *p_Dpb) +{ + RK_S32 poc = 0, pos = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + H264dVideoCtx_t *p_Vid = p_Dpb->p_Vid; + + //!< diagnostics + VAL_CHECK(ret, p_Dpb->used_size > 0); //!< Cannot output frame, DPB empty + //!< find smallest POC + FUN_CHECK(ret = get_smallest_poc(p_Dpb, &poc, &pos)); + VAL_CHECK(ret, pos != -1); + //!< JVT-P072 ends + FUN_CHECK(ret = write_stored_frame(p_Vid, p_Dpb->fs[pos])); + //!< free frame store and move empty store to end of buffer + if (!is_used_for_reference(p_Dpb->fs[pos])) + { + FUN_CHECK(ret = remove_frame_from_dpb(p_Dpb, pos)); + } + return ret = MPP_OK; +__FAILED: + ASSERT(0); + return ret; +} + +static MPP_RET adaptive_memory_management(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p) +{ + H264_DRPM_t *tmp_drpm = NULL; + MPP_RET ret = MPP_ERR_UNKNOW; + H264dVideoCtx_t *p_Vid = p_Dpb->p_Vid; + + p_Vid->last_has_mmco_5 = 0; + VAL_CHECK(ret, !p->idr_flag && p->adaptive_ref_pic_buffering_flag); + while (p->dec_ref_pic_marking_buffer) + { + tmp_drpm = p->dec_ref_pic_marking_buffer; + switch (tmp_drpm->memory_management_control_operation) + { + case 0: + VAL_CHECK(ret, tmp_drpm->Next == NULL); + break; + case 1: + mm_unmark_short_term_for_reference(p_Dpb, p, tmp_drpm->difference_of_pic_nums_minus1); + update_ref_list(p_Dpb); + break; + case 2: + mm_unmark_long_term_for_reference(p_Dpb, p, tmp_drpm->long_term_pic_num); + update_ltref_list(p_Dpb); + break; + case 3: + mm_assign_long_term_frame_idx(p_Dpb, p, tmp_drpm->difference_of_pic_nums_minus1, tmp_drpm->long_term_frame_idx); + update_ref_list(p_Dpb); + update_ltref_list(p_Dpb); + break; + case 4: + mm_update_max_long_term_frame_idx(p_Dpb, tmp_drpm->max_long_term_frame_idx_plus1); + update_ltref_list(p_Dpb); + break; + case 5: + mm_unmark_all_short_term_for_reference(p_Dpb); + mm_unmark_all_long_term_for_reference(p_Dpb); + p_Vid->last_has_mmco_5 = 1; + break; + case 6: + mm_mark_current_picture_long_term(p_Dpb, p, tmp_drpm->long_term_frame_idx); + check_num_ref(p_Dpb); + break; + default: + ret = MPP_NOK; + goto __FAILED; + } + p->dec_ref_pic_marking_buffer = tmp_drpm->Next; + mpp_free(tmp_drpm); + } + if (p_Vid->last_has_mmco_5) //!< similar IDR frame + { + p->pic_num = p->frame_num = 0; + switch (p->structure) + { + case TOP_FIELD: + p->is_mmco_5 = 1; + p->top_poc_mmco5 = p->top_poc; + p->poc = p->top_poc = 0; + break; + + case BOTTOM_FIELD: + p->is_mmco_5 = 1; + p->bot_poc_mmco5 = p->bottom_poc; + p->poc = p->bottom_poc = 0; + break; + + case FRAME: + p->is_mmco_5 = 1; + p->top_poc_mmco5 = p->top_poc; + p->bot_poc_mmco5 = p->bottom_poc; + p->poc_mmco5 = min(p->top_poc, p->bottom_poc); + p->top_poc -= p->poc; + p->bottom_poc -= p->poc; + + p->poc = min(p->top_poc, p->bottom_poc); + p->frame_poc = p->poc; + break; + + } + if (p->layer_id == 0) + { + FUN_CHECK(ret = flush_dpb(p_Vid->p_Dpb_layer[0])); + } + else + { + FUN_CHECK(ret = flush_dpb(p_Vid->p_Dpb_layer[1])); + } + + } + return ret = MPP_OK; +__FAILED: + ASSERT(0); + return ret; +} + +static MPP_RET dpb_split_field(H264dVideoCtx_t *p_Vid, H264_FrameStore_t *fs) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264_StorePic_t *frame = fs->frame; + H264_StorePic_t *fs_top = NULL, *fs_btm = NULL; + + fs->poc = frame->poc; + if (!frame->frame_mbs_only_flag) + { + fs_top = fs->top_field = alloc_storable_picture(p_Vid, TOP_FIELD); + fs_btm = fs->bottom_field = alloc_storable_picture(p_Vid, BOTTOM_FIELD); + MEM_CHECK(ret, fs_top &&fs_btm); + fs_top->colmv_no_used_flag = frame->colmv_no_used_flag; + fs_btm->colmv_no_used_flag = frame->colmv_no_used_flag; + + if (frame->mem_malloc_type == Mem_Malloc || frame->mem_malloc_type == Mem_Clone) + { + fs_top->mem_mark = frame->mem_mark; + fs_btm->mem_mark = frame->mem_mark; + fs_top->mem_malloc_type = frame->mem_malloc_type; + fs_btm->mem_malloc_type = frame->mem_malloc_type; + frame->mem_mark->bot_used += 1; // picture memory add 1 + frame->mem_mark->top_used += 1; + } + fs_top->poc = frame->top_poc; + fs_btm->poc = frame->bottom_poc; + fs_top->layer_id = frame->layer_id; + fs_btm->layer_id = frame->layer_id; + + fs_top->view_id = frame->view_id; + fs_btm->view_id = frame->view_id; + fs_top->frame_poc = frame->frame_poc; + + fs_top->bottom_poc = fs_btm->bottom_poc = frame->bottom_poc; + fs_top->top_poc = fs_btm->top_poc = frame->top_poc; + fs_btm->frame_poc = frame->frame_poc; + + fs_top->used_for_reference = fs_btm->used_for_reference = frame->used_for_reference; + fs_top->is_long_term = fs_btm->is_long_term = frame->is_long_term; + fs->long_term_frame_idx = fs_top->long_term_frame_idx = fs_btm->long_term_frame_idx = frame->long_term_frame_idx; + fs_top->mb_aff_frame_flag = fs_btm->mb_aff_frame_flag = frame->mb_aff_frame_flag; + + frame->top_field = fs_top; + frame->bottom_field = fs_btm; + frame->frame = frame; + fs_top->bottom_field = fs_btm; + fs_top->frame = frame; + fs_top->top_field = fs_top; + fs_btm->top_field = fs_top; + fs_btm->frame = frame; + fs_btm->bottom_field = fs_btm; + + fs_top->is_mmco_5 = frame->is_mmco_5; + fs_btm->is_mmco_5 = frame->is_mmco_5; + fs_top->poc_mmco5 = frame->poc_mmco5; + fs_btm->poc_mmco5 = frame->poc_mmco5; + fs_top->top_poc_mmco5 = frame->top_poc_mmco5; + fs_btm->bot_poc_mmco5 = frame->bot_poc_mmco5; + + fs_top->view_id = fs_btm->view_id = fs->view_id; + fs_top->inter_view_flag = fs->inter_view_flag[0]; + fs_btm->inter_view_flag = fs->inter_view_flag[1]; + + fs_top->chroma_format_idc = fs_btm->chroma_format_idc = frame->chroma_format_idc; + fs_top->iCodingType = fs_btm->iCodingType = frame->iCodingType; + } + else + { + fs->top_field = NULL; + fs->bottom_field = NULL; + frame->top_field = NULL; + frame->bottom_field = NULL; + frame->frame = frame; + } + return ret = MPP_OK; +__FAILED: + mpp_free(fs->top_field); + mpp_free(fs->bottom_field); + ASSERT(0); + + return ret; +} + +static MPP_RET dpb_combine_field(H264dVideoCtx_t *p_Vid, H264_FrameStore_t *fs, RK_U8 combine_flag) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + FUN_CHECK(ret = dpb_combine_field_yuv(p_Vid, fs, combine_flag)); + fs->frame->layer_id = fs->layer_id; + fs->frame->view_id = fs->view_id; + fs->frame->iCodingType = fs->top_field->iCodingType; //FIELD_CODING; + + return ret = MPP_OK; +__FAILED: + ASSERT(0); + return ret; +} + +static MPP_RET direct_output(H264dVideoCtx_t *p_Vid, H264_StorePic_t *p) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + if (p->structure == FRAME) + { + //!< we have a frame (or complementary field pair), so output it directly + FUN_CHECK(ret = flush_direct_output(p_Vid)); + write_picture(p, p_Vid); + free_storable_picture(p); + goto __RETURN; + } + + if (p->structure == TOP_FIELD) + { + if (p_Vid->out_buffer.is_used & 1) + { + FUN_CHECK(ret = flush_direct_output(p_Vid)); + } + p_Vid->out_buffer.top_field = p; + p_Vid->out_buffer.is_used |= 1; + } + + if (p->structure == BOTTOM_FIELD) + { + if (p_Vid->out_buffer.is_used & 2) + { + FUN_CHECK(ret = flush_direct_output(p_Vid)); + } + p_Vid->out_buffer.bottom_field = p; + p_Vid->out_buffer.is_used |= 2; + } + + if (p_Vid->out_buffer.is_used == 3) + { + //!< we have both fields, so output them + FUN_CHECK(ret = dpb_combine_field_yuv(p_Vid, &p_Vid->out_buffer, 0)); + p_Vid->out_buffer.frame->view_id = p_Vid->out_buffer.view_id; + write_picture(p_Vid->out_buffer.frame, p_Vid); + free_storable_picture(p_Vid->out_buffer.frame); + p_Vid->out_buffer.frame = NULL; + free_storable_picture(p_Vid->out_buffer.top_field); + p_Vid->out_buffer.top_field = NULL; + free_storable_picture(p_Vid->out_buffer.bottom_field); + p_Vid->out_buffer.bottom_field = NULL; + p_Vid->out_buffer.is_used = 0; + } + +__RETURN: + return ret = MPP_OK; +__FAILED: + ASSERT(0); + return ret; +} + +static MPP_RET store_picture_in_dpb(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p) +{ + RK_S32 poc = 0, pos = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + H264dVideoCtx_t *p_Vid = p_Dpb->p_Vid; + + VAL_CHECK(ret, NULL != p); //!< if frame, check for new store + p_Vid->last_has_mmco_5 = 0; + p_Vid->last_pic_bottom_field = p->structure == BOTTOM_FIELD; + if (p->idr_flag) + { + FUN_CHECK(ret = idr_memory_management(p_Dpb, p)); + } + else //!< adaptive memory management + { + if (p->used_for_reference && p->adaptive_ref_pic_buffering_flag) + { + FUN_CHECK(ret = adaptive_memory_management(p_Dpb, p)); + } + } + if (get_filed_dpb_combine_flag(p_Dpb, p)) + { + FUN_CHECK(ret = insert_picture_in_dpb(p_Vid, p_Dpb->last_picture, p, 1)); //!< field_dpb_combine + update_ref_list(p_Dpb); + update_ltref_list(p_Dpb); + p_Dpb->last_picture = NULL; + goto __RETURN; + } + //!< sliding window, if necessary + if (!p->idr_flag && p->used_for_reference && !p->adaptive_ref_pic_buffering_flag) + { + ASSERT(!p->idr_flag); + sliding_window_memory_management(p_Dpb, p); + p->is_long_term = 0; + } + //!< first try to remove unused frames + if (p_Dpb->used_size == p_Dpb->size) + { + remove_unused_frame_from_dpb(p_Dpb); + } + //!< then output frames until one can be removed + while (p_Dpb->used_size == p_Dpb->size) + { + //!< non-reference frames may be output directly + FUN_CHECK(ret = get_smallest_poc(p_Dpb, &poc, &pos)); + if (!p->used_for_reference) + { + if ((-1 == pos) || (p->poc < poc)) + { + FUN_CHECK(ret = direct_output(p_Vid, p)); + goto __RETURN; + } + } + //!< flush a frame + if ((-1 == pos) || (p->poc < poc)) + { + FUN_CHECK(ret = remove_frame_from_dpb(p_Dpb, 0)); + } + FUN_CHECK(ret = output_one_frame_from_dpb(p_Dpb)); + } + + //!< store at end of buffer + FUN_CHECK(ret = insert_picture_in_dpb(p_Vid, p_Dpb->fs[p_Dpb->used_size], p, 0)); + if (p->structure != FRAME) + { + p_Dpb->last_picture = p_Dpb->fs[p_Dpb->used_size]; + } + else + { + p_Dpb->last_picture = NULL; + } + p_Dpb->used_size++; + update_ref_list(p_Dpb); + update_ltref_list(p_Dpb); + +__RETURN: + return ret = MPP_OK; +__FAILED: + ASSERT(0); + return ret; +} + +/*! +*********************************************************************** +* \brief +* free frame store picture +*********************************************************************** +*/ +//extern "C" +void free_frame_store(H264_FrameStore_t* f) +{ + if (f) + { + if (f->frame) + { + free_storable_picture(f->frame); + f->frame = NULL; + } + if (f->top_field) + { + free_storable_picture(f->top_field); + f->top_field = NULL; + } + if (f->bottom_field) + { + free_storable_picture(f->bottom_field); + f->bottom_field = NULL; + } + mpp_free(f); + } +} + +/*! +*********************************************************************** +* \brief +* free dpb +*********************************************************************** +*/ +//extern "C" +void free_dpb(H264_DpbBuf_t *p_Dpb) +{ + RK_U32 i = 0; + H264dVideoCtx_t *p_Vid = p_Dpb->p_Vid; + + if (p_Dpb->fs) + { + for (i = 0; i < p_Dpb->size; i++) + { + free_frame_store(p_Dpb->fs[i]); + } + mpp_free(p_Dpb->fs); + } + mpp_free(p_Dpb->fs_ref); + mpp_free(p_Dpb->fs_ltref); + if (p_Dpb->fs_ilref) + { + for (i = 0; i < 1; i++) + { + free_frame_store(p_Dpb->fs_ilref[i]); + } + mpp_free(p_Dpb->fs_ilref); + } + p_Dpb->last_output_view_id = -1; + p_Dpb->last_output_poc = INT_MIN; + p_Dpb->init_done = 0; + if (p_Vid->no_reference_picture) + { + free_storable_picture(p_Vid->no_reference_picture); + p_Vid->no_reference_picture = NULL; + } +} + +/*! +*********************************************************************** +* \brief +* alloc one picture +*********************************************************************** +*/ +//extern "C" +void update_ref_list(H264_DpbBuf_t *p_Dpb) +{ + RK_U8 i = 0, j = 0; + for (i = 0, j = 0; i < p_Dpb->used_size; i++) + { + if (is_short_term_reference(p_Dpb->fs[i])) + { + p_Dpb->fs_ref[j++] = p_Dpb->fs[i]; + } + } + + p_Dpb->ref_frames_in_buffer = j; + + while (j < p_Dpb->size) + { + p_Dpb->fs_ref[j++] = NULL; + } +} +/*! +*********************************************************************** +* \brief +* alloc one picture +*********************************************************************** +*/ +//extern "C" +void update_ltref_list(H264_DpbBuf_t *p_Dpb) +{ + RK_U8 i = 0, j = 0; + for (i = 0, j = 0; i < p_Dpb->used_size; i++) + { + if (is_long_term_reference(p_Dpb->fs[i])) + { + p_Dpb->fs_ltref[j++] = p_Dpb->fs[i]; + } + } + + p_Dpb->ltref_frames_in_buffer = j; + + while (j < p_Dpb->size) + { + p_Dpb->fs_ltref[j++] = NULL; + } +} + +/*! +*********************************************************************** +* \brief +* alloc one picture +*********************************************************************** +*/ +//extern "C" +MPP_RET idr_memory_management(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p) +{ + RK_U32 i = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + + if (p->no_output_of_prior_pics_flag) + { + //!< free all stored pictures + for (i = 0; i < p_Dpb->used_size; i++) + { + //!< reset all reference settings + free_frame_store(p_Dpb->fs[i]); + p_Dpb->fs[i] = alloc_frame_store(); + MEM_CHECK(ret, p_Dpb->fs[i]); + } + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) + { + p_Dpb->fs_ref[i] = NULL; + } + for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) + { + p_Dpb->fs_ltref[i] = NULL; + } + p_Dpb->used_size = 0; + } + else + { + FUN_CHECK(ret = flush_dpb(p_Dpb)); + } + p_Dpb->last_picture = NULL; + + update_ref_list(p_Dpb); + update_ltref_list(p_Dpb); + p_Dpb->last_output_poc = INT_MIN; + + if (p->long_term_reference_flag) + { + p_Dpb->max_long_term_pic_idx = 0; + p->is_long_term = 1; + p->long_term_frame_idx = 0; + } + else + { + p_Dpb->max_long_term_pic_idx = -1; + p->is_long_term = 0; + } + p_Dpb->last_output_view_id = -1; + + return ret = MPP_OK; + +__FAILED: + for (i = 0; i < p_Dpb->used_size; i++) // when error and free malloc buf + { + free_frame_store(p_Dpb->fs[i]); + } + ASSERT(0); + return ret; +} + + +/*! +*********************************************************************** +* \brief +* alloc one picture +*********************************************************************** +*/ +//extern "C" +MPP_RET insert_picture_in_dpb(H264dVideoCtx_t *p_Vid, H264_FrameStore_t *fs, H264_StorePic_t* p, RK_U8 combine_flag) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + ASSERT(p != NULL); + ASSERT(fs != NULL); + switch (p->structure) + { + case FRAME: + fs->frame = p; + fs->is_used = 3; + if (p->used_for_reference) + { + fs->is_reference = 3; + fs->is_orig_reference = 3; + if (p->is_long_term) + { + fs->is_long_term = 3; + fs->long_term_frame_idx = p->long_term_frame_idx; + } + } + fs->layer_id = p->layer_id; + fs->view_id = p->view_id; + fs->inter_view_flag[0] = fs->inter_view_flag[1] = p->inter_view_flag; + fs->anchor_pic_flag[0] = fs->anchor_pic_flag[1] = p->anchor_pic_flag; + FUN_CHECK(ret = dpb_split_field(p_Vid, fs)); + break; + case TOP_FIELD: + fs->top_field = p; + fs->is_used |= 1; + fs->layer_id = p->layer_id; + fs->view_id = p->view_id; + fs->inter_view_flag[0] = p->inter_view_flag; + fs->anchor_pic_flag[0] = p->anchor_pic_flag; + if (p->used_for_reference) + { + fs->is_reference |= 1; + fs->is_orig_reference |= 1; + if (p->is_long_term) + { + fs->is_long_term |= 1; + fs->long_term_frame_idx = p->long_term_frame_idx; + } + } + if (fs->is_used == 3) + { + FUN_CHECK(ret = dpb_combine_field(p_Vid, fs, combine_flag)); + } + else + { + fs->poc = p->poc; + } + break; + case BOTTOM_FIELD: + fs->bottom_field = p; + fs->is_used |= 2; + fs->layer_id = p->layer_id; + fs->view_id = p->view_id; + fs->inter_view_flag[1] = p->inter_view_flag; + fs->anchor_pic_flag[1] = p->anchor_pic_flag; + if (p->used_for_reference) + { + fs->is_reference |= 2; + fs->is_orig_reference |= 2; + if (p->is_long_term) + { + fs->is_long_term |= 2; + fs->long_term_frame_idx = p->long_term_frame_idx; + } + } + if (fs->is_used == 3) + { + FUN_CHECK(ret = dpb_combine_field(p_Vid, fs, combine_flag)); + } + else + { + fs->poc = p->poc; + } + break; + } + fs->frame_num = p->pic_num; + fs->is_output = p->is_output; + + return ret = MPP_OK; +__FAILED: + ASSERT(0); + return ret; +} + + +/*! +*********************************************************************** +* \brief +* alloc one picture +*********************************************************************** +*/ +//extern "C" +void free_storable_picture(H264_StorePic_t *p) +{ + if (p) + { + if (p->mem_malloc_type == Mem_Malloc || p->mem_malloc_type == Mem_Clone) + { + free_dpb_memory_index(p->mem_mark, p->structure, p->layer_id); + } + + mpp_free(p); + } +} + +/*! +*********************************************************************** +* \brief +* alloc one picture +*********************************************************************** +*/ +//extern "C" +H264_StorePic_t *alloc_storable_picture(H264dVideoCtx_t *p_Vid, RK_S32 structure) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264_StorePic_t *s = mpp_calloc(H264_StorePic_t, 1); + + MEM_CHECK(ret, s); + s->view_id = -1; + s->structure = structure; + (void)p_Vid; + + return s; +__FAILED: + (void)ret; + return NULL; +} + +/*! +*********************************************************************** +* \brief +* alloc one picture +*********************************************************************** +*/ +//extern "C" + +RK_U32 get_filed_dpb_combine_flag(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p) +{ + RK_U32 combine_flag = 0; + + if ((p->structure == TOP_FIELD) || (p->structure == BOTTOM_FIELD)) + { + // check for frame store with same pic_number + if (p_Dpb->last_picture) + { + if ((RK_S32)p_Dpb->last_picture->frame_num == p->pic_num) + { + if (((p->structure == TOP_FIELD) && (p_Dpb->last_picture->is_used == 2)) || ((p->structure == BOTTOM_FIELD) && (p_Dpb->last_picture->is_used == 1))) + { + if ((p->used_for_reference && (p_Dpb->last_picture->is_orig_reference != 0)) || + (!p->used_for_reference && (p_Dpb->last_picture->is_orig_reference == 0))) + { + return combine_flag = 1; + } + } + } + } + } + + return combine_flag = 0; +} + +/*! +*********************************************************************** +* \brief +* init dpb +*********************************************************************** +*/ +//extern "C" +MPP_RET init_dpb(H264dVideoCtx_t *p_Vid, H264_DpbBuf_t *p_Dpb, RK_S32 type) // type=1 AVC type=2 MVC +{ + RK_U32 i = 0; + RK_S32 PicSizeInMbs = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + H264_SPS_t *active_sps = p_Vid->active_sps; + LogCtx_t *runlog = p_Dpb->p_Vid->p_Dec->logctx.parr[RUN_PARSE]; + + p_Dpb->p_Vid = p_Vid; + if (p_Dpb->init_done) + { + free_dpb(p_Dpb); + } + p_Dpb->size = getDpbSize(p_Vid, active_sps) + (type == 2 ? 0 : 1); + p_Dpb->num_ref_frames = active_sps->max_num_ref_frames; + if (active_sps->max_dec_frame_buffering < active_sps->max_num_ref_frames) + { + LogError(runlog, "DPB size at specified level is smaller than reference frames"); + goto __FAILED; + } + p_Dpb->used_size = 0; + p_Dpb->last_picture = NULL; + p_Dpb->ref_frames_in_buffer = 0; + p_Dpb->ltref_frames_in_buffer = 0; + //-------- + p_Dpb->fs = mpp_calloc(H264_FrameStore_t*, p_Dpb->size); + p_Dpb->fs_ref = mpp_calloc(H264_FrameStore_t*, p_Dpb->size); + p_Dpb->fs_ltref = mpp_calloc(H264_FrameStore_t*, p_Dpb->size); + p_Dpb->fs_ilref = mpp_calloc(H264_FrameStore_t*, 1); + MEM_CHECK(ret, p_Dpb->fs && p_Dpb->fs_ref && p_Dpb->fs_ltref && p_Dpb->fs_ilref); + for (i = 0; i < p_Dpb->size; i++) + { + p_Dpb->fs[i] = alloc_frame_store(); + MEM_CHECK(ret, p_Dpb->fs[i]); + p_Dpb->fs_ref[i] = NULL; + p_Dpb->fs_ltref[i] = NULL; + p_Dpb->fs[i]->layer_id = MVC_INIT_VIEW_ID; + p_Dpb->fs[i]->view_id = MVC_INIT_VIEW_ID; + p_Dpb->fs[i]->inter_view_flag[0] = p_Dpb->fs[i]->inter_view_flag[1] = 0; + p_Dpb->fs[i]->anchor_pic_flag[0] = p_Dpb->fs[i]->anchor_pic_flag[1] = 0; + } + if (type == 2) + { + p_Dpb->fs_ilref[0] = alloc_frame_store(); + MEM_CHECK(ret, p_Dpb->fs_ilref[0]); + //!< These may need some cleanups + p_Dpb->fs_ilref[0]->view_id = MVC_INIT_VIEW_ID; + p_Dpb->fs_ilref[0]->inter_view_flag[0] = p_Dpb->fs_ilref[0]->inter_view_flag[1] = 0; + p_Dpb->fs_ilref[0]->anchor_pic_flag[0] = p_Dpb->fs_ilref[0]->anchor_pic_flag[1] = 0; + //!< given that this is in a different buffer, do we even need proc_flag anymore? + } + else + { + p_Dpb->fs_ilref[0] = NULL; + } + //!< allocate a dummy storable picture + if (!p_Vid->no_reference_picture) + { + PicSizeInMbs = (p_Vid->active_sps->pic_height_in_map_units_minus1 + 1) * (p_Vid->active_sps->pic_width_in_mbs_minus1 + 1); + p_Vid->no_reference_picture = alloc_storable_picture(p_Vid, FRAME); + MEM_CHECK(ret, p_Vid->no_reference_picture); + p_Vid->no_reference_picture->top_field = p_Vid->no_reference_picture; + p_Vid->no_reference_picture->bottom_field = p_Vid->no_reference_picture; + p_Vid->no_reference_picture->frame = p_Vid->no_reference_picture; + } + p_Dpb->last_output_poc = INT_MIN; + p_Dpb->last_output_view_id = -1; + p_Vid->last_has_mmco_5 = 0; + p_Dpb->init_done = 1; + (void)PicSizeInMbs; + + return ret = MPP_OK; +__FAILED: + ASSERT(0); + return ret; +} +/*! +*********************************************************************** +* \brief +* flush dpb +*********************************************************************** +*/ +//extern "C" + +MPP_RET flush_dpb(H264_DpbBuf_t *p_Dpb) +{ + RK_U32 i = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + + //!< diagnostics + if (!p_Dpb->init_done) + { + goto __RETURN; + } + //!< mark all frames unused + for (i = 0; i < p_Dpb->used_size; i++) + { + VAL_CHECK(ret, p_Dpb->fs[i]->layer_id == p_Dpb->layer_id); + unmark_for_reference(p_Dpb->fs[i]); + } + while (!remove_unused_frame_from_dpb(p_Dpb)); + //!< output frames in POC order + while (p_Dpb->used_size) + { + FUN_CHECK(ret = output_one_frame_from_dpb(p_Dpb)); + } + p_Dpb->last_output_poc = INT_MIN; +__RETURN: + return ret = MPP_OK; +__FAILED: + return ret; +} + +/*! +*********************************************************************** +* \brief +* parse sps and process sps +*********************************************************************** +*/ +//extern "C" +MPP_RET exit_picture(H264dVideoCtx_t *p_Vid, H264_StorePic_t **dec_picture) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + //!< return if the last picture has already been finished + if (!(*dec_picture) || !p_Vid->exit_picture_flag + || !p_Vid->have_outpicture_flag || !p_Vid->iNumOfSlicesDecoded) + { + goto __RETURN; + } + +#if 0 + set_curframe_poc((*dec_picture), &p_Vid->p_Dec->regs); +#endif + FUN_CHECK(ret = store_picture_in_dpb(p_Vid->p_Dpb_layer[(*dec_picture)->layer_id], *dec_picture)); + printf("--rkv_h264_decoder ending, g_framecnt=%d \n", p_Vid->g_framecnt++); +#if 0 + update_all_logctx_framenum(&p_Vid->p_Dec->logctx, p_Vid->g_framecnt); +#endif + *dec_picture = NULL; + +__RETURN: + return ret = MPP_OK; + +__FAILED: + ASSERT(0); + return ret; +} + +/*! +*********************************************************************** +* \brief +* prepare dpb info for regsiter syntax +*********************************************************************** +*/ +//extern "C" +MPP_RET prepare_init_dpb_info(H264_SLICE_t *currSlice) +{ + RK_U64 ADDR_Y = 0; + RK_U32 i = 0, j = 0, k = 0; + RK_S32 poc = 0, TOP_POC = 0, BOT_POC = 0; + RK_S32 layer_id = 0, voidx = 0, is_used = 0; + H264_DpbBuf_t *p_Dpb = currSlice->p_Dpb; + H264_DecCtx_t *p_Dec = currSlice->p_Dec; + + memset(p_Dec->dpb_info, 0, DPB_INFO_SIZE * sizeof(H264_DpbInfo_t)); + memset(p_Dec->refpic_info_p, 0, REFPIC_INFO_SIZE * sizeof(H264_RefPicInfo_t)); + memset(p_Dec->refpic_info[0], 0, REFPIC_INFO_SIZE * sizeof(H264_RefPicInfo_t)); + memset(p_Dec->refpic_info[1], 0, REFPIC_INFO_SIZE * sizeof(H264_RefPicInfo_t)); + + if (currSlice->idr_flag && !currSlice->layer_id) // idr_flag==1 && layer_id==0 + { + goto __RETURN; + } + //!<---- reference + for (i = 0, j = 0; j < p_Dpb->ref_frames_in_buffer; i++, j++) + { + if (p_Dpb->fs_ref[j]->is_used == 3) + { + p_Dec->dpb_info[i].ADDR_Y = (RK_U64)&p_Dpb->fs_ref[j]->frame; + if (p_Dpb->fs_ref[j]->frame->iCodingType == FIELD_CODING) + { + p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ref[j]->top_field->poc; + p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ref[j]->bottom_field->poc; + } + else + { + if (p_Dpb->fs_ref[j]->frame->frame_poc != p_Dpb->fs_ref[j]->frame->poc) + { + p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ref[j]->frame->top_poc - p_Dpb->fs_ref[j]->frame->frame_poc; + p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ref[j]->frame->bottom_poc - p_Dpb->fs_ref[j]->frame->frame_poc; + } + else + { + p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ref[j]->frame->top_poc; + p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ref[j]->frame->bottom_poc; + } + } + p_Dec->dpb_info[i].field_flag = p_Dpb->fs_ref[j]->frame->iCodingType == FIELD_CODING; + p_Dec->dpb_info[i].mem_mark_idx = p_Dpb->fs_ref[j]->frame->mem_mark->index; + p_Dec->dpb_info[i].colmv_is_used = (p_Dpb->fs_ref[j]->frame->colmv_no_used_flag ? 0 : 1); + } + else if (p_Dpb->fs_ref[j]->is_used) + { + if (p_Dpb->fs_ref[j]->is_used & 0x1) // top + { + p_Dec->dpb_info[i].ADDR_Y = (RK_U64)&p_Dpb->fs_ref[j]->top_field; + + p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ref[j]->top_field->poc; + p_Dec->dpb_info[i].BOT_POC = 0; + p_Dec->dpb_info[i].field_flag = 1; + p_Dec->dpb_info[i].mem_mark_idx = p_Dpb->fs_ref[j]->top_field->mem_mark->index; + p_Dec->dpb_info[i].colmv_is_used = (p_Dpb->fs_ref[j]->top_field->colmv_no_used_flag ? 0 : 1); + } + else// if(p_Dpb->fs_ref[j]->is_used & 0x2) // bottom + { + p_Dec->dpb_info[i].ADDR_Y = (RK_U64)&p_Dpb->fs_ref[j]->bottom_field; + p_Dec->dpb_info[i].TOP_POC = 0; + p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ref[j]->bottom_field->poc; + p_Dec->dpb_info[i].field_flag = 1; + p_Dec->dpb_info[i].mem_mark_idx = p_Dpb->fs_ref[j]->bottom_field->mem_mark->index; + p_Dec->dpb_info[i].colmv_is_used = (p_Dpb->fs_ref[j]->bottom_field->colmv_no_used_flag ? 0 : 1); + + } + } + p_Dec->dpb_info[i].frame_num_wrap = p_Dpb->fs_ref[j]->frame_num_wrap; + p_Dec->dpb_info[i].is_long_term = 0; + p_Dec->dpb_info[i].voidx = p_Dpb->fs_ref[j]->layer_id; + p_Dec->dpb_info[i].view_id = p_Dpb->fs_ref[j]->view_id; + p_Dec->dpb_info[i].is_used = p_Dpb->fs_ref[j]->is_used; + } + //!<---- long term reference + for (j = 0; j < p_Dpb->ltref_frames_in_buffer; i++, j++) + { + if (p_Dpb->fs_ltref[j]->is_used == 3) + { + p_Dec->dpb_info[i].ADDR_Y = (RK_U64)&p_Dpb->fs_ltref[j]->frame; + + if (p_Dpb->fs_ltref[j]->frame->iCodingType == FIELD_CODING) + { + p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ltref[j]->top_field->poc; + p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ltref[j]->bottom_field->poc; + } + else + { + if (p_Dpb->fs_ltref[j]->frame->frame_poc != p_Dpb->fs_ltref[j]->frame->poc) + { + p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ltref[j]->frame->top_poc - p_Dpb->fs_ltref[j]->frame->frame_poc; + p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ltref[j]->frame->bottom_poc - p_Dpb->fs_ltref[j]->frame->frame_poc; + } + else + { + p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ltref[j]->frame->top_poc; + p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ltref[j]->frame->bottom_poc; + } + + } + p_Dec->dpb_info[i].field_flag = p_Dpb->fs_ltref[j]->frame->iCodingType == FIELD_CODING; + p_Dec->dpb_info[i].mem_mark_idx = p_Dpb->fs_ltref[j]->frame->mem_mark->index; + p_Dec->dpb_info[i].colmv_is_used = (p_Dpb->fs_ltref[j]->frame->colmv_no_used_flag ? 0 : 1); + } + else if (p_Dpb->fs_ltref[j]->is_used) + { + if (p_Dpb->fs_ltref[j]->is_used & 0x1) + { + p_Dec->dpb_info[i].ADDR_Y = (RK_U64)&p_Dpb->fs_ltref[j]->top_field; + p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ltref[j]->top_field->poc; + p_Dec->dpb_info[i].BOT_POC = 0; + p_Dec->dpb_info[i].field_flag = 1; + p_Dec->dpb_info[i].mem_mark_idx = p_Dpb->fs_ltref[j]->top_field->mem_mark->index; + p_Dec->dpb_info[i].colmv_is_used = (p_Dpb->fs_ltref[j]->top_field->colmv_no_used_flag ? 0 : 1); + + } + else// if(p_Dpb->fs_ref[j]->is_used & 0x2) + { + p_Dec->dpb_info[i].ADDR_Y = (RK_U64)&p_Dpb->fs_ltref[j]->bottom_field; + p_Dec->dpb_info[i].TOP_POC = 0; + p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ltref[j]->bottom_field->poc; + p_Dec->dpb_info[i].field_flag = 1; + p_Dec->dpb_info[i].mem_mark_idx = p_Dpb->fs_ltref[j]->bottom_field->mem_mark->index; + p_Dec->dpb_info[i].colmv_is_used = (p_Dpb->fs_ltref[j]->bottom_field->colmv_no_used_flag ? 0 : 1); + } + } + p_Dec->dpb_info[i].frame_num_wrap = p_Dpb->fs_ltref[j]->long_term_frame_idx;//long term use long_term_frame_idx + p_Dec->dpb_info[i].is_long_term = 1; + p_Dec->dpb_info[i].voidx = p_Dpb->fs_ltref[j]->layer_id; + p_Dec->dpb_info[i].view_id = p_Dpb->fs_ltref[j]->view_id; + p_Dec->dpb_info[i].is_used = p_Dpb->fs_ltref[j]->is_used; + } + //!<---- short term reference + for (j = 0; j < p_Dpb->used_size_il; i++, j++) + { + if (currSlice->structure == FRAME && p_Dpb->fs_ilref[j]->is_used == 3) + { + if (p_Dpb->fs_ilref[j]->inter_view_flag[0] == 0 && p_Dpb->fs_ilref[j]->inter_view_flag[1] == 0) + break; + p_Dec->dpb_info[i].ADDR_Y = (RK_U64)&p_Dpb->fs_ilref[j]->frame; + + if (p_Dpb->fs_ilref[j]->frame->is_mmco_5) + { + p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ilref[j]->frame->top_poc_mmco5; + p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ilref[j]->frame->bot_poc_mmco5; + } + else + { + p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ilref[j]->frame->top_poc; + p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ilref[j]->frame->bottom_poc; + } + p_Dec->dpb_info[i].field_flag = p_Dpb->fs_ilref[j]->frame->iCodingType == FIELD_CODING; + p_Dec->dpb_info[i].mem_mark_idx = p_Dpb->fs_ilref[j]->frame->mem_mark->index; + p_Dec->dpb_info[i].colmv_is_used = (p_Dpb->fs_ilref[j]->frame->colmv_no_used_flag ? 0 : 1); + + } + else if (currSlice->structure != FRAME && p_Dpb->fs_ilref[j]->is_used) + { + if (p_Dpb->fs_ilref[j]->is_used == 0x3) + { + if (p_Dpb->fs_ilref[j]->inter_view_flag[currSlice->structure == BOTTOM_FIELD] == 0) + break; + p_Dec->dpb_info[i].ADDR_Y = (RK_U64)&p_Dpb->fs_ilref[j]->top_field; + + if (p_Dpb->fs_ilref[j]->top_field->is_mmco_5) + { + p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ilref[j]->top_field->top_poc_mmco5; + } + else + { + p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ilref[j]->top_field->top_poc; + } + if (p_Dpb->fs_ilref[j]->bottom_field->is_mmco_5) + { + p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ilref[j]->bottom_field->bot_poc_mmco5; + } + else + { + p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ilref[j]->bottom_field->bottom_poc; + } + p_Dec->dpb_info[i].field_flag = p_Dpb->fs_ilref[j]->frame->iCodingType == FIELD_CODING; + p_Dec->dpb_info[i].mem_mark_idx = p_Dpb->fs_ilref[j]->frame->mem_mark->index; + p_Dec->dpb_info[i].colmv_is_used = (p_Dpb->fs_ilref[j]->frame->colmv_no_used_flag ? 0 : 1); + } + if (p_Dpb->fs_ilref[j]->is_used & 0x1) + { + if (p_Dpb->fs_ilref[j]->inter_view_flag[0] == 0) + break; + p_Dec->dpb_info[i].ADDR_Y = (RK_U64)&p_Dpb->fs_ilref[j]->top_field; + + if (p_Dpb->fs_ilref[j]->top_field->is_mmco_5) + { + p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ilref[j]->top_field->top_poc_mmco5; + } + else + { + p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ilref[j]->top_field->top_poc; + } + p_Dec->dpb_info[i].BOT_POC = 0; + p_Dec->dpb_info[i].field_flag = 1; + p_Dec->dpb_info[i].mem_mark_idx = p_Dpb->fs_ilref[j]->top_field->mem_mark->index; + p_Dec->dpb_info[i].colmv_is_used = (p_Dpb->fs_ilref[j]->top_field->colmv_no_used_flag ? 0 : 1); + + } + else// if(p_Dpb->fs_ref[j]->is_used & 0x2) + { + if (p_Dpb->fs_ilref[j]->inter_view_flag[1] == 0) + break; + p_Dec->dpb_info[i].ADDR_Y = (RK_U64)&p_Dpb->fs_ilref[j]->bottom_field; + + p_Dec->dpb_info[i].TOP_POC = 0; + if (p_Dpb->fs_ilref[j]->bottom_field->is_mmco_5) + { + p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ilref[j]->bottom_field->bot_poc_mmco5; + } + else + { + p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ilref[j]->bottom_field->bottom_poc; + } + p_Dec->dpb_info[i].field_flag = 1; + p_Dec->dpb_info[i].mem_mark_idx = p_Dpb->fs_ilref[j]->bottom_field->mem_mark->index; + p_Dec->dpb_info[i].colmv_is_used = (p_Dpb->fs_ilref[j]->bottom_field->colmv_no_used_flag ? 0 : 1); + } + } + p_Dec->dpb_info[i].frame_num_wrap = p_Dpb->fs_ilref[j]->frame_num_wrap; + p_Dec->dpb_info[i].is_long_term = 0; + p_Dec->dpb_info[i].voidx = p_Dpb->fs_ilref[j]->layer_id; + p_Dec->dpb_info[i].view_id = p_Dpb->fs_ilref[j]->view_id; + p_Dec->dpb_info[i].is_used = p_Dpb->fs_ilref[j]->is_used; + } + //!<------ set listP ------- + for (j = 0; j < 32; j++) + { + poc = 0; + layer_id = currSlice->listP[0][j]->layer_id; + if (j < currSlice->listXsizeP[0]) + { + if (currSlice->listP[0][j]->structure == FRAME) + { + poc = (currSlice->listP[0][j]->is_mmco_5 && currSlice->layer_id && currSlice->listP[0][j]->layer_id == 0) + ? currSlice->listP[0][j]->poc_mmco5 : currSlice->listP[0][j]->poc; + } + else if (currSlice->listP[0][j]->structure == TOP_FIELD) + { + + poc = (currSlice->listP[0][j]->is_mmco_5 && currSlice->layer_id && currSlice->listP[0][j]->layer_id == 0) + ? currSlice->listP[0][j]->top_poc_mmco5 : currSlice->listP[0][j]->top_poc; + } + else + { + poc = (currSlice->listP[0][j]->is_mmco_5 && currSlice->layer_id && currSlice->listP[0][j]->layer_id == 0) + ? currSlice->listP[0][j]->bot_poc_mmco5 : currSlice->listP[0][j]->bottom_poc; + } + for (i = 0; i < 16; i++) + { + ADDR_Y = p_Dec->dpb_info[i].ADDR_Y; + TOP_POC = p_Dec->dpb_info[i].TOP_POC; + BOT_POC = p_Dec->dpb_info[i].BOT_POC; + voidx = p_Dec->dpb_info[i].voidx; + is_used = p_Dec->dpb_info[i].is_used; + if (currSlice->structure == FRAME && ADDR_Y) + { + if (poc == min(TOP_POC, BOT_POC) && (layer_id == voidx)) + break; + } + else + { + if (is_used == 3) + { + if ((poc == BOT_POC || poc == TOP_POC) && layer_id == voidx) + break; + } + else if (is_used & 1) + { + if (poc == TOP_POC && layer_id == voidx) + break; + } + else if (is_used & 2) + { + if (poc == BOT_POC && layer_id == voidx) + break; + } + } + } + ASSERT(i < 16); + p_Dec->refpic_info_p[j].dpb_idx = i; + + if (currSlice->listP[0][j]->structure == BOTTOM_FIELD) + { + p_Dec->refpic_info_p[j].bottom_flag = 1; + } + else + { + p_Dec->refpic_info_p[j].bottom_flag = 0; + } + p_Dec->refpic_info_p[j].valid = 1; + } + else + { + p_Dec->refpic_info_p[j].valid = 0; + p_Dec->refpic_info_p[j].dpb_idx = 0; + p_Dec->refpic_info_p[j].bottom_flag = 0; + } + } + //!<------ set listB ------- + for (k = 0; k < 2; k++) + { + for (j = 0; j < 32; j++) + { + poc = 0; + layer_id = currSlice->listB[k][j]->layer_id; + if (j < currSlice->listXsizeB[k]) + { + if (currSlice->listB[k][j]->structure == FRAME) + { + poc = (currSlice->listB[k][j]->is_mmco_5 && currSlice->layer_id && currSlice->listB[k][j]->layer_id == 0) + ? currSlice->listB[k][j]->poc_mmco5 : currSlice->listB[k][j]->poc; + } + else if (currSlice->listB[k][j]->structure == TOP_FIELD) + { + poc = (currSlice->listB[k][j]->is_mmco_5 && currSlice->layer_id && currSlice->listB[k][j]->layer_id == 0) + ? currSlice->listB[k][j]->top_poc_mmco5 : currSlice->listB[k][j]->top_poc; + } + else + { + poc = (currSlice->listB[k][j]->is_mmco_5 && currSlice->layer_id && currSlice->listB[k][j]->layer_id == 0) + ? currSlice->listB[k][j]->bot_poc_mmco5 : currSlice->listB[k][j]->bottom_poc; + } + for (i = 0; i < 16; i++) + { + ADDR_Y = p_Dec->dpb_info[i].ADDR_Y; + TOP_POC = p_Dec->dpb_info[i].TOP_POC; + BOT_POC = p_Dec->dpb_info[i].BOT_POC; + voidx = p_Dec->dpb_info[i].voidx; + is_used = p_Dec->dpb_info[i].is_used; + if (currSlice->structure == FRAME && ADDR_Y) + { + if (poc == min(TOP_POC, BOT_POC) && (layer_id == voidx)) + break; + } + else + { + if (is_used == 3) + { + if ((poc == BOT_POC || poc == TOP_POC) && layer_id == voidx) + break; + } + else if (is_used & 1) + { + if (poc == TOP_POC && (layer_id == voidx || (layer_id != voidx && !currSlice->bottom_field_flag))) + break; + } + else if (is_used & 2) + { + if (poc == BOT_POC && (layer_id == voidx || (layer_id != voidx && currSlice->bottom_field_flag))) + break; + } + } + } + ASSERT(i < 16); + p_Dec->refpic_info[k][j].dpb_idx = i; + + if (currSlice->listB[k][j]->structure == BOTTOM_FIELD) + { + p_Dec->refpic_info[k][j].bottom_flag = 1; + } + else + { + p_Dec->refpic_info[k][j].bottom_flag = 0; + } + + p_Dec->refpic_info[k][j].valid = 1; + } + else + { + p_Dec->refpic_info[k][j].valid = 0; + p_Dec->refpic_info[k][j].dpb_idx = 0; + p_Dec->refpic_info[k][j].bottom_flag = 0; + } + } + } +__RETURN: + return MPP_OK; +} +/*! +*********************************************************************** +* \brief +* update dpb +*********************************************************************** +*/ +//extern "C" +MPP_RET update_dpb(H264_DecCtx_t *p_Dec) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + p_Dec->parser_end_flag = 0; + p_Dec->p_Vid->exit_picture_flag = 1; + p_Dec->p_Vid->have_outpicture_flag = 1; + FUN_CHECK(ret = exit_picture(p_Dec->p_Vid, &p_Dec->p_Vid->dec_picture)); + p_Dec->p_Vid->iNumOfSlicesDecoded = 0; + p_Dec->p_Vid->exit_picture_flag = 0; + + return ret = MPP_OK; +__FAILED: + ASSERT(0); + return ret; +} + diff --git a/mpp/codec/dec/h264/h264d_dpb.h b/mpp/codec/dec/h264/h264d_dpb.h new file mode 100644 index 00000000..cc203e0f --- /dev/null +++ b/mpp/codec/dec/h264/h264d_dpb.h @@ -0,0 +1,54 @@ +/* +* +* 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. +*/ + +#ifndef _H264D_DPB_H_ +#define _H264D_DPB_H_ + + +#include "rk_type.h" +#include "mpp_err.h" +#include "h264d_global.h" + + +#ifdef __cplusplus +extern "C" { +#endif + void update_ref_list(H264_DpbBuf_t *p_Dpb); + void update_ltref_list(H264_DpbBuf_t *p_Dpb); + void free_storable_picture(H264_StorePic_t *p); + void free_frame_store(H264_FrameStore_t *f); + + MPP_RET idr_memory_management(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p); + MPP_RET insert_picture_in_dpb(H264dVideoCtx_t *p_Vid, H264_FrameStore_t *fs, H264_StorePic_t *p, RK_U8 combine_flag); + + MPP_RET init_dpb (H264dVideoCtx_t *p_Vid, H264_DpbBuf_t *p_Dpb, RK_S32 type); + MPP_RET flush_dpb(H264_DpbBuf_t *p_Dpb); + MPP_RET update_dpb(H264_DecCtx_t *p_Dec); + void free_dpb (H264_DpbBuf_t *p_Dpb); + MPP_RET exit_picture(H264dVideoCtx_t *p_Vid, H264_StorePic_t **dec_picture); + MPP_RET prepare_init_dpb_info(H264_SLICE_t *currSlice); + + RK_U32 get_filed_dpb_combine_flag(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p); + H264_StorePic_t *alloc_storable_picture(H264dVideoCtx_t *p_Vid, RK_S32 structure); + +#ifdef __cplusplus +} +#endif + +//======================================== +#endif /* end of _H264D_DPB_H_ */ + diff --git a/mpp/codec/dec/h264/h264d_fill.c b/mpp/codec/dec/h264/h264d_fill.c new file mode 100644 index 00000000..ae309181 --- /dev/null +++ b/mpp/codec/dec/h264/h264d_fill.c @@ -0,0 +1,426 @@ +/* +* +* 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. +*/ + +#include +#include + +#include "mpp_mem.h" + +#include "h264d_log.h" +#include "h264d_fill.h" + +#define MODULE_TAG "h264d_fill" + +#define FF_ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0])) +#define ALIGN(x, a) ( ((x) + (a) - 1) & (~((a) - 1)) ) + +static const RK_U8 start_code[3] = { 0, 0, 1 }; + + +static MPP_RET realloc_slice_list(H264dDxvaCtx_t *dxva_ctx) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + dxva_ctx->max_slice_size += ADD_SLICE_SIZE; + dxva_ctx->slice_long = mpp_realloc(dxva_ctx->slice_long, DXVA_Slice_H264_Long, dxva_ctx->max_slice_size); + MEM_CHECK(ret, dxva_ctx->slice_long); + + return ret = MPP_OK; +__FAILED: + ASSERT(0); + return ret; +} + + +static MPP_RET realloc_stream_buffer(H264dDxvaCtx_t *dxva_ctx, RK_U32 stream_add) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + if (stream_add > FRAME_BUF_ADD_SIZE) + { + dxva_ctx->max_strm_size += ALIGN(stream_add, 128); + } + else + { + dxva_ctx->max_strm_size += FRAME_BUF_ADD_SIZE; + } + dxva_ctx->bitstream = mpp_realloc(dxva_ctx->bitstream, RK_U8, dxva_ctx->max_strm_size); + MEM_CHECK (ret, dxva_ctx->bitstream); + + return ret = MPP_OK; +__FAILED: + ASSERT(0); + return ret; +} + +static MPP_RET fill_stream_data(H264dDxvaCtx_t *dxva_ctx, H264_Nalu_t *p_nal) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + RK_U32 stream_offset = 0; + RK_U32 streamlen_add = 0; + DXVA_Slice_H264_Long *p_long = NULL; + + if (dxva_ctx->slice_count >= dxva_ctx->max_slice_size) + { + FUN_CHECK(ret = realloc_slice_list(dxva_ctx)); + } + streamlen_add = p_nal->sodb_len + sizeof(start_code); + stream_offset = dxva_ctx->strm_offset + streamlen_add; + if (stream_offset > dxva_ctx->max_strm_size) + { + FUN_CHECK (ret = realloc_stream_buffer(dxva_ctx, streamlen_add)); + } + p_long = &dxva_ctx->slice_long[dxva_ctx->slice_count]; + memset(p_long, 0, sizeof(DXVA_Slice_H264_Long)); + p_long->BSNALunitDataLocation = dxva_ctx->strm_offset; + p_long->wBadSliceChopping = 0; //!< set to 0 in Rock-Chip RKVDEC IP + memcpy(&dxva_ctx->bitstream[dxva_ctx->strm_offset], start_code, sizeof(start_code)); + dxva_ctx->strm_offset += sizeof(start_code); + memcpy(&dxva_ctx->bitstream[dxva_ctx->strm_offset], p_nal->sodb_buf, p_nal->sodb_len); + dxva_ctx->strm_offset += p_nal->sodb_len; + p_long->SliceBytesInBuffer = dxva_ctx->strm_offset - p_long->BSNALunitDataLocation; + + return ret = MPP_OK; +__FAILED: + return ret; +} + +static void fill_picture_entry(DXVA_PicEntry_H264 *pic, RK_U32 index, RK_U32 flag) +{ + ASSERT((index & 0x7f) == index && (flag & 0x01) == flag); + pic->bPicEntry = index | (flag << 7); +} + + +/*! +*********************************************************************** +* \brief +* fill picture parameters +*********************************************************************** +*/ +//extern "C" +void fill_qmatrix(H264dVideoCtx_t *p_Vid, DXVA_Qmatrix_H264 *qm) +{ + RK_S32 i = 0, j = 0; + + memset(qm, 0, sizeof(DXVA_Qmatrix_H264)); + for (i = 0; i < 6; ++i) //!< 4x4, 6 lists + { + for (j = 0; j < H264ScalingList4x4Length; j++) + { + qm->bScalingLists4x4[i][j] = p_Vid->qmatrix[i][j]; + } + } + for (i = 6; i < ((p_Vid->active_sps->chroma_format_idc != YUV444) ? 8 : 12); ++i) + { + for (j = 0; j < H264ScalingList8x8Length; j++) + { + qm->bScalingLists8x8[i-6][j] = p_Vid->qmatrix[i][j]; + } + } +} +/*! +*********************************************************************** +* \brief +* fill picture parameters +*********************************************************************** +*/ +//extern "C" +void fill_picparams(H264dVideoCtx_t *p_Vid, DXVA_PicParams_H264_MVC *pp) +{ + RK_U32 i = 0, j = 0, num_views = 0; + H264_StorePic_t *dec_picture = p_Vid->dec_picture; + H264_DpbInfo_t *dpb_info = p_Vid->p_Dec->dpb_info; + + memset(pp, 0, sizeof(DXVA_PicParams_H264_MVC)); + //!< Configure current picture + fill_picture_entry(&pp->CurrPic, dec_picture->mem_mark->index, dec_picture->structure == BOTTOM_FIELD); + + //!< Configure the set of references + pp->UsedForReferenceFlags = 0; + pp->NonExistingFrameFlags = 0; + + for (i = 0, j = 0; i < FF_ARRAY_ELEMS(pp->RefFrameList); i++) + { + if (dpb_info[i].ADDR_Y) + { + fill_picture_entry(&pp->RefFrameList[i], dpb_info[i].mem_mark_idx, dpb_info[i].is_long_term); + pp->FieldOrderCntList[i][0] = dpb_info[i].TOP_POC; + pp->FieldOrderCntList[i][1] = dpb_info[i].BOT_POC; + pp->FrameNumList[i] = dpb_info[i].frame_num_wrap; + if (dpb_info[i].is_used & 0x01) //!< top_field + { + pp->UsedForReferenceFlags |= 1 << (2 * i + 0); + } + if (dpb_info[i].is_used & 0x02) //!< bot_field + { + pp->UsedForReferenceFlags |= 1 << (2 * i + 1); + } + } + else + { + pp->RefFrameList[i].bPicEntry = 0xff; + pp->FieldOrderCntList[i][0] = 0; + pp->FieldOrderCntList[i][1] = 0; + pp->FrameNumList[i] = 0; + } + } + pp->wFrameWidthInMbsMinus1 = p_Vid->active_sps->pic_width_in_mbs_minus1; + pp->wFrameHeightInMbsMinus1 = p_Vid->active_sps->pic_height_in_map_units_minus1; + pp->num_ref_frames = p_Vid->active_sps->max_num_ref_frames; + + pp->wBitFields = ((dec_picture->iCodingType == FIELD_CODING) << 0) //!< field_pic_flag + | (dec_picture->mb_aff_frame_flag << 1) //!< MbaffFrameFlag + | (0 << 2) //!< residual_colour_transform_flag + | (0 << 3) //!< sp_for_switch_flag + | (p_Vid->active_sps->chroma_format_idc << 4) //!< chroma_format_idc + | (dec_picture->used_for_reference << 6) //!< RefPicFlag + | (p_Vid->active_pps->constrained_intra_pred_flag << 7) //!< constrained_intra_pred_flag + | (p_Vid->active_pps->weighted_pred_flag << 8) //!< weighted_pred_flag + | (p_Vid->active_pps->weighted_bipred_idc << 9) //!< weighted_bipred_idc + | (1 << 11) //!< MbsConsecutiveFlag + | (p_Vid->active_sps->frame_mbs_only_flag << 12) //!< frame_mbs_only_flag + | (p_Vid->active_pps->transform_8x8_mode_flag << 13) //!< transform_8x8_mode_flag + | ((p_Vid->active_sps->level_idc >= 31) << 14) //!< MinLumaBipredSize8x8Flag + | (1 << 15); //!< IntraPicFlag (Modified if we detect a non-intra slice in dxva2_h264_decode_slice) + + pp->bit_depth_luma_minus8 = p_Vid->active_sps->bit_depth_luma_minus8; + pp->bit_depth_chroma_minus8 = p_Vid->active_sps->bit_depth_chroma_minus8; + pp->Reserved16Bits = 3; //!< FIXME is there a way to detect the right mode + + pp->StatusReportFeedbackNumber = 1 /*+ ctx->report_id++*/; + + pp->CurrFieldOrderCnt[0] = 0; + if (dec_picture->structure == TOP_FIELD || dec_picture->structure == FRAME) + { + pp->CurrFieldOrderCnt[0] = dec_picture->top_poc; + } + pp->CurrFieldOrderCnt[1] = 0; + if (dec_picture->structure == BOTTOM_FIELD || dec_picture->structure == FRAME) + { + pp->CurrFieldOrderCnt[1] = dec_picture->bottom_poc; + } + pp->pic_init_qs_minus26 = p_Vid->active_pps->pic_init_qs_minus26; + pp->chroma_qp_index_offset = p_Vid->active_pps->chroma_qp_index_offset; + pp->second_chroma_qp_index_offset = p_Vid->active_pps->second_chroma_qp_index_offset; + pp->ContinuationFlag = 1; + pp->pic_init_qp_minus26 = p_Vid->active_pps->pic_init_qp_minus26; + pp->num_ref_idx_l0_active_minus1 = p_Vid->active_pps->num_ref_idx_l0_default_active_minus1; + pp->num_ref_idx_l1_active_minus1 = p_Vid->active_pps->num_ref_idx_l1_default_active_minus1; + pp->Reserved8BitsA = 0; + + pp->frame_num = dec_picture->frame_num; + pp->log2_max_frame_num_minus4 = p_Vid->active_sps->log2_max_frame_num_minus4; + pp->pic_order_cnt_type = p_Vid->active_sps->pic_order_cnt_type; + if (pp->pic_order_cnt_type == 0) + { + pp->log2_max_pic_order_cnt_lsb_minus4 = p_Vid->active_sps->log2_max_pic_order_cnt_lsb_minus4; + } + else if (pp->pic_order_cnt_type == 1) + { + pp->delta_pic_order_always_zero_flag = p_Vid->active_sps->delta_pic_order_always_zero_flag; + } + pp->direct_8x8_inference_flag = p_Vid->active_sps->direct_8x8_inference_flag; + pp->entropy_coding_mode_flag = p_Vid->active_pps->entropy_coding_mode_flag; + pp->pic_order_present_flag = p_Vid->active_pps->bottom_field_pic_order_in_frame_present_flag; + pp->num_slice_groups_minus1 = p_Vid->active_pps->num_slice_groups_minus1; + pp->slice_group_map_type = p_Vid->active_pps->slice_group_map_type; + pp->deblocking_filter_control_present_flag = p_Vid->active_pps->deblocking_filter_control_present_flag; + pp->redundant_pic_cnt_present_flag = p_Vid->active_pps->redundant_pic_cnt_present_flag; + pp->Reserved8BitsB = 0; + pp->slice_group_change_rate_minus1 = 0; //!< XXX not implemented by FFmpeg + //pp->SliceGroupMap[810]; //!< XXX not implemented by FFmpeg + + //!< Following are H.264 MVC Specific parameters + if (p_Vid->active_subsps) + { + pp->num_views_minus1 = p_Vid->active_subsps->num_views_minus1; + num_views = 1 + pp->num_views_minus1; + ASSERT(num_views <= 16); + for (i = 0; i < num_views; i++) + { + pp->view_id[i] = p_Vid->active_subsps->view_id[i]; + pp->num_anchor_refs_l0[i] = p_Vid->active_subsps->num_anchor_refs_l0[i]; + for (j = 0; j < pp->num_anchor_refs_l0[i]; j++) + { + pp->anchor_ref_l0[i][j] = p_Vid->active_subsps->anchor_ref_l0[i][j]; + } + pp->num_anchor_refs_l1[i] = p_Vid->active_subsps->num_anchor_refs_l1[i]; + for (j = 0; j < pp->num_anchor_refs_l1[i]; j++) + { + pp->anchor_ref_l1[i][j] = p_Vid->active_subsps->anchor_ref_l1[i][j]; + } + pp->num_non_anchor_refs_l0[i] = p_Vid->active_subsps->num_non_anchor_refs_l0[i]; + for (j = 0; j < pp->num_non_anchor_refs_l0[i]; j++) + { + pp->non_anchor_ref_l0[i][j] = p_Vid->active_subsps->non_anchor_ref_l0[i][j]; + } + pp->num_non_anchor_refs_l1[i] = p_Vid->active_subsps->num_non_anchor_refs_l1[i]; + for (j = 0; j < pp->num_non_anchor_refs_l1[i]; j++) + { + pp->non_anchor_ref_l1[i][j] = p_Vid->active_subsps->non_anchor_ref_l1[i][j]; + } + } + for (i = num_views; i < 16; i++) + { + pp->view_id[i] = 0xffff; + } + } + pp->curr_view_id = dec_picture->view_id; + pp->anchor_pic_flag = dec_picture->anchor_pic_flag; + pp->inter_view_flag = dec_picture->inter_view_flag; + for (i = 0; i < 16; i++) + { + pp->ViewIDList[i] = p_Vid->p_Dec->dpb_info[i].view_id; + } + //!< add in Rock-chip RKVDEC IP + for (i = 0; i < 16; i++) + { + if (p_Vid->p_Dec->dpb_info[i].colmv_is_used) + { + pp->RefPicColmvUsedFlags |= 1 << i; + } + if (p_Vid->p_Dec->dpb_info[i].field_flag) + { + pp->RefPicFiledFlags |= 1 << i; + } + pp->RefPicLayerIdList[i] = p_Vid->p_Dec->dpb_info[i].voidx; + } + if (p_Vid->active_pps->pic_scaling_matrix_present_flag + || p_Vid->active_sps->seq_scaling_matrix_present_flag) + { + pp->scaleing_list_enable_flag = 1; + } + else + { + pp->scaleing_list_enable_flag = 0; + } +} + +/*! +*********************************************************************** +* \brief +* fill slice short struct +*********************************************************************** +*/ +//extern "C" +MPP_RET fill_slice(H264_SLICE_t *currSlice, H264dDxvaCtx_t *dxva_ctx) +{ + RK_U32 list = 0, i = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + DXVA_Slice_H264_Long *p_long = NULL; + RK_S32 dpb_idx = 0, dpb_valid = 0, bottom_flag = 0; + + FUN_CHECK(ret = fill_stream_data(dxva_ctx, &currSlice->p_Cur->nalu)); + p_long = &dxva_ctx->slice_long[dxva_ctx->slice_count]; + //!< fill slice long contents + p_long->first_mb_in_slice = currSlice->start_mb_nr; + p_long->NumMbsForSlice = 0; //!< XXX it is set once we have all slices + p_long->slice_type = currSlice->slice_type; + p_long->num_ref_idx_l0_active_minus1 = currSlice->active_pps->num_ref_idx_l0_default_active_minus1; + p_long->num_ref_idx_l1_active_minus1 = currSlice->active_pps->num_ref_idx_l1_default_active_minus1; + p_long->redundant_pic_cnt = currSlice->redundant_pic_cnt; + p_long->direct_spatial_mv_pred_flag = currSlice->direct_spatial_mv_pred_flag; + p_long->slice_id = dxva_ctx->slice_count; + + for (i = 0; i < FF_ARRAY_ELEMS(p_long->RefPicList[0]); i++) + { + dpb_idx = currSlice->p_Dec->refpic_info_p[i].dpb_idx; + dpb_valid = (currSlice->p_Dec->dpb_info[dpb_idx].ADDR_Y ? 1 : 0); + if (dpb_valid) + { + bottom_flag = currSlice->p_Dec->refpic_info_p[i].bottom_flag; + fill_picture_entry(&p_long->RefPicList[0][i], dpb_idx, bottom_flag); + } + else + { + p_long->RefPicList[0][i].bPicEntry = 0xff; + } + } + + for (list = 0; list < 2; list++) + { + for (i = 0; i < FF_ARRAY_ELEMS(p_long->RefPicList[list + 1]); i++) + { + dpb_idx = currSlice->p_Dec->refpic_info[list][i].dpb_idx; + dpb_valid = (currSlice->p_Dec->dpb_info[dpb_idx].ADDR_Y ? 1 : 0); + if (dpb_valid) + { + bottom_flag = currSlice->p_Dec->refpic_info[list][i].bottom_flag; + fill_picture_entry(&p_long->RefPicList[list + 1][i], dpb_idx, bottom_flag); + } + else + { + p_long->RefPicList[list + 1][i].bPicEntry = 0xff; + } + } + } + dxva_ctx->slice_count++; + + return ret = MPP_OK; +__FAILED: + return ret; +} + + +/*! +*********************************************************************** +* \brief +* check parser is end and then configure register +*********************************************************************** +*/ +//extern "C" +void commit_buffer(H264dDxvaCtx_t *dxva_ctx) +{ + H264dSyntax_t *p_syn = &dxva_ctx->syn; + DXVA2_DecodeBufferDesc *p_dec = NULL; + + p_syn->num = 0; + //!< commit picture paramters + p_dec = &p_syn->buf[p_syn->num++]; + memset(p_dec, 0, sizeof(DXVA2_DecodeBufferDesc)); + p_dec->CompressedBufferType = DXVA2_PictureParametersBufferType; + p_dec->pvPVPState = (void *)&dxva_ctx->pp; + p_dec->DataSize = sizeof(DXVA_PicParams_H264_MVC); + p_dec->NumMBsInBuffer = 0; + //!< commit scanlist Qmatrix + p_dec = &p_syn->buf[p_syn->num++]; + memset(p_dec, 0, sizeof(DXVA2_DecodeBufferDesc)); + p_dec->CompressedBufferType = DXVA2_InverseQuantizationMatrixBufferType; + p_dec->pvPVPState = (void *)&dxva_ctx->qm; + p_dec->DataSize = sizeof(DXVA_Qmatrix_H264); + p_dec->NumMBsInBuffer = 0; + //!< commit bitstream + p_dec = &p_syn->buf[p_syn->num++]; + memset(p_dec, 0, sizeof(DXVA2_DecodeBufferDesc)); + p_dec->CompressedBufferType = DXVA2_BitStreamDateBufferType; + p_dec->DataSize = ALIGN(dxva_ctx->strm_offset, 16); + memset(dxva_ctx->bitstream + dxva_ctx->strm_offset, 0, p_dec->DataSize - dxva_ctx->strm_offset); + p_dec->pvPVPState = (void *)dxva_ctx->bitstream; + //!< commit slice control, DXVA_Slice_H264_Long + p_dec = &p_syn->buf[p_syn->num++]; + memset(p_dec, 0, sizeof(DXVA2_DecodeBufferDesc)); + p_dec->CompressedBufferType = DXVA2_SliceControlBufferType; + p_dec->NumMBsInBuffer = (dxva_ctx->pp.wFrameHeightInMbsMinus1 + 1) + * (dxva_ctx->pp.wFrameWidthInMbsMinus1 + 1); + p_dec->pvPVPState = dxva_ctx->slice_long; + p_dec->DataSize = dxva_ctx->slice_count * sizeof(DXVA_Slice_H264_Long); + + //!< reset dxva parameters + dxva_ctx->slice_count = 0; + dxva_ctx->strm_offset = 0; +} \ No newline at end of file diff --git a/mpp/codec/dec/h264/h264d_fill.h b/mpp/codec/dec/h264/h264d_fill.h new file mode 100644 index 00000000..8b91aadf --- /dev/null +++ b/mpp/codec/dec/h264/h264d_fill.h @@ -0,0 +1,43 @@ +/* +* +* 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. +*/ + +#ifndef _H264D_FILL_H_ +#define _H264D_FILL_H_ + +#include "rk_type.h" +#include "mpp_err.h" +#include "dxva_syntax.h" +#include "h264d_syntax.h" +#include "h264d_global.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + void fill_picparams(H264dVideoCtx_t *p_Vid, DXVA_PicParams_H264_MVC *pp); + void fill_qmatrix(H264dVideoCtx_t *p_Vid, DXVA_Qmatrix_H264 *qm); + void commit_buffer(H264dDxvaCtx_t *dxva); + MPP_RET fill_slice(H264_SLICE_t *currSlice, H264dDxvaCtx_t *dxva_ctx); +#ifdef __cplusplus +} +#endif + +//======================================== +#endif /* end of _RKV_H264_DECODER_FILL_H_ */ + diff --git a/mpp/codec/dec/h264/h264d_global.h b/mpp/codec/dec/h264/h264d_global.h index 63749651..1dabe8b8 100644 --- a/mpp/codec/dec/h264/h264d_global.h +++ b/mpp/codec/dec/h264/h264d_global.h @@ -22,6 +22,8 @@ #include "rk_type.h" #include "rk_mpi.h" +#include "mpp_dec.h" +#include "h264d_api.h" #include "h264d_log.h" #include "h264d_bitread.h" #include "h264d_syntax.h" @@ -46,6 +48,13 @@ #define NALU_BUF_MAX_SIZE 64//512*1024 #define NALU_BUF_ADD_SIZE 32//512 +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif //!< AVC Profile IDC definitions typedef enum { @@ -664,7 +673,7 @@ typedef struct h264_sei_t { RK_S32 type; RK_S32 payload_size; struct { - RK_S32 recovery_frame_cnt; + RK_U32 recovery_frame_cnt; RK_S32 exact_match_flag; RK_S32 broken_link_flag; RK_S32 changing_slice_group_idc; @@ -796,8 +805,7 @@ typedef struct h264d_dxva_ctx_t { struct _DXVA_PicParams_H264_MVC pp; struct _DXVA_Qmatrix_H264 qm; RK_U32 max_slice_size; - RK_U32 slice_count; - struct _DXVA_Slice_H264_Short *slice_short; //!< MAX_SLICES + RK_U32 slice_count; struct _DXVA_Slice_H264_Long *slice_long; //!< MAX_SLICES RK_U8 *bitstream; RK_U32 max_strm_size; @@ -806,7 +814,6 @@ typedef struct h264d_dxva_ctx_t { struct h264_dec_ctx_t *p_Dec; } H264dDxvaCtx_t; - //!< input parameter typedef struct h264d_input_ctx_t { RK_U8 is_eos; @@ -815,6 +822,14 @@ typedef struct h264d_input_ctx_t { struct h264d_video_ctx_t *p_Vid; //!< parameters for video decoder enum mpp_decmtd_type dec_mtd; MppParserInitCfg init; + //!< input data + RK_U8 *in_buf; + size_t *in_size; + RK_S64 *in_timestamp; + //!< output data + RK_U8 *out_buf; + RK_U32 *out_length; + } H264dInputCtx_t; //!< current stream @@ -920,6 +935,50 @@ typedef struct h264d_mem_t { struct h264d_dxva_ctx_t dxva_ctx[MAX_TASK_SIZE]; } H264_DecMem_t; +//!< nalu state used in read nalu +typedef enum nalu_state_tpye{ + NALU_NULL = 0, + + //StreamError, + HaveNoStream, + NaluNotSupport, + //ReadNaluError, + //StartofNalu, + EndofStream, + //ReallocBufError, + MidOfNalu, + EndOfNalu, + StartOfPicture, + StartOfSlice, + SkipNALU, + NALU_SPS, + NALU_SubSPS, + NALU_PPS, + NALU_SEI, + + NALU_MAX, +} NALU_STATUS; + +//!< slice state used in parse loop +typedef enum slice_state_type { + SliceSTATE_NULL = 0, + SliceSTATE_IDLE, + + SliceSTATE_ResetSlice, + SliceSTATE_ReadNalu, + SliceSTATE_ParseNalu, + SliceSTATE_InitPicture, + ////SliceSTATE_InitSlice, + SliceSTATE_GetSliceData, + //SliceSTATE_RegisterOneSlice, + SliceSTATE_RegisterOneFrame, + SliceSTATE_Error, + SliceSTATE_MAX, + +} SLICE_STATUS; + + + //!< decoder video parameter typedef struct h264_dec_ctx_t { struct h264d_mem_t *mem; @@ -933,10 +992,11 @@ typedef struct h264_dec_ctx_t { struct h264d_cur_ctx_t *p_Cur; //!< current parameters, use in read nalu struct h264d_video_ctx_t *p_Vid; //!< parameters for video decoder RK_U32 spt_decode_mtds; //!< support decoder methods - RK_S32 nalu_ret; //!< current nalu state - RK_S32 next_state; //!< RKV_SLICE_STATUS + NALU_STATUS nalu_ret; //!< current nalu state + SLICE_STATUS next_state; //!< RKV_SLICE_STATUS RK_U8 first_frame_flag; RK_U8 parser_end_flag; + RK_U8 dxva_idx; struct h264d_logctx_t logctx; //!< debug log file struct log_ctx_t logctxbuf[LOG_MAX]; } H264_DecCtx_t; diff --git a/mpp/codec/dec/h264/h264d_init.c b/mpp/codec/dec/h264/h264d_init.c new file mode 100644 index 00000000..63488c87 --- /dev/null +++ b/mpp/codec/dec/h264/h264d_init.c @@ -0,0 +1,1389 @@ +/* +* +* 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. +*/ + +#include +#include + +#include "mpp_mem.h" + +#include "h264d_log.h" +#include "h264d_init.h" +#include "h264d_dpb.h" +#include "h264d_scalist.h" +#include "h264d_fill.h" + +#define MODULE_TAG "h264d_init" + + + +static MPP_RET decode_poc(H264dVideoCtx_t *p_Vid, H264_SLICE_t *pSlice) +{ + RK_S32 i = 0; + RK_U32 MaxPicOrderCntLsb = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + H264_SPS_t *active_sps = p_Vid->active_sps; + // for POC mode 0: + MaxPicOrderCntLsb = (1 << (active_sps->log2_max_pic_order_cnt_lsb_minus4 + 4)); + + switch (active_sps->pic_order_cnt_type) + { + case 0: // POC MODE 0 + // 1st + if (pSlice->idr_flag) + { + p_Vid->PrevPicOrderCntMsb = 0; + p_Vid->PrevPicOrderCntLsb = 0; + } + else + { + if (p_Vid->last_has_mmco_5) + { + if (p_Vid->last_pic_bottom_field) + { + p_Vid->PrevPicOrderCntMsb = 0; + p_Vid->PrevPicOrderCntLsb = 0; + } + else + { + p_Vid->PrevPicOrderCntMsb = 0; + p_Vid->PrevPicOrderCntLsb = pSlice->toppoc; + } + } + } + // Calculate the MSBs of current picture + if (pSlice->pic_order_cnt_lsb < p_Vid->PrevPicOrderCntLsb && + (p_Vid->PrevPicOrderCntLsb - pSlice->pic_order_cnt_lsb) >= (RK_S32)(MaxPicOrderCntLsb / 2)) + { + pSlice->PicOrderCntMsb = p_Vid->PrevPicOrderCntMsb + MaxPicOrderCntLsb; + } + else if (pSlice->pic_order_cnt_lsb > p_Vid->PrevPicOrderCntLsb && + (pSlice->pic_order_cnt_lsb - p_Vid->PrevPicOrderCntLsb) > (RK_S32)(MaxPicOrderCntLsb / 2)) + { + pSlice->PicOrderCntMsb = p_Vid->PrevPicOrderCntMsb - MaxPicOrderCntLsb; + } + else + { + pSlice->PicOrderCntMsb = p_Vid->PrevPicOrderCntMsb; + } + // 2nd + if (pSlice->field_pic_flag == 0) + { //frame pix + pSlice->toppoc = pSlice->PicOrderCntMsb + pSlice->pic_order_cnt_lsb; + pSlice->bottompoc = pSlice->toppoc + pSlice->delta_pic_order_cnt_bottom; + pSlice->ThisPOC = pSlice->framepoc = (pSlice->toppoc < pSlice->bottompoc) ? pSlice->toppoc : pSlice->bottompoc; // POC200301 + } + else if (pSlice->bottom_field_flag == 0) + { //top field + pSlice->ThisPOC = pSlice->toppoc = pSlice->PicOrderCntMsb + pSlice->pic_order_cnt_lsb; + } + else + { //bottom field + pSlice->ThisPOC = pSlice->bottompoc = pSlice->PicOrderCntMsb + pSlice->pic_order_cnt_lsb; + } + pSlice->framepoc = pSlice->ThisPOC; + p_Vid->ThisPOC = pSlice->ThisPOC; + //if ( pSlice->frame_num != p_Vid->PreviousFrameNum) //Seems redundant + p_Vid->PreviousFrameNum = pSlice->frame_num; + if (pSlice->nal_reference_idc) + { + p_Vid->PrevPicOrderCntLsb = pSlice->pic_order_cnt_lsb; + p_Vid->PrevPicOrderCntMsb = pSlice->PicOrderCntMsb; + } + break; + + case 1: // POC MODE 1 + // 1st + if (pSlice->idr_flag) + { + p_Vid->FrameNumOffset = 0; // first pix of IDRGOP, + VAL_CHECK(ret, 0 == pSlice->frame_num); + } + else + { + if (p_Vid->last_has_mmco_5) + { + p_Vid->PreviousFrameNumOffset = 0; + p_Vid->PreviousFrameNum = 0; + } + if (pSlice->frame_num < (RK_S32)p_Vid->PreviousFrameNum) + { //not first pix of IDRGOP + p_Vid->FrameNumOffset = p_Vid->PreviousFrameNumOffset + p_Vid->max_frame_num; + } + else + { + p_Vid->FrameNumOffset = p_Vid->PreviousFrameNumOffset; + } + } + // 2nd + if (active_sps->num_ref_frames_in_pic_order_cnt_cycle) + { + pSlice->AbsFrameNum = p_Vid->FrameNumOffset + pSlice->frame_num; + } + else + { + pSlice->AbsFrameNum = 0; + } + if ((!pSlice->nal_reference_idc) && pSlice->AbsFrameNum > 0) + { + pSlice->AbsFrameNum--; + } + // 3rd + p_Vid->ExpectedDeltaPerPicOrderCntCycle = 0; + if (active_sps->num_ref_frames_in_pic_order_cnt_cycle) + { + for (i = 0; i < (RK_S32)active_sps->num_ref_frames_in_pic_order_cnt_cycle; i++) + { + p_Vid->ExpectedDeltaPerPicOrderCntCycle += active_sps->offset_for_ref_frame[i]; + } + } + if (pSlice->AbsFrameNum) + { + p_Vid->PicOrderCntCycleCnt = (pSlice->AbsFrameNum - 1) / active_sps->num_ref_frames_in_pic_order_cnt_cycle; + p_Vid->FrameNumInPicOrderCntCycle = (pSlice->AbsFrameNum - 1) % active_sps->num_ref_frames_in_pic_order_cnt_cycle; + p_Vid->ExpectedPicOrderCnt = p_Vid->PicOrderCntCycleCnt*p_Vid->ExpectedDeltaPerPicOrderCntCycle; + for (i = 0; i <= (RK_S32)p_Vid->FrameNumInPicOrderCntCycle; i++) + p_Vid->ExpectedPicOrderCnt += active_sps->offset_for_ref_frame[i]; + } + else + { + p_Vid->ExpectedPicOrderCnt = 0; + } + if (!pSlice->nal_reference_idc) + { + p_Vid->ExpectedPicOrderCnt += active_sps->offset_for_non_ref_pic; + } + if (pSlice->field_pic_flag == 0) + { //frame pix + pSlice->toppoc = p_Vid->ExpectedPicOrderCnt + pSlice->delta_pic_order_cnt[0]; + pSlice->bottompoc = pSlice->toppoc + active_sps->offset_for_top_to_bottom_field + pSlice->delta_pic_order_cnt[1]; + pSlice->ThisPOC = pSlice->framepoc = (pSlice->toppoc < pSlice->bottompoc) ? pSlice->toppoc : pSlice->bottompoc; // POC200301 + } + else if (pSlice->bottom_field_flag == 0) + { //top field + pSlice->ThisPOC = pSlice->toppoc = p_Vid->ExpectedPicOrderCnt + pSlice->delta_pic_order_cnt[0]; + } + else + { //bottom field + pSlice->ThisPOC = pSlice->bottompoc = p_Vid->ExpectedPicOrderCnt + active_sps->offset_for_top_to_bottom_field + pSlice->delta_pic_order_cnt[0]; + } + pSlice->framepoc = pSlice->ThisPOC; + p_Vid->PreviousFrameNum = pSlice->frame_num; + p_Vid->PreviousFrameNumOffset = p_Vid->FrameNumOffset; + break; + + + case 2: // POC MODE 2 + if (pSlice->idr_flag) // IDR picture + { + p_Vid->FrameNumOffset = 0; // first pix of IDRGOP, + pSlice->ThisPOC = pSlice->framepoc = pSlice->toppoc = pSlice->bottompoc = 0; + VAL_CHECK(ret, 0 == pSlice->frame_num); + } + else + { + if (p_Vid->last_has_mmco_5) + { + p_Vid->PreviousFrameNum = 0; + p_Vid->PreviousFrameNumOffset = 0; + } + if (pSlice->frame_num < (RK_S32)p_Vid->PreviousFrameNum) + { + p_Vid->FrameNumOffset = p_Vid->PreviousFrameNumOffset + p_Vid->max_frame_num; + } + else + { + p_Vid->FrameNumOffset = p_Vid->PreviousFrameNumOffset; + } + pSlice->AbsFrameNum = p_Vid->FrameNumOffset + pSlice->frame_num; + if (!pSlice->nal_reference_idc) + { + pSlice->ThisPOC = (2 * pSlice->AbsFrameNum - 1); + } + else + { + pSlice->ThisPOC = (2 * pSlice->AbsFrameNum); + } + if (pSlice->field_pic_flag == 0) + { + pSlice->toppoc = pSlice->bottompoc = pSlice->framepoc = pSlice->ThisPOC; + } + else if (pSlice->bottom_field_flag == 0) + { + pSlice->toppoc = pSlice->framepoc = pSlice->ThisPOC; + } + else + { + pSlice->bottompoc = pSlice->framepoc = pSlice->ThisPOC; + } + } + p_Vid->PreviousFrameNum = pSlice->frame_num; + p_Vid->PreviousFrameNumOffset = p_Vid->FrameNumOffset; + break; + default: + ret = MPP_NOK; + goto __FAILED; + } + return ret = MPP_OK; + +__FAILED: + ASSERT(0); + return ret; +} + +static MPP_RET store_proc_picture_in_dpb(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dVideoCtx_t *p_Vid = p_Dpb->p_Vid; + H264_FrameStore_t *fs = p_Dpb->fs_ilref[0]; + + VAL_CHECK(ret, NULL != p); + if (p_Dpb->used_size_il > 0) + { + if (fs->frame) + { + free_storable_picture(fs->frame); + fs->frame = NULL; + } + if (fs->top_field) + { + free_storable_picture(fs->top_field); + fs->top_field = NULL; + } + if (fs->bottom_field) + { + free_storable_picture(fs->bottom_field); + fs->bottom_field = NULL; + } + fs->is_used = 0; + fs->is_reference = 0; + p_Dpb->used_size_il--; + } + if (fs->is_used > 0) //checking; + { + if (p->structure == FRAME) + { + VAL_CHECK(ret, fs->frame == NULL); + } + else if (p->structure == TOP_FIELD) + { + VAL_CHECK(ret, fs->top_field == NULL); + } + else if (p->structure == BOTTOM_FIELD) + { + VAL_CHECK(ret, fs->bottom_field == NULL); + } + } + FUN_CHECK(ret= insert_picture_in_dpb(p_Vid, fs, p, 0)); + if ((p->structure == FRAME && fs->is_used == 3) + || (p->structure != FRAME && fs->is_used && fs->is_used < 3)) + { + p_Dpb->used_size_il++; + } + + return ret = MPP_OK; +__FAILED: + ASSERT(0); + return ret; +} + +static void clone_dpb_memory_index(H264_DpbMark_t *pmem_dpb, RK_S32 structure, RK_S32 layer_id, RK_S32 framecnt) +{ + //!<---- index add ---- + if (structure == FRAME || structure == TOP_FIELD) + { + pmem_dpb->top_used += 1; + } + if (structure == FRAME || structure == BOTTOM_FIELD) + { + pmem_dpb->bot_used += 1; + } + (void)layer_id; + (void)framecnt; +} + +static H264_StorePic_t* clone_storable_picture(H264dVideoCtx_t *p_Vid, H264_StorePic_t *p_pic) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264_StorePic_t *p_stored_pic = alloc_storable_picture(p_Vid, p_Vid->structure); + + MEM_CHECK(ret, p_stored_pic); + p_stored_pic->mem_malloc_type = Mem_Clone; + p_stored_pic->mem_mark = p_pic->mem_mark; + clone_dpb_memory_index(p_stored_pic->mem_mark, p_stored_pic->structure, p_pic->layer_id, p_Vid->g_framecnt); + p_stored_pic->colmv_no_used_flag = 1; // clone, colmv is not be used + + p_stored_pic->pic_num = p_pic->pic_num; + p_stored_pic->frame_num = p_pic->frame_num; + p_stored_pic->long_term_frame_idx = p_pic->long_term_frame_idx; + p_stored_pic->long_term_pic_num = p_pic->long_term_pic_num; + p_stored_pic->is_long_term = 0; + p_stored_pic->non_existing = p_pic->non_existing; + p_stored_pic->max_slice_id = p_pic->max_slice_id; + p_stored_pic->structure = p_pic->structure; + + p_stored_pic->mb_aff_frame_flag = p_pic->mb_aff_frame_flag; + p_stored_pic->poc = p_pic->poc; + p_stored_pic->top_poc = p_pic->top_poc; + p_stored_pic->bottom_poc = p_pic->bottom_poc; + p_stored_pic->frame_poc = p_pic->frame_poc; + p_stored_pic->is_mmco_5 = p_pic->is_mmco_5; + p_stored_pic->poc_mmco5 = p_pic->poc_mmco5; + p_stored_pic->top_poc_mmco5 = p_pic->top_poc_mmco5; + p_stored_pic->bot_poc_mmco5 = p_pic->bot_poc_mmco5; + p_stored_pic->pic_num = p_pic->pic_num; + p_stored_pic->frame_num = p_pic->frame_num; + p_stored_pic->slice_type = p_pic->slice_type; + p_stored_pic->idr_flag = p_pic->idr_flag; + p_stored_pic->no_output_of_prior_pics_flag = p_pic->no_output_of_prior_pics_flag; + p_stored_pic->long_term_reference_flag = 0; + p_stored_pic->adaptive_ref_pic_buffering_flag = 0; + p_stored_pic->dec_ref_pic_marking_buffer = NULL; + p_stored_pic->PicWidthInMbs = p_pic->PicWidthInMbs; + + p_stored_pic->chroma_format_idc = p_pic->chroma_format_idc; + p_stored_pic->frame_mbs_only_flag = p_pic->frame_mbs_only_flag; + p_stored_pic->frame_cropping_flag = p_pic->frame_cropping_flag; + if (p_stored_pic->frame_cropping_flag) + { + p_stored_pic->frame_crop_left_offset = p_pic->frame_crop_left_offset; + p_stored_pic->frame_crop_right_offset = p_pic->frame_crop_right_offset; + p_stored_pic->frame_crop_top_offset = p_pic->frame_crop_top_offset; + p_stored_pic->frame_crop_bottom_offset = p_pic->frame_crop_bottom_offset; + } + // MVC-related parameters + p_stored_pic->inter_view_flag = p_pic->inter_view_flag; + p_stored_pic->anchor_pic_flag = 0; + p_stored_pic->view_id = p_pic->view_id; + p_stored_pic->layer_id = p_pic->layer_id; + p_stored_pic->proc_flag = 1; + p_stored_pic->is_output = 1; + p_stored_pic->used_for_reference = 1; + + return p_stored_pic; +__FAILED: + (void)ret; + ASSERT(0); + return NULL; +} + +static MPP_RET init_mvc_picture(H264_SLICE_t *currSlice) +{ + RK_U32 i = 0; + RK_S32 poc = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + H264dVideoCtx_t *p_Vid = currSlice->p_Vid; + H264_DpbBuf_t *p_Dpb = p_Vid->p_Dpb_layer[0]; + H264_StorePic_t *p_pic = NULL; + H264_FrameStore_t *fs = NULL; + H264_StorePic_t *p_clone = NULL; + + // find BL reconstructed picture + if (currSlice->structure == FRAME) + { + for (i = 0; i < p_Dpb->used_size; i++) + { + fs = p_Dpb->fs[i]; + if (fs->frame) + { + poc = fs->frame->is_mmco_5 ? fs->frame->poc_mmco5 : fs->frame->poc; + } + if (fs->frame && (fs->frame->layer_id == 0) && (poc == currSlice->framepoc)) + { + p_pic = fs->frame; + if (!fs->frame->is_mmco_5) + { + break; + } + } + } + } + else if (currSlice->structure == TOP_FIELD) + { + for (i = 0; i < p_Dpb->used_size; i++) + { + fs = p_Dpb->fs[i]; + if (fs->top_field) + { + poc = fs->top_field->is_mmco_5 ? fs->top_field->top_poc_mmco5 : fs->top_field->top_poc; + } + if (fs->top_field && (fs->top_field->layer_id == 0) && (poc == currSlice->toppoc)) + { + p_pic = fs->top_field; + if (!fs->top_field->is_mmco_5) + { + break; + } + } + } + } + else + { + for (i = 0; i < p_Dpb->used_size; i++) + { + fs = p_Dpb->fs[i]; + if (fs->bottom_field) + { + poc = fs->bottom_field->is_mmco_5 ? fs->bottom_field->bot_poc_mmco5 : fs->bottom_field->bottom_poc; + } + if (fs->bottom_field && (fs->bottom_field->layer_id == 0) && (poc == currSlice->bottompoc)) + { + p_pic = fs->bottom_field; + if (!fs->bottom_field->is_mmco_5) + { + break; + } + } + } + } + if (p_pic) + { + p_clone = clone_storable_picture(p_Vid, p_pic); + MEM_CHECK(ret, p_clone); + FUN_CHECK(ret = store_proc_picture_in_dpb(currSlice->p_Dpb, p_clone)); + } + + return ret = MPP_OK; +__FAILED: + return ret; +} + +static void malloc_dpb_memory_index(H264dVideoCtx_t *p_Vid, RK_S32 structure, RK_U8 combine_flag, RK_S32 layer_id) +{ + RK_U8 idx = 1; + H264_DpbMark_t *pmem_dpb = p_Vid->p_Dec->dpb_mark; + + if (!combine_flag) //--- malloc + { + while (pmem_dpb[idx].top_used || pmem_dpb[idx].bot_used) + { + idx++; + } + ASSERT(idx <= MAX_DPB_SIZE); + p_Vid->active_dpb_mark[layer_id] = &pmem_dpb[idx]; + } + //--- index add ---- + if (structure == FRAME || structure == TOP_FIELD) + { + p_Vid->active_dpb_mark[layer_id]->top_used += 1; + } + if (structure == FRAME || structure == BOTTOM_FIELD) + { + p_Vid->active_dpb_mark[layer_id]->bot_used += 1; + } +} + +static MPP_RET alloc_decpic(H264_SLICE_t *currSlice) +{ + RK_S32 combine_flag = 0; + H264_StorePic_t *dec_picture = NULL; + MPP_RET ret = MPP_ERR_UNKNOW; + H264dVideoCtx_t *p_Vid = currSlice->p_Vid; + H264_SPS_t *active_sps = p_Vid->active_sps; + H264_DpbBuf_t *p_Dpb = currSlice->p_Dpb; + + dec_picture = alloc_storable_picture(p_Vid, currSlice->structure); + MEM_CHECK(ret, dec_picture); + currSlice->toppoc = p_Vid->last_toppoc[currSlice->layer_id]; + currSlice->bottompoc = p_Vid->last_bottompoc[currSlice->layer_id]; + currSlice->framepoc = p_Vid->last_framepoc[currSlice->layer_id]; + currSlice->ThisPOC = p_Vid->last_thispoc[currSlice->layer_id]; + FUN_CHECK(ret = decode_poc(p_Vid, currSlice)); //!< calculate POC + + dec_picture->top_poc = currSlice->toppoc; + dec_picture->bottom_poc = currSlice->bottompoc; + dec_picture->frame_poc = currSlice->framepoc; + dec_picture->ThisPOC = currSlice->ThisPOC; + + p_Vid->last_toppoc[currSlice->layer_id] = currSlice->toppoc; + p_Vid->last_bottompoc[currSlice->layer_id] = currSlice->bottompoc; + p_Vid->last_framepoc[currSlice->layer_id] = currSlice->framepoc; + p_Vid->last_thispoc[currSlice->layer_id] = currSlice->ThisPOC; + + if (currSlice->structure == FRAME) + { + if (currSlice->mb_aff_frame_flag) + { + dec_picture->iCodingType = FRAME_MB_PAIR_CODING; + } + else + { + dec_picture->iCodingType = FRAME_CODING; + } + } + else + { + dec_picture->iCodingType = FIELD_CODING; + } + dec_picture->layer_id = currSlice->layer_id; + dec_picture->view_id = currSlice->view_id; + dec_picture->inter_view_flag = currSlice->inter_view_flag; + dec_picture->anchor_pic_flag = currSlice->anchor_pic_flag; + if (dec_picture->layer_id == 1) + { + if ((p_Vid->profile_idc == MVC_HIGH) || (p_Vid->profile_idc == STEREO_HIGH)) + { + FUN_CHECK(ret = init_mvc_picture(currSlice)); + } + } + if (currSlice->structure == TOP_FIELD) + { + dec_picture->poc = currSlice->toppoc; + } + else if (currSlice->structure == BOTTOM_FIELD) + { + dec_picture->poc = currSlice->bottompoc; + } + else if (currSlice->structure == FRAME) + { + dec_picture->poc = currSlice->framepoc; + } + else + { + ret = MPP_OK; + goto __FAILED; + } + dec_picture->slice_type = p_Vid->type; + dec_picture->used_for_reference = (currSlice->nal_reference_idc != 0); + dec_picture->idr_flag = currSlice->idr_flag; + dec_picture->no_output_of_prior_pics_flag = currSlice->no_output_of_prior_pics_flag; + dec_picture->long_term_reference_flag = currSlice->long_term_reference_flag; + dec_picture->adaptive_ref_pic_buffering_flag = currSlice->adaptive_ref_pic_buffering_flag; + dec_picture->dec_ref_pic_marking_buffer = currSlice->dec_ref_pic_marking_buffer; + + currSlice->dec_ref_pic_marking_buffer = NULL; + dec_picture->mb_aff_frame_flag = currSlice->mb_aff_frame_flag; + dec_picture->PicWidthInMbs = p_Vid->PicWidthInMbs; + dec_picture->pic_num = currSlice->frame_num; + dec_picture->frame_num = currSlice->frame_num; + dec_picture->chroma_format_idc = active_sps->chroma_format_idc; + + dec_picture->frame_mbs_only_flag = active_sps->frame_mbs_only_flag; + dec_picture->frame_cropping_flag = active_sps->frame_cropping_flag; + if (dec_picture->frame_cropping_flag) + { + dec_picture->frame_crop_left_offset = active_sps->frame_crop_left_offset; + dec_picture->frame_crop_right_offset = active_sps->frame_crop_right_offset; + dec_picture->frame_crop_top_offset = active_sps->frame_crop_top_offset; + dec_picture->frame_crop_bottom_offset = active_sps->frame_crop_bottom_offset; + } + combine_flag = get_filed_dpb_combine_flag(p_Dpb, dec_picture); + dec_picture->mem_malloc_type = Mem_Malloc; + malloc_dpb_memory_index(p_Vid, dec_picture->structure, combine_flag, dec_picture->layer_id); // malloc dpb_memory + dec_picture->mem_mark = p_Vid->active_dpb_mark[currSlice->layer_id]; + dec_picture->colmv_no_used_flag = 0; + + p_Vid->last_pic_structure = dec_picture->structure; + p_Vid->dec_picture = dec_picture; + + return ret = MPP_OK; +__FAILED: + mpp_free(dec_picture); + ASSERT(0); + + return ret; +} + +static void update_pic_num(H264_SLICE_t *currSlice) +{ + RK_U32 i = 0; + H264dVideoCtx_t *p_Vid = currSlice->p_Vid; + H264_DpbBuf_t *p_Dpb = currSlice->p_Dpb; + H264_SPS_t *active_sps = p_Vid->active_sps; + + RK_S32 add_top = 0, add_bottom = 0; + RK_S32 max_frame_num = 1 << (active_sps->log2_max_frame_num_minus4 + 4); + + if (currSlice->idr_flag) + { + return; + } + if (currSlice->structure == FRAME) + { + for (i = 0; iref_frames_in_buffer; i++) + { + if (p_Dpb->fs_ref[i]->is_used == 3) + { + if ((p_Dpb->fs_ref[i]->frame->used_for_reference) && (!p_Dpb->fs_ref[i]->frame->is_long_term)) + { + if ((RK_S32)p_Dpb->fs_ref[i]->frame_num > currSlice->frame_num) + { + p_Dpb->fs_ref[i]->frame_num_wrap = p_Dpb->fs_ref[i]->frame_num - max_frame_num; + } + else + { + p_Dpb->fs_ref[i]->frame_num_wrap = p_Dpb->fs_ref[i]->frame_num; + } + p_Dpb->fs_ref[i]->frame->pic_num = p_Dpb->fs_ref[i]->frame_num_wrap; + } + } + } + //!< update long_term_pic_num + for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) + { + if (p_Dpb->fs_ltref[i]->is_used == 3) + { + if (p_Dpb->fs_ltref[i]->frame->is_long_term) + { + p_Dpb->fs_ltref[i]->frame->long_term_pic_num = p_Dpb->fs_ltref[i]->frame->long_term_frame_idx; + } + } + } + } + else + { + if (currSlice->structure == TOP_FIELD) + { + add_top = 1; + add_bottom = 0; + } + else + { + add_top = 0; + add_bottom = 1; + } + + for (i = 0; iref_frames_in_buffer; i++) + { + if (p_Dpb->fs_ref[i]->is_reference) + { + if ((RK_S32)p_Dpb->fs_ref[i]->frame_num > currSlice->frame_num) + { + p_Dpb->fs_ref[i]->frame_num_wrap = p_Dpb->fs_ref[i]->frame_num - max_frame_num; + } + else + { + p_Dpb->fs_ref[i]->frame_num_wrap = p_Dpb->fs_ref[i]->frame_num; + } + if (p_Dpb->fs_ref[i]->is_reference & 1) + { + p_Dpb->fs_ref[i]->top_field->pic_num = (2 * p_Dpb->fs_ref[i]->frame_num_wrap) + add_top; + } + if (p_Dpb->fs_ref[i]->is_reference & 2) + { + p_Dpb->fs_ref[i]->bottom_field->pic_num = (2 * p_Dpb->fs_ref[i]->frame_num_wrap) + add_bottom; + } + } + } + //!< update long_term_pic_num + for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) + { + if (p_Dpb->fs_ltref[i]->is_long_term & 1) + { + p_Dpb->fs_ltref[i]->top_field->long_term_pic_num = 2 * p_Dpb->fs_ltref[i]->top_field->long_term_frame_idx + add_top; + } + if (p_Dpb->fs_ltref[i]->is_long_term & 2) + { + p_Dpb->fs_ltref[i]->bottom_field->long_term_pic_num = 2 * p_Dpb->fs_ltref[i]->bottom_field->long_term_frame_idx + add_bottom; + } + } + } +} + +static MPP_RET init_picture_decoding(H264dVideoCtx_t *p_Vid, H264_SLICE_t *pSlice) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + if (pSlice->layer_id && !pSlice->svc_extension_flag && !pSlice->mvcExt.non_idr_flag) //!< MVC idr_flag==1 + { + ASSERT(pSlice->layer_id == 1); + FUN_CHECK(ret = idr_memory_management(p_Vid->p_Dpb_layer[pSlice->layer_id], p_Vid->dec_picture)); + } + update_ref_list(p_Vid->p_Dpb_layer[pSlice->layer_id]); + update_ltref_list(p_Vid->p_Dpb_layer[pSlice->layer_id]); + update_pic_num(pSlice); + + return ret = MPP_OK; +__FAILED: + ASSERT(0); + return ret; +} + + +static RK_S32 compare_pic_by_pic_num_desc(const void *arg1, const void *arg2) +{ + RK_S32 pic_num1 = (*(H264_StorePic_t**)arg1)->pic_num; + RK_S32 pic_num2 = (*(H264_StorePic_t**)arg2)->pic_num; + + if (pic_num1 < pic_num2) + return 1; + if (pic_num1 > pic_num2) + return -1; + else + return 0; +} + +static RK_S32 compare_pic_by_lt_pic_num_asc(const void *arg1, const void *arg2) +{ + RK_S32 long_term_pic_num1 = (*(H264_StorePic_t**)arg1)->long_term_pic_num; + RK_S32 long_term_pic_num2 = (*(H264_StorePic_t**)arg2)->long_term_pic_num; + + if (long_term_pic_num1 < long_term_pic_num2) + return -1; + if (long_term_pic_num1 > long_term_pic_num2) + return 1; + else + return 0; +} + +static RK_S32 compare_fs_by_frame_num_desc(const void *arg1, const void *arg2) +{ + RK_S32 frame_num_wrap1 = (*(H264_FrameStore_t**)arg1)->frame_num_wrap; + RK_S32 frame_num_wrap2 = (*(H264_FrameStore_t**)arg2)->frame_num_wrap; + if (frame_num_wrap1 < frame_num_wrap2) + return 1; + if (frame_num_wrap1 > frame_num_wrap2) + return -1; + else + return 0; +} + +static RK_S32 compare_fs_by_lt_pic_idx_asc(const void *arg1, const void *arg2) +{ + RK_S32 long_term_frame_idx1 = (*(H264_FrameStore_t**)arg1)->long_term_frame_idx; + RK_S32 long_term_frame_idx2 = (*(H264_FrameStore_t**)arg2)->long_term_frame_idx; + + if (long_term_frame_idx1 < long_term_frame_idx2) + return -1; + else if (long_term_frame_idx1 > long_term_frame_idx2) + return 1; + else + return 0; +} + +static RK_U32 is_long_ref(H264_StorePic_t *s) +{ + return ((s->used_for_reference) && (s->is_long_term)); +} + +static RK_U32 is_short_ref(H264_StorePic_t *s) +{ + return ((s->used_for_reference) && (!(s->is_long_term))); +} + +static void gen_pic_list_from_frame_list(RK_S32 currStructure, H264_FrameStore_t **fs_list, + RK_S32 list_idx, H264_StorePic_t **list, RK_U8 *list_size, RK_U32 long_term) +{ + RK_S32 top_idx = 0; + RK_S32 bot_idx = 0; + + RK_U32(*is_ref)(H264_StorePic_t *s) = (long_term) ? is_long_ref : is_short_ref; + + if (currStructure == TOP_FIELD) + { + while ((top_idx < list_idx) || (bot_idx < list_idx)) + { + for (; top_idx < list_idx; top_idx++) + { + if (fs_list[top_idx]->is_used & 1) + { + if (is_ref(fs_list[top_idx]->top_field)) + { + //top_field; + (*list_size)++; + top_idx++; + break; + } + } + } + for (; bot_idx < list_idx; bot_idx++) + { + if (fs_list[bot_idx]->is_used & 2) + { + if (is_ref(fs_list[bot_idx]->bottom_field)) + { + //bottom_field; + (*list_size)++; + bot_idx++; + break; + } + } + } + } + } + if (currStructure == BOTTOM_FIELD) + { + while ((top_idx < list_idx) || (bot_idx < list_idx)) + { + for (; bot_idx < list_idx; bot_idx++) + { + if (fs_list[bot_idx]->is_used & 2) + { + if (is_ref(fs_list[bot_idx]->bottom_field)) + { + // short term ref pic + list[(RK_S16)*list_size] = fs_list[bot_idx]->bottom_field; + (*list_size)++; + bot_idx++; + break; + } + } + } + for (; top_idx < list_idx; top_idx++) + { + if (fs_list[top_idx]->is_used & 1) + { + if (is_ref(fs_list[top_idx]->top_field)) + { + //!< short term ref pic + list[(RK_S16)*list_size] = fs_list[top_idx]->top_field; + (*list_size)++; + top_idx++; + break; + } + } + } + } + } +} + +static RK_U32 is_view_id_in_ref_view_list(RK_S32 view_id, RK_S32 *ref_view_id, RK_S32 num_ref_views) +{ + RK_S32 i; + for (i = 0; i < num_ref_views; i++) + { + if (view_id == ref_view_id[i]) + break; + } + + return (num_ref_views && (i < num_ref_views)); +} + +static MPP_RET append_interview_list(H264_DpbBuf_t *p_Dpb, + PictureStructure currPicStructure, RK_S32 list_idx, H264_FrameStore_t **list, + RK_S32 *listXsize, RK_S32 currPOC, RK_S32 curr_layer_id, RK_S32 anchor_pic_flag) +{ + RK_S32 poc = 0; + RK_S32 fld_idx = 0; + RK_U32 pic_avail = 0; + RK_S32 num_ref_views = 0; + RK_S32 *ref_view_id = NULL; + MPP_RET ret = MPP_ERR_UNKNOW; + RK_S32 iVOIdx = curr_layer_id; + H264_FrameStore_t *fs = p_Dpb->fs_ilref[0]; + H264dVideoCtx_t *p_Vid = p_Dpb->p_Vid; + + VAL_CHECK(ret, iVOIdx >= 0); //!< Error: iVOIdx: %d is not less than 0 + if (anchor_pic_flag) + { + num_ref_views = list_idx ? p_Vid->active_subsps->num_anchor_refs_l1[iVOIdx] : p_Vid->active_subsps->num_anchor_refs_l0[iVOIdx]; + ref_view_id = list_idx ? p_Vid->active_subsps->anchor_ref_l1[iVOIdx] : p_Vid->active_subsps->anchor_ref_l0[iVOIdx]; + } + else + { + num_ref_views = list_idx ? p_Vid->active_subsps->num_non_anchor_refs_l1[iVOIdx] : p_Vid->active_subsps->num_non_anchor_refs_l0[iVOIdx]; + ref_view_id = list_idx ? p_Vid->active_subsps->non_anchor_ref_l1[iVOIdx] : p_Vid->active_subsps->non_anchor_ref_l0[iVOIdx]; + } + + if (currPicStructure == BOTTOM_FIELD) + fld_idx = 1; + else + fld_idx = 0; + + if (currPicStructure == FRAME) + { + pic_avail = (fs->is_used == 3); + if (pic_avail) + { + poc = fs->frame->is_mmco_5 ? fs->frame->poc_mmco5 : fs->frame->poc; + } + } + else if (currPicStructure == TOP_FIELD) + { + pic_avail = fs->is_used & 1; + if (pic_avail) + { + poc = fs->top_field->is_mmco_5 ? fs->top_field->top_poc_mmco5 : fs->top_field->poc; + } + } + else if (currPicStructure == BOTTOM_FIELD) + { + pic_avail = fs->is_used & 2; + if (pic_avail) + { + poc = fs->bottom_field->is_mmco_5 ? fs->bottom_field->bot_poc_mmco5 : fs->bottom_field->poc; + } + } + else + { + pic_avail = 0; + } + + if (pic_avail && fs->inter_view_flag[fld_idx]) + { + if (poc == currPOC) + { + if (is_view_id_in_ref_view_list(fs->view_id, ref_view_id, num_ref_views)) + { + //!< add one inter-view reference; + list[*listXsize] = fs; + //!< next; + (*listXsize)++; + } + } + } + return ret = MPP_OK; +__FAILED: + ASSERT(0); + return ret; +} + +static void gen_pic_list_from_frame_interview_list(RK_S32 currStructure, + H264_FrameStore_t **fs_list, RK_S32 list_idx, H264_StorePic_t **list, RK_U8 *list_size) +{ + RK_S32 i; + + if (currStructure == TOP_FIELD) + { + for (i = 0; i < list_idx; i++) + { + list[(RK_S32)(*list_size)] = fs_list[i]->top_field; + (*list_size)++; + } + } + if (currStructure == BOTTOM_FIELD) + { + for (i = 0; i < list_idx; i++) + { + list[(RK_S32)(*list_size)] = fs_list[i]->bottom_field; + (*list_size)++; + } + } +} + +static RK_S32 compare_pic_by_poc_desc(const void *arg1, const void *arg2) +{ + RK_S32 poc1 = (*(H264_StorePic_t**)arg1)->poc; + RK_S32 poc2 = (*(H264_StorePic_t**)arg2)->poc; + + if (poc1 < poc2) + return 1; + if (poc1 > poc2) + return -1; + else + return 0; +} + +static RK_S32 compare_pic_by_poc_asc(const void *arg1, const void *arg2) +{ + RK_S32 poc1 = (*(H264_StorePic_t**)arg1)->poc; + RK_S32 poc2 = (*(H264_StorePic_t**)arg2)->poc; + + if (poc1 < poc2) + return -1; + if (poc1 > poc2) + return 1; + else + return 0; +} + +static RK_S32 compare_fs_by_poc_desc(const void *arg1, const void *arg2) +{ + RK_S32 poc1 = (*(H264_FrameStore_t**)arg1)->poc; + RK_S32 poc2 = (*(H264_FrameStore_t**)arg2)->poc; + + if (poc1 < poc2) + return 1; + else if (poc1 > poc2) + return -1; + else + return 0; +} + +static RK_S32 compare_fs_by_poc_asc(const void *arg1, const void *arg2) +{ + RK_S32 poc1 = (*(H264_FrameStore_t**)arg1)->poc; + RK_S32 poc2 = (*(H264_FrameStore_t**)arg2)->poc; + + if (poc1 < poc2) + return -1; + else if (poc1 > poc2) + return 1; + else + return 0; +} + +static MPP_RET init_lists_p_slice_mvc(H264_SLICE_t *currSlice) +{ + RK_U32 i = 0; + RK_S32 list0idx = 0; + RK_S32 listltidx = 0; + H264_FrameStore_t **fs_list0 = 0; + H264_FrameStore_t **fs_listlt = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + H264dVideoCtx_t *p_Vid = currSlice->p_Vid; + H264_DpbBuf_t *p_Dpb = currSlice->p_Dpb; + RK_S32 currPOC = currSlice->ThisPOC; + RK_S32 anchor_pic_flag = currSlice->anchor_pic_flag; + + currSlice->listinterviewidx0 = 0; + currSlice->listinterviewidx1 = 0; + + if (currSlice->structure == FRAME) + { + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) + { + if (p_Dpb->fs_ref[i]->is_used == 3) + { + if ((p_Dpb->fs_ref[i]->frame->used_for_reference) && (!p_Dpb->fs_ref[i]->frame->is_long_term)) + { + currSlice->listP[0][list0idx++] = p_Dpb->fs_ref[i]->frame; + } + } + } + // order list 0 by PicNum + qsort((void *)currSlice->listP[0], list0idx, sizeof(H264_StorePic_t*), compare_pic_by_pic_num_desc); + currSlice->listXsizeP[0] = (RK_U8)list0idx; + // long term handling + for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) + { + if (p_Dpb->fs_ltref[i]->is_used == 3) + { + if (p_Dpb->fs_ltref[i]->frame->is_long_term) + { + currSlice->listP[0][list0idx++] = p_Dpb->fs_ltref[i]->frame; + } + } + } + qsort((void *)&currSlice->listP[0][(RK_S16)currSlice->listXsizeP[0]], + list0idx - currSlice->listXsizeP[0], sizeof(H264_StorePic_t*), compare_pic_by_lt_pic_num_asc); + currSlice->listXsizeP[0] = (RK_U8)list0idx; + } + else + { + fs_list0 = mpp_calloc(H264_FrameStore_t*, p_Dpb->size); + fs_listlt = mpp_calloc(H264_FrameStore_t*, p_Dpb->size); + MEM_CHECK(ret, fs_list0 && fs_listlt); + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) + { + if (p_Dpb->fs_ref[i]->is_reference) + { + fs_list0[list0idx++] = p_Dpb->fs_ref[i]; + } + } + qsort((void *)fs_list0, list0idx, sizeof(H264_FrameStore_t*), compare_fs_by_frame_num_desc); + currSlice->listXsizeP[0] = 0; + gen_pic_list_from_frame_list(currSlice->structure, fs_list0, list0idx, currSlice->listP[0], &currSlice->listXsizeP[0], 0); + // long term handling + for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) + { + fs_listlt[listltidx++] = p_Dpb->fs_ltref[i]; + } + qsort((void *)fs_listlt, listltidx, sizeof(H264_FrameStore_t*), compare_fs_by_lt_pic_idx_asc); + gen_pic_list_from_frame_list(currSlice->structure, fs_listlt, listltidx, currSlice->listP[0], &currSlice->listXsizeP[0], 1); + mpp_free(fs_list0); + mpp_free(fs_listlt); + } + + currSlice->listXsizeP[1] = 0; + if (currSlice->svc_extension_flag == 0) + { + RK_S32 curr_layer_id = currSlice->layer_id; + currSlice->fs_listinterview0 = mpp_calloc(H264_FrameStore_t*, p_Dpb->size); + MEM_CHECK(ret, currSlice->fs_listinterview0); + list0idx = currSlice->listXsizeP[0]; + if (currSlice->structure == FRAME) + { + FUN_CHECK(ret = append_interview_list(p_Vid->p_Dpb_layer[1], 0, 0, + currSlice->fs_listinterview0, &currSlice->listinterviewidx0, currPOC, curr_layer_id, anchor_pic_flag)); + for (i = 0; i < (RK_U32)currSlice->listinterviewidx0; i++) + { + currSlice->listP[0][list0idx++] = currSlice->fs_listinterview0[i]->frame; + } + currSlice->listXsizeP[0] = (RK_U8)list0idx; + } + else + { + FUN_CHECK(ret = append_interview_list(p_Vid->p_Dpb_layer[1], currSlice->structure, 0, + currSlice->fs_listinterview0, &currSlice->listinterviewidx0, currPOC, curr_layer_id, anchor_pic_flag)); + gen_pic_list_from_frame_interview_list(currSlice->structure, currSlice->fs_listinterview0, + currSlice->listinterviewidx0, currSlice->listP[0], &currSlice->listXsizeP[0]); + } + } + // set the unused list entries to NULL + for (i = currSlice->listXsizeP[0]; i < (MAX_LIST_SIZE); i++) + { + currSlice->listP[0][i] = p_Vid->no_reference_picture; + } + for (i = currSlice->listXsizeP[1]; i < (MAX_LIST_SIZE); i++) + { + currSlice->listP[1][i] = p_Vid->no_reference_picture; + } + mpp_free(currSlice->fs_listinterview0); + + return ret = MPP_OK; +__FAILED: + ASSERT(0); + mpp_free(fs_list0); + mpp_free(fs_listlt); + mpp_free(currSlice->fs_listinterview0); + + return ret; +} + +static MPP_RET init_lists_b_slice_mvc(H264_SLICE_t *currSlice) +{ + RK_U32 i = 0; + RK_S32 j = 0; + RK_S32 list0idx = 0; + RK_S32 list0idx_1 = 0; + RK_S32 listltidx = 0; + H264_FrameStore_t **fs_list0 = NULL; + H264_FrameStore_t **fs_list1 = NULL; + H264_FrameStore_t **fs_listlt = NULL; + MPP_RET ret = MPP_ERR_UNKNOW; + + H264dVideoCtx_t *p_Vid = currSlice->p_Vid; + H264_DpbBuf_t *p_Dpb = currSlice->p_Dpb; + RK_S32 currPOC = currSlice->ThisPOC; + RK_S32 anchor_pic_flag = currSlice->anchor_pic_flag; + + currSlice->listinterviewidx0 = 0; + currSlice->listinterviewidx1 = 0; + // B-Slice + if (currSlice->structure == FRAME) + { + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) + { + if (p_Dpb->fs_ref[i]->is_used == 3) + { + if ((p_Dpb->fs_ref[i]->frame->used_for_reference) && (!p_Dpb->fs_ref[i]->frame->is_long_term)) + { + if (currSlice->framepoc >= p_Dpb->fs_ref[i]->frame->poc) + { + currSlice->listB[0][list0idx++] = p_Dpb->fs_ref[i]->frame; + } + } + } + } + qsort((void *)currSlice->listB[0], list0idx, sizeof(H264_StorePic_t*), compare_pic_by_poc_desc); + list0idx_1 = list0idx; + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) + { + if (p_Dpb->fs_ref[i]->is_used == 3) + { + if ((p_Dpb->fs_ref[i]->frame->used_for_reference) && (!p_Dpb->fs_ref[i]->frame->is_long_term)) + { + if (currSlice->framepoc < p_Dpb->fs_ref[i]->frame->poc) + { + currSlice->listB[0][list0idx++] = p_Dpb->fs_ref[i]->frame; + } + } + } + } + qsort((void *)&currSlice->listB[0][list0idx_1], list0idx - list0idx_1, sizeof(H264_StorePic_t*), compare_pic_by_poc_asc); + + for (j = 0; j < list0idx_1; j++) + { + currSlice->listB[1][list0idx - list0idx_1 + j] = currSlice->listB[0][j]; + } + for (j = list0idx_1; j < list0idx; j++) + { + currSlice->listB[1][j - list0idx_1] = currSlice->listB[0][j]; + } + currSlice->listXsizeB[0] = currSlice->listXsizeB[1] = (RK_U8)list0idx; + // long term handling + for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) + { + if (p_Dpb->fs_ltref[i]->is_used == 3) + { + if (p_Dpb->fs_ltref[i]->frame->is_long_term) + { + currSlice->listB[0][list0idx] = p_Dpb->fs_ltref[i]->frame; + currSlice->listB[1][list0idx++] = p_Dpb->fs_ltref[i]->frame; + } + } + } + qsort((void *)&currSlice->listB[0][(RK_S16)currSlice->listXsizeB[0]], + list0idx - currSlice->listXsizeB[0], sizeof(H264_StorePic_t*), compare_pic_by_lt_pic_num_asc); + qsort((void *)&currSlice->listB[1][(RK_S16)currSlice->listXsizeB[0]], + list0idx - currSlice->listXsizeB[0], sizeof(H264_StorePic_t*), compare_pic_by_lt_pic_num_asc); + currSlice->listXsizeB[0] = currSlice->listXsizeB[1] = (RK_U8)list0idx; + } + else + { + fs_list0 = mpp_calloc(H264_FrameStore_t*, p_Dpb->size); + fs_list1 = mpp_calloc(H264_FrameStore_t*, p_Dpb->size); + fs_listlt = mpp_calloc(H264_FrameStore_t*, p_Dpb->size); + MEM_CHECK(ret, fs_list0 && fs_list1 && fs_listlt); + currSlice->listXsizeB[0] = 0; + currSlice->listXsizeB[1] = 1; + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) + { + if (p_Dpb->fs_ref[i]->is_used) + { + if (currSlice->ThisPOC >= p_Dpb->fs_ref[i]->poc) + { + fs_list0[list0idx++] = p_Dpb->fs_ref[i]; + } + } + } + qsort((void *)fs_list0, list0idx, sizeof(H264_FrameStore_t*), compare_fs_by_poc_desc); + list0idx_1 = list0idx; + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) + { + if (p_Dpb->fs_ref[i]->is_used) + { + if (currSlice->ThisPOC < p_Dpb->fs_ref[i]->poc) + { + fs_list0[list0idx++] = p_Dpb->fs_ref[i]; + } + } + } + qsort((void *)&fs_list0[list0idx_1], list0idx - list0idx_1, sizeof(H264_FrameStore_t*), compare_fs_by_poc_asc); + + for (j = 0; j < list0idx_1; j++) + { + fs_list1[list0idx - list0idx_1 + j] = fs_list0[j]; + } + for (j = list0idx_1; j < list0idx; j++) + { + fs_list1[j - list0idx_1] = fs_list0[j]; + } + currSlice->listXsizeB[0] = 0; + currSlice->listXsizeB[1] = 0; + gen_pic_list_from_frame_list(currSlice->structure, fs_list0, list0idx, currSlice->listB[0], &currSlice->listXsizeB[0], 0); + gen_pic_list_from_frame_list(currSlice->structure, fs_list1, list0idx, currSlice->listB[1], &currSlice->listXsizeB[1], 0); + + // long term handling + for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) + { + fs_listlt[listltidx++] = p_Dpb->fs_ltref[i]; + } + qsort((void *)fs_listlt, listltidx, sizeof(H264_FrameStore_t*), compare_fs_by_lt_pic_idx_asc); + + gen_pic_list_from_frame_list(currSlice->structure, fs_listlt, listltidx, currSlice->listB[0], &currSlice->listXsizeB[0], 1); + gen_pic_list_from_frame_list(currSlice->structure, fs_listlt, listltidx, currSlice->listB[1], &currSlice->listXsizeB[1], 1); + + mpp_free(fs_list0); + mpp_free(fs_list1); + mpp_free(fs_listlt); + } + if ((currSlice->listXsizeB[0] == currSlice->listXsizeB[1]) && (currSlice->listXsizeB[0] > 1)) + { + // check if lists are identical, if yes swap first two elements of currSlice->listX[1] + RK_S32 diff = 0; + for (j = 0; j < currSlice->listXsizeB[0]; j++) + { + if (currSlice->listB[0][j] != currSlice->listB[1][j]) + { + diff = 1; + break; + } + } + if (!diff) + { + H264_StorePic_t *tmp_s = currSlice->listB[1][0]; + currSlice->listB[1][0] = currSlice->listB[1][1]; + currSlice->listB[1][1] = tmp_s; + } + } + if (currSlice->svc_extension_flag == 0) + { + RK_S32 curr_layer_id = currSlice->layer_id; + // B-Slice + currSlice->fs_listinterview0 = mpp_calloc(H264_FrameStore_t*, p_Dpb->size); + currSlice->fs_listinterview1 = mpp_calloc(H264_FrameStore_t*, p_Dpb->size); + MEM_CHECK(ret, currSlice->fs_listinterview0 && currSlice->fs_listinterview1); + list0idx = currSlice->listXsizeB[0]; + if (currSlice->structure == FRAME) + { + FUN_CHECK(ret = append_interview_list(p_Vid->p_Dpb_layer[1], 0, 0, + currSlice->fs_listinterview0, &currSlice->listinterviewidx0, currPOC, curr_layer_id, anchor_pic_flag)); + FUN_CHECK(ret = append_interview_list(p_Vid->p_Dpb_layer[1], 0, 1, + currSlice->fs_listinterview1, &currSlice->listinterviewidx1, currPOC, curr_layer_id, anchor_pic_flag)); + + for (i = 0; i < (RK_U32)currSlice->listinterviewidx0; i++) + { + currSlice->listB[0][list0idx++] = currSlice->fs_listinterview0[i]->frame; + } + currSlice->listXsizeB[0] = (RK_U8)list0idx; + list0idx = currSlice->listXsizeB[1]; + for (i = 0; i < (RK_U32)currSlice->listinterviewidx1; i++) + { + currSlice->listB[1][list0idx++] = currSlice->fs_listinterview1[i]->frame; + } + currSlice->listXsizeB[1] = (RK_U8)list0idx; + } + else + { + FUN_CHECK(ret = append_interview_list(p_Vid->p_Dpb_layer[1], currSlice->structure, 0, + currSlice->fs_listinterview0, &currSlice->listinterviewidx0, currPOC, curr_layer_id, anchor_pic_flag)); + gen_pic_list_from_frame_interview_list(currSlice->structure, currSlice->fs_listinterview0, + currSlice->listinterviewidx0, currSlice->listB[0], &currSlice->listXsizeB[0]); + FUN_CHECK(ret = append_interview_list(p_Vid->p_Dpb_layer[1], currSlice->structure, 1, + currSlice->fs_listinterview1, &currSlice->listinterviewidx1, currPOC, curr_layer_id, anchor_pic_flag)); + gen_pic_list_from_frame_interview_list(currSlice->structure, currSlice->fs_listinterview1, + currSlice->listinterviewidx1, currSlice->listB[1], &currSlice->listXsizeB[1]); + } + } + // set the unused list entries to NULL + for (i = currSlice->listXsizeB[0]; i < (MAX_LIST_SIZE); i++) + { + currSlice->listB[0][i] = p_Vid->no_reference_picture; + } + for (i = currSlice->listXsizeB[1]; i < (MAX_LIST_SIZE); i++) + { + currSlice->listB[1][i] = p_Vid->no_reference_picture; + } + mpp_free(currSlice->fs_listinterview0); + mpp_free(currSlice->fs_listinterview1); + + return ret = MPP_OK; +__FAILED: + ASSERT(0); + mpp_free(fs_list0); + mpp_free(fs_list1); + mpp_free(fs_listlt); + mpp_free(currSlice->fs_listinterview0); + mpp_free(currSlice->fs_listinterview1); + + return ret; +} + +/*! +*********************************************************************** +* \brief +* check parser is end and then configure register +*********************************************************************** +*/ +//extern "C" +MPP_RET init_picture(H264_SLICE_t *currSlice) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264_DecCtx_t *p_Dec = currSlice->p_Vid->p_Dec; + + FUN_CHECK(ret = alloc_decpic(currSlice)); + //!< idr_memory_management MVC_layer, idr_flag==1 + FUN_CHECK(ret = init_picture_decoding(currSlice->p_Vid, currSlice)); + //!< except (idr_flag ==1 && layer_id==0) + if (!currSlice->idr_flag || currSlice->layer_id) + { + FUN_CHECK(ret = init_lists_p_slice_mvc(currSlice)); + FUN_CHECK(ret = init_lists_b_slice_mvc(currSlice)); + } + prepare_init_dpb_info(currSlice); + fill_picparams(currSlice->p_Vid, &p_Dec->dxva_ctx->pp); + prepare_init_scanlist(currSlice); + fill_qmatrix(currSlice->p_Vid, &p_Dec->dxva_ctx->qm); + + return ret = MPP_OK; +__FAILED: + return ret; +} + diff --git a/mpp/codec/dec/h264/h264d_init.h b/mpp/codec/dec/h264/h264d_init.h new file mode 100644 index 00000000..e2a0591a --- /dev/null +++ b/mpp/codec/dec/h264/h264d_init.h @@ -0,0 +1,39 @@ +/* +* +* 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. +*/ + +#ifndef _H264D_INIT_H_ +#define _H264D_INIT_H_ + + +#include "rk_type.h" +#include "mpp_err.h" +#include "h264d_global.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + MPP_RET init_picture (H264_SLICE_t *currSlice); + +#ifdef __cplusplus +} +#endif + +//======================================== +#endif /* end of _RKV_H264_DECODER_INIT_H_ */ + diff --git a/mpp/codec/dec/h264/h264d_log.c b/mpp/codec/dec/h264/h264d_log.c index ab783642..0f05dce5 100644 --- a/mpp/codec/dec/h264/h264d_log.c +++ b/mpp/codec/dec/h264/h264d_log.c @@ -26,7 +26,8 @@ #define LOG_BUF_SIZE 512 -#define GetBitVal(val, pos) ( ( (val)>>(pos) ) & 0x1 & (val) ) + +RK_U32 g_nalu_cnt = 0; const LogEnvStr_t logenv_name = { "h264d_log_help", @@ -67,8 +68,14 @@ const char *logctrl_name[LOG_MAX] = { "WRITE_REG ", }; +/*! +*********************************************************************** +* \brief +* get log env +*********************************************************************** +*/ -static MPP_RET get_logenv(LogEnv_t *env) +MPP_RET get_logenv(LogEnv_t *env) { //!< read env mpp_env_get_u32(logenv_name.help, &env->help, 0); @@ -83,8 +90,13 @@ static MPP_RET get_logenv(LogEnv_t *env) return MPP_OK; } - -static void print_env_help(LogEnv_t *env) +/*! +*********************************************************************** +* \brief +* print env help +*********************************************************************** +*/ +void print_env_help(LogEnv_t *env) { RK_U8 i = 0; (void)env; @@ -107,8 +119,13 @@ static void print_env_help(LogEnv_t *env) } fprintf(stdout, "------------------------------------------------- \n"); } - -static void show_env_flags(LogEnv_t *env) +/*! +*********************************************************************** +* \brief +* show env flags +*********************************************************************** +*/ +void show_env_flags(LogEnv_t *env) { RK_U8 i = 0; fprintf(stdout, "------------- h264d debug setting ------------- \n"); @@ -122,164 +139,31 @@ static void show_env_flags(LogEnv_t *env) } fprintf(stdout, "------------------------------------------------- \n"); } - -static MPP_RET explain_ctrl_flag(RK_U32 ctrl_val, LogFlag_t *pflag) +/*! +*********************************************************************** +* \brief +* explain log ctrl flag +*********************************************************************** +*/ +MPP_RET explain_ctrl_flag(RK_U32 ctrl_val, LogFlag_t *pflag) { pflag->print_en = GetBitVal(ctrl_val, LOG_PRINT ); pflag->write_en = GetBitVal(ctrl_val, LOG_WRITE ); pflag->debug_en = GetBitVal(ctrl_val, LOG_DEBUG_EN ) - && GetBitVal(ctrl_val, LOG_READ_NALU ) - && GetBitVal(ctrl_val, LOG_READ_SPS ) - && GetBitVal(ctrl_val, LOG_READ_SUBSPS ) - && GetBitVal(ctrl_val, LOG_READ_PPS ) - && GetBitVal(ctrl_val, LOG_READ_SLICE ) - && GetBitVal(ctrl_val, LOG_WRITE_SPSPPS ) - && GetBitVal(ctrl_val, LOG_WRITE_RPS ) - && GetBitVal(ctrl_val, LOG_WRITE_SCANLIST) - && GetBitVal(ctrl_val, LOG_WRITE_STEAM ) - && GetBitVal(ctrl_val, LOG_WRITE_REG ); + || GetBitVal(ctrl_val, LOG_READ_NALU ) + || GetBitVal(ctrl_val, LOG_READ_SPS ) + || GetBitVal(ctrl_val, LOG_READ_SUBSPS ) + || GetBitVal(ctrl_val, LOG_READ_PPS ) + || GetBitVal(ctrl_val, LOG_READ_SLICE ) + || GetBitVal(ctrl_val, LOG_WRITE_SPSPPS ) + || GetBitVal(ctrl_val, LOG_WRITE_RPS ) + || GetBitVal(ctrl_val, LOG_WRITE_SCANLIST) + || GetBitVal(ctrl_val, LOG_WRITE_STEAM ) + || GetBitVal(ctrl_val, LOG_WRITE_REG ); return MPP_OK; } -static void close_log_files(LogEnv_t *env) -{ - FCLOSE(env->fp_driver); - FCLOSE(env->fp_syn_parse); - FCLOSE(env->fp_syn_hal); - FCLOSE(env->fp_run_parse); - FCLOSE(env->fp_run_hal); -} -static MPP_RET open_log_files(LogEnv_t *env, LogFlag_t *pflag) -{ - char fname[128] = { 0 }; - - INP_CHECK(!pflag->write_en); - - //!< runlog file - if (GetBitVal(env->ctrl, LOG_DEBUG_EN)) { - sprintf(fname, "%s/h264d_parse_runlog.dat", env->outpath); - FLE_CHECK(env->fp_run_parse = fopen(fname, "wb")); - sprintf(fname, "%s/h264d_hal_runlog.dat", env->outpath); - FLE_CHECK(env->fp_run_hal = fopen(fname, "wb")); - } - //!< fpga drive file - if (GetBitVal(env->ctrl, LOG_FPGA)) { - sprintf(fname, "%s/h264d_driver_data.dat", env->outpath); - FLE_CHECK(env->fp_driver = fopen(fname, "wb")); - } - //!< read syntax - if ( GetBitVal(env->ctrl, LOG_READ_NALU ) - || GetBitVal(env->ctrl, LOG_READ_SPS ) - || GetBitVal(env->ctrl, LOG_READ_SUBSPS) - || GetBitVal(env->ctrl, LOG_READ_PPS ) - || GetBitVal(env->ctrl, LOG_READ_SLICE ) ) { - sprintf(fname, "%s/h264d_read_syntax.dat", env->outpath); - FLE_CHECK(env->fp_syn_parse = fopen(fname, "wb")); - } - //!< write syntax - if ( GetBitVal(env->ctrl, LOG_WRITE_SPSPPS ) - || GetBitVal(env->ctrl, LOG_WRITE_RPS ) - || GetBitVal(env->ctrl, LOG_WRITE_SCANLIST) - || GetBitVal(env->ctrl, LOG_WRITE_STEAM ) - || GetBitVal(env->ctrl, LOG_WRITE_REG ) ) { - sprintf(fname, "%s/h264d_write_syntax.dat", env->outpath); - FLE_CHECK(env->fp_syn_hal = fopen(fname, "wb")); - } - -__RETURN: - return MPP_OK; - -__FAILED: - return MPP_NOK; -} -/*! -*********************************************************************** -* \brief -* log deinit -*********************************************************************** -*/ -MPP_RET h264d_log_deinit(H264dLogCtx_t *logctx) -{ - close_log_files(&logctx->env); - - return MPP_OK; -} -/*! -*********************************************************************** -* \brief -* log init -*********************************************************************** -*/ -MPP_RET h264d_log_init(H264dLogCtx_t *logctx, LogCtx_t *logbuf) -{ - RK_U8 i = 0; - MPP_RET ret = MPP_NOK; - LogCtx_t *pcur = NULL; - - FUN_CHECK(ret = get_logenv(&logctx->env)); - if (logctx->env.help) { - print_env_help(&logctx->env); - } - if (logctx->env.show) { - show_env_flags(&logctx->env); - } - FUN_CHECK(ret = explain_ctrl_flag(logctx->env.ctrl, &logctx->log_flag)); - if ( !logctx->log_flag.debug_en - && !logctx->log_flag.print_en && !logctx->log_flag.write_en ) { - logctx->log_flag.debug_en = 0; - goto __RETURN; - } - logctx->log_flag.level = (1 << logctx->env.level) - 1; - //!< open file - FUN_CHECK(ret = open_log_files(&logctx->env, &logctx->log_flag)); - //!< set logctx - while (i < LOG_MAX) { - if (GetBitVal(logctx->env.ctrl, i)) { - pcur = logctx->parr[i] = &logbuf[i]; - pcur->tag = logctrl_name[i]; - pcur->flag = &logctx->log_flag; - - switch (i) { - case LOG_FPGA: - pcur->fp = logctx->env.fp_driver; - break; - case RUN_PARSE: - pcur->fp = logctx->env.fp_run_parse; - break; - case RUN_HAL: - pcur->fp = logctx->env.fp_run_hal; - break; - case LOG_READ_NALU: - case LOG_READ_SPS: - case LOG_READ_SUBSPS: - case LOG_READ_PPS: - case LOG_READ_SLICE: - pcur->fp = logctx->env.fp_syn_parse; - break; - case LOG_WRITE_SPSPPS: - case LOG_WRITE_RPS: - case LOG_WRITE_SCANLIST: - case LOG_WRITE_STEAM: - case LOG_WRITE_REG: - pcur->fp = logctx->env.fp_syn_hal; - default: - break; - } - } - i++; - } - -__RETURN: - return ret = MPP_OK; -__FAILED: - logctx->log_flag.debug_en = 0; - h264d_log_deinit(logctx); - - return ret; -} - - /*! *********************************************************************** * \brief @@ -305,7 +189,8 @@ void writelog(LogCtx_t *ctx, char *filename, RK_U32 line, char *loglevel, const printf("[ TAG = %s ], file: %s, line: %d, [ %s ], %s \n", ctx->tag, pfn, line, loglevel, argbuf); } if (ctx->fp && ctx->flag->write_en) { - fprintf(ctx->fp, "[ TAG = %s ], file: %s, line: %d, [ %s ], %s \n", ctx->tag, pfn, line, loglevel, argbuf); + fprintf(ctx->fp, "%s \n", argbuf); + //fprintf(ctx->fp, "[ TAG = %s ], file: %s, line: %d, [ %s ], %s \n", ctx->tag, pfn, line, loglevel, argbuf); fflush(ctx->fp); } va_end(argptr); diff --git a/mpp/codec/dec/h264/h264d_parse.c b/mpp/codec/dec/h264/h264d_parse.c index acbb7031..e4e5d793 100644 --- a/mpp/codec/dec/h264/h264d_parse.c +++ b/mpp/codec/dec/h264/h264d_parse.c @@ -16,18 +16,388 @@ */ #include #include + +#include "mpp_mem.h" +#include "mpp_packet.h" +#include "mpp_packet_impl.h" +#include "hal_task.h" + #include "h264d_parse.h" +#include "h264d_slice.h" +#include "h264d_sps.h" +#include "h264d_pps.h" +#include "h264d_sei.h" +#include "h264d_init.h" +#include "h264d_fill.h" +#define MODULE_TAG "h264d_parse" +static void reset_slice(H264dVideoCtx_t *p_Vid) +{ + RK_U32 i = 0, j = 0; + H264_SLICE_t *currSlice = &p_Vid->p_Cur->slice; + FunctionIn(p_Vid->p_Dec->logctx.parr[RUN_PARSE]); + memset(currSlice, 0, sizeof(H264_SLICE_t)); + //-- re-init parameters + currSlice->view_id = -1; + currSlice->p_Vid = p_Vid; + currSlice->p_Dec = p_Vid->p_Dec; + currSlice->p_Cur = p_Vid->p_Cur; + currSlice->p_Inp = p_Vid->p_Inp; + currSlice->logctx = &p_Vid->p_Dec->logctx; + + //--- reset listP listB + for (i = 0; i < 2; i++) + { + currSlice->listP[i] = p_Vid->p_Cur->listP[i]; + currSlice->listB[i] = p_Vid->p_Cur->listB[i]; + for (j = 0; j < MAX_LIST_SIZE; j++) + { + currSlice->listP[i][j] = NULL; + currSlice->listB[i][j] = NULL; + } + currSlice->listXsizeP[i] = 0; + currSlice->listXsizeB[i] = 0; + } + FunctionOut(p_Vid->p_Dec->logctx.parr[RUN_PARSE]); +} +static MPP_RET realloc_curstrearm_buffer(H264dCurStream_t *p_strm) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + p_strm->buf = mpp_realloc(p_strm->buf, RK_U8, p_strm->max_size + NALU_BUF_ADD_SIZE); + MEM_CHECK(ret, p_strm->buf); + p_strm->max_size += NALU_BUF_ADD_SIZE; + + return ret = MPP_OK; +__FAILED: + return ret; +} + +static void reset_nalu(H264_Nalu_t*p_nal, H264dCurStream_t *p_strm) +{ + if (p_strm->endcode_found) + { + p_strm->startcode_found = p_strm->endcode_found; + memset(p_nal, 0, sizeof(H264_Nalu_t)); + p_strm->endcode_found = 0; + } + p_nal->sodb_buf = p_strm->buf; +} + +static void find_prefix_code(RK_U8 *p_data, H264dCurStream_t *p_strm) +{ + p_strm->prefixdata[0] = p_strm->prefixdata[1]; + p_strm->prefixdata[1] = p_strm->prefixdata[2]; + p_strm->prefixdata[2] = *p_data; + + if (p_strm->prefixdata[0] == 0x00 + && p_strm->prefixdata[1] == 0x00 + && p_strm->prefixdata[2] == 0x01) + { + if (p_strm->startcode_found) + { + p_strm->endcode_found = 1; + } + else + { + p_strm->startcode_found = 1; + } + } +} -/*! -*********************************************************************** -* \brief -* get current data value, used in read sei syntax -*********************************************************************** -*/ - - +static MPP_RET read_nalu(H264_SLICE_t *currSlice) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + RK_U8 *p_curdata = NULL; + H264dLogCtx_t *logctx = currSlice->logctx; + H264_DecCtx_t *p_Dec = currSlice->p_Dec; + H264dCurCtx_t *p_Cur = currSlice->p_Cur; + H264dInputCtx_t *p_Inp = currSlice->p_Inp; + + FunctionIn(logctx->parr[RUN_PARSE]); + reset_nalu(&p_Cur->nalu, &p_Cur->strm); + while ((*p_Inp->in_size) > 0) + { + p_curdata = &p_Inp->in_buf[p_Cur->strm.offset++]; + (*p_Inp->in_size) -= 1; + + if (p_Cur->strm.startcode_found) + { + if (p_Cur->nalu.sodb_len >= p_Cur->strm.max_size) + { + FUN_CHECK(ret = realloc_curstrearm_buffer(&p_Cur->strm)); + p_Cur->nalu.sodb_buf = p_Cur->strm.buf; + } + p_Cur->nalu.sodb_buf[p_Cur->nalu.sodb_len++] = *p_curdata; + } + find_prefix_code(p_curdata, &p_Cur->strm); + if (p_Cur->strm.endcode_found) + { + p_Cur->nalu.sodb_len -= START_PREFIX_3BYTE; + while (p_Cur->nalu.sodb_buf[p_Cur->nalu.sodb_len - 1] == 0x00) //!< find non-zeros byte + { + p_Cur->nalu.sodb_len--; + } + p_Dec->nalu_ret = EndOfNalu; + break; + } + } + if (!(*p_Inp->in_size)) //!< check input + { + p_Cur->strm.offset = 0; + p_Cur->strm.endcode_found = (p_Inp->is_eos && p_Cur->nalu.sodb_len) ? 1 : p_Cur->strm.endcode_found; + p_Dec->nalu_ret = p_Inp->is_eos ? (p_Cur->nalu.sodb_len ? EndOfNalu : EndofStream) : HaveNoStream; + } + + FunctionIn(logctx->parr[RUN_PARSE]); + + return ret = MPP_OK; +__FAILED: + + return ret; +} + +static MPP_RET parser_nalu_header(H264_SLICE_t *currSlice) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + H264dLogCtx_t *logctx = currSlice->logctx; + H264dCurCtx_t *p_Cur = currSlice->p_Cur; + BitReadCtx_t *p_bitctx = &p_Cur->bitctx; + H264_Nalu_t *cur_nal = &p_Cur->nalu; + + FunctionIn(logctx->parr[RUN_PARSE]); + set_bitread_ctx(p_bitctx, cur_nal->sodb_buf, cur_nal->sodb_len); + set_bitread_logctx(p_bitctx, logctx->parr[LOG_READ_NALU]); + WRITE_LOG(p_bitctx, "================== NAL begin ==================="); + READ_BITS(ret, p_bitctx, 1, &cur_nal->forbidden_bit, "forbidden_bit"); + ASSERT(cur_nal->forbidden_bit == 0); + READ_BITS(ret, p_bitctx, 2, (RK_S32 *)&cur_nal->nal_reference_idc, "nal_ref_idc"); + READ_BITS(ret, p_bitctx, 5, (RK_S32 *)&cur_nal->nal_unit_type, "nal_unit_type"); + if (g_nalu_cnt == 321) + { + g_nalu_cnt = g_nalu_cnt; + } + cur_nal->ualu_header_bytes = 1; + currSlice->svc_extension_flag = -1; //!< initialize to -1 + if ((cur_nal->nal_unit_type == NALU_TYPE_PREFIX) || (cur_nal->nal_unit_type == NALU_TYPE_SLC_EXT)) + { + READ_ONEBIT(ret, p_bitctx, &currSlice->svc_extension_flag, "svc_extension_flag"); + if (currSlice->svc_extension_flag) + { + FPRINT(logctx->parr[LOG_READ_NALU]->fp, "g_nalu_cnt=%d, nalu_type=%d, len=%d \n", g_nalu_cnt++, cur_nal->nal_unit_type, cur_nal->sodb_len); + currSlice->mvcExt.valid = 0; + LogInfo(logctx->parr[RUN_PARSE], "svc_extension is not supported."); + goto __FAILED; + } + else //!< MVC + { + currSlice->mvcExt.valid = 1; + READ_ONEBIT(ret, p_bitctx, &currSlice->mvcExt.non_idr_flag, "nalu_type"); + READ_BITS(ret, p_bitctx, 6, &currSlice->mvcExt.priority_id, "priority_id"); + READ_BITS(ret, p_bitctx, 10, &currSlice->mvcExt.view_id, "view_id"); + READ_BITS(ret, p_bitctx, 3, &currSlice->mvcExt.temporal_id, "temporal_id"); + READ_ONEBIT(ret, p_bitctx, &currSlice->mvcExt.anchor_pic_flag, "anchor_pic_flag"); + READ_ONEBIT(ret, p_bitctx, &currSlice->mvcExt.inter_view_flag, "inter_view_flag"); + READ_ONEBIT(ret, p_bitctx, &currSlice->mvcExt.reserved_one_bit, "reserved_one_bit"); + ASSERT(currSlice->mvcExt.reserved_one_bit == 1); + currSlice->mvcExt.iPrefixNALU = (cur_nal->nal_unit_type == NALU_TYPE_PREFIX) ? 1 : 0; + if (cur_nal->nal_unit_type == NALU_TYPE_SLC_EXT) //!< combine NALU_TYPE_SLC_EXT into NALU_TYPE_SLICE + { + cur_nal->nal_unit_type = NALU_TYPE_SLICE; + } + FPRINT(logctx->parr[LOG_READ_NALU]->fp, "g_nalu_cnt=%d, nalu_type=%d, len=%d \n", g_nalu_cnt++, cur_nal->nal_unit_type, cur_nal->sodb_len); + } + cur_nal->ualu_header_bytes += 3; + } + else + { + FPRINT(logctx->parr[LOG_READ_NALU]->fp, "g_nalu_cnt=%d, nalu_type=%d, len=%d \n", g_nalu_cnt++, cur_nal->nal_unit_type, cur_nal->sodb_len); + } + set_bitread_ctx(p_bitctx, (cur_nal->sodb_buf + cur_nal->ualu_header_bytes), (cur_nal->sodb_len - cur_nal->ualu_header_bytes)); // reset + + FunctionOut(logctx->parr[RUN_PARSE]); + + return ret = MPP_OK; +__FAILED: + return ret; +} +static MPP_RET parser_nalu(H264_SLICE_t *currSlice) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + LogCtx_t *runlog = currSlice->logctx->parr[RUN_PARSE]; + FunctionIn(runlog); + FUN_CHECK(ret = parser_nalu_header(currSlice)); + //!< nalu_parse + switch (currSlice->p_Cur->nalu.nal_unit_type) + { + case NALU_TYPE_SLICE: + case NALU_TYPE_IDR: + FUN_CHECK(ret = process_slice(currSlice)); + if (currSlice->is_new_picture_flag) + { + currSlice->p_Dec->nalu_ret = StartOfPicture; + } + else + { + currSlice->p_Dec->nalu_ret = StartOfSlice; + } + LogTrace(runlog, "nalu_type=SLICE."); + break; + case NALU_TYPE_SPS: + FUN_CHECK(ret = process_sps(currSlice)); + currSlice->p_Dec->nalu_ret = NALU_SPS; + LogTrace(runlog, "nalu_type=SPS"); + break; + case NALU_TYPE_PPS: + FUN_CHECK(ret = process_pps(currSlice)); + currSlice->p_Dec->nalu_ret = NALU_PPS; + LogTrace(runlog, "nalu_type=PPS"); + break; + case NALU_TYPE_SUB_SPS: + FUN_CHECK(ret = process_subsps(currSlice)); + currSlice->p_Dec->nalu_ret = NALU_SubSPS; + LogTrace(runlog, "nalu_type=SUB_SPS"); + break; + case NALU_TYPE_SEI: + FUN_CHECK(ret = process_sei(currSlice)); + LogTrace(runlog, "nalu_type=SEI"); + currSlice->p_Dec->nalu_ret = NALU_SEI; + break; + case NALU_TYPE_SLC_EXT: + LogTrace(runlog, "Found NALU_TYPE_SLC_EXT."); + currSlice->p_Dec->nalu_ret = SkipNALU; + break; + case NALU_TYPE_PREFIX: + LogTrace(runlog, "Found NALU_TYPE_PREFIX."); + currSlice->p_Dec->nalu_ret = SkipNALU; + break; + case NALU_TYPE_AUD: + LogTrace(runlog, "Found NALU_TYPE_AUD."); + currSlice->p_Dec->nalu_ret = SkipNALU; + break; + case NALU_TYPE_EOSEQ: + LogTrace(runlog, "Found NALU_TYPE_EOSEQ."); + currSlice->p_Dec->nalu_ret = SkipNALU; + break; + case NALU_TYPE_EOSTREAM: + LogTrace(runlog, "Found NALU_TYPE_EOSTREAM."); + currSlice->p_Dec->nalu_ret = SkipNALU; + break; + case NALU_TYPE_FILL: + LogTrace(runlog, "Found NALU_TYPE_FILL."); + currSlice->p_Dec->nalu_ret = SkipNALU; + break; + case NALU_TYPE_VDRD: + LogTrace(runlog, "Found NALU_TYPE_VDRD."); + currSlice->p_Dec->nalu_ret = SkipNALU; + break; + case NALU_TYPE_DPA: + case NALU_TYPE_DPB: + case NALU_TYPE_DPC: + LogError(runlog, "Found NALU_TYPE_DPA DPB DPC, and not supported."); + currSlice->p_Dec->nalu_ret = NaluNotSupport; + break; + default: + currSlice->p_Dec->nalu_ret = SkipNALU; + break; + } + FunctionIn(runlog); + + return ret = MPP_OK; +__FAILED: + + return ret; +} +/*! +*********************************************************************** +* \brief +* loop function for parser +*********************************************************************** +*/ +MPP_RET parse_loop(H264_DecCtx_t *p_Dec) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + RK_U32 while_loop_flag = 1; + + + FunctionIn(p_Dec->logctx.parr[RUN_PARSE]); + //!< ==== parse loop ==== + while (while_loop_flag) + { + switch (p_Dec->next_state) + { + case SliceSTATE_ResetSlice: + reset_slice(p_Dec->p_Vid); + p_Dec->next_state = SliceSTATE_ReadNalu; + break; + case SliceSTATE_ReadNalu: + (ret = read_nalu(&p_Dec->p_Cur->slice)); + if (p_Dec->nalu_ret == EndOfNalu) + { + p_Dec->next_state = SliceSTATE_ParseNalu; + } + else if (p_Dec->nalu_ret == EndofStream) + { + p_Dec->next_state = SliceSTATE_RegisterOneFrame; + } + else if (p_Dec->nalu_ret == HaveNoStream) + { + while_loop_flag = 0; + } + break; + case SliceSTATE_ParseNalu: + (ret = parser_nalu(&p_Dec->p_Cur->slice)); + if (p_Dec->nalu_ret == StartOfSlice) + { + p_Dec->next_state = SliceSTATE_GetSliceData; + } + else if (p_Dec->nalu_ret == StartOfPicture) + { + if (p_Dec->first_frame_flag) + { + p_Dec->next_state = SliceSTATE_InitPicture; + p_Dec->first_frame_flag = 0; + } + else + { + p_Dec->next_state = SliceSTATE_RegisterOneFrame; + } + } + else + { + p_Dec->next_state = SliceSTATE_ReadNalu; + } + break; + case SliceSTATE_InitPicture: + (ret = init_picture(&p_Dec->p_Cur->slice)); + p_Dec->next_state = SliceSTATE_GetSliceData; + break; + case SliceSTATE_GetSliceData: + (ret = fill_slice(&p_Dec->p_Cur->slice, p_Dec->dxva_ctx)); + p_Dec->p_Vid->iNumOfSlicesDecoded++; + p_Dec->next_state = SliceSTATE_ResetSlice; + break; + case SliceSTATE_RegisterOneFrame: + commit_buffer(p_Dec->dxva_ctx); + while_loop_flag = 0; + p_Dec->parser_end_flag = 1; + p_Dec->next_state = SliceSTATE_InitPicture; + break; + default: + ret = MPP_NOK; + goto __FAILED; + } + } + FunctionIn(p_Dec->logctx.parr[RUN_PARSE]); +//__RETURN: + return ret = MPP_OK; +__FAILED: + + return ret; +} + + diff --git a/mpp/codec/dec/h264/h264d_parse.h b/mpp/codec/dec/h264/h264d_parse.h index 0ea4e3dd..61a3cad1 100644 --- a/mpp/codec/dec/h264/h264d_parse.h +++ b/mpp/codec/dec/h264/h264d_parse.h @@ -20,58 +20,7 @@ #include "rk_type.h" #include "mpp_err.h" - -typedef enum { - NALU_NULL = 0, - - //StreamError, - //HaveNoStream, - //NaluNotSupport, - //ReadNaluError, - //NALU_ERROR, - //NALU_OK, - //StartofNalu, - //EndofStream, - //ReallocBufError, - //MidOfNalu, - //EndOfNalu, - //StartOfPicture, - //StartOfSlice, - //SkipNALU, - //NALU_SPS, - //NALU_SubSPS, - //NALU_PPS, - //NALU_SEI, - - NALU_MAX, -} NALU_STATUS; - - -typedef enum Rkv_slice_state_t { - SliceSTATE_NULL = 0, - SliceSTATE_IDLE, - - //SliceSTATE_GetLastSlice, - SliceSTATE_ResetSlice, - //SliceSTATE_ReadNalu, - //SliceSTATE_ParseNalu, - //SliceSTATE_DecodeOneSlice, - //SliceSTATE_InitPicture, - //SliceSTATE_GetOuterDpbMemory, - ////SliceSTATE_InitSlice, - //SliceSTATE_GetSliceData, - //SliceSTATE_RegisterOneSlice, - //SliceSTATE_RegisterOneFrame, - //SliceSTATE_ExitPicture, - //SliceSTATE_ErrorMaster, - - //SliceSTATE_Return, - SliceSTATE_MAX, - -} RKV_SLICE_STATUS; - - - +#include "h264d_global.h" @@ -80,6 +29,11 @@ extern "C" { #endif + MPP_RET parse_loop(H264_DecCtx_t *p_Dec); + + + + #ifdef __cplusplus } #endif diff --git a/mpp/codec/dec/h264/h264d_pps.c b/mpp/codec/dec/h264/h264d_pps.c new file mode 100644 index 00000000..bc355cca --- /dev/null +++ b/mpp/codec/dec/h264/h264d_pps.c @@ -0,0 +1,183 @@ +/* +* +* 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. +*/ +#include + +#include "mpp_err.h" + +#include "h264d_log.h" +#include "h264d_bitread.h" +#include "h264d_pps.h" +#include "h264d_scalist.h" +#include "h264d_dpb.h" + +#define MODULE_TAG "h264d_pps" + +static void reset_curpps_data(H264_PPS_t *cur_pps) +{ + memset(cur_pps, 0, sizeof(H264_PPS_t)); + cur_pps->seq_parameter_set_id = -1; // reset + cur_pps->pic_parameter_set_id = -1; +} + +static MPP_RET parse_pps_calingLists(BitReadCtx_t *p_bitctx, H264_SPS_t *sps, H264_PPS_t *pps) +{ + RK_S32 i = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + + for (i = 0; i < 6; ++i) + { + READ_ONEBIT(ret, p_bitctx, &pps->pic_scaling_list_present_flag[i], "pic_scaling_list_present_flag"); + + if (pps->pic_scaling_list_present_flag[i]) + { + FUN_CHECK (ret = parse_scalingList(p_bitctx, H264ScalingList4x4Length, + pps->ScalingList4x4[i], &pps->UseDefaultScalingMatrix4x4Flag[i])); + } + } + if (pps->transform_8x8_mode_flag) + { + for (i = 0; i < ((sps->chroma_format_idc != 3) ? 2 : 6); ++i) + { + READ_ONEBIT(ret, p_bitctx, &pps->pic_scaling_list_present_flag[i + 6], "pic_scaling_list_present_flag"); + if (pps->pic_scaling_list_present_flag[i + 6]) + { + FUN_CHECK(ret = parse_scalingList(p_bitctx, H264ScalingList8x8Length, + pps->ScalingList8x8[i], &pps->UseDefaultScalingMatrix8x8Flag[i])); + } + } + } + + return ret = MPP_OK; +__FAILED: + ASSERT(0); + return ret; +} + +static MPP_RET parser_pps(BitReadCtx_t *p_bitctx, H264_SPS_t *cur_sps, H264_PPS_t *cur_pps) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + WRITE_LOG(p_bitctx, "----------------------------- PPS begin --------------------------------"); + READ_UE(ret, p_bitctx, &cur_pps->pic_parameter_set_id, "pic_parameter_set_id"); + READ_UE(ret, p_bitctx, &cur_pps->seq_parameter_set_id, "seq_parameter_set_id"); + VAL_CHECK(ret, cur_pps->seq_parameter_set_id < 32); + + READ_ONEBIT(ret, p_bitctx, &cur_pps->entropy_coding_mode_flag, "entropy_coding_mode_flag"); + READ_ONEBIT(ret, p_bitctx, &cur_pps->bottom_field_pic_order_in_frame_present_flag, "bottom_field_pic_order_in_frame_present_flag"); + + READ_UE(ret, p_bitctx, &cur_pps->num_slice_groups_minus1, "num_slice_groups_minus1"); + VAL_CHECK(ret, cur_pps->num_slice_groups_minus1 <= 1); + READ_UE(ret, p_bitctx, &cur_pps->num_ref_idx_l0_default_active_minus1, "num_ref_idx_l0_default_active_minus1"); + VAL_CHECK(ret, cur_pps->num_ref_idx_l0_default_active_minus1 < 32); + READ_UE(ret, p_bitctx, &cur_pps->num_ref_idx_l1_default_active_minus1, "num_ref_idx_l1_default_active_minus1"); + VAL_CHECK(ret, cur_pps->num_ref_idx_l1_default_active_minus1 < 32); + READ_ONEBIT(ret, p_bitctx, &cur_pps->weighted_pred_flag, "weighted_pred_flag"); + READ_BITS(ret, p_bitctx, 2, &cur_pps->weighted_bipred_idc, "weighted_bipred_idc"); + VAL_CHECK(ret, cur_pps->weighted_bipred_idc < 3); + READ_SE(ret, p_bitctx, &cur_pps->pic_init_qp_minus26, "pic_init_qp_minus26"); + CHECK_RANGE(ret, p_bitctx, cur_pps->pic_init_qp_minus26, -26, 25); + READ_SE(ret, p_bitctx, &cur_pps->pic_init_qs_minus26, "pic_init_qs_minus26"); + CHECK_RANGE(ret, p_bitctx, cur_pps->pic_init_qs_minus26, -26, 25); + READ_SE(ret, p_bitctx, &cur_pps->chroma_qp_index_offset, "chroma_qp_index_offset"); + CHECK_RANGE(ret, p_bitctx, cur_pps->chroma_qp_index_offset, -12, 12); + cur_pps->second_chroma_qp_index_offset = cur_pps->chroma_qp_index_offset; + READ_ONEBIT(ret, p_bitctx, &cur_pps->deblocking_filter_control_present_flag, "deblocking_filter_control_present_flag"); + READ_ONEBIT(ret, p_bitctx, &cur_pps->constrained_intra_pred_flag, "constrained_intra_pred_flag"); + READ_ONEBIT(ret, p_bitctx, &cur_pps->redundant_pic_cnt_present_flag, "redundant_pic_cnt_present_flag"); + VAL_CHECK(ret ,cur_pps->redundant_pic_cnt_present_flag == 0); + + if (has_more_rbsp_data(p_bitctx)) + { + READ_ONEBIT(ret, p_bitctx, &cur_pps->transform_8x8_mode_flag, "transform_8x8_mode_flag"); + READ_ONEBIT(ret, p_bitctx, &cur_pps->pic_scaling_matrix_present_flag, "pic_scaling_matrix_present_flag"); + if (cur_pps->pic_scaling_matrix_present_flag) + { + LogInfo(p_bitctx->ctx, "Picture scaling matrix present."); + FUN_CHECK(ret = parse_pps_calingLists(p_bitctx, cur_sps, cur_pps)); + } + READ_SE(ret, p_bitctx, &cur_pps->second_chroma_qp_index_offset, "second_chroma_qp_index_offset"); + } + else + { + cur_pps->transform_8x8_mode_flag = 0; + cur_pps->second_chroma_qp_index_offset = cur_pps->chroma_qp_index_offset; + } + cur_pps->Valid = 1; + + return ret = MPP_OK; + +__FAILED: + ASSERT(0); + return ret; +} + + +/*! +*********************************************************************** +* \brief +* parser pps and process pps +*********************************************************************** +*/ +//extern "C" +MPP_RET process_pps(H264_SLICE_t *currSlice) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dLogCtx_t *logctx = currSlice->logctx; + H264dCurCtx_t *p_Cur = currSlice->p_Cur; + BitReadCtx_t *p_bitctx = &p_Cur->bitctx; + H264_PPS_t *cur_pps = &p_Cur->pps; + + FunctionIn(logctx->parr[RUN_PARSE]); + reset_curpps_data(cur_pps);// reset + set_bitread_logctx(p_bitctx, logctx->parr[LOG_READ_PPS]); + FUN_CHECK(ret = parser_pps(p_bitctx, &p_Cur->sps, cur_pps)); + //!< MakePPSavailable + ASSERT(cur_pps->Valid == 1); + memcpy(&currSlice->p_Vid->ppsSet[cur_pps->pic_parameter_set_id], cur_pps, sizeof(H264_PPS_t)); + + FunctionOut(logctx->parr[RUN_PARSE]); + + return ret = MPP_OK; +__FAILED: + return ret; +} + +/*! +*********************************************************************** +* \brief +* prase sps and process sps +*********************************************************************** +*/ +//extern "C" +MPP_RET activate_pps(H264dVideoCtx_t *p_Vid, H264_PPS_t *pps) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + if (p_Vid->active_pps != pps) + { + if (p_Vid->dec_picture) + { + //!< return if the last picture has already been finished + FUN_CHECK(ret = exit_picture(p_Vid, &p_Vid->dec_picture)); + } + p_Vid->active_pps = pps; + } + + return ret = MPP_OK; +__FAILED: + return ret; +} diff --git a/mpp/codec/dec/h264/h264d_pps.h b/mpp/codec/dec/h264/h264d_pps.h new file mode 100644 index 00000000..cbc4ca03 --- /dev/null +++ b/mpp/codec/dec/h264/h264d_pps.h @@ -0,0 +1,39 @@ +/* +* +* 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. +*/ + +#ifndef _H264D_PPS_H_ +#define _H264D_PPS_H_ + +#include "rk_type.h" +#include "mpp_err.h" +#include "h264d_global.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + MPP_RET process_pps(H264_SLICE_t *currSlice); + MPP_RET activate_pps(H264dVideoCtx_t *p_Vid, H264_PPS_t *pps); + +#ifdef __cplusplus +} +#endif + +//======================================== +#endif /* end of _H264D_PPS_H_ */ + diff --git a/mpp/codec/dec/h264/h264d_rwfile.c b/mpp/codec/dec/h264/h264d_rwfile.c index bc1ff4fc..b65d6797 100644 --- a/mpp/codec/dec/h264/h264d_rwfile.c +++ b/mpp/codec/dec/h264/h264d_rwfile.c @@ -496,10 +496,10 @@ static MPP_RET read_next_nalu(InputParams *p_in) GetBitCtx_t *pStrmData = (GetBitCtx_t *)p_in->bitctx; memset(pStrmData, 0, sizeof(GetBitCtx_t)); set_streamdata(pStrmData, p_in->IO.pNALU, 4); - read_bits(pStrmData, 1, &forbidden_bit); + read_bits( pStrmData, 1, &forbidden_bit); ASSERT(forbidden_bit == 0); - read_bits(pStrmData, 2, &nal_reference_idc); - read_bits(pStrmData, 5, &nal_unit_type); + read_bits( pStrmData, 2, &nal_reference_idc); + read_bits( pStrmData, 5, &nal_unit_type); nalu_header_bytes = 1; if ((nal_unit_type == NALU_TYPE_PREFIX) || (nal_unit_type == NALU_TYPE_SLC_EXT)) { @@ -616,7 +616,7 @@ static void write_driver_bytes(FILE *fp_out, TempDataCtx_t *in_tmpctx, FILE *fp_ fwrite(&in_tmpctx->len, sizeof(RK_U32), 1, fp_out); fwrite(in_tmpctx->data, sizeof(RK_U8), in_tmpctx->len, fp_out); write_bytes(fp_in, &m_tmpctx, fp_out); - goto __FAILED; + return; default: printf("ERROR: frame_no=%d. \n", frame_no); ASSERT(0); @@ -625,8 +625,6 @@ static void write_driver_bytes(FILE *fp_out, TempDataCtx_t *in_tmpctx, FILE *fp_ fread(&header, 1, sizeof(RK_U32), fp_in); fread(&datasize, 1, sizeof(RK_U32), fp_in); } -__FAILED: - return; } @@ -638,8 +636,8 @@ __FAILED: */ MPP_RET h264d_configure(InputParams *p_in, RK_S32 ac, char *av[]) { - MPP_RET ret = MPP_NOK; - VAL_CHECK(ac > 1); + MPP_RET ret = MPP_ERR_UNKNOW; + VAL_CHECK(ret, ac > 1); display_input_cmd(ac, av); FUN_CHECK (ret = parse_command(p_in, ac, av)); @@ -672,20 +670,20 @@ MPP_RET h264d_close_files(InputParams *p_in) */ MPP_RET h264d_open_files(InputParams *p_in) { - MPP_RET ret = MPP_NOK; + MPP_RET ret = MPP_ERR_UNKNOW; - FLE_CHECK(p_in->fp_bitstream = fopen(p_in->infile_name, "rb")); + FLE_CHECK(ret, p_in->fp_bitstream = fopen(p_in->infile_name, "rb")); #if defined(_MSC_VER) - FLE_CHECK(p_in->fp_golden_data = open_file(p_in->cmp_path_dir, p_in->infile_name, "_trunk.dat", "rb")); - FLE_CHECK(p_in->fp_driver_data = open_file(p_in->out_path_dir, p_in->infile_name, "_driver.dat", "wb")); + FLE_CHECK(ret, p_in->fp_golden_data = open_file(p_in->cmp_path_dir, p_in->infile_name, ".dat", "rb")); + FLE_CHECK(ret, p_in->fp_driver_data = open_file(p_in->out_path_dir, p_in->infile_name, "_fpga.dat", "wb")); #elif defined(__GNUC__) char golden_dir[] = "/home/dw/h264d_fpga/AVC_MVC_ALL_BITSTRAM/h264d_fpga_dat"; char dirver_dir[] = "./h264d_dat"; if (access(dirver_dir, 0) != 0) mkdir(dirver_dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); - FLE_CHECK(p_in->fp_golden_data = open_file(golden_dir, p_in->infile_name, ".dat", "rb")); - FLE_CHECK(p_in->fp_driver_data = open_file(dirver_dir, p_in->infile_name, "_driver.dat", "wb")); + FLE_CHECK(ret, p_in->fp_golden_data = open_file(golden_dir, p_in->infile_name, ".dat", "rb")); + FLE_CHECK(ret, p_in->fp_driver_data = open_file(dirver_dir, p_in->infile_name, "_driver.dat", "wb")); #endif return MPP_OK; @@ -720,16 +718,18 @@ MPP_RET h264d_free_frame_buffer(InputParams *p_in) */ MPP_RET h264d_alloc_frame_buffer(InputParams *p_in) { - MEM_CHECK(p_in->IO.pbuf = mpp_malloc_size(RK_U8, IOBUFSIZE)); - MEM_CHECK(p_in->strm.pbuf = mpp_malloc_size(RK_U8, STMBUFSIZE)); - MEM_CHECK(p_in->bitctx = mpp_malloc_size(void, sizeof(GetBitCtx_t))); + MPP_RET ret = MPP_ERR_UNKNOW; + p_in->IO.pbuf = mpp_malloc_size(RK_U8, IOBUFSIZE); + p_in->strm.pbuf = mpp_malloc_size(RK_U8, STMBUFSIZE); + p_in->bitctx = mpp_malloc_size(void, sizeof(GetBitCtx_t)); + MEM_CHECK(ret, p_in->IO.pbuf && p_in->strm.pbuf && p_in->bitctx); p_in->is_fist_nalu = 1; p_in->is_fist_frame = 1; return MPP_OK; __FAILED: - return MPP_NOK; + return ret; } @@ -755,7 +755,7 @@ MPP_RET h264d_read_one_frame(InputParams *p_in, MppPacket pkt) read_next_nalu(p_in); } while (!p_in->is_new_frame && !p_in->is_eof); //-- set code input context - ((MppPacketImpl *)pkt)->data = p_in->strm.pbuf; + ((MppPacketImpl *)pkt)->pos = p_in->strm.pbuf; ((MppPacketImpl *)pkt)->size = p_in->strm.strmbytes; if (p_in->is_eof) { mpp_packet_set_eos(pkt); @@ -771,21 +771,24 @@ MPP_RET h264d_read_one_frame(InputParams *p_in, MppPacket pkt) */ MPP_RET h264d_write_fpga_data(InputParams *p_in) { - MPP_RET ret = MPP_NOK; + MPP_RET ret = MPP_ERR_UNKNOW; TempDataCtx_t tmpctx = { 0 }; FILE *fp_log = NULL; RK_U32 frame_no = 0; char *out_name = NULL; mpp_env_get_str(logenv_name.outpath, &out_name, NULL); - FLE_CHECK(p_in->fp_driver_data && p_in->fp_driver_data); - FLE_CHECK(fp_log = fopen(strcat(out_name, "/h264d_driverdata.dat"), "rb")); - MEM_CHECK(tmpctx.data = mpp_calloc_size(RK_U8, 128)); //!< for read golden fpga data - do { + FLE_CHECK(ret, p_in->fp_golden_data && p_in->fp_driver_data); + fp_log = fopen(strcat(out_name, "/h264d_driver_data.dat"), "rb"); + FLE_CHECK(ret, fp_log); + tmpctx.data = mpp_calloc_size(RK_U8, 128); + MEM_CHECK(ret, tmpctx.data); //!< for read golden fpga data + while (!feof(p_in->fp_golden_data) && !feof(fp_log)) + { read_golden_data (p_in->fp_golden_data, &tmpctx, frame_no); write_driver_bytes(p_in->fp_driver_data, &tmpctx, fp_log, frame_no); frame_no++; - } while (!feof(p_in->fp_golden_data) && !feof(fp_log) && (frame_no <= p_in->iFrmdecoded)); + } mpp_free(tmpctx.data); FCLOSE(fp_log); @@ -796,5 +799,5 @@ __FAILED: mpp_free(tmpctx.data); FCLOSE(fp_log); - return ret = MPP_NOK; + return ret; } diff --git a/mpp/codec/dec/h264/h264d_scalist.c b/mpp/codec/dec/h264/h264d_scalist.c new file mode 100644 index 00000000..1b82bb82 --- /dev/null +++ b/mpp/codec/dec/h264/h264d_scalist.c @@ -0,0 +1,409 @@ +/* +* +* 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. +*/ + +#include +#include + +#include "h264d_bitread.h" +#include "h264d_scalist.h" + + + +static RK_U8 ZZ_SCAN[16] = +{ 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15 }; + +static RK_U8 ZZ_SCAN8[64] = +{ 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, +12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, +35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, +58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 }; + +static RK_S32 Default4x4Intra[H264ScalingList4x4Length] = +{ 6, 13, 20, 28, 13, 20, 28, 32, 20, 28, 32, 37, 28, 32, 37, 42 }; + +static RK_S32 Default4x4Inter[H264ScalingList4x4Length] = +{ 10, 14, 20, 24, 14, 20, 24, 27, 20, 24, 27, 30, 24, 27, 30, 34 }; + +static RK_S32 Default8x8Intra[H264ScalingList8x8Length] = +{ 6, 10, 13, 16, 18, 23, 25, 27, 10, 11, 16, 18, 23, 25, 27, 29, +13, 16, 18, 23, 25, 27, 29, 31, 16, 18, 23, 25, 27, 29, 31, 33, +18, 23, 25, 27, 29, 31, 33, 36, 23, 25, 27, 29, 31, 33, 36, 38, +25, 27, 29, 31, 33, 36, 38, 40, 27, 29, 31, 33, 36, 38, 40, 42 }; + +static RK_S32 Default8x8Inter[H264ScalingList8x8Length] = +{ 9, 13, 15, 17, 19, 21, 22, 24, 13, 13, 17, 19, 21, 22, 24, 25, +15, 17, 19, 21, 22, 24, 25, 27, 17, 19, 21, 22, 24, 25, 27, 28, +19, 21, 22, 24, 25, 27, 28, 30, 21, 22, 24, 25, 27, 28, 30, 32, +22, 24, 25, 27, 28, 30, 32, 33, 24, 25, 27, 28, 30, 32, 33, 35 }; + +static RK_S32 Default4x4[16] = +{ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 }; + +static RK_S32 Default8x8[64] = +{ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, +16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, +16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, +16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 }; + + +static void set_sps_scanlist_matrix(H264_SPS_t *sps, H264dVideoCtx_t *p_Vid) +{ + RK_S32 i = 0; + + for (i = 0; i < 6; ++i) + { + if (!sps->seq_scaling_list_present_flag[i]) // fall-back rule A + { + if (i == 0) + { + p_Vid->qmatrix[i] = Default4x4Intra; + } + else if (i == 3) + { + p_Vid->qmatrix[i] = Default4x4Inter; + } + else + { + p_Vid->qmatrix[i] = p_Vid->qmatrix[i - 1]; + } + } + else + { + if (sps->UseDefaultScalingMatrix4x4Flag[i]) + { + + p_Vid->qmatrix[i] = (i < 3) ? Default4x4Intra : Default4x4Inter; + } + else + { + p_Vid->qmatrix[i] = sps->ScalingList4x4[i]; + } + } + } + + for (i = 6; i < ((sps->chroma_format_idc != YUV444) ? 8 : 12); ++i) + { + if (!sps->seq_scaling_list_present_flag[i]) // fall-back rule A + { + if (i == 6) + { + p_Vid->qmatrix[i] = Default8x8Intra; + } + else if (i == 7) + { + p_Vid->qmatrix[i] = Default8x8Inter; + } + else + { + p_Vid->qmatrix[i] = p_Vid->qmatrix[i - 2]; + } + } + else + { + if (sps->UseDefaultScalingMatrix8x8Flag[i - 6]) + { + + p_Vid->qmatrix[i] = (i == 6 || i == 8 || i == 10) ? Default8x8Intra : Default8x8Inter; + } + else + { + p_Vid->qmatrix[i] = sps->ScalingList8x8[i - 6]; + } + } + } +} + +static void set_pps_scanlist_matrix(H264_SPS_t *sps, H264_PPS_t *pps, H264dVideoCtx_t *p_Vid) +{ + RK_S32 i = 0; + + for (i = 0; i < 6; ++i) + { + if (!pps->pic_scaling_list_present_flag[i]) // fall-back rule B + { + if (i == 0) + { + if (!sps->seq_scaling_matrix_present_flag) + { + p_Vid->qmatrix[i] = Default4x4Intra; + } + } + else if (i == 3) + { + if (!sps->seq_scaling_matrix_present_flag) + { + p_Vid->qmatrix[i] = Default4x4Inter; + } + } + else + { + p_Vid->qmatrix[i] = p_Vid->qmatrix[i - 1]; + } + } + else + { + if (pps->UseDefaultScalingMatrix4x4Flag[i]) + { + p_Vid->qmatrix[i] = (i < 3) ? Default4x4Intra : Default4x4Inter; + } + else + { + p_Vid->qmatrix[i] = pps->ScalingList4x4[i]; + } + } + } + for (i = 6; i < ((sps->chroma_format_idc != YUV444) ? 8 : 12); ++i) + { + if (!pps->pic_scaling_list_present_flag[i]) // fall-back rule B + { + if (i == 6) + { + if (!sps->seq_scaling_matrix_present_flag) + { + p_Vid->qmatrix[i] = Default8x8Intra; + } + } + else if (i == 7) + { + if (!sps->seq_scaling_matrix_present_flag) + p_Vid->qmatrix[i] = Default8x8Inter; + } + else + p_Vid->qmatrix[i] = p_Vid->qmatrix[i - 2]; + } + else + { + if (pps->UseDefaultScalingMatrix8x8Flag[i - 6]) + { + p_Vid->qmatrix[i] = (i == 6 || i == 8 || i == 10) ? Default8x8Intra : Default8x8Inter; + } + else + { + p_Vid->qmatrix[i] = pps->ScalingList8x8[i - 6]; + } + } + } +} + +/*! +*********************************************************************** +* \brief +* check profile +*********************************************************************** +*/ +//extern "C" +RK_U32 is_prext_profile(RK_U32 profile_idc) +{ + return (profile_idc >= FREXT_HP || profile_idc == FREXT_CAVLC444) ? 1 : 0; +} + +/*! +*********************************************************************** +* \brief +* parse sps and process sps +*********************************************************************** +*/ +//extern "C" +MPP_RET parse_scalingList(BitReadCtx_t *p_bitctx, RK_S32 size, RK_S32 *scaling_list, RK_S32 *use_default) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + RK_S32 last_scale = 8; + RK_S32 next_scale = 8; + RK_S32 delta_scale = 0; + RK_S32 j = 0, scanj = 0; + + RK_U8 *zz_scan = (size > 16) ? ZZ_SCAN8 : ZZ_SCAN; + + *use_default = 0; + for (j = 0; j < size; ++j) + { + scanj = zz_scan[j]; + if (next_scale != 0) + { + READ_SE(ret, p_bitctx, &delta_scale, "delta_scale"); + CHECK_RANGE(ret, p_bitctx, delta_scale, -128, 127); + next_scale = (last_scale + delta_scale + 256) & 0xff; + *use_default = (scanj == 0 && next_scale == 0) ? 1 : 0; + } + scaling_list[scanj] = (next_scale == 0) ? last_scale : next_scale; + last_scale = scaling_list[scanj]; + } + + return ret = MPP_OK; +__FAILED: + return ret; +} + + +/*! +*********************************************************************** +* \brief +* parse sps and process sps +*********************************************************************** +*/ +//extern "C" +MPP_RET get_max_dec_frame_buf_size(H264_SPS_t *sps) +{ + RK_S32 size = 0; + RK_S32 pic_size = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + + + switch (sps->level_idc) + { + case 9: + size = 152064; + break; + case 10: + size = 152064; + break; + case 11: + if (sps->constrained_set3_flag && !is_prext_profile(sps->profile_idc)) + { + size = 152064; + } + else + { + size = 345600; + } + break; + case 12: + size = 912384; + break; + case 13: + size = 912384; + break; + case 20: + size = 912384; + break; + case 21: + size = 1824768; + break; + case 22: + size = 3110400; + break; + case 30: + size = 3110400; + break; + case 31: + size = 6912000; + break; + case 32: + size = 7864320; + break; + case 40: + size = 12582912; + break; + case 41: + size = 12582912; + break; + case 42: + size = 13369344; + break; + case 50: + size = 42393600; + break; + case 51: + size = 70778880; + break; + case 52: + size = 70778880; + break; + default: + ASSERT(0); // undefined level + return ret = MPP_NOK; + } + pic_size = (sps->pic_width_in_mbs_minus1 + 1) + * (sps->pic_height_in_map_units_minus1 + 1) + * (sps->frame_mbs_only_flag ? 1 : 2) * 384; + size /= pic_size; + size = min(size, 16); + sps->max_dec_frame_buffering = size; + + return ret = MPP_OK; +} + +/*! +*********************************************************************** +* \brief +* parse sps and process sps +*********************************************************************** +*/ +//extern "C" +MPP_RET parse_sps_scalinglists(BitReadCtx_t *p_bitctx, H264_SPS_t *sps) +{ + RK_S32 i = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + // Parse scaling_list4x4. + for (i = 0; i < 6; ++i) + { + READ_ONEBIT(ret, p_bitctx, &sps->seq_scaling_list_present_flag[i], "seq_scaling_list_present_flag"); + + if (sps->seq_scaling_list_present_flag[i]) + { + FUN_CHECK(ret = parse_scalingList(p_bitctx, H264ScalingList4x4Length, + sps->ScalingList4x4[i], &sps->UseDefaultScalingMatrix4x4Flag[i])); + } + } + // Parse scaling_list8x8. + for (i = 0; i < ((sps->chroma_format_idc != YUV444) ? 2 : 6); ++i) + { + READ_ONEBIT(ret, p_bitctx, &sps->seq_scaling_list_present_flag[6 + i], "seq_scaling_list_present_flag"); + if (sps->seq_scaling_list_present_flag[6 + i]) + { + FUN_CHECK(ret = parse_scalingList(p_bitctx, H264ScalingList8x8Length, + sps->ScalingList8x8[i], &sps->UseDefaultScalingMatrix8x8Flag[i])); + } + } + + return ret = MPP_OK; +__FAILED: + return ret; +} +/*! +*********************************************************************** +* \brief +* prepare scanlist info to register syntax +*********************************************************************** +*/ +//extern "C" +MPP_RET prepare_init_scanlist(H264_SLICE_t *currSlice) +{ + RK_S32 i = 0; + H264_SPS_t *sps = currSlice->p_Vid->active_sps; + H264_PPS_t *pps = currSlice->p_Vid->active_pps; + + if (!pps->pic_scaling_matrix_present_flag && !sps->seq_scaling_matrix_present_flag) + { + for (i = 0; i < 12; i++) + { + currSlice->p_Vid->qmatrix[i] = (i < 6) ? Default4x4 : Default8x8; + } + } + else + { + if (sps->seq_scaling_matrix_present_flag) // check sps first + { + set_sps_scanlist_matrix(sps, currSlice->p_Vid); + } + if (pps->pic_scaling_matrix_present_flag) // then check pps + { + set_pps_scanlist_matrix(sps, pps, currSlice->p_Vid); + } + } + return MPP_OK; +} diff --git a/mpp/codec/dec/h264/h264d_scalist.h b/mpp/codec/dec/h264/h264d_scalist.h new file mode 100644 index 00000000..924656cc --- /dev/null +++ b/mpp/codec/dec/h264/h264d_scalist.h @@ -0,0 +1,41 @@ +/* +* +* 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. +*/ + + +#ifndef _H264D_SCALIST_H_ +#define _H264D_SCALIST_H_ + +#include "rk_type.h" +#include "mpp_err.h" +#include "h264d_global.h" + + +#ifdef __cplusplus +extern "C" { +#endif + RK_U32 is_prext_profile(RK_U32 profile_idc); + MPP_RET get_max_dec_frame_buf_size(H264_SPS_t *sps); + MPP_RET parse_scalingList(BitReadCtx_t *p_bitctx, RK_S32 size, RK_S32 *scaling_list, RK_S32 *use_default); + MPP_RET parse_sps_scalinglists(BitReadCtx_t *p_bitctx, H264_SPS_t *sps); + MPP_RET prepare_init_scanlist(H264_SLICE_t *currSlice); +#ifdef __cplusplus +} +#endif + +//======================================== +#endif /* end of _H264D_SCALIST_H_ */ + diff --git a/mpp/codec/dec/h264/h264d_sei.c b/mpp/codec/dec/h264/h264d_sei.c new file mode 100644 index 00000000..c82ebf14 --- /dev/null +++ b/mpp/codec/dec/h264/h264d_sei.c @@ -0,0 +1,410 @@ +/* +* +* 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. +*/ + + +#include +#include + +#include "h264d_log.h" +#include "h264d_bitread.h" +#include "h264d_sps.h" +#include "h264d_sei.h" + +#define MODULE_TAG "h264d_sei" + +static void interpret_spare_pic() +{ + +} +static void interpret_subsequence_info() +{ + +} +static void interpret_subsequence_layer_characteristics_info() +{ + +} +static void interpret_subsequence_characteristics_info() +{ + +} +static void interpret_scene_information() +{ + +} +static void interpret_user_data_registered_itu_t_t35_info() +{ + +} +static void interpret_user_data_unregistered_info() +{ + +} +static void interpret_pan_scan_rect_info() +{ + +} +static void interpret_filler_payload_info() +{ + +} +static void interpret_dec_ref_pic_marking_repetition_info() +{ + +} +static void interpret_full_frame_freeze_info() +{ + +} +static void interpret_full_frame_freeze_release_info() +{ + +} +static void interpret_full_frame_snapshot_info() +{ + +} +static void interpret_progressive_refinement_start_info() +{ + +} +static void interpret_progressive_refinement_end_info() +{ + +} +static void interpret_motion_constrained_slice_group_set_info() +{ + +} +static void interpret_picture_timing_info() +{ + +} +static void interpret_film_grain_characteristics_info() +{ + +} +static void interpret_deblocking_filter_display_preference_info() +{ + +} +static void interpret_stereo_video_info_info() +{ + +} +static void interpret_post_filter_hints_info() +{ + +} +static void interpret_tone_mapping() +{ + +} +static void interpret_frame_packing_arrangement_info() +{ + +} +static void interpret_mvc_scalability_info() +{ + +} + +static MPP_RET interpret_recovery_point_info(RK_U8 *payload, RK_S32 size, BitReadCtx_t *p_bitctx, H264_SEI_t *sei_msg) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + set_bitread_ctx(p_bitctx, payload, size); + + READ_UE(ret, p_bitctx, &sei_msg->recovery_point.recovery_frame_cnt, "recovery_frame_cnt"); + READ_ONEBIT(ret, p_bitctx, &sei_msg->recovery_point.exact_match_flag, "exact_match_flag"); + READ_ONEBIT(ret, p_bitctx, &sei_msg->recovery_point.broken_link_flag, "broken_link_flag"); + READ_BITS(ret, p_bitctx, 2, &sei_msg->recovery_point.changing_slice_group_idc, "changing_slice_group_idc"); + + return ret = MPP_OK; +__FAILED: + return ret; +} + + +static MPP_RET interpret_mvc_scalable_nesting_info(RK_U8 *payload, RK_S32 size, BitReadCtx_t *p_bitctx, H264_SEI_t *sei_msg) +{ + RK_S32 i; + RK_U32 operation_point_flag; + RK_U32 all_view_components_in_au_flag; + RK_S32 num_view_components_minus1; + RK_S32 sei_view_id; + RK_S32 num_view_components_op_minus1; + RK_S32 sei_op_view_id; + RK_S32 sei_op_temporal_id; + MPP_RET ret = MPP_ERR_UNKNOW; + + BitReadCtx_t tmp_strmdata = { 0 }; + BitReadCtx_t *p_strm = &tmp_strmdata; + set_bitread_ctx(p_strm, payload, size); + + READ_ONEBIT(ret, p_strm, &operation_point_flag, "operation_point_flag"); + if (!operation_point_flag) + { + READ_ONEBIT(ret, p_strm, &all_view_components_in_au_flag, "all_view_components_in_au_flag"); + READ_UE(ret, p_strm, &num_view_components_minus1, "num_view_components_minus1"); + for (i = 0; i <= num_view_components_minus1; i++) + { + READ_BITS(ret, p_strm, 10, &sei_view_id, "sei_view_id"); + } + } + else + { + READ_UE(ret, p_strm, &num_view_components_op_minus1, "num_view_components_op_minus1"); + for (i = 0; i <= num_view_components_op_minus1; i++) + { + READ_BITS(ret, p_strm, 10, &sei_op_view_id, "sei_op_view_id"); + } + READ_BITS(ret, p_strm, 3, &sei_op_temporal_id, "sei_op_temporal_id"); + } + + p_bitctx->used_bits = p_strm->used_bits; + sei_msg->mvc_scalable_nesting_flag = 1; + return ret = MPP_OK; +__FAILED: + return ret; +} + +static MPP_RET interpret_buffering_period_info(RK_U8 *payload, RK_S32 size, BitReadCtx_t *p_bitctx, H264_SEI_t *sei_msg) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + BitReadCtx_t tmp_strmdata = { 0 }; + + p_bitctx = &tmp_strmdata; + set_bitread_ctx(p_bitctx, payload, size); + READ_UE(ret, p_bitctx, &sei_msg->seq_parameter_set_id, "seq_parameter_set_id"); + + return ret = MPP_OK; +__FAILED: + return ret; + +} + +static void interpret_reserved_info(RK_U8 *payload, RK_S32 size, BitReadCtx_t *p_bitctx, H264_SEI_t *sei_msg) +{ + RK_S32 offset = 0; + RK_U8 payload_byte = 0; + + while (offset < size) + { + payload_byte = payload[offset]; + offset++; + } + (void)p_bitctx; + (void)sei_msg; + (void)payload_byte; +} + +static MPP_RET parserSEI(BitReadCtx_t *p_bitctx, H264_SEI_t *sei_msg, RK_U8 *msg) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + //!< sei_payload( type, size ); + switch (sei_msg->type) + { + case SEI_BUFFERING_PERIOD: + FUN_CHECK(ret = interpret_buffering_period_info(msg, sei_msg->payload_size, p_bitctx, sei_msg)); + break; + case SEI_PIC_TIMING: + interpret_picture_timing_info(); + break; + case SEI_PAN_SCAN_RECT: + interpret_pan_scan_rect_info(); + break; + case SEI_FILLER_PAYLOAD: + interpret_filler_payload_info(); + break; + case SEI_USER_DATA_REGISTERED_ITU_T_T35: + interpret_user_data_registered_itu_t_t35_info(); + break; + case SEI_USER_DATA_UNREGISTERED: + interpret_user_data_unregistered_info(); + break; + case SEI_RECOVERY_POINT: + FUN_CHECK(ret = interpret_recovery_point_info(msg, sei_msg->payload_size, p_bitctx, sei_msg)); + break; + case SEI_DEC_REF_PIC_MARKING_REPETITION: + interpret_dec_ref_pic_marking_repetition_info(); + break; + case SEI_SPARE_PIC: + interpret_spare_pic(); + break; + case SEI_SCENE_INFO: + interpret_scene_information(); + break; + case SEI_SUB_SEQ_INFO: + interpret_subsequence_info(); + break; + case SEI_SUB_SEQ_LAYER_CHARACTERISTICS: + interpret_subsequence_layer_characteristics_info(); + break; + case SEI_SUB_SEQ_CHARACTERISTICS: + interpret_subsequence_characteristics_info(); + break; + case SEI_FULL_FRAME_FREEZE: + interpret_full_frame_freeze_info(); + break; + case SEI_FULL_FRAME_FREEZE_RELEASE: + interpret_full_frame_freeze_release_info(); + break; + case SEI_FULL_FRAME_SNAPSHOT: + interpret_full_frame_snapshot_info(); + break; + case SEI_PROGRESSIVE_REFINEMENT_SEGMENT_START: + interpret_progressive_refinement_start_info(); + break; + case SEI_PROGRESSIVE_REFINEMENT_SEGMENT_END: + interpret_progressive_refinement_end_info(); + break; + case SEI_MOTION_CONSTRAINED_SLICE_GROUP_SET: + interpret_motion_constrained_slice_group_set_info(); + case SEI_FILM_GRAIN_CHARACTERISTICS: + interpret_film_grain_characteristics_info(); + break; + case SEI_DEBLOCKING_FILTER_DISPLAY_PREFERENCE: + interpret_deblocking_filter_display_preference_info(); + break; + case SEI_STEREO_VIDEO_INFO: + interpret_stereo_video_info_info(); + break; + case SEI_TONE_MAPPING: + interpret_tone_mapping(); + break; + case SEI_POST_FILTER_HINTS: + interpret_post_filter_hints_info(); + break; + case SEI_FRAME_PACKING_ARRANGEMENT: + interpret_frame_packing_arrangement_info(); + break; + case SEI_MVC_SCALABLE_NESTING: + FUN_CHECK(ret = interpret_mvc_scalable_nesting_info(msg, sei_msg->payload_size, p_bitctx, sei_msg)); + break; + case SEI_VIEW_SCALABILITY_INFO: + interpret_mvc_scalability_info(); + break; + default: + interpret_reserved_info(msg, sei_msg->payload_size, p_bitctx, sei_msg); + break; + } + + return ret = MPP_OK; +__FAILED: + return ret; +} + +static MPP_RET analysisSEI(H264_SLICE_t *cur_slice) +{ + H264_SPS_t *sps = NULL; + H264_subSPS_t *subset_sps = NULL; + MPP_RET ret = MPP_ERR_UNKNOW; + H264dVideoCtx_t *p_Vid = cur_slice->p_Vid; + H264_SEI_t *sei_msg = &cur_slice->p_Cur->sei; + + switch (sei_msg->type) // sei_payload( type, size ) + { + case SEI_BUFFERING_PERIOD: + if (sei_msg->mvc_scalable_nesting_flag) + { + p_Vid->active_mvc_sps_flag = 1; + sps = NULL; + subset_sps = &p_Vid->subspsSet[sei_msg->seq_parameter_set_id]; + } + else + { + p_Vid->active_mvc_sps_flag = 0; + sps = &p_Vid->spsSet[sei_msg->seq_parameter_set_id]; + subset_sps = NULL; + } + p_Vid->exit_picture_flag = 1; + FUN_CHECK(ret = activate_sps(p_Vid, sps, subset_sps)); + break; + default: + + break; + } + + return ret = MPP_OK; + +__FAILED: + return ret; +} + +/*! +*********************************************************************** +* \brief +* parse SEI information +*********************************************************************** +*/ +//extern "C" +MPP_RET process_sei(H264_SLICE_t *currSlice) +{ + RK_S32 nn = 0; + RK_S32 tmp_byte = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + H264_SEI_t *sei_msg = &currSlice->p_Cur->sei; + BitReadCtx_t *p_bitctx = &currSlice->p_Cur->bitctx; + + FunctionIn(currSlice->logctx->parr[RUN_PARSE]); + memset(sei_msg, 0, sizeof(*sei_msg)); + sei_msg->mvc_scalable_nesting_flag = 0; //init to false + + do + { + sei_msg->type = 0; + READ_BITS(ret, p_bitctx, 8, &tmp_byte, "tmp_byte"); + while (tmp_byte == 0xFF) + { + sei_msg->type += 255; + READ_BITS(ret, p_bitctx, 8, &tmp_byte, "tmp_type"); + } + sei_msg->type += tmp_byte; // this is the last byte + + sei_msg->payload_size = 0; + READ_BITS(ret, p_bitctx, 8, &tmp_byte, "tmp_type"); + while (tmp_byte == 0xFF) + { + sei_msg->payload_size += 255; + READ_BITS(ret, p_bitctx, 8, &tmp_byte, "tmp_type"); + } + sei_msg->payload_size += tmp_byte; // this is the last byte + + //--- read sei info + FUN_CHECK(ret = parserSEI(p_bitctx, sei_msg, p_bitctx->data_)); + //--- analysis sei info + FUN_CHECK(ret = analysisSEI(currSlice)); + //--- set offset to read next sei nal + if (SEI_MVC_SCALABLE_NESTING == sei_msg->type) + { + sei_msg->payload_size = ((p_bitctx->used_bits + 0x07) >> 3); + } + for (nn = 0; nn < sei_msg->payload_size; nn++) // read bytes + { + READ_BITS(ret, p_bitctx, 8, &tmp_byte, "tmp_byte"); + } + + } while ((p_bitctx->data_[0] != 0x80) && (p_bitctx->bytes_left_ > 1)); // more_rbsp_data() msg[offset] != 0x80 + + FunctionOut(currSlice->logctx->parr[RUN_PARSE]); + + return ret = MPP_OK; + +__FAILED: + ASSERT(0); + return ret; +} diff --git a/mpp/codec/dec/h264/h264d_sei.h b/mpp/codec/dec/h264/h264d_sei.h new file mode 100644 index 00000000..55ca6201 --- /dev/null +++ b/mpp/codec/dec/h264/h264d_sei.h @@ -0,0 +1,37 @@ +/* +* +* 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. +*/ + +#ifndef _H264D_SEI_H_ +#define _H264D_SEI_H_ + +#include "rk_type.h" +#include "mpp_err.h" +#include "h264d_global.h" + +#ifdef __cplusplus +extern "C" { +#endif + + MPP_RET process_sei(H264_SLICE_t *currSlice); + +#ifdef __cplusplus +} +#endif + +//======================================== +#endif /* end of _H264D_SEI_H_ */ + diff --git a/mpp/codec/dec/h264/h264d_slice.c b/mpp/codec/dec/h264/h264d_slice.c new file mode 100644 index 00000000..4f3532d8 --- /dev/null +++ b/mpp/codec/dec/h264/h264d_slice.c @@ -0,0 +1,659 @@ +/* +* +* 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. +*/ + +#include "mpp_mem.h" + +#include "h264d_log.h" +#include "h264d_slice.h" +#include "h264d_sps.h" +#include "h264d_pps.h" + +#define MODULE_TAG "h264d_slice" + +static void free_slice_drpm_buffer(H264_SLICE_t *currSlice) // dec_ref_pic_marking +{ + H264_DRPM_t *tmp_drpm = NULL; + + while (currSlice->dec_ref_pic_marking_buffer) + { + tmp_drpm = currSlice->dec_ref_pic_marking_buffer; + currSlice->dec_ref_pic_marking_buffer = tmp_drpm->Next; + mpp_free(tmp_drpm); + } +} + +static RK_S32 get_voidx(H264_subSPS_t *subset_spsSet, H264_subSPS_t **subset_sps, RK_S32 iViewId) +{ + RK_S32 i = 0, iVOIdx = -1; + RK_S32 *piViewIdMap = NULL; + H264_subSPS_t *active_subset_sps = *subset_sps; + + if (active_subset_sps) + { + piViewIdMap = active_subset_sps->view_id; + for (iVOIdx = active_subset_sps->num_views_minus1; iVOIdx >= 0; iVOIdx--) + if (piViewIdMap[iVOIdx] == iViewId) + break; + } + else + { + for (i = 0; i < MAXSPS; i++) + { + if (subset_spsSet[i].num_views_minus1 >= 0 && subset_spsSet[i].sps.Valid) + { + break; + } + } + + if (i < MAXSPS) + { + *subset_sps = active_subset_sps = &subset_spsSet[i]; + piViewIdMap = active_subset_sps->view_id; + for (iVOIdx = active_subset_sps->num_views_minus1; iVOIdx >= 0; iVOIdx--) + if (piViewIdMap[iVOIdx] == iViewId) + break; + + return iVOIdx; + } + else + { + iVOIdx = 0; + } + } + + return iVOIdx; +} + +static RK_U32 is_new_picture(H264_SLICE_t *currSlice) +{ + RK_U32 is_new_pic_flag = 0; + RK_S32 result = 0, result1 = 0; + H264dVideoCtx_t *p_Vid = currSlice->p_Vid; + H264_OldSlice_t *p_old_slice = &currSlice->p_Vid->old_slice; + + currSlice->is_new_picture_flag = 0; + if (p_old_slice == NULL) // fist slice + { + is_new_pic_flag = 1; + goto __Updata; + } + else + { + result |= (currSlice->start_mb_nr == 0); + result |= (p_old_slice->pps_id != (RK_S32)currSlice->pic_parameter_set_id); + result |= (p_old_slice->frame_num != currSlice->frame_num); + result |= (p_old_slice->field_pic_flag != currSlice->field_pic_flag); + if (currSlice->field_pic_flag && p_old_slice->field_pic_flag) + { + result |= (p_old_slice->bottom_field_flag != currSlice->bottom_field_flag); + } + if (p_Vid->old_slice.current_mb_nr != 0) + { + if (currSlice->mb_aff_frame_flag) + result |= (currSlice->start_mb_nr << 1) < (p_Vid->old_slice.current_mb_nr); + else + result |= currSlice->start_mb_nr < p_Vid->old_slice.current_mb_nr; + } + result |= (p_old_slice->nal_ref_idc != currSlice->nal_reference_idc) + && ((p_old_slice->nal_ref_idc == 0) || (currSlice->nal_reference_idc == 0)); + result |= (p_old_slice->idr_flag != currSlice->idr_flag); + if (currSlice->idr_flag && p_old_slice->idr_flag) + { + result |= (p_old_slice->idr_pic_id != (RK_S32)currSlice->idr_pic_id); + } + if (p_Vid->active_sps->pic_order_cnt_type == 0) + { + result1 |= (p_old_slice->pic_oder_cnt_lsb != currSlice->pic_order_cnt_lsb); + if (p_Vid->active_pps->bottom_field_pic_order_in_frame_present_flag && !currSlice->field_pic_flag) + { + result1 |= (p_old_slice->delta_pic_oder_cnt_bottom != currSlice->delta_pic_order_cnt_bottom); + } + } + else if (p_Vid->active_sps->pic_order_cnt_type == 1) + { + if (!p_Vid->active_sps->delta_pic_order_always_zero_flag) + { + result1 |= (p_old_slice->delta_pic_order_cnt[0] != currSlice->delta_pic_order_cnt[0]); + if (p_Vid->active_pps->bottom_field_pic_order_in_frame_present_flag && !currSlice->field_pic_flag) + { + result1 |= (p_old_slice->delta_pic_order_cnt[1] != currSlice->delta_pic_order_cnt[1]); + } + } + } + else + { + result1 |= (p_old_slice->frame_num != currSlice->frame_num); + } + result |= (currSlice->view_id != p_old_slice->view_id); + result |= (currSlice->inter_view_flag != p_old_slice->inter_view_flag); + result |= (currSlice->anchor_pic_flag != p_old_slice->anchor_pic_flag); + result |= (currSlice->layer_id != p_old_slice->layer_id); + } + if (result) + { + is_new_pic_flag = 1; + goto __Updata; + } + else + { + return is_new_pic_flag = 0; + } +__Updata: + currSlice->is_new_picture_flag = 1; + p_old_slice->current_mb_nr = currSlice->current_mb_nr; + p_old_slice->pps_id = currSlice->pic_parameter_set_id; + p_old_slice->frame_num = currSlice->frame_num; //p_Vid->frame_num; + p_old_slice->field_pic_flag = currSlice->field_pic_flag; //p_Vid->field_pic_flag; + + if (currSlice->field_pic_flag) + { + p_old_slice->bottom_field_flag = currSlice->bottom_field_flag; + } + + p_old_slice->nal_ref_idc = currSlice->nal_reference_idc; + p_old_slice->idr_flag = currSlice->idr_flag; + + if (currSlice->idr_flag) + { + p_old_slice->idr_pic_id = currSlice->idr_pic_id; + } + + if (p_Vid->active_sps->pic_order_cnt_type == 0) + { + p_old_slice->pic_oder_cnt_lsb = currSlice->pic_order_cnt_lsb; + p_old_slice->delta_pic_oder_cnt_bottom = currSlice->delta_pic_order_cnt_bottom; + } + + if (p_Vid->active_sps->pic_order_cnt_type == 1) + { + p_old_slice->delta_pic_order_cnt[0] = currSlice->delta_pic_order_cnt[0]; + p_old_slice->delta_pic_order_cnt[1] = currSlice->delta_pic_order_cnt[1]; + } + p_old_slice->view_id = currSlice->view_id; + p_old_slice->inter_view_flag = currSlice->inter_view_flag; + p_old_slice->anchor_pic_flag = currSlice->anchor_pic_flag; + p_old_slice->layer_id = currSlice->layer_id; + + return is_new_pic_flag; +} + +static MPP_RET ref_pic_list_mvc_modification(H264_SLICE_t *currSlice) +{ + RK_U32 i = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + RK_U32 modification_of_pic_nums_idc = 0; + RK_U32 abs_diff_pic_num_minus1 = 0; + RK_U32 long_term_pic_idx = 0; + RK_U32 abs_diff_view_idx_minus1 = 0; + BitReadCtx_t *p_bitctx = &currSlice->p_Cur->bitctx; + + if ((currSlice->slice_type % 5) != I_SLICE && (currSlice->slice_type % 5) != SI_SLICE) + { + READ_ONEBIT(ret, p_bitctx, &currSlice->ref_pic_list_reordering_flag[LIST_0], "ref_pic_list_reordering_flag"); + if (currSlice->ref_pic_list_reordering_flag[LIST_0]) + { + i = 0; + do + { + READ_UE(ret, p_bitctx, &modification_of_pic_nums_idc, "modification_of_pic_nums_idc"); + if (modification_of_pic_nums_idc == 0 || modification_of_pic_nums_idc == 1) + { + READ_UE(ret, p_bitctx, &abs_diff_pic_num_minus1, "abs_diff_pic_num_minus1_lx"); + } + else + { + if (modification_of_pic_nums_idc == 2) + { + READ_UE(ret, p_bitctx, &long_term_pic_idx, "long_term_pic_idx"); + } + else if (modification_of_pic_nums_idc == 4 || modification_of_pic_nums_idc == 5) + { + READ_UE(ret, p_bitctx, &abs_diff_view_idx_minus1, "abs_diff_view_idx_minus1"); + } + } + i++; + } while (modification_of_pic_nums_idc != 3); + } + } + if (currSlice->slice_type % 5 == B_SLICE) + { + READ_ONEBIT(ret, p_bitctx, &currSlice->ref_pic_list_reordering_flag[LIST_1], "ref_pic_list_reordering_flag"); + if (currSlice->ref_pic_list_reordering_flag[LIST_1]) + { + i = 0; + do + { + READ_UE(ret, p_bitctx, &modification_of_pic_nums_idc, "modification_of_pic_nums_idc"); + if (modification_of_pic_nums_idc == 0 || modification_of_pic_nums_idc == 1) + { + READ_UE(ret, p_bitctx, &abs_diff_pic_num_minus1, "abs_diff_pic_num_minus1_lx"); + } + else + { + if (modification_of_pic_nums_idc == 2) + { + READ_UE(ret, p_bitctx, &long_term_pic_idx, "long_term_pic_idx"); + } + else if (modification_of_pic_nums_idc == 4 || modification_of_pic_nums_idc == 5) + { + READ_UE(ret, p_bitctx, &abs_diff_view_idx_minus1, "abs_diff_view_idx_minus1"); + } + } + i++; + } while (modification_of_pic_nums_idc != 3); + } + } + ASSERT(currSlice->redundant_pic_cnt == 0); //!< not support reference index of redundant slices + + return ret = MPP_OK; +__FAILED: + return ret; +} + +static MPP_RET pred_weight_table(H264_SLICE_t *currSlice) +{ + RK_S32 se_tmp = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + RK_U32 i = 0, j = 0, temp = 0; + BitReadCtx_t *p_bitctx = &currSlice->p_Cur->bitctx; + + READ_UE(ret, p_bitctx, &temp, "log2_weight_denom"); + if (currSlice->active_sps->chroma_format_idc) + { + READ_UE(ret, p_bitctx, &temp, "log2_weight_denom"); + } + for (i = 0; i < currSlice->num_ref_idx_active[LIST_0]; i++) + { + READ_ONEBIT(ret, p_bitctx, &temp, "luma_weight_flag_l0"); + if (temp) + { + READ_SE(ret, p_bitctx, &se_tmp, "pred_weight"); //!< slice->wp_weight[LIST_0][i][0] + READ_SE(ret, p_bitctx, &se_tmp, "pred_offset"); //!< slice->wp_offset[LIST_0][i][0] + } + if (currSlice->active_sps->chroma_format_idc) + { + READ_ONEBIT(ret, p_bitctx, &temp, "chroma_weight_flag_l0"); + for (j = 1; j < 3; j++) + { + if (temp) //!< chroma_weight_flag_l0 + { + READ_SE(ret, p_bitctx, &se_tmp, "pred_weight"); //!< slice->wp_weight[LIST_0][i][j] + READ_SE(ret, p_bitctx, &se_tmp, "pred_offset"); //!< slice->wp_offset[LIST_0][i][j] + } + } + } + } + + if ((currSlice->slice_type == B_SLICE) && currSlice->p_Vid->active_pps->weighted_bipred_idc == 1) + { + for (i = 0; i < currSlice->num_ref_idx_active[LIST_1]; i++) + { + READ_ONEBIT(ret, p_bitctx, &temp, "luma_weight_flag_l1"); + if (temp) + { + READ_SE(ret, p_bitctx, &se_tmp, "pred_weight"); //!< slice->wp_weight[LIST_1][i][0] + READ_SE(ret, p_bitctx, &se_tmp, "pred_offset"); //!< slice->wp_offset[LIST_1][i][0] + } + if (currSlice->active_sps->chroma_format_idc) + { + READ_ONEBIT(ret, p_bitctx, &temp, "chroma_weight_flag_l1"); + for (j = 1; j < 3; j++) + { + if (temp) // chroma_weight_flag_l1 + { + READ_SE(ret, p_bitctx, &se_tmp, "pred_weight"); //!< slice->wp_weight[LIST_1][i][j] + READ_SE(ret, p_bitctx, &se_tmp, "pred_offset"); //!< slice->wp_offset[LIST_1][i][j] + } + } + } + } + } + + return ret = MPP_OK; +__FAILED: + return ret; +} + +static MPP_RET dec_ref_pic_marking(H264_SLICE_t *pSlice) +{ + RK_U32 val = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + H264_DRPM_t *tmp_drpm = NULL, *tmp_drpm2 = NULL; + H264dVideoCtx_t *p_Vid = pSlice->p_Vid; + BitReadCtx_t *p_bitctx = &pSlice->p_Cur->bitctx; + //!< free old buffer content + free_slice_drpm_buffer(pSlice); + if (pSlice->idr_flag || + (pSlice->svc_extension_flag == 0 && pSlice->mvcExt.non_idr_flag == 0)) + { + READ_ONEBIT(ret, p_bitctx, &pSlice->no_output_of_prior_pics_flag, "no_output_of_prior_pics_flag"); + p_Vid->no_output_of_prior_pics_flag = pSlice->no_output_of_prior_pics_flag; + READ_ONEBIT(ret, p_bitctx, &pSlice->long_term_reference_flag, "long_term_reference_flag"); + } + else + { + READ_ONEBIT(ret, p_bitctx, &pSlice->adaptive_ref_pic_buffering_flag, "adaptive_ref_pic_buffering_flag"); + + if (pSlice->adaptive_ref_pic_buffering_flag) + { + do //!< read Memory Management Control Operation + { + tmp_drpm = mpp_calloc(H264_DRPM_t, 1); + MEM_CHECK(ret, tmp_drpm); + tmp_drpm->Next = NULL; + READ_UE(ret, p_bitctx, &val, "memory_management_control_operation"); + tmp_drpm->memory_management_control_operation = val; + + if ((val == 1) || (val == 3)) + { + READ_UE(ret, p_bitctx, &tmp_drpm->difference_of_pic_nums_minus1, "difference_of_pic_nums_minus1"); + } + if (val == 2) + { + READ_UE(ret, p_bitctx, &tmp_drpm->long_term_pic_num, "long_term_pic_num"); + } + if ((val == 3) || (val == 6)) + { + READ_UE(ret, p_bitctx, &tmp_drpm->long_term_frame_idx, "long_term_frame_idx"); + } + if (val == 4) + { + READ_UE(ret, p_bitctx, &tmp_drpm->max_long_term_frame_idx_plus1, "max_long_term_frame_idx_plus1"); + } + // add command + if (pSlice->dec_ref_pic_marking_buffer == NULL) + { + pSlice->dec_ref_pic_marking_buffer = tmp_drpm; + } + else + { + tmp_drpm2 = pSlice->dec_ref_pic_marking_buffer; + while (tmp_drpm2->Next != NULL) + { + tmp_drpm2 = tmp_drpm2->Next; + } + tmp_drpm2->Next = tmp_drpm; + } + + } while (val != 0); + } + } + + return ret = MPP_OK; +__FAILED: + + return ret; +} + +static void init_slice_parmeters(H264_SLICE_t *currSlice) +{ + H264dVideoCtx_t *p_Vid = currSlice->p_Vid; + H264_Nalu_t *cur_nalu = &currSlice->p_Cur->nalu; + + //--- init slice syntax + currSlice->idr_flag = ((cur_nalu->nal_unit_type == NALU_TYPE_IDR) + || (currSlice->mvcExt.valid && !currSlice->mvcExt.non_idr_flag)); + currSlice->nal_reference_idc = cur_nalu->nal_reference_idc; + if ((!currSlice->svc_extension_flag) || currSlice->mvcExt.iPrefixNALU) // MVC or have prefixNALU + { + currSlice->view_id = currSlice->mvcExt.view_id; + currSlice->inter_view_flag = currSlice->mvcExt.inter_view_flag; + currSlice->anchor_pic_flag = currSlice->mvcExt.anchor_pic_flag; + } + else if (currSlice->svc_extension_flag == -1) // normal AVC + { + currSlice->view_id = currSlice->mvcExt.valid ? p_Vid->active_subsps->view_id[0] : 0; + currSlice->inter_view_flag = 1; + currSlice->anchor_pic_flag = currSlice->idr_flag; + } + currSlice->layer_id = get_voidx(p_Vid->subspsSet, &p_Vid->active_subsps, currSlice->view_id); + if (currSlice->layer_id >= 0) // if not found, layer_id == -1 + { + currSlice->p_Dpb = p_Vid->p_Dpb_layer[currSlice->layer_id]; + } +} + +static MPP_RET set_slice_user_parmeters(H264_SLICE_t *currSlice) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264_PPS_t *cur_pps = NULL; + H264_SPS_t *cur_sps = NULL; + H264_subSPS_t *cur_subsps = NULL; + H264dVideoCtx_t *p_Vid = currSlice->p_Vid; + //!< use parameter set + cur_pps = &p_Vid->ppsSet[currSlice->pic_parameter_set_id]; + ASSERT(cur_pps != NULL); + if (currSlice->mvcExt.valid) + { + cur_sps = &p_Vid->subspsSet[cur_pps->seq_parameter_set_id].sps; + cur_subsps = &p_Vid->subspsSet[cur_pps->seq_parameter_set_id]; + if (cur_subsps->Valid) + { + if ((RK_S32)currSlice->mvcExt.view_id == cur_subsps->view_id[0]) // combine subsps to sps + { + p_Vid->active_mvc_sps_flag = 0; + cur_subsps = NULL; + cur_sps = &p_Vid->spsSet[cur_pps->seq_parameter_set_id]; + } + else if ((RK_S32)currSlice->mvcExt.view_id == cur_subsps->view_id[1]) + { + p_Vid->active_mvc_sps_flag = 1; + } + } + else + { + p_Vid->active_mvc_sps_flag = 0; + cur_sps = &p_Vid->spsSet[cur_pps->seq_parameter_set_id]; + cur_subsps = NULL; + } + } + else + { + p_Vid->active_mvc_sps_flag = 0; + cur_sps = &p_Vid->spsSet[cur_pps->seq_parameter_set_id]; + cur_subsps = NULL; + } + ASSERT(cur_sps->separate_colour_plane_flag == 0); + FUN_CHECK(ret = activate_sps(p_Vid, cur_sps, cur_subsps)); + FUN_CHECK(ret = activate_pps(p_Vid, cur_pps)); + //!< Set SPS to the subset SPS parameters + if (currSlice->svc_extension_flag == 0) + { + p_Vid->active_subsps = &p_Vid->subspsSet[cur_pps->seq_parameter_set_id]; + } + currSlice->active_sps = p_Vid->active_sps; + currSlice->active_pps = p_Vid->active_pps; + + return MPP_OK; +__FAILED: + ASSERT(0); + return ret; +} + +/*! +*********************************************************************** +* \brief +* parse SEI information +*********************************************************************** +*/ +//extern "C" +void recycle_slice(H264_SLICE_t *currSlice) +{ + if (currSlice) + { + free_slice_drpm_buffer(currSlice); + } +} +/*! +*********************************************************************** +* \brief +* parse SEI information +*********************************************************************** +*/ +//extern "C" +MPP_RET process_slice(H264_SLICE_t *currSlice) +{ + RK_U32 temp = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + H264dLogCtx_t *logctx = currSlice->logctx; + H264dVideoCtx_t *p_Vid = currSlice->p_Vid; + H264dCurCtx_t *p_Cur = currSlice->p_Cur; + BitReadCtx_t *p_bitctx = &p_Cur->bitctx; + + FunctionIn(logctx->parr[RUN_PARSE]); + //--- initial value ---- + currSlice->p_Dpb_layer[0] = p_Vid->p_Dpb_layer[0]; + currSlice->p_Dpb_layer[1] = p_Vid->p_Dpb_layer[1]; + set_bitread_logctx(p_bitctx, logctx->parr[LOG_READ_SLICE]); + init_slice_parmeters(currSlice); + WRITE_LOG(p_bitctx, "----------------------------- SLICE begin --------------------------------"); + //------- read slice head syntax -------- + READ_UE(ret, p_bitctx, &currSlice->start_mb_nr, "first_mb_in_slice"); + READ_UE(ret, p_bitctx, &temp, "slice_type"); + p_Vid->slice_type = currSlice->slice_type = temp % 5; + READ_UE(ret, p_bitctx, &currSlice->pic_parameter_set_id, "slice_pic_parameter_set_id"); + + FUN_CHECK(ret = set_slice_user_parmeters(currSlice)); + //!< read rest slice header syntax + READ_BITS(ret, p_bitctx, currSlice->active_sps->log2_max_frame_num_minus4 + 4, &currSlice->frame_num, "frame_num"); + if (currSlice->active_sps->frame_mbs_only_flag) //!< user in_slice info + { + p_Vid->structure = FRAME; + currSlice->field_pic_flag = 0; + currSlice->bottom_field_flag = 0; + } + else + { + READ_ONEBIT(ret, p_bitctx, &currSlice->field_pic_flag, "field_pic_flag"); + if (currSlice->field_pic_flag) + { + READ_ONEBIT(ret, p_bitctx, &currSlice->bottom_field_flag, "field_pic_flag"); + p_Vid->structure = currSlice->bottom_field_flag ? BOTTOM_FIELD : TOP_FIELD; + } + else + { + p_Vid->structure = FRAME; + currSlice->bottom_field_flag = 0; + } + } + currSlice->structure = p_Vid->structure; + currSlice->mb_aff_frame_flag = (currSlice->active_sps->mb_adaptive_frame_field_flag && (currSlice->field_pic_flag == 0)); + if (currSlice->idr_flag) + { + READ_UE(ret, p_bitctx, &currSlice->idr_pic_id, "idr_pic_id"); + } + else if (currSlice->svc_extension_flag == 0 && currSlice->mvcExt.non_idr_flag == 0) + { + READ_UE(ret, p_bitctx, &currSlice->idr_pic_id, "idr_pic_id"); + } + if (currSlice->active_sps->pic_order_cnt_type == 0) + { + READ_BITS(ret, p_bitctx, currSlice->active_sps->log2_max_pic_order_cnt_lsb_minus4 + 4, &currSlice->pic_order_cnt_lsb, "pic_order_cnt_lsb"); + if (currSlice->p_Vid->active_pps->bottom_field_pic_order_in_frame_present_flag == 1 + && !currSlice->field_pic_flag) + { + READ_SE(ret, p_bitctx, &currSlice->delta_pic_order_cnt_bottom, "delta_pic_order_cnt_bottom"); + } + else + { + currSlice->delta_pic_order_cnt_bottom = 0; + } + } + if (currSlice->active_sps->pic_order_cnt_type == 1) + { + if (!currSlice->active_sps->delta_pic_order_always_zero_flag) + { + READ_SE(ret, p_bitctx, &currSlice->delta_pic_order_cnt[0], "delta_pic_order_cnt[0]"); + + if (currSlice->p_Vid->active_pps->bottom_field_pic_order_in_frame_present_flag == 1 && !currSlice->field_pic_flag) + { + READ_SE(ret, p_bitctx, &currSlice->delta_pic_order_cnt[1], "delta_pic_order_cnt[1]"); + } + else + { + currSlice->delta_pic_order_cnt[1] = 0; // set to zero if not in stream + } + } + else + { + currSlice->delta_pic_order_cnt[0] = 0; + currSlice->delta_pic_order_cnt[1] = 0; + } + } + //! redundant_pic_cnt is missing here + ASSERT(currSlice->p_Vid->active_pps->redundant_pic_cnt_present_flag == 0); // add by dw, high 4:2:2 profile not support + if (currSlice->p_Vid->active_pps->redundant_pic_cnt_present_flag) + { + READ_UE(ret, p_bitctx, &currSlice->redundant_pic_cnt, "redundant_pic_cnt"); + } + + if (currSlice->slice_type == B_SLICE) + { + READ_ONEBIT(ret, p_bitctx, &currSlice->direct_spatial_mv_pred_flag, "direct_spatial_mv_pred_flag"); + } + else + { + currSlice->direct_spatial_mv_pred_flag = 0; + } + currSlice->num_ref_idx_active[LIST_0] = currSlice->p_Vid->active_pps->num_ref_idx_l0_default_active_minus1 + 1; + currSlice->num_ref_idx_active[LIST_1] = currSlice->p_Vid->active_pps->num_ref_idx_l1_default_active_minus1 + 1; + + if (currSlice->slice_type == P_SLICE + || currSlice->slice_type == SP_SLICE || currSlice->slice_type == B_SLICE) + { + //!< "direct_spatial_mv_pred_flag" + READ_ONEBIT(ret, p_bitctx, &currSlice->num_ref_idx_override_flag, "num_ref_idx_override_flag"); + if (currSlice->num_ref_idx_override_flag) + { + READ_UE(ret, p_bitctx, &currSlice->num_ref_idx_active[LIST_0], "num_ref_idx_active0"); + currSlice->num_ref_idx_active[LIST_0] += 1; + if (currSlice->slice_type == B_SLICE) + { + READ_UE(ret, p_bitctx, &currSlice->num_ref_idx_active[LIST_1], "num_ref_idx_active1"); + currSlice->num_ref_idx_active[LIST_1] += 1; + } + } + } + if (currSlice->slice_type != B_SLICE) + { + currSlice->num_ref_idx_active[LIST_1] = 0; + } + + if (is_new_picture(currSlice)) + { + FUN_CHECK(ret = ref_pic_list_mvc_modification(currSlice)); + if ((currSlice->p_Vid->active_pps->weighted_pred_flag + && (currSlice->slice_type == P_SLICE || currSlice->slice_type == SP_SLICE)) + || (currSlice->p_Vid->active_pps->weighted_bipred_idc == 1 && (currSlice->slice_type == B_SLICE))) + { + FUN_CHECK(ret = pred_weight_table(currSlice)); + } + if (currSlice->nal_reference_idc) + { + FUN_CHECK(ret = dec_ref_pic_marking(currSlice)); + } + currSlice->is_new_picture_flag = 1; + } + + FunctionOut(logctx->parr[RUN_PARSE]); + + return ret = MPP_OK; +__FAILED: + recycle_slice(currSlice); + + return ret; +} diff --git a/mpp/codec/dec/h264/h264d_slice.h b/mpp/codec/dec/h264/h264d_slice.h new file mode 100644 index 00000000..26f8a766 --- /dev/null +++ b/mpp/codec/dec/h264/h264d_slice.h @@ -0,0 +1,39 @@ +/* +* +* 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. +*/ + +#ifndef __H264D_SLICE_H__ +#define __H264D_SLICE_H__ + +#include "rk_type.h" +#include "mpp_err.h" +#include "h264d_global.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + void recycle_slice(H264_SLICE_t *currSlice); + MPP_RET process_slice(H264_SLICE_t *currSlice); + +#ifdef __cplusplus +} +#endif + +//======================================== +#endif /* end of __H264D_SLICE_H__ */ + diff --git a/mpp/codec/dec/h264/h264d_sps.c b/mpp/codec/dec/h264/h264d_sps.c new file mode 100644 index 00000000..ad265978 --- /dev/null +++ b/mpp/codec/dec/h264/h264d_sps.c @@ -0,0 +1,592 @@ +/* +* +* 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. +*/ +#include + +#include "mpp_mem.h" + +#include "h264d_log.h" +#include "h264d_bitread.h" +#include "h264d_sps.h" +#include "h264d_scalist.h" +#include "h264d_dpb.h" + + +#define MODULE_TAG "h264d_sps" + +static void reset_cur_sps_data(H264_SPS_t *cur_sps) +{ + memset(cur_sps, 0, sizeof(H264_SPS_t)); + cur_sps->seq_parameter_set_id = -1; // reset +} + +static void reset_cur_subpps_data(H264_subSPS_t *cur_subpps) +{ + memset(cur_subpps, 0, sizeof(H264_subSPS_t)); + cur_subpps->sps.seq_parameter_set_id = -1; // reset + cur_subpps->num_views_minus1 = -1; + cur_subpps->num_level_values_signalled_minus1 = -1; +} + +static MPP_RET read_hrd_parameters(BitReadCtx_t *p_bitctx, H264_HRD_t *hrd) +{ + RK_U32 SchedSelIdx = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + + READ_UE(ret, p_bitctx, &hrd->cpb_cnt_minus1, "cpb_cnt_minus1"); + READ_BITS(ret, p_bitctx, 4, &hrd->bit_rate_scale, "bit_rate_scale"); + READ_BITS(ret, p_bitctx, 4, &hrd->cpb_size_scale, "cpb_size_scale"); + for (SchedSelIdx = 0; SchedSelIdx <= hrd->cpb_cnt_minus1; SchedSelIdx++) + { + READ_UE(ret, p_bitctx, &hrd->bit_rate_value_minus1[SchedSelIdx], "VUI: bit_rate_value_minus1"); + READ_UE(ret, p_bitctx, &hrd->cpb_size_value_minus1[SchedSelIdx], "VUI: cpb_size_value_minus1"); + READ_ONEBIT(ret, p_bitctx, &hrd->cbr_flag[SchedSelIdx], "VUI: cbr_flag"); + } + READ_BITS(ret, p_bitctx, 5, &hrd->initial_cpb_removal_delay_length_minus1, "initial_cpb_removal_delay_length_minus1"); + READ_BITS(ret, p_bitctx, 5, &hrd->cpb_removal_delay_length_minus1, "cpb_removal_delay_length_minus1"); + READ_BITS(ret, p_bitctx, 5, &hrd->dpb_output_delay_length_minus1, "dpb_output_delay_length_minus1"); + READ_BITS(ret, p_bitctx, 5, &hrd->time_offset_length, "time_offset_length"); + + return ret = MPP_OK; +__FAILED: + return ret; +} + +static void init_VUI(H264_VUI_t *vui) +{ + vui->matrix_coefficients = 2; +} + +static MPP_RET read_VUI(BitReadCtx_t *p_bitctx, H264_VUI_t *vui) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + READ_ONEBIT(ret, p_bitctx, &vui->aspect_ratio_info_present_flag, "vui.aspect_ratio_info_present_flag"); + if (vui->aspect_ratio_info_present_flag) + { + READ_BITS(ret, p_bitctx, 8, &vui->aspect_ratio_idc, "vui.aspect_ratio_idc"); + if (255 == vui->aspect_ratio_idc) + { + READ_BITS(ret, p_bitctx, 16, &vui->sar_width, "VUI: sar_width"); + READ_BITS(ret, p_bitctx, 16, &vui->sar_height, "VUI: sar_height"); + } + } + READ_ONEBIT(ret, p_bitctx, &vui->overscan_info_present_flag, "VUI: overscan_info_present_flag"); + if (vui->overscan_info_present_flag) + { + READ_ONEBIT(ret, p_bitctx, &vui->overscan_appropriate_flag, "VUI: overscan_appropriate_flag"); + } + READ_ONEBIT(ret, p_bitctx, &vui->video_signal_type_present_flag, "VUI: video_signal_type_present_flag"); + if (vui->video_signal_type_present_flag) + { + READ_BITS(ret, p_bitctx, 3, &vui->video_format, "VUI: video_format"); + READ_ONEBIT(ret, p_bitctx, &vui->video_full_range_flag, "VUI: video_full_range_flag"); + READ_ONEBIT(ret, p_bitctx, &vui->colour_description_present_flag, "VUI: color_description_present_flag"); + if (vui->colour_description_present_flag) + { + READ_BITS(ret, p_bitctx, 8, &vui->colour_primaries, "VUI: colour_primaries"); + READ_BITS(ret, p_bitctx, 8, &vui->transfer_characteristics, "VUI: transfer_characteristics"); + READ_BITS(ret, p_bitctx, 8, &vui->matrix_coefficients, "VUI: matrix_coefficients"); + } + } + READ_ONEBIT(ret, p_bitctx, &vui->chroma_location_info_present_flag, "VUI: chroma_location_info_present_flag"); + if (vui->chroma_location_info_present_flag) + { + READ_UE(ret, p_bitctx, &vui->chroma_sample_loc_type_top_field, "VUI: chroma_sample_loc_type_top_field"); + READ_UE(ret, p_bitctx, &vui->chroma_sample_loc_type_bottom_field, "VUI: chroma_sample_loc_type_bottom_field"); + } + READ_ONEBIT(ret, p_bitctx, &vui->timing_info_present_flag, "VUI: timing_info_present_flag"); + if (vui->timing_info_present_flag) + { + READ_BITS(ret, p_bitctx, 16, &vui->num_units_in_tick, "VUI: num_units_in_tick(high 16bit)"); + READ_BITS(ret, p_bitctx, 16, &vui->num_units_in_tick, "VUI: num_units_in_tick(low 16bit)"); + READ_BITS(ret, p_bitctx, 16, &vui->time_scale, "VUI: time_scale(high 16bit)"); + READ_BITS(ret, p_bitctx, 16, &vui->time_scale, "VUI: time_scale(low 16bit)"); + READ_ONEBIT(ret, p_bitctx, &vui->fixed_frame_rate_flag, "VUI: fixed_frame_rate_flag"); + } + READ_ONEBIT(ret, p_bitctx, &vui->nal_hrd_parameters_present_flag, "VUI: nal_hrd_parameters_present_flag"); + if (vui->nal_hrd_parameters_present_flag) + { + FUN_CHECK(ret = read_hrd_parameters(p_bitctx, &vui->nal_hrd_parameters)); + } + READ_ONEBIT(ret, p_bitctx, &vui->vcl_hrd_parameters_present_flag, "VUI: vcl_hrd_parameters_present_flag"); + if (vui->vcl_hrd_parameters_present_flag) + { + FUN_CHECK(ret = read_hrd_parameters(p_bitctx, &vui->vcl_hrd_parameters)); + } + if (vui->nal_hrd_parameters_present_flag || vui->vcl_hrd_parameters_present_flag) + { + READ_ONEBIT(ret, p_bitctx, &vui->low_delay_hrd_flag, "VUI: low_delay_hrd_flag"); + } + READ_ONEBIT(ret, p_bitctx, &vui->pic_struct_present_flag, "VUI: pic_struct_present_flag"); + READ_ONEBIT(ret, p_bitctx, &vui->bitstream_restriction_flag, "VUI: bitstream_restriction_flag"); + if (vui->bitstream_restriction_flag) + { + READ_ONEBIT(ret, p_bitctx, &vui->motion_vectors_over_pic_boundaries_flag, "VUI: motion_vectors_over_pic_boundaries_flag"); + READ_UE(ret, p_bitctx, &vui->max_bytes_per_pic_denom, "VUI: max_bytes_per_pic_denom"); + READ_UE(ret, p_bitctx, &vui->max_bits_per_mb_denom, "VUI: max_bits_per_mb_denom"); + READ_UE(ret, p_bitctx, &vui->log2_max_mv_length_horizontal, "VUI: log2_max_mv_length_horizontal"); + READ_UE(ret, p_bitctx, &vui->log2_max_mv_length_vertical, "VUI: log2_max_mv_length_vertical"); + READ_UE(ret, p_bitctx, &vui->num_reorder_frames, "VUI: num_reorder_frames"); + READ_UE(ret, p_bitctx, &vui->max_dec_frame_buffering, "VUI: max_dec_frame_buffering"); + } + + return ret = MPP_OK; +__FAILED: + return ret; +} + +static MPP_RET parser_sps(BitReadCtx_t *p_bitctx, H264_SPS_t *cur_sps) +{ + RK_S32 i = 0, temp = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + //!< init Fidelity Range Extensions stuff + cur_sps->chroma_format_idc = 1; + cur_sps->bit_depth_luma_minus8 = 0; + cur_sps->bit_depth_chroma_minus8 = 0; + cur_sps->qpprime_y_zero_transform_bypass_flag = 0; + cur_sps->separate_colour_plane_flag = 0; + cur_sps->log2_max_pic_order_cnt_lsb_minus4 = 0; + cur_sps->delta_pic_order_always_zero_flag = 0; + WRITE_LOG(p_bitctx, "----------------------------- SPS begin --------------------------------"); + READ_BITS(ret, p_bitctx, 8, &cur_sps->profile_idc, "profile_idc"); + VAL_CHECK (ret, (cur_sps->profile_idc == BASELINE) || (cur_sps->profile_idc == H264_MAIN) + || (cur_sps->profile_idc == EXTENDED) || (cur_sps->profile_idc == FREXT_HP) + || (cur_sps->profile_idc == FREXT_Hi10P) || (cur_sps->profile_idc == FREXT_Hi422) + || (cur_sps->profile_idc == FREXT_Hi444) || (cur_sps->profile_idc == FREXT_CAVLC444) + || (cur_sps->profile_idc == MVC_HIGH) || (cur_sps->profile_idc == STEREO_HIGH) + ); + READ_ONEBIT(ret, p_bitctx, &cur_sps->constrained_set0_flag, "constrained_set0_flag"); + READ_ONEBIT(ret, p_bitctx, &cur_sps->constrained_set1_flag, "constrained_set1_flag"); + READ_ONEBIT(ret, p_bitctx, &cur_sps->constrained_set2_flag, "constrained_set2_flag"); + READ_ONEBIT(ret, p_bitctx, &cur_sps->constrained_set3_flag, "constrained_set3_flag"); + READ_ONEBIT(ret, p_bitctx, &cur_sps->constrained_set4_flag, "constrained_set4_flag"); + READ_ONEBIT(ret, p_bitctx, &cur_sps->constrained_set5_flag, "constrained_set5_flag"); + READ_BITS(ret, p_bitctx, 2, &temp, "reserved_zero_2bits"); // reserved_zero_2bits + ASSERT(temp == 0); + READ_BITS(ret, p_bitctx, 8, &cur_sps->level_idc, "level_idc"); + READ_UE(ret, p_bitctx, &cur_sps->seq_parameter_set_id, "seq_parameter_set_id"); + ASSERT(cur_sps->seq_parameter_set_id < 32); + + if (cur_sps->profile_idc == 100 || cur_sps->profile_idc == 110 + || cur_sps->profile_idc == 122 || cur_sps->profile_idc == 244 + || cur_sps->profile_idc == 44 || cur_sps->profile_idc == 83 + || cur_sps->profile_idc == 86 || cur_sps->profile_idc == 118 + || cur_sps->profile_idc == 128 || cur_sps->profile_idc == 138) + { + READ_UE(ret, p_bitctx, &cur_sps->chroma_format_idc, "chroma_format_idc"); + ASSERT(cur_sps->chroma_format_idc < 4); + + if (cur_sps->chroma_format_idc == 3) + { + READ_ONEBIT(ret, p_bitctx, &cur_sps->separate_colour_plane_flag, "separate_colour_plane_flag"); + LogError(p_bitctx->ctx, "Not support YUV444 format current."); + } + + READ_UE(ret, p_bitctx, &cur_sps->bit_depth_luma_minus8, "bit_depth_luma_minus8"); + ASSERT(cur_sps->bit_depth_luma_minus8 < 7); + READ_UE(ret, p_bitctx, &cur_sps->bit_depth_chroma_minus8, "bit_depth_chroma_minus8"); + ASSERT(cur_sps->bit_depth_chroma_minus8 < 7); + READ_ONEBIT(ret, p_bitctx, &cur_sps->qpprime_y_zero_transform_bypass_flag, "qpprime_y_zero_transform_bypass_flag"); + READ_ONEBIT(ret, p_bitctx, &cur_sps->seq_scaling_matrix_present_flag, "seq_scaling_matrix_present_flag"); + if (cur_sps->seq_scaling_matrix_present_flag) + { + LogInfo(p_bitctx->ctx, "Scaling matrix present."); + if (parse_sps_scalinglists(p_bitctx, cur_sps)) + { + LogError(p_bitctx->ctx, "rkv_parse_sps_scalinglists error."); + } + } + } + READ_UE(ret, p_bitctx, &cur_sps->log2_max_frame_num_minus4, "log2_max_frame_num_minus4"); + ASSERT(cur_sps->log2_max_frame_num_minus4 < 13); + READ_UE(ret, p_bitctx, &cur_sps->pic_order_cnt_type, "pic_order_cnt_type"); + ASSERT(cur_sps->pic_order_cnt_type < 3); + + cur_sps->log2_max_pic_order_cnt_lsb_minus4 = 0; + cur_sps->delta_pic_order_always_zero_flag = RET_FALSE; + if (0 == cur_sps->pic_order_cnt_type) + { + READ_UE(ret, p_bitctx, &cur_sps->log2_max_pic_order_cnt_lsb_minus4, "log2_max_pic_order_cnt_lsb_minus4"); + ASSERT(cur_sps->log2_max_pic_order_cnt_lsb_minus4 < 13); + } + else if (1 == cur_sps->pic_order_cnt_type) + { + READ_ONEBIT(ret, p_bitctx, &cur_sps->delta_pic_order_always_zero_flag, "delta_pic_order_always_zero_flag"); + READ_SE(ret, p_bitctx, &cur_sps->offset_for_non_ref_pic, "offset_for_non_ref_pic"); + READ_SE(ret, p_bitctx, &cur_sps->offset_for_top_to_bottom_field, "offset_for_top_to_bottom_field"); + READ_UE(ret, p_bitctx, &cur_sps->num_ref_frames_in_pic_order_cnt_cycle, "num_ref_frames_in_pic_order_cnt_cycle"); + ASSERT(cur_sps->num_ref_frames_in_pic_order_cnt_cycle < 256); + for (i = 0; i < cur_sps->num_ref_frames_in_pic_order_cnt_cycle; ++i) + { + READ_SE(ret, p_bitctx, &cur_sps->offset_for_ref_frame[i], "offset_for_ref_frame"); + cur_sps->expected_delta_per_pic_order_cnt_cycle += cur_sps->offset_for_ref_frame[i]; + } + } + READ_UE(ret, p_bitctx, &cur_sps->max_num_ref_frames, "max_num_ref_frames"); + READ_ONEBIT(ret, p_bitctx, &cur_sps->gaps_in_frame_num_value_allowed_flag, "gaps_in_frame_num_value_allowed_flag"); + READ_UE(ret, p_bitctx, &cur_sps->pic_width_in_mbs_minus1, "pic_width_in_mbs_minus1"); + READ_UE(ret, p_bitctx, &cur_sps->pic_height_in_map_units_minus1, "pic_height_in_map_units_minus1"); + READ_ONEBIT(ret, p_bitctx, &cur_sps->frame_mbs_only_flag, "frame_mbs_only_flag"); + if (!cur_sps->frame_mbs_only_flag) + { + READ_ONEBIT(ret, p_bitctx, &cur_sps->mb_adaptive_frame_field_flag, "mb_adaptive_frame_field_flag"); + } + READ_ONEBIT(ret, p_bitctx, &cur_sps->direct_8x8_inference_flag, "direct_8x8_inference_flag"); + + READ_ONEBIT(ret, p_bitctx, &cur_sps->frame_cropping_flag, "frame_cropping_flag"); + if (cur_sps->frame_cropping_flag) + { + READ_UE(ret, p_bitctx, &cur_sps->frame_crop_left_offset, "frame_crop_left_offset"); + READ_UE(ret, p_bitctx, &cur_sps->frame_crop_right_offset, "frame_crop_right_offset"); + READ_UE(ret, p_bitctx, &cur_sps->frame_crop_top_offset, "frame_crop_top_offset"); + READ_UE(ret, p_bitctx, &cur_sps->frame_crop_bottom_offset, "frame_crop_bottom_offset"); + } + READ_ONEBIT(ret, p_bitctx, &cur_sps->vui_parameters_present_flag, "vui_parameters_present_flag"); + + init_VUI(&cur_sps->vui_seq_parameters); + if (cur_sps->vui_parameters_present_flag) + { + FUN_CHECK(ret = read_VUI(p_bitctx, &cur_sps->vui_seq_parameters)); + } + cur_sps->Valid = 1; + + return ret = MPP_OK; +__FAILED: + return ret; +} + +static MPP_RET sps_mvc_extension(BitReadCtx_t *p_bitctx, H264_subSPS_t *subset_sps) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + RK_S32 i = 0, j = 0, num_views = 0; + + READ_UE(ret, p_bitctx, &subset_sps->num_views_minus1, "SPS_MVC_EXT:num_views_minus1"); + num_views = 1 + subset_sps->num_views_minus1; + //======================== + if (num_views > 0) + { + subset_sps->view_id = mpp_calloc(RK_S32, num_views); + subset_sps->num_anchor_refs_l0 = mpp_calloc(RK_S32, num_views); + subset_sps->num_anchor_refs_l1 = mpp_calloc(RK_S32, num_views); + subset_sps->anchor_ref_l0 = mpp_calloc(RK_S32*, num_views); + subset_sps->anchor_ref_l1 = mpp_calloc(RK_S32*, num_views); + subset_sps->num_non_anchor_refs_l0 = mpp_calloc(RK_S32, num_views); + subset_sps->num_non_anchor_refs_l1 = mpp_calloc(RK_S32, num_views); + subset_sps->non_anchor_ref_l0 = mpp_calloc(RK_S32*, num_views); + subset_sps->non_anchor_ref_l1 = mpp_calloc(RK_S32*, num_views); + MEM_CHECK(ret, subset_sps->view_id && subset_sps->num_anchor_refs_l0 + && subset_sps->num_anchor_refs_l1 && subset_sps->anchor_ref_l0 + && subset_sps->anchor_ref_l1 && subset_sps->num_non_anchor_refs_l0 + && subset_sps->num_non_anchor_refs_l1 && subset_sps->non_anchor_ref_l0 + && subset_sps->non_anchor_ref_l1); + } + for (i = 0; i < num_views; i++) + { + READ_UE(ret, p_bitctx, &subset_sps->view_id[i], "SPS_MVC_EXT: view_id"); + } + for (i = 1; i < num_views; i++) + { + READ_UE(ret, p_bitctx, &subset_sps->num_anchor_refs_l0[i], "SPS_MVC_EXT: num_anchor_refs_l0"); + if (subset_sps->num_anchor_refs_l0[i]) + { + subset_sps->anchor_ref_l0[i] = mpp_calloc(RK_S32, subset_sps->num_anchor_refs_l0[i]); + MEM_CHECK(ret, subset_sps->anchor_ref_l0[i]); + for (j = 0; j < subset_sps->num_anchor_refs_l0[i]; j++) + { + READ_UE(ret, p_bitctx, &subset_sps->anchor_ref_l0[i][j], "SPS_MVC_EXT: anchor_ref_l0"); + } + } + READ_UE(ret, p_bitctx, &subset_sps->num_anchor_refs_l1[i], "SPS_MVC_EXT: num_anchor_refs_l1"); + if (subset_sps->num_anchor_refs_l1[i]) + { + subset_sps->anchor_ref_l1[i] = mpp_calloc(RK_S32, subset_sps->num_anchor_refs_l1[i]); + MEM_CHECK(ret, subset_sps->anchor_ref_l1[i]); + for (j = 0; j < subset_sps->num_anchor_refs_l1[i]; j++) + { + READ_UE(ret, p_bitctx, &subset_sps->anchor_ref_l1[i][j], "SPS_MVC_EXT: anchor_ref_l0"); + } + } + } + for (i = 1; i < num_views; i++) + { + READ_UE(ret, p_bitctx, &subset_sps->num_non_anchor_refs_l0[i], "SPS_MVC_EXT: num_non_anchor_refs_l0"); + if (subset_sps->num_non_anchor_refs_l0[i]) + { + subset_sps->non_anchor_ref_l0[i] = mpp_calloc(RK_S32, subset_sps->num_non_anchor_refs_l0[i]); + MEM_CHECK(ret, subset_sps->non_anchor_ref_l0[i]); + for (j = 0; j < subset_sps->num_non_anchor_refs_l0[i]; j++) + { + READ_UE(ret, p_bitctx, &subset_sps->non_anchor_ref_l0[i][j], "SPS_MVC_EXT: non_anchor_ref_l0"); + } + } + READ_UE(ret, p_bitctx, &subset_sps->num_non_anchor_refs_l1[i], "SPS_MVC_EXT: num_non_anchor_refs_l1"); + if (subset_sps->num_non_anchor_refs_l1[i]) + { + subset_sps->non_anchor_ref_l1[i] = mpp_calloc(RK_S32, subset_sps->num_non_anchor_refs_l1[i]); + MEM_CHECK(ret, subset_sps->non_anchor_ref_l1[i]); + + for (j = 0; j < subset_sps->num_non_anchor_refs_l1[i]; j++) + { + READ_UE(ret, p_bitctx, &subset_sps->non_anchor_ref_l1[i][j], "SPS_MVC_EXT: non_anchor_ref_l1"); + } + } + } + return ret = MPP_OK; +__FAILED: + ASSERT(0); + return ret; +} + +static MPP_RET parser_subsps_ext(BitReadCtx_t *p_bitctx, H264_subSPS_t *cur_subsps) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + if ((cur_subsps->sps.profile_idc == MVC_HIGH) + || (cur_subsps->sps.profile_idc == STEREO_HIGH)) + { + READ_ONEBIT(ret, p_bitctx, &cur_subsps->bit_equal_to_one, "bit_equal_to_one"); + ASSERT(cur_subsps->bit_equal_to_one == 1); + FUN_CHECK(ret = sps_mvc_extension(p_bitctx, cur_subsps)); + + READ_ONEBIT(ret, p_bitctx, &cur_subsps->mvc_vui_parameters_present_flag, "mvc_vui_parameters_present_flag"); + } + + return ret = MPP_OK; +__FAILED: + return ret; +} + +static void update_video_pars(H264dVideoCtx_t *p_Vid, H264_SPS_t *sps) +{ + p_Vid->max_frame_num = 1 << (sps->log2_max_frame_num_minus4 + 4); + p_Vid->PicWidthInMbs = (sps->pic_width_in_mbs_minus1 + 1); + p_Vid->FrameHeightInMbs = (2 - sps->frame_mbs_only_flag) * (sps->pic_height_in_map_units_minus1 + 1); + p_Vid->yuv_format = sps->chroma_format_idc; + + p_Vid->width = p_Vid->PicWidthInMbs * MB_BLOCK_SIZE; + p_Vid->height = p_Vid->FrameHeightInMbs * MB_BLOCK_SIZE; + + if (p_Vid->yuv_format == YUV420) + { + p_Vid->width_cr = (p_Vid->width >> 1); + p_Vid->height_cr = (p_Vid->height >> 1); + } + else if (p_Vid->yuv_format == YUV422) + { + p_Vid->width_cr = (p_Vid->width >> 1); + p_Vid->height_cr = p_Vid->height; + } +} + +static RK_U32 video_pars_changed(H264dVideoCtx_t *p_Vid, H264_SPS_t *sps, RK_U8 layer_id) +{ + RK_U32 ret = 0; + + ret |= p_Vid->p_Dpb_layer[layer_id]->num_ref_frames != sps->max_num_ref_frames; + ret |= p_Vid->last_pic_width_in_mbs_minus1[layer_id] != sps->pic_width_in_mbs_minus1; + ret |= p_Vid->last_pic_height_in_map_units_minus1[layer_id] != sps->pic_height_in_map_units_minus1; + ret |= p_Vid->last_profile_idc[layer_id] != sps->profile_idc; + ret |= p_Vid->last_level_idc[layer_id] != sps->level_idc; + ret |= !p_Vid->p_Dpb_layer[layer_id]->init_done; + + return ret; +} + +static void update_last_video_pars(H264dVideoCtx_t *p_Vid, H264_SPS_t *sps, RK_U8 layer_id) +{ + p_Vid->last_pic_width_in_mbs_minus1[layer_id] = sps->pic_width_in_mbs_minus1; + p_Vid->last_pic_height_in_map_units_minus1[layer_id] = sps->pic_height_in_map_units_minus1; + p_Vid->last_profile_idc[layer_id] = sps->profile_idc; + p_Vid->last_level_idc[layer_id] = sps->level_idc; +} + +/*! +*********************************************************************** +* \brief +* prase sps and process sps +*********************************************************************** +*/ +//extern "C" +MPP_RET process_sps(H264_SLICE_t *currSlice) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dLogCtx_t *logctx = currSlice->logctx; + H264dCurCtx_t *p_Cur = currSlice->p_Cur; + BitReadCtx_t *p_bitctx = &p_Cur->bitctx; + H264_SPS_t *cur_sps = &p_Cur->sps; + + FunctionIn(logctx->parr[RUN_PARSE]); + reset_cur_sps_data(cur_sps); // reset + set_bitread_logctx(p_bitctx, logctx->parr[LOG_READ_SPS]); + //!< parse sps + FUN_CHECK(ret = parser_sps(p_bitctx, cur_sps)); + //!< decide "max_dec_frame_buffering" for DPB + FUN_CHECK(ret = get_max_dec_frame_buf_size(cur_sps)); + //!< make SPS available, copy + if (cur_sps->Valid) + { + memcpy(&currSlice->p_Vid->spsSet[cur_sps->seq_parameter_set_id], cur_sps, sizeof(H264_SPS_t)); + } + FunctionOut(logctx->parr[RUN_PARSE]); + + return ret = MPP_OK; +__FAILED: + ASSERT(0); + return ret; +} + + +/*! +*********************************************************************** +* \brief +* prase sps and process sps +*********************************************************************** +*/ +//extern "C" +void recycle_subsps(H264_subSPS_t *subset_sps) +{ + RK_S32 i = 0, num_views = 0; + + num_views = 1 + subset_sps->num_views_minus1; + for (i = 1; inum_anchor_refs_l0[i] > 0) + { + mpp_free(subset_sps->anchor_ref_l0[i]); + } + if (subset_sps->num_anchor_refs_l1[i] > 0) + { + mpp_free(subset_sps->anchor_ref_l1[i]); + } + if (subset_sps->num_non_anchor_refs_l0[i] > 0) + { + mpp_free(subset_sps->non_anchor_ref_l0[i]); + } + if (subset_sps->num_non_anchor_refs_l1[i] > 0) + { + mpp_free(subset_sps->non_anchor_ref_l1[i]); + } + } + if (num_views > 0) + { + mpp_free(subset_sps->view_id); + mpp_free(subset_sps->num_anchor_refs_l0); + mpp_free(subset_sps->num_anchor_refs_l1); + mpp_free(subset_sps->anchor_ref_l0); + mpp_free(subset_sps->anchor_ref_l1); + mpp_free(subset_sps->num_non_anchor_refs_l0); + mpp_free(subset_sps->num_non_anchor_refs_l1); + mpp_free(subset_sps->non_anchor_ref_l0); + mpp_free(subset_sps->non_anchor_ref_l1); + } + subset_sps->Valid = 0; +} + +/*! +*********************************************************************** +* \brief +* prase sps and process sps +*********************************************************************** +*/ +//extern "C" +MPP_RET process_subsps(H264_SLICE_t *currSlice) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dLogCtx_t *logctx = currSlice->logctx; + BitReadCtx_t *p_bitctx = &currSlice->p_Cur->bitctx; + H264_subSPS_t *cur_subsps = &currSlice->p_Cur->subsps; + H264_subSPS_t *p_subset = NULL; + + FunctionIn(logctx->parr[RUN_PARSE]); + reset_cur_subpps_data(cur_subsps); //reset + set_bitread_logctx(p_bitctx, logctx->parr[LOG_READ_SUBSPS]); + WRITE_LOG(p_bitctx, "----------------------------- subSPS begin --------------------------------"); + FUN_CHECK(ret = parser_sps(p_bitctx, &cur_subsps->sps)); + FUN_CHECK(ret = parser_subsps_ext(p_bitctx, cur_subsps)); + if (cur_subsps->sps.Valid) + { + cur_subsps->Valid = 1; + currSlice->p_Vid->profile_idc = cur_subsps->sps.profile_idc; + } + get_max_dec_frame_buf_size(&cur_subsps->sps); + //!< make subSPS available + p_subset = &currSlice->p_Vid->subspsSet[cur_subsps->sps.seq_parameter_set_id]; + if (p_subset->Valid) + { + recycle_subsps(p_subset); + } + memcpy(p_subset, cur_subsps, sizeof(H264_subSPS_t)); + FunctionOut(logctx->parr[RUN_PARSE]); + + return ret = MPP_OK; +__FAILED: + recycle_subsps(&currSlice->p_Cur->subsps); + //ASSERT(0); + + return ret; +} + +/*! +*********************************************************************** +* \brief +* prase sps and process sps +*********************************************************************** +*/ +//extern "C" +MPP_RET activate_sps(H264dVideoCtx_t *p_Vid, H264_SPS_t *sps, H264_subSPS_t *subset_sps) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + if (p_Vid->dec_picture) + { + FUN_CHECK(ret = exit_picture(p_Vid, &p_Vid->dec_picture)); + } + if (p_Vid->active_mvc_sps_flag) // layer_id == 1 + { + p_Vid->active_sps = &subset_sps->sps; + p_Vid->active_subsps = subset_sps; + p_Vid->active_sps_id[0] = 0; + p_Vid->active_sps_id[1] = subset_sps->sps.seq_parameter_set_id; + if (video_pars_changed(p_Vid, p_Vid->active_sps, 1)) + { + FUN_CHECK(ret = flush_dpb(p_Vid->p_Dpb_layer[1])); + FUN_CHECK(ret = init_dpb(p_Vid, p_Vid->p_Dpb_layer[1], 2)); + update_last_video_pars(p_Vid, p_Vid->active_sps, 1); + } + } + else //!< layer_id == 0 + { + p_Vid->active_sps = sps; + p_Vid->active_subsps = NULL; + p_Vid->active_sps_id[0] = sps->seq_parameter_set_id; + p_Vid->active_sps_id[1] = 0; + if (video_pars_changed(p_Vid, p_Vid->active_sps, 0)) + { + if (!p_Vid->no_output_of_prior_pics_flag) + { + FUN_CHECK(ret = flush_dpb(p_Vid->p_Dpb_layer[0])); + } + FUN_CHECK(ret = init_dpb(p_Vid, p_Vid->p_Dpb_layer[0], 1)); + update_last_video_pars(p_Vid, p_Vid->active_sps, 0); + } + } + update_video_pars(p_Vid, p_Vid->active_sps); + + return ret = MPP_OK; +__FAILED: + return ret; +} diff --git a/mpp/codec/dec/h264/h264d_sps.h b/mpp/codec/dec/h264/h264d_sps.h new file mode 100644 index 00000000..a72d51ec --- /dev/null +++ b/mpp/codec/dec/h264/h264d_sps.h @@ -0,0 +1,41 @@ +/* +* +* 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. +*/ + +#ifndef _H264D_SPS_H_ +#define _H264D_SPS_H_ + +#include "rk_type.h" +#include "mpp_err.h" +#include "h264d_global.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + MPP_RET process_sps (H264_SLICE_t *currSlice); + void recycle_subsps(H264_subSPS_t *subset_sps); + MPP_RET process_subsps(H264_SLICE_t *currSlice); + MPP_RET activate_sps(H264dVideoCtx_t *p_Vid, H264_SPS_t *sps, H264_subSPS_t *subset_sps); + +#ifdef __cplusplus +} +#endif + +//======================================== +#endif /* end of _H264D_SPS_H_ */ + diff --git a/mpp/common/h264d_log.h b/mpp/common/h264d_log.h index 50a3ae33..d9d921f7 100644 --- a/mpp/common/h264d_log.h +++ b/mpp/common/h264d_log.h @@ -18,6 +18,8 @@ #define __H264D_LOG_H__ #include +#include + #include "rk_type.h" #include "mpp_err.h" @@ -34,6 +36,8 @@ typedef enum { RET_TURE = 1, } RET_tpye; +//!< get bit value +#define GetBitVal(val, pos) ( ( (val)>>(pos) ) & 0x1 & (val) ) //!< marco #define ASSERT assert #define FCLOSE(fp) do{ if(fp) fclose(fp); fp = NULL; } while (0) @@ -110,53 +114,111 @@ typedef struct log_env_ctx_t { FILE *fp_run_hal; } LogEnv_t; + typedef struct h264d_logctx_t { - LogEnv_t env; - LogFlag_t log_flag; - LogCtx_t *parr[LOG_MAX]; + LogEnv_t env; + LogFlag_t log_flag; + LogCtx_t *parr[LOG_MAX]; } H264dLogCtx_t; - //!< write log -#define LogEnable(ctx, loglevel) ( ctx && ctx->flag->debug_en && (ctx->flag->level & loglevel) ) +#define LogEnable(ctx, loglevel) ( ctx && ctx->flag->debug_en && (ctx->flag->level & loglevel) ) -#define LogTrace(ctx, ...) do{ if(LogEnable(ctx, LOG_LEVEL_TRACE))\ - writelog(ctx, __FILE__, __LINE__, "TRACE", __VA_ARGS__); }while (0) -#define LogInfo(ctx, ...) do{ if(LogEnable(ctx, LOG_LEVEL_INFO))\ - writelog(ctx, __FILE__, __LINE__, "INFO", __VA_ARGS__); }while (0) -#define LogWarnning(ctx, ...) do{ if(LogEnable(ctx, LOG_LEVEL_WARNNING))\ - writelog(ctx, __FILE__, __LINE__, "WARNNING", __VA_ARGS__); }while (0) -#define LogError(ctx, ...) do{ if(LogEnable(ctx, LOG_LEVEL_ERROR))\ - writelog(ctx, __FILE__, __LINE__, "ERROR", __VA_ARGS__); ASSERT(0); }while (0) -#define LogFatal(ctx, ...) do{ if(LogEnable(ctx, LOG_LEVEL_ERROR))\ - writelog(ctx, __FILE__, __LINE__, "FATAL", __VA_ARGS__); ASSERT(0); }while (0) -#define FunctionIn(ctx) do{ if(LogEnable(ctx, LOG_LEVEL_TRACE))\ - writelog(ctx, __FILE__, __LINE__, "FunIn", __FUNCTION__); } while (0) -#define FunctionOut(ctx) do{if(LogEnable(ctx, LOG_LEVEL_TRACE))\ - writelog(ctx, __FILE__, __LINE__, "FunOut", __FUNCTION__); } while (0) +#define LogTrace(ctx, ...)\ + do{ if(LogEnable(ctx, LOG_LEVEL_TRACE)) {\ + writelog(ctx, __FILE__, __LINE__, "TRACE", __VA_ARGS__);\ + } }while (0) +#define LogInfo(ctx, ...)\ + do{ if(LogEnable(ctx, LOG_LEVEL_INFO)) {\ + writelog(ctx, __FILE__, __LINE__, "INFO", __VA_ARGS__);\ + } }while (0) + +#define LogWarnning(ctx, ...)\ + do{ if(LogEnable(ctx, LOG_LEVEL_WARNNING)) {\ + writelog(ctx, __FILE__, __LINE__, "WARNNING", __VA_ARGS__);\ + } }while (0) + +#define LogError(ctx, ...)\ + do{ if(LogEnable(ctx, LOG_LEVEL_ERROR)) {\ + writelog(ctx, __FILE__, __LINE__, "ERROR", __VA_ARGS__);\ + ASSERT(0);\ + } }while (0) +#define LogFatal(ctx, ...)\ + do{ if(LogEnable(ctx, LOG_LEVEL_ERROR)) {\ + writelog(ctx, __FILE__, __LINE__, "FATAL", __VA_ARGS__);\ + ASSERT(0);\ + } }while (0) + +#define FunctionIn(ctx)\ + do{ if(LogEnable(ctx, LOG_LEVEL_TRACE)) {\ + writelog(ctx, __FILE__, __LINE__, "FunIn", __FUNCTION__);\ + } } while (0) + +#define FunctionOut(ctx)\ + do{if(LogEnable(ctx, LOG_LEVEL_TRACE)) {\ + writelog(ctx, __FILE__, __LINE__, "FunOut", __FUNCTION__);\ + } } while (0) -#define __RETURN __Ret +#define __RETURN __Return #define __FAILED __failed -#define VAL_CHECK(val) do{ if(!(val)) goto __FAILED; } while (0) //!< vaule check -#define FUN_CHECK(val) do{ if((val)) goto __FAILED; } while (0) //!< function return check -#define MEM_CHECK(val) do{ if(!(val)) goto __FAILED; } while (0) //!< memory check -#define FLE_CHECK(val) do{ if(!(val)) goto __FAILED; } while (0) //!< file check -#define INP_CHECK(val) do{ if((val)) goto __RETURN; } while (0) //!< input check +#define VAL_CHECK(ret, val)\ + do{ if(!(val)){\ + ret = MPP_ERR_VALUE;\ + fprintf(stderr, "ERROR: value error.\n");\ + goto __FAILED;\ + } } while (0) //!< vaule check + +//!< memory malloc check +#define MEM_CHECK(ret, val)\ + do{ if(!(val)) {\ + ret = MPP_ERR_MALLOC;\ + fprintf(stderr, "ERROR: malloc buffer.\n");\ + ASSERT(0); goto __FAILED;\ + } } while (0) +//!< file check +#define FLE_CHECK(ret, val)\ + do{ if(!(val)) {\ + ret = MPP_ERR_OPEN_FILE;\ + fprintf(stderr, "ERROR: open file.\n");\ + ASSERT(0); goto __FAILED;\ + } } while (0) + +//!< input check +#define INP_CHECK(ret, ctx, val)\ + do{ if((val)) {\ + ret = MPP_ERR_INIT;\ + fprintf(stderr, "ERROR: input empty.\n");\ + goto __RETURN;\ + } } while (0) + //!< function return check +#define FUN_CHECK(val)\ + do{ if((val) < 0) {\ + goto __FAILED;\ + } } while (0) + +#define FPRINT(fp, ...) { if (fp) { fprintf(fp, ## __VA_ARGS__); fflush(fp);} } + +extern RK_U32 g_nalu_cnt; + + #ifdef __cplusplus extern "C" { #endif extern const LogEnvStr_t logenv_name; +extern const char *logctrl_name[LOG_MAX]; +extern const char *loglevel_name[LOG_LEVEL_MAX]; -MPP_RET h264d_log_init (H264dLogCtx_t *logctx, LogCtx_t *logbuf); -MPP_RET h264d_log_deinit(H264dLogCtx_t *logctx); +MPP_RET get_logenv(LogEnv_t *env); +void print_env_help(LogEnv_t *env); +void show_env_flags(LogEnv_t *env); +MPP_RET explain_ctrl_flag(RK_U32 ctrl_val, LogFlag_t *pflag); void writelog(LogCtx_t *ctx, char *fname, RK_U32 line, char *loglevel, const char *msg, ...); - #ifdef __cplusplus } #endif diff --git a/mpp/common/h264d_syntax.h b/mpp/common/h264d_syntax.h index 1b21fe71..ebc49819 100644 --- a/mpp/common/h264d_syntax.h +++ b/mpp/common/h264d_syntax.h @@ -413,7 +413,7 @@ typedef struct _DXVA_PicParams_H264_MVC { typedef struct h264d_syntax_t { RK_U32 num; DXVA2_DecodeBufferDesc *buf; -} H264D_Syntax_t; +} H264dSyntax_t; #endif /*__H264D_SYNTAX_H__*/ diff --git a/mpp/hal/inc/hal_h264d_api.h b/mpp/hal/inc/hal_h264d_api.h index ccd497b1..6cde13b6 100644 --- a/mpp/hal/inc/hal_h264d_api.h +++ b/mpp/hal/inc/hal_h264d_api.h @@ -19,312 +19,11 @@ #ifndef __HAL_H264D_API_H__ #define __HAL_H264D_API_H__ +#include "rk_type.h" +#include "mpp_err.h" #include "mpp_hal.h" -typedef struct h264_mmu_t { - RK_U32 mmu_dte_addr; - struct { - RK_U32 pageing_enabled : 1; - RK_U32 page_fault_active : 1; - RK_U32 stail_active : 1; - RK_U32 mmu_idle : 1; - RK_U32 replay_buffer_empty1 : 1; - RK_U32 page_fault_is_write : 1; - RK_U32 page_fault_bus_id : 5; - RK_U32 reserve : 8; - //RK_U32 field0000 : 1; - } mmu_status; - struct { - RK_U32 mmu_cmd : 3; - RK_U32 field0000 : 1; - } mmu_cmd; - RK_U32 page_fault_addr; - RK_U32 mmu_zap_one_line; - struct int_rawstat { - RK_U32 page_fault : 1; - RK_U32 read_bus_error : 1; - } raw_stat; - struct int_clear { - RK_U32 page_fault : 1; - RK_U32 read_bus_error : 1; - } clear; - struct int_mask { - RK_U32 page_fault : 1; - RK_U32 read_bus_error : 1; - } mask; - struct int_status { - RK_U32 page_fault : 1; - RK_U32 read_bus_error : 1; - } status; - RK_U32 mmu_auto_gating : 1; -} H264_MMU_t; - -typedef struct h264_cache_t { - struct st_version { - RK_U32 version_minor : 8; - RK_U32 version_major : 8; - RK_U32 product_id : 16; - } version; - struct st_size { - RK_U32 line_size : 8; - RK_U32 associativity : 8; - RK_U32 cache_size : 8; - RK_U32 external_bus_width : 8; - } size; - struct st_status { - RK_U32 cmd_busy : 1; - RK_U32 data_busy : 1; - } status; - struct st_command { - RK_U32 command : 4; - RK_U32 sw_addrb_sel : 2; - } command; - RK_U32 clear_page; - RK_U32 max_reads : 5; - struct st_enable { - RK_U32 permit_cacheable_access : 1; - RK_U32 permit_cach_read_allocate : 1; - RK_U32 sw_readbuffer_counter_reject_en : 1; - RK_U32 sw_cache_clk_disgate : 1; - RK_U32 sw_cache_linsize : 1; - } enable; - RK_U32 perfcnt_src0; - RK_U32 perfcnt_val0; - RK_U32 perfcnt_src1; - RK_U32 perfcnt_val1; -} H264_CACHE_t; - -typedef struct h264_regs_t { - struct { - RK_U32 minor_ver : 8; - RK_U32 level : 1; - RK_U32 dec_support : 3; - RK_U32 profile : 1; - RK_U32 reserve0 : 1; - RK_U32 codec_flag : 1; - RK_U32 reserve1 : 1; - RK_U32 prod_num : 16; - } swreg0_id; - struct { - RK_U32 sw_dec_e : 1;//0 - RK_U32 sw_dec_clkgate_e : 1; // 1 - RK_U32 reserve0 : 1;// 2 - RK_U32 sw_timeout_mode : 1; // 3 - RK_U32 sw_dec_irq_dis : 1;//4 // 4 - RK_U32 sw_dec_timeout_e : 1; //5 - RK_U32 sw_buf_empty_en : 1; // 6 - RK_U32 sw_stmerror_waitdecfifo_empty : 1; // 7 - RK_U32 sw_dec_irq : 1; // 8 - RK_U32 sw_dec_irq_raw : 1; // 9 - RK_U32 reserve2 : 2; - RK_U32 sw_dec_rdy_sta : 1; //12 - RK_U32 sw_dec_bus_sta : 1; //13 - RK_U32 sw_dec_error_sta : 1; // 14 - RK_U32 sw_dec_timeout_sta : 1; //15 - RK_U32 sw_dec_empty_sta : 1; // 16 - RK_U32 sw_colmv_ref_error_sta : 1; // 17 - RK_U32 sw_cabu_end_sta : 1; // 18 - RK_U32 sw_h264orvp9_error_mode : 1; //19 - RK_U32 sw_softrst_en_p : 1; //20 - RK_U32 sw_force_softreset_valid : 1; //21 - RK_U32 sw_softreset_rdy : 1; // 22 - } swreg1_int; - struct { - RK_U32 sw_in_endian : 1; - RK_U32 sw_in_swap32_e : 1; - RK_U32 sw_in_swap64_e : 1; - RK_U32 sw_str_endian : 1; - RK_U32 sw_str_swap32_e : 1; - RK_U32 sw_str_swap64_e : 1; - RK_U32 sw_out_endian : 1; - RK_U32 sw_out_swap32_e : 1; - RK_U32 sw_out_cbcr_swap : 1; - RK_U32 reserve0 : 1; - RK_U32 sw_rlc_mode_direct_write : 1; - RK_U32 sw_rlc_mode : 1; - RK_U32 sw_strm_start_bit : 7; - RK_U32 reserve1 : 1; - RK_U32 sw_dec_mode : 2; - RK_U32 reserve2 : 2; - RK_U32 sw_h264_rps_mode : 1; - RK_U32 sw_h264_stream_mode : 1; - RK_U32 sw_h264_stream_lastpacket : 1; - RK_U32 sw_h264_firstslice_flag : 1; - RK_U32 sw_h264_frame_orslice : 1; - RK_U32 sw_buspr_slot_disable : 1; - } swreg2_sysctrl; - struct { - RK_U32 sw_y_hor_virstride : 9; - RK_U32 reserve : 2; - RK_U32 sw_slice_num_highbit : 1; - RK_U32 sw_uv_hor_virstride : 9; - RK_U32 sw_slice_num_lowbits : 11; - } swreg3_picpar; - struct { - RK_U32 reverse0 : 4; - RK_U32 sw_strm_rlc_base : 28; - } swreg4_strm_rlc_base; - struct { - RK_U32 sw_stream_len : 27; - } swreg5_stream_rlc_len; - struct { - RK_U32 reverse0 : 4; - RK_U32 sw_cabactbl_base : 28; - } swreg6_cabactbl_prob_base; - struct { - RK_U32 reverse0 : 4; - RK_U32 sw_decout_base : 28; - } swreg7_decout_base; - struct { - RK_U32 sw_y_virstride : 20; - } swreg8_y_virstride; - struct { - RK_U32 sw_yuv_virstride : 21; - } swreg9_yuv_virstride; - struct { - RK_U32 sw_ref_field : 1; - RK_U32 sw_ref_topfield_used : 1; - RK_U32 sw_ref_botfield_used : 1; - RK_U32 sw_ref_colmv_use_flag : 1; - RK_U32 sw_refer_base : 28; - } swreg10_24_refer0_14_base[15]; - RK_U32 swreg25_39_refer0_14_poc[15]; - struct { - RK_U32 sw_cur_poc : 32; - } swreg40_cur_poc; - struct { - RK_U32 reserve : 3; - RK_U32 sw_rlcwrite_base : 29; - } swreg41_rlcwrite_base; - struct { - RK_U32 reserve : 4; - RK_U32 sw_pps_base : 28; - } swreg42_pps_base; - struct swreg_sw_rps_base { - RK_U32 reserve : 4; - RK_U32 sw_rps_base : 28; - } swreg43_rps_base; - struct swreg_strmd_error_e { - RK_U32 sw_strmd_error_e : 28; - RK_U32 reserve : 4; - } swreg44_strmd_error_en; - struct { - RK_U32 sw_strmd_error_status : 28; - RK_U32 sw_colmv_error_ref_picidx : 4; - } swreg45_strmd_error_status; - struct { - RK_U32 sw_strmd_error_ctu_xoffset : 8; - RK_U32 sw_strmd_error_ctu_yoffset : 8; - RK_U32 sw_streamfifo_space2full : 7; - RK_U32 reserve : 1; - RK_U32 sw_vp9_error_ctu0_en : 1; - } swreg46_strmd_error_ctu; - struct { - RK_U32 sw_saowr_xoffet : 9; - RK_U32 reserve : 7; - RK_U32 sw_saowr_yoffset : 10; - } swreg47_sao_ctu_position; - struct { - RK_U32 sw_ref_field : 1; - RK_U32 sw_ref_topfield_used : 1; - RK_U32 sw_ref_botfield_used : 1; - RK_U32 sw_ref_colmv_use_flag : 1; - RK_U32 sw_refer_base : 28; - } swreg48_refer15_base; - RK_U32 swreg49_63_refer15_29_poc[15]; - struct { - RK_U32 sw_performance_cycle : 32; - } swreg64_performance_cycle; - struct { - RK_U32 sw_axi_ddr_rdata : 32; - } swreg65_axi_ddr_rdata; - struct { - RK_U32 sw_axi_ddr_rdata : 32; - } swreg66_axi_ddr_wdata; - struct { - RK_U32 sw_busifd_resetn : 1; - RK_U32 sw_cabac_resetn : 1; - RK_U32 sw_dec_ctrl_resetn : 1; - RK_U32 sw_transd_resetn : 1; - RK_U32 sw_intra_resetn : 1; - RK_U32 sw_inter_resetn : 1; - RK_U32 sw_recon_resetn : 1; - RK_U32 sw_filer_resetn : 1; - } swreg67_fpgadebug_reset; - struct { - RK_U32 perf_cnt0_sel : 6; - RK_U32 reserve0 : 2; - RK_U32 perf_cnt1_sel : 6; - RK_U32 reserve1 : 2; - RK_U32 perf_cnt2_sel : 6; - } swreg68_performance_sel; - struct { - RK_U32 perf_cnt0 : 32; - } swreg69_performance_cnt0; - struct { - RK_U32 perf_cnt1 : 32; - } swreg70_performance_cnt1; - struct { - RK_U32 perf_cnt2 : 32; - } swreg71_performance_cnt2; - RK_U32 swreg72_refer30_poc; - RK_U32 swreg73_refer31_poc; - struct { - RK_U32 sw_h264_cur_poc1 : 32; - } swreg74_h264_cur_poc1; - struct { - RK_U32 reserve : 4; - RK_U32 sw_errorinfo_base : 28; - } swreg75_h264_errorinfo_base; - struct { - RK_U32 sw_slicedec_num : 14; - RK_U32 reserve : 1; - RK_U32 sw_strmd_detect_error_flag : 1; - RK_U32 sw_error_packet_num : 14; - } swreg76_h264_errorinfo_num; - struct { - RK_U32 sw_h264_error_en_highbits : 30; - RK_U32 reserve : 2; - } swreg77_h264_error_e; - RK_U32 compare_len; -} H264_REGS_t; - - - -//typedef struct hal_h264d_logctx_t -//{ -// struct rkv_log_flag_t *log_flag; -// struct rkv_log_ctx_t *spspps; -// struct rkv_log_ctx_t *rps; -// struct rkv_log_ctx_t *scanlist; -// struct rkv_log_ctx_t *sodb; -// struct rkv_log_ctx_t *reg; -// struct rkv_log_ctx_t *driver; // fwrite -// struct rkv_log_ctx_t *runlog; // fprintf -// -//}HAL_H264dLogCtx_t; - - -//typedef struct hal_h264d_initctx_t -//{ -// HAL_H264dLogCtx_t *logctx; -//}HAL_H264dInitCtx_t; -// -// -//typedef struct hal_h264d_inctx_t -//{ -// struct h264d_syntax_t *syn; -// -//}HAL_H264dInCtx_t; -// -//typedef struct hal_h264d_outctx_t -//{ -// H264_REGS_t *reg; -// H264_MMU_t *mmu; -// H264_CACHE_t *cache; -// -//}HAL_H264dOutCtx_t; #ifdef __cplusplus extern "C" { diff --git a/mpp/hal/rkdec/h264d/CMakeLists.txt b/mpp/hal/rkdec/h264d/CMakeLists.txt index 140d8b0a..0fc8662c 100644 --- a/mpp/hal/rkdec/h264d/CMakeLists.txt +++ b/mpp/hal/rkdec/h264d/CMakeLists.txt @@ -9,13 +9,19 @@ set(HAL_H264D_API # hal h264 header set(HAL_H264D_HDR - + hal_h264d_global.h + hal_h264d_reg.h + hal_h264d_fifo.h + hal_h264d_packet.h ) # hal h264 decoder sourse set(HAL_H264D_SRC hal_h264d_api.c - + hal_h264d_reg.c + hal_h264d_fifo.c + hal_h264d_packet.c + ) add_library(hal_h264d STATIC diff --git a/mpp/hal/rkdec/h264d/hal_h264d_api.c b/mpp/hal/rkdec/h264d/hal_h264d_api.c index 64cda5fc..eba0021a 100644 --- a/mpp/hal/rkdec/h264d/hal_h264d_api.c +++ b/mpp/hal/rkdec/h264d/hal_h264d_api.c @@ -14,77 +14,345 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#define MODULE_TAG "hal_h264d" + +#include +#include +#include + +#include "rk_type.h" +#include "mpp_err.h" +#include "mpp_mem.h" + +#include "dxva_syntax.h" +#include "h264d_syntax.h" #include "h264d_log.h" + +#include "hal_h264d_global.h" +#include "hal_h264d_reg.h" +#include "hal_h264d_packet.h" #include "hal_h264d_api.h" + +#define MODULE_TAG "hal_h264d_api" + + + +static void close_log_files(LogEnv_t *env) +{ + FCLOSE(env->fp_driver); + FCLOSE(env->fp_syn_hal); + FCLOSE(env->fp_run_hal); +} + +static MPP_RET open_log_files(LogEnv_t *env, LogFlag_t *pflag) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + char fname[128] = { 0 }; + + INP_CHECK(ret, ctx, !pflag->write_en); + //!< runlog file + if (GetBitVal(env->ctrl, LOG_DEBUG_EN)) { + sprintf(fname, "%s/h264d_hal_runlog.dat", env->outpath); + FLE_CHECK(ret, env->fp_run_hal = fopen(fname, "wb")); + } + //!< fpga drive file + if (GetBitVal(env->ctrl, LOG_FPGA)) { + sprintf(fname, "%s/h264d_driver_data.dat", env->outpath); + FLE_CHECK(ret, env->fp_driver = fopen(fname, "wb")); + } + //!< write syntax + if ( GetBitVal(env->ctrl, LOG_WRITE_SPSPPS ) + || GetBitVal(env->ctrl, LOG_WRITE_RPS ) + || GetBitVal(env->ctrl, LOG_WRITE_SCANLIST) + || GetBitVal(env->ctrl, LOG_WRITE_STEAM ) + || GetBitVal(env->ctrl, LOG_WRITE_REG ) ) { + sprintf(fname, "%s/h264d_write_syntax.dat", env->outpath); + FLE_CHECK(ret, env->fp_syn_hal = fopen(fname, "wb")); + } + +__RETURN: + return MPP_OK; + +__FAILED: + return ret; +} + +static MPP_RET logctx_deinit(H264dLogCtx_t *logctx) +{ + close_log_files(&logctx->env); + + return MPP_OK; +} + +static MPP_RET logctx_init(H264dLogCtx_t *logctx, LogCtx_t *logbuf) +{ + RK_U8 i = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + LogCtx_t *pcur = NULL; + + FUN_CHECK(ret = get_logenv(&logctx->env)); + + FUN_CHECK(ret = explain_ctrl_flag(logctx->env.ctrl, &logctx->log_flag)); + if ( !logctx->log_flag.debug_en + && !logctx->log_flag.print_en && !logctx->log_flag.write_en ) { + logctx->log_flag.debug_en = 0; + goto __RETURN; + } + logctx->log_flag.level = (1 << logctx->env.level) - 1; + //!< open file + FUN_CHECK(ret = open_log_files(&logctx->env, &logctx->log_flag)); + //!< set logctx + while (i < LOG_MAX) { + if (GetBitVal(logctx->env.ctrl, i)) { + pcur = logctx->parr[i] = &logbuf[i]; + pcur->tag = logctrl_name[i]; + pcur->flag = &logctx->log_flag; + + switch (i) { + case LOG_FPGA: + pcur->fp = logctx->env.fp_driver; + break; + case RUN_HAL: + pcur->fp = logctx->env.fp_run_hal; + break; + case LOG_WRITE_SPSPPS: + case LOG_WRITE_RPS: + case LOG_WRITE_SCANLIST: + case LOG_WRITE_STEAM: + case LOG_WRITE_REG: + pcur->fp = logctx->env.fp_syn_hal; + default: + break; + } + } + i++; + } +__RETURN: + return ret = MPP_OK; +__FAILED: + logctx->log_flag.debug_en = 0; + logctx_deinit(logctx); + + return ret; +} + + +/*! +*********************************************************************** +* \brief +* init +*********************************************************************** +*/ +//extern "C" MPP_RET hal_h264d_init(void *hal, MppHalCfg *cfg) { - printf("begin=%s \n", logenv_name.begframe); + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + INP_CHECK(ret, ctx, NULL == p_hal); + memset(p_hal, 0, sizeof(H264dHalCtx_t)); + //!< init logctx + FUN_CHECK(ret = logctx_init(&p_hal->logctx, p_hal->logctxbuf)); + FunctionIn(p_hal->logctx.parr[RUN_HAL]); + p_hal->mem = mpp_calloc(H264dHalMem_t, 1); + MEM_CHECK(ret, p_hal->mem); + p_hal->regs = &p_hal->mem->regs; + p_hal->mmu_regs = &p_hal->mem->mmu_regs; + p_hal->cache_regs = &p_hal->mem->cache_regs; + p_hal->pkts = &p_hal->mem->pkts; + FUN_CHECK(ret = alloc_fifo_packet(&p_hal->logctx, p_hal->pkts)); - (void)hal; + FunctionOut(p_hal->logctx.parr[RUN_HAL]); (void)cfg; - +__RETURN: return MPP_OK; -} +__FAILED: + hal_h264d_deinit(hal); + return ret; +} +/*! +*********************************************************************** +* \brief +* deinit +*********************************************************************** +*/ +//extern "C" MPP_RET hal_h264d_deinit(void *hal) { - (void)hal; - return MPP_OK; -} + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + INP_CHECK(ret, ctx, NULL == p_hal); + FunctionIn(p_hal->logctx.parr[RUN_HAL]); + + free_fifo_packet(p_hal->pkts); + mpp_free(p_hal->mem); + + FunctionOut(p_hal->logctx.parr[RUN_HAL]); + logctx_deinit(&p_hal->logctx); +__RETURN: + return ret = MPP_OK; +} +/*! +*********************************************************************** +* \brief +* generate register +*********************************************************************** +*/ +//extern "C" MPP_RET hal_h264d_gen_regs(void *hal, HalTask *task) { - (void)hal; + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; - ((HalDecTask*)&task->dec)->valid = 0; + INP_CHECK(ret, ctx, NULL == p_hal); + FunctionIn(p_hal->logctx.parr[RUN_HAL]); + explain_input_buffer(hal, &task->dec); + prepare_spspps_packet(hal, &p_hal->pkts->spspps); + prepare_framerps_packet(hal, &p_hal->pkts->rps); + prepare_scanlist_packet(hal, &p_hal->pkts->scanlist); + prepare_stream_packet(hal, &p_hal->pkts->strm); + generate_regs(p_hal, &p_hal->pkts->reg); + + printf("++++++++++ hal_h264_decoder, g_framecnt=%d \n", p_hal->g_framecnt++); + ((HalDecTask*)&task->dec)->valid = 0; + FunctionOut(p_hal->logctx.parr[RUN_HAL]); - return MPP_OK; +__RETURN: + return ret = MPP_OK; } +/*! +*********************************************************************** +* \brief h +* start hard +*********************************************************************** +*/ +//extern "C" + MPP_RET hal_h264d_start(void *hal, HalTask *task) { - (void)hal; - (void)task; - return MPP_OK; -} + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + INP_CHECK(ret, ctx, NULL == p_hal); + FunctionIn(p_hal->logctx.parr[RUN_HAL]); + + + + + + FunctionOut(p_hal->logctx.parr[RUN_HAL]); + (void)task; +__RETURN: + return ret = MPP_OK; +} +/*! +*********************************************************************** +* \brief +* wait hard +*********************************************************************** +*/ +//extern "C" MPP_RET hal_h264d_wait(void *hal, HalTask *task) { - (void)hal; - (void)task; - return MPP_OK; -} + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + INP_CHECK(ret, ctx, NULL == p_hal); + FunctionIn(p_hal->logctx.parr[RUN_HAL]); + + + + + + FunctionOut(p_hal->logctx.parr[RUN_HAL]); + (void)task; +__RETURN: + return ret = MPP_OK; +} +/*! +*********************************************************************** +* \brief +* reset +*********************************************************************** +*/ +//extern "C" MPP_RET hal_h264d_reset(void *hal) { - (void)hal; - return MPP_OK; -} + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + INP_CHECK(ret, ctx, NULL == p_hal); + FunctionIn(p_hal->logctx.parr[RUN_HAL]); + + memset(&p_hal->regs, 0, sizeof(H264_REGS_t)); + memset(&p_hal->mmu_regs, 0, sizeof(H264_MMU_t)); + memset(&p_hal->cache_regs, 0, sizeof(H264_CACHE_t)); + reset_fifo_packet(p_hal->pkts); + + FunctionOut(p_hal->logctx.parr[RUN_HAL]); +__RETURN: + return ret = MPP_OK; +} +/*! +*********************************************************************** +* \brief +* flush +*********************************************************************** +*/ +//extern "C" MPP_RET hal_h264d_flush(void *hal) { - (void)hal; - return MPP_OK; -} + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + INP_CHECK(ret, ctx, NULL == p_hal); + FunctionIn(p_hal->logctx.parr[RUN_HAL]); + + + + + + FunctionOut(p_hal->logctx.parr[RUN_HAL]); +__RETURN: + return ret = MPP_OK; +} +/*! +*********************************************************************** +* \brief +* control +*********************************************************************** +*/ +//extern "C" MPP_RET hal_h264d_control(void *hal, RK_S32 cmd_type, void *param) { - (void)hal; - (void)cmd_type; - (void)param; - return MPP_OK; + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + + INP_CHECK(ret, ctx, NULL == p_hal); + FunctionIn(p_hal->logctx.parr[RUN_HAL]); + + + + + + FunctionOut(p_hal->logctx.parr[RUN_HAL]); + (void)hal; + (void)cmd_type; + (void)param; +__RETURN: + return ret = MPP_OK; } const MppHalApi hal_api_h264d = { "h264d_rkdec", MPP_CTX_DEC, MPP_VIDEO_CodingAVC, - 0, + sizeof(H264dHalCtx_t), 0, hal_h264d_init, hal_h264d_deinit, diff --git a/mpp/hal/rkdec/h264d/hal_h264d_fifo.c b/mpp/hal/rkdec/h264d/hal_h264d_fifo.c new file mode 100644 index 00000000..14681306 --- /dev/null +++ b/mpp/hal/rkdec/h264d/hal_h264d_fifo.c @@ -0,0 +1,205 @@ + +/* + * Copyright 2010 Rockchip Electronics S.LSI 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. + */ + +#include +#include + +#include "mpp_mem.h" + +#include "h264d_log.h" +#include "hal_h264d_fifo.h" + +#define MODULE_TAG "hal_h264d_fifo" + +/*! +*********************************************************************** +* \brief +* write fifo data to file +*********************************************************************** +*/ +//extern "C" +void fifo_fwrite(FILE *fp, void *psrc, RK_U32 size) +{ + fwrite(psrc, 1, size, fp); + fflush(fp); +} + +/*! +*********************************************************************** +* \brief +* flush left bytes to fifo +*********************************************************************** +*/ +//extern "C" +void fifo_flush_bits(FifoCtx_t *pkt) +{ + if (pkt->bitpos) + { + fifo_write_bits(pkt, 0, (64 - pkt->bitpos), "flush"); + pkt->index++; + pkt->bitpos = 0; + } +} + +//void fifo_fwrite_header(FifoCtx_t *pkt, RK_S32 pkt_size) +//{ +// if (pkt->fp_data) +// { +// pkt->size = pkt_size; +// fifo_fwrite(pkt->fp_data, &pkt->header, sizeof(RK_U32)); +// fifo_fwrite(pkt->fp_data, &pkt->size, sizeof(RK_U32)); +// } +//} + +/*! +*********************************************************************** +* \brief +* fwrite header and data +*********************************************************************** +*/ +//extern "C" +void fifo_fwrite_data(FifoCtx_t *pkt) +{ + RK_U32 pkt_size = 0; + + if (pkt->fp_data) + { + pkt_size = pkt->index*sizeof(RK_U64); + fifo_fwrite(pkt->fp_data, &pkt->header, sizeof(RK_U32)); + fifo_fwrite(pkt->fp_data, &pkt_size, sizeof(RK_U32)); + fifo_fwrite(pkt->fp_data, pkt->pbuf, pkt->index*sizeof(RK_U64)); + } +} + +/*! +*********************************************************************** +* \brief +* write bits to fifo +*********************************************************************** +*/ +//extern "C" +void fifo_write_bits(FifoCtx_t *pkt, RK_U64 invalue, RK_U8 lbits, const char *name) +{ + RK_U8 hbits = 0; + + if (!lbits) return; + + hbits = 64 - lbits; + invalue = (invalue << hbits) >> hbits; + LogInfo(pkt->logctx, "%48s = %10d (bits=%d)", name, invalue, lbits); + pkt->bvalue |= invalue << pkt->bitpos; // high bits value + if ((pkt->bitpos + lbits) >= 64) + { + pkt->pbuf[pkt->index] = pkt->bvalue; + //printf("pdata[%d]=%16x \n", pkt->index, pkt->bvalue); + pkt->bvalue = invalue >> (64 - pkt->bitpos); // low bits value + pkt->index++; + ASSERT(pkt->index <= pkt->buflen); + } + pkt->pbuf[pkt->index] = pkt->bvalue; + pkt->bitpos = (pkt->bitpos + lbits) & 63; +} +/*! +*********************************************************************** +* \brief +* align fifo bits +*********************************************************************** +*/ +//extern "C" +void fifo_align_bits(FifoCtx_t *pkt, RK_U8 align_bits) +{ + RK_U32 word_offset = 0, bits_offset = 0, bitlen = 0; + + word_offset = (align_bits >= 64) ? ((pkt->index &(((align_bits & 0xfe0) >> 6) - 1)) << 6) : 0; + bits_offset = (align_bits - (word_offset + (pkt->bitpos % align_bits))) % align_bits; + while (bits_offset > 0) + { + bitlen = (bits_offset >= 8) ? 8 : bits_offset; + fifo_write_bits(pkt, 0, bitlen, "align"); + bits_offset -= bitlen; + } +} +/*! +*********************************************************************** +* \brief +* write bytes to fifo +*********************************************************************** +*/ +//extern "C" +void fifo_write_bytes(FifoCtx_t *pkt, void *psrc, RK_U32 size) +{ + RK_U8 hbits = 0; + RK_U32 bitslen = 0; + RK_U8 *pdst = NULL; + + hbits = 64 - pkt->bitpos; + pkt->pbuf[pkt->index] = pkt->bitpos ? ((pkt->bvalue << hbits) >> hbits) : 0; + if (size) + { + pdst = (RK_U8 *)&pkt->pbuf[pkt->index]; + pdst += pkt->bitpos / 8; + + memcpy(pdst, psrc, size); + bitslen = size * 8 + pkt->bitpos; + + pkt->index += bitslen / 64; + pkt->bitpos = bitslen & 63; + + hbits = 64 - pkt->bitpos; + pkt->bvalue = pkt->bitpos ? ((pkt->pbuf[pkt->index] << hbits) >> hbits) : 0; + } +} + +void fifo_packet_reset(FifoCtx_t *pkt) +{ + pkt->index = 0; + pkt->bitpos = 0; + pkt->bvalue = 0; + pkt->size = 0; +} + +/*! +*********************************************************************** +* \brief +* init fifo packet +*********************************************************************** +*/ +//extern "C" +MPP_RET fifo_packet_init(FifoCtx_t *pkt, RK_S32 header, RK_S32 size) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + pkt->header = header; + pkt->index = 0; + pkt->bitpos = 0; + pkt->bvalue = 0; + pkt->size = 0; + pkt->buflen = (size + 7) / 8; // align 64bit + pkt->pbuf = NULL; + if (pkt->buflen) + { + pkt->pbuf = mpp_malloc(RK_U64, pkt->buflen); + MEM_CHECK(ret, pkt->pbuf); + } + + return MPP_OK; + +__FAILED: + return ret; +} + + diff --git a/mpp/hal/rkdec/h264d/hal_h264d_fifo.h b/mpp/hal/rkdec/h264d/hal_h264d_fifo.h new file mode 100644 index 00000000..781d6540 --- /dev/null +++ b/mpp/hal/rkdec/h264d/hal_h264d_fifo.h @@ -0,0 +1,46 @@ +#ifndef __HAL_H264D_FIFO_H__ +#define __HAL_H264D_FIFO_H__ + +#include "rk_type.h" +#include "mpp_err.h" +#include "h264d_log.h" + + +typedef struct +{ + RK_U32 header; + RK_U32 buflen; //!< max buf length, 64bit uint + RK_U32 index; //!< current uint position + RK_U64 *pbuf; //!< outpacket data + RK_U64 bvalue; //!< buffer value, 64 bit + RK_U8 bitpos; //!< bit pos in 64bit + RK_U32 size; //!< data size,except header + LogCtx_t *logctx; //!< for debug + FILE *fp_data; //!< for fpga +}FifoCtx_t; + + +#ifdef __cplusplus +extern "C" { +#endif + + void fifo_packet_reset (FifoCtx_t *pkt); + void fifo_fwrite_header(FifoCtx_t *pkt, RK_S32 pkt_size); + void fifo_fwrite_data (FifoCtx_t *pkt); + void fifo_write_bits (FifoCtx_t *pkt, RK_U64 invalue, RK_U8 lbits, const char *name); + void fifo_flush_bits (FifoCtx_t *pkt); + void fifo_align_bits (FifoCtx_t *pkt, RK_U8 align_bits); + void fifo_write_bytes (FifoCtx_t *pkt, void *psrc, RK_U32 size); + void fifo_fwrite (FILE *fp, void *psrc, RK_U32 size); + MPP_RET fifo_packet_init (FifoCtx_t *pkt, RK_S32 header, RK_S32 size); +#ifdef __cplusplus +} +#endif + + + +//!<============================ +#endif //!<__HAL_H264D_FIFO_H__ + + + diff --git a/mpp/hal/rkdec/h264d/hal_h264d_global.h b/mpp/hal/rkdec/h264d/hal_h264d_global.h new file mode 100644 index 00000000..c62ab13c --- /dev/null +++ b/mpp/hal/rkdec/h264d/hal_h264d_global.h @@ -0,0 +1,65 @@ +/* +* +* 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. +*/ + + +#ifndef __HAL_H264D_GLOBAL_H__ +#define __HAL_H264D_GLOBAL_H__ + +#include "mpp_hal.h" +#include "dxva_syntax.h" +#include "h264d_syntax.h" + +#include "h264d_log.h" +#include "hal_h264d_reg.h" +#include "hal_h264d_fifo.h" +#include "hal_h264d_packet.h" + + +typedef struct h264d_hal_mem_t +{ + H264_REGS_t regs; //!< for register + H264_MMU_t mmu_regs; + H264_CACHE_t cache_regs; + H264_FifoPkt_t pkts; +}H264dHalMem_t; + +typedef struct h264d_hal_ctx_t +{ + H264dHalMem_t *mem; + H264_REGS_t *regs; + H264_MMU_t *mmu_regs; + H264_CACHE_t *cache_regs; + H264_FifoPkt_t *pkts; + RK_U8 spt_BitstrmRaw; + RK_U8 set_BitstrmRaw; + + DXVA_PicParams_H264_MVC *pp; + DXVA_Qmatrix_H264 *qm; + RK_U32 slice_num; + DXVA_Slice_H264_Short *slice_short; //!< MAX_SLICES + DXVA_Slice_H264_Long *slice_long; //!< MAX_SLICES + RK_U8 *bitstream; + RK_U32 strm_len; + RK_U32 g_framecnt; + H264dLogCtx_t logctx; //!< debug log file + LogCtx_t logctxbuf[LOG_MAX]; + +}H264dHalCtx_t; + + + +#endif /*__HAL_H264D_REG_H__*/ diff --git a/mpp/hal/rkdec/h264d/hal_h264d_packet.c b/mpp/hal/rkdec/h264d/hal_h264d_packet.c new file mode 100644 index 00000000..593d6a14 --- /dev/null +++ b/mpp/hal/rkdec/h264d/hal_h264d_packet.c @@ -0,0 +1,518 @@ + +/* + * Copyright 2010 Rockchip Electronics S.LSI 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. + */ + +#include +#include + +#include "mpp_mem.h" +#include "hal_task.h" + +#include "dxva_syntax.h" +#include "h264d_log.h" +#include "h264d_syntax.h" +#include "hal_h264d_fifo.h" +#include "hal_h264d_api.h" +#include "hal_h264d_packet.h" +#include "hal_h264d_global.h" + +#define MODULE_TAG "hal_h264d_packet" + +//!< Header +#define H264dREG_HEADER 0x48474552 +#define H264dPPS_HEADER 0x48535050 +#define H264dSCL_HEADER 0x534c4353 +#define H264dRPS_HEADER 0x48535052 +#define H264dCRC_HEADER 0x48435243 +#define H264dSTM_HEADER 0x4d525453 +#define H264dERR_HEADER 0x524f5245 + + +enum { + H264ScalingList4x4Length = 16, + H264ScalingList8x8Length = 64, +} ScalingListLength; + + +static void write_sps_to_fifo(H264dHalCtx_t *p_hal, FifoCtx_t *pkt) +{ + fifo_write_bits(pkt, -1, 4, "seq_parameter_set_id"); //!< not used in hard + fifo_write_bits(pkt, -1, 8, "profile_idc"); //!< not used in hard + fifo_write_bits(pkt, -1, 1, "constraint_set3_flag"); //!< not used in hard + fifo_write_bits(pkt, p_hal->pp->chroma_format_idc, 2, "chroma_format_idc"); + fifo_write_bits(pkt, (p_hal->pp->bit_depth_luma_minus8 + 8), 3, "bit_depth_luma"); + fifo_write_bits(pkt, (p_hal->pp->bit_depth_chroma_minus8 + 8), 3, "bit_depth_chroma"); + fifo_write_bits(pkt, 0, 1, "qpprime_y_zero_transform_bypass_flag"); //!< not supported in hard + fifo_write_bits(pkt, p_hal->pp->log2_max_frame_num_minus4, 4, "log2_max_frame_num_minus4"); + fifo_write_bits(pkt, p_hal->pp->num_ref_frames, 5, "max_num_ref_frames"); + fifo_write_bits(pkt, p_hal->pp->pic_order_cnt_type, 2, "pic_order_cnt_type"); + fifo_write_bits(pkt, p_hal->pp->log2_max_pic_order_cnt_lsb_minus4, 4, "log2_max_pic_order_cnt_lsb_minus4"); + fifo_write_bits(pkt, p_hal->pp->delta_pic_order_always_zero_flag, 1, "delta_pic_order_always_zero_flag"); + fifo_write_bits(pkt, (p_hal->pp->wFrameWidthInMbsMinus1 + 1), 9, "pic_width_in_mbs"); + fifo_write_bits(pkt, (p_hal->pp->wFrameHeightInMbsMinus1 + 1), 9, "pic_height_in_mbs"); + fifo_write_bits(pkt, p_hal->pp->frame_mbs_only_flag, 1, "frame_mbs_only_flag"); + fifo_write_bits(pkt, p_hal->pp->MbaffFrameFlag, 1, "mb_adaptive_frame_field_flag"); + fifo_write_bits(pkt, p_hal->pp->direct_8x8_inference_flag, 1, "direct_8x8_inference_flag"); + + fifo_write_bits(pkt, 1, 1, "mvc_extension_enable"); + fifo_write_bits(pkt, (p_hal->pp->num_views_minus1 + 1), 2, "num_views"); + fifo_write_bits(pkt, p_hal->pp->view_id[0], 10, "view_id[2]"); + fifo_write_bits(pkt, p_hal->pp->view_id[1], 10, "view_id[2]"); + fifo_write_bits(pkt, p_hal->pp->num_anchor_refs_l0[0], 1, "num_anchor_refs_l0"); + if (p_hal->pp->num_anchor_refs_l0[0]) + { + fifo_write_bits(pkt, p_hal->pp->anchor_ref_l0[0][0], 10, "anchor_ref_l0"); + } + else + { + fifo_write_bits(pkt, 0, 10, "anchor_ref_l0"); + } + fifo_write_bits(pkt, p_hal->pp->num_anchor_refs_l1[0], 1, "num_anchor_refs_l1"); + if (p_hal->pp->num_anchor_refs_l1[0]) + { + fifo_write_bits(pkt, p_hal->pp->anchor_ref_l1[0][0], 10, "anchor_ref_l1"); + } + else + { + fifo_write_bits(pkt, 0, 10, "anchor_ref_l1"); + } + fifo_write_bits(pkt, p_hal->pp->num_non_anchor_refs_l0[0], 1, "num_non_anchor_refs_l0"); + if (p_hal->pp->num_non_anchor_refs_l0[0]) + { + fifo_write_bits(pkt, p_hal->pp->non_anchor_ref_l0[0][0], 10, "non_anchor_ref_l0"); + } + else + { + fifo_write_bits(pkt, 0, 10, "non_anchor_ref_l0"); + } + fifo_write_bits(pkt, p_hal->pp->num_non_anchor_refs_l1[0], 1, "num_non_anchor_refs_l1"); + if (p_hal->pp->num_non_anchor_refs_l1[0]) + { + fifo_write_bits(pkt, p_hal->pp->non_anchor_ref_l1[0][0], 10, "non_anchor_ref_l1"); + } + else + { + fifo_write_bits(pkt, 0, 10, "non_anchor_ref_l1"); + } + fifo_align_bits(pkt, 32); +} + +static void write_pps_to_fifo(H264dHalCtx_t *p_hal, FifoCtx_t *pkt) +{ + fifo_write_bits(pkt, -1, 8, "pps_pic_parameter_set_id"); + fifo_write_bits(pkt, -1, 5, "pps_seq_parameter_set_id"); + fifo_write_bits(pkt, p_hal->pp->entropy_coding_mode_flag, 1, "entropy_coding_mode_flag"); + fifo_write_bits(pkt, p_hal->pp->pic_order_present_flag, 1, "bottom_field_pic_order_in_frame_present_flag"); + fifo_write_bits(pkt, p_hal->pp->num_ref_idx_l0_active_minus1, 5, "num_ref_idx_l0_default_active_minus1"); + fifo_write_bits(pkt, p_hal->pp->num_ref_idx_l1_active_minus1, 5, "num_ref_idx_l1_default_active_minus1"); + fifo_write_bits(pkt, p_hal->pp->weighted_pred_flag, 1, "weighted_pred_flag"); + fifo_write_bits(pkt, p_hal->pp->weighted_bipred_idc, 2, "weighted_bipred_idc"); + fifo_write_bits(pkt, p_hal->pp->pic_init_qp_minus26, 7, "pic_init_qp_minus26"); + fifo_write_bits(pkt, p_hal->pp->pic_init_qs_minus26, 6, "pic_init_qs_minus26"); + fifo_write_bits(pkt, p_hal->pp->chroma_qp_index_offset, 5, "chroma_qp_index_offset"); + fifo_write_bits(pkt, p_hal->pp->deblocking_filter_control_present_flag, 1, "deblocking_filter_control_present_flag"); + fifo_write_bits(pkt, p_hal->pp->constrained_intra_pred_flag, 1, "constrained_intra_pred_flag"); + fifo_write_bits(pkt, p_hal->pp->redundant_pic_cnt_present_flag, 1, "redundant_pic_cnt_present_flag"); + fifo_write_bits(pkt, p_hal->pp->transform_8x8_mode_flag, 1, "transform_8x8_mode_flag"); + fifo_write_bits(pkt, p_hal->pp->second_chroma_qp_index_offset, 5, "second_chroma_qp_index_offset"); + fifo_write_bits(pkt, p_hal->pp->scaleing_list_enable_flag, 1, "scaleing_list_enable_flag"); + fifo_write_bits(pkt, 0/*(RK_U32)p_hal->pkts.scanlist.pbuf*/, 32, "Scaleing_list_address"); + +} + + +/*! +*********************************************************************** +* \brief +* reset fifo packet +*********************************************************************** +*/ +//extern "C" +void reset_fifo_packet(H264_FifoPkt_t *pkt) +{ + if (pkt) + { + fifo_packet_reset(&pkt->spspps); + fifo_packet_reset(&pkt->rps); + fifo_packet_reset(&pkt->strm); + fifo_packet_reset(&pkt->scanlist); + fifo_packet_reset(&pkt->reg); + } +} + +/*! +*********************************************************************** +* \brief +* free fifo pakcket +*********************************************************************** +*/ +//extern "C" +void free_fifo_packet(H264_FifoPkt_t *pkt) +{ + if (pkt) + { + mpp_free(pkt->spspps.pbuf); + mpp_free(pkt->rps.pbuf); + mpp_free(pkt->scanlist.pbuf); + mpp_free(pkt->reg.pbuf); + } +} +/*! +*********************************************************************** +* \brief +* alloc fifo packet +*********************************************************************** +*/ +//extern "C" +MPP_RET alloc_fifo_packet(H264dLogCtx_t *logctx, H264_FifoPkt_t *pkts) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + LogCtx_t *log_driver = NULL; + RK_U32 pps_size = 256 * 32 + 16; + RK_U32 rps_size = 128 + 16; + RK_U32 strm_size = 0; + RK_U32 sclst_size = 256; + RK_U32 regs_size = 512; + + //!< initial packages header and malloc buffer + FUN_CHECK(ret = fifo_packet_init(&pkts->spspps, H264dPPS_HEADER, pps_size)); + FUN_CHECK(ret = fifo_packet_init(&pkts->rps, H264dRPS_HEADER, rps_size)); + FUN_CHECK(ret = fifo_packet_init(&pkts->strm, H264dSTM_HEADER, strm_size)); + FUN_CHECK(ret = fifo_packet_init(&pkts->scanlist, H264dSCL_HEADER, sclst_size)); + FUN_CHECK(ret = fifo_packet_init(&pkts->reg, H264dREG_HEADER, regs_size)); + + //!< set logctx + pkts->spspps.logctx = logctx->parr[LOG_WRITE_SPSPPS]; + pkts->rps.logctx = logctx->parr[LOG_WRITE_RPS]; + pkts->scanlist.logctx = logctx->parr[LOG_WRITE_SCANLIST]; + pkts->reg.logctx = logctx->parr[LOG_WRITE_REG]; + + //!< set bitstream file output + log_driver = logctx->parr[LOG_FPGA]; + if (log_driver && log_driver->flag->write_en) + { + pkts->spspps.fp_data = log_driver->fp; + pkts->rps.fp_data = log_driver->fp; + pkts->scanlist.fp_data = log_driver->fp; + pkts->reg.fp_data = log_driver->fp; + pkts->strm.fp_data = log_driver->fp; + } + else + { + pkts->spspps.fp_data = NULL; + pkts->rps.fp_data = NULL; + pkts->scanlist.fp_data = NULL; + pkts->reg.fp_data = NULL; + pkts->strm.fp_data = NULL; + } + return ret = MPP_OK; +__FAILED: + free_fifo_packet(pkts); + + return ret; +} + +/*! +*********************************************************************** +* \brief +* expalin decoder buffer dest +*********************************************************************** +*/ +//extern "C" +void explain_input_buffer(void *hal, HalDecTask *task) +{ + RK_U32 i = 0; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + DXVA2_DecodeBufferDesc *pdes = (DXVA2_DecodeBufferDesc *)task->syntax.data; + for (i = 0; i < task->syntax.number; i++) + { + switch (pdes[i].CompressedBufferType) + { + case DXVA2_PictureParametersBufferType: + p_hal->pp = (DXVA_PicParams_H264_MVC *)pdes[i].pvPVPState; + break; + case DXVA2_InverseQuantizationMatrixBufferType: + p_hal->qm = (DXVA_Qmatrix_H264 *)pdes[i].pvPVPState; + break; + case DXVA2_SliceControlBufferType: + p_hal->slice_num = pdes[i].DataSize / sizeof(DXVA_Slice_H264_Long); + p_hal->slice_long = (DXVA_Slice_H264_Long *)pdes[i].pvPVPState; + break; + case DXVA2_BitStreamDateBufferType: + p_hal->bitstream = (RK_U8 *)pdes[i].pvPVPState; + p_hal->strm_len = pdes[i].DataSize; + break; + default: + break; + } + } +} +/*! +*********************************************************************** +* \brief +* prepare sps_sps packet +*********************************************************************** +*/ +//extern "C" +void prepare_spspps_packet(void *hal, FifoCtx_t *pkt) +{ + RK_S32 i = 0; + RK_S32 is_long_term = 0, voidx = 0; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + fifo_packet_reset(pkt); + LogInfo(pkt->logctx, "------------------ Frame SPS_PPS begin ------------------------"); + write_sps_to_fifo(p_hal, pkt); + write_pps_to_fifo(p_hal, pkt); + + for (i = 0; i < 16; i++) + { + is_long_term = (p_hal->pp->RefFrameList[i].bPicEntry != 0xff) ? p_hal->pp->RefFrameList[i].AssociatedFlag : 0; + fifo_write_bits(pkt, is_long_term, 1, "is_long_term"); + } + for (i = 0; i < 16; i++) + { + voidx = (p_hal->pp->RefFrameList[i].bPicEntry != 0xff) ? p_hal->pp->RefPicLayerIdList[i] : 0; + fifo_write_bits(pkt, voidx, 1, "voidx"); + } + fifo_align_bits(pkt, 64); + fifo_fwrite_data(pkt); //!< "PPSH" header 32 bit +} +/*! +*********************************************************************** +* \brief +* prepare frame rps packet +*********************************************************************** +*/ +//extern "C" +void prepare_framerps_packet(void *hal, FifoCtx_t *pkt) +{ + RK_S32 i = 0, j = 0; + RK_S32 dpb_idx = 0, voidx = 0; + RK_S32 dpb_valid = 0, bottom_flag = 0; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + + fifo_packet_reset(pkt); + LogInfo(pkt->logctx, "------------------ Frame RPS begin ------------------------"); + for (i = 0; i < 16; i++) + { + fifo_write_bits(pkt, p_hal->pp->FrameNumList[i], 16, "frame_num_wrap"); + } + for (i = 0; i < 16; i++) + { + fifo_write_bits(pkt, 0, 1, "NULL"); + } + for (i = 0; i < 16; i++) + { + fifo_write_bits(pkt, p_hal->pp->RefPicLayerIdList[i], 1, "voidx"); + } + for (i = 0; i < 32; i++) + { + dpb_valid = (p_hal->slice_long[0].RefPicList[0][i].bPicEntry == 0xff) ? 0 : 1; + dpb_idx = dpb_valid ? p_hal->slice_long[0].RefPicList[0][i].Index7Bits : 0; + bottom_flag = dpb_valid ? p_hal->slice_long[0].RefPicList[0][i].AssociatedFlag : 0; + voidx = dpb_valid ? p_hal->pp->RefPicLayerIdList[dpb_idx] : 0; + fifo_write_bits(pkt, dpb_idx | (dpb_valid << 4), 5, "dpb_idx"); + fifo_write_bits(pkt, bottom_flag, 1, "bottom_flag"); + fifo_write_bits(pkt, voidx, 1, "voidx"); + } + for (j = 1; j < 3; j++) + { + for (i = 0; i < 32; i++) + { + dpb_valid = (p_hal->slice_long[0].RefPicList[j][i].bPicEntry == 0xff) ? 0 : 1; + dpb_idx = dpb_valid ? p_hal->slice_long[0].RefPicList[j][i].Index7Bits : 0; + bottom_flag = dpb_valid ? p_hal->slice_long[0].RefPicList[j][i].AssociatedFlag : 0; + voidx = dpb_valid ? p_hal->pp->RefPicLayerIdList[dpb_idx] : 0; + fifo_write_bits(pkt, dpb_idx | (dpb_valid << 4), 5, "dpb_idx"); + fifo_write_bits(pkt, bottom_flag, 1, "bottom_flag"); + fifo_write_bits(pkt, voidx, 1, "voidx"); + } + } + fifo_align_bits(pkt, 128); + fifo_flush_bits(pkt); + fifo_fwrite_data(pkt); //!< "RPSH" header 32 bit +} +/*! +*********************************************************************** +* \brief +* prepare scanlist packet +*********************************************************************** +*/ +//extern "C" +void prepare_scanlist_packet(void *hal, FifoCtx_t *pkt) +{ + RK_S32 i = 0; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + + if (p_hal->pp->scaleing_list_enable_flag) + { + fifo_packet_reset(pkt); + LogInfo(pkt->logctx, "------------------ Scanlist begin ------------------------"); + for (i = 0; i < 6; ++i) //!< 4x4, 6 lists + { + fifo_write_bytes(pkt, p_hal->qm->bScalingLists4x4[i], H264ScalingList4x4Length); + } + for (i = 0; i < 2; ++i) + { + fifo_write_bytes(pkt, p_hal->qm->bScalingLists8x8[i], H264ScalingList8x8Length); + } + fifo_fwrite_data(pkt); //!< "SCLS" header 32 bit + } +} +/*! +*********************************************************************** +* \brief +* prepare stream packet +*********************************************************************** +*/ +//extern "C" +void prepare_stream_packet(void *hal, FifoCtx_t *pkt) +{ + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + + fifo_packet_reset(pkt); + pkt->pbuf = (RK_U64 *)p_hal->bitstream; + pkt->index = p_hal->strm_len / 8; + fifo_fwrite_data(pkt); // "STRM" header 32 bit +} +/*! +*********************************************************************** +* \brief +* generate register packet +*********************************************************************** +*/ +//extern "C" +void generate_regs(void *hal, FifoCtx_t *pkt) +{ + RK_S32 i = 0; + RK_U8 bit_depth[3] = { 0 }; + RK_U32 sw_y_hor_virstride = 0; + RK_U32 sw_uv_hor_virstride = 0; + RK_U32 sw_y_virstride = 0; + RK_U32 yuv_virstride = 0; + RK_U32 pic_h[3] = { 0 }, pic_w[3] = { 0 }; + RK_U32 mb_width = 0, mb_height = 0, mv_size = 0; + + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + H264_REGS_t *p_regs = p_hal->regs; + memset(p_regs, 0, sizeof(H264_REGS_t)); + + if (p_regs->swreg2_sysctrl.sw_rlc_mode == 1) + { + p_regs->swreg5_stream_rlc_len.sw_stream_len = 0; + } + else + { + p_regs->swreg5_stream_rlc_len.sw_stream_len = p_hal->strm_len; + } + //!< caculate the yuv_frame_size and mv_size + mb_width = p_hal->pp->wFrameWidthInMbsMinus1 + 1; + mb_height = (2 - p_hal->pp->frame_mbs_only_flag)*(p_hal->pp->wFrameHeightInMbsMinus1 + 1); + mv_size = mb_width * mb_height * 8; // 64bit per 4x4 + bit_depth[0] = p_hal->pp->bit_depth_luma_minus8 + 8; + if (p_hal->pp->chroma_format_idc) // Y420 Y422 + { + bit_depth[1] = p_hal->pp->bit_depth_chroma_minus8 + 8; + } + else //!< Y400 + { + bit_depth[1] = 0; + } + pic_h[0] = mb_height * 16; + if (p_hal->pp->chroma_format_idc == 2) // Y422 + { + pic_h[1] = mb_height * 16; + } + else //!< Y420 + { + pic_h[1] = mb_height * 8; + } + pic_w[0] = mb_width * 16; + pic_w[1] = mb_width * 16; + sw_y_hor_virstride = ((pic_w[0] * bit_depth[0] + 127) & (~127)) / 128; + sw_uv_hor_virstride = ((pic_w[1] * bit_depth[1] + 127) & (~127)) / 128; + + if (sw_y_hor_virstride > p_regs->swreg3_picpar.sw_y_hor_virstride) + { + p_regs->swreg3_picpar.sw_y_hor_virstride = sw_y_hor_virstride; + } + if (sw_uv_hor_virstride > p_regs->swreg3_picpar.sw_uv_hor_virstride) + { + p_regs->swreg3_picpar.sw_uv_hor_virstride = sw_uv_hor_virstride; + } + sw_y_virstride = pic_h[0] * p_regs->swreg3_picpar.sw_y_hor_virstride; + if (sw_y_virstride > p_regs->swreg8_y_virstride.sw_y_virstride) + { + p_regs->swreg8_y_virstride.sw_y_virstride = sw_y_virstride; + } + if (p_hal->pp->chroma_format_idc == 0) // YUV400 + { + yuv_virstride = p_regs->swreg8_y_virstride.sw_y_virstride; + } + else + { + yuv_virstride = pic_h[0] * p_regs->swreg3_picpar.sw_y_hor_virstride + + pic_h[1] * p_regs->swreg3_picpar.sw_uv_hor_virstride; + } + if (yuv_virstride > p_regs->swreg9_yuv_virstride.sw_yuv_virstride) + { + p_regs->swreg9_yuv_virstride.sw_yuv_virstride = yuv_virstride; + } + p_regs->compare_len = (p_regs->swreg9_yuv_virstride.sw_yuv_virstride + mv_size) * 2; + if (p_regs->swreg2_sysctrl.sw_h264_rps_mode) // rps_mode == 1 + { + p_regs->swreg43_rps_base.sw_rps_base += 0x8; + } + p_regs->swreg3_picpar.sw_slice_num_lowbits = 0x7ff; // p_Vid->iNumOfSlicesDecoded & 0x7ff + p_regs->swreg3_picpar.sw_slice_num_highbit = 1; // (p_Vid->iNumOfSlicesDecoded >> 11) & 1 + //!< set current + p_regs->swreg40_cur_poc.sw_cur_poc = p_hal->pp->CurrFieldOrderCnt[0]; + p_regs->swreg74_h264_cur_poc1.sw_h264_cur_poc1 = p_hal->pp->CurrFieldOrderCnt[1]; + p_regs->swreg7_decout_base.sw_decout_base = p_hal->pp->CurrPic.Index7Bits; + //!< set reference + for (i = 0; i < 15; i++) + { + p_regs->swreg25_39_refer0_14_poc[i] = (i & 1) ? p_hal->pp->FieldOrderCntList[i / 2][1] : p_hal->pp->FieldOrderCntList[i / 2][0]; + p_regs->swreg49_63_refer15_29_poc[i] = (i & 1) ? p_hal->pp->FieldOrderCntList[(i + 15) / 2][0] : p_hal->pp->FieldOrderCntList[(i + 15) / 2][1]; + p_regs->swreg10_24_refer0_14_base[i].sw_ref_field = (p_hal->pp->RefPicFiledFlags >> i) & 0x01; + p_regs->swreg10_24_refer0_14_base[i].sw_ref_topfield_used = (p_hal->pp->UsedForReferenceFlags >> (2 * i + 0)) & 0x01; + p_regs->swreg10_24_refer0_14_base[i].sw_ref_botfield_used = (p_hal->pp->UsedForReferenceFlags >> (2 * i + 1)) & 0x01; + p_regs->swreg10_24_refer0_14_base[i].sw_ref_colmv_use_flag = (p_hal->pp->RefPicColmvUsedFlags >> i) & 0x01; + if (p_hal->pp->RefFrameList[i].bPicEntry != 0xff) + { + p_regs->swreg10_24_refer0_14_base[i].sw_refer_base = p_hal->pp->RefFrameList[i].Index7Bits; + } + } + p_regs->swreg72_refer30_poc = p_hal->pp->FieldOrderCntList[i][0]; + p_regs->swreg73_refer31_poc = p_hal->pp->FieldOrderCntList[i][1]; + p_regs->swreg48_refer15_base.sw_ref_field = (p_hal->pp->RefPicFiledFlags >> 15) & 0x01; + p_regs->swreg48_refer15_base.sw_ref_topfield_used = (p_hal->pp->UsedForReferenceFlags >> 30) & 0x01; + p_regs->swreg48_refer15_base.sw_ref_botfield_used = (p_hal->pp->UsedForReferenceFlags >> 31) & 0x01; + p_regs->swreg48_refer15_base.sw_ref_colmv_use_flag = (p_hal->pp->RefPicColmvUsedFlags >> 15) & 0x01; + if (p_hal->pp->RefFrameList[15].bPicEntry != 0xff) + { + p_regs->swreg48_refer15_base.sw_refer_base = p_hal->pp->RefFrameList[15].Index7Bits; + } + + fifo_packet_reset(pkt); + fifo_write_bytes(pkt, (void *)p_hal->regs, sizeof(H264_REGS_t)); + fifo_write_bytes(pkt, (void *)p_hal->mmu_regs, sizeof(H264_MMU_t)); + fifo_write_bytes(pkt, (void *)p_hal->cache_regs, sizeof(H264_CACHE_t)); + fifo_align_bits(pkt, 64); + fifo_flush_bits(pkt); + fifo_fwrite_data(pkt); //!< "REGH" header 32 bit +} + diff --git a/mpp/hal/rkdec/h264d/hal_h264d_packet.h b/mpp/hal/rkdec/h264d/hal_h264d_packet.h new file mode 100644 index 00000000..77948481 --- /dev/null +++ b/mpp/hal/rkdec/h264d/hal_h264d_packet.h @@ -0,0 +1,45 @@ +#ifndef __HAL_H264D_PACKET_H__ +#define __HAL_H264D_PACKET_H__ + +#include "rk_type.h" +#include "mpp_err.h" +#include "hal_task.h" + +#include "h264d_log.h" +#include "hal_h264d_fifo.h" + +typedef struct h264_fifo_packet_t +{ + FifoCtx_t spspps; + FifoCtx_t rps; + FifoCtx_t strm; + FifoCtx_t scanlist; + FifoCtx_t reg; +}H264_FifoPkt_t; + + +#ifdef __cplusplus +extern "C" { +#endif + void reset_fifo_packet(H264_FifoPkt_t *pkt); + void free_fifo_packet (H264_FifoPkt_t *pkt); + MPP_RET alloc_fifo_packet(H264dLogCtx_t *logctx, H264_FifoPkt_t *pkts); + + void explain_input_buffer (void *hal, HalDecTask *task); + void prepare_spspps_packet (void *hal, FifoCtx_t *pkt); + void prepare_framerps_packet(void *hal, FifoCtx_t *pkt); + void prepare_scanlist_packet(void *hal, FifoCtx_t *pkt); + void prepare_stream_packet (void *hal, FifoCtx_t *pkt); + void generate_regs (void *hal, FifoCtx_t *pkt); + +#ifdef __cplusplus +} +#endif + + + +//!<============================ +#endif // __HAL_H264D_PACKET_H__ + + + diff --git a/mpp/hal/rkdec/h264d/hal_h264d_reg.c b/mpp/hal/rkdec/h264d/hal_h264d_reg.c new file mode 100644 index 00000000..584b9ab9 --- /dev/null +++ b/mpp/hal/rkdec/h264d/hal_h264d_reg.c @@ -0,0 +1,270 @@ +/* +* +* 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. +*/ + + +#include +#include +#include + +#include "rk_type.h" +#include "mpp_err.h" +#include "mpp_mem.h" + +#include "h264d_log.h" +#include "hal_h264d_reg.h" + + + +#define MODULE_TAG "hal_h264d_reg" + + + +const RK_U8 H264_Cabac_table[] = +{ + 0x14, 0xf1, 0x02, 0x36, 0x03, 0x4a, 0x14, 0xf1, 0x02, 0x36, 0x03, 0x4a, 0xe4, 0x7f, 0xe9, 0x68, + 0xfa, 0x35, 0xff, 0x36, 0x07, 0x33, 0x17, 0x21, 0x17, 0x02, 0x15, 0x00, 0x01, 0x09, 0x00, 0x31, + 0xdb, 0x76, 0x05, 0x39, 0xf3, 0x4e, 0xf5, 0x41, 0x01, 0x3e, 0x0c, 0x31, 0xfc, 0x49, 0x11, 0x32, + 0x12, 0x40, 0x09, 0x2b, 0x1d, 0x00, 0x1a, 0x43, 0x10, 0x5a, 0x09, 0x68, 0xd2, 0x7f, 0xec, 0x68, + 0x01, 0x43, 0xf3, 0x4e, 0xf5, 0x41, 0x01, 0x3e, 0xfa, 0x56, 0xef, 0x5f, 0xfa, 0x3d, 0x09, 0x2d, + 0xfd, 0x45, 0xfa, 0x51, 0xf5, 0x60, 0x06, 0x37, 0x07, 0x43, 0xfb, 0x56, 0x02, 0x58, 0x00, 0x3a, + 0xfd, 0x4c, 0xf6, 0x5e, 0x05, 0x36, 0x04, 0x45, 0xfd, 0x51, 0x00, 0x58, 0xf9, 0x43, 0xfb, 0x4a, + 0xfc, 0x4a, 0xfb, 0x50, 0xf9, 0x48, 0x01, 0x3a, 0x00, 0x29, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f, + 0xf7, 0x53, 0x04, 0x56, 0x00, 0x61, 0xf9, 0x48, 0x0d, 0x29, 0x03, 0x3e, 0x00, 0x2d, 0xfc, 0x4e, + 0xfd, 0x60, 0xe5, 0x7e, 0xe4, 0x62, 0xe7, 0x65, 0xe9, 0x43, 0xe4, 0x52, 0xec, 0x5e, 0xf0, 0x53, + 0xea, 0x6e, 0xeb, 0x5b, 0xee, 0x66, 0xf3, 0x5d, 0xe3, 0x7f, 0xf9, 0x5c, 0xfb, 0x59, 0xf9, 0x60, + 0xf3, 0x6c, 0xfd, 0x2e, 0xff, 0x41, 0xff, 0x39, 0xf7, 0x5d, 0xfd, 0x4a, 0xf7, 0x5c, 0xf8, 0x57, + 0xe9, 0x7e, 0x05, 0x36, 0x06, 0x3c, 0x06, 0x3b, 0x06, 0x45, 0xff, 0x30, 0x00, 0x44, 0xfc, 0x45, + 0xf8, 0x58, 0xfe, 0x55, 0xfa, 0x4e, 0xff, 0x4b, 0xf9, 0x4d, 0x02, 0x36, 0x05, 0x32, 0xfd, 0x44, + 0x01, 0x32, 0x06, 0x2a, 0xfc, 0x51, 0x01, 0x3f, 0xfc, 0x46, 0x00, 0x43, 0x02, 0x39, 0xfe, 0x4c, + 0x0b, 0x23, 0x04, 0x40, 0x01, 0x3d, 0x0b, 0x23, 0x12, 0x19, 0x0c, 0x18, 0x0d, 0x1d, 0x0d, 0x24, + 0xf6, 0x5d, 0xf9, 0x49, 0xfe, 0x49, 0x0d, 0x2e, 0x09, 0x31, 0xf9, 0x64, 0x09, 0x35, 0x02, 0x35, + 0x05, 0x35, 0xfe, 0x3d, 0x00, 0x38, 0x00, 0x38, 0xf3, 0x3f, 0xfb, 0x3c, 0xff, 0x3e, 0x04, 0x39, + 0xfa, 0x45, 0x04, 0x39, 0x0e, 0x27, 0x04, 0x33, 0x0d, 0x44, 0x03, 0x40, 0x01, 0x3d, 0x09, 0x3f, + 0x07, 0x32, 0x10, 0x27, 0x05, 0x2c, 0x04, 0x34, 0x0b, 0x30, 0xfb, 0x3c, 0xff, 0x3b, 0x00, 0x3b, + 0x16, 0x21, 0x05, 0x2c, 0x0e, 0x2b, 0xff, 0x4e, 0x00, 0x3c, 0x09, 0x45, 0x0b, 0x1c, 0x02, 0x28, + 0x03, 0x2c, 0x00, 0x31, 0x00, 0x2e, 0x02, 0x2c, 0x02, 0x33, 0x00, 0x2f, 0x04, 0x27, 0x02, 0x3e, + 0x06, 0x2e, 0x00, 0x36, 0x03, 0x36, 0x02, 0x3a, 0x04, 0x3f, 0x06, 0x33, 0x06, 0x39, 0x07, 0x35, + 0x06, 0x34, 0x06, 0x37, 0x0b, 0x2d, 0x0e, 0x24, 0x08, 0x35, 0xff, 0x52, 0x07, 0x37, 0xfd, 0x4e, + 0x0f, 0x2e, 0x16, 0x1f, 0xff, 0x54, 0x19, 0x07, 0x1e, 0xf9, 0x1c, 0x03, 0x1c, 0x04, 0x20, 0x00, + 0x22, 0xff, 0x1e, 0x06, 0x1e, 0x06, 0x20, 0x09, 0x1f, 0x13, 0x1a, 0x1b, 0x1a, 0x1e, 0x25, 0x14, + 0x1c, 0x22, 0x11, 0x46, 0x01, 0x43, 0x05, 0x3b, 0x09, 0x43, 0x10, 0x1e, 0x12, 0x20, 0x12, 0x23, + 0x16, 0x1d, 0x18, 0x1f, 0x17, 0x26, 0x12, 0x2b, 0x14, 0x29, 0x0b, 0x3f, 0x09, 0x3b, 0x09, 0x40, + 0xff, 0x5e, 0xfe, 0x59, 0xf7, 0x6c, 0xfa, 0x4c, 0xfe, 0x2c, 0x00, 0x2d, 0x00, 0x34, 0xfd, 0x40, + 0xfe, 0x3b, 0xfc, 0x46, 0xfc, 0x4b, 0xf8, 0x52, 0xef, 0x66, 0xf7, 0x4d, 0x03, 0x18, 0x00, 0x2a, + 0x00, 0x30, 0x00, 0x37, 0xfa, 0x3b, 0xf9, 0x47, 0xf4, 0x53, 0xf5, 0x57, 0xe2, 0x77, 0x01, 0x3a, + 0xfd, 0x1d, 0xff, 0x24, 0x01, 0x26, 0x02, 0x2b, 0xfa, 0x37, 0x00, 0x3a, 0x00, 0x40, 0xfd, 0x4a, + 0xf6, 0x5a, 0x00, 0x46, 0xfc, 0x1d, 0x05, 0x1f, 0x07, 0x2a, 0x01, 0x3b, 0xfe, 0x3a, 0xfd, 0x48, + 0xfd, 0x51, 0xf5, 0x61, 0x00, 0x3a, 0x08, 0x05, 0x0a, 0x0e, 0x0e, 0x12, 0x0d, 0x1b, 0x02, 0x28, + 0x00, 0x3a, 0xfd, 0x46, 0xfa, 0x4f, 0xf8, 0x55, 0x00, 0x00, 0xf3, 0x6a, 0xf0, 0x6a, 0xf6, 0x57, + 0xeb, 0x72, 0xee, 0x6e, 0xf2, 0x62, 0xea, 0x6e, 0xeb, 0x6a, 0xee, 0x67, 0xeb, 0x6b, 0xe9, 0x6c, + 0xe6, 0x70, 0xf6, 0x60, 0xf4, 0x5f, 0xfb, 0x5b, 0xf7, 0x5d, 0xea, 0x5e, 0xfb, 0x56, 0x09, 0x43, + 0xfc, 0x50, 0xf6, 0x55, 0xff, 0x46, 0x07, 0x3c, 0x09, 0x3a, 0x05, 0x3d, 0x0c, 0x32, 0x0f, 0x32, + 0x12, 0x31, 0x11, 0x36, 0x0a, 0x29, 0x07, 0x2e, 0xff, 0x33, 0x07, 0x31, 0x08, 0x34, 0x09, 0x29, + 0x06, 0x2f, 0x02, 0x37, 0x0d, 0x29, 0x0a, 0x2c, 0x06, 0x32, 0x05, 0x35, 0x0d, 0x31, 0x04, 0x3f, + 0x06, 0x40, 0xfe, 0x45, 0xfe, 0x3b, 0x06, 0x46, 0x0a, 0x2c, 0x09, 0x1f, 0x0c, 0x2b, 0x03, 0x35, + 0x0e, 0x22, 0x0a, 0x26, 0xfd, 0x34, 0x0d, 0x28, 0x11, 0x20, 0x07, 0x2c, 0x07, 0x26, 0x0d, 0x32, + 0x0a, 0x39, 0x1a, 0x2b, 0x0e, 0x0b, 0x0b, 0x0e, 0x09, 0x0b, 0x12, 0x0b, 0x15, 0x09, 0x17, 0xfe, + 0x20, 0xf1, 0x20, 0xf1, 0x22, 0xeb, 0x27, 0xe9, 0x2a, 0xdf, 0x29, 0xe1, 0x2e, 0xe4, 0x26, 0xf4, + 0x15, 0x1d, 0x2d, 0xe8, 0x35, 0xd3, 0x30, 0xe6, 0x41, 0xd5, 0x2b, 0xed, 0x27, 0xf6, 0x1e, 0x09, + 0x12, 0x1a, 0x14, 0x1b, 0x00, 0x39, 0xf2, 0x52, 0xfb, 0x4b, 0xed, 0x61, 0xdd, 0x7d, 0x1b, 0x00, + 0x1c, 0x00, 0x1f, 0xfc, 0x1b, 0x06, 0x22, 0x08, 0x1e, 0x0a, 0x18, 0x16, 0x21, 0x13, 0x16, 0x20, + 0x1a, 0x1f, 0x15, 0x29, 0x1a, 0x2c, 0x17, 0x2f, 0x10, 0x41, 0x0e, 0x47, 0x08, 0x3c, 0x06, 0x3f, + 0x11, 0x41, 0x15, 0x18, 0x17, 0x14, 0x1a, 0x17, 0x1b, 0x20, 0x1c, 0x17, 0x1c, 0x18, 0x17, 0x28, + 0x18, 0x20, 0x1c, 0x1d, 0x17, 0x2a, 0x13, 0x39, 0x16, 0x35, 0x16, 0x3d, 0x0b, 0x56, 0x0c, 0x28, + 0x0b, 0x33, 0x0e, 0x3b, 0xfc, 0x4f, 0xf9, 0x47, 0xfb, 0x45, 0xf7, 0x46, 0xf8, 0x42, 0xf6, 0x44, + 0xed, 0x49, 0xf4, 0x45, 0xf0, 0x46, 0xf1, 0x43, 0xec, 0x3e, 0xed, 0x46, 0xf0, 0x42, 0xea, 0x41, + 0xec, 0x3f, 0x09, 0xfe, 0x1a, 0xf7, 0x21, 0xf7, 0x27, 0xf9, 0x29, 0xfe, 0x2d, 0x03, 0x31, 0x09, + 0x2d, 0x1b, 0x24, 0x3b, 0xfa, 0x42, 0xf9, 0x23, 0xf9, 0x2a, 0xf8, 0x2d, 0xfb, 0x30, 0xf4, 0x38, + 0xfa, 0x3c, 0xfb, 0x3e, 0xf8, 0x42, 0xf8, 0x4c, 0xfb, 0x55, 0xfa, 0x51, 0xf6, 0x4d, 0xf9, 0x51, + 0xef, 0x50, 0xee, 0x49, 0xfc, 0x4a, 0xf6, 0x53, 0xf7, 0x47, 0xf7, 0x43, 0xff, 0x3d, 0xf8, 0x42, + 0xf2, 0x42, 0x00, 0x3b, 0x02, 0x3b, 0x15, 0xf3, 0x21, 0xf2, 0x27, 0xf9, 0x2e, 0xfe, 0x33, 0x02, + 0x3c, 0x06, 0x3d, 0x11, 0x37, 0x22, 0x2a, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x14, 0xf1, 0x02, 0x36, 0x03, 0x4a, 0x14, 0xf1, 0x02, 0x36, 0x03, 0x4a, 0xe4, 0x7f, 0xe9, 0x68, + 0xfa, 0x35, 0xff, 0x36, 0x07, 0x33, 0x16, 0x19, 0x22, 0x00, 0x10, 0x00, 0xfe, 0x09, 0x04, 0x29, + 0xe3, 0x76, 0x02, 0x41, 0xfa, 0x47, 0xf3, 0x4f, 0x05, 0x34, 0x09, 0x32, 0xfd, 0x46, 0x0a, 0x36, + 0x1a, 0x22, 0x13, 0x16, 0x28, 0x00, 0x39, 0x02, 0x29, 0x24, 0x1a, 0x45, 0xd3, 0x7f, 0xf1, 0x65, + 0xfc, 0x4c, 0xfa, 0x47, 0xf3, 0x4f, 0x05, 0x34, 0x06, 0x45, 0xf3, 0x5a, 0x00, 0x34, 0x08, 0x2b, + 0xfe, 0x45, 0xfb, 0x52, 0xf6, 0x60, 0x02, 0x3b, 0x02, 0x4b, 0xfd, 0x57, 0xfd, 0x64, 0x01, 0x38, + 0xfd, 0x4a, 0xfa, 0x55, 0x00, 0x3b, 0xfd, 0x51, 0xf9, 0x56, 0xfb, 0x5f, 0xff, 0x42, 0xff, 0x4d, + 0x01, 0x46, 0xfe, 0x56, 0xfb, 0x48, 0x00, 0x3d, 0x00, 0x29, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f, + 0xf7, 0x53, 0x04, 0x56, 0x00, 0x61, 0xf9, 0x48, 0x0d, 0x29, 0x03, 0x3e, 0x0d, 0x0f, 0x07, 0x33, + 0x02, 0x50, 0xd9, 0x7f, 0xee, 0x5b, 0xef, 0x60, 0xe6, 0x51, 0xdd, 0x62, 0xe8, 0x66, 0xe9, 0x61, + 0xe5, 0x77, 0xe8, 0x63, 0xeb, 0x6e, 0xee, 0x66, 0xdc, 0x7f, 0x00, 0x50, 0xfb, 0x59, 0xf9, 0x5e, + 0xfc, 0x5c, 0x00, 0x27, 0x00, 0x41, 0xf1, 0x54, 0xdd, 0x7f, 0xfe, 0x49, 0xf4, 0x68, 0xf7, 0x5b, + 0xe1, 0x7f, 0x03, 0x37, 0x07, 0x38, 0x07, 0x37, 0x08, 0x3d, 0xfd, 0x35, 0x00, 0x44, 0xf9, 0x4a, + 0xf7, 0x58, 0xf3, 0x67, 0xf3, 0x5b, 0xf7, 0x59, 0xf2, 0x5c, 0xf8, 0x4c, 0xf4, 0x57, 0xe9, 0x6e, + 0xe8, 0x69, 0xf6, 0x4e, 0xec, 0x70, 0xef, 0x63, 0xb2, 0x7f, 0xba, 0x7f, 0xce, 0x7f, 0xd2, 0x7f, + 0xfc, 0x42, 0xfb, 0x4e, 0xfc, 0x47, 0xf8, 0x48, 0x02, 0x3b, 0xff, 0x37, 0xf9, 0x46, 0xfa, 0x4b, + 0xf8, 0x59, 0xde, 0x77, 0xfd, 0x4b, 0x20, 0x14, 0x1e, 0x16, 0xd4, 0x7f, 0x00, 0x36, 0xfb, 0x3d, + 0x00, 0x3a, 0xff, 0x3c, 0xfd, 0x3d, 0xf8, 0x43, 0xe7, 0x54, 0xf2, 0x4a, 0xfb, 0x41, 0x05, 0x34, + 0x02, 0x39, 0x00, 0x3d, 0xf7, 0x45, 0xf5, 0x46, 0x12, 0x37, 0xfc, 0x47, 0x00, 0x3a, 0x07, 0x3d, + 0x09, 0x29, 0x12, 0x19, 0x09, 0x20, 0x05, 0x2b, 0x09, 0x2f, 0x00, 0x2c, 0x00, 0x33, 0x02, 0x2e, + 0x13, 0x26, 0xfc, 0x42, 0x0f, 0x26, 0x0c, 0x2a, 0x09, 0x22, 0x00, 0x59, 0x04, 0x2d, 0x0a, 0x1c, + 0x0a, 0x1f, 0x21, 0xf5, 0x34, 0xd5, 0x12, 0x0f, 0x1c, 0x00, 0x23, 0xea, 0x26, 0xe7, 0x22, 0x00, + 0x27, 0xee, 0x20, 0xf4, 0x66, 0xa2, 0x00, 0x00, 0x38, 0xf1, 0x21, 0xfc, 0x1d, 0x0a, 0x25, 0xfb, + 0x33, 0xe3, 0x27, 0xf7, 0x34, 0xde, 0x45, 0xc6, 0x43, 0xc1, 0x2c, 0xfb, 0x20, 0x07, 0x37, 0xe3, + 0x20, 0x01, 0x00, 0x00, 0x1b, 0x24, 0x21, 0xe7, 0x22, 0xe2, 0x24, 0xe4, 0x26, 0xe4, 0x26, 0xe5, + 0x22, 0xee, 0x23, 0xf0, 0x22, 0xf2, 0x20, 0xf8, 0x25, 0xfa, 0x23, 0x00, 0x1e, 0x0a, 0x1c, 0x12, + 0x1a, 0x19, 0x1d, 0x29, 0x00, 0x4b, 0x02, 0x48, 0x08, 0x4d, 0x0e, 0x23, 0x12, 0x1f, 0x11, 0x23, + 0x15, 0x1e, 0x11, 0x2d, 0x14, 0x2a, 0x12, 0x2d, 0x1b, 0x1a, 0x10, 0x36, 0x07, 0x42, 0x10, 0x38, + 0x0b, 0x49, 0x0a, 0x43, 0xf6, 0x74, 0xe9, 0x70, 0xf1, 0x47, 0xf9, 0x3d, 0x00, 0x35, 0xfb, 0x42, + 0xf5, 0x4d, 0xf7, 0x50, 0xf7, 0x54, 0xf6, 0x57, 0xde, 0x7f, 0xeb, 0x65, 0xfd, 0x27, 0xfb, 0x35, + 0xf9, 0x3d, 0xf5, 0x4b, 0xf1, 0x4d, 0xef, 0x5b, 0xe7, 0x6b, 0xe7, 0x6f, 0xe4, 0x7a, 0xf5, 0x4c, + 0xf6, 0x2c, 0xf6, 0x34, 0xf6, 0x39, 0xf7, 0x3a, 0xf0, 0x48, 0xf9, 0x45, 0xfc, 0x45, 0xfb, 0x4a, + 0xf7, 0x56, 0x02, 0x42, 0xf7, 0x22, 0x01, 0x20, 0x0b, 0x1f, 0x05, 0x34, 0xfe, 0x37, 0xfe, 0x43, + 0x00, 0x49, 0xf8, 0x59, 0x03, 0x34, 0x07, 0x04, 0x0a, 0x08, 0x11, 0x08, 0x10, 0x13, 0x03, 0x25, + 0xff, 0x3d, 0xfb, 0x49, 0xff, 0x46, 0xfc, 0x4e, 0x00, 0x00, 0xeb, 0x7e, 0xe9, 0x7c, 0xec, 0x6e, + 0xe6, 0x7e, 0xe7, 0x7c, 0xef, 0x69, 0xe5, 0x79, 0xe5, 0x75, 0xef, 0x66, 0xe6, 0x75, 0xe5, 0x74, + 0xdf, 0x7a, 0xf6, 0x5f, 0xf2, 0x64, 0xf8, 0x5f, 0xef, 0x6f, 0xe4, 0x72, 0xfa, 0x59, 0xfe, 0x50, + 0xfc, 0x52, 0xf7, 0x55, 0xf8, 0x51, 0xff, 0x48, 0x05, 0x40, 0x01, 0x43, 0x09, 0x38, 0x00, 0x45, + 0x01, 0x45, 0x07, 0x45, 0xf9, 0x45, 0xfa, 0x43, 0xf0, 0x4d, 0xfe, 0x40, 0x02, 0x3d, 0xfa, 0x43, + 0xfd, 0x40, 0x02, 0x39, 0xfd, 0x41, 0xfd, 0x42, 0x00, 0x3e, 0x09, 0x33, 0xff, 0x42, 0xfe, 0x47, + 0xfe, 0x4b, 0xff, 0x46, 0xf7, 0x48, 0x0e, 0x3c, 0x10, 0x25, 0x00, 0x2f, 0x12, 0x23, 0x0b, 0x25, + 0x0c, 0x29, 0x0a, 0x29, 0x02, 0x30, 0x0c, 0x29, 0x0d, 0x29, 0x00, 0x3b, 0x03, 0x32, 0x13, 0x28, + 0x03, 0x42, 0x12, 0x32, 0x13, 0xfa, 0x12, 0xfa, 0x0e, 0x00, 0x1a, 0xf4, 0x1f, 0xf0, 0x21, 0xe7, + 0x21, 0xea, 0x25, 0xe4, 0x27, 0xe2, 0x2a, 0xe2, 0x2f, 0xd6, 0x2d, 0xdc, 0x31, 0xde, 0x29, 0xef, + 0x20, 0x09, 0x45, 0xb9, 0x3f, 0xc1, 0x42, 0xc0, 0x4d, 0xb6, 0x36, 0xd9, 0x34, 0xdd, 0x29, 0xf6, + 0x24, 0x00, 0x28, 0xff, 0x1e, 0x0e, 0x1c, 0x1a, 0x17, 0x25, 0x0c, 0x37, 0x0b, 0x41, 0x25, 0xdf, + 0x27, 0xdc, 0x28, 0xdb, 0x26, 0xe2, 0x2e, 0xdf, 0x2a, 0xe2, 0x28, 0xe8, 0x31, 0xe3, 0x26, 0xf4, + 0x28, 0xf6, 0x26, 0xfd, 0x2e, 0xfb, 0x1f, 0x14, 0x1d, 0x1e, 0x19, 0x2c, 0x0c, 0x30, 0x0b, 0x31, + 0x1a, 0x2d, 0x16, 0x16, 0x17, 0x16, 0x1b, 0x15, 0x21, 0x14, 0x1a, 0x1c, 0x1e, 0x18, 0x1b, 0x22, + 0x12, 0x2a, 0x19, 0x27, 0x12, 0x32, 0x0c, 0x46, 0x15, 0x36, 0x0e, 0x47, 0x0b, 0x53, 0x19, 0x20, + 0x15, 0x31, 0x15, 0x36, 0xfb, 0x55, 0xfa, 0x51, 0xf6, 0x4d, 0xf9, 0x51, 0xef, 0x50, 0xee, 0x49, + 0xfc, 0x4a, 0xf6, 0x53, 0xf7, 0x47, 0xf7, 0x43, 0xff, 0x3d, 0xf8, 0x42, 0xf2, 0x42, 0x00, 0x3b, + 0x02, 0x3b, 0x11, 0xf6, 0x20, 0xf3, 0x2a, 0xf7, 0x31, 0xfb, 0x35, 0x00, 0x40, 0x03, 0x44, 0x0a, + 0x42, 0x1b, 0x2f, 0x39, 0xfb, 0x47, 0x00, 0x18, 0xff, 0x24, 0xfe, 0x2a, 0xfe, 0x34, 0xf7, 0x39, + 0xfa, 0x3f, 0xfc, 0x41, 0xfc, 0x43, 0xf9, 0x52, 0xfd, 0x51, 0xfd, 0x4c, 0xf9, 0x48, 0xfa, 0x4e, + 0xf4, 0x48, 0xf2, 0x44, 0xfd, 0x46, 0xfa, 0x4c, 0xfb, 0x42, 0xfb, 0x3e, 0x00, 0x39, 0xfc, 0x3d, + 0xf7, 0x3c, 0x01, 0x36, 0x02, 0x3a, 0x11, 0xf6, 0x20, 0xf3, 0x2a, 0xf7, 0x31, 0xfb, 0x35, 0x00, + 0x40, 0x03, 0x44, 0x0a, 0x42, 0x1b, 0x2f, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x14, 0xf1, 0x02, 0x36, 0x03, 0x4a, 0x14, 0xf1, 0x02, 0x36, 0x03, 0x4a, 0xe4, 0x7f, 0xe9, 0x68, + 0xfa, 0x35, 0xff, 0x36, 0x07, 0x33, 0x1d, 0x10, 0x19, 0x00, 0x0e, 0x00, 0xf6, 0x33, 0xfd, 0x3e, + 0xe5, 0x63, 0x1a, 0x10, 0xfc, 0x55, 0xe8, 0x66, 0x05, 0x39, 0x06, 0x39, 0xef, 0x49, 0x0e, 0x39, + 0x14, 0x28, 0x14, 0x0a, 0x1d, 0x00, 0x36, 0x00, 0x25, 0x2a, 0x0c, 0x61, 0xe0, 0x7f, 0xea, 0x75, + 0xfe, 0x4a, 0xfc, 0x55, 0xe8, 0x66, 0x05, 0x39, 0xfa, 0x5d, 0xf2, 0x58, 0xfa, 0x2c, 0x04, 0x37, + 0xf5, 0x59, 0xf1, 0x67, 0xeb, 0x74, 0x13, 0x39, 0x14, 0x3a, 0x04, 0x54, 0x06, 0x60, 0x01, 0x3f, + 0xfb, 0x55, 0xf3, 0x6a, 0x05, 0x3f, 0x06, 0x4b, 0xfd, 0x5a, 0xff, 0x65, 0x03, 0x37, 0xfc, 0x4f, + 0xfe, 0x4b, 0xf4, 0x61, 0xf9, 0x32, 0x01, 0x3c, 0x00, 0x29, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f, + 0xf7, 0x53, 0x04, 0x56, 0x00, 0x61, 0xf9, 0x48, 0x0d, 0x29, 0x03, 0x3e, 0x07, 0x22, 0xf7, 0x58, + 0xec, 0x7f, 0xdc, 0x7f, 0xef, 0x5b, 0xf2, 0x5f, 0xe7, 0x54, 0xe7, 0x56, 0xf4, 0x59, 0xef, 0x5b, + 0xe1, 0x7f, 0xf2, 0x4c, 0xee, 0x67, 0xf3, 0x5a, 0xdb, 0x7f, 0x0b, 0x50, 0x05, 0x4c, 0x02, 0x54, + 0x05, 0x4e, 0xfa, 0x37, 0x04, 0x3d, 0xf2, 0x53, 0xdb, 0x7f, 0xfb, 0x4f, 0xf5, 0x68, 0xf5, 0x5b, + 0xe2, 0x7f, 0x00, 0x41, 0xfe, 0x4f, 0x00, 0x48, 0xfc, 0x5c, 0xfa, 0x38, 0x03, 0x44, 0xf8, 0x47, + 0xf3, 0x62, 0xfc, 0x56, 0xf4, 0x58, 0xfb, 0x52, 0xfd, 0x48, 0xfc, 0x43, 0xf8, 0x48, 0xf0, 0x59, + 0xf7, 0x45, 0xff, 0x3b, 0x05, 0x42, 0x04, 0x39, 0xfc, 0x47, 0xfe, 0x47, 0x02, 0x3a, 0xff, 0x4a, + 0xfc, 0x2c, 0xff, 0x45, 0x00, 0x3e, 0xf9, 0x33, 0xfc, 0x2f, 0xfa, 0x2a, 0xfd, 0x29, 0xfa, 0x35, + 0x08, 0x4c, 0xf7, 0x4e, 0xf5, 0x53, 0x09, 0x34, 0x00, 0x43, 0xfb, 0x5a, 0x01, 0x43, 0xf1, 0x48, + 0xfb, 0x4b, 0xf8, 0x50, 0xeb, 0x53, 0xeb, 0x40, 0xf3, 0x1f, 0xe7, 0x40, 0xe3, 0x5e, 0x09, 0x4b, + 0x11, 0x3f, 0xf8, 0x4a, 0xfb, 0x23, 0xfe, 0x1b, 0x0d, 0x5b, 0x03, 0x41, 0xf9, 0x45, 0x08, 0x4d, + 0xf6, 0x42, 0x03, 0x3e, 0xfd, 0x44, 0xec, 0x51, 0x00, 0x1e, 0x01, 0x07, 0xfd, 0x17, 0xeb, 0x4a, + 0x10, 0x42, 0xe9, 0x7c, 0x11, 0x25, 0x2c, 0xee, 0x32, 0xde, 0xea, 0x7f, 0x04, 0x27, 0x00, 0x2a, + 0x07, 0x22, 0x0b, 0x1d, 0x08, 0x1f, 0x06, 0x25, 0x07, 0x2a, 0x03, 0x28, 0x08, 0x21, 0x0d, 0x2b, + 0x0d, 0x24, 0x04, 0x2f, 0x03, 0x37, 0x02, 0x3a, 0x06, 0x3c, 0x08, 0x2c, 0x0b, 0x2c, 0x0e, 0x2a, + 0x07, 0x30, 0x04, 0x38, 0x04, 0x34, 0x0d, 0x25, 0x09, 0x31, 0x13, 0x3a, 0x0a, 0x30, 0x0c, 0x2d, + 0x00, 0x45, 0x14, 0x21, 0x08, 0x3f, 0x23, 0xee, 0x21, 0xe7, 0x1c, 0xfd, 0x18, 0x0a, 0x1b, 0x00, + 0x22, 0xf2, 0x34, 0xd4, 0x27, 0xe8, 0x13, 0x11, 0x1f, 0x19, 0x24, 0x1d, 0x18, 0x21, 0x22, 0x0f, + 0x1e, 0x14, 0x16, 0x49, 0x14, 0x22, 0x13, 0x1f, 0x1b, 0x2c, 0x13, 0x10, 0x0f, 0x24, 0x0f, 0x24, + 0x15, 0x1c, 0x19, 0x15, 0x1e, 0x14, 0x1f, 0x0c, 0x1b, 0x10, 0x18, 0x2a, 0x00, 0x5d, 0x0e, 0x38, + 0x0f, 0x39, 0x1a, 0x26, 0xe8, 0x7f, 0xe8, 0x73, 0xea, 0x52, 0xf7, 0x3e, 0x00, 0x35, 0x00, 0x3b, + 0xf2, 0x55, 0xf3, 0x59, 0xf3, 0x5e, 0xf5, 0x5c, 0xe3, 0x7f, 0xeb, 0x64, 0xf2, 0x39, 0xf4, 0x43, + 0xf5, 0x47, 0xf6, 0x4d, 0xeb, 0x55, 0xf0, 0x58, 0xe9, 0x68, 0xf1, 0x62, 0xdb, 0x7f, 0xf6, 0x52, + 0xf8, 0x30, 0xf8, 0x3d, 0xf8, 0x42, 0xf9, 0x46, 0xf2, 0x4b, 0xf6, 0x4f, 0xf7, 0x53, 0xf4, 0x5c, + 0xee, 0x6c, 0xfc, 0x4f, 0xea, 0x45, 0xf0, 0x4b, 0xfe, 0x3a, 0x01, 0x3a, 0xf3, 0x4e, 0xf7, 0x53, + 0xfc, 0x51, 0xf3, 0x63, 0xf3, 0x51, 0xfa, 0x26, 0xf3, 0x3e, 0xfa, 0x3a, 0xfe, 0x3b, 0xf0, 0x49, + 0xf6, 0x4c, 0xf3, 0x56, 0xf7, 0x53, 0xf6, 0x57, 0x00, 0x00, 0xea, 0x7f, 0xe7, 0x7f, 0xe7, 0x78, + 0xe5, 0x7f, 0xed, 0x72, 0xe9, 0x75, 0xe7, 0x76, 0xe6, 0x75, 0xe8, 0x71, 0xe4, 0x76, 0xe1, 0x78, + 0xdb, 0x7c, 0xf6, 0x5e, 0xf1, 0x66, 0xf6, 0x63, 0xf3, 0x6a, 0xce, 0x7f, 0xfb, 0x5c, 0x11, 0x39, + 0xfb, 0x56, 0xf3, 0x5e, 0xf4, 0x5b, 0xfe, 0x4d, 0x00, 0x47, 0xff, 0x49, 0x04, 0x40, 0xf9, 0x51, + 0x05, 0x40, 0x0f, 0x39, 0x01, 0x43, 0x00, 0x44, 0xf6, 0x43, 0x01, 0x44, 0x00, 0x4d, 0x02, 0x40, + 0x00, 0x44, 0xfb, 0x4e, 0x07, 0x37, 0x05, 0x3b, 0x02, 0x41, 0x0e, 0x36, 0x0f, 0x2c, 0x05, 0x3c, + 0x02, 0x46, 0xfe, 0x4c, 0xee, 0x56, 0x0c, 0x46, 0x05, 0x40, 0xf4, 0x46, 0x0b, 0x37, 0x05, 0x38, + 0x00, 0x45, 0x02, 0x41, 0xfa, 0x4a, 0x05, 0x36, 0x07, 0x36, 0xfa, 0x4c, 0xf5, 0x52, 0xfe, 0x4d, + 0xfe, 0x4d, 0x19, 0x2a, 0x11, 0xf3, 0x10, 0xf7, 0x11, 0xf4, 0x1b, 0xeb, 0x25, 0xe2, 0x29, 0xd8, + 0x2a, 0xd7, 0x30, 0xd1, 0x27, 0xe0, 0x2e, 0xd8, 0x34, 0xcd, 0x2e, 0xd7, 0x34, 0xd9, 0x2b, 0xed, + 0x20, 0x0b, 0x3d, 0xc9, 0x38, 0xd2, 0x3e, 0xce, 0x51, 0xbd, 0x2d, 0xec, 0x23, 0xfe, 0x1c, 0x0f, + 0x22, 0x01, 0x27, 0x01, 0x1e, 0x11, 0x14, 0x26, 0x12, 0x2d, 0x0f, 0x36, 0x00, 0x4f, 0x24, 0xf0, + 0x25, 0xf2, 0x25, 0xef, 0x20, 0x01, 0x22, 0x0f, 0x1d, 0x0f, 0x18, 0x19, 0x22, 0x16, 0x1f, 0x10, + 0x23, 0x12, 0x1f, 0x1c, 0x21, 0x29, 0x24, 0x1c, 0x1b, 0x2f, 0x15, 0x3e, 0x12, 0x1f, 0x13, 0x1a, + 0x24, 0x18, 0x18, 0x17, 0x1b, 0x10, 0x18, 0x1e, 0x1f, 0x1d, 0x16, 0x29, 0x16, 0x2a, 0x10, 0x3c, + 0x0f, 0x34, 0x0e, 0x3c, 0x03, 0x4e, 0xf0, 0x7b, 0x15, 0x35, 0x16, 0x38, 0x19, 0x3d, 0x15, 0x21, + 0x13, 0x32, 0x11, 0x3d, 0xfd, 0x4e, 0xf8, 0x4a, 0xf7, 0x48, 0xf6, 0x48, 0xee, 0x4b, 0xf4, 0x47, + 0xf5, 0x3f, 0xfb, 0x46, 0xef, 0x4b, 0xf2, 0x48, 0xf0, 0x43, 0xf8, 0x35, 0xf2, 0x3b, 0xf7, 0x34, + 0xf5, 0x44, 0x09, 0xfe, 0x1e, 0xf6, 0x1f, 0xfc, 0x21, 0xff, 0x21, 0x07, 0x1f, 0x0c, 0x25, 0x17, + 0x1f, 0x26, 0x14, 0x40, 0xf7, 0x47, 0xf9, 0x25, 0xf8, 0x2c, 0xf5, 0x31, 0xf6, 0x38, 0xf4, 0x3b, + 0xf8, 0x3f, 0xf7, 0x43, 0xfa, 0x44, 0xf6, 0x4f, 0xfd, 0x4e, 0xf8, 0x4a, 0xf7, 0x48, 0xf6, 0x48, + 0xee, 0x4b, 0xf4, 0x47, 0xf5, 0x3f, 0xfb, 0x46, 0xef, 0x4b, 0xf2, 0x48, 0xf0, 0x43, 0xf8, 0x35, + 0xf2, 0x3b, 0xf7, 0x34, 0xf5, 0x44, 0x09, 0xfe, 0x1e, 0xf6, 0x1f, 0xfc, 0x21, 0xff, 0x21, 0x07, + 0x1f, 0x0c, 0x25, 0x17, 0x1f, 0x26, 0x14, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x14, 0xf1, 0x02, 0x36, 0x03, 0x4a, 0x14, 0xf1, 0x02, 0x36, 0x03, 0x4a, 0xe4, 0x7f, 0xe9, 0x68, + 0xfa, 0x35, 0xff, 0x36, 0x07, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f, + 0xf7, 0x53, 0x04, 0x56, 0x00, 0x61, 0xf9, 0x48, 0x0d, 0x29, 0x03, 0x3e, 0x00, 0x0b, 0x01, 0x37, + 0x00, 0x45, 0xef, 0x7f, 0xf3, 0x66, 0x00, 0x52, 0xf9, 0x4a, 0xeb, 0x6b, 0xe5, 0x7f, 0xe1, 0x7f, + 0xe8, 0x7f, 0xee, 0x5f, 0xe5, 0x7f, 0xeb, 0x72, 0xe2, 0x7f, 0xef, 0x7b, 0xf4, 0x73, 0xf0, 0x7a, + 0xf5, 0x73, 0xf4, 0x3f, 0xfe, 0x44, 0xf1, 0x54, 0xf3, 0x68, 0xfd, 0x46, 0xf8, 0x5d, 0xf6, 0x5a, + 0xe2, 0x7f, 0xff, 0x4a, 0xfa, 0x61, 0xf9, 0x5b, 0xec, 0x7f, 0xfc, 0x38, 0xfb, 0x52, 0xf9, 0x4c, + 0xea, 0x7d, 0xf9, 0x5d, 0xf5, 0x57, 0xfd, 0x4d, 0xfb, 0x47, 0xfc, 0x3f, 0xfc, 0x44, 0xf4, 0x54, + 0xf9, 0x3e, 0xf9, 0x41, 0x08, 0x3d, 0x05, 0x38, 0xfe, 0x42, 0x01, 0x40, 0x00, 0x3d, 0xfe, 0x4e, + 0x01, 0x32, 0x07, 0x34, 0x0a, 0x23, 0x00, 0x2c, 0x0b, 0x26, 0x01, 0x2d, 0x00, 0x2e, 0x05, 0x2c, + 0x1f, 0x11, 0x01, 0x33, 0x07, 0x32, 0x1c, 0x13, 0x10, 0x21, 0x0e, 0x3e, 0xf3, 0x6c, 0xf1, 0x64, + 0xf3, 0x65, 0xf3, 0x5b, 0xf4, 0x5e, 0xf6, 0x58, 0xf0, 0x54, 0xf6, 0x56, 0xf9, 0x53, 0xf3, 0x57, + 0xed, 0x5e, 0x01, 0x46, 0x00, 0x48, 0xfb, 0x4a, 0x12, 0x3b, 0xf8, 0x66, 0xf1, 0x64, 0x00, 0x5f, + 0xfc, 0x4b, 0x02, 0x48, 0xf5, 0x4b, 0xfd, 0x47, 0x0f, 0x2e, 0xf3, 0x45, 0x00, 0x3e, 0x00, 0x41, + 0x15, 0x25, 0xf1, 0x48, 0x09, 0x39, 0x10, 0x36, 0x00, 0x3e, 0x0c, 0x48, 0x18, 0x00, 0x0f, 0x09, + 0x08, 0x19, 0x0d, 0x12, 0x0f, 0x09, 0x0d, 0x13, 0x0a, 0x25, 0x0c, 0x12, 0x06, 0x1d, 0x14, 0x21, + 0x0f, 0x1e, 0x04, 0x2d, 0x01, 0x3a, 0x00, 0x3e, 0x07, 0x3d, 0x0c, 0x26, 0x0b, 0x2d, 0x0f, 0x27, + 0x0b, 0x2a, 0x0d, 0x2c, 0x10, 0x2d, 0x0c, 0x29, 0x0a, 0x31, 0x1e, 0x22, 0x12, 0x2a, 0x0a, 0x37, + 0x11, 0x33, 0x11, 0x2e, 0x00, 0x59, 0x1a, 0xed, 0x16, 0xef, 0x1a, 0xef, 0x1e, 0xe7, 0x1c, 0xec, + 0x21, 0xe9, 0x25, 0xe5, 0x21, 0xe9, 0x28, 0xe4, 0x26, 0xef, 0x21, 0xf5, 0x28, 0xf1, 0x29, 0xfa, + 0x26, 0x01, 0x29, 0x11, 0x1e, 0xfa, 0x1b, 0x03, 0x1a, 0x16, 0x25, 0xf0, 0x23, 0xfc, 0x26, 0xf8, + 0x26, 0xfd, 0x25, 0x03, 0x26, 0x05, 0x2a, 0x00, 0x23, 0x10, 0x27, 0x16, 0x0e, 0x30, 0x1b, 0x25, + 0x15, 0x3c, 0x0c, 0x44, 0x02, 0x61, 0xfd, 0x47, 0xfa, 0x2a, 0xfb, 0x32, 0xfd, 0x36, 0xfe, 0x3e, + 0x00, 0x3a, 0x01, 0x3f, 0xfe, 0x48, 0xff, 0x4a, 0xf7, 0x5b, 0xfb, 0x43, 0xfb, 0x1b, 0xfd, 0x27, + 0xfe, 0x2c, 0x00, 0x2e, 0xf0, 0x40, 0xf8, 0x44, 0xf6, 0x4e, 0xfa, 0x4d, 0xf6, 0x56, 0xf4, 0x5c, + 0xf1, 0x37, 0xf6, 0x3c, 0xfa, 0x3e, 0xfc, 0x41, 0xf4, 0x49, 0xf8, 0x4c, 0xf9, 0x50, 0xf7, 0x58, + 0xef, 0x6e, 0xf5, 0x61, 0xec, 0x54, 0xf5, 0x4f, 0xfa, 0x49, 0xfc, 0x4a, 0xf3, 0x56, 0xf3, 0x60, + 0xf5, 0x61, 0xed, 0x75, 0xf8, 0x4e, 0xfb, 0x21, 0xfc, 0x30, 0xfe, 0x35, 0xfd, 0x3e, 0xf3, 0x47, + 0xf6, 0x4f, 0xf4, 0x56, 0xf3, 0x5a, 0xf2, 0x61, 0x00, 0x00, 0xfa, 0x5d, 0xfa, 0x54, 0xf8, 0x4f, + 0x00, 0x42, 0xff, 0x47, 0x00, 0x3e, 0xfe, 0x3c, 0xfe, 0x3b, 0xfb, 0x4b, 0xfd, 0x3e, 0xfc, 0x3a, + 0xf7, 0x42, 0xff, 0x4f, 0x00, 0x47, 0x03, 0x44, 0x0a, 0x2c, 0xf9, 0x3e, 0x0f, 0x24, 0x0e, 0x28, + 0x10, 0x1b, 0x0c, 0x1d, 0x01, 0x2c, 0x14, 0x24, 0x12, 0x20, 0x05, 0x2a, 0x01, 0x30, 0x0a, 0x3e, + 0x11, 0x2e, 0x09, 0x40, 0xf4, 0x68, 0xf5, 0x61, 0xf0, 0x60, 0xf9, 0x58, 0xf8, 0x55, 0xf9, 0x55, + 0xf7, 0x55, 0xf3, 0x58, 0x04, 0x42, 0xfd, 0x4d, 0xfd, 0x4c, 0xfa, 0x4c, 0x0a, 0x3a, 0xff, 0x4c, + 0xff, 0x53, 0xf9, 0x63, 0xf2, 0x5f, 0x02, 0x5f, 0x00, 0x4c, 0xfb, 0x4a, 0x00, 0x46, 0xf5, 0x4b, + 0x01, 0x44, 0x00, 0x41, 0xf2, 0x49, 0x03, 0x3e, 0x04, 0x3e, 0xff, 0x44, 0xf3, 0x4b, 0x0b, 0x37, + 0x05, 0x40, 0x0c, 0x46, 0x0f, 0x06, 0x06, 0x13, 0x07, 0x10, 0x0c, 0x0e, 0x12, 0x0d, 0x0d, 0x0b, + 0x0d, 0x0f, 0x0f, 0x10, 0x0c, 0x17, 0x0d, 0x17, 0x0f, 0x14, 0x0e, 0x1a, 0x0e, 0x2c, 0x11, 0x28, + 0x11, 0x2f, 0x18, 0x11, 0x15, 0x15, 0x19, 0x16, 0x1f, 0x1b, 0x16, 0x1d, 0x13, 0x23, 0x0e, 0x32, + 0x0a, 0x39, 0x07, 0x3f, 0xfe, 0x4d, 0xfc, 0x52, 0xfd, 0x5e, 0x09, 0x45, 0xf4, 0x6d, 0x24, 0xdd, + 0x24, 0xde, 0x20, 0xe6, 0x25, 0xe2, 0x2c, 0xe0, 0x22, 0xee, 0x22, 0xf1, 0x28, 0xf1, 0x21, 0xf9, + 0x23, 0xfb, 0x21, 0x00, 0x26, 0x02, 0x21, 0x0d, 0x17, 0x23, 0x0d, 0x3a, 0x1d, 0xfd, 0x1a, 0x00, + 0x16, 0x1e, 0x1f, 0xf9, 0x23, 0xf1, 0x22, 0xfd, 0x22, 0x03, 0x24, 0xff, 0x22, 0x05, 0x20, 0x0b, + 0x23, 0x05, 0x22, 0x0c, 0x27, 0x0b, 0x1e, 0x1d, 0x22, 0x1a, 0x1d, 0x27, 0x13, 0x42, 0x1f, 0x15, + 0x1f, 0x1f, 0x19, 0x32, 0xef, 0x78, 0xec, 0x70, 0xee, 0x72, 0xf5, 0x55, 0xf1, 0x5c, 0xf2, 0x59, + 0xe6, 0x47, 0xf1, 0x51, 0xf2, 0x50, 0x00, 0x44, 0xf2, 0x46, 0xe8, 0x38, 0xe9, 0x44, 0xe8, 0x32, + 0xf5, 0x4a, 0x17, 0xf3, 0x1a, 0xf3, 0x28, 0xf1, 0x31, 0xf2, 0x2c, 0x03, 0x2d, 0x06, 0x2c, 0x22, + 0x21, 0x36, 0x13, 0x52, 0xfd, 0x4b, 0xff, 0x17, 0x01, 0x22, 0x01, 0x2b, 0x00, 0x36, 0xfe, 0x37, + 0x00, 0x3d, 0x01, 0x40, 0x00, 0x44, 0xf7, 0x5c, 0xf2, 0x6a, 0xf3, 0x61, 0xf1, 0x5a, 0xf4, 0x5a, + 0xee, 0x58, 0xf6, 0x49, 0xf7, 0x4f, 0xf2, 0x56, 0xf6, 0x49, 0xf6, 0x46, 0xf6, 0x45, 0xfb, 0x42, + 0xf7, 0x40, 0xfb, 0x3a, 0x02, 0x3b, 0x15, 0xf6, 0x18, 0xf5, 0x1c, 0xf8, 0x1c, 0xff, 0x1d, 0x03, + 0x1d, 0x09, 0x23, 0x14, 0x1d, 0x24, 0x0e, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; diff --git a/mpp/hal/rkdec/h264d/hal_h264d_reg.h b/mpp/hal/rkdec/h264d/hal_h264d_reg.h new file mode 100644 index 00000000..17cd3f0a --- /dev/null +++ b/mpp/hal/rkdec/h264d/hal_h264d_reg.h @@ -0,0 +1,307 @@ +/* +* +* 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. +*/ + + +#ifndef __HAL_H264D_REG_H__ +#define __HAL_H264D_REG_H__ + +#include "mpp_hal.h" + +typedef struct h264_mmu_t { + RK_U32 mmu_dte_addr; + struct { + RK_U32 pageing_enabled : 1; + RK_U32 page_fault_active : 1; + RK_U32 stail_active : 1; + RK_U32 mmu_idle : 1; + RK_U32 replay_buffer_empty1 : 1; + RK_U32 page_fault_is_write : 1; + RK_U32 page_fault_bus_id : 5; + RK_U32 reserve : 8; + //RK_U32 field0000 : 1; + } mmu_status; + struct { + RK_U32 mmu_cmd : 3; + RK_U32 field0000 : 1; + } mmu_cmd; + + RK_U32 page_fault_addr; + RK_U32 mmu_zap_one_line; + struct int_rawstat { + RK_U32 page_fault : 1; + RK_U32 read_bus_error : 1; + } raw_stat; + struct int_clear { + RK_U32 page_fault : 1; + RK_U32 read_bus_error : 1; + } clear; + struct int_mask { + RK_U32 page_fault : 1; + RK_U32 read_bus_error : 1; + } mask; + struct int_status { + RK_U32 page_fault : 1; + RK_U32 read_bus_error : 1; + } status; + RK_U32 mmu_auto_gating : 1; +} H264_MMU_t; + +typedef struct h264_cache_t { + struct st_version { + RK_U32 version_minor : 8; + RK_U32 version_major : 8; + RK_U32 product_id : 16; + } version; + struct st_size { + RK_U32 line_size : 8; + RK_U32 associativity : 8; + RK_U32 cache_size : 8; + RK_U32 external_bus_width : 8; + } size; + struct st_status { + RK_U32 cmd_busy : 1; + RK_U32 data_busy : 1; + } status; + struct st_command { + RK_U32 command : 4; + RK_U32 sw_addrb_sel : 2; + } command; + RK_U32 clear_page; + RK_U32 max_reads : 5; + struct st_enable { + RK_U32 permit_cacheable_access : 1; + RK_U32 permit_cach_read_allocate : 1; + RK_U32 sw_readbuffer_counter_reject_en : 1; + RK_U32 sw_cache_clk_disgate : 1; + RK_U32 sw_cache_linsize : 1; + } enable; + RK_U32 perfcnt_src0; + RK_U32 perfcnt_val0; + RK_U32 perfcnt_src1; + RK_U32 perfcnt_val1; +} H264_CACHE_t; + +typedef struct h264_regs_t { + struct { + RK_U32 minor_ver : 8; + RK_U32 level : 1; + RK_U32 dec_support : 3; + RK_U32 profile : 1; + RK_U32 reserve0 : 1; + RK_U32 codec_flag : 1; + RK_U32 reserve1 : 1; + RK_U32 prod_num : 16; + } swreg0_id; + struct { + RK_U32 sw_dec_e : 1;//0 + RK_U32 sw_dec_clkgate_e : 1; // 1 + RK_U32 reserve0 : 1;// 2 + RK_U32 sw_timeout_mode : 1; // 3 + RK_U32 sw_dec_irq_dis : 1;//4 // 4 + RK_U32 sw_dec_timeout_e : 1; //5 + RK_U32 sw_buf_empty_en : 1; // 6 + RK_U32 sw_stmerror_waitdecfifo_empty : 1; // 7 + RK_U32 sw_dec_irq : 1; // 8 + RK_U32 sw_dec_irq_raw : 1; // 9 + RK_U32 reserve2 : 2; + RK_U32 sw_dec_rdy_sta : 1; //12 + RK_U32 sw_dec_bus_sta : 1; //13 + RK_U32 sw_dec_error_sta : 1; // 14 + RK_U32 sw_dec_timeout_sta : 1; //15 + RK_U32 sw_dec_empty_sta : 1; // 16 + RK_U32 sw_colmv_ref_error_sta : 1; // 17 + RK_U32 sw_cabu_end_sta : 1; // 18 + RK_U32 sw_h264orvp9_error_mode : 1; //19 + RK_U32 sw_softrst_en_p : 1; //20 + RK_U32 sw_force_softreset_valid : 1; //21 + RK_U32 sw_softreset_rdy : 1; // 22 + } swreg1_int; + struct { + RK_U32 sw_in_endian : 1; + RK_U32 sw_in_swap32_e : 1; + RK_U32 sw_in_swap64_e : 1; + RK_U32 sw_str_endian : 1; + RK_U32 sw_str_swap32_e : 1; + RK_U32 sw_str_swap64_e : 1; + RK_U32 sw_out_endian : 1; + RK_U32 sw_out_swap32_e : 1; + RK_U32 sw_out_cbcr_swap : 1; + RK_U32 reserve0 : 1; + RK_U32 sw_rlc_mode_direct_write : 1; + RK_U32 sw_rlc_mode : 1; + RK_U32 sw_strm_start_bit : 7; + RK_U32 reserve1 : 1; + RK_U32 sw_dec_mode : 2; + RK_U32 reserve2 : 2; + RK_U32 sw_h264_rps_mode : 1; + RK_U32 sw_h264_stream_mode : 1; + RK_U32 sw_h264_stream_lastpacket : 1; + RK_U32 sw_h264_firstslice_flag : 1; + RK_U32 sw_h264_frame_orslice : 1; + RK_U32 sw_buspr_slot_disable : 1; + } swreg2_sysctrl; + struct { + RK_U32 sw_y_hor_virstride : 9; + RK_U32 reserve : 2; + RK_U32 sw_slice_num_highbit : 1; + RK_U32 sw_uv_hor_virstride : 9; + RK_U32 sw_slice_num_lowbits : 11; + } swreg3_picpar; + struct { + RK_U32 reverse0 : 4; + RK_U32 sw_strm_rlc_base : 28; + } swreg4_strm_rlc_base; + struct { + RK_U32 sw_stream_len : 27; + } swreg5_stream_rlc_len; + struct { + RK_U32 reverse0 : 4; + RK_U32 sw_cabactbl_base : 28; + } swreg6_cabactbl_prob_base; + struct { + RK_U32 reverse0 : 4; + RK_U32 sw_decout_base : 28; + } swreg7_decout_base; + struct { + RK_U32 sw_y_virstride : 20; + } swreg8_y_virstride; + struct { + RK_U32 sw_yuv_virstride : 21; + } swreg9_yuv_virstride; + struct { + RK_U32 sw_ref_field : 1; + RK_U32 sw_ref_topfield_used : 1; + RK_U32 sw_ref_botfield_used : 1; + RK_U32 sw_ref_colmv_use_flag : 1; + RK_U32 sw_refer_base : 28; + } swreg10_24_refer0_14_base[15]; + RK_U32 swreg25_39_refer0_14_poc[15]; + struct { + RK_U32 sw_cur_poc : 32; + } swreg40_cur_poc; + struct { + RK_U32 reserve : 3; + RK_U32 sw_rlcwrite_base : 29; + } swreg41_rlcwrite_base; + struct { + RK_U32 reserve : 4; + RK_U32 sw_pps_base : 28; + } swreg42_pps_base; + struct swreg_sw_rps_base { + RK_U32 reserve : 4; + RK_U32 sw_rps_base : 28; + } swreg43_rps_base; + struct swreg_strmd_error_e { + RK_U32 sw_strmd_error_e : 28; + RK_U32 reserve : 4; + } swreg44_strmd_error_en; + struct { + RK_U32 sw_strmd_error_status : 28; + RK_U32 sw_colmv_error_ref_picidx : 4; + } swreg45_strmd_error_status; + struct { + RK_U32 sw_strmd_error_ctu_xoffset : 8; + RK_U32 sw_strmd_error_ctu_yoffset : 8; + RK_U32 sw_streamfifo_space2full : 7; + RK_U32 reserve : 1; + RK_U32 sw_vp9_error_ctu0_en : 1; + } swreg46_strmd_error_ctu; + struct { + RK_U32 sw_saowr_xoffet : 9; + RK_U32 reserve : 7; + RK_U32 sw_saowr_yoffset : 10; + } swreg47_sao_ctu_position; + struct { + RK_U32 sw_ref_field : 1; + RK_U32 sw_ref_topfield_used : 1; + RK_U32 sw_ref_botfield_used : 1; + RK_U32 sw_ref_colmv_use_flag : 1; + RK_U32 sw_refer_base : 28; + } swreg48_refer15_base; + RK_U32 swreg49_63_refer15_29_poc[15]; + struct { + RK_U32 sw_performance_cycle : 32; + } swreg64_performance_cycle; + struct { + RK_U32 sw_axi_ddr_rdata : 32; + } swreg65_axi_ddr_rdata; + struct { + RK_U32 sw_axi_ddr_rdata : 32; + } swreg66_axi_ddr_wdata; + struct { + RK_U32 sw_busifd_resetn : 1; + RK_U32 sw_cabac_resetn : 1; + RK_U32 sw_dec_ctrl_resetn : 1; + RK_U32 sw_transd_resetn : 1; + RK_U32 sw_intra_resetn : 1; + RK_U32 sw_inter_resetn : 1; + RK_U32 sw_recon_resetn : 1; + RK_U32 sw_filer_resetn : 1; + } swreg67_fpgadebug_reset; + struct { + RK_U32 perf_cnt0_sel : 6; + RK_U32 reserve0 : 2; + RK_U32 perf_cnt1_sel : 6; + RK_U32 reserve1 : 2; + RK_U32 perf_cnt2_sel : 6; + } swreg68_performance_sel; + struct { + RK_U32 perf_cnt0 : 32; + } swreg69_performance_cnt0; + struct { + RK_U32 perf_cnt1 : 32; + } swreg70_performance_cnt1; + struct { + RK_U32 perf_cnt2 : 32; + } swreg71_performance_cnt2; + RK_U32 swreg72_refer30_poc; + RK_U32 swreg73_refer31_poc; + struct { + RK_U32 sw_h264_cur_poc1 : 32; + } swreg74_h264_cur_poc1; + struct { + RK_U32 reserve : 4; + RK_U32 sw_errorinfo_base : 28; + } swreg75_h264_errorinfo_base; + struct { + RK_U32 sw_slicedec_num : 14; + RK_U32 reserve : 1; + RK_U32 sw_strmd_detect_error_flag : 1; + RK_U32 sw_error_packet_num : 14; + } swreg76_h264_errorinfo_num; + struct { + RK_U32 sw_h264_error_en_highbits : 30; + RK_U32 reserve : 2; + } swreg77_h264_error_e; + RK_U32 compare_len; +} H264_REGS_t; + + + +#ifdef __cplusplus +extern "C" { +#endif + + extern const RK_U8 H264_Cabac_table[]; + + + +#ifdef __cplusplus +} +#endif + +#endif /*__HAL_H264D_REG_H__*/ diff --git a/mpp/test/h264d_test.c b/mpp/test/h264d_test.c index 7a7c9127..24d486a5 100644 --- a/mpp/test/h264d_test.c +++ b/mpp/test/h264d_test.c @@ -43,7 +43,7 @@ static MPP_RET manual_set_env(void) #if defined(_MSC_VER) mpp_env_set_u32("h264d_log_help", 1 ); mpp_env_set_u32("h264d_log_show", 1 ); - mpp_env_set_u32("h264d_log_ctrl", 0xFFFB ); + mpp_env_set_u32("h264d_log_ctrl", 0x007B ); mpp_env_set_u32("h264d_log_level", 5 ); mpp_env_set_u32("h264d_log_decframe", 0 ); mpp_env_set_u32("h264d_log_begframe", 0 ); @@ -74,15 +74,16 @@ static MPP_RET decoder_deinit(MppDec *pApi) static MPP_RET decoder_init(MppDec *pApi) { - MPP_RET ret = MPP_NOK; + MPP_RET ret = MPP_ERR_UNKNOW; MppParserInitCfg parser_cfg; MppHalCfg hal_cfg; // set decoder pApi->parser_api = &api_h264d_parser; - MEM_CHECK(pApi->parser_ctx = mpp_calloc_size(void, pApi->parser_api->ctx_size)); + pApi->parser_ctx = mpp_calloc_size(void, pApi->parser_api->ctx_size); + MEM_CHECK(ret, pApi->parser_ctx); // malloc slot FUN_CHECK(ret = mpp_buf_slot_init(&pApi->slots)); - MEM_CHECK(pApi->slots); + MEM_CHECK(ret, pApi->slots); // init parser part memset(&parser_cfg, 0, sizeof(parser_cfg)); parser_cfg.slots = pApi->slots; @@ -106,13 +107,13 @@ __FAILED: int main(int argc, char **argv) { - MPP_RET ret = MPP_OK; + MPP_RET ret = MPP_ERR_UNKNOW; + InputParams *pIn = mpp_calloc(InputParams, 1); MppDec *pApi = mpp_calloc(MppDec, 1); MppPacketImpl *pkt = mpp_calloc_size(MppPacketImpl, sizeof(MppPacketImpl)); HalTask *task = mpp_calloc_size(HalTask, sizeof(HalTask)); - - MEM_CHECK(pIn && pApi && pkt && task); + MEM_CHECK(ret, pIn && pApi && pkt && task); mpp_log("== test start == \n"); // set debug mode FUN_CHECK(ret = manual_set_env()); @@ -124,25 +125,23 @@ int main(int argc, char **argv) // init FUN_CHECK(ret = decoder_init(pApi)); do { - //if (!pkt->size) + if (!pkt->size) { - FUN_CHECK(ret = h264d_read_one_frame(pIn, (MppPacket)pkt)); - mpp_log("---- decoder, Frame_no = %d \n", pIn->iFrmdecoded++); + FUN_CHECK(ret = h264d_read_one_frame(pIn, (MppPacket)pkt)); } FUN_CHECK(ret = pApi->parser_api->parse(pApi->parser_ctx, pkt, &task->dec)); if (((HalDecTask*)&task->dec)->valid) { - FUN_CHECK(ret = mpp_hal_reg_gen(pApi->hal_ctx, task)); - mpp_log("---- decoder, Frame_no = %d \n", pIn->iFrmdecoded++); - if (((MppPacketImpl *)pkt)->flag & MPP_PACKET_FLAG_EOS) { + FUN_CHECK(ret = mpp_hal_reg_gen(pApi->hal_ctx, task)); + //mpp_log("---- decoder, Frame_no = %d \n", pIn->iFrmdecoded); + //!< end of stream + if (!pkt->size && (pkt->flag & MPP_PACKET_FLAG_EOS)) { break; } - } - if (pIn->is_eof) { - break; + pIn->iFrmdecoded++; } } while (!pIn->iDecFrmNum || (pIn->iFrmdecoded < pIn->iDecFrmNum)); - mpp_log("== all test return == \n"); + mpp_log("+++++++ all test return +++++++ \n"); ret = MPP_OK; __FAILED: decoder_deinit(pApi);