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