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
h264bsdExtractNalUnit(u8 * pByteStream,u32 len,strmData_t * pStrmData,u32 * readBytes)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