Home | History | Annotate | Download | only in src
      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 &timestamp)
   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