/******************************************************************************
 *
 * 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_parse_mb_header.c
 *
 * \brief
 *    This file contains context identifier encoding routines.
 *
 * \date
 *    04/02/2003
 *
 * \author  NS
 ***************************************************************************
 */
#include <string.h>
#include "ih264d_structs.h"
#include "ih264d_bitstrm.h"
#include "ih264d_cabac.h"
#include "ih264_typedefs.h"
#include "ih264_macros.h"
#include "ih264_platform_macros.h"
#include "ih264d_defs.h"
#include "ih264d_error_handler.h"
#include "ih264d_tables.h"
#include "ih264d_debug.h"
#include "ih264d_defs.h"
#include "ih264d_defs.h"
#include "ih264d_mb_utils.h"
#include "ih264d_parse_mb_header.h"
#include "ih264d_defs.h"

/*! < CtxtInc index 0 - CtxMbTypeI, CtxMbTypeSISuffix
 index 1 - CtxMbTypePSuffix, CtxMbTypeBSuffix
 */



/*!
 **************************************************************************
 * \if Function name : ih264d_parse_mb_type_intra_cabac \endif
 *
 * \brief
 *    This function decodes MB type using CABAC entropy coding mode.
 *
 * \return
 *    MBType.
 *
 **************************************************************************
 */
UWORD8 ih264d_parse_mb_type_intra_cabac(UWORD8 u1_inter,
                                        struct _DecStruct * ps_dec)
{
    decoding_envirnoment_t * ps_cab_env = &ps_dec->s_cab_dec_env;
    dec_bit_stream_t * ps_bitstrm = ps_dec->ps_bitstrm;
    ctxt_inc_mb_info_t * ps_left_ctxt = ps_dec->p_left_ctxt_mb_info;
    ctxt_inc_mb_info_t * ps_top_ctxt = ps_dec->p_top_ctxt_mb_info;
    bin_ctxt_model_t *ps_mb_bin_ctxt = ps_dec->p_mb_type_t;
    WORD8 u1_mb_type, u1_bin;
    UWORD32 u4_cxt_inc;

    u4_cxt_inc = 0;
    if(!u1_inter)
    {
        if(ps_left_ctxt != ps_dec->ps_def_ctxt_mb_info)
            u4_cxt_inc += ((ps_left_ctxt->u1_mb_type != CAB_I4x4) ? 1 : 0);
        if(ps_top_ctxt != ps_dec->ps_def_ctxt_mb_info)
            u4_cxt_inc += ((ps_top_ctxt->u1_mb_type != CAB_I4x4) ? 1 : 0);
    }
    else
    {
        ps_mb_bin_ctxt = ps_mb_bin_ctxt + 3 + (ps_dec->u1_B << 1);
    }

    /* b0 */
    u1_mb_type = (UWORD8)ih264d_decode_bin(u4_cxt_inc, ps_mb_bin_ctxt, ps_bitstrm,
                                          ps_cab_env);
    if(u1_mb_type)
    {
        /* I16x16 or I_PCM mode */
        /* b1 */
        u1_bin = ih264d_decode_terminate(ps_cab_env, ps_bitstrm);
        if(u1_bin == 0)
        {
            /* I16x16 mode */
            /* Read b2 and b3 */
            u4_cxt_inc = (u1_inter) ? 0x021 : 0x043;

            u1_bin = ih264d_decode_bins(2, u4_cxt_inc, ps_mb_bin_ctxt, ps_bitstrm,
                                        ps_cab_env);

            if(u1_bin & 0x01)
                u1_mb_type += 4;

            if(u1_bin & 0x02)
                u1_mb_type += 12;

            if(u1_bin & 0x01)
            {
                /* since b3=1, Read three bins */
                u4_cxt_inc = (u1_inter) ? 0x0332 : 0x0765;
                u1_bin = (UWORD8)ih264d_decode_bins(3, u4_cxt_inc, ps_mb_bin_ctxt,
                                                    ps_bitstrm, ps_cab_env);

            }
            else
            {
                /* Read two bins */
                u4_cxt_inc = (u1_inter) ? 0x033 : 0x076;
                u1_bin = (UWORD8)ih264d_decode_bins(2, u4_cxt_inc, ps_mb_bin_ctxt,
                                                    ps_bitstrm, ps_cab_env);
            }
            u1_mb_type += u1_bin;
        }
        else
        {
            /* I_PCM mode */
            /* b1=1 */
            u1_mb_type = 25;
        }
    }
    return (u1_mb_type);
}

/*!
 **************************************************************************
 * \if Function name : ih264d_parse_mb_type_cabac \endif
 *
 * \brief
 *    This function decodes MB type using CABAC entropy coding mode.
 *
 * \return
 *    MBType.
 *
 **************************************************************************
 */
UWORD32 ih264d_parse_mb_type_cabac(struct _DecStruct * ps_dec)
{
    const UWORD8 uc_slice_type = ps_dec->ps_cur_slice->u1_slice_type;
    decoding_envirnoment_t *ps_cab_env = &ps_dec->s_cab_dec_env;
    dec_bit_stream_t *ps_bitstrm = ps_dec->ps_bitstrm;
    ctxt_inc_mb_info_t *ps_left_ctxt = ps_dec->p_left_ctxt_mb_info;
    ctxt_inc_mb_info_t *ps_top_ctxt = ps_dec->p_top_ctxt_mb_info;
    WORD8 c_ctxt_inc;
    bin_ctxt_model_t *ps_mb_bin_ctxt = ps_dec->p_mb_type_t;
    WORD8 u1_mb_type = 0, u1_bin;
    UWORD32 u4_cxt_inc;

    INC_SYM_COUNT(ps_cab_env);

    c_ctxt_inc = 0;

    if(uc_slice_type == SI_SLICE)
    {
        /* b0 */
        if(ps_left_ctxt != ps_dec->ps_def_ctxt_mb_info)
            c_ctxt_inc += ((ps_left_ctxt->u1_mb_type != CAB_SI4x4) ? 1 : 0);
        if(ps_top_ctxt != ps_dec->ps_def_ctxt_mb_info)
            c_ctxt_inc += ((ps_top_ctxt->u1_mb_type != CAB_SI4x4) ? 1 : 0);

        u4_cxt_inc = c_ctxt_inc;
        u1_bin = (UWORD8)ih264d_decode_bin(u4_cxt_inc, ps_mb_bin_ctxt, ps_bitstrm,
                                           ps_cab_env);
        if(u1_bin == 0)
        {
            /* SI MB */
            u1_mb_type = 0;
        }
        else
        {
            u1_mb_type = 1 + ih264d_parse_mb_type_intra_cabac(0, ps_dec);
        }
    }
    else if(uc_slice_type == P_SLICE)
    {
        /* P Slice */
        /* b0 */
        u4_cxt_inc = 0;
        u1_bin = (UWORD8)ih264d_decode_bin(u4_cxt_inc, ps_mb_bin_ctxt, ps_bitstrm,
                                           ps_cab_env);
        if(!u1_bin)
        {
            /* Inter MB types */
            /* b1 */
            u4_cxt_inc = 0x01;
            u1_bin = (UWORD8)ih264d_decode_bin(u4_cxt_inc, ps_mb_bin_ctxt,
                                               ps_bitstrm, ps_cab_env);
            /* b2 */
            u4_cxt_inc = u1_bin + 2;
            u1_mb_type = (UWORD8)ih264d_decode_bin(u4_cxt_inc, ps_mb_bin_ctxt,
                                                  ps_bitstrm, ps_cab_env);
            u1_mb_type = (u1_bin << 1) + u1_mb_type;
            if(u1_mb_type)
                u1_mb_type = 4 - u1_mb_type;
        }
        else
        {
            /* Intra Prefix 1 found */
            /* Intra MB type */
            u1_mb_type = 5 + ih264d_parse_mb_type_intra_cabac(1, ps_dec);
        }
    }
    else if(uc_slice_type == B_SLICE)
    {
        WORD8 a, b;
        /* B Slice */
        /* b0 */
        /* a = b = 0, if B slice and MB is a SKIP or B_DIRECT16x16 */
        a = 0;
        b = 0;
        u1_mb_type = 0;
        if(ps_left_ctxt != ps_dec->ps_def_ctxt_mb_info)
            a = ((ps_left_ctxt->u1_mb_type & CAB_BD16x16_MASK) != CAB_BD16x16);
        if(ps_top_ctxt != ps_dec->ps_def_ctxt_mb_info)
            b = ((ps_top_ctxt->u1_mb_type & CAB_BD16x16_MASK) != CAB_BD16x16);

        u4_cxt_inc = a + b;

        u1_bin = (UWORD8)ih264d_decode_bin(u4_cxt_inc, ps_mb_bin_ctxt, ps_bitstrm,
                                           ps_cab_env);

        if(u1_bin)
        {

            /* b1 */
            u4_cxt_inc = 0x03;
            u1_bin = (UWORD8)ih264d_decode_bin(u4_cxt_inc, ps_mb_bin_ctxt,
                                               ps_bitstrm, ps_cab_env);

            if(!u1_bin)
            {
                /* b2 */
                u4_cxt_inc = 0x05;
                u1_bin = (UWORD8)ih264d_decode_bin(u4_cxt_inc, ps_mb_bin_ctxt,
                                                   ps_bitstrm, ps_cab_env);

                u1_mb_type = u1_bin + 1;
            }
            else
            {
                u1_mb_type = 3;
                /* b2 */
                u4_cxt_inc = 0x04;
                u1_bin = (UWORD8)ih264d_decode_bin(u4_cxt_inc, ps_mb_bin_ctxt,
                                                   ps_bitstrm, ps_cab_env);

                if(u1_bin)
                {
                    u1_mb_type += 8;
                    /* b3 */
                    u4_cxt_inc = 0x05;
                    u1_bin = (UWORD8)ih264d_decode_bin(u4_cxt_inc, ps_mb_bin_ctxt,
                                                       ps_bitstrm, ps_cab_env);

                    if(!u1_bin)
                    {
                        u1_mb_type++;
                        /* b4, b5, b6 */
                        u4_cxt_inc = 0x0555;
                        u1_bin = (UWORD8)ih264d_decode_bins(3, u4_cxt_inc,
                                                            ps_mb_bin_ctxt,
                                                            ps_bitstrm,
                                                            ps_cab_env);



                        u1_mb_type += u1_bin;
                    }
                    else
                    {
                        /* b4 */
                        u4_cxt_inc = 0x05;
                        u1_bin = (UWORD8)ih264d_decode_bin(u4_cxt_inc,
                                                           ps_mb_bin_ctxt,
                                                           ps_bitstrm,
                                                           ps_cab_env);

                        if(u1_bin)
                        {
                            /* b5 */
                            u1_bin = (UWORD8)ih264d_decode_bin(u4_cxt_inc,
                                                               ps_mb_bin_ctxt,
                                                               ps_bitstrm,
                                                               ps_cab_env);

                            u1_mb_type += (u1_bin ? 11 : 0);
                        }
                        else
                        {
                            u1_mb_type = 20;
                            /* b5 */
                            u1_bin = (UWORD8)ih264d_decode_bin(u4_cxt_inc,
                                                               ps_mb_bin_ctxt,
                                                               ps_bitstrm,
                                                               ps_cab_env);

                            if(!u1_bin)
                            {
                                /* b6 */
                                u1_bin = (UWORD8)ih264d_decode_bin(u4_cxt_inc,
                                                                   ps_mb_bin_ctxt,
                                                                   ps_bitstrm,
                                                                   ps_cab_env);

                                u1_mb_type += u1_bin;
                            }
                            else
                            {
                                /* Intra Prefix 111101 found */
                                /* Intra MB type */
                                u1_mb_type =
                                                23
                                                                + ih264d_parse_mb_type_intra_cabac(
                                                                                1,
                                                                                ps_dec);
                            }
                        }
                    }
                }
                else
                {
                    /* b3, b4, b5 */
                    u4_cxt_inc = 0x0555;
                    u1_bin = (UWORD8)ih264d_decode_bins(3, u4_cxt_inc,
                                                        ps_mb_bin_ctxt, ps_bitstrm,
                                                        ps_cab_env);




                    u1_mb_type += u1_bin;
                }
            }
        }
    }
    return ((UWORD32)u1_mb_type);
}

/*!
 **************************************************************************
 * \if Function name : DecSubMBType \endif
 *
 * \brief
 *    This function decodes MB type using CABAC entropy coding mode.
 *
 * \return
 *    MBType.
 *
 **************************************************************************
 */
UWORD32 ih264d_parse_submb_type_cabac(const UWORD8 u1_slc_type_b,
                                      decoding_envirnoment_t * ps_cab_env,
                                      dec_bit_stream_t * ps_bitstrm,
                                      bin_ctxt_model_t * ps_sub_mb_cxt)
{
    WORD8 u1_sub_mb_type, u1_bin;

    INC_SYM_COUNT(ps_cab_env);

    u1_sub_mb_type = 0;
    u1_bin = (UWORD8)ih264d_decode_bin(0, ps_sub_mb_cxt, ps_bitstrm,
                                       ps_cab_env);

    if(u1_slc_type_b ^ u1_bin)
        return 0;

    if(!u1_slc_type_b)
    {
        /* P Slice */
        u1_sub_mb_type = 1;
        u1_bin = (UWORD8)ih264d_decode_bin(1, ps_sub_mb_cxt, ps_bitstrm,
                                           ps_cab_env);
        if(u1_bin == 1)
        {
            u1_bin = (UWORD8)ih264d_decode_bin(2, ps_sub_mb_cxt, ps_bitstrm,
                                               ps_cab_env);
            u1_sub_mb_type = (2 + (!u1_bin));
        }

        return u1_sub_mb_type;
    }
    else
    {
        /* B Slice */

        /* b1 */
        u1_bin = (UWORD8)ih264d_decode_bin(1, ps_sub_mb_cxt, ps_bitstrm,
                                           ps_cab_env);
        if(u1_bin)
        {
            /* b2 */
            u1_bin = (UWORD8)ih264d_decode_bin(2, ps_sub_mb_cxt, ps_bitstrm,
                                               ps_cab_env);
            if(u1_bin)
            {
                /* b3 */
                u1_sub_mb_type = 7;
                u1_bin = (UWORD8)ih264d_decode_bin(3, ps_sub_mb_cxt, ps_bitstrm,
                                                   ps_cab_env);
                u1_sub_mb_type += u1_bin << 2;
                u1_bin = !u1_bin;
                /* b4 */
                if(u1_bin == 0)
                {
                    u1_bin = ih264d_decode_bin(3, ps_sub_mb_cxt, ps_bitstrm,
                                               ps_cab_env);
                }
                else
                {
                    u1_bin = (UWORD8)ih264d_decode_bins(2, 0x33, ps_sub_mb_cxt,
                                                        ps_bitstrm, ps_cab_env);
                }

                return (u1_sub_mb_type + u1_bin);
            }
            else
            {
                /* b3 */
                u1_bin = (UWORD8)ih264d_decode_bins(2, 0x33, ps_sub_mb_cxt,
                                                    ps_bitstrm, ps_cab_env);
                return (3 + u1_bin);
            }
        }
        else
        {
            /* b2 */
            u1_bin = (UWORD8)ih264d_decode_bin(3, ps_sub_mb_cxt, ps_bitstrm,
                                               ps_cab_env);
            return (1 + u1_bin);
        }
    }
}

/*!
 **************************************************************************
 * \if Function name : ih264d_parse_ref_idx_cabac \endif
 *
 * \brief
 *    This function decodes Reference Index using CABAC entropy coding mode.
 *
 * \return
 *    None
 *
 **************************************************************************
 */
WORD32 ih264d_parse_ref_idx_cabac(const UWORD8 u1_num_part,
                                const UWORD8 u1_b2,
                                const UWORD8 u1_max_ref_minus1,
                                const UWORD8 u1_mb_mode,
                                WORD8 * pi1_ref_idx,
                                WORD8 * const pi1_lft_cxt,
                                WORD8 * const pi1_top_cxt,
                                decoding_envirnoment_t * const ps_cab_env,
                                dec_bit_stream_t * const ps_bitstrm,
                                bin_ctxt_model_t * const ps_ref_cxt)
{
    UWORD8 u1_a, u1_b;
    UWORD32 u4_cxt_inc;
    UWORD8 u1_blk_no, u1_i, u1_idx_lft, u1_idx_top;
    WORD8 i1_ref_idx;

    for(u1_blk_no = 0, u1_i = 0; u1_i < u1_num_part; u1_i++, pi1_ref_idx++)
    {
        u1_idx_lft = ((u1_blk_no & 0x02) >> 1) + u1_b2;
        u1_idx_top = (u1_blk_no & 0x01) + u1_b2;
        i1_ref_idx = *pi1_ref_idx;

        if(i1_ref_idx > 0)
        {
            u1_a = pi1_lft_cxt[u1_idx_lft] > 0;
            u1_b = pi1_top_cxt[u1_idx_top] > 0;

            u4_cxt_inc = u1_a + (u1_b << 1);
            u4_cxt_inc = (u4_cxt_inc | 0x55540);

            i1_ref_idx = (WORD8)ih264d_decode_bins_unary(32, u4_cxt_inc,
                                                         ps_ref_cxt, ps_bitstrm,
                                                         ps_cab_env);

            if((i1_ref_idx > u1_max_ref_minus1) || (i1_ref_idx < 0))
            {
                return ERROR_REF_IDX;
            }

            *pi1_ref_idx = i1_ref_idx;

            INC_SYM_COUNT(ps_cab_env);

        }

        /* Storing Reference Idx Information */
        pi1_lft_cxt[u1_idx_lft] = i1_ref_idx;
        pi1_top_cxt[u1_idx_top] = i1_ref_idx;
        u1_blk_no = u1_blk_no + 1 + (u1_mb_mode & 0x01);
    }
    /* if(!u1_sub_mb) */
    if(u1_num_part != 4)
    {
        pi1_lft_cxt[(!(u1_mb_mode & 0x1)) + u1_b2] = pi1_lft_cxt[u1_b2];
        pi1_top_cxt[(!(u1_mb_mode & 0x2)) + u1_b2] = pi1_top_cxt[u1_b2];
    }
    return OK;
}

/*!
 **************************************************************************
 * \if Function name : ih264d_parse_mb_qp_delta_cabac \endif
 *
 * \brief
 *    This function decodes MB Qp delta using CABAC entropy coding mode.
 *
 * \return
 *    None
 *
 **************************************************************************
 */
WORD32 ih264d_parse_mb_qp_delta_cabac(struct _DecStruct * ps_dec,
                                      WORD8 *pi1_mb_qp_delta)
{
    decoding_envirnoment_t * ps_cab_env = &ps_dec->s_cab_dec_env;
    dec_bit_stream_t * ps_bitstrm = ps_dec->ps_bitstrm;

    UWORD8 u1_code_num;
    bin_ctxt_model_t *ps_mb_qp_delta_ctxt = ps_dec->p_mb_qp_delta_t;
    UWORD32 u4_cxt_inc;

    INC_SYM_COUNT(ps_cab_env);

    u4_cxt_inc = (!(!(ps_dec->i1_prev_mb_qp_delta)));

    u1_code_num = 0;
    u4_cxt_inc = (u4_cxt_inc | 0x33320);
    /* max number of bins = 53,
     since Range for MbQpDelta= -26 to +25 inclusive, UNARY code */
    u1_code_num = ih264d_decode_bins_unary(32, u4_cxt_inc, ps_mb_qp_delta_ctxt,
                                          ps_bitstrm, ps_cab_env);
    if(u1_code_num == 32)
    {
        /* Read remaining 21 bins */
        UWORD8 uc_codeNumX;
        u4_cxt_inc = 0x33333;
        uc_codeNumX = ih264d_decode_bins_unary(21, u4_cxt_inc, ps_mb_qp_delta_ctxt,
                                               ps_bitstrm, ps_cab_env);
        u1_code_num = u1_code_num + uc_codeNumX;
    }

    *pi1_mb_qp_delta = (u1_code_num + 1) >> 1;
    /* Table 9.3: If code_num is even Syntax Element has -ve value */
    if(!(u1_code_num & 0x01))
        *pi1_mb_qp_delta = -(*pi1_mb_qp_delta);

    /* Range of MbQpDelta= -26 to +25 inclusive */
    if((*pi1_mb_qp_delta < -26) || (*pi1_mb_qp_delta > 25))
        return ERROR_INV_RANGE_QP_T;
    ps_dec->i1_prev_mb_qp_delta = *pi1_mb_qp_delta;
    return OK;
}
/*!
 **************************************************************************
 * \if Function name : ih264d_parse_chroma_pred_mode_cabac \endif
 *
 * \brief
 *    This function decodes Chroma Pred mode using CABAC entropy coding mode.
 *
 * \return
 *    None
 *
 **************************************************************************
 */
WORD8 ih264d_parse_chroma_pred_mode_cabac(struct _DecStruct * ps_dec)
{
    decoding_envirnoment_t * ps_cab_env = &ps_dec->s_cab_dec_env;
    dec_bit_stream_t * ps_bitstrm = ps_dec->ps_bitstrm;
    ctxt_inc_mb_info_t * ps_left_ctxt = ps_dec->p_left_ctxt_mb_info;
    ctxt_inc_mb_info_t * ps_top_ctxt = ps_dec->p_top_ctxt_mb_info;
    WORD8 i1_chroma_pred_mode, a, b;
    UWORD32 u4_cxt_inc;

    INC_SYM_COUNT(ps_cab_env);

    /* Binarization is TU and Cmax=3 */
    i1_chroma_pred_mode = 0;
    a = 0;
    b = 0;

    a = ((ps_left_ctxt->u1_intra_chroma_pred_mode != 0) ? 1 : 0);

    b = ((ps_top_ctxt->u1_intra_chroma_pred_mode != 0) ? 1 : 0);
    u4_cxt_inc = a + b;

    u4_cxt_inc = (u4_cxt_inc | 0x330);

    i1_chroma_pred_mode = ih264d_decode_bins_tunary(
                    3, u4_cxt_inc, ps_dec->p_intra_chroma_pred_mode_t,
                    ps_bitstrm, ps_cab_env);

    return (i1_chroma_pred_mode);
}

/*****************************************************************************/
/*                                                                           */
/*  Function Name : ih264d_parse_transform8x8flag_cabac                                     */
/*                                                                           */
/*  Description   :                                                          */
/*  Inputs        :                                                          */
/*                                                                           */
/*                                                                           */
/*  Returns       :                                                          */
/*                                                                           */
/*  Revision History:                                                        */
/*                                                                           */
/*         DD MM YYYY   Author(s)       Changes (Describe the changes made)  */
/*                      Rajasekhar      Creation                             */
/*                                                                           */
/*****************************************************************************/
UWORD8 ih264d_parse_transform8x8flag_cabac(struct _DecStruct * ps_dec,
                                           dec_mb_info_t * ps_cur_mb_info)
{
    decoding_envirnoment_t * ps_cab_env = &ps_dec->s_cab_dec_env;
    dec_bit_stream_t * ps_bitstrm = ps_dec->ps_bitstrm;
    ctxt_inc_mb_info_t * ps_left_ctxt = ps_dec->p_left_ctxt_mb_info;
    ctxt_inc_mb_info_t * ps_top_ctxt = ps_dec->p_top_ctxt_mb_info;
    UWORD8 u1_transform_8x8flag;
    UWORD8 u1_mb_ngbr_avail = ps_cur_mb_info->u1_mb_ngbr_availablity;

    WORD8 a, b;
    UWORD32 u4_cxt_inc;

    /* for calculating the context increment for transform8x8 u4_flag */
    /* it reads transform8x8 u4_flag of the neighbors through */

    /* Binarization is FLC */
    a = 0;
    b = 0;

    if(u1_mb_ngbr_avail & LEFT_MB_AVAILABLE_MASK)
    {
        a = ps_left_ctxt->u1_transform8x8_ctxt;
    }
    if(u1_mb_ngbr_avail & TOP_MB_AVAILABLE_MASK)
    {
        b = ps_top_ctxt->u1_transform8x8_ctxt;

    }

    u4_cxt_inc = a + b;

    u1_transform_8x8flag = ih264d_decode_bin(
                    u4_cxt_inc, ps_dec->s_high_profile.ps_transform8x8_flag,
                    ps_bitstrm, ps_cab_env);

    return (u1_transform_8x8flag);
}

/*!
 **************************************************************************
 * \if Function name : ih264d_read_intra_pred_modes_cabac \endif
 *
 * \brief
 *    Reads the intra pred mode related values of I4x4 MB from bitstream.
 *
 *    This function will read the prev intra pred mode flags and
 *    stores it in pu1_prev_intra4x4_pred_mode_flag. If the u4_flag
 *    indicates that most probable mode is not intra pred mode, then
 *    the rem_intra4x4_pred_mode is read and stored in
 *    pu1_rem_intra4x4_pred_mode array.
 *
 *
 * \return
 *    0 on success and Error code otherwise
 *
 **************************************************************************
 */
WORD32 ih264d_read_intra_pred_modes_cabac(dec_struct_t * ps_dec,
                                          UWORD8 * pu1_prev_intra4x4_pred_mode_flag,
                                          UWORD8 * pu1_rem_intra4x4_pred_mode,
                                          UWORD8 u1_tran_form8x8)
{
    WORD32 i4x4_luma_blk_idx = 0;
    dec_bit_stream_t * ps_bitstrm = ps_dec->ps_bitstrm;
    decoding_envirnoment_t * ps_cab_env = &ps_dec->s_cab_dec_env;
    bin_ctxt_model_t *ps_ctxt_ipred_luma_mpm, *ps_ctx_ipred_luma_rm;
    WORD32 i4_rem_intra4x4_pred_mode;
    UWORD32 u4_prev_intra4x4_pred_mode_flag;
    UWORD32 u4_code_int_range, u4_code_int_val_ofst;
    const UWORD32 *pu4_table = (const UWORD32 *)ps_cab_env->cabac_table;

    ps_ctxt_ipred_luma_mpm = ps_dec->p_prev_intra4x4_pred_mode_flag_t;
    ps_ctx_ipred_luma_rm = ps_dec->p_rem_intra4x4_pred_mode_t;
    SWITCHOFFTRACE;

    i4x4_luma_blk_idx = (0 == u1_tran_form8x8) ? 16 : 4;

    u4_code_int_range = ps_cab_env->u4_code_int_range;
    u4_code_int_val_ofst = ps_cab_env->u4_code_int_val_ofst;

    do
    {

        DECODE_ONE_BIN_MACRO(ps_ctxt_ipred_luma_mpm, u4_code_int_range,
                             u4_code_int_val_ofst, pu4_table, ps_bitstrm,
                             u4_prev_intra4x4_pred_mode_flag)
        *pu1_prev_intra4x4_pred_mode_flag = u4_prev_intra4x4_pred_mode_flag;

        i4_rem_intra4x4_pred_mode = -1;
        if(!u4_prev_intra4x4_pred_mode_flag)
        {

            /*inlining DecodeDecisionBins_FLC*/

            {

                UWORD8 u1_max_bins = 3;
                UWORD32 u4_value;
                UWORD32 u4_symbol, i;

                i = 0;
                u4_value = 0;

                do
                {

                    DECODE_ONE_BIN_MACRO(ps_ctx_ipred_luma_rm, u4_code_int_range,
                                         u4_code_int_val_ofst, pu4_table,
                                         ps_bitstrm, u4_symbol)

                    INC_BIN_COUNT(ps_cab_env);INC_DECISION_BINS(ps_cab_env);

                    u4_value = u4_value | (u4_symbol << i);

                    i++;
                }
                while(i < u1_max_bins);

                i4_rem_intra4x4_pred_mode = (u4_value);

            }

        }

        (*pu1_rem_intra4x4_pred_mode) = i4_rem_intra4x4_pred_mode;

        COPYTHECONTEXT("intra4x4_pred_mode", i4_rem_intra4x4_pred_mode);

        pu1_prev_intra4x4_pred_mode_flag++;
        pu1_rem_intra4x4_pred_mode++;

        i4x4_luma_blk_idx--;
    }
    while(i4x4_luma_blk_idx);

    ps_cab_env->u4_code_int_range = u4_code_int_range;
    ps_cab_env->u4_code_int_val_ofst = u4_code_int_val_ofst;

    return (0);

}

/*!
 **************************************************************************
 * \if Function name : ih264d_parse_ctx_cbp_cabac \endif
 *
 * \brief
 *    This function decodes CtxCbpLuma and CtxCbpChroma (CBP of a Macroblock).
 *    using CABAC entropy coding mode.
 *
 * \return
 *    CBP of a MB.
 *
 **************************************************************************
 */
UWORD32 ih264d_parse_ctx_cbp_cabac(struct _DecStruct * ps_dec)
{

    UWORD32 u4_cxt_inc;
    decoding_envirnoment_t * ps_cab_env = &ps_dec->s_cab_dec_env;
    dec_bit_stream_t * ps_bitstrm = ps_dec->ps_bitstrm;
    ctxt_inc_mb_info_t * ps_left_ctxt = ps_dec->p_left_ctxt_mb_info;
    ctxt_inc_mb_info_t * ps_top_ctxt = ps_dec->p_top_ctxt_mb_info;
    bin_ctxt_model_t *ps_ctxt_cbp_luma = ps_dec->p_cbp_luma_t, *ps_bin_ctxt;
    WORD8 c_Cbp; //,i,j;
    UWORD32 u4_code_int_range, u4_code_int_val_ofst;
    UWORD32 u4_offset, *pu4_buffer;
    const UWORD32 *pu4_table = (const UWORD32 *)ps_cab_env->cabac_table;

    INC_SYM_COUNT(ps_cab_env);



    /* CBP Luma, FL, Cmax = 15, L = 4 */
    u4_cxt_inc = (!((ps_top_ctxt->u1_cbp >> 2) & 0x01)) << 1;
    u4_cxt_inc += !((ps_left_ctxt->u1_cbp >> 1) & 0x01);

    u4_offset = ps_bitstrm->u4_ofst;
    pu4_buffer = ps_bitstrm->pu4_buffer;

    u4_code_int_range = ps_cab_env->u4_code_int_range;
    u4_code_int_val_ofst = ps_cab_env->u4_code_int_val_ofst;
    /*renormalize to ensure there 23 bits more in the u4_code_int_val_ofst*/
    {
        UWORD32 u4_clz, read_bits;

        u4_clz = CLZ(u4_code_int_range);
        FLUSHBITS(u4_offset, u4_clz)
        NEXTBITS(read_bits, u4_offset, pu4_buffer, 23)
        u4_code_int_range = u4_code_int_range << u4_clz;
        u4_code_int_val_ofst = (u4_code_int_val_ofst << u4_clz) | read_bits;
    }

    ps_bin_ctxt = ps_ctxt_cbp_luma + u4_cxt_inc;

    /*inlining DecodeDecision_onebin without renorm*/
    {

        UWORD32 u4_qnt_int_range, u4_int_range_lps;
        UWORD32 u4_symbol, u1_mps_state;
        UWORD32 table_lookup;
        UWORD32 u4_clz;

        u1_mps_state = (ps_bin_ctxt->u1_mps_state);

        u4_clz = CLZ(u4_code_int_range);
        u4_qnt_int_range = u4_code_int_range << u4_clz;
        u4_qnt_int_range = (u4_qnt_int_range >> 29) & 0x3;

        table_lookup = pu4_table[(u1_mps_state << 2) + u4_qnt_int_range];
        u4_int_range_lps = table_lookup & 0xff;

        u4_int_range_lps = u4_int_range_lps << (23 - u4_clz);
        u4_code_int_range = u4_code_int_range - u4_int_range_lps;

        u4_symbol = ((u1_mps_state >> 6) & 0x1);

        /*if mps*/
        u1_mps_state = (table_lookup >> 8) & 0x7F;

        CHECK_IF_LPS(u4_code_int_range, u4_code_int_val_ofst, u4_symbol,
                     u4_int_range_lps, u1_mps_state, table_lookup)

        INC_BIN_COUNT(ps_cab_env);

        ps_bin_ctxt->u1_mps_state = u1_mps_state;

        c_Cbp = u4_symbol;

    }

    u4_cxt_inc = (!((ps_top_ctxt->u1_cbp >> 3) & 0x01)) << 1;
    u4_cxt_inc += !(c_Cbp & 0x01);
    ps_bin_ctxt = ps_ctxt_cbp_luma + u4_cxt_inc;
    /*inlining DecodeDecision_onebin without renorm*/

    {

        UWORD32 u4_qnt_int_range, u4_int_range_lps;
        UWORD32 u4_symbol, u1_mps_state;
        UWORD32 table_lookup;
        UWORD32 u4_clz;

        u1_mps_state = (ps_bin_ctxt->u1_mps_state);

        u4_clz = CLZ(u4_code_int_range);
        u4_qnt_int_range = u4_code_int_range << u4_clz;
        u4_qnt_int_range = (u4_qnt_int_range >> 29) & 0x3;

        table_lookup = pu4_table[(u1_mps_state << 2) + u4_qnt_int_range];
        u4_int_range_lps = table_lookup & 0xff;

        u4_int_range_lps = u4_int_range_lps << (23 - u4_clz);
        u4_code_int_range = u4_code_int_range - u4_int_range_lps;

        u4_symbol = ((u1_mps_state >> 6) & 0x1);

        /*if mps*/
        u1_mps_state = (table_lookup >> 8) & 0x7F;

        CHECK_IF_LPS(u4_code_int_range, u4_code_int_val_ofst, u4_symbol,
                     u4_int_range_lps, u1_mps_state, table_lookup)

        INC_BIN_COUNT(ps_cab_env);

        ps_bin_ctxt->u1_mps_state = u1_mps_state;

        c_Cbp |= u4_symbol << 1;

    }

    u4_cxt_inc = (!(c_Cbp & 0x01)) << 1;
    u4_cxt_inc += !((ps_left_ctxt->u1_cbp >> 3) & 0x01);
    ps_bin_ctxt = ps_ctxt_cbp_luma + u4_cxt_inc;
    /*inlining DecodeDecision_onebin without renorm*/

    {

        UWORD32 u4_qnt_int_range, u4_int_range_lps;
        UWORD32 u4_symbol, u1_mps_state;
        UWORD32 table_lookup;
        UWORD32 u4_clz;

        u1_mps_state = (ps_bin_ctxt->u1_mps_state);

        u4_clz = CLZ(u4_code_int_range);
        u4_qnt_int_range = u4_code_int_range << u4_clz;
        u4_qnt_int_range = (u4_qnt_int_range >> 29) & 0x3;

        table_lookup = pu4_table[(u1_mps_state << 2) + u4_qnt_int_range];
        u4_int_range_lps = table_lookup & 0xff;

        u4_int_range_lps = u4_int_range_lps << (23 - u4_clz);
        u4_code_int_range = u4_code_int_range - u4_int_range_lps;

        u4_symbol = ((u1_mps_state >> 6) & 0x1);

        /*if mps*/
        u1_mps_state = (table_lookup >> 8) & 0x7F;

        CHECK_IF_LPS(u4_code_int_range, u4_code_int_val_ofst, u4_symbol,
                     u4_int_range_lps, u1_mps_state, table_lookup)

        INC_BIN_COUNT(ps_cab_env);

        ps_bin_ctxt->u1_mps_state = u1_mps_state;

        c_Cbp |= u4_symbol << 2;

    }

    u4_cxt_inc = (!((c_Cbp >> 1) & 0x01)) << 1;
    u4_cxt_inc += !((c_Cbp >> 2) & 0x01);
    ps_bin_ctxt = ps_ctxt_cbp_luma + u4_cxt_inc;
    /*inlining DecodeDecision_onebin without renorm*/

    {

        UWORD32 u4_qnt_int_range, u4_int_range_lps;
        UWORD32 u4_symbol, u1_mps_state;
        UWORD32 table_lookup;
        UWORD32 u4_clz;

        u1_mps_state = (ps_bin_ctxt->u1_mps_state);

        u4_clz = CLZ(u4_code_int_range);
        u4_qnt_int_range = u4_code_int_range << u4_clz;
        u4_qnt_int_range = (u4_qnt_int_range >> 29) & 0x3;

        table_lookup = pu4_table[(u1_mps_state << 2) + u4_qnt_int_range];
        u4_int_range_lps = table_lookup & 0xff;

        u4_int_range_lps = u4_int_range_lps << (23 - u4_clz);
        u4_code_int_range = u4_code_int_range - u4_int_range_lps;

        u4_symbol = ((u1_mps_state >> 6) & 0x1);

        /*if mps*/
        u1_mps_state = (table_lookup >> 8) & 0x7F;

        CHECK_IF_LPS(u4_code_int_range, u4_code_int_val_ofst, u4_symbol,
                     u4_int_range_lps, u1_mps_state, table_lookup)

        INC_BIN_COUNT(ps_cab_env);

        ps_bin_ctxt->u1_mps_state = u1_mps_state;

        c_Cbp |= u4_symbol << 3;

    }

    if(u4_code_int_range < ONE_RIGHT_SHIFTED_BY_8)
    {

        RENORM_RANGE_OFFSET(u4_code_int_range, u4_code_int_val_ofst, u4_offset,
                            pu4_buffer)

    }

    {
        UWORD32 u4_cxt_inc;
        WORD8 a, b, c, d;
        bin_ctxt_model_t *p_CtxtCbpChroma = ps_dec->p_cbp_chroma_t;

        /* CBP Chroma, TU, Cmax = 2 */
        a = 0;
        b = 0;
        c = 0;
        d = 0;

        {
            a = (ps_top_ctxt->u1_cbp > 15) ? 2 : 0;
            c = (ps_top_ctxt->u1_cbp > 31) ? 2 : 0;
        }

        {
            b = (ps_left_ctxt->u1_cbp > 15) ? 1 : 0;
            d = (ps_left_ctxt->u1_cbp > 31) ? 1 : 0;
        }
        u4_cxt_inc = a + b;
        u4_cxt_inc = (u4_cxt_inc | ((4 + c + d) << 4));

        /*inlining ih264d_decode_bins_tunary */

        {

            UWORD8 u1_max_bins = 2;
            UWORD32 u4_ctx_inc = u4_cxt_inc;

            UWORD32 u4_value;
            UWORD32 u4_symbol;
            UWORD8 u4_ctx_Inc;
            bin_ctxt_model_t *ps_bin_ctxt;
            u4_value = 0;

            do
            {
                u4_ctx_Inc = u4_ctx_inc & 0xF;
                u4_ctx_inc = u4_ctx_inc >> 4;

                ps_bin_ctxt = p_CtxtCbpChroma + u4_ctx_Inc;
                /*inlining DecodeDecision_onebin*/
                {

                    UWORD32 u4_qnt_int_range, u4_int_range_lps;

                    UWORD32 u1_mps_state;
                    UWORD32 table_lookup;
                    UWORD32 u4_clz;

                    u1_mps_state = (ps_bin_ctxt->u1_mps_state);

                    u4_clz = CLZ(u4_code_int_range);
                    u4_qnt_int_range = u4_code_int_range << u4_clz;
                    u4_qnt_int_range = (u4_qnt_int_range >> 29) & 0x3;

                    table_lookup = pu4_table[(u1_mps_state << 2)
                                    + u4_qnt_int_range];
                    u4_int_range_lps = table_lookup & 0xff;

                    u4_int_range_lps = u4_int_range_lps << (23 - u4_clz);
                    u4_code_int_range = u4_code_int_range - u4_int_range_lps;

                    u4_symbol = ((u1_mps_state >> 6) & 0x1);

                    /*if mps*/
                    u1_mps_state = (table_lookup >> 8) & 0x7F;

                    CHECK_IF_LPS(u4_code_int_range, u4_code_int_val_ofst,
                                 u4_symbol, u4_int_range_lps, u1_mps_state,
                                 table_lookup)

                    if(u4_code_int_range < ONE_RIGHT_SHIFTED_BY_8)
                    {
                        RENORM_RANGE_OFFSET(u4_code_int_range,
                                            u4_code_int_val_ofst, u4_offset,
                                            pu4_buffer)
                    }
                    ps_bin_ctxt->u1_mps_state = u1_mps_state;
                }

                INC_BIN_COUNT(ps_cab_env);INC_DECISION_BINS(
                                ps_cab_env);

                u4_value++;
            }
            while((u4_value < u1_max_bins) & (u4_symbol));

            u4_value = u4_value - 1 + u4_symbol;

            a = (u4_value);

        }

c_Cbp = (c_Cbp | (a << 4));
}

ps_bitstrm->u4_ofst = u4_offset;

ps_cab_env->u4_code_int_range = u4_code_int_range;
ps_cab_env->u4_code_int_val_ofst = u4_code_int_val_ofst;

return (c_Cbp);
}

/*!
 **************************************************************************
 * \if Function name : ih264d_get_mvd_cabac \endif
 *
 * \brief
 *    This function decodes Horz and Vert mvd_l0 and mvd_l1 using CABAC entropy
 *    coding mode as defined in 9.3.2.3.
 *
 * \return
 *    None
 *
 **************************************************************************
 */
void ih264d_get_mvd_cabac(UWORD8 u1_sub_mb,
                          UWORD8 u1_b2,
                          UWORD8 u1_part_wd,
                          UWORD8 u1_part_ht,
                          UWORD8 u1_dec_mvd,
                          dec_struct_t *ps_dec,
                          mv_pred_t *ps_mv)
{
    UWORD8 u1_abs_mvd_x = 0, u1_abs_mvd_y = 0;
    UWORD8 u1_sub_mb_x, u1_sub_mb_y;
    UWORD8 *pu1_top_mv_ctxt, *pu1_lft_mv_ctxt;
    WORD16 *pi2_mv;

    u1_sub_mb_x = (UWORD8)(u1_sub_mb & 0x03);
    u1_sub_mb_y = (UWORD8)(u1_sub_mb >> 2);
    pu1_top_mv_ctxt = &ps_dec->ps_curr_ctxt_mb_info->u1_mv[u1_sub_mb_x][u1_b2];
    pu1_lft_mv_ctxt = &ps_dec->pu1_left_mv_ctxt_inc[u1_sub_mb_y][u1_b2];
    pi2_mv = &ps_mv->i2_mv[u1_b2];

    if(u1_dec_mvd)
    {
        WORD16 i2_mv_x, i2_mv_y;
        WORD32 i2_temp;
        {
            decoding_envirnoment_t * ps_cab_env = &ps_dec->s_cab_dec_env;
            dec_bit_stream_t * ps_bitstrm = ps_dec->ps_bitstrm;
            UWORD16 u2_abs_mvd_x_a, u2_abs_mvd_x_b, u2_abs_mvd_y_a,
                            u2_abs_mvd_y_b;

            u2_abs_mvd_x_b = (UWORD16)pu1_top_mv_ctxt[0];
            u2_abs_mvd_y_b = (UWORD16)pu1_top_mv_ctxt[1];
            u2_abs_mvd_x_a = (UWORD16)pu1_lft_mv_ctxt[0];
            u2_abs_mvd_y_a = (UWORD16)pu1_lft_mv_ctxt[1];

            i2_temp = u2_abs_mvd_x_a + u2_abs_mvd_x_b;

            i2_mv_x = ih264d_parse_mvd_cabac(ps_bitstrm, ps_cab_env,
                                             ps_dec->p_mvd_x_t, i2_temp);

            i2_temp = u2_abs_mvd_y_a + u2_abs_mvd_y_b;

            i2_mv_y = ih264d_parse_mvd_cabac(ps_bitstrm, ps_cab_env,
                                             ps_dec->p_mvd_y_t, i2_temp);
        }

        /***********************************************************************/
        /* Store the abs_mvd_values in cabac contexts                          */
        /* The follownig code can be easily optimzed if mvX, mvY clip values   */
        /* are packed in 16 bits follwed by memcpy                             */
        /***********************************************************************/
        u1_abs_mvd_x = CLIP3(0, 127, ABS(i2_mv_x));
        u1_abs_mvd_y = CLIP3(0, 127, ABS(i2_mv_y));

        COPYTHECONTEXT("MVD", i2_mv_x);COPYTHECONTEXT("MVD", i2_mv_y);

        /* Storing Mv residuals */
        pi2_mv[0] = i2_mv_x;
        pi2_mv[1] = i2_mv_y;
    }

    /***************************************************************/
    /* Store abs_mvd_values cabac contexts                         */
    /***************************************************************/
#ifndef ARM
    {
        UWORD8 u1_i;
        for(u1_i = 0; u1_i < u1_part_wd; u1_i++, pu1_top_mv_ctxt += 4)
        {
            pu1_top_mv_ctxt[0] = u1_abs_mvd_x;
            pu1_top_mv_ctxt[1] = u1_abs_mvd_y;
        }

        for(u1_i = 0; u1_i < u1_part_ht; u1_i++, pu1_lft_mv_ctxt += 4)
        {
            pu1_lft_mv_ctxt[0] = u1_abs_mvd_x;
            pu1_lft_mv_ctxt[1] = u1_abs_mvd_y;
        }
    }
#else
    /* Optimising the loop, with Little-Endian Assumption */
    {
        UWORD16 *pu2_top_cxt = (UWORD16 *)pu1_top_mv_ctxt;
        UWORD16 *pu2_lft_cxt = (UWORD16 *)pu1_lft_mv_ctxt;
        UWORD16 u2_pack_mvd = (UWORD16)((u1_abs_mvd_y << 8) | u1_abs_mvd_x);
        UWORD8 u1_wd = u1_part_wd, u1_ht = u1_part_ht;

        u1_wd--;
        *pu2_top_cxt = u2_pack_mvd;
        pu2_top_cxt += 2;
        if(u1_wd)
        {
            u1_wd--;
            *pu2_top_cxt = u2_pack_mvd;
            pu2_top_cxt += 2;
        }
        if(u1_wd)
        {
            *pu2_top_cxt = u2_pack_mvd;
            pu2_top_cxt += 2;
            *pu2_top_cxt = u2_pack_mvd;
        }
        u1_ht--;
        *pu2_lft_cxt = u2_pack_mvd;
        pu2_lft_cxt += 2;
        if(u1_ht)
        {
            u1_ht--;
            *pu2_lft_cxt = u2_pack_mvd;
            pu2_lft_cxt += 2;
        }
        if(u1_ht)
        {
            *pu2_lft_cxt = u2_pack_mvd;
            pu2_lft_cxt += 2;
            *pu2_lft_cxt = u2_pack_mvd;
        }
    }
#endif
}

/*****************************************************************************/
/*                                                                           */
/*  Function Name : ih264d_parse_mvd_cabac                                                  */
/*                                                                           */
/*  Description   : This cabac function decodes the mvd in a given direction */
/*                  direction ( x or y ) as defined in 9.3.2.3.              */
/*                                                                           */
/*  Inputs        : 1. pointer to Bitstream                                  */
/*                  2. pointer to cabac decoding environmnet                 */
/*                  3. pointer to Mvd context                                */
/*                  4. abs(Top mvd) = u2_abs_mvd_b                           */
/*                  5. abs(left mvd)= u2_abs_mvd_a                           */
/*                                                                           */
/*  Processing    : see section 9.3.2.3 of the standard                      */
/*                                                                           */
/*  Outputs       : i2_mvd                                                   */
/*  Returns       : i2_mvd                                                   */
/*                                                                           */
/*  Issues        : none                                                     */
/*                                                                           */
/*  Revision History:                                                        */
/*                                                                           */
/*         DD MM YYYY   Author(s)       Changes (Describe the changes made)  */
/*         16 06 2005   Jay          Draft                                   */
/*                                                                           */
/*****************************************************************************/
WORD16 ih264d_parse_mvd_cabac(dec_bit_stream_t * ps_bitstrm,
                              decoding_envirnoment_t * ps_cab_env,
                              bin_ctxt_model_t * p_ctxt_mvd,
                              UWORD32 i4_temp)

{
    WORD8 k;
    WORD16 i2_suf;
    WORD16 i2_mvd;
    UWORD16 u2_abs_mvd;
    UWORD32 u4_ctx_inc;
    UWORD32 u4_prefix;
    const UWORD32 *pu4_table = (const UWORD32 *)ps_cab_env->cabac_table;
    UWORD32 u4_code_int_range, u4_code_int_val_ofst;

    /*  if mvd < 9                                                  */
    /*  mvd =  Prefix                                                   */
    /*  else                                                            */
    /*  mvd = Prefix + Suffix                                           */
    /*  decode sign bit                                                 */
    /*  Prefix TU decoding Cmax =Ucoff and Suffix 3rd order Exp-Golomb  */

    u2_abs_mvd = (UWORD16)i4_temp;
    u4_ctx_inc = 1;

    if(u2_abs_mvd < 3)
        u4_ctx_inc = 0;
    else if(u2_abs_mvd > 32)
        u4_ctx_inc = 2;

    u4_ctx_inc = (u4_ctx_inc | 0x65430);

    /*inlining modified version of ih264d_decode_bins_unary*/

    {
        UWORD8 u1_max_bins = 9;
        UWORD32 u4_value;
        UWORD32 u4_symbol;
        bin_ctxt_model_t *ps_bin_ctxt;
        UWORD32 u4_ctx_Inc;

        u4_value = 0;
        u4_code_int_range = ps_cab_env->u4_code_int_range;
        u4_code_int_val_ofst = ps_cab_env->u4_code_int_val_ofst;

        do
        {
            u4_ctx_Inc = u4_ctx_inc & 0xf;
            u4_ctx_inc = u4_ctx_inc >> 4;

            ps_bin_ctxt = p_ctxt_mvd + u4_ctx_Inc;

            DECODE_ONE_BIN_MACRO(ps_bin_ctxt, u4_code_int_range,
                                 u4_code_int_val_ofst, pu4_table, ps_bitstrm,
                                 u4_symbol)

            INC_BIN_COUNT(ps_cab_env);INC_DECISION_BINS(ps_cab_env);

            u4_value++;

        }
        while(u4_symbol && u4_value < 5);

        ps_bin_ctxt = p_ctxt_mvd + 6;

        if(u4_symbol && (u4_value < u1_max_bins))
        {

            do
            {

                DECODE_ONE_BIN_MACRO(ps_bin_ctxt, u4_code_int_range,
                                     u4_code_int_val_ofst, pu4_table,
                                     ps_bitstrm, u4_symbol)

                INC_BIN_COUNT(ps_cab_env);INC_DECISION_BINS(ps_cab_env);
                u4_value++;
            }
            while(u4_symbol && (u4_value < u1_max_bins));

        }

        ps_cab_env->u4_code_int_range = u4_code_int_range;
        ps_cab_env->u4_code_int_val_ofst = u4_code_int_val_ofst;
        u4_value = u4_value - 1 + u4_symbol;
        u4_prefix = (u4_value);
    }

    i2_mvd = u4_prefix;

    if(i2_mvd == 9)
    {
        /* Read Suffix */
        k = ih264d_decode_bypass_bins_unary(ps_cab_env, ps_bitstrm);
        i2_suf = (1 << k) - 1;
        k = k + 3;
        i2_suf = (i2_suf << 3);
        i2_mvd += i2_suf;
        i2_suf = ih264d_decode_bypass_bins(ps_cab_env, k, ps_bitstrm);
        i2_mvd += i2_suf;
    }
    /* Read Sign bit */
    if(!i2_mvd)
        return (i2_mvd);

    else
    {
        UWORD32 u4_code_int_val_ofst, u4_code_int_range;

        u4_code_int_val_ofst = ps_cab_env->u4_code_int_val_ofst;
        u4_code_int_range = ps_cab_env->u4_code_int_range;

        if(u4_code_int_range < ONE_RIGHT_SHIFTED_BY_9)
        {
            UWORD32 *pu4_buffer, u4_offset;

            pu4_buffer = ps_bitstrm->pu4_buffer;
            u4_offset = ps_bitstrm->u4_ofst;

            RENORM_RANGE_OFFSET(u4_code_int_range, u4_code_int_val_ofst,
                                u4_offset, pu4_buffer)
            ps_bitstrm->u4_ofst = u4_offset;
        }

        u4_code_int_range = u4_code_int_range >> 1;

        if(u4_code_int_val_ofst >= u4_code_int_range)
        {
            /* S=1 */
            u4_code_int_val_ofst -= u4_code_int_range;
            i2_mvd = (-i2_mvd);
        }

        ps_cab_env->u4_code_int_val_ofst = u4_code_int_val_ofst;
        ps_cab_env->u4_code_int_range = u4_code_int_range;

        return (i2_mvd);

    }
}