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  * @file   M4READER_Wav.c
     19  * @brief  Generic encapsulation of the core pcm reader
     20  * @note   This file implements the generic M4READER interface
     21  *         on top of the PCM reader
     22  ************************************************************************
     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 #include "M4TOOL_VersionInfo.h"
     31 #include "M4PCMR_CoreReader.h"
     32 #include "M4READER_Pcm.h"
     33 /**
     34  ************************************************************************
     35  * structure    M4READER_WAV_Context
     36  * @brief       This structure defines the internal context of a wav reader instance
     37  * @note        The context is allocated and de-allocated by the reader
     38  ************************************************************************
     39  */
     40 typedef struct _M4READER_PCM_Context
     41 {
     42     M4OSA_Context           m_coreContext;        /**< core wav reader context */
     43     M4_StreamHandler*       m_pAudioStream;       /**< pointer on the audio stream description
     44                                                         returned by the core */
     45     M4SYS_AccessUnit        m_audioAu;            /**< audio access unit to be filled by the core */
     46     M4OSA_FileReadPointer*  m_pOsaFileReaderFcts; /**< OSAL file read functions */
     47 
     48 } M4READER_PCM_Context;
     49 
     50 
     51 /**
     52  ************************************************************************
     53  * @brief   Creates a wav reader instance
     54  * @note    allocates the context
     55  * @param   pContext:            (OUT)  Pointer to a wav reader context
     56  * @return  M4NO_ERROR:                 there is no error
     57  * @return  M4ERR_ALLOC:                a memory allocation has failed
     58  * @return  M4ERR_PARAMETER:            at least one parameter is not properly set (in DEBUG only)
     59  ************************************************************************
     60  */
     61 M4OSA_ERR M4READER_PCM_create(M4OSA_Context* pContext)
     62 {
     63     M4READER_PCM_Context*   pReaderContext;
     64 
     65     M4OSA_DEBUG_IF1((pContext == 0),       M4ERR_PARAMETER,
     66          "M4READER_PCM_create: invalid context pointer");
     67 
     68     pReaderContext = (M4READER_PCM_Context*)M4OSA_32bitAlignedMalloc(sizeof(M4READER_PCM_Context),
     69          M4READER_WAV, (M4OSA_Char *)"M4READER_PCM_Context");
     70     if (pReaderContext == M4OSA_NULL)
     71     {
     72         return M4ERR_ALLOC;
     73     }
     74 
     75     pReaderContext->m_coreContext         = M4OSA_NULL;
     76     pReaderContext->m_pAudioStream        = M4OSA_NULL;
     77     pReaderContext->m_audioAu.dataAddress = M4OSA_NULL;
     78     pReaderContext->m_pOsaFileReaderFcts  = M4OSA_NULL;
     79 
     80     *pContext = pReaderContext;
     81 
     82     return M4NO_ERROR;
     83 }
     84 
     85 /**
     86  ************************************************************************
     87  * @brief   Destroy the instance of the reader
     88  * @note    the context is un-allocated
     89  * @param   context:         (IN) context of the network reader
     90  * @return  M4NO_ERROR:           there is no error
     91  * @return  M4ERR_PARAMETER:      at least one parameter is not properly set (in DEBUG only)
     92  ************************************************************************
     93  */
     94 M4OSA_ERR M4READER_PCM_destroy(M4OSA_Context context)
     95 {
     96     M4READER_PCM_Context* pC = (M4READER_PCM_Context*)context;
     97 
     98     /* Check function parameters */
     99     M4OSA_DEBUG_IF1((M4OSA_NULL == pC), M4ERR_PARAMETER,
    100          "M4READER_PCM_destroy: invalid context pointer");
    101 
    102     free(pC);
    103 
    104     return M4NO_ERROR;
    105 }
    106 
    107 /**
    108  ************************************************************************
    109  * @brief   Initializes the reader instance
    110  * @param   context:           (IN)    context of the network reader
    111  * @param   pFileDescriptor:   (IN)    Pointer to proprietary data identifying the media to open
    112  * @return  M4NO_ERROR:                there is no error
    113  * @return  M4ERR_PARAMETER:           at least one parameter is not properly set (in DEBUG only)
    114  ************************************************************************
    115  */
    116 M4OSA_ERR M4READER_PCM_open(M4OSA_Context context, M4OSA_Void* pFileDescriptor)
    117 {
    118     M4READER_PCM_Context*   pC = (M4READER_PCM_Context*)context;
    119     M4OSA_ERR               err;
    120 
    121     /* Check function parameters */
    122     M4OSA_DEBUG_IF1((M4OSA_NULL == pC), M4ERR_PARAMETER,
    123          "M4READER_PCM_open: invalid context pointer");
    124     M4OSA_DEBUG_IF1((M4OSA_NULL == pFileDescriptor),   M4ERR_PARAMETER,
    125          "M4READER_PCM_open: invalid pointer pFileDescriptor");
    126 
    127     err = M4PCMR_openRead(&(pC->m_coreContext), (M4OSA_Char*)pFileDescriptor,
    128          pC->m_pOsaFileReaderFcts);
    129 
    130     return err;
    131 }
    132 
    133 /**
    134  ************************************************************************
    135  * @brief     close the reader
    136  * @note
    137  * @param     context:        (IN)    Context of the reader
    138  * @return    M4NO_ERROR                 there is no error
    139  * @return    M4ERR_PARAMETER            the context is NULL
    140  * @return    M4ERR_BAD_CONTEXT        provided context is not a valid one
    141  ************************************************************************
    142  */
    143 M4OSA_ERR M4READER_PCM_close(M4OSA_Context context)
    144 {
    145     M4READER_PCM_Context*   pC = (M4READER_PCM_Context*)context;
    146     M4OSA_ERR               err;
    147 
    148     /* Check function parameters */
    149     M4OSA_DEBUG_IF1((M4OSA_NULL == pC), M4ERR_PARAMETER,
    150          "M4READER_PCM_close: invalid context pointer");
    151 
    152     /* Free audio AU and audio stream */
    153     if (M4OSA_NULL != pC->m_pAudioStream)
    154     {
    155         if (M4OSA_NULL != pC->m_audioAu.dataAddress)
    156         {
    157             err = M4PCMR_freeAU(pC->m_coreContext, pC->m_pAudioStream->m_streamId,
    158                  &pC->m_audioAu);
    159             if (err != M4NO_ERROR)
    160             {
    161                 M4OSA_TRACE1_0("M4READER_PCM_close: Error when freeing audio access unit");
    162                 return err;
    163             }
    164         }
    165         free(pC->m_pAudioStream);
    166         pC->m_pAudioStream = M4OSA_NULL;
    167     }
    168 
    169 
    170     if (M4OSA_NULL != pC->m_coreContext)
    171     {
    172         /* Close tha PCM file */
    173        err = M4PCMR_closeRead(pC->m_coreContext);
    174        pC->m_coreContext = M4OSA_NULL;
    175     }
    176 
    177 
    178     return err;
    179 }
    180 
    181 /**
    182  ************************************************************************
    183  * @brief   set en option value of the reader
    184  * @note    this function follows the set/get option mechanism described in OSAL 3.0
    185  *          it allows the caller to set a property value:
    186  * @param    context:        (IN)    Context of the reader
    187  * @param    optionId:       (IN)    indicates the option to set
    188  * @param    pValue:         (IN)    pointer to structure or value (allocated by user)
    189  *                                    where option is stored
    190  *
    191  * @return    M4NO_ERROR             there is no error
    192  * @return    M4ERR_BAD_CONTEXT      provided context is not a valid one
    193  * @return    M4ERR_PARAMETER        at least one parameter is not properly set
    194  * @return    M4ERR_BAD_OPTION_ID    when the option ID is not a valid one
    195  ************************************************************************
    196  */
    197 M4OSA_ERR M4READER_PCM_setOption(M4OSA_Context context, M4OSA_OptionID optionId, void* pValue)
    198 {
    199     M4READER_PCM_Context* pC = (M4READER_PCM_Context*)context;
    200     M4OSA_ERR err = M4NO_ERROR;
    201 
    202     /* Check function parameters */
    203     M4OSA_DEBUG_IF1((M4OSA_NULL == pC),     M4ERR_PARAMETER,
    204          "M4READER_PCM_setOption: invalid context pointer");
    205     M4OSA_DEBUG_IF1((M4OSA_NULL == pValue), M4ERR_PARAMETER,
    206          "M4READER_PCM_setOption: invalid value pointer");
    207 
    208     switch(optionId)
    209     {
    210     case M4READER_kOptionID_SetOsaFileReaderFctsPtr :
    211         {
    212             pC->m_pOsaFileReaderFcts = (M4OSA_FileReadPointer*)pValue;
    213         }
    214         break;
    215     default :
    216         {
    217             err = M4ERR_PARAMETER;
    218         }
    219     }
    220 
    221     return err;
    222 }
    223 
    224 /**
    225  ************************************************************************
    226  * @brief   Retrieves the an option value from the reader, given an option ID.
    227  * @note    this function follows the set/get option mechanism described in OSAL 3.0
    228  *          it allows the caller to retrieve a property value:
    229  *
    230  * @param   context:  (IN) context of the network reader
    231  * @param   optionId: (IN) option identificator whose option value is to be retrieved.
    232  * @param   pValue:  (OUT) option value retrieved.
    233  *
    234  * @return  M4NO_ERROR:          there is no error
    235  * @return  M4ERR_PARAMETER:     at least one parameter is not properly set (in DEBUG only)
    236  * @return  M4ERR_BAD_OPTION_ID: the required option identificator is unknown
    237  ************************************************************************
    238  */
    239 M4OSA_ERR M4READER_PCM_getOption(M4OSA_Context context, M4OSA_OptionID optionId, void* pValue)
    240 {
    241     M4READER_PCM_Context*   pContext = (M4READER_PCM_Context*)context;
    242     M4OSA_ERR               err      = M4NO_ERROR;
    243 
    244     /* no check of context at this level because some option does not need it */
    245     M4OSA_DEBUG_IF1((pValue == 0), M4ERR_PARAMETER,
    246          "M4READER_PCM_getOption: invalid pointer on value");
    247 
    248     switch (optionId)
    249     {
    250     case M4READER_kOptionID_Duration:
    251         *((M4OSA_UInt32*)pValue) = pContext->m_pAudioStream->m_duration;
    252         break;
    253 
    254     case M4READER_kOptionID_Version:
    255         err = M4PCMR_getVersion((M4_VersionInfo*)pValue);
    256         break;
    257 
    258     case M4READER_kOptionID_Copyright:
    259         return M4ERR_NOT_IMPLEMENTED;
    260         break;
    261 
    262     case M4READER_kOptionID_Bitrate:
    263         {
    264             M4OSA_UInt32* pBitrate = (M4OSA_UInt32*)pValue;
    265             if (M4OSA_NULL != pContext->m_pAudioStream)
    266             {
    267                 *pBitrate = pContext->m_pAudioStream->m_averageBitRate;
    268             }
    269             else
    270             {
    271                 pBitrate = 0;
    272                 err = M4ERR_PARAMETER;
    273             }
    274         }
    275         break;
    276 
    277     default:
    278         err = M4ERR_BAD_OPTION_ID;
    279         M4OSA_TRACE1_0("M4READER_PCM_getOption: unsupported optionId");
    280         break;
    281     }
    282 
    283     return err;
    284 }
    285 
    286 /**
    287  ************************************************************************
    288  * @brief   Get the next stream found in the media
    289  * @note
    290  *
    291  * @param   context:        (IN)  context of the network reader
    292  * @param   pMediaFamily:   (OUT) pointer to a user allocated M4READER_MediaFamily that will
    293  *                                be filled
    294  * @param   pStreamHandler: (OUT) pointer to a stream handler that will be allocated and filled
    295  *                                with the found stream description
    296  *
    297  * @return  M4NO_ERROR:       there is no error.
    298  * @return  M4ERR_PARAMETER:  at least one parameter is not properly set (in DEBUG only)
    299  * @return  M4WAR_NO_MORE_STREAM    no more available stream in the media (all streams found)
    300  ************************************************************************
    301  */
    302 M4OSA_ERR M4READER_PCM_getNextStream(M4OSA_Context context, M4READER_MediaFamily *pMediaFamily,
    303                                      M4_StreamHandler **pStreamHandler)
    304 {
    305     M4READER_PCM_Context*   pC=(M4READER_PCM_Context*)context;
    306     M4OSA_ERR               err;
    307 /*    M4_StreamHandler*       pStreamHandler = M4OSA_NULL;*/
    308     M4SYS_StreamDescription streamDesc;
    309     M4_AudioStreamHandler*  pAudioStreamHandler;
    310     M4OSA_Double            fDuration;
    311     M4SYS_StreamID          streamIdArray[2];
    312     M4PCMC_DecoderSpecificInfo* pDsi;
    313 
    314     M4OSA_DEBUG_IF1((pC == 0),             M4ERR_PARAMETER,
    315          "M4READER_PCM_getNextStream: invalid context");
    316     M4OSA_DEBUG_IF1((pMediaFamily == 0),   M4ERR_PARAMETER,
    317          "M4READER_PCM_getNextStream: invalid pointer to MediaFamily");
    318     M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
    319          "M4READER_PCM_getNextStream: invalid pointer to StreamHandler");
    320 
    321     err = M4PCMR_getNextStream( pC->m_coreContext, &streamDesc);
    322     if (err == M4WAR_NO_MORE_STREAM)
    323     {
    324         streamIdArray[0] = 0;
    325         streamIdArray[1] = 0;
    326         err = M4PCMR_startReading(pC->m_coreContext, streamIdArray); /*to put in open function*/
    327 
    328         return M4WAR_NO_MORE_STREAM;
    329     }
    330     else if (M4NO_ERROR != err)
    331     {
    332         return err; /*also return M4WAR_NO_MORE_STREAM*/
    333     }
    334 
    335     switch (streamDesc.streamType)
    336     {
    337         case M4SYS_kAudioUnknown:
    338         case M4SYS_kPCM_16bitsS:
    339         case M4SYS_kPCM_16bitsU:
    340         case M4SYS_kPCM_8bitsU:
    341             *pMediaFamily = M4READER_kMediaFamilyAudio;
    342             M4OSA_TRACE2_0("M4READER_PCM_getNextStream: found audio stream");
    343             break;
    344         default:
    345             *pMediaFamily = M4READER_kMediaFamilyUnknown;
    346             M4OSA_TRACE2_0("M4READER_PCM_getNextStream: found UNKNOWN stream");
    347             return M4NO_ERROR;
    348     }
    349 
    350     pAudioStreamHandler = (M4_AudioStreamHandler*)M4OSA_32bitAlignedMalloc(sizeof(M4_AudioStreamHandler),
    351          M4READER_WAV, (M4OSA_Char *)"M4_AudioStreamHandler");
    352     if (pAudioStreamHandler == M4OSA_NULL)
    353     {
    354         return M4ERR_ALLOC;
    355     }
    356     pAudioStreamHandler->m_structSize = sizeof(M4_AudioStreamHandler);
    357     pC->m_pAudioStream = (M4_StreamHandler*)(pAudioStreamHandler);
    358 
    359     pDsi = (M4PCMC_DecoderSpecificInfo*)(streamDesc.decoderSpecificInfo);
    360     M4OSA_DEBUG_IF1((pDsi == 0), M4ERR_PARAMETER,
    361          "M4READER_PCM_getNextStream: invalid decoder specific info in stream");
    362 
    363     pAudioStreamHandler->m_samplingFrequency = pDsi->SampleFrequency;
    364     pAudioStreamHandler->m_byteSampleSize    = (M4OSA_UInt32)(pDsi->BitsPerSample/8);
    365     /* m_byteFrameLength is badly named: it is not in bytes but in samples number */
    366     if(pAudioStreamHandler->m_samplingFrequency == 8000)
    367     {
    368         /* AMR case */
    369         pAudioStreamHandler->m_byteFrameLength   =
    370              (((streamDesc.averageBitrate/8)/50)/pDsi->nbChannels)\
    371                 /pAudioStreamHandler->m_byteSampleSize;/*/50 to get around 20 ms of audio*/
    372     }
    373     else
    374     {
    375         /* AAC Case */
    376         pAudioStreamHandler->m_byteFrameLength =
    377              (M4OSA_UInt32)(((streamDesc.averageBitrate/8)/15.625)/pDsi->nbChannels)\
    378                 /pAudioStreamHandler->m_byteSampleSize;
    379     }
    380 
    381     pAudioStreamHandler->m_nbChannels        = pDsi->nbChannels;
    382 
    383     M4OSA_TIME_TO_MS( fDuration, streamDesc.duration, streamDesc.timeScale);
    384     pC->m_pAudioStream->m_duration                = (M4OSA_Int32)fDuration;
    385     pC->m_pAudioStream->m_pDecoderSpecificInfo    = (M4OSA_UInt8*)(streamDesc.decoderSpecificInfo);
    386     pC->m_pAudioStream->m_decoderSpecificInfoSize = streamDesc.decoderSpecificInfoSize;
    387     pC->m_pAudioStream->m_streamId                = streamDesc.streamID;
    388     pC->m_pAudioStream->m_pUserData               =
    389         (void*)streamDesc.timeScale; /*trick to change*/
    390     pC->m_pAudioStream->m_averageBitRate          = streamDesc.averageBitrate;
    391     pC->m_pAudioStream->m_maxAUSize               =
    392          pAudioStreamHandler->m_byteFrameLength*pAudioStreamHandler->m_byteSampleSize\
    393             *pAudioStreamHandler->m_nbChannels;
    394     pC->m_pAudioStream->m_streamType              = M4DA_StreamTypeAudioPcm;
    395 
    396     *pStreamHandler = pC->m_pAudioStream;
    397     return err;
    398 }
    399 
    400 /**
    401  ************************************************************************
    402  * @brief   fill the access unit structure with initialization values
    403  * @note
    404  *
    405  * @param   context:        (IN) context of the network reader
    406  * @param   pStreamHandler: (IN) pointer to the stream handler to which the access unit will
    407  *                                 be associated
    408  * @param   pAccessUnit:    (IN) pointer to the access unit(allocated by the caller) to initialize
    409  * @return  M4NO_ERROR:       there is no error.
    410  * @return  M4ERR_PARAMETER:  at least one parameter is not properly set (in DEBUG only)
    411  ************************************************************************
    412  */
    413 M4OSA_ERR M4READER_PCM_fillAuStruct(M4OSA_Context context, M4_StreamHandler *pStreamHandler,
    414                                      M4_AccessUnit *pAccessUnit)
    415 {
    416     M4READER_PCM_Context*   pC = (M4READER_PCM_Context*)context;
    417     M4SYS_AccessUnit*       pAu;
    418 
    419     M4OSA_DEBUG_IF1((pC == 0),             M4ERR_PARAMETER,
    420          "M4READER_PCM_fillAuStruct: invalid context");
    421     M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
    422          "M4READER_PCM_fillAuStruct: invalid pointer to M4_StreamHandler");
    423     M4OSA_DEBUG_IF1((pAccessUnit == 0),    M4ERR_PARAMETER,
    424          "M4READER_PCM_fillAuStruct: invalid pointer to M4_AccessUnit");
    425 
    426     if (pStreamHandler == (M4_StreamHandler*)pC->m_pAudioStream)
    427     {
    428         pAu = &pC->m_audioAu;
    429     }
    430     else
    431     {
    432         M4OSA_TRACE1_0("M4READER_PCM_fillAuStruct: passed StreamHandler is not known");
    433         return M4ERR_PARAMETER;
    434     }
    435 
    436     pAu->dataAddress = M4OSA_NULL;
    437     pAu->size        = 0;
    438     pAu->CTS         = 0;
    439     pAu->DTS         = 0;
    440     pAu->attribute   = 0;
    441     pAu->nbFrag      = 0;
    442 
    443     pAccessUnit->m_size         = 0;
    444     pAccessUnit->m_CTS          = 0;
    445     pAccessUnit->m_DTS          = 0;
    446     pAccessUnit->m_attribute    = 0;
    447     pAccessUnit->m_dataAddress  = M4OSA_NULL;/*pBuffer;*/
    448     pAccessUnit->m_maxsize      = pStreamHandler->m_maxAUSize;
    449     pAccessUnit->m_streamID     = pStreamHandler->m_streamId;
    450     pAccessUnit->m_structSize   = sizeof(M4_AccessUnit);
    451 
    452     return M4NO_ERROR;
    453 }
    454 
    455 /**
    456  ************************************************************************
    457  * @brief   reset the stream, that is: seek it to beginning and make it ready to be read
    458  * @note
    459  * @param   context:        (IN) context of the network reader
    460  * @param   pStreamHandler: (IN) The stream handler of the stream to reset
    461  * @return  M4NO_ERROR: there is no error.
    462  ************************************************************************
    463  */
    464 M4OSA_ERR M4READER_PCM_reset(M4OSA_Context context, M4_StreamHandler *pStreamHandler)
    465 {
    466     M4READER_PCM_Context*   pC = (M4READER_PCM_Context*)context;
    467     M4SYS_StreamID          streamIdArray[2];
    468     M4OSA_ERR               err;
    469     M4SYS_AccessUnit*       pAu;
    470     M4OSA_Time                time64 = 0;
    471 
    472     M4OSA_DEBUG_IF1((pC == 0), M4ERR_PARAMETER, "M4READER_PCM_reset: invalid context");
    473     M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
    474          "M4READER_PCM_reset: invalid pointer to M4_StreamHandler");
    475 
    476     if (pStreamHandler == (M4_StreamHandler*)pC->m_pAudioStream)
    477     {
    478         pAu = &pC->m_audioAu;
    479     }
    480     else
    481     {
    482         M4OSA_TRACE1_0("M4READER_PCM_reset: passed StreamHandler is not known");
    483         return M4ERR_PARAMETER;
    484     }
    485 
    486     if (pAu->dataAddress != M4OSA_NULL)
    487     {
    488         err = M4PCMR_freeAU(pC->m_coreContext, pStreamHandler->m_streamId, pAu);
    489         if (err != M4NO_ERROR)
    490         {
    491             M4OSA_TRACE1_0("M4READER_PCM_reset: error when freeing access unit");
    492             return err;
    493         }
    494         pAu->dataAddress = M4OSA_NULL;
    495     }
    496 
    497     streamIdArray[0] = pStreamHandler->m_streamId;
    498     streamIdArray[1] = 0;
    499 
    500     pAu->CTS = 0;
    501     pAu->DTS = 0;
    502 
    503     /* This call is needed only when replay during playback */
    504     err = M4PCMR_seek(pC->m_coreContext, streamIdArray, time64, M4SYS_kBeginning, &time64);
    505 
    506     return err;
    507 }
    508 
    509 /**
    510  ************************************************************************
    511  * @brief   Get the next access unit of the specified stream
    512  * @note
    513  * @param   context:        (IN)        Context of the reader
    514  * @param   pStreamHandler  (IN)        The stream handler of the stream to make jump
    515  * @param   pAccessUnit     (IN/OUT)    Pointer to an access unit to fill with read data
    516  *                                      (the au structure is allocated by the user, and must be
    517  *                                        initialized
    518  *                                      by calling M4READER_fillAuStruct_fct after creation)
    519  * @return  M4NO_ERROR                  there is no error
    520  * @return  M4ERR_BAD_CONTEXT           provided context is not a valid one
    521  * @return  M4ERR_PARAMETER             at least one parameter is not properly set
    522  * @returns M4ERR_ALLOC                 memory allocation failed
    523  * @returns M4ERR_BAD_STREAM_ID         at least one of the stream Id. does not exist.
    524  * @returns M4WAR_NO_DATA_YET           there is no enough data on the stream for new access unit
    525  * @returns M4WAR_NO_MORE_AU            there are no more access unit in the stream (end of stream)
    526  ************************************************************************
    527  */
    528 M4OSA_ERR M4READER_PCM_getNextAu(M4OSA_Context context, M4_StreamHandler *pStreamHandler,
    529                                  M4_AccessUnit *pAccessUnit)
    530 {
    531     M4READER_PCM_Context*   pC = (M4READER_PCM_Context*)context;
    532     M4OSA_ERR               err = M4NO_ERROR;
    533     M4SYS_AccessUnit*       pAu;
    534 
    535     M4OSA_DEBUG_IF1((pC == 0),             M4ERR_PARAMETER,
    536          "M4READER_PCM_getNextAu: invalid context");
    537     M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
    538          "M4READER_PCM_getNextAu: invalid pointer to M4_StreamHandler");
    539     M4OSA_DEBUG_IF1((pAccessUnit == 0),    M4ERR_PARAMETER,
    540          "M4READER_PCM_getNextAu: invalid pointer to M4_AccessUnit");
    541 
    542     /* keep trace of the allocated buffers in AU to be able to free them at destroy()
    543        but be aware that system is risky and would need upgrade if more than
    544        one video and one audio AU is needed */
    545     if (pStreamHandler == (M4_StreamHandler*)pC->m_pAudioStream)
    546     {
    547         pAu = &pC->m_audioAu;
    548     }
    549     else
    550     {
    551         M4OSA_TRACE1_0("M4READER_PCM_getNextAu: passed StreamHandler is not known");
    552         return M4ERR_PARAMETER;
    553     }
    554 
    555     if (pAu->dataAddress != M4OSA_NULL)
    556     {
    557         err = M4PCMR_freeAU(pC->m_coreContext, pStreamHandler->m_streamId, pAu);
    558         if (err != M4NO_ERROR)
    559         {
    560             M4OSA_TRACE1_0("M4READER_PCM_getNextAu: error when freeing access unit");
    561             return err;
    562         }
    563     }
    564 
    565     pAu->nbFrag = 0;
    566     err = M4PCMR_nextAU(pC->m_coreContext, pStreamHandler->m_streamId, pAu);
    567 
    568     if (err == M4NO_ERROR)
    569     {
    570         pAccessUnit->m_dataAddress = (M4OSA_MemAddr8)pAu->dataAddress;
    571         pAccessUnit->m_size = pAu->size;
    572         pAccessUnit->m_CTS  = (M4OSA_Double)pAu->CTS;
    573         pAccessUnit->m_DTS  = (M4OSA_Double)pAu->DTS;
    574         pAccessUnit->m_attribute = pAu->attribute;
    575     }
    576     else
    577     {
    578         pAccessUnit->m_size=0;
    579     }
    580 
    581     return err;
    582 }
    583 
    584 
    585 /**
    586  ************************************************************************
    587  * @brief   jump into the stream at the specified time
    588  * @note
    589  * @param   context:        (IN)     Context of the reader
    590  * @param   pStreamHandler  (IN)     the stream handler of the stream to make jump
    591  * @param   pTime           (IN/OUT) IN:  the time to jump to (in ms)
    592  *                                   OUT: the time to which the stream really jumped
    593  *                                        But in this reader, we do not modify the time
    594  * @return  M4NO_ERROR              there is no error
    595  * @return  M4ERR_BAD_CONTEXT       provided context is not a valid one
    596  * @return  M4ERR_PARAMETER         at least one parameter is not properly set
    597  * @return  M4ERR_ALLOC             there is no more memory available
    598  * @return  M4ERR_BAD_STREAM_ID     the streamID does not exist
    599  ************************************************************************
    600  */
    601 M4OSA_ERR M4READER_PCM_jump(M4OSA_Context context, M4_StreamHandler *pStreamHandler,
    602      M4OSA_Int32* pTime)
    603 {
    604     M4READER_PCM_Context*   pC = (M4READER_PCM_Context*)context;
    605     M4SYS_StreamID          streamIdArray[2];
    606     M4OSA_ERR               err;
    607     M4SYS_AccessUnit*       pAu;
    608     M4OSA_Time                time64;
    609 
    610     M4OSA_DEBUG_IF1((pC == 0), M4ERR_PARAMETER, "M4READER_PCM_jump: invalid context");
    611     M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
    612          "M4READER_PCM_jump: invalid pointer to M4_StreamHandler");
    613     M4OSA_DEBUG_IF1((pTime == 0), M4ERR_PARAMETER, "M4READER_PCM_jump: invalid time pointer");
    614 
    615     time64 = (M4OSA_Time)*pTime;
    616 
    617     if (pStreamHandler == pC->m_pAudioStream)
    618     {
    619         pAu = &pC->m_audioAu;
    620     }
    621     else
    622     {
    623         M4OSA_TRACE1_0("M4READER_PCM_jump: passed StreamHandler is not known");
    624         return M4ERR_PARAMETER;
    625     }
    626 
    627     if (pAu->dataAddress != M4OSA_NULL)
    628     {
    629         err = M4PCMR_freeAU(pC->m_coreContext, pStreamHandler->m_streamId, pAu);
    630         if (err != M4NO_ERROR)
    631         {
    632             M4OSA_TRACE1_0("M4READER_PCM_jump: Error when freeing access unit");
    633             return err;
    634         }
    635         pAu->dataAddress = M4OSA_NULL;
    636     }
    637 
    638     streamIdArray[0] = pStreamHandler->m_streamId;
    639     streamIdArray[1] = 0;
    640 
    641     pAu->CTS = time64;
    642     pAu->DTS = time64;
    643 
    644     err = M4PCMR_seek(pC->m_coreContext, streamIdArray, time64, M4SYS_kBeginning, &time64);
    645 
    646     *pTime = (M4OSA_Int32)time64;
    647 
    648     return err;
    649 }
    650 
    651 /**
    652  *************************************************************************
    653  * @brief Retrieves the generic interfaces implemented by the reader
    654  *
    655  * @param pMediaType          : Pointer on a M4READER_MediaType (allocated by the caller)
    656  *                              that will be filled with the media type supported by this reader
    657  * @param pRdrGlobalInterface : Address of a pointer that will be set to the global interface
    658  *                              implemented by this reader. The interface is a structure allocated
    659  *                              by the function and must be un-allocated by the caller.
    660  * @param pRdrDataInterface   : Address of a pointer that will be set to the data interface
    661  *                              implemented by this reader. The interface is a structure allocated
    662  *                              by the function and must be un-allocated by the caller.
    663  *
    664  * @returns : M4NO_ERROR     if OK
    665  *            ERR_ALLOC      if an allocation failed
    666  *            ERR_PARAMETER  at least one parameter is not properly set (in DEBUG only)
    667  *************************************************************************
    668  */
    669 M4OSA_ERR   M4READER_PCM_getInterfaces(M4READER_MediaType *pMediaType,
    670                                        M4READER_GlobalInterface **pRdrGlobalInterface,
    671                                        M4READER_DataInterface **pRdrDataInterface)
    672 /************************************************************************/
    673 {
    674     M4OSA_DEBUG_IF1((pMediaType == 0),          M4ERR_PARAMETER,
    675          "M4READER_PCM_getInterfaces: invalid pointer to MediaType passed");
    676     M4OSA_DEBUG_IF1((pRdrGlobalInterface == 0), M4ERR_PARAMETER,
    677          "M4READER_PCM_getInterfaces: invalid pointer to M4READER_GlobalInterface");
    678     M4OSA_DEBUG_IF1((pRdrDataInterface == 0),   M4ERR_PARAMETER,
    679          "M4READER_PCM_getInterfaces: invalid pointer to M4READER_DataInterface");
    680 
    681     *pRdrGlobalInterface =
    682          (M4READER_GlobalInterface*)M4OSA_32bitAlignedMalloc( sizeof(M4READER_GlobalInterface), M4READER_WAV,
    683              (M4OSA_Char *)"M4READER_PCM GlobalInterface");
    684     if (M4OSA_NULL == *pRdrGlobalInterface)
    685     {
    686         return M4ERR_ALLOC;
    687     }
    688     *pRdrDataInterface =
    689          (M4READER_DataInterface*)M4OSA_32bitAlignedMalloc( sizeof(M4READER_DataInterface), M4READER_WAV,
    690             (M4OSA_Char *) "M4READER_PCM DataInterface");
    691     if (M4OSA_NULL == *pRdrDataInterface)
    692     {
    693         free(*pRdrGlobalInterface);
    694         return M4ERR_ALLOC;
    695     }
    696 
    697     *pMediaType = M4READER_kMediaTypePCM;
    698 
    699     (*pRdrGlobalInterface)->m_pFctCreate           = M4READER_PCM_create;
    700     (*pRdrGlobalInterface)->m_pFctDestroy          = M4READER_PCM_destroy;
    701     (*pRdrGlobalInterface)->m_pFctOpen             = M4READER_PCM_open;
    702     (*pRdrGlobalInterface)->m_pFctClose            = M4READER_PCM_close;
    703     (*pRdrGlobalInterface)->m_pFctStart            = M4OSA_NULL;
    704     (*pRdrGlobalInterface)->m_pFctStop             = M4OSA_NULL;
    705     (*pRdrGlobalInterface)->m_pFctGetOption        = M4READER_PCM_getOption;
    706     (*pRdrGlobalInterface)->m_pFctSetOption        = M4READER_PCM_setOption;
    707     (*pRdrGlobalInterface)->m_pFctGetNextStream    = M4READER_PCM_getNextStream;
    708     (*pRdrGlobalInterface)->m_pFctFillAuStruct     = M4READER_PCM_fillAuStruct;
    709     (*pRdrGlobalInterface)->m_pFctJump             = M4READER_PCM_jump;
    710     (*pRdrGlobalInterface)->m_pFctReset            = M4READER_PCM_reset;
    711     (*pRdrGlobalInterface)->m_pFctGetPrevRapTime   = M4OSA_NULL; /*all AUs are RAP*/
    712 
    713     (*pRdrDataInterface)->m_pFctGetNextAu          = M4READER_PCM_getNextAu;
    714 
    715     (*pRdrDataInterface)->m_readerContext = M4OSA_NULL;
    716 
    717     return M4NO_ERROR;
    718 }
    719 
    720 
    721