/* ------------------------------------------------------------------
 * Copyright (C) 1998-2009 PacketVideo
 *
 * 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.
 * -------------------------------------------------------------------
 */
/*
*     -------------------------------------------------------------------       *
*                    MPEG-4 Simple Profile Video Decoder                        *
*     -------------------------------------------------------------------       *
*
* This software module was originally developed by
*
*   Paulo Nunes (IST / ACTS-MoMuSyS)
*   Robert Danielsen (Telenor / ACTS-MoMuSyS)
*
* in the course of development of the MPEG-4 Video (ISO/IEC 14496-2) standard.
* This software module is an implementation of a part of one or more MPEG-4
* Video (ISO/IEC 14496-2) tools as specified by the MPEG-4 Video (ISO/IEC
* 14496-2) standard.
*
* ISO/IEC gives users of the MPEG-4 Video (ISO/IEC 14496-2) standard free
* license to this software module or modifications thereof for use in hardware
* or software products claiming conformance to the MPEG-4 Video (ISO/IEC
* 14496-2) standard.
*
* Those intending to use this software module in hardware or software products
* are advised that its use may infringe existing patents. The original
* developer of this software module and his/her company, the subsequent
* editors and their companies, and ISO/IEC have no liability for use of this
* software module or modifications thereof in an implementation. Copyright is
* not released for non MPEG-4 Video (ISO/IEC 14496-2) Standard conforming
* products.
*
* ACTS-MoMuSys partners retain full right to use the code for his/her own
* purpose, assign or donate the code to a third party and to inhibit third
* parties from using the code for non MPEG-4 Video (ISO/IEC 14496-2) Standard
* conforming products. This copyright notice must be included in all copies or
* derivative works.
*
* Copyright (c) 1996
*
*****************************************************************************/

/***********************************************************HeaderBegin*******
*
* File: vlc_dec.c
*
* Author:   Paulo Nunes (IST) - Paulo.Nunes@lx.it.pt
* Created:  1-Mar-96
*
* Description: This file contains the VLC functions needed to decode a
*       bitstream.
*
* Notes:
*       The functions contained in this file were adapted from
*       tmndecode
*       Written by Karl Olav Lillevold <kol@nta.no>,
*       1995 Telenor R&D.
*       Donated to the Momusys-project as background code by
*       Telenor.
*
*       based on mpeg2decode, (C) 1994, MPEG Software Simulation Group
*       and mpeg2play, (C) 1994 Stefan Eckart
*                   <stefan@lis.e-technik.tu-muenchen.de>
*
*
* Modified: 9-May-96 Paulo Nunes: Reformatted. New headers.
*              17-Jan-97 Jan De Lameillieure (HHI) : corrected in
*              01.05.97 Luis Ducla-Soares: added RvlcDecTCOEF() to allow decoding
*                                          of Reversible VLCs.
*       09.03.98 Paulo Nunes: Cleaning.
*
***********************************************************HeaderEnd*********/

#include "mp4dec_lib.h"
#include "vlc_dec_tab.h"
#include "vlc_decode.h"
#include "bitstream.h"
#include "max_level.h"


/* ====================================================================== /
    Function : DecodeUserData()
    Date     : 04/10/2000
    History  :
    Modified : 04/16/2001 : removed status checking of PV_BitstreamFlushBits

        This is simply a realization of the user_data() function
        in the ISO/IEC 14496-2 manual.
/ ====================================================================== */
PV_STATUS DecodeUserData(BitstreamDecVideo *stream)
{
    PV_STATUS status;
    uint32 code;

    BitstreamReadBits32HC(stream);
    BitstreamShowBits32(stream, 24, &code);

    while (code != 1)
    {
        /* Discard user data for now.   04/05/2000 */
        BitstreamReadBits16(stream, 8);
        BitstreamShowBits32(stream, 24, &code);
        status = BitstreamCheckEndBuffer(stream);
        if (status == PV_END_OF_VOP) return status;    /*  03/19/2002 */
    }
    return PV_SUCCESS;
}



/***********************************************************CommentBegin******
*
*       3/10/00  : initial modification to the
*                new PV-Decoder Lib format.
*       3/29/00  : added return code check to some functions and
*                optimize the code.
*
***********************************************************CommentEnd********/
PV_STATUS PV_GetMBvectors(VideoDecData *video, uint mode)
{
    PV_STATUS status;
    BitstreamDecVideo *stream = video->bitstream;
    int  f_code_f = video->currVop->fcodeForward;
    int  vlc_code_mag;


    MOT *mot_x = video->motX;
    MOT *mot_y = video->motY;

    int k, offset;
    int x_pos = video->mbnum_col;
    int y_pos = video->mbnum_row;
    int doubleWidth = video->nMBPerRow << 1;
    int pos = (x_pos + y_pos * doubleWidth) << 1;
    MOT mvx = 0, mvy = 0;


    if (f_code_f == 1)
    {
#ifdef PV_ANNEX_IJKT_SUPPORT
        if (mode == MODE_INTER4V || mode == MODE_INTER4V_Q)
#else
        if (mode == MODE_INTER4V)
#endif
        {
            for (k = 0; k < 4; k++)
            {
                offset = (k & 1) + (k >> 1) * doubleWidth;
                mv_prediction(video, k, &mvx, &mvy);
                /* decode component x */
                status = PV_VlcDecMV(stream, &vlc_code_mag);
                if (status != PV_SUCCESS)
                {
                    return status;
                }

                mvx += (MOT)vlc_code_mag;
                mvx = (MOT)(((mvx + 32) & 0x3F) - 32);


                status = PV_VlcDecMV(stream, &vlc_code_mag);
                if (status != PV_SUCCESS)
                {
                    return status;
                }

                mvy += (MOT)vlc_code_mag;
                mvy = (MOT)(((mvy + 32) & 0x3F) - 32);

                mot_x[pos+offset] = (MOT) mvx;
                mot_y[pos+offset] = (MOT) mvy;
            }
        }
        else
        {
            mv_prediction(video, 0, &mvx, &mvy);
            /* For PVOPs, field  appears only in MODE_INTER & MODE_INTER_Q */
            status = PV_VlcDecMV(stream, &vlc_code_mag);
            if (status != PV_SUCCESS)
            {
                return status;
            }

            mvx += (MOT)vlc_code_mag;
            mvx = (MOT)(((mvx + 32) & 0x3F) - 32);


            status = PV_VlcDecMV(stream, &vlc_code_mag);
            if (status != PV_SUCCESS)
            {
                return status;
            }


            mvy += (MOT)vlc_code_mag;
            mvy = (MOT)(((mvy + 32) & 0x3F) - 32);


            mot_x[pos] = mot_x[pos+1] = (MOT) mvx;
            mot_y[pos] = mot_y[pos+1] = (MOT) mvy;
            pos += doubleWidth;
            mot_x[pos] = mot_x[pos+1] = (MOT) mvx;
            mot_y[pos] = mot_y[pos+1] = (MOT) mvy;
        }
    }
    else
    {
#ifdef PV_ANNEX_IJKT_SUPPORT
        if (mode == MODE_INTER4V || mode == MODE_INTER4V_Q)
#else
        if (mode == MODE_INTER4V)
#endif
        {
            for (k = 0; k < 4; k++)
            {
                offset = (k & 1) + (k >> 1) * doubleWidth;
                mv_prediction(video, k, &mvx, &mvy);
                status = PV_DecodeMBVec(stream, &mvx, &mvy, f_code_f);
                mot_x[pos+offset] = (MOT) mvx;
                mot_y[pos+offset] = (MOT) mvy;
                if (status != PV_SUCCESS)
                {
                    return status;
                }
            }
        }
        else
        {
            mv_prediction(video, 0, &mvx, &mvy);
            /* For PVOPs, field  appears only in MODE_INTER & MODE_INTER_Q */
            status = PV_DecodeMBVec(stream, &mvx, &mvy, f_code_f);
            mot_x[pos] = mot_x[pos+1] = (MOT) mvx;
            mot_y[pos] = mot_y[pos+1] = (MOT) mvy;
            pos += doubleWidth;
            mot_x[pos] = mot_x[pos+1] = (MOT) mvx;
            mot_y[pos] = mot_y[pos+1] = (MOT) mvy;
            if (status != PV_SUCCESS)
            {
                return status;
            }
        }
    }
    return PV_SUCCESS;
}


/***********************************************************CommentBegin******
*       3/10/00  : initial modification to the
*                new PV-Decoder Lib format.
*       3/29/00  : added return code check to some functions
*       5/10/00  : check whether the decoded vector is legal.
*       4/17/01  : use MOT type
***********************************************************CommentEnd********/
PV_STATUS PV_DecodeMBVec(BitstreamDecVideo *stream, MOT *mv_x, MOT *mv_y, int f_code_f)
{
    PV_STATUS status;
    int  vlc_code_magx, vlc_code_magy;
    int  residualx = 0, residualy = 0;

    /* decode component x */
    status = PV_VlcDecMV(stream, &vlc_code_magx);
    if (status != PV_SUCCESS)
    {
        return status;
    }

    if (vlc_code_magx)
    {
        residualx = (int) BitstreamReadBits16_INLINE(stream, (int)(f_code_f - 1));
    }


    /* decode component y */
    status = PV_VlcDecMV(stream, &vlc_code_magy);
    if (status != PV_SUCCESS)
    {
        return status;
    }

    if (vlc_code_magy)
    {
        residualy = (int) BitstreamReadBits16_INLINE(stream, (int)(f_code_f - 1));
    }


    if (PV_DeScaleMVD(f_code_f, residualx, vlc_code_magx, mv_x) != PV_SUCCESS)
    {
        return PV_FAIL;
    }

    if (PV_DeScaleMVD(f_code_f, residualy, vlc_code_magy, mv_y) != PV_SUCCESS)
    {
        return PV_FAIL;
    }

    return PV_SUCCESS;
}


/***********************************************************CommentBegin******
*       3/31/2000 : initial modification to the new PV-Decoder Lib format.
*       5/10/2000 : check to see if the decoded vector falls within
*                           the legal fcode range.
*
***********************************************************CommentEnd********/
PV_STATUS PV_DeScaleMVD(
    int  f_code,       /* <-- MV range in 1/2 units: 1=32,2=64,...,7=2048     */
    int  residual,     /* <-- part of the MV Diff. FLC coded                  */
    int  vlc_code_mag, /* <-- part of the MV Diff. VLC coded                  */
    MOT  *vector       /* --> Obtained MV component in 1/2 units              */
)
{
    int   half_range = (1 << (f_code + 4));
    int   mask = (half_range << 1) - 1;
    int   diff_vector;


    if (vlc_code_mag == 0)
    {
        diff_vector = vlc_code_mag;
    }
    else
    {
        diff_vector = ((PV_ABS(vlc_code_mag) - 1) << (f_code - 1)) + residual + 1;
        if (vlc_code_mag < 0)
        {
            diff_vector = -diff_vector;
        }
    }

    *vector += (MOT)(diff_vector);

    *vector = (MOT)((*vector + half_range) & mask) - half_range;

    return PV_SUCCESS;
}



void mv_prediction(
    VideoDecData *video,
    int block,
    MOT *mvx,
    MOT *mvy
)
{
    /*----------------------------------------------------------------------------
    ; Define all local variables
    ----------------------------------------------------------------------------*/
    MOT *motxdata = video->motX;
    MOT *motydata = video->motY;
    int mbnum_col = video->mbnum_col;
    int mbnum_row = video->mbnum_row;
    uint8 *slice_nb = video->sliceNo;
    int nMBPerRow = video->nMBPerRow;
    int nMVPerRow = nMBPerRow << 1;
    int mbnum = video->mbnum;
    int p1x = 0, p2x = 0, p3x = 0;
    int p1y = 0, p2y = 0, p3y = 0;
    int rule1 = 0, rule2 = 0, rule3 = 0;
    int     indx;

    indx = ((mbnum_col << 1) + (block & 1)) + ((mbnum_row << 1)  + (block >> 1)) * nMVPerRow - 1; /* left block */

    if (block & 1)           /* block 1, 3 */
    {
        p1x = motxdata[indx];
        p1y = motydata[indx];
        rule1 = 1;
    }
    else                    /* block 0, 2 */
    {
        if (mbnum_col > 0 && slice_nb[mbnum] == slice_nb[mbnum-1])
        {
            p1x = motxdata[indx];
            p1y = motydata[indx];
            rule1 = 1;
        }
    }

    indx = indx + 1 - nMVPerRow; /* upper_block */
    if (block >> 1)
    {
        indx -= (block & 1);
        p2x = motxdata[indx];
        p2y = motydata[indx];
        p3x = motxdata[indx + 1];
        p3y = motydata[indx + 1];
        rule2 = rule3 = 1;
    }
    else
    {                           /* block 0,1 */
        if (mbnum_row)
        {
            if (slice_nb[mbnum] == slice_nb[mbnum-nMBPerRow])
            {
                p2x = motxdata[indx];
                p2y = motydata[indx];
                rule2 = 1;
            }
            if (mbnum_col < nMBPerRow - 1 && slice_nb[mbnum] == slice_nb[mbnum-nMBPerRow+1])
            {
                indx = indx + 2 - (block & 1);
                p3x = motxdata[indx];
                p3y = motydata[indx];
                rule3 = 1;
            }
        }
    }

    if (rule1 + rule2 + rule3 > 1)
    {
        *mvx = (MOT)PV_MEDIAN(p1x, p2x, p3x);
        *mvy = (MOT)PV_MEDIAN(p1y, p2y, p3y);
    }
    else if (rule1 + rule2 + rule3 == 1)
    {
        /* two of three are zero */
        *mvx = (MOT)(p1x + p2x + p3x);
        *mvy = (MOT)(p1y + p2y + p3y);
    }
    else
    {
        /* all MBs are outside the VOP */
        *mvx = *mvy = 0;
    }
    /*----------------------------------------------------------------------------
    ; Return nothing or data or data pointer
    ----------------------------------------------------------------------------*/
    return;
}

/***********************************************************CommentBegin******
*
*       3/30/2000 : initial modification to the new PV-Decoder Lib format.
*       4/16/2001 : removed checking of status for PV_BitstreamFlushBits
***********************************************************CommentEnd********/

PV_STATUS PV_VlcDecMV(BitstreamDecVideo *stream, int *mv)
{
    PV_STATUS status = PV_SUCCESS;
    uint code;

    BitstreamShow13Bits(stream, &code);

    if (code >> 12)
    {
        *mv = 0; /* Vector difference = 0 */
        PV_BitstreamFlushBits(stream, 1);
        return PV_SUCCESS;
    }

    if (code >= 512)
    {
        code = (code >> 8) - 2;
        PV_BitstreamFlushBits(stream, PV_TMNMVtab0[code].len + 1);
        *mv = PV_TMNMVtab0[code].val;
        return status;
    }

    if (code >= 128)
    {
        code = (code >> 2) - 32;
        PV_BitstreamFlushBits(stream, PV_TMNMVtab1[code].len + 1);
        *mv = PV_TMNMVtab1[code].val;
        return status;
    }

    if (code < 4)
    {
        *mv = -1;
        return PV_FAIL;
    }

    code -= 4;

    PV_BitstreamFlushBits(stream, PV_TMNMVtab2[code].len + 1);

    *mv = PV_TMNMVtab2[code].val;
    return status;
}


/***********************************************************CommentBegin******
*       3/30/2000 : initial modification to the new PV-Decoder Lib
*                           format and the change of error-handling method.
*       4/16/01   : removed status checking of PV_BitstreamFlushBits
***********************************************************CommentEnd********/

int PV_VlcDecMCBPC_com_intra(BitstreamDecVideo *stream)
{
    uint code;

    BitstreamShowBits16(stream, 9, &code);


    if (code < 8)
    {
        return VLC_CODE_ERROR;
    }

    code >>= 3;

    if (code >= 32)
    {
        PV_BitstreamFlushBits(stream, 1);
        return 3;
    }

    PV_BitstreamFlushBits(stream, PV_MCBPCtabintra[code].len);

    return PV_MCBPCtabintra[code].val;
}


/***********************************************************CommentBegin******
*
*       3/30/2000 : initial modification to the new PV-Decoder Lib
*                           format and the change of error-handling method.
*       4/16/2001 : removed checking of return status of PV_BitstreamFlushBits
***********************************************************CommentEnd********/

int PV_VlcDecMCBPC_com_inter(BitstreamDecVideo *stream)
{
    uint code;

    BitstreamShowBits16(stream, 9, &code);

    if (code == 0)
    {
        return VLC_CODE_ERROR;
    }
    else if (code >= 256)
    {
        PV_BitstreamFlushBits(stream, 1);
        return 0;
    }

    PV_BitstreamFlushBits(stream, PV_MCBPCtab[code].len);
    return PV_MCBPCtab[code].val;
}

#ifdef PV_ANNEX_IJKT_SUPPORT
int PV_VlcDecMCBPC_com_inter_H263(BitstreamDecVideo *stream)
{
    uint code;

    BitstreamShow13Bits(stream, &code);

    if (code < 8)
    {
        return VLC_CODE_ERROR;
    }
    else if (code >= 4096)
    {
        PV_BitstreamFlushBits(stream, 1);
        return 0;
    }
    if (code >= 16)
    {
        PV_BitstreamFlushBits(stream, PV_MCBPCtab[code >> 4].len);
        return PV_MCBPCtab[code >> 4].val;
    }
    else
    {
        PV_BitstreamFlushBits(stream, PV_MCBPCtab1[code - 8].len);
        return PV_MCBPCtab1[code - 8].val;
    }
}
#endif
/***********************************************************CommentBegin******
*       3/30/2000 : initial modification to the new PV-Decoder Lib
*                           format and the change of error-handling method.
*       4/16/2001 : removed status checking for PV_BitstreamFlushBits
***********************************************************CommentEnd********/

int PV_VlcDecCBPY(BitstreamDecVideo *stream, int intra)
{
    int CBPY = 0;
    uint code;

    BitstreamShowBits16(stream, 6, &code);


    if (code < 2)
    {
        return -1;
    }
    else if (code >= 48)
    {
        PV_BitstreamFlushBits(stream, 2);
        CBPY = 15;
    }
    else
    {
        PV_BitstreamFlushBits(stream, PV_CBPYtab[code].len);
        CBPY = PV_CBPYtab[code].val;
    }

    if (intra == 0) CBPY = 15 - CBPY;
    CBPY = CBPY & 15;
    return CBPY;
}


/***********************************************************CommentBegin******
*       3/31/2000 : initial modification to the new PV-Decoder Lib format.
*
*       8/23/2000 : optimize the function by removing unnecessary BitstreamShowBits()
*                       function calls.
*
*       9/6/2000 : change the API to check for end-of-buffer for proper
*                           termination of decoding process.
***********************************************************CommentEnd********/
PV_STATUS PV_VlcDecIntraDCPredSize(BitstreamDecVideo *stream, int compnum, uint *DC_size)
{
    PV_STATUS status = PV_FAIL;      /*  07/09/01 */
    uint  code;

    *DC_size = 0;
    if (compnum < 4)  /* luminance block */
    {

        BitstreamShowBits16(stream, 11, &code);

        if (code == 1)
        {
            *DC_size = 12;
            PV_BitstreamFlushBits(stream, 11);
            return PV_SUCCESS;
        }
        code >>= 1;
        if (code == 1)
        {
            *DC_size = 11;
            PV_BitstreamFlushBits(stream, 10);
            return PV_SUCCESS;
        }
        code >>= 1;
        if (code == 1)
        {
            *DC_size = 10;
            PV_BitstreamFlushBits(stream, 9);
            return PV_SUCCESS;
        }

        code >>= 1;
        if (code == 1)
        {
            *DC_size = 9;
            PV_BitstreamFlushBits(stream, 8);
            return PV_SUCCESS;
        }

        code >>= 1;
        if (code == 1)
        {
            *DC_size = 8;
            PV_BitstreamFlushBits(stream, 7);
            return PV_SUCCESS;
        }

        code >>= 1;
        if (code == 1)
        {
            *DC_size = 7;
            PV_BitstreamFlushBits(stream, 6);
            return PV_SUCCESS;
        }

        code >>= 1;
        if (code == 1)
        {
            *DC_size = 6;
            PV_BitstreamFlushBits(stream, 5);
            return PV_SUCCESS;
        }

        code >>= 1;
        if (code == 1)
        {
            *DC_size = 5;
            PV_BitstreamFlushBits(stream, 4);
            return PV_SUCCESS;
        }

        code >>= 1;
        if (code == 1)
        {
            *DC_size = 4;
            PV_BitstreamFlushBits(stream, 3);
            return PV_SUCCESS;
        }
        else if (code == 2)
        {
            *DC_size = 3;
            PV_BitstreamFlushBits(stream, 3);
            return PV_SUCCESS;
        }
        else if (code == 3)
        {
            *DC_size = 0;
            PV_BitstreamFlushBits(stream, 3);
            return PV_SUCCESS;
        }

        code >>= 1;
        if (code == 2)
        {
            *DC_size = 2;
            PV_BitstreamFlushBits(stream, 2);
            return PV_SUCCESS;
        }
        else if (code == 3)
        {
            *DC_size = 1;
            PV_BitstreamFlushBits(stream, 2);
            return PV_SUCCESS;
        }
    }
    else /* chrominance block */
    {

        BitstreamShow13Bits(stream, &code);
        code >>= 1;
        if (code == 1)
        {
            *DC_size = 12;
            PV_BitstreamFlushBits(stream, 12);
            return PV_SUCCESS;
        }

        code >>= 1;
        if (code == 1)
        {
            *DC_size = 11;
            PV_BitstreamFlushBits(stream, 11);
            return PV_SUCCESS;
        }

        code >>= 1;
        if (code == 1)
        {
            *DC_size = 10;
            PV_BitstreamFlushBits(stream, 10);
            return PV_SUCCESS;
        }

        code >>= 1;
        if (code == 1)
        {
            *DC_size = 9;
            PV_BitstreamFlushBits(stream, 9);
            return PV_SUCCESS;
        }

        code >>= 1;
        if (code == 1)
        {
            *DC_size = 8;
            PV_BitstreamFlushBits(stream, 8);
            return PV_SUCCESS;
        }

        code >>= 1;
        if (code == 1)
        {
            *DC_size = 7;
            PV_BitstreamFlushBits(stream, 7);
            return PV_SUCCESS;
        }

        code >>= 1;
        if (code == 1)
        {
            *DC_size = 6;
            PV_BitstreamFlushBits(stream, 6);
            return PV_SUCCESS;
        }

        code >>= 1;
        if (code == 1)
        {
            *DC_size = 5;
            PV_BitstreamFlushBits(stream, 5);
            return PV_SUCCESS;
        }

        code >>= 1;
        if (code == 1)
        {
            *DC_size = 4;
            PV_BitstreamFlushBits(stream, 4);
            return PV_SUCCESS;
        }

        code >>= 1;
        if (code == 1)
        {
            *DC_size = 3;
            PV_BitstreamFlushBits(stream, 3);
            return PV_SUCCESS;
        }

        code >>= 1;
        {
            *DC_size = (int)(3 - code);
            PV_BitstreamFlushBits(stream, 2);
            return PV_SUCCESS;
        }
    }

    return status;
}

/***********************************************************CommentBegin******
*
*
*       3/30/2000 : initial modification to the new PV-Decoder Lib
*                           format and the change of error-handling method.
*
***********************************************************CommentEnd********/



PV_STATUS VlcDecTCOEFIntra(BitstreamDecVideo *stream, Tcoef *pTcoef)
{
    uint code;
    const VLCtab2 *tab;

    BitstreamShow13Bits(stream, &code);

    /* 10/17/2000, perform a little bit better on ARM by putting the whole function in VlcDecTCOEFFIntra */
    /*  if(GetTcoeffIntra(code,pTcoef,&tab,stream)!=PV_SUCCESS) return status;*/
    if (code >= 1024)
    {
        tab = &PV_DCT3Dtab3[(code >> 6) - 16];
    }
    else
    {
        if (code >= 256)
        {
            tab = &PV_DCT3Dtab4[(code >> 3) - 32];
        }
        else
        {
            if (code >= 16)
            {
                tab = &PV_DCT3Dtab5[(code>>1) - 8];
            }
            else
            {
                return PV_FAIL;
            }
        }
    }

    PV_BitstreamFlushBits(stream, tab->len + 1);
    pTcoef->sign = (code >> (12 - tab->len)) & 1;
    pTcoef->run = (uint) tab->run; //(tab->val >> 8) & 255;
    pTcoef->level = (int) tab->level; //tab->val & 255;
    pTcoef->last = (uint) tab->last; //(tab->val >> 16) & 1;


    /* the following is modified for 3-mode escape -- boon */
    if (tab->level != 0xFF)
    {
        return PV_SUCCESS;
    }

    //if (((tab->run<<8)|(tab->level)|(tab->last<<16)) == VLC_ESCAPE_CODE)

    if (!pTcoef->sign)
    {
        /* first escape mode. level is offset */
        BitstreamShow13Bits(stream, &code);

        /* 10/17/2000, perform a little bit better on ARM by putting the whole function in VlcDecTCOEFFIntra */
        /*          if(GetTcoeffIntra(code,pTcoef,&tab,stream)!=PV_SUCCESS) return status;*/
        if (code >= 1024)
        {
            tab = &PV_DCT3Dtab3[(code >> 6) - 16];
        }
        else
        {
            if (code >= 256)
            {
                tab = &PV_DCT3Dtab4[(code >> 3) - 32];
            }
            else
            {
                if (code >= 16)
                {
                    tab = &PV_DCT3Dtab5[(code>>1) - 8];
                }
                else
                {
                    return PV_FAIL;
                }
            }
        }

        PV_BitstreamFlushBits(stream, tab->len + 1);

        /* sign bit */
        pTcoef->sign = (code >> (12 - tab->len)) & 1;
        pTcoef->run = (uint)tab->run; //(tab->val >> 8) & 255;
        pTcoef->level = (int)tab->level; //tab->val & 255;
        pTcoef->last = (uint)tab->last; //(tab->val >> 16) & 1;


        /* need to add back the max level */
        if ((pTcoef->last == 0 && pTcoef->run > 14) || (pTcoef->last == 1 && pTcoef->run > 20))
        {
            return PV_FAIL;
        }
        pTcoef->level = pTcoef->level + intra_max_level[pTcoef->last][pTcoef->run];


    }
    else
    {
        uint run_offset;
        run_offset = BitstreamRead1Bits_INLINE(stream);

        if (!run_offset)
        {
            /* second escape mode. run is offset */
            BitstreamShow13Bits(stream, &code);

            /* 10/17/2000, perform a little bit better on ARM by putting the whole function in VlcDecTCOEFFIntra */
            /*              if(GetTcoeffIntra(code,pTcoef,&tab,stream)!=PV_SUCCESS) return status;*/
            if (code >= 1024)
            {
                tab = &PV_DCT3Dtab3[(code >> 6) - 16];
            }
            else
            {
                if (code >= 256)
                {
                    tab = &PV_DCT3Dtab4[(code >> 3) - 32];
                }
                else
                {
                    if (code >= 16)
                    {
                        tab = &PV_DCT3Dtab5[(code>>1) - 8];
                    }
                    else
                    {
                        return PV_FAIL;
                    }
                }
            }

            PV_BitstreamFlushBits(stream, tab->len + 1);
            /* sign bit */
            pTcoef->sign = (code >> (12 - tab->len)) & 1;
            pTcoef->run = (uint)tab->run; //(tab->val >> 8) & 255;
            pTcoef->level = (int)tab->level; //tab->val & 255;
            pTcoef->last = (uint)tab->last; //(tab->val >> 16) & 1;



            /* need to add back the max run */
            if (pTcoef->last)
            {
                if (pTcoef->level > 8)
                {
                    return PV_FAIL;
                }
                pTcoef->run = pTcoef->run + intra_max_run1[pTcoef->level] + 1;
            }
            else
            {
                if (pTcoef->level > 27)
                {
                    return PV_FAIL;
                }
                pTcoef->run = pTcoef->run + intra_max_run0[pTcoef->level] + 1;
            }


        }
        else
        {

            code = BitstreamReadBits16_INLINE(stream, 8);
            pTcoef->last = code >> 7;
            pTcoef->run = (code >> 1) & 0x3F;
            pTcoef->level = (int)(BitstreamReadBits16_INLINE(stream, 13) >> 1);

            if (pTcoef->level >= 2048)
            {
                pTcoef->sign = 1;
                pTcoef->level = 4096 - pTcoef->level;
            }
            else
            {
                pTcoef->sign = 0;
            }
        } /* flc */
    }

    return PV_SUCCESS;

} /* VlcDecTCOEFIntra */

PV_STATUS VlcDecTCOEFInter(BitstreamDecVideo *stream, Tcoef *pTcoef)
{
    uint code;
    const VLCtab2 *tab;

    BitstreamShow13Bits(stream, &code);

    /* 10/17/2000, perform a little bit better on ARM by putting the whole function in VlcDecTCOEFFInter */
    /*  if(GetTcoeffInter(code,pTcoef,&tab,stream)!=PV_SUCCESS) return status;*/
    if (code >= 1024)
    {
        tab = &PV_DCT3Dtab0[(code >> 6) - 16];
    }
    else
    {
        if (code >= 256)
        {
            tab = &PV_DCT3Dtab1[(code >> 3) - 32];
        }
        else
        {
            if (code >= 16)
            {
                tab = &PV_DCT3Dtab2[(code>>1) - 8];
            }
            else
            {
                return PV_FAIL;
            }
        }
    }
    PV_BitstreamFlushBits(stream, tab->len + 1);
    pTcoef->sign = (code >> (12 - tab->len)) & 1;
    pTcoef->run = (uint)tab->run;     //(tab->val >> 4) & 255;
    pTcoef->level = (int)tab->level; //tab->val & 15;
    pTcoef->last = (uint)tab->last;   //(tab->val >> 12) & 1;

    /* the following is modified for 3-mode escape -- boon */
    if (tab->run != 0xBF)
    {
        return PV_SUCCESS;
    }
    //if (((tab->run<<4)|(tab->level)|(tab->last<<12)) == VLC_ESCAPE_CODE)


    if (!pTcoef->sign)
    {
        /* first escape mode. level is offset */
        BitstreamShow13Bits(stream, &code);

        /* 10/17/2000, perform a little bit better on ARM by putting the whole function in VlcDecTCOEFFInter */
        /*          if(GetTcoeffInter(code,pTcoef,&tab,stream)!=PV_SUCCESS) return status;*/
        if (code >= 1024)
        {
            tab = &PV_DCT3Dtab0[(code >> 6) - 16];
        }
        else
        {
            if (code >= 256)
            {
                tab = &PV_DCT3Dtab1[(code >> 3) - 32];
            }
            else
            {
                if (code >= 16)
                {
                    tab = &PV_DCT3Dtab2[(code>>1) - 8];
                }
                else
                {
                    return PV_FAIL;
                }
            }
        }
        PV_BitstreamFlushBits(stream, tab->len + 1);
        pTcoef->sign = (code >> (12 - tab->len)) & 1;
        pTcoef->run = (uint)tab->run;     //(tab->val >> 4) & 255;
        pTcoef->level = (int)tab->level; //tab->val & 15;
        pTcoef->last = (uint)tab->last;   //(tab->val >> 12) & 1;

        /* need to add back the max level */
        if ((pTcoef->last == 0 && pTcoef->run > 26) || (pTcoef->last == 1 && pTcoef->run > 40))
        {
            return PV_FAIL;
        }
        pTcoef->level = pTcoef->level + inter_max_level[pTcoef->last][pTcoef->run];
    }
    else
    {
        uint run_offset;
        run_offset = BitstreamRead1Bits_INLINE(stream);

        if (!run_offset)
        {
            /* second escape mode. run is offset */
            BitstreamShow13Bits(stream, &code);

            /* 10/17/2000, perform a little bit better on ARM by putting the whole function in VlcDecTCOEFFInter */
            /*if(GetTcoeffInter(code,pTcoef,&tab,stream)!=PV_SUCCESS) return status;*/
            if (code >= 1024)
            {
                tab = &PV_DCT3Dtab0[(code >> 6) - 16];
            }
            else
            {
                if (code >= 256)
                {
                    tab = &PV_DCT3Dtab1[(code >> 3) - 32];
                }
                else
                {
                    if (code >= 16)
                    {
                        tab = &PV_DCT3Dtab2[(code>>1) - 8];
                    }
                    else
                    {
                        return PV_FAIL;
                    }
                }
            }
            PV_BitstreamFlushBits(stream, tab->len + 1);
            pTcoef->sign = (code >> (12 - tab->len)) & 1;
            pTcoef->run = (uint)tab->run;     //(tab->val >> 4) & 255;
            pTcoef->level = (int)tab->level; //tab->val & 15;
            pTcoef->last = (uint)tab->last;   //(tab->val >> 12) & 1;

            /* need to add back the max run */
            if (pTcoef->last)
            {
                if (pTcoef->level > 3)
                {
                    return PV_FAIL;
                }
                pTcoef->run = pTcoef->run + inter_max_run1[pTcoef->level] + 1;
            }
            else
            {
                if (pTcoef->level > 12)
                {
                    return PV_FAIL;
                }
                pTcoef->run = pTcoef->run + inter_max_run0[pTcoef->level] + 1;
            }
        }
        else
        {

            code = BitstreamReadBits16_INLINE(stream, 8);
            pTcoef->last = code >> 7;
            pTcoef->run = (code >> 1) & 0x3F;
            pTcoef->level = (int)(BitstreamReadBits16_INLINE(stream, 13) >> 1);



            if (pTcoef->level >= 2048)
            {
                pTcoef->sign = 1;
                pTcoef->level = 4096 - pTcoef->level;
            }
            else
            {
                pTcoef->sign = 0;
            }
        } /* flc */
    }

    return PV_SUCCESS;

} /* VlcDecTCOEFInter */

/*=======================================================
    Function:   VlcDecTCOEFShortHeader()
    Date    :   04/27/99
    Purpose :   New function used in decoding of video planes
                with short header
    Modified:   05/23/2000
                for new decoder structure.
=========================================================*/
PV_STATUS VlcDecTCOEFShortHeader(BitstreamDecVideo *stream, Tcoef *pTcoef/*, int intra*/)
{
    uint code;
    const VLCtab2 *tab;

    BitstreamShow13Bits(stream, &code);

    /*intra = 0;*/

    if (code >= 1024) tab = &PV_DCT3Dtab0[(code >> 6) - 16];
    else
    {
        if (code >= 256) tab = &PV_DCT3Dtab1[(code >> 3) - 32];
        else
        {
            if (code >= 16) tab = &PV_DCT3Dtab2[(code>>1) - 8];
            else return PV_FAIL;
        }
    }

    PV_BitstreamFlushBits(stream, tab->len + 1);
    pTcoef->sign = (code >> (12 - tab->len)) & 1;
    pTcoef->run = (uint)tab->run;//(tab->val >> 4) & 255;
    pTcoef->level = (int)tab->level;//tab->val & 15;
    pTcoef->last = (uint)tab->last;//(tab->val >> 12) & 1;

    /* the following is modified for 3-mode escape -- boon */
    if (((tab->run << 4) | (tab->level) | (tab->last << 12)) != VLC_ESCAPE_CODE)    /* ESCAPE */
    {
        return PV_SUCCESS;
    }


    /* escape mode 4 - H.263 type */
    pTcoef->last = pTcoef->sign; /* Last */
    pTcoef->run = BitstreamReadBits16_INLINE(stream, 6); /* Run */
    pTcoef->level = (int) BitstreamReadBits16_INLINE(stream, 8); /* Level */

    if (pTcoef->level == 0 || pTcoef->level == 128)
    {
        return PV_FAIL;
    }

    if (pTcoef->level > 128)
    {
        pTcoef->sign = 1;
        pTcoef->level = 256 - pTcoef->level;
    }
    else
    {
        pTcoef->sign = 0;
    }



    return PV_SUCCESS;

}   /* VlcDecTCOEFShortHeader */

#ifdef PV_ANNEX_IJKT_SUPPORT
PV_STATUS VlcDecTCOEFShortHeader_AnnexI(BitstreamDecVideo *stream, Tcoef *pTcoef/*, int intra*/)
{
    uint code;
    const VLCtab2 *tab;

    BitstreamShow13Bits(stream, &code);

    /*intra = 0;*/

    if (code >= 1024) tab = &PV_DCT3Dtab6[(code >> 6) - 16];
    else
    {
        if (code >= 256) tab = &PV_DCT3Dtab7[(code >> 3) - 32];
        else
        {
            if (code >= 16) tab = &PV_DCT3Dtab8[(code>>1) - 8];
            else return PV_FAIL;
        }
    }

    PV_BitstreamFlushBits(stream, tab->len + 1);
    pTcoef->sign = (code >> (12 - tab->len)) & 1;
    pTcoef->run = (uint)tab->run;//(tab->val >> 4) & 255;
    pTcoef->level = (int)tab->level;//tab->val & 15;
    pTcoef->last = (uint)tab->last;//(tab->val >> 12) & 1;

    /* the following is modified for 3-mode escape -- boon */
    if (((tab->run << 6) | (tab->level) | (tab->last << 12)) != VLC_ESCAPE_CODE)    /* ESCAPE */
    {
        return PV_SUCCESS;
    }
    /* escape mode 4 - H.263 type */
    pTcoef->last = pTcoef->sign; /* Last */
    pTcoef->run = BitstreamReadBits16(stream, 6); /* Run */
    pTcoef->level = (int) BitstreamReadBits16(stream, 8); /* Level */

    if (pTcoef->level == 0 || pTcoef->level == 128)
    {
        return PV_FAIL;
    }


    if (pTcoef->level > 128)
    {
        pTcoef->sign = 1;
        pTcoef->level = 256 - pTcoef->level;
    }
    else pTcoef->sign = 0;



    return PV_SUCCESS;

}   /* VlcDecTCOEFShortHeader_AnnexI */

PV_STATUS VlcDecTCOEFShortHeader_AnnexT(BitstreamDecVideo *stream, Tcoef *pTcoef/*, int intra*/)
{
    uint code;
    const VLCtab2 *tab;

    BitstreamShow13Bits(stream, &code);

    /*intra = 0;*/

    if (code >= 1024) tab = &PV_DCT3Dtab0[(code >> 6) - 16];
    else
    {
        if (code >= 256) tab = &PV_DCT3Dtab1[(code >> 3) - 32];
        else
        {
            if (code >= 16) tab = &PV_DCT3Dtab2[(code>>1) - 8];
            else return PV_FAIL;
        }
    }

    PV_BitstreamFlushBits(stream, tab->len + 1);
    pTcoef->sign = (code >> (12 - tab->len)) & 1;
    pTcoef->run = (uint)tab->run;//(tab->val >> 4) & 255;
    pTcoef->level = (int)tab->level;//tab->val & 15;
    pTcoef->last = (uint)tab->last;//(tab->val >> 12) & 1;

    /* the following is modified for 3-mode escape --  */
    if (((tab->run << 4) | (tab->level) | (tab->last << 12)) != VLC_ESCAPE_CODE)    /* ESCAPE */
    {
        return PV_SUCCESS;
    }
    /* escape mode 4 - H.263 type */
    pTcoef->last = pTcoef->sign; /* Last */
    pTcoef->run = BitstreamReadBits16(stream, 6); /* Run */
    pTcoef->level = (int) BitstreamReadBits16(stream, 8); /* Level */

    if (pTcoef->level == 0)
    {
        return PV_FAIL;
    }

    if (pTcoef->level >= 128)
    {
        pTcoef->sign = 1;
        pTcoef->level = 256 - pTcoef->level;
    }
    else
    {
        pTcoef->sign = 0;
    }

    if (pTcoef->level == 128)
    {
        code = BitstreamReadBits16(stream, 11);        /* ANNEX_T */

        code = (code >> 6 & 0x1F) | (code << 5 & 0x7ff);
        if (code > 1024)
        {
            pTcoef->sign = 1;
            pTcoef->level = (2048 - code);
        }
        else
        {
            pTcoef->sign = 0;
            pTcoef->level = code;
        }
    }

    return PV_SUCCESS;

}   /* VlcDecTCOEFShortHeader */


PV_STATUS VlcDecTCOEFShortHeader_AnnexIT(BitstreamDecVideo *stream, Tcoef *pTcoef/*, int intra*/)
{
    uint code;
    const VLCtab2 *tab;

    BitstreamShow13Bits(stream, &code);

    /*intra = 0;*/

    if (code >= 1024) tab = &PV_DCT3Dtab6[(code >> 6) - 16];
    else
    {
        if (code >= 256) tab = &PV_DCT3Dtab7[(code >> 3) - 32];
        else
        {
            if (code >= 16) tab = &PV_DCT3Dtab8[(code>>1) - 8];
            else return PV_FAIL;
        }
    }

    PV_BitstreamFlushBits(stream, tab->len + 1);
    pTcoef->sign = (code >> (12 - tab->len)) & 1;
    pTcoef->run = (uint)tab->run;//(tab->val >> 4) & 255;
    pTcoef->level = (int)tab->level;//tab->val & 15;
    pTcoef->last = (uint)tab->last;//(tab->val >> 12) & 1;

    /* the following is modified for 3-mode escape --  */
    if (((tab->run << 6) | (tab->level) | (tab->last << 12)) != VLC_ESCAPE_CODE)    /* ESCAPE */
    {
        return PV_SUCCESS;
    }
    /* escape mode 4 - H.263 type */
    pTcoef->last = pTcoef->sign; /* Last */
    pTcoef->run = BitstreamReadBits16(stream, 6); /* Run */
    pTcoef->level = (int) BitstreamReadBits16(stream, 8); /* Level */

    if (pTcoef->level == 0)
    {
        return PV_FAIL;
    }

    if (pTcoef->level >= 128)
    {
        pTcoef->sign = 1;
        pTcoef->level = 256 - pTcoef->level;
    }
    else
    {
        pTcoef->sign = 0;
    }

    if (pTcoef->level == 128)
    {
        code = BitstreamReadBits16(stream, 11);        /* ANNEX_T */

        code = (code >> 6 & 0x1F) | (code << 5 & 0x7ff);
        if (code > 1024)
        {
            pTcoef->sign = 1;
            pTcoef->level = (2048 - code);
        }
        else
        {
            pTcoef->sign = 0;
            pTcoef->level = code;
        }
    }


    return PV_SUCCESS;

}   /* VlcDecTCOEFShortHeader_AnnexI */
#endif
/***********************************************************CommentBegin******
*       3/30/2000 : initial modification to the new PV-Decoder Lib
*                           format and the change of error-handling method.
*                           The coefficient is now returned thru a pre-
*                           initialized parameters for speedup.
*
***********************************************************CommentEnd********/


PV_STATUS RvlcDecTCOEFInter(BitstreamDecVideo *stream, Tcoef *pTcoef)
{
    uint code, mask;
    const VLCtab2 *tab2;
    int count, len, num[2] = {0, 0} /*  01/30/01 */;

    mask = 0x4000;      /* mask  100000000000000   */
    BitstreamShow15Bits(stream, &code);   /*  03/07/01 */

    len = 1;

    //  09/20/99 Escape mode
    /// Bitstream Exchange
    if (code < 2048)
    {
        PV_BitstreamFlushBits(stream, 5);
        pTcoef->last = BitstreamRead1Bits_INLINE(stream);
        pTcoef->run = BitstreamReadBits16_INLINE(stream, 6);
        //  09/20/99 New marker bit
        PV_BitstreamFlushBits(stream, 1);
        //  09/20/99 The length for LEVEL used to be 7 in the old version
        pTcoef->level = (int)(BitstreamReadBits16_INLINE(stream, 12) >> 1);
        //  09/20/99 Another new marker bit
//      PV_BitstreamFlushBitsCheck(stream, 1);
        pTcoef->sign = BitstreamReadBits16_INLINE(stream, 5) & 0x1;  /* fix   3/13/01  */
        return PV_SUCCESS;
    }

    if (code & mask)
    {
        count = 1;
        while (mask && count > 0)       /* fix  3/28/01  */
        {
            mask = mask >> 1;
            if (code & mask)
                count--;
            else
                num[0]++; /* number of zeros in the middle */
            len++;
        }
    }
    else
    {
        count = 2;
        while (mask && count > 0)           /* fix  3/28/01  */
        {
            mask = mask >> 1;
            if (!(code & mask))
                count--;
            else
                num[count-1]++; /* number of ones in the middle */
            len++;
        }
    }

    code = code & 0x7fff;
    code = code >> (15 - (len + 1));

    /*  1/30/01, add fast decoding algorithm here */
    /* code is in two forms : 0xxxx0xxx00 or 0xxx0xxx01
                         num[1] and num[0] x
                        or  : 1xxxxx10 or 1xxxxx11
                                num[0]  x      */

    /* len+1 is the length of the above */

    if (num[1] > 10 || num[0] > 11) /* invalid RVLC code */
        return PV_FAIL;

    if (code&(1 << len))
        tab2 = RvlcDCTtabInter + 146 + (num[0] << 1) + (code & 1);
    else
        tab2 = RvlcDCTtabInter + ptrRvlcTab[num[1]] + (num[0] << 1) + (code & 1);

    PV_BitstreamFlushBits(stream, (int) tab2->len);
    pTcoef->run = (uint)tab2->run;//(tab->val >> 8) & 255;
    pTcoef->level = (int)tab2->level;//tab->val & 255;
    pTcoef->last = (uint)tab2->last;//(tab->val >> 16) & 1;

    pTcoef->sign = BitstreamRead1Bits_INLINE(stream);
    return PV_SUCCESS;
}               /* RvlcDecTCOEFInter */

PV_STATUS RvlcDecTCOEFIntra(BitstreamDecVideo *stream, Tcoef *pTcoef)
{
    uint code, mask;
    const VLCtab2 *tab2;
    int count, len, num[2] = {0, 0} /*  01/30/01 */;

    mask = 0x4000;      /* mask  100000000000000   */
    BitstreamShow15Bits(stream, &code);

    len = 1;

    //  09/20/99 Escape mode
    /// Bitstream Exchange
    if (code < 2048)
    {
        PV_BitstreamFlushBits(stream, 5);
        pTcoef->last = BitstreamRead1Bits_INLINE(stream);
        pTcoef->run = BitstreamReadBits16_INLINE(stream, 6);
        //  09/20/99 New marker bit
        PV_BitstreamFlushBits(stream, 1);
        //  09/20/99 The length for LEVEL used to be 7 in the old version
        pTcoef->level = (int)(BitstreamReadBits16_INLINE(stream, 12) >> 1);
        //  09/20/99 Another new marker bit
//      PV_BitstreamFlushBitsCheck(stream, 1);
        pTcoef->sign = BitstreamReadBits16_INLINE(stream, 5) & 0x1; /* fix   03/13/01 */
        return PV_SUCCESS;
    }

    if (code & mask)
    {
        count = 1;
        while (mask && count > 0)                          /* fix  03/28/01 */
        {
            mask = mask >> 1;
            if (code & mask)
                count--;
            else
                num[0]++; /* number of zeros in the middle */
            len++;
        }
    }
    else
    {
        count = 2;
        while (mask && count > 0)              /* fix  03/28/01 */
        {
            mask = mask >> 1;
            if (!(code & mask))
                count--;
            else
                num[count-1]++; /* number of ones in the middle */
            len++;
        }
    }

    code = code & 0x7fff;
    code = code >> (15 - (len + 1));

    /*  1/30/01, add fast decoding algorithm here */
    /* code is in two forms : 0xxxx0xxx00 or 0xxx0xxx01
                         num[1] and num[0] x
                        or  : 1xxxxx10 or 1xxxxx11
                                num[0]  x      */

    /* len+1 is the length of the above */

    if (num[1] > 10 || num[0] > 11) /* invalid RVLC code */
        return PV_FAIL;

    if (code & (1 << len))
        tab2 = RvlcDCTtabIntra + 146 + (num[0] << 1) + (code & 1);
    else
        tab2 = RvlcDCTtabIntra + ptrRvlcTab[num[1]] + (num[0] << 1) + (code & 1);

    PV_BitstreamFlushBits(stream, (int) tab2->len);
    pTcoef->run = (uint)tab2->run;//(tab->val >> 8) & 255;
    pTcoef->level = (int)tab2->level;//tab->val & 255;
    pTcoef->last = (uint)tab2->last;//(tab->val >> 16) & 1;

    pTcoef->sign = BitstreamRead1Bits_INLINE(stream);
    return PV_SUCCESS;
}               /* RvlcDecTCOEFIntra */

