1 /*--------------------------------------------------------------------------
2 Copyright (c) 2010, Code Aurora Forum. All rights reserved.
3
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are met:
6 * Redistributions of source code must retain the above copyright
7 notice, this list of conditions and the following disclaimer.
8 * Redistributions in binary form must reproduce the above copyright
9 notice, this list of conditions and the following disclaimer in the
10 documentation and/or other materials provided with the distribution.
11 * Neither the name of Code Aurora nor
12 the names of its contributors may be used to endorse or promote
13 products derived from this software without specific prior written
14 permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 --------------------------------------------------------------------------*/
28 /*========================================================================
29
30 O p e n M M
31 V i d e o U t i l i t i e s
32
33 *//** @file VideoUtils.cpp
34 This module contains utilities and helper routines.
35
36 @par EXTERNALIZED FUNCTIONS
37
38 @par INITIALIZATION AND SEQUENCING REQUIREMENTS
39 (none)
40
41 *//*====================================================================== */
42
43 /* =======================================================================
44
45 INCLUDE FILES FOR MODULE
46
47 ========================================================================== */
48 #include "h264_utils.h"
49 #include "omx_vdec.h"
50 #include <string.h>
51 #include <stdlib.h>
52
53 /* =======================================================================
54
55 DEFINITIONS AND DECLARATIONS FOR MODULE
56
57 This section contains definitions for constants, macros, types, variables
58 and other items needed by this module.
59
60 ========================================================================== */
61
62 #define SIZE_NAL_FIELD_MAX 4
63 #define BASELINE_PROFILE 66
64 #define MAIN_PROFILE 77
65 #define HIGH_PROFILE 100
66
67 #define MAX_SUPPORTED_LEVEL 32
68
69
RbspParser(const uint8 * _begin,const uint8 * _end)70 RbspParser::RbspParser (const uint8 *_begin, const uint8 *_end)
71 : begin (_begin), end(_end), pos (- 1), bit (0),
72 cursor (0xFFFFFF), advanceNeeded (true)
73 {
74 }
75
76 // Destructor
77 /*lint -e{1540} Pointer member neither freed nor zeroed by destructor
78 * No problem
79 */
~RbspParser()80 RbspParser::~RbspParser () {}
81
82 // Return next RBSP byte as a word
next()83 uint32 RbspParser::next ()
84 {
85 if (advanceNeeded) advance ();
86 //return static_cast<uint32> (*pos);
87 return static_cast<uint32> (begin[pos]);
88 }
89
90 // Advance RBSP decoder to next byte
advance()91 void RbspParser::advance ()
92 {
93 ++pos;
94 //if (pos >= stop)
95 if (begin + pos == end)
96 {
97 /*lint -e{730} Boolean argument to function
98 * I don't see a problem here
99 */
100 //throw false;
101 DEBUG_PRINT_LOW("H264Parser-->NEED TO THROW THE EXCEPTION...\n");
102 }
103 cursor <<= 8;
104 //cursor |= static_cast<uint32> (*pos);
105 cursor |= static_cast<uint32> (begin[pos]);
106 if ((cursor & 0xFFFFFF) == 0x000003)
107 {
108 advance ();
109 }
110 advanceNeeded = false;
111 }
112
113 // Decode unsigned integer
u(uint32 n)114 uint32 RbspParser::u (uint32 n)
115 {
116 uint32 i, s, x = 0;
117 for (i = 0; i < n; i += s)
118 {
119 s = static_cast<uint32>STD_MIN(static_cast<int>(8 - bit),
120 static_cast<int>(n - i));
121 x <<= s;
122
123 x |= ((next () >> ((8 - static_cast<uint32>(bit)) - s)) &
124 ((1 << s) - 1));
125
126 bit = (bit + s) % 8;
127 if (!bit)
128 {
129 advanceNeeded = true;
130 }
131 }
132 return x;
133 }
134
135 // Decode unsigned integer Exp-Golomb-coded syntax element
ue()136 uint32 RbspParser::ue ()
137 {
138 int leadingZeroBits = -1;
139 for (uint32 b = 0; !b; ++leadingZeroBits)
140 {
141 b = u (1);
142 }
143 return ((1 << leadingZeroBits) - 1) +
144 u (static_cast<uint32>(leadingZeroBits));
145 }
146
147 // Decode signed integer Exp-Golomb-coded syntax element
se()148 int32 RbspParser::se ()
149 {
150 const uint32 x = ue ();
151 if (!x) return 0;
152 else if (x & 1) return static_cast<int32> ((x >> 1) + 1);
153 else return - static_cast<int32> (x >> 1);
154 }
155
allocate_rbsp_buffer(uint32 inputBufferSize)156 void H264_Utils::allocate_rbsp_buffer(uint32 inputBufferSize)
157 {
158 m_rbspBytes = (byte *) calloc(1,inputBufferSize);
159 m_prv_nalu.nal_ref_idc = 0;
160 m_prv_nalu.nalu_type = NALU_TYPE_UNSPECIFIED;
161 }
162
H264_Utils()163 H264_Utils::H264_Utils(): m_height(0),
164 m_width(0),
165 m_rbspBytes(NULL),
166 m_au_data (false)
167 {
168 initialize_frame_checking_environment();
169 }
170
~H264_Utils()171 H264_Utils::~H264_Utils()
172 {
173 /* if(m_pbits)
174 {
175 delete(m_pbits);
176 m_pbits = NULL;
177 }
178 */
179 if (m_rbspBytes)
180 {
181 free(m_rbspBytes);
182 m_rbspBytes = NULL;
183 }
184 }
185
186 /***********************************************************************/
187 /*
188 FUNCTION:
189 H264_Utils::initialize_frame_checking_environment
190
191 DESCRIPTION:
192 Extract RBSP data from a NAL
193
194 INPUT/OUTPUT PARAMETERS:
195 None
196
197 RETURN VALUE:
198 boolean
199
200 SIDE EFFECTS:
201 None.
202 */
203 /***********************************************************************/
initialize_frame_checking_environment()204 void H264_Utils::initialize_frame_checking_environment()
205 {
206 m_forceToStichNextNAL = false;
207 m_au_data = false;
208 m_prv_nalu.nal_ref_idc = 0;
209 m_prv_nalu.nalu_type = NALU_TYPE_UNSPECIFIED;
210 }
211
212 /***********************************************************************/
213 /*
214 FUNCTION:
215 H264_Utils::extract_rbsp
216
217 DESCRIPTION:
218 Extract RBSP data from a NAL
219
220 INPUT/OUTPUT PARAMETERS:
221 <In>
222 buffer : buffer containing start code or nal length + NAL units
223 buffer_length : the length of the NAL buffer
224 start_code : If true, start code is detected,
225 otherwise size nal length is detected
226 size_of_nal_length_field: size of nal length field
227
228 <Out>
229 rbsp_bistream : extracted RBSP bistream
230 rbsp_length : the length of the RBSP bitstream
231 nal_unit : decoded NAL header information
232
233 RETURN VALUE:
234 boolean
235
236 SIDE EFFECTS:
237 None.
238 */
239 /***********************************************************************/
240
extract_rbsp(OMX_IN OMX_U8 * buffer,OMX_IN OMX_U32 buffer_length,OMX_IN OMX_U32 size_of_nal_length_field,OMX_OUT OMX_U8 * rbsp_bistream,OMX_OUT OMX_U32 * rbsp_length,OMX_OUT NALU * nal_unit)241 boolean H264_Utils::extract_rbsp(OMX_IN OMX_U8 *buffer,
242 OMX_IN OMX_U32 buffer_length,
243 OMX_IN OMX_U32 size_of_nal_length_field,
244 OMX_OUT OMX_U8 *rbsp_bistream,
245 OMX_OUT OMX_U32 *rbsp_length,
246 OMX_OUT NALU *nal_unit)
247 {
248 byte coef1, coef2, coef3;
249 uint32 pos = 0;
250 uint32 nal_len = buffer_length;
251 uint32 sizeofNalLengthField = 0;
252 uint32 zero_count;
253 boolean eRet = true;
254 boolean start_code = (size_of_nal_length_field==0)?true:false;
255
256 DEBUG_PRINT_LOW("extract_rbsp\n");
257
258 if(start_code) {
259 // Search start_code_prefix_one_3bytes (0x000001)
260 coef2 = buffer[pos++];
261 coef3 = buffer[pos++];
262 do {
263 if(pos >= buffer_length)
264 {
265 DEBUG_PRINT_ERROR("ERROR: In %s() - line %d", __func__, __LINE__);
266 return false;
267 }
268
269 coef1 = coef2;
270 coef2 = coef3;
271 coef3 = buffer[pos++];
272 } while(coef1 || coef2 || coef3 != 1);
273 }
274 else if (size_of_nal_length_field)
275 {
276 /* This is the case to play multiple NAL units inside each access unit*/
277 /* Extract the NAL length depending on sizeOfNALength field */
278 sizeofNalLengthField = size_of_nal_length_field;
279 nal_len = 0;
280 while(size_of_nal_length_field--)
281 {
282 nal_len |= buffer[pos++]<<(size_of_nal_length_field<<3);
283 }
284 if (nal_len >= buffer_length)
285 {
286 DEBUG_PRINT_ERROR("ERROR: In %s() - line %d", __func__, __LINE__);
287 return false;
288 }
289 }
290
291 if (nal_len > buffer_length)
292 {
293 DEBUG_PRINT_ERROR("ERROR: In %s() - line %d", __func__, __LINE__);
294 return false;
295 }
296 if(pos + 1 > (nal_len + sizeofNalLengthField))
297 {
298 DEBUG_PRINT_ERROR("ERROR: In %s() - line %d", __func__, __LINE__);
299 return false;
300 }
301 if (nal_unit->forbidden_zero_bit = (buffer[pos] & 0x80))
302 {
303 DEBUG_PRINT_ERROR("ERROR: In %s() - line %d", __func__, __LINE__);
304 }
305 nal_unit->nal_ref_idc = (buffer[pos] & 0x60) >> 5;
306 nal_unit->nalu_type = buffer[pos++] & 0x1f;
307 DEBUG_PRINT_LOW("\n@#@# Pos = %x NalType = %x buflen = %d",pos-1,nal_unit->nalu_type,buffer_length);
308 *rbsp_length = 0;
309
310
311 if( nal_unit->nalu_type == NALU_TYPE_EOSEQ ||
312 nal_unit->nalu_type == NALU_TYPE_EOSTREAM)
313 return (nal_len + sizeofNalLengthField);
314
315 zero_count = 0;
316 while (pos < (nal_len+sizeofNalLengthField)) //similar to for in p-42
317 {
318 if( zero_count == 2 ) {
319 if( buffer[pos] == 0x03 ) {
320 pos ++;
321 zero_count = 0;
322 continue;
323 }
324 if( buffer[pos] <= 0x01 ) {
325 if( start_code ) {
326 *rbsp_length -= 2;
327 pos -= 2;
328 return pos;
329 }
330 }
331 zero_count = 0;
332 }
333 zero_count ++;
334 if( buffer[pos] != 0 )
335 zero_count = 0;
336
337 rbsp_bistream[(*rbsp_length)++] = buffer[pos++];
338 }
339
340 return eRet;
341 }
342
343 /*===========================================================================
344 FUNCTION:
345 H264_Utils::iSNewFrame
346
347 DESCRIPTION:
348 Returns true if NAL parsing successfull otherwise false.
349
350 INPUT/OUTPUT PARAMETERS:
351 <In>
352 buffer : buffer containing start code or nal length + NAL units
353 buffer_length : the length of the NAL buffer
354 start_code : If true, start code is detected,
355 otherwise size nal length is detected
356 size_of_nal_length_field: size of nal length field
357 <out>
358 isNewFrame: true if the NAL belongs to a differenet frame
359 false if the NAL belongs to a current frame
360
361 RETURN VALUE:
362 boolean true, if nal parsing is successful
363 false, if the nal parsing has errors
364
365 SIDE EFFECTS:
366 None.
367 ===========================================================================*/
isNewFrame(OMX_IN OMX_U8 * buffer,OMX_IN OMX_U32 buffer_length,OMX_IN OMX_U32 size_of_nal_length_field,OMX_OUT OMX_BOOL & isNewFrame)368 bool H264_Utils::isNewFrame(OMX_IN OMX_U8 *buffer,
369 OMX_IN OMX_U32 buffer_length,
370 OMX_IN OMX_U32 size_of_nal_length_field,
371 OMX_OUT OMX_BOOL &isNewFrame)
372 {
373 NALU nal_unit;
374 uint16 first_mb_in_slice = 0;
375 uint32 numBytesInRBSP = 0;
376 bool eRet = true;
377
378 DEBUG_PRINT_LOW("get_h264_nal_type %p nal_length %d nal_length_field %d\n",
379 buffer, buffer_length, size_of_nal_length_field);
380
381 if ( false == extract_rbsp(buffer, buffer_length, size_of_nal_length_field,
382 m_rbspBytes, &numBytesInRBSP, &nal_unit) )
383 {
384 DEBUG_PRINT_ERROR("ERROR: In %s() - extract_rbsp() failed", __func__);
385 isNewFrame = OMX_FALSE;
386 eRet = false;
387 }
388 else
389 {
390 switch (nal_unit.nalu_type)
391 {
392 case NALU_TYPE_IDR:
393 case NALU_TYPE_NON_IDR:
394 {
395 DEBUG_PRINT_LOW("\n Found a AU Boundary %d ",nal_unit.nalu_type);
396 if (m_forceToStichNextNAL)
397 {
398 isNewFrame = OMX_FALSE;
399 }
400 else
401 {
402 RbspParser rbsp_parser(m_rbspBytes, (m_rbspBytes+numBytesInRBSP));
403 first_mb_in_slice = rbsp_parser.ue();
404
405 if((!first_mb_in_slice) || /*(slice.prv_frame_num != slice.frame_num ) ||*/
406 ( (m_prv_nalu.nal_ref_idc != nal_unit.nal_ref_idc) && ( nal_unit.nal_ref_idc * m_prv_nalu.nal_ref_idc == 0 ) ) ||
407 /*( ((m_prv_nalu.nalu_type == NALU_TYPE_IDR) && (nal_unit.nalu_type == NALU_TYPE_IDR)) && (slice.idr_pic_id != slice.prv_idr_pic_id) ) || */
408 ( (m_prv_nalu.nalu_type != nal_unit.nalu_type ) && ((m_prv_nalu.nalu_type == NALU_TYPE_IDR) || (nal_unit.nalu_type == NALU_TYPE_IDR)) ) )
409 {
410 //DEBUG_PRINT_LOW("Found a New Frame due to NALU_TYPE_IDR/NALU_TYPE_NON_IDR");
411 isNewFrame = OMX_TRUE;
412 }
413 else
414 {
415 isNewFrame = OMX_FALSE;
416 }
417 }
418 m_au_data = true;
419 m_forceToStichNextNAL = false;
420 break;
421 }
422 case NALU_TYPE_SPS:
423 case NALU_TYPE_PPS:
424 case NALU_TYPE_SEI:
425 case NALU_TYPE_UNSPECIFIED:
426 case NALU_TYPE_EOSEQ:
427 case NALU_TYPE_EOSTREAM:
428 {
429 DEBUG_PRINT_LOW("\n Non AU boundary NAL %d",nal_unit.nalu_type);
430 if(m_au_data)
431 {
432 isNewFrame = OMX_TRUE;
433 m_au_data = false;
434 }
435 else
436 {
437 isNewFrame = OMX_FALSE;
438 }
439
440 m_forceToStichNextNAL = true;
441 break;
442 }
443 case NALU_TYPE_ACCESS_DELIM:
444 default:
445 {
446 isNewFrame = OMX_FALSE;
447 // Do not update m_forceToStichNextNAL
448 break;
449 }
450 } // end of switch
451 } // end of if
452 m_prv_nalu = nal_unit;
453 DEBUG_PRINT_LOW("get_h264_nal_type - newFrame value %d\n",isNewFrame);
454 return eRet;
455 }
456