libavc/decoder/ih264d_mb_utils.c
Marco Nelissen 8ef4c3f614 Multithreading changes and better error resilience
Fixed the following bugs
Issue 21145276
Issue 21144884
Issue 21181133
Issue 21181134

Decoder now returns error if the level in stream is higher than level at init

Change-Id: I8892c62bd98f7854d046510330c05a1e9ca826b2
2015-06-03 07:27:36 -07:00

1474 lines
64 KiB
C

/******************************************************************************
*
* Copyright (C) 2015 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 ih264d_mb_utils.c
*
* \brief
* Contains utitlity functions needed for Macroblock decoding
*
* \date
* 18/12/2002
*
* \author AI
**************************************************************************
*/
#include <string.h>
#include <stdlib.h>
#include "ih264d_bitstrm.h"
#include "ih264d_defs.h"
#include "ih264d_debug.h"
#include "ih264d_structs.h"
#include "ih264d_defs.h"
#include "ih264d_mb_utils.h"
#include "ih264d_parse_slice.h"
#include "ih264d_error_handler.h"
#include "ih264d_parse_mb_header.h"
#include "ih264d_cabac.h"
#include "ih264d_defs.h"
#include "ih264d_tables.h"
/*****************************************************************************/
/* */
/* Function Name : get_mb_info_cavlc */
/* */
/* Description : This function sets the following information of cur MB */
/* (a) mb_x and mb_y */
/* (b) Neighbour availablity */
/* (c) Macroblock location in the frame buffer */
/* (e) For mbaff predicts field/frame u4_flag for topMb */
/* and sets the field/frame for botMb. This is */
/* written in ps_dec->u1_cur_mb_fld_dec_flag */
/* */
/* Inputs : pointer to decstruct */
/* pointer to current mb info */
/* currentMbaddress */
/* */
/* Processing : leftMb and TopMb params are used by DecMbskip and */
/* DecCtxMbfield modules so that these modules do not */
/* check for neigbour availability and then find the */
/* neigbours for context increments */
/* */
/* Returns : OK */
/* */
/* Issues : <List any issues or problems with this function> */
/* */
/* Revision History: */
/* */
/* DD MM YYYY Author(s) Changes (Describe the changes made) */
/* 13 07 2002 Jay Draft */
/* */
/*****************************************************************************/
UWORD32 ih264d_get_mb_info_cavlc_nonmbaff(dec_struct_t *ps_dec,
const UWORD16 u2_cur_mb_address,
dec_mb_info_t * ps_cur_mb_info,
UWORD32 u4_mbskip_run)
{
WORD32 mb_x;
WORD32 mb_y;
UWORD8 u1_mb_ngbr_avail = 0;
UWORD16 u2_frm_width_in_mb = ps_dec->u2_frm_wd_in_mbs;
WORD16 i2_prev_slice_mbx = ps_dec->i2_prev_slice_mbx;
UWORD16 u2_top_right_mask = TOP_RIGHT_DEFAULT_AVAILABLE;
UWORD16 u2_top_left_mask = TOP_LEFT_DEFAULT_AVAILABLE;
UNUSED(u4_mbskip_run);
/*--------------------------------------------------------------------*/
/* Calculate values of mb_x and mb_y */
/*--------------------------------------------------------------------*/
mb_x = (WORD16)ps_dec->u2_mbx;
mb_y = (WORD16)ps_dec->u2_mby;
ps_dec->u2_cur_mb_addr = u2_cur_mb_address;
mb_x++;
if(mb_x == u2_frm_width_in_mb)
{
mb_x = 0;
mb_y++;
}
if(mb_y > ps_dec->i2_prev_slice_mby)
{
/* if not in the immemdiate row of prev slice end then top
will be available */
if(mb_y > (ps_dec->i2_prev_slice_mby + 1))
i2_prev_slice_mbx = -1;
if(mb_x > i2_prev_slice_mbx)
{
u1_mb_ngbr_avail |= TOP_MB_AVAILABLE_MASK;
u2_top_right_mask |= TOP_RIGHT_TOP_AVAILABLE;
u2_top_left_mask |= TOP_LEFT_TOP_AVAILABLE;
}
if((mb_x > (i2_prev_slice_mbx - 1))
&& (mb_x != (u2_frm_width_in_mb - 1)))
{
u1_mb_ngbr_avail |= TOP_RIGHT_MB_AVAILABLE_MASK;
u2_top_right_mask |= TOP_RIGHT_TOPR_AVAILABLE;
}
if(mb_x > (i2_prev_slice_mbx + 1))
{
u1_mb_ngbr_avail |= TOP_LEFT_MB_AVAILABLE_MASK;
u2_top_left_mask |= TOP_LEFT_TOPL_AVAILABLE;
}
/* Next row Left will be available*/
i2_prev_slice_mbx = -1;
}
/* Same row */
if(mb_x > (i2_prev_slice_mbx + 1))
{
u1_mb_ngbr_avail |= LEFT_MB_AVAILABLE_MASK;
u2_top_left_mask |= TOP_LEFT_LEFT_AVAILABLE;
}
{
mb_neigbour_params_t *ps_cur_mb_row = ps_dec->ps_cur_mb_row;
mb_neigbour_params_t *ps_top_mb_row = ps_dec->ps_top_mb_row;
/* copy the parameters of topleft Mb */
ps_cur_mb_info->u1_topleft_mbtype = ps_dec->u1_topleft_mbtype;
/* Neighbour pointer assignments*/
ps_cur_mb_info->ps_curmb = ps_cur_mb_row + mb_x;
ps_cur_mb_info->ps_left_mb = ps_cur_mb_row + mb_x - 1;
ps_cur_mb_info->ps_top_mb = ps_top_mb_row + mb_x;
ps_cur_mb_info->ps_top_right_mb = ps_top_mb_row + mb_x + 1;
/* Update the parameters of topleftmb*/
ps_dec->u1_topleft_mbtype = ps_cur_mb_info->ps_top_mb->u1_mb_type;
}
ps_dec->u2_mby = mb_y;
ps_dec->u2_mbx = mb_x;
ps_cur_mb_info->u2_mbx = mb_x;
ps_cur_mb_info->u2_mby = mb_y;
ps_cur_mb_info->u1_topmb = 1;
ps_dec->i4_submb_ofst += SUB_BLK_SIZE;
ps_dec->u1_mb_ngbr_availablity = u1_mb_ngbr_avail;
ps_cur_mb_info->u1_mb_ngbr_availablity = u1_mb_ngbr_avail;
ps_cur_mb_info->ps_curmb->u1_mb_fld = ps_dec->u1_cur_mb_fld_dec_flag;
ps_cur_mb_info->u1_mb_field_decodingflag = ps_dec->u1_cur_mb_fld_dec_flag;
ps_cur_mb_info->u2_top_left_avail_mask = u2_top_left_mask;
ps_cur_mb_info->u2_top_right_avail_mask = u2_top_right_mask;
return (OK);
}
/*****************************************************************************/
/* */
/* Function Name : get_mb_info_cavlc */
/* */
/* Description : This function sets the following information of cur MB */
/* (a) mb_x and mb_y */
/* (b) Neighbour availablity */
/* (c) Macroblock location in the frame buffer */
/* (e) For mbaff predicts field/frame u4_flag for topMb */
/* and sets the field/frame for botMb. This is */
/* written in ps_dec->u1_cur_mb_fld_dec_flag */
/* */
/* Inputs : pointer to decstruct */
/* pointer to current mb info */
/* currentMbaddress */
/* */
/* Processing : leftMb and TopMb params are used by DecMbskip and */
/* DecCtxMbfield modules so that these modules do not */
/* check for neigbour availability and then find the */
/* neigbours for context increments */
/* */
/* Returns : OK */
/* */
/* Issues : <List any issues or problems with this function> */
/* */
/* Revision History: */
/* */
/* DD MM YYYY Author(s) Changes (Describe the changes made) */
/* 13 07 2002 Jay Draft */
/* */
/*****************************************************************************/
UWORD32 ih264d_get_mb_info_cavlc_mbaff(dec_struct_t *ps_dec,
const UWORD16 u2_cur_mb_address,
dec_mb_info_t * ps_cur_mb_info,
UWORD32 u4_mbskip_run)
{
UWORD16 u2_mb_x;
UWORD16 u2_mb_y;
UWORD8 u1_mb_ngbr_avail = 0;
UWORD16 u2_frm_width_in_mb = ps_dec->u2_frm_wd_in_mbs;
UWORD8 u1_top_mb = 1 - (u2_cur_mb_address & 0x01);
WORD16 i2_prev_slice_mbx = ps_dec->i2_prev_slice_mbx;
UWORD8 u1_cur_mb_field = 0;
UWORD16 u2_top_right_mask = TOP_RIGHT_DEFAULT_AVAILABLE;
UWORD16 u2_top_left_mask = TOP_LEFT_DEFAULT_AVAILABLE;
/*--------------------------------------------------------------------*/
/* Calculate values of mb_x and mb_y */
/*--------------------------------------------------------------------*/
u2_mb_x = ps_dec->u2_mbx;
u2_mb_y = ps_dec->u2_mby;
ps_dec->u2_cur_mb_addr = u2_cur_mb_address;
if(u1_top_mb)
{
u2_mb_x++;
if(u2_mb_x == u2_frm_width_in_mb)
{
u2_mb_x = 0;
u2_mb_y += 2;
}
if(u2_mb_y > ps_dec->i2_prev_slice_mby)
{
/* if not in the immemdiate row of prev slice end then top
will be available */
if(u2_mb_y > (ps_dec->i2_prev_slice_mby + 2))
i2_prev_slice_mbx = -1;
if(u2_mb_x > i2_prev_slice_mbx)
{
u1_mb_ngbr_avail |= TOP_MB_AVAILABLE_MASK;
u1_cur_mb_field = ps_dec->ps_top_mb_row[u2_mb_x << 1].u1_mb_fld;
u2_top_right_mask |= TOP_RIGHT_TOP_AVAILABLE;
u2_top_left_mask |= TOP_LEFT_TOP_AVAILABLE;
}
if((u2_mb_x > (i2_prev_slice_mbx - 1))
&& (u2_mb_x != (u2_frm_width_in_mb - 1)))
{
u1_mb_ngbr_avail |= TOP_RIGHT_MB_AVAILABLE_MASK;
u2_top_right_mask |= TOP_RIGHT_TOPR_AVAILABLE;
}
if(u2_mb_x > (i2_prev_slice_mbx + 1))
{
u1_mb_ngbr_avail |= TOP_LEFT_MB_AVAILABLE_MASK;
u2_top_left_mask |= TOP_LEFT_TOPL_AVAILABLE;
}
i2_prev_slice_mbx = -1;
}
/* Same row */
if(u2_mb_x > (i2_prev_slice_mbx + 1))
{
u1_mb_ngbr_avail |= LEFT_MB_AVAILABLE_MASK;
u1_cur_mb_field =
ps_dec->ps_cur_mb_row[(u2_mb_x << 1) - 1].u1_mb_fld;
u2_top_left_mask |= TOP_LEFT_LEFT_AVAILABLE;
}
/* Read u1_cur_mb_field from the bitstream if u4_mbskip_run <= 1*/
if(u4_mbskip_run <= 1)
u1_cur_mb_field = (UWORD8)ih264d_get_bit_h264(ps_dec->ps_bitstrm);
ps_dec->u1_cur_mb_fld_dec_flag = u1_cur_mb_field;
ps_dec->u2_top_left_mask = u2_top_left_mask;
ps_dec->u2_top_right_mask = u2_top_right_mask;
}
else
{
u1_mb_ngbr_avail = ps_dec->u1_mb_ngbr_availablity;
u1_cur_mb_field = ps_dec->u1_cur_mb_fld_dec_flag;
u2_top_left_mask = ps_dec->u2_top_left_mask;
u2_top_right_mask = ps_dec->u2_top_right_mask;
if(!u1_cur_mb_field)
{
/* Top is available */
u1_mb_ngbr_avail |= TOP_MB_AVAILABLE_MASK;
u2_top_right_mask |= TOP_RIGHT_TOP_AVAILABLE;
u2_top_left_mask |= TOP_LEFT_TOP_AVAILABLE;
/* Top Right not available */
u1_mb_ngbr_avail &= TOP_RT_SUBBLOCK_MASK_MOD;
u2_top_right_mask &= (~TOP_RIGHT_TOPR_AVAILABLE);
if(u1_mb_ngbr_avail & LEFT_MB_AVAILABLE_MASK)
{
u1_mb_ngbr_avail |= TOP_LEFT_MB_AVAILABLE_MASK;
u2_top_left_mask |= TOP_LEFT_LEFT_AVAILABLE;
u2_top_left_mask |= TOP_LEFT_TOPL_AVAILABLE;
}
}
}
ps_dec->u2_mby = u2_mb_y;
ps_dec->u2_mbx = u2_mb_x;
ps_cur_mb_info->u2_mbx = u2_mb_x;
ps_cur_mb_info->u2_mby = u2_mb_y;
ps_cur_mb_info->u1_topmb = u1_top_mb;
ps_dec->i4_submb_ofst += SUB_BLK_SIZE;
ps_dec->u1_mb_ngbr_availablity = u1_mb_ngbr_avail;
ps_cur_mb_info->u1_mb_ngbr_availablity = u1_mb_ngbr_avail;
ps_cur_mb_info->u1_mb_field_decodingflag = u1_cur_mb_field;
ps_cur_mb_info->u2_top_left_avail_mask = u2_top_left_mask;
ps_cur_mb_info->u2_top_right_avail_mask = u2_top_right_mask;
ih264d_get_mbaff_neighbours(ps_dec, ps_cur_mb_info, u1_cur_mb_field);
return (OK);
}
/*****************************************************************************/
/* */
/* Function Name : get_mb_info_cabac */
/* */
/* Description : This function sets the following information of cur MB */
/* (a) mb_x and mb_y */
/* (b) Neighbour availablity */
/* (c) Macroblock location in the frame buffer */
/* (e) leftMb parama and TopMb params of curMB */
/* (f) For Mbaff case leftMb params and TopMb params of */
/* bottomMb are also set if curMB is top */
/* (g) For mbaff predicts field/frame u4_flag for topMb */
/* and sets the field/frame for botMb. This is */
/* written in ps_dec->u1_cur_mb_fld_dec_flag */
/* */
/* Inputs : pointer to decstruct */
/* pointer to current mb info */
/* currentMbaddress */
/* */
/* Processing : leftMb and TopMb params are used by DecMbskip and */
/* DecCtxMbfield modules so that these modules do not */
/* check for neigbour availability and then find the */
/* neigbours for context increments */
/* */
/* Returns : OK */
/* */
/* Issues : <List any issues or problems with this function> */
/* */
/* Revision History: */
/* */
/* DD MM YYYY Author(s) Changes (Describe the changes made) */
/* 13 07 2002 Jay Draft */
/* */
/*****************************************************************************/
UWORD32 ih264d_get_mb_info_cabac_nonmbaff(dec_struct_t *ps_dec,
const UWORD16 u2_cur_mb_address,
dec_mb_info_t * ps_cur_mb_info,
UWORD32 u4_mbskip)
{
WORD32 mb_x;
WORD32 mb_y;
UWORD32 u1_mb_ngbr_avail = 0;
UWORD32 u2_frm_width_in_mb = ps_dec->u2_frm_wd_in_mbs;
UWORD32 u1_top_mb = 1;
WORD32 i2_prev_slice_mbx = ps_dec->i2_prev_slice_mbx;
UWORD32 u2_top_right_mask = TOP_RIGHT_DEFAULT_AVAILABLE;
UWORD32 u2_top_left_mask = TOP_LEFT_DEFAULT_AVAILABLE;
ctxt_inc_mb_info_t * const p_ctx_inc_mb_map = ps_dec->p_ctxt_inc_mb_map;
/*--------------------------------------------------------------------*/
/* Calculate values of mb_x and mb_y */
/*--------------------------------------------------------------------*/
mb_x = (WORD16)ps_dec->u2_mbx;
mb_y = (WORD16)ps_dec->u2_mby;
ps_dec->u2_cur_mb_addr = u2_cur_mb_address;
mb_x++;
if((UWORD32)mb_x == u2_frm_width_in_mb)
{
mb_x = 0;
mb_y++;
}
/*********************************************************************/
/* Cabac Context Initialisations */
/*********************************************************************/
ps_dec->ps_curr_ctxt_mb_info = p_ctx_inc_mb_map + mb_x;
ps_dec->p_left_ctxt_mb_info = p_ctx_inc_mb_map - 1;
ps_dec->p_top_ctxt_mb_info = p_ctx_inc_mb_map - 1;
/********************************************************************/
/* neighbour availablility */
/********************************************************************/
if(mb_y > ps_dec->i2_prev_slice_mby)
{
/* if not in the immemdiate row of prev slice end then top
will be available */
if(mb_y > (ps_dec->i2_prev_slice_mby + 1))
i2_prev_slice_mbx = -1;
if(mb_x > i2_prev_slice_mbx)
{
u1_mb_ngbr_avail |= TOP_MB_AVAILABLE_MASK;
u2_top_right_mask |= TOP_RIGHT_TOP_AVAILABLE;
u2_top_left_mask |= TOP_LEFT_TOP_AVAILABLE;
ps_dec->p_top_ctxt_mb_info = ps_dec->ps_curr_ctxt_mb_info;
}
if((mb_x > (i2_prev_slice_mbx - 1))
&& ((UWORD32)mb_x != (u2_frm_width_in_mb - 1)))
{
u1_mb_ngbr_avail |= TOP_RIGHT_MB_AVAILABLE_MASK;
u2_top_right_mask |= TOP_RIGHT_TOPR_AVAILABLE;
}
if(mb_x > (i2_prev_slice_mbx + 1))
{
u1_mb_ngbr_avail |= TOP_LEFT_MB_AVAILABLE_MASK;
u2_top_left_mask |= TOP_LEFT_TOPL_AVAILABLE;
}
/* Next row */
i2_prev_slice_mbx = -1;
}
/* Same row */
if(mb_x > (i2_prev_slice_mbx + 1))
{
u1_mb_ngbr_avail |= LEFT_MB_AVAILABLE_MASK;
u2_top_left_mask |= TOP_LEFT_LEFT_AVAILABLE;
ps_dec->p_left_ctxt_mb_info = ps_dec->ps_curr_ctxt_mb_info - 1;
}
{
mb_neigbour_params_t *ps_cur_mb_row = ps_dec->ps_cur_mb_row;
mb_neigbour_params_t *ps_top_mb_row = ps_dec->ps_top_mb_row;
/* copy the parameters of topleft Mb */
ps_cur_mb_info->u1_topleft_mbtype = ps_dec->u1_topleft_mbtype;
/* Neighbour pointer assignments*/
ps_cur_mb_info->ps_curmb = ps_cur_mb_row + mb_x;
ps_cur_mb_info->ps_left_mb = ps_cur_mb_row + mb_x - 1;
ps_cur_mb_info->ps_top_mb = ps_top_mb_row + mb_x;
ps_cur_mb_info->ps_top_right_mb = ps_top_mb_row + mb_x + 1;
/* Update the parameters of topleftmb*/
ps_dec->u1_topleft_mbtype = ps_cur_mb_info->ps_top_mb->u1_mb_type;
}
ps_dec->u2_mby = mb_y;
ps_dec->u2_mbx = mb_x;
ps_cur_mb_info->u2_mbx = mb_x;
ps_cur_mb_info->u2_mby = mb_y;
ps_cur_mb_info->u1_topmb = u1_top_mb;
ps_dec->i4_submb_ofst += SUB_BLK_SIZE;
ps_dec->u1_mb_ngbr_availablity = u1_mb_ngbr_avail;
ps_cur_mb_info->u1_mb_ngbr_availablity = u1_mb_ngbr_avail;
ps_cur_mb_info->ps_curmb->u1_mb_fld = ps_dec->u1_cur_mb_fld_dec_flag;
ps_cur_mb_info->u1_mb_field_decodingflag = ps_dec->u1_cur_mb_fld_dec_flag;
ps_cur_mb_info->u2_top_left_avail_mask = u2_top_left_mask;
ps_cur_mb_info->u2_top_right_avail_mask = u2_top_right_mask;
/*********************************************************************/
/* Assign the neigbours */
/*********************************************************************/
if(u4_mbskip)
{
UWORD32 u4_ctx_inc =
2
- ((!!(ps_dec->p_top_ctxt_mb_info->u1_mb_type
& CAB_SKIP_MASK))
+ (!!(ps_dec->p_left_ctxt_mb_info->u1_mb_type
& CAB_SKIP_MASK)));
u4_mbskip = ih264d_decode_bin(u4_ctx_inc, ps_dec->p_mb_skip_flag_t,
ps_dec->ps_bitstrm, &ps_dec->s_cab_dec_env);
if(!u4_mbskip)
{
if(!(u1_mb_ngbr_avail & LEFT_MB_AVAILABLE_MASK))
{
UWORD32 *pu4_buf;
UWORD8 *pu1_buf;
pu1_buf = ps_dec->pu1_left_nnz_y;
pu4_buf = (UWORD32 *)pu1_buf;
*pu4_buf = 0;
pu1_buf = ps_dec->pu1_left_nnz_uv;
pu4_buf = (UWORD32 *)pu1_buf;
*pu4_buf = 0;
*(ps_dec->pu1_left_yuv_dc_csbp) = 0;
MEMSET_16BYTES(&ps_dec->pu1_left_mv_ctxt_inc[0][0], 0);
*(UWORD32 *)ps_dec->pi1_left_ref_idx_ctxt_inc = 0;
}
if(!(u1_mb_ngbr_avail & TOP_MB_AVAILABLE_MASK))
{
MEMSET_16BYTES(ps_dec->ps_curr_ctxt_mb_info->u1_mv, 0);
memset(ps_dec->ps_curr_ctxt_mb_info->i1_ref_idx, 0, 4);
}
}
}
return (u4_mbskip);
}
/*****************************************************************************/
/* */
/* Function Name : get_mb_info_cabac */
/* */
/* Description : This function sets the following information of cur MB */
/* (a) mb_x and mb_y */
/* (b) Neighbour availablity */
/* (c) Macroblock location in the frame buffer */
/* (e) leftMb parama and TopMb params of curMB */
/* (f) For Mbaff case leftMb params and TopMb params of */
/* bottomMb are also set if curMB is top */
/* (g) For mbaff predicts field/frame u4_flag for topMb */
/* and sets the field/frame for botMb. This is */
/* written in ps_dec->u1_cur_mb_fld_dec_flag */
/* */
/* Inputs : pointer to decstruct */
/* pointer to current mb info */
/* currentMbaddress */
/* */
/* Processing : leftMb and TopMb params are used by DecMbskip and */
/* DecCtxMbfield modules so that these modules do not */
/* check for neigbour availability and then find the */
/* neigbours for context increments */
/* */
/* Returns : OK */
/* */
/* Issues : <List any issues or problems with this function> */
/* */
/* Revision History: */
/* */
/* DD MM YYYY Author(s) Changes (Describe the changes made) */
/* 13 07 2002 Jay Draft */
/* */
/*****************************************************************************/
UWORD32 ih264d_get_mb_info_cabac_mbaff(dec_struct_t *ps_dec,
const UWORD16 u2_cur_mb_address,
dec_mb_info_t * ps_cur_mb_info,
UWORD32 u4_mbskip)
{
WORD32 mb_x;
WORD32 mb_y;
UWORD8 u1_mb_ngbr_avail = 0;
UWORD16 u2_frm_width_in_mb = ps_dec->u2_frm_wd_in_mbs;
ctxt_inc_mb_info_t * const p_ctx_inc_mb_map = ps_dec->p_ctxt_inc_mb_map;
ctxt_inc_mb_info_t *ps_curr_ctxt, *ps_top_ctxt, *ps_left_ctxt;
mb_neigbour_params_t *ps_cur_mb_row = ps_dec->ps_cur_mb_row;
mb_neigbour_params_t *ps_top_mb_row = ps_dec->ps_top_mb_row;
UWORD32 u4_left_mb_pair_fld = 0;
UWORD32 u4_top_mb_pair_fld = 0;
UWORD8 u1_cur_mb_field = 0;
UWORD8 u1_top_mb = 1 - (u2_cur_mb_address & 0x01);
WORD16 i2_prev_slice_mbx = ps_dec->i2_prev_slice_mbx;
UWORD16 u2_top_right_mask = TOP_RIGHT_DEFAULT_AVAILABLE;
UWORD16 u2_top_left_mask = TOP_LEFT_DEFAULT_AVAILABLE;
/*--------------------------------------------------------------------*/
/* Calculate values of mb_x and mb_y */
/*--------------------------------------------------------------------*/
mb_x = (WORD16)ps_dec->u2_mbx;
mb_y = (WORD16)ps_dec->u2_mby;
ps_dec->u2_cur_mb_addr = u2_cur_mb_address;
ps_top_ctxt = ps_left_ctxt = p_ctx_inc_mb_map - 1;
if(u1_top_mb)
{
ctxt_inc_mb_info_t *ps_left_mb_of_bot = ps_left_ctxt;
ctxt_inc_mb_info_t *ps_top_mb_of_bot = ps_top_ctxt;
mb_x++;
if(mb_x == u2_frm_width_in_mb)
{
mb_x = 0;
mb_y += 2;
}
ps_curr_ctxt = p_ctx_inc_mb_map + (mb_x << 1);
if(mb_y > ps_dec->i2_prev_slice_mby)
{
UWORD8 u1_cur_mb_fld_flag_known = 0;
/* Next row */
if(mb_x > 0)
{
/***********************************************************************/
/* Left Mb is avialable */
/***********************************************************************/
u1_mb_ngbr_avail |= LEFT_MB_AVAILABLE_MASK;
ps_left_ctxt = ps_curr_ctxt - 2;
ps_left_mb_of_bot = ps_curr_ctxt - 1;
u1_cur_mb_field = u4_left_mb_pair_fld = ps_cur_mb_row[(mb_x
<< 1) - 1].u1_mb_fld;
u1_cur_mb_fld_flag_known = 1;
u2_top_left_mask |= TOP_LEFT_LEFT_AVAILABLE;
}
/* if not in the immemdiate row of prev slice end then top
will be available */
if(mb_y > (ps_dec->i2_prev_slice_mby + 2))
i2_prev_slice_mbx = -1;
if(mb_x > i2_prev_slice_mbx)
{
/*********************************************************************/
/* Top Mb is avialable */
/*********************************************************************/
u1_mb_ngbr_avail |= TOP_MB_AVAILABLE_MASK;
u2_top_right_mask |= TOP_RIGHT_TOP_AVAILABLE;
u2_top_left_mask |= TOP_LEFT_TOP_AVAILABLE;
/* point to MbAddrB + 1 */
ps_top_ctxt = ps_curr_ctxt + 1;
u4_top_mb_pair_fld = ps_top_mb_row[(mb_x << 1)].u1_mb_fld;
u1_cur_mb_field =
u1_cur_mb_fld_flag_known ?
u1_cur_mb_field :
u4_top_mb_pair_fld;
ps_top_mb_of_bot = u1_cur_mb_field ? ps_top_ctxt : ps_curr_ctxt;
/* MbAddrB */
ps_top_ctxt -= (u1_cur_mb_field && u4_top_mb_pair_fld);
}
if((mb_x > (i2_prev_slice_mbx - 1))
&& (mb_x != (u2_frm_width_in_mb - 1)))
{
u1_mb_ngbr_avail |= TOP_RIGHT_MB_AVAILABLE_MASK;
u2_top_right_mask |= TOP_RIGHT_TOPR_AVAILABLE;
}
if(mb_x > (i2_prev_slice_mbx + 1))
{
u1_mb_ngbr_avail |= TOP_LEFT_MB_AVAILABLE_MASK;
u2_top_left_mask |= TOP_LEFT_TOPL_AVAILABLE;
}
}
else
{
/* Same row */
if(mb_x > (i2_prev_slice_mbx + 1))
{
/***************************************************************/
/* Left Mb is avialable */
/***************************************************************/
u1_mb_ngbr_avail |= LEFT_MB_AVAILABLE_MASK;
u1_cur_mb_field = u4_left_mb_pair_fld = ps_cur_mb_row[(mb_x
<< 1) - 1].u1_mb_fld;
ps_left_ctxt = ps_curr_ctxt - 2;
ps_left_mb_of_bot = ps_curr_ctxt - 1;
u2_top_left_mask |= TOP_LEFT_LEFT_AVAILABLE;
}
}
/*********************************************************/
/* Check whether the call is from I slice or Inter slice */
/*********************************************************/
if(u4_mbskip)
{
UWORD32 u4_ctx_inc = 2
- ((!!(ps_top_ctxt->u1_mb_type & CAB_SKIP_MASK))
+ (!!(ps_left_ctxt->u1_mb_type
& CAB_SKIP_MASK)));
dec_bit_stream_t * const ps_bitstrm = ps_dec->ps_bitstrm;
decoding_envirnoment_t *ps_cab_dec_env = &ps_dec->s_cab_dec_env;
bin_ctxt_model_t *p_mb_skip_flag_t = ps_dec->p_mb_skip_flag_t;
ps_dec->u4_next_mb_skip = 0;
u4_mbskip = ih264d_decode_bin(u4_ctx_inc, p_mb_skip_flag_t,
ps_bitstrm, ps_cab_dec_env);
if(u4_mbskip)
{
UWORD32 u4_next_mbskip;
ps_curr_ctxt->u1_mb_type = CAB_SKIP;
u4_ctx_inc =
2
- ((!!(ps_top_mb_of_bot->u1_mb_type
& CAB_SKIP_MASK))
+ (!!(ps_left_mb_of_bot->u1_mb_type
& CAB_SKIP_MASK)));
/* Decode the skip u4_flag of bottom Mb */
u4_next_mbskip = ih264d_decode_bin(u4_ctx_inc, p_mb_skip_flag_t,
ps_bitstrm,
ps_cab_dec_env);
ps_dec->u4_next_mb_skip = u4_next_mbskip;
if(!u4_next_mbskip)
{
u4_ctx_inc = u4_top_mb_pair_fld + u4_left_mb_pair_fld;
u1_cur_mb_field = ih264d_decode_bin(
u4_ctx_inc, ps_dec->p_mb_field_dec_flag_t,
ps_bitstrm, ps_cab_dec_env);
}
}
}
if(!u4_mbskip)
{
UWORD32 u4_ctx_inc = u4_top_mb_pair_fld + u4_left_mb_pair_fld;
u1_cur_mb_field = ih264d_decode_bin(u4_ctx_inc,
ps_dec->p_mb_field_dec_flag_t,
ps_dec->ps_bitstrm,
&ps_dec->s_cab_dec_env);
}
ps_dec->u1_cur_mb_fld_dec_flag = u1_cur_mb_field;
ps_dec->u2_top_left_mask = u2_top_left_mask;
ps_dec->u2_top_right_mask = u2_top_right_mask;
ps_dec->u2_mby = mb_y;
ps_dec->u2_mbx = mb_x;
}
else
{
u1_cur_mb_field = ps_dec->u1_cur_mb_fld_dec_flag;
u1_mb_ngbr_avail = ps_dec->u1_mb_ngbr_availablity;
u2_top_left_mask = ps_dec->u2_top_left_mask;
u2_top_right_mask = ps_dec->u2_top_right_mask;
ps_curr_ctxt = p_ctx_inc_mb_map + (mb_x << 1) + 1;
if(u1_mb_ngbr_avail & LEFT_MB_AVAILABLE_MASK)
{
u4_left_mb_pair_fld = ps_cur_mb_row[(mb_x << 1) - 1].u1_mb_fld;
/* point to A if top else A+1 */
ps_left_ctxt = ps_curr_ctxt - 2
- (u4_left_mb_pair_fld != u1_cur_mb_field);
}
if(u1_cur_mb_field)
{
if(u1_mb_ngbr_avail & TOP_MB_AVAILABLE_MASK)
{
/* point to MbAddrB + 1 */
ps_top_ctxt = ps_curr_ctxt;
}
}
else
{
/* Top is available */
u1_mb_ngbr_avail |= TOP_MB_AVAILABLE_MASK;
u2_top_right_mask |= TOP_RIGHT_TOP_AVAILABLE;
u2_top_left_mask |= TOP_LEFT_TOP_AVAILABLE;
/* Top Right not available */
u1_mb_ngbr_avail &= TOP_RT_SUBBLOCK_MASK_MOD;
u2_top_right_mask &= (~TOP_RIGHT_TOPR_AVAILABLE);
if(u1_mb_ngbr_avail & LEFT_MB_AVAILABLE_MASK)
{
u1_mb_ngbr_avail |= TOP_LEFT_MB_AVAILABLE_MASK;
u2_top_left_mask |= TOP_LEFT_LEFT_AVAILABLE;
u2_top_left_mask |= TOP_LEFT_TOPL_AVAILABLE;
}
/* CurMbAddr - 1 */
ps_top_ctxt = ps_curr_ctxt - 1;
}
if(u4_mbskip)
{
if(ps_curr_ctxt[-1].u1_mb_type & CAB_SKIP_MASK)
{
/* If previous mb is skipped, return value of next mb skip */
u4_mbskip = ps_dec->u4_next_mb_skip;
}
else
{
/* If previous mb is not skipped then call DecMbSkip */
UWORD32 u4_ctx_inc =
2
- ((!!(ps_top_ctxt->u1_mb_type
& CAB_SKIP_MASK))
+ (!!(ps_left_ctxt->u1_mb_type
& CAB_SKIP_MASK)));
u4_mbskip = ih264d_decode_bin(u4_ctx_inc,
ps_dec->p_mb_skip_flag_t,
ps_dec->ps_bitstrm,
&ps_dec->s_cab_dec_env);
}
}
}
ps_cur_mb_info->u2_mbx = mb_x;
ps_cur_mb_info->u2_mby = mb_y;
ps_cur_mb_info->u1_topmb = u1_top_mb;
ps_dec->i4_submb_ofst += SUB_BLK_SIZE;
ps_dec->u1_mb_ngbr_availablity = u1_mb_ngbr_avail;
ps_cur_mb_info->u1_mb_ngbr_availablity = u1_mb_ngbr_avail;
ps_cur_mb_info->u1_mb_field_decodingflag = u1_cur_mb_field;
ps_cur_mb_info->u2_top_left_avail_mask = u2_top_left_mask;
ps_cur_mb_info->u2_top_right_avail_mask = u2_top_right_mask;
ih264d_get_mbaff_neighbours(ps_dec, ps_cur_mb_info, u1_cur_mb_field);
{
ih264d_get_cabac_context_mbaff(ps_dec, ps_cur_mb_info, u4_mbskip);
}
{
bin_ctxt_model_t *p_cabac_ctxt_table_t = ps_dec->p_cabac_ctxt_table_t;
if(u1_cur_mb_field)
{
p_cabac_ctxt_table_t += SIGNIFICANT_COEFF_FLAG_FLD;
}
else
{
p_cabac_ctxt_table_t += SIGNIFICANT_COEFF_FLAG_FRAME;
}
{
bin_ctxt_model_t * * p_significant_coeff_flag_t =
ps_dec->p_significant_coeff_flag_t;
p_significant_coeff_flag_t[0] = p_cabac_ctxt_table_t
+ SIG_COEFF_CTXT_CAT_0_OFFSET;
p_significant_coeff_flag_t[1] = p_cabac_ctxt_table_t
+ SIG_COEFF_CTXT_CAT_1_OFFSET;
p_significant_coeff_flag_t[2] = p_cabac_ctxt_table_t
+ SIG_COEFF_CTXT_CAT_2_OFFSET;
p_significant_coeff_flag_t[3] = p_cabac_ctxt_table_t
+ SIG_COEFF_CTXT_CAT_3_OFFSET;
p_significant_coeff_flag_t[4] = p_cabac_ctxt_table_t
+ SIG_COEFF_CTXT_CAT_4_OFFSET;
p_significant_coeff_flag_t[5] = p_cabac_ctxt_table_t
+ SIG_COEFF_CTXT_CAT_5_OFFSET;
}
}
return (u4_mbskip);
}
/*****************************************************************************/
/* */
/* Function Name : ih264d_get_cabac_context_mbaff */
/* */
/* Description : Gets the current macroblock Cabac Context and sets the */
/* top and left cabac context ptrs in CtxIncMbMap */
/* 1. For Coss field left neigbours it alters coded block */
/* u4_flag , motion vectors, reference indices, cbp of */
/* the left neigbours which increases the code i4_size */
/* 2. For Coss field top neigbours it alters motion */
/* vectors reference indices of the top neigbours */
/* which further increases the code i4_size */
/* */
/* Inputs : 1. dec_struct_t */
/* 2. CurMbAddr used for Mbaff (only to see if curMB */
/* is top or bottom) */
/* 3. uc_curMbFldDecFlag only for Mbaff */
/* */
/* Returns : 0 */
/* */
/* Issues : code i4_size can be reduced if ui_CodedBlockFlag storage */
/* structure in context is changed. This change however */
/* would break the parseResidual4x4Cabac asm routine. */
/* */
/* Revision History: */
/* */
/* DD MM YYYY Author(s) Changes (Describe the changes made) */
/* 18 06 2005 Jay */
/* */
/*****************************************************************************/
UWORD32 ih264d_get_cabac_context_mbaff(dec_struct_t * ps_dec,
dec_mb_info_t *ps_cur_mb_info,
UWORD32 u4_mbskip)
{
const UWORD8 u1_mb_ngbr_availablity = ps_dec->u1_mb_ngbr_availablity;
ctxt_inc_mb_info_t * const p_ctx_inc_mb_map = ps_dec->p_ctxt_inc_mb_map;
UWORD8 (*pu1_left_mv_ctxt_inc_2d)[4] = &ps_dec->pu1_left_mv_ctxt_inc[0];
WORD8 (*pi1_left_ref_idx_ctxt_inc) = ps_dec->pi1_left_ref_idx_ctxt_inc;
const UWORD8 u1_cur_mb_fld_flag = ps_cur_mb_info->u1_mb_field_decodingflag;
const UWORD8 u1_topmb = ps_cur_mb_info->u1_topmb;
const UWORD8 uc_botMb = 1 - ps_cur_mb_info->u1_topmb;
ctxt_inc_mb_info_t * ps_leftMB;
ps_dec->ps_curr_ctxt_mb_info = p_ctx_inc_mb_map + (ps_dec->u2_mbx << 1);
ps_dec->p_top_ctxt_mb_info = ps_dec->ps_curr_ctxt_mb_info;
if(u1_topmb)
{
pu1_left_mv_ctxt_inc_2d = ps_dec->u1_left_mv_ctxt_inc_arr[0];
pi1_left_ref_idx_ctxt_inc = &ps_dec->i1_left_ref_idx_ctx_inc_arr[0][0];
ps_dec->pu1_left_yuv_dc_csbp = &ps_dec->u1_yuv_dc_csbp_topmb;
}
else
{
/* uc_botMb */
pu1_left_mv_ctxt_inc_2d = ps_dec->u1_left_mv_ctxt_inc_arr[1];
pi1_left_ref_idx_ctxt_inc = &ps_dec->i1_left_ref_idx_ctx_inc_arr[1][0];
ps_dec->pu1_left_yuv_dc_csbp = &ps_dec->u1_yuv_dc_csbp_bot_mb;
ps_dec->ps_curr_ctxt_mb_info += 1;
}
ps_dec->pu1_left_mv_ctxt_inc = pu1_left_mv_ctxt_inc_2d;
ps_dec->pi1_left_ref_idx_ctxt_inc = pi1_left_ref_idx_ctxt_inc;
if(u1_mb_ngbr_availablity & LEFT_MB_AVAILABLE_MASK)
{
const UWORD8 u1_left_mb_fld_flag = ps_cur_mb_info->ps_left_mb->u1_mb_fld;
ps_leftMB = ps_dec->ps_curr_ctxt_mb_info - 2;
if(u1_left_mb_fld_flag != u1_cur_mb_fld_flag)
{
ctxt_inc_mb_info_t *ps_tempLeft;
UWORD8 u1_cbp_t, u1_cbp_b;
UWORD8 u1_cr_cpb;
ps_leftMB -= uc_botMb;
ps_tempLeft = ps_dec->ps_left_mb_ctxt_info;
ps_tempLeft->u1_mb_type = ps_leftMB->u1_mb_type;
ps_tempLeft->u1_intra_chroma_pred_mode =
ps_leftMB->u1_intra_chroma_pred_mode;
ps_tempLeft->u1_transform8x8_ctxt = ps_leftMB->u1_transform8x8_ctxt;
u1_cr_cpb = ps_leftMB->u1_cbp;
/*****************************************************************/
/* reform RefIdx, CBP, MV and CBF ctxInc taking care of A and A+1*/
/*****************************************************************/
if(u1_cur_mb_fld_flag)
{
/* current MB is a FLD and left a FRM */
UWORD8 (* const pu1_left_mv_ctxt_inc_2d_arr_top)[4] =
ps_dec->u1_left_mv_ctxt_inc_arr[0];
UWORD8 (* const pu1_left_mv_ctxt_inc_2d_arr_bot)[4] =
ps_dec->u1_left_mv_ctxt_inc_arr[1];
WORD8 (* const i1_left_ref_idx_ctxt_inc_arr_top) =
&ps_dec->i1_left_ref_idx_ctx_inc_arr[0][0];
WORD8 (* const i1_left_ref_idx_ctxt_inc_arr_bot) =
&ps_dec->i1_left_ref_idx_ctx_inc_arr[1][0];
u1_cbp_t = ps_leftMB->u1_cbp;
u1_cbp_b = (ps_leftMB + 1)->u1_cbp;
ps_tempLeft->u1_cbp = (u1_cbp_t & 0x02)
| ((u1_cbp_b & 0x02) << 2);
// set motionvectors as
// 0T = 0T 0B = 0T
// 1T = 2T 1B = 2T
// 2T = 0B 2B = 0B
// 3T = 2B 3B = 2B
if(u1_topmb)
{
/********************************************/
/* Bottoms DC CBF = Top DC CBF */
/********************************************/
ps_dec->u1_yuv_dc_csbp_bot_mb =
ps_dec->u1_yuv_dc_csbp_topmb;
*(UWORD32 *)pu1_left_mv_ctxt_inc_2d[3] =
*(UWORD32 *)pu1_left_mv_ctxt_inc_2d_arr_bot[2];
*(UWORD32 *)pu1_left_mv_ctxt_inc_2d[1] =
*(UWORD32 *)pu1_left_mv_ctxt_inc_2d_arr_top[2];
*(UWORD32 *)pu1_left_mv_ctxt_inc_2d[2] =
*(UWORD32 *)pu1_left_mv_ctxt_inc_2d_arr_bot[0];
*(UWORD32 *)pu1_left_mv_ctxt_inc_2d[0] =
*(UWORD32 *)pu1_left_mv_ctxt_inc_2d_arr_top[0];
i1_left_ref_idx_ctxt_inc_arr_top[1] =
i1_left_ref_idx_ctxt_inc_arr_bot[0];
i1_left_ref_idx_ctxt_inc_arr_top[3] =
i1_left_ref_idx_ctxt_inc_arr_bot[2];
*(UWORD32 *)(i1_left_ref_idx_ctxt_inc_arr_bot) =
*(UWORD32 *)(i1_left_ref_idx_ctxt_inc_arr_top);
memcpy(pu1_left_mv_ctxt_inc_2d_arr_bot,
pu1_left_mv_ctxt_inc_2d_arr_top, 16);
}
{
UWORD8 i;
for(i = 0; i < 4; i++)
{
pu1_left_mv_ctxt_inc_2d[i][1] >>= 1;
pu1_left_mv_ctxt_inc_2d[i][3] >>= 1;
}
}
}
else
{
/* current MB is a FRM and left FLD */
if(u1_topmb)
{
u1_cbp_t = ps_leftMB->u1_cbp;
u1_cbp_t = (u1_cbp_t & 0x02);
ps_tempLeft->u1_cbp = (u1_cbp_t | (u1_cbp_t << 2));
/********************************************/
/* Bottoms DC CBF = Top DC CBF */
/********************************************/
ps_dec->u1_yuv_dc_csbp_bot_mb =
ps_dec->u1_yuv_dc_csbp_topmb;
// set motionvectors as
// 3B = 2B = 3T
// 1B = 0B = 2T
// 3T = 2T = 1T
// 1T = 0T = 0T
*(UWORD32 *)pu1_left_mv_ctxt_inc_2d[7] =
*(UWORD32 *)pu1_left_mv_ctxt_inc_2d[3];
*(UWORD32 *)pu1_left_mv_ctxt_inc_2d[6] =
*(UWORD32 *)pu1_left_mv_ctxt_inc_2d[3];
*(UWORD32 *)pu1_left_mv_ctxt_inc_2d[5] =
*(UWORD32 *)pu1_left_mv_ctxt_inc_2d[2];
*(UWORD32 *)pu1_left_mv_ctxt_inc_2d[4] =
*(UWORD32 *)pu1_left_mv_ctxt_inc_2d[2];
*(UWORD32 *)pu1_left_mv_ctxt_inc_2d[3] =
*(UWORD32 *)pu1_left_mv_ctxt_inc_2d[1];
*(UWORD32 *)pu1_left_mv_ctxt_inc_2d[2] =
*(UWORD32 *)pu1_left_mv_ctxt_inc_2d[1];
*(UWORD32 *)pu1_left_mv_ctxt_inc_2d[1] =
*(UWORD32 *)pu1_left_mv_ctxt_inc_2d[0];
pi1_left_ref_idx_ctxt_inc[7] = (pi1_left_ref_idx_ctxt_inc[3]
- 1);
pi1_left_ref_idx_ctxt_inc[6] = (pi1_left_ref_idx_ctxt_inc[3]
- 1);
pi1_left_ref_idx_ctxt_inc[5] = (pi1_left_ref_idx_ctxt_inc[1]
- 1);
pi1_left_ref_idx_ctxt_inc[4] = (pi1_left_ref_idx_ctxt_inc[1]
- 1);
pi1_left_ref_idx_ctxt_inc[3] = (pi1_left_ref_idx_ctxt_inc[2]
- 1);
pi1_left_ref_idx_ctxt_inc[2] = (pi1_left_ref_idx_ctxt_inc[2]
- 1);
pi1_left_ref_idx_ctxt_inc[1] = (pi1_left_ref_idx_ctxt_inc[0]
- 1);
pi1_left_ref_idx_ctxt_inc[0] = (pi1_left_ref_idx_ctxt_inc[0]
- 1);
}
else
{
u1_cbp_t = ps_leftMB->u1_cbp;
u1_cbp_t = (u1_cbp_t & 0x08);
ps_tempLeft->u1_cbp = (u1_cbp_t | (u1_cbp_t >> 2));
}
{
UWORD8 i;
for(i = 0; i < 4; i++)
{
pu1_left_mv_ctxt_inc_2d[i][1] <<= 1;
pu1_left_mv_ctxt_inc_2d[i][3] <<= 1;
}
}
}
ps_tempLeft->u1_cbp = ps_tempLeft->u1_cbp + ((u1_cr_cpb >> 4) << 4);
ps_leftMB = ps_tempLeft;
}
ps_dec->p_left_ctxt_mb_info = ps_leftMB;
}
else
{
ps_dec->p_left_ctxt_mb_info = p_ctx_inc_mb_map - 1;
if(!u4_mbskip)
{
*(ps_dec->pu1_left_yuv_dc_csbp) = 0;
MEMSET_16BYTES(&pu1_left_mv_ctxt_inc_2d[0][0], 0);
*(UWORD32 *)pi1_left_ref_idx_ctxt_inc = 0;
}
}
/*************************************************************************/
/* Now get the top context mb info */
/*************************************************************************/
{
UWORD8 (*u1_top_mv_ctxt_inc_arr_2d)[4] =
ps_dec->ps_curr_ctxt_mb_info->u1_mv;
WORD8 (*pi1_top_ref_idx_ctxt_inc) =
ps_dec->ps_curr_ctxt_mb_info->i1_ref_idx;
UWORD8 uc_topMbFldDecFlag = ps_cur_mb_info->ps_top_mb->u1_mb_fld;
if(u1_mb_ngbr_availablity & TOP_MB_AVAILABLE_MASK)
{
if(ps_cur_mb_info->i1_offset)
ps_dec->p_top_ctxt_mb_info += 1;
if(!u4_mbskip)
{
memcpy(u1_top_mv_ctxt_inc_arr_2d,
&ps_dec->p_top_ctxt_mb_info->u1_mv, 16);
memcpy(pi1_top_ref_idx_ctxt_inc,
&ps_dec->p_top_ctxt_mb_info->i1_ref_idx, 4);
if(uc_topMbFldDecFlag ^ u1_cur_mb_fld_flag)
{
UWORD8 i;
if(u1_cur_mb_fld_flag)
{
for(i = 0; i < 4; i++)
{
u1_top_mv_ctxt_inc_arr_2d[i][1] >>= 1;
u1_top_mv_ctxt_inc_arr_2d[i][3] >>= 1;
}
}
else
{
for(i = 0; i < 4; i++)
{
u1_top_mv_ctxt_inc_arr_2d[i][1] <<= 1;
u1_top_mv_ctxt_inc_arr_2d[i][3] <<= 1;
pi1_top_ref_idx_ctxt_inc[i] -= 1;
}
}
}
}
}
else
{
ps_dec->p_top_ctxt_mb_info = p_ctx_inc_mb_map - 1;
if(!u4_mbskip)
{
MEMSET_16BYTES(&u1_top_mv_ctxt_inc_arr_2d[0][0], 0);
memset(pi1_top_ref_idx_ctxt_inc, 0, 4);
}
}
}
return OK;
}
/*****************************************************************************/
/* */
/* Function Name : ih264d_update_mbaff_left_nnz */
/* */
/* Description : This function updates the left luma and chroma nnz for */
/* mbaff cases. */
/* */
/* Inputs : <What inputs does the function take?> */
/* Globals : <Does it use any global variables?> */
/* Processing : <Describe how the function operates - include algorithm */
/* description> */
/* Outputs : <What does the function produce?> */
/* Returns : <What does the function return?> */
/* */
/* Issues : <List any issues or problems with this function> */
/* */
/* Revision History: */
/* */
/* DD MM YYYY Author(s) Changes (Describe the changes made) */
/* 13 07 2002 Ittiam Draft */
/* */
/*****************************************************************************/
void ih264d_update_mbaff_left_nnz(dec_struct_t * ps_dec,
dec_mb_info_t * ps_cur_mb_info)
{
UWORD32 *pu4_buf;
UWORD8 *pu1_buf;
if(ps_cur_mb_info->u1_topmb)
{
pu1_buf = ps_dec->pu1_left_nnz_y;
pu4_buf = (UWORD32 *)pu1_buf;
ps_dec->u4_n_left_temp_y = *pu4_buf;
pu1_buf = ps_dec->pu1_left_nnz_uv;
pu4_buf = (UWORD32 *)pu1_buf;
ps_dec->u4_n_left_temp_uv = *pu4_buf;
}
else
{
ps_dec->u4_n_leftY[0] = ps_dec->u4_n_left_temp_y;
pu1_buf = ps_dec->pu1_left_nnz_y;
pu4_buf = (UWORD32 *)pu1_buf;
ps_dec->u4_n_leftY[1] = *pu4_buf;
ps_dec->u4_n_left_cr[0] = ps_dec->u4_n_left_temp_uv;
pu1_buf = ps_dec->pu1_left_nnz_uv;
pu4_buf = (UWORD32 *)pu1_buf;
ps_dec->u4_n_left_cr[1] = *pu4_buf;
}
}
/*!
**************************************************************************
* \if Function name : ih264d_get_mbaff_neighbours \endif
*
* \brief
* Gets the neighbors for the current MB if it is of type MB-AFF
* frame.
*
* \return
* None
*
**************************************************************************
*/
void ih264d_get_mbaff_neighbours(dec_struct_t * ps_dec,
dec_mb_info_t * ps_cur_mb_info,
UWORD8 uc_curMbFldDecFlag)
{
mb_neigbour_params_t *ps_left_mb;
mb_neigbour_params_t *ps_top_mb;
mb_neigbour_params_t *ps_top_right_mb = NULL;
mb_neigbour_params_t *ps_curmb;
const UWORD8 u1_topmb = ps_cur_mb_info->u1_topmb;
const UWORD8 uc_botMb = 1 - u1_topmb;
const UWORD32 u4_mb_x = ps_cur_mb_info->u2_mbx;
/* Current MbParams location in top row buffer */
ps_curmb = ps_dec->ps_cur_mb_row + (u4_mb_x << 1) + uc_botMb;
ps_left_mb = ps_curmb - 2;
/* point to A if top else A+1 */
if(uc_botMb && (ps_left_mb->u1_mb_fld != uc_curMbFldDecFlag))
{
/* move from A + 1 to A */
ps_left_mb--;
}
ps_cur_mb_info->i1_offset = 0;
if((uc_curMbFldDecFlag == 0) && uc_botMb)
{
mb_neigbour_params_t *ps_topleft_mb;
/* CurMbAddr - 1 */
ps_top_mb = ps_curmb - 1;
/* Mark Top right Not available */
/* point to A */
ps_topleft_mb = ps_curmb - 3;
if(ps_topleft_mb->u1_mb_fld)
{
/* point to A + 1 */
ps_topleft_mb++;
}
ps_cur_mb_info->u1_topleft_mb_fld = ps_topleft_mb->u1_mb_fld;
ps_cur_mb_info->u1_topleft_mbtype = ps_topleft_mb->u1_mb_type;
}
else
{
/* Top = B + 1 */
ps_top_mb = ps_dec->ps_top_mb_row + (u4_mb_x << 1) + 1;
ps_top_right_mb = ps_top_mb + 2;
ps_cur_mb_info->i1_offset = 4;
/* TopRight = C + 1 */
/* TopLeft = D+1 */
ps_cur_mb_info->u1_topleft_mb_fld = ps_dec->u1_topleft_mb_fld_bot;
ps_cur_mb_info->u1_topleft_mbtype = ps_dec->u1_topleft_mbtype_bot;
if(uc_curMbFldDecFlag && u1_topmb)
{
if(ps_top_mb->u1_mb_fld)
{
/* MbAddrB */
ps_top_mb--;
ps_cur_mb_info->i1_offset = 0;
}
/* If topright is field then point to C */
ps_top_right_mb -= ps_top_right_mb->u1_mb_fld ? 1 : 0;
if(ps_cur_mb_info->u1_topleft_mb_fld)
{
/* TopLeft = D */
ps_cur_mb_info->u1_topleft_mb_fld = ps_dec->u1_topleft_mb_fld;
ps_cur_mb_info->u1_topleft_mbtype = ps_dec->u1_topleft_mbtype;
}
}
}
if(u1_topmb)
{
/* Update the parameters of topleftmb*/
ps_dec->u1_topleft_mb_fld = ps_top_mb->u1_mb_fld;
ps_dec->u1_topleft_mbtype = ps_top_mb->u1_mb_type;
/* Set invscan and dequantMatrixScan*/
if(uc_curMbFldDecFlag)
{
ps_dec->pu1_inv_scan = (UWORD8 *)gau1_ih264d_inv_scan_fld;
}
else
{
ps_dec->pu1_inv_scan = (UWORD8 *)gau1_ih264d_inv_scan;
}
ps_dec->pu2_quant_scale_y =
gau2_ih264_iquant_scale_4x4[ps_dec->u1_qp_y_rem6];
ps_dec->pu2_quant_scale_u =
gau2_ih264_iquant_scale_4x4[ps_dec->u1_qp_u_rem6];
ps_dec->pu2_quant_scale_v =
gau2_ih264_iquant_scale_4x4[ps_dec->u1_qp_v_rem6];
}
else
{
/* Update the parameters of topleftmb*/
mb_neigbour_params_t *ps_top_mb_temp = ps_dec->ps_top_mb_row
+ (u4_mb_x << 1) + 1;
ps_dec->u1_topleft_mb_fld_bot = ps_top_mb_temp->u1_mb_fld;
ps_dec->u1_topleft_mbtype_bot = ps_top_mb_temp->u1_mb_type;
}
ps_cur_mb_info->ps_left_mb = ps_left_mb;
ps_cur_mb_info->ps_top_mb = ps_top_mb;
ps_cur_mb_info->ps_top_right_mb = ps_top_right_mb;
ps_cur_mb_info->ps_curmb = ps_curmb;
ps_curmb->u1_mb_fld = uc_curMbFldDecFlag;
{
/* Form Left NNZ */
UWORD8 u1_is_left_mb_fld = ps_left_mb->u1_mb_fld;
UWORD8 *pu1_left_mb_pair_nnz_y = (UWORD8 *)&ps_dec->u4_n_leftY[0];
UWORD8 *pu1_left_mb_pair_nnz_uv = (UWORD8 *)&ps_dec->u4_n_left_cr[0];
UWORD8 *pu1_left_nnz_y = ps_dec->pu1_left_nnz_y;
UWORD8 *pu1_left_nnz_uv = ps_dec->pu1_left_nnz_uv;
if(uc_curMbFldDecFlag == u1_is_left_mb_fld)
{
*(UWORD32 *)pu1_left_nnz_y = *(UWORD32 *)(pu1_left_mb_pair_nnz_y
+ (uc_botMb << 2));
*(UWORD32 *)pu1_left_nnz_uv = *(UWORD32 *)(pu1_left_mb_pair_nnz_uv
+ (uc_botMb << 2));
}
else if((uc_curMbFldDecFlag == 0) && u1_topmb && u1_is_left_mb_fld)
{
/* 0 0 1 1 of u4_n_leftY[0], 0 0 2 2 of u4_n_left_cr[0] */
pu1_left_nnz_y[0] = pu1_left_nnz_y[1] = pu1_left_mb_pair_nnz_y[0];
pu1_left_nnz_y[2] = pu1_left_nnz_y[3] = pu1_left_mb_pair_nnz_y[1];
pu1_left_nnz_uv[0] = pu1_left_nnz_uv[1] =
pu1_left_mb_pair_nnz_uv[0];
pu1_left_nnz_uv[2] = pu1_left_nnz_uv[3] =
pu1_left_mb_pair_nnz_uv[2];
}
else if((uc_curMbFldDecFlag == 0) && uc_botMb && u1_is_left_mb_fld)
{
/* 2 2 3 3 of u4_n_leftY[0] , 1 1 3 3 of u4_n_left_cr[0] */
pu1_left_nnz_y[0] = pu1_left_nnz_y[1] = pu1_left_mb_pair_nnz_y[2];
pu1_left_nnz_y[2] = pu1_left_nnz_y[3] = pu1_left_mb_pair_nnz_y[3];
pu1_left_nnz_uv[0] = pu1_left_nnz_uv[1] =
pu1_left_mb_pair_nnz_uv[1];
pu1_left_nnz_uv[2] = pu1_left_nnz_uv[3] =
pu1_left_mb_pair_nnz_uv[3];
}
else
{
/* 0 2 0 2 of u4_n_leftY[0], u4_n_leftY[1] */
pu1_left_nnz_y[0] = pu1_left_mb_pair_nnz_y[0];
pu1_left_nnz_y[1] = pu1_left_mb_pair_nnz_y[2];
pu1_left_nnz_y[2] = pu1_left_mb_pair_nnz_y[4 + 0];
pu1_left_nnz_y[3] = pu1_left_mb_pair_nnz_y[4 + 2];
/* 0 of u4_n_left_cr[0] and 0 u4_n_left_cr[1]
2 of u4_n_left_cr[0] and 2 u4_n_left_cr[1] */
pu1_left_nnz_uv[0] = pu1_left_mb_pair_nnz_uv[0];
pu1_left_nnz_uv[1] = pu1_left_mb_pair_nnz_uv[4 + 0];
pu1_left_nnz_uv[2] = pu1_left_mb_pair_nnz_uv[2];
pu1_left_nnz_uv[3] = pu1_left_mb_pair_nnz_uv[4 + 2];
}
}
}
/*
**************************************************************************
* \if Function name : ih264d_transfer_mb_group_data \endif
*
* \brief
* Transfer the Following things
* N-Mb DeblkParams Data ( To Ext DeblkParams Buffer )
* N-Mb Recon Data ( To Ext Frame Buffer )
* N-Mb Intrapredline Data ( Updated Internally)
* N-Mb MV Data ( To Ext MV Buffer )
* N-Mb MVTop/TopRight Data ( To Int MV Top Scratch Buffers)
*
* \return
* None
*
**************************************************************************
*/
void ih264d_transfer_mb_group_data(dec_struct_t * ps_dec,
const UWORD8 u1_num_mbs,
const UWORD8 u1_end_of_row, /* Cur n-Mb End of Row Flag */
const UWORD8 u1_end_of_row_next /* Next n-Mb End of Row Flag */
)
{
dec_mb_info_t *ps_cur_mb_info = ps_dec->ps_nmb_info;
tfr_ctxt_t *ps_trns_addr = &ps_dec->s_tran_addrecon;
UWORD16 u2_mb_y;
UWORD32 y_offset;
UWORD32 u4_frame_stride;
mb_neigbour_params_t *ps_temp;
const UWORD8 u1_mbaff = ps_dec->ps_cur_slice->u1_mbaff_frame_flag;
UNUSED(u1_end_of_row_next);
ps_trns_addr->pu1_dest_y += ps_trns_addr->u4_inc_y[u1_end_of_row];
ps_trns_addr->pu1_dest_u += ps_trns_addr->u4_inc_uv[u1_end_of_row];
ps_trns_addr->pu1_dest_v += ps_trns_addr->u4_inc_uv[u1_end_of_row];
/* Swap top and current pointers */
if(u1_end_of_row)
{
if(ps_dec->u1_separate_parse)
{
u2_mb_y = ps_dec->i2_dec_thread_mb_y;
}
else
{
ps_temp = ps_dec->ps_cur_mb_row;
ps_dec->ps_cur_mb_row = ps_dec->ps_top_mb_row;
ps_dec->ps_top_mb_row = ps_temp;
u2_mb_y = ps_dec->u2_mby + (1 + u1_mbaff);
}
u4_frame_stride = ps_dec->u2_frm_wd_y
<< ps_dec->ps_cur_slice->u1_field_pic_flag;
y_offset = (u2_mb_y * u4_frame_stride) << 4;
ps_trns_addr->pu1_dest_y = ps_dec->s_cur_pic.pu1_buf1 + y_offset;
u4_frame_stride = ps_dec->u2_frm_wd_uv
<< ps_dec->ps_cur_slice->u1_field_pic_flag;
y_offset = (u2_mb_y * u4_frame_stride) << 3;
ps_trns_addr->pu1_dest_u = ps_dec->s_cur_pic.pu1_buf2 + y_offset;
ps_trns_addr->pu1_dest_v = ps_dec->s_cur_pic.pu1_buf3 + y_offset;
ps_trns_addr->pu1_mb_y = ps_trns_addr->pu1_dest_y;
ps_trns_addr->pu1_mb_u = ps_trns_addr->pu1_dest_u;
ps_trns_addr->pu1_mb_v = ps_trns_addr->pu1_dest_v;
}
/*
* The Slice boundary is also a valid condition to transfer. So recalculate
* the Left increment, in case the number of MBs is lesser than the
* N MB value. u1_num_mbs will be equal to N of N MB if the entire N Mb is
* decoded.
*/
ps_dec->s_tran_addrecon.u2_mv_left_inc = ((u1_num_mbs >> u1_mbaff) - 1)
<< (4 + u1_mbaff);
ps_dec->s_tran_addrecon.u2_mv_top_left_inc = (u1_num_mbs << 2) - 1
- (u1_mbaff << 2);
if(ps_dec->u1_separate_parse == 0)
{
/* reassign left MV and cur MV pointers */
ps_dec->ps_mv_left = ps_dec->ps_mv_cur
+ ps_dec->s_tran_addrecon.u2_mv_left_inc;
ps_dec->ps_mv_cur += (u1_num_mbs << 4);
}
/* Increment deblock parameters pointer in external memory */
if(ps_dec->u1_separate_parse == 1)
{
ps_dec->ps_deblk_mbn_dec_thrd += u1_num_mbs;
}
else
{
ps_dec->ps_deblk_mbn += u1_num_mbs;
}
}