/*
 * Copyright (C) 2009 The Android Open Source Project
 * Modified for use by h264bsd standalone library
 *
 * 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.
 */

/*------------------------------------------------------------------------------

    Table of contents

     1. Include headers
     2. External compiler flags
     3. Module defines
     4. Local function prototypes
     5. Functions
          h264bsdCountLeadingZeros
          h264bsdRbspTrailingBits
          h264bsdMoreRbspData
          h264bsdNextMbAddress
          h264bsdSetCurrImageMbPointers

------------------------------------------------------------------------------*/

/*------------------------------------------------------------------------------
    1. Include headers
------------------------------------------------------------------------------*/

#include "h264bsd_util.h"

/*------------------------------------------------------------------------------
    2. External compiler flags
--------------------------------------------------------------------------------

--------------------------------------------------------------------------------
    3. Module defines
------------------------------------------------------------------------------*/

/* look-up table for expected values of stuffing bits */
static const u32 stuffingTable[8] = {0x1,0x2,0x4,0x8,0x10,0x20,0x40,0x80};

/* look-up table for chroma quantization parameter as a function of luma QP */
const u32 h264bsdQpC[52] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,
    20,21,22,23,24,25,26,27,28,29,29,30,31,32,32,33,34,34,35,35,36,36,37,37,37,
    38,38,38,39,39,39,39};

/*------------------------------------------------------------------------------
    4. Local function prototypes
------------------------------------------------------------------------------*/

/*------------------------------------------------------------------------------

   5.1  Function: h264bsdCountLeadingZeros

        Functional description:
            Count leading zeros in a code word. Code word is assumed to be
            right-aligned, last bit of the code word in the lsb of the value.

        Inputs:
            value   code word
            length  number of bits in the code word

        Outputs:
            none

        Returns:
            number of leading zeros in the code word

------------------------------------------------------------------------------*/
#ifndef H264DEC_NEON
u32 h264bsdCountLeadingZeros(u32 value, u32 length)
{

/* Variables */

    u32 zeros = 0;
    u32 mask = 1 << (length - 1);

/* Code */

    ASSERT(length <= 32);

    while (mask && !(value & mask))
    {
        zeros++;
        mask >>= 1;
    }
    return(zeros);

}
#endif
/*------------------------------------------------------------------------------

   5.2  Function: h264bsdRbspTrailingBits

        Functional description:
            Check Raw Byte Stream Payload (RBSP) trailing bits, i.e. stuffing.
            Rest of the current byte (whole byte if allready byte aligned)
            in the stream buffer shall contain a '1' bit followed by zero or
            more '0' bits.

        Inputs:
            pStrmData   pointer to stream data structure

        Outputs:
            none

        Returns:
            HANTRO_OK      RBSP trailing bits found
            HANTRO_NOK     otherwise

------------------------------------------------------------------------------*/

u32 h264bsdRbspTrailingBits(strmData_t *pStrmData)
{

/* Variables */

    u32 stuffing;
    u32 stuffingLength;

/* Code */

    ASSERT(pStrmData);
    ASSERT(pStrmData->bitPosInWord < 8);

    stuffingLength = 8 - pStrmData->bitPosInWord;

    stuffing = h264bsdGetBits(pStrmData, stuffingLength);
    if (stuffing == END_OF_STREAM)
        return(HANTRO_NOK);

    if (stuffing != stuffingTable[stuffingLength - 1])
        return(HANTRO_NOK);
    else
        return(HANTRO_OK);

}

/*------------------------------------------------------------------------------

   5.3  Function: h264bsdMoreRbspData

        Functional description:
            Check if there is more data in the current RBSP. The standard
            defines this function so that there is more data if
                -more than 8 bits left or
                -last bits are not RBSP trailing bits

        Inputs:
            pStrmData   pointer to stream data structure

        Outputs:
            none

        Returns:
            HANTRO_TRUE    there is more data
            HANTRO_FALSE   no more data

------------------------------------------------------------------------------*/

u32 h264bsdMoreRbspData(strmData_t *pStrmData)
{

/* Variables */

    u32 bits;

/* Code */

    ASSERT(pStrmData);
    ASSERT(pStrmData->strmBuffReadBits <= 8 * pStrmData->strmBuffSize);

    bits = pStrmData->strmBuffSize * 8 - pStrmData->strmBuffReadBits;

    if (bits == 0)
        return(HANTRO_FALSE);

    if ( (bits > 8) ||
         ((h264bsdShowBits32(pStrmData)>>(32-bits)) != (1ul << (bits-1))) )
        return(HANTRO_TRUE);
    else
        return(HANTRO_FALSE);

}

/*------------------------------------------------------------------------------

   5.4  Function: h264bsdNextMbAddress

        Functional description:
            Get address of the next macroblock in the current slice group.

        Inputs:
            pSliceGroupMap      slice group for each macroblock
            picSizeInMbs        size of the picture
            currMbAddr          where to start

        Outputs:
            none

        Returns:
            address of the next macroblock
            0   if none of the following macroblocks belong to same slice
                group as currMbAddr

------------------------------------------------------------------------------*/

u32 h264bsdNextMbAddress(u32 *pSliceGroupMap, u32 picSizeInMbs, u32 currMbAddr)
{

/* Variables */

    u32 i, sliceGroup;

/* Code */

    ASSERT(pSliceGroupMap);
    ASSERT(picSizeInMbs);
    ASSERT(currMbAddr < picSizeInMbs);

    sliceGroup = pSliceGroupMap[currMbAddr];

    i = currMbAddr + 1;
    while ((i < picSizeInMbs) && (pSliceGroupMap[i] != sliceGroup))
    {
        i++;
    }

    if (i == picSizeInMbs)
        i = 0;

    return(i);

}


/*------------------------------------------------------------------------------

   5.5  Function: h264bsdSetCurrImageMbPointers

        Functional description:
            Set luma and chroma pointers in image_t for current MB

        Inputs:
            image       Current image
            mbNum       number of current MB

        Outputs:
            none

        Returns:
            none
------------------------------------------------------------------------------*/
void h264bsdSetCurrImageMbPointers(image_t *image, u32 mbNum)
{
    u32 width, height;
    u32 picSize;
    u32 row, col;
    u32 tmp;

    width = image->width;
    height = image->height;
    row = mbNum / width;
    col = mbNum % width;

    tmp = row * width;
    picSize = width * height;

    image->luma = (u8*)(image->data + col * 16 + tmp * 256);
    image->cb = (u8*)(image->data + picSize * 256 + tmp * 64 + col * 8);
    image->cr = (u8*)(image->cb + picSize * 64);
}
