• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  ***********************************************************************/
SwapFileToHostByteOrderInt32(uint8 * pBuf2)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  ***********************************************************************/
ReadBuffer(uint8 * pBuf2,int32 length,int32 & pos)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  ***********************************************************************/
SwapFileToHostByteOrderInt16(uint8 * pBuf2)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  ***********************************************************************/
MP3Parser(PVFile * aFileHandle)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  ***********************************************************************/
~MP3Parser()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  ***********************************************************************/
ParseMP3File(PVFile * fpUsed,bool aEnableCRC)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->GetCPM() == NULL && 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  ***********************************************************************/
ScanMP3File(PVFile * fpUsed,uint32 aFramesToScan)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->GetCPM() == NULL)
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  ***********************************************************************/
GetMP3Header(uint32 & aFrameHeader,MP3HeaderType & aMP3HeaderInfo)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  ***********************************************************************/
DecodeMP3Header(MP3HeaderType & aMP3HeaderInfo,MP3ConfigInfoType & aMP3ConfigInfo,bool aComputeAvgBitrate)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  ***********************************************************************/
DecodeVBRIHeader(uint8 * VbriBuffer,VBRIHeaderType & vbriHDType,MP3HeaderType & aMP3HeaderInfo)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  ***********************************************************************/
DecodeXINGHeader(uint8 * XingBuffer,XINGHeaderType & mp3XingHD,MP3HeaderType & hdrInfo)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  ***********************************************************************/
GetMP3FileHeader(MP3ConfigInfoType * pMP3Config)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  ***********************************************************************/
GetChannelMode() const1277 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  ***********************************************************************/
GetDurationFromMetadata()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  **********************************************************************/
ConvertSizeToTime(uint32 aFileSize,uint32 & aNPTInMS)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  **********************************************************************/
GetDuration(bool aMetadataDuration)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->GetCPM())
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  ***********************************************************************/
GetMetadataSize(uint32 & aMetadataSize)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  ***********************************************************************/
GetMinBytesRequired(bool aNextBytes)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  ***********************************************************************/
GetNextBundledAccessUnits(uint32 * n,GAU * pgau,MP3ErrorType & error)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  ***********************************************************************/
PeekNextBundledAccessUnits(uint32 * n,MediaMetaInfo * mInfo)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  ***********************************************************************/
GetNextMediaSample(uint8 * buffer,uint32 size,uint32 & framesize,uint32 & timestamp)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  ***********************************************************************/
SeekToTimestamp(uint32 timestampInMsec)1794 uint32  MP3Parser::SeekToTimestamp(uint32 timestampInMsec)
1795 {
1796     uint32 SeekPosition = 0;
1797     SeekPosition = SeekPointFromTimestamp(timestampInMsec);
1798     if (!((!fp->GetCPM()) && (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  ***********************************************************************/
SeekPointFromTimestamp(uint32 & timestamp)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->GetCPM())
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->GetCPM())
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  ***********************************************************************/
mp3FindSync(uint32 seekPoint,uint32 & syncOffset,PVFile * aFile)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->GetCPM() != NULL)
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  ***********************************************************************/
IsValidFrame(uint8 * pBuffer,uint32 offset,uint32 seekPoint,PVFile * aFile)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  ***********************************************************************/
IsValidFrameHeader(uint8 * mp3Frame,bool & bCRCPresent,uint32 firstSyncOffset,uint32 seekPoint,PVFile * aFile)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  ***********************************************************************/
mp3VerifyCRC(MP3HeaderType mp3HdrInfo,MP3ConfigInfoType mp3CI)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 }
CalcCRC16(uint8 * pBuffer,uint32 dwBitSize)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  ***********************************************************************/
GetSampleCountInFile()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  ***********************************************************************/
GetMaximumDecodeBufferSize()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  ***********************************************************************/
GetFileSize()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  ***********************************************************************/
GetTimestampForCurrentSample() const2560 uint32 MP3Parser::GetTimestampForCurrentSample() const
2561 {
2562     return iTimestamp;
2563 }
2564 
GetTimestampForSample(int32 aFrameNumber) const2565 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  ***********************************************************************/
GetDecoderSpecificInfoSize()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  ***********************************************************************/
GetDecoderSpecificInfoContent() const2593 uint8 const * MP3Parser::GetDecoderSpecificInfoContent() const
2594 {
2595     return (const uint8 *)&(ConfigData);
2596 }
2597 
CalculateBufferSizeForHeader(uint8 * VbriHead)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  ***********************************************************************/
IsMp3File(MP3_FF_FILE * aFile,uint32 aInitSearchFileSize)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 
GetFileOffsetForAutoResume(uint32 & aOffset)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  ***********************************************************************/
SetFileSize(const uint32 aFileSize)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  **/
EstimateDurationFromExternalFileSize(uint32 & aClipDuration)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  ***********************************************************************/
GetDurationFromVBRIHeader(uint32 & aClipDuration)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  ***********************************************************************/
GetDurationFromRandomScan(uint32 & aClipDuration)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  ***********************************************************************/
ComputeDurationFromNRandomFrames(PVFile * fpUsed,int32 aNumFrames,int32 aNumRandomLoc)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 
GetDurationFromCompleteScan(uint32 & aClipDuration)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 
FillTOCTable(uint32 aFilePos,uint32 aTimeStampToFrame)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