• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
M4READER_PCM_create(M4OSA_Context * pContext)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  */
M4READER_PCM_destroy(M4OSA_Context context)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  */
M4READER_PCM_open(M4OSA_Context context,M4OSA_Void * pFileDescriptor)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  */
M4READER_PCM_close(M4OSA_Context context)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  */
M4READER_PCM_setOption(M4OSA_Context context,M4OSA_OptionID optionId,void * pValue)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  */
M4READER_PCM_getOption(M4OSA_Context context,M4OSA_OptionID optionId,void * pValue)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  */
M4READER_PCM_getNextStream(M4OSA_Context context,M4READER_MediaFamily * pMediaFamily,M4_StreamHandler ** pStreamHandler)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  */
M4READER_PCM_fillAuStruct(M4OSA_Context context,M4_StreamHandler * pStreamHandler,M4_AccessUnit * pAccessUnit)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  */
M4READER_PCM_reset(M4OSA_Context context,M4_StreamHandler * pStreamHandler)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  */
M4READER_PCM_getNextAu(M4OSA_Context context,M4_StreamHandler * pStreamHandler,M4_AccessUnit * pAccessUnit)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  */
M4READER_PCM_jump(M4OSA_Context context,M4_StreamHandler * pStreamHandler,M4OSA_Int32 * pTime)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  */
M4READER_PCM_getInterfaces(M4READER_MediaType * pMediaType,M4READER_GlobalInterface ** pRdrGlobalInterface,M4READER_DataInterface ** pRdrDataInterface)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