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*/
43typedef 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*/
65M4OSA_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*/
102M4OSA_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*/
136M4OSA_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*/
164M4OSA_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*/
244M4OSA_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*/
345M4OSA_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*/
407M4OSA_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*/
474M4OSA_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*/
517M4OSA_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*/
587M4OSA_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*/
661M4OSA_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*/
740M4OSA_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