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 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 */ 80 RbspParser::~RbspParser () {} 81 82 // Return next RBSP byte as a word 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 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 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 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 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 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 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 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 /***********************************************************************/ 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 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 ===========================================================================*/ 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