/****************************************************************************** * * 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 #include #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 : */ /* */ /* 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 : */ /* */ /* 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 : */ /* */ /* 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 : */ /* */ /* 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 : */ /* Globals : */ /* Processing : */ /* Outputs : */ /* Returns : */ /* */ /* Issues : */ /* */ /* 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 == 0) { ps_dec->ps_deblk_mbn += u1_num_mbs; } }