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 #include "frameparser.h" 29 #include "omx_vdec.h" 30 31 #ifdef _ANDROID_ 32 extern "C"{ 33 #include<utils/Log.h> 34 } 35 #endif//_ANDROID_ 36 37 static unsigned char H264_mask_code[4] = {0xFF,0xFF,0xFF,0xFF}; 38 static unsigned char H264_start_code[4] = {0x00,0x00,0x00,0x01}; 39 40 static unsigned char MPEG4_start_code[4] = {0x00,0x00,0x01,0xB6}; 41 static unsigned char MPEG4_mask_code[4] = {0xFF,0xFF,0xFF,0xFF}; 42 43 static unsigned char H263_start_code[4] = {0x00,0x00,0x80,0x00}; 44 static unsigned char H263_mask_code[4] = {0xFF,0xFF,0xFC,0x00}; 45 46 static unsigned char VC1_AP_start_code[4] = {0x00,0x00,0x01,0x0D}; 47 static unsigned char VC1_AP_mask_code[4] = {0xFF,0xFF,0xFF,0xFF}; 48 49 frame_parse::frame_parse():mutils(NULL), 50 parse_state(A0), 51 last_byte(0), 52 prev_one(0), 53 state_nal(NAL_LENGTH_ACC), 54 nal_length(0), 55 accum_length(0), 56 bytes_tobeparsed(0), 57 time_stamp (0), 58 flags (0) 59 { 60 memset (start_code,0,sizeof (start_code)); 61 memset (mask_code,0,sizeof (mask_code)); 62 } 63 64 frame_parse::~frame_parse () 65 { 66 if (mutils) 67 delete mutils; 68 69 mutils = NULL; 70 } 71 72 int frame_parse::init_start_codes (codec_type codec_type_parse) 73 { 74 /*Check if Codec Type is proper and we are in proper state*/ 75 if (codec_type_parse > CODEC_TYPE_VC1 || parse_state != A0) 76 { 77 return -1; 78 } 79 80 switch (codec_type_parse) 81 { 82 case CODEC_TYPE_MPEG4: 83 memcpy (start_code,MPEG4_start_code,4); 84 memcpy (mask_code,MPEG4_mask_code,4); 85 break; 86 case CODEC_TYPE_H263: 87 memcpy (start_code,H263_start_code,4); 88 memcpy (mask_code,H263_mask_code,4); 89 break; 90 case CODEC_TYPE_H264: 91 memcpy (start_code,H264_start_code,4); 92 memcpy (mask_code,H264_mask_code,4); 93 break; 94 case CODEC_TYPE_VC1: 95 memcpy (start_code,VC1_AP_start_code,4); 96 memcpy (mask_code,VC1_AP_mask_code,4); 97 break; 98 } 99 return 1; 100 } 101 102 103 int frame_parse::init_nal_length (unsigned int nal_len) 104 { 105 if (nal_len == 0 || nal_len > 4 || state_nal != NAL_LENGTH_ACC) 106 { 107 return -1; 108 } 109 nal_length = nal_len; 110 111 return 1; 112 } 113 114 int frame_parse::parse_mpeg4_frame ( OMX_BUFFERHEADERTYPE *source, 115 OMX_BUFFERHEADERTYPE *dest , 116 OMX_U32 *partialframe) 117 { 118 OMX_U8 *pdest = NULL,*psource = NULL; 119 OMX_U32 dest_len =0, source_len = 0, temp_len = 0; 120 OMX_U32 parsed_length = 0,i=0; 121 int residue_byte = 0; 122 123 if (source == NULL || dest == NULL || partialframe == NULL) 124 { 125 return -1; 126 } 127 128 /*Calculate how many bytes are left in source and destination*/ 129 dest_len = dest->nAllocLen - (dest->nFilledLen + dest->nOffset); 130 psource = source->pBuffer + source->nOffset; 131 pdest = dest->pBuffer + (dest->nFilledLen + dest->nOffset); 132 source_len = source->nFilledLen; 133 134 /*Need Minimum of 4 for destination to copy atleast Start code*/ 135 if (dest_len < 4 || source_len == 0) 136 { 137 DEBUG_PRINT_LOW("\n Dest_len %d source_len %d",dest_len,source_len); 138 if (source_len == 0 && (source->nFlags & 0x01)) 139 { 140 DEBUG_PRINT_LOW("\n EOS condition Inform Client that it is complete frame"); 141 *partialframe = 0; 142 return 1; 143 } 144 DEBUG_PRINT_LOW("\n Error in Parsing bitstream"); 145 return -1; 146 } 147 148 /*Check if State of the previous find is a Start code*/ 149 if (parse_state == A4) 150 { 151 /*Check for minimun size should be 4*/ 152 dest->nFlags = flags; 153 dest->nTimeStamp = time_stamp; 154 update_metadata(source->nTimeStamp,source->nFlags); 155 memcpy (pdest,start_code,4); 156 pdest [2] = prev_one; 157 pdest [3] = last_byte; 158 dest->nFilledLen += 4; 159 pdest += 4; 160 parse_state = A0; 161 } 162 163 /*Entry State Machine*/ 164 while ( source->nFilledLen > 0 && parse_state != A0 165 && parse_state != A4 && dest_len > 0 166 ) 167 { 168 //printf ("\n In the Entry Loop"); 169 switch (parse_state) 170 { 171 case A3: 172 /*If fourth Byte is matching then start code is found*/ 173 if ((*psource & mask_code [3]) == start_code [3]) 174 { 175 last_byte = *psource; 176 parse_state = A4; 177 source->nFilledLen--; 178 source->nOffset++; 179 psource++; 180 } 181 else if ((start_code [1] == start_code [0]) && (start_code [2] == start_code [1])) 182 { 183 parse_state = A2; 184 memcpy (pdest,start_code,1); 185 pdest++; 186 dest->nFilledLen++; 187 dest_len--; 188 } 189 else if (start_code [2] == start_code [0]) 190 { 191 parse_state = A1; 192 memcpy (pdest,start_code,2); 193 pdest += 2; 194 dest->nFilledLen += 2; 195 dest_len -= 2; 196 } 197 else 198 { 199 parse_state = A0; 200 memcpy (pdest,start_code,3); 201 pdest += 3; 202 dest->nFilledLen +=3; 203 dest_len -= 3; 204 } 205 break; 206 207 case A2: 208 if ((*psource & mask_code [2]) == start_code [2]) 209 { 210 prev_one = *psource; 211 parse_state = A3; 212 source->nFilledLen--; 213 source->nOffset++; 214 psource++; 215 } 216 else if ( start_code [1] == start_code [0]) 217 { 218 parse_state = A1; 219 memcpy (pdest,start_code,1); 220 dest->nFilledLen +=1; 221 dest_len--; 222 pdest++; 223 } 224 else 225 { 226 parse_state = A0; 227 memcpy (pdest,start_code,2); 228 dest->nFilledLen +=2; 229 dest_len -= 2; 230 pdest += 2; 231 } 232 break; 233 234 case A1: 235 if ((*psource & mask_code [1]) == start_code [1]) 236 { 237 parse_state = A2; 238 source->nFilledLen--; 239 source->nOffset++; 240 psource++; 241 } 242 else 243 { 244 memcpy (pdest,start_code,1); 245 dest->nFilledLen +=1; 246 pdest++; 247 dest_len--; 248 parse_state = A0; 249 } 250 break; 251 case A4: 252 case A0: 253 break; 254 } 255 dest_len = dest->nAllocLen - (dest->nFilledLen + dest->nOffset); 256 } 257 258 if (parse_state == A4) 259 { 260 *partialframe = 0; 261 DEBUG_PRINT_LOW("\n Nal Found length is %d",dest->nFilledLen); 262 return 1; 263 } 264 265 /*Partial Frame is true*/ 266 *partialframe = 1; 267 268 /*Calculate how many bytes are left in source and destination*/ 269 dest_len = dest->nAllocLen - (dest->nFilledLen + dest->nOffset); 270 psource = source->pBuffer + source->nOffset; 271 pdest = dest->pBuffer + (dest->nFilledLen + dest->nOffset); 272 source_len = source->nFilledLen; 273 274 temp_len = (source_len < dest_len)?source_len:dest_len; 275 276 /*Check if entry state machine consumed source or destination*/ 277 if (temp_len == 0) 278 { 279 return 1; 280 } 281 282 /*Parsing State Machine*/ 283 while (parsed_length < temp_len) 284 { 285 switch (parse_state) 286 { 287 case A0: 288 if ((psource [parsed_length] & mask_code [0]) == start_code[0]) 289 { 290 parse_state = A1; 291 } 292 parsed_length++; 293 break; 294 case A1: 295 if ((psource [parsed_length] & mask_code [1]) == start_code [1]) 296 { 297 parsed_length++; 298 parse_state = A2; 299 } 300 else 301 { 302 parse_state = A0; 303 } 304 break; 305 case A2: 306 if ((psource [parsed_length] & mask_code [2]) == start_code [2]) 307 { 308 prev_one = psource [parsed_length]; 309 parsed_length++; 310 parse_state = A3; 311 } 312 else if (start_code [1] == start_code [0]) 313 { 314 parse_state = A1; 315 } 316 else 317 { 318 parse_state = A0; 319 } 320 break; 321 case A3: 322 if ((psource [parsed_length] & mask_code [3]) == start_code [3]) 323 { 324 last_byte = psource [parsed_length]; 325 parsed_length++; 326 parse_state = A4; 327 } 328 else if ((start_code [1] == start_code [0]) && (start_code [2] == start_code [1])) 329 { 330 parse_state = A2; 331 } 332 else if (start_code [2] == start_code [0]) 333 { 334 parse_state = A1; 335 } 336 else 337 { 338 parse_state = A0; 339 } 340 break; 341 default: 342 break; 343 } 344 345 /*Found the code break*/ 346 if (parse_state == A4) 347 { 348 break; 349 } 350 } 351 352 /*Exit State Machine*/ 353 psource = source->pBuffer + source->nOffset; 354 switch (parse_state) 355 { 356 case A4: 357 *partialframe = 0; 358 if (parsed_length > 4) 359 { 360 memcpy (pdest,psource,(parsed_length-4)); 361 dest->nFilledLen += (parsed_length-4); 362 } 363 break; 364 case A3: 365 if (parsed_length > 3) 366 { 367 memcpy (pdest,psource,(parsed_length-3)); 368 dest->nFilledLen += (parsed_length-3); 369 } 370 break; 371 case A2: 372 if (parsed_length > 2) 373 { 374 memcpy (pdest,psource,(parsed_length-2)); 375 dest->nFilledLen += (parsed_length-2); 376 } 377 break; 378 case A1: 379 if (parsed_length > 1) 380 { 381 memcpy (pdest,psource,(parsed_length-1)); 382 dest->nFilledLen += (parsed_length-1); 383 } 384 break; 385 case A0: 386 memcpy (pdest,psource,(parsed_length)); 387 dest->nFilledLen += (parsed_length); 388 break; 389 } 390 391 if (source->nFilledLen < parsed_length) 392 { 393 printf ("\n FATAL Error"); 394 return -1; 395 } 396 source->nFilledLen -= parsed_length; 397 source->nOffset += parsed_length; 398 399 return 1; 400 } 401 402 403 int frame_parse::parse_h264_nallength (OMX_BUFFERHEADERTYPE *source, 404 OMX_BUFFERHEADERTYPE *dest , 405 OMX_U32 *partialframe) 406 { 407 OMX_U8 *pdest = NULL,*psource = NULL; 408 OMX_U32 dest_len =0, source_len = 0, temp_len = 0,parsed_length = 0; 409 410 if (source == NULL || dest == NULL || partialframe == NULL) 411 { 412 return -1; 413 } 414 415 /*Calculate the length's*/ 416 dest_len = dest->nAllocLen - (dest->nFilledLen + dest->nOffset); 417 source_len = source->nFilledLen; 418 419 if (dest_len < 4 || source_len == 0 || nal_length == 0) 420 { 421 DEBUG_PRINT_LOW("\n Destination %d source %d nal length %d",\ 422 dest_len,source_len,nal_length); 423 return -1; 424 } 425 *partialframe = 1; 426 temp_len = (source_len < dest_len)?source_len:dest_len; 427 psource = source->pBuffer + source->nOffset; 428 pdest = dest->pBuffer + (dest->nFilledLen + dest->nOffset); 429 430 /* Find the Bytes to Accumalte*/ 431 if (state_nal == NAL_LENGTH_ACC) 432 { 433 while (parsed_length < temp_len ) 434 { 435 bytes_tobeparsed |= (((OMX_U32)(*psource))) << (((nal_length-accum_length-1) << 3)); 436 437 /*COPY THE DATA FOR C-SIM TO BE REOMVED ON TARGET*/ 438 //*pdest = *psource; 439 accum_length++; 440 source->nFilledLen--; 441 source->nOffset++; 442 psource++; 443 //dest->nFilledLen++; 444 //pdest++; 445 parsed_length++; 446 447 if (accum_length == nal_length) 448 { 449 accum_length = 0; 450 state_nal = NAL_PARSING; 451 memcpy (pdest,H264_start_code,4); 452 dest->nFilledLen += 4; 453 break; 454 } 455 } 456 } 457 458 dest_len = dest->nAllocLen - (dest->nFilledLen + dest->nOffset); 459 source_len = source->nFilledLen; 460 temp_len = (source_len < dest_len)?source_len:dest_len; 461 462 psource = source->pBuffer + source->nOffset; 463 pdest = dest->pBuffer + (dest->nFilledLen + dest->nOffset); 464 465 /*Already in Parsing state go ahead and copy*/ 466 if(state_nal == NAL_PARSING && temp_len > 0) 467 { 468 if (temp_len < bytes_tobeparsed) 469 { 470 memcpy (pdest,psource,temp_len); 471 dest->nFilledLen += temp_len; 472 source->nOffset += temp_len; 473 source->nFilledLen -= temp_len; 474 bytes_tobeparsed -= temp_len; 475 } 476 else 477 { 478 memcpy (pdest,psource,bytes_tobeparsed); 479 temp_len -= bytes_tobeparsed; 480 dest->nFilledLen += bytes_tobeparsed; 481 source->nOffset += bytes_tobeparsed; 482 source->nFilledLen -= bytes_tobeparsed; 483 bytes_tobeparsed = 0; 484 } 485 } 486 487 if (bytes_tobeparsed == 0 && state_nal == NAL_PARSING) 488 { 489 *partialframe = 0; 490 state_nal = NAL_LENGTH_ACC; 491 } 492 493 return 1; 494 } 495 496 void frame_parse::flush () 497 { 498 parse_state = A0; 499 state_nal = NAL_LENGTH_ACC; 500 accum_length = 0; 501 bytes_tobeparsed = 0; 502 } 503 504 void frame_parse::update_metadata (unsigned int ts ,unsigned int flgs) 505 { 506 time_stamp = ts; 507 flags = flgs; 508 } 509