Home | History | Annotate | Download | only in source
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /*------------------------------------------------------------------------------
     18 
     19     Table of contents
     20 
     21      1. Include headers
     22      2. External compiler flags
     23      3. Module defines
     24      4. Local function prototypes
     25      5. Functions
     26           ExtractNalUnit
     27 
     28 ------------------------------------------------------------------------------*/
     29 
     30 /*------------------------------------------------------------------------------
     31     1. Include headers
     32 ------------------------------------------------------------------------------*/
     33 
     34 #include "h264bsd_byte_stream.h"
     35 #include "h264bsd_util.h"
     36 
     37 /*------------------------------------------------------------------------------
     38     2. External compiler flags
     39 --------------------------------------------------------------------------------
     40 
     41 --------------------------------------------------------------------------------
     42     3. Module defines
     43 ------------------------------------------------------------------------------*/
     44 
     45 #define BYTE_STREAM_ERROR  0xFFFFFFFF
     46 
     47 /*------------------------------------------------------------------------------
     48     4. Local function prototypes
     49 ------------------------------------------------------------------------------*/
     50 
     51 /*------------------------------------------------------------------------------
     52 
     53     Function name: ExtractNalUnit
     54 
     55         Functional description:
     56             Extracts one NAL unit from the byte stream buffer. Removes
     57             emulation prevention bytes if present. The original stream buffer
     58             is used directly and is therefore modified if emulation prevention
     59             bytes are present in the stream.
     60 
     61             Stream buffer is assumed to contain either exactly one NAL unit
     62             and nothing else, or one or more NAL units embedded in byte
     63             stream format described in the Annex B of the standard. Function
     64             detects which one is used based on the first bytes in the buffer.
     65 
     66         Inputs:
     67             pByteStream     pointer to byte stream buffer
     68             len             length of the stream buffer (in bytes)
     69 
     70         Outputs:
     71             pStrmData       stream information is stored here
     72             readBytes       number of bytes "consumed" from the stream buffer
     73 
     74         Returns:
     75             HANTRO_OK       success
     76             HANTRO_NOK      error in byte stream
     77 
     78 ------------------------------------------------------------------------------*/
     79 
     80 u32 h264bsdExtractNalUnit(u8 *pByteStream, u32 len, strmData_t *pStrmData,
     81     u32 *readBytes)
     82 {
     83 
     84 /* Variables */
     85 
     86     u32 i, tmp;
     87     u32 byteCount,initByteCount;
     88     u32 zeroCount;
     89     u8  byte;
     90     u32 hasEmulation = HANTRO_FALSE;
     91     u32 invalidStream = HANTRO_FALSE;
     92     u8 *readPtr, *writePtr;
     93 
     94 /* Code */
     95 
     96     ASSERT(pByteStream);
     97     ASSERT(len);
     98     ASSERT(len < BYTE_STREAM_ERROR);
     99     ASSERT(pStrmData);
    100 
    101     /* byte stream format if starts with 0x000001 or 0x000000 */
    102     if (len > 3 && pByteStream[0] == 0x00 && pByteStream[1] == 0x00 &&
    103         (pByteStream[2]&0xFE) == 0x00)
    104     {
    105         /* search for NAL unit start point, i.e. point after first start code
    106          * prefix in the stream */
    107         zeroCount = byteCount = 2;
    108         readPtr = pByteStream + 2;
    109         /*lint -e(716) while(1) used consciously */
    110         while (1)
    111         {
    112             byte = *readPtr++;
    113             byteCount++;
    114 
    115             if (byteCount == len)
    116             {
    117                 /* no start code prefix found -> error */
    118                 *readBytes = len;
    119                 return(HANTRO_NOK);
    120             }
    121 
    122             if (!byte)
    123                 zeroCount++;
    124             else if ((byte == 0x01) && (zeroCount >= 2))
    125                 break;
    126             else
    127                 zeroCount = 0;
    128         }
    129 
    130         initByteCount = byteCount;
    131 
    132         /* determine size of the NAL unit. Search for next start code prefix
    133          * or end of stream and ignore possible trailing zero bytes */
    134         zeroCount = 0;
    135         /*lint -e(716) while(1) used consciously */
    136         while (1)
    137         {
    138             byte = *readPtr++;
    139             byteCount++;
    140             if (!byte)
    141                 zeroCount++;
    142 
    143             if ( (byte == 0x03) && (zeroCount == 2) )
    144             {
    145                 hasEmulation = HANTRO_TRUE;
    146             }
    147 
    148             if ( (byte == 0x01) && (zeroCount >= 2 ) )
    149             {
    150                 pStrmData->strmBuffSize =
    151                     byteCount - initByteCount - zeroCount - 1;
    152                 zeroCount -= MIN(zeroCount, 3);
    153                 break;
    154             }
    155             else if (byte)
    156             {
    157                 if (zeroCount >= 3)
    158                     invalidStream = HANTRO_TRUE;
    159                 zeroCount = 0;
    160             }
    161 
    162             if (byteCount == len)
    163             {
    164                 pStrmData->strmBuffSize = byteCount - initByteCount - zeroCount;
    165                 break;
    166             }
    167 
    168         }
    169     }
    170     /* separate NAL units as input -> just set stream params */
    171     else
    172     {
    173         initByteCount = 0;
    174         zeroCount = 0;
    175         pStrmData->strmBuffSize = len;
    176         hasEmulation = HANTRO_TRUE;
    177     }
    178 
    179     pStrmData->pStrmBuffStart    = pByteStream + initByteCount;
    180     pStrmData->pStrmCurrPos      = pStrmData->pStrmBuffStart;
    181     pStrmData->bitPosInWord      = 0;
    182     pStrmData->strmBuffReadBits  = 0;
    183 
    184     /* return number of bytes "consumed" */
    185     *readBytes = pStrmData->strmBuffSize + initByteCount + zeroCount;
    186 
    187     if (invalidStream)
    188     {
    189         return(HANTRO_NOK);
    190     }
    191 
    192     /* remove emulation prevention bytes before rbsp processing */
    193     if (hasEmulation)
    194     {
    195         tmp = pStrmData->strmBuffSize;
    196         readPtr = writePtr = pStrmData->pStrmBuffStart;
    197         zeroCount = 0;
    198         for (i = tmp; i--;)
    199         {
    200             if ((zeroCount == 2) && (*readPtr == 0x03))
    201             {
    202                 /* emulation prevention byte shall be followed by one of the
    203                  * following bytes: 0x00, 0x01, 0x02, 0x03. This implies that
    204                  * emulation prevention 0x03 byte shall not be the last byte
    205                  * of the stream. */
    206                 if ( (i == 0) || (*(readPtr+1) > 0x03) )
    207                     return(HANTRO_NOK);
    208 
    209                 /* do not write emulation prevention byte */
    210                 readPtr++;
    211                 zeroCount = 0;
    212             }
    213             else
    214             {
    215                 /* NAL unit shall not contain byte sequences 0x000000,
    216                  * 0x000001 or 0x000002 */
    217                 if ( (zeroCount == 2) && (*readPtr <= 0x02) )
    218                     return(HANTRO_NOK);
    219 
    220                 if (*readPtr == 0)
    221                     zeroCount++;
    222                 else
    223                     zeroCount = 0;
    224 
    225                 *writePtr++ = *readPtr++;
    226             }
    227         }
    228 
    229         /* (readPtr - writePtr) indicates number of "removed" emulation
    230          * prevention bytes -> subtract from stream buffer size */
    231         pStrmData->strmBuffSize -= (u32)(readPtr - writePtr);
    232     }
    233 
    234     return(HANTRO_OK);
    235 
    236 }
    237 
    238