Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      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 express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /**
     18  ******************************************************************************
     19  * @file        M4AMRR_CoreReader.c
     20  * @brief       Implementation of AMR parser
     21  * @note        This file contains the API Implementation for
     22  *              AMR Parser.
     23  ******************************************************************************
     24 */
     25 #include "M4AMRR_CoreReader.h"
     26 #include "M4OSA_Debug.h"
     27 #include "M4OSA_CoreID.h"
     28 
     29 /**
     30  ******************************************************************************
     31  * Maximum bitrate per amr type
     32  ******************************************************************************
     33 */
     34 #define M4AMRR_NB_MAX_BIT_RATE    12200
     35 #define M4AMRR_WB_MAX_BIT_RATE    23850
     36 
     37 /**
     38  ******************************************************************************
     39  * AMR reader context ID
     40  ******************************************************************************
     41 */
     42 #define M4AMRR_CONTEXTID    0x414d5252
     43 
     44 /**
     45  ******************************************************************************
     46  * An AMR frame is 20ms
     47  ******************************************************************************
     48 */
     49 #define M4AMRR_FRAME_LENGTH     20
     50 
     51 /**
     52  ******************************************************************************
     53  * For the seek, the file is splitted in 40 segments for faster search
     54  ******************************************************************************
     55 */
     56 #define    M4AMRR_NUM_SEEK_ENTRIES 40
     57 
     58 #define M4AMRR_NB_SAMPLE_FREQUENCY 8000        /**< Narrow band sampling rate */
     59 #define M4AMRR_WB_SAMPLE_FREQUENCY 16000    /**< Wide band sampling rate */
     60 
     61 /**
     62  ******************************************************************************
     63  * AMR reader version numbers
     64  ******************************************************************************
     65 */
     66 /* CHANGE_VERSION_HERE */
     67 #define M4AMRR_VERSION_MAJOR 1
     68 #define M4AMRR_VERSION_MINOR 11
     69 #define M4AMRR_VERSION_REVISION 3
     70 
     71 /**
     72  ******************************************************************************
     73  * structure    M4_AMRR_Context
     74  * @brief        Internal AMR reader context structure
     75  ******************************************************************************
     76 */
     77 typedef struct
     78 {
     79     M4OSA_UInt32             m_contextId ;      /* Fixed Id. to check for valid Context*/
     80     M4OSA_FileReadPointer*   m_pOsaFilePtrFct;  /* File function pointer */
     81     M4SYS_StreamDescription* m_pStreamHandler;  /* Stream Description */
     82     M4OSA_UInt32*            m_pSeekIndex;      /* Seek Index Table */
     83     M4OSA_UInt32             m_seekInterval;    /* Stores the seek Interval stored in the Index */
     84     M4OSA_UInt32             m_maxAuSize;       /* Stores the max Au Size */
     85     M4OSA_MemAddr32          m_pdataAddress;    /* Pointer to store AU data */
     86     M4SYS_StreamType         m_streamType;      /* Stores the stream type AMR NB or WB */
     87     M4OSA_Context            m_pAMRFile;        /* Data storage */
     88     M4AMRR_State             m_status;          /* AMR Reader Status */
     89     M4OSA_Int32              m_structSize;      /* size of structure*/
     90 } M4_AMRR_Context;
     91 
     92 /**
     93  ******************************************************************************
     94  * Parser internal functions, not usable from outside the reader context
     95  ******************************************************************************
     96 */
     97 M4OSA_UInt32    M4AMRR_getAuSize(M4OSA_UInt32 frameType,  M4SYS_StreamType streamType);
     98 M4OSA_UInt32    M4AMRR_getBitrate(M4OSA_UInt32 frameType,  M4SYS_StreamType streamType);
     99 
    100 /**
    101  ******************************************************************************
    102  * M4OSA_UInt32    M4AMRR_getAuSize(M4OSA_UInt32 frameType,  M4SYS_StreamType streamType)
    103  * @brief    Internal function to the AMR Parser, returns the AU size of the Frame
    104  * @note     This function takes the stream type and the frametype and returns the
    105  *           frame lenght
    106  * @param    frameType(IN)    : AMR frame type
    107  * @param    streamType(IN)    : AMR stream type NB or WB
    108  * @returns  The frame size based on the frame type.
    109  ******************************************************************************
    110  */
    111 M4OSA_UInt32    M4AMRR_getAuSize(M4OSA_UInt32 frameType,  M4SYS_StreamType streamType)
    112 {
    113     const M4OSA_UInt32    M4AMRR_NB_AUSIZE[]={13,14,16,18,20,21,27,32,6,6,6};
    114     const M4OSA_UInt32    M4AMRR_WB_AUSIZE[]={18,24,33,37,41,47,51,59,61,6};
    115 
    116     if ( streamType == M4SYS_kAMR )
    117     {
    118             return M4AMRR_NB_AUSIZE[frameType];
    119     }
    120     else /* M4SYS_kAMR_WB */
    121     {
    122             return M4AMRR_WB_AUSIZE[frameType];
    123     }
    124 }
    125 
    126 /**
    127  ******************************************************************************
    128  * M4OSA_UInt32    M4AMRR_getBitrate(M4OSA_UInt32 frameType,  M4SYS_StreamType streamType)
    129  * @brief    Internal function to the AMR Parser, returns the Bit rate of the Frame
    130  * @note     This function takes the stream type and the frametype and returns the
    131  *           bit rate for the given frame.
    132  * @param    frameType(IN)    : AMR frame type
    133  * @param    streamType(IN)    : AMR stream type NB or WB
    134  * @returns  The frame's bit rate based on the frame type.
    135  ******************************************************************************
    136  */
    137 M4OSA_UInt32    M4AMRR_getBitrate(M4OSA_UInt32 frameType,  M4SYS_StreamType streamType)
    138 {
    139     const M4OSA_UInt32    M4AMRR_NB_BITRATE[]=
    140         {4750,5150,5900,6700,7400,7950,10200,12200,12200,12200,12200};
    141     const M4OSA_UInt32    M4AMRR_WB_BITRATE[]=
    142         {6600,8850,12650,14250,15850,18250,19850,23050,23850,12200};
    143 
    144     if ( streamType == M4SYS_kAMR )
    145     {
    146             return M4AMRR_NB_BITRATE[frameType];
    147     }
    148     else /* M4SYS_kAMR_WB */
    149     {
    150             return M4AMRR_WB_BITRATE[frameType];
    151     }
    152 }
    153 
    154 /*********************************************************/
    155 M4OSA_ERR M4AMRR_openRead(M4OSA_Context* pContext, M4OSA_Void* pFileDescriptor,
    156                         M4OSA_FileReadPointer* pFileFunction)
    157 /*********************************************************/
    158 {
    159     M4_AMRR_Context*    pStreamContext;
    160     M4OSA_FilePosition  filePos;
    161 
    162     M4OSA_ERR err = M4ERR_FILE_NOT_FOUND ;
    163     M4OSA_UInt32 size ;
    164     M4OSA_UInt32 data ;
    165     M4OSA_Char *M4_Token;
    166     M4OSA_UInt32 *tokenPtr;
    167 
    168     /* Header for AMR NB */
    169     M4OSA_UInt32 M4_AMR_1       = 0x4d412123;
    170     M4OSA_UInt32 M4_AMR_NB_2    = 0x00000a52;
    171 
    172     /* Header for AMR WB */
    173     M4OSA_UInt32 M4_AMR_WB_2    = 0x42572d52;
    174     M4OSA_UInt32 M4_AMR_WB_3    = 0x0000000a;
    175     *pContext = M4OSA_NULL ;
    176 
    177     M4OSA_DEBUG_IF2((M4OSA_NULL == pContext),M4ERR_PARAMETER,"Context M4OSA_NULL");
    178     M4OSA_DEBUG_IF2((M4OSA_NULL == pFileDescriptor),M4ERR_PARAMETER,"File Desc. M4OSA_NULL");
    179 
    180     M4_Token = (M4OSA_Char*)M4OSA_32bitAlignedMalloc(sizeof(M4OSA_MemAddr32)*3, M4AMR_READER,
    181                  (M4OSA_Char *)("M4_Token"));
    182     if(M4OSA_NULL == M4_Token)
    183     {
    184         M4OSA_DEBUG_IF3((M4OSA_NULL == M4_Token),M4ERR_ALLOC,"Mem Alloc failed - M4_Token");
    185         return M4ERR_ALLOC ;
    186     }
    187 
    188     pStreamContext= (M4_AMRR_Context*)M4OSA_32bitAlignedMalloc(sizeof(M4_AMRR_Context), M4AMR_READER,
    189                      (M4OSA_Char *)("pStreamContext"));
    190     if(M4OSA_NULL == pStreamContext)
    191     {
    192         free(M4_Token);
    193         *pContext = M4OSA_NULL ;
    194         return M4ERR_ALLOC ;
    195     }
    196 
    197     /* Initialize the context */
    198     pStreamContext->m_contextId = M4AMRR_CONTEXTID;
    199     pStreamContext->m_structSize=sizeof(M4_AMRR_Context);
    200     pStreamContext->m_pOsaFilePtrFct=pFileFunction ;
    201     pStreamContext->m_pStreamHandler = M4OSA_NULL ;
    202     pStreamContext->m_pAMRFile = M4OSA_NULL ;
    203     pStreamContext->m_status = M4AMRR_kOpening ;
    204     pStreamContext->m_pSeekIndex = M4OSA_NULL ;
    205     pStreamContext->m_seekInterval = 0;
    206     pStreamContext->m_maxAuSize = 0 ;
    207     pStreamContext->m_pdataAddress = M4OSA_NULL;
    208     err=pStreamContext->m_pOsaFilePtrFct->openRead(&pStreamContext->m_pAMRFile,
    209         (M4OSA_Char*)pFileDescriptor,M4OSA_kFileRead );
    210     if ( err != M4NO_ERROR )
    211     {
    212         /* M4OSA_DEBUG_IF3((err != M4NO_ERROR),err,"File open failed"); */
    213         free(pStreamContext);
    214         free(M4_Token);
    215         *pContext = M4OSA_NULL ;
    216         return err ;
    217     }
    218 
    219     pStreamContext->m_status = M4AMRR_kOpening ;
    220 
    221     size = 6;
    222     pStreamContext->m_pOsaFilePtrFct->readData(pStreamContext->m_pAMRFile,
    223                 (M4OSA_MemAddr8)M4_Token, &size);
    224     if(size != 6)
    225     {
    226         goto cleanup;
    227     }
    228 
    229     tokenPtr = (M4OSA_UInt32*)M4_Token ;
    230     /* Check for the first 4 bytes of the header common to WB and NB*/
    231     if (*tokenPtr != M4_AMR_1)
    232     {
    233         goto cleanup;
    234     }
    235 
    236     tokenPtr++;
    237     data = *tokenPtr & 0x0000FFFF ;
    238     /* Check if the next part is Narrow band header */
    239     if (data!= M4_AMR_NB_2)
    240     {
    241         /* Stream is AMR Wide Band */
    242         filePos = 4;
    243         pStreamContext->m_pOsaFilePtrFct->seek(pStreamContext->m_pAMRFile,
    244              M4OSA_kFileSeekBeginning, &filePos);
    245         size = 5;
    246         pStreamContext->m_pOsaFilePtrFct->readData(pStreamContext->m_pAMRFile,
    247              (M4OSA_MemAddr8)M4_Token, &size);
    248         if(size != 5)
    249             goto cleanup;
    250         tokenPtr=(M4OSA_UInt32*)M4_Token;
    251         /* Check for the Wide band hader */
    252         if(*tokenPtr!= M4_AMR_WB_2)
    253             goto cleanup;
    254         tokenPtr++;
    255         data = *tokenPtr & 0x000000FF ;
    256         if(data!= M4_AMR_WB_3)
    257             goto cleanup;
    258         pStreamContext->m_streamType = M4SYS_kAMR_WB ;
    259     }
    260     else
    261     {
    262         /* Stream is a Narrow band stream */
    263         pStreamContext->m_streamType = M4SYS_kAMR ;
    264     }
    265     /*  No Profile level defined */
    266     pStreamContext->m_status = M4AMRR_kOpened;
    267 
    268     free(M4_Token);
    269     *pContext = pStreamContext ;
    270     return M4NO_ERROR;
    271 
    272 cleanup:
    273 
    274     if(M4OSA_NULL != pStreamContext->m_pAMRFile)
    275     {
    276         pStreamContext->m_pOsaFilePtrFct->closeRead(pStreamContext->m_pAMRFile);
    277     }
    278 
    279     free(M4_Token);
    280     free(pStreamContext);
    281 
    282     *pContext = M4OSA_NULL ;
    283 
    284     return (M4OSA_ERR)M4ERR_AMR_NOT_COMPLIANT;
    285 }
    286 
    287 
    288 /*********************************************************/
    289 M4OSA_ERR M4AMRR_getNextStream(M4OSA_Context Context, M4SYS_StreamDescription* pStreamDesc )
    290 /*********************************************************/
    291 {
    292     M4_AMRR_Context*    pStreamContext=(M4_AMRR_Context*)Context;
    293     M4OSA_Char            frameHeader, frameType ;
    294     M4OSA_UInt32        size, auCount=0;
    295     M4OSA_FilePosition  filePos;
    296 
    297     M4OSA_DEBUG_IF2((M4OSA_NULL == Context),M4ERR_PARAMETER,"Context M4OSA_NULL");
    298     M4OSA_DEBUG_IF2((M4OSA_NULL == pStreamDesc),M4ERR_PARAMETER,"Stream Desc. M4OSA_NULL");
    299     M4OSA_DEBUG_IF2((pStreamContext->m_contextId != M4AMRR_CONTEXTID),M4ERR_BAD_CONTEXT,
    300          "Bad Context");
    301     M4OSA_DEBUG_IF1(( pStreamContext->m_status != M4AMRR_kOpened), M4ERR_STATE, "Invalid State");
    302 
    303     if (M4OSA_NULL != pStreamContext->m_pStreamHandler)
    304     {
    305         return M4WAR_NO_MORE_STREAM ;
    306     }
    307 
    308     size = 1;
    309     pStreamContext->m_pOsaFilePtrFct->readData(pStreamContext->m_pAMRFile,
    310          (M4OSA_MemAddr8)&frameHeader, &size);
    311 
    312     /* XFFF FXXX -> F is the Frame type */
    313     frameType = ( frameHeader & 0x78 ) >> 3 ;
    314 
    315     if ( frameType == 15 )
    316     {
    317         return M4WAR_NO_DATA_YET ;
    318     }
    319 
    320     if (( pStreamContext->m_streamType == M4SYS_kAMR ) && ( frameType > 11 ))
    321     {
    322         return (M4OSA_ERR)M4ERR_AMR_INVALID_FRAME_TYPE;
    323     }
    324 
    325     if (( pStreamContext->m_streamType == M4SYS_kAMR_WB ) && ( frameType > 9 ))
    326     {
    327         return (M4OSA_ERR)M4ERR_AMR_INVALID_FRAME_TYPE;
    328     }
    329 
    330     /* Average bit rate is assigned the bitrate of the first frame */
    331     pStreamDesc->averageBitrate = M4AMRR_getBitrate(frameType,pStreamContext->m_streamType);
    332 
    333     filePos = -1;
    334     pStreamContext->m_pOsaFilePtrFct->seek(pStreamContext->m_pAMRFile, M4OSA_kFileSeekCurrent,
    335          &filePos);
    336 
    337     /* Initialize pStreamDesc */
    338     pStreamDesc->profileLevel = 0xFF ;
    339     pStreamDesc->decoderSpecificInfoSize = 0 ;
    340     pStreamDesc->decoderSpecificInfo = M4OSA_NULL ;
    341     pStreamDesc->maxBitrate = (pStreamContext->m_streamType ==
    342         M4SYS_kAMR )?M4AMRR_NB_MAX_BIT_RATE:M4AMRR_WB_MAX_BIT_RATE;
    343     pStreamDesc->profileLevel = 0xFF ;
    344     pStreamDesc->streamID = 1;
    345     pStreamDesc->streamType = pStreamContext->m_streamType;
    346 
    347     /* Timescale equals Sampling Frequency: NB-8000 Hz, WB-16000 Hz */
    348     pStreamDesc->timeScale = (pStreamContext->m_streamType == M4SYS_kAMR )?8000:16000;
    349     pStreamDesc->duration = M4OSA_TIME_UNKNOWN;
    350 
    351     pStreamContext->m_pStreamHandler =
    352          (M4SYS_StreamDescription*)M4OSA_32bitAlignedMalloc(sizeof(M4SYS_StreamDescription),
    353              M4AMR_READER, (M4OSA_Char *)("pStreamContext->m_pStreamHandler"));
    354     if(M4OSA_NULL == pStreamContext->m_pStreamHandler)
    355     {
    356         return M4ERR_ALLOC;
    357     }
    358 
    359     /* Copy the Stream Desc. into the Context */
    360     pStreamContext->m_pStreamHandler->averageBitrate = pStreamDesc->averageBitrate;
    361     pStreamContext->m_pStreamHandler->decoderSpecificInfo = M4OSA_NULL ;
    362     pStreamContext->m_pStreamHandler->decoderSpecificInfoSize = 0 ;
    363     pStreamContext->m_pStreamHandler->duration = M4OSA_TIME_UNKNOWN;
    364     pStreamContext->m_pStreamHandler->profileLevel = 0xFF ;
    365     pStreamContext->m_pStreamHandler->streamID = 1;
    366     pStreamContext->m_pStreamHandler->streamType = pStreamDesc->streamType ;
    367     pStreamContext->m_pStreamHandler->timeScale = pStreamDesc->timeScale ;
    368 
    369     /* Count the number of Access Unit in the File to get the */
    370     /* duration of the stream = 20 ms * number of access unit */
    371     while(1)
    372     {
    373         size = 1;
    374         pStreamContext->m_pOsaFilePtrFct->readData(pStreamContext->m_pAMRFile,
    375              (M4OSA_MemAddr8)&frameHeader, &size);
    376         if ( size == 0)
    377             break ;
    378         frameType = (frameHeader & 0x78) >> 3 ;
    379         /* Get the frame size and skip so many bytes */
    380         if(frameType != 15){
    381             /* GLA 20050628 when frametype is >10 we read over a table */
    382             if(frameType > 10)
    383                 continue ;
    384 
    385             size = M4AMRR_getAuSize(frameType, pStreamContext->m_streamType);
    386             if(size > pStreamContext->m_maxAuSize )
    387             {
    388                 pStreamContext->m_maxAuSize = size ;
    389             }
    390             filePos = size-1;
    391             pStreamContext->m_pOsaFilePtrFct->seek(pStreamContext->m_pAMRFile,
    392                  M4OSA_kFileSeekCurrent, &filePos);
    393             auCount++;
    394         }
    395     }
    396 
    397     /* Each Frame is 20 m Sec. */
    398     pStreamContext->m_pStreamHandler->duration = auCount * M4AMRR_FRAME_LENGTH ;
    399     pStreamDesc->duration = pStreamContext->m_pStreamHandler->duration ;
    400 
    401     /* Put the file pointer back at the first Access unit */
    402     if( pStreamContext->m_streamType == M4SYS_kAMR )
    403     {
    404         filePos = 6;
    405         pStreamContext->m_pOsaFilePtrFct->seek(pStreamContext->m_pAMRFile,
    406              M4OSA_kFileSeekBeginning, &filePos);
    407     }
    408     if ( pStreamContext->m_streamType == M4SYS_kAMR_WB )
    409     {
    410         filePos = 9;
    411         pStreamContext->m_pOsaFilePtrFct->seek(pStreamContext->m_pAMRFile,
    412              M4OSA_kFileSeekBeginning, &filePos);
    413     }
    414     return M4NO_ERROR ;
    415 }
    416 
    417 /*********************************************************/
    418 M4OSA_ERR M4AMRR_startReading(M4OSA_Context Context, M4SYS_StreamID* pStreamIDs )
    419 /*********************************************************/
    420 {
    421     M4_AMRR_Context* pStreamContext=(M4_AMRR_Context*)Context;
    422     M4OSA_Int32 size = 0 ;
    423 
    424     M4OSA_DEBUG_IF2((M4OSA_NULL == Context),M4ERR_PARAMETER,"Context M4OSA_NULL");
    425     M4OSA_DEBUG_IF2((M4OSA_NULL == pStreamIDs),M4ERR_PARAMETER,"Stream Ids. M4OSA_NULL");
    426     M4OSA_DEBUG_IF2((pStreamContext->m_contextId != M4AMRR_CONTEXTID),M4ERR_BAD_CONTEXT,
    427          "Bad Context");
    428     M4OSA_DEBUG_IF1(( pStreamContext->m_status != M4AMRR_kOpened), M4ERR_STATE, "Invalid State");
    429 
    430     while( pStreamIDs[size] != 0 )
    431     {
    432         if( pStreamIDs[size++] != 1 )
    433         {
    434             return M4ERR_BAD_STREAM_ID ;
    435         }
    436     }
    437 
    438     /* Allocate memory for data Address for use in NextAU() */
    439     if(M4OSA_NULL == pStreamContext->m_pdataAddress)
    440     {
    441         size = pStreamContext->m_maxAuSize ;
    442         /* dataAddress is owned by Parser, application should not delete or free it */
    443         pStreamContext->m_pdataAddress =(M4OSA_MemAddr32)M4OSA_32bitAlignedMalloc(size + (4 - size % 4),
    444             M4AMR_READER, (M4OSA_Char *)("pStreamContext->m_pdataAddress"));
    445         if(M4OSA_NULL == pStreamContext->m_pdataAddress)
    446         {
    447                 M4OSA_DEBUG_IF3((M4OSA_NULL == pStreamContext->m_pdataAddress),M4ERR_ALLOC,
    448                     "Mem Alloc failed - dataAddress");
    449                 return M4ERR_ALLOC;
    450         }
    451     }
    452 
    453     /* Set the state of context to Reading */
    454     pStreamContext->m_status = M4AMRR_kReading ;
    455 
    456     return M4NO_ERROR ;
    457 }
    458 
    459 
    460 /*********************************************************/
    461 M4OSA_ERR M4AMRR_nextAU(M4OSA_Context Context, M4SYS_StreamID StreamID, M4SYS_AccessUnit* pAu)
    462 /*********************************************************/
    463 {
    464     M4_AMRR_Context* pStreamContext=(M4_AMRR_Context*)Context;
    465     M4OSA_Char        frameHeader ;
    466     M4OSA_Char        frameType ;
    467     M4OSA_Int32        auSize;
    468     M4OSA_UInt32    size ;
    469     M4OSA_FilePosition  filePos;
    470 
    471     M4OSA_DEBUG_IF2((M4OSA_NULL == Context),M4ERR_PARAMETER,"Context M4OSA_NULL");
    472     M4OSA_DEBUG_IF2((M4OSA_NULL == pAu),M4ERR_PARAMETER,"Access Unit . M4OSA_NULL");
    473     M4OSA_DEBUG_IF2((pStreamContext->m_contextId != M4AMRR_CONTEXTID),M4ERR_BAD_CONTEXT,
    474          "Bad Context");
    475     M4OSA_DEBUG_IF1(( pStreamContext->m_status != M4AMRR_kReading), M4ERR_STATE, "Invalid State");
    476 
    477     if ( StreamID != 1 )
    478     {
    479             return M4ERR_BAD_STREAM_ID;
    480     }
    481 
    482     /* Read the frame header byte */
    483     size = pStreamContext->m_maxAuSize;
    484     pStreamContext->m_pOsaFilePtrFct->readData(pStreamContext->m_pAMRFile,
    485          (M4OSA_MemAddr8)pStreamContext->m_pdataAddress, &size);
    486     if(size != pStreamContext->m_maxAuSize)
    487     {
    488         return M4WAR_NO_MORE_AU;
    489     }
    490 
    491     frameHeader = ((M4OSA_MemAddr8)pStreamContext->m_pdataAddress)[0];
    492 
    493     frameType = ( frameHeader & 0x78 ) >> 3 ;
    494 
    495     if (( pStreamContext->m_streamType == M4SYS_kAMR ) &&
    496         ( frameType > 11 ) && ( frameType != 15 ))
    497     {
    498         return (M4OSA_ERR)M4ERR_AMR_INVALID_FRAME_TYPE;
    499     }
    500 
    501     if (( pStreamContext->m_streamType == M4SYS_kAMR_WB ) &&
    502         ( frameType > 9 ) && ( frameType != 15 ))
    503     {
    504         return (M4OSA_ERR)M4ERR_AMR_INVALID_FRAME_TYPE;
    505     }
    506 
    507     /* Get the frame size */
    508     if(frameType == 15)
    509     {
    510         auSize = 1;
    511     }
    512     else
    513     {
    514         auSize = M4AMRR_getAuSize(frameType, pStreamContext->m_streamType);
    515     }
    516 
    517     size -= auSize ;
    518     if(size != 0)
    519     {
    520         filePos = -((M4OSA_FilePosition)size);
    521         pStreamContext->m_pOsaFilePtrFct->seek(pStreamContext->m_pAMRFile,
    522              M4OSA_kFileSeekCurrent, &filePos);
    523     }
    524 
    525     pAu->size = auSize ;
    526 
    527     /* even when frameType == 15 (no data frame), ARM core decoder outputs full PCM buffer */
    528     /*if(frameType == 15 )
    529     {
    530         pAu->CTS += 0;
    531     }*/
    532     /*else*/
    533     {
    534         pAu->CTS += M4AMRR_FRAME_LENGTH ;
    535     }
    536 
    537 
    538     pAu->DTS = pAu->CTS ;
    539     pAu->attribute = M4SYS_kFragAttrOk;
    540 
    541     pAu->stream = pStreamContext->m_pStreamHandler;
    542     pAu->dataAddress = pStreamContext->m_pdataAddress ;
    543 
    544     if(frameHeader & 0x80)
    545     {
    546         return M4WAR_NO_MORE_AU;
    547     }
    548 
    549     /* Change the state to implement NextAu->freeAu->NextAu FSM */
    550     pStreamContext->m_status = M4AMRR_kReading_nextAU ;
    551 
    552     return M4NO_ERROR ;
    553 }
    554 
    555 /*********************************************************/
    556 M4OSA_ERR M4AMRR_freeAU(M4OSA_Context Context, M4SYS_StreamID StreamID, M4SYS_AccessUnit* pAu)
    557 /*********************************************************/
    558 {
    559     M4_AMRR_Context* pStreamContext=(M4_AMRR_Context*)Context;
    560     M4OSA_DEBUG_IF2((M4OSA_NULL == Context),M4ERR_PARAMETER,"Context M4OSA_NULL");
    561     M4OSA_DEBUG_IF2((M4OSA_NULL == pAu),M4ERR_PARAMETER,"Access Unit . M4OSA_NULL");
    562     M4OSA_DEBUG_IF2((pStreamContext->m_contextId != M4AMRR_CONTEXTID),M4ERR_BAD_CONTEXT,
    563          "Bad Context");
    564     M4OSA_DEBUG_IF1(( pStreamContext->m_status != M4AMRR_kReading_nextAU), M4ERR_STATE,
    565          "Invalid State");
    566 
    567     if (( StreamID != 1 ) && ( StreamID != 0))
    568     {
    569             return M4ERR_BAD_STREAM_ID;
    570     }
    571 
    572     /* Change the state to Reading so as to allow access to next AU */
    573     pStreamContext->m_status = M4AMRR_kReading ;
    574 
    575     return M4NO_ERROR ;
    576 }
    577 
    578 /*********************************************************/
    579 M4OSA_ERR M4AMRR_seek(M4OSA_Context Context, M4SYS_StreamID* pStreamID, M4OSA_Time time,
    580                          M4SYS_SeekAccessMode seekMode, M4OSA_Time* pObtainCTS)
    581 /*********************************************************/
    582 {
    583     M4_AMRR_Context* pStreamContext=(M4_AMRR_Context*)Context;
    584     M4OSA_UInt32 count, prevAU, nextAU ;
    585     M4OSA_UInt32 size ;
    586     M4OSA_UInt32 auSize ;
    587     M4OSA_UInt32 position, partSeekTime;
    588     M4OSA_UInt32 auCount = 0, skipAuCount = 0 ;
    589     M4OSA_Char    frameHeader ;
    590     M4OSA_Char    frameType ;
    591     M4OSA_FilePosition  filePos;
    592     M4OSA_Double time_double;
    593 
    594     /*Make explicit time cast, but take care that timescale is not used !!!*/
    595     M4OSA_TIME_TO_MS(time_double, time, 1000);
    596 
    597     *pObtainCTS = 0;
    598 
    599     M4OSA_DEBUG_IF2((M4OSA_NULL == Context),M4ERR_PARAMETER,"Context M4OSA_NULL");
    600     M4OSA_DEBUG_IF2((pStreamContext->m_contextId != M4AMRR_CONTEXTID),M4ERR_BAD_CONTEXT,
    601          "Bad Context");
    602     M4OSA_DEBUG_IF1(( pStreamContext->m_status != M4AMRR_kReading) && \
    603         ( pStreamContext->m_status != M4AMRR_kOpened), M4ERR_STATE, "Invalid State");
    604     M4OSA_DEBUG_IF1((time_double < 0),M4ERR_PARAMETER,"negative time");
    605 
    606     /* Coming to seek for the first time, need to build the seekIndex Table */
    607     if(M4OSA_NULL == pStreamContext->m_pSeekIndex)
    608     {
    609         M4OSA_Double duration_double;
    610 
    611         count = 0 ;
    612         pStreamContext->m_pSeekIndex =
    613              (M4OSA_UInt32*)M4OSA_32bitAlignedMalloc(M4AMRR_NUM_SEEK_ENTRIES * sizeof(M4OSA_UInt32),
    614                  M4AMR_READER, (M4OSA_Char *)("pStreamContext->m_pSeekIndex"));
    615 
    616         if(M4OSA_NULL == pStreamContext->m_pSeekIndex)
    617         {
    618             M4OSA_DEBUG_IF3((M4OSA_NULL == pStreamContext->m_pSeekIndex),M4ERR_ALLOC,
    619                 "Mem Alloc Failed - SeekIndex");
    620             return M4ERR_ALLOC ;
    621         }
    622 
    623         /* point to the first AU */
    624         if( pStreamContext->m_streamType == M4SYS_kAMR )
    625         {
    626             filePos = 6;
    627         }
    628         else /*if ( pStreamContext->m_streamType == M4SYS_kAMR_WB )*/
    629         {
    630             filePos = 9;
    631         }
    632 
    633         pStreamContext->m_pOsaFilePtrFct->seek(pStreamContext->m_pAMRFile,
    634              M4OSA_kFileSeekBeginning, &filePos);
    635 
    636         /* Set the postion to begining of first AU */
    637         position = (pStreamContext->m_streamType != M4SYS_kAMR)?9:6;
    638 
    639         /*Make explicit time cast, but take care that timescale is not used !!!*/
    640         M4OSA_TIME_TO_MS(duration_double, pStreamContext->m_pStreamHandler->duration, 1000);
    641 
    642         /* Calculate the seek Interval duration based on total dutation */
    643         /* Interval = (duration / ENTRIES) in multiples of AU frame length */
    644         pStreamContext->m_seekInterval =
    645              (M4OSA_UInt32)(duration_double / M4AMRR_NUM_SEEK_ENTRIES) ;
    646         pStreamContext->m_seekInterval /= M4AMRR_FRAME_LENGTH ;
    647         pStreamContext->m_seekInterval *= M4AMRR_FRAME_LENGTH ;
    648         skipAuCount = pStreamContext->m_seekInterval / M4AMRR_FRAME_LENGTH ;
    649 
    650         pStreamContext->m_pSeekIndex[count++]=position;
    651         while(count < M4AMRR_NUM_SEEK_ENTRIES )
    652         {
    653             size = 1;
    654             pStreamContext->m_pOsaFilePtrFct->readData(pStreamContext->m_pAMRFile,
    655                  (M4OSA_MemAddr8)&frameHeader, &size);
    656             if ( size == 0)
    657             {
    658                 break ;
    659             }
    660             frameType = (frameHeader & 0x78) >> 3 ;
    661             if(frameType != 15)
    662             {
    663                 /**< bugfix Ronan Cousyn 05/04/2006: In the core reader AMR, the
    664                  * function M4AMRR_seek doesn't check the frameType */
    665                 if (( pStreamContext->m_streamType == M4SYS_kAMR ) && ( frameType > 10 ))
    666                 {
    667                     return M4ERR_AMR_INVALID_FRAME_TYPE;
    668                 }
    669                 if (( pStreamContext->m_streamType == M4SYS_kAMR_WB ) && ( frameType > 9 ))
    670                 {
    671                     return M4ERR_AMR_INVALID_FRAME_TYPE;
    672                 }
    673                 auSize = M4AMRR_getAuSize(frameType, pStreamContext->m_streamType);
    674                 position += auSize ;
    675                 filePos = auSize-1;
    676                 pStreamContext->m_pOsaFilePtrFct->seek(pStreamContext->m_pAMRFile,
    677                      M4OSA_kFileSeekCurrent, &filePos);
    678                 auCount++;
    679             }
    680             else
    681             {
    682                 position ++;
    683             }
    684             /* Skip the number of AU's as per interval and store in the Index table */
    685             if ( (skipAuCount != 0) && !(auCount % skipAuCount))
    686             {
    687                 pStreamContext->m_pSeekIndex[count++] = position;
    688             }
    689         }
    690     }/* End of Building the seek table */
    691 
    692     /* Use the seek table to seek the required time in the stream */
    693 
    694     /* If we are seeking the begining of the file point to first AU */
    695     if ( seekMode == M4SYS_kBeginning )
    696     {
    697         if( pStreamContext->m_streamType == M4SYS_kAMR )
    698         {
    699             filePos = 6;
    700         }
    701         else /*if ( pStreamContext->m_streamType == M4SYS_kAMR_WB )*/
    702         {
    703             filePos = 9;
    704         }
    705         pStreamContext->m_pOsaFilePtrFct->seek(pStreamContext->m_pAMRFile,
    706              M4OSA_kFileSeekBeginning, &filePos );
    707         return M4NO_ERROR ;
    708     }
    709 
    710     /* Get the Nearest Second */
    711     if (0 != pStreamContext->m_seekInterval)
    712     {
    713         position = (M4OSA_UInt32)(time_double / pStreamContext->m_seekInterval);
    714     }
    715     else
    716     {
    717         /*avoid division by 0*/
    718         position = 0;
    719     }
    720 
    721     /* We have only 40 seek Index. */
    722     position=(position >= M4AMRR_NUM_SEEK_ENTRIES)?M4AMRR_NUM_SEEK_ENTRIES-1:position;
    723 
    724     /* SeekIndex will point to nearest Au, we need to search for the
    725     required time form that position */
    726     partSeekTime = (M4OSA_UInt32)time_double - position * pStreamContext->m_seekInterval;
    727 
    728     position = pStreamContext->m_pSeekIndex[position];
    729 
    730     if(!position)
    731     {
    732         return M4WAR_INVALID_TIME ;
    733     }
    734 
    735     /* point the file pointer to nearest AU */
    736     filePos = position;
    737     pStreamContext->m_pOsaFilePtrFct->seek(pStreamContext->m_pAMRFile, M4OSA_kFileSeekBeginning,
    738          &filePos );
    739 
    740     if ( partSeekTime == 0)
    741     {
    742         *pObtainCTS = time;
    743         return M4NO_ERROR;
    744     }
    745 
    746     *pObtainCTS = (M4OSA_Time)(time_double - (M4OSA_Double)partSeekTime);
    747 
    748     switch(seekMode)
    749     {
    750         /* Get the AU before the target time */
    751         case M4SYS_kPreviousRAP:
    752         case M4SYS_kNoRAPprevious:
    753             position = partSeekTime / M4AMRR_FRAME_LENGTH ;
    754             if ( !(partSeekTime % M4AMRR_FRAME_LENGTH) )
    755             {
    756                 position -- ;
    757             }
    758         break;
    759         /* Get the Closest AU following the target time */
    760         case M4SYS_kNextRAP:
    761         case M4SYS_kNoRAPnext:
    762             position = (partSeekTime + M4AMRR_FRAME_LENGTH )/ M4AMRR_FRAME_LENGTH ;
    763         break;
    764         /*  Get the closest AU to target time */
    765         case M4SYS_kClosestRAP:
    766         case M4SYS_kNoRAPclosest:
    767             prevAU = partSeekTime-(partSeekTime/M4AMRR_FRAME_LENGTH)*M4AMRR_FRAME_LENGTH;
    768             nextAU =
    769                  ((partSeekTime+M4AMRR_FRAME_LENGTH)/M4AMRR_FRAME_LENGTH)*M4AMRR_FRAME_LENGTH -\
    770                      partSeekTime ;
    771             if(prevAU < nextAU)
    772             {
    773                 position = partSeekTime / M4AMRR_FRAME_LENGTH ;
    774             }
    775             else
    776             {
    777                 position = (partSeekTime + M4AMRR_FRAME_LENGTH )/ M4AMRR_FRAME_LENGTH ;
    778             }
    779         break;
    780         case M4SYS_kBeginning:
    781         break;
    782     }
    783 
    784     count = 0 ;
    785     /* Skip the Access unit in the stream to skip the part seek time,
    786        to reach the required target time */
    787     while(count < position )
    788     {
    789         size = 1;
    790         pStreamContext->m_pOsaFilePtrFct->readData(pStreamContext->m_pAMRFile,
    791              (M4OSA_MemAddr8)&frameHeader, &size);
    792         if ( size == 0)
    793         {
    794             /* If the target time is invalid, point to begining and return */
    795             *pObtainCTS = 0;
    796             filePos = pStreamContext->m_pSeekIndex[0];
    797             pStreamContext->m_pOsaFilePtrFct->seek(pStreamContext->m_pAMRFile,
    798                  M4OSA_kFileSeekBeginning, &filePos);
    799             return M4WAR_INVALID_TIME ;
    800         }
    801         *pObtainCTS += M4AMRR_FRAME_LENGTH; /*Should use M4OSA_INT64_ADD !!*/
    802         count++;
    803         frameType = (frameHeader & 0x78) >> 3 ;
    804         if(frameType == 15)
    805         {
    806             auSize = 1 ;
    807         }
    808         else
    809         {
    810             auSize = M4AMRR_getAuSize(frameType, pStreamContext->m_streamType);
    811         }
    812 
    813         filePos = auSize-1;
    814         pStreamContext->m_pOsaFilePtrFct->seek(pStreamContext->m_pAMRFile,
    815              M4OSA_kFileSeekCurrent, &filePos);
    816     }
    817 
    818     return M4NO_ERROR;
    819 }
    820 
    821 /*********************************************************/
    822 M4OSA_ERR M4AMRR_closeRead(M4OSA_Context Context)
    823 /*********************************************************/
    824 {
    825     M4_AMRR_Context* pStreamContext=(M4_AMRR_Context*)Context;
    826     M4OSA_DEBUG_IF2((M4OSA_NULL == Context),M4ERR_PARAMETER,"Context M4OSA_NULL");
    827 
    828     /* Close the AMR stream */
    829     pStreamContext->m_pOsaFilePtrFct->closeRead(pStreamContext->m_pAMRFile);
    830 
    831     pStreamContext->m_status=M4AMRR_kClosed ;
    832 
    833     /* Check if AU data Address is allocated memory and free it */
    834     if(M4OSA_NULL != pStreamContext->m_pdataAddress)
    835     {
    836         free(pStreamContext->m_pdataAddress);
    837     }
    838 
    839     /* Check if the stream handler is allocated memory */
    840     if(M4OSA_NULL != pStreamContext->m_pStreamHandler)
    841     {
    842         free(pStreamContext->m_pStreamHandler);
    843     }
    844 
    845     /* Seek table is created only when seek is used, so check if memory is allocated */
    846     if(M4OSA_NULL != pStreamContext->m_pSeekIndex)
    847     {
    848         free(pStreamContext->m_pSeekIndex);
    849     }
    850 
    851     /* Free the context */
    852     free(pStreamContext);
    853 
    854     return M4NO_ERROR ;
    855 }
    856 
    857 /*********************************************************/
    858 M4OSA_ERR M4AMRR_getState(M4OSA_Context Context, M4AMRR_State* pState, M4SYS_StreamID streamId)
    859 /*********************************************************/
    860 {
    861     M4_AMRR_Context* pStreamContext=(M4_AMRR_Context*)Context;
    862     M4OSA_DEBUG_IF2((M4OSA_NULL == Context),M4ERR_PARAMETER,"Context M4OSA_NULL");
    863     M4OSA_DEBUG_IF2((pStreamContext->m_contextId != M4AMRR_CONTEXTID),M4ERR_BAD_CONTEXT,
    864          "Bad Context");
    865 
    866     if (( streamId != 1 ) && ( streamId != 0))
    867     {
    868             return M4ERR_BAD_STREAM_ID;
    869     }
    870 
    871     *pState = pStreamContext->m_status ;
    872 
    873     return M4NO_ERROR ;
    874 }
    875 
    876 
    877 /*********************************************************/
    878 M4OSA_ERR M4AMRR_getVersion    (M4_VersionInfo *pVersion)
    879 /*********************************************************/
    880 {
    881     M4OSA_TRACE1_1("M4AMRR_getVersion called with pVersion: 0x%x\n", pVersion);
    882     M4OSA_DEBUG_IF1(((M4OSA_UInt32) pVersion == 0),M4ERR_PARAMETER,
    883          "pVersion is NULL in M4AMRR_getVersion");
    884 
    885     pVersion->m_major = M4AMRR_VERSION_MAJOR;
    886     pVersion->m_minor = M4AMRR_VERSION_MINOR;
    887     pVersion->m_revision = M4AMRR_VERSION_REVISION;
    888 
    889     return M4NO_ERROR;
    890 }
    891 
    892 /*********************************************************/
    893 M4OSA_ERR M4AMRR_getmaxAUsize(M4OSA_Context Context, M4OSA_UInt32 *pMaxAuSize)
    894 /*********************************************************/
    895 {
    896     M4_AMRR_Context* pStreamContext=(M4_AMRR_Context*)Context;
    897 
    898     /**
    899      * Check input parameters */
    900     M4OSA_DEBUG_IF1((M4OSA_NULL == Context),  M4ERR_PARAMETER,
    901                 "M4AMRR_getmaxAUsize: Context is M4OSA_NULL");
    902     M4OSA_DEBUG_IF1((M4OSA_NULL == pMaxAuSize),M4ERR_PARAMETER,
    903                 "M4AMRR_getmaxAUsize: pMaxAuSize is M4OSA_NULL");
    904 
    905     *pMaxAuSize = pStreamContext->m_maxAuSize;
    906 
    907     return M4NO_ERROR;
    908 }
    909 
    910