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   M4READER_Amr.c
     20  * @brief  Generic encapsulation of the core amr reader
     21  * @note   This file implements the generic M4READER interface
     22  *         on top of the AMR reader
     23  ************************************************************************
     24 */
     25 #include "M4OSA_Types.h"
     26 #include "M4OSA_Error.h"
     27 #include "M4OSA_Memory.h"
     28 #include "M4OSA_Debug.h"
     29 #include "M4OSA_CoreID.h"
     30 
     31 #include "M4_Utils.h"
     32 
     33 #include "M4AMRR_CoreReader.h"
     34 #include "M4READER_Amr.h"
     35 
     36 /**
     37  ************************************************************************
     38  * structure    M4READER_AMR_Context
     39  * @brief       This structure defines the internal context of a amr reader instance
     40  * @note        The context is allocated and de-allocated by the reader
     41  ************************************************************************
     42 */
     43 typedef struct _M4READER_AMR_Context
     44 {
     45     M4OSA_Context           m_pCoreContext;     /**< core amr reader context */
     46     M4_AudioStreamHandler*  m_pAudioStream;     /**< pointer on the audio stream
     47                                                  description returned by the core */
     48     M4SYS_AccessUnit        m_audioAu;          /**< audio access unit to be filled by the core */
     49     M4OSA_Time              m_maxDuration;      /**< duration of the audio stream */
     50     M4OSA_FileReadPointer*    m_pOsaFileReaderFcts;    /**< OSAL file read functions */
     51 
     52 } M4READER_AMR_Context;
     53 
     54 
     55 /**
     56  ************************************************************************
     57  * @brief    create an instance of the reader
     58  * @note     allocates the context
     59  * @param    pContext:        (OUT)    pointer on a reader context
     60  * @return    M4NO_ERROR                 there is no error
     61  * @return    M4ERR_ALLOC                a memory allocation has failed
     62  * @return    M4ERR_PARAMETER            at least one parameter is not properly set (in DEBUG only)
     63  ************************************************************************
     64 */
     65 M4OSA_ERR M4READER_AMR_create(M4OSA_Context *pContext)
     66 {
     67     M4READER_AMR_Context* pReaderContext;
     68 
     69     /* Check function parameters */
     70     M4OSA_DEBUG_IF1((pContext == 0), M4ERR_PARAMETER,
     71          "M4READER_AMR_create: invalid context pointer");
     72 
     73     pReaderContext = (M4READER_AMR_Context*)M4OSA_32bitAlignedMalloc(sizeof(M4READER_AMR_Context),
     74          M4READER_AMR, (M4OSA_Char *)"M4READER_AMR_Context");
     75     if (pReaderContext == M4OSA_NULL)
     76     {
     77         return M4ERR_ALLOC;
     78     }
     79 
     80     pReaderContext->m_pAudioStream  = M4OSA_NULL;
     81     pReaderContext->m_audioAu.dataAddress = M4OSA_NULL;
     82     pReaderContext->m_maxDuration = 0;
     83     pReaderContext->m_pCoreContext = M4OSA_NULL;
     84     pReaderContext->m_pOsaFileReaderFcts = M4OSA_NULL;
     85 
     86     *pContext = pReaderContext;
     87 
     88     return M4NO_ERROR;
     89 }
     90 
     91 /**
     92  ************************************************************************
     93  * @brief    destroy the instance of the reader
     94  * @note     after this call the context is invalid
     95  *
     96  * @param    context:        (IN)    Context of the reader
     97  *
     98  * @return    M4NO_ERROR                 there is no error
     99  * @return    M4ERR_PARAMETER            at least one parameter is not properly set
    100  ************************************************************************
    101 */
    102 M4OSA_ERR M4READER_AMR_destroy(M4OSA_Context context)
    103 {
    104     M4READER_AMR_Context*   pC=(M4READER_AMR_Context*)context;
    105 
    106     /* Check function parameters*/
    107     M4OSA_DEBUG_IF1((M4OSA_NULL == pC), M4ERR_PARAMETER,
    108          "M4READER_AMR_destroy: invalid context pointer");
    109 
    110     /**
    111      *    Check input parameter */
    112     if (M4OSA_NULL == pC)
    113     {
    114         M4OSA_TRACE1_0("M4READER_AMR_destroy(): M4READER_AMR_destroy: context is M4OSA_NULL,\
    115              returning M4ERR_PARAMETER");
    116         return M4ERR_PARAMETER;
    117     }
    118 
    119     free(pC);
    120 
    121     return M4NO_ERROR;
    122 }
    123 
    124 
    125 /**
    126  ************************************************************************
    127  * @brief    open the reader and initializes its created instance
    128  * @note     this function opens the AMR file
    129  * @param    context:            (IN)    Context of the reader
    130  * @param    pFileDescriptor:    (IN)    Pointer to proprietary data identifying the media to open
    131  * @return    M4NO_ERROR                     there is no error
    132  * @return    M4ERR_PARAMETER                the context is NULL
    133  * @return    M4ERR_BAD_CONTEXT            provided context is not a valid one
    134  ************************************************************************
    135 */
    136 M4OSA_ERR M4READER_AMR_open(M4OSA_Context context, M4OSA_Void* pFileDescriptor)
    137 {
    138     M4READER_AMR_Context*    pC = (M4READER_AMR_Context*)context;
    139     M4OSA_ERR                err;
    140 
    141     /* Check function parameters*/
    142     M4OSA_DEBUG_IF1((M4OSA_NULL == pC),              M4ERR_PARAMETER,
    143          "M4READER_AMR_open: invalid context pointer");
    144     M4OSA_DEBUG_IF1((M4OSA_NULL == pFileDescriptor), M4ERR_PARAMETER,
    145          "M4READER_AMR_open: invalid pointer pFileDescriptor");
    146 
    147     err = M4AMRR_openRead( &pC->m_pCoreContext, pFileDescriptor, pC->m_pOsaFileReaderFcts);
    148 
    149     return err;
    150 }
    151 
    152 
    153 
    154 /**
    155  ************************************************************************
    156  * @brief    close the reader
    157  * @note
    158  * @param    context:        (IN)    Context of the reader
    159  * @return    M4NO_ERROR                 there is no error
    160  * @return    M4ERR_PARAMETER            the context is NULL
    161  * @return    M4ERR_BAD_CONTEXT        provided context is not a valid one
    162  ************************************************************************
    163 */
    164 M4OSA_ERR   M4READER_AMR_close(M4OSA_Context context)
    165 {
    166     M4READER_AMR_Context*    pC = (M4READER_AMR_Context*)context;
    167     M4OSA_ERR                err;
    168     M4AMRR_State State;
    169 
    170     /* Check function parameters*/
    171     M4OSA_DEBUG_IF1((M4OSA_NULL == pC), M4ERR_PARAMETER,
    172          "M4READER_AMR_close: invalid context pointer");
    173 
    174     /**
    175      *    Check input parameter */
    176     if (M4OSA_NULL == pC)
    177     {
    178         M4OSA_TRACE1_0("M4READER_AMR_close(): M4READER_AMR_close: context is M4OSA_NULL,\
    179              returning M4ERR_PARAMETER");
    180         return M4ERR_PARAMETER;
    181     }
    182 
    183     if (M4OSA_NULL != pC->m_pAudioStream)
    184     {
    185         err = M4AMRR_getState(pC->m_pCoreContext, &State,
    186                 ((M4_StreamHandler*)pC->m_pAudioStream)->m_streamId);
    187         if(M4NO_ERROR != err)
    188         {
    189             M4OSA_TRACE1_0("M4READER_AMR_close: error when calling M4AMRR_getState\n");
    190             return err;
    191         }
    192 
    193         if (M4AMRR_kReading_nextAU == State)
    194         {
    195             err = M4AMRR_freeAU(pC->m_pCoreContext,
    196                 ((M4_StreamHandler*)pC->m_pAudioStream)->m_streamId,  &pC->m_audioAu);
    197             if (err != M4NO_ERROR)
    198             {
    199                 M4OSA_TRACE1_0("M4READER_AMR_close: error when freeing access unit\n");
    200                 return err;
    201             }
    202         }
    203 
    204         /* Delete the DSI if needed */
    205         if(M4OSA_NULL != pC->m_pAudioStream->m_basicProperties.m_pDecoderSpecificInfo)
    206         {
    207             free(\
    208                 pC->m_pAudioStream->m_basicProperties.m_pDecoderSpecificInfo);
    209 
    210             pC->m_pAudioStream->m_basicProperties.m_decoderSpecificInfoSize = 0;
    211             pC->m_pAudioStream->m_basicProperties.m_pDecoderSpecificInfo = M4OSA_NULL;
    212         }
    213 
    214         /* Finally destroy the stream handler */
    215         free(pC->m_pAudioStream);
    216         pC->m_pAudioStream = M4OSA_NULL;
    217     }
    218 
    219     if (M4OSA_NULL != pC->m_pCoreContext)
    220     {
    221         err = M4AMRR_closeRead(pC->m_pCoreContext);
    222         pC->m_pCoreContext = M4OSA_NULL;
    223     }
    224 
    225     return err;
    226 }
    227 
    228 /**
    229  ************************************************************************
    230  * @brief    Get the next stream found in the media
    231  * @note    current version needs to translate M4SYS_Stream to M4_StreamHandler
    232  *
    233  * @param    context:        (IN)   Context of the reader
    234  * @param    pMediaFamily:   (OUT)  pointer to a user allocated M4READER_MediaFamily
    235  *                                  that will be filled with the media family of the found stream
    236  * @param    pStreamHandler: (OUT)  pointer to a stream handler that will be
    237  *                                  allocated and filled with the found stream description
    238  *
    239  * @return    M4NO_ERROR            there is no error
    240  * @return    M4WAR_NO_MORE_STREAM  no more available stream in the media (all streams found)
    241  * @return    M4ERR_PARAMETER       at least one parameter is not properly set (in DEBUG mode only)
    242  ************************************************************************
    243 */
    244 M4OSA_ERR M4READER_AMR_getNextStream(M4OSA_Context context, M4READER_MediaFamily *pMediaFamily,
    245                                      M4_StreamHandler **pStreamHandlerParam)
    246 {
    247     M4READER_AMR_Context*   pC=(M4READER_AMR_Context*)context;
    248     M4OSA_ERR               err;
    249     M4SYS_StreamID          streamIdArray[2];
    250     M4SYS_StreamDescription streamDesc;
    251     M4_AudioStreamHandler*  pAudioStreamHandler;
    252     M4_StreamHandler*       pStreamHandler;
    253 
    254     M4OSA_DEBUG_IF1((pC == 0),                  M4ERR_PARAMETER,
    255                 "M4READER_AMR_getNextStream: invalid context");
    256     M4OSA_DEBUG_IF1((pMediaFamily == 0),        M4ERR_PARAMETER,
    257                 "M4READER_AMR_getNextStream: invalid pointer to MediaFamily");
    258     M4OSA_DEBUG_IF1((pStreamHandlerParam == 0), M4ERR_PARAMETER,
    259                 "M4READER_AMR_getNextStream: invalid pointer to StreamHandler");
    260 
    261     err = M4AMRR_getNextStream( pC->m_pCoreContext, &streamDesc);
    262     if (err == M4WAR_NO_MORE_STREAM)
    263     {
    264         streamIdArray[0] = 0;
    265         streamIdArray[1] = 0;
    266         err = M4AMRR_startReading(pC->m_pCoreContext, streamIdArray);
    267         if ((M4OSA_UInt32)M4ERR_ALLOC == err)
    268         {
    269             M4OSA_TRACE2_0("M4READER_AMR_getNextStream: M4AMRR_startReading returns M4ERR_ALLOC!");
    270             return err;
    271         }
    272         return M4WAR_NO_MORE_STREAM;
    273     }
    274     else if (err != M4NO_ERROR)
    275     {
    276         return err;
    277     }
    278 
    279     *pMediaFamily = M4READER_kMediaFamilyAudio;
    280 
    281     pAudioStreamHandler = (M4_AudioStreamHandler*)M4OSA_32bitAlignedMalloc(sizeof(M4_AudioStreamHandler),
    282                         M4READER_AMR, (M4OSA_Char *)"M4_AudioStreamHandler");
    283     if (pAudioStreamHandler == M4OSA_NULL)
    284     {
    285         return M4ERR_ALLOC;
    286     }
    287     pStreamHandler =(M4_StreamHandler*)(pAudioStreamHandler);
    288     *pStreamHandlerParam = pStreamHandler;
    289     pC->m_pAudioStream = pAudioStreamHandler;
    290 
    291     pAudioStreamHandler->m_structSize = sizeof(M4_AudioStreamHandler);
    292 
    293     /*
    294      * Audio stream handler fields are initialised with 0 value.
    295      * They will be properly set by the AMR decoder
    296      */
    297     pAudioStreamHandler->m_samplingFrequency = 0;
    298     pAudioStreamHandler->m_byteFrameLength   = 0;
    299     pAudioStreamHandler->m_byteSampleSize    = 0;
    300     pAudioStreamHandler->m_nbChannels        = 0;
    301 
    302     pStreamHandler->m_pDecoderSpecificInfo    = (M4OSA_UInt8*)(streamDesc.decoderSpecificInfo);
    303     pStreamHandler->m_decoderSpecificInfoSize = streamDesc.decoderSpecificInfoSize;
    304     pStreamHandler->m_streamId                = streamDesc.streamID;
    305     pStreamHandler->m_duration                = streamDesc.duration;
    306     pStreamHandler->m_pUserData               = (void*)streamDesc.timeScale; /*trick to change*/
    307 
    308     if (streamDesc.duration > pC->m_maxDuration)
    309     {
    310         pC->m_maxDuration = streamDesc.duration;
    311     }
    312     pStreamHandler->m_averageBitRate          = streamDesc.averageBitrate;
    313 
    314     M4AMRR_getmaxAUsize(pC->m_pCoreContext, &pStreamHandler->m_maxAUSize);
    315 
    316     switch (streamDesc.streamType)
    317     {
    318     case M4SYS_kAMR:
    319         pStreamHandler->m_streamType = M4DA_StreamTypeAudioAmrNarrowBand;
    320         break;
    321     case M4SYS_kAMR_WB:
    322         pStreamHandler->m_streamType = M4DA_StreamTypeAudioAmrWideBand;
    323         break;
    324     default:
    325         break;
    326     }
    327 
    328     return err;
    329 }
    330 
    331 /**
    332  ************************************************************************
    333  * @brief    fill the access unit structure with initialization values
    334  * @note
    335  * @param    context:        (IN)     Context of the reader
    336  * @param    pStreamHandler: (IN)     pointer to the stream handler to
    337  *                                    which the access unit will be associated
    338  * @param    pAccessUnit:    (IN/OUT) pointer to the access unit (allocated by the caller)
    339  *                                      to initialize
    340  *
    341  * @return    M4NO_ERROR              there is no error
    342  * @return    M4ERR_PARAMETER         at least one parameter is not properly set
    343  ************************************************************************
    344 */
    345 M4OSA_ERR M4READER_AMR_fillAuStruct(M4OSA_Context context, M4_StreamHandler *pStreamHandler,
    346                                      M4_AccessUnit *pAccessUnit)
    347 {
    348     M4READER_AMR_Context*   pC = (M4READER_AMR_Context*)context;
    349     M4SYS_AccessUnit*       pAu;
    350 
    351     M4OSA_DEBUG_IF1((pC == 0),             M4ERR_PARAMETER,
    352          "M4READER_AMR_fillAuStruct: invalid context");
    353     M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
    354          "M4READER_AMR_fillAuStruct: invalid pointer to M4_StreamHandler");
    355     M4OSA_DEBUG_IF1((pAccessUnit == 0),    M4ERR_PARAMETER,
    356          "M4READER_AMR_fillAuStruct: invalid pointer to M4_AccessUnit");
    357 
    358     if (pStreamHandler == (M4_StreamHandler*)pC->m_pAudioStream)
    359     {
    360         pAu = &pC->m_audioAu;
    361     }
    362     else
    363     {
    364         M4OSA_TRACE1_0("M4READER_AMR_fillAuStruct: passed StreamHandler is not known\n");
    365         return M4ERR_PARAMETER;
    366     }
    367 
    368     pAu->dataAddress = M4OSA_NULL;
    369     pAu->size        = 0;
    370     /* JC: bug fix 1197 (set CTS to -20 in order the first AU CTS is 0) */
    371     pAu->CTS         = -20;
    372     pAu->DTS         = -20;
    373     pAu->attribute   = 0;
    374     pAu->nbFrag      = 0;
    375 
    376     pAccessUnit->m_size         = 0;
    377     /* JC: bug fix 1197 (set CTS to -20 in order the first AU CTS is 0) */
    378     pAccessUnit->m_CTS          = -20;
    379     pAccessUnit->m_DTS          = -20;
    380     pAccessUnit->m_attribute    = 0;
    381     pAccessUnit->m_dataAddress  = M4OSA_NULL;/*pBuffer;*/
    382     pAccessUnit->m_maxsize      = pStreamHandler->m_maxAUSize;
    383     pAccessUnit->m_streamID     = pStreamHandler->m_streamId;
    384     pAccessUnit->m_structSize   = sizeof(M4_AccessUnit);
    385 
    386     return M4NO_ERROR;
    387 }
    388 
    389 /**
    390  ************************************************************************
    391  * @brief    get an option value from the reader
    392  * @note    this function follows the set/get option mechanism described in OSAL 3.0
    393  *          it allows the caller to retrieve a property value:
    394  *          - the duration of the longest stream of the media
    395  *          - the version number of the reader (not implemented yet)
    396  *
    397  * @param    context:        (IN)    Context of the reader
    398  * @param    optionId:        (IN)    indicates the option to get
    399  * @param    pValue:            (OUT)    pointer to structure or value (allocated by user)
    400  *                                       where option is stored
    401  *
    402  * @return    M4NO_ERROR                 there is no error
    403  * @return    M4ERR_PARAMETER            at least one parameter is not properly set
    404  * @return    M4ERR_BAD_OPTION_ID        when the option ID is not a valid one
    405  ************************************************************************
    406 */
    407 M4OSA_ERR M4READER_AMR_getOption(M4OSA_Context context, M4OSA_OptionID optionId,
    408                                  M4OSA_DataOption pValue)
    409 
    410 {
    411     M4READER_AMR_Context* pC = (M4READER_AMR_Context*)context;
    412     M4OSA_ERR err = M4NO_ERROR;
    413 
    414     /* Check function parameters */
    415     M4OSA_DEBUG_IF1((M4OSA_NULL == pC),     M4ERR_PARAMETER, "invalid context pointer");
    416     M4OSA_DEBUG_IF1((M4OSA_NULL == pValue), M4ERR_PARAMETER, "invalid value pointer");
    417 
    418     switch(optionId)
    419     {
    420     case M4READER_kOptionID_Duration :
    421         {
    422             *(M4OSA_Time*)pValue = pC->m_maxDuration;
    423         }
    424         break;
    425 
    426     case M4READER_kOptionID_Bitrate:
    427         {
    428             M4OSA_UInt32* pBitrate = (M4OSA_UInt32*)pValue;
    429             if (M4OSA_NULL != pC->m_pAudioStream)
    430             {
    431                 *pBitrate = pC->m_pAudioStream->m_basicProperties.m_averageBitRate;
    432             }
    433             else
    434             {
    435                 pBitrate = 0;
    436                 err = M4ERR_PARAMETER;
    437             }
    438 
    439         }
    440         break;
    441     case M4READER_kOptionID_Version:
    442         {
    443             err = M4AMRR_getVersion((M4_VersionInfo*)pValue);
    444         }
    445         break;
    446 
    447     default :
    448         {
    449             err = M4ERR_PARAMETER;
    450         }
    451     }
    452 
    453     return err;
    454 }
    455 
    456 /**
    457  ************************************************************************
    458  * @brief   set en option value of the readder
    459  * @note    this function follows the set/get option mechanism described in OSAL 3.0
    460  *          it allows the caller to set a property value:
    461  *          - the OSAL file read functions
    462  *
    463  * @param   context:    (IN)        Context of the decoder
    464  * @param   optionId:   (IN)        Identifier indicating the option to set
    465  * @param   pValue:     (IN)        Pointer to structure or value (allocated by user)
    466  *                                  where option is stored
    467  *
    468  * @return  M4NO_ERROR              There is no error
    469  * @return  M4ERR_BAD_OPTION_ID     The option ID is not a valid one
    470  * @return  M4ERR_STATE             State automaton is not applied
    471  * @return  M4ERR_PARAMETER         The option parameter is invalid
    472  ************************************************************************
    473 */
    474 M4OSA_ERR M4READER_AMR_setOption(M4OSA_Context context, M4OSA_OptionID optionId,
    475                                  M4OSA_DataOption pValue)
    476 {
    477     M4READER_AMR_Context* pC = (M4READER_AMR_Context*)context;
    478     M4OSA_ERR err = M4NO_ERROR;
    479 
    480     /* Check function parameters */
    481     M4OSA_DEBUG_IF1((M4OSA_NULL == pC),     M4ERR_PARAMETER, "invalid context pointer");
    482     M4OSA_DEBUG_IF1((M4OSA_NULL == pValue), M4ERR_PARAMETER, "invalid value pointer");
    483 
    484     switch(optionId)
    485     {
    486     case M4READER_kOptionID_SetOsaFileReaderFctsPtr :
    487         {
    488             pC->m_pOsaFileReaderFcts = (M4OSA_FileReadPointer*)pValue;
    489         }
    490         break;
    491     default :
    492         {
    493             err = M4ERR_PARAMETER;
    494         }
    495     }
    496 
    497     return err;
    498 }
    499 
    500 /**
    501  ************************************************************************
    502  * @brief    reset the stream, that is seek it to beginning and make it ready to be read
    503  * @note    this function is to be deprecated in next versions
    504  *
    505  * @param    context:        (IN)    Context of the reader
    506  * @param    pStreamHandler    (IN)    The stream handler of the stream to reset
    507  *
    508  * @return    M4NO_ERROR                 there is no error
    509  * @return    M4ERR_PARAMETER            at least one parameter is not properly set
    510  * @return    M4ERR_ALLOC                there is no more memory available
    511  * @return    M4ERR_BAD_STREAM_ID        the streamID does not exist
    512  * @return    M4ERR_STATE    this function cannot be called now
    513  * @return    M4ERR_BAD_CONTEXT        provided context is not a valid one
    514  * @return    M4WAR_INVALID_TIME        beginning of the stream can not be reached
    515  ************************************************************************
    516 */
    517 M4OSA_ERR M4READER_AMR_reset(M4OSA_Context context, M4_StreamHandler *pStreamHandler)
    518 {
    519     M4READER_AMR_Context*   pC = (M4READER_AMR_Context*)context;
    520     M4SYS_StreamID          streamIdArray[2];
    521     M4OSA_ERR               err;
    522     M4SYS_AccessUnit*       pAu;
    523     M4OSA_Time              time64 = 0;
    524     M4AMRR_State            State;
    525 
    526     M4OSA_DEBUG_IF1((pC == 0), M4ERR_PARAMETER, "M4READER_AMR_reset: invalid context");
    527     M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
    528          "M4READER_AMR_reset: invalid pointer to M4_StreamHandler");
    529 
    530     if (pStreamHandler == (M4_StreamHandler*)pC->m_pAudioStream)
    531     {
    532         pAu = &pC->m_audioAu;
    533     }
    534     else
    535     {
    536         M4OSA_TRACE1_0("M4READER_AMR_reset: passed StreamHandler is not known\n");
    537         return M4ERR_PARAMETER;
    538     }
    539 
    540     err = M4AMRR_getState(pC->m_pCoreContext, &State, pStreamHandler->m_streamId);
    541     if (M4AMRR_kReading_nextAU == State)
    542     {
    543         err = M4AMRR_freeAU(pC->m_pCoreContext, pStreamHandler->m_streamId, pAu);
    544         if (err != M4NO_ERROR)
    545         {
    546             M4OSA_TRACE1_0("M4READER_AMR_reset: error when freeing access unit\n");
    547             return err;
    548         }
    549         pAu->dataAddress = M4OSA_NULL;
    550     }
    551 
    552     streamIdArray[0] = pStreamHandler->m_streamId;
    553     streamIdArray[1] = 0;
    554 
    555     err = M4NO_ERROR;
    556 
    557     /* for reset during playback */
    558     /* (set CTS to -20 in order the first AU CTS is 0) */
    559     pAu->CTS = -20;
    560     pAu->DTS = -20;
    561 
    562     err = M4AMRR_seek(pC->m_pCoreContext, streamIdArray, time64, M4SYS_kBeginning, &time64);
    563     if (err != M4NO_ERROR)
    564     {
    565         M4OSA_TRACE1_0("M4READER_AMR_reset: error when calling M4AMRR_seek()\n");
    566         return err;
    567     }
    568 
    569     return err;
    570 }
    571 
    572 /**
    573  ************************************************************************
    574  * @brief    jump into the stream at the specified time
    575  * @note
    576  * @param    context:        (IN)     Context of the reader
    577  * @param    pStreamHandler    (IN)     the stream description of the stream to make jump
    578  * @param    pTime            (IN/OUT) IN:  the time to jump to (in ms)
    579  *                                     OUT: the time to which the stream really jumped
    580  * @return    M4NO_ERROR                 there is no error
    581  * @return    M4ERR_BAD_CONTEXT        provided context is not a valid one
    582  * @return    M4ERR_PARAMETER            at least one parameter is not properly set
    583  * @return    M4ERR_ALLOC                there is no more memory available
    584  * @return    M4WAR_INVALID_TIME        the time can not be reached
    585  ************************************************************************
    586 */
    587 M4OSA_ERR M4READER_AMR_jump(M4OSA_Context context, M4_StreamHandler *pStreamHandler,
    588                              M4OSA_Int32* pTime)
    589 {
    590     M4READER_AMR_Context*   pC = (M4READER_AMR_Context*)context;
    591     M4SYS_StreamID          streamIdArray[2];
    592     M4OSA_ERR               err;
    593     M4SYS_AccessUnit*       pAu;
    594     M4OSA_Time              time64 = (M4OSA_Time)*pTime;
    595     M4AMRR_State            State;
    596 
    597     M4OSA_DEBUG_IF1((pC == 0), M4ERR_PARAMETER, "M4READER_AMR_reset: invalid context");
    598     M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
    599          "M4READER_AMR_reset: invalid pointer to M4_StreamHandler");
    600     M4OSA_DEBUG_IF1((pTime == 0), M4ERR_PARAMETER, "M4READER_3GP_jump: invalid time pointer");
    601 
    602     if (pStreamHandler == (M4_StreamHandler*)pC->m_pAudioStream)
    603     {
    604         pAu = &pC->m_audioAu;
    605     }
    606     else
    607     {
    608         M4OSA_TRACE1_0("M4READER_AMR_jump: passed StreamHandler is not known\n");
    609         return M4ERR_PARAMETER;
    610     }
    611 
    612     err = M4AMRR_getState(pC->m_pCoreContext, &State, pStreamHandler->m_streamId);
    613     if (M4AMRR_kReading_nextAU == State)
    614     {
    615         err = M4AMRR_freeAU(pC->m_pCoreContext, pStreamHandler->m_streamId, pAu);
    616         if (err != M4NO_ERROR)
    617         {
    618             M4OSA_TRACE1_0("M4READER_AMR_jump: error when freeing access unit\n");
    619             return err;
    620         }
    621         pAu->dataAddress = M4OSA_NULL;
    622     }
    623 
    624     streamIdArray[0] = pStreamHandler->m_streamId;
    625     streamIdArray[1] = 0;
    626 
    627     pAu->CTS = time64;
    628     pAu->DTS = time64;
    629     err = M4AMRR_seek(pC->m_pCoreContext, streamIdArray, time64, M4SYS_kNoRAPprevious, &time64);
    630     if (err != M4NO_ERROR)
    631     {
    632         M4OSA_TRACE1_0("M4READER_AMR_jump: error when calling M4AMRR_seek()\n");
    633         return err;
    634     }
    635 
    636     *pTime = (M4OSA_Int32)time64;
    637 
    638     return err;
    639 }
    640 
    641 /**
    642  ************************************************************************
    643  * @brief   Gets an access unit (AU) from the stream handler source.
    644  * @note    An AU is the smallest possible amount of data to be decoded by a decoder (audio/video).
    645  *          In the current version, we need to translate M4OSA_AccessUnit to M4_AccessUnit
    646  *
    647  * @param    context:        (IN)        Context of the reader
    648  * @param    pStreamHandler  (IN)        The stream handler of the stream to make jump
    649  * @param    pAccessUnit     (IN/OUT)    Pointer to an access unit to fill with read data (the au
    650                                          structure is allocated by the user, and must be
    651                                          initialized by calling M4READER_fillAuStruct_fct after
    652                                          creation)
    653  * @return    M4NO_ERROR              there is no error
    654  * @return    M4ERR_BAD_CONTEXT       provided context is not a valid one
    655  * @return    M4ERR_PARAMETER         at least one parameter is not properly set
    656  * @return    M4ERR_ALLOC             memory allocation failed
    657  * @return    M4ERR_BAD_STREAM_ID     at least one of the stream Id. does not exist.
    658  * @return    M4WAR_NO_MORE_AU        there are no more access unit in the stream (end of stream)
    659  ************************************************************************
    660 */
    661 M4OSA_ERR M4READER_AMR_getNextAu(M4OSA_Context context, M4_StreamHandler *pStreamHandler,
    662                                 M4_AccessUnit *pAccessUnit)
    663 {
    664     M4READER_AMR_Context*   pC = (M4READER_AMR_Context*)context;
    665     M4OSA_ERR               err = M4NO_ERROR;
    666     M4SYS_AccessUnit*       pAu;
    667     M4_MediaTime            timeScale;
    668     M4AMRR_State            State;
    669 
    670     M4OSA_DEBUG_IF1((pC == 0),             M4ERR_PARAMETER,
    671          "M4READER_AMR_getNextAu: invalid context");
    672     M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
    673          "M4READER_AMR_getNextAu: invalid pointer to M4_StreamHandler");
    674     M4OSA_DEBUG_IF1((pAccessUnit == 0),    M4ERR_PARAMETER,
    675          "M4READER_AMR_getNextAu: invalid pointer to M4_AccessUnit");
    676 
    677     /* keep trace of the allocated buffers in AU to be able to free them at destroy()
    678        but be aware that system is risky and would need upgrade if more than
    679        one video and one audio AU is needed */
    680     if (pStreamHandler == (M4_StreamHandler*)pC->m_pAudioStream)
    681     {
    682         pAu = &pC->m_audioAu;
    683     }
    684     else
    685     {
    686         M4OSA_TRACE1_0("M4READER_AMR_getNextAu: passed StreamHandler is not known\n");
    687         return M4ERR_PARAMETER;
    688     }
    689 
    690     err = M4AMRR_getState(pC->m_pCoreContext, &State, pStreamHandler->m_streamId);
    691     if (M4AMRR_kReading_nextAU == State)
    692     {
    693         err = M4AMRR_freeAU(pC->m_pCoreContext, pStreamHandler->m_streamId, pAu);
    694         if (err != M4NO_ERROR)
    695         {
    696             M4OSA_TRACE1_0("M4READER_AVI_getNextAu: error when freeing access unit\n");
    697             return err;
    698         }
    699         pAu->dataAddress = M4OSA_NULL;
    700     }
    701 
    702     pAu->nbFrag = 0;
    703     err = M4AMRR_nextAU(pC->m_pCoreContext, pStreamHandler->m_streamId, pAu);
    704 
    705     if (err == M4NO_ERROR)
    706     {
    707         timeScale = (M4OSA_Float)(M4OSA_Int32)(pStreamHandler->m_pUserData)/1000;
    708         pAccessUnit->m_dataAddress = (M4OSA_MemAddr8)pAu->dataAddress;
    709         pAccessUnit->m_size = pAu->size;
    710         pAccessUnit->m_CTS  = (M4_MediaTime)pAu->CTS/*/timeScale*/;
    711         pAccessUnit->m_DTS  = (M4_MediaTime)pAu->DTS/*/timeScale*/;
    712         pAccessUnit->m_attribute = pAu->attribute;
    713     }
    714     else
    715     {
    716         pAccessUnit->m_size=0;
    717     }
    718 
    719     return err;
    720 }
    721 
    722 /**
    723 *************************************************************************
    724 * @brief Retrieves the generic interfaces implemented by the reader
    725 *
    726 * @param pMediaType          : Pointer on a M4READER_MediaType (allocated by the caller)
    727 *                              that will be filled with the media type supported by this reader
    728 * @param pRdrGlobalInterface : Address of a pointer that will be set to the global interface implemented
    729 *                              by this reader. The interface is a structure allocated by the function and must
    730 *                              be un-allocated by the caller.
    731 * @param pRdrDataInterface   : Address of a pointer that will be set to the data interface implemented
    732 *                              by this reader. The interface is a structure allocated by the function and must
    733 *                              be un-allocated by the caller.
    734 *
    735 * @returns : M4NO_ERROR     if OK
    736 *            ERR_ALLOC      if an allocation failed
    737 *            ERR_PARAMETER  at least one parameter is not properly set (in DEBUG only)
    738 *************************************************************************
    739 */
    740 M4OSA_ERR   M4READER_AMR_getInterfaces(M4READER_MediaType *pMediaType,
    741                                          M4READER_GlobalInterface **pRdrGlobalInterface,
    742                                          M4READER_DataInterface **pRdrDataInterface)
    743 {
    744     M4OSA_DEBUG_IF1((pMediaType == 0),          M4ERR_PARAMETER,
    745          "M4READER_AMR_getInterfaces: invalid pointer to MediaType");
    746     M4OSA_DEBUG_IF1((pRdrGlobalInterface == 0), M4ERR_PARAMETER,
    747          "M4READER_AMR_getInterfaces: invalid pointer to M4READER_GlobalInterface");
    748     M4OSA_DEBUG_IF1((pRdrDataInterface == 0),   M4ERR_PARAMETER,
    749          "M4READER_AMR_getInterfaces: invalid pointer to M4READER_DataInterface");
    750 
    751     *pRdrGlobalInterface =
    752          (M4READER_GlobalInterface*)M4OSA_32bitAlignedMalloc( sizeof(M4READER_GlobalInterface),
    753              M4READER_AMR, (M4OSA_Char *)"M4READER_GlobalInterface" );
    754     if (M4OSA_NULL == *pRdrGlobalInterface)
    755     {
    756         *pRdrDataInterface = M4OSA_NULL;
    757         return M4ERR_ALLOC;
    758     }
    759     *pRdrDataInterface = (M4READER_DataInterface*)M4OSA_32bitAlignedMalloc( sizeof(M4READER_DataInterface),
    760          M4READER_AMR, (M4OSA_Char *)"M4READER_DataInterface");
    761     if (M4OSA_NULL == *pRdrDataInterface)
    762     {
    763         free(*pRdrGlobalInterface);
    764         *pRdrGlobalInterface = M4OSA_NULL;
    765         return M4ERR_ALLOC;
    766     }
    767 
    768     *pMediaType = M4READER_kMediaTypeAMR;
    769 
    770     (*pRdrGlobalInterface)->m_pFctCreate           = M4READER_AMR_create;
    771     (*pRdrGlobalInterface)->m_pFctDestroy          = M4READER_AMR_destroy;
    772     (*pRdrGlobalInterface)->m_pFctOpen             = M4READER_AMR_open;
    773     (*pRdrGlobalInterface)->m_pFctClose            = M4READER_AMR_close;
    774     (*pRdrGlobalInterface)->m_pFctGetOption        = M4READER_AMR_getOption;
    775     (*pRdrGlobalInterface)->m_pFctSetOption        = M4READER_AMR_setOption;
    776     (*pRdrGlobalInterface)->m_pFctGetNextStream    = M4READER_AMR_getNextStream;
    777     (*pRdrGlobalInterface)->m_pFctFillAuStruct     = M4READER_AMR_fillAuStruct;
    778     (*pRdrGlobalInterface)->m_pFctStart            = M4OSA_NULL;
    779     (*pRdrGlobalInterface)->m_pFctStop             = M4OSA_NULL;
    780     (*pRdrGlobalInterface)->m_pFctJump             = M4READER_AMR_jump;
    781     (*pRdrGlobalInterface)->m_pFctReset            = M4READER_AMR_reset;
    782     (*pRdrGlobalInterface)->m_pFctGetPrevRapTime   = M4OSA_NULL; /*all AUs are RAP*/
    783 
    784     (*pRdrDataInterface)->m_pFctGetNextAu          = M4READER_AMR_getNextAu;
    785 
    786     (*pRdrDataInterface)->m_readerContext = M4OSA_NULL;
    787 
    788     return M4NO_ERROR;
    789 }
    790 
    791