1 /*--------------------------------------------------------------------------
2 Copyright (c) 2010, Code Aurora Forum. All rights reserved.
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
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 /*========================================================================
31 V i d e o U t i l i t i e s
33 *//** @file VideoUtils.cpp
34 This module contains utilities and helper routines.
36 @par EXTERNALIZED FUNCTIONS
38 @par INITIALIZATION AND SEQUENCING REQUIREMENTS
41 *//*====================================================================== */
43 /* =======================================================================
45 INCLUDE FILES FOR MODULE
47 ========================================================================== */
48 #include "h264_utils.h"
53 /* =======================================================================
55 DEFINITIONS AND DECLARATIONS FOR MODULE
57 This section contains definitions for constants, macros, types, variables
58 and other items needed by this module.
60 ========================================================================== */
62 #define SIZE_NAL_FIELD_MAX 4
63 #define BASELINE_PROFILE 66
64 #define MAIN_PROFILE 77
65 #define HIGH_PROFILE 100
67 #define MAX_SUPPORTED_LEVEL 32
70 RbspParser::RbspParser (const uint8 *_begin, const uint8 *_end)
71 : begin (_begin), end(_end), pos (- 1), bit (0),
72 cursor (0xFFFFFF), advanceNeeded (true)
77 /*lint -e{1540} Pointer member neither freed nor zeroed by destructor
80 RbspParser::~RbspParser () {}
82 // Return next RBSP byte as a word
83 uint32 RbspParser::next ()
85 if (advanceNeeded) advance ();
86 //return static_cast<uint32> (*pos);
87 return static_cast<uint32> (begin[pos]);
90 // Advance RBSP decoder to next byte
91 void RbspParser::advance ()
95 if (begin + pos == end)
97 /*lint -e{730} Boolean argument to function
98 * I don't see a problem here
101 DEBUG_PRINT_LOW("H264Parser-->NEED TO THROW THE EXCEPTION...\n");
104 //cursor |= static_cast<uint32> (*pos);
105 cursor |= static_cast<uint32> (begin[pos]);
106 if ((cursor & 0xFFFFFF) == 0x000003)
110 advanceNeeded = false;
113 // Decode unsigned integer
114 uint32 RbspParser::u (uint32 n)
117 for (i = 0; i < n; i += s)
119 s = static_cast<uint32>STD_MIN(static_cast<int>(8 - bit),
120 static_cast<int>(n - i));
123 x |= ((next () >> ((8 - static_cast<uint32>(bit)) - s)) &
129 advanceNeeded = true;
135 // Decode unsigned integer Exp-Golomb-coded syntax element
136 uint32 RbspParser::ue ()
138 int leadingZeroBits = -1;
139 for (uint32 b = 0; !b; ++leadingZeroBits)
143 return ((1 << leadingZeroBits) - 1) +
144 u (static_cast<uint32>(leadingZeroBits));
147 // Decode signed integer Exp-Golomb-coded syntax element
148 int32 RbspParser::se ()
150 const uint32 x = ue ();
152 else if (x & 1) return static_cast<int32> ((x >> 1) + 1);
153 else return - static_cast<int32> (x >> 1);
156 void H264_Utils::allocate_rbsp_buffer(uint32 inputBufferSize)
158 m_rbspBytes = (byte *) calloc(1,inputBufferSize);
159 m_prv_nalu.nal_ref_idc = 0;
160 m_prv_nalu.nalu_type = NALU_TYPE_UNSPECIFIED;
163 H264_Utils::H264_Utils(): m_height(0),
168 initialize_frame_checking_environment();
171 H264_Utils::~H264_Utils()
186 /***********************************************************************/
189 H264_Utils::initialize_frame_checking_environment
192 Extract RBSP data from a NAL
194 INPUT/OUTPUT PARAMETERS:
203 /***********************************************************************/
204 void H264_Utils::initialize_frame_checking_environment()
206 m_forceToStichNextNAL = false;
208 m_prv_nalu.nal_ref_idc = 0;
209 m_prv_nalu.nalu_type = NALU_TYPE_UNSPECIFIED;
212 /***********************************************************************/
215 H264_Utils::extract_rbsp
218 Extract RBSP data from a NAL
220 INPUT/OUTPUT PARAMETERS:
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
229 rbsp_bistream : extracted RBSP bistream
230 rbsp_length : the length of the RBSP bitstream
231 nal_unit : decoded NAL header information
239 /***********************************************************************/
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)
248 byte coef1, coef2, coef3;
250 uint32 nal_len = buffer_length;
251 uint32 sizeofNalLengthField = 0;
254 boolean start_code = (size_of_nal_length_field==0)?true:false;
256 DEBUG_PRINT_LOW("extract_rbsp\n");
259 // Search start_code_prefix_one_3bytes (0x000001)
260 coef2 = buffer[pos++];
261 coef3 = buffer[pos++];
263 if(pos >= buffer_length)
265 DEBUG_PRINT_ERROR("ERROR: In %s() - line %d", __func__, __LINE__);
271 coef3 = buffer[pos++];
272 } while(coef1 || coef2 || coef3 != 1);
274 else if (size_of_nal_length_field)
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;
280 while(size_of_nal_length_field--)
282 nal_len |= buffer[pos++]<<(size_of_nal_length_field<<3);
284 if (nal_len >= buffer_length)
286 DEBUG_PRINT_ERROR("ERROR: In %s() - line %d", __func__, __LINE__);
291 if (nal_len > buffer_length)
293 DEBUG_PRINT_ERROR("ERROR: In %s() - line %d", __func__, __LINE__);
296 if(pos + 1 > (nal_len + sizeofNalLengthField))
298 DEBUG_PRINT_ERROR("ERROR: In %s() - line %d", __func__, __LINE__);
301 if (nal_unit->forbidden_zero_bit = (buffer[pos] & 0x80))
303 DEBUG_PRINT_ERROR("ERROR: In %s() - line %d", __func__, __LINE__);
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);
311 if( nal_unit->nalu_type == NALU_TYPE_EOSEQ ||
312 nal_unit->nalu_type == NALU_TYPE_EOSTREAM)
313 return (nal_len + sizeofNalLengthField);
316 while (pos < (nal_len+sizeofNalLengthField)) //similar to for in p-42
318 if( zero_count == 2 ) {
319 if( buffer[pos] == 0x03 ) {
324 if( buffer[pos] <= 0x01 ) {
334 if( buffer[pos] != 0 )
337 rbsp_bistream[(*rbsp_length)++] = buffer[pos++];
343 /*===========================================================================
345 H264_Utils::iSNewFrame
348 Returns true if NAL parsing successfull otherwise false.
350 INPUT/OUTPUT PARAMETERS:
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
358 isNewFrame: true if the NAL belongs to a differenet frame
359 false if the NAL belongs to a current frame
362 boolean true, if nal parsing is successful
363 false, if the nal parsing has errors
367 ===========================================================================*/
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)
374 uint16 first_mb_in_slice = 0;
375 uint32 numBytesInRBSP = 0;
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);
381 if ( false == extract_rbsp(buffer, buffer_length, size_of_nal_length_field,
382 m_rbspBytes, &numBytesInRBSP, &nal_unit) )
384 DEBUG_PRINT_ERROR("ERROR: In %s() - extract_rbsp() failed", __func__);
385 isNewFrame = OMX_FALSE;
390 switch (nal_unit.nalu_type)
393 case NALU_TYPE_NON_IDR:
395 DEBUG_PRINT_LOW("\n Found a AU Boundary %d ",nal_unit.nalu_type);
396 if (m_forceToStichNextNAL)
398 isNewFrame = OMX_FALSE;
402 RbspParser rbsp_parser(m_rbspBytes, (m_rbspBytes+numBytesInRBSP));
403 first_mb_in_slice = rbsp_parser.ue();
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)) ) )
410 //DEBUG_PRINT_LOW("Found a New Frame due to NALU_TYPE_IDR/NALU_TYPE_NON_IDR");
411 isNewFrame = OMX_TRUE;
415 isNewFrame = OMX_FALSE;
419 m_forceToStichNextNAL = false;
425 case NALU_TYPE_UNSPECIFIED:
426 case NALU_TYPE_EOSEQ:
427 case NALU_TYPE_EOSTREAM:
429 DEBUG_PRINT_LOW("\n Non AU boundary NAL %d",nal_unit.nalu_type);
432 isNewFrame = OMX_TRUE;
437 isNewFrame = OMX_FALSE;
440 m_forceToStichNextNAL = true;
443 case NALU_TYPE_ACCESS_DELIM:
446 isNewFrame = OMX_FALSE;
447 // Do not update m_forceToStichNextNAL
452 m_prv_nalu = nal_unit;
453 DEBUG_PRINT_LOW("get_h264_nal_type - newFrame value %d\n",isNewFrame);