Home | History | Annotate | Download | only in src
      1 /* ------------------------------------------------------------------
      2  * Copyright (C) 1998-2009 PacketVideo
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
     13  * express or implied.
     14  * See the License for the specific language governing permissions
     15  * and limitations under the License.
     16  * -------------------------------------------------------------------
     17  */
     18 // -*- c++ -*-
     19 // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
     20 
     21 //                 A M R    F I L E    P A R S E R
     22 
     23 // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
     24 
     25 
     26 /**
     27  *  @file amrfileparser.cpp
     28  *  @brief This file contains the implementation of the raw GSM-AMR file parser.
     29  */
     30 
     31 //----------------------------------------------------------------------------
     32 // INCLUDES
     33 //----------------------------------------------------------------------------
     34 #include "amrfileparser.h"
     35 
     36 // Use default DLL entry point for Symbian
     37 #include "oscl_dll.h"
     38 OSCL_DLL_ENTRY_POINT_DEFAULT()
     39 
     40 
     41 /* Table containing the sum of the frame type byte     */
     42 /* and the number of speech bytes for each codec mode  */
     43 /* for IETF input format                                */
     44 static const int32 IetfDecInputBytes[NO_POSSIBLE_MODES] =
     45 {
     46     13, /* 4.75 */
     47     14, /* 5.15 */
     48     16, /* 5.90 */
     49     18, /* 6.70 */
     50     20, /* 7.40 */
     51     21, /* 7.95 */
     52     27, /* 10.2 */
     53     32, /* 12.2 */
     54     6, /* GsmAmr comfort noise */
     55     7, /* Gsm-Efr comfort noise */
     56     6, /* IS-641 comfort noise */
     57     6, /* Pdc-Efr comfort noise */
     58     1, /* future use; 0 length but set to 1 to skip the frame type byte */
     59     1, /* future use; 0 length but set to 1 to skip the frame type byte */
     60     1, /* future use; 0 length but set to 1 to skip the frame type byte */
     61     1  /* No transmission */
     62 };
     63 
     64 /* Table containing the number of speech bytes for each codec mode  */
     65 /* for IF2 input format                                             */
     66 static const int32 If2DecInputBytes[NO_POSSIBLE_MODES] =
     67 {
     68     13, /* 4.75 */
     69     14, /* 5.15 */
     70     16, /* 5.90 */
     71     18, /* 6.70 */
     72     19, /* 7.40 */
     73     21, /* 7.95 */
     74     26, /* 10.2 */
     75     31, /* 12.2 */
     76     6, /* GsmAmr comfort noise */
     77     6, /* Gsm-Efr comfort noise */
     78     6, /* IS-641 comfort noise */
     79     6, /* Pdc-Efr comfort noise */
     80     1, /* future use; 0 length but set to 1 to skip the frame type byte */
     81     1, /* future use; 0 length but set to 1 to skip the frame type byte */
     82     1, /* future use; 0 length but set to 1 to skip the frame type byte */
     83     1  /* No transmission */
     84 };
     85 
     86 static const int32 IetfWBDecInputBytes[NO_POSSIBLE_MODES] =
     87 {
     88     18, /* 6.60 */
     89     24, /* 8.85 */
     90     33, /* 12.65 */
     91     37, /* 14.25 */
     92     41, /* 15.85 */
     93     47, /* 18.25 */
     94     51, /* 19.85 */
     95     59, /* 23.05 */
     96     61, /* 23.85 */
     97     6,  /* SID */
     98     1,  /* For future use : Set to 1 to skip the frame type byte */
     99     1,  /* For future use : Set to 1 to skip the frame type byte */
    100     1,  /* For future use : Set to 1 to skip the frame type byte */
    101     1,  /* For future use : Set to 1 to skip the frame type byte */
    102     1,  /* Speech lost */
    103     1   /* No data/transmission */
    104 };
    105 
    106 //! specially used in ResetPlayback(), re-position the file pointer
    107 int32 bitstreamObject::reset(int32 filePos)
    108 {
    109     iFrame_type = 0;
    110     iBytesRead  = iInitFilePos + filePos; // set the initial value
    111     iBytesProcessed = iBytesRead;
    112     if (ipAMRFile)
    113     {
    114         ipAMRFile->Seek(iInitFilePos + filePos, Oscl_File::SEEKSET);
    115     }
    116     iPos = bitstreamObject::MAIN_BUFF_SIZE + bitstreamObject::SECOND_BUFF_SIZE;
    117     return refill();
    118 }
    119 
    120 //! read data from bitstream, this is the only function to read data from file
    121 int32 bitstreamObject::refill()
    122 {
    123     PVMF_AMRPARSER_LOGDEBUG((0, "Refill In ipos=%d, iBytesRead=%d, iBytesProcessed=%d, iActualSize=%d, iFileSize=%d", iPos, iBytesRead, iBytesProcessed, iActual_size, iFileSize));
    124 
    125     if (iBytesRead > 0 && iFileSize > 0 && iBytesRead >= iFileSize)
    126     {
    127         // if number of bytes read so far exceed the file size,
    128         // then first update the file size (PDL case).
    129         if (!UpdateFileSize()) return bitstreamObject::MISC_ERROR;
    130 
    131         //At this point we're within 32 bytes of the end of data.
    132         //Quit reading data but don't return EOF until all data is processed.
    133         if (iBytesProcessed < iBytesRead)
    134         {
    135             return bitstreamObject::EVERYTHING_OK;
    136         }
    137         else
    138         {
    139             //there is no more data to read.
    140             if (iBytesRead >= iFileSize || iBytesProcessed >= iFileSize)
    141                 return bitstreamObject::DATA_INSUFFICIENT;
    142         }
    143     }
    144 
    145     if (!ipAMRFile)
    146     {
    147         return bitstreamObject::MISC_ERROR;
    148     }
    149 
    150     // Get file size at the very first time
    151     if (iFileSize == 0)
    152     {
    153         if (ipAMRFile->Seek(0, Oscl_File::SEEKEND))
    154         {
    155             return bitstreamObject::MISC_ERROR;
    156         }
    157 
    158         iFileSize = ipAMRFile->Tell();
    159 
    160         if (iFileSize <= 0)
    161         {
    162             return bitstreamObject::MISC_ERROR;
    163         }
    164 
    165         if (ipAMRFile->Seek(0, Oscl_File::SEEKSET))
    166         {
    167             return bitstreamObject::MISC_ERROR;
    168         }
    169 
    170         // first-time read, set the initial value of iPos
    171         iPos = bitstreamObject::SECOND_BUFF_SIZE;
    172         iBytesProcessed = 0;
    173     }
    174     // we are currently positioned at the end of the data buffer.
    175     else if (iPos == bitstreamObject::MAIN_BUFF_SIZE + bitstreamObject::SECOND_BUFF_SIZE)
    176     {
    177         // reset iPos and refill from the beginning of the buffer.
    178         iPos = bitstreamObject::SECOND_BUFF_SIZE;
    179     }
    180 
    181     else if (iPos >= iActual_size)
    182     {
    183         int32 len = 0;
    184         // move the remaining stuff to the beginning of iBuffer
    185         if (iActual_size + bitstreamObject::SECOND_BUFF_SIZE > iPos)
    186         {
    187             // we are currently positioned within SECOND_BUFF_SIZE bytes from the end of the buffer.
    188             len = iActual_size + bitstreamObject::SECOND_BUFF_SIZE - iPos;
    189         }
    190         else
    191         {
    192             // no leftover data.
    193             len = 0;
    194         }
    195 
    196         oscl_memcpy(&iBuffer[bitstreamObject::SECOND_BUFF_SIZE-len], &iBuffer[iPos], len);
    197         iPos = bitstreamObject::SECOND_BUFF_SIZE - len;
    198 
    199         // update the file size for the PDL scenario where more data has been downloaded
    200         // into the file but the file size has not been updated yet.
    201         if (iBytesRead + iMax_size > iFileSize)
    202         {
    203             if (!UpdateFileSize()) return bitstreamObject::MISC_ERROR;
    204         }
    205     }
    206 
    207     // read data
    208     if ((iActual_size = ipAMRFile->Read(&iBuffer[bitstreamObject::SECOND_BUFF_SIZE], 1, iMax_size)) == 0)
    209     {
    210         return bitstreamObject::READ_ERROR;
    211     }
    212 
    213     iBytesRead += iActual_size;
    214 
    215     PVMF_AMRPARSER_LOGDEBUG((0, "Refill Out ipos=%d, iBytesRead=%d, iBytesProcessed=%d, iActualSize=%d, iFileSize=%d", iPos, iBytesRead, iBytesProcessed, iActual_size, iFileSize));
    216 
    217     return bitstreamObject::EVERYTHING_OK;
    218 }
    219 
    220 //! most important function to get one frame data plus frame type, used in getNextBundledAccessUnits()
    221 int32 bitstreamObject::getNextFrame(uint8* frameBuffer, uint8& frame_type, bool bHeaderIncluded)
    222 {
    223     PVMF_AMRPARSER_LOGDEBUG((0, "GetNextFrame In ipos=%d, iBytesRead=%d, iBytesProcessed=%d, iActualSize=%d, iFileSize=%d", iPos, iBytesRead, iBytesProcessed, iActual_size, iFileSize));
    224     if (!frameBuffer)
    225     {
    226         return bitstreamObject::MISC_ERROR;
    227     }
    228 
    229     int32 ret_value = bitstreamObject::EVERYTHING_OK;
    230 
    231     // Need to refill?
    232     if (iFileSize == 0 || iPos >= iActual_size)
    233     {
    234         ret_value = refill();
    235         if (ret_value)
    236         {
    237             return ret_value;
    238         }
    239     }
    240 
    241     int32 frame_size = 0;
    242     uint8 *pBuffer = &iBuffer[iPos];
    243 
    244     if (EAMRIETF_SingleNB == iAmrFormat) // IETF format single channel NB
    245     {
    246         // Search the next IETF frame header (NOT returning error when the error is corrupt)
    247         while ((iBuffer[iPos] & 0x83) != 0)
    248         {
    249             // Wrong IETF frame header(P+FT(4bits)+Q+PP)
    250             if (iPos + 1 >= iActual_size)
    251             {
    252                 ret_value = refill();
    253                 if (ret_value)
    254                 {
    255                     return ret_value;
    256                 }
    257             }
    258             iPos++;
    259             iBytesProcessed++;
    260         }
    261         pBuffer = &iBuffer[iPos];
    262         frame_type = (uint8)((pBuffer[0] >> 3) & 0x0f);
    263         frame_size = IetfDecInputBytes[(uint16)frame_type];
    264     }
    265     else if (EAMRIETF_SingleWB == iAmrFormat) // IETF format single channel WB
    266     {
    267         frame_type = (uint8)((pBuffer[0] >> 3) & 0x0f);
    268         frame_size = IetfWBDecInputBytes[(uint16)frame_type];
    269     }
    270     else if (iAmrFormat == EAMRIF2) // IF2 format
    271     {
    272         frame_type = (uint8)(pBuffer[0] & 0x0f);
    273         frame_size = If2DecInputBytes[(uint16)frame_type];
    274     }
    275     else
    276     {
    277         return bitstreamObject::MISC_ERROR;
    278     }
    279 
    280     PVMF_AMRPARSER_LOGDEBUG((0, "GetNextFrame Before Read frame ipos=%d, iBytesRead=%d, iBytesProcessed=%d, iActualSize=%d, iFileSize=%d", iPos, iBytesRead, iBytesProcessed, iActual_size, iFileSize));
    281 
    282     if (frame_size > 0)
    283     {
    284         if (bHeaderIncluded)
    285         {
    286             oscl_memcpy(frameBuffer, &pBuffer[0], frame_size);   // With frame header
    287         }
    288         else
    289         {
    290             oscl_memcpy(frameBuffer, &pBuffer[1], frame_size - 1); // NO frame header
    291         }
    292     }
    293     iPos += frame_size;
    294     iBytesProcessed += frame_size;
    295 
    296     PVMF_AMRPARSER_LOGDEBUG((0, "GetNextFrame Out ipos=%d, iBytesRead=%d, iBytesProcessed=%d, iActualSize=%d, iFileSize=%d", iPos, iBytesRead, iBytesProcessed, iActual_size, iFileSize));
    297     return ret_value;
    298 }
    299 
    300 //! parse the IETF bitstream header: "$!AMR" + 0x0a, and get format(IETF, IF2, or WMF)
    301 int32 bitstreamObject::parseIETFHeader()
    302 {
    303     int32 returnValue = reset();
    304     if (returnValue == bitstreamObject::EVERYTHING_OK)
    305     {
    306         iAmrFormat = EAMRUnrecognized;
    307 
    308         // first time read, we don't use iSecond_buffer
    309         uint8 *pBuffer = &iBuffer[iPos];
    310         if (iActual_size >= 5 &&
    311                 pBuffer[0] == '#' &&
    312                 pBuffer[1] == '!' &&
    313                 pBuffer[2] == 'A' &&
    314                 pBuffer[3] == 'M' &&
    315                 pBuffer[4] == 'R')
    316         {
    317 
    318             if (pBuffer[5] == 0x0a)
    319             {
    320                 // single channel AMR file
    321                 iAmrFormat  = EAMRIETF_SingleNB;
    322                 iInitFilePos = 6;
    323             }
    324 
    325             else if (iActual_size >= 11 &&
    326                      pBuffer[5]  == '_' &&
    327                      pBuffer[6]  == 'M' &&
    328                      pBuffer[7]  == 'C' &&
    329                      pBuffer[8]  == '1' &&
    330                      pBuffer[9]  == '.' &&
    331                      pBuffer[10] == '0' &&
    332                      pBuffer[11] == 0x0a)
    333             {
    334                 // multi-channel AMR file
    335                 iAmrFormat = EAMRIETF_MultiNB;
    336                 iInitFilePos = 12;
    337             }
    338             else if (iActual_size >= 8  &&
    339                      pBuffer[5] == '-'  &&
    340                      pBuffer[6] == 'W'  &&
    341                      pBuffer[7] == 'B')
    342             {
    343 
    344                 if (pBuffer[8] == 0x0a)
    345                 {
    346                     // single channel AMR-WB file
    347                     iAmrFormat  = EAMRIETF_SingleWB;
    348                     iInitFilePos = 9;
    349                 }
    350                 else if (iActual_size >= 14     &&
    351                          pBuffer[8]   == '_'    &&
    352                          pBuffer[9]   == 'M'    &&
    353                          pBuffer[10]  == 'C'    &&
    354                          pBuffer[11]  == '1'    &&
    355                          pBuffer[12]  == '.'    &&
    356                          pBuffer[13]  == '0'    &&
    357                          pBuffer[14]  == 0x0a)
    358                 {
    359                     // multi-channel AMR-WB file
    360                     iAmrFormat = EAMRIETF_MultiWB;
    361                     iInitFilePos = 15;
    362                 }
    363             }
    364         }
    365         iPos += iInitFilePos;
    366         iBytesProcessed += iInitFilePos;
    367 
    368         // get the frame header
    369         if (iAmrFormat == EAMRUnrecognized)
    370         {
    371             iFrame_type = iBuffer[iPos] & 0xf;
    372         }
    373         else // IETF
    374         {
    375             iFrame_type = (iBuffer[iPos] >> 3) & 0xf;
    376         }
    377     }
    378 
    379     return returnValue;
    380 }
    381 
    382 //! get clip information: file size, format(IETF or IF2) and frame_type(bitrate)
    383 int32 bitstreamObject::getFileInfo(int32& fileSize, int32& format, int32& frame_type)
    384 {
    385     fileSize = format = 0;
    386     int32 ret_value = bitstreamObject::EVERYTHING_OK;
    387     if (iFileSize == 0)
    388     {
    389         ret_value = parseIETFHeader();
    390         if (ret_value)
    391         {
    392             return ret_value;
    393         }
    394     }
    395 
    396     fileSize = iFileSize;
    397     format = iAmrFormat;
    398     frame_type = iFrame_type;
    399     return ret_value;
    400 }
    401 
    402 //! get the updated file size
    403 bool bitstreamObject::UpdateFileSize()
    404 {
    405     if (ipAMRFile != NULL)
    406     {
    407         uint32 aRemBytes = 0;
    408         if (ipAMRFile->GetRemainingBytes(aRemBytes))
    409         {
    410             uint32 currPos = (uint32)(ipAMRFile->Tell());
    411             iFileSize = currPos + aRemBytes;
    412             return true;
    413         }
    414     }
    415     return false;
    416 }
    417 
    418 
    419 //----------------------------------------------------------------------------
    420 // FUNCTION NAME: CAMRFileParser::CAMRFileParser
    421 //----------------------------------------------------------------------------
    422 // INPUT AND OUTPUT DEFINITIONS
    423 //
    424 //  Inputs:
    425 //    None
    426 //
    427 //  Outputs:
    428 //    None
    429 //
    430 //  Returns:
    431 //    None
    432 //
    433 //  Global Variables Used:
    434 //    None
    435 //
    436 //----------------------------------------------------------------------------
    437 // FUNCTION DESCRIPTION
    438 //
    439 //  Constructor for CAMRFileParser class
    440 //----------------------------------------------------------------------------
    441 // REQUIREMENTS
    442 //
    443 //----------------------------------------------------------------------------
    444 // REFERENCES
    445 //
    446 //------------------------------------------------------------------------------
    447 // CAUTION
    448 //
    449 //------------------------------------------------------------------------------
    450 OSCL_EXPORT_REF CAMRFileParser::CAMRFileParser(void)
    451 {
    452     iAMRDuration        = -1;
    453     iAMRBitRate         = 0;
    454     iTotalNumFramesRead = 0;
    455     iAMRFormat          = EAMRUnrecognized;
    456     iEndOfFileReached   = false;
    457     iRandomAccessTimeInterval = 0;
    458     iCountToClaculateRDATimeInterval = 0;
    459     iLogger = PVLogger::GetLoggerObject("pvamr_parser");
    460     iDiagnosticLogger = PVLogger::GetLoggerObject("playerdiagnostics.pvamr_parser");
    461 
    462     ipBSO = NULL;
    463 }
    464 
    465 //----------------------------------------------------------------------------
    466 // FUNCTION NAME: CAMRFileParser::~CAMRFileParser
    467 //----------------------------------------------------------------------------
    468 // INPUT AND OUTPUT DEFINITIONS
    469 //
    470 //  Inputs:
    471 //    None
    472 //
    473 //  Outputs:
    474 //    None
    475 //
    476 //  Returns:
    477 //    None
    478 //
    479 //  Global Variables Used:
    480 //    None
    481 //
    482 //----------------------------------------------------------------------------
    483 // FUNCTION DESCRIPTION
    484 //
    485 //  Destructor for CAMRFileParser class
    486 //----------------------------------------------------------------------------
    487 // REQUIREMENTS
    488 //
    489 //----------------------------------------------------------------------------
    490 // REFERENCES
    491 //
    492 //------------------------------------------------------------------------------
    493 // CAUTION
    494 //
    495 //------------------------------------------------------------------------------
    496 OSCL_EXPORT_REF CAMRFileParser::~CAMRFileParser(void)
    497 {
    498     iAMRFile.Close();
    499     OSCL_DELETE(ipBSO);
    500     ipBSO = NULL;
    501 }
    502 
    503 //----------------------------------------------------------------------------
    504 // FUNCTION NAME: CAMRFileParser::InitAMRFile
    505 //----------------------------------------------------------------------------
    506 // INPUT AND OUTPUT DEFINITIONS
    507 //
    508 //  Inputs:
    509 //    iClip = pointer to the AMR file name to be played of type TPtrC
    510 //
    511 //  Outputs:
    512 //    None
    513 //
    514 //  Returns:
    515 //    returnValue = true if the init succeeds, else false.
    516 //
    517 //  Global Variables Used:
    518 //    None
    519 //
    520 //----------------------------------------------------------------------------
    521 // FUNCTION DESCRIPTION
    522 //
    523 //  This function opens the AMR file, checks for AMR format type, calculates
    524 //  the track duration, and sets the AMR bitrate value.
    525 //
    526 //----------------------------------------------------------------------------
    527 // REQUIREMENTS
    528 //
    529 //----------------------------------------------------------------------------
    530 // REFERENCES
    531 //
    532 //------------------------------------------------------------------------------
    533 // CAUTION
    534 //
    535 //------------------------------------------------------------------------------
    536 OSCL_EXPORT_REF bool CAMRFileParser::InitAMRFile(OSCL_wString& aClip, bool aInitParsingEnable, Oscl_FileServer* aFileSession, PVMFCPMPluginAccessInterfaceFactory*aCPM, OsclFileHandle*aHandle, uint32 countToClaculateRDATimeInterval)
    537 {
    538     iAMRFile.SetCPM(aCPM);
    539     iAMRFile.SetFileHandle(aHandle);
    540 
    541     // Open the file (aClip)
    542     if (iAMRFile.Open(aClip.get_cstr(), (Oscl_File::MODE_READ | Oscl_File::MODE_BINARY), *aFileSession) != 0)
    543     {
    544         PVMF_AMRPARSER_LOGERROR((0, "CAMRFileParser::InitAMRFile- File Open failed"));
    545         return false;
    546     }
    547 
    548     // create ipBSO
    549     ipBSO = OSCL_NEW(bitstreamObject, (iLogger, &iAMRFile));
    550     if (!ipBSO)
    551     {
    552         return false;
    553     }
    554     if (!ipBSO->get())
    555     {
    556         return false; // make sure the memory allocation is going well
    557     }
    558 
    559     // get file info
    560     int32 frameTypeIndex = 0;
    561     if (ipBSO->getFileInfo(iAMRFileSize, iAMRFormat, frameTypeIndex))
    562     {
    563         PVMF_AMRPARSER_LOGERROR((0, "CAMRFileParser::InitAMRFile- getFileInfo failed "));
    564         return false;
    565     }
    566 
    567     // Reject unsupported AMR file types
    568     if (frameTypeIndex >= 16 ||
    569             iAMRFormat == EAMRETS ||
    570             iAMRFormat == EAMRIETF_MultiNB ||
    571             iAMRFormat == EAMRIETF_MultiWB ||
    572             iAMRFormat == EAMRWMF ||
    573             iAMRFormat == EAMRUnrecognized)
    574     {
    575         PVMF_AMRPARSER_LOGERROR((0, "CAMRFileParser::Unsupported AMR type "));
    576         return false;
    577     }
    578 
    579     // Set bitrate
    580     if (EAMRIETF_SingleWB != iAMRFormat)
    581     {
    582         AMRFF_Frame_Type_3GPP frameType3GPP = (AMRFF_Frame_Type_3GPP)frameTypeIndex;
    583         SetBitRate(frameType3GPP);
    584     }
    585     else // for wide band
    586     {
    587         AMRFF_WB_Frame_Type_3GPP frameType3GPP = (AMRFF_WB_Frame_Type_3GPP)frameTypeIndex;
    588         SetBitRate(frameType3GPP);
    589     }
    590 
    591     // Determine file duration and set up random positioning table if needed
    592     CalculateDuration(aInitParsingEnable, countToClaculateRDATimeInterval);
    593     return true;
    594 }
    595 
    596 bool CAMRFileParser::CalculateDuration(bool aInitParsingEnable, uint32 countToClaculateRDATimeInterval)
    597 {
    598     iCountToClaculateRDATimeInterval = countToClaculateRDATimeInterval;
    599     uint32 FrameCount = iCountToClaculateRDATimeInterval;
    600     iRandomAccessTimeInterval = countToClaculateRDATimeInterval * TIME_STAMP_PER_FRAME;
    601 
    602     if (aInitParsingEnable)
    603     {
    604         // Go through each frame to calculate AMR file duration.
    605         int32 status = bitstreamObject::EVERYTHING_OK;
    606         uint8 frame_type = 15;
    607         iAMRDuration = 0;
    608 
    609         int32 error = 0;
    610 
    611         int32 filePos = 0;
    612 
    613         OSCL_TRY(error, iRPTable.push_back(filePos));
    614         OSCL_FIRST_CATCH_ANY(error, return false);
    615 
    616         while (status == bitstreamObject::EVERYTHING_OK)
    617         {
    618             // get the next frame
    619 
    620             status = ipBSO->getNextFrame(iAMRFrameBuffer, frame_type); // NO IETF frame header
    621 
    622             if (status == bitstreamObject::EVERYTHING_OK)
    623             {
    624                 // calculate the number of frames // BX
    625                 iAMRDuration += TIME_STAMP_PER_FRAME;
    626 
    627                 // set up the table for randow positioning
    628                 int32 frame_length = 0;
    629 
    630                 if (iAMRFormat == EAMRIF2)
    631                 {
    632                     frame_length = If2DecInputBytes[(uint16)frame_type];
    633                 }
    634                 else if (iAMRFormat == EAMRIETF_SingleNB)
    635                 {
    636                     frame_length = IetfDecInputBytes[(uint16)frame_type];
    637                 }
    638                 else if (EAMRIETF_SingleWB == iAMRFormat)
    639                 {
    640                     frame_length = IetfWBDecInputBytes[(uint16)frame_type];
    641                 }
    642                 else
    643                 {
    644                     PVMF_AMRPARSER_LOGERROR((0, "CAMRFileParser::CalculateDuration- Format unknown"));
    645                     return false;
    646                 }
    647 
    648                 filePos += frame_length;
    649 
    650                 error = 0;
    651                 if (!FrameCount)
    652                 {
    653                     OSCL_TRY(error, iRPTable.push_back(filePos));
    654                     OSCL_FIRST_CATCH_ANY(error, return false);
    655                     FrameCount = countToClaculateRDATimeInterval;
    656                 }
    657             }
    658 
    659             else if (status == bitstreamObject::END_OF_FILE)
    660             {
    661                 break;
    662             }
    663 
    664             else
    665             {
    666                 // error happens!
    667                 PVMF_AMRPARSER_LOGERROR((0, "CAMRFileParser::getNextFrame Fails Error Code %d", status));
    668                 if (ipBSO->reset())
    669                 {
    670                     return false;
    671                 }
    672 
    673                 return false;
    674             }
    675             FrameCount--;
    676         }
    677 
    678         ResetPlayback(0);
    679     }
    680     return true;
    681 }
    682 
    683 //----------------------------------------------------------------------------
    684 // FUNCTION NAME: CAMRFileParser::RetrieveAMRFileInfo
    685 //----------------------------------------------------------------------------
    686 // INPUT AND OUTPUT DEFINITIONS
    687 //
    688 //  Inputs:
    689 //    aMedia     = pointer to CPVMedia class
    690 //    aTrackId   = pointer to the ID specific to the current AMR track
    691 //    aTimescale = pointer to the sampling frequency value, for AMR it is 8000 Hz.
    692 //
    693 //  Outputs:
    694 //    None
    695 //
    696 //  Returns:
    697 //    false if an error happens, else true
    698 //
    699 //  Global Variables Used:
    700 //    None
    701 //
    702 //----------------------------------------------------------------------------
    703 // FUNCTION DESCRIPTION
    704 //
    705 //  This function opens the AMR file, checks for AMR format type, calculates
    706 //  the track duration, and sets the AMR bitrate value.
    707 //
    708 //----------------------------------------------------------------------------
    709 // REQUIREMENTS
    710 //
    711 //----------------------------------------------------------------------------
    712 // REFERENCES
    713 //
    714 //------------------------------------------------------------------------------
    715 // CAUTION
    716 //
    717 //------------------------------------------------------------------------------
    718 OSCL_EXPORT_REF bool CAMRFileParser::RetrieveFileInfo(TPVAmrFileInfo& aInfo)
    719 {
    720     if (iAMRFormat == EAMRUnrecognized)
    721     {
    722         // File is not open and parsed
    723         return false;
    724     }
    725 
    726     aInfo.iBitrate = iAMRBitRate;
    727     aInfo.iTimescale = 1000;
    728     aInfo.iDuration = iAMRDuration;
    729     aInfo.iFileSize = iAMRFileSize;
    730     aInfo.iAmrFormat = iAMRFormat;
    731     PVMF_AMRPARSER_LOGDIAGNOSTICS((0, "CAMRFileParser::RetrieveFileInfo- duration = %d, bitrate = %d, filesize = %d", iAMRDuration, iAMRBitRate, iAMRFileSize));
    732 
    733     return true;
    734 }
    735 
    736 
    737 //----------------------------------------------------------------------------
    738 // FUNCTION NAME: CAMRFileParser::SetBitRate
    739 //----------------------------------------------------------------------------
    740 // INPUT AND OUTPUT DEFINITIONS
    741 //
    742 //  Inputs:
    743 //    aFrameType3GPP = 3GPP frame type for the AMR frame of type AMRFF_Frame_Type_3GPP
    744 //
    745 //  Outputs:
    746 //    None
    747 //
    748 //  Returns:
    749 //    None
    750 //
    751 //  Global Variables Used:
    752 //    None
    753 //
    754 //----------------------------------------------------------------------------
    755 // FUNCTION DESCRIPTION
    756 //
    757 //  This function takes in the 3GPP frametype and sets the AMR bitrate value
    758 //  depending on the AMR frametype.
    759 //
    760 //----------------------------------------------------------------------------
    761 // REQUIREMENTS
    762 //
    763 //----------------------------------------------------------------------------
    764 // REFERENCES
    765 //
    766 //------------------------------------------------------------------------------
    767 // CAUTION
    768 //
    769 //------------------------------------------------------------------------------
    770 void CAMRFileParser::SetBitRate(AMRFF_Frame_Type_3GPP aFrameType3GPP)
    771 {
    772     switch (aFrameType3GPP)
    773     {
    774         case AMRFF_AMR_475:
    775         {
    776             iAMRBitRate =  4750;
    777             break;
    778         }
    779         case AMRFF_AMR_515:
    780         {
    781             iAMRBitRate =  5150;
    782             break;
    783         }
    784         case AMRFF_AMR_59:
    785         {
    786             iAMRBitRate =  5900;
    787             break;
    788         }
    789         case AMRFF_AMR_67:
    790         {
    791             iAMRBitRate =  6700;
    792             break;
    793         }
    794         case AMRFF_AMR_74:
    795         {
    796             iAMRBitRate =  7400;
    797             break;
    798         }
    799         case AMRFF_AMR_795:
    800         {
    801             iAMRBitRate =  7950;
    802             break;
    803         }
    804         case AMRFF_AMR_102:
    805         {
    806             iAMRBitRate = 10200;
    807             break;
    808         }
    809         case AMRFF_AMR_122:
    810         {
    811             iAMRBitRate = 12200;
    812             break;
    813         }
    814         default:
    815         {
    816             iAMRBitRate = 0;
    817             break;
    818         }
    819     }
    820     return;
    821 }
    822 
    823 
    824 void CAMRFileParser::SetBitRate(AMRFF_WB_Frame_Type_3GPP aFrameType3GPP)
    825 {
    826     switch (aFrameType3GPP)
    827     {
    828         case AMRFF_WB_660:
    829         {
    830             iAMRBitRate =  6600;
    831             break;
    832         }
    833         case AMRFF_WB_885:
    834         {
    835             iAMRBitRate =  8850;
    836             break;
    837         }
    838         case AMRFF_WB_1265:
    839         {
    840             iAMRBitRate =  12650;
    841             break;
    842         }
    843         case AMRFF_WB_1425:
    844         {
    845             iAMRBitRate =  14250;
    846             break;
    847         }
    848         case AMRFF_WB_1585:
    849         {
    850             iAMRBitRate =  15850;
    851             break;
    852         }
    853         case AMRFF_WB_1825:
    854         {
    855             iAMRBitRate =  18250;
    856             break;
    857         }
    858         case AMRFF_WB_1985:
    859         {
    860             iAMRBitRate = 19850;
    861             break;
    862         }
    863         case AMRFF_WB_2305:
    864         {
    865             iAMRBitRate = 23050;
    866             break;
    867         }
    868         case AMRFF_WB_2385:
    869         {
    870             iAMRBitRate = 23850;
    871             break;
    872         }
    873         default:
    874         {
    875             iAMRBitRate = 0;
    876             break;
    877         }
    878     }
    879     return;
    880 }
    881 
    882 
    883 
    884 //----------------------------------------------------------------------------
    885 // FUNCTION NAME: CAMRFileParser::ResetPlayback
    886 //----------------------------------------------------------------------------
    887 // INPUT AND OUTPUT DEFINITIONS
    888 //
    889 //  Inputs:
    890 //    aStartTime = integer value as where to move the playback positioning to.
    891 //
    892 //  Outputs:
    893 //    None
    894 //
    895 //  Returns:
    896 //    0 if success, -1 if failure
    897 //
    898 //  Global Variables Used:
    899 //    None
    900 //
    901 //----------------------------------------------------------------------------
    902 // FUNCTION DESCRIPTION
    903 //
    904 //  This function sets the file pointer to the location that aStartTime would
    905 //  point to in the file.
    906 //
    907 //----------------------------------------------------------------------------
    908 // REQUIREMENTS
    909 //
    910 //----------------------------------------------------------------------------
    911 // REFERENCES
    912 //
    913 //------------------------------------------------------------------------------
    914 // CAUTION
    915 //
    916 //------------------------------------------------------------------------------
    917 OSCL_EXPORT_REF int32 CAMRFileParser::ResetPlayback(int32 aStartTime)
    918 {
    919     // get file size info, //iAMRFile.Size(fileSize)
    920     int32 result;
    921     if (iAMRFileSize <= 0)
    922     {
    923         int32 frameTypeIndex;
    924         if (ipBSO->getFileInfo(iAMRFileSize, iAMRFormat, frameTypeIndex))
    925         {
    926             PVMF_AMRPARSER_LOGERROR((0, "CAMRFileParser::Reset Playback Failed"));
    927             return bitstreamObject::MISC_ERROR;
    928         }
    929     }
    930 
    931     iEndOfFileReached = false;
    932     // initialize "iTotalNumFramesRead"
    933     // note: +1 means we choose the next frame(ts>=aStartTime)
    934     iTotalNumFramesRead = aStartTime / TIME_STAMP_PER_FRAME + (aStartTime > 0) * 1;
    935 
    936     uint32 tblIdx = aStartTime / (iRandomAccessTimeInterval);// +(aStartTime>0)*1;
    937     iTotalNumFramesRead = tblIdx * iCountToClaculateRDATimeInterval;
    938 
    939     PVMF_AMRPARSER_LOGDIAGNOSTICS((0, "CAMRFileParser::resetplayback - TotalNumFramesRead=%d", iTotalNumFramesRead));
    940     // set new file position
    941     int32 newPosition = 0;
    942     if (iTotalNumFramesRead > 0)
    943     {
    944         // At the first time, don't do reset
    945         if (iAMRDuration != 0 && iRPTable.size() == 0)
    946         {
    947             newPosition = (iAMRFileSize * aStartTime) / iAMRDuration;
    948             PVMF_AMRPARSER_LOGDIAGNOSTICS((0, "CAMRFileParser::resetplayback - newPosition=%d", newPosition));
    949             if (newPosition < 0)
    950             {
    951                 // if we have no duration information, reset the file position at 0.
    952                 newPosition = 0;
    953             }
    954         }
    955         else if (iRPTable.size() > 0)
    956         {
    957             // use the randow positioning table to determine the file position
    958             if (tblIdx  >= iRPTable.size())
    959             {
    960                 // Requesting past the end of table so set to (end of table-1)
    961                 // to be at the last sample
    962                 tblIdx = ((int32)iRPTable.size()) - 2;
    963             }
    964             newPosition = iRPTable[tblIdx];
    965         }
    966     }
    967     result = ipBSO->reset(newPosition);
    968     if (newPosition >= 0 && result)
    969     {
    970         PVMF_AMRPARSER_LOGERROR((0, "AMRBitstreamObject::refill- Misc Error"));
    971         return result;
    972     }
    973     iEndOfFileReached = false;
    974 
    975     return bitstreamObject::EVERYTHING_OK;
    976 }
    977 
    978 
    979 //----------------------------------------------------------------------------
    980 // FUNCTION NAME: CAMRFileParser::SeekPointFromTimestamp
    981 //----------------------------------------------------------------------------
    982 // INPUT AND OUTPUT DEFINITIONS
    983 //
    984 //  Inputs:
    985 //    aStartTime = integer value as for the specified start time
    986 //
    987 //  Outputs:
    988 //    None
    989 //
    990 //  Returns:
    991 //    Timestamp in milliseconds of the actual position
    992 //
    993 //  Global Variables Used:
    994 //    None
    995 //
    996 //----------------------------------------------------------------------------
    997 // FUNCTION DESCRIPTION
    998 //
    999 //  This function returns the timestamp for an actual position corresponding
   1000 //  to the specified start time
   1001 //
   1002 //----------------------------------------------------------------------------
   1003 // REQUIREMENTS
   1004 //
   1005 //----------------------------------------------------------------------------
   1006 // REFERENCES
   1007 //
   1008 //------------------------------------------------------------------------------
   1009 // CAUTION
   1010 //
   1011 //------------------------------------------------------------------------------
   1012 OSCL_EXPORT_REF uint32 CAMRFileParser::SeekPointFromTimestamp(uint32 aStartTime)
   1013 {
   1014     // get file size info, //iAMRFile.Size(fileSize)
   1015     if (iAMRFileSize <= 0)
   1016     {
   1017         int32 frameTypeIndex;
   1018         if (ipBSO->getFileInfo(iAMRFileSize, iAMRFormat, frameTypeIndex))
   1019         {
   1020             return 0;
   1021         }
   1022     }
   1023 
   1024     // Determine the frame number corresponding to timestamp
   1025     // note: +1 means we choose the next frame(ts>=aStartTime)
   1026     uint32 startframenum = aStartTime / TIME_STAMP_PER_FRAME + (aStartTime > 0) * 1;
   1027 
   1028     // Correct the frame number if necessary
   1029     if (startframenum > 0)
   1030     {
   1031         if (iAMRDuration != 0 && iRPTable.size() <= 0)
   1032         {
   1033             // Duration not known and reposition table not available so go to first frame
   1034             startframenum = 0;
   1035         }
   1036         else if (iRPTable.size() > 0)
   1037         {
   1038             if (startframenum >= iRPTable.size())
   1039             {
   1040                 // Requesting past the end of table so set to (end of table-1)
   1041                 // to be at the last sample
   1042                 startframenum = ((int32)iRPTable.size()) - 2;
   1043             }
   1044         }
   1045     }
   1046 
   1047     return (startframenum*TIME_STAMP_PER_FRAME);
   1048 }
   1049 
   1050 //----------------------------------------------------------------------------
   1051 // FUNCTION NAME: CAMRFileParser::GetNextBundledAccessUnits
   1052 //----------------------------------------------------------------------------
   1053 // INPUT AND OUTPUT DEFINITIONS
   1054 //
   1055 //  Inputs:
   1056 //    aNumSamples = requested number of frames to be read from file
   1057 //    aGau        = frame information structure of type GAU
   1058 //
   1059 //  Outputs:
   1060 //    None
   1061 //
   1062 //  Returns:
   1063 //    0 if success, -1 if failure
   1064 //
   1065 //  Global Variables Used:
   1066 //    None
   1067 //
   1068 //----------------------------------------------------------------------------
   1069 // FUNCTION DESCRIPTION
   1070 //
   1071 //  This function attempts to read in the number of AMR frames specified by
   1072 //  aNumSamples. It formats the read data to WMF bit order and stores it in
   1073 //  the GAU structure.
   1074 //
   1075 //----------------------------------------------------------------------------
   1076 // REQUIREMENTS
   1077 //
   1078 //----------------------------------------------------------------------------
   1079 // REFERENCES
   1080 //
   1081 //------------------------------------------------------------------------------
   1082 // CAUTION
   1083 //
   1084 //------------------------------------------------------------------------------
   1085 OSCL_EXPORT_REF int32 CAMRFileParser::GetNextBundledAccessUnits(uint32 *aNumSamples, GAU *aGau)
   1086 {
   1087     // AMR format has already been identified in InitAMRFile function.
   1088     // Check if AMR format is valid as the safeguard
   1089     if (iAMRFormat == EAMRUnrecognized)
   1090     {
   1091         PVMF_AMRPARSER_LOGERROR((0, "CAMRFileParser::GetNextBundledAccessUnits Failed - Unrecognized format"));
   1092         return bitstreamObject::MISC_ERROR;
   1093     }
   1094 
   1095     // Check the requested number of frames is not greater than the max supported
   1096     if (*aNumSamples > MAX_NUM_FRAMES_PER_BUFF)
   1097     {
   1098         PVMF_AMRPARSER_LOGERROR((0, "CAMRFileParser::GetNextBundledAccessUnits Failed - requested number of frames is greater than the max supported"));
   1099         return bitstreamObject::MISC_ERROR;
   1100     }
   1101 
   1102     int32 returnValue = bitstreamObject::EVERYTHING_OK;
   1103 
   1104     if (iEndOfFileReached)
   1105     {
   1106         *aNumSamples = 0;
   1107         return bitstreamObject::END_OF_FILE;
   1108     }
   1109 
   1110     uint8* pTempGau = (uint8 *) aGau->buf.fragments[0].ptr;
   1111     uint32 gauBufferSize = aGau->buf.fragments[0].len;
   1112     uint32 i, bytesReadInGau = 0, numSamplesRead = 0;
   1113 
   1114     for (i = 0; i < *aNumSamples && !iEndOfFileReached; i++)
   1115     {
   1116         // get the next frame
   1117         bool bHeaderIncluded = true;
   1118         returnValue = ipBSO->getNextFrame(iAMRFrameBuffer, iAMRFrameHeaderBuffer[i], bHeaderIncluded);
   1119         if (returnValue == bitstreamObject::END_OF_FILE)
   1120         {
   1121             iEndOfFileReached = true;
   1122             break;
   1123         }
   1124         else if (returnValue == bitstreamObject::EVERYTHING_OK)
   1125 
   1126         {
   1127         }
   1128         else if (returnValue == bitstreamObject::DATA_INSUFFICIENT)
   1129         {
   1130             *aNumSamples = 0;
   1131             return returnValue;
   1132         }
   1133         else
   1134         {   // error happens!!
   1135             *aNumSamples = 0;
   1136             return bitstreamObject::READ_ERROR;
   1137         }
   1138 
   1139         // Now a frame exists in iAMRFrameBuffer, move it to aGau
   1140         int32 frame_size = 0;
   1141         if (iAMRFormat == EAMRIF2)
   1142         {
   1143             frame_size = If2DecInputBytes[(uint16)iAMRFrameHeaderBuffer[i]];
   1144         }
   1145         else if (iAMRFormat == EAMRIETF_SingleNB)
   1146         {
   1147             frame_size = IetfDecInputBytes[(uint16)iAMRFrameHeaderBuffer[i]];
   1148         }
   1149         else if (iAMRFormat == EAMRIETF_SingleWB)
   1150         {
   1151             frame_size = IetfWBDecInputBytes[(uint16)iAMRFrameHeaderBuffer[i]];
   1152         }
   1153         else
   1154         {
   1155             PVMF_AMRPARSER_LOGERROR((0, "AMRBitstreamObject::refill- Misc Error"));
   1156             return bitstreamObject::MISC_ERROR;
   1157         }
   1158 
   1159         // Check whether the gau buffer will be overflow
   1160         if (bytesReadInGau + frame_size >= gauBufferSize)
   1161         {
   1162             // Undo the read
   1163             ipBSO->undoGetNextFrame(frame_size);
   1164             break;
   1165         }
   1166 
   1167         if (frame_size > 0)
   1168         {
   1169             oscl_memcpy(pTempGau, iAMRFrameBuffer, frame_size);
   1170 
   1171             pTempGau += frame_size;
   1172             bytesReadInGau += frame_size;
   1173         }
   1174         aGau->info[i].len = frame_size;
   1175         aGau->info[i].ts  = (iTotalNumFramesRead + (numSamplesRead++)) * TIME_STAMP_PER_FRAME;
   1176 
   1177     } // end of: for(i = 0; i < *aNumSamples && !iEndOfFileReached; i++)
   1178 
   1179     aGau->info[0].ts = iTotalNumFramesRead * TIME_STAMP_PER_FRAME;
   1180 
   1181     *aNumSamples = numSamplesRead;
   1182     iTotalNumFramesRead += numSamplesRead;
   1183 
   1184     //We may have reached EOF but also found some samples.
   1185     //don't return EOF until there are no samples left.
   1186     if (returnValue == bitstreamObject::END_OF_FILE
   1187             && numSamplesRead > 0)
   1188         return bitstreamObject::EVERYTHING_OK;
   1189 
   1190     return returnValue;
   1191 }
   1192 
   1193 OSCL_EXPORT_REF int32 CAMRFileParser::PeekNextTimestamp(uint32 *aTimestamp)
   1194 {
   1195 
   1196     *aTimestamp = iTotalNumFramesRead * TIME_STAMP_PER_FRAME;
   1197 
   1198     return bitstreamObject::EVERYTHING_OK;
   1199 }
   1200 
   1201 
   1202 OSCL_EXPORT_REF uint8 CAMRFileParser::GetFrameTypeInCurrentBundledAccessUnits(uint32 frameIndex)
   1203 {
   1204     if (frameIndex >= MAX_NUM_FRAMES_PER_BUFF)
   1205     {
   1206         return 0;
   1207     }
   1208     return iAMRFrameHeaderBuffer[frameIndex];
   1209 }
   1210 
   1211 OSCL_EXPORT_REF int32 CAMRFileParser::getTrackMaxBufferSizeDB()
   1212 {
   1213     if (ipBSO)
   1214     {
   1215         return ipBSO->getTrackMaxBufferSizeDB();
   1216     }
   1217     else
   1218     {
   1219         return -1;
   1220     }
   1221 }
   1222 
   1223 
   1224 OSCL_EXPORT_REF uint8* CAMRFileParser::getCodecSpecificInfo()
   1225 {
   1226 
   1227     bool bHeaderIncluded = true;
   1228     ipBSO->getNextFrame(iAMRFrameBuffer, iAMRFrameHeaderBuffer[1], bHeaderIncluded);
   1229     return  iAMRFrameHeaderBuffer;
   1230 }
   1231 
   1232 
   1233