1 /* ------------------------------------------------------------------ 2 * Copyright (C) 1998-2009 PacketVideo 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 13 * express or implied. 14 * See the License for the specific language governing permissions 15 * and limitations under the License. 16 * ------------------------------------------------------------------- 17 */ 18 #include "pv_avifile_parser.h" 19 20 21 PVAviFileParser::PVAviFileParser(OSCL_wHeapString<OsclMemAllocator> aFileName, int32& aError, Oscl_FileServer* aFileServer, 22 PVMFCPMPluginAccessInterfaceFactory* aCPM, OsclFileHandle* aFileHandle) 23 { 24 ipFileHeader = NULL; 25 ipIdxChunk = NULL; 26 iIdxChunkPresent = false; 27 iFileSize = 0; 28 iHeaderChunkSize = 0; 29 iMovieChunkSize = 0; 30 iMovieChunkStartOffset = 0; 31 iIndxChunkSize = 0; 32 iSampleOffset = 0; 33 iTimeStampVideo = 0; 34 iTimeStampAudio = 0; 35 36 OSCL_TRY(aError, ipFilePtr = OSCL_NEW(PVFile, ());); 37 38 if (0 == aError) 39 { 40 ipFilePtr->SetCPM(aCPM); 41 ipFilePtr->SetFileHandle(aFileHandle); 42 43 aError = PV_AVI_FILE_PARSER_SUCCESS; 44 45 if (ipFilePtr->Open(aFileName.get_cstr(), (Oscl_File::MODE_READ | Oscl_File::MODE_BINARY), *aFileServer) != 0) 46 { 47 aError = PV_AVI_FILE_PARSER_FILE_OPEN_ERROR; 48 } 49 } 50 } 51 52 PV_AVI_FILE_PARSER_ERROR_TYPE 53 PVAviFileParser::ParseFile() 54 { 55 iError = PV_AVI_FILE_PARSER_SUCCESS; 56 ipFilePtr->Seek(0, Oscl_File::SEEKSET); 57 58 // Seek to the end to find the file size 59 uint32 filesize = 0; 60 if (ipFilePtr->Seek(0, Oscl_File::SEEKEND)) 61 { 62 iError = PV_AVI_FILE_PARSER_SEEK_ERROR; 63 return iError; 64 } 65 filesize = ipFilePtr->Tell(); 66 67 // Seek back to the beginning 68 ipFilePtr->Seek(0, Oscl_File::SEEKSET); 69 uint32 chunkType = 0; 70 71 if ((iError = PVAviFileParserUtils::ReadNextChunkType(ipFilePtr, chunkType)) != PV_AVI_FILE_PARSER_SUCCESS) 72 { 73 PVAVIFILE_LOGERROR((0, "PVAviFileParser::ParseFile: UnSupported Chunk at begining of the file")); 74 return iError; 75 } 76 77 //first chunk must be RIFF 78 if (chunkType != RIFF) 79 { 80 PVAVIFILE_LOGERROR((0, "PVAviFileParser::ParseFile: First Chunk Must be RIFF")); 81 iError = PV_AVI_FILE_PARSER_WRONG_FILE; 82 return iError; 83 } 84 85 if (PV_AVI_FILE_PARSER_SUCCESS != PVAviFileParserUtils::read32(ipFilePtr, iFileSize, true)) 86 { 87 iError = PV_AVI_FILE_PARSER_READ_ERROR; 88 return iError; 89 } 90 91 if ((iFileSize <= 0) || (iFileSize > filesize)) 92 { 93 iError = PV_AVI_FILE_PARSER_WRONG_SIZE; 94 return iError; 95 } 96 97 if ((iError = PVAviFileParserUtils::ReadNextChunkType(ipFilePtr, chunkType)) != PV_AVI_FILE_PARSER_SUCCESS) 98 { 99 PVAVIFILE_LOGERROR((0, "PVAviFileParser::ParseFile: UnSupported Chunk at begining of the file")); 100 return iError; 101 } 102 103 //second chunk must be AVI 104 if (chunkType != AVI) 105 { 106 PVAVIFILE_LOGERROR((0, "Second Chunk Must be AVI")); 107 iError = PV_AVI_FILE_PARSER_WRONG_FILE; 108 return iError; 109 } 110 111 uint32 bytesRead = CHUNK_SIZE; 112 uint32 listSize = 0; 113 uint32 oldChkType = chunkType; 114 115 while (bytesRead < iFileSize) 116 { 117 oldChkType = chunkType; 118 if ((iError = PVAviFileParserUtils::ReadNextChunkType(ipFilePtr, chunkType)) != PV_AVI_FILE_PARSER_SUCCESS) 119 { 120 if ((PV_AVI_FILE_PARSER_UNSUPPORTED_CHUNK == iError)) 121 { 122 PVAVIFILE_LOGINFO((0, "PVAviFileParser::ParseFile: Unsupported chunk")); 123 124 uint32 chksz = 0; 125 if (oldChkType != LIST) 126 { 127 //get the size of unsupported chunk and skip it. 128 if (PV_AVI_FILE_PARSER_SUCCESS != PVAviFileParserUtils::read32(ipFilePtr, chksz, true)) 129 { 130 PVAVIFILE_LOGERROR((0, "PVAviFileParser::ParseFile: File Read Error")); 131 iError = PV_AVI_FILE_PARSER_READ_ERROR; 132 break; 133 } 134 135 ipFilePtr->Seek(chksz, Oscl_File::SEEKCUR); 136 bytesRead += chksz + CHUNK_SIZE + CHUNK_SIZE; //chunk data + chunk size + chunk type; 137 138 } 139 else 140 { 141 //skip the entire list if not supported 142 chksz = listSize - CHUNK_SIZE ; //subtract list name already read 143 ipFilePtr->Seek(chksz, Oscl_File::SEEKCUR); 144 bytesRead += listSize; 145 } 146 147 PVAVIFILE_LOGINFO((0, "PVAviFileParser::ParseFile: Unsupported chunk skipped")); 148 iError = PV_AVI_FILE_PARSER_SUCCESS; 149 continue; 150 } 151 else 152 { 153 break; 154 } 155 } 156 bytesRead += CHUNK_SIZE; 157 158 if (LIST == chunkType) 159 { 160 if (PV_AVI_FILE_PARSER_SUCCESS != PVAviFileParserUtils::read32(ipFilePtr, listSize, true)) 161 { 162 iError = PV_AVI_FILE_PARSER_READ_ERROR; 163 break; 164 } 165 166 bytesRead += CHUNK_SIZE; 167 if (bytesRead > iFileSize) 168 { 169 iError = PV_AVI_FILE_PARSER_BYTE_COUNT_ERROR; 170 break; 171 } 172 173 if ((listSize <= 0) || (listSize > iFileSize)) 174 { 175 iError = PV_AVI_FILE_PARSER_WRONG_SIZE; 176 break; 177 } 178 } 179 else if (HDRL == chunkType) 180 { 181 PVAVIFILE_LOGINFO((0, "PVAviFileParser::ParseFile: Found File Header")); 182 183 iHeaderChunkSize = listSize - CHUNK_SIZE; //subtract 4 bytes of chunk type 184 ipFileHeader = OSCL_NEW(PVAviFileHeader, (ipFilePtr, iHeaderChunkSize)); 185 if (ipFileHeader != NULL) 186 { 187 iError = ipFileHeader->GetStatus(); 188 if (iError != PV_AVI_FILE_PARSER_SUCCESS) 189 { 190 OSCL_DELETE(ipFileHeader); 191 ipFileHeader = NULL; 192 break; 193 } 194 } 195 bytesRead += iHeaderChunkSize; 196 if (bytesRead > iFileSize) 197 { 198 iError = PV_AVI_FILE_PARSER_BYTE_COUNT_ERROR; 199 break; 200 } 201 } 202 else if (MOVI == chunkType) 203 { 204 PVAVIFILE_LOGINFO((0, "PVAviFileParser::ParseFile: Found MOVI Chunk")); 205 206 iMovieChunkSize = listSize - CHUNK_SIZE; 207 iMovieChunkStartOffset = ipFilePtr->Tell(); //get movi chunk start offset. 208 iSampleOffset = iMovieChunkStartOffset; 209 ipFilePtr->Seek(iMovieChunkSize, Oscl_File::SEEKCUR); 210 211 uint32 numStr = GetNumStreams(); 212 for (uint32 ii = 0; ii < numStr; ii++) 213 { 214 iStreamCount.push_back(ii); 215 iStreamSampleCount.push_back(0); 216 } 217 218 bytesRead += iMovieChunkSize; 219 220 } 221 else if (IDX1 == chunkType) 222 { 223 PVAVIFILE_LOGINFO((0, "PVAviFileParser::ParseFile: Found Index Table")); 224 225 if (PV_AVI_FILE_PARSER_SUCCESS != PVAviFileParserUtils::read32(ipFilePtr, iIndxChunkSize, true)) 226 { 227 iError = PV_AVI_FILE_PARSER_READ_ERROR; 228 break; 229 } 230 231 bytesRead += CHUNK_SIZE; 232 if (bytesRead > iFileSize) 233 { 234 iError = PV_AVI_FILE_PARSER_BYTE_COUNT_ERROR; 235 break; 236 } 237 238 if ((iIndxChunkSize <= 0) || (iIndxChunkSize > iFileSize)) 239 { 240 iError = PV_AVI_FILE_PARSER_WRONG_SIZE; 241 break; 242 } 243 uint32 numStreams = GetNumStreams(); 244 ipIdxChunk = OSCL_NEW(PVAviFileIdxChunk, (ipFilePtr, iIndxChunkSize, numStreams)); 245 if (ipIdxChunk != NULL) 246 { 247 iError = ipIdxChunk->GetStatus(); 248 if (iError != PV_AVI_FILE_PARSER_SUCCESS) 249 { 250 OSCL_DELETE(ipIdxChunk); 251 ipIdxChunk = NULL; 252 break; 253 } 254 iIdxChunkPresent = true; 255 } 256 bytesRead += iIndxChunkSize; 257 } 258 else if (JUNK == chunkType) 259 { 260 PVAVIFILE_LOGINFO((0, "PVAviFileParser::ParseFile: Skip Junk data")); 261 262 uint32 junkSize = 0; 263 if (PV_AVI_FILE_PARSER_SUCCESS != PVAviFileParserUtils::read32(ipFilePtr, junkSize, true)) 264 { 265 iError = PV_AVI_FILE_PARSER_READ_ERROR; 266 break; 267 } 268 269 bytesRead += CHUNK_SIZE; 270 if (bytesRead > iFileSize) 271 { 272 iError = PV_AVI_FILE_PARSER_BYTE_COUNT_ERROR; 273 break; 274 } 275 276 if ((junkSize <= 0) || (junkSize > iFileSize)) 277 { 278 iError = PV_AVI_FILE_PARSER_WRONG_SIZE; 279 break; 280 } 281 282 ipFilePtr->Seek(junkSize, Oscl_File::SEEKCUR); 283 bytesRead += junkSize; 284 if (bytesRead > iFileSize) 285 { 286 iError = PV_AVI_FILE_PARSER_BYTE_COUNT_ERROR; 287 break; 288 } 289 } 290 else 291 { 292 iError = PV_AVI_FILE_PARSER_WRONG_CHUNK; 293 break; 294 } 295 296 } //while (bytesRead <= iFileSize) 297 298 return iError; 299 } 300 301 PV_AVI_FILE_PARSER_ERROR_TYPE 302 PVAviFileParser::GetNextMediaSample(uint32& arStreamNo, uint8* aBuffer, 303 uint32& arSize, uint32& arTimeStamp) 304 { 305 if (iSampleOffset >= iFileSize) 306 { 307 PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: Wrong offset")); 308 return PV_AVI_FILE_PARSER_WRONG_OFFSET; 309 } 310 311 if (iSampleOffset == iMovieChunkStartOffset) 312 { 313 //first Sample reset sample count. 314 for (uint32 ii = 0; ii < GetNumStreams(); ii++) 315 { 316 iStreamSampleCount[ii] = 0; 317 } 318 319 ipFilePtr->Seek(0, Oscl_File::SEEKSET); 320 } 321 322 uint32 CurrOff = ipFilePtr->Tell(); 323 if (CurrOff > iSampleOffset) 324 { 325 PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: Wrong offset")); 326 return PV_AVI_FILE_PARSER_WRONG_OFFSET; 327 } 328 329 ipFilePtr->Seek((iSampleOffset - CurrOff), Oscl_File::SEEKCUR); 330 331 uint32 bytesRead = 0; 332 uint32 data = 0; 333 if (PV_AVI_FILE_PARSER_SUCCESS != PVAviFileParserUtils::read32(ipFilePtr, data)) 334 { 335 PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: Read Error")); 336 return PV_AVI_FILE_PARSER_READ_ERROR; 337 } 338 339 int32 strNo = PVAviFileParserUtils::GetStreamNumber(data); 340 if (PV_AVI_FILE_PARSER_ERROR_UNKNOWN == strNo) 341 { 342 PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: Wrong Stream No")); 343 return PV_AVI_FILE_PARSER_ERROR_WRONG_STREAM_NUM; 344 } 345 346 arStreamNo = strNo; 347 348 bytesRead += CHUNK_SIZE; 349 350 uint32 size = 0; 351 if (PV_AVI_FILE_PARSER_SUCCESS != PVAviFileParserUtils::read32(ipFilePtr, size, true)) 352 { 353 PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: File Read Error")); 354 return PV_AVI_FILE_PARSER_READ_ERROR; 355 } 356 357 bytesRead += CHUNK_SIZE; 358 359 if (size > arSize) 360 { 361 PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: Insufficient Buffer Size")); 362 return PV_AVI_FILE_PARSER_INSUFFICIENT_MEMORY; 363 } 364 365 arSize = size; 366 367 if (PVAviFileParserUtils::read8(ipFilePtr, aBuffer, arSize) != arSize) 368 { 369 PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: File Read Error")); 370 return PV_AVI_FILE_PARSER_READ_ERROR; 371 } 372 373 iSampleOffset = iSampleOffset + arSize + bytesRead; 374 375 uint32 offsetFrmMoviChk = iSampleOffset - iMovieChunkStartOffset; 376 377 if (offsetFrmMoviChk >= iMovieChunkSize) 378 { 379 PVAVIFILE_LOGINFO((0, "PVAviFileParser::GetNextMediaSample: EOF Reached")); 380 return PV_AVI_FILE_PARSER_EOF_REACHED; 381 } 382 383 //calculate time stamp 384 if (oscl_strstr(GetStreamMimeType(arStreamNo).get_str(), "audio")) 385 { 386 arTimeStamp = iTimeStampAudio; 387 uint32 sampleSize = GetBitsPerSample(arStreamNo); 388 sampleSize = sampleSize / BIT_COUNT8; //in bytes 389 OsclFloat samplingRate = GetFrameRate(arStreamNo); 390 if (sampleSize > 0) 391 { 392 OsclFloat sampleCount = (OsclFloat)arSize / sampleSize; 393 if (samplingRate > 0) 394 { 395 iTimeStampAudio += (uint32)((sampleCount * 1000) / samplingRate); 396 } 397 } 398 } 399 else 400 { 401 if (iStreamSampleCount[arStreamNo] > 0) 402 { 403 uint32 frameDurationInms = GetFrameDuration() / 1000; 404 arTimeStamp = (iStreamSampleCount[arStreamNo] * (frameDurationInms)); 405 } 406 else 407 { 408 arTimeStamp = 0; 409 } 410 } 411 412 iStreamSampleCount[arStreamNo] = iStreamSampleCount[arStreamNo] + 1; 413 return PV_AVI_FILE_PARSER_SUCCESS; 414 } 415 416 417 PV_AVI_FILE_PARSER_ERROR_TYPE 418 PVAviFileParser::GetNextStreamSampleInfo(uint32 aStreamNo, uint32& arSize, uint32& arOffset) 419 { 420 if (false == iIdxChunkPresent) 421 { 422 return PV_AVI_FILE_PARSER_NO_INDEX_CHUNK; 423 } 424 else 425 { 426 return GetStreamOffsetFromIndexTable(aStreamNo, arSize, arOffset); 427 } 428 } 429 430 PV_AVI_FILE_PARSER_ERROR_TYPE 431 PVAviFileParser::GetNextStreamMediaSample(uint32 aStreamNo, uint8* aBuffer, 432 uint32& arSize, uint32& arTimeStamp) 433 { 434 uint32 sampleOffset = 0; 435 PV_AVI_FILE_PARSER_ERROR_TYPE error = PV_AVI_FILE_PARSER_SUCCESS; 436 437 if (false == iIdxChunkPresent) 438 { 439 error = GetStreamOffset(aStreamNo, arSize, sampleOffset); 440 441 if ((error != PV_AVI_FILE_PARSER_SUCCESS)) 442 { 443 if (PV_AVI_FILE_PARSER_NO_OFFSET_FOUND == error) 444 { 445 arSize = 0; 446 arTimeStamp = 0; 447 //probably EOS has been reached. 448 return PV_AVI_FILE_PARSER_EOS_REACHED; 449 } 450 else 451 { 452 return error; 453 } 454 } 455 456 uint32 offsetFrmMoviChk = sampleOffset - iMovieChunkStartOffset; 457 if (offsetFrmMoviChk >= iMovieChunkSize) 458 { 459 PVAVIFILE_LOGINFO((0, "PVAviFileParser::GetNextStreamMediaSample: EOF Reached")); 460 return PV_AVI_FILE_PARSER_EOF_REACHED; 461 } 462 } 463 else 464 { 465 error = GetStreamOffsetFromIndexTable(aStreamNo, arSize, sampleOffset); 466 if (error != PV_AVI_FILE_PARSER_SUCCESS) 467 { 468 return error; 469 } 470 } 471 472 if (PVAviFileParserUtils::read8(ipFilePtr, aBuffer, arSize) != arSize) 473 { 474 PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: File Read Error")); 475 return PV_AVI_FILE_PARSER_READ_ERROR; 476 } 477 478 //calculate time stamp 479 if (oscl_strstr(GetStreamMimeType(aStreamNo).get_str(), "audio")) 480 { 481 arTimeStamp = iTimeStampAudio; 482 uint32 sampleSize = GetBitsPerSample(aStreamNo); 483 sampleSize = sampleSize / BIT_COUNT8; //in bytes 484 OsclFloat samplingRate = GetFrameRate(aStreamNo); 485 if (sampleSize > 0) 486 { 487 OsclFloat sampleCount = (OsclFloat)arSize / sampleSize; 488 if (samplingRate > 0) 489 { 490 iTimeStampAudio += (uint32)((sampleCount * 1000) / samplingRate); 491 } 492 } 493 } 494 else 495 { 496 if (iStreamSampleCount[aStreamNo] > 0) 497 { 498 uint32 frameDurationInms = GetFrameDuration() / 1000; 499 arTimeStamp = (iStreamSampleCount[aStreamNo] * (frameDurationInms)); 500 } 501 else 502 { 503 arTimeStamp = 0; 504 } 505 } 506 507 iStreamSampleCount[aStreamNo] = iStreamSampleCount[aStreamNo] + 1; 508 509 return PV_AVI_FILE_PARSER_SUCCESS; 510 } 511 512 513 PV_AVI_FILE_PARSER_ERROR_TYPE 514 PVAviFileParser::GetStreamOffsetFromIndexTable(uint32 aStreamNo, uint32& arSize, uint32& arOffset) 515 { 516 uint32 sampleOffset = 0; 517 518 if (iStreamSampleCount[aStreamNo] >= ipIdxChunk->GetNumberOfSamplesInStream(aStreamNo)) 519 { 520 PVAVIFILE_LOGINFO((0, "PVAviFileParser::GetNextMediaSample: EOF Reached")); 521 return PV_AVI_FILE_PARSER_EOS_REACHED; 522 } 523 524 sampleOffset = ipIdxChunk->GetOffset(aStreamNo, iStreamSampleCount[aStreamNo]); 525 uint32 size = ipIdxChunk->GetSampleSize(aStreamNo, iStreamSampleCount[aStreamNo]); 526 527 if (size > arSize) 528 { 529 PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: Insufficient Buffer Size")); 530 return PV_AVI_FILE_PARSER_INSUFFICIENT_MEMORY; 531 } 532 533 arSize = size; 534 535 if (ipIdxChunk->IsOffsetFromMoviList()) 536 { 537 arOffset = iMovieChunkStartOffset + sampleOffset - CHUNK_SIZE; 538 } 539 else 540 { 541 arOffset = sampleOffset; 542 } 543 544 arOffset += (CHUNK_SIZE + CHUNK_SIZE); //add 4 bytes each for sample type and data size param. 545 546 if ((arOffset > iFileSize)) 547 { 548 PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: File Size & Byte Count mismatch")); 549 return PV_AVI_FILE_PARSER_BYTE_COUNT_ERROR; 550 } 551 552 ipFilePtr->Seek(0, Oscl_File::SEEKSET); 553 ipFilePtr->Seek(arOffset, Oscl_File::SEEKCUR); 554 555 return PV_AVI_FILE_PARSER_SUCCESS; 556 } 557 558 559 PV_AVI_FILE_PARSER_ERROR_TYPE 560 PVAviFileParser::GetStreamOffset(uint32 aStreamNo, uint32& arSampleSize, uint32& arOffset) 561 { 562 uint32 startOffset = 0; 563 arOffset = 0; 564 bool foundOffset = false; 565 566 if (iStreamSampleOffset.size() == 0) 567 { 568 uint32 numstreams = GetNumStreams(); 569 startOffset = iMovieChunkStartOffset; 570 571 for (uint32 ii = 0; ii < numstreams; ii++) 572 { 573 iStreamSampleOffset.push_back(startOffset); 574 } 575 } 576 else 577 { 578 startOffset = iStreamSampleOffset[aStreamNo]; 579 } 580 581 ipFilePtr->Seek(startOffset, Oscl_File::SEEKSET); 582 uint32 currentFileOffset = startOffset; 583 584 uint32 endOfdataPosition = iMovieChunkStartOffset + iMovieChunkSize; 585 586 while (currentFileOffset < endOfdataPosition) 587 { 588 uint32 data = 0; 589 if (PV_AVI_FILE_PARSER_SUCCESS != PVAviFileParserUtils::read32(ipFilePtr, data)) 590 { 591 PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: Read Error")); 592 return PV_AVI_FILE_PARSER_READ_ERROR; 593 } 594 595 int32 strNo = PVAviFileParserUtils::GetStreamNumber(data); 596 if (PV_AVI_FILE_PARSER_ERROR_UNKNOWN == strNo) 597 { 598 PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: Wrong Stream No")); 599 return PV_AVI_FILE_PARSER_ERROR_WRONG_STREAM_NUM; 600 } 601 602 uint32 size = 0; 603 if (PV_AVI_FILE_PARSER_SUCCESS != PVAviFileParserUtils::read32(ipFilePtr, size, true)) 604 { 605 PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: File Read Error")); 606 return PV_AVI_FILE_PARSER_READ_ERROR; 607 } 608 609 if ((uint32)strNo == aStreamNo) 610 { 611 arOffset = ipFilePtr->Tell(); 612 iStreamSampleOffset[aStreamNo] = arOffset + size; 613 if (size > arSampleSize) 614 { 615 PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: Insufficient Buffer Size")); 616 return PV_AVI_FILE_PARSER_INSUFFICIENT_MEMORY; 617 } 618 619 arSampleSize = size; 620 foundOffset = true; 621 break; 622 } 623 else 624 { 625 ipFilePtr->Seek(size, Oscl_File::SEEKCUR); 626 foundOffset = false; 627 } 628 629 currentFileOffset = ipFilePtr->Tell(); 630 } 631 632 if (foundOffset) 633 { 634 return PV_AVI_FILE_PARSER_SUCCESS; 635 } 636 else 637 { 638 return PV_AVI_FILE_PARSER_NO_OFFSET_FOUND; 639 } 640 } 641 642 OSCL_EXPORT_REF void PVAviFileParser::Reset() 643 { 644 PVAVIFILE_LOGINFO((0, "PVAviFileParser::Reset")); 645 646 uint32 ii = 0; 647 for (ii = 0; ii < GetNumStreams(); ii++) 648 { 649 iStreamSampleCount[ii] = 0; 650 } 651 652 if (iStreamSampleOffset.size() > 0) 653 { 654 for (ii = 0; ii < iStreamSampleOffset.size(); ii++) 655 { 656 iStreamSampleOffset.pop_back(); 657 } 658 } 659 660 iSampleOffset = iMovieChunkStartOffset; 661 iTimeStampAudio = 0; 662 } 663 664 OSCL_EXPORT_REF void PVAviFileParser::Reset(uint32 aStreamNo) 665 { 666 PVAVIFILE_LOGINFO((0, "PVAviFileParser::Reset stream")); 667 668 iStreamSampleCount[aStreamNo] = 0; 669 670 if (iStreamSampleOffset.size() > aStreamNo) 671 { 672 iStreamSampleOffset[aStreamNo] = iMovieChunkStartOffset; 673 } 674 675 if (oscl_strstr(GetStreamMimeType(aStreamNo).get_str(), "audio")) 676 { 677 iTimeStampAudio = 0; 678 } 679 } 680 681 OSCL_EXPORT_REF bool PVAviFileParser::GetFormatSpecificInfo(uint32 aStreamNum, OsclRefCounterMemFrag& arFormatSpecificDataFrag) 682 { 683 uint8* buff = NULL; 684 uint32 len = 0; 685 686 ipFileHeader->GetFormatSpecificInfo(aStreamNum, buff, len); 687 688 if ((buff == NULL) || (len == 0)) 689 { 690 return false; 691 } 692 693 OsclMemAllocDestructDealloc<uint8> my_alloc; 694 OsclRefCounter* my_refcnt; 695 696 uint aligned_refcnt_size = 697 oscl_mem_aligned_size(sizeof(OsclRefCounterSA< OsclMemAllocDestructDealloc<uint8> >)); 698 699 uint8* my_ptr = NULL; 700 int32 errcode = 0; 701 OSCL_TRY(errcode, my_ptr = (uint8*) oscl_malloc(aligned_refcnt_size + len)); 702 703 if (errcode != OsclErrNone) 704 { 705 return false; 706 } 707 708 my_refcnt = OSCL_PLACEMENT_NEW(my_ptr, OsclRefCounterSA< OsclMemAllocDestructDealloc<uint8> >(my_ptr)); 709 my_ptr += aligned_refcnt_size; 710 711 oscl_memcpy(my_ptr, buff, len); 712 713 OsclMemoryFragment memfrag; 714 memfrag.len = len; 715 memfrag.ptr = my_ptr; 716 717 OsclRefCounterMemFrag refcntMemFrag(memfrag, my_refcnt, memfrag.len); 718 arFormatSpecificDataFrag = refcntMemFrag; 719 return true; 720 721 } 722 723 //method to get codec specific info 724 OSCL_EXPORT_REF bool PVAviFileParser::GetCodecSpecificData(uint32 aStreamNum, OsclRefCounterMemFrag& arFormatSpecificDataFrag) 725 { 726 uint8* buff = NULL; 727 uint32 len = 0; 728 ipFileHeader->GetCodecSpecificData(aStreamNum, buff, len); 729 730 if ((buff == NULL) || (len == 0)) 731 { 732 return false; 733 } 734 735 OsclMemAllocDestructDealloc<uint8> my_alloc; 736 OsclRefCounter* my_refcnt; 737 738 uint aligned_refcnt_size = 739 oscl_mem_aligned_size(sizeof(OsclRefCounterSA< OsclMemAllocDestructDealloc<uint8> >)); 740 741 uint8* my_ptr = NULL; 742 int32 errcode = 0; 743 OSCL_TRY(errcode, my_ptr = (uint8*) oscl_malloc(aligned_refcnt_size + len)); 744 745 if (errcode != OsclErrNone) 746 { 747 return false; 748 } 749 750 my_refcnt = OSCL_PLACEMENT_NEW(my_ptr, OsclRefCounterSA< OsclMemAllocDestructDealloc<uint8> >(my_ptr)); 751 my_ptr += aligned_refcnt_size; 752 753 oscl_memcpy(my_ptr, buff, len); 754 755 OsclMemoryFragment memfrag; 756 memfrag.len = len; 757 memfrag.ptr = my_ptr; 758 759 OsclRefCounterMemFrag refcntMemFrag(memfrag, my_refcnt, memfrag.len); 760 arFormatSpecificDataFrag = refcntMemFrag; 761 return true; 762 } 763 764 PVAviFileParser::~PVAviFileParser() 765 { 766 if (NULL != ipFileHeader) 767 { 768 OSCL_DELETE(ipFileHeader); 769 ipFileHeader = NULL; 770 } 771 772 if (NULL != ipIdxChunk) 773 { 774 OSCL_DELETE(ipIdxChunk); 775 ipIdxChunk = NULL; 776 } 777 778 if (ipFilePtr->IsOpen()) 779 { 780 ipFilePtr->Close(); 781 } 782 783 OSCL_DELETE(ipFilePtr); 784 } 785 786 uint32 PVAviFileParser::GetFileSuggestedBufferSize() 787 { 788 uint32 buffSz = ipFileHeader->GetFileSuggestedBufferSize(); 789 if (0 == buffSz) 790 { 791 uint32 numStr = ipFileHeader->GetNumStreams(); 792 for (uint32 ii = 0; ii < numStr; ii++) 793 { 794 uint32 strSz = ipFileHeader->GetStreamSuggestedBufferSize(ii); 795 if (buffSz < strSz) 796 { 797 buffSz = strSz; 798 } 799 } 800 } 801 return buffSz; 802 } 803 804 bool PVAviFileParser::GetVideoFormatType(uint8* aHdlr, uint32& arSize, uint32 aStreamNo) 805 { 806 uint32 numstr = GetNumStreams(); 807 uint32 ii = 0; 808 bool retTyp = false; 809 for (ii = 0; ii < numstr; ii++) 810 { 811 if ((oscl_strstr((GetStreamMimeType(ii)).get_cstr(), "video")) && (aStreamNo == ii)) 812 { 813 ipFileHeader->GetHandlerType(ii, aHdlr, arSize); 814 retTyp = true; 815 } 816 } 817 return retTyp; 818 } 819 820 OSCL_EXPORT_REF Oscl_Vector<uint32, OsclMemAllocator> PVAviFileParser::GetAudioStreamCountList() 821 { 822 uint32 ii = 0; 823 Oscl_Vector<uint32, OsclMemAllocator> audioStrNum; 824 for (ii = 0; ii < GetNumStreams(); ii++) 825 { 826 if (oscl_strstr((GetStreamMimeType(ii)).get_cstr(), "audio")) 827 { 828 audioStrNum.push_back(ii); 829 } 830 } 831 832 return audioStrNum; 833 } 834 835 OSCL_EXPORT_REF Oscl_Vector<uint32, OsclMemAllocator> PVAviFileParser::GetVideoStreamCountList() 836 { 837 uint32 ii = 0; 838 Oscl_Vector<uint32, OsclMemAllocator> vidStrNum; 839 for (ii = 0; ii < GetNumStreams(); ii++) 840 { 841 if (oscl_strstr((GetStreamMimeType(ii)).get_cstr(), "video")) 842 { 843 vidStrNum.push_back(ii); 844 } 845 } 846 847 return vidStrNum; 848 } 849 850 OSCL_EXPORT_REF uint32 PVAviFileParser::GetFileDuration() 851 { 852 uint32 frameDuration = ipFileHeader->GetFrameDuration(); 853 uint32 totalFrames = ipFileHeader->GetTotalFrames(); 854 uint32 fileDuration = (uint32)((OsclFloat)(frameDuration * totalFrames) / 1000000.0); //in seconds 855 return fileDuration; 856 } 857 858 OSCL_EXPORT_REF PVAviFileStreamHeaderStruct 859 PVAviFileParser::GetStreamHeaderStruct(uint32 aStreamNum) 860 { 861 return (ipFileHeader->GetStreamHeaderStruct(aStreamNum)); 862 } 863 864 OSCL_EXPORT_REF uint32 PVAviFileParser::GetNumStreams() 865 { 866 return (ipFileHeader->GetNumStreams()); 867 } 868 869 OSCL_EXPORT_REF OSCL_HeapString<OsclMemAllocator> 870 PVAviFileParser::GetStreamMimeType(uint32 aStreamNum) 871 { 872 return (ipFileHeader->GetStreamMimeType(aStreamNum)); 873 } 874 875 OSCL_EXPORT_REF uint32 PVAviFileParser::GetWidth(int32 aStreamNo) 876 { 877 return (ipFileHeader->GetWidth(aStreamNo)); 878 } 879 880 OSCL_EXPORT_REF uint32 PVAviFileParser::GetHeight(bool& rBottomUp, int32 aStreamNo) 881 { 882 return (ipFileHeader->GetHeight(rBottomUp, aStreamNo)); 883 } 884 885 OSCL_EXPORT_REF uint32 PVAviFileParser::GetFrameDuration() 886 { 887 return (ipFileHeader->GetFrameDuration()); 888 } 889 890 OSCL_EXPORT_REF OsclFloat PVAviFileParser::GetFrameRate(uint32 aStreamNum) 891 { 892 return (ipFileHeader->GetSamplingRate(aStreamNum)); 893 } 894 895 OSCL_EXPORT_REF uint32 PVAviFileParser::GetStreamDuration(uint32 aStreamNum) 896 { 897 return (ipFileHeader->GetStreamDuration(aStreamNum)); 898 } 899