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 ×tamp)
1814 {
1815 uint32 seekPoint = 0;
1816 uint32 seekOffset = 0;
1817 OsclFloat percent = 0;
1818 uint32 binNo = 0;
1819
1820 bool bUseTOCForRepos = false;
1821
1822 uint32 maxTSInTOC = iTOCFilledCount * iBinWidth;
1823 if (iTOCFilledCount > 1 && (timestamp < maxTSInTOC || iDurationScanComplete))
1824 {
1825 bUseTOCForRepos = true;
1826 }
1827
1828 // XING - Use VBR TOC Header
1829 if ((mp3Type == EXINGType) && (iXingHeader.flags & TOC_FLAG))
1830 {
1831 // Interpolate in TOC to get file seek point in bytes
1832 OsclFloat fpc = (OsclFloat)timestamp / (OsclFloat)iClipDurationFromVBRIHeader;
1833 OsclFloat fa, fb, fx;
1834 uint32 pc;
1835
1836 if (fpc < 0.00f)
1837 fpc = 0.00f;
1838
1839 if (fpc > 1.00f)
1840 fpc = 1.00f;
1841
1842 pc = (uint32)(fpc * 100.00f);
1843 fa = (OsclFloat)iXingHeader.TOC[pc];
1844
1845 if (pc > 99)
1846 pc = 99;
1847
1848 if (pc < 99)
1849 fb = (OsclFloat)iXingHeader.TOC[pc+1];
1850 else
1851 fb = 256.00f;
1852
1853 // //////////////////////////////////////////////////////////
1854 // Linearly interpolate between fa and fb
1855 // TOC's appear to max out at TOC[80] = 0cff (255)
1856 // //////////////////////////////////////////////////////////
1857 fx = fa + (fb - fa) * ((100.00f * fpc) - (OsclFloat)pc);
1858 percent = fx;
1859 if (iXingHeader.flags == 15 || iXingHeader.flags == 7 || iXingHeader.flags == 3)
1860 {
1861 seekPoint = (int32)((fx / 256.00f) * (OsclFloat)iXingHeader.bytes);
1862 if ((seekPoint > (uint32)iXingHeader.bytes))
1863 {
1864 seekPoint = 0;
1865 percent = 0;
1866 }
1867 }
1868 else
1869 {
1870 seekPoint = 0;
1871 percent = 0;
1872 }
1873 }
1874 else if (mp3Type == EVBRIType)
1875 // //////////////////////////////////////////////////////////
1876 // CBR or VBRI
1877 {
1878 uint32 i = 0, fraction = 0, SamplesPerFrame;
1879 OsclFloat fLengthMS;
1880 OsclFloat fLengthMSPerTOCEntry;
1881 OsclFloat fAccumulatedTimeMS = 0.0f;
1882 (iVbriHeader.sampleRate >= 32000) ? (SamplesPerFrame = 1152) : (SamplesPerFrame = 576);
1883
1884
1885 fLengthMS = ((OsclFloat)iVbriHeader.frames * (OsclFloat)SamplesPerFrame)
1886 / (OsclFloat)iVbriHeader.sampleRate * 1000.0f;
1887
1888 fLengthMSPerTOCEntry = (OsclFloat)fLengthMS / (OsclFloat)(iVbriHeader.entriesTOC + 1);
1889
1890 if (timestamp > fLengthMS)
1891 timestamp = (uint32)fLengthMS;
1892
1893 while (fAccumulatedTimeMS <= timestamp)
1894 {
1895 seekPoint += iVbriHeader.TOC[i];
1896 fAccumulatedTimeMS += fLengthMSPerTOCEntry;
1897 i++;
1898 }
1899
1900 fraction = ((int)((((fAccumulatedTimeMS - timestamp) / fLengthMSPerTOCEntry)
1901 + (1.0f / (2.0f * (OsclFloat)iVbriHeader.fTableEntry))) * (OsclFloat)iVbriHeader.fTableEntry));
1902
1903 seekPoint -= (int)((OsclFloat)iVbriHeader.TOC[i-1] * (OsclFloat)(fraction)
1904 / (OsclFloat)iVbriHeader.fTableEntry);
1905 }
1906 else if (bUseTOCForRepos)
1907 {
1908 // Use TOC for calculating seek point.
1909 OsclFloat fpc = (OsclFloat)timestamp / (OsclFloat)iClipDurationInMsec;
1910 binNo = (uint32)(fpc * iTOCFilledCount);
1911 uint32 TScurr = binNo * iBinWidth;
1912 while (TScurr > timestamp)
1913 {
1914 binNo--;
1915 TScurr = binNo * iBinWidth;
1916 }
1917
1918 uint32 offsetDiff = iTOC[binNo+1] - iTOC[binNo];
1919 uint32 tsDiff = timestamp - TScurr;
1920 seekPoint = iTOC[binNo] + tsDiff * (offsetDiff / iBinWidth);
1921 }
1922 else
1923 {
1924 /**
1925 * vbri and xing headers are not present. seek offset will be
1926 * calculated on the basis of average bit rate
1927 **/
1928 int32 avgBR = 0;
1929 if (fp->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