| /****************************************************************************** |
| * |
| * 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_mb_utils.c |
| * |
| * @brief |
| * Contains utitlity functions needed for Macroblock decoding |
| * |
| * @author |
| * Kishore |
| * |
| * @par List of Functions: |
| * - isvcd_get_mb_info_cabac_nonmbaff() |
| * |
| * @remarks |
| * None |
| * |
| ******************************************************************************* |
| */ |
| |
| #include <string.h> |
| #include <stdlib.h> |
| #include "ih264d_bitstrm.h" |
| #include "ih264d_defs.h" |
| #include "ih264d_debug.h" |
| #include "isvcd_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_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) */ |
| /* 06 09 2021 Kishore Draft */ |
| /* */ |
| /*****************************************************************************/ |
| UWORD32 isvcd_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++; |
| if(mb_y >= ps_dec->u2_frm_ht_in_mbs) |
| { |
| mb_y = ps_dec->u2_frm_ht_in_mbs - 1; |
| } |
| } |
| /*********************************************************************/ |
| /* 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) |
| { |
| UWORD8 u1_a, u1_b; |
| UWORD32 u4_ctx_inc; |
| |
| u1_a = (ps_dec->p_top_ctxt_mb_info->u1_mb_type != CAB_INFERRED) |
| ? (!!(ps_dec->p_top_ctxt_mb_info->u1_mb_type & CAB_SKIP_MASK)) |
| : 0; |
| u1_b = (ps_dec->p_left_ctxt_mb_info->u1_mb_type != CAB_INFERRED) |
| ? (!!(ps_dec->p_left_ctxt_mb_info->u1_mb_type & CAB_SKIP_MASK)) |
| : 0; |
| u4_ctx_inc = 2 - (u1_a + u1_b); |
| |
| 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 : isvcd_get_mb_info_cavlc_nonmbaff */ |
| /* */ |
| /* 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) */ |
| /* 24 01 2023 Kishore Draft */ |
| /* */ |
| /*****************************************************************************/ |
| |
| UWORD32 isvcd_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->u2_frm_ht_in_mbs) |
| { |
| mb_y = ps_dec->u2_frm_ht_in_mbs - 1; |
| } |
| } |
| 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); |
| } |