/****************************************************************************** * * 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_cabac.c * * @brief * This file contains function definitions related to CABAC parsing * * @author * Ittiam * * * List of Functions * * ihevcd_cabac_init() * ihevcd_cabac_decode_bin() * ihevcd_cabac_decode_bypass_bin() * ihevcd_cabac_decode_bypass_bins_tunary() * ihevcd_cabac_decode_terminate() * ihevcd_cabac_decode_bin_tunary() * ihevcd_cabac_decode_bypass_bins() * ihevcd_cabac_decode_bypass_bins_egk() * ihevcd_cabac_decode_trunc_rice() * ihevcd_cabac_flush() * ****************************************************************************** */ /*****************************************************************************/ /* File Includes */ /*****************************************************************************/ #include #include #include #include #include #include "ihevc_typedefs.h" #include "iv.h" #include "ivd.h" #include "ihevcd_cxa.h" #include "ihevc_debug.h" #include "ihevc_macros.h" #include "ihevc_platform_macros.h" #include "ihevc_cabac_tables.h" #include "ihevc_defs.h" #include "ihevc_structs.h" #include "ihevc_cabac_tables.h" #include "ihevcd_defs.h" #include "ihevcd_function_selector.h" #include "ihevcd_structs.h" #include "ihevcd_error.h" #include "ihevcd_bitstream.h" #include "ihevcd_cabac.h" #include "ihevcd_trace.h" #ifdef TRACE extern trace_t g_trace; #endif #if DEBUG_CABAC_RANGE_OFST #if FULLRANGE #define DEBUG_RANGE_OFST(str, m_range, m_ofst ) \ {\ UWORD32 m_clz, m_range_shift, m_ofst_shift; \ m_clz = CLZ(m_range); \ m_clz -= (32 - RANGE_NUMBITS); \ m_range_shift = m_range << m_clz; \ m_range_shift = m_range_shift >> RANGE_SHIFT; \ m_ofst_shift = m_ofst << m_clz; \ m_ofst_shift = m_ofst_shift >> RANGE_SHIFT; \ fprintf( g_trace.fp, "%-40s R: %3d O: %3d\n", str, m_range_shift, m_ofst_shift); \ } #else #define DEBUG_RANGE_OFST(str, m_range, m_ofst) \ fprintf( g_trace.fp, "%-40s R: %3d O: %3d\n", str, m_range, m_ofst); #endif #else #define DEBUG_RANGE_OFST(str, m_range, m_ofst ) #endif /*****************************************************************************/ /* Function Definitions */ /*****************************************************************************/ /** ****************************************************************************** * * @brief Initializes the decoder cabac engine * * @par Description * This routine needs to be called at start of slice/frame decode * * @param[in,out] ps_cabac_ctxt * pointer to cabac context (handle) * * @param[in] ps_bitstrm * pointer to bitstream context (handle) * * @param[in] qp * current slice Qp * * @param[in] cabac_init_idc * current slice init idc (range [0 - 2]) * * @param[in] pu1_init_ctxt * Init cabac context to be used (range [0 - 2]) * * @return success or failure error code * ****************************************************************************** */ IHEVCD_ERROR_T ihevcd_cabac_init(cab_ctxt_t *ps_cabac, bitstrm_t *ps_bitstrm, WORD32 qp, WORD32 cabac_init_idc, const UWORD8 *pu1_init_ctxt) { /* Sanity checks */ ASSERT(ps_cabac != NULL); ASSERT(ps_bitstrm != NULL); ASSERT((qp >= 0) && (qp < 52)); ASSERT((cabac_init_idc >= 0) && (cabac_init_idc < 3)); UNUSED(qp); UNUSED(cabac_init_idc); /* CABAC engine uses 32 bit range instead of 9 bits as specified by * the spec. This is done to reduce number of renormalizations */ /* cabac engine initialization */ #if FULLRANGE ps_cabac->u4_range = (UWORD32)510 << RANGE_SHIFT; BITS_GET(ps_cabac->u4_ofst, ps_bitstrm->pu4_buf, ps_bitstrm->u4_bit_ofst, ps_bitstrm->u4_cur_word, ps_bitstrm->u4_nxt_word, (9 + RANGE_SHIFT)); #else ps_cabac->u4_range = (UWORD32)510; BITS_GET(ps_cabac->u4_ofst, ps_bitstrm->pu4_buf, ps_bitstrm->u4_bit_ofst, ps_bitstrm->u4_cur_word, ps_bitstrm->u4_nxt_word, 9); #endif /* cabac context initialization based on init idc and slice qp */ memcpy(ps_cabac->au1_ctxt_models, pu1_init_ctxt, IHEVC_CAB_CTXT_END); DEBUG_RANGE_OFST("init", ps_cabac->u4_range, ps_cabac->u4_ofst); /* * If the offset is greater than or equal to range, return fail. */ if(ps_cabac->u4_ofst >= ps_cabac->u4_range) { return ((IHEVCD_ERROR_T)IHEVCD_FAIL); } return ((IHEVCD_ERROR_T)IHEVCD_SUCCESS); } IHEVCD_ERROR_T ihevcd_cabac_reset(cab_ctxt_t *ps_cabac, bitstrm_t *ps_bitstrm) { /* Sanity checks */ ASSERT(ps_cabac != NULL); ASSERT(ps_bitstrm != NULL); /* CABAC engine uses 32 bit range instead of 9 bits as specified by * the spec. This is done to reduce number of renormalizations */ /* cabac engine initialization */ #if FULLRANGE ps_cabac->u4_range = (UWORD32)510 << RANGE_SHIFT; BITS_GET(ps_cabac->u4_ofst, ps_bitstrm->pu4_buf, ps_bitstrm->u4_bit_ofst, ps_bitstrm->u4_cur_word, ps_bitstrm->u4_nxt_word, (9 + RANGE_SHIFT)); #else ps_cabac->u4_range = (UWORD32)510; BITS_GET(ps_cabac->u4_ofst, ps_bitstrm->pu4_buf, ps_bitstrm->u4_bit_ofst, ps_bitstrm->u4_cur_word, ps_bitstrm->u4_nxt_word, 9); #endif return ((IHEVCD_ERROR_T)IHEVCD_SUCCESS); } /** ****************************************************************************** * * @brief Decodes a bin based on probablilty and mps packed context model * * @par Description * Decodes a bin as per Section : 9.3.3.2.1 and calls renormalization if required * as per section 9.3.3.2.2 * 1. Apart from decoding bin, context model is updated as per state transition * 2. Range and Low renormalization is done based on bin and original state * 3. After renorm bistream is updated (if required) * * @param[in,out] ps_cabac * pointer to cabac context (handle) * * @param[in] ctxt_index * index of cabac context model containing pState[bits6-1] | MPS[bit0] * * @param[in] ps_bitstrm * Bitstream context * * @return bin(boolean) to be decoded * ****************************************************************************** */ UWORD32 ihevcd_cabac_decode_bin(cab_ctxt_t *ps_cabac, bitstrm_t *ps_bitstrm, WORD32 ctxt_index ) { UWORD32 u4_range = ps_cabac->u4_range; UWORD32 u4_ofst = ps_cabac->u4_ofst; UWORD32 u4_rlps; UWORD32 u4_bin; UWORD8 *pu1_ctxt_model = &ps_cabac->au1_ctxt_models[ctxt_index]; WORD32 state_mps = *pu1_ctxt_model; #if FULLRANGE WORD32 clz; #endif UWORD32 u4_qnt_range; /* Sanity checks */ ASSERT(u4_range >= 256); ASSERT((ctxt_index >= 0) && (ctxt_index < IHEVC_CAB_CTXT_END)); ASSERT(state_mps < 128); #if FULLRANGE clz = CLZ(u4_range); clz -= (32 - RANGE_NUMBITS); u4_qnt_range = u4_range << clz; u4_qnt_range = (u4_qnt_range >> (RANGE_SHIFT + 6)) & 0x3; #else u4_qnt_range = (u4_range >> 6) & 0x3; #endif /* Get the lps range from LUT based on quantized range and state */ u4_rlps = gau1_ihevc_cabac_rlps[state_mps >> 1][u4_qnt_range]; #if FULLRANGE u4_rlps = u4_rlps << (RANGE_SHIFT - clz); #endif u4_range -= u4_rlps; u4_bin = state_mps & 1; if(u4_ofst >= u4_range) { u4_bin = 1 - u4_bin; u4_ofst -= u4_range; u4_range = u4_rlps; } *pu1_ctxt_model = gau1_ihevc_next_state[(state_mps << 1) | u4_bin]; /*****************************************************************/ /* Re-normalization; calculate bits generated based on range(R) */ /*****************************************************************/ if(u4_range < (1 << 8)) { UWORD32 u4_bits; WORD32 numbits; numbits = CLZ(u4_range); numbits -= (32 - RANGE_NUMBITS); #if !FULLRANGE numbits -= RANGE_SHIFT; #endif BITS_GET(u4_bits, ps_bitstrm->pu4_buf, ps_bitstrm->u4_bit_ofst, ps_bitstrm->u4_cur_word, ps_bitstrm->u4_nxt_word, numbits); u4_ofst <<= numbits; u4_ofst |= u4_bits; u4_range <<= numbits; } /* Update the cabac context */ ps_cabac->u4_range = u4_range; ps_cabac->u4_ofst = u4_ofst; DEBUG_RANGE_OFST("bin", ps_cabac->u4_range, ps_cabac->u4_ofst); return (u4_bin); } /** ****************************************************************************** * * @brief Decodes a bypass bin (equi-probable 0 / 1) * * @par Description * Decodes a bypss bin as per Section : 9.3.3.2.3 * * @param[in,out] ps_cabac * pointer to cabac context (handle) * * @param[in] ps_bitstrm * Bitstream context * * @return Decoded bypass bin * ****************************************************************************** */ UWORD32 ihevcd_cabac_decode_bypass_bin(cab_ctxt_t *ps_cabac, bitstrm_t *ps_bitstrm) { UWORD32 u4_bin; UWORD32 u4_range = ps_cabac->u4_range; UWORD32 u4_ofst = ps_cabac->u4_ofst; UWORD32 u4_bits; /* Sanity checks */ ASSERT(u4_range >= 256); BIT_GET(u4_bits, ps_bitstrm->pu4_buf, ps_bitstrm->u4_bit_ofst, ps_bitstrm->u4_cur_word, ps_bitstrm->u4_nxt_word); u4_ofst <<= 1; u4_ofst |= u4_bits; u4_bin = 0; if(u4_ofst >= u4_range) { u4_bin = 1; u4_ofst -= u4_range; } /* Update the cabac context */ ps_cabac->u4_ofst = u4_ofst; DEBUG_RANGE_OFST("bypass end", ps_cabac->u4_range, ps_cabac->u4_ofst); return (u4_bin); } /** ****************************************************************************** * * @brief Decodes a terminate bin (1:terminate 0:do not terminate) * * @par Description * Decodes a terminate bin to be called for end_of_slice_flag and pcm_flag * as per Section : 9.3.3.2.4 * * @param[in,out] ps_cabac * pointer to cabac context (handle) * * @param[in] ps_bitstrm * Bitstream context * * @return Decoded Bin to indicate whether to terminate or not * ****************************************************************************** */ UWORD32 ihevcd_cabac_decode_terminate(cab_ctxt_t *ps_cabac, bitstrm_t *ps_bitstrm) { UWORD32 u4_range = ps_cabac->u4_range; UWORD32 u4_ofst = ps_cabac->u4_ofst; UWORD32 u4_bin; #if FULLRANGE WORD32 clz; #endif /* Sanity checks */ ASSERT(u4_range >= 256); #if FULLRANGE clz = CLZ(u4_range); clz -= (32 - RANGE_NUMBITS); u4_range -= 2 << (RANGE_SHIFT - clz); #else u4_range -= 2; #endif if(u4_ofst >= u4_range) { u4_bin = 1; #if FULLRANGE /* In case of FULLRANGE extra bits read earlier need to pushed back to the bitstream */ { WORD32 clz; WORD32 numbits; clz = CLZ(ps_cabac->u4_range); numbits = (32 - clz); numbits -= 9; ihevcd_bits_seek(ps_bitstrm, -numbits); } #endif } else { u4_bin = 0; } if(0 == u4_bin) { UWORD32 u4_bits; WORD32 numbits; numbits = CLZ(u4_range); numbits -= (32 - RANGE_NUMBITS); #if !FULLRANGE numbits -= RANGE_SHIFT; #endif /* Renormalize if required */ if(numbits) { BITS_GET(u4_bits, ps_bitstrm->pu4_buf, ps_bitstrm->u4_bit_ofst, ps_bitstrm->u4_cur_word, ps_bitstrm->u4_nxt_word, numbits); u4_ofst <<= numbits; u4_ofst |= u4_bits; u4_range <<= numbits; } } /* bits to be inserted in the bitstream */ ps_cabac->u4_range = u4_range; ps_cabac->u4_ofst = u4_ofst; DEBUG_RANGE_OFST("term", ps_cabac->u4_range, ps_cabac->u4_ofst); return (u4_bin); } /** ****************************************************************************** * * @brief Decodes a bypass bin (equi-probable 0 / 1) * * @par Description * Decodes a bypss bin as per Section : 9.3.3.2.3 * * @param[in,out] ps_cabac * pointer to cabac context (handle) * * @param[in] ps_bitstrm * Bitstream context * * @param[in] numbins * Number of bins to decoded * * @return Decoded bypass bin * * @remarks Tested only for numbins less than 17 * ****************************************************************************** */ UWORD32 ihevcd_cabac_decode_bypass_bins(cab_ctxt_t *ps_cabac, bitstrm_t *ps_bitstrm, WORD32 numbins) { UWORD32 u4_bins; UWORD32 u4_range = ps_cabac->u4_range; UWORD32 u4_ofst = ps_cabac->u4_ofst; UWORD32 u4_bits; ASSERT(u4_range >= 256); ASSERT(numbins > 0); /* Sanity checks */ ASSERT(numbins < 17); u4_bins = 0; BITS_GET(u4_bits, ps_bitstrm->pu4_buf, ps_bitstrm->u4_bit_ofst, ps_bitstrm->u4_cur_word, ps_bitstrm->u4_nxt_word, numbins); do { UWORD32 u4_bit; numbins--; u4_bit = (u4_bits >> numbins) & 1; u4_ofst <<= 1; u4_ofst |= u4_bit; u4_bins <<= 1; if(u4_ofst >= u4_range) { u4_bins += 1; u4_ofst -= u4_range; } }while(numbins); /* Update the cabac context */ ps_cabac->u4_ofst = u4_ofst; DEBUG_RANGE_OFST("bypass", ps_cabac->u4_range, ps_cabac->u4_ofst); return (u4_bins); } /** ****************************************************************************** * * @brief Decodes a truncated unary symbol associated with context model(s) * * @par Description * Decodes symbols coded with TUnary binarization as per sec 9.3.2.2 * This is used for computing symbols like qp_delta, * last_sig_coeff_prefix_x, last_sig_coeff_prefix_y. * * The context models associated with each bin is computed as : * current bin context = "base context idx" + (bin_idx >> shift) * where * 1. "base context idx" is the base index for the syntax element * 2. "bin_idx" is the current bin index of the unary code * 3. "shift" is the shift factor associated with this syntax element * * @param[in,out] ps_cabac * pointer to cabac context (handle) * * @param[in] ps_bitstrm * Bitstream context * * @param[in] c_max * maximum value of sym (required for tunary binarization) * * @param[in] ctxt_index * base context model index for this syntax element * * @param[in] ctxt_shift * shift factor for context increments associated with this syntax element * * @param[in] ctxt_inc_max * max value of context increment beyond which all bins will use same ctxt * * @return syntax element decoded * ****************************************************************************** */ UWORD32 ihevcd_cabac_decode_bins_tunary(cab_ctxt_t *ps_cabac, bitstrm_t *ps_bitstrm, WORD32 c_max, WORD32 ctxt_index, WORD32 ctxt_shift, WORD32 ctxt_inc_max) { UWORD32 u4_sym; WORD32 bin; /* Sanity checks */ ASSERT(c_max > 0); ASSERT((ctxt_index >= 0) && (ctxt_index < IHEVC_CAB_CTXT_END)); ASSERT((ctxt_index + (c_max >> ctxt_shift)) < IHEVC_CAB_CTXT_END); u4_sym = 0; do { WORD32 bin_index; bin_index = ctxt_index + MIN((u4_sym >> ctxt_shift), (UWORD32)ctxt_inc_max); IHEVCD_CABAC_DECODE_BIN(bin, ps_cabac, ps_bitstrm, bin_index); u4_sym++; }while(((WORD32)u4_sym < c_max) && bin); u4_sym = u4_sym - 1 + bin; return (u4_sym); } /** ****************************************************************************** * * @brief Decodes a syntax element as truncated unary bypass bins * * @par Description * Decodes symbols coded with TUnary binarization as per sec 9.3.2.2 * These symbols are coded as bypass bins * This is used for computing symbols like merge_idx, * mpm_idx etc * * @param[in,out]ps_cabac * pointer to cabac context (handle) * * @param[in] ps_bitstrm * Bitstream context * * @param[in] c_max * maximum value of sym (required for tunary binarization) * * @return syntax element decoded * ****************************************************************************** */ UWORD32 ihevcd_cabac_decode_bypass_bins_tunary(cab_ctxt_t *ps_cabac, bitstrm_t *ps_bitstrm, WORD32 c_max) { UWORD32 u4_sym; WORD32 bin; UWORD32 u4_ofst = ps_cabac->u4_ofst; UWORD32 u4_range = ps_cabac->u4_range; UWORD32 u4_bits; /* Sanity checks */ ASSERT(c_max > 0); ASSERT(u4_range >= 256); u4_sym = 0; BITS_NXT(u4_bits, ps_bitstrm->pu4_buf, ps_bitstrm->u4_bit_ofst, ps_bitstrm->u4_cur_word, ps_bitstrm->u4_nxt_word, (UWORD32)c_max); u4_bits <<= (32 - c_max); do { u4_ofst <<= 1; u4_ofst |= (u4_bits >> 31); u4_bits <<= 1; bin = 0; if(u4_ofst >= u4_range) { bin = 1; u4_ofst -= u4_range; } u4_sym++; }while(((WORD32)u4_sym < c_max) && bin); BITS_FLUSH(ps_bitstrm->pu4_buf, ps_bitstrm->u4_bit_ofst, ps_bitstrm->u4_cur_word, ps_bitstrm->u4_nxt_word, u4_sym); u4_sym = u4_sym - 1 + bin; /* Update the cabac context */ ps_cabac->u4_ofst = u4_ofst; return (u4_sym); } /** ****************************************************************************** * * @brief Decodes a syntax element as kth order Exp-Golomb code (EGK) * * @par Description * Decodes a syntax element binarized as kth order Exp-Golomb code (EGK) * Elements are coded as bypass bins * * @param[in,out] ps_cabac * pointer to cabac context (handle) * * @param[in] u4_sym * syntax element to be coded as EGK * * @param[in] k * order of EGk * * @return success or failure error code * ****************************************************************************** */ UWORD32 ihevcd_cabac_decode_bypass_bins_egk(cab_ctxt_t *ps_cabac, bitstrm_t *ps_bitstrm, WORD32 k) { UWORD32 u4_sym; WORD32 numones; WORD32 bin; /* Sanity checks */ ASSERT((k >= 0)); numones = k; bin = 1; u4_sym = 0; while(bin && (numones <= 16)) { IHEVCD_CABAC_DECODE_BYPASS_BIN(bin, ps_cabac, ps_bitstrm); u4_sym += bin << numones++; } numones -= 1; if(numones) { UWORD32 u4_suffix; IHEVCD_CABAC_DECODE_BYPASS_BINS(u4_suffix, ps_cabac, ps_bitstrm, numones); u4_sym += u4_suffix; } return (u4_sym); } /** ****************************************************************************** * * @brief Decodes a syntax element as truncated rice code (TR) * * @par Description * Decodes a syntax element as truncated rice code (TR) * Elements are coded as bypass bins * This function ise used for coeff_abs_level_remaining coding when * level is less than c_rice_max * * @param[in,out] ps_cabac * pointer to cabac context (handle) * * @param[in] u4_sym * syntax element to be coded as truncated rice code * * @param[in] c_rice_param * shift factor for truncated unary prefix coding of (u4_sym >> c_rice_param) * * @param[in] c_rice_max * max symbol val below which a suffix is coded as (u4_sym%(1<= 0)); /* Decode prefix coded as TUnary */ c_max = c_rice_max >> c_rice_param; u4_sym = 0; do { IHEVCD_CABAC_DECODE_BYPASS_BIN(bin, ps_cabac, ps_bitstrm); u4_sym++; }while(((WORD32)u4_sym < c_max) && bin); u4_sym = u4_sym - 1 + bin; /* If suffix is present, then decode c_rice_param number of bins */ if(c_rice_param) { IHEVCD_CABAC_DECODE_BYPASS_BINS(u4_suffix, ps_cabac, ps_bitstrm, c_rice_param); u4_sym = (u4_sym << c_rice_param) | u4_suffix; } return (u4_sym); }