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 // -*- c++ -*- 19 // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 20 // 21 // M P 3 P A R S E R 22 // 23 // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 24 25 26 /** 27 * @file mp3parser.cpp 28 * @brief This file contains the implementation of the actual MP3 29 * file parser. 30 */ 31 /*********************************************************************** 32 * Include Files 33 ***********************************************************************/ 34 #include "mp3parser.h" 35 #include "mp3fileio.h" 36 37 #include "oscl_mem.h" 38 #include "oscl_stdstring.h" 39 #include "oscl_utf8conv.h" 40 41 /*********************************************************************** 42 * Constant Defines 43 ***********************************************************************/ 44 // Maximum debug message length 45 #define KMAXMSGSIZE 1024 46 #define KMAX_MP3FRAME_LENGTH_IN_BYTES 2884 47 // Initial search range, resetted to the file size once valid mp3 48 // frame is found 49 #define KMAX_INITIAL_SEARCH_FILE_SIZE_IN_BYTES 500000 50 // If the Xing header reports a size that is smaller than the file length 51 // by this much, consider the Xing header invalid. 52 #define XING_SIZE_FUZZINESS 0.90 53 54 /*********************************************************************** 55 * Global constant definitions 56 ***********************************************************************/ 57 58 /*********************************************************************** 59 * XING VBR Header Constants 60 ***********************************************************************/ 61 static const uint32 FRAMES_FLAG = 0x0001; 62 static const uint32 BYTES_FLAG = 0x0002; 63 static const uint32 TOC_FLAG = 0x0004; 64 static const uint32 VBR_SCALE_FLAG = 0x0008; 65 static const uint32 FRAMES_AND_BYTES = (FRAMES_FLAG | BYTES_FLAG); 66 67 static const uint8 MPEG_LAYER_I = 0x03; 68 static const uint8 MPEG_LAYER_II = 0x02; 69 static const uint8 MPEG_LAYER_III = 0X01; 70 71 static const uint8 CHANNEL_MODE_JOINT_STEREO = 0x01; 72 static const uint8 CHANNEL_MODE_STEREO = 0x00; 73 static const uint8 CHANNEL_MODE_DUAL_CHANNEL = 0x02; 74 static const uint8 CHANNEL_MODE_MONO = 0x03; 75 76 static const uint8 FRAME_VESION_MPEG_1 = 0x03; 77 static const uint8 FRAME_VESION_MPEG_2 = 0x02; 78 static const uint8 FRAME_VESION_MPEG_2_5 = 0x00; 79 80 static const uint8 MP3_FRAME_HEADER_SIZE = 0x04; 81 static const uint32 MP3_FIRST_FRAME_SIZE = 128; 82 /*********************************************************************** 83 * End XING VBR Header Constants 84 ***********************************************************************/ 85 86 /*********************************************************************** 87 * MP3 Frame Header Constants 88 ***********************************************************************/ 89 // MP3 Frame Header Format 90 // AAAAAAAA AAABBCCD EEEEFFGH IIJJKLMM 91 // Bits 31-21 (A) 92 static const uint32 FRAME_SYNC_MASK = 0xFFE00000; 93 static const uint32 FRAME_SYNC_SHIFT = 21; 94 95 // Bits 20-19 (B) 96 static const uint32 FRAME_VER_ID_MASK = 0x00180000; 97 static const uint32 FRAME_VER_ID_SHIFT = 19; 98 99 // Bits 18-17 (C) 100 static const uint32 FRAME_LAYER_ID_MASK = 0x00060000; 101 static const uint32 FRAME_LAYER_ID_SHIFT = 17; 102 103 // Bits 16 (D) 104 static const uint32 FRAME_PROT_MASK = 0x00010000; 105 static const uint32 FRAME_PROT_SHIFT = 16; 106 107 // Bits 15-12 (E) 108 static const uint32 FRAME_BR_INDEX_MASK = 0x0000F000; 109 static const uint32 FRAME_BR_INDEX_SHIFT = 12; 110 111 // Bits 11-10 (F) 112 static const uint32 FRAME_SR_FREQ_MASK = 0x00000C00; 113 static const uint32 FRAME_SR_FREQ_SHIFT = 10; 114 115 // Bits 9 (G) 116 static const uint32 FRAME_PADDING_MASK = 0x00000200; 117 static const uint32 FRAME_PADDING_SHIFT = 9; 118 119 // Bits 8 (H) 120 static const uint32 FRAME_PRIVATE_MASK = 0x00000100; 121 static const uint32 FRAME_PRIVATE_SHIFT = 8; 122 123 // Bits 7-6 (I) 124 static const uint32 FRAME_CH_MODE_MASK = 0x000000C0; 125 static const uint32 FRAME_CH_MODE_SHIFT = 6; 126 127 // Bits 5-4 (J) 128 static const uint32 FRAME_MODE_EXTN_MASK = 0x00000030; 129 static const uint32 FRAME_MODE_EXTN_SHIFT = 4; 130 131 // Bits 3 (K) 132 static const uint32 FRAME_COPYRIGHT_MASK = 0x00000008; 133 static const uint32 FRAME_COPYRIGHT_SHIFT = 3; 134 135 // Bits 2 (L) 136 static const uint32 FRAME_ORIGINAL_MASK = 0x00000004; 137 static const uint32 FRAME_ORIGINAL_SHIFT = 2; 138 139 // Bits 1-0 (M) 140 static const uint32 FRAME_EMPHASIS_MASK = 0x00000003; 141 static const uint32 FRAME_EMPHASIS_SHIFT = 0; 142 /*********************************************************************** 143 * End MP3 Frame Header Constants 144 ***********************************************************************/ 145 146 /*********************************************************************** 147 * BitRate Index Table (Version 1) 148 ***********************************************************************/ 149 static const int32 brIndexTableV1[4][16] = 150 { 151 // RESERVED 152 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 153 // Version 1, Layer III 154 {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0}, 155 // Version 1, Layer II 156 {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0}, 157 // Version 1, Layer I 158 {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0} 159 }; 160 161 /*********************************************************************** 162 * BitRate Index Table (Versions 2 and 2.5) 163 ***********************************************************************/ 164 static const int32 brIndexTableV2[4][16] = 165 { 166 // RESERVED 167 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 168 // Version 2, Layer III 169 {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0}, 170 // Version 2, Layer II 171 {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0}, 172 // Version 2, Layer I 173 {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0} 174 }; 175 176 /*********************************************************************** 177 * SampleRate Index Table 178 ***********************************************************************/ 179 static const int32 srIndexTable[] = 180 { 181 // MPEG 2.5 182 11025, 12000, 8000, 0, 183 // RESERVED 184 0, 0, 0, 0, 185 // MPEG 2 186 22050, 24000, 16000, 0, 187 // MPEG 1 188 44100, 48000, 32000, 0 189 }; 190 191 /*********************************************************************** 192 * FrameRate Index Table 10 * sample rate / samples per frame 193 ***********************************************************************/ 194 static const int32 frIndexTable[4][3] = 195 { 196 // MPEG Version 2.5 197 { 385 / 2, 210, 278 / 2 }, 198 // RESERVED 199 { 0, 0, 0 }, 200 // MPEG Versions 2 201 { 385, 418, 278 }, 202 // MPEG Version 1 203 { 385, 418, 278 } 204 }; 205 206 /*********************************************************************** 207 * Samples Per Frame Index Table 208 ***********************************************************************/ 209 static const int32 spfIndexTable[4][4] = 210 { 211 // MPEG 2.5 212 {0, 576, 1152, 384}, 213 // RESERVED 214 {0, 0, 0, 0}, 215 // MPEG 2 216 {0, 576, 1152, 384}, 217 // MPEG 1 218 {0, 1152, 1152, 384} 219 }; 220 221 222 /*********************************************************************** 223 * FUNCTION: SwapFileToHostByteOrderInt32 224 * DESCRIPTION: Swaps the bytes in an integer to the correct host 225 * byte order 226 * INPUT/OUTPUT PARAMETERS: 227 * RETURN VALUE: 228 * SIDE EFFECTS: 229 ***********************************************************************/ 230 static uint32 SwapFileToHostByteOrderInt32(uint8 * pBuf2) 231 { 232 uint32 temp; 233 uint8 * pBuf1 = (uint8 *) & temp; 234 235 #if (OSCL_BYTE_ORDER_LITTLE_ENDIAN) 236 pBuf1[3] = pBuf2[0]; 237 pBuf1[2] = pBuf2[1]; 238 pBuf1[1] = pBuf2[2]; 239 pBuf1[0] = pBuf2[3]; 240 #elif (OSCL_BYTE_ORDER_BIG_ENDIAN) 241 pBuf1[3] = pBuf2[3]; 242 pBuf1[2] = pBuf2[2]; 243 pBuf1[1] = pBuf2[1]; 244 pBuf1[0] = pBuf2[0]; 245 #endif 246 247 return temp; 248 } 249 250 /*********************************************************************** 251 * FUNCTION: ReadBuffer 252 * DESCRIPTION: Read data from buffer 253 * INPUT/OUTPUT PARAMETERS: 254 * RETURN VALUE: 255 * SIDE EFFECTS: 256 ***********************************************************************/ 257 static uint32 ReadBuffer(uint8 * pBuf2, int32 length, int32 &pos) 258 { 259 int32 i, b, number = 0; 260 261 if (pBuf2) 262 { 263 for (i = 0; i < length ; i++) 264 { 265 b = length - 1 - i ; 266 number = number | (uint32)(pBuf2[pos+i] & 0xff) << (8 * b); 267 } 268 pos += length ; 269 return number; 270 } 271 else 272 { 273 return 0; 274 } 275 } 276 277 /*********************************************************************** 278 * FUNCTION: SwapFileToHostByteOrderInt16 279 * DESCRIPTION: Swaps the bytes in an integer to the correct host byte order 280 * INPUT/OUTPUT PARAMETERS: 281 * RETURN VALUE: 282 * SIDE EFFECTS: 283 ***********************************************************************/ 284 static uint16 SwapFileToHostByteOrderInt16(uint8 * pBuf2) 285 { 286 uint16 temp; 287 uint8 * pBuf1 = (uint8 *) & temp; 288 289 oscl_memcpy(&temp, pBuf2, 2); 290 291 #if (OSCL_BYTE_ORDER_LITTLE_ENDIAN) 292 pBuf1[1] = pBuf2[0]; 293 pBuf1[0] = pBuf2[1]; 294 #elif (OSCL_BYTE_ORDER_BIG_ENDIAN) 295 pBuf1[1] = pBuf2[1]; 296 pBuf1[0] = pBuf2[0]; 297 #endif 298 299 return temp; 300 } 301 302 /*********************************************************************** 303 * FUNCTION: Constructor 304 * DESCRIPTION: 305 * INPUT/OUTPUT PARAMETERS: 306 * RETURN VALUE: 307 * SIDE EFFECTS: 308 ***********************************************************************/ 309 MP3Parser::MP3Parser(PVFile* aFileHandle) 310 { 311 fp = aFileHandle; 312 // initialize all member variables 313 iLocalFileSize = 0; 314 iFileSizeFromExternalSource = 0; 315 iInitSearchFileSize = KMAX_INITIAL_SEARCH_FILE_SIZE_IN_BYTES; 316 iLocalFileSizeSet = false; 317 iEnableCrcCalc = false; 318 mp3Type = EVBRType; 319 iTagSize = 0; 320 StartOffset = 0; 321 iCurrFrameNumber = 0; 322 ConfigSize = 0; 323 iNumberOfFrames = 0; 324 // average bitrate values 325 iAvgBitrateInbps = 0; 326 iAvgBitrateInbpsFromRandomScan = 0; 327 iAvgBitrateInbpsFromCompleteScan = 0; 328 iScannedFrameCount = 0; 329 // scan completion flag 330 iDurationScanComplete = false; 331 // duration values from various sources 332 iClipDurationInMsec = 0; 333 iClipDurationFromEstimation = 0; 334 iClipDurationComputed = 0; 335 iClipDurationFromVBRIHeader = 0; 336 iClipDurationFromRandomScan = 0; 337 iClipDurationFromMetadata = 0; 338 339 iSamplesPerFrame = 0; 340 iSamplingRate = 0; 341 342 iTimestamp = 0; 343 iFirstScan = true; 344 345 iTOC = NULL; 346 iTOCFilledCount = 0; 347 iTimestampPrev = 0; 348 iScanTimestamp = 0; 349 iBinWidth = 0; 350 351 iVbriHeader.TOC = NULL; 352 oscl_memset(&iMP3ConfigInfo, 0, sizeof(iMP3ConfigInfo)); 353 oscl_memset(&iMP3HeaderInfo, 0, sizeof(iMP3HeaderInfo)); 354 oscl_memset(&iXingHeader, 0, sizeof(iXingHeader)); 355 oscl_memset(ConfigData, 0, sizeof(ConfigData)); 356 oscl_memset(&iVbriHeader, 0, sizeof(iVbriHeader)); 357 pSyncBuffer = NULL; 358 } 359 360 361 /*********************************************************************** 362 * FUNCTION: Destructor 363 * DESCRIPTION: 364 * INPUT/OUTPUT PARAMETERS: 365 * RETURN VALUE: 366 * SIDE EFFECTS: 367 ***********************************************************************/ 368 MP3Parser::~MP3Parser() 369 { 370 // The File Pointer is only used. FileHandles are opened and closed 371 // as required. 372 fp = NULL; 373 iClipDurationInMsec = 0; 374 iClipDurationComputed = 0; 375 iLocalFileSize = 0; 376 iLocalFileSize = false; 377 iInitSearchFileSize = 0; 378 iCurrFrameNumber = 0; 379 iNumberOfFrames = 0; 380 ConfigSize = 0; 381 StartOffset = 0; 382 if (iVbriHeader.TOC != NULL) 383 OSCL_ARRAY_DELETE(iVbriHeader.TOC); 384 if (pSyncBuffer) 385 { 386 OSCL_ARRAY_DELETE(pSyncBuffer); 387 pSyncBuffer = NULL; 388 } 389 iMaxSyncBufferSize = 0; 390 391 if (iTOC) 392 { 393 OSCL_ARRAY_DELETE(iTOC); 394 iTOC = NULL; 395 } 396 397 oscl_memset(&iMP3ConfigInfo, 0, sizeof(iMP3ConfigInfo)); 398 oscl_memset(&iMP3HeaderInfo, 0, sizeof(iMP3HeaderInfo)); 399 oscl_memset(&iXingHeader, 0, sizeof(iXingHeader)); 400 oscl_memset(&ConfigData, 0, sizeof(ConfigData)); 401 oscl_memset(&iVbriHeader, 0, sizeof(iVbriHeader)); 402 } 403 404 /*********************************************************************** 405 * FUNCTION: ParseMP3File 406 * DESCRIPTION: This function MUST be called after the Constructor and before 407 * any other public function is called. Otherwise the object's 408 * member data will be uninitialized. 409 * INPUT/OUTPUT PARAMETERS: 410 * RETURN VALUE: 411 * SIDE EFFECTS: 412 ***********************************************************************/ 413 MP3ErrorType MP3Parser::ParseMP3File(PVFile * fpUsed, bool aEnableCRC) 414 { 415 //init members 416 iEnableCrcCalc = aEnableCRC; 417 fp = fpUsed; 418 419 iLocalFileSize = 0; 420 iLocalFileSizeSet = false; 421 iCurrFrameNumber = 0; 422 iNumberOfFrames = 0; 423 ConfigSize = 0; 424 StartOffset = 0; 425 426 uint32 firstHeader = 0; 427 uint8 pFirstFrame[MP3_FIRST_FRAME_SIZE]; 428 uint8 pFrameHeader[MP3_FRAME_HEADER_SIZE]; 429 430 uint8 * pBuf = pFirstFrame; 431 oscl_memset(&iMP3ConfigInfo, 0, sizeof(iMP3ConfigInfo)); 432 oscl_memset(&iMP3HeaderInfo, 0, sizeof(iMP3HeaderInfo)); 433 oscl_memset(&iXingHeader, 0, sizeof(iXingHeader)); 434 oscl_memset(&ConfigData, 0, sizeof(ConfigData)); 435 oscl_memset(&iVbriHeader, 0, sizeof(iVbriHeader)); 436 437 MP3ErrorType errCode = MP3_SUCCESS; 438 // SAVE THE CURRENT FILE POSITION 439 errCode = MP3Utils::SeektoOffset(fp, 0, Oscl_File::SEEKSET); 440 // try to retrieve the file size 441 if (fp->GetFileBufferingCapacity() == 0 && MP3Utils::getCurrentFileSize(fp, iLocalFileSize)) 442 { 443 iLocalFileSizeSet = true; 444 iInitSearchFileSize = OSCL_MIN(iInitSearchFileSize, iLocalFileSize); 445 if (iLocalFileSize == 0) 446 { 447 return MP3_END_OF_FILE; 448 } 449 } 450 451 if (!iLocalFileSizeSet) 452 { 453 uint32 remBytes = 0; 454 if (fp->GetRemainingBytes(remBytes)) 455 { 456 iInitSearchFileSize = OSCL_MIN(iInitSearchFileSize, remBytes); 457 } 458 } 459 460 if (fp->GetFileBufferingCapacity() <= 0) 461 { 462 // Parse the MetaData (Beginning or End) 463 // Position the File Pointer at the first Audio Frame 464 if (iId3TagParser.ParseID3Tag(fp) == PVMFSuccess) 465 { 466 // This is the position of the first MP3 Frame in the File 467 if (iId3TagParser.IsID3V2Present()) 468 { 469 iTagSize = iId3TagParser.GetByteOffsetToStartOfAudioFrames(); 470 } 471 } 472 } 473 else 474 { 475 // get id3 tag size only 476 iId3TagParser.IsID3V2Present(fp, iTagSize); 477 } 478 479 if (iTagSize > 0) 480 { 481 StartOffset = iTagSize; 482 } 483 484 MP3ErrorType err = MP3Utils::SeektoOffset(fp, StartOffset, Oscl_File::SEEKSET); 485 if (MP3_SUCCESS != err) 486 { 487 return err; 488 } 489 490 uint32 seekOffset = 0; 491 err = mp3FindSync(StartOffset, seekOffset, fp); 492 if (err != MP3_SUCCESS) 493 { 494 // in eof scenario parser reports eof error to the user 495 // eof will be reported in case when no valid sync 496 // word is find in the maximum specified search limit 497 return err; 498 } 499 500 StartOffset += seekOffset; 501 err = MP3Utils::SeektoOffset(fp, StartOffset, Oscl_File::SEEKSET); 502 if (MP3_SUCCESS != err) 503 { 504 return err; 505 } 506 507 if (!MP3FileIO::readByteData(fp, MP3_FRAME_HEADER_SIZE, pFrameHeader)) 508 { 509 return MP3_INSUFFICIENT_DATA; 510 } 511 firstHeader = SwapFileToHostByteOrderInt32(pFrameHeader); 512 513 if (!GetMP3Header(firstHeader, iMP3HeaderInfo)) 514 { 515 return MP3_FILE_HDR_READ_ERR; 516 } 517 518 if (!DecodeMP3Header(iMP3HeaderInfo, iMP3ConfigInfo, false)) 519 { 520 return MP3_FILE_HDR_DECODE_ERR; 521 } 522 else 523 { 524 oscl_memcpy(ConfigData, pFrameHeader, MP3_FRAME_HEADER_SIZE); 525 ConfigSize = MP3_FRAME_HEADER_SIZE; 526 } 527 528 int32 revSeek = 0 - MP3_FRAME_HEADER_SIZE - seekOffset; 529 errCode = MP3Utils::SeektoOffset(fp, revSeek, Oscl_File::SEEKCUR); 530 if (MP3_SUCCESS != errCode) 531 { 532 return errCode; 533 } 534 535 if (!MP3FileIO::readByteData(fp, MP3_FIRST_FRAME_SIZE, pFirstFrame)) 536 { 537 return MP3_INSUFFICIENT_DATA; 538 } 539 540 revSeek = 0 - MP3_FIRST_FRAME_SIZE; 541 //VBRI header exist exactly 32 bytes after first frame header 542 if ((oscl_memcmp((pBuf + VBRI_HEADER_OFFSET), STR_VBRI_HEADER_IDENTIFIER, VBR_HEADER_SIZE) == 0)) 543 { 544 int32 bufferSize = CalculateBufferSizeForHeader(pBuf + 36); 545 int32 actualBufferSize = bufferSize + VBRI_HEADER_OFFSET + VBR_HEADER_SIZE; 546 uint8* tempBuf = OSCL_ARRAY_NEW(uint8, actualBufferSize); 547 548 MP3ErrorType err = MP3Utils::SeektoOffset(fp, revSeek, Oscl_File::SEEKCUR); 549 if (MP3_SUCCESS != err) 550 { 551 OSCL_ARRAY_DELETE(tempBuf); 552 return err; 553 } 554 555 if (!MP3FileIO::readByteData(fp, actualBufferSize, tempBuf)) 556 { 557 OSCL_ARRAY_DELETE(tempBuf); 558 return MP3_INSUFFICIENT_DATA; 559 } 560 else 561 { 562 if (pBuf) 563 { 564 pBuf = NULL; 565 pBuf = tempBuf; 566 pBuf += 36; 567 } 568 } 569 570 revSeek = 0 - actualBufferSize; 571 if (!DecodeVBRIHeader(pBuf, iVbriHeader, iMP3HeaderInfo)) 572 { 573 OSCL_ARRAY_DELETE(tempBuf); 574 return MP3_FILE_VBRI_HDR_ERR; 575 } 576 else 577 { 578 mp3Type = EVBRIType; 579 iLocalFileSize = iVbriHeader.bytes; 580 OSCL_ARRAY_DELETE(tempBuf); 581 } 582 } 583 else 584 { 585 uint32 offset = 0; 586 // Determine offset of XING headers 587 if ((iMP3HeaderInfo.layerID == MPEG_LAYER_III)) 588 { 589 // MPEG 1 590 if (iMP3HeaderInfo.frameVer == 3) //MPEG version 1 591 { 592 if (iMP3HeaderInfo.chMode != 3) 593 { 594 offset = (32 + 4); 595 pBuf += offset; 596 } 597 else 598 { 599 offset = (17 + 4); 600 pBuf += offset; 601 } 602 } 603 else 604 { 605 // MPEG 2 606 if (iMP3HeaderInfo.chMode != 3) 607 { 608 offset = (17 + 4); 609 pBuf += offset; 610 } 611 else 612 { 613 offset = (9 + 4); 614 pBuf += offset; 615 } 616 } 617 } 618 619 // Check for MP3 Header Tags, XING or INFO 620 if ((oscl_memcmp(pBuf, STR_XING_HEADER_IDENTIFIER, VBR_HEADER_SIZE) == 0) || 621 (oscl_memcmp(pBuf, STR_INFO_HEADER_IDENTIFIER, VBR_HEADER_SIZE) == 0)) 622 { 623 MP3ErrorType err = MP3Utils::SeektoOffset(fp, offset - MP3_FIRST_FRAME_SIZE, Oscl_File::SEEKCUR); 624 if (MP3_SUCCESS != err) 625 { 626 return err; 627 } 628 revSeek = 0 - offset; 629 630 if (!MP3FileIO::readByteData(fp, MP3_FIRST_FRAME_SIZE, pFirstFrame)) 631 { 632 return MP3_INSUFFICIENT_DATA; 633 } 634 635 revSeek -= MP3_FIRST_FRAME_SIZE; 636 637 if (!DecodeXINGHeader(pFirstFrame, iXingHeader, iMP3HeaderInfo)) 638 return MP3_FILE_XING_HDR_ERR; 639 else 640 mp3Type = EXINGType; 641 } 642 } 643 644 // Calculate the sampling rate and samples per frame. 645 iSamplesPerFrame = spfIndexTable[iMP3HeaderInfo.frameVer][iMP3HeaderInfo.layerID]; 646 iSamplingRate = srIndexTable[((iMP3HeaderInfo.frameVer)*4) + iMP3HeaderInfo.srIndex]; 647 648 // If the mp3Type is XING or VBRI, then first check if they have a valid duration 649 // If the header has no valid duration then just mark the content to as a VBR content 650 if (mp3Type == EXINGType || mp3Type == EVBRIType) 651 { 652 // Get the duration 653 uint32 clipduration = 0; 654 GetDurationFromVBRIHeader(clipduration); 655 if (clipduration == 0) 656 { 657 // not a valid duration, just set the clip to be VBR type 658 mp3Type = EVBRType; 659 } 660 } 661 662 // If XING or VBRI Headers are not present then we need to build our own TOC for 663 // repositioning. 664 // And even if XING header is present and TOC flags are not present we need to build 665 // our own TOC. 666 if ((mp3Type != EXINGType || !(iXingHeader.flags & TOC_FLAG)) && 667 (mp3Type != EVBRIType)) 668 { 669 iTOC = OSCL_ARRAY_NEW(int32, MAX_TOC_ENTRY_COUNT + 1); 670 oscl_memset(iTOC, 0, sizeof(iTOC)); 671 } 672 673 iAvgBitrateInbps = iMP3ConfigInfo.BitRate; 674 // Set the position to the position of the first MP3 frame 675 errCode = MP3Utils::SeektoOffset(fp, revSeek + seekOffset, Oscl_File::SEEKCUR); 676 if (MP3_SUCCESS != errCode) 677 { 678 return errCode; 679 } 680 iCurrFrameNumber = 0; 681 return MP3_SUCCESS; 682 } 683 684 /*********************************************************************** 685 * Function : ScanMP3File 686 * Purpose : Fetches duration of the clip playing 687 * Duration is returned, by different 688 * means by the pre-defined priorities 689 * Input : fpUsed 690 * Output : iClipDurationComputed 691 * Return : error code 692 * Modified : 693 ***********************************************************************/ 694 MP3ErrorType MP3Parser::ScanMP3File(PVFile * fpUsed, uint32 aFramesToScan) 695 { 696 uint32 firstHeader = 0; 697 uint8 pFrameHeader[MP3_FRAME_HEADER_SIZE]; 698 int32 audioOffset = 0; 699 uint32 seekOffset = 0; 700 MP3ErrorType status = MP3_ERROR_UNKNOWN; 701 MP3HeaderType mp3HeaderInfo; 702 MP3ConfigInfoType mp3ConfigInfo; 703 704 if (iClipDurationFromMetadata || (iClipDurationFromVBRIHeader && 705 ((iVbriHeader.entriesTOC >= 0) || 706 (iXingHeader.flags & TOC_FLAG))) 707 ) 708 { 709 // if Duration can be obtained from either VBRI/XING Headers or from metadata, 710 // we will not scan the file for duration 711 return MP3_DURATION_PRESENT; 712 } 713 714 if (iTOCFilledCount == MAX_TOC_ENTRY_COUNT) 715 { 716 status = FillTOCTable(0, 0); 717 if (status == MP3_ERROR_UNKNOWN) 718 { 719 // This will happen when FillTocTable returns error because of 720 // NULL TOCTable. 721 // Not a valid condition this should never happen, except if 722 // there was memory allocation failure during ParseMP3File. 723 // If happens return Duration Present to avoid any further ScanMp3File calls. 724 return MP3_DURATION_PRESENT; 725 } 726 return MP3_SUCCESS; 727 } 728 729 if (iFirstScan) 730 { 731 if (iTagSize > 0) 732 { 733 audioOffset = StartOffset; 734 MP3ErrorType err = MP3Utils::SeektoOffset(fpUsed, audioOffset, Oscl_File::SEEKSET); 735 if (MP3_SUCCESS != err) 736 { 737 return err; 738 } 739 } 740 iFirstScan = false; 741 } 742 else 743 { 744 audioOffset = iLastScanPosition; 745 } 746 747 // Set length of initial search to the min between default and filesize 748 iInitSearchFileSize = OSCL_MIN(iInitSearchFileSize, iLocalFileSize); 749 750 uint32 numFrames = 0; 751 int32 bitrate = 0; 752 uint32 frameDur = 0; 753 754 while (numFrames < aFramesToScan) 755 { 756 firstHeader = 0; 757 oscl_memset(&pFrameHeader, 0, sizeof(pFrameHeader)); 758 759 if (fpUsed->Read(pFrameHeader, 1, MP3_FRAME_HEADER_SIZE) != MP3_FRAME_HEADER_SIZE) 760 { 761 if (fpUsed->GetFileBufferingCapacity() == 0) 762 { 763 iDurationScanComplete = true; 764 } 765 status = FillTOCTable(audioOffset, 0); 766 if (status == MP3_ERROR_UNKNOWN) 767 { 768 // This will happen when FillTocTable returns error because of 769 // NULL TOCTable. 770 // Not a valid condition this should never happen, except if 771 // there was memory allocation failure during ParseMP3File. 772 // If happens return Duration Present to avoid any further ScanMp3File calls. 773 return MP3_DURATION_PRESENT; 774 } 775 return MP3_INSUFFICIENT_DATA; 776 } 777 firstHeader = SwapFileToHostByteOrderInt32(pFrameHeader); 778 uint32 offset = MP3Utils::getCurrentFilePosition(fpUsed); 779 if (!GetMP3Header(firstHeader, mp3HeaderInfo)) 780 { 781 MP3Utils::SeektoOffset(fp, 0 - MP3_FRAME_HEADER_SIZE, Oscl_File::SEEKCUR); 782 MP3ErrorType err = mp3FindSync(offset, seekOffset, fpUsed); 783 if (err == MP3_SUCCESS) 784 { 785 offset += seekOffset; 786 err = MP3Utils::SeektoOffset(fpUsed, seekOffset, Oscl_File::SEEKCUR); 787 if (MP3_SUCCESS != err) 788 { 789 return err; 790 } 791 792 if (!MP3FileIO::readByteData(fpUsed, MP3_FRAME_HEADER_SIZE, pFrameHeader)) 793 { 794 iDurationScanComplete = true; 795 status = FillTOCTable(offset, iScanTimestamp); 796 if (status == MP3_ERROR_UNKNOWN) 797 { 798 // This will happen when FillTocTable returns error because of 799 // NULL TOCTable. 800 // Not a valid condition this should never happen, except if 801 // there was memory allocation failure during ParseMP3File. 802 // If happens return Duration Present to avoid any further ScanMp3File calls. 803 return MP3_DURATION_PRESENT; 804 } 805 return MP3_INSUFFICIENT_DATA; 806 } 807 808 firstHeader = SwapFileToHostByteOrderInt32(pFrameHeader); 809 if (! GetMP3Header(firstHeader, mp3HeaderInfo)) 810 { 811 iDurationScanComplete = true; 812 status = FillTOCTable(offset, iScanTimestamp); 813 if (status == MP3_ERROR_UNKNOWN) 814 { 815 // This will happen when FillTocTable returns error because of 816 // NULL TOCTable. 817 // Not a valid condition this should never happen, except if 818 // there was memory allocation failure during ParseMP3File. 819 // If happens return Duration Present to avoid any further ScanMp3File calls. 820 return MP3_DURATION_PRESENT; 821 } 822 return MP3_FILE_HDR_READ_ERR; 823 } 824 } 825 else 826 { 827 iDurationScanComplete = true; 828 status = FillTOCTable(offset, iScanTimestamp); 829 if (status == MP3_ERROR_UNKNOWN) 830 { 831 // This will happen when FillTocTable returns error because of 832 // NULL TOCTable. 833 // Not a valid condition this should never happen, except if 834 // there was memory allocation failure during ParseMP3File. 835 // If happens return Duration Present to avoid any further ScanMp3File calls. 836 return MP3_DURATION_PRESENT; 837 } 838 return err; 839 } 840 } 841 842 if (!DecodeMP3Header(mp3HeaderInfo, mp3ConfigInfo, false)) 843 { 844 iDurationScanComplete = true; 845 status = FillTOCTable(offset, iScanTimestamp); 846 if (status == MP3_ERROR_UNKNOWN) 847 { 848 // This will happen when FillTocTable returns error because of 849 // NULL TOCTable. 850 // Not a valid condition this should never happen, except if 851 // there was memory allocation failure during ParseMP3File. 852 // If happens return Duration Present to avoid any further ScanMp3File calls. 853 return MP3_DURATION_PRESENT; 854 } 855 return MP3_FILE_HDR_DECODE_ERR; 856 } 857 858 MP3Utils::SeektoOffset(fpUsed, mp3ConfigInfo.FrameLengthInBytes - MP3_FRAME_HEADER_SIZE, Oscl_File::SEEKCUR); 859 bitrate = mp3ConfigInfo.BitRate; 860 frameDur = frameDur + (uint32)((OsclFloat) mp3ConfigInfo.FrameLengthInBytes * 8000.00f / mp3ConfigInfo.BitRate); 861 iLastScanPosition = fpUsed->Tell(); 862 numFrames++; 863 iScannedFrameCount++; 864 865 if (iScannedFrameCount > 1) 866 { 867 if (bitrate != iAvgBitrateInbpsFromCompleteScan) 868 { 869 iAvgBitrateInbpsFromCompleteScan += (int32)((int32)bitrate - (int32)iAvgBitrateInbpsFromCompleteScan) / (int32)iScannedFrameCount; 870 } 871 } 872 else 873 { 874 iAvgBitrateInbpsFromCompleteScan = bitrate; 875 mp3Type = ECBRType; 876 } 877 } 878 879 // After scan of frames we need to fill the TOC table 880 status = FillTOCTable(audioOffset, iScanTimestamp); 881 if (status == MP3_ERROR_UNKNOWN) 882 { 883 // This will happen when FillTocTable returns error because of 884 // NULL TOCTable. 885 // Not a valid condition this should never happen, except if 886 // there was memory allocation failure during ParseMP3File. 887 // If happens return Duration Present to avoid any further ScanMp3File calls. 888 return MP3_DURATION_PRESENT; 889 } 890 iScanTimestamp = iScanTimestamp + frameDur; 891 892 return MP3_SUCCESS; 893 } 894 895 896 897 /*********************************************************************** 898 * FUNCTION: GetMP3Header 899 * DESCRIPTION: Parse Header Bit fields into a structure (Pass in 4 bytes) 900 * Validate ranges and reserved fields. 901 * INPUT/OUTPUT PARAMETERS: 902 * RETURN VALUE: 903 * SIDE EFFECTS: 904 ***********************************************************************/ 905 bool MP3Parser::GetMP3Header(uint32 &aFrameHeader, MP3HeaderType &aMP3HeaderInfo) 906 { 907 oscl_memset(&aMP3HeaderInfo, 0, sizeof(aMP3HeaderInfo)); 908 909 if ((aFrameHeader & FRAME_SYNC_MASK) != (FRAME_SYNC_MASK)) 910 { 911 return false; 912 } 913 914 aMP3HeaderInfo.frameVer = ((aFrameHeader & FRAME_VER_ID_MASK) >> FRAME_VER_ID_SHIFT); 915 aMP3HeaderInfo.layerID = ((aFrameHeader & FRAME_LAYER_ID_MASK) >> FRAME_LAYER_ID_SHIFT); 916 aMP3HeaderInfo.crcFollows = ((aFrameHeader & FRAME_PROT_MASK) >> FRAME_PROT_SHIFT); 917 aMP3HeaderInfo.brIndex = ((aFrameHeader & FRAME_BR_INDEX_MASK) >> FRAME_BR_INDEX_SHIFT); 918 aMP3HeaderInfo.srIndex = ((aFrameHeader & FRAME_SR_FREQ_MASK) >> FRAME_SR_FREQ_SHIFT); 919 aMP3HeaderInfo.prvBit = ((aFrameHeader & FRAME_PRIVATE_MASK) >> FRAME_PRIVATE_SHIFT); 920 aMP3HeaderInfo.padBit = ((aFrameHeader & FRAME_PADDING_MASK) >> FRAME_PADDING_SHIFT); 921 aMP3HeaderInfo.chMode = ((aFrameHeader & FRAME_CH_MODE_MASK) >> FRAME_CH_MODE_SHIFT); 922 aMP3HeaderInfo.modeExtn = ((aFrameHeader & FRAME_MODE_EXTN_MASK) >> FRAME_MODE_EXTN_SHIFT); 923 924 // Validate the header 925 // Skip Frames with Invalid/Reserved Fields set 926 if ((aMP3HeaderInfo.srIndex == 3) || (aMP3HeaderInfo.brIndex == 15) || 927 (aMP3HeaderInfo.frameVer == 1) || (aMP3HeaderInfo.layerID != 1)) /* layerID == 1 <> layer III or mp3 */ 928 { 929 return false; 930 } 931 932 return true; 933 } 934 935 936 937 /*********************************************************************** 938 * FUNCTION: DecodeMP3Header 939 * DESCRIPTION: Decode the MP3 Header struct and place the derived values 940 * into the supplied MP3 Config data structure. 941 * INPUT/OUTPUT PARAMETERS: 942 * RETURN VALUE: 943 * SIDE EFFECTS: 944 ***********************************************************************/ 945 bool MP3Parser::DecodeMP3Header(MP3HeaderType &aMP3HeaderInfo, MP3ConfigInfoType &aMP3ConfigInfo, bool aComputeAvgBitrate) 946 { 947 uint32 bitRate, samplingRate; 948 uint32 FrameLengthInBytes; 949 uint32 FrameSizeUnComp; 950 951 aMP3ConfigInfo.SamplingRate = 0; 952 aMP3ConfigInfo.BitRate = 0; 953 aMP3ConfigInfo.FrameLengthInBytes = 0; 954 aMP3ConfigInfo.FrameSizeUnComp = 0; 955 aMP3ConfigInfo.NumberOfChannels = 0; 956 957 if (aMP3HeaderInfo.frameVer == 3) // MPEG Ver 1 958 { 959 bitRate = 1000 * brIndexTableV1[aMP3HeaderInfo.layerID][aMP3HeaderInfo.brIndex]; 960 } 961 else if ((aMP3HeaderInfo.frameVer == 2) || (aMP3HeaderInfo.frameVer == 0)) 962 { // MPEG Ver 2.0, 2.5 963 bitRate = 1000 * brIndexTableV2[aMP3HeaderInfo.layerID][aMP3HeaderInfo.brIndex]; 964 } 965 else 966 { 967 return false; 968 } 969 970 if (bitRate == 0) 971 { 972 return false; 973 } 974 975 samplingRate = srIndexTable[((aMP3HeaderInfo.frameVer)*4) + aMP3HeaderInfo.srIndex]; 976 if (samplingRate == 0) 977 { 978 return false; 979 } 980 981 // Compressed Frame Size 982 if (aMP3HeaderInfo.layerID == 3) // Layer I 983 { 984 if (aMP3HeaderInfo.frameVer == 3) // MPEG Ver 1 985 { 986 FrameLengthInBytes = (12 * bitRate / samplingRate + aMP3HeaderInfo.padBit) * 4; 987 FrameSizeUnComp = 384; 988 } 989 else // MPEG Ver 2, 2.5 990 { 991 FrameLengthInBytes = (6 * bitRate / samplingRate + aMP3HeaderInfo.padBit) * 4; 992 FrameSizeUnComp = 192; 993 } 994 } 995 else // Layer II & III 996 { 997 if (aMP3HeaderInfo.frameVer == 3) // MPEG Ver 1 998 { 999 FrameLengthInBytes = (144 * bitRate / samplingRate + aMP3HeaderInfo.padBit); 1000 FrameSizeUnComp = 1152; 1001 } 1002 else // MPEG Ver 2,2.5 1003 { 1004 FrameLengthInBytes = (72 * bitRate / samplingRate + aMP3HeaderInfo.padBit); 1005 FrameSizeUnComp = 576; 1006 } 1007 } 1008 1009 switch (aMP3HeaderInfo.chMode) 1010 { 1011 case 0: 1012 aMP3ConfigInfo.NumberOfChannels = 2; // Stereo 1013 break; 1014 case 1: // Joint Ch. Stereo 1015 case 2: // Dual Ch. Stereo 1016 aMP3ConfigInfo.NumberOfChannels = 2; // Stereo 1017 break; 1018 case 3: 1019 aMP3ConfigInfo.NumberOfChannels = 1; // Mono 1020 break; 1021 default: 1022 break; 1023 } 1024 1025 aMP3ConfigInfo.SamplingRate = samplingRate; 1026 aMP3ConfigInfo.BitRate = bitRate; 1027 aMP3ConfigInfo.FrameLengthInBytes = FrameLengthInBytes; 1028 aMP3ConfigInfo.FrameSizeUnComp = FrameSizeUnComp; 1029 1030 if (mp3Type != EVBRIType) 1031 { 1032 if ((mp3Type == EXINGType && !(iXingHeader.flags & TOC_FLAG) && !(iXingHeader.flags & FRAMES_FLAG)) || mp3Type == EVBRType) 1033 { 1034 if (aComputeAvgBitrate) 1035 { 1036 int32 filesize = OSCL_MAX(iFileSizeFromExternalSource, iLocalFileSize); 1037 uint32 audioDataSize = (filesize - StartOffset); 1038 if (iId3TagParser.IsID3V1Present()) 1039 { 1040 // The TAG in an ID3V1.x MP3 File is 128 bytes long 1041 audioDataSize -= ID3_V1_TAG_SIZE; 1042 } 1043 iNumberOfFrames = audioDataSize / (aMP3ConfigInfo.FrameLengthInBytes); 1044 1045 if (aMP3ConfigInfo.BitRate <= 0) 1046 { 1047 return true; 1048 } 1049 if (iCurrFrameNumber == 1) 1050 { 1051 iAvgBitrateInbps = aMP3ConfigInfo.BitRate; 1052 } 1053 if (iCurrFrameNumber > 1) 1054 { 1055 if (aMP3ConfigInfo.BitRate != iAvgBitrateInbps) 1056 { 1057 iAvgBitrateInbps += (aMP3ConfigInfo.BitRate - (int32)iAvgBitrateInbps) / iCurrFrameNumber; 1058 } 1059 } 1060 } 1061 } 1062 } 1063 return true; 1064 } 1065 1066 /*********************************************************************** 1067 * FUNCTION: DecodeVBRIHeader 1068 * DESCRIPTION: Decode VBRI Header and store TOC entries used for 1069 repositioning 1070 * INPUT/OUTPUT PARAMETERS: 1071 * RETURN VALUE: 1072 * SIDE EFFECTS: 1073 ***********************************************************************/ 1074 bool MP3Parser::DecodeVBRIHeader(uint8 *VbriBuffer, VBRIHeaderType &vbriHDType, 1075 MP3HeaderType &aMP3HeaderInfo) 1076 { 1077 uint8 * pBuf = VbriBuffer; 1078 int32 pos = 0; 1079 int32 i, tableLength; 1080 pBuf += 4; 1081 vbriHDType.hId = aMP3HeaderInfo.layerID; 1082 vbriHDType.sampleRate = srIndexTable[((aMP3HeaderInfo.frameVer)*4) + aMP3HeaderInfo.srIndex]; 1083 pBuf += 6; 1084 vbriHDType.bytes = SwapFileToHostByteOrderInt32(pBuf); 1085 pBuf += 4; 1086 vbriHDType.frames = SwapFileToHostByteOrderInt32(pBuf); 1087 iNumberOfFrames = vbriHDType.frames; 1088 pBuf += 4; 1089 vbriHDType.entriesTOC = SwapFileToHostByteOrderInt16(pBuf); 1090 pBuf += 2; 1091 vbriHDType.scale = SwapFileToHostByteOrderInt16(pBuf); 1092 pBuf += 2; 1093 vbriHDType.sTableEntry = SwapFileToHostByteOrderInt16(pBuf); 1094 pBuf += 2; 1095 vbriHDType.fTableEntry = SwapFileToHostByteOrderInt16(pBuf); 1096 pBuf += 2; 1097 1098 tableLength = vbriHDType.entriesTOC * vbriHDType.sTableEntry; 1099 1100 vbriHDType.TOC = OSCL_ARRAY_NEW(int32, vbriHDType.entriesTOC + 1); 1101 1102 for (i = 0; i <= (vbriHDType.entriesTOC); i++) 1103 { 1104 vbriHDType.TOC[i] = ReadBuffer(pBuf, vbriHDType.sTableEntry, pos) * vbriHDType.scale; 1105 } 1106 return true; 1107 } 1108 1109 1110 /*********************************************************************** 1111 * FUNCTION: DecodeXINGHeader 1112 * DESCRIPTION: 1113 * INPUT/OUTPUT PARAMETERS: 1114 * RETURN VALUE: 1115 * SIDE EFFECTS: 1116 ***********************************************************************/ 1117 bool MP3Parser::DecodeXINGHeader(uint8 *XingBuffer, 1118 XINGHeaderType &mp3XingHD, 1119 MP3HeaderType &hdrInfo) 1120 { 1121 /* 4 XING - 4 flags - 4 frames - 4 bytes - 100 toc */ 1122 1123 uint8 * pBuf = XingBuffer; 1124 int32 i, head_flags; 1125 mp3XingHD.flags = 0; 1126 pBuf += 4; 1127 mp3XingHD.hId = hdrInfo.layerID; 1128 head_flags = mp3XingHD.flags = SwapFileToHostByteOrderInt32(pBuf); 1129 pBuf += 4; 1130 1131 if (head_flags & FRAMES_FLAG) 1132 { 1133 mp3XingHD.frames = SwapFileToHostByteOrderInt32(pBuf); 1134 pBuf += 4; 1135 } 1136 1137 if (head_flags & BYTES_FLAG) 1138 { 1139 mp3XingHD.bytes = SwapFileToHostByteOrderInt32(pBuf); 1140 pBuf += 4; 1141 1142 if (head_flags & FRAMES_FLAG) 1143 { 1144 // check if the number of frames and the number of 1145 // bytes roughly match up 1146 int bytesperframe = mp3XingHD.bytes / mp3XingHD.frames; 1147 // 52 and 1440 are the minimum and maximum number of bytes per frame for 1148 // a compliant mp3 stream (8kbps@22050Hz and 320kbps@32000Hz respectively) 1149 if (bytesperframe < 52 || bytesperframe > 1440) 1150 { 1151 head_flags = mp3XingHD.flags = 0; 1152 } 1153 } 1154 if (iLocalFileSize != 0) 1155 { 1156 // check if the number of bytes and the file size roughly 1157 // match up 1158 if (mp3XingHD.bytes > iLocalFileSize) 1159 { 1160 head_flags = mp3XingHD.flags = 0; 1161 } 1162 if (mp3XingHD.bytes < iLocalFileSize * XING_SIZE_FUZZINESS) 1163 { 1164 head_flags = mp3XingHD.flags = 0; 1165 } 1166 } 1167 } 1168 1169 if (head_flags & TOC_FLAG) 1170 { 1171 for (i = 0; i < 100; i++) 1172 { 1173 mp3XingHD.TOC[i] = pBuf[i]; 1174 } 1175 pBuf += 100; 1176 } 1177 1178 mp3XingHD.vbr_scale = 0; 1179 if (head_flags & VBR_SCALE_FLAG) 1180 { 1181 mp3XingHD.vbr_scale = SwapFileToHostByteOrderInt32(pBuf); 1182 pBuf += 4;; 1183 } 1184 if (head_flags & FRAMES_FLAG) 1185 { 1186 iNumberOfFrames = mp3XingHD.frames; 1187 } 1188 return true; 1189 } 1190 1191 1192 /*********************************************************************** 1193 * FUNCTION: GetMP3FileHeader 1194 * DESCRIPTION: Returns information necessary to configure the audio device 1195 * INPUT/OUTPUT PARAMETERS: 1196 * RETURN VALUE: 1197 * SIDE EFFECTS: 1198 ***********************************************************************/ 1199 bool MP3Parser::GetMP3FileHeader(MP3ConfigInfoType * pMP3Config) 1200 { 1201 if (pMP3Config != NULL) 1202 { 1203 // For CBR (Constatnt Bit Rate) files, the frame sizes do not 1204 // vary. So it is sufficient to simply use the first frame's 1205 // sizes and lengths. For VBR, we'll want to use the maximum 1206 // sizes and lengths possible. 1207 oscl_memcpy(pMP3Config, &iMP3ConfigInfo, sizeof(iMP3ConfigInfo)); 1208 if (mp3Type == EXINGType || mp3Type == EVBRIType) 1209 { 1210 // Ensure the Application reserves enough space for the largest 1211 // data rate for this file. 1212 // This should be the Maximum Data Rate in the file, for a 1213 // Variable Bitrate File 1214 1215 if (iMP3HeaderInfo.frameVer == 3) // MPEG Ver 1 1216 { 1217 pMP3Config->BitRate = 1000 * brIndexTableV1[iMP3HeaderInfo.layerID][14]; 1218 } 1219 else // MPEG Ver 2, 2.5 1220 { 1221 pMP3Config->BitRate = 1000 * brIndexTableV2[iMP3HeaderInfo.layerID][14]; 1222 } 1223 1224 // Compressed Frame Size 1225 uint32 bitRate = pMP3Config->BitRate; 1226 uint32 samplingRate = pMP3Config->SamplingRate; 1227 uint32 FrameLengthInBytes; 1228 uint32 FrameSizeUnComp; 1229 1230 if (iMP3HeaderInfo.layerID == 3) // Layer I 1231 { 1232 if (iMP3HeaderInfo.frameVer == 3) // MPEG Ver 1 1233 { 1234 FrameLengthInBytes = (12 * bitRate / samplingRate + 1) * 4; 1235 FrameSizeUnComp = 384; 1236 } 1237 else // MPEG Ver 2, 2.5 1238 { 1239 FrameLengthInBytes = (6 * bitRate / samplingRate + 1) * 4; 1240 FrameSizeUnComp = 192; 1241 } 1242 } 1243 else // Layer II & III 1244 { 1245 if (iMP3HeaderInfo.frameVer == 3) // MPEG Ver 1 1246 { 1247 FrameLengthInBytes = (144 * bitRate / samplingRate + 1); 1248 FrameSizeUnComp = 1152; 1249 } 1250 else // MPEG Ver 2,2.5 1251 { 1252 FrameLengthInBytes = (72 * bitRate / samplingRate + 1); 1253 FrameSizeUnComp = 576; 1254 } 1255 } 1256 // This should be the largest Frame Size in the File. 1257 // The Application uses this information for allocating Audio 1258 // Device Buffers. 1259 // Maximum possible at any sample rate is 2880 with a pad byte; use 2884 to word align 1260 // however we have just calculated the maximum at this particular sample rate 1261 pMP3Config->FrameLengthInBytes = FrameLengthInBytes; 1262 pMP3Config->FrameSizeUnComp = FrameSizeUnComp; 1263 } 1264 return true; 1265 } 1266 return false; 1267 } 1268 1269 /*********************************************************************** 1270 * Function : GetChannelMode 1271 * Purpose : Fetch Channel mode for the clip 1272 * Input : None 1273 * Output : 1274 * Return : ChannelMode 1275 * Modified : 1276 ***********************************************************************/ 1277 uint32 MP3Parser::GetChannelMode() const 1278 { 1279 return iMP3HeaderInfo.chMode; 1280 } 1281 1282 /*********************************************************************** 1283 * Function : GetDurationFromMetadata 1284 * Purpose : Fetch duration value from id3 frame (TLEN - track length) 1285 * Input : None 1286 * Output : iClipDurationFromMetadata 1287 * Return : clip duration 1288 * Modified : 1289 ***********************************************************************/ 1290 uint32 MP3Parser::GetDurationFromMetadata() 1291 { 1292 if (iClipDurationFromMetadata <= 0) 1293 { 1294 PvmiKvpSharedPtrVector frame; 1295 PVMFMetadataList keyList; 1296 keyList.push_back("duration-from-metadata"); 1297 iId3TagParser.GetID3Frame(keyList[0], frame); 1298 if (frame.size() > 0) 1299 { 1300 iClipDurationFromMetadata = frame[0]->value.uint32_value; 1301 } 1302 } 1303 return iClipDurationFromMetadata; 1304 } 1305 1306 /*********************************************************************** 1307 * Function : ConvertSizeToTime 1308 * Purpose : Fetches duration of the clip playing 1309 * Duration is returned, by different 1310 * means by the pre-defined priorities 1311 * Input : aMetadataDuration, true if duration from metadata is needed 1312 * Output : None 1313 * Return : Clip duration 1314 * Modified : 1315 **********************************************************************/ 1316 int32 MP3Parser::ConvertSizeToTime(uint32 aFileSize, uint32& aNPTInMS) 1317 { 1318 uint32 duration = 0; 1319 uint32 fileSize = aFileSize; 1320 1321 if (iId3TagParser.IsID3V2Present()) 1322 { 1323 if (iTagSize > fileSize) 1324 { 1325 return -1; 1326 } 1327 fileSize -= iTagSize; 1328 } 1329 if (iId3TagParser.IsID3V1Present()) 1330 { 1331 // id3v1.x tags are 128 bytes long 1332 fileSize -= ID3_V1_TAG_SIZE; 1333 } 1334 1335 if (iAvgBitrateInbps > 0) 1336 { 1337 duration = (uint32)((OsclFloat)(fileSize * 8000.00f / iAvgBitrateInbps)); 1338 aNPTInMS = duration; 1339 return 0; 1340 } 1341 1342 return -1; 1343 } 1344 1345 /*********************************************************************** 1346 * Function : GetDuration 1347 * Purpose : Fetches duration of the clip playing 1348 * Duration is returned, by different 1349 * means by the pre-defined priorities 1350 * Input : aMetadataDuration, true if duration from metadata is needed 1351 * Output : None 1352 * Return : Clip duration 1353 * Modified : 1354 **********************************************************************/ 1355 uint32 MP3Parser::GetDuration(bool aMetadataDuration) 1356 { 1357 if (aMetadataDuration) 1358 { 1359 return GetDurationFromMetadata(); 1360 } 1361 1362 uint32 clipDuration = 0; 1363 1364 // local clip playback 1365 if (fp->GetFileBufferingCapacity() == 0) 1366 { 1367 // if scanning is complete, send the clip duration from scan 1368 // else if vbri/xing headers exist send duration from that 1369 // else scan "N" random frames to estimate duration from avg bitrate 1370 if (!iDurationScanComplete) 1371 { 1372 if (mp3Type == EXINGType || mp3Type == EVBRIType) 1373 { 1374 if (MP3_SUCCESS != GetDurationFromVBRIHeader(clipDuration)) 1375 { 1376 clipDuration = 0; 1377 } 1378 } 1379 1380 if (clipDuration == 0 && GetDurationFromMetadata() > 0) 1381 { 1382 clipDuration = iClipDurationFromMetadata; 1383 // random scan will not be performed, 1384 // estimate bitrate from filesize and duration 1385 } 1386 else if (clipDuration == 0) 1387 { 1388 if (MP3_SUCCESS == GetDurationFromRandomScan(clipDuration)) 1389 { 1390 iClipDurationInMsec = clipDuration; 1391 return clipDuration; 1392 } 1393 } 1394 // if control gets here, that means avg bit rate from random scan is not calculated. 1395 if (iAvgBitrateInbpsFromRandomScan <= 0) 1396 { 1397 uint32 fileSize = iLocalFileSize; 1398 if (iId3TagParser.IsID3V2Present()) 1399 { 1400 fileSize -= StartOffset; 1401 } 1402 if (iId3TagParser.IsID3V1Present()) 1403 { 1404 // id3v1.x tags are 128 bytes long 1405 fileSize -= ID3_V1_TAG_SIZE; 1406 } 1407 iAvgBitrateInbpsFromRandomScan = (int32)((OsclFloat)(fileSize * 8000.00f) / clipDuration); 1408 } 1409 } 1410 else 1411 { 1412 GetDurationFromCompleteScan(clipDuration); 1413 } 1414 } 1415 else 1416 { 1417 // PD/PS playback 1418 // duration can only be estimated using content length provided by user 1419 // If content length has not been recieved, then duration cant be estimated 1420 // in that case duration value "unknown" is notified to the user 1421 if (mp3Type == EXINGType || mp3Type == EVBRIType) 1422 { 1423 if (MP3_SUCCESS != GetDurationFromVBRIHeader(clipDuration)) 1424 { 1425 clipDuration = 0; 1426 } 1427 } 1428 if (clipDuration == 0 && MP3_SUCCESS == EstimateDurationFromExternalFileSize(clipDuration)) 1429 { 1430 clipDuration = iClipDurationFromEstimation; 1431 } 1432 } 1433 iClipDurationInMsec = clipDuration; 1434 return clipDuration; 1435 } 1436 1437 /*********************************************************************** 1438 * Function : GetMetadataSize 1439 * Purpose : Fetches size of id3 data 1440 * Input : None 1441 * Output : aSize, size of metadata 1442 * Return : error code 1443 * Modified : 1444 ***********************************************************************/ 1445 MP3ErrorType MP3Parser::GetMetadataSize(uint32 &aMetadataSize) 1446 { 1447 if (fp) 1448 { 1449 if (iId3TagParser.IsID3V2Present(fp, iTagSize) && iTagSize > 0) 1450 { 1451 aMetadataSize = iTagSize; 1452 return MP3_SUCCESS; 1453 } 1454 } 1455 aMetadataSize = 0; 1456 return MP3_METADATA_NOTPARSED; 1457 } 1458 1459 /*********************************************************************** 1460 * Function : GetMinBytesRequired 1461 * Purpose : Fetches size of maximum Mp3 frame 1462 * Input : None 1463 * Output : None 1464 * Return : aSize, size of max mp3 frame 1465 * Modified : 1466 ***********************************************************************/ 1467 uint32 MP3Parser::GetMinBytesRequired(bool aNextBytes) 1468 { 1469 uint32 minBytes = KMAX_MP3FRAME_LENGTH_IN_BYTES; 1470 if (aNextBytes && fp) 1471 { 1472 // case where parse file has failed due to lack of data 1473 // in that case request next n bytes. 1474 minBytes += fp->Tell(); 1475 } 1476 return minBytes; 1477 } 1478 1479 /*********************************************************************** 1480 * FUNCTION: GetNextBundledAccessUnits 1481 * DESCRIPTION: 1482 * INPUT/OUTPUT PARAMETERS: 1483 * RETURN VALUE: 1484 * SIDE EFFECTS: 1485 ***********************************************************************/ 1486 int32 MP3Parser::GetNextBundledAccessUnits(uint32 *n, GAU *pgau, MP3ErrorType &error) 1487 { 1488 uint32 nBytesRead = 0; 1489 uint32 framets = 0; 1490 uint32 nBytesReadTotal = 0; 1491 int32 i; 1492 error = MP3_ERROR_UNKNOWN; 1493 if ((pgau == NULL) || (pgau->buf.num_fragments > 1) 1494 || (n == NULL)) 1495 { 1496 return 0; 1497 } 1498 1499 uint8 * pOutputBuffer = (uint8 *)pgau->buf.fragments[0].ptr; 1500 int32 iLength = pgau->buf.fragments[0].len; 1501 for (i = 0; (i < (int32)*n) && (iLength > 0); i++) 1502 { 1503 pgau->numMediaSamples = i; 1504 1505 error = GetNextMediaSample(pOutputBuffer, iLength, nBytesRead, framets); 1506 if ((error == MP3_SUCCESS)) 1507 { 1508 if (nBytesRead > 0) 1509 { 1510 // Frame was read successfully 1511 pgau->info[i].len = nBytesRead; 1512 pgau->info[i].ts = framets; 1513 } 1514 } 1515 else 1516 { 1517 // Read failure 1518 break; 1519 } 1520 1521 iLength -= nBytesRead; 1522 pOutputBuffer += nBytesRead; 1523 nBytesReadTotal += nBytesRead; 1524 } 1525 *n = i; 1526 return nBytesReadTotal; 1527 } 1528 /*********************************************************************** 1529 * FUNCTION: PeekNextBundledAccessUnits 1530 * DESCRIPTION: 1531 * INPUT/OUTPUT PARAMETERS: 1532 * RETURN VALUE: 1533 * SIDE EFFECTS: 1534 ***********************************************************************/ 1535 int32 MP3Parser::PeekNextBundledAccessUnits(uint32 *n, MediaMetaInfo *mInfo) 1536 { 1537 uint32 nBytesToRead = 0; 1538 if ((mInfo == NULL) || (n == NULL)) 1539 { 1540 return 0; 1541 } 1542 1543 for (uint32 i = 0; i < *n; i++) 1544 { 1545 if ((iCurrFrameNumber + (int32)i) >= iNumberOfFrames) 1546 { 1547 break; 1548 } 1549 1550 mInfo->ts = GetTimestampForSample(iCurrFrameNumber + i); 1551 // Don't care 1552 mInfo->layer = 0; 1553 // Maximum Frame Length 1554 mInfo->len = (iMP3ConfigInfo.FrameLengthInBytes + MP3_FRAME_HEADER_SIZE); 1555 mInfo->sample_info = 0; 1556 mInfo->dropFlag = 0; 1557 1558 nBytesToRead += mInfo->len; 1559 } 1560 return nBytesToRead; 1561 } 1562 1563 1564 /*********************************************************************** 1565 * FUNCTION: GetNextMediaSample 1566 * DESCRIPTION: 1567 * INPUT/OUTPUT PARAMETERS: 1568 * RETURN VALUE: 1569 * SIDE EFFECTS: 1570 ***********************************************************************/ 1571 MP3ErrorType MP3Parser::GetNextMediaSample(uint8 *buffer, uint32 size, uint32& framesize, uint32& timestamp) 1572 { 1573 MP3ErrorType mp3Err = MP3_SUCCESS; 1574 1575 BEGIN: 1576 uint32 currentFilePosn = 0; 1577 uint32 mp3Header = 0; 1578 uint32 mp3FrameSizeInBytes = 0; 1579 MP3HeaderType mp3HeaderInfo = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 1580 MP3ConfigInfoType mp3CDInfo = {0, 0, 0, 0, 0}; 1581 uint8 *buf = buffer; 1582 1583 framesize = 0; 1584 timestamp = 0; 1585 // Read and Decode the MP3 Frame Header to obtain the 1586 // correct number of bytes in this frame. 1587 currentFilePosn = MP3Utils::getCurrentFilePosition(fp); 1588 1589 // If content length is known (non-0), avoid reading beyond EOF 1590 uint32 contentLength = MP3FileIO::getContentLength(fp); 1591 if (0 != contentLength) 1592 { 1593 // check for reading beyond EOF 1594 if ((currentFilePosn + MP3_FRAME_HEADER_SIZE) >= contentLength) 1595 { 1596 return MP3_END_OF_FILE; 1597 } 1598 } 1599 1600 if (!MP3FileIO::readByteData(fp, MP3_FRAME_HEADER_SIZE, buf)) 1601 { 1602 return MP3_INSUFFICIENT_DATA; 1603 } 1604 1605 // Convert the File Byte Order to Host Memory Byte Order 1606 // for 32 bit integers 1607 mp3Header = SwapFileToHostByteOrderInt32(buf); 1608 1609 // Adjust the buffer write location in preparation for 1610 // the next read 1611 if (! GetMP3Header(mp3Header, mp3HeaderInfo)) 1612 { 1613 // //////////////////////////////////////////////////////////////////////////// 1614 // If we don't find a valid MP3 Marker point we will attempt recovery. 1615 uint32 seekOffset = 0; 1616 MP3Utils::SeektoOffset(fp, 0 - MP3_FRAME_HEADER_SIZE, Oscl_File::SEEKCUR); 1617 MP3ErrorType err = mp3FindSync(currentFilePosn, seekOffset, fp); 1618 1619 if (err == MP3_SUCCESS) 1620 { 1621 err = MP3Utils::SeektoOffset(fp, seekOffset, Oscl_File::SEEKCUR); 1622 if (MP3_SUCCESS != err) 1623 { 1624 return err; 1625 } 1626 currentFilePosn += seekOffset; 1627 1628 if (0 != contentLength) 1629 { 1630 // if content length is known, check for reading beyond EOF 1631 if ((currentFilePosn + MP3_FRAME_HEADER_SIZE) >= contentLength) 1632 { 1633 return MP3_END_OF_FILE; 1634 } 1635 } 1636 1637 if (!MP3FileIO::readByteData(fp, MP3_FRAME_HEADER_SIZE, buf)) 1638 { 1639 return MP3_INSUFFICIENT_DATA; 1640 } 1641 1642 mp3Header = SwapFileToHostByteOrderInt32(buf); 1643 if (! GetMP3Header(mp3Header, mp3HeaderInfo)) 1644 { 1645 return MP3_FILE_HDR_READ_ERR; 1646 } 1647 } 1648 else 1649 { 1650 return err; 1651 } 1652 } 1653 1654 buf += MP3_FRAME_HEADER_SIZE; 1655 iCurrFrameNumber++; 1656 if (! DecodeMP3Header(mp3HeaderInfo, mp3CDInfo, true)) 1657 { 1658 iCurrFrameNumber--; 1659 return MP3_FILE_HDR_DECODE_ERR; 1660 } 1661 1662 int32 revSeek = 0 - MP3_FRAME_HEADER_SIZE; 1663 mp3FrameSizeInBytes = mp3CDInfo.FrameLengthInBytes; 1664 1665 MP3ErrorType err = MP3Utils::SeektoOffset(fp, revSeek, Oscl_File::SEEKCUR); 1666 if (MP3_SUCCESS != err) 1667 { 1668 iCurrFrameNumber--; 1669 return err; 1670 } 1671 1672 mp3Err = mp3VerifyCRC(mp3HeaderInfo, mp3CDInfo); 1673 if (mp3Err == MP3_CRC_ERR) 1674 { 1675 //wrong CRC skip frame. since crc was wrong there 1676 //could be error in calculating frame size. So try to find sync again. 1677 iCurrFrameNumber--; 1678 currentFilePosn += MP3_FRAME_HEADER_SIZE; 1679 if (MP3_SUCCESS != MP3Utils::SeektoOffset(fp, MP3_FRAME_HEADER_SIZE, Oscl_File::SEEKCUR)) 1680 { 1681 return err; 1682 } 1683 1684 uint32 seekOffset = 0; 1685 MP3Utils::SeektoOffset(fp, 0 - MP3_FRAME_HEADER_SIZE, Oscl_File::SEEKCUR); 1686 1687 MP3ErrorType err = mp3FindSync(currentFilePosn, seekOffset, fp); 1688 if (err == MP3_SUCCESS) 1689 { 1690 err = MP3Utils::SeektoOffset(fp, seekOffset, Oscl_File::SEEKCUR); 1691 if (MP3_SUCCESS != err) 1692 { 1693 return err; 1694 } 1695 currentFilePosn += seekOffset; 1696 goto BEGIN; 1697 } 1698 else 1699 { 1700 //no sync found return error 1701 return err; 1702 } 1703 } 1704 else if (mp3Err == MP3_INSUFFICIENT_DATA) 1705 { 1706 iCurrFrameNumber--; 1707 return mp3Err; 1708 } 1709 1710 err = MP3Utils::SeektoOffset(fp, MP3_FRAME_HEADER_SIZE, Oscl_File::SEEKCUR); 1711 if (MP3_SUCCESS != err) 1712 { 1713 iCurrFrameNumber--; 1714 return err; 1715 } 1716 1717 currentFilePosn = MP3Utils::getCurrentFilePosition(fp); 1718 1719 uint32 fileSz = 0; 1720 MP3Utils::getCurrentFileSize(fp, fileSz); 1721 if ((fileSz != 0) && (currentFilePosn + (mp3FrameSizeInBytes - MP3_FRAME_HEADER_SIZE) > (uint32)fileSz)) 1722 { 1723 // At EOF 1724 iCurrFrameNumber--; 1725 framesize = 0; 1726 timestamp = GetTimestampForCurrentSample(); 1727 if (mp3CDInfo.BitRate > 0) 1728 { 1729 iTimestamp = uint32(timestamp + (OsclFloat) mp3CDInfo.FrameLengthInBytes * 8000.00f / mp3CDInfo.BitRate); 1730 } 1731 if (0 != contentLength) 1732 { 1733 // if content length is known, check for reading beyond EOF 1734 if ((currentFilePosn + mp3FrameSizeInBytes - MP3_FRAME_HEADER_SIZE) >= contentLength) 1735 { 1736 return MP3_END_OF_FILE; 1737 } 1738 } 1739 err = MP3Utils::SeektoOffset(fp, 0 - MP3_FRAME_HEADER_SIZE, Oscl_File::SEEKCUR); 1740 if (MP3_SUCCESS != err) 1741 { 1742 return err; 1743 } 1744 return MP3_INSUFFICIENT_DATA; 1745 } 1746 1747 if (size < mp3FrameSizeInBytes) 1748 { 1749 framesize = mp3FrameSizeInBytes; 1750 iCurrFrameNumber--; 1751 return MP3_FILE_READ_ERR; 1752 } 1753 1754 framesize = mp3FrameSizeInBytes; 1755 timestamp = GetTimestampForCurrentSample(); 1756 1757 // update timestamp for next sample 1758 // calculate frameDuration 1759 if (mp3CDInfo.BitRate > 0) 1760 { 1761 iTimestamp = uint32(timestamp + (OsclFloat) mp3CDInfo.FrameLengthInBytes * 8000.00f / mp3CDInfo.BitRate); 1762 } 1763 1764 // Take into account the header (4 Bytes) already read up front 1765 // to obtain the correct Frame Size in Bytes 1766 if (0 != contentLength) 1767 { 1768 // if content length is known, check for reading beyond EOF 1769 if ((currentFilePosn + mp3FrameSizeInBytes - MP3_FRAME_HEADER_SIZE) >= contentLength) 1770 { 1771 return MP3_END_OF_FILE; 1772 } 1773 } 1774 1775 // Take into account the header (4 Bytes) already read up front 1776 // to obtain the correct Frame Size in Bytes 1777 bool res = MP3FileIO::readByteData(fp, mp3FrameSizeInBytes - MP3_FRAME_HEADER_SIZE, buf); 1778 if ((iLocalFileSize == 0) && res == false) 1779 { 1780 iCurrFrameNumber--; 1781 return MP3_INSUFFICIENT_DATA; 1782 } 1783 1784 return MP3_SUCCESS; 1785 } 1786 1787 /*********************************************************************** 1788 * FUNCTION: SeekToTimestamp 1789 * DESCRIPTION: 1790 * INPUT/OUTPUT PARAMETERS: 1791 * RETURN VALUE: 1792 * SIDE EFFECTS: 1793 ***********************************************************************/ 1794 uint32 MP3Parser::SeekToTimestamp(uint32 timestampInMsec) 1795 { 1796 uint32 SeekPosition = 0; 1797 SeekPosition = SeekPointFromTimestamp(timestampInMsec); 1798 if (!((fp->GetFileBufferingCapacity() == 0) && (SeekPosition == iLocalFileSize) && (timestampInMsec == iClipDurationInMsec))) 1799 { 1800 SeekPosition += StartOffset; 1801 } 1802 MP3Utils::SeektoOffset(fp, SeekPosition, Oscl_File::SEEKSET); 1803 return timestampInMsec; 1804 } 1805 1806 /*********************************************************************** 1807 * FUNCTION: SeekPointFromTimestamp 1808 * DESCRIPTION: 1809 * INPUT/OUTPUT PARAMETERS: 1810 * RETURN VALUE: 1811 * SIDE EFFECTS: 1812 ***********************************************************************/ 1813 uint32 MP3Parser::SeekPointFromTimestamp(uint32 ×tamp) 1814 { 1815 uint32 seekPoint = 0; 1816 uint32 seekOffset = 0; 1817 OsclFloat percent = 0; 1818 uint32 binNo = 0; 1819 1820 bool bUseTOCForRepos = false; 1821 1822 uint32 maxTSInTOC = iTOCFilledCount * iBinWidth; 1823 if (iTOCFilledCount > 1 && (timestamp < maxTSInTOC || iDurationScanComplete)) 1824 { 1825 bUseTOCForRepos = true; 1826 } 1827 1828 // XING - Use VBR TOC Header 1829 if ((mp3Type == EXINGType) && (iXingHeader.flags & TOC_FLAG)) 1830 { 1831 // Interpolate in TOC to get file seek point in bytes 1832 OsclFloat fpc = (OsclFloat)timestamp / (OsclFloat)iClipDurationFromVBRIHeader; 1833 OsclFloat fa, fb, fx; 1834 uint32 pc; 1835 1836 if (fpc < 0.00f) 1837 fpc = 0.00f; 1838 1839 if (fpc > 1.00f) 1840 fpc = 1.00f; 1841 1842 pc = (uint32)(fpc * 100.00f); 1843 fa = (OsclFloat)iXingHeader.TOC[pc]; 1844 1845 if (pc > 99) 1846 pc = 99; 1847 1848 if (pc < 99) 1849 fb = (OsclFloat)iXingHeader.TOC[pc+1]; 1850 else 1851 fb = 256.00f; 1852 1853 // ////////////////////////////////////////////////////////// 1854 // Linearly interpolate between fa and fb 1855 // TOC's appear to max out at TOC[80] = 0cff (255) 1856 // ////////////////////////////////////////////////////////// 1857 fx = fa + (fb - fa) * ((100.00f * fpc) - (OsclFloat)pc); 1858 percent = fx; 1859 if (iXingHeader.flags == 15 || iXingHeader.flags == 7 || iXingHeader.flags == 3) 1860 { 1861 seekPoint = (int32)((fx / 256.00f) * (OsclFloat)iXingHeader.bytes); 1862 if ((seekPoint > (uint32)iXingHeader.bytes)) 1863 { 1864 seekPoint = 0; 1865 percent = 0; 1866 } 1867 } 1868 else 1869 { 1870 seekPoint = 0; 1871 percent = 0; 1872 } 1873 } 1874 else if (mp3Type == EVBRIType) 1875 // ////////////////////////////////////////////////////////// 1876 // CBR or VBRI 1877 { 1878 uint32 i = 0, fraction = 0, SamplesPerFrame; 1879 OsclFloat fLengthMS; 1880 OsclFloat fLengthMSPerTOCEntry; 1881 OsclFloat fAccumulatedTimeMS = 0.0f; 1882 (iVbriHeader.sampleRate >= 32000) ? (SamplesPerFrame = 1152) : (SamplesPerFrame = 576); 1883 1884 1885 fLengthMS = ((OsclFloat)iVbriHeader.frames * (OsclFloat)SamplesPerFrame) 1886 / (OsclFloat)iVbriHeader.sampleRate * 1000.0f; 1887 1888 fLengthMSPerTOCEntry = (OsclFloat)fLengthMS / (OsclFloat)(iVbriHeader.entriesTOC + 1); 1889 1890 if (timestamp > fLengthMS) 1891 timestamp = (uint32)fLengthMS; 1892 1893 while (fAccumulatedTimeMS <= timestamp) 1894 { 1895 seekPoint += iVbriHeader.TOC[i]; 1896 fAccumulatedTimeMS += fLengthMSPerTOCEntry; 1897 i++; 1898 } 1899 1900 fraction = ((int)((((fAccumulatedTimeMS - timestamp) / fLengthMSPerTOCEntry) 1901 + (1.0f / (2.0f * (OsclFloat)iVbriHeader.fTableEntry))) * (OsclFloat)iVbriHeader.fTableEntry)); 1902 1903 seekPoint -= (int)((OsclFloat)iVbriHeader.TOC[i-1] * (OsclFloat)(fraction) 1904 / (OsclFloat)iVbriHeader.fTableEntry); 1905 } 1906 else if (bUseTOCForRepos) 1907 { 1908 // Use TOC for calculating seek point. 1909 OsclFloat fpc = (OsclFloat)timestamp / (OsclFloat)iClipDurationInMsec; 1910 binNo = (uint32)(fpc * iTOCFilledCount); 1911 uint32 TScurr = binNo * iBinWidth; 1912 while (TScurr > timestamp) 1913 { 1914 binNo--; 1915 TScurr = binNo * iBinWidth; 1916 } 1917 1918 uint32 offsetDiff = iTOC[binNo+1] - iTOC[binNo]; 1919 uint32 tsDiff = timestamp - TScurr; 1920 seekPoint = iTOC[binNo] + tsDiff * (offsetDiff / iBinWidth); 1921 } 1922 else 1923 { 1924 /** 1925 * vbri and xing headers are not present. seek offset will be 1926 * calculated on the basis of average bit rate 1927 **/ 1928 int32 avgBR = 0; 1929 if (fp->GetFileBufferingCapacity() > 0) 1930 { 1931 avgBR = iAvgBitrateInbps; 1932 } 1933 else 1934 { 1935 if (iDurationScanComplete && (iAvgBitrateInbpsFromCompleteScan > 0)) 1936 { 1937 avgBR = iAvgBitrateInbpsFromCompleteScan; 1938 } 1939 else 1940 { 1941 avgBR = iAvgBitrateInbpsFromRandomScan; 1942 } 1943 } 1944 seekPoint = (uint32)((OsclFloat)(avgBR * (OsclFloat)timestamp) / 8000.0f); 1945 } 1946 1947 /** 1948 * If we don't find a sync point we will start playing from the beginning again 1949 * try finding seek points only for local playback 1950 * Since in PD/PS scenarios we might not be having enough data to find the seek point 1951 * We can find the seek point when we are resuming the playback 1952 **/ 1953 if (seekPoint > 0 && fp->GetFileBufferingCapacity() == 0) 1954 { 1955 // seek to the reposition point location 1956 MP3Utils::SeektoOffset(fp, seekPoint + StartOffset, Oscl_File::SEEKSET); 1957 uint32 retVal = mp3FindSync(seekPoint + StartOffset, seekOffset, fp); 1958 1959 if (retVal == MP3_SUCCESS) 1960 { 1961 seekPoint += seekOffset; 1962 MP3Utils::SeektoOffset(fp, seekOffset, Oscl_File::SEEKCUR); 1963 if (iDurationScanComplete) 1964 { 1965 uint32 offsetDiff = iTOC[binNo+1] - iTOC[binNo]; 1966 timestamp = (binNo * iBinWidth) + (iBinWidth * (seekPoint - iTOC[binNo]) / offsetDiff); 1967 } 1968 } 1969 else if (retVal == MP3_INSUFFICIENT_DATA || retVal == MP3_END_OF_FILE) 1970 { 1971 // if parser hits Insufficent data during local playback or end of file, 1972 // we need to set seekpoint and timestamp to clip duration and node will report as end of track. 1973 seekPoint = iLocalFileSize; 1974 timestamp = iClipDurationInMsec; 1975 iTimestamp = timestamp; 1976 // return from here as we need not compute Current Frame Number 1977 return seekPoint; 1978 } 1979 else 1980 { 1981 seekPoint = 0; 1982 timestamp = 0; 1983 } 1984 } 1985 1986 1987 if (seekPoint > 0) 1988 { 1989 if (iMP3ConfigInfo.FrameSizeUnComp > 0 && iMP3ConfigInfo.SamplingRate > 0) 1990 { 1991 iCurrFrameNumber = (int32)(timestamp * (iMP3ConfigInfo.SamplingRate / iMP3ConfigInfo.FrameSizeUnComp) / 1000.00f); 1992 } 1993 } 1994 else 1995 { 1996 iCurrFrameNumber = 0; 1997 timestamp = 0; 1998 } 1999 iTimestamp = timestamp; 2000 return seekPoint; 2001 } 2002 2003 2004 /*********************************************************************** 2005 * FUNCTION: mp3FindSync 2006 * DESCRIPTION: This function reads the whole file searching for a sync 2007 * word. Once it finds one, it check for 4 continuous sync 2008 * words to avoid a false synchronization 2009 * INPUT/OUTPUT PARAMETERS: 2010 * RETURN VALUE: 2011 * SIDE EFFECTS: 2012 ***********************************************************************/ 2013 MP3ErrorType MP3Parser::mp3FindSync(uint32 seekPoint, uint32 &syncOffset, PVFile* aFile) 2014 { 2015 syncOffset = 0; 2016 iMaxSyncBufferSize = 627; /* default for 192 kbps, 44.1 kHz */ 2017 2018 if (aFile->GetFileBufferingCapacity() > 0) 2019 { 2020 iLocalFileSizeSet = (int32)MP3Utils::getCurrentFileSize(aFile, iLocalFileSize); 2021 } 2022 2023 uint32 contentLength = MP3FileIO::getContentLength(aFile); 2024 if ((contentLength != 0) && ((seekPoint + iMaxSyncBufferSize) >= contentLength)) 2025 { 2026 // if content length is known, check for reading beyond EOF 2027 return MP3_END_OF_FILE; 2028 } 2029 2030 if ((iLocalFileSize != 0) && (seekPoint + iMaxSyncBufferSize > (uint32)iLocalFileSize)) 2031 { 2032 return MP3_INSUFFICIENT_DATA; 2033 } 2034 2035 if (pSyncBuffer) 2036 { 2037 OSCL_ARRAY_DELETE(pSyncBuffer); 2038 pSyncBuffer = NULL; 2039 } 2040 2041 int32 leavecode = 0; 2042 OSCL_TRY(leavecode, pSyncBuffer = OSCL_ARRAY_NEW(uint8, iMaxSyncBufferSize + 1)); 2043 if (leavecode || pSyncBuffer == NULL) 2044 { 2045 return MP3_ERROR_UNKNOWN; /* buffer couldn't be allocated */ 2046 } 2047 2048 seekPoint = aFile->Tell(); 2049 uint32 i = 0; 2050 uint32 j = 0; 2051 uint32 BufferSize = 0; 2052 pSyncBuffer[0] = 0; 2053 bool syncFound = false; 2054 MP3ErrorType mp3Err = MP3_SUCCESS; 2055 uint32 maxSearchOffset = 0; 2056 int32 revSeek = 0; 2057 if (iLocalFileSizeSet) 2058 { 2059 maxSearchOffset = OSCL_MIN(iInitSearchFileSize, iLocalFileSize - seekPoint); 2060 } 2061 else 2062 { 2063 uint32 remBytes = 0; 2064 if (aFile->GetRemainingBytes(remBytes)) 2065 { 2066 maxSearchOffset = OSCL_MIN(iInitSearchFileSize, aFile->Tell() + remBytes - seekPoint); 2067 } 2068 } 2069 2070 for (j = 0; j < maxSearchOffset; j += iMaxSyncBufferSize) 2071 { 2072 revSeek = 0; 2073 // Grab a new buffer for a byte by byte search 2074 if (!MP3FileIO::readByteData(aFile, iMaxSyncBufferSize, &pSyncBuffer[1], &BufferSize)) 2075 { 2076 if (pSyncBuffer) 2077 { 2078 OSCL_ARRAY_DELETE(pSyncBuffer); 2079 pSyncBuffer = NULL; 2080 } 2081 return MP3_ERROR_UNKNOWN_OBJECT; 2082 } 2083 revSeek -= j; 2084 // Find the first Sync Marker by doing a byte by byte search. 2085 // Once we have found the sync words, the frame is validated. 2086 // For frame header validation, we read four bytes. 2087 // So the search for sync words should be stopped when we have less than 2088 // 4 bytes in the buffer. 2089 if (BufferSize > 3) 2090 { 2091 for (i = 0; i < (BufferSize - 3); i++) 2092 { 2093 if (pSyncBuffer[i] == 0xFF) 2094 { 2095 // MPEG 1, 2 2096 if ((pSyncBuffer[i+1] & 0xF0) == 0xF0) 2097 { 2098 // if partial match is found verify that 4 consecutives sync word are valid 2099 MP3Utils::SeektoOffset(aFile, 0 - (int32) iMaxSyncBufferSize + (int32) i - 1, Oscl_File::SEEKCUR); 2100 mp3Err = IsValidFrame(&(pSyncBuffer[i]), j + i - 1, seekPoint, aFile); 2101 if (mp3Err == MP3_SUCCESS) 2102 { 2103 MP3Utils::SeektoOffset(aFile, 0 - (int32)j - i + 1, Oscl_File::SEEKCUR); 2104 break; 2105 } 2106 else if (mp3Err == MP3_INSUFFICIENT_DATA) 2107 { 2108 if (pSyncBuffer) 2109 { 2110 OSCL_ARRAY_DELETE(pSyncBuffer); 2111 pSyncBuffer = NULL; 2112 } 2113 return mp3Err; 2114 } 2115 else 2116 { 2117 // Drop the frame 2118 MP3Utils::SeektoOffset(aFile, iMaxSyncBufferSize - i + 1, Oscl_File::SEEKCUR); 2119 } 2120 } 2121 // MPEG 2.5 2122 else if ((pSyncBuffer[i+1] & 0xF0) == 0xE0) 2123 { 2124 // if partial match is found verify that 4 consecutives sync word are valid 2125 MP3Utils::SeektoOffset(aFile, 0 - (int32) iMaxSyncBufferSize + (int32) i - 1, Oscl_File::SEEKCUR); 2126 mp3Err = IsValidFrame(&(pSyncBuffer[i]), j + i - 1, seekPoint, aFile); 2127 2128 if (mp3Err == MP3_SUCCESS) 2129 { 2130 MP3Utils::SeektoOffset(aFile, 0 - (int32)j - i + 1, Oscl_File::SEEKCUR); 2131 break; 2132 } 2133 else if (mp3Err == MP3_INSUFFICIENT_DATA) 2134 { 2135 if (pSyncBuffer) 2136 { 2137 OSCL_ARRAY_DELETE(pSyncBuffer); 2138 pSyncBuffer = NULL; 2139 } 2140 return mp3Err; 2141 } 2142 else 2143 { 2144 // Drop the frame 2145 MP3Utils::SeektoOffset(aFile, iMaxSyncBufferSize - i + 1, Oscl_File::SEEKCUR); 2146 } 2147 } 2148 } 2149 } 2150 if (i < (BufferSize - 3)) 2151 { 2152 syncFound = true; 2153 break; /* sync was found */ 2154 } /* else grab new buffer and keep searching */ 2155 pSyncBuffer[0] = pSyncBuffer[iMaxSyncBufferSize]; 2156 } 2157 else 2158 { 2159 break; 2160 } 2161 } 2162 2163 if (pSyncBuffer) 2164 { 2165 OSCL_ARRAY_DELETE(pSyncBuffer); 2166 pSyncBuffer = NULL; 2167 } 2168 2169 if (!syncFound) 2170 { 2171 return MP3_END_OF_FILE; /* File does not have any valid sync word */ 2172 } 2173 2174 if (iLocalFileSizeSet) 2175 { 2176 /* One valid frame was found -> reset initial size to file size */ 2177 iInitSearchFileSize = iLocalFileSize; 2178 } 2179 else 2180 { 2181 uint32 remBytes = 0; 2182 if (aFile->GetRemainingBytes(remBytes)) 2183 { 2184 /* One valid frame was found -> reset initial size remaining file size*/ 2185 iInitSearchFileSize = OSCL_MIN(iInitSearchFileSize, remBytes); 2186 } 2187 } 2188 2189 syncOffset = j + i - 1; /* set offset */ 2190 return MP3_SUCCESS; 2191 } 2192 2193 2194 /*********************************************************************** 2195 * FUNCTION: IsValidFrame 2196 * DESCRIPTION: 2197 * INPUT/OUTPUT PARAMETERS: 2198 * RETURN VALUE: 2199 * SIDE EFFECTS: 2200 ***********************************************************************/ 2201 MP3ErrorType MP3Parser::IsValidFrame(uint8 * pBuffer, 2202 uint32 offset, 2203 uint32 seekPoint, 2204 PVFile* aFile) 2205 { 2206 bool bCRCPresent = false; 2207 MP3ErrorType err = MP3_SUCCESS; 2208 // Is the MP3 Frame Header Valid? 2209 err = IsValidFrameHeader(pBuffer, bCRCPresent, offset, seekPoint, aFile); 2210 return err; 2211 } 2212 2213 /*********************************************************************** 2214 * FUNCTION: IsValidFrameHeader 2215 * DESCRIPTION: This function now check the sync word and then with the 2216 * information retrieved from the header, predict the location 2217 * of the following 3 headers. Then, if the sampling frequencies 2218 * and number of channels match for all headers, the frame header 2219 * is considered valid 2220 * INPUT/OUTPUT PARAMETERS: 2221 * RETURN VALUE: 2222 * SIDE EFFECTS: 2223 ***********************************************************************/ 2224 MP3ErrorType MP3Parser::IsValidFrameHeader(uint8 *mp3Frame, bool &bCRCPresent, 2225 uint32 firstSyncOffset, uint32 seekPoint, 2226 PVFile* aFile) 2227 { 2228 OSCL_UNUSED_ARG(firstSyncOffset); 2229 OSCL_UNUSED_ARG(seekPoint); 2230 2231 PVFile* fpUsed = fp; 2232 if (aFile) 2233 { 2234 fpUsed = aFile; 2235 } 2236 MP3HeaderType mp3HeaderInfo = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 2237 MP3ConfigInfoType mp3CDInfo = {0, 0, 0, 0, 0}; 2238 MP3ConfigInfoType mp3CDInfo2 = {0, 0, 0, 0, 0}; 2239 MP3ConfigInfoType mp3CDInfo3 = {0, 0, 0, 0, 0}; 2240 MP3ConfigInfoType mp3CDInfo4 = {0, 0, 0, 0, 0}; 2241 int32 flength = 0; 2242 int32 revSeek = 0; 2243 bool status; 2244 2245 uint32 mp3Header = SwapFileToHostByteOrderInt32(mp3Frame); 2246 2247 2248 bCRCPresent = false; 2249 if (!GetMP3Header(mp3Header, mp3HeaderInfo)) 2250 { 2251 return MP3_FILE_HDR_READ_ERR; 2252 } 2253 2254 if (!DecodeMP3Header(mp3HeaderInfo, mp3CDInfo, false)) 2255 { 2256 return MP3_FILE_HDR_READ_ERR; 2257 } 2258 2259 // A flag of 0 means the CRC is present 2260 bCRCPresent = !(mp3HeaderInfo.crcFollows); 2261 2262 /* 2263 * Search 4 consecutives header to guarantee that we 2264 * really latch on a valid sync word 2265 */ 2266 flength = mp3CDInfo.FrameLengthInBytes; 2267 MP3ErrorType err = MP3Utils::SeektoOffset(fpUsed, flength, Oscl_File::SEEKCUR); 2268 if (MP3_SUCCESS != err) 2269 { 2270 return err; 2271 } 2272 revSeek -= flength; 2273 2274 if (!MP3FileIO::readByteData(fpUsed, MP3_FRAME_HEADER_SIZE, (uint8 *)&mp3Header)) 2275 { 2276 MP3Utils::SeektoOffset(fpUsed, revSeek , Oscl_File::SEEKCUR); 2277 return MP3_INSUFFICIENT_DATA; 2278 } 2279 2280 mp3Header = SwapFileToHostByteOrderInt32((uint8 *) & mp3Header); 2281 2282 status = GetMP3Header(mp3Header, mp3HeaderInfo); 2283 status = DecodeMP3Header(mp3HeaderInfo, mp3CDInfo2, false); 2284 2285 flength = mp3CDInfo2.FrameLengthInBytes; 2286 2287 err = MP3Utils::SeektoOffset(fpUsed, flength - MP3_FRAME_HEADER_SIZE, Oscl_File::SEEKCUR); 2288 if (MP3_SUCCESS != err) 2289 { 2290 MP3Utils::SeektoOffset(fpUsed, revSeek - MP3_FRAME_HEADER_SIZE, Oscl_File::SEEKCUR); 2291 return err; 2292 } 2293 revSeek -= flength; 2294 2295 if (!MP3FileIO::readByteData(fpUsed, MP3_FRAME_HEADER_SIZE, (uint8 *)&mp3Header)) 2296 { 2297 MP3Utils::SeektoOffset(fpUsed, revSeek , Oscl_File::SEEKCUR); 2298 return MP3_INSUFFICIENT_DATA; 2299 } 2300 2301 mp3Header = SwapFileToHostByteOrderInt32((uint8 *) & mp3Header); 2302 2303 status = GetMP3Header(mp3Header, mp3HeaderInfo); 2304 status = DecodeMP3Header(mp3HeaderInfo, mp3CDInfo3, false); 2305 2306 flength = mp3CDInfo3.FrameLengthInBytes; 2307 err = MP3Utils::SeektoOffset(fpUsed, flength - MP3_FRAME_HEADER_SIZE, Oscl_File::SEEKCUR); 2308 if (MP3_SUCCESS != err) 2309 { 2310 MP3Utils::SeektoOffset(fpUsed, revSeek - MP3_FRAME_HEADER_SIZE, Oscl_File::SEEKCUR); 2311 return err; 2312 } 2313 revSeek -= flength; 2314 2315 if (!MP3FileIO::readByteData(fpUsed, MP3_FRAME_HEADER_SIZE, (uint8 *)&mp3Header)) 2316 { 2317 MP3Utils::SeektoOffset(fpUsed, revSeek, Oscl_File::SEEKCUR); 2318 return MP3_INSUFFICIENT_DATA; 2319 } 2320 revSeek -= MP3_FRAME_HEADER_SIZE; 2321 2322 mp3Header = SwapFileToHostByteOrderInt32((uint8 *) & mp3Header); 2323 2324 status = GetMP3Header(mp3Header, mp3HeaderInfo); 2325 status = DecodeMP3Header(mp3HeaderInfo, mp3CDInfo4, false); 2326 2327 2328 /* 2329 * Check that the sampling rate and the number of channels is 2330 * the same for all the frames (everything else may change) 2331 */ 2332 if ((mp3CDInfo.SamplingRate != mp3CDInfo2.SamplingRate) | 2333 (mp3CDInfo3.SamplingRate != mp3CDInfo4.SamplingRate) | 2334 (mp3CDInfo3.SamplingRate != mp3CDInfo.SamplingRate)) 2335 { 2336 MP3Utils::SeektoOffset(fpUsed, revSeek, Oscl_File::SEEKCUR); 2337 return MP3_FILE_HDR_READ_ERR; 2338 } 2339 2340 if ((mp3CDInfo.NumberOfChannels != mp3CDInfo2.NumberOfChannels) | 2341 (mp3CDInfo3.NumberOfChannels != mp3CDInfo4.NumberOfChannels) | 2342 (mp3CDInfo3.NumberOfChannels != mp3CDInfo.NumberOfChannels)) 2343 { 2344 MP3Utils::SeektoOffset(fpUsed, revSeek, Oscl_File::SEEKCUR); 2345 return MP3_FILE_HDR_READ_ERR; 2346 } 2347 2348 // seek back to position from where we started 2349 MP3Utils::SeektoOffset(fpUsed, revSeek, Oscl_File::SEEKCUR); 2350 return MP3_SUCCESS; 2351 } 2352 2353 /*********************************************************************** 2354 * FUNCTION: mp3VerifyCRC 2355 * DESCRIPTION: 2356 * INPUT/OUTPUT PARAMETERS: verifies the crc if crc check is enabled and 2357 * crc flag is present 2358 * RETURN VALUE: 2359 * SIDE EFFECTS: 2360 ***********************************************************************/ 2361 MP3ErrorType MP3Parser::mp3VerifyCRC(MP3HeaderType mp3HdrInfo, MP3ConfigInfoType mp3CI) 2362 { 2363 if (!iEnableCrcCalc || mp3HdrInfo.crcFollows) 2364 { 2365 return MP3_SUCCESS; 2366 } 2367 2368 uint32 numberOfBits; 2369 uint32 bound = 32; 2370 uint32 numberOfBytes = 0; 2371 uint8 crcData[2]; 2372 2373 if (mp3HdrInfo.chMode == CHANNEL_MODE_JOINT_STEREO) 2374 bound = 4 + mp3HdrInfo.modeExtn * 4; 2375 2376 2377 switch (mp3HdrInfo.layerID) 2378 { 2379 case MPEG_LAYER_I: 2380 numberOfBits = 4 * (mp3CI.NumberOfChannels * bound + (32 - bound)); 2381 break; 2382 case MPEG_LAYER_II: 2383 // no check for Layer II 2384 return MP3_SUCCESS; 2385 2386 case MPEG_LAYER_III: 2387 numberOfBits = (mp3HdrInfo.frameVer == FRAME_VESION_MPEG_1) ? 2388 (mp3HdrInfo.chMode == CHANNEL_MODE_MONO ? 17 * 8 : 32 * 8) : 2389 (mp3HdrInfo.chMode == CHANNEL_MODE_MONO ? 9 * 8 : 17 * 8) ; 2390 2391 break; 2392 default: 2393 return MP3_SUCCESS; 2394 } 2395 2396 // Add header size and CRC value. 2397 //CalcCRC16 will take care of removing first 2 bytes of Hdr and 2 bytes of CRCvalue 2398 numberOfBits += MP3_FRAME_HEADER_SIZE * 8 + 16; 2399 2400 numberOfBytes = numberOfBits % 8 ? numberOfBits / 8 + 1 : numberOfBits / 8; 2401 2402 uint8 *buffer = OSCL_ARRAY_NEW(uint8 , numberOfBytes + 1); 2403 int32 revSeek = 0; 2404 if (!MP3FileIO::readByteData(fp, numberOfBytes, (uint8 *)buffer)) 2405 { 2406 return MP3_INSUFFICIENT_DATA; 2407 } 2408 2409 revSeek -= numberOfBytes; 2410 2411 uint16 calcCRC16 = CalcCRC16(buffer, numberOfBits); 2412 2413 // read crc from frame 2414 uint32 remBytes = 0; 2415 if (fp->GetRemainingBytes(remBytes)) 2416 { 2417 if (remBytes >= MP3_FRAME_HEADER_SIZE) 2418 { 2419 MP3Utils::SeektoOffset(fp, MP3_FRAME_HEADER_SIZE, Oscl_File::SEEKCUR); 2420 revSeek -= MP3_FRAME_HEADER_SIZE; 2421 } 2422 else 2423 { 2424 MP3Utils::SeektoOffset(fp, revSeek, Oscl_File::SEEKCUR); 2425 return MP3_INSUFFICIENT_DATA; 2426 } 2427 } 2428 else 2429 { 2430 MP3Utils::SeektoOffset(fp, revSeek, Oscl_File::SEEKCUR); 2431 return MP3_ERROR_UNKNOWN; 2432 } 2433 2434 if (!MP3FileIO::readByteData(fp, 2, (uint8 *)crcData)) 2435 { 2436 MP3Utils::SeektoOffset(fp, revSeek, Oscl_File::SEEKCUR); 2437 return MP3_INSUFFICIENT_DATA; 2438 } 2439 revSeek -= 2; 2440 2441 uint16 crcVal = SwapFileToHostByteOrderInt16(&crcData[0]); 2442 2443 // seek back to original start position 2444 MP3ErrorType err = MP3Utils::SeektoOffset(fp, revSeek, Oscl_File::SEEKCUR); 2445 if (MP3_SUCCESS != err) 2446 { 2447 return err; 2448 } 2449 2450 if (calcCRC16 == crcVal) 2451 { 2452 OSCL_ARRAY_DELETE(buffer); 2453 return MP3_SUCCESS; 2454 } 2455 2456 OSCL_ARRAY_DELETE(buffer); 2457 return MP3_CRC_ERR; 2458 2459 } 2460 uint16 MP3Parser::CalcCRC16(uint8* pBuffer, uint32 dwBitSize) 2461 { 2462 uint32 n; 2463 uint16 tmpchar, crcmask, tmpi; 2464 crcmask = tmpchar = 0; 2465 uint16 crc = 0xffff; // start with inverted value of 0 2466 2467 // start with byte 2 of header 2468 for (n = 16; n < dwBitSize; n++) 2469 { 2470 if (n < 32 || n >= 48) // skip the 2 bytes of the crc itself 2471 { 2472 if (n % 8 == 0) 2473 { 2474 crcmask = 1 << 8; 2475 tmpchar = pBuffer[n/8]; 2476 } 2477 crcmask >>= 1; 2478 tmpi = crc & 0x8000; 2479 crc <<= 1; 2480 2481 if (!tmpi ^ !(tmpchar & crcmask)) 2482 crc ^= 0x8005; 2483 } 2484 } 2485 crc &= 0xffff; // invert the result 2486 return crc; 2487 } 2488 2489 /*********************************************************************** 2490 * FUNCTION: GetSampleCountInFile 2491 * DESCRIPTION: 2492 * INPUT/OUTPUT PARAMETERS: 2493 * RETURN VALUE: 2494 * SIDE EFFECTS: 2495 ***********************************************************************/ 2496 uint32 MP3Parser::GetSampleCountInFile() 2497 { 2498 return iNumberOfFrames; 2499 } 2500 2501 /*********************************************************************** 2502 * FUNCTION: GetMaximumDecodeBufferSize 2503 * DESCRIPTION: 2504 * INPUT/OUTPUT PARAMETERS: 2505 * RETURN VALUE: 2506 * SIDE EFFECTS: 2507 ***********************************************************************/ 2508 uint32 MP3Parser::GetMaximumDecodeBufferSize() 2509 { 2510 // Compressed Frame Size 2511 uint32 maxBitRate; 2512 uint32 minSamplingRate ; 2513 uint32 frameLengthInBytes; 2514 uint32 samplesPerFrame; 2515 2516 if (iMP3HeaderInfo.frameVer == 3) // MPEG Ver 1 2517 { 2518 maxBitRate = brIndexTableV1[iMP3HeaderInfo.layerID][14]; 2519 } 2520 else // MPEG Ver 2, 2.5 2521 { 2522 maxBitRate = brIndexTableV2[iMP3HeaderInfo.layerID][14]; 2523 } 2524 2525 samplesPerFrame = spfIndexTable[iMP3HeaderInfo.frameVer][iMP3HeaderInfo.layerID]; 2526 minSamplingRate = srIndexTable[((iMP3HeaderInfo.frameVer)*4) + 2]; 2527 2528 if (minSamplingRate != 0) 2529 { 2530 frameLengthInBytes = 125 * (maxBitRate * samplesPerFrame) / (minSamplingRate); 2531 } 2532 else 2533 { 2534 frameLengthInBytes = KMAX_MP3FRAME_LENGTH_IN_BYTES; // allow for pad byte 2535 } 2536 2537 return frameLengthInBytes; 2538 } 2539 2540 2541 /*********************************************************************** 2542 * FUNCTION: GetFileSize 2543 * DESCRIPTION: 2544 * INPUT/OUTPUT PARAMETERS: 2545 * RETURN VALUE: 2546 * SIDE EFFECTS: 2547 ***********************************************************************/ 2548 uint32 MP3Parser::GetFileSize() 2549 { 2550 return iLocalFileSize; 2551 } 2552 2553 /*********************************************************************** 2554 * FUNCTION: GetTimestampForCurrentSample 2555 * DESCRIPTION: 2556 * INPUT/OUTPUT PARAMETERS: 2557 * RETURN VALUE: 2558 * SIDE EFFECTS: 2559 ***********************************************************************/ 2560 uint32 MP3Parser::GetTimestampForCurrentSample() const 2561 { 2562 return iTimestamp; 2563 } 2564 2565 uint32 MP3Parser::GetTimestampForSample(int32 aFrameNumber) const 2566 { 2567 uint32 timestamp = 0; 2568 timestamp = (uint32)((1000.00f * (OsclFloat)aFrameNumber * 2569 (OsclFloat)iMP3ConfigInfo.FrameSizeUnComp) / 2570 (OsclFloat)iMP3ConfigInfo.SamplingRate); 2571 return timestamp; 2572 } 2573 2574 /*********************************************************************** 2575 * FUNCTION: GetDecoderSpecificInfoSize 2576 * DESCRIPTION: 2577 * INPUT/OUTPUT PARAMETERS: 2578 * RETURN VALUE: 2579 * SIDE EFFECTS: 2580 ***********************************************************************/ 2581 uint32 MP3Parser::GetDecoderSpecificInfoSize() 2582 { 2583 return ConfigSize; 2584 } 2585 2586 /*********************************************************************** 2587 * FUNCTION: GetDecoderSpecificInfoContent 2588 * DESCRIPTION: 2589 * INPUT/OUTPUT PARAMETERS: 2590 * RETURN VALUE: 2591 * SIDE EFFECTS: 2592 ***********************************************************************/ 2593 uint8 const * MP3Parser::GetDecoderSpecificInfoContent() const 2594 { 2595 return (const uint8 *)&(ConfigData); 2596 } 2597 2598 int32 MP3Parser :: CalculateBufferSizeForHeader(uint8 *VbriHead) 2599 { 2600 int32 tableLength; 2601 int32 tempEntriesTOC, tempSizePerTableEntry; 2602 2603 VbriHead += 18; 2604 tempEntriesTOC = SwapFileToHostByteOrderInt16(VbriHead); 2605 VbriHead += 4; 2606 2607 tempSizePerTableEntry = SwapFileToHostByteOrderInt16(VbriHead); 2608 tableLength = tempEntriesTOC * tempSizePerTableEntry; 2609 2610 int32 returnValue = tableLength + 26; //TOC bytes + Upper header bytes 2611 2612 VbriHead -= 22; //Reset the file pointer to its original place 2613 2614 return returnValue; 2615 } 2616 2617 /*********************************************************************** 2618 * Function : IsMp3File 2619 * Purpose : Verifies whether the file passed in is a possibly 2620 * valid mp3 clip 2621 * Input : aFile, file to check 2622 * aInitSearchFileSize, amount of data to use for verification 2623 * Output : None 2624 * Return : error code 2625 * Modified : 2626 ***********************************************************************/ 2627 MP3ErrorType MP3Parser::IsMp3File(MP3_FF_FILE* aFile, uint32 aInitSearchFileSize) 2628 { 2629 MP3ErrorType errCode = MP3_SUCCESS; 2630 uint8 pFrameHeader[MP3_FRAME_HEADER_SIZE]; 2631 uint32 firstHeader = 0; 2632 StartOffset = 0; 2633 int32 revSeek = 0; 2634 2635 // get the file pointer 2636 fp = &(aFile->_pvfile); 2637 2638 errCode = MP3Utils::SeektoOffset(fp, 0, Oscl_File::SEEKSET); 2639 // try to retrieve the file size 2640 if (MP3Utils::getCurrentFileSize(fp, iLocalFileSize)) 2641 { 2642 iLocalFileSizeSet = true; 2643 iInitSearchFileSize = OSCL_MIN(aInitSearchFileSize, iLocalFileSize); 2644 if (iLocalFileSize == 0) 2645 { 2646 return MP3_END_OF_FILE; 2647 } 2648 } 2649 2650 if (!iLocalFileSizeSet) 2651 { 2652 uint32 remBytes = 0; 2653 if (fp->GetRemainingBytes(remBytes)) 2654 { 2655 iInitSearchFileSize = OSCL_MIN(iInitSearchFileSize, remBytes); 2656 } 2657 } 2658 2659 // seek to the begining position in the file 2660 2661 // verify if the id3 tags are present in this clip 2662 PVID3ParCom tagParser; 2663 iTagSize = 0; 2664 if (true == tagParser.IsID3V2Present(fp, iTagSize)) 2665 { 2666 // move the file read pointer to begining of audio data 2667 StartOffset += iTagSize; 2668 } 2669 2670 // seek to the begining position in the file 2671 MP3Utils::SeektoOffset(fp, StartOffset, Oscl_File::SEEKSET); 2672 2673 if (!MP3FileIO::readByteData(fp, MP3_FRAME_HEADER_SIZE, (uint8 *)pFrameHeader)) 2674 { 2675 return MP3_INSUFFICIENT_DATA; 2676 } 2677 revSeek = 0 - MP3_FRAME_HEADER_SIZE; 2678 2679 firstHeader = SwapFileToHostByteOrderInt32(pFrameHeader); 2680 2681 if (!GetMP3Header(firstHeader, iMP3HeaderInfo)) 2682 { 2683 uint32 seekOffset = 0; 2684 MP3Utils::SeektoOffset(fp, 0 - MP3_FRAME_HEADER_SIZE, Oscl_File::SEEKCUR); 2685 errCode = mp3FindSync(StartOffset, seekOffset, fp); 2686 if (errCode == MP3_SUCCESS) 2687 { 2688 errCode = MP3Utils::SeektoOffset(fp, seekOffset, Oscl_File::SEEKCUR); 2689 if (MP3_SUCCESS != errCode) 2690 { 2691 return errCode; 2692 } 2693 StartOffset += seekOffset; 2694 2695 if (!MP3FileIO::readByteData(fp, MP3_FRAME_HEADER_SIZE, pFrameHeader)) 2696 { 2697 return MP3_INSUFFICIENT_DATA; 2698 } 2699 2700 firstHeader = SwapFileToHostByteOrderInt32(pFrameHeader); 2701 2702 if (!GetMP3Header(firstHeader, iMP3HeaderInfo)) 2703 { 2704 return MP3_FILE_HDR_READ_ERR; 2705 } 2706 // retrieval of header was successful, try to decode it here. 2707 if (! DecodeMP3Header(iMP3HeaderInfo, iMP3ConfigInfo, false)) 2708 { 2709 // Header was invalid, decoding of header failed. 2710 return MP3_FILE_HDR_DECODE_ERR; 2711 } 2712 return MP3_SUCCESS; 2713 } 2714 else if (errCode == MP3_INSUFFICIENT_DATA) 2715 { 2716 MP3Utils::SeektoOffset(fp, fp->Tell() - StartOffset, Oscl_File::SEEKCUR); 2717 return errCode; 2718 } 2719 else 2720 { 2721 // File is not identified with the provided data 2722 return MP3_ERROR_UNKNOWN_OBJECT; 2723 } 2724 } 2725 2726 // retrieval of header was successful, try to decode it here. 2727 if (! DecodeMP3Header(iMP3HeaderInfo, iMP3ConfigInfo, false)) 2728 { 2729 // Header was invalid, decoding of header failed. 2730 return MP3_FILE_HDR_DECODE_ERR; 2731 } 2732 // mp3 header was valid it is an mp3 clip 2733 // return success. 2734 return MP3_SUCCESS; 2735 } 2736 2737 uint32 MP3Parser::GetFileOffsetForAutoResume(uint32& aOffset) 2738 { 2739 uint32 ts = GetTimestampForCurrentSample() + 10000; 2740 uint32 SeekPosition = 0; 2741 2742 uint32 seekpoint = SeekPointFromTimestamp(ts); 2743 if (seekpoint) 2744 { 2745 SeekPosition = StartOffset + seekpoint; 2746 } 2747 aOffset = SeekPosition; 2748 return 0; 2749 } 2750 2751 /*********************************************************************** 2752 * Function : SetFileSize 2753 * Purpose : Notification from the lib user for the file size, 2754 * Once File size is received, the same is used to 2755 * estimate the clip duration 2756 * Return : error code 2757 * Input : aFileSize 2758 * Output : None 2759 * Modified : 2760 ***********************************************************************/ 2761 MP3ErrorType MP3Parser::SetFileSize(const uint32 aFileSize) 2762 { 2763 iFileSizeFromExternalSource = aFileSize; 2764 iLocalFileSize = aFileSize; 2765 return MP3_SUCCESS; 2766 } 2767 2768 /** 2769 * Function : EstimateDurationFromExternalFileSize 2770 * Purpose : Estimates the clip duration from external file size 2771 * Return : error code 2772 * Input : None 2773 * Output : Clip duration 2774 * Modified : 2775 **/ 2776 MP3ErrorType MP3Parser::EstimateDurationFromExternalFileSize(uint32 &aClipDuration) 2777 { 2778 if (iClipDurationFromEstimation > 0) 2779 { 2780 aClipDuration = iClipDurationFromEstimation; 2781 return MP3_SUCCESS; 2782 } 2783 2784 if (iFileSizeFromExternalSource <= 0 || iMP3ConfigInfo.FrameLengthInBytes <= 0) 2785 { 2786 aClipDuration = 0; 2787 return MP3_ERROR_UNKNOWN; 2788 } 2789 uint32 fileSize = iFileSizeFromExternalSource; 2790 if (iId3TagParser.IsID3V2Present()) 2791 { 2792 fileSize -= StartOffset; 2793 } 2794 if (iId3TagParser.IsID3V1Present()) 2795 { 2796 // id3v1.x tags are 128 bytes long 2797 fileSize -= ID3_V1_TAG_SIZE; 2798 } 2799 2800 if ((iMP3HeaderInfo.srIndex == 3) || (iMP3HeaderInfo.brIndex == 15) || 2801 (iMP3HeaderInfo.frameVer == 1) || (iMP3HeaderInfo.layerID != 1)) 2802 { 2803 // invalid frame data, can not estimate duration 2804 return MP3_SUCCESS; 2805 } 2806 2807 iClipDurationFromEstimation = (uint32)((OsclFloat)(fileSize * 8000.00f / iAvgBitrateInbps)); 2808 aClipDuration = iClipDurationFromEstimation; 2809 return MP3_SUCCESS; 2810 } 2811 2812 /*********************************************************************** 2813 * Function : GetDurationFromVBRIHeader 2814 * Purpose : Estimates the clip duration from Vbri/Xing headers 2815 * Return : error code 2816 * Input : None 2817 * Output : Clip duration 2818 * Modified : 2819 ***********************************************************************/ 2820 MP3ErrorType MP3Parser::GetDurationFromVBRIHeader(uint32 &aClipDuration) 2821 { 2822 if (mp3Type != EVBRIType && mp3Type != EXINGType) 2823 { 2824 return MP3_ERROR_UNKNOWN; 2825 } 2826 2827 if ((mp3Type == EXINGType) && !(iXingHeader.flags & FRAMES_FLAG)) 2828 { 2829 return MP3_ERROR_UNKNOWN; 2830 } 2831 2832 if (iClipDurationFromVBRIHeader > 0) 2833 { 2834 aClipDuration = iClipDurationFromVBRIHeader; 2835 return MP3_SUCCESS; 2836 } 2837 2838 if ((iMP3HeaderInfo.srIndex == 3) || (iMP3HeaderInfo.brIndex == 15) || 2839 (iMP3HeaderInfo.frameVer == 1) || (iMP3HeaderInfo.layerID != 1)) 2840 { 2841 // invalid frame data, can not estimate duration 2842 return MP3_ERROR_UNKNOWN; 2843 } 2844 2845 iClipDurationFromVBRIHeader = (uint32)((OsclFloat)(iNumberOfFrames * iSamplesPerFrame) / iSamplingRate * 1000.00f); 2846 aClipDuration = iClipDurationFromVBRIHeader; 2847 return MP3_SUCCESS; 2848 } 2849 2850 /*********************************************************************** 2851 * Function : GetDurationFromRandomScan 2852 * Purpose : Estimates the clip duration by average bitrate 2853 * Average bit rate is calculated by randomnly scannning 2854 * predefined number of frames 2855 * Return : error code 2856 * Input : None 2857 * Output : Clip duration 2858 * Modified : 2859 ***********************************************************************/ 2860 MP3ErrorType MP3Parser::GetDurationFromRandomScan(uint32 &aClipDuration) 2861 { 2862 if (iClipDurationFromRandomScan > 0) 2863 { 2864 aClipDuration = iClipDurationFromRandomScan; 2865 return MP3_SUCCESS; 2866 } 2867 2868 MP3ErrorType status = MP3_SUCCESS; 2869 uint32 currFilePos = MP3Utils::getCurrentFilePosition(fp); 2870 2871 status = ComputeDurationFromNRandomFrames(fp); 2872 if (MP3_ERROR_UNKNOWN != status) 2873 { 2874 uint32 fileSz = iLocalFileSize - StartOffset; 2875 iClipDurationFromRandomScan = (uint32)(fileSz * 8000.00f / iAvgBitrateInbpsFromRandomScan); 2876 aClipDuration = iClipDurationFromRandomScan; 2877 } 2878 MP3Utils::SeektoOffset(fp, currFilePos, Oscl_File::SEEKSET); 2879 return status; 2880 } 2881 2882 /*********************************************************************** 2883 * Function : ComputeDurationFromNRandomFrames 2884 * Purpose : Estimates average bit rate by randomnly scannning input 2885 * number of frames 2886 * Return : error code 2887 * Input : numFrames 2888 * Output : iAvgBitrateInbpsFromRandomScan 2889 * Modified : 2890 ***********************************************************************/ 2891 MP3ErrorType MP3Parser::ComputeDurationFromNRandomFrames(PVFile * fpUsed, int32 aNumFrames, int32 aNumRandomLoc) 2892 { 2893 uint32 firstHeader = 0; 2894 uint8 pFrameHeader[MP3_FRAME_HEADER_SIZE]; 2895 uint32 audioOffset = 0; 2896 int32 totBR = 0; 2897 int32 avgBitRate = 0; 2898 int32 framecount = 0; 2899 uint32 randomByteOffset = 0; 2900 int32 audioDataSize = 0; 2901 MP3HeaderType mp3HeaderInfo; 2902 MP3ConfigInfoType mp3ConfigInfo; 2903 MP3ErrorType err = MP3_SUCCESS; 2904 2905 oscl_memset(&mp3ConfigInfo, 0, sizeof(mp3ConfigInfo)); 2906 oscl_memset(&mp3HeaderInfo, 0, sizeof(mp3HeaderInfo)); 2907 2908 // try to fetch file size 2909 if (iLocalFileSizeSet) 2910 { 2911 audioDataSize = iLocalFileSize; 2912 } 2913 2914 audioDataSize -= StartOffset; 2915 if (iId3TagParser.IsID3V1Present()) 2916 { 2917 audioDataSize -= ID3_V1_TAG_SIZE; 2918 } 2919 2920 randomByteOffset = StartOffset; 2921 uint32 skipMultiple = audioDataSize / (aNumRandomLoc + 1); 2922 2923 int32 numSearchLoc = 0; 2924 while (numSearchLoc < aNumRandomLoc) 2925 { 2926 // find random location to which we should seek in order to find 2927 uint32 currFilePosn = MP3Utils::getCurrentFilePosition(fpUsed); 2928 randomByteOffset = currFilePosn + skipMultiple; 2929 2930 if (randomByteOffset > iLocalFileSize) 2931 { 2932 break; 2933 } 2934 // initialize frame count 2935 framecount = 0; 2936 audioOffset = randomByteOffset; 2937 MP3Utils::SeektoOffset(fpUsed, audioOffset, Oscl_File::SEEKSET); 2938 // Find sync 2939 uint32 seekOffset = 0; 2940 err = mp3FindSync(audioOffset, seekOffset, fpUsed); 2941 if (err != MP3_SUCCESS) 2942 { 2943 break; 2944 } 2945 audioOffset += seekOffset; 2946 MP3Utils::SeektoOffset(fpUsed, seekOffset, Oscl_File::SEEKCUR); 2947 // lets check rest of the frames 2948 while (framecount < aNumFrames) 2949 { 2950 // Read 4 bytes 2951 if (!MP3FileIO::readByteData(fpUsed, MP3_FRAME_HEADER_SIZE, pFrameHeader)) 2952 { 2953 err = MP3_INSUFFICIENT_DATA; 2954 break; 2955 } 2956 2957 firstHeader = SwapFileToHostByteOrderInt32(pFrameHeader); 2958 // Read header 2959 if (!GetMP3Header(firstHeader, mp3HeaderInfo)) 2960 { 2961 err = MP3_FILE_HDR_READ_ERR; 2962 break; 2963 } 2964 // Decode header 2965 if (!DecodeMP3Header(mp3HeaderInfo, mp3ConfigInfo, false)) 2966 { 2967 err = MP3_FILE_HDR_DECODE_ERR; 2968 break; 2969 } 2970 2971 MP3Utils::SeektoOffset(fpUsed, mp3ConfigInfo.FrameLengthInBytes - MP3_FRAME_HEADER_SIZE, Oscl_File::SEEKCUR); 2972 framecount++; 2973 2974 // initialize avgBitRate first time only 2975 if (1 == framecount) 2976 { 2977 avgBitRate = mp3ConfigInfo.BitRate; 2978 } 2979 2980 if (mp3ConfigInfo.BitRate != avgBitRate) 2981 { 2982 avgBitRate += (mp3ConfigInfo.BitRate - avgBitRate) / framecount; 2983 } 2984 } 2985 totBR += avgBitRate; 2986 numSearchLoc++; 2987 } 2988 // calculate average bitrate 2989 iAvgBitrateInbpsFromRandomScan = numSearchLoc > 0 ? totBR / numSearchLoc : 0; 2990 if (!iAvgBitrateInbpsFromRandomScan) 2991 { 2992 return MP3_ERROR_UNKNOWN; 2993 } 2994 return err; 2995 } 2996 2997 void MP3Parser::GetDurationFromCompleteScan(uint32 &aClipDuration) 2998 { 2999 if (iClipDurationComputed > 0) 3000 { 3001 aClipDuration = iClipDurationComputed; 3002 return; 3003 } 3004 uint32 samplesPerFrame = spfIndexTable[iMP3HeaderInfo.frameVer][iMP3HeaderInfo.layerID]; 3005 uint32 samplingRate = srIndexTable[((iMP3HeaderInfo.frameVer)*4) + iMP3HeaderInfo.srIndex]; 3006 OsclFloat samplingRateinKHz = (OsclFloat)samplingRate / 1000; 3007 3008 iClipDurationComputed = (uint32)(iScannedFrameCount * (OsclFloat)(samplesPerFrame / samplingRateinKHz)); 3009 aClipDuration = iClipDurationComputed; 3010 } 3011 3012 MP3ErrorType MP3Parser::FillTOCTable(uint32 aFilePos, uint32 aTimeStampToFrame) 3013 { 3014 if (iTOC == NULL) 3015 { 3016 // Not a valid condition this should never happen, except if 3017 // there was memory allocation failure during ParseMP3File. 3018 // Just return Failure here to avoid any further calls of FillTOCTable 3019 return MP3_ERROR_UNKNOWN; 3020 } 3021 3022 if (iDurationScanComplete) 3023 { 3024 iTOC[iTOCFilledCount] = aFilePos; 3025 iTOCFilledCount++; 3026 if (0 == iTimestampPrev) 3027 { 3028 GetDurationFromCompleteScan(iBinWidth); 3029 } 3030 return MP3_SUCCESS; 3031 } 3032 3033 if ((iTOCFilledCount < MAX_TOC_ENTRY_COUNT) && ((aTimeStampToFrame - iTimestampPrev) >= iBinWidth)) 3034 { 3035 if (iTimestampPrev != aTimeStampToFrame) 3036 { 3037 if ((aTimeStampToFrame - iTimestampPrev) > iBinWidth) 3038 { 3039 iBinWidth = aTimeStampToFrame - iTimestampPrev; 3040 } 3041 } 3042 // push the file offset into TOC table 3043 iTOC[iTOCFilledCount] = aFilePos - StartOffset; 3044 iTOCFilledCount++; 3045 iTimestampPrev = aTimeStampToFrame; 3046 } 3047 else if (iTOCFilledCount == MAX_TOC_ENTRY_COUNT) 3048 { 3049 // run the compaction algorithm to compress the TOC table 3050 for (uint32 i = 0; i < (MAX_TOC_ENTRY_COUNT / 2); i++) 3051 { 3052 iTOC[i] = iTOC[2*i]; 3053 } 3054 iTimestampPrev = iTimestampPrev - iBinWidth; 3055 iBinWidth = 2 * iBinWidth; 3056 iTOCFilledCount = MAX_TOC_ENTRY_COUNT / 2; 3057 } 3058 return MP3_SUCCESS; 3059 } 3060 3061 3062 3063 3064