| /****************************************************************************** |
| * |
| * Copyright (C) 2012 Ittiam Systems Pvt Ltd, Bangalore |
| * |
| * 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. |
| * |
| ******************************************************************************/ |
| /** |
| ******************************************************************************* |
| * @file |
| * ihevcd_parse_residual.c |
| * |
| * @brief |
| * Contains functions for parsing residual data at TU level |
| * |
| * @author |
| * Harish |
| * |
| * @par List of Functions: |
| * |
| * @remarks |
| * None |
| * |
| ******************************************************************************* |
| */ |
| /*****************************************************************************/ |
| /* File Includes */ |
| /*****************************************************************************/ |
| #include <stdio.h> |
| #include <stddef.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <assert.h> |
| |
| #include "ihevc_typedefs.h" |
| #include "iv.h" |
| #include "ivd.h" |
| #include "ihevcd_cxa.h" |
| |
| #include "ihevc_defs.h" |
| #include "ihevc_debug.h" |
| #include "ihevc_structs.h" |
| #include "ihevc_macros.h" |
| #include "ihevc_platform_macros.h" |
| |
| #include "ihevc_common_tables.h" |
| #include "ihevc_error.h" |
| #include "ihevc_cabac_tables.h" |
| |
| #include "ihevcd_trace.h" |
| #include "ihevcd_defs.h" |
| #include "ihevcd_function_selector.h" |
| #include "ihevcd_structs.h" |
| #include "ihevcd_error.h" |
| #include "ihevcd_nal.h" |
| #include "ihevcd_bitstream.h" |
| #include "ihevcd_utils.h" |
| #include "ihevcd_parse_residual.h" |
| #include "ihevcd_cabac.h" |
| |
| /** |
| ***************************************************************************** |
| * @brief returns context increment for sig coeff based on csbf neigbour |
| * flags (bottom and right) and current coeff postion in 4x4 block |
| * See section 9.3.3.1.4 for details on this context increment |
| * |
| * input : neigbour csbf flags(bit0:rightcsbf, bit1:bottom csbf) |
| * coeff idx in raster order (0-15) |
| * |
| * output : context increment for sig coeff flag |
| * |
| ***************************************************************************** |
| */ |
| const UWORD8 gau1_ihevcd_sigcoeff_ctxtinc[3][4][16] = |
| { |
| |
| { |
| /* nbr csbf = 0: sigCtx = (xP+yP == 0) ? 2 : (xP+yP < 3) ? 1: 0 */ |
| { 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, |
| /* nbr csbf = 1: sigCtx = (yP == 0) ? 2 : (yP == 1) ? 1: 0 */ |
| { 2, 1, 2, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0 }, |
| /* nbr csbf = 2: sigCtx = (xP == 0) ? 2 : (xP == 1) ? 1: 0 */ |
| { 2, 2, 1, 2, 1, 0, 2, 1, 0, 0, 1, 0, 0, 0, 0, 0 }, |
| /* nbr csbf = 3: sigCtx = 2 */ |
| { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }, |
| }, |
| { |
| /* nbr csbf = 0: sigCtx = (xP+yP == 0) ? 2 : (xP+yP < 3) ? 1: 0 */ |
| { 2, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 }, |
| /* nbr csbf = 1: sigCtx = (yP == 0) ? 2 : (yP == 1) ? 1: 0 */ |
| { 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, |
| /* nbr csbf = 2: sigCtx = (xP == 0) ? 2 : (xP == 1) ? 1: 0 */ |
| { 2, 1, 0, 0, 2, 1, 0, 0, 2, 1, 0, 0, 2, 1, 0, 0 }, |
| /* nbr csbf = 3: sigCtx = 2 */ |
| { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }, |
| }, |
| { |
| /* nbr csbf = 0: sigCtx = (xP+yP == 0) ? 2 : (xP+yP < 3) ? 1: 0 */ |
| { 2, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 }, |
| /* nbr csbf = 1: sigCtx = (yP == 0) ? 2 : (yP == 1) ? 1: 0 */ |
| { 2, 1, 0, 0, 2, 1, 0, 0, 2, 1, 0, 0, 2, 1, 0, 0 }, |
| /* nbr csbf = 2: sigCtx = (xP == 0) ? 2 : (xP == 1) ? 1: 0 */ |
| { 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, |
| /* nbr csbf = 3: sigCtx = 2 */ |
| { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }, |
| }, |
| |
| |
| }; |
| |
| |
| |
| /** |
| ***************************************************************************** |
| * @brief returns context increment for sig coeff for 4x4 tranform size as |
| * per Table 9-39 in section 9.3.3.1.4 |
| * |
| * input : coeff idx in raster order (0-15) |
| * |
| * output : context increment for sig coeff flag |
| * |
| ***************************************************************************** |
| */ |
| const UWORD8 gau1_ihevcd_sigcoeff_ctxtinc_tr4[3][16] = |
| { |
| /* Upright diagonal scan */ |
| { |
| 0, 2, 1, 6, |
| 3, 4, 7, 6, |
| 4, 5, 7, 8, |
| 5, 8, 8, 8, |
| }, |
| /* Horizontal scan */ |
| { |
| 0, 1, 4, 5, |
| 2, 3, 4, 5, |
| 6, 6, 8, 8, |
| 7, 7, 8, 8, |
| }, |
| /* Vertical scan */ |
| { |
| 0, 2, 6, 7, |
| 1, 3, 6, 7, |
| 4, 4, 8, 8, |
| 5, 5, 8, 8, |
| }, |
| }; |
| |
| |
| /** |
| ******************************************************************************* |
| * |
| * @brief |
| * Parses Residual coding |
| * |
| * @par Description: |
| * Parses Residual coding as per Section:7.3.13 |
| * |
| * @param[in] ps_codec |
| * Pointer to codec context |
| * |
| * @returns error code from IHEVCD_ERROR_T |
| * |
| * @remarks |
| * |
| * |
| ******************************************************************************* |
| */ |
| |
| WORD32 ihevcd_parse_residual_coding(codec_t *ps_codec, |
| WORD32 x0, WORD32 y0, |
| WORD32 log2_trafo_size, |
| WORD32 c_idx, |
| WORD32 intra_pred_mode) |
| { |
| IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS; |
| WORD32 transform_skip_flag; |
| WORD32 value; |
| pps_t *ps_pps; |
| WORD32 last_scan_pos, last_sub_blk; |
| bitstrm_t *ps_bitstrm = &ps_codec->s_parse.s_bitstrm; |
| WORD32 last_significant_coeff_x_prefix, last_significant_coeff_y_prefix; |
| WORD32 last_significant_coeff_x, last_significant_coeff_y; |
| const UWORD8 *pu1_scan_blk = NULL, *pu1_scan_coeff; |
| WORD32 scan_idx; |
| WORD32 i; |
| WORD32 sign_data_hiding_flag; |
| cab_ctxt_t *ps_cabac = &ps_codec->s_parse.s_cabac; |
| WORD32 gt1_ctxt = 1; |
| WORD32 c_max; |
| UWORD16 au2_csbf[9]; |
| tu_sblk_coeff_data_t *ps_tu_sblk_coeff_data; |
| WORD8 *pi1_num_coded_subblks; |
| WORD32 num_subblks; |
| WORD32 sig_coeff_base_ctxt, abs_gt1_base_ctxt; |
| UNUSED(x0); |
| UNUSED(y0); |
| ps_pps = ps_codec->s_parse.ps_pps; |
| |
| sign_data_hiding_flag = ps_pps->i1_sign_data_hiding_flag; |
| transform_skip_flag = 0; |
| if(ps_pps->i1_transform_skip_enabled_flag && |
| !ps_codec->s_parse.s_cu.i4_cu_transquant_bypass && |
| (log2_trafo_size == 2)) |
| { |
| WORD32 ctxt_idx; |
| |
| if(!c_idx) |
| { |
| ctxt_idx = IHEVC_CAB_TFM_SKIP0; |
| } |
| else |
| { |
| ctxt_idx = IHEVC_CAB_TFM_SKIP12; |
| } |
| TRACE_CABAC_CTXT("transform_skip_flag", ps_cabac->u4_range, ctxt_idx); |
| value = ihevcd_cabac_decode_bin(ps_cabac, |
| ps_bitstrm, |
| ctxt_idx); |
| AEV_TRACE("transform_skip_flag", value, ps_cabac->u4_range); |
| transform_skip_flag = value; |
| } |
| |
| /* code the last_coeff_x_prefix as tunary binarized code */ |
| { |
| WORD32 ctxt_idx_x, ctxt_idx_y, ctx_shift; |
| WORD32 ctx_offset; |
| c_max = (log2_trafo_size << 1) - 1; |
| |
| if(!c_idx) |
| { |
| ctx_offset = (3 * (log2_trafo_size - 2)) + ((log2_trafo_size - 1) >> 2); |
| ctxt_idx_x = IHEVC_CAB_COEFFX_PREFIX + ctx_offset; |
| ctxt_idx_y = IHEVC_CAB_COEFFY_PREFIX + ctx_offset; |
| ctx_shift = (log2_trafo_size + 1) >> 2; |
| } |
| else |
| { |
| ctxt_idx_x = IHEVC_CAB_COEFFX_PREFIX + 15; |
| ctxt_idx_y = IHEVC_CAB_COEFFY_PREFIX + 15; |
| ctx_shift = log2_trafo_size - 2; |
| } |
| |
| TRACE_CABAC_CTXT("last_coeff_x_prefix", ps_cabac->u4_range, ctxt_idx_x); |
| last_significant_coeff_x_prefix = ihevcd_cabac_decode_bins_tunary(ps_cabac, |
| ps_bitstrm, |
| c_max, |
| ctxt_idx_x, |
| ctx_shift, |
| c_max); |
| |
| AEV_TRACE("last_coeff_x_prefix", last_significant_coeff_x_prefix, ps_cabac->u4_range); |
| |
| TRACE_CABAC_CTXT("last_coeff_y_prefix", ps_cabac->u4_range, ctxt_idx_y); |
| last_significant_coeff_y_prefix = ihevcd_cabac_decode_bins_tunary(ps_cabac, |
| ps_bitstrm, |
| c_max, |
| ctxt_idx_y, |
| ctx_shift, |
| c_max); |
| |
| AEV_TRACE("last_coeff_y_prefix", last_significant_coeff_y_prefix, ps_cabac->u4_range); |
| |
| |
| last_significant_coeff_x = last_significant_coeff_x_prefix; |
| if(last_significant_coeff_x_prefix > 3) |
| { |
| WORD32 suf_length = ((last_significant_coeff_x_prefix - 2) >> 1); |
| |
| value = ihevcd_cabac_decode_bypass_bins(ps_cabac, |
| ps_bitstrm, |
| suf_length); |
| |
| AEV_TRACE("last_coeff_x_suffix", value, ps_cabac->u4_range); |
| |
| |
| last_significant_coeff_x = |
| (1 << ((last_significant_coeff_x_prefix >> 1) - 1)) * |
| (2 + (last_significant_coeff_x_prefix & 1)) + value; |
| } |
| |
| |
| last_significant_coeff_y = last_significant_coeff_y_prefix; |
| if(last_significant_coeff_y_prefix > 3) |
| { |
| WORD32 suf_length = ((last_significant_coeff_y_prefix - 2) >> 1); |
| value = ihevcd_cabac_decode_bypass_bins(ps_cabac, |
| ps_bitstrm, |
| suf_length); |
| |
| AEV_TRACE("last_coeff_y_suffix", value, ps_cabac->u4_range); |
| last_significant_coeff_y = |
| (1 << ((last_significant_coeff_y_prefix >> 1) - 1)) * |
| (2 + (last_significant_coeff_y_prefix & 1)) + value; |
| } |
| |
| } |
| |
| /* Choose a scan matrix based on intra flag, intra pred mode, transform size |
| and luma/chroma */ |
| scan_idx = SCAN_DIAG_UPRIGHT; |
| if(PRED_MODE_INTRA == ps_codec->s_parse.s_cu.i4_pred_mode) |
| { |
| if((2 == log2_trafo_size) || ((3 == log2_trafo_size) && (0 == c_idx))) |
| { |
| if((6 <= intra_pred_mode) && |
| (14 >= intra_pred_mode)) |
| { |
| scan_idx = SCAN_VERT; |
| } |
| else if((22 <= intra_pred_mode) && |
| (30 >= intra_pred_mode)) |
| { |
| scan_idx = SCAN_HORZ; |
| } |
| } |
| } |
| |
| /* In case the scan is vertical, then swap X and Y positions */ |
| if(SCAN_VERT == scan_idx) |
| { |
| SWAP(last_significant_coeff_x, last_significant_coeff_y); |
| } |
| |
| { |
| WORD8 *pi1_scan_idx; |
| WORD8 *pi1_buf = (WORD8 *)ps_codec->s_parse.pv_tu_coeff_data; |
| |
| /* First WORD8 gives number of coded subblocks */ |
| pi1_num_coded_subblks = pi1_buf++; |
| |
| /* Set number of coded subblocks in the current TU to zero */ |
| /* This will be updated later */ |
| *pi1_num_coded_subblks = 0; |
| |
| /* Second WORD8 gives (scan idx << 1) | trans_skip */ |
| pi1_scan_idx = pi1_buf++; |
| *pi1_scan_idx = (scan_idx << 1) | transform_skip_flag; |
| |
| /* Store the incremented pointer in pv_tu_coeff_data */ |
| ps_codec->s_parse.pv_tu_coeff_data = pi1_buf; |
| |
| } |
| /** |
| * Given last_significant_coeff_y and last_significant_coeff_x find last sub block |
| * This is done by ignoring lower two bits of last_significant_coeff_y and last_significant_coeff_x |
| * and using scan matrix for lookup |
| */ |
| |
| /* If transform is 4x4, last_sub_blk is zero */ |
| last_sub_blk = 0; |
| |
| /* If transform is larger than 4x4, then based on scan_idx and transform size, choose a scan table */ |
| |
| if(log2_trafo_size > 2) |
| { |
| WORD32 scan_pos; |
| WORD32 scan_mat_size; |
| pu1_scan_blk = (UWORD8 *)gapv_ihevc_scan[scan_idx * 3 + (log2_trafo_size - 2 - 1)]; |
| |
| |
| /* Divide the current transform to 4x4 subblocks and count number of 4x4 in the first row */ |
| /* This will be size of scan matrix to be used for subblock scanning */ |
| scan_mat_size = 1 << (log2_trafo_size - 2); |
| scan_pos = ((last_significant_coeff_y >> 2) * scan_mat_size) + |
| (last_significant_coeff_x >> 2); |
| |
| last_sub_blk = pu1_scan_blk[scan_pos]; |
| } |
| pu1_scan_coeff = &gau1_ihevc_scan4x4[scan_idx][0]; |
| |
| { |
| WORD32 scan_pos; |
| |
| scan_pos = ((last_significant_coeff_y & 3) << 2) + |
| (last_significant_coeff_x & 3); |
| |
| last_scan_pos = pu1_scan_coeff[scan_pos]; |
| } |
| if(log2_trafo_size > 2) |
| pu1_scan_blk = (UWORD8 *)gapv_ihevc_invscan[scan_idx * 3 + (log2_trafo_size - 2 - 1)]; |
| pu1_scan_coeff = &gau1_ihevc_invscan4x4[scan_idx][0]; |
| |
| /* Set CSBF array to zero */ |
| { |
| UWORD32 *pu4_csbf; |
| pu4_csbf = (void *)au2_csbf; |
| *pu4_csbf++ = 0; |
| *pu4_csbf++ = 0; |
| *pu4_csbf++ = 0; |
| *pu4_csbf = 0; |
| /* To avoid a check for y pos, 9th WORD16 in the array is set to zero */ |
| au2_csbf[8] = 0; |
| } |
| |
| /*************************************************************************/ |
| /* derive base context index for sig coeff as per section 9.3.3.1.4 */ |
| /* TODO; convert to look up based on luma/chroma, scan type and tfr size */ |
| /*************************************************************************/ |
| if(!c_idx) |
| { |
| sig_coeff_base_ctxt = IHEVC_CAB_COEFF_FLAG; |
| abs_gt1_base_ctxt = IHEVC_CAB_COEFABS_GRTR1_FLAG; |
| |
| if(3 == log2_trafo_size) |
| { |
| /* 8x8 transform size */ |
| sig_coeff_base_ctxt += (scan_idx == SCAN_DIAG_UPRIGHT) ? 9 : 15; |
| } |
| else if(3 < log2_trafo_size) |
| { |
| /* larger transform sizes */ |
| sig_coeff_base_ctxt += 21; |
| } |
| } |
| else |
| { |
| /* chroma context initializations */ |
| sig_coeff_base_ctxt = IHEVC_CAB_COEFF_FLAG + 27; |
| abs_gt1_base_ctxt = IHEVC_CAB_COEFABS_GRTR1_FLAG + 16; |
| |
| if(3 == log2_trafo_size) |
| { |
| /* 8x8 transform size */ |
| sig_coeff_base_ctxt += 9; |
| } |
| else if(3 < log2_trafo_size) |
| { |
| /* larger transform sizes */ |
| sig_coeff_base_ctxt += 12; |
| } |
| } |
| num_subblks = 0; |
| /* Parse each 4x4 subblocks */ |
| for(i = last_sub_blk; i >= 0; i--) |
| { |
| WORD32 sub_blk_pos; |
| WORD32 infer_sig_coeff_flag; |
| WORD32 cur_csbf; |
| |
| WORD32 n; |
| WORD32 num_coeff; |
| /* Sig coeff map for 16 entries in raster scan order. Upper 16 bits are used. |
| * MSB gives sig coeff flag for 0th coeff and so on |
| * UWORD16 would have been enough but kept as UWORD32 for code optimizations |
| * In arm unnecessary masking operations are saved |
| */ |
| UWORD32 u4_sig_coeff_map_raster; |
| WORD32 sign_hidden; |
| |
| /* Sig coeff map in scan order */ |
| UWORD32 u4_sig_coeff_map; |
| WORD32 coeff_abs_level_greater2_flag; |
| UWORD32 u4_coeff_abs_level_greater1_map; |
| UWORD32 u4_coeff_abs_level_greater2_map; |
| UWORD32 u4_coeff_sign_map; |
| WORD32 first_sig_scan_pos, last_sig_scan_pos, num_greater1_flag, first_greater1_scan_pos; |
| WORD32 num_sig_coeff, sum_abs_level; |
| WORD32 nbr_csbf; |
| |
| |
| WORD32 ctxt_set; |
| WORD32 rice_param; |
| WORD32 xs, ys; |
| |
| |
| sub_blk_pos = 0; |
| if(i && (log2_trafo_size > 2)) |
| sub_blk_pos = pu1_scan_blk[i]; |
| |
| /* Get xs and ys from scan position */ |
| /* This is needed for context modelling of significant coeff flag */ |
| xs = sub_blk_pos & ((1 << (log2_trafo_size - 2)) - 1); |
| ys = sub_blk_pos >> (log2_trafo_size - 2); |
| |
| |
| /* Check if neighbor subblocks are coded */ |
| { |
| |
| nbr_csbf = 0; |
| |
| /* Get Bottom sub blocks CSBF */ |
| nbr_csbf |= (au2_csbf[ys + 1] >> xs) & 1; |
| nbr_csbf <<= 1; |
| |
| /* Get Right sub blocks CSBF */ |
| /* Even if xs is equal to (1 << (log2_trafo_size - 2 )) - 1, |
| since au2_csbf is set to zero at the beginning, csbf for |
| neighbor will be read as 0 */ |
| |
| nbr_csbf |= (au2_csbf[ys] >> (xs + 1)) & 1; |
| |
| |
| } |
| cur_csbf = 0; |
| |
| /* DC coeff is inferred, only if coded_sub_block is explicitly parsed as 1 */ |
| /* i.e. it is not inferred for first and last subblock */ |
| infer_sig_coeff_flag = 0; |
| if((i < last_sub_blk) && (i > 0)) |
| { |
| WORD32 ctxt_idx = IHEVC_CAB_CODED_SUBLK_IDX; |
| |
| /* ctxt based on right / bottom avail csbf, section 9.3.3.1.3 */ |
| ctxt_idx += (nbr_csbf) ? 1 : 0; |
| |
| /* Ctxt based on luma or chroma */ |
| ctxt_idx += c_idx ? 2 : 0; |
| TRACE_CABAC_CTXT("coded_sub_block_flag", ps_cabac->u4_range, ctxt_idx); |
| IHEVCD_CABAC_DECODE_BIN(cur_csbf, ps_cabac, ps_bitstrm, ctxt_idx); |
| AEV_TRACE("coded_sub_block_flag", cur_csbf, ps_cabac->u4_range); |
| |
| infer_sig_coeff_flag = 1; |
| } |
| else /* if((i == last_sub_blk) || (sub_blk_pos == 0)) */ |
| { |
| /* CSBF is set to 1 for first and last subblock */ |
| /* Note for these subblocks sig_coeff_map is not inferred but instead parsed */ |
| cur_csbf = 1; |
| } |
| |
| /* Set current sub blocks CSBF */ |
| { |
| UWORD32 u4_mask = 1 << xs; |
| if(cur_csbf) |
| au2_csbf[ys] |= u4_mask; |
| else |
| au2_csbf[ys] &= ~u4_mask; |
| |
| } |
| |
| /* If current subblock is not coded, proceed to the next subblock */ |
| if(0 == cur_csbf) |
| continue; |
| |
| n = 15; |
| u4_sig_coeff_map_raster = 0; |
| u4_sig_coeff_map = 0; |
| num_coeff = 0; |
| if(i == last_sub_blk) |
| { |
| WORD32 pos = ((last_significant_coeff_y & 3) << 2) + |
| (last_significant_coeff_x & 3); |
| n = (last_scan_pos - 1); |
| /* Set Significant coeff map for last significant coeff flag as 1 */ |
| u4_sig_coeff_map_raster = 1 << pos; |
| u4_sig_coeff_map = 1 << last_scan_pos; |
| num_coeff = 1; |
| } |
| |
| for(; n >= 0; n--) |
| { |
| WORD32 significant_coeff_flag; |
| |
| if((n > 0 || !infer_sig_coeff_flag)) |
| { |
| //WORD32 coeff_pos; |
| WORD32 sig_ctxinc; |
| WORD32 ctxt_idx; |
| |
| /* Coefficient position is needed for deriving context index for significant_coeff_flag */ |
| //coeff_pos = pu1_scan_coeff[n]; |
| /* derive the context inc as per section 9.3.3.1.4 */ |
| sig_ctxinc = 0; |
| if(2 == log2_trafo_size) |
| { |
| |
| /* 4x4 transform size increment uses lookup */ |
| sig_ctxinc = gau1_ihevcd_sigcoeff_ctxtinc_tr4[scan_idx][n]; |
| } |
| else if(n || i) |
| { |
| /* ctxt for AC coeff depends on curpos and neigbour csbf */ |
| sig_ctxinc = gau1_ihevcd_sigcoeff_ctxtinc[scan_idx][nbr_csbf][n]; |
| |
| /* based on luma subblock pos */ |
| sig_ctxinc += (i && (!c_idx)) ? 3 : 0; |
| |
| } |
| else |
| { |
| /* DC coeff has fixed context for luma and chroma */ |
| sig_coeff_base_ctxt = (0 == c_idx) ? IHEVC_CAB_COEFF_FLAG : |
| (IHEVC_CAB_COEFF_FLAG + 27); |
| } |
| |
| ctxt_idx = sig_ctxinc + sig_coeff_base_ctxt; |
| TRACE_CABAC_CTXT("significant_coeff_flag", ps_cabac->u4_range, ctxt_idx); |
| IHEVCD_CABAC_DECODE_BIN(significant_coeff_flag, ps_cabac, |
| ps_bitstrm, |
| ctxt_idx); |
| AEV_TRACE("significant_coeff_flag", significant_coeff_flag, ps_cabac->u4_range); |
| |
| |
| /* If at least one non-zero coeff is signalled then do not infer sig coeff map */ |
| /* for (0,0) coeff in the current sub block */ |
| if(significant_coeff_flag) |
| infer_sig_coeff_flag = 0; |
| |
| // u4_sig_coeff_map_raster |= significant_coeff_flag |
| // << coeff_pos; |
| u4_sig_coeff_map |= significant_coeff_flag << n; |
| num_coeff += significant_coeff_flag; |
| } |
| |
| |
| } |
| /*********************************************************************/ |
| /* If infer_sig_coeff_flag is 1 then treat the 0th coeff as non zero */ |
| /* If infer_sig_coeff_flag is zero, then last significant_coeff_flag */ |
| /* is parsed in the above loop */ |
| /*********************************************************************/ |
| if(infer_sig_coeff_flag) |
| { |
| u4_sig_coeff_map_raster |= 1; |
| u4_sig_coeff_map |= 1; |
| num_coeff++; |
| } |
| |
| /*********************************************************************/ |
| /* First subblock does not get an explicit csbf. It is assumed to */ |
| /* be 1. For this subblock there is chance of getting all */ |
| /* sig_coeff_flags to be zero. In such a case proceed to the next */ |
| /* subblock(which is end of parsing for the current transform block) */ |
| /*********************************************************************/ |
| |
| if(0 == num_coeff) |
| continue; |
| |
| /* Increment number of coded subblocks for the current TU */ |
| num_subblks++; |
| |
| /* Set sig coeff map and subblock position */ |
| ps_tu_sblk_coeff_data = (tu_sblk_coeff_data_t *)ps_codec->s_parse.pv_tu_coeff_data; |
| ps_tu_sblk_coeff_data->u2_sig_coeff_map = u4_sig_coeff_map; |
| ps_tu_sblk_coeff_data->u2_subblk_pos = (ys << 8) | xs; |
| |
| first_sig_scan_pos = 16; |
| last_sig_scan_pos = -1; |
| num_greater1_flag = 0; |
| first_greater1_scan_pos = -1; |
| u4_coeff_abs_level_greater1_map = 0; |
| |
| |
| /* context set based on luma subblock pos */ |
| ctxt_set = (i && (!c_idx)) ? 2 : 0; |
| |
| /* See section 9.3.3.1.5 */ |
| ctxt_set += (0 == gt1_ctxt) ? 1 : 0; |
| |
| gt1_ctxt = 1; |
| /* Instead of initializing n to 15, set it to 31-CLZ(sig coeff map) */ |
| { |
| UWORD32 u4_sig_coeff_map_shift; |
| UWORD32 clz; |
| clz = CLZ(u4_sig_coeff_map); |
| n = 31 - clz; |
| u4_sig_coeff_map_shift = u4_sig_coeff_map << clz; |
| /* For loop for n changed to do while to break early if sig_coeff_map_shift becomes zero */ |
| do |
| { |
| //WORD32 coeff_pos; |
| WORD32 ctxt_idx; |
| |
| //TODO: Scan lookup will be removed later and instead u4_sig_coeff_map will be used |
| //coeff_pos = pu1_scan_coeff[n]; |
| |
| if((u4_sig_coeff_map_shift >> 31) & 1) |
| { |
| |
| /* abs_level_greater1_flag is sent for only first 8 non-zero levels in a subblock */ |
| if(num_greater1_flag < 8) |
| { |
| WORD32 coeff_abs_level_greater1_flag; |
| |
| ctxt_idx = (ctxt_set * 4) + abs_gt1_base_ctxt + gt1_ctxt; |
| |
| TRACE_CABAC_CTXT("coeff_abs_level_greater1_flag", ps_cabac->u4_range, ctxt_idx); |
| IHEVCD_CABAC_DECODE_BIN(coeff_abs_level_greater1_flag, ps_cabac, ps_bitstrm, ctxt_idx); |
| AEV_TRACE("coeff_abs_level_greater1_flag", coeff_abs_level_greater1_flag, ps_cabac->u4_range); |
| |
| u4_coeff_abs_level_greater1_map |= coeff_abs_level_greater1_flag << n; |
| num_greater1_flag++; |
| |
| /* first_greater1_scan_pos is obtained using CLZ on u4_coeff_abs_level_greater1_map*/ |
| /* outside the loop instead of the following check inside the loop */ |
| /* if( coeff_abs_level_greater1_flag && first_greater1_scan_pos == -1) */ |
| /* first_greater1_scan_pos = n; */ |
| |
| if(coeff_abs_level_greater1_flag) |
| { |
| gt1_ctxt = 0; |
| } |
| else if(gt1_ctxt && (gt1_ctxt < 3)) |
| { |
| gt1_ctxt++; |
| } |
| |
| } |
| else |
| break; |
| |
| /* instead of computing last and first significan scan position using checks below */ |
| /* They are computed outside the loop using CLZ and CTZ on sig_coeff_map */ |
| /* if(last_sig_scan_pos == -1) */ |
| /* last_sig_scan_pos = n; */ |
| /* first_sig_scan_pos = n; */ |
| } |
| u4_sig_coeff_map_shift <<= 1; |
| n--; |
| /* If there are zero coeffs, then shift by as many zero coeffs and decrement n */ |
| clz = CLZ(u4_sig_coeff_map_shift); |
| u4_sig_coeff_map_shift <<= clz; |
| n -= clz; |
| }while(u4_sig_coeff_map_shift); |
| } |
| /* At this level u4_sig_coeff_map is non-zero i.e. has atleast one non-zero coeff */ |
| last_sig_scan_pos = (31 - CLZ(u4_sig_coeff_map)); |
| first_sig_scan_pos = CTZ(u4_sig_coeff_map); |
| sign_hidden = (((last_sig_scan_pos - first_sig_scan_pos) > 3) && !ps_codec->s_parse.s_cu.i4_cu_transquant_bypass); |
| |
| u4_coeff_abs_level_greater2_map = 0; |
| |
| if(u4_coeff_abs_level_greater1_map) |
| { |
| /* Check if the first level > 1 is greater than 2 */ |
| WORD32 ctxt_idx; |
| first_greater1_scan_pos = (31 - CLZ(u4_coeff_abs_level_greater1_map)); |
| |
| |
| ctxt_idx = IHEVC_CAB_COEFABS_GRTR2_FLAG; |
| |
| ctxt_idx += (!c_idx) ? ctxt_set : (ctxt_set + 4); |
| TRACE_CABAC_CTXT("coeff_abs_level_greater2_flag", ps_cabac->u4_range, ctxt_idx); |
| IHEVCD_CABAC_DECODE_BIN(coeff_abs_level_greater2_flag, ps_cabac, ps_bitstrm, ctxt_idx); |
| AEV_TRACE("coeff_abs_level_greater2_flag", coeff_abs_level_greater2_flag, ps_cabac->u4_range); |
| u4_coeff_abs_level_greater2_map = coeff_abs_level_greater2_flag << first_greater1_scan_pos; |
| } |
| |
| |
| u4_coeff_sign_map = 0; |
| |
| /* Parse sign flags */ |
| if(!sign_data_hiding_flag || !sign_hidden) |
| { |
| IHEVCD_CABAC_DECODE_BYPASS_BINS(value, ps_cabac, ps_bitstrm, num_coeff); |
| AEV_TRACE("sign_flags", value, ps_cabac->u4_range); |
| u4_coeff_sign_map = value << (32 - num_coeff); |
| } |
| else |
| { |
| IHEVCD_CABAC_DECODE_BYPASS_BINS(value, ps_cabac, ps_bitstrm, (num_coeff - 1)); |
| AEV_TRACE("sign_flags", value, ps_cabac->u4_range); |
| u4_coeff_sign_map = value << (32 - (num_coeff - 1)); |
| } |
| |
| num_sig_coeff = 0; |
| sum_abs_level = 0; |
| rice_param = 0; |
| { |
| UWORD32 clz; |
| UWORD32 u4_sig_coeff_map_shift; |
| clz = CLZ(u4_sig_coeff_map); |
| n = 31 - clz; |
| u4_sig_coeff_map_shift = u4_sig_coeff_map << clz; |
| /* For loop for n changed to do while to break early if sig_coeff_map_shift becomes zero */ |
| do |
| { |
| |
| if((u4_sig_coeff_map_shift >> 31) & 1) |
| { |
| WORD32 base_lvl; |
| WORD32 coeff_abs_level_remaining; |
| WORD32 level; |
| base_lvl = 1; |
| |
| /* Update base_lvl if it is greater than 1 */ |
| if((u4_coeff_abs_level_greater1_map >> n) & 1) |
| base_lvl++; |
| |
| /* Update base_lvl if it is greater than 2 */ |
| if((u4_coeff_abs_level_greater2_map >> n) & 1) |
| base_lvl++; |
| |
| /* If level is greater than 3/2/1 based on the greater1 and greater2 maps, |
| * decode remaining level (level - base_lvl) will be signalled as bypass bins |
| */ |
| coeff_abs_level_remaining = 0; |
| if(base_lvl == ((num_sig_coeff < 8) ? ((n == first_greater1_scan_pos) ? 3 : 2) : 1)) |
| { |
| UWORD32 u4_prefix; |
| WORD32 bin; |
| |
| u4_prefix = 0; |
| |
| do |
| { |
| IHEVCD_CABAC_DECODE_BYPASS_BIN(bin, ps_cabac, ps_bitstrm); |
| u4_prefix++; |
| |
| if((WORD32)u4_prefix == 19 - rice_param) |
| { |
| bin = 1; |
| break; |
| } |
| |
| }while(bin); |
| |
| u4_prefix = u4_prefix - 1; |
| if(u4_prefix < 3) |
| { |
| UWORD32 u4_suffix; |
| |
| coeff_abs_level_remaining = (u4_prefix << rice_param); |
| if(rice_param) |
| { |
| IHEVCD_CABAC_DECODE_BYPASS_BINS(u4_suffix, ps_cabac, ps_bitstrm, rice_param); |
| |
| coeff_abs_level_remaining |= u4_suffix; |
| } |
| } |
| else |
| { |
| UWORD32 u4_suffix; |
| UWORD32 u4_numbins; |
| |
| //u4_prefix = CLIP3(u4_prefix, 0, 19 - rice_param); |
| |
| u4_numbins = (u4_prefix - 3 + rice_param); |
| coeff_abs_level_remaining = (((1 << (u4_prefix - 3)) + 3 - 1) << rice_param); |
| if(u4_numbins) |
| { |
| IHEVCD_CABAC_DECODE_BYPASS_BINS(u4_suffix, ps_cabac, ps_bitstrm, u4_numbins); |
| coeff_abs_level_remaining += u4_suffix; |
| } |
| } |
| |
| |
| AEV_TRACE("coeff_abs_level_remaining", coeff_abs_level_remaining, ps_cabac->u4_range); |
| base_lvl += coeff_abs_level_remaining; |
| |
| } |
| |
| /* update the rice param based on coeff level */ |
| if((base_lvl > (3 << rice_param)) && (rice_param < 4)) |
| { |
| rice_param++; |
| } |
| |
| /* Compute absolute level */ |
| level = base_lvl; |
| |
| /* Update level with the sign */ |
| if((u4_coeff_sign_map >> 31) & 1) |
| level = -level; |
| |
| u4_coeff_sign_map <<= 1; |
| /* Update sign in case sign is hidden */ |
| if(sign_data_hiding_flag && sign_hidden) |
| { |
| sum_abs_level += base_lvl; |
| |
| if(n == first_sig_scan_pos && ((sum_abs_level % 2) == 1)) |
| level = -level; |
| } |
| |
| /* Store the resulting level in non-zero level array */ |
| ps_tu_sblk_coeff_data->ai2_level[num_sig_coeff++] = level; |
| //AEV_TRACE("level", level, 0); |
| } |
| u4_sig_coeff_map_shift <<= 1; |
| n--; |
| /* If there are zero coeffs, then shift by as many zero coeffs and decrement n */ |
| clz = CLZ(u4_sig_coeff_map_shift); |
| u4_sig_coeff_map_shift <<= clz; |
| n -= clz; |
| |
| |
| }while(u4_sig_coeff_map_shift); |
| } |
| |
| /* Increment the pv_tu_sblk_coeff_data */ |
| { |
| UWORD8 *pu1_buf = (UWORD8 *)ps_codec->s_parse.pv_tu_coeff_data; |
| pu1_buf += sizeof(tu_sblk_coeff_data_t) - SUBBLK_COEFF_CNT * sizeof(WORD16); |
| pu1_buf += num_coeff * sizeof(WORD16); |
| ps_codec->s_parse.pv_tu_coeff_data = pu1_buf; |
| |
| } |
| |
| } |
| /* Set number of coded sub blocks in the current TU */ |
| *pi1_num_coded_subblks = num_subblks; |
| |
| return ret; |
| } |