unplugged-system/external/libavc/decoder/svc/isvcd_utils.c

909 lines
34 KiB
C

/******************************************************************************
*
* Copyright (C) 2022 The Android Open Source Project
*
* 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.
*
*****************************************************************************
* Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
*/
/**
*******************************************************************************
* @file
* isvcd_utils.c
*
* @brief
* Contains routines that handle of start and end of pic processing
*
* @author
* Kishore
*
* @remarks
* None
*
*******************************************************************************
*/
#include <string.h>
#include "ih264_typedefs.h"
#include "ithread.h"
#include "ih264d_deblocking.h"
#include "ih264d_parse_slice.h"
#include "ih264d_parse_cavlc.h"
#include "ih264d_dpb_manager.h"
#include "ih264d_defs.h"
#include "isvcd_structs.h"
#include "ih264d_mem_request.h"
#include "ih264_typedefs.h"
#include "ih264_macros.h"
#include "ih264_platform_macros.h"
#include "ih264d_tables.h"
#include "ih264d_debug.h"
#include "ih264d_mb_utils.h"
#include "ih264d_error_handler.h"
#include "ih264d_dpb_manager.h"
#include "ih264d_utils.h"
#include "ih264d_defs.h"
#include "ih264d_tables.h"
#include "ih264d_inter_pred.h"
#include "ih264d_dpb_manager.h"
#include "iv.h"
#include "ivd.h"
#include "ih264d_format_conv.h"
#include "ih264_error.h"
#include "ih264_disp_mgr.h"
#include "ih264_buf_mgr.h"
#include "ih264d_utils.h"
WORD32 ih264d_init_dec_mb_grp(dec_struct_t *ps_dec);
/*!
**************************************************************************
* \if Function name : isvcd_free_dynamic_bufs \endif
*
* \brief
* This function frees dynamic memory allocated by Decoder.
*
* \param ps_dec: Pointer to dec_struct_t.
*
* \return
* Returns i4_status as returned by MemManager.
*
**************************************************************************
*/
WORD16 isvcd_free_dynamic_bufs(svc_dec_lyr_struct_t *ps_svc_lyr_dec)
{
dec_struct_t *ps_dec = &ps_svc_lyr_dec->s_dec;
/* Free any avc dynamic buffers that are allocated */
ih264d_free_dynamic_bufs(ps_dec);
PS_DEC_ALIGNED_FREE(ps_dec, ps_svc_lyr_dec->pu1_crop_wnd_flag);
PS_DEC_ALIGNED_FREE(ps_dec, ps_svc_lyr_dec->ps_inter_lyr_mb_prms_base);
PS_DEC_ALIGNED_FREE(ps_dec, ps_svc_lyr_dec->ps_il_pred_mv_bank_buf_base);
PS_DEC_ALIGNED_FREE(ps_dec, ps_svc_lyr_dec->pi2_il_residual_resample_luma_base);
PS_DEC_ALIGNED_FREE(ps_dec, ps_svc_lyr_dec->pi2_il_residual_resample_chroma_base);
PS_DEC_ALIGNED_FREE(ps_dec, ps_svc_lyr_dec->ps_svc_frm_mb_info);
PS_DEC_ALIGNED_FREE(ps_dec, ps_svc_lyr_dec->pu2_frm_res_luma_csbp);
PS_DEC_ALIGNED_FREE(ps_dec, ps_svc_lyr_dec->pu1_svc_base_mode_flag);
return 0;
}
/*!
**************************************************************************
* \if Function name : isvcd_allocate_dynamic_bufs \endif
*
* \brief
* This function allocates memory required by Decoder.
*
* \param ps_dec: Pointer to dec_struct_t.
*
* \return
* Returns i4_status as returned by MemManager.
*
**************************************************************************
*/
WORD16 isvcd_allocate_dynamic_bufs(svc_dec_lyr_struct_t *ps_svc_lyr_dec)
{
dec_struct_t *ps_dec = &ps_svc_lyr_dec->s_dec;
WORD16 i16_status = 0;
UWORD8 uc_frmOrFld = (1 - ps_dec->ps_cur_sps->u1_frame_mbs_only_flag);
dec_seq_params_t *ps_sps = ps_dec->ps_cur_sps;
UWORD32 u4_total_mbs = ps_sps->u2_total_num_of_mbs << uc_frmOrFld;
WORD32 size;
void *pv_buf;
void *pv_mem_ctxt = ps_dec->pv_mem_ctxt;
size = u4_total_mbs;
i16_status = ih264d_allocate_dynamic_bufs(ps_dec);
if(i16_status != OK)
{
/* Free any dynamic buffers that are allocated */
ih264d_free_dynamic_bufs(ps_dec);
ps_dec->i4_error_code = IVD_MEM_ALLOC_FAILED;
return IVD_MEM_ALLOC_FAILED;
}
if(u4_total_mbs == 0)
{
return IVD_MEM_ALLOC_FAILED;
}
/* Allocate frame level mb info */
size = sizeof(dec_svc_mb_info_t) * u4_total_mbs;
pv_buf = ps_dec->pf_aligned_alloc(pv_mem_ctxt, 128, size);
RETURN_IF((NULL == pv_buf), IV_FAIL);
ps_svc_lyr_dec->ps_svc_frm_mb_info = pv_buf;
memset(ps_svc_lyr_dec->ps_svc_frm_mb_info, 0, size);
/* Allocate frame level residual luma csbp info */
size = sizeof(UWORD16) * u4_total_mbs;
pv_buf = ps_dec->pf_aligned_alloc(pv_mem_ctxt, 128, size);
RETURN_IF((NULL == pv_buf), IV_FAIL);
ps_svc_lyr_dec->pu2_frm_res_luma_csbp = pv_buf;
memset(ps_svc_lyr_dec->pu2_frm_res_luma_csbp, 0, size);
ps_svc_lyr_dec->i4_frm_res_luma_csbp_stride = ps_dec->u2_frm_wd_in_mbs;
/* Allocate frame level residual luma csbp info */
size = sizeof(UWORD8) * u4_total_mbs;
pv_buf = ps_dec->pf_aligned_alloc(pv_mem_ctxt, 128, size);
RETURN_IF((NULL == pv_buf), IV_FAIL);
ps_svc_lyr_dec->pu1_svc_base_mode_flag = pv_buf;
memset(ps_svc_lyr_dec->pu1_svc_base_mode_flag, 0, size);
ps_svc_lyr_dec->i4_frm_svc_base_mode_cabac_stride = ps_dec->u2_frm_wd_in_mbs;
ps_svc_lyr_dec->i4_frm_svc_base_mode_cabac_size = u4_total_mbs;
/* Allocate frame level crop windows flags */
size = sizeof(UWORD8) * u4_total_mbs;
pv_buf = ps_dec->pf_aligned_alloc(pv_mem_ctxt, 128, size);
RETURN_IF((NULL == pv_buf), IV_FAIL);
ps_svc_lyr_dec->pu1_crop_wnd_flag = pv_buf;
memset(ps_svc_lyr_dec->pu1_crop_wnd_flag, 0, size);
/**********************************/
/*Creation of Inter layer buffers */
/**********************************/
/* MB type buffer : one element per MB */
size = (ps_dec->u2_frm_wd_in_mbs + 2) * (ps_dec->u2_frm_ht_in_mbs + 2) *
sizeof(inter_lyr_mb_prms_t);
pv_buf = ps_dec->pf_aligned_alloc(pv_mem_ctxt, 128, size);
RETURN_IF((NULL == pv_buf), IV_FAIL);
memset(pv_buf, -1, size);
ps_svc_lyr_dec->ps_inter_lyr_mb_prms_base = pv_buf;
ps_svc_lyr_dec->u2_inter_lyr_mb_prms_stride = ps_dec->u2_frm_wd_in_mbs + 2;
ps_svc_lyr_dec->ps_inter_lyr_mb_prms_frm_start =
ps_svc_lyr_dec->ps_inter_lyr_mb_prms_base + 1 + ps_svc_lyr_dec->u2_inter_lyr_mb_prms_stride;
ps_svc_lyr_dec->u4_inter_lyr_mb_prms_size = (ps_dec->u2_frm_wd_in_mbs + 2) *
(ps_dec->u2_frm_ht_in_mbs + 2) *
sizeof(inter_lyr_mb_prms_t);
/* Luma Residual data at each layer : dafault 0*/
size = ((ps_dec->u2_pic_wd + 4) * (ps_dec->u2_pic_ht + 4)) * sizeof(WORD16);
pv_buf = ps_dec->pf_aligned_alloc(pv_mem_ctxt, 128, size);
RETURN_IF((NULL == pv_buf), IV_FAIL);
memset(pv_buf, 0, size);
ps_svc_lyr_dec->pi2_il_residual_resample_luma_base = pv_buf;
ps_svc_lyr_dec->u2_residual_resample_luma_stride = (ps_dec->u2_pic_wd + 4);
ps_svc_lyr_dec->pi2_il_residual_resample_mb_luma_frm_start =
ps_svc_lyr_dec->pi2_il_residual_resample_luma_base + 2 +
(2 * ps_svc_lyr_dec->u2_residual_resample_luma_stride);
ps_svc_lyr_dec->u4_residual_resample_luma_size =
((ps_dec->u2_pic_wd + 4) * (ps_dec->u2_pic_ht + 4)) * sizeof(WORD16);
/* Chroma Residual data at each layer : dafault 0*/
size = (((4 + ps_dec->u2_pic_wd) * ((4 + ps_dec->u2_pic_ht) >> 1)) * sizeof(WORD16));
pv_buf = ps_dec->pf_aligned_alloc(pv_mem_ctxt, 128, size);
RETURN_IF((NULL == pv_buf), IV_FAIL);
memset(pv_buf, 0, size);
ps_svc_lyr_dec->pi2_il_residual_resample_chroma_base = pv_buf;
ps_svc_lyr_dec->u2_residual_resample_chroma_stride = (ps_dec->u2_pic_wd + 4);
ps_svc_lyr_dec->pi2_il_residual_resample_mb_chroma_frm_start =
ps_svc_lyr_dec->pi2_il_residual_resample_chroma_base + 2 +
ps_svc_lyr_dec->u2_residual_resample_chroma_stride;
ps_svc_lyr_dec->u4_residual_resample_chroma_size =
(((4 + ps_dec->u2_pic_wd) * ((4 + ps_dec->u2_pic_ht) >> 1)) * sizeof(WORD16));
/* mv bank buffer : 16 elements per MB: each at 4x4 block level */
size = ((ps_dec->u2_pic_wd) * (ps_dec->u2_pic_ht >> 4)) * sizeof(mv_pred_t);
pv_buf = ps_dec->pf_aligned_alloc(pv_mem_ctxt, 128, size);
RETURN_IF((NULL == pv_buf), IV_FAIL);
memset(pv_buf, 0, size);
ps_svc_lyr_dec->ps_il_pred_mv_bank_buf_base = pv_buf;
/*syntax for SVC related bin ctxt tables*/
{
bin_ctxt_model_t *const p_cabac_ctxt_table_t = ps_dec->p_cabac_ctxt_table_t;
ps_svc_lyr_dec->ps_base_mode_flag = p_cabac_ctxt_table_t + CABAC_BASE_MODE_FLAG;
ps_svc_lyr_dec->ps_motion_prediction_flag_l0 = p_cabac_ctxt_table_t + CABAC_MOT_PRED_FLAG0;
ps_svc_lyr_dec->ps_motion_prediction_flag_l1 = p_cabac_ctxt_table_t + CABAC_MOT_PRED_FLAG1;
ps_svc_lyr_dec->ps_residual_prediction_flag = p_cabac_ctxt_table_t + CABAC_RES_PRED_FLAG;
}
return (i16_status);
}
/*!
**************************************************************************
* \if Function name : isvcd_decode_pic_order_cnt \endif
*
* \brief
* Calculates picture order count of picture.
*
* \return
* Returns the pic order count of the picture to which current
* Slice belongs.
*
**************************************************************************
*/
WORD32 isvcd_decode_pic_order_cnt(
UWORD8 u1_is_idr_slice, UWORD32 u2_frame_num, pocstruct_t *ps_prev_poc, pocstruct_t *ps_cur_poc,
dec_slice_params_t *ps_cur_slice, /*!< Pointer to current slice Params*/
dec_pic_params_t *ps_pps, UWORD8 u1_nal_ref_idc, UWORD8 u1_bottom_field_flag,
UWORD8 u1_field_pic_flag, WORD32 *pi4_poc, dec_struct_t *ps_dec)
{
WORD64 i8_pic_msb;
WORD32 i4_top_field_order_cnt = 0, i4_bottom_field_order_cnt = 0;
dec_seq_params_t *ps_seq = ps_dec->ps_cur_sps;
WORD32 i4_prev_frame_num_ofst;
switch(ps_seq->u1_pic_order_cnt_type)
{
case 0:
/* POC TYPE 0 */
if(u1_is_idr_slice)
{
ps_prev_poc->i4_pic_order_cnt_msb = 0;
ps_prev_poc->i4_pic_order_cnt_lsb = 0;
}
if(ps_prev_poc->u1_mmco_equalto5)
{
if(ps_prev_poc->u1_bot_field != 1)
{
ps_prev_poc->i4_pic_order_cnt_msb = 0;
ps_prev_poc->i4_pic_order_cnt_lsb = ps_prev_poc->i4_top_field_order_count;
}
else
{
ps_prev_poc->i4_pic_order_cnt_msb = 0;
ps_prev_poc->i4_pic_order_cnt_lsb = 0;
}
}
if((ps_cur_poc->i4_pic_order_cnt_lsb < ps_prev_poc->i4_pic_order_cnt_lsb) &&
((ps_prev_poc->i4_pic_order_cnt_lsb - ps_cur_poc->i4_pic_order_cnt_lsb) >=
(ps_seq->i4_max_pic_order_cntLsb >> 1)))
{
i8_pic_msb =
(WORD64) ps_prev_poc->i4_pic_order_cnt_msb + ps_seq->i4_max_pic_order_cntLsb;
}
else if((ps_cur_poc->i4_pic_order_cnt_lsb > ps_prev_poc->i4_pic_order_cnt_lsb) &&
((ps_cur_poc->i4_pic_order_cnt_lsb - ps_prev_poc->i4_pic_order_cnt_lsb) >=
(ps_seq->i4_max_pic_order_cntLsb >> 1)))
{
i8_pic_msb =
(WORD64) ps_prev_poc->i4_pic_order_cnt_msb - ps_seq->i4_max_pic_order_cntLsb;
}
else
{
i8_pic_msb = ps_prev_poc->i4_pic_order_cnt_msb;
}
if(!u1_field_pic_flag || !u1_bottom_field_flag)
{
WORD64 i8_result = i8_pic_msb + ps_cur_poc->i4_pic_order_cnt_lsb;
if(IS_OUT_OF_RANGE_S32(i8_result))
{
return ERROR_INV_POC;
}
i4_top_field_order_cnt = (WORD32) i8_result;
}
if(!u1_field_pic_flag)
{
WORD64 i8_result =
(WORD64) i4_top_field_order_cnt + ps_cur_poc->i4_delta_pic_order_cnt_bottom;
if(IS_OUT_OF_RANGE_S32(i8_result))
{
return ERROR_INV_POC;
}
i4_bottom_field_order_cnt = (WORD32) i8_result;
}
else if(u1_bottom_field_flag)
{
WORD64 i8_result = i8_pic_msb + ps_cur_poc->i4_pic_order_cnt_lsb;
if(IS_OUT_OF_RANGE_S32(i8_result))
{
return ERROR_INV_POC;
}
i4_bottom_field_order_cnt = (WORD32) i8_result;
}
if(IS_OUT_OF_RANGE_S32(i8_pic_msb))
{
return ERROR_INV_POC;
}
ps_cur_poc->i4_pic_order_cnt_msb = (WORD32) i8_pic_msb;
break;
case 1:
{
/* POC TYPE 1 */
UWORD8 i;
WORD32 prev_frame_num;
WORD32 frame_num_ofst;
WORD32 abs_frm_num;
WORD32 poc_cycle_cnt, frame_num_in_poc_cycle;
WORD64 i8_expected_delta_poc_cycle;
WORD32 expected_poc;
WORD64 i8_result;
prev_frame_num = (WORD32) ps_cur_slice->u2_frame_num;
if(!u1_is_idr_slice)
{
if(ps_cur_slice->u1_mmco_equalto5)
{
prev_frame_num = 0;
i4_prev_frame_num_ofst = 0;
}
else
{
i4_prev_frame_num_ofst = ps_prev_poc->i4_prev_frame_num_ofst;
}
}
else
i4_prev_frame_num_ofst = 0;
/* 1. Derivation for FrameNumOffset */
if(u1_is_idr_slice)
{
frame_num_ofst = 0;
ps_cur_poc->i4_delta_pic_order_cnt[0] = 0;
ps_cur_poc->i4_delta_pic_order_cnt[1] = 0;
}
else if(prev_frame_num > ((WORD32) u2_frame_num))
{
WORD64 i8_result =
i4_prev_frame_num_ofst + (WORD64) ps_seq->u2_u4_max_pic_num_minus1 + 1;
if(IS_OUT_OF_RANGE_S32(i8_result))
{
return ERROR_INV_FRAME_NUM;
}
frame_num_ofst = (WORD32) i8_result;
}
else
frame_num_ofst = i4_prev_frame_num_ofst;
/* 2. Derivation for absFrameNum */
if(0 != ps_seq->u1_num_ref_frames_in_pic_order_cnt_cycle)
{
WORD64 i8_result = frame_num_ofst + (WORD64) u2_frame_num;
if(IS_OUT_OF_RANGE_S32(i8_result))
{
return ERROR_INV_FRAME_NUM;
}
abs_frm_num = (WORD32) i8_result;
}
else
abs_frm_num = 0;
if((u1_nal_ref_idc == 0) && (abs_frm_num > 0)) abs_frm_num = abs_frm_num - 1;
/* 4. expectedDeltaPerPicOrderCntCycle is derived as */
i8_expected_delta_poc_cycle = 0;
for(i = 0; i < ps_seq->u1_num_ref_frames_in_pic_order_cnt_cycle; i++)
{
i8_expected_delta_poc_cycle += ps_seq->i4_ofst_for_ref_frame[i];
}
/* 3. When absFrameNum > 0, picOrderCntCycleCnt and
frame_num_in_poc_cycle are derived as : */
/* 5. expectedPicOrderCnt is derived as : */
if(abs_frm_num > 0)
{
poc_cycle_cnt =
DIV((abs_frm_num - 1), ps_seq->u1_num_ref_frames_in_pic_order_cnt_cycle);
frame_num_in_poc_cycle =
MOD((abs_frm_num - 1), ps_seq->u1_num_ref_frames_in_pic_order_cnt_cycle);
i8_result = poc_cycle_cnt * i8_expected_delta_poc_cycle;
for(i = 0; i <= frame_num_in_poc_cycle; i++)
{
i8_result = i8_result + ps_seq->i4_ofst_for_ref_frame[i];
}
if(IS_OUT_OF_RANGE_S32(i8_result)) return ERROR_INV_POC;
expected_poc = (WORD32) i8_result;
}
else
expected_poc = 0;
if(u1_nal_ref_idc == 0)
{
i8_result = (WORD64) expected_poc + ps_seq->i4_ofst_for_non_ref_pic;
if(IS_OUT_OF_RANGE_S32(i8_result)) return ERROR_INV_POC;
expected_poc = (WORD32) i8_result;
}
/* 6. TopFieldOrderCnt or BottomFieldOrderCnt are derived as */
if(!u1_field_pic_flag)
{
i8_result = (WORD64) expected_poc + ps_cur_poc->i4_delta_pic_order_cnt[0];
if(IS_OUT_OF_RANGE_S32(i8_result)) return ERROR_INV_POC;
i4_top_field_order_cnt = (WORD32) i8_result;
i8_result = (WORD64) i4_top_field_order_cnt +
ps_seq->i4_ofst_for_top_to_bottom_field +
ps_cur_poc->i4_delta_pic_order_cnt[1];
if(IS_OUT_OF_RANGE_S32(i8_result)) return ERROR_INV_POC;
i4_bottom_field_order_cnt = (WORD32) i8_result;
}
else if(!u1_bottom_field_flag)
{
i8_result = (WORD64) expected_poc + ps_cur_poc->i4_delta_pic_order_cnt[0];
if(IS_OUT_OF_RANGE_S32(i8_result)) return ERROR_INV_POC;
i4_top_field_order_cnt = (WORD32) i8_result;
}
else
{
i8_result = (WORD64) expected_poc + ps_seq->i4_ofst_for_top_to_bottom_field +
ps_cur_poc->i4_delta_pic_order_cnt[0];
if(IS_OUT_OF_RANGE_S32(i8_result)) return ERROR_INV_POC;
i4_bottom_field_order_cnt = (WORD32) i8_result;
}
/* Copy the current POC info into Previous POC structure */
ps_cur_poc->i4_prev_frame_num_ofst = frame_num_ofst;
}
break;
case 2:
{
/* POC TYPE 2 */
WORD32 prev_frame_num;
WORD32 frame_num_ofst;
WORD32 tmp_poc;
prev_frame_num = (WORD32) ps_cur_slice->u2_frame_num;
if(!u1_is_idr_slice)
{
if(ps_cur_slice->u1_mmco_equalto5)
{
prev_frame_num = 0;
i4_prev_frame_num_ofst = 0;
}
else
i4_prev_frame_num_ofst = ps_prev_poc->i4_prev_frame_num_ofst;
}
else
i4_prev_frame_num_ofst = 0;
/* 1. Derivation for FrameNumOffset */
if(u1_is_idr_slice)
{
frame_num_ofst = 0;
ps_cur_poc->i4_delta_pic_order_cnt[0] = 0;
ps_cur_poc->i4_delta_pic_order_cnt[1] = 0;
}
else if(prev_frame_num > ((WORD32) u2_frame_num))
{
WORD64 i8_result =
i4_prev_frame_num_ofst + (WORD64) ps_seq->u2_u4_max_pic_num_minus1 + 1;
if(IS_OUT_OF_RANGE_S32(i8_result))
{
return ERROR_INV_FRAME_NUM;
}
frame_num_ofst = (WORD32) i8_result;
}
else
frame_num_ofst = i4_prev_frame_num_ofst;
/* 2. Derivation for tempPicOrderCnt */
if(u1_is_idr_slice)
tmp_poc = 0;
else if(u1_nal_ref_idc == 0)
{
WORD64 i8_result = ((frame_num_ofst + (WORD64) u2_frame_num) << 1) - 1;
if(IS_OUT_OF_RANGE_S32(i8_result))
{
return ERROR_INV_POC;
}
tmp_poc = (WORD32) i8_result;
}
else
{
WORD64 i8_result = (frame_num_ofst + (WORD64) u2_frame_num) << 1;
if(IS_OUT_OF_RANGE_S32(i8_result))
{
return ERROR_INV_POC;
}
tmp_poc = (WORD32) i8_result;
}
/* 6. TopFieldOrderCnt or BottomFieldOrderCnt are derived as */
if(!u1_field_pic_flag)
{
i4_top_field_order_cnt = tmp_poc;
i4_bottom_field_order_cnt = tmp_poc;
}
else if(!u1_bottom_field_flag)
i4_top_field_order_cnt = tmp_poc;
else
i4_bottom_field_order_cnt = tmp_poc;
/* Copy the current POC info into Previous POC structure */
ps_prev_poc->i4_prev_frame_num_ofst = frame_num_ofst;
ps_cur_poc->i4_prev_frame_num_ofst = frame_num_ofst;
}
break;
default:
return ERROR_INV_POC_TYPE_T;
break;
}
if(!u1_field_pic_flag) // or a complementary field pair
{
*pi4_poc = MIN(i4_top_field_order_cnt, i4_bottom_field_order_cnt);
ps_pps->i4_top_field_order_cnt = i4_top_field_order_cnt;
ps_pps->i4_bottom_field_order_cnt = i4_bottom_field_order_cnt;
}
else if(!u1_bottom_field_flag)
{
*pi4_poc = i4_top_field_order_cnt;
ps_pps->i4_top_field_order_cnt = i4_top_field_order_cnt;
}
else
{
*pi4_poc = i4_bottom_field_order_cnt;
ps_pps->i4_bottom_field_order_cnt = i4_bottom_field_order_cnt;
}
ps_pps->i4_avg_poc = *pi4_poc;
return OK;
}
/*****************************************************************************/
/* */
/* Function Name : isvcd_decode_gaps_in_frame_num */
/* */
/* Description : This function decodes gaps in frame number */
/* */
/* Inputs : ps_dec Decoder parameters */
/* u2_frame_num current frame number */
/* */
/* Globals : None */
/* Processing : This functionality needs to be implemented */
/* Outputs : None */
/* Returns : None */
/* */
/* Issues : Not implemented */
/* */
/* Revision History: */
/* */
/* DD MM YYYY Author(s) Changes (Describe the changes made) */
/* 06 05 2002 NS Draft */
/* */
/*****************************************************************************/
WORD32 isvcd_decode_gaps_in_frame_num(dec_struct_t *ps_dec, UWORD16 u2_frame_num)
{
UWORD32 u4_next_frm_num, u4_start_frm_num;
UWORD32 u4_max_frm_num;
pocstruct_t s_tmp_poc;
WORD32 i4_poc;
dec_slice_params_t *ps_cur_slice;
dec_pic_params_t *ps_pic_params;
WORD8 i1_gap_idx;
WORD32 *i4_gaps_start_frm_num;
dpb_manager_t *ps_dpb_mgr;
WORD8 *pi1_gaps_per_seq;
WORD32 ret;
ps_cur_slice = ps_dec->ps_cur_slice;
if(ps_cur_slice->u1_field_pic_flag)
{
if(ps_dec->u2_prev_ref_frame_num == u2_frame_num) return 0;
}
u4_next_frm_num = ps_dec->u2_prev_ref_frame_num + 1;
u4_max_frm_num = ps_dec->ps_cur_sps->u2_u4_max_pic_num_minus1 + 1;
if(u4_next_frm_num >= u4_max_frm_num)
{
u4_next_frm_num -= u4_max_frm_num;
}
if(u4_next_frm_num == u2_frame_num)
{
return (0);
}
if((ps_dec->u1_nal_unit_type == IDR_SLICE_NAL) && (u4_next_frm_num >= u2_frame_num))
{
return (0);
}
u4_start_frm_num = u4_next_frm_num;
s_tmp_poc.i4_pic_order_cnt_lsb = 0;
s_tmp_poc.i4_delta_pic_order_cnt_bottom = 0;
s_tmp_poc.i4_pic_order_cnt_lsb = 0;
s_tmp_poc.i4_delta_pic_order_cnt_bottom = 0;
s_tmp_poc.i4_delta_pic_order_cnt[0] = 0;
s_tmp_poc.i4_delta_pic_order_cnt[1] = 0;
ps_cur_slice = ps_dec->ps_cur_slice;
ps_pic_params = ps_dec->ps_cur_pps;
ps_dpb_mgr = ps_dec->ps_dpb_mgr;
/* Find a empty slot to store gap seqn info */
i4_gaps_start_frm_num = ps_dpb_mgr->ai4_gaps_start_frm_num;
for(i1_gap_idx = 0; i1_gap_idx < MAX_FRAMES; i1_gap_idx++)
{
if(INVALID_FRAME_NUM == i4_gaps_start_frm_num[i1_gap_idx]) break;
}
if(MAX_FRAMES == i1_gap_idx)
{
UWORD32 i4_error_code;
i4_error_code = ERROR_DBP_MANAGER_T;
return i4_error_code;
}
i4_poc = 0;
i4_gaps_start_frm_num[i1_gap_idx] = u4_start_frm_num;
ps_dpb_mgr->ai4_gaps_end_frm_num[i1_gap_idx] = u2_frame_num - 1;
pi1_gaps_per_seq = ps_dpb_mgr->ai1_gaps_per_seq;
pi1_gaps_per_seq[i1_gap_idx] = 0;
while(u4_next_frm_num != u2_frame_num)
{
ih264d_delete_nonref_nondisplay_pics(ps_dpb_mgr);
if(ps_pic_params->ps_sps->u1_pic_order_cnt_type)
{
/* allocate a picture buffer and insert it as ST node */
ret =
isvcd_decode_pic_order_cnt(0, u4_next_frm_num, &ps_dec->s_prev_pic_poc, &s_tmp_poc,
ps_cur_slice, ps_pic_params, 1, 0, 0, &i4_poc, ps_dec);
if(ret != OK) return ret;
/* Display seq no calculations */
if(i4_poc >= ps_dec->i4_max_poc) ps_dec->i4_max_poc = i4_poc;
/* IDR Picture or POC wrap around */
if(i4_poc == 0)
{
WORD64 i8_temp;
i8_temp = (WORD64) ps_dec->i4_prev_max_display_seq + ps_dec->i4_max_poc +
ps_dec->u1_max_dec_frame_buffering + 1;
/*If i4_prev_max_display_seq overflows integer range, reset it */
ps_dec->i4_prev_max_display_seq =
IS_OUT_OF_RANGE_S32(i8_temp) ? 0 : (WORD32) i8_temp;
ps_dec->i4_max_poc = 0;
}
ps_cur_slice->u1_mmco_equalto5 = 0;
ps_cur_slice->u2_frame_num = u4_next_frm_num;
}
if(ps_dpb_mgr->i1_poc_buf_id_entries >= ps_dec->u1_max_dec_frame_buffering)
{
ret = ih264d_assign_display_seq(ps_dec);
if(ret != OK) return ret;
}
{
WORD64 i8_display_poc;
i8_display_poc = (WORD64) ps_dec->i4_prev_max_display_seq + i4_poc;
if(IS_OUT_OF_RANGE_S32(i8_display_poc))
{
ps_dec->i4_prev_max_display_seq = 0;
}
}
ret = ih264d_insert_pic_in_display_list(ps_dec->ps_dpb_mgr, (WORD8) DO_NOT_DISP,
(WORD32) (ps_dec->i4_prev_max_display_seq + i4_poc),
u4_next_frm_num);
if(ret != OK) return ret;
pi1_gaps_per_seq[i1_gap_idx]++;
ret = ih264d_do_mmco_for_gaps(ps_dpb_mgr, ps_dec->ps_cur_sps->u1_num_ref_frames);
if(ret != OK) return ret;
ih264d_delete_nonref_nondisplay_pics(ps_dpb_mgr);
u4_next_frm_num++;
if(u4_next_frm_num >= u4_max_frm_num)
{
u4_next_frm_num -= u4_max_frm_num;
}
}
return OK;
}
/*!
**************************************************************************
* \if Function name : isvcd_init_pic \endif
*
* \brief
* Initializes the picture.
*
* \return
* 0 on Success and Error code otherwise
*
* \note
* This function is called when first slice of the
* NON -IDR picture is encountered.
**************************************************************************
*/
WORD32 isvcd_init_pic(svc_dec_lyr_struct_t *ps_svc_lyr_dec, UWORD16 u2_frame_num, WORD32 i4_poc,
dec_pic_params_t *ps_pps)
{
dec_struct_t *ps_dec = &ps_svc_lyr_dec->s_dec;
dec_seq_params_t *ps_seq = ps_dec->ps_cur_sps;
prev_seq_params_t *ps_prev_seq_params = &ps_dec->s_prev_seq_params;
WORD32 ret;
ps_dec->ps_cur_slice->u2_frame_num = u2_frame_num;
ps_dec->ps_cur_slice->i4_poc = i4_poc;
ps_dec->ps_cur_pps = ps_pps;
ps_dec->ps_cur_pps->pv_codec_handle = ps_dec;
ps_dec->ps_dpb_mgr->i4_max_frm_num = ps_seq->u2_u4_max_pic_num_minus1 + 1;
ps_dec->ps_dpb_mgr->u2_pic_ht = ps_dec->u2_pic_ht;
ps_dec->ps_dpb_mgr->u2_pic_wd = ps_dec->u2_pic_wd;
ps_dec->i4_pic_type = NA_SLICE;
ps_dec->i4_frametype = IV_NA_FRAME;
ps_dec->i4_content_type = IV_CONTENTTYPE_NA;
/*--------------------------------------------------------------------*/
/* Get the value of MaxMbAddress and frmheight in Mbs */
/*--------------------------------------------------------------------*/
ps_seq->u2_max_mb_addr =
(ps_seq->u2_frm_wd_in_mbs *
(ps_dec->u2_pic_ht >> (4 + ps_dec->ps_cur_slice->u1_field_pic_flag))) -
1;
ps_dec->u2_frm_ht_in_mbs = (ps_dec->u2_pic_ht >> (4 + ps_dec->ps_cur_slice->u1_field_pic_flag));
/***************************************************************************/
/* If change in Level or the required PicBuffers i4_size is more than the */
/* current one FREE the current PicBuffers and allocate affresh */
/***************************************************************************/
if(!ps_dec->u1_init_dec_flag)
{
ps_dec->u1_max_dec_frame_buffering = ih264d_get_dpb_size(ps_seq);
ps_dec->i4_display_delay = ps_dec->u1_max_dec_frame_buffering;
if((1 == ps_seq->u1_vui_parameters_present_flag) &&
(1 == ps_seq->s_vui.u1_bitstream_restriction_flag))
{
if(ps_seq->u1_frame_mbs_only_flag == 1)
ps_dec->i4_display_delay = ps_seq->s_vui.u4_num_reorder_frames + 1;
else
ps_dec->i4_display_delay = ps_seq->s_vui.u4_num_reorder_frames * 2 + 2;
}
if(IVD_DECODE_FRAME_OUT == ps_dec->e_frm_out_mode) ps_dec->i4_display_delay = 0;
if(ps_dec->u4_share_disp_buf == 0)
{
if(ps_seq->u1_frame_mbs_only_flag == 1)
ps_dec->u1_pic_bufs = ps_dec->i4_display_delay + ps_seq->u1_num_ref_frames + 1;
else
ps_dec->u1_pic_bufs = ps_dec->i4_display_delay + ps_seq->u1_num_ref_frames * 2 + 2;
}
else
{
ps_dec->u1_pic_bufs = (WORD32) ps_dec->u4_num_disp_bufs;
}
/* Ensure at least two buffers are allocated */
ps_dec->u1_pic_bufs = MAX(ps_dec->u1_pic_bufs, 2);
if(ps_dec->u4_share_disp_buf == 0)
ps_dec->u1_pic_bufs = MIN(ps_dec->u1_pic_bufs, (H264_MAX_REF_PICS * 2));
ps_dec->u1_max_dec_frame_buffering =
MIN(ps_dec->u1_max_dec_frame_buffering, ps_dec->u1_pic_bufs);
/* Temporary hack to run Tractor Cav/Cab/MbAff Profiler streams also for
* CAFI1_SVA_C.264 in conformance*/
if(ps_dec->u1_init_dec_flag)
{
ih264d_release_pics_in_dpb((void *) ps_dec, ps_dec->u1_pic_bufs);
ih264d_release_display_bufs(ps_dec);
ih264d_reset_ref_bufs(ps_dec->ps_dpb_mgr);
}
/*********************************************************************/
/* Configuring decoder parameters based on level and then */
/* fresh pointer initialisation in decoder scratch and state buffers */
/*********************************************************************/
if(!ps_dec->u1_init_dec_flag || ((ps_seq->u1_level_idc < H264_LEVEL_3_0) ^
(ps_prev_seq_params->u1_level_idc < H264_LEVEL_3_0)))
{
ret = ih264d_init_dec_mb_grp(ps_dec);
if(ret != OK) return ret;
}
ret = isvcd_allocate_dynamic_bufs(ps_svc_lyr_dec);
if(ret != OK)
{
/* Free any dynamic buffers that are allocated */
isvcd_free_dynamic_bufs(ps_svc_lyr_dec);
ps_dec->i4_error_code = IVD_MEM_ALLOC_FAILED;
return IVD_MEM_ALLOC_FAILED;
}
ret = ih264d_create_pic_buffers(ps_dec->u1_pic_bufs, ps_dec);
if(ret != OK) return ret;
ret = ih264d_create_mv_bank(ps_dec, ps_dec->u2_pic_wd, ps_dec->u2_pic_ht);
if(ret != OK) return ret;
/* In shared mode, set all of them as used by display */
if(ps_dec->u4_share_disp_buf == 1)
{
WORD32 i;
for(i = 0; i < ps_dec->u1_pic_bufs; i++)
{
ih264_buf_mgr_set_status((buf_mgr_t *) ps_dec->pv_pic_buf_mgr, i, BUF_MGR_IO);
}
}
ps_dec->u1_init_dec_flag = 1;
ps_prev_seq_params->u2_frm_wd_in_mbs = ps_seq->u2_frm_wd_in_mbs;
ps_prev_seq_params->u1_level_idc = ps_seq->u1_level_idc;
ps_prev_seq_params->u1_profile_idc = ps_seq->u1_profile_idc;
ps_prev_seq_params->u2_frm_ht_in_mbs = ps_seq->u2_frm_ht_in_mbs;
ps_prev_seq_params->u1_frame_mbs_only_flag = ps_seq->u1_frame_mbs_only_flag;
ps_prev_seq_params->u1_direct_8x8_inference_flag = ps_seq->u1_direct_8x8_inference_flag;
ps_dec->i4_cur_display_seq = 0;
ps_dec->i4_prev_max_display_seq = 0;
ps_dec->i4_max_poc = 0;
{
/* 0th entry of CtxtIncMbMap will be always be containing default values
for CABAC context representing MB not available */
ctxt_inc_mb_info_t *p_DefCtxt = ps_dec->p_ctxt_inc_mb_map - 1;
UWORD8 *pu1_temp;
WORD8 i;
p_DefCtxt->u1_mb_type = CAB_SKIP;
p_DefCtxt->u1_cbp = 0x0f;
p_DefCtxt->u1_intra_chroma_pred_mode = 0;
p_DefCtxt->u1_yuv_dc_csbp = 0x7;
p_DefCtxt->u1_transform8x8_ctxt = 0;
pu1_temp = (UWORD8 *) p_DefCtxt->i1_ref_idx;
for(i = 0; i < 4; i++, pu1_temp++) (*pu1_temp) = 0;
pu1_temp = (UWORD8 *) p_DefCtxt->u1_mv;
for(i = 0; i < 16; i++, pu1_temp++) (*pu1_temp) = 0;
ps_dec->ps_def_ctxt_mb_info = p_DefCtxt;
}
}
/* reset DBP commands read u4_flag */
ps_dec->ps_dpb_cmds->u1_dpb_commands_read = 0;
return OK;
}