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 19 /*********************************************************************************/ 20 /* ------------------------------------------------------------------- */ 21 /* MPEG-4 Mpeg4File Class */ 22 /* ------------------------------------------------------------------- */ 23 /*********************************************************************************/ 24 /* 25 The Mpeg4File Class is the class that will construct and maintain all the 26 mecessary data structures to be able to render a valid MP4 file to disk. 27 Format. 28 */ 29 30 31 #define IMPLEMENT_Mpeg4File 32 33 #include "oscl_int64_utils.h" 34 35 #ifndef MPEG4FILE_H_INCLUDED 36 #include "mpeg4file.h" 37 #endif 38 39 #include "atomdefs.h" 40 #include "atomutils.h" 41 #include "filetypeatom.h" 42 #include "oscl_utf8conv.h" 43 #include "oscl_string.h" 44 #include "oscl_snprintf.h" 45 #include "amrdecoderspecificinfo.h" 46 #include "h263decoderspecificinfo.h" 47 #include "media_clock_converter.h" 48 49 typedef Oscl_Vector<TrackAtom*, OsclMemAllocator> trackAtomVecType; 50 typedef Oscl_Vector<MovieFragmentAtom*, OsclMemAllocator> movieFragmentAtomVecType; 51 typedef Oscl_Vector<uint32, OsclMemAllocator> movieFragmentOffsetVecType; 52 typedef Oscl_Vector<TrackDurationInfo*, OsclMemAllocator> trackDurationInfoVecType; 53 typedef Oscl_Vector<MovieFragmentRandomAccessAtom*, OsclMemAllocator> movieFragmentRandomAccessAtomVecType; 54 55 // Stream-in Constructor 56 Mpeg4File::Mpeg4File(MP4_FF_FILE *fp, 57 OSCL_wString& filename, 58 uint32 parsingMode) 59 { 60 61 _pmovieAtom = NULL; 62 _puserDataAtom = NULL; 63 _pFileTypeAtom = NULL; 64 _pMovieFragmentAtom = NULL; 65 _mp4ErrorCode = EVERYTHING_FINE; 66 _isMovieFragmentsPresent = false; 67 _pointerMovieAtomEnd = 0; 68 _movieFragmentFilePtr = NULL; 69 _pMovieFragmentAtomVec = NULL; 70 _pMfraOffsetAtom = NULL; 71 _pMovieFragmentRandomAccessAtomVec = NULL; 72 _pTrackExtendsAtomVec = NULL; 73 _pMoofOffsetVec = NULL; 74 _ptrMoofEnds = 0; 75 _parsing_mode = parsingMode; 76 _pTrackDurationContainer = NULL; 77 oMfraFound = false; 78 _oVideoTrackPresent = false; 79 parseMoofCompletely = true; 80 isResetPlayBackCalled = false; 81 82 parseMoofCompletely = true; 83 moofParsingCompleted = true; 84 moofSize = 0; 85 moofType = UNKNOWN_ATOM; 86 moofCount = 0; 87 moofPtrPos = 0; 88 currMoofNum = 0; 89 countOfTrunsParsed = 0; 90 91 // Create miscellaneous vector of atoms 92 PV_MP4_FF_NEW(fp->auditCB, trackAtomVecType, (), _pTrackAtomVec); 93 PV_MP4_FF_NEW(fp->auditCB, movieFragmentAtomVecType, (), _pMovieFragmentAtomVec); 94 PV_MP4_FF_NEW(fp->auditCB, movieFragmentOffsetVecType, (), _pMoofOffsetVec); 95 PV_MP4_FF_NEW(fp->auditCB, movieFragmentRandomAccessAtomVecType, (), _pMovieFragmentRandomAccessAtomVec); 96 PV_MP4_FF_NEW(fp->auditCB, PVID3ParCom, (), _pID3Parser); 97 98 99 iLogger = PVLogger::GetLoggerObject("mp4ffparser"); 100 iStateVarLogger = PVLogger::GetLoggerObject("mp4ffparser_mediasamplestats"); 101 iParsedDataLogger = PVLogger::GetLoggerObject("mp4ffparser_parseddata"); 102 103 _success = true; // Initial state 104 105 int32 fileSize; 106 int32 filePointer; 107 filePointer = AtomUtils::getCurrentFilePosition(fp); 108 uint32 fsize = 0; 109 AtomUtils::getCurrentFileSize(fp, fsize); 110 fileSize = (int32)fsize; 111 112 _oPVContent = false; 113 _oPVContentDownloadable = false; 114 _commonFilePtr = NULL; 115 _fileSize = fsize; 116 117 int32 count = fileSize - filePointer;// -DEFAULT_ATOM_SIZE; 118 119 //top level moov, mdat, udat 120 while (count > 0) 121 { 122 // Read in atoms until reach end of file 123 //there is a case that next atom is valid, but not in top level 124 //so only check top level now 125 uint32 atomType = UNKNOWN_ATOM; 126 uint32 atomSize = 0; 127 128 AtomUtils::getNextAtomType(fp, atomSize, atomType); 129 130 if ((atomType == SKIP_ATOM) 131 || (atomType == FREE_SPACE_ATOM) 132 || (atomType == UUID_ATOM) 133 || (atomType == UNKNOWN_ATOM) 134 || (atomType == MEDIA_DATA_ATOM)) 135 { 136 if (atomSize == 1) 137 { 138 uint64 largeSize = 0; 139 AtomUtils::read64(fp, largeSize); 140 uint32 size = 141 Oscl_Int64_Utils::get_uint64_lower32(largeSize); 142 count -= size; 143 size -= 8; //for large size 144 size -= DEFAULT_ATOM_SIZE; 145 AtomUtils::seekFromCurrPos(fp, size); 146 } 147 else 148 { 149 if (atomSize < DEFAULT_ATOM_SIZE) 150 { 151 _success = false; 152 _mp4ErrorCode = ZERO_OR_NEGATIVE_ATOM_SIZE; 153 break; 154 } 155 if (count < (int32)atomSize) 156 { 157 _success = false; 158 _mp4ErrorCode = READ_FAILED; 159 break; 160 } 161 count -= atomSize; 162 atomSize -= DEFAULT_ATOM_SIZE; 163 AtomUtils::seekFromCurrPos(fp, atomSize); 164 } 165 } 166 else if (atomType == USER_DATA_ATOM) 167 { 168 //"udta" 169 // Check for 'pvmm' to see if it is "our" 'udta' atom 170 171 uint32 isPVMMAtom = AtomUtils::peekNextNthBytes(fp, 2); 172 173 if (isPVMMAtom == PVUSER_DATA_ATOM) 174 { 175 if (_puserDataAtom == NULL) 176 { 177 PV_MP4_FF_NEW(fp->auditCB, UserDataAtom, (fp, atomSize, atomType), _puserDataAtom); 178 _oPVContent = true; 179 uint32 contentType = getContentType(); 180 if (contentType == DEFAULT_AUTHORING_MODE) 181 { 182 _oPVContentDownloadable = true; 183 } 184 count -= _puserDataAtom->getSize(); 185 } 186 else 187 { 188 _success = false; 189 _mp4ErrorCode = READ_USER_DATA_ATOM_FAILED; 190 break; 191 } 192 } 193 else 194 { 195 // Skip third party user data atom 196 if (atomSize < DEFAULT_ATOM_SIZE) 197 { 198 _success = false; 199 _mp4ErrorCode = ZERO_OR_NEGATIVE_ATOM_SIZE; 200 break; 201 } 202 if (count < (int32)atomSize) 203 { 204 _success = false; 205 _mp4ErrorCode = READ_FAILED; 206 break; 207 } 208 count -= atomSize; 209 atomSize -= DEFAULT_ATOM_SIZE; 210 AtomUtils::seekFromCurrPos(fp, atomSize); 211 } 212 213 214 } 215 else if (atomType == FILE_TYPE_ATOM) 216 { 217 if (_pFileTypeAtom == NULL) 218 { 219 //"ftyp" 220 PV_MP4_FF_NEW(fp->auditCB, FileTypeAtom, (fp, atomSize, atomType), _pFileTypeAtom); 221 222 if (!_pFileTypeAtom->MP4Success()) 223 { 224 _success = false; 225 _mp4ErrorCode = READ_FILE_TYPE_ATOM_FAILED; 226 break; 227 } 228 229 uint32 majorBrand = _pFileTypeAtom->getMajorBrand(); 230 uint32 majorBrandInfo = ENoFileType; 231 uint32 compatibleBrandInfo = ENoFileType; 232 233 234 switch (majorBrand) 235 { 236 case WMF_BRAND: 237 majorBrandInfo |= EWMF; 238 break; 239 240 case BRAND_3GPP4: 241 majorBrandInfo |= E3GP4; 242 break; 243 244 case BRAND_3GPP5: 245 majorBrandInfo |= E3GP5; 246 break; 247 248 case MOBILE_MP4: 249 majorBrandInfo |= EMMP4; 250 break; 251 252 case BRAND_MP41: 253 majorBrandInfo |= EMP41; 254 break; 255 256 case BRAND_MP42: 257 majorBrandInfo |= EMP42; 258 _mp4ErrorCode = UNSUPPORTED_FILE_TYPE; 259 break; 260 261 case BRAND_ISOM: 262 majorBrandInfo |= EISOM; 263 _mp4ErrorCode = UNSUPPORTED_FILE_TYPE; 264 break; 265 266 default: 267 majorBrandInfo |= EUNKNOWN_TYPE; 268 _mp4ErrorCode = UNSUPPORTED_FILE_TYPE; 269 break; 270 } 271 272 Oscl_Vector<uint32, OsclMemAllocator> *compatibleBrandArray = 273 _pFileTypeAtom->getCompatibleBrand(); 274 275 if (compatibleBrandArray != NULL) 276 { 277 for (uint32 i = 0; i < compatibleBrandArray->size(); i++) 278 { 279 uint32 compatibleBrand = (*compatibleBrandArray)[i]; 280 281 switch (compatibleBrand) 282 { 283 case WMF_BRAND: 284 compatibleBrandInfo |= EWMF; 285 break; 286 287 case BRAND_3GPP4: 288 compatibleBrandInfo |= E3GP4; 289 break; 290 291 case BRAND_3GPP5: 292 compatibleBrandInfo |= E3GP5; 293 break; 294 295 case MOBILE_MP4: 296 compatibleBrandInfo |= EMMP4; 297 break; 298 299 case BRAND_MP41: 300 compatibleBrandInfo |= EMP41; 301 break; 302 303 case BRAND_MP42: 304 compatibleBrandInfo |= EMP42; 305 _mp4ErrorCode = UNSUPPORTED_FILE_TYPE; 306 break; 307 308 case BRAND_ISOM: 309 compatibleBrandInfo |= EISOM; 310 _mp4ErrorCode = UNSUPPORTED_FILE_TYPE; 311 break; 312 313 default: 314 compatibleBrandInfo |= EUNKNOWN_TYPE; 315 _mp4ErrorCode = UNSUPPORTED_FILE_TYPE; 316 break; 317 } 318 } 319 } 320 321 count -= _pFileTypeAtom->getSize(); 322 } 323 else 324 { 325 //multiple "ftyp" atom not allowed.skipping 326 count -= atomSize; 327 atomSize -= DEFAULT_ATOM_SIZE; 328 AtomUtils::seekFromCurrPos(fp, atomSize); 329 } 330 } 331 else if (atomType == MOVIE_ATOM) 332 { 333 334 335 //"moov" 336 if (_pmovieAtom == NULL) 337 { 338 // Only 1 movie atom allowed! 339 PV_MP4_FF_NEW(fp->auditCB, MovieAtom, 340 (fp, 341 filename, 342 atomSize, 343 atomType, 344 _oPVContent, 345 _oPVContentDownloadable, 346 parsingMode 347 ), 348 _pmovieAtom); 349 350 if (!_pmovieAtom->MP4Success()) 351 { 352 _success = false; 353 _mp4ErrorCode = _pmovieAtom->GetMP4Error(); 354 break; 355 } 356 _isMovieFragmentsPresent = _pmovieAtom->IsMovieFragmentPresent(); 357 populateTrackDurationVec(); 358 _pTrackExtendsAtomVec = _pmovieAtom->getTrackExtendsAtomVec(); 359 360 if (_isMovieFragmentsPresent) 361 { 362 atomSize -= DEFAULT_ATOM_SIZE; 363 _pointerMovieAtomEnd = AtomUtils::getCurrentFilePosition(fp); 364 _ptrMoofEnds = _pointerMovieAtomEnd; 365 OsclAny*ptr = oscl_malloc(sizeof(MP4_FF_FILE)); 366 if (ptr == NULL) 367 { 368 _success = false; 369 _mp4ErrorCode = MEMORY_ALLOCATION_FAILED; 370 return; 371 } 372 _movieFragmentFilePtr = OSCL_PLACEMENT_NEW(ptr, MP4_FF_FILE(*fp)); 373 _movieFragmentFilePtr ->_pvfile.Copy(fp->_pvfile); 374 _movieFragmentFilePtr ->_pvfile.SetCPM(fp->_pvfile.GetCPM()); 375 } 376 count -= _pmovieAtom->getSize(); 377 _scalability = _pmovieAtom->getScalability(); 378 _fileType = _pmovieAtom->getFileType(); 379 380 if (parsingMode != 0) 381 { 382 if (_isMovieFragmentsPresent) 383 { 384 parseMFRA(); 385 } 386 break; 387 } 388 if (!_isMovieFragmentsPresent) 389 { 390 //no moofs, exit the parsing loop since 391 //we are done parsing the moov atom 392 break; 393 } 394 395 396 } 397 else 398 { //after the change above, we will never hit here. 399 _success = false; 400 _mp4ErrorCode = DUPLICATE_MOVIE_ATOMS; 401 break; 402 } 403 } 404 else if (atomType == MOVIE_FRAGMENT_ATOM) 405 { 406 uint32 moofStartOffset = AtomUtils::getCurrentFilePosition(fp); 407 moofStartOffset -= DEFAULT_ATOM_SIZE; 408 _pMoofOffsetVec->push_back(moofStartOffset); 409 410 MovieFragmentAtom *pMovieFragmentAtom = NULL; 411 PV_MP4_FF_NEW(fp->auditCB, MovieFragmentAtom, (fp, atomSize, atomType, _pTrackDurationContainer, _pTrackExtendsAtomVec, parseMoofCompletely, moofParsingCompleted, countOfTrunsParsed), pMovieFragmentAtom); 412 413 if (!pMovieFragmentAtom->MP4Success()) 414 { 415 _success = false; 416 _mp4ErrorCode = pMovieFragmentAtom->GetMP4Error(); 417 break; 418 } 419 pMovieFragmentAtom->setParent(this); 420 count -= pMovieFragmentAtom->getSize(); 421 _ptrMoofEnds = AtomUtils::getCurrentFilePosition(fp); 422 _pMovieFragmentAtomVec->push_back(pMovieFragmentAtom); 423 } 424 else if (atomType == MOVIE_FRAGMENT_RANDOM_ACCESS_ATOM) 425 { 426 MovieFragmentRandomAccessAtom *pMovieFragmentRandomAccessAtom = NULL; 427 PV_MP4_FF_NEW(fp->auditCB, MovieFragmentRandomAccessAtom, (fp, atomSize, atomType), pMovieFragmentRandomAccessAtom); 428 429 if (!pMovieFragmentRandomAccessAtom->MP4Success()) 430 { 431 _success = false; 432 _mp4ErrorCode = pMovieFragmentRandomAccessAtom->GetMP4Error(); 433 break; 434 } 435 pMovieFragmentRandomAccessAtom->setParent(this); 436 count -= pMovieFragmentRandomAccessAtom->getSize(); 437 _pMovieFragmentRandomAccessAtomVec->push_back(pMovieFragmentRandomAccessAtom); 438 oMfraFound = true; 439 } 440 else 441 { 442 if (count > 0) 443 { 444 _mp4ErrorCode = READ_UNKNOWN_ATOM; 445 _success = false; 446 } 447 break; 448 } 449 } 450 451 if (_success) 452 { 453 // Check that the movie atom was in fact read in 454 if (_pmovieAtom == NULL) 455 { 456 _success = false; 457 _mp4ErrorCode = NO_MOVIE_ATOM_PRESENT; 458 } 459 else 460 { 461 // CHECK IF THERE ARE ANY VALID MEDIA TRACKS IN THE FILE 462 int32 numMediaTracks = getNumTracks(); 463 if (numMediaTracks == 0) 464 { 465 _success = false; 466 _mp4ErrorCode = NO_META_DATA_FOR_MEDIA_TRACKS; 467 } 468 if (_success) 469 { 470 uint32 bufferCapacity = AtomUtils::getFileBufferingCapacity(fp); 471 if (0 != bufferCapacity) 472 { 473 // progressive playback 474 int32* offsetList = (int32 *)oscl_malloc(sizeof(int32) * numMediaTracks); 475 if (NULL == offsetList) 476 { 477 _success = false; 478 _mp4ErrorCode = MEMORY_ALLOCATION_FAILED; 479 } 480 else 481 { 482 // get the list of track ids 483 uint32* idList = (uint32 *)oscl_malloc(sizeof(uint32) * numMediaTracks); 484 _pmovieAtom->getTrackIDList(idList, numMediaTracks); 485 486 // get the first sample file offset of each track 487 for (int32 i = 0; i < numMediaTracks; i++) 488 { 489 int32 retVal = _pmovieAtom->getOffsetByTime(idList[i], 0, &offsetList[i]); 490 if (EVERYTHING_FINE != retVal) 491 { 492 _success = false; 493 _mp4ErrorCode = retVal; 494 break; 495 } 496 } 497 // check if any of the two offsets are too far apart 498 // to coexist in the cache at the same time 499 if (_success) 500 { 501 uint32 largest = 0, temp = 0; 502 for (int i = 0; i < numMediaTracks; i++) 503 { 504 for (int j = 0; j < numMediaTracks; j++) 505 { 506 // same as abs() 507 if (offsetList[i] > offsetList[j]) 508 { 509 temp = offsetList[i] - offsetList[j]; 510 } 511 else 512 { 513 temp = offsetList[j] - offsetList[i]; 514 } 515 516 if (temp > largest) 517 { 518 largest = temp; 519 } 520 } 521 } 522 523 if (largest > bufferCapacity) 524 { 525 // the samples are not interleaved properly 526 // this clip is not authored for progressive playback 527 _success = false; 528 _mp4ErrorCode = INSUFFICIENT_BUFFER_SIZE; 529 } 530 } 531 532 oscl_free(idList); 533 } 534 535 oscl_free(offsetList); 536 } 537 } 538 } 539 } 540 541 542 // Check for any atoms that may have read past the EOF that were not 543 // already caught by any earlier error handling 544 545 if (filePointer > fileSize) 546 { 547 _mp4ErrorCode = READ_FAILED; // Read past EOF 548 _success = false; 549 } 550 551 // skip ID3 tag parsing for progressive playback for now 552 uint32 bufferCapacity = AtomUtils::getFileBufferingCapacity(fp); 553 if (0 == bufferCapacity) 554 { 555 parseID3Header(fp); 556 } 557 //Populate the title vector with all the title metadata values. 558 if (!populateMetadataVectors()) 559 { 560 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "Mpeg4File::populateTitleVector() Failed")); 561 } 562 563 } 564 565 566 PVMFStatus Mpeg4File::populateMetadataVectors() 567 { 568 if ((!populateTitleVector()) || (!populateAuthorVector() || 569 (!populateAlbumVector()) || 570 (!populateArtistVector()) || (!populateGenreVector()) || 571 (!populateYearVector()) || (!populateCopyrightVector()) || 572 (!populateCommentVector()) || (!populateDescriptionVector()) || 573 (!populateRatingVector())) 574 ) 575 { 576 return PVMFFailure; 577 } 578 579 return PVMFSuccess; 580 } 581 582 uint32 Mpeg4File::getNumTitle() 583 { 584 uint32 numTitle = 0; 585 MP4FFParserOriginalCharEnc chartype = ORIGINAL_CHAR_TYPE_UNKNOWN; 586 numTitle = getNumAssetInfoTitleAtoms(); 587 if (getPVTitle(chartype).get_size() > 0) 588 { 589 numTitle++; 590 } 591 if (getITunesTitle().get_size() > 0) 592 { 593 numTitle++; 594 } 595 PvmiKvpSharedPtrVector framevector; 596 GetID3MetaData(framevector); 597 uint32 num_frames = framevector.size(); 598 for (uint32 i = 0; i < num_frames; i++) 599 { 600 if (framevector.size() > 0) 601 { 602 if (oscl_strstr(framevector[i]->key, "title") != 0) 603 { 604 numTitle++; 605 break; 606 } 607 } 608 } 609 return numTitle; 610 } 611 612 //This function populates the Title Vector with values from Asset Info, Itunes, FullMusic and PV Proprietary Atoms. 613 PVMFStatus Mpeg4File::populateTitleVector() 614 { 615 int32 leavecode = 0, leavecode1 = 0, leavecode2 = 0; 616 int32 numTitle = getNumTitle(); 617 ReserveMemoryForValuesVector(titleValues, numTitle, leavecode); 618 ReserveMemoryForLangCodeVector(iTitleLangCode, numTitle, leavecode1); 619 OSCL_TRY(leavecode2, iTitleCharType.reserve(numTitle)); 620 MP4FFParserOriginalCharEnc charType = ORIGINAL_CHAR_TYPE_UNKNOWN; 621 if (leavecode != 0 || leavecode1 != 0 || leavecode2 != 0) 622 { 623 return PVMFFailure; 624 } 625 int32 numAssetInfoTitle = getNumAssetInfoTitleAtoms(); 626 627 628 if (numAssetInfoTitle > 0) 629 { 630 for (int32 i = 0; i < numAssetInfoTitle; i++) 631 { 632 OSCL_wHeapString<OsclMemAllocator> valuestring = getAssetInfoTitleNotice(charType, i); 633 634 titleValues.push_front(valuestring); 635 iTitleLangCode.push_front(getAssetInfoTitleLangCode(i)); 636 iTitleCharType.push_front(charType); 637 } 638 } 639 if (getPVTitle(charType).get_size() > 0) 640 { 641 OSCL_wHeapString<OsclMemAllocator> valuestring = getPVTitle(charType); 642 titleValues.push_front(valuestring); 643 iTitleLangCode.push_front(0); 644 iTitleCharType.push_front(charType); 645 } 646 if (getITunesTitle().get_size() > 0) 647 { 648 OSCL_wHeapString<OsclMemAllocator> valuestring = getITunesTitle(); 649 titleValues.push_front(valuestring); 650 iTitleLangCode.push_front(0); 651 iTitleCharType.push_front(ORIGINAL_CHAR_TYPE_UNKNOWN); 652 } 653 PvmiKvpSharedPtrVector framevector; 654 GetID3MetaData(framevector); 655 uint32 num_frames = framevector.size(); 656 for (uint32 i = 0; i < num_frames; i++) 657 { 658 if (framevector.size() > 0) 659 { 660 if (oscl_strstr(framevector[i]->key, "title") != 0) 661 { 662 uint32 len = oscl_strlen(framevector[i]->value.pChar_value); 663 oscl_memset(_id3v1Title, 0, ID3V1_STR_MAX_SIZE); 664 oscl_UTF8ToUnicode(framevector[i]->value.pChar_value, len, _id3v1Title, len*2 + 2); 665 titleValues.push_front(_id3v1Title); 666 iTitleLangCode.push_front(0); 667 iTitleCharType.push_front(ORIGINAL_CHAR_TYPE_UNKNOWN); 668 break; 669 } 670 } 671 } 672 return PVMFSuccess; 673 } 674 675 // This function returns the titles based on index value, to the parser node. 676 PVMFStatus Mpeg4File::getTitle(uint32 index, OSCL_wString& aVal, uint16& aLangCode, MP4FFParserOriginalCharEnc& aCharEncType) 677 { 678 if (index < titleValues.size()) 679 { 680 aVal = NULL; 681 aLangCode = 0; 682 aCharEncType = ORIGINAL_CHAR_TYPE_UNKNOWN; 683 aVal = titleValues[index].get_cstr(); 684 aLangCode = iTitleLangCode[index]; 685 aCharEncType = iTitleCharType[index]; 686 return PVMFSuccess; 687 } 688 return PVMFErrArgument; 689 } 690 691 uint32 Mpeg4File::getNumAuthor() 692 { 693 uint32 numAuthor = 0; 694 MP4FFParserOriginalCharEnc chartype = ORIGINAL_CHAR_TYPE_UNKNOWN; 695 numAuthor = getNumAssetInfoAuthorAtoms(); 696 697 if (getPVAuthor(chartype).get_size() > 0) 698 { 699 numAuthor++; 700 } 701 return numAuthor; 702 } 703 704 //This function populates the Author Vector with values from Asset Info and PV Proprietary Atoms. 705 PVMFStatus Mpeg4File::populateAuthorVector() 706 { 707 int32 leavecode = 0, leavecode1 = 0, leavecode2 = 0; 708 int32 numAuthor = getNumAuthor(); 709 ReserveMemoryForValuesVector(authorValues, numAuthor, leavecode); 710 ReserveMemoryForLangCodeVector(iAuthorLangCode, numAuthor, leavecode1); 711 OSCL_TRY(leavecode2, iAuthorCharType.reserve(numAuthor)); 712 MP4FFParserOriginalCharEnc charType = ORIGINAL_CHAR_TYPE_UNKNOWN; 713 if (leavecode != 0 || leavecode1 != 0 || leavecode2 != 0) 714 { 715 return PVMFFailure; 716 } 717 int32 numAssetInfoAuthor = getNumAssetInfoAuthorAtoms(); 718 if (numAssetInfoAuthor > 0) 719 { 720 for (int32 i = 0; i < numAssetInfoAuthor; i++) 721 { 722 OSCL_wHeapString<OsclMemAllocator> valuestring = getAssetInfoAuthorNotice(charType, i); 723 authorValues.push_front(valuestring); 724 iAuthorLangCode.push_front(getAssetInfoAuthorLangCode(i)); 725 iAuthorCharType.push_front(charType); 726 } 727 } 728 if (getPVAuthor(charType).get_size() > 0) 729 { 730 OSCL_wHeapString<OsclMemAllocator> valuestring = getPVAuthor(charType); 731 authorValues.push_front(valuestring); 732 iAuthorLangCode.push_front(0); 733 iAuthorCharType.push_front(charType); 734 } 735 return PVMFSuccess; 736 } 737 738 // This function returns the Author based on index value, to the parser node. 739 PVMFStatus Mpeg4File::getAuthor(uint32 index, OSCL_wString& aVal, uint16& aLangCode, MP4FFParserOriginalCharEnc& aCharEncType) 740 { 741 if (index < authorValues.size()) 742 { 743 aVal = NULL; 744 aLangCode = 0; 745 aCharEncType = ORIGINAL_CHAR_TYPE_UNKNOWN; 746 aVal = authorValues[index].get_cstr(); 747 aLangCode = iAuthorLangCode[index]; 748 aCharEncType = iAuthorCharType[index]; 749 return PVMFSuccess; 750 } 751 return PVMFErrArgument; 752 } 753 754 uint32 Mpeg4File::getNumAlbum() 755 { 756 uint32 numAlbum = 0; 757 numAlbum = getNumAssetInfoAlbumAtoms(); 758 if (getITunesAlbum().get_size() > 0) 759 { 760 numAlbum++; 761 } 762 PvmiKvpSharedPtrVector framevector; 763 GetID3MetaData(framevector); 764 uint32 num_frames = framevector.size(); 765 for (uint32 i = 0; i < num_frames; i++) 766 { 767 if (framevector.size() > 0) 768 { 769 if (oscl_strstr(framevector[i]->key, "album") != 0) 770 { 771 numAlbum++; 772 break; 773 } 774 } 775 } 776 return numAlbum; 777 } 778 779 //This function populates the Album Vector with values from Asset Info, Itunes, FullMusic Atoms. 780 PVMFStatus Mpeg4File::populateAlbumVector() 781 { 782 int32 leavecode = 0, leavecode1 = 0, leavecode2 = 0; 783 int32 numAlbum = getNumAlbum(); 784 ReserveMemoryForValuesVector(albumValues, numAlbum, leavecode); 785 ReserveMemoryForLangCodeVector(iAlbumLangCode, numAlbum, leavecode1); 786 OSCL_TRY(leavecode2, iAlbumCharType.reserve(numAlbum)); 787 MP4FFParserOriginalCharEnc charType = ORIGINAL_CHAR_TYPE_UNKNOWN; 788 if (leavecode != 0 || leavecode1 != 0 || leavecode2 != 0) 789 { 790 return PVMFFailure; 791 } 792 int32 numAssetInfoAlbum = getNumAssetInfoAlbumAtoms(); 793 if (numAssetInfoAlbum > 0) 794 { 795 for (int32 i = 0; i < numAssetInfoAlbum; i++) 796 { 797 OSCL_wHeapString<OsclMemAllocator> valuestring = getAssetInfoAlbumNotice(charType, i); 798 albumValues.push_front(valuestring); 799 iAlbumLangCode.push_front(getAssetInfoAlbumLangCode(i)); 800 iAlbumCharType.push_front(charType); 801 } 802 } 803 if (getITunesAlbum().get_size() > 0) 804 { 805 OSCL_wHeapString<OsclMemAllocator> valuestring = getITunesAlbum(); 806 albumValues.push_front(valuestring); 807 iAlbumLangCode.push_front(0); 808 iAlbumCharType.push_front(ORIGINAL_CHAR_TYPE_UNKNOWN); 809 } 810 PvmiKvpSharedPtrVector framevector; 811 GetID3MetaData(framevector); 812 uint32 num_frames = framevector.size(); 813 for (uint32 i = 0; i < num_frames; i++) 814 { 815 if (framevector.size() > 0) 816 { 817 if (oscl_strstr(framevector[i]->key, "album") != 0) 818 { 819 uint32 len = oscl_strlen(framevector[i]->value.pChar_value); 820 oscl_memset(_id3v1Album, 0, ID3V1_STR_MAX_SIZE); 821 oscl_UTF8ToUnicode(framevector[i]->value.pChar_value, len, _id3v1Album, len*2 + 2); 822 albumValues.push_front(_id3v1Album); 823 iAlbumLangCode.push_front(0); 824 iAlbumCharType.push_front(ORIGINAL_CHAR_TYPE_UNKNOWN); 825 break; 826 } 827 } 828 } 829 830 return PVMFSuccess; 831 } 832 833 // This function returns the Album based on index value, to the parser node. 834 PVMFStatus Mpeg4File::getAlbum(uint32 index, OSCL_wString& aVal, uint16& aLangCode, MP4FFParserOriginalCharEnc& aCharEncType) 835 { 836 if (index < albumValues.size()) 837 { 838 aVal = NULL; 839 aLangCode = 0; 840 aCharEncType = ORIGINAL_CHAR_TYPE_UNKNOWN; 841 aVal = albumValues[index].get_cstr(); 842 aLangCode = iAlbumLangCode[index]; 843 aCharEncType = iAlbumCharType[index]; 844 return PVMFSuccess; 845 } 846 return PVMFErrArgument; 847 } 848 849 uint32 Mpeg4File::getNumArtist() 850 { 851 uint32 numArtist = 0; 852 numArtist = getNumAssetInfoPerformerAtoms(); 853 854 if (getITunesArtist().get_size() > 0) 855 { 856 numArtist++; 857 } 858 if (getITunesAlbumArtist().get_size() > 0) //AlbumArtist 859 { 860 numArtist++; 861 } 862 863 PvmiKvpSharedPtrVector framevector; 864 GetID3MetaData(framevector); 865 uint32 num_frames = framevector.size(); 866 for (uint32 i = 0; i < num_frames; i++) 867 { 868 if (framevector.size() > 0) 869 { 870 if (oscl_strstr(framevector[i]->key, "artist") != 0) 871 { 872 numArtist++; 873 break; 874 } 875 } 876 } 877 return numArtist; 878 } 879 880 881 //This function populates the Artist Vector with values from Asset Info, Itunes, FullMusic Atoms. 882 PVMFStatus Mpeg4File::populateArtistVector() 883 { 884 int32 leavecode = 0, leavecode1 = 0, leavecode2 = 0; 885 int32 numArtist = getNumArtist(); 886 ReserveMemoryForValuesVector(artistValues, numArtist, leavecode); 887 ReserveMemoryForLangCodeVector(iArtistLangCode, numArtist, leavecode1); 888 OSCL_TRY(leavecode2, iArtistCharType.reserve(numArtist)); 889 MP4FFParserOriginalCharEnc charType = ORIGINAL_CHAR_TYPE_UNKNOWN; 890 if (leavecode != 0 || leavecode1 != 0 || leavecode2 != 0) 891 { 892 return PVMFFailure; 893 } 894 int32 numAssetInfoPerformer = getNumAssetInfoPerformerAtoms(); 895 if (numAssetInfoPerformer > 0) 896 { 897 for (int32 i = 0; i < numAssetInfoPerformer; i++) 898 { 899 OSCL_wHeapString<OsclMemAllocator> valuestring = getAssetInfoPerformerNotice(charType, i); 900 artistValues.push_front(valuestring); 901 iArtistLangCode.push_front(getAssetInfoPerformerLangCode(i)); 902 iArtistCharType.push_front(charType); 903 } 904 } 905 if (getITunesArtist().get_size() > 0) 906 { 907 OSCL_wHeapString<OsclMemAllocator> valuestring = getITunesArtist(); 908 artistValues.push_front(valuestring); 909 iArtistLangCode.push_front(0); 910 iArtistCharType.push_front(ORIGINAL_CHAR_TYPE_UNKNOWN); 911 } 912 if (getITunesAlbumArtist().get_size() > 0) //AlbumArtist 913 { 914 OSCL_wHeapString<OsclMemAllocator> valuestring = getITunesAlbumArtist(); 915 artistValues.push_front(valuestring); 916 iArtistLangCode.push_front(0); 917 iArtistCharType.push_front(ORIGINAL_CHAR_TYPE_UNKNOWN); 918 } 919 PvmiKvpSharedPtrVector framevector; 920 GetID3MetaData(framevector); 921 uint32 num_frames = framevector.size(); 922 for (uint32 i = 0; i < num_frames; i++) 923 { 924 if (framevector.size() > 0) 925 { 926 if (oscl_strstr(framevector[i]->key, "artist") != 0) 927 { 928 uint32 len = oscl_strlen(framevector[i]->value.pChar_value); 929 oscl_memset(_id3v1Artist, 0, ID3V1_STR_MAX_SIZE); 930 oscl_UTF8ToUnicode(framevector[i]->value.pChar_value, len, _id3v1Artist, len*2 + 2); 931 artistValues.push_front(_id3v1Artist); 932 iArtistLangCode.push_front(0); 933 iArtistCharType.push_front(ORIGINAL_CHAR_TYPE_UNKNOWN); 934 break; 935 } 936 } 937 } 938 return PVMFSuccess; 939 } 940 941 // This function returns the Artists based on index value, to the parser node. 942 PVMFStatus Mpeg4File::getArtist(uint32 index, OSCL_wString& aVal, uint16& aLangCode, MP4FFParserOriginalCharEnc& aCharEncType) 943 { 944 if (index < artistValues.size()) 945 { 946 aVal = NULL; 947 aLangCode = 0; 948 aCharEncType = ORIGINAL_CHAR_TYPE_UNKNOWN; 949 aVal = artistValues[index].get_cstr(); 950 aLangCode = iArtistLangCode[index]; 951 aCharEncType = iArtistCharType[index]; 952 return PVMFSuccess; 953 } 954 return PVMFErrArgument; 955 } 956 957 uint32 Mpeg4File::getNumGenre() 958 { 959 uint32 numGenre = 0; 960 numGenre = getNumAssetInfoGenreAtoms(); 961 962 if (getITunesGnreString().get_size() > 0) 963 { 964 numGenre++; 965 } 966 if (getITunesGnreID() > 0) 967 { 968 numGenre++; 969 } 970 return numGenre; 971 } 972 973 //This function populates the Genre Vector with values from Asset Info, Itunes, FullMusic Atoms. 974 PVMFStatus Mpeg4File::populateGenreVector() 975 { 976 int32 leavecode = 0, leavecode1 = 0, leavecode2 = 0; 977 int32 numGenre = getNumGenre(); 978 ReserveMemoryForValuesVector(genreValues, numGenre, leavecode); 979 ReserveMemoryForLangCodeVector(iGenreLangCode, numGenre, leavecode1); 980 OSCL_TRY(leavecode2, iGenreCharType.reserve(numGenre)); 981 MP4FFParserOriginalCharEnc charType = ORIGINAL_CHAR_TYPE_UNKNOWN; 982 if (leavecode != 0 || leavecode1 != 0 || leavecode2 != 0) 983 { 984 return PVMFFailure; 985 } 986 int32 numAssetInfoGenre = getNumAssetInfoGenreAtoms(); 987 if (numAssetInfoGenre > 0) 988 { 989 for (int32 i = 0; i < numAssetInfoGenre; i++) 990 { 991 OSCL_wHeapString<OsclMemAllocator> valuestring = getAssetInfoGenreNotice(charType, i); 992 genreValues.push_front(valuestring); 993 iGenreLangCode.push_front(getAssetInfoGenreLangCode(i)); 994 iGenreCharType.push_front(charType); 995 } 996 } 997 if (getITunesGnreString().get_size() > 0) 998 { 999 OSCL_wHeapString<OsclMemAllocator> valuestring = getITunesGnreString(); 1000 genreValues.push_front(valuestring); 1001 iGenreLangCode.push_front(0); 1002 iGenreCharType.push_front(ORIGINAL_CHAR_TYPE_UNKNOWN); 1003 } 1004 return PVMFSuccess; 1005 } 1006 1007 // This function returns the Genres based on index value, to the parser node. 1008 PVMFStatus Mpeg4File::getGenre(uint32 index, OSCL_wString& aVal, uint16& aLangCode, MP4FFParserOriginalCharEnc& aCharEncType) 1009 { 1010 if (index < genreValues.size()) 1011 { 1012 aVal = NULL; 1013 aLangCode = 0; 1014 aCharEncType = ORIGINAL_CHAR_TYPE_UNKNOWN; 1015 aVal = genreValues[index].get_cstr(); 1016 aLangCode = iGenreLangCode[index]; 1017 aCharEncType = iGenreCharType[index]; 1018 return PVMFSuccess; 1019 } 1020 return PVMFErrArgument; 1021 } 1022 1023 1024 uint32 Mpeg4File::getNumCopyright() 1025 { 1026 uint32 numCopyright = 0; 1027 MP4FFParserOriginalCharEnc chartype = ORIGINAL_CHAR_TYPE_UNKNOWN; 1028 numCopyright = getNumCopyRightAtoms(); 1029 if (getPVCopyright(chartype).get_size() > 0) 1030 { 1031 numCopyright++; 1032 } 1033 if (getITunesCopyright().get_size() > 0) 1034 { 1035 numCopyright++; 1036 } 1037 return numCopyright; 1038 } 1039 1040 1041 //This function populates the Copyright Vector with values from Asset Info, Itunes and PV Proprietary Atoms. 1042 PVMFStatus Mpeg4File::populateCopyrightVector() 1043 { 1044 int32 leavecode = 0, leavecode1 = 0, leavecode2 = 0; 1045 int32 numCopyright = getNumCopyright(); 1046 ReserveMemoryForValuesVector(copyrightValues, numCopyright, leavecode); 1047 ReserveMemoryForLangCodeVector(iCopyrightLangCode, numCopyright, leavecode1); 1048 OSCL_TRY(leavecode2, iCopyrightCharType.reserve(numCopyright)); 1049 MP4FFParserOriginalCharEnc charType = ORIGINAL_CHAR_TYPE_UNKNOWN; 1050 if (leavecode != 0 || leavecode1 != 0 || leavecode2 != 0) 1051 { 1052 return PVMFFailure; 1053 } 1054 int32 numAssetInfoCopyright = getNumCopyRightAtoms(); 1055 if (numAssetInfoCopyright > 0) 1056 { 1057 for (int32 i = 0; i < numAssetInfoCopyright; i++) 1058 { 1059 OSCL_wHeapString<OsclMemAllocator> valuestring = getCopyRightString(charType, i); 1060 copyrightValues.push_front(valuestring); 1061 iCopyrightLangCode.push_front(getCopyRightLanguageCode(i)); 1062 iCopyrightCharType.push_front(charType); 1063 } 1064 } 1065 if (getPVCopyright(charType).get_size() > 0) 1066 { 1067 OSCL_wHeapString<OsclMemAllocator> valuestring = getPVCopyright(charType); 1068 copyrightValues.push_front(valuestring); 1069 iCopyrightLangCode.push_front(0); 1070 iCopyrightCharType.push_front(charType); 1071 } 1072 if (getITunesCopyright().get_size() > 0) 1073 { 1074 OSCL_wHeapString<OsclMemAllocator> valuestring = getITunesCopyright(); 1075 copyrightValues.push_front(valuestring); 1076 iCopyrightLangCode.push_front(0); 1077 iCopyrightCharType.push_front(ORIGINAL_CHAR_TYPE_UNKNOWN); 1078 } 1079 return PVMFSuccess; 1080 } 1081 1082 // This function returns the Copyrights based on index value, to the parser node. 1083 PVMFStatus Mpeg4File::getCopyright(uint32 index, OSCL_wString& aVal, uint16& aLangCode, MP4FFParserOriginalCharEnc& aCharEncType) 1084 { 1085 if (index < copyrightValues.size()) 1086 { 1087 aVal = NULL; 1088 aLangCode = 0; 1089 aCharEncType = ORIGINAL_CHAR_TYPE_UNKNOWN; 1090 aVal = copyrightValues[index].get_cstr(); 1091 aLangCode = iCopyrightLangCode[index]; 1092 aCharEncType = iCopyrightCharType[index]; 1093 return PVMFSuccess; 1094 } 1095 return PVMFErrArgument; 1096 } 1097 1098 1099 uint32 Mpeg4File::getNumComment() 1100 { 1101 uint32 numComment = 0; 1102 1103 1104 if (getITunesComment().get_size() > 0) 1105 { 1106 numComment++; 1107 } 1108 PvmiKvpSharedPtrVector framevector; 1109 GetID3MetaData(framevector); 1110 uint32 num_frames = framevector.size(); 1111 for (uint32 i = 0; i < num_frames; i++) 1112 { 1113 if (framevector.size() > 0) 1114 { 1115 if (oscl_strstr(framevector[i]->key, "comment") != 0) 1116 { 1117 numComment++; 1118 break; 1119 } 1120 } 1121 } 1122 1123 return numComment; 1124 } 1125 1126 1127 //This function populates the Comment Vector with values from Itunes, FullMusic Atoms. 1128 PVMFStatus Mpeg4File::populateCommentVector() 1129 { 1130 int32 leavecode = 0, leavecode1 = 0, leavecode2 = 0; 1131 int32 numComment = getNumComment(); 1132 ReserveMemoryForValuesVector(commentValues, numComment, leavecode); 1133 ReserveMemoryForLangCodeVector(iCommentLangCode, numComment, leavecode1); 1134 OSCL_TRY(leavecode2, iCommentCharType.reserve(numComment)); 1135 if (leavecode != 0 || leavecode1 != 0 || leavecode2 != 0) 1136 { 1137 return PVMFFailure; 1138 } 1139 1140 if (getITunesComment().get_size() > 0) 1141 { 1142 OSCL_wHeapString<OsclMemAllocator> valuestring = getITunesComment(); 1143 commentValues.push_front(valuestring); 1144 iCommentLangCode.push_front(0); 1145 iCommentCharType.push_front(ORIGINAL_CHAR_TYPE_UNKNOWN); 1146 } 1147 PvmiKvpSharedPtrVector framevector; 1148 GetID3MetaData(framevector); 1149 uint32 num_frames = framevector.size(); 1150 for (uint32 i = 0; i < num_frames; i++) 1151 { 1152 if (framevector.size() > 0) 1153 { 1154 if (oscl_strstr(framevector[i]->key, "comment") != 0) 1155 { 1156 uint32 len = oscl_strlen(framevector[i]->value.pChar_value); 1157 oscl_memset(_id3v1Comment, 0, ID3V1_STR_MAX_SIZE); 1158 oscl_UTF8ToUnicode(framevector[i]->value.pChar_value, len, _id3v1Comment, len*2 + 2); 1159 commentValues.push_front(_id3v1Comment); 1160 iCommentLangCode.push_front(0); 1161 iCommentCharType.push_front(ORIGINAL_CHAR_TYPE_UNKNOWN); 1162 break; 1163 } 1164 } 1165 } 1166 1167 return PVMFSuccess; 1168 } 1169 1170 // This function returns the Comments based on index value, to the parser node. 1171 PVMFStatus Mpeg4File::getComment(uint32 index, OSCL_wString& aVal, uint16& aLangCode, MP4FFParserOriginalCharEnc& aCharEncType) 1172 { 1173 if (index < commentValues.size()) 1174 { 1175 aVal = NULL; 1176 aLangCode = 0; 1177 aCharEncType = ORIGINAL_CHAR_TYPE_UNKNOWN; 1178 aVal = commentValues[index].get_cstr(); 1179 aLangCode = iCommentLangCode[index]; 1180 aCharEncType = iCommentCharType[index]; 1181 return PVMFSuccess; 1182 } 1183 return PVMFErrArgument; 1184 } 1185 1186 1187 uint32 Mpeg4File::getNumDescription() 1188 { 1189 uint32 numDescription = 0; 1190 MP4FFParserOriginalCharEnc chartype = ORIGINAL_CHAR_TYPE_UNKNOWN; 1191 numDescription = getNumAssetInfoDescAtoms(); 1192 if (getPVDescription(chartype).get_size() > 0) 1193 { 1194 numDescription++; 1195 } 1196 if (getITunesDescription().get_size() > 0) 1197 { 1198 numDescription++; 1199 } 1200 1201 return numDescription; 1202 } 1203 1204 1205 //This function populates the Description Vector with values from Asset Info, Itunes and PV Proprietary Atoms. 1206 PVMFStatus Mpeg4File::populateDescriptionVector() 1207 { 1208 int32 leavecode = 0, leavecode1 = 0, leavecode2 = 0; 1209 int32 numDescription = getNumDescription(); 1210 ReserveMemoryForValuesVector(descriptionValues, numDescription, leavecode); 1211 ReserveMemoryForLangCodeVector(iDescriptionLangCode, numDescription, leavecode1); 1212 OSCL_TRY(leavecode2, iDescriptionCharType.reserve(numDescription)); 1213 MP4FFParserOriginalCharEnc charType = ORIGINAL_CHAR_TYPE_UNKNOWN; 1214 if (leavecode != 0 || leavecode1 != 0 || leavecode2 != 0) 1215 { 1216 return PVMFFailure; 1217 } 1218 int32 numAssetInfoDescription = getNumAssetInfoDescAtoms(); 1219 if (numAssetInfoDescription > 0) 1220 { 1221 for (int32 i = 0; i < numAssetInfoDescription; i++) 1222 { 1223 OSCL_wHeapString<OsclMemAllocator> valuestring = getAssetInfoDescNotice(charType, i); 1224 descriptionValues.push_front(valuestring); 1225 iDescriptionLangCode.push_front(getAssetInfoDescLangCode(i)); 1226 iDescriptionCharType.push_front(charType); 1227 } 1228 } 1229 if (getPVDescription(charType).get_size() > 0) 1230 { 1231 OSCL_wHeapString<OsclMemAllocator> valuestring = getPVDescription(charType); 1232 descriptionValues.push_front(valuestring); 1233 iDescriptionLangCode.push_front(0); 1234 iDescriptionCharType.push_front(charType); 1235 } 1236 1237 if (getITunesDescription().get_size() > 0) 1238 { 1239 OSCL_wHeapString<OsclMemAllocator> valuestring = getITunesDescription(); 1240 descriptionValues.push_front(valuestring); 1241 iDescriptionLangCode.push_front(0); 1242 iDescriptionCharType.push_front(ORIGINAL_CHAR_TYPE_UNKNOWN); 1243 } 1244 1245 return PVMFSuccess; 1246 } 1247 1248 // This function returns the Descriptions based on index value, to the parser node. 1249 PVMFStatus Mpeg4File::getDescription(uint32 index, OSCL_wString& aVal, uint16& aLangCode, MP4FFParserOriginalCharEnc& 1250 aCharEncType) 1251 { 1252 if (index < descriptionValues.size()) 1253 { 1254 aVal = NULL; 1255 aLangCode = 0; 1256 aCharEncType = ORIGINAL_CHAR_TYPE_UNKNOWN; 1257 aVal = descriptionValues[index].get_cstr(); 1258 aLangCode = iDescriptionLangCode[index]; 1259 aCharEncType = iDescriptionCharType[index]; 1260 return PVMFSuccess; 1261 } 1262 return PVMFErrArgument; 1263 } 1264 1265 1266 uint32 Mpeg4File::getNumRating() 1267 { 1268 uint32 numRating = 0; 1269 MP4FFParserOriginalCharEnc chartype = ORIGINAL_CHAR_TYPE_UNKNOWN; 1270 numRating = getNumAssetInfoRatingAtoms(); 1271 1272 if (getPVRating(chartype).get_size() > 0) 1273 { 1274 numRating++; 1275 } 1276 return numRating; 1277 } 1278 1279 1280 //This function populates the Rating Vector with values from Asset Info and PV Proprietary Atoms. 1281 PVMFStatus Mpeg4File::populateRatingVector() 1282 { 1283 int32 leavecode = 0, leavecode1 = 0, leavecode2 = 0; 1284 int32 numRating = getNumRating(); 1285 ReserveMemoryForValuesVector(ratingValues, numRating, leavecode); 1286 ReserveMemoryForLangCodeVector(iRatingLangCode, numRating, leavecode1); 1287 OSCL_TRY(leavecode2, iRatingCharType.reserve(numRating)); 1288 MP4FFParserOriginalCharEnc charType = ORIGINAL_CHAR_TYPE_UNKNOWN; 1289 if (leavecode != 0 || leavecode1 != 0 || leavecode2 != 0) 1290 { 1291 return PVMFFailure; 1292 } 1293 int32 numAssetInfoRating = getNumAssetInfoRatingAtoms(); 1294 if (numAssetInfoRating > 0) 1295 { 1296 for (int32 i = 0; i < numAssetInfoRating; i++) 1297 { 1298 OSCL_wHeapString<OsclMemAllocator> valuestring = getAssetInfoRatingNotice(charType, i); 1299 ratingValues.push_front(valuestring); 1300 iRatingLangCode.push_front(getAssetInfoRatingLangCode(i)); 1301 iRatingCharType.push_front(charType); 1302 } 1303 } 1304 if (getPVRating(charType).get_size() > 0) 1305 { 1306 OSCL_wHeapString<OsclMemAllocator> valuestring = getPVRating(charType); 1307 ratingValues.push_front(valuestring); 1308 iRatingLangCode.push_front(0); 1309 iRatingCharType.push_front(charType); 1310 } 1311 1312 return PVMFSuccess; 1313 } 1314 1315 // This function returns the Ratings based on index value, to the parser node. 1316 PVMFStatus Mpeg4File::getRating(uint32 index, OSCL_wString& aVal, uint16& aLangCode, MP4FFParserOriginalCharEnc& 1317 aCharEncType) 1318 { 1319 if (index < ratingValues.size()) 1320 { 1321 aVal = NULL; 1322 aLangCode = 0; 1323 aCharEncType = ORIGINAL_CHAR_TYPE_UNKNOWN; 1324 aVal = ratingValues[index].get_cstr(); 1325 aLangCode = iRatingLangCode[index]; 1326 aCharEncType = iRatingCharType[index]; 1327 return PVMFSuccess; 1328 } 1329 return PVMFErrArgument; 1330 } 1331 1332 1333 uint32 Mpeg4File::getNumYear() 1334 { 1335 uint32 numYear = 0; 1336 numYear = getNumAssetInfoRecordingYearAtoms(); 1337 if (getITunesYear().get_size() > 0) 1338 { 1339 numYear++; 1340 } 1341 1342 PvmiKvpSharedPtrVector framevector; 1343 GetID3MetaData(framevector); 1344 uint32 num_frames = framevector.size(); 1345 for (uint32 i = 0; i < num_frames; i++) 1346 { 1347 if (framevector.size() > 0) 1348 { 1349 if (oscl_strstr(framevector[i]->key, "year") != 0) 1350 { 1351 numYear++; 1352 break; 1353 } 1354 } 1355 } 1356 return numYear; 1357 } 1358 1359 1360 //This function populates the Year Vector with values from Asset Info, Itunes, FullMusic and PV Proprietary Atoms. 1361 PVMFStatus Mpeg4File::populateYearVector() 1362 { 1363 int32 leavecode = 0; 1364 int32 numYear = getNumYear(); 1365 OSCL_TRY(leavecode, yearValues.reserve(numYear)); 1366 1367 if (leavecode != 0) 1368 { 1369 return PVMFFailure; 1370 } 1371 int32 numAssetInfoRecordingYear = getNumAssetInfoRecordingYearAtoms(); 1372 if (numAssetInfoRecordingYear > 0) 1373 { 1374 for (int32 i = 0; i < numAssetInfoRecordingYear; i++) 1375 { 1376 uint16 valuestring = getAssetInfoRecordingYear(i); 1377 yearValues.push_front(valuestring); 1378 } 1379 } 1380 if (getITunesYear().get_size() > 0) 1381 { 1382 uint32 value, i; 1383 OSCL_wHeapString<OsclMemAllocator> values1 = getITunesYear(); 1384 char valuestring[256]; 1385 oscl_UnicodeToUTF8(values1.get_cstr(), values1.get_size(), valuestring, 256); 1386 i = PV_atoi(valuestring, 'd', value); 1387 yearValues.push_front(value); 1388 } 1389 PvmiKvpSharedPtrVector framevector; 1390 GetID3MetaData(framevector); 1391 uint32 num_frames = framevector.size(); 1392 for (uint32 i = 0; i < num_frames; i++) 1393 { 1394 if (framevector.size() > 0) 1395 { 1396 if (oscl_strstr(framevector[i]->key, "year") != 0) 1397 { 1398 PV_atoi(framevector[i]->value.pChar_value, 'd', _id3v1Year); 1399 yearValues.push_front(_id3v1Year); 1400 break; 1401 } 1402 } 1403 } 1404 1405 return PVMFSuccess; 1406 } 1407 1408 // This function returns the Years based on index value, to the parser node. 1409 PVMFStatus Mpeg4File::getYear(uint32 index, uint32& aVal) 1410 { 1411 if (index < yearValues.size()) 1412 { 1413 aVal = 0; 1414 aVal = yearValues[index]; 1415 1416 return PVMFSuccess; 1417 } 1418 return PVMFErrArgument; 1419 } 1420 OSCL_wString& Mpeg4File::getPVTitle(MP4FFParserOriginalCharEnc &charType) 1421 { 1422 PVUserDataAtom *patom = NULL; 1423 if (_puserDataAtom != NULL) 1424 { 1425 patom = 1426 (PVUserDataAtom*) _puserDataAtom->getAtomOfType(FourCharConstToUint32('p', 'v', 'm', 'm')); 1427 } 1428 else 1429 { 1430 return _emptyString; 1431 } 1432 1433 if (patom != NULL) 1434 { 1435 return patom->getPVTitle(charType); 1436 } 1437 else 1438 { 1439 return _emptyString; 1440 } 1441 } 1442 1443 OSCL_wString& Mpeg4File::getPVAuthor(MP4FFParserOriginalCharEnc &charType) 1444 { 1445 PVUserDataAtom *patom = NULL; 1446 if (_puserDataAtom != NULL) 1447 { 1448 patom = 1449 (PVUserDataAtom*) _puserDataAtom->getAtomOfType(FourCharConstToUint32('p', 'v', 'm', 'm')); 1450 } 1451 else 1452 { 1453 return _emptyString; 1454 } 1455 1456 if (patom != NULL) 1457 { 1458 return patom->getPVAuthor(charType); 1459 } 1460 else 1461 { 1462 return _emptyString; 1463 } 1464 } 1465 1466 OSCL_wString& Mpeg4File::getPVVersion(MP4FFParserOriginalCharEnc &charType) 1467 { 1468 OSCL_UNUSED_ARG(charType); 1469 1470 PVUserDataAtom *patom = NULL; 1471 if (_puserDataAtom != NULL) 1472 { 1473 patom = 1474 (PVUserDataAtom*) _puserDataAtom->getAtomOfType(FourCharConstToUint32('p', 'v', 'm', 'm')); 1475 } 1476 else 1477 { 1478 return _emptyString; 1479 } 1480 1481 if (patom != NULL) 1482 { 1483 return patom->getPVVersion(); 1484 } 1485 else 1486 { 1487 return _emptyString; 1488 } 1489 } 1490 1491 OSCL_wString& Mpeg4File::getPVCopyright(MP4FFParserOriginalCharEnc &charType) 1492 { 1493 PVUserDataAtom *patom = NULL; 1494 if (_puserDataAtom != NULL) 1495 { 1496 patom = 1497 (PVUserDataAtom*) _puserDataAtom->getAtomOfType(FourCharConstToUint32('p', 'v', 'm', 'm')); 1498 } 1499 else 1500 { 1501 return _emptyString; 1502 } 1503 1504 if (patom != NULL) 1505 { 1506 return patom->getPVCopyright(charType); 1507 } 1508 else 1509 { 1510 return _emptyString; 1511 } 1512 } 1513 1514 OSCL_wString& Mpeg4File::getPVDescription(MP4FFParserOriginalCharEnc &charType) 1515 { 1516 PVUserDataAtom *patom = NULL; 1517 if (_puserDataAtom != NULL) 1518 { 1519 patom = 1520 (PVUserDataAtom*) _puserDataAtom->getAtomOfType(FourCharConstToUint32('p', 'v', 'm', 'm')); 1521 } 1522 else 1523 { 1524 return _emptyString; 1525 } 1526 1527 if (patom != NULL) 1528 { 1529 return patom->getPVDescription(charType); 1530 } 1531 else 1532 { 1533 return _emptyString; 1534 } 1535 } 1536 1537 OSCL_wString& Mpeg4File::getPVRating(MP4FFParserOriginalCharEnc &charType) 1538 { 1539 PVUserDataAtom *patom = NULL; 1540 if (_puserDataAtom != NULL) 1541 { 1542 patom = 1543 (PVUserDataAtom*) _puserDataAtom->getAtomOfType(FourCharConstToUint32('p', 'v', 'm', 'm')); 1544 } 1545 else 1546 { 1547 return _emptyString; 1548 } 1549 1550 if (patom != NULL) 1551 { 1552 return patom->getPVRating(charType); 1553 } 1554 else 1555 { 1556 return _emptyString; 1557 } 1558 } 1559 1560 OSCL_wHeapString<OsclMemAllocator> Mpeg4File::getCreationDate(MP4FFParserOriginalCharEnc &charType) 1561 { 1562 PVUserDataAtom *patom = NULL; 1563 if (_puserDataAtom != NULL) 1564 { 1565 patom = 1566 (PVUserDataAtom*) _puserDataAtom->getAtomOfType(FourCharConstToUint32('p', 'v', 'm', 'm')); 1567 if (patom != NULL) 1568 { 1569 return patom->getPVCreationDate(charType); 1570 } 1571 else 1572 { 1573 return _emptyString; 1574 } 1575 } 1576 else 1577 { 1578 return (_pmovieAtom->getCreationDate()); 1579 } 1580 } 1581 1582 // Destructor 1583 Mpeg4File::~Mpeg4File() 1584 { 1585 uint32 i; 1586 // Clean up atoms 1587 if (_pmovieAtom != NULL) 1588 { 1589 PV_MP4_FF_DELETE(NULL, MovieAtom, _pmovieAtom); 1590 } 1591 1592 //Delete all the track atoms in the vec 1593 for (i = 0; i < _pTrackAtomVec->size(); i++) 1594 { 1595 PV_MP4_FF_DELETE(NULL, TrackAtom, (*_pTrackAtomVec)[i]); 1596 } 1597 1598 // Delete the vectors themselves 1599 PV_MP4_FF_TEMPLATED_DELETE(NULL, trackAtomVecType, Oscl_Vector, _pTrackAtomVec); 1600 1601 1602 titleValues.destroy(); 1603 iTitleLangCode.destroy(); 1604 iTitleCharType.destroy(); 1605 1606 authorValues.destroy(); 1607 iAuthorLangCode.destroy(); 1608 iAuthorCharType.destroy(); 1609 1610 1611 albumValues.destroy(); 1612 iAlbumLangCode.destroy(); 1613 iAlbumCharType.destroy(); 1614 1615 1616 artistValues.destroy(); 1617 iArtistLangCode.destroy(); 1618 iArtistCharType.destroy(); 1619 1620 1621 genreValues.destroy(); 1622 iGenreLangCode.destroy(); 1623 iGenreCharType.destroy(); 1624 1625 1626 yearValues.destroy(); 1627 1628 1629 copyrightValues.destroy(); 1630 iCopyrightLangCode.destroy(); 1631 iCopyrightCharType.destroy(); 1632 1633 1634 commentValues.destroy(); 1635 iCommentLangCode.destroy(); 1636 iCommentCharType.destroy(); 1637 1638 1639 descriptionValues.destroy(); 1640 iDescriptionLangCode.destroy(); 1641 iDescriptionCharType.destroy(); 1642 1643 1644 ratingValues.destroy(); 1645 iRatingLangCode.destroy(); 1646 iRatingCharType.destroy() ; 1647 1648 1649 //delete all movie fragments 1650 for (i = 0; i < _pMovieFragmentAtomVec->size(); i++) 1651 { 1652 PV_MP4_FF_DELETE(NULL, MovieFragmentAtom, (*_pMovieFragmentAtomVec)[i]); 1653 } 1654 PV_MP4_FF_TEMPLATED_DELETE(NULL, movieFragmentAtomVecType, Oscl_Vector, _pMovieFragmentAtomVec); 1655 //delete all movie fragments randomm access box 1656 for (i = 0; i < _pMovieFragmentRandomAccessAtomVec->size(); i++) 1657 { 1658 PV_MP4_FF_DELETE(NULL, MovieFragmentRandomAccessAtom, (*_pMovieFragmentRandomAccessAtomVec)[i]); 1659 } 1660 // Delete the vectors themselves 1661 PV_MP4_FF_TEMPLATED_DELETE(NULL, movieFragmentRandomAccessAtomVecType, Oscl_Vector, _pMovieFragmentRandomAccessAtomVec); 1662 1663 if (_pMoofOffsetVec != NULL) 1664 PV_MP4_FF_TEMPLATED_DELETE(NULL, movieFragmentOffsetVecType, Oscl_Vector, _pMoofOffsetVec); 1665 1666 1667 if (_pMfraOffsetAtom != NULL) 1668 { 1669 PV_MP4_FF_DELETE(NULL, MfraOffsetAtom, _pMfraOffsetAtom); 1670 } 1671 1672 if (_pTrackDurationContainer != NULL) 1673 { 1674 for (i = 0; i < _pTrackDurationContainer->_pTrackdurationInfoVec->size(); i++) 1675 { 1676 PV_MP4_FF_DELETE(NULL, TrackDurationInfo, (*_pTrackDurationContainer->_pTrackdurationInfoVec)[i]); 1677 } 1678 PV_MP4_FF_TEMPLATED_DELETE(NULL, trackDurationInfoVecType, Oscl_Vector, _pTrackDurationContainer->_pTrackdurationInfoVec); 1679 1680 PV_MP4_FF_DELETE(NULL, TrackDurationContainer, _pTrackDurationContainer); 1681 } 1682 1683 // Delete user data if present 1684 if (_puserDataAtom != NULL) 1685 { 1686 PV_MP4_FF_DELETE(NULL, UserDataAtom, _puserDataAtom); 1687 } 1688 1689 if (_pFileTypeAtom != NULL) 1690 { 1691 PV_MP4_FF_DELETE(NULL, FileTypeAtom, _pFileTypeAtom); 1692 } 1693 1694 if (_movieFragmentFilePtr != NULL) 1695 { 1696 if (_movieFragmentFilePtr->IsOpen()) 1697 { 1698 AtomUtils::CloseMP4File(_movieFragmentFilePtr); 1699 } 1700 oscl_free(_movieFragmentFilePtr); 1701 } 1702 if (_pID3Parser) 1703 { 1704 PV_MP4_FF_DELETE(null, PVID3ParCom, _pID3Parser); 1705 _pID3Parser = NULL; 1706 } 1707 } 1708 1709 1710 uint64 Mpeg4File::getMovieDuration() const 1711 { 1712 uint64 overallMovieDuration = 0; 1713 uint32 id = 0; 1714 if (_isMovieFragmentsPresent) 1715 { 1716 overallMovieDuration = _pmovieAtom->getMovieFragmentDuration(); 1717 if (Oscl_Int64_Utils::get_uint64_lower32(overallMovieDuration) != 0) 1718 { 1719 return overallMovieDuration; 1720 } 1721 else if (_parsing_mode == 0) 1722 { 1723 uint numTracks = _pmovieAtom->getNumTracks(); 1724 uint32 *trackList = (uint32 *) oscl_malloc(sizeof(uint32) * numTracks); 1725 if (! trackList) 1726 return 0; // malloc failure 1727 _pmovieAtom->getTrackWholeIDList(trackList); 1728 uint32 prevtrackDuration = 0, trackduration = 0; 1729 for (uint32 i = 0; i < numTracks; i++) 1730 { 1731 TrackDurationInfo* pTrackDurationInfo = (*_pTrackDurationContainer->_pTrackdurationInfoVec)[i]; 1732 trackduration = pTrackDurationInfo->trackDuration; 1733 if (prevtrackDuration > trackduration) 1734 { 1735 trackduration = prevtrackDuration; 1736 } 1737 else 1738 { 1739 prevtrackDuration = trackduration; 1740 id = trackList[i]; 1741 } 1742 } 1743 Oscl_Int64_Utils::set_uint64(overallMovieDuration, 0, trackduration); 1744 1745 TrackAtom *trackAtom = NULL; 1746 uint32 mediaTimeScale = 0xFFFFFFFE; 1747 1748 if (_pmovieAtom != NULL) 1749 { 1750 trackAtom = _pmovieAtom->getTrackForID(id); 1751 } 1752 if (trackAtom != NULL) 1753 { 1754 mediaTimeScale = trackAtom->getMediaTimescale(); 1755 if (mediaTimeScale == 0) 1756 { 1757 // unlikely : getMediaTimescale can return 0 1758 mediaTimeScale = 0xFFFFFFFE; 1759 } 1760 } 1761 1762 overallMovieDuration = (overallMovieDuration / (uint64)mediaTimeScale) * (uint64)getMovieTimescale(); 1763 oscl_free(trackList); 1764 return overallMovieDuration; 1765 } 1766 else 1767 { 1768 return overallMovieDuration; 1769 } 1770 } 1771 else if (_pmovieAtom != NULL) 1772 { 1773 // Get the overall duration of the Mpeg-4 presentation 1774 return _pmovieAtom->getDuration(); 1775 } 1776 return 0; 1777 } 1778 1779 uint64 Mpeg4File::getMovieFragmentDuration() const 1780 { 1781 if (_pmovieAtom != NULL) 1782 { 1783 return _pmovieAtom->getMovieFragmentDuration(); 1784 } 1785 else 1786 return 0; 1787 } 1788 1789 uint32 Mpeg4File::getTimestampForSampleNumber(uint32 id, uint32 sampleNumber) 1790 { 1791 TrackAtom *trackAtom; 1792 1793 if (_pmovieAtom != NULL) 1794 { 1795 trackAtom = _pmovieAtom->getTrackForID(id); 1796 1797 if (trackAtom != NULL) 1798 { 1799 return trackAtom->getTimestampForSampleNumber(sampleNumber); 1800 } 1801 else 1802 { 1803 return 0; 1804 } 1805 } 1806 else 1807 { 1808 return 0; 1809 } 1810 } 1811 1812 int32 Mpeg4File::getSampleSizeAt(uint32 id, int32 sampleNum) 1813 { 1814 TrackAtom *trackAtom; 1815 1816 if (_pmovieAtom != NULL) 1817 { 1818 trackAtom = _pmovieAtom->getTrackForID(id); 1819 1820 if (trackAtom != NULL) 1821 { 1822 return (trackAtom->getSampleSizeAt(sampleNum)); 1823 } 1824 else 1825 { 1826 return 0; 1827 } 1828 } 1829 else 1830 { 1831 return 0; 1832 } 1833 } 1834 1835 uint64 Mpeg4File::getTrackMediaDurationForMovie(uint32 id) 1836 { 1837 TrackAtom *trackAtom; 1838 if (_pmovieAtom != NULL) 1839 { 1840 trackAtom = _pmovieAtom->getTrackForID(id); 1841 } 1842 else 1843 { 1844 return 0; 1845 } 1846 if (trackAtom != NULL) 1847 { 1848 return trackAtom->getTrackDuration(); 1849 } 1850 else 1851 { 1852 return 0; 1853 } 1854 1855 } 1856 // From TrackHeader 1857 uint64 Mpeg4File::getTrackDuration(uint32 id) 1858 { 1859 TrackAtom *trackAtom; 1860 if (_pmovieAtom != NULL) 1861 { 1862 trackAtom = _pmovieAtom->getTrackForID(id); 1863 } 1864 else 1865 { 1866 return 0; 1867 } 1868 if (_isMovieFragmentsPresent) 1869 { 1870 if (_parsing_mode) 1871 return _pmovieAtom->getMovieFragmentDuration(); 1872 else 1873 { 1874 int32 numTracks = _pmovieAtom->getNumTracks(); 1875 uint32 *trackList = (uint32 *) oscl_malloc(sizeof(uint32) * numTracks); 1876 if (!trackList) 1877 return 0; // malloc failed 1878 _pmovieAtom->getTrackWholeIDList(trackList); 1879 uint64 trackduration = 0; 1880 for (int32 i = 0; i < numTracks; i++) 1881 { 1882 if (trackList[i] == id) 1883 { 1884 TrackDurationInfo* pTrackDurationInfo = (*_pTrackDurationContainer->_pTrackdurationInfoVec)[i]; 1885 oscl_free(trackList); 1886 return trackduration = pTrackDurationInfo->trackDuration; 1887 } 1888 } 1889 oscl_free(trackList); 1890 } 1891 } 1892 if (trackAtom != NULL) 1893 { 1894 return trackAtom->getTrackDuration(); 1895 } 1896 else 1897 { 1898 return 0; 1899 } 1900 } 1901 1902 // From TrackReference 1903 uint32 Mpeg4File::trackDependsOn(uint32 id) 1904 { 1905 TrackAtom *trackAtom; 1906 if (_pmovieAtom != NULL) 1907 { 1908 trackAtom = _pmovieAtom->getTrackForID(id); 1909 } 1910 else 1911 { 1912 return 0; 1913 } 1914 1915 if (trackAtom != NULL) 1916 { 1917 return trackAtom->dependsOn(); 1918 } 1919 else 1920 { 1921 return 0; 1922 } 1923 1924 } 1925 1926 // From MediaHeader 1927 uint64 Mpeg4File::getTrackMediaDuration(uint32 id) 1928 { 1929 TrackAtom *trackAtom; 1930 if (_pmovieAtom != NULL) 1931 { 1932 trackAtom = _pmovieAtom->getTrackForID(id); 1933 } 1934 else 1935 { 1936 return 0; 1937 } 1938 if (_isMovieFragmentsPresent) 1939 { 1940 if (_parsing_mode) 1941 return _pmovieAtom->getMovieFragmentDuration(); 1942 else 1943 { 1944 int numTracks = _pmovieAtom->getNumTracks(); 1945 uint32 *trackList = (uint32 *) oscl_malloc(sizeof(uint32) * numTracks); 1946 if (!trackList) 1947 return 0; // malloc failed 1948 _pmovieAtom->getTrackWholeIDList(trackList); 1949 uint32 trackduration = 0; 1950 for (int32 i = 0; i < numTracks; i++) 1951 { 1952 if (trackList[i] == id) 1953 { 1954 TrackDurationInfo* pTrackDurationInfo = (*_pTrackDurationContainer->_pTrackdurationInfoVec)[i]; 1955 oscl_free(trackList); 1956 return trackduration = pTrackDurationInfo->trackDuration; 1957 } 1958 } 1959 oscl_free(trackList); 1960 } 1961 } 1962 1963 if (trackAtom != NULL) 1964 { 1965 return trackAtom->getMediaDuration(); 1966 } 1967 else 1968 { 1969 return 0; 1970 } 1971 } 1972 1973 uint32 Mpeg4File::getTrackMediaTimescale(uint32 id) 1974 { 1975 TrackAtom *trackAtom; 1976 if (_pmovieAtom != NULL) 1977 { 1978 trackAtom = _pmovieAtom->getTrackForID(id); 1979 } 1980 else 1981 { 1982 // RETURN UNDEFINED VALUE 1983 return (0xFFFFFFFF); 1984 } 1985 1986 if (trackAtom != NULL) 1987 { 1988 return trackAtom->getMediaTimescale(); 1989 } 1990 else 1991 { 1992 // RETURN UNDEFINED VALUE 1993 return (0xFFFFFFFF); 1994 } 1995 } 1996 1997 uint16 Mpeg4File::getTrackLangCode(uint32 id) 1998 { 1999 2000 TrackAtom *trackAtom; 2001 if (_pmovieAtom != NULL) 2002 { 2003 trackAtom = _pmovieAtom->getTrackForID(id); 2004 } 2005 else 2006 { 2007 // RETURN UNDEFINED VALUE 2008 return (0xFFFF); 2009 } 2010 2011 if (trackAtom != NULL) 2012 { 2013 return trackAtom->getLanguageCode(); 2014 } 2015 else 2016 { 2017 // RETURN UNDEFINED VALUE 2018 return (0xFFFF); 2019 } 2020 } 2021 2022 // From Handler 2023 uint32 Mpeg4File::getTrackMediaType(uint32 id) 2024 { 2025 TrackAtom *trackAtom; 2026 if (_pmovieAtom != NULL) 2027 { 2028 trackAtom = _pmovieAtom->getTrackForID(id); 2029 } 2030 else 2031 { 2032 // RETURN UNDEFINED VALUE 2033 return (0xFFFFFFFF); 2034 } 2035 2036 if (trackAtom != NULL) 2037 { 2038 return trackAtom->getMediaType(); 2039 } 2040 else 2041 { 2042 // RETURN UNDEFINED VALUE 2043 return (0xFFFFFFFF); 2044 } 2045 2046 } 2047 2048 // From SampleDescription 2049 int32 Mpeg4File::getTrackNumSampleEntries(uint32 id) 2050 { 2051 TrackAtom *trackAtom; 2052 2053 if (_pmovieAtom != NULL) 2054 { 2055 trackAtom = _pmovieAtom->getTrackForID(id); 2056 } 2057 else 2058 { 2059 return 0; 2060 } 2061 2062 if (trackAtom != NULL) 2063 { 2064 return trackAtom->getNumSampleEntries(); 2065 } 2066 else 2067 { 2068 return 0; 2069 } 2070 } 2071 2072 // From DecoderConfigDescriptor 2073 DecoderSpecificInfo *Mpeg4File::getTrackDecoderSpecificInfo(uint32 id) 2074 { 2075 TrackAtom *trackAtom; 2076 if (_pmovieAtom != NULL) 2077 { 2078 trackAtom = _pmovieAtom->getTrackForID(id); 2079 } 2080 else 2081 { 2082 return NULL; 2083 } 2084 2085 if (trackAtom != NULL) 2086 { 2087 return trackAtom->getDecoderSpecificInfo(); 2088 } 2089 else 2090 { 2091 return NULL; 2092 } 2093 2094 } 2095 2096 // From DecoderConfigDescriptor 2097 DecoderSpecificInfo * 2098 Mpeg4File::getTrackDecoderSpecificInfoAtSDI(uint32 trackID, uint32 index) 2099 { 2100 if (_pmovieAtom != NULL) 2101 { 2102 return (_pmovieAtom->getTrackDecoderSpecificInfoAtSDI(trackID, index)); 2103 } 2104 else 2105 { 2106 return NULL; 2107 } 2108 } 2109 2110 uint8 *Mpeg4File::getTrackDecoderSpecificInfoContent(uint32 id) 2111 { 2112 DecoderSpecificInfo *decoderSpecificInfo; 2113 decoderSpecificInfo = getTrackDecoderSpecificInfo(id); 2114 2115 if (decoderSpecificInfo != NULL) 2116 { 2117 return decoderSpecificInfo->getInfo(); 2118 } 2119 else 2120 { 2121 return NULL; 2122 } 2123 } 2124 2125 uint32 Mpeg4File::getTrackDecoderSpecificInfoSize(uint32 id) 2126 { 2127 DecoderSpecificInfo *decoderSpecificInfo; 2128 decoderSpecificInfo = getTrackDecoderSpecificInfo(id); 2129 2130 if (decoderSpecificInfo != NULL) 2131 { 2132 return decoderSpecificInfo->getInfoSize(); 2133 } 2134 else 2135 { 2136 return 0; 2137 } 2138 } 2139 2140 2141 void Mpeg4File::getTrackMIMEType(uint32 id, OSCL_String& aMimeType) // Based on OTI value 2142 { 2143 TrackAtom *trackAtom = NULL; 2144 2145 if (_pmovieAtom != NULL) 2146 { 2147 trackAtom = _pmovieAtom->getTrackForID(id); 2148 } 2149 2150 if (trackAtom != NULL) 2151 { 2152 trackAtom->getMIMEType(aMimeType); 2153 } 2154 } 2155 2156 2157 int32 Mpeg4File::getTrackMaxBufferSizeDB(uint32 id) 2158 { 2159 TrackAtom *trackAtom; 2160 2161 if (_pmovieAtom != NULL) 2162 { 2163 trackAtom = _pmovieAtom->getTrackForID(id); 2164 } 2165 else 2166 { 2167 return 0; 2168 } 2169 2170 if (trackAtom != NULL) 2171 { 2172 return trackAtom->getMaxBufferSizeDB(); 2173 } 2174 else 2175 { 2176 return 0; 2177 } 2178 } 2179 2180 int32 Mpeg4File::getTrackAverageBitrate(uint32 id) 2181 { 2182 TrackAtom *trackAtom; 2183 2184 if (_pmovieAtom != NULL) 2185 { 2186 trackAtom = _pmovieAtom->getTrackForID(id); 2187 } 2188 else 2189 { 2190 return 0; 2191 } 2192 2193 if (trackAtom != NULL) 2194 { 2195 return trackAtom->getAverageBitrate(); 2196 } 2197 else 2198 { 2199 return 0; 2200 } 2201 } 2202 2203 // PASP Box 2204 //Hspacing 2205 uint32 Mpeg4File::getHspacing(uint32 id) 2206 { 2207 2208 TrackAtom *trackAtom; 2209 2210 if (_pmovieAtom != NULL) 2211 { 2212 trackAtom = _pmovieAtom->getTrackForID(id); 2213 } 2214 else 2215 { 2216 return 0; 2217 } 2218 2219 if (trackAtom != NULL) 2220 { 2221 return trackAtom->getHspacing(); 2222 } 2223 else 2224 { 2225 return 0; 2226 } 2227 } 2228 2229 //Vspacing 2230 uint32 Mpeg4File::getVspacing(uint32 id) 2231 { 2232 2233 TrackAtom *trackAtom; 2234 2235 if (_pmovieAtom != NULL) 2236 { 2237 trackAtom = _pmovieAtom->getTrackForID(id); 2238 } 2239 else 2240 { 2241 return 0; 2242 } 2243 2244 if (trackAtom != NULL) 2245 { 2246 return trackAtom->getVspacing(); 2247 } 2248 else 2249 { 2250 return 0; 2251 } 2252 } 2253 2254 2255 uint32 2256 Mpeg4File::getMovieTimescale() const 2257 { 2258 if (_pmovieAtom != NULL) 2259 { 2260 // Set the overall timescale of the Mpeg-4 presentation 2261 return _pmovieAtom->getTimeScale(); 2262 } 2263 else 2264 { 2265 // RETURN UNDEFINED VALUE 2266 return (0xFFFFFFFF); 2267 } 2268 } 2269 2270 /* ======================================================================== */ 2271 bool 2272 Mpeg4File::IsMobileMP4() 2273 { 2274 bool oMMP4 = false; 2275 2276 if (_pFileTypeAtom != NULL) 2277 { 2278 uint32 majorBrand = _pFileTypeAtom->getMajorBrand(); 2279 2280 if (majorBrand != MOBILE_MP4) 2281 { 2282 Oscl_Vector<uint32, OsclMemAllocator> *_compatibleBrand = 2283 _pFileTypeAtom->getCompatibleBrand(); 2284 if (_compatibleBrand != NULL) 2285 { 2286 for (uint32 i = 0; i < _compatibleBrand->size(); i++) 2287 { 2288 uint32 brand = (*_compatibleBrand)[i]; 2289 2290 if (brand == MOBILE_MP4) 2291 { 2292 oMMP4 = true; 2293 } 2294 } 2295 } 2296 else 2297 { 2298 return false; 2299 } 2300 } 2301 else 2302 { 2303 oMMP4 = true; 2304 } 2305 } 2306 else 2307 { 2308 return false; 2309 } 2310 2311 if (oMMP4 == true) 2312 { 2313 if (!(_pmovieAtom->checkMMP4())) 2314 { 2315 return false; 2316 } 2317 } 2318 2319 return (oMMP4); 2320 } 2321 2322 uint8 2323 Mpeg4File::parseBufferAndGetNumAMRFrames(uint8* buffer, uint32 size) 2324 { 2325 uint32 inputBufferSize = size; 2326 uint8* inputPtr = buffer; 2327 uint8 numArmFrames = 0; 2328 2329 if (((int32)(size) <= 0) || 2330 (buffer == NULL)) 2331 { 2332 return 0; 2333 } 2334 2335 uint8 aFrameSizes[16] = {12, 13, 15, 17, 19, 20, 26, 31, 2336 5, 0, 0, 0, 0, 0, 0, 0 2337 }; 2338 2339 while (inputBufferSize > 0) 2340 { 2341 uint8 toc_byte = *(inputPtr); 2342 2343 uint8 frame_type = (uint8)((toc_byte >> 3) & 0x0F); 2344 2345 inputPtr += 1; 2346 inputBufferSize -= 1; 2347 2348 if ((frame_type > 8) && (frame_type != 15)) 2349 { 2350 return 0; 2351 } 2352 2353 numArmFrames++; 2354 inputPtr += aFrameSizes[(uint16)frame_type]; 2355 inputBufferSize -= aFrameSizes[(uint16)frame_type]; 2356 } 2357 return (numArmFrames); 2358 } 2359 2360 2361 uint32 Mpeg4File::getTrackLevelOMA2DRMInfoSize(uint32 trackID) 2362 { 2363 TrackAtom *trackAtom; 2364 2365 if (_pmovieAtom != NULL) 2366 { 2367 trackAtom = _pmovieAtom->getTrackForID(trackID); 2368 } 2369 else 2370 { 2371 return 0; 2372 } 2373 2374 if (trackAtom != NULL) 2375 { 2376 return trackAtom->getTrackLevelOMA2DRMInfoSize(); 2377 } 2378 else 2379 { 2380 return 0; 2381 } 2382 } 2383 2384 uint8* Mpeg4File::getTrackLevelOMA2DRMInfo(uint32 trackID) 2385 { 2386 TrackAtom *trackAtom; 2387 2388 if (_pmovieAtom != NULL) 2389 { 2390 trackAtom = _pmovieAtom->getTrackForID(trackID); 2391 } 2392 else 2393 { 2394 return NULL; 2395 } 2396 2397 if (trackAtom != NULL) 2398 { 2399 return trackAtom->getTrackLevelOMA2DRMInfo(); 2400 } 2401 else 2402 { 2403 return NULL; 2404 } 2405 } 2406 2407 2408 MP4_ERROR_CODE 2409 Mpeg4File::RequestReadCapacityNotification(PvmiDataStreamObserver& aObserver, 2410 uint32 aFileOffset, 2411 OsclAny* aContextData) 2412 { 2413 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "Mpeg4File::RequestReadCapacityNotification In Offset %d", aFileOffset)); 2414 uint32 capacity = 0; 2415 if (_commonFilePtr != NULL) 2416 { 2417 uint32 currPos = (uint32)(AtomUtils::getCurrentFilePosition(_commonFilePtr)); 2418 if (aFileOffset > currPos) 2419 { 2420 capacity = (aFileOffset - currPos); 2421 bool retVal = 2422 _commonFilePtr->_pvfile.RequestReadCapacityNotification(aObserver, 2423 capacity, 2424 aContextData); 2425 if (retVal) 2426 { 2427 return EVERYTHING_FINE; 2428 } 2429 else 2430 { 2431 return DEFAULT_ERROR; 2432 } 2433 } 2434 return SUFFICIENT_DATA_IN_FILE; 2435 } 2436 return DEFAULT_ERROR; 2437 } 2438 2439 2440 MP4_ERROR_CODE 2441 Mpeg4File::GetCurrentFileSize(uint32& aFileSize) 2442 { 2443 aFileSize = 0; 2444 if (AtomUtils::getCurrentFileSize(_commonFilePtr, aFileSize) == true) 2445 { 2446 return EVERYTHING_FINE; 2447 } 2448 if (_commonFilePtr == NULL && _fileSize != 0) 2449 { 2450 aFileSize = _fileSize; 2451 return EVERYTHING_FINE; 2452 } 2453 return DEFAULT_ERROR; 2454 } 2455 2456 int32 Mpeg4File::getNextBundledAccessUnits(const uint32 trackID, 2457 uint32 *n, 2458 GAU *pgau) 2459 { 2460 uint32 samplesTobeRead; 2461 samplesTobeRead = *n; 2462 uint32 totalSampleRead = 0; 2463 if (getNumTracks() == 0) 2464 { 2465 return -1; 2466 } 2467 2468 if (_pmovieAtom != NULL) 2469 { 2470 int32 ret = _pmovieAtom->getNextBundledAccessUnits(trackID, n, pgau); 2471 if (ret == END_OF_TRACK) 2472 { 2473 if (!_isMovieFragmentsPresent) 2474 return ret; 2475 2476 totalSampleRead += *n; 2477 bool oAllMoofExhausted = false; 2478 bool oAllMoofParsed = false; 2479 2480 if (_parsing_mode == 0) 2481 { 2482 if (_pMovieFragmentAtomVec != NULL && _isMovieFragmentsPresent) 2483 { 2484 if (samplesTobeRead >= *n) 2485 *n = samplesTobeRead - *n; 2486 } 2487 else 2488 return ret; 2489 2490 int32 return1 = 0; 2491 while (_movieFragmentIdx[trackID] < _pMovieFragmentAtomVec->size()) 2492 { 2493 uint32 movieFragmentIdx = _movieFragmentIdx[trackID]; 2494 MovieFragmentAtom *pMovieFragmentAtom = (*_pMovieFragmentAtomVec)[movieFragmentIdx]; 2495 if (pMovieFragmentAtom != NULL) 2496 { 2497 if ((uint32)pMovieFragmentAtom->getSequenceNumber() == _movieFragmentSeqIdx[trackID]) 2498 { 2499 TrackFragmentAtom *trackfragment = pMovieFragmentAtom->getTrackFragmentforID(trackID); 2500 if (trackfragment != NULL) 2501 { 2502 if (trackfragment->getTrackId() == trackID) 2503 { 2504 return1 = pMovieFragmentAtom->getNextBundledAccessUnits(trackID, n, totalSampleRead, pgau); 2505 totalSampleRead += *n; 2506 if (return1 != END_OF_TRACK) 2507 { 2508 *n = totalSampleRead; 2509 return return1; 2510 } 2511 else 2512 { 2513 _movieFragmentSeqIdx[trackID]++; 2514 if (samplesTobeRead >= *n) 2515 { 2516 samplesTobeRead = samplesTobeRead - *n; 2517 *n = samplesTobeRead; 2518 } 2519 } 2520 } 2521 } 2522 } 2523 } 2524 _movieFragmentIdx[trackID]++; 2525 } 2526 if (return1 == END_OF_TRACK) 2527 { 2528 *n = totalSampleRead; 2529 _movieFragmentIdx[trackID] = 0; 2530 return return1; 2531 } 2532 } 2533 else 2534 { 2535 int32 return1 = 0; 2536 while (!oAllMoofExhausted) 2537 { 2538 if (oAllMoofParsed && (_pMovieFragmentAtomVec->size() < _movieFragmentIdx[trackID])) 2539 { 2540 oAllMoofExhausted = true; 2541 *n = 0; 2542 break; 2543 } 2544 2545 while (!oAllMoofParsed) 2546 { 2547 if (moofParsingCompleted) 2548 { 2549 uint32 moofIndex = 0; 2550 bool moofToBeParsed = false; 2551 if (_pMovieFragmentAtomVec->size() > _movieFragmentIdx[trackID]) 2552 { 2553 MovieFragmentAtom *pMovieFragmentAtom = NULL; 2554 uint32 idx = _movieFragmentIdx[trackID]; 2555 pMovieFragmentAtom = (*_pMovieFragmentAtomVec)[_movieFragmentIdx[trackID]]; 2556 if (pMovieFragmentAtom == NULL) 2557 { 2558 isResetPlayBackCalled = true; 2559 moofToBeParsed = true; 2560 moofIndex = _movieFragmentIdx[trackID]; 2561 } 2562 else if (isResetPlayBackCalled) 2563 { 2564 isResetPlayBackCalled = false; 2565 2566 // if moofs are already parsed, so go to the end of MOOF Vector. 2567 2568 uint32 currFilePos = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr); 2569 if (currFilePos < _ptrMoofEnds) 2570 { 2571 uint32 offset = (_ptrMoofEnds - currFilePos); 2572 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, offset); 2573 } 2574 else if (currFilePos == _ptrMoofEnds) 2575 { 2576 // no need to seek the File Pointer 2577 } 2578 else 2579 { 2580 AtomUtils::seekFromStart(_movieFragmentFilePtr, _ptrMoofEnds); 2581 } 2582 2583 idx = currMoofNum - 1; 2584 uint32 i = idx + 1; 2585 while (i < _pMovieFragmentAtomVec->size()) 2586 { 2587 idx++; 2588 pMovieFragmentAtom = (*_pMovieFragmentAtomVec)[idx]; 2589 if (pMovieFragmentAtom == NULL) 2590 { 2591 uint32 moof_start_offset = (*_pMoofOffsetVec)[idx-1]; 2592 AtomUtils::seekFromStart(_movieFragmentFilePtr, moof_start_offset); 2593 uint32 atomType = UNKNOWN_ATOM; 2594 uint32 atomSize = 0; 2595 AtomUtils::getNextAtomType(_movieFragmentFilePtr, atomSize, atomType); 2596 if (atomType == MOVIE_FRAGMENT_ATOM) 2597 { 2598 atomSize -= DEFAULT_ATOM_SIZE; 2599 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, atomSize); 2600 _ptrMoofEnds = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr); 2601 } 2602 isResetPlayBackCalled = true; 2603 moofToBeParsed = true; 2604 moofIndex = idx; 2605 break; 2606 } 2607 pMovieFragmentAtom->resetPlayback(); 2608 i++; 2609 } 2610 uint32 moof_start_offset = (*_pMoofOffsetVec)[idx]; 2611 AtomUtils::seekFromStart(_movieFragmentFilePtr, moof_start_offset); 2612 uint32 atomType = UNKNOWN_ATOM; 2613 uint32 atomSize = 0; 2614 AtomUtils::getNextAtomType(_movieFragmentFilePtr, atomSize, atomType); 2615 if (atomType == MOVIE_FRAGMENT_ATOM) 2616 { 2617 atomSize -= DEFAULT_ATOM_SIZE; 2618 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, atomSize); 2619 _ptrMoofEnds = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr); 2620 } 2621 } 2622 } 2623 2624 uint32 fileSize = 0; 2625 AtomUtils::getCurrentFileSize(_movieFragmentFilePtr, fileSize); 2626 uint32 currFilePos = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr); 2627 if (currFilePos < _ptrMoofEnds) 2628 { 2629 uint32 offset = (_ptrMoofEnds - currFilePos); 2630 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, offset); 2631 } 2632 else 2633 { 2634 AtomUtils::seekFromStart(_movieFragmentFilePtr, _ptrMoofEnds); 2635 } 2636 uint32 filePointer = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr); 2637 int32 count = fileSize - filePointer;// -DEFAULT_ATOM_SIZE; 2638 2639 while (count > 0) 2640 { 2641 uint32 atomType = UNKNOWN_ATOM; 2642 uint32 atomSize = 0; 2643 uint32 currPos = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr); 2644 AtomUtils::getNextAtomType(_movieFragmentFilePtr, atomSize, atomType); 2645 if ((currPos + atomSize) > fileSize) 2646 { 2647 AtomUtils::seekFromStart(_movieFragmentFilePtr, currPos); 2648 if (_movieFragmentIdx[trackID] < _pMovieFragmentAtomVec->size()) 2649 { 2650 // dont report insufficient data as we still have a moof/moofs to 2651 // retrieve data. So just go and retrieve the data. 2652 break; 2653 } 2654 else 2655 { 2656 // We have run out of MOOF atoms so report insufficient data. 2657 return INSUFFICIENT_DATA; 2658 } 2659 } 2660 2661 if (atomType == MOVIE_FRAGMENT_ATOM) 2662 { 2663 uint32 moofStartOffset = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr); 2664 moofStartOffset -= DEFAULT_ATOM_SIZE; 2665 parseMoofCompletely = false; 2666 moofSize = atomSize; 2667 moofType = atomType; 2668 moofCount = count; 2669 _ptrMoofEnds = moofStartOffset + atomSize; 2670 2671 PV_MP4_FF_NEW(_movieFragmentFilePtr->auditCB, MovieFragmentAtom, (_movieFragmentFilePtr, atomSize, atomType, _pTrackDurationContainer, _pTrackExtendsAtomVec, parseMoofCompletely, moofParsingCompleted, countOfTrunsParsed), _pMovieFragmentAtom); 2672 moofSize = atomSize; 2673 moofPtrPos = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr); 2674 2675 currMoofNum = _pMovieFragmentAtom->getSequenceNumber(); 2676 if (moofToBeParsed) 2677 { 2678 (*_pMovieFragmentAtomVec)[moofIndex] = _pMovieFragmentAtom; 2679 (*_pMoofOffsetVec)[moofIndex] = moofStartOffset; 2680 } 2681 else 2682 { 2683 _pMoofOffsetVec->push_back(moofStartOffset); 2684 _pMovieFragmentAtomVec->push_back(_pMovieFragmentAtom); 2685 } 2686 2687 if (moofParsingCompleted) 2688 { 2689 if (!_pMovieFragmentAtom->MP4Success()) 2690 { 2691 _success = false; 2692 _mp4ErrorCode = _pMovieFragmentAtom->GetMP4Error(); 2693 oAllMoofExhausted = true; 2694 break; 2695 } 2696 _pMovieFragmentAtom->setParent(this); 2697 count -= _pMovieFragmentAtom->getSize(); 2698 2699 break; 2700 } 2701 2702 break; 2703 } 2704 else if (atomType == MEDIA_DATA_ATOM) 2705 { 2706 if (atomSize == 1) 2707 { 2708 uint64 largeSize = 0; 2709 AtomUtils::read64(_movieFragmentFilePtr, largeSize); 2710 uint32 size = 2711 Oscl_Int64_Utils::get_uint64_lower32(largeSize); 2712 count -= size; 2713 size -= 8; //for large size 2714 size -= DEFAULT_ATOM_SIZE; 2715 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, size); 2716 } 2717 else 2718 { 2719 if (atomSize < DEFAULT_ATOM_SIZE) 2720 { 2721 _success = false; 2722 _mp4ErrorCode = ZERO_OR_NEGATIVE_ATOM_SIZE; 2723 oAllMoofExhausted = true; 2724 break; 2725 } 2726 if (count < (int32)atomSize) 2727 { 2728 _success = false; 2729 _mp4ErrorCode = INSUFFICIENT_DATA; 2730 ret = _mp4ErrorCode; 2731 oAllMoofExhausted = true; 2732 AtomUtils::seekFromStart(_movieFragmentFilePtr, currPos); 2733 break; 2734 } 2735 count -= atomSize; 2736 atomSize -= DEFAULT_ATOM_SIZE; 2737 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, atomSize); 2738 } 2739 } 2740 2741 else 2742 { 2743 if (count > 0) 2744 { 2745 count -= atomSize; 2746 atomSize -= DEFAULT_ATOM_SIZE; 2747 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, atomSize); 2748 } 2749 2750 } 2751 } 2752 if (count <= 0) 2753 { 2754 oAllMoofParsed = true; 2755 break; 2756 } 2757 break; 2758 } 2759 else if (!moofParsingCompleted) 2760 { 2761 if (currMoofNum != (uint32) _pMovieFragmentAtom->getSequenceNumber()) 2762 { 2763 uint32 size = _pMovieFragmentAtomVec->size(); 2764 _pMovieFragmentAtom = (*_pMovieFragmentAtomVec)[size - 1]; 2765 } 2766 uint32 currPos = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr); 2767 if (currPos > moofPtrPos) 2768 { 2769 uint32 offset = (currPos - moofPtrPos); 2770 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, -((int32)offset)); 2771 } 2772 else 2773 { 2774 uint32 offset = (moofPtrPos - currPos); 2775 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, offset); 2776 } 2777 2778 _pMovieFragmentAtom->ParseMoofAtom(_movieFragmentFilePtr, moofSize, moofType, _pTrackDurationContainer, _pTrackExtendsAtomVec, moofParsingCompleted, countOfTrunsParsed); 2779 moofPtrPos = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr); 2780 if (moofParsingCompleted) 2781 { 2782 if (!_pMovieFragmentAtom->MP4Success()) 2783 { 2784 _success = false; 2785 _mp4ErrorCode = _pMovieFragmentAtom->GetMP4Error(); 2786 oAllMoofExhausted = true; 2787 break; 2788 } 2789 _pMovieFragmentAtom->setParent(this); 2790 moofCount -= _pMovieFragmentAtom->getSize(); 2791 } 2792 2793 if (currPos > moofPtrPos) 2794 { 2795 uint32 offset = (currPos - moofPtrPos); 2796 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, offset); 2797 } 2798 else 2799 { 2800 uint32 offset = (moofPtrPos - currPos); 2801 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, -((int32)offset)); 2802 } 2803 2804 if (moofCount <= 0) 2805 { 2806 oAllMoofParsed = true; 2807 break; 2808 } 2809 break; 2810 } 2811 } 2812 2813 if (return1 != END_OF_TRACK) 2814 { 2815 if (samplesTobeRead >= *n) 2816 *n = samplesTobeRead - *n; 2817 } 2818 2819 uint32 movieFragmentIdx = _movieFragmentIdx[trackID]; 2820 MovieFragmentAtom *pMovieFragmentAtom = NULL; 2821 2822 if (movieFragmentIdx < _pMovieFragmentAtomVec->size()) 2823 pMovieFragmentAtom = (*_pMovieFragmentAtomVec)[movieFragmentIdx]; 2824 2825 if (pMovieFragmentAtom != NULL) 2826 { 2827 uint32 seqNum = pMovieFragmentAtom->getSequenceNumber(); 2828 if (seqNum == _movieFragmentSeqIdx[trackID]) 2829 { 2830 TrackFragmentAtom *trackfragment = pMovieFragmentAtom->getTrackFragmentforID(trackID); 2831 if (trackfragment != NULL) 2832 { 2833 if (trackfragment->getTrackId() == trackID) 2834 { 2835 return1 = pMovieFragmentAtom->getNextBundledAccessUnits(trackID, n, totalSampleRead, pgau); 2836 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "Mpeg4File::getNextBundledAccessUnits return %d", return1)); 2837 totalSampleRead += *n; 2838 if (return1 != END_OF_TRACK) 2839 { 2840 *n = totalSampleRead; 2841 return return1; 2842 } 2843 else 2844 { 2845 _movieFragmentSeqIdx[trackID]++; 2846 if (samplesTobeRead >= *n) 2847 { 2848 samplesTobeRead = samplesTobeRead - *n; 2849 *n = samplesTobeRead; 2850 if (movieFragmentIdx < _pMovieFragmentAtomVec->size()) 2851 { 2852 _movieFragmentIdx[trackID]++; 2853 } 2854 } 2855 } 2856 } 2857 } 2858 else 2859 { 2860 uint32 movieFragmentIdx2 = _movieFragmentIdx[trackID]; 2861 2862 if (oAllMoofParsed) 2863 { 2864 // look for all moofs 2865 if (movieFragmentIdx2 < _pMovieFragmentAtomVec->size()) 2866 { 2867 _movieFragmentIdx[trackID]++; 2868 _movieFragmentSeqIdx[trackID]++; 2869 } 2870 else 2871 { 2872 return END_OF_TRACK; 2873 } 2874 2875 } 2876 else 2877 { 2878 if (movieFragmentIdx2 < _pMovieFragmentAtomVec->size()) 2879 { 2880 if ((movieFragmentIdx2 == (_pMovieFragmentAtomVec->size() - 1)) && moofParsingCompleted) 2881 { 2882 _movieFragmentIdx[trackID]++; 2883 _movieFragmentSeqIdx[trackID]++; 2884 } 2885 else if (movieFragmentIdx2 < (_pMovieFragmentAtomVec->size() - 1)) 2886 { 2887 _movieFragmentIdx[trackID]++; 2888 _movieFragmentSeqIdx[trackID]++; 2889 *n = 0; 2890 return NO_SAMPLE_IN_CURRENT_MOOF; 2891 } 2892 } 2893 } 2894 } 2895 } 2896 else 2897 { 2898 uint32 movieFragmentIdx2 = _movieFragmentIdx[trackID]; 2899 2900 if (oAllMoofParsed) 2901 { 2902 // look for all moofs 2903 if (movieFragmentIdx2 < _pMovieFragmentAtomVec->size()) 2904 { 2905 _movieFragmentIdx[trackID]++; 2906 _movieFragmentSeqIdx[trackID]++; 2907 } 2908 else 2909 { 2910 return END_OF_TRACK; 2911 } 2912 2913 } 2914 else 2915 { 2916 if (movieFragmentIdx2 < _pMovieFragmentAtomVec->size()) 2917 { 2918 if ((movieFragmentIdx2 == (_pMovieFragmentAtomVec->size() - 1)) && moofParsingCompleted) 2919 { 2920 _movieFragmentIdx[trackID]++; 2921 _movieFragmentSeqIdx[trackID]++; 2922 } 2923 else if (movieFragmentIdx2 < (_pMovieFragmentAtomVec->size() - 1)) 2924 { 2925 _movieFragmentIdx[trackID]++; 2926 _movieFragmentSeqIdx[trackID]++; 2927 *n = 0; 2928 return NO_SAMPLE_IN_CURRENT_MOOF; 2929 } 2930 } 2931 } 2932 } 2933 } 2934 else 2935 { 2936 if (movieFragmentIdx < _pMovieFragmentAtomVec->size()) 2937 { 2938 _movieFragmentIdx[trackID]++; 2939 _movieFragmentSeqIdx[trackID]++; 2940 } 2941 else if (oAllMoofParsed) 2942 { 2943 _movieFragmentIdx[trackID]++; 2944 _movieFragmentSeqIdx[trackID]++; 2945 } 2946 2947 } 2948 } 2949 } 2950 } 2951 return ret; 2952 } 2953 return -1; 2954 } 2955 2956 MovieFragmentAtom * Mpeg4File::getMovieFragmentForTrackId(uint32 id) 2957 { 2958 MovieFragmentAtom *movieFragmentAtom = NULL; 2959 uint32 i = 0; 2960 2961 if (_pMovieFragmentAtomVec == NULL) 2962 return NULL; 2963 2964 while (i < _pMovieFragmentAtomVec->size()) 2965 { 2966 movieFragmentAtom = (*_pMovieFragmentAtomVec)[i]; 2967 if (movieFragmentAtom != NULL) 2968 { 2969 TrackFragmentAtom *trackfragment = movieFragmentAtom->getTrackFragmentforID(id); 2970 if (trackfragment != NULL) 2971 { 2972 if (trackfragment->getTrackId() == id) 2973 { 2974 return movieFragmentAtom; 2975 } 2976 } 2977 } 2978 i++; 2979 } 2980 return NULL; 2981 } 2982 2983 void Mpeg4File::populateTrackDurationVec() 2984 { 2985 uint32 trackDuration = 0; 2986 if (_pmovieAtom != NULL) 2987 { 2988 uint32 ids[256]; 2989 uint32 size = 256; 2990 _pmovieAtom->getTrackIDList(ids, size); 2991 int32 numtracks = _pmovieAtom->getNumTracks(); 2992 PV_MP4_FF_NEW(fp->auditCB, TrackDurationContainer, (), _pTrackDurationContainer); 2993 PV_MP4_FF_NEW(fp->auditCB, trackDurationInfoVecType, (), _pTrackDurationContainer->_pTrackdurationInfoVec); 2994 for (int32 i = 0; i < numtracks; i++) 2995 { 2996 uint32 trackID = ids[i]; 2997 TrackDurationInfo *trackinfo = NULL; 2998 trackDuration = Oscl_Int64_Utils::get_uint64_lower32(_pmovieAtom->getTrackMediaDuration(trackID)); 2999 PV_MP4_FF_NEW(fp->auditCB, TrackDurationInfo, (trackDuration, trackID), trackinfo); 3000 (*_pTrackDurationContainer->_pTrackdurationInfoVec).push_back(trackinfo); 3001 _movieFragmentIdx[trackID] = 0; 3002 _peekMovieFragmentIdx[trackID] = 0; 3003 _movieFragmentSeqIdx[trackID] = 1; 3004 _peekMovieFragmentSeqIdx[trackID] = 1; 3005 } 3006 } 3007 } 3008 3009 uint32 Mpeg4File::GetByteOffsetToStartOfAudioFrames() 3010 { 3011 return _pID3Parser->GetByteOffsetToStartOfAudioFrames(); 3012 3013 } 3014 3015 void Mpeg4File::GetID3MetaData(PvmiKvpSharedPtrVector &id3Frames) 3016 { 3017 _pID3Parser->GetID3Frames(id3Frames); 3018 3019 } 3020 3021 bool Mpeg4File::IsID3Frame(const OSCL_String& frameType) 3022 { 3023 return _pID3Parser->IsID3FrameAvailable(frameType); 3024 } 3025 3026 void Mpeg4File::GetID3Frame(const OSCL_String& aFrameType, PvmiKvpSharedPtrVector& aFrame) 3027 { 3028 _pID3Parser->GetID3Frame(aFrameType, aFrame); 3029 } 3030 3031 PVID3Version Mpeg4File::GetID3Version() const 3032 { 3033 return _pID3Parser->GetID3Version(); 3034 } 3035 3036 void Mpeg4File::parseID3Header(MP4_FF_FILE *aFile) 3037 { 3038 int32 curpos = AtomUtils::getCurrentFilePosition(aFile); 3039 AtomUtils::seekFromStart(aFile, 0); 3040 _pID3Parser->ParseID3Tag(&aFile->_pvfile); 3041 AtomUtils::seekFromStart(aFile, curpos); 3042 } 3043 3044 uint32 Mpeg4File::getContentType() 3045 { 3046 PVContentTypeAtom *pAtom = NULL; 3047 3048 if (_puserDataAtom != NULL) 3049 { 3050 pAtom = 3051 (PVContentTypeAtom*) _puserDataAtom->getAtomOfType(PV_CONTENT_TYPE_ATOM); 3052 3053 if (pAtom != NULL) 3054 { 3055 return pAtom->getContentType(); 3056 } 3057 else 3058 { 3059 if (_oPVContent) 3060 { 3061 //Old PV Content, that doesnt have this atom 3062 //All such content is non-interleaved, with meta data 3063 //towards the very end 3064 return (DEFAULT_AUTHORING_MODE); 3065 } 3066 } 3067 } 3068 3069 //Third party content 3070 return (0xFFFFFFFF); 3071 } 3072 3073 3074 MP4_ERROR_CODE Mpeg4File::getKeyMediaSampleNumAt(uint32 aTrackId, 3075 uint32 aKeySampleNum, 3076 GAU *pgau) 3077 { 3078 if (_pmovieAtom == NULL) 3079 { 3080 return READ_SAMPLE_TABLE_ATOM_FAILED; 3081 } 3082 MP4_ERROR_CODE ret = _pmovieAtom->getKeyMediaSampleNumAt(aTrackId, aKeySampleNum, pgau); 3083 if (ret == READ_FAILED) 3084 { 3085 uint32 totalSampleRead = 0; 3086 if (_isMovieFragmentsPresent) 3087 { 3088 uint32 n = 1; 3089 uint32 movieFragmentIdx = _movieFragmentIdx[aTrackId]; 3090 MovieFragmentAtom *pMovieFragmentAtom = NULL; 3091 3092 if (movieFragmentIdx < _pMovieFragmentAtomVec->size()) 3093 pMovieFragmentAtom = (*_pMovieFragmentAtomVec)[movieFragmentIdx]; 3094 3095 if (pMovieFragmentAtom != NULL) 3096 { 3097 uint32 seqNum = pMovieFragmentAtom->getSequenceNumber(); 3098 if (seqNum == _movieFragmentSeqIdx[aTrackId]) 3099 { 3100 TrackFragmentAtom *trackfragment = pMovieFragmentAtom->getTrackFragmentforID(aTrackId); 3101 if (trackfragment != NULL) 3102 { 3103 if (trackfragment->getTrackId() == aTrackId) 3104 { 3105 return (MP4_ERROR_CODE)pMovieFragmentAtom->getNextBundledAccessUnits(aTrackId, &n, totalSampleRead, pgau); 3106 } 3107 } 3108 } 3109 } 3110 } 3111 return READ_FAILED; 3112 } 3113 else 3114 { 3115 return ret; 3116 } 3117 } 3118 3119 3120 3121 int32 Mpeg4File::getOffsetByTime(uint32 id, uint32 ts, int32* sampleFileOffset , uint32 jitterbuffertimeinmillisec) 3122 { 3123 int32 ret = DEFAULT_ERROR; 3124 uint32 sigmaAtomSize = 0; 3125 if (_pmovieAtom != NULL) 3126 { 3127 ret = _pmovieAtom->getOffsetByTime(id, ts, sampleFileOffset); 3128 if (ret == DEFAULT_ERROR || ret == LAST_SAMPLE_IN_MOOV) 3129 { 3130 if (_isMovieFragmentsPresent) 3131 { 3132 uint32 sigmaTrafDuration = 0; 3133 3134 for (uint32 idx = 0; idx < _pMovieFragmentAtomVec->size(); idx++) 3135 { 3136 MovieFragmentAtom *pMovieFragmentAtom = (*_pMovieFragmentAtomVec)[idx]; 3137 if (pMovieFragmentAtom != NULL) 3138 { 3139 uint32 currTrafDuration = pMovieFragmentAtom->getCurrentTrafDuration(id); 3140 if (currTrafDuration >= ts) 3141 { 3142 pMovieFragmentAtom = (*_pMovieFragmentAtomVec)[idx]; 3143 return pMovieFragmentAtom->getOffsetByTime(id, ts, sampleFileOffset); 3144 } 3145 sigmaTrafDuration += currTrafDuration; 3146 } 3147 } 3148 3149 if (_parsing_mode == 1) 3150 { 3151 if (moofParsingCompleted) 3152 { 3153 // do nothing 3154 } 3155 else 3156 { 3157 if ((uint32)_pMovieFragmentAtom->getSequenceNumber() == _movieFragmentSeqIdx[id]) 3158 { 3159 AtomUtils::seekFromStart(_movieFragmentFilePtr, moofPtrPos); 3160 3161 while (!moofParsingCompleted) 3162 { 3163 _pMovieFragmentAtom->ParseMoofAtom(_movieFragmentFilePtr, moofSize, moofType, _pTrackDurationContainer, _pTrackExtendsAtomVec, moofParsingCompleted, countOfTrunsParsed); 3164 } 3165 3166 if (moofParsingCompleted) 3167 { 3168 if (!_pMovieFragmentAtom->MP4Success()) 3169 { 3170 _success = false; 3171 _mp4ErrorCode = _pMovieFragmentAtom->GetMP4Error(); 3172 } 3173 _pMovieFragmentAtom->setParent(this); 3174 moofSize = _pMovieFragmentAtom->getSize(); 3175 moofCount -= _pMovieFragmentAtom->getSize(); 3176 } 3177 3178 uint32 currTrafDuration = _pMovieFragmentAtom->getCurrentTrafDuration(id); 3179 3180 if (currTrafDuration >= ts) 3181 { 3182 ret = _pMovieFragmentAtom->getOffsetByTime(id, ts, sampleFileOffset); 3183 if (*sampleFileOffset == 0) 3184 { 3185 // do nothing, continue parsing 3186 } 3187 else 3188 { 3189 return ret; 3190 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "getOffsetByTime:: ret Sample Offset=> Sample Offset= %d ret %d********@@@@@@@@@@@@@@@@", *sampleFileOffset, ret)); 3191 } 3192 } 3193 sigmaTrafDuration += currTrafDuration; 3194 } 3195 else 3196 { 3197 // This condition will only happen when the MovieFragmentAtomVec size is 3198 // greater than 1. 3199 uint32 i = _pMovieFragmentAtomVec->size(); 3200 _ptrMoofEnds = (*_pMoofOffsetVec)[i-2] + (*_pMovieFragmentAtomVec)[i-2]->getSize(); 3201 _pMoofOffsetVec->pop_back(); 3202 _pMovieFragmentAtomVec->pop_back(); 3203 PV_MP4_FF_DELETE(NULL, MovieFragmentAtom , (*_pMovieFragmentAtomVec)[i-1]); 3204 parseMoofCompletely = true; 3205 moofParsingCompleted = true; 3206 moofSize = 0; 3207 moofType = UNKNOWN_ATOM; 3208 moofCount = 0; 3209 moofPtrPos = 0; 3210 } 3211 } 3212 3213 uint32 fileSize = 0; 3214 uint32 currfptr = 0; 3215 3216 AtomUtils::getCurrentFileSize(_movieFragmentFilePtr, fileSize); 3217 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "getOffsetByTime::FileSize %d Track ID %d ********@@@@@@@@@@@@@@@@", fileSize, id)); 3218 3219 AtomUtils::seekFromStart(_movieFragmentFilePtr, _ptrMoofEnds); 3220 uint32 filePointer = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr); 3221 int32 count = fileSize - filePointer;// -DEFAULT_ATOM_SIZE; 3222 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "getOffsetByTime:: TS= %d ********@@@@@@@@@@@@@@@@, count=%d, filePointer=%d", ts, count, filePointer)); 3223 3224 while (count > 0) 3225 { 3226 uint32 atomType = UNKNOWN_ATOM; 3227 uint32 atomSize = 0; 3228 AtomUtils::Flush(_movieFragmentFilePtr); 3229 AtomUtils::getNextAtomType(_movieFragmentFilePtr, atomSize, atomType); 3230 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "getOffsetByTime:: count=%d, AtomSize=%d, atomtype=%d", count, atomSize, atomType)); 3231 if (atomSize < DEFAULT_ATOM_SIZE) 3232 { 3233 3234 ret = DEFAULT_ERROR; 3235 break; 3236 } 3237 sigmaAtomSize += atomSize; 3238 if (atomType == MOVIE_FRAGMENT_ATOM) 3239 { 3240 uint32 moofStartOffset = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr); 3241 moofStartOffset -= DEFAULT_ATOM_SIZE; 3242 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "getOffsetByTime:: MovieFragmentAtom moofStartOffset=%d", moofStartOffset)); 3243 3244 moofSize = atomSize; 3245 3246 if ((moofStartOffset + atomSize) > fileSize) 3247 { 3248 uint32 timeScale = _pmovieAtom->getTrackMediaTimescale(id); 3249 if ((timeScale == 0) || (timeScale == 0xFFFFFFFF)) 3250 { 3251 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "getOffsetByTime:: Invalid timeScale %d for Id %d", timeScale, id)); 3252 return DEFAULT_ERROR; 3253 } 3254 3255 uint32 trackPlayedSoFarInSec = ts / timeScale - jitterbuffertimeinmillisec / 1000; 3256 uint32 rateOfDataUsageKbPerSec = 0; 3257 if (trackPlayedSoFarInSec != 0) 3258 { 3259 rateOfDataUsageKbPerSec = fileSize / trackPlayedSoFarInSec; 3260 } 3261 // estimate data for PVMF_MP4FFPARSER_PSEUDO_STREAMING_DURATION_IN_SEC 3262 uint32 dataNeededAhead = (rateOfDataUsageKbPerSec * jitterbuffertimeinmillisec) / 1000; 3263 3264 *sampleFileOffset = moofStartOffset + atomSize + DEFAULT_ATOM_SIZE + dataNeededAhead; 3265 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "getOffsetByTime:: Insufficient data ot get Sample Offset= %d ********@@@@@@@@@@@@@@@@", *sampleFileOffset)); 3266 ret = EVERYTHING_FINE; 3267 break; 3268 } 3269 3270 _pMoofOffsetVec->push_back(moofStartOffset); 3271 parseMoofCompletely = true; 3272 3273 PV_MP4_FF_NEW(_movieFragmentFilePtr->auditCB, MovieFragmentAtom, (_movieFragmentFilePtr, atomSize, atomType, _pTrackDurationContainer, _pTrackExtendsAtomVec, parseMoofCompletely, moofParsingCompleted, countOfTrunsParsed), _pMovieFragmentAtom); 3274 3275 if (!_pMovieFragmentAtom->MP4Success()) 3276 { 3277 3278 _success = false; 3279 _mp4ErrorCode = _pMovieFragmentAtom->GetMP4Error(); 3280 break; 3281 } 3282 count -= _pMovieFragmentAtom->getSize(); 3283 _pMovieFragmentAtom->setParent(this); 3284 3285 _pMovieFragmentAtomVec->push_back(_pMovieFragmentAtom); 3286 _ptrMoofEnds = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr); 3287 3288 uint32 currTrafDuration = _pMovieFragmentAtom->getCurrentTrafDuration(id); 3289 3290 if (currTrafDuration >= ts) 3291 { 3292 ret = _pMovieFragmentAtom->getOffsetByTime(id, ts, sampleFileOffset); 3293 if (*sampleFileOffset == 0) 3294 { 3295 // do nothing, continue parsing 3296 } 3297 else 3298 { 3299 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "getOffsetByTime:: ret Sample Offset=> Sample Offset= %d ret %d********@@@@@@@@@@@@@@@@", *sampleFileOffset, ret)); 3300 break; 3301 } 3302 } 3303 sigmaTrafDuration += currTrafDuration; 3304 } 3305 else if (atomType == MEDIA_DATA_ATOM) 3306 { 3307 3308 if (atomSize == 1) 3309 { 3310 uint64 largeSize = 0; 3311 AtomUtils::read64(_movieFragmentFilePtr, largeSize); 3312 uint32 size = 3313 Oscl_Int64_Utils::get_uint64_lower32(largeSize); 3314 count -= size; 3315 size -= 8; //for large size 3316 size -= DEFAULT_ATOM_SIZE; 3317 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, size); 3318 } 3319 else 3320 { 3321 currfptr = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr); 3322 if ((currfptr + atomSize) > fileSize) 3323 { 3324 uint32 timeScale = _pmovieAtom->getTrackMediaTimescale(id); 3325 if ((timeScale == 0) || (timeScale == 0xFFFFFFFF)) 3326 { 3327 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "getOffsetByTime:: Invalid timeScale %d for Id %d", timeScale, id)); 3328 return DEFAULT_ERROR; 3329 } 3330 uint32 trackPlayedSoFarInSec = ts / timeScale - jitterbuffertimeinmillisec / 1000; 3331 uint32 rateOfDataUsageKbPerSec = 0; 3332 if (trackPlayedSoFarInSec != 0) 3333 { 3334 rateOfDataUsageKbPerSec = fileSize / trackPlayedSoFarInSec; 3335 } 3336 3337 // estimate data for PVMF_MP4FFPARSER_PSEUDO_STREAMING_DURATION_IN_SEC 3338 uint32 dataNeededAhead = (rateOfDataUsageKbPerSec * jitterbuffertimeinmillisec) / 1000; 3339 *sampleFileOffset = currfptr + atomSize + moofSize + dataNeededAhead; 3340 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "getOffsetByTime:: Insufficient data ot get Sample Offset= %d ********@@@@@@@@@@@@@@@@", *sampleFileOffset)); 3341 ret = EVERYTHING_FINE; 3342 break; 3343 3344 } 3345 count -= atomSize; 3346 atomSize -= DEFAULT_ATOM_SIZE; 3347 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, atomSize); 3348 } 3349 } 3350 3351 else 3352 { 3353 if (count > 0) 3354 { 3355 count -= atomSize; 3356 atomSize -= DEFAULT_ATOM_SIZE; 3357 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, atomSize); 3358 } 3359 } 3360 } 3361 if (sigmaTrafDuration == 0) 3362 { 3363 AtomUtils::getCurrentFileSize(_movieFragmentFilePtr, fileSize); 3364 *sampleFileOffset = fileSize + 1000; 3365 3366 ret = EVERYTHING_FINE; 3367 } 3368 } 3369 } 3370 else if (ret == LAST_SAMPLE_IN_MOOV) 3371 { 3372 ret = EVERYTHING_FINE; 3373 } 3374 3375 } 3376 3377 return ret; 3378 } 3379 else 3380 { 3381 3382 return ret; 3383 } 3384 } 3385 3386 int32 Mpeg4File::getTimestampForRandomAccessPoints(uint32 id, uint32 *num, uint32 *tsBuf, uint32* numBuf, uint32 *offsetBuf) 3387 { 3388 if (_pmovieAtom != NULL) 3389 { 3390 uint32 requestedSamples = *num, delta = 0, returnedSampleFromMoov = 0; 3391 uint32 ret = _pmovieAtom->getTimestampForRandomAccessPoints(id, num, tsBuf, numBuf, offsetBuf); 3392 if (ret == 1) 3393 { 3394 returnedSampleFromMoov = *num; 3395 if (requestedSamples != 0) 3396 { 3397 if (requestedSamples == returnedSampleFromMoov) 3398 return ret; 3399 3400 if (requestedSamples > returnedSampleFromMoov) 3401 { 3402 delta = requestedSamples - returnedSampleFromMoov; 3403 } 3404 } 3405 3406 } 3407 else 3408 delta = *num; 3409 3410 if (_isMovieFragmentsPresent) 3411 { 3412 if (_pMovieFragmentRandomAccessAtomVec != NULL) 3413 { // Only one mfra possible in a clip so this loop will run only once 3414 for (uint32 idx = 0; idx < _pMovieFragmentRandomAccessAtomVec->size(); idx++) 3415 { 3416 MovieFragmentRandomAccessAtom *pMovieFragmentRandomAccessAtom = (*_pMovieFragmentRandomAccessAtomVec)[idx]; 3417 ret = pMovieFragmentRandomAccessAtom->getTimestampForRandomAccessPoints(id, &delta, tsBuf, numBuf, offsetBuf, returnedSampleFromMoov); 3418 *num = delta; 3419 return ret; 3420 } 3421 3422 } 3423 } 3424 return ret; 3425 } 3426 return 0; 3427 } 3428 3429 int32 Mpeg4File::getTimestampForRandomAccessPointsBeforeAfter(uint32 id, uint32 ts, uint32 *tsBuf, uint32* numBuf, 3430 uint32& numsamplestoget, 3431 uint32 howManyKeySamples) 3432 { 3433 if (_pmovieAtom != NULL) 3434 { 3435 int32 ret = _pmovieAtom->getTimestampForRandomAccessPointsBeforeAfter(id, ts, tsBuf, numBuf, numsamplestoget, howManyKeySamples); 3436 if (ret != 1) 3437 { 3438 if (_isMovieFragmentsPresent) 3439 { 3440 if (_pMovieFragmentRandomAccessAtomVec != NULL) 3441 { // Only one mfra possible in a clip so this loop will run only once 3442 for (uint32 idx = 0; idx < _pMovieFragmentRandomAccessAtomVec->size(); idx++) 3443 { 3444 MovieFragmentRandomAccessAtom *pMovieFragmentRandomAccessAtom = (*_pMovieFragmentRandomAccessAtomVec)[idx]; 3445 ret = pMovieFragmentRandomAccessAtom->getTimestampForRandomAccessPointsBeforeAfter(id, ts, tsBuf, numBuf, numsamplestoget, howManyKeySamples); 3446 return ret; 3447 } 3448 3449 } 3450 } 3451 } 3452 return ret; 3453 3454 } 3455 else 3456 { 3457 return 0; 3458 } 3459 } 3460 3461 3462 3463 void Mpeg4File::resetAllMovieFragments() 3464 { 3465 uint32 trackDuration = 0; 3466 if (_isMovieFragmentsPresent) 3467 { 3468 if (_pMovieFragmentAtomVec != NULL) 3469 { 3470 int numTracks = _pmovieAtom->getNumTracks(); 3471 uint32 *trackList = (uint32 *) oscl_malloc(sizeof(uint32) * numTracks); 3472 if (!trackList) 3473 return; // malloc failed 3474 3475 _pmovieAtom->getTrackWholeIDList(trackList); 3476 for (int32 i = 0; i < numTracks; i++) 3477 { 3478 uint32 trackID = trackList[i]; 3479 _movieFragmentIdx[trackID] = 0; 3480 _peekMovieFragmentIdx[trackID] = 0; 3481 _movieFragmentSeqIdx[trackID] = 1; 3482 _peekMovieFragmentSeqIdx[trackID] = 1; 3483 TrackDurationInfo *trackinfo = NULL; 3484 if (_pTrackDurationContainer != NULL) 3485 { 3486 TrackDurationInfo *pTrackDurationInfo = (*_pTrackDurationContainer->_pTrackdurationInfoVec)[i]; 3487 if (pTrackDurationInfo != NULL) 3488 { 3489 PV_MP4_FF_DELETE(NULL, TrackDurationInfo, pTrackDurationInfo); 3490 pTrackDurationInfo = NULL; 3491 } 3492 } 3493 trackDuration = Oscl_Int64_Utils::get_uint64_lower32(_pmovieAtom->getTrackMediaDuration(trackID)); 3494 PV_MP4_FF_NEW(fp->auditCB, TrackDurationInfo, (trackDuration, trackID), trackinfo); 3495 (*_pTrackDurationContainer->_pTrackdurationInfoVec)[i] = trackinfo; 3496 } 3497 oscl_free(trackList); 3498 for (uint32 idx = 0; idx < _pMovieFragmentAtomVec->size(); idx++) 3499 { 3500 MovieFragmentAtom *pMovieFragmentAtom = (*_pMovieFragmentAtomVec)[idx]; 3501 if (pMovieFragmentAtom != NULL) 3502 pMovieFragmentAtom->resetPlayback(); 3503 3504 } 3505 } 3506 } 3507 } 3508 3509 3510 uint32 Mpeg4File::resetPlayback(uint32 time, uint16 numTracks, uint32 *trackList, bool bResetToIFrame) 3511 { 3512 OSCL_UNUSED_ARG(numTracks); 3513 3514 uint32 modifiedTimeStamp = time; 3515 uint32 trackID = 0; 3516 3517 uint32 retVal = 0; 3518 bool oMoofFound = false; 3519 3520 uint32 convertedTS = 0; 3521 uint32 timestamp = 0, returnedTS = 0; 3522 3523 uint32 moof_offset = 0, traf_number = 0, trun_number = 0, sample_num = 0; 3524 3525 trackID = *trackList; // numTracks is the track index in trackList 3526 if (getTrackMediaType(trackID) == MEDIA_TYPE_VISUAL) 3527 { 3528 _oVideoTrackPresent = true; 3529 } 3530 3531 if (_isMovieFragmentsPresent) 3532 { 3533 if (_pMovieFragmentAtomVec->size() > 1) 3534 { 3535 // The boolean is used to reset all MOOFs to start after reposition. This should 3536 // be true only when number of MOOFs in MOOF vector queue is more than one. 3537 isResetPlayBackCalled = true; 3538 } 3539 } 3540 3541 if (getTrackMediaType(trackID) == MEDIA_TYPE_VISUAL) 3542 { 3543 if (repositionFromMoof(time, trackID)) 3544 { 3545 //moof 3546 modifiedTimeStamp = time; 3547 3548 // convert modifiedTimeStamp (which is in ms) to the appropriate 3549 // media time scale 3550 MediaClockConverter mcc1(1000); 3551 mcc1.update_clock(modifiedTimeStamp); 3552 convertedTS = mcc1.get_converted_ts(getTrackMediaTimescale(trackID)); 3553 if (oMfraFound) 3554 { 3555 for (uint32 idx = 0; idx < _pMovieFragmentRandomAccessAtomVec->size(); idx++) 3556 { 3557 MovieFragmentRandomAccessAtom *pMovieFragmentRandomAccessAtom = (*_pMovieFragmentRandomAccessAtomVec)[idx]; 3558 uint32 ret = pMovieFragmentRandomAccessAtom->getSyncSampleInfoClosestToTime(trackID, convertedTS, moof_offset, traf_number, trun_number, sample_num); 3559 if (ret == 0) 3560 { 3561 if (moofParsingCompleted) 3562 { 3563 // do nothing 3564 } 3565 else 3566 { 3567 uint32 i = _pMovieFragmentAtomVec->size(); 3568 _pMoofOffsetVec->pop_back(); 3569 _pMovieFragmentAtomVec->pop_back(); 3570 PV_MP4_FF_DELETE(NULL, MovieFragmentAtom , (*_pMovieFragmentAtomVec)[i-1]); 3571 parseMoofCompletely = true; 3572 moofParsingCompleted = true; 3573 moofSize = 0; 3574 moofType = UNKNOWN_ATOM; 3575 moofCount = 0; 3576 moofPtrPos = 0; 3577 } 3578 3579 for (uint32 idx = 0; idx < _pMoofOffsetVec->size(); idx++) 3580 { 3581 uint32 moof_start_offset = (*_pMoofOffsetVec)[idx]; 3582 if (moof_start_offset == moof_offset) 3583 { 3584 _movieFragmentIdx[trackID] = idx; 3585 _peekMovieFragmentIdx[trackID] = idx; 3586 _movieFragmentSeqIdx[trackID] = (*_pMovieFragmentAtomVec)[idx]->getSequenceNumber(); 3587 _peekMovieFragmentSeqIdx[trackID] = _movieFragmentSeqIdx[trackID]; 3588 _pMovieFragmentAtom = (*_pMovieFragmentAtomVec)[idx]; 3589 currMoofNum = _pMovieFragmentAtom->getSequenceNumber(); 3590 oMoofFound = true; 3591 3592 AtomUtils::seekFromStart(_movieFragmentFilePtr, moof_offset); 3593 uint32 atomType = UNKNOWN_ATOM; 3594 uint32 atomSize = 0; 3595 AtomUtils::getNextAtomType(_movieFragmentFilePtr, atomSize, atomType); 3596 if (atomType == MOVIE_FRAGMENT_ATOM) 3597 { 3598 atomSize -= DEFAULT_ATOM_SIZE; 3599 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, atomSize); 3600 _ptrMoofEnds = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr); 3601 } 3602 break; 3603 } 3604 } 3605 3606 if (_parsing_mode == 1) 3607 { 3608 if (!oMoofFound) 3609 { 3610 uint32 fileSize = 0; 3611 _ptrMoofEnds = moof_offset; 3612 AtomUtils::getCurrentFileSize(_movieFragmentFilePtr, fileSize); 3613 AtomUtils::seekFromStart(_movieFragmentFilePtr, _ptrMoofEnds); 3614 uint32 filePointer = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr); 3615 int32 count = fileSize - filePointer;// -DEFAULT_ATOM_SIZE; 3616 3617 while (count > 0) 3618 { 3619 uint32 atomType = UNKNOWN_ATOM; 3620 uint32 atomSize = 0; 3621 AtomUtils::getNextAtomType(_movieFragmentFilePtr, atomSize, atomType); 3622 if (atomType == MOVIE_FRAGMENT_ATOM) 3623 { 3624 parseMoofCompletely = true; 3625 3626 uint32 moofStartOffset = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr); 3627 moofStartOffset -= DEFAULT_ATOM_SIZE; 3628 3629 if (moofParsingCompleted) 3630 { 3631 // do nothing 3632 } 3633 else 3634 { 3635 uint32 i = _pMovieFragmentAtomVec->size(); 3636 _pMoofOffsetVec->pop_back(); 3637 _pMovieFragmentAtomVec->pop_back(); 3638 PV_MP4_FF_DELETE(NULL, MovieFragmentAtom , (*_pMovieFragmentAtomVec)[i-1]); 3639 parseMoofCompletely = true; 3640 moofParsingCompleted = true; 3641 moofSize = 0; 3642 moofType = UNKNOWN_ATOM; 3643 moofCount = 0; 3644 moofPtrPos = 0; 3645 } 3646 3647 PV_MP4_FF_NEW(_movieFragmentFilePtr->auditCB, MovieFragmentAtom, (_movieFragmentFilePtr, atomSize, atomType, _pTrackDurationContainer, _pTrackExtendsAtomVec, parseMoofCompletely, moofParsingCompleted, countOfTrunsParsed), _pMovieFragmentAtom); 3648 3649 if (!_pMovieFragmentAtom->MP4Success()) 3650 { 3651 _success = false; 3652 _mp4ErrorCode = _pMovieFragmentAtom->GetMP4Error(); 3653 break; 3654 } 3655 3656 _pMovieFragmentAtom->setParent(this); 3657 count -= _pMovieFragmentAtom->getSize(); 3658 3659 uint32 i = _pMovieFragmentAtomVec->size(); 3660 3661 MovieFragmentAtom *pMovieFragmentAtom = NULL; 3662 uint32 prevMoofSeqNum = 0; 3663 3664 if (i > 0) 3665 { 3666 pMovieFragmentAtom = (*_pMovieFragmentAtomVec)[i-1]; 3667 3668 if (pMovieFragmentAtom != NULL) 3669 prevMoofSeqNum = (*_pMovieFragmentAtomVec)[i-1]->getSequenceNumber(); 3670 } 3671 3672 currMoofNum = _pMovieFragmentAtom->getSequenceNumber(); 3673 3674 for (uint32 idx = prevMoofSeqNum; idx < currMoofNum - 1; idx++) 3675 { 3676 _pMovieFragmentAtomVec->push_back(NULL); 3677 _pMoofOffsetVec->push_back(0); 3678 } 3679 if (currMoofNum > i) 3680 { 3681 _pMoofOffsetVec->push_back(moofStartOffset); 3682 _pMovieFragmentAtomVec->push_back(_pMovieFragmentAtom); 3683 } 3684 else if ((*_pMovieFragmentAtomVec)[currMoofNum-1] == NULL) 3685 { 3686 (*_pMovieFragmentAtomVec)[currMoofNum-1] = _pMovieFragmentAtom; 3687 (*_pMoofOffsetVec)[currMoofNum-1] = moofStartOffset; 3688 } 3689 else 3690 { 3691 PV_MP4_FF_DELETE(_movieFragmentFilePtr->auditCB, MovieFragmentAtom, _pMovieFragmentAtom); 3692 _pMovieFragmentAtom = NULL; 3693 break; 3694 3695 } 3696 _movieFragmentSeqIdx[trackID] = currMoofNum; 3697 _movieFragmentIdx[trackID] = currMoofNum - 1; 3698 _peekMovieFragmentIdx[trackID] = currMoofNum - 1; 3699 _peekMovieFragmentSeqIdx[trackID] = currMoofNum; 3700 3701 oMoofFound = true; 3702 3703 _ptrMoofEnds = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr); 3704 break; 3705 } 3706 else if (atomType == MEDIA_DATA_ATOM) 3707 { 3708 if (atomSize == 1) 3709 { 3710 uint64 largeSize = 0; 3711 AtomUtils::read64(_movieFragmentFilePtr, largeSize); 3712 uint32 size = 3713 Oscl_Int64_Utils::get_uint64_lower32(largeSize); 3714 count -= size; 3715 size -= 8; //for large size 3716 size -= DEFAULT_ATOM_SIZE; 3717 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, size); 3718 } 3719 else 3720 { 3721 if (atomSize < DEFAULT_ATOM_SIZE) 3722 { 3723 _success = false; 3724 _mp4ErrorCode = ZERO_OR_NEGATIVE_ATOM_SIZE; 3725 break; 3726 } 3727 if (count < (int32)atomSize) 3728 { 3729 _success = false; 3730 _mp4ErrorCode = READ_FAILED; 3731 break; 3732 } 3733 count -= atomSize; 3734 atomSize -= DEFAULT_ATOM_SIZE; 3735 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, atomSize); 3736 } 3737 } 3738 3739 else 3740 { 3741 if (count > 0) 3742 { 3743 count -= atomSize; 3744 atomSize -= DEFAULT_ATOM_SIZE; 3745 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, atomSize); 3746 } 3747 3748 } 3749 } 3750 } 3751 3752 } 3753 3754 if (_pmovieAtom != NULL) 3755 _pmovieAtom->resetTrackToEOT(); 3756 3757 if (_pMovieFragmentAtom != NULL) 3758 returnedTS = _pMovieFragmentAtom->resetPlayback(trackID, convertedTS, traf_number, trun_number, sample_num); 3759 } 3760 else 3761 { 3762 // Not a valid tfra entries, cannot reposition. 3763 return 0; 3764 } 3765 } 3766 3767 } 3768 else 3769 return 0; 3770 3771 // convert returnedTS (which is in media time scale) to the ms 3772 MediaClockConverter mcc(getTrackMediaTimescale(trackID)); 3773 mcc.update_clock(returnedTS); 3774 timestamp = mcc.get_converted_ts(1000); 3775 3776 if (timestamp <= modifiedTimeStamp) 3777 { 3778 modifiedTimeStamp = timestamp; 3779 } 3780 3781 } 3782 else 3783 { 3784 if (_isMovieFragmentsPresent) 3785 { 3786 if (_pMovieFragmentAtomVec->size() > 0) 3787 { 3788 if (moofParsingCompleted) 3789 { 3790 // do nothing 3791 } 3792 else 3793 { 3794 uint32 i = _pMovieFragmentAtomVec->size(); 3795 _pMoofOffsetVec->pop_back(); 3796 _pMovieFragmentAtomVec->pop_back(); 3797 PV_MP4_FF_DELETE(NULL, MovieFragmentAtom , (*_pMovieFragmentAtomVec)[i-1]); 3798 parseMoofCompletely = true; 3799 moofParsingCompleted = true; 3800 moofSize = 0; 3801 moofType = UNKNOWN_ATOM; 3802 moofCount = 0; 3803 moofPtrPos = 0; 3804 } 3805 } 3806 } 3807 3808 //movie 3809 if (_pmovieAtom != NULL) 3810 { 3811 resetAllMovieFragments(); 3812 uint32 trackVideo = trackID; 3813 uint32 numTrackForVideo = 1; 3814 modifiedTimeStamp = _pmovieAtom->resetPlayback(modifiedTimeStamp, numTrackForVideo, &trackVideo, bResetToIFrame); 3815 } 3816 } 3817 } 3818 retVal = modifiedTimeStamp; 3819 if ((getTrackMediaType(trackID) == MEDIA_TYPE_AUDIO) || 3820 (getTrackMediaType(trackID) == MEDIA_TYPE_TEXT)) 3821 { 3822 if (repositionFromMoof(time, trackID)) 3823 { 3824 oMoofFound = false; 3825 //moof 3826 // convert modifiedTimeStamp (which is in ms) to the appropriate 3827 // media time scale 3828 MediaClockConverter mcc1(1000); 3829 mcc1.update_clock(modifiedTimeStamp); 3830 convertedTS = mcc1.get_converted_ts(getTrackMediaTimescale(trackID)); 3831 if (oMfraFound) 3832 { 3833 for (uint32 idx = 0; idx < _pMovieFragmentRandomAccessAtomVec->size(); idx++) 3834 { 3835 MovieFragmentRandomAccessAtom *pMovieFragmentRandomAccessAtom = (*_pMovieFragmentRandomAccessAtomVec)[idx]; 3836 uint32 ret = pMovieFragmentRandomAccessAtom->getSyncSampleInfoClosestToTime(trackID, convertedTS, moof_offset, traf_number, trun_number, sample_num); 3837 if (ret == 0) 3838 { 3839 if (moofParsingCompleted) 3840 { 3841 // do nothing 3842 } 3843 else 3844 { 3845 uint32 i = _pMovieFragmentAtomVec->size(); 3846 _pMoofOffsetVec->pop_back(); 3847 _pMovieFragmentAtomVec->pop_back(); 3848 PV_MP4_FF_DELETE(NULL, MovieFragmentAtom , (*_pMovieFragmentAtomVec)[i-1]); 3849 parseMoofCompletely = true; 3850 moofParsingCompleted = true; 3851 moofSize = 0; 3852 moofType = UNKNOWN_ATOM; 3853 moofCount = 0; 3854 moofPtrPos = 0; 3855 } 3856 // 3857 for (idx = 0; idx < _pMoofOffsetVec->size(); idx++) 3858 { 3859 uint32 moof_start_offset = (*_pMoofOffsetVec)[idx]; 3860 if (moof_start_offset == moof_offset) 3861 { 3862 _movieFragmentIdx[trackID] = idx; 3863 _peekMovieFragmentIdx[trackID] = idx; 3864 _movieFragmentSeqIdx[trackID] = (*_pMovieFragmentAtomVec)[idx]->getSequenceNumber(); 3865 _peekMovieFragmentSeqIdx[trackID] = _movieFragmentSeqIdx[trackID]; 3866 _pMovieFragmentAtom = (*_pMovieFragmentAtomVec)[idx]; 3867 currMoofNum = _pMovieFragmentAtom->getSequenceNumber(); 3868 oMoofFound = true; 3869 3870 AtomUtils::seekFromStart(_movieFragmentFilePtr, moof_offset); 3871 uint32 atomType = UNKNOWN_ATOM; 3872 uint32 atomSize = 0; 3873 AtomUtils::getNextAtomType(_movieFragmentFilePtr, atomSize, atomType); 3874 if (atomType == MOVIE_FRAGMENT_ATOM) 3875 { 3876 atomSize -= DEFAULT_ATOM_SIZE; 3877 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, atomSize); 3878 _ptrMoofEnds = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr); 3879 } 3880 break; 3881 } 3882 } 3883 // 3884 } 3885 else 3886 { 3887 // Not a valid tfra entries, cannot reposition. 3888 return 0; 3889 } 3890 } 3891 if (_parsing_mode == 1 && !oMoofFound) 3892 { 3893 3894 if (!oMoofFound) 3895 { 3896 _ptrMoofEnds = moof_offset; 3897 uint32 fileSize = 0; 3898 AtomUtils::getCurrentFileSize(_movieFragmentFilePtr, fileSize); 3899 AtomUtils::seekFromStart(_movieFragmentFilePtr, _ptrMoofEnds); 3900 uint32 filePointer = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr); 3901 int32 count = fileSize - filePointer;// -DEFAULT_ATOM_SIZE; 3902 3903 while (count > 0) 3904 { 3905 uint32 atomType = UNKNOWN_ATOM; 3906 uint32 atomSize = 0; 3907 AtomUtils::getNextAtomType(_movieFragmentFilePtr, atomSize, atomType); 3908 if (atomType == MOVIE_FRAGMENT_ATOM) 3909 { 3910 uint32 moofStartOffset = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr); 3911 moofStartOffset -= DEFAULT_ATOM_SIZE; 3912 parseMoofCompletely = true; 3913 3914 if (moofParsingCompleted) 3915 { 3916 // do nothing 3917 } 3918 else 3919 { 3920 uint32 i = _pMovieFragmentAtomVec->size(); 3921 _pMoofOffsetVec->pop_back(); 3922 _pMovieFragmentAtomVec->pop_back(); 3923 PV_MP4_FF_DELETE(NULL, MovieFragmentAtom , (*_pMovieFragmentAtomVec)[i-1]); 3924 parseMoofCompletely = true; 3925 moofParsingCompleted = true; 3926 moofSize = 0; 3927 moofType = UNKNOWN_ATOM; 3928 moofCount = 0; 3929 moofPtrPos = 0; 3930 } 3931 3932 PV_MP4_FF_NEW(_movieFragmentFilePtr->auditCB, MovieFragmentAtom, (_movieFragmentFilePtr, atomSize, atomType, _pTrackDurationContainer, _pTrackExtendsAtomVec, parseMoofCompletely, moofParsingCompleted, countOfTrunsParsed), _pMovieFragmentAtom); 3933 3934 if (!_pMovieFragmentAtom->MP4Success()) 3935 { 3936 _success = false; 3937 _mp4ErrorCode = _pMovieFragmentAtom->GetMP4Error(); 3938 break; 3939 } 3940 3941 _pMovieFragmentAtom->setParent(this); 3942 count -= _pMovieFragmentAtom->getSize(); 3943 uint32 i = _pMovieFragmentAtomVec->size(); 3944 3945 MovieFragmentAtom *pMovieFragmentAtom = NULL; 3946 uint32 prevMoofSeqNum = 0; 3947 3948 if (i > 0) 3949 { 3950 pMovieFragmentAtom = (*_pMovieFragmentAtomVec)[i-1]; 3951 3952 if (pMovieFragmentAtom != NULL) 3953 prevMoofSeqNum = (*_pMovieFragmentAtomVec)[i-1]->getSequenceNumber(); 3954 } 3955 currMoofNum = _pMovieFragmentAtom->getSequenceNumber(); 3956 3957 for (uint32 idx = prevMoofSeqNum; idx < currMoofNum - 1; idx++) 3958 { 3959 _pMovieFragmentAtomVec->push_back(NULL); 3960 _pMoofOffsetVec->push_back(0); 3961 } 3962 3963 if (currMoofNum > i) 3964 { 3965 _pMoofOffsetVec->push_back(moofStartOffset); 3966 _pMovieFragmentAtomVec->push_back(_pMovieFragmentAtom); 3967 } 3968 else if ((*_pMovieFragmentAtomVec)[currMoofNum-1] == NULL) 3969 { 3970 (*_pMovieFragmentAtomVec)[currMoofNum-1] = _pMovieFragmentAtom; 3971 (*_pMoofOffsetVec)[currMoofNum-1] = moofStartOffset; 3972 } 3973 else 3974 { 3975 PV_MP4_FF_DELETE(_movieFragmentFilePtr->auditCB, MovieFragmentAtom, _pMovieFragmentAtom); 3976 _pMovieFragmentAtom = NULL; 3977 break; 3978 3979 } 3980 if (oMfraFound) 3981 { 3982 currMoofNum = _pMovieFragmentAtom->getSequenceNumber(); 3983 _movieFragmentIdx[trackID] = currMoofNum - 1 ; 3984 _peekMovieFragmentIdx[trackID] = currMoofNum - 1; 3985 _movieFragmentSeqIdx[trackID] = currMoofNum; 3986 _peekMovieFragmentSeqIdx[trackID] = _movieFragmentSeqIdx[trackID]; 3987 oMoofFound = true; 3988 if (!_oVideoTrackPresent) 3989 { 3990 _ptrMoofEnds = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr); 3991 } 3992 break; 3993 } 3994 uint32 currTrafDuration = _pMovieFragmentAtom->getCurrentTrafDuration(trackID); 3995 if (currTrafDuration >= modifiedTimeStamp) 3996 { 3997 currMoofNum = _pMovieFragmentAtom->getSequenceNumber(); 3998 _movieFragmentIdx[trackID] = currMoofNum - 1; 3999 _peekMovieFragmentIdx[trackID] = currMoofNum - 1; 4000 _movieFragmentSeqIdx[trackID] = currMoofNum; 4001 _peekMovieFragmentSeqIdx[trackID] = _movieFragmentSeqIdx[trackID]; 4002 oMoofFound = true; 4003 if (!_oVideoTrackPresent) 4004 { 4005 _ptrMoofEnds = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr); 4006 } 4007 break; 4008 } 4009 4010 } 4011 else if (atomType == MEDIA_DATA_ATOM) 4012 { 4013 if (atomSize == 1) 4014 { 4015 uint64 largeSize = 0; 4016 AtomUtils::read64(_movieFragmentFilePtr, largeSize); 4017 uint32 size = 4018 Oscl_Int64_Utils::get_uint64_lower32(largeSize); 4019 count -= size; 4020 size -= 8; //for large size 4021 size -= DEFAULT_ATOM_SIZE; 4022 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, size); 4023 } 4024 else 4025 { 4026 if (atomSize < DEFAULT_ATOM_SIZE) 4027 { 4028 _success = false; 4029 _mp4ErrorCode = ZERO_OR_NEGATIVE_ATOM_SIZE; 4030 break; 4031 } 4032 if (count < (int32)atomSize) 4033 { 4034 _success = false; 4035 _mp4ErrorCode = READ_FAILED; 4036 break; 4037 } 4038 count -= atomSize; 4039 atomSize -= DEFAULT_ATOM_SIZE; 4040 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, atomSize); 4041 } 4042 } 4043 4044 else 4045 { 4046 if (count > 0) 4047 { 4048 count -= atomSize; 4049 atomSize -= DEFAULT_ATOM_SIZE; 4050 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, atomSize); 4051 } 4052 4053 } 4054 } 4055 } 4056 4057 } 4058 4059 if (_pmovieAtom != NULL) 4060 _pmovieAtom->resetTrackToEOT(); 4061 4062 if (_pMovieFragmentAtom != NULL) 4063 returnedTS = _pMovieFragmentAtom->resetPlayback(trackID, convertedTS, traf_number, trun_number, sample_num); 4064 } 4065 else 4066 return 0; 4067 4068 // convert returnedTS (which is in media time scale) to the ms 4069 MediaClockConverter mcc(getTrackMediaTimescale(trackID)); 4070 mcc.update_clock(returnedTS); 4071 timestamp = mcc.get_converted_ts(1000); 4072 4073 4074 if (timestamp <= modifiedTimeStamp) 4075 { 4076 modifiedTimeStamp = timestamp; 4077 } 4078 retVal = modifiedTimeStamp; 4079 4080 } 4081 else 4082 { 4083 if (_isMovieFragmentsPresent) 4084 { 4085 if (_pMovieFragmentAtomVec->size() > 0) 4086 { 4087 if (moofParsingCompleted) 4088 { 4089 // do nothing 4090 } 4091 else 4092 { 4093 uint32 i = _pMovieFragmentAtomVec->size(); 4094 _pMoofOffsetVec->pop_back(); 4095 _pMovieFragmentAtomVec->pop_back(); 4096 PV_MP4_FF_DELETE(NULL, MovieFragmentAtom , (*_pMovieFragmentAtomVec)[i-1]); 4097 parseMoofCompletely = true; 4098 moofParsingCompleted = true; 4099 moofSize = 0; 4100 moofType = UNKNOWN_ATOM; 4101 moofCount = 0; 4102 moofPtrPos = 0; 4103 } 4104 } 4105 } 4106 4107 //movie 4108 if (_pmovieAtom != NULL) 4109 { 4110 resetAllMovieFragments(); 4111 uint32 trackAudio = trackID; 4112 uint32 numTrackforAudio = 1; 4113 retVal = _pmovieAtom->resetPlayback(modifiedTimeStamp, numTrackforAudio, &trackAudio 4114 , bResetToIFrame); 4115 } 4116 } 4117 4118 } 4119 return retVal; 4120 4121 } 4122 4123 4124 4125 int32 Mpeg4File::queryRepositionTime(uint32 time, 4126 uint16 numTracks, 4127 uint32 *trackList, 4128 bool bResetToIFrame, 4129 bool bBeforeRequestedTime) 4130 { 4131 4132 uint32 i = 0; 4133 uint32 ret = 0; 4134 uint32 modifiedTimeStamp = time; 4135 uint32 trackID = 0; 4136 uint32 trackIds[256]; 4137 4138 bool oVideoTrackFound = false; 4139 int j = 1; 4140 for (i = 0; i < numTracks; i++) 4141 { 4142 trackID = trackList[i]; 4143 if (getTrackMediaType(trackID) == MEDIA_TYPE_VISUAL) 4144 { 4145 trackIds[0] = trackList[i]; 4146 oVideoTrackFound = true; 4147 } 4148 else 4149 { 4150 trackIds[j++] = trackList[i]; 4151 } 4152 } 4153 4154 uint32 convertedTS = 0; 4155 uint32 timestamp = 0, returnedTS = 0; 4156 4157 for (i = 0; i < numTracks; i++) 4158 { 4159 trackID = trackIds[i]; 4160 4161 if (!oVideoTrackFound) 4162 trackID = trackList[i]; 4163 4164 if (getTrackMediaType(trackID) == MEDIA_TYPE_VISUAL) 4165 { 4166 if (repositionFromMoof(time, trackID)) 4167 { 4168 //moof 4169 modifiedTimeStamp = time; 4170 4171 // convert modifiedTimeStamp (which is in ms) to the appropriate 4172 // media time scale 4173 MediaClockConverter mcc1(1000); 4174 mcc1.update_clock(modifiedTimeStamp); 4175 convertedTS = mcc1.get_converted_ts(getTrackMediaTimescale(trackID)); 4176 if (oMfraFound) 4177 { 4178 oMfraFound = true; 4179 for (uint32 idx = 0; idx < _pMovieFragmentRandomAccessAtomVec->size(); idx++) 4180 { 4181 4182 MovieFragmentRandomAccessAtom *pMovieFragmentRandomAccessAtom = (*_pMovieFragmentRandomAccessAtomVec)[idx]; 4183 returnedTS = pMovieFragmentRandomAccessAtom->queryRepositionTime(trackID, convertedTS, bResetToIFrame, 4184 bBeforeRequestedTime); 4185 if (returnedTS != 0) 4186 { 4187 break; 4188 } 4189 } 4190 } 4191 else 4192 { 4193 oMfraFound = false; 4194 if (_parsing_mode == 1) 4195 return -1; 4196 } 4197 4198 // convert returnedTS (which is in media time scale) to the ms 4199 MediaClockConverter mcc(getTrackMediaTimescale(trackID)); 4200 mcc.update_clock(returnedTS); 4201 timestamp = mcc.get_converted_ts(1000); 4202 4203 modifiedTimeStamp = timestamp; 4204 4205 ret = modifiedTimeStamp; 4206 4207 } 4208 else 4209 { 4210 //movie 4211 if (_pmovieAtom != NULL) 4212 { 4213 modifiedTimeStamp = _pmovieAtom->queryRepositionTime(time, 4214 numTracks, 4215 trackList, 4216 bResetToIFrame, 4217 bBeforeRequestedTime); 4218 ret = modifiedTimeStamp; 4219 } 4220 } 4221 } 4222 4223 if ((getTrackMediaType(trackID) == MEDIA_TYPE_AUDIO) || 4224 (getTrackMediaType(trackID) == MEDIA_TYPE_TEXT)) 4225 { 4226 if (repositionFromMoof(time, trackID)) 4227 { 4228 //moof 4229 MediaClockConverter mcc1(1000); 4230 mcc1.update_clock(modifiedTimeStamp); 4231 convertedTS = mcc1.get_converted_ts(getTrackMediaTimescale(trackID)); 4232 4233 for (uint32 idx = 0; idx < _pMovieFragmentRandomAccessAtomVec->size(); idx++) 4234 { 4235 4236 MovieFragmentRandomAccessAtom *pMovieFragmentRandomAccessAtom = (*_pMovieFragmentRandomAccessAtomVec)[idx]; 4237 returnedTS = pMovieFragmentRandomAccessAtom->queryRepositionTime(trackID, convertedTS, bResetToIFrame, 4238 bBeforeRequestedTime); 4239 if (returnedTS != 0) 4240 { 4241 break; 4242 } 4243 } 4244 // convert returnedTS (which is in media time scale) to the ms 4245 MediaClockConverter mcc(getTrackMediaTimescale(trackID)); 4246 mcc.update_clock(returnedTS); 4247 timestamp = mcc.get_converted_ts(1000); 4248 4249 if (!oVideoTrackFound) 4250 { 4251 if (getTrackMediaType(trackID) == MEDIA_TYPE_AUDIO) 4252 { 4253 modifiedTimeStamp = timestamp; 4254 } 4255 else if (getTrackMediaType(trackID) == MEDIA_TYPE_TEXT && numTracks == 1) 4256 { 4257 modifiedTimeStamp = timestamp; 4258 } 4259 } 4260 4261 return modifiedTimeStamp; 4262 4263 } 4264 else 4265 { 4266 //movie 4267 if (_pmovieAtom != NULL) 4268 { 4269 modifiedTimeStamp = _pmovieAtom->queryRepositionTime(modifiedTimeStamp, 4270 numTracks, 4271 trackList, 4272 bResetToIFrame, 4273 bBeforeRequestedTime); 4274 4275 if (!oVideoTrackFound) 4276 { 4277 if (getTrackMediaType(trackID) == MEDIA_TYPE_AUDIO) 4278 { 4279 ret = modifiedTimeStamp; 4280 } 4281 else if (getTrackMediaType(trackID) == MEDIA_TYPE_TEXT && numTracks == 1) 4282 { 4283 ret = modifiedTimeStamp; 4284 } 4285 } 4286 } 4287 4288 } 4289 4290 } 4291 } 4292 return ret; 4293 } 4294 4295 4296 4297 int32 Mpeg4File::parseMFRA() 4298 { 4299 uint32 ret = 0; 4300 uint32 fileSize = 0; 4301 uint32 MfraStartOffset = 0; 4302 AtomUtils::getCurrentFileSize(_movieFragmentFilePtr, fileSize); 4303 AtomUtils::seekFromStart(_movieFragmentFilePtr, fileSize); 4304 AtomUtils::rewindFilePointerByN(_movieFragmentFilePtr, 16); 4305 4306 uint32 atomType = UNKNOWN_ATOM; 4307 uint32 atomSize = 0; 4308 AtomUtils::getNextAtomType(_movieFragmentFilePtr, atomSize, atomType); 4309 4310 if (atomType == MOVIE_FRAGMENT_RANDOM_ACCESS_OFFSET_ATOM) 4311 { 4312 if (_pMfraOffsetAtom == NULL) 4313 { 4314 PV_MP4_FF_NEW(fp->auditCB, MfraOffsetAtom, (_movieFragmentFilePtr, atomSize, atomType), _pMfraOffsetAtom); 4315 if (!_pMfraOffsetAtom->MP4Success()) 4316 { 4317 _success = false; 4318 _mp4ErrorCode = READ_MOVIE_FRAGMENT_RANDOM_ACCESS_OFFSET_FAILED; 4319 return _mp4ErrorCode; 4320 } 4321 MfraStartOffset = _pMfraOffsetAtom->getSizeStoredInmfro(); 4322 4323 } 4324 } 4325 AtomUtils::rewindFilePointerByN(_movieFragmentFilePtr, MfraStartOffset); 4326 AtomUtils::getNextAtomType(_movieFragmentFilePtr, atomSize, atomType); 4327 if (atomType == MOVIE_FRAGMENT_RANDOM_ACCESS_ATOM) 4328 { 4329 if (_pMovieFragmentRandomAccessAtomVec->size() == 0) 4330 { 4331 MovieFragmentRandomAccessAtom *pMovieFragmentRandomAccessAtom = NULL; 4332 PV_MP4_FF_NEW(fp->auditCB, MovieFragmentRandomAccessAtom, (_movieFragmentFilePtr, atomSize, atomType), pMovieFragmentRandomAccessAtom); 4333 4334 if (!pMovieFragmentRandomAccessAtom->MP4Success()) 4335 { 4336 PV_MP4_FF_DELETE(NULL, MovieFragmentRandomAccessAtom, pMovieFragmentRandomAccessAtom); 4337 _success = false; 4338 _mp4ErrorCode = pMovieFragmentRandomAccessAtom->GetMP4Error(); 4339 return _mp4ErrorCode ; 4340 } 4341 pMovieFragmentRandomAccessAtom->setParent(this); 4342 _pMovieFragmentRandomAccessAtomVec->push_back(pMovieFragmentRandomAccessAtom); 4343 oMfraFound = true; 4344 } 4345 } 4346 4347 return ret; 4348 4349 } 4350 4351 4352 int32 Mpeg4File::peekNextBundledAccessUnits(const uint32 trackID, 4353 uint32 *n, 4354 MediaMetaInfo *mInfo) 4355 { 4356 // IF THERE ARE NO MEDIA TRACKS, RETURN READ ERROR 4357 uint32 samplesTobeRead; 4358 samplesTobeRead = *n; 4359 uint32 totalSampleRead = 0; 4360 if (getNumTracks() == 0) 4361 { 4362 return -1; 4363 } 4364 if (_pmovieAtom != NULL) 4365 { 4366 uint32 ret = (_pmovieAtom->peekNextBundledAccessUnits(trackID, n, mInfo)); 4367 if (ret == END_OF_TRACK) 4368 { 4369 if (!_isMovieFragmentsPresent) 4370 return ret; 4371 4372 bool oAllMoofExhausted = false; 4373 4374 totalSampleRead += *n; 4375 4376 if (totalSampleRead == samplesTobeRead) 4377 { 4378 *n = totalSampleRead; 4379 return EVERYTHING_FINE; 4380 } 4381 4382 if (_pMovieFragmentAtomVec != NULL) 4383 { 4384 if (samplesTobeRead >= *n) 4385 *n = samplesTobeRead - *n; 4386 if (*n == 0) 4387 *n = samplesTobeRead; 4388 } 4389 else 4390 return ret; 4391 4392 if (_parsing_mode == 0) 4393 { 4394 int32 return1 = 0; 4395 while (_peekMovieFragmentIdx[trackID] < _pMovieFragmentAtomVec->size()) 4396 { 4397 uint32 peekMovieFragmentIdx = _peekMovieFragmentIdx[trackID]; 4398 MovieFragmentAtom *pMovieFragmentAtom = (*_pMovieFragmentAtomVec)[peekMovieFragmentIdx]; 4399 if (pMovieFragmentAtom != NULL) 4400 { 4401 if ((uint32)pMovieFragmentAtom->getSequenceNumber() == _peekMovieFragmentSeqIdx[trackID]) 4402 { 4403 TrackFragmentAtom *trackfragment = pMovieFragmentAtom->getTrackFragmentforID(trackID); 4404 if (trackfragment != NULL) 4405 { 4406 if (trackfragment->getTrackId() == trackID) 4407 { 4408 return1 = pMovieFragmentAtom->peekNextBundledAccessUnits(trackID, n, totalSampleRead, mInfo); 4409 totalSampleRead += *n; 4410 if (return1 != END_OF_TRACK) 4411 { 4412 *n = totalSampleRead; 4413 return return1; 4414 } 4415 else 4416 { 4417 _peekMovieFragmentSeqIdx[trackID]++; 4418 if (samplesTobeRead >= *n) 4419 { 4420 samplesTobeRead = samplesTobeRead - *n; 4421 *n = samplesTobeRead; 4422 } 4423 } 4424 } 4425 } 4426 } 4427 } 4428 _peekMovieFragmentIdx[trackID]++; 4429 } 4430 if (return1 == END_OF_TRACK) 4431 { 4432 *n = totalSampleRead; 4433 _peekMovieFragmentIdx[trackID] = 0; 4434 _peekMovieFragmentSeqIdx[trackID] = 1; 4435 return return1; 4436 } 4437 } 4438 else 4439 { 4440 4441 while (!oAllMoofExhausted) 4442 { 4443 uint32 moofIndex = 0; 4444 bool moofToBeParsed = false; 4445 4446 if (_pMovieFragmentAtomVec->size() > _peekMovieFragmentIdx[trackID]) 4447 { 4448 MovieFragmentAtom *pMovieFragmentAtom = NULL; 4449 pMovieFragmentAtom = (*_pMovieFragmentAtomVec)[_peekMovieFragmentIdx[trackID]]; 4450 if (pMovieFragmentAtom == NULL) 4451 { 4452 moofToBeParsed = true; 4453 moofIndex = _peekMovieFragmentIdx[trackID]; 4454 } 4455 } 4456 if ((_pMovieFragmentAtomVec->size() <= _peekMovieFragmentIdx[trackID]) || moofToBeParsed) 4457 { 4458 uint32 fileSize = 0; 4459 AtomUtils::getCurrentFileSize(_movieFragmentFilePtr, fileSize); 4460 AtomUtils::seekFromStart(_movieFragmentFilePtr, _ptrMoofEnds); 4461 uint32 filePointer = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr); 4462 int32 count = fileSize - filePointer;// -DEFAULT_ATOM_SIZE; 4463 4464 while (count > 0) 4465 { 4466 uint32 atomType = UNKNOWN_ATOM; 4467 uint32 atomSize = 0; 4468 uint32 currPos = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr); 4469 AtomUtils::getNextAtomType(_movieFragmentFilePtr, atomSize, atomType); 4470 if ((currPos + atomSize) > fileSize) 4471 { 4472 AtomUtils::seekFromStart(_movieFragmentFilePtr, currPos); 4473 return INSUFFICIENT_DATA; 4474 } 4475 if (atomType == MOVIE_FRAGMENT_ATOM) 4476 { 4477 uint32 moofStartOffset = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr); 4478 moofStartOffset -= DEFAULT_ATOM_SIZE; 4479 4480 parseMoofCompletely = true; 4481 4482 PV_MP4_FF_NEW(_movieFragmentFilePtr->auditCB, MovieFragmentAtom, (_movieFragmentFilePtr, atomSize, atomType, _pTrackDurationContainer, _pTrackExtendsAtomVec, parseMoofCompletely, moofParsingCompleted, countOfTrunsParsed), _pMovieFragmentAtom); 4483 4484 if (!_pMovieFragmentAtom->MP4Success()) 4485 { 4486 _success = false; 4487 _mp4ErrorCode = _pMovieFragmentAtom->GetMP4Error(); 4488 oAllMoofExhausted = true; 4489 break; 4490 } 4491 _pMovieFragmentAtom->setParent(this); 4492 count -= _pMovieFragmentAtom->getSize(); 4493 if (moofToBeParsed) 4494 { 4495 (*_pMovieFragmentAtomVec)[moofIndex] = _pMovieFragmentAtom; 4496 (*_pMoofOffsetVec)[moofIndex] = moofStartOffset; 4497 } 4498 else 4499 { 4500 _pMoofOffsetVec->push_back(moofStartOffset); 4501 _pMovieFragmentAtomVec->push_back(_pMovieFragmentAtom); 4502 } 4503 _ptrMoofEnds = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr); 4504 4505 break; 4506 } 4507 else if (atomType == MEDIA_DATA_ATOM) 4508 { 4509 if (atomSize == 1) 4510 { 4511 uint64 largeSize = 0; 4512 AtomUtils::read64(_movieFragmentFilePtr, largeSize); 4513 uint32 size = 4514 Oscl_Int64_Utils::get_uint64_lower32(largeSize); 4515 count -= size; 4516 size -= 8; //for large size 4517 size -= DEFAULT_ATOM_SIZE; 4518 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, size); 4519 } 4520 else 4521 { 4522 if (atomSize < DEFAULT_ATOM_SIZE) 4523 { 4524 _success = false; 4525 oAllMoofExhausted = true; 4526 _mp4ErrorCode = ZERO_OR_NEGATIVE_ATOM_SIZE; 4527 break; 4528 } 4529 if (count < (int32)atomSize) 4530 { 4531 _success = false; 4532 oAllMoofExhausted = true; 4533 _mp4ErrorCode = INSUFFICIENT_DATA; 4534 AtomUtils::seekFromStart(_movieFragmentFilePtr, currPos); 4535 ret = _mp4ErrorCode; 4536 break; 4537 } 4538 count -= atomSize; 4539 atomSize -= DEFAULT_ATOM_SIZE; 4540 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, atomSize); 4541 } 4542 } 4543 4544 else 4545 { 4546 if (count > 0) 4547 { 4548 count -= atomSize; 4549 atomSize -= DEFAULT_ATOM_SIZE; 4550 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, atomSize); 4551 } 4552 break; 4553 } 4554 } 4555 if (count <= 0) 4556 { 4557 oAllMoofExhausted = true; 4558 if (_pMovieFragmentAtomVec->size() < _peekMovieFragmentIdx[trackID]) 4559 break; 4560 } 4561 } 4562 4563 int32 return1 = 0; 4564 MovieFragmentAtom *pMovieFragmentAtom = NULL; 4565 uint32 movieFragmentIdx = _peekMovieFragmentIdx[trackID]; 4566 4567 if (movieFragmentIdx < _pMovieFragmentAtomVec->size()) 4568 pMovieFragmentAtom = (*_pMovieFragmentAtomVec)[movieFragmentIdx]; 4569 4570 if (pMovieFragmentAtom != NULL) 4571 { 4572 uint32 seqNum = pMovieFragmentAtom->getSequenceNumber(); 4573 if (seqNum == _peekMovieFragmentSeqIdx[trackID]) 4574 { 4575 TrackFragmentAtom *trackfragment = pMovieFragmentAtom->getTrackFragmentforID(trackID); 4576 if (trackfragment != NULL) 4577 { 4578 if (trackfragment->getTrackId() == trackID) 4579 { 4580 return1 = pMovieFragmentAtom->peekNextBundledAccessUnits(trackID, n, totalSampleRead, mInfo); 4581 totalSampleRead += *n; 4582 if (return1 != END_OF_TRACK) 4583 { 4584 *n = totalSampleRead; 4585 return return1; 4586 } 4587 else 4588 { 4589 _peekMovieFragmentSeqIdx[trackID]++; 4590 if (samplesTobeRead >= *n) 4591 { 4592 samplesTobeRead = samplesTobeRead - *n; 4593 *n = samplesTobeRead; 4594 } 4595 } 4596 } 4597 } 4598 else 4599 { 4600 _peekMovieFragmentIdx[trackID]++; 4601 _peekMovieFragmentSeqIdx[trackID]++; 4602 *n = 0; 4603 return NO_SAMPLE_IN_CURRENT_MOOF; 4604 } 4605 } 4606 } 4607 _peekMovieFragmentIdx[trackID]++; 4608 4609 } 4610 } 4611 } 4612 return ret; 4613 } 4614 else 4615 { 4616 return -1; 4617 } 4618 } 4619 4620 4621 uint32 Mpeg4File::getSampleCountInTrack(uint32 id) 4622 { 4623 uint32 nTotalSamples = 0; 4624 if (_pmovieAtom != NULL) 4625 { 4626 nTotalSamples = (_pmovieAtom->getSampleCountInTrack(id)); 4627 if (!_isMovieFragmentsPresent) 4628 return nTotalSamples; 4629 4630 if (_parsing_mode == 0) 4631 { 4632 if (_pMovieFragmentAtomVec->size() > 0) 4633 { 4634 for (uint32 idx = 0; idx < _pMovieFragmentAtomVec->size(); idx++) 4635 { 4636 MovieFragmentAtom *pMovieFragmentAtom = (*_pMovieFragmentAtomVec)[idx]; 4637 if (pMovieFragmentAtom != NULL) 4638 { 4639 nTotalSamples += pMovieFragmentAtom->getTotalSampleInTraf(id); 4640 } 4641 } 4642 return nTotalSamples; 4643 } 4644 } 4645 return nTotalSamples; 4646 } 4647 return 0; 4648 } 4649 4650 4651 bool Mpeg4File::IsTFRAPresentForTrack(uint32 TrackId, bool oVideoAudioTextTrack) 4652 { 4653 if (_pMovieFragmentRandomAccessAtomVec != NULL) 4654 { 4655 for (uint32 idx = 0; idx < _pMovieFragmentRandomAccessAtomVec->size(); idx++) 4656 { 4657 4658 MovieFragmentRandomAccessAtom *pMovieFragmentRandomAccessAtom = (*_pMovieFragmentRandomAccessAtomVec)[idx]; 4659 return pMovieFragmentRandomAccessAtom->IsTFRAPresentForTrack(TrackId, oVideoAudioTextTrack); 4660 } 4661 } 4662 return false; 4663 } 4664 4665 4666 /* 4667 This function has been modified to check the entry count in TFRA for all tracks are equal. 4668 The code change is under macro DISABLE_REPOS_ON_CLIPS_HAVING_UNEQUAL_TFRA_ENTRY_COUNT 4669 */ 4670 bool Mpeg4File::IsTFRAPresentForAllTrack(uint32 numTracks, uint32 *trackList) 4671 { 4672 4673 #if (DISABLE_REPOS_ON_CLIPS_HAVING_UNEQUAL_TFRA_ENTRY_COUNT) 4674 bool oVideoAudioTextTrack = false; 4675 // This flag will be true for Video in AVT,VT & AV and for Audio in AT. 4676 // Based on this flag IsTFRAPresentForTrack() functions behaviour is changing 4677 // We are comparing the entry count for all the tracks to entry count of V in case of Vonly,AVT,VT & AV clips 4678 // and in case of Aonly & AT clips, entry count for all the tracks is compared with entry count of audio. For Tonly 4679 // clips, entry count for text track is compared with its own entry count. 4680 4681 // Support for clips having Video track. 4682 for (int32 i = 0; i < numTracks; i++) 4683 { 4684 uint32 trackID = trackList[i]; 4685 if (getTrackMediaType(trackID) == MEDIA_TYPE_VISUAL) 4686 { 4687 oVideoAudioTextTrack = true; 4688 if (IsTFRAPresentForTrack(trackID, oVideoAudioTextTrack) == false) 4689 { 4690 return false; 4691 } 4692 break; 4693 } 4694 } 4695 // Support for clips having Audio track and no Video track. 4696 if (!oVideoAudioTextTrack) 4697 { 4698 for (int32 i = 0; i < numTracks; i++) 4699 { 4700 uint32 trackID = trackList[i]; 4701 if (getTrackMediaType(trackID) == MEDIA_TYPE_AUDIO) 4702 { 4703 oVideoAudioTextTrack = true; 4704 if (IsTFRAPresentForTrack(trackID, oVideoAudioTextTrack) == false) 4705 { 4706 return false; 4707 } 4708 break; 4709 } 4710 } 4711 } 4712 // Support for clips having only Text track. 4713 if (!oVideoAudioTextTrack && numTracks == 1) 4714 { 4715 for (uint32 i = 0; i < numTracks; i++) 4716 { 4717 uint32 trackID = trackList[i]; 4718 if (getTrackMediaType(trackID) == MEDIA_TYPE_TEXT) 4719 { 4720 oVideoAudioTextTrack = true; 4721 if (IsTFRAPresentForTrack(trackID, oVideoAudioTextTrack) == false) 4722 { 4723 return false; 4724 } 4725 break; 4726 } 4727 } 4728 } 4729 #endif // DISABLE_REPOS_ON_CLIPS_HAVING_UNEQUAL_TFRA_ENTRY_COUNT 4730 for (uint32 idx = 0; idx < numTracks; idx++) 4731 { 4732 uint32 trackID = trackList[idx]; 4733 // second argument is false always 4734 if (IsTFRAPresentForTrack(trackID, false) == false) 4735 { 4736 return false; 4737 } 4738 } 4739 return true; 4740 } 4741 4742 void Mpeg4File::resetPlayback() 4743 { 4744 if (_pmovieAtom == NULL) 4745 return; 4746 4747 _pmovieAtom->resetPlayback(); 4748 4749 if (_isMovieFragmentsPresent) 4750 { 4751 if (_pMovieFragmentAtomVec != NULL) 4752 { 4753 int numTracks = _pmovieAtom->getNumTracks(); 4754 uint32 *trackList = (uint32 *) oscl_malloc(sizeof(uint32) * numTracks); 4755 if (!trackList) 4756 return; // malloc failed 4757 4758 _pmovieAtom->getTrackWholeIDList(trackList); 4759 for (int i = 0; i < numTracks; i++) 4760 { 4761 uint32 trackID = trackList[i]; 4762 _peekMovieFragmentIdx[trackID] = 0; 4763 _movieFragmentIdx[trackID] = 0; 4764 _movieFragmentSeqIdx[trackID] = 1; 4765 _peekMovieFragmentSeqIdx[trackID] = 1; 4766 } 4767 oscl_free(trackList); 4768 for (uint32 idx = 0; idx < _pMovieFragmentAtomVec->size(); idx++) 4769 { 4770 MovieFragmentAtom *pMovieFragmentAtom = (*_pMovieFragmentAtomVec)[idx]; 4771 if (pMovieFragmentAtom != NULL) 4772 pMovieFragmentAtom->resetPlayback(); 4773 4774 } 4775 } 4776 } 4777 } 4778 4779 uint32 Mpeg4File::repositionFromMoof(uint32 time, uint32 trackID) 4780 { 4781 uint32 modifiedTimeStamp = time; 4782 uint32 convertedTS = 0; 4783 uint32 trackDuration = Oscl_Int64_Utils::get_uint64_lower32(getTrackMediaDurationForMovie(trackID));//getMovieDuration() - getMovieFragmentDuration(); 4784 4785 MediaClockConverter mcc1(1000); 4786 mcc1.update_clock(modifiedTimeStamp); 4787 convertedTS = mcc1.get_converted_ts(getTrackMediaTimescale(trackID)); 4788 4789 if (_isMovieFragmentsPresent) 4790 { 4791 if (IsTFRAPresentForTrack(trackID, false) == false) 4792 { 4793 return 0; 4794 } 4795 if (modifiedTimeStamp >= trackDuration) 4796 { 4797 return 1; //repos in moof 4798 } 4799 } 4800 return 0; //repos in moov 4801 } 4802 4803 MP4_ERROR_CODE Mpeg4File::CancelNotificationSync() 4804 { 4805 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "Mpeg4File::CancelNotificationSync")); 4806 4807 bool retVal = _commonFilePtr->_pvfile.CancelNotificationSync(); 4808 4809 if (retVal) 4810 { 4811 return EVERYTHING_FINE; 4812 } 4813 else 4814 { 4815 return DEFAULT_ERROR; 4816 } 4817 } 4818 4819 bool Mpeg4File::CreateDataStreamSessionForExternalDownload(OSCL_wString& aFilename, 4820 PVMFCPMPluginAccessInterfaceFactory* aCPMAccessFactory, 4821 OsclFileHandle* aHandle, 4822 Oscl_FileServer* aFileServSession) 4823 { 4824 OsclAny*ptr = oscl_malloc(sizeof(MP4_FF_FILE)); 4825 if (ptr == NULL) 4826 { 4827 _success = false; 4828 _mp4ErrorCode = MEMORY_ALLOCATION_FAILED; 4829 return false; 4830 } 4831 _commonFilePtr = OSCL_PLACEMENT_NEW(ptr, MP4_FF_FILE()); 4832 4833 if (_commonFilePtr != NULL) 4834 { 4835 _commonFilePtr->_fileServSession = aFileServSession; 4836 _commonFilePtr->_pvfile.SetCPM(aCPMAccessFactory); 4837 _commonFilePtr->_pvfile.SetFileHandle(aHandle); 4838 4839 if (AtomUtils::OpenMP4File(aFilename, 4840 Oscl_File::MODE_READ | Oscl_File::MODE_BINARY, 4841 _commonFilePtr) != 0) 4842 { 4843 return false; 4844 } 4845 4846 uint32 fileSize; 4847 AtomUtils::getCurrentFileSize(_commonFilePtr, fileSize); 4848 _commonFilePtr->_fileSize = (int32)fileSize; 4849 } 4850 return true; 4851 } 4852 4853 void Mpeg4File::DestroyDataStreamForExternalDownload() 4854 { 4855 if (_commonFilePtr != NULL) 4856 { 4857 if (_commonFilePtr->IsOpen()) 4858 { 4859 AtomUtils::CloseMP4File(_commonFilePtr); 4860 } 4861 oscl_free(_commonFilePtr); 4862 _commonFilePtr = NULL; 4863 } 4864 } 4865 4866 //Below APIs are used to supress Warning 4867 void Mpeg4File::ReserveMemoryForLangCodeVector(Oscl_Vector<uint16, OsclMemAllocator> &iLangCode, int32 capacity, int32 &leavecode) 4868 { 4869 leavecode = 0; 4870 OSCL_TRY(leavecode, iLangCode.reserve(capacity)); 4871 4872 } 4873 4874 void Mpeg4File::ReserveMemoryForValuesVector(Oscl_Vector<OSCL_wHeapString<OsclMemAllocator>, OsclMemAllocator> &iValues, int32 capacity, int32 &leavecode) 4875 { 4876 leavecode = 0; 4877 OSCL_TRY(leavecode, iValues.reserve(capacity)); 4878 4879 } 4880 4881 4882