10c1bc742181ded4930842b46e9507372f0b1b963James Dong/*
20c1bc742181ded4930842b46e9507372f0b1b963James Dong * Copyright (C) 2009 The Android Open Source Project
30c1bc742181ded4930842b46e9507372f0b1b963James Dong *
40c1bc742181ded4930842b46e9507372f0b1b963James Dong * Licensed under the Apache License, Version 2.0 (the "License");
50c1bc742181ded4930842b46e9507372f0b1b963James Dong * you may not use this file except in compliance with the License.
60c1bc742181ded4930842b46e9507372f0b1b963James Dong * You may obtain a copy of the License at
70c1bc742181ded4930842b46e9507372f0b1b963James Dong *
80c1bc742181ded4930842b46e9507372f0b1b963James Dong *      http://www.apache.org/licenses/LICENSE-2.0
90c1bc742181ded4930842b46e9507372f0b1b963James Dong *
100c1bc742181ded4930842b46e9507372f0b1b963James Dong * Unless required by applicable law or agreed to in writing, software
110c1bc742181ded4930842b46e9507372f0b1b963James Dong * distributed under the License is distributed on an "AS IS" BASIS,
120c1bc742181ded4930842b46e9507372f0b1b963James Dong * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130c1bc742181ded4930842b46e9507372f0b1b963James Dong * See the License for the specific language governing permissions and
140c1bc742181ded4930842b46e9507372f0b1b963James Dong * limitations under the License.
150c1bc742181ded4930842b46e9507372f0b1b963James Dong */
160c1bc742181ded4930842b46e9507372f0b1b963James Dong
170c1bc742181ded4930842b46e9507372f0b1b963James Dong/*------------------------------------------------------------------------------
180c1bc742181ded4930842b46e9507372f0b1b963James Dong
190c1bc742181ded4930842b46e9507372f0b1b963James Dong    Table of contents
200c1bc742181ded4930842b46e9507372f0b1b963James Dong
210c1bc742181ded4930842b46e9507372f0b1b963James Dong     1. Include headers
220c1bc742181ded4930842b46e9507372f0b1b963James Dong     2. External compiler flags
230c1bc742181ded4930842b46e9507372f0b1b963James Dong     3. Module defines
240c1bc742181ded4930842b46e9507372f0b1b963James Dong     4. Local function prototypes
250c1bc742181ded4930842b46e9507372f0b1b963James Dong     5. Functions
260c1bc742181ded4930842b46e9507372f0b1b963James Dong          ExtractNalUnit
270c1bc742181ded4930842b46e9507372f0b1b963James Dong
280c1bc742181ded4930842b46e9507372f0b1b963James Dong------------------------------------------------------------------------------*/
290c1bc742181ded4930842b46e9507372f0b1b963James Dong
300c1bc742181ded4930842b46e9507372f0b1b963James Dong/*------------------------------------------------------------------------------
310c1bc742181ded4930842b46e9507372f0b1b963James Dong    1. Include headers
320c1bc742181ded4930842b46e9507372f0b1b963James Dong------------------------------------------------------------------------------*/
330c1bc742181ded4930842b46e9507372f0b1b963James Dong
340c1bc742181ded4930842b46e9507372f0b1b963James Dong#include "h264bsd_byte_stream.h"
350c1bc742181ded4930842b46e9507372f0b1b963James Dong#include "h264bsd_util.h"
360c1bc742181ded4930842b46e9507372f0b1b963James Dong
370c1bc742181ded4930842b46e9507372f0b1b963James Dong/*------------------------------------------------------------------------------
380c1bc742181ded4930842b46e9507372f0b1b963James Dong    2. External compiler flags
390c1bc742181ded4930842b46e9507372f0b1b963James Dong--------------------------------------------------------------------------------
400c1bc742181ded4930842b46e9507372f0b1b963James Dong
410c1bc742181ded4930842b46e9507372f0b1b963James Dong--------------------------------------------------------------------------------
420c1bc742181ded4930842b46e9507372f0b1b963James Dong    3. Module defines
430c1bc742181ded4930842b46e9507372f0b1b963James Dong------------------------------------------------------------------------------*/
440c1bc742181ded4930842b46e9507372f0b1b963James Dong
450c1bc742181ded4930842b46e9507372f0b1b963James Dong#define BYTE_STREAM_ERROR  0xFFFFFFFF
460c1bc742181ded4930842b46e9507372f0b1b963James Dong
470c1bc742181ded4930842b46e9507372f0b1b963James Dong/*------------------------------------------------------------------------------
480c1bc742181ded4930842b46e9507372f0b1b963James Dong    4. Local function prototypes
490c1bc742181ded4930842b46e9507372f0b1b963James Dong------------------------------------------------------------------------------*/
500c1bc742181ded4930842b46e9507372f0b1b963James Dong
510c1bc742181ded4930842b46e9507372f0b1b963James Dong/*------------------------------------------------------------------------------
520c1bc742181ded4930842b46e9507372f0b1b963James Dong
530c1bc742181ded4930842b46e9507372f0b1b963James Dong    Function name: ExtractNalUnit
540c1bc742181ded4930842b46e9507372f0b1b963James Dong
550c1bc742181ded4930842b46e9507372f0b1b963James Dong        Functional description:
560c1bc742181ded4930842b46e9507372f0b1b963James Dong            Extracts one NAL unit from the byte stream buffer. Removes
570c1bc742181ded4930842b46e9507372f0b1b963James Dong            emulation prevention bytes if present. The original stream buffer
580c1bc742181ded4930842b46e9507372f0b1b963James Dong            is used directly and is therefore modified if emulation prevention
590c1bc742181ded4930842b46e9507372f0b1b963James Dong            bytes are present in the stream.
600c1bc742181ded4930842b46e9507372f0b1b963James Dong
610c1bc742181ded4930842b46e9507372f0b1b963James Dong            Stream buffer is assumed to contain either exactly one NAL unit
620c1bc742181ded4930842b46e9507372f0b1b963James Dong            and nothing else, or one or more NAL units embedded in byte
630c1bc742181ded4930842b46e9507372f0b1b963James Dong            stream format described in the Annex B of the standard. Function
640c1bc742181ded4930842b46e9507372f0b1b963James Dong            detects which one is used based on the first bytes in the buffer.
650c1bc742181ded4930842b46e9507372f0b1b963James Dong
660c1bc742181ded4930842b46e9507372f0b1b963James Dong        Inputs:
670c1bc742181ded4930842b46e9507372f0b1b963James Dong            pByteStream     pointer to byte stream buffer
680c1bc742181ded4930842b46e9507372f0b1b963James Dong            len             length of the stream buffer (in bytes)
690c1bc742181ded4930842b46e9507372f0b1b963James Dong
700c1bc742181ded4930842b46e9507372f0b1b963James Dong        Outputs:
710c1bc742181ded4930842b46e9507372f0b1b963James Dong            pStrmData       stream information is stored here
720c1bc742181ded4930842b46e9507372f0b1b963James Dong            readBytes       number of bytes "consumed" from the stream buffer
730c1bc742181ded4930842b46e9507372f0b1b963James Dong
740c1bc742181ded4930842b46e9507372f0b1b963James Dong        Returns:
750c1bc742181ded4930842b46e9507372f0b1b963James Dong            HANTRO_OK       success
760c1bc742181ded4930842b46e9507372f0b1b963James Dong            HANTRO_NOK      error in byte stream
770c1bc742181ded4930842b46e9507372f0b1b963James Dong
780c1bc742181ded4930842b46e9507372f0b1b963James Dong------------------------------------------------------------------------------*/
790c1bc742181ded4930842b46e9507372f0b1b963James Dong
800c1bc742181ded4930842b46e9507372f0b1b963James Dongu32 h264bsdExtractNalUnit(u8 *pByteStream, u32 len, strmData_t *pStrmData,
810c1bc742181ded4930842b46e9507372f0b1b963James Dong    u32 *readBytes)
820c1bc742181ded4930842b46e9507372f0b1b963James Dong{
830c1bc742181ded4930842b46e9507372f0b1b963James Dong
840c1bc742181ded4930842b46e9507372f0b1b963James Dong/* Variables */
850c1bc742181ded4930842b46e9507372f0b1b963James Dong
860c1bc742181ded4930842b46e9507372f0b1b963James Dong    u32 i, tmp;
870c1bc742181ded4930842b46e9507372f0b1b963James Dong    u32 byteCount,initByteCount;
880c1bc742181ded4930842b46e9507372f0b1b963James Dong    u32 zeroCount;
890c1bc742181ded4930842b46e9507372f0b1b963James Dong    u8  byte;
900c1bc742181ded4930842b46e9507372f0b1b963James Dong    u32 hasEmulation = HANTRO_FALSE;
910c1bc742181ded4930842b46e9507372f0b1b963James Dong    u32 invalidStream = HANTRO_FALSE;
920c1bc742181ded4930842b46e9507372f0b1b963James Dong    u8 *readPtr, *writePtr;
930c1bc742181ded4930842b46e9507372f0b1b963James Dong
940c1bc742181ded4930842b46e9507372f0b1b963James Dong/* Code */
950c1bc742181ded4930842b46e9507372f0b1b963James Dong
960c1bc742181ded4930842b46e9507372f0b1b963James Dong    ASSERT(pByteStream);
970c1bc742181ded4930842b46e9507372f0b1b963James Dong    ASSERT(len);
980c1bc742181ded4930842b46e9507372f0b1b963James Dong    ASSERT(len < BYTE_STREAM_ERROR);
990c1bc742181ded4930842b46e9507372f0b1b963James Dong    ASSERT(pStrmData);
1000c1bc742181ded4930842b46e9507372f0b1b963James Dong
1010c1bc742181ded4930842b46e9507372f0b1b963James Dong    /* byte stream format if starts with 0x000001 or 0x000000 */
1020c1bc742181ded4930842b46e9507372f0b1b963James Dong    if (len > 3 && pByteStream[0] == 0x00 && pByteStream[1] == 0x00 &&
1030c1bc742181ded4930842b46e9507372f0b1b963James Dong        (pByteStream[2]&0xFE) == 0x00)
1040c1bc742181ded4930842b46e9507372f0b1b963James Dong    {
1050c1bc742181ded4930842b46e9507372f0b1b963James Dong        /* search for NAL unit start point, i.e. point after first start code
1060c1bc742181ded4930842b46e9507372f0b1b963James Dong         * prefix in the stream */
1070c1bc742181ded4930842b46e9507372f0b1b963James Dong        zeroCount = byteCount = 2;
1080c1bc742181ded4930842b46e9507372f0b1b963James Dong        readPtr = pByteStream + 2;
1090c1bc742181ded4930842b46e9507372f0b1b963James Dong        /*lint -e(716) while(1) used consciously */
1100c1bc742181ded4930842b46e9507372f0b1b963James Dong        while (1)
1110c1bc742181ded4930842b46e9507372f0b1b963James Dong        {
1120c1bc742181ded4930842b46e9507372f0b1b963James Dong            byte = *readPtr++;
1130c1bc742181ded4930842b46e9507372f0b1b963James Dong            byteCount++;
1140c1bc742181ded4930842b46e9507372f0b1b963James Dong
1150c1bc742181ded4930842b46e9507372f0b1b963James Dong            if (byteCount == len)
1160c1bc742181ded4930842b46e9507372f0b1b963James Dong            {
1170c1bc742181ded4930842b46e9507372f0b1b963James Dong                /* no start code prefix found -> error */
1180c1bc742181ded4930842b46e9507372f0b1b963James Dong                *readBytes = len;
1190c1bc742181ded4930842b46e9507372f0b1b963James Dong                return(HANTRO_NOK);
1200c1bc742181ded4930842b46e9507372f0b1b963James Dong            }
1210c1bc742181ded4930842b46e9507372f0b1b963James Dong
1220c1bc742181ded4930842b46e9507372f0b1b963James Dong            if (!byte)
1230c1bc742181ded4930842b46e9507372f0b1b963James Dong                zeroCount++;
1240c1bc742181ded4930842b46e9507372f0b1b963James Dong            else if ((byte == 0x01) && (zeroCount >= 2))
1250c1bc742181ded4930842b46e9507372f0b1b963James Dong                break;
1260c1bc742181ded4930842b46e9507372f0b1b963James Dong            else
1270c1bc742181ded4930842b46e9507372f0b1b963James Dong                zeroCount = 0;
1280c1bc742181ded4930842b46e9507372f0b1b963James Dong        }
1290c1bc742181ded4930842b46e9507372f0b1b963James Dong
1300c1bc742181ded4930842b46e9507372f0b1b963James Dong        initByteCount = byteCount;
1310c1bc742181ded4930842b46e9507372f0b1b963James Dong
1320c1bc742181ded4930842b46e9507372f0b1b963James Dong        /* determine size of the NAL unit. Search for next start code prefix
1330c1bc742181ded4930842b46e9507372f0b1b963James Dong         * or end of stream and ignore possible trailing zero bytes */
1340c1bc742181ded4930842b46e9507372f0b1b963James Dong        zeroCount = 0;
1350c1bc742181ded4930842b46e9507372f0b1b963James Dong        /*lint -e(716) while(1) used consciously */
1360c1bc742181ded4930842b46e9507372f0b1b963James Dong        while (1)
1370c1bc742181ded4930842b46e9507372f0b1b963James Dong        {
1380c1bc742181ded4930842b46e9507372f0b1b963James Dong            byte = *readPtr++;
1390c1bc742181ded4930842b46e9507372f0b1b963James Dong            byteCount++;
1400c1bc742181ded4930842b46e9507372f0b1b963James Dong            if (!byte)
1410c1bc742181ded4930842b46e9507372f0b1b963James Dong                zeroCount++;
1420c1bc742181ded4930842b46e9507372f0b1b963James Dong
1430c1bc742181ded4930842b46e9507372f0b1b963James Dong            if ( (byte == 0x03) && (zeroCount == 2) )
1440c1bc742181ded4930842b46e9507372f0b1b963James Dong            {
1450c1bc742181ded4930842b46e9507372f0b1b963James Dong                hasEmulation = HANTRO_TRUE;
1460c1bc742181ded4930842b46e9507372f0b1b963James Dong            }
1470c1bc742181ded4930842b46e9507372f0b1b963James Dong
1480c1bc742181ded4930842b46e9507372f0b1b963James Dong            if ( (byte == 0x01) && (zeroCount >= 2 ) )
1490c1bc742181ded4930842b46e9507372f0b1b963James Dong            {
1500c1bc742181ded4930842b46e9507372f0b1b963James Dong                pStrmData->strmBuffSize =
1510c1bc742181ded4930842b46e9507372f0b1b963James Dong                    byteCount - initByteCount - zeroCount - 1;
1520c1bc742181ded4930842b46e9507372f0b1b963James Dong                zeroCount -= MIN(zeroCount, 3);
1530c1bc742181ded4930842b46e9507372f0b1b963James Dong                break;
1540c1bc742181ded4930842b46e9507372f0b1b963James Dong            }
1550c1bc742181ded4930842b46e9507372f0b1b963James Dong            else if (byte)
1560c1bc742181ded4930842b46e9507372f0b1b963James Dong            {
1570c1bc742181ded4930842b46e9507372f0b1b963James Dong                if (zeroCount >= 3)
1580c1bc742181ded4930842b46e9507372f0b1b963James Dong                    invalidStream = HANTRO_TRUE;
1590c1bc742181ded4930842b46e9507372f0b1b963James Dong                zeroCount = 0;
1600c1bc742181ded4930842b46e9507372f0b1b963James Dong            }
1610c1bc742181ded4930842b46e9507372f0b1b963James Dong
1620c1bc742181ded4930842b46e9507372f0b1b963James Dong            if (byteCount == len)
1630c1bc742181ded4930842b46e9507372f0b1b963James Dong            {
1640c1bc742181ded4930842b46e9507372f0b1b963James Dong                pStrmData->strmBuffSize = byteCount - initByteCount - zeroCount;
1650c1bc742181ded4930842b46e9507372f0b1b963James Dong                break;
1660c1bc742181ded4930842b46e9507372f0b1b963James Dong            }
1670c1bc742181ded4930842b46e9507372f0b1b963James Dong
1680c1bc742181ded4930842b46e9507372f0b1b963James Dong        }
1690c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
1700c1bc742181ded4930842b46e9507372f0b1b963James Dong    /* separate NAL units as input -> just set stream params */
1710c1bc742181ded4930842b46e9507372f0b1b963James Dong    else
1720c1bc742181ded4930842b46e9507372f0b1b963James Dong    {
1730c1bc742181ded4930842b46e9507372f0b1b963James Dong        initByteCount = 0;
1740c1bc742181ded4930842b46e9507372f0b1b963James Dong        zeroCount = 0;
1750c1bc742181ded4930842b46e9507372f0b1b963James Dong        pStrmData->strmBuffSize = len;
1760c1bc742181ded4930842b46e9507372f0b1b963James Dong        hasEmulation = HANTRO_TRUE;
1770c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
1780c1bc742181ded4930842b46e9507372f0b1b963James Dong
1790c1bc742181ded4930842b46e9507372f0b1b963James Dong    pStrmData->pStrmBuffStart    = pByteStream + initByteCount;
1800c1bc742181ded4930842b46e9507372f0b1b963James Dong    pStrmData->pStrmCurrPos      = pStrmData->pStrmBuffStart;
1810c1bc742181ded4930842b46e9507372f0b1b963James Dong    pStrmData->bitPosInWord      = 0;
1820c1bc742181ded4930842b46e9507372f0b1b963James Dong    pStrmData->strmBuffReadBits  = 0;
1830c1bc742181ded4930842b46e9507372f0b1b963James Dong
1840c1bc742181ded4930842b46e9507372f0b1b963James Dong    /* return number of bytes "consumed" */
1850c1bc742181ded4930842b46e9507372f0b1b963James Dong    *readBytes = pStrmData->strmBuffSize + initByteCount + zeroCount;
1860c1bc742181ded4930842b46e9507372f0b1b963James Dong
1870c1bc742181ded4930842b46e9507372f0b1b963James Dong    if (invalidStream)
1880c1bc742181ded4930842b46e9507372f0b1b963James Dong    {
1890c1bc742181ded4930842b46e9507372f0b1b963James Dong        return(HANTRO_NOK);
1900c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
1910c1bc742181ded4930842b46e9507372f0b1b963James Dong
1920c1bc742181ded4930842b46e9507372f0b1b963James Dong    /* remove emulation prevention bytes before rbsp processing */
1930c1bc742181ded4930842b46e9507372f0b1b963James Dong    if (hasEmulation)
1940c1bc742181ded4930842b46e9507372f0b1b963James Dong    {
1950c1bc742181ded4930842b46e9507372f0b1b963James Dong        tmp = pStrmData->strmBuffSize;
1960c1bc742181ded4930842b46e9507372f0b1b963James Dong        readPtr = writePtr = pStrmData->pStrmBuffStart;
1970c1bc742181ded4930842b46e9507372f0b1b963James Dong        zeroCount = 0;
1980c1bc742181ded4930842b46e9507372f0b1b963James Dong        for (i = tmp; i--;)
1990c1bc742181ded4930842b46e9507372f0b1b963James Dong        {
2000c1bc742181ded4930842b46e9507372f0b1b963James Dong            if ((zeroCount == 2) && (*readPtr == 0x03))
2010c1bc742181ded4930842b46e9507372f0b1b963James Dong            {
2020c1bc742181ded4930842b46e9507372f0b1b963James Dong                /* emulation prevention byte shall be followed by one of the
2030c1bc742181ded4930842b46e9507372f0b1b963James Dong                 * following bytes: 0x00, 0x01, 0x02, 0x03. This implies that
2040c1bc742181ded4930842b46e9507372f0b1b963James Dong                 * emulation prevention 0x03 byte shall not be the last byte
2050c1bc742181ded4930842b46e9507372f0b1b963James Dong                 * of the stream. */
2060c1bc742181ded4930842b46e9507372f0b1b963James Dong                if ( (i == 0) || (*(readPtr+1) > 0x03) )
2070c1bc742181ded4930842b46e9507372f0b1b963James Dong                    return(HANTRO_NOK);
2080c1bc742181ded4930842b46e9507372f0b1b963James Dong
2090c1bc742181ded4930842b46e9507372f0b1b963James Dong                /* do not write emulation prevention byte */
2100c1bc742181ded4930842b46e9507372f0b1b963James Dong                readPtr++;
2110c1bc742181ded4930842b46e9507372f0b1b963James Dong                zeroCount = 0;
2120c1bc742181ded4930842b46e9507372f0b1b963James Dong            }
2130c1bc742181ded4930842b46e9507372f0b1b963James Dong            else
2140c1bc742181ded4930842b46e9507372f0b1b963James Dong            {
2150c1bc742181ded4930842b46e9507372f0b1b963James Dong                /* NAL unit shall not contain byte sequences 0x000000,
2160c1bc742181ded4930842b46e9507372f0b1b963James Dong                 * 0x000001 or 0x000002 */
2170c1bc742181ded4930842b46e9507372f0b1b963James Dong                if ( (zeroCount == 2) && (*readPtr <= 0x02) )
2180c1bc742181ded4930842b46e9507372f0b1b963James Dong                    return(HANTRO_NOK);
2190c1bc742181ded4930842b46e9507372f0b1b963James Dong
2200c1bc742181ded4930842b46e9507372f0b1b963James Dong                if (*readPtr == 0)
2210c1bc742181ded4930842b46e9507372f0b1b963James Dong                    zeroCount++;
2220c1bc742181ded4930842b46e9507372f0b1b963James Dong                else
2230c1bc742181ded4930842b46e9507372f0b1b963James Dong                    zeroCount = 0;
2240c1bc742181ded4930842b46e9507372f0b1b963James Dong
2250c1bc742181ded4930842b46e9507372f0b1b963James Dong                *writePtr++ = *readPtr++;
2260c1bc742181ded4930842b46e9507372f0b1b963James Dong            }
2270c1bc742181ded4930842b46e9507372f0b1b963James Dong        }
2280c1bc742181ded4930842b46e9507372f0b1b963James Dong
2290c1bc742181ded4930842b46e9507372f0b1b963James Dong        /* (readPtr - writePtr) indicates number of "removed" emulation
2300c1bc742181ded4930842b46e9507372f0b1b963James Dong         * prevention bytes -> subtract from stream buffer size */
2310c1bc742181ded4930842b46e9507372f0b1b963James Dong        pStrmData->strmBuffSize -= (u32)(readPtr - writePtr);
2320c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
2330c1bc742181ded4930842b46e9507372f0b1b963James Dong
2340c1bc742181ded4930842b46e9507372f0b1b963James Dong    return(HANTRO_OK);
2350c1bc742181ded4930842b46e9507372f0b1b963James Dong
2360c1bc742181ded4930842b46e9507372f0b1b963James Dong}
2370c1bc742181ded4930842b46e9507372f0b1b963James Dong
238