C++程序  |  760行  |  21.73 KB

/******************************************************************************
*
* 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 <stdio.h>
#include <stddef.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>

#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<<c_rice_param))
 *    This is currently (4 << c_rice_param) for coeff_abs_level_remaining
 *
 *  @return      success or failure error code
 *
 ******************************************************************************
 */
UWORD32 ihevcd_cabac_decode_bypass_bins_trunc_rice(cab_ctxt_t *ps_cabac,
                                                   bitstrm_t *ps_bitstrm,
                                                   WORD32 c_rice_param,
                                                   WORD32 c_rice_max)
{
    UWORD32 u4_sym;
    WORD32 bin;
    WORD32 c_max;
    UWORD32 u4_suffix;
    /* Sanity checks */
    ASSERT((c_rice_param >= 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);
}