| /* |
| * Copyright (C) 2011 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /** |
| ************************************************************************ |
| * @file M4READER_Amr.c |
| * @brief Generic encapsulation of the core amr reader |
| * @note This file implements the generic M4READER interface |
| * on top of the AMR reader |
| ************************************************************************ |
| */ |
| #include "M4OSA_Types.h" |
| #include "M4OSA_Error.h" |
| #include "M4OSA_Memory.h" |
| #include "M4OSA_Debug.h" |
| #include "M4OSA_CoreID.h" |
| |
| #include "M4_Utils.h" |
| |
| #include "M4AMRR_CoreReader.h" |
| #include "M4READER_Amr.h" |
| |
| /** |
| ************************************************************************ |
| * structure M4READER_AMR_Context |
| * @brief This structure defines the internal context of a amr reader instance |
| * @note The context is allocated and de-allocated by the reader |
| ************************************************************************ |
| */ |
| typedef struct _M4READER_AMR_Context |
| { |
| M4OSA_Context m_pCoreContext; /**< core amr reader context */ |
| M4_AudioStreamHandler* m_pAudioStream; /**< pointer on the audio stream |
| description returned by the core */ |
| M4SYS_AccessUnit m_audioAu; /**< audio access unit to be filled by the core */ |
| M4OSA_Time m_maxDuration; /**< duration of the audio stream */ |
| M4OSA_FileReadPointer* m_pOsaFileReaderFcts; /**< OSAL file read functions */ |
| |
| } M4READER_AMR_Context; |
| |
| |
| /** |
| ************************************************************************ |
| * @brief create an instance of the reader |
| * @note allocates the context |
| * @param pContext: (OUT) pointer on a reader context |
| * @return M4NO_ERROR there is no error |
| * @return M4ERR_ALLOC a memory allocation has failed |
| * @return M4ERR_PARAMETER at least one parameter is not properly set (in DEBUG only) |
| ************************************************************************ |
| */ |
| M4OSA_ERR M4READER_AMR_create(M4OSA_Context *pContext) |
| { |
| M4READER_AMR_Context* pReaderContext; |
| |
| /* Check function parameters */ |
| M4OSA_DEBUG_IF1((pContext == 0), M4ERR_PARAMETER, |
| "M4READER_AMR_create: invalid context pointer"); |
| |
| pReaderContext = (M4READER_AMR_Context*)M4OSA_32bitAlignedMalloc(sizeof(M4READER_AMR_Context), |
| M4READER_AMR, (M4OSA_Char *)"M4READER_AMR_Context"); |
| if (pReaderContext == M4OSA_NULL) |
| { |
| return M4ERR_ALLOC; |
| } |
| |
| pReaderContext->m_pAudioStream = M4OSA_NULL; |
| pReaderContext->m_audioAu.dataAddress = M4OSA_NULL; |
| pReaderContext->m_maxDuration = 0; |
| pReaderContext->m_pCoreContext = M4OSA_NULL; |
| pReaderContext->m_pOsaFileReaderFcts = M4OSA_NULL; |
| |
| *pContext = pReaderContext; |
| |
| return M4NO_ERROR; |
| } |
| |
| /** |
| ************************************************************************ |
| * @brief destroy the instance of the reader |
| * @note after this call the context is invalid |
| * |
| * @param context: (IN) Context of the reader |
| * |
| * @return M4NO_ERROR there is no error |
| * @return M4ERR_PARAMETER at least one parameter is not properly set |
| ************************************************************************ |
| */ |
| M4OSA_ERR M4READER_AMR_destroy(M4OSA_Context context) |
| { |
| M4READER_AMR_Context* pC=(M4READER_AMR_Context*)context; |
| |
| /* Check function parameters*/ |
| M4OSA_DEBUG_IF1((M4OSA_NULL == pC), M4ERR_PARAMETER, |
| "M4READER_AMR_destroy: invalid context pointer"); |
| |
| /** |
| * Check input parameter */ |
| if (M4OSA_NULL == pC) |
| { |
| M4OSA_TRACE1_0("M4READER_AMR_destroy(): M4READER_AMR_destroy: context is M4OSA_NULL,\ |
| returning M4ERR_PARAMETER"); |
| return M4ERR_PARAMETER; |
| } |
| |
| free(pC); |
| |
| return M4NO_ERROR; |
| } |
| |
| |
| /** |
| ************************************************************************ |
| * @brief open the reader and initializes its created instance |
| * @note this function opens the AMR file |
| * @param context: (IN) Context of the reader |
| * @param pFileDescriptor: (IN) Pointer to proprietary data identifying the media to open |
| * @return M4NO_ERROR there is no error |
| * @return M4ERR_PARAMETER the context is NULL |
| * @return M4ERR_BAD_CONTEXT provided context is not a valid one |
| ************************************************************************ |
| */ |
| M4OSA_ERR M4READER_AMR_open(M4OSA_Context context, M4OSA_Void* pFileDescriptor) |
| { |
| M4READER_AMR_Context* pC = (M4READER_AMR_Context*)context; |
| M4OSA_ERR err; |
| |
| /* Check function parameters*/ |
| M4OSA_DEBUG_IF1((M4OSA_NULL == pC), M4ERR_PARAMETER, |
| "M4READER_AMR_open: invalid context pointer"); |
| M4OSA_DEBUG_IF1((M4OSA_NULL == pFileDescriptor), M4ERR_PARAMETER, |
| "M4READER_AMR_open: invalid pointer pFileDescriptor"); |
| |
| err = M4AMRR_openRead( &pC->m_pCoreContext, pFileDescriptor, pC->m_pOsaFileReaderFcts); |
| |
| return err; |
| } |
| |
| |
| |
| /** |
| ************************************************************************ |
| * @brief close the reader |
| * @note |
| * @param context: (IN) Context of the reader |
| * @return M4NO_ERROR there is no error |
| * @return M4ERR_PARAMETER the context is NULL |
| * @return M4ERR_BAD_CONTEXT provided context is not a valid one |
| ************************************************************************ |
| */ |
| M4OSA_ERR M4READER_AMR_close(M4OSA_Context context) |
| { |
| M4READER_AMR_Context* pC = (M4READER_AMR_Context*)context; |
| M4OSA_ERR err; |
| M4AMRR_State State; |
| |
| /* Check function parameters*/ |
| M4OSA_DEBUG_IF1((M4OSA_NULL == pC), M4ERR_PARAMETER, |
| "M4READER_AMR_close: invalid context pointer"); |
| |
| /** |
| * Check input parameter */ |
| if (M4OSA_NULL == pC) |
| { |
| M4OSA_TRACE1_0("M4READER_AMR_close(): M4READER_AMR_close: context is M4OSA_NULL,\ |
| returning M4ERR_PARAMETER"); |
| return M4ERR_PARAMETER; |
| } |
| |
| if (M4OSA_NULL != pC->m_pAudioStream) |
| { |
| err = M4AMRR_getState(pC->m_pCoreContext, &State, |
| ((M4_StreamHandler*)pC->m_pAudioStream)->m_streamId); |
| if(M4NO_ERROR != err) |
| { |
| M4OSA_TRACE1_0("M4READER_AMR_close: error when calling M4AMRR_getState\n"); |
| return err; |
| } |
| |
| if (M4AMRR_kReading_nextAU == State) |
| { |
| err = M4AMRR_freeAU(pC->m_pCoreContext, |
| ((M4_StreamHandler*)pC->m_pAudioStream)->m_streamId, &pC->m_audioAu); |
| if (err != M4NO_ERROR) |
| { |
| M4OSA_TRACE1_0("M4READER_AMR_close: error when freeing access unit\n"); |
| return err; |
| } |
| } |
| |
| /* Delete the DSI if needed */ |
| if(M4OSA_NULL != pC->m_pAudioStream->m_basicProperties.m_pDecoderSpecificInfo) |
| { |
| free(\ |
| pC->m_pAudioStream->m_basicProperties.m_pDecoderSpecificInfo); |
| |
| pC->m_pAudioStream->m_basicProperties.m_decoderSpecificInfoSize = 0; |
| pC->m_pAudioStream->m_basicProperties.m_pDecoderSpecificInfo = M4OSA_NULL; |
| } |
| |
| /* Finally destroy the stream handler */ |
| free(pC->m_pAudioStream); |
| pC->m_pAudioStream = M4OSA_NULL; |
| } |
| |
| if (M4OSA_NULL != pC->m_pCoreContext) |
| { |
| err = M4AMRR_closeRead(pC->m_pCoreContext); |
| pC->m_pCoreContext = M4OSA_NULL; |
| } |
| |
| return err; |
| } |
| |
| /** |
| ************************************************************************ |
| * @brief Get the next stream found in the media |
| * @note current version needs to translate M4SYS_Stream to M4_StreamHandler |
| * |
| * @param context: (IN) Context of the reader |
| * @param pMediaFamily: (OUT) pointer to a user allocated M4READER_MediaFamily |
| * that will be filled with the media family of the found stream |
| * @param pStreamHandler: (OUT) pointer to a stream handler that will be |
| * allocated and filled with the found stream description |
| * |
| * @return M4NO_ERROR there is no error |
| * @return M4WAR_NO_MORE_STREAM no more available stream in the media (all streams found) |
| * @return M4ERR_PARAMETER at least one parameter is not properly set (in DEBUG mode only) |
| ************************************************************************ |
| */ |
| M4OSA_ERR M4READER_AMR_getNextStream(M4OSA_Context context, M4READER_MediaFamily *pMediaFamily, |
| M4_StreamHandler **pStreamHandlerParam) |
| { |
| M4READER_AMR_Context* pC=(M4READER_AMR_Context*)context; |
| M4OSA_ERR err; |
| M4SYS_StreamID streamIdArray[2]; |
| M4SYS_StreamDescription streamDesc; |
| M4_AudioStreamHandler* pAudioStreamHandler; |
| M4_StreamHandler* pStreamHandler; |
| |
| M4OSA_DEBUG_IF1((pC == 0), M4ERR_PARAMETER, |
| "M4READER_AMR_getNextStream: invalid context"); |
| M4OSA_DEBUG_IF1((pMediaFamily == 0), M4ERR_PARAMETER, |
| "M4READER_AMR_getNextStream: invalid pointer to MediaFamily"); |
| M4OSA_DEBUG_IF1((pStreamHandlerParam == 0), M4ERR_PARAMETER, |
| "M4READER_AMR_getNextStream: invalid pointer to StreamHandler"); |
| |
| err = M4AMRR_getNextStream( pC->m_pCoreContext, &streamDesc); |
| if (err == M4WAR_NO_MORE_STREAM) |
| { |
| streamIdArray[0] = 0; |
| streamIdArray[1] = 0; |
| err = M4AMRR_startReading(pC->m_pCoreContext, streamIdArray); |
| if ((M4OSA_UInt32)M4ERR_ALLOC == err) |
| { |
| M4OSA_TRACE2_0("M4READER_AMR_getNextStream: M4AMRR_startReading returns M4ERR_ALLOC!"); |
| return err; |
| } |
| return M4WAR_NO_MORE_STREAM; |
| } |
| else if (err != M4NO_ERROR) |
| { |
| return err; |
| } |
| |
| *pMediaFamily = M4READER_kMediaFamilyAudio; |
| |
| pAudioStreamHandler = (M4_AudioStreamHandler*)M4OSA_32bitAlignedMalloc(sizeof(M4_AudioStreamHandler), |
| M4READER_AMR, (M4OSA_Char *)"M4_AudioStreamHandler"); |
| if (pAudioStreamHandler == M4OSA_NULL) |
| { |
| return M4ERR_ALLOC; |
| } |
| pStreamHandler =(M4_StreamHandler*)(pAudioStreamHandler); |
| *pStreamHandlerParam = pStreamHandler; |
| pC->m_pAudioStream = pAudioStreamHandler; |
| |
| pAudioStreamHandler->m_structSize = sizeof(M4_AudioStreamHandler); |
| |
| /* |
| * Audio stream handler fields are initialised with 0 value. |
| * They will be properly set by the AMR decoder |
| */ |
| pAudioStreamHandler->m_samplingFrequency = 0; |
| pAudioStreamHandler->m_byteFrameLength = 0; |
| pAudioStreamHandler->m_byteSampleSize = 0; |
| pAudioStreamHandler->m_nbChannels = 0; |
| |
| pStreamHandler->m_pDecoderSpecificInfo = (M4OSA_UInt8*)(streamDesc.decoderSpecificInfo); |
| pStreamHandler->m_decoderSpecificInfoSize = streamDesc.decoderSpecificInfoSize; |
| pStreamHandler->m_streamId = streamDesc.streamID; |
| pStreamHandler->m_duration = streamDesc.duration; |
| pStreamHandler->m_pUserData = (void*)streamDesc.timeScale; /*trick to change*/ |
| |
| if (streamDesc.duration > pC->m_maxDuration) |
| { |
| pC->m_maxDuration = streamDesc.duration; |
| } |
| pStreamHandler->m_averageBitRate = streamDesc.averageBitrate; |
| |
| M4AMRR_getmaxAUsize(pC->m_pCoreContext, &pStreamHandler->m_maxAUSize); |
| |
| switch (streamDesc.streamType) |
| { |
| case M4SYS_kAMR: |
| pStreamHandler->m_streamType = M4DA_StreamTypeAudioAmrNarrowBand; |
| break; |
| case M4SYS_kAMR_WB: |
| pStreamHandler->m_streamType = M4DA_StreamTypeAudioAmrWideBand; |
| break; |
| default: |
| break; |
| } |
| |
| return err; |
| } |
| |
| /** |
| ************************************************************************ |
| * @brief fill the access unit structure with initialization values |
| * @note |
| * @param context: (IN) Context of the reader |
| * @param pStreamHandler: (IN) pointer to the stream handler to |
| * which the access unit will be associated |
| * @param pAccessUnit: (IN/OUT) pointer to the access unit (allocated by the caller) |
| * to initialize |
| * |
| * @return M4NO_ERROR there is no error |
| * @return M4ERR_PARAMETER at least one parameter is not properly set |
| ************************************************************************ |
| */ |
| M4OSA_ERR M4READER_AMR_fillAuStruct(M4OSA_Context context, M4_StreamHandler *pStreamHandler, |
| M4_AccessUnit *pAccessUnit) |
| { |
| M4READER_AMR_Context* pC = (M4READER_AMR_Context*)context; |
| M4SYS_AccessUnit* pAu; |
| |
| M4OSA_DEBUG_IF1((pC == 0), M4ERR_PARAMETER, |
| "M4READER_AMR_fillAuStruct: invalid context"); |
| M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER, |
| "M4READER_AMR_fillAuStruct: invalid pointer to M4_StreamHandler"); |
| M4OSA_DEBUG_IF1((pAccessUnit == 0), M4ERR_PARAMETER, |
| "M4READER_AMR_fillAuStruct: invalid pointer to M4_AccessUnit"); |
| |
| if (pStreamHandler == (M4_StreamHandler*)pC->m_pAudioStream) |
| { |
| pAu = &pC->m_audioAu; |
| } |
| else |
| { |
| M4OSA_TRACE1_0("M4READER_AMR_fillAuStruct: passed StreamHandler is not known\n"); |
| return M4ERR_PARAMETER; |
| } |
| |
| pAu->dataAddress = M4OSA_NULL; |
| pAu->size = 0; |
| /* JC: bug fix 1197 (set CTS to -20 in order the first AU CTS is 0) */ |
| pAu->CTS = -20; |
| pAu->DTS = -20; |
| pAu->attribute = 0; |
| pAu->nbFrag = 0; |
| |
| pAccessUnit->m_size = 0; |
| /* JC: bug fix 1197 (set CTS to -20 in order the first AU CTS is 0) */ |
| pAccessUnit->m_CTS = -20; |
| pAccessUnit->m_DTS = -20; |
| pAccessUnit->m_attribute = 0; |
| pAccessUnit->m_dataAddress = M4OSA_NULL;/*pBuffer;*/ |
| pAccessUnit->m_maxsize = pStreamHandler->m_maxAUSize; |
| pAccessUnit->m_streamID = pStreamHandler->m_streamId; |
| pAccessUnit->m_structSize = sizeof(M4_AccessUnit); |
| |
| return M4NO_ERROR; |
| } |
| |
| /** |
| ************************************************************************ |
| * @brief get an option value from the reader |
| * @note this function follows the set/get option mechanism described in OSAL 3.0 |
| * it allows the caller to retrieve a property value: |
| * - the duration of the longest stream of the media |
| * - the version number of the reader (not implemented yet) |
| * |
| * @param context: (IN) Context of the reader |
| * @param optionId: (IN) indicates the option to get |
| * @param pValue: (OUT) pointer to structure or value (allocated by user) |
| * where option is stored |
| * |
| * @return M4NO_ERROR there is no error |
| * @return M4ERR_PARAMETER at least one parameter is not properly set |
| * @return M4ERR_BAD_OPTION_ID when the option ID is not a valid one |
| ************************************************************************ |
| */ |
| M4OSA_ERR M4READER_AMR_getOption(M4OSA_Context context, M4OSA_OptionID optionId, |
| M4OSA_DataOption pValue) |
| |
| { |
| M4READER_AMR_Context* pC = (M4READER_AMR_Context*)context; |
| M4OSA_ERR err = M4NO_ERROR; |
| |
| /* Check function parameters */ |
| M4OSA_DEBUG_IF1((M4OSA_NULL == pC), M4ERR_PARAMETER, "invalid context pointer"); |
| M4OSA_DEBUG_IF1((M4OSA_NULL == pValue), M4ERR_PARAMETER, "invalid value pointer"); |
| |
| switch(optionId) |
| { |
| case M4READER_kOptionID_Duration : |
| { |
| *(M4OSA_Time*)pValue = pC->m_maxDuration; |
| } |
| break; |
| |
| case M4READER_kOptionID_Bitrate: |
| { |
| M4OSA_UInt32* pBitrate = (M4OSA_UInt32*)pValue; |
| if (M4OSA_NULL != pC->m_pAudioStream) |
| { |
| *pBitrate = pC->m_pAudioStream->m_basicProperties.m_averageBitRate; |
| } |
| else |
| { |
| pBitrate = 0; |
| err = M4ERR_PARAMETER; |
| } |
| |
| } |
| break; |
| case M4READER_kOptionID_Version: |
| { |
| err = M4AMRR_getVersion((M4_VersionInfo*)pValue); |
| } |
| break; |
| |
| default : |
| { |
| err = M4ERR_PARAMETER; |
| } |
| } |
| |
| return err; |
| } |
| |
| /** |
| ************************************************************************ |
| * @brief set en option value of the readder |
| * @note this function follows the set/get option mechanism described in OSAL 3.0 |
| * it allows the caller to set a property value: |
| * - the OSAL file read functions |
| * |
| * @param context: (IN) Context of the decoder |
| * @param optionId: (IN) Identifier indicating the option to set |
| * @param pValue: (IN) Pointer to structure or value (allocated by user) |
| * where option is stored |
| * |
| * @return M4NO_ERROR There is no error |
| * @return M4ERR_BAD_OPTION_ID The option ID is not a valid one |
| * @return M4ERR_STATE State automaton is not applied |
| * @return M4ERR_PARAMETER The option parameter is invalid |
| ************************************************************************ |
| */ |
| M4OSA_ERR M4READER_AMR_setOption(M4OSA_Context context, M4OSA_OptionID optionId, |
| M4OSA_DataOption pValue) |
| { |
| M4READER_AMR_Context* pC = (M4READER_AMR_Context*)context; |
| M4OSA_ERR err = M4NO_ERROR; |
| |
| /* Check function parameters */ |
| M4OSA_DEBUG_IF1((M4OSA_NULL == pC), M4ERR_PARAMETER, "invalid context pointer"); |
| M4OSA_DEBUG_IF1((M4OSA_NULL == pValue), M4ERR_PARAMETER, "invalid value pointer"); |
| |
| switch(optionId) |
| { |
| case M4READER_kOptionID_SetOsaFileReaderFctsPtr : |
| { |
| pC->m_pOsaFileReaderFcts = (M4OSA_FileReadPointer*)pValue; |
| } |
| break; |
| default : |
| { |
| err = M4ERR_PARAMETER; |
| } |
| } |
| |
| return err; |
| } |
| |
| /** |
| ************************************************************************ |
| * @brief reset the stream, that is seek it to beginning and make it ready to be read |
| * @note this function is to be deprecated in next versions |
| * |
| * @param context: (IN) Context of the reader |
| * @param pStreamHandler (IN) The stream handler of the stream to reset |
| * |
| * @return M4NO_ERROR there is no error |
| * @return M4ERR_PARAMETER at least one parameter is not properly set |
| * @return M4ERR_ALLOC there is no more memory available |
| * @return M4ERR_BAD_STREAM_ID the streamID does not exist |
| * @return M4ERR_STATE this function cannot be called now |
| * @return M4ERR_BAD_CONTEXT provided context is not a valid one |
| * @return M4WAR_INVALID_TIME beginning of the stream can not be reached |
| ************************************************************************ |
| */ |
| M4OSA_ERR M4READER_AMR_reset(M4OSA_Context context, M4_StreamHandler *pStreamHandler) |
| { |
| M4READER_AMR_Context* pC = (M4READER_AMR_Context*)context; |
| M4SYS_StreamID streamIdArray[2]; |
| M4OSA_ERR err; |
| M4SYS_AccessUnit* pAu; |
| M4OSA_Time time64 = 0; |
| M4AMRR_State State; |
| |
| M4OSA_DEBUG_IF1((pC == 0), M4ERR_PARAMETER, "M4READER_AMR_reset: invalid context"); |
| M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER, |
| "M4READER_AMR_reset: invalid pointer to M4_StreamHandler"); |
| |
| if (pStreamHandler == (M4_StreamHandler*)pC->m_pAudioStream) |
| { |
| pAu = &pC->m_audioAu; |
| } |
| else |
| { |
| M4OSA_TRACE1_0("M4READER_AMR_reset: passed StreamHandler is not known\n"); |
| return M4ERR_PARAMETER; |
| } |
| |
| err = M4AMRR_getState(pC->m_pCoreContext, &State, pStreamHandler->m_streamId); |
| if (M4AMRR_kReading_nextAU == State) |
| { |
| err = M4AMRR_freeAU(pC->m_pCoreContext, pStreamHandler->m_streamId, pAu); |
| if (err != M4NO_ERROR) |
| { |
| M4OSA_TRACE1_0("M4READER_AMR_reset: error when freeing access unit\n"); |
| return err; |
| } |
| pAu->dataAddress = M4OSA_NULL; |
| } |
| |
| streamIdArray[0] = pStreamHandler->m_streamId; |
| streamIdArray[1] = 0; |
| |
| err = M4NO_ERROR; |
| |
| /* for reset during playback */ |
| /* (set CTS to -20 in order the first AU CTS is 0) */ |
| pAu->CTS = -20; |
| pAu->DTS = -20; |
| |
| err = M4AMRR_seek(pC->m_pCoreContext, streamIdArray, time64, M4SYS_kBeginning, &time64); |
| if (err != M4NO_ERROR) |
| { |
| M4OSA_TRACE1_0("M4READER_AMR_reset: error when calling M4AMRR_seek()\n"); |
| return err; |
| } |
| |
| return err; |
| } |
| |
| /** |
| ************************************************************************ |
| * @brief jump into the stream at the specified time |
| * @note |
| * @param context: (IN) Context of the reader |
| * @param pStreamHandler (IN) the stream description of the stream to make jump |
| * @param pTime (IN/OUT) IN: the time to jump to (in ms) |
| * OUT: the time to which the stream really jumped |
| * @return M4NO_ERROR there is no error |
| * @return M4ERR_BAD_CONTEXT provided context is not a valid one |
| * @return M4ERR_PARAMETER at least one parameter is not properly set |
| * @return M4ERR_ALLOC there is no more memory available |
| * @return M4WAR_INVALID_TIME the time can not be reached |
| ************************************************************************ |
| */ |
| M4OSA_ERR M4READER_AMR_jump(M4OSA_Context context, M4_StreamHandler *pStreamHandler, |
| M4OSA_Int32* pTime) |
| { |
| M4READER_AMR_Context* pC = (M4READER_AMR_Context*)context; |
| M4SYS_StreamID streamIdArray[2]; |
| M4OSA_ERR err; |
| M4SYS_AccessUnit* pAu; |
| M4OSA_Time time64 = (M4OSA_Time)*pTime; |
| M4AMRR_State State; |
| |
| M4OSA_DEBUG_IF1((pC == 0), M4ERR_PARAMETER, "M4READER_AMR_reset: invalid context"); |
| M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER, |
| "M4READER_AMR_reset: invalid pointer to M4_StreamHandler"); |
| M4OSA_DEBUG_IF1((pTime == 0), M4ERR_PARAMETER, "M4READER_3GP_jump: invalid time pointer"); |
| |
| if (pStreamHandler == (M4_StreamHandler*)pC->m_pAudioStream) |
| { |
| pAu = &pC->m_audioAu; |
| } |
| else |
| { |
| M4OSA_TRACE1_0("M4READER_AMR_jump: passed StreamHandler is not known\n"); |
| return M4ERR_PARAMETER; |
| } |
| |
| err = M4AMRR_getState(pC->m_pCoreContext, &State, pStreamHandler->m_streamId); |
| if (M4AMRR_kReading_nextAU == State) |
| { |
| err = M4AMRR_freeAU(pC->m_pCoreContext, pStreamHandler->m_streamId, pAu); |
| if (err != M4NO_ERROR) |
| { |
| M4OSA_TRACE1_0("M4READER_AMR_jump: error when freeing access unit\n"); |
| return err; |
| } |
| pAu->dataAddress = M4OSA_NULL; |
| } |
| |
| streamIdArray[0] = pStreamHandler->m_streamId; |
| streamIdArray[1] = 0; |
| |
| pAu->CTS = time64; |
| pAu->DTS = time64; |
| err = M4AMRR_seek(pC->m_pCoreContext, streamIdArray, time64, M4SYS_kNoRAPprevious, &time64); |
| if (err != M4NO_ERROR) |
| { |
| M4OSA_TRACE1_0("M4READER_AMR_jump: error when calling M4AMRR_seek()\n"); |
| return err; |
| } |
| |
| *pTime = (M4OSA_Int32)time64; |
| |
| return err; |
| } |
| |
| /** |
| ************************************************************************ |
| * @brief Gets an access unit (AU) from the stream handler source. |
| * @note An AU is the smallest possible amount of data to be decoded by a decoder (audio/video). |
| * In the current version, we need to translate M4OSA_AccessUnit to M4_AccessUnit |
| * |
| * @param context: (IN) Context of the reader |
| * @param pStreamHandler (IN) The stream handler of the stream to make jump |
| * @param pAccessUnit (IN/OUT) Pointer to an access unit to fill with read data (the au |
| structure is allocated by the user, and must be |
| initialized by calling M4READER_fillAuStruct_fct after |
| creation) |
| * @return M4NO_ERROR there is no error |
| * @return M4ERR_BAD_CONTEXT provided context is not a valid one |
| * @return M4ERR_PARAMETER at least one parameter is not properly set |
| * @return M4ERR_ALLOC memory allocation failed |
| * @return M4ERR_BAD_STREAM_ID at least one of the stream Id. does not exist. |
| * @return M4WAR_NO_MORE_AU there are no more access unit in the stream (end of stream) |
| ************************************************************************ |
| */ |
| M4OSA_ERR M4READER_AMR_getNextAu(M4OSA_Context context, M4_StreamHandler *pStreamHandler, |
| M4_AccessUnit *pAccessUnit) |
| { |
| M4READER_AMR_Context* pC = (M4READER_AMR_Context*)context; |
| M4OSA_ERR err = M4NO_ERROR; |
| M4SYS_AccessUnit* pAu; |
| M4_MediaTime timeScale; |
| M4AMRR_State State; |
| |
| M4OSA_DEBUG_IF1((pC == 0), M4ERR_PARAMETER, |
| "M4READER_AMR_getNextAu: invalid context"); |
| M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER, |
| "M4READER_AMR_getNextAu: invalid pointer to M4_StreamHandler"); |
| M4OSA_DEBUG_IF1((pAccessUnit == 0), M4ERR_PARAMETER, |
| "M4READER_AMR_getNextAu: invalid pointer to M4_AccessUnit"); |
| |
| /* keep trace of the allocated buffers in AU to be able to free them at destroy() |
| but be aware that system is risky and would need upgrade if more than |
| one video and one audio AU is needed */ |
| if (pStreamHandler == (M4_StreamHandler*)pC->m_pAudioStream) |
| { |
| pAu = &pC->m_audioAu; |
| } |
| else |
| { |
| M4OSA_TRACE1_0("M4READER_AMR_getNextAu: passed StreamHandler is not known\n"); |
| return M4ERR_PARAMETER; |
| } |
| |
| err = M4AMRR_getState(pC->m_pCoreContext, &State, pStreamHandler->m_streamId); |
| if (M4AMRR_kReading_nextAU == State) |
| { |
| err = M4AMRR_freeAU(pC->m_pCoreContext, pStreamHandler->m_streamId, pAu); |
| if (err != M4NO_ERROR) |
| { |
| M4OSA_TRACE1_0("M4READER_AVI_getNextAu: error when freeing access unit\n"); |
| return err; |
| } |
| pAu->dataAddress = M4OSA_NULL; |
| } |
| |
| pAu->nbFrag = 0; |
| err = M4AMRR_nextAU(pC->m_pCoreContext, pStreamHandler->m_streamId, pAu); |
| |
| if (err == M4NO_ERROR) |
| { |
| timeScale = (M4OSA_Float)(M4OSA_Int32)(pStreamHandler->m_pUserData)/1000; |
| pAccessUnit->m_dataAddress = (M4OSA_MemAddr8)pAu->dataAddress; |
| pAccessUnit->m_size = pAu->size; |
| pAccessUnit->m_CTS = (M4_MediaTime)pAu->CTS/*/timeScale*/; |
| pAccessUnit->m_DTS = (M4_MediaTime)pAu->DTS/*/timeScale*/; |
| pAccessUnit->m_attribute = pAu->attribute; |
| } |
| else |
| { |
| pAccessUnit->m_size=0; |
| } |
| |
| return err; |
| } |
| |
| /** |
| ************************************************************************* |
| * @brief Retrieves the generic interfaces implemented by the reader |
| * |
| * @param pMediaType : Pointer on a M4READER_MediaType (allocated by the caller) |
| * that will be filled with the media type supported by this reader |
| * @param pRdrGlobalInterface : Address of a pointer that will be set to the global interface implemented |
| * by this reader. The interface is a structure allocated by the function and must |
| * be un-allocated by the caller. |
| * @param pRdrDataInterface : Address of a pointer that will be set to the data interface implemented |
| * by this reader. The interface is a structure allocated by the function and must |
| * be un-allocated by the caller. |
| * |
| * @returns : M4NO_ERROR if OK |
| * ERR_ALLOC if an allocation failed |
| * ERR_PARAMETER at least one parameter is not properly set (in DEBUG only) |
| ************************************************************************* |
| */ |
| M4OSA_ERR M4READER_AMR_getInterfaces(M4READER_MediaType *pMediaType, |
| M4READER_GlobalInterface **pRdrGlobalInterface, |
| M4READER_DataInterface **pRdrDataInterface) |
| { |
| M4OSA_DEBUG_IF1((pMediaType == 0), M4ERR_PARAMETER, |
| "M4READER_AMR_getInterfaces: invalid pointer to MediaType"); |
| M4OSA_DEBUG_IF1((pRdrGlobalInterface == 0), M4ERR_PARAMETER, |
| "M4READER_AMR_getInterfaces: invalid pointer to M4READER_GlobalInterface"); |
| M4OSA_DEBUG_IF1((pRdrDataInterface == 0), M4ERR_PARAMETER, |
| "M4READER_AMR_getInterfaces: invalid pointer to M4READER_DataInterface"); |
| |
| *pRdrGlobalInterface = |
| (M4READER_GlobalInterface*)M4OSA_32bitAlignedMalloc( sizeof(M4READER_GlobalInterface), |
| M4READER_AMR, (M4OSA_Char *)"M4READER_GlobalInterface" ); |
| if (M4OSA_NULL == *pRdrGlobalInterface) |
| { |
| *pRdrDataInterface = M4OSA_NULL; |
| return M4ERR_ALLOC; |
| } |
| *pRdrDataInterface = (M4READER_DataInterface*)M4OSA_32bitAlignedMalloc( sizeof(M4READER_DataInterface), |
| M4READER_AMR, (M4OSA_Char *)"M4READER_DataInterface"); |
| if (M4OSA_NULL == *pRdrDataInterface) |
| { |
| free(*pRdrGlobalInterface); |
| *pRdrGlobalInterface = M4OSA_NULL; |
| return M4ERR_ALLOC; |
| } |
| |
| *pMediaType = M4READER_kMediaTypeAMR; |
| |
| (*pRdrGlobalInterface)->m_pFctCreate = M4READER_AMR_create; |
| (*pRdrGlobalInterface)->m_pFctDestroy = M4READER_AMR_destroy; |
| (*pRdrGlobalInterface)->m_pFctOpen = M4READER_AMR_open; |
| (*pRdrGlobalInterface)->m_pFctClose = M4READER_AMR_close; |
| (*pRdrGlobalInterface)->m_pFctGetOption = M4READER_AMR_getOption; |
| (*pRdrGlobalInterface)->m_pFctSetOption = M4READER_AMR_setOption; |
| (*pRdrGlobalInterface)->m_pFctGetNextStream = M4READER_AMR_getNextStream; |
| (*pRdrGlobalInterface)->m_pFctFillAuStruct = M4READER_AMR_fillAuStruct; |
| (*pRdrGlobalInterface)->m_pFctStart = M4OSA_NULL; |
| (*pRdrGlobalInterface)->m_pFctStop = M4OSA_NULL; |
| (*pRdrGlobalInterface)->m_pFctJump = M4READER_AMR_jump; |
| (*pRdrGlobalInterface)->m_pFctReset = M4READER_AMR_reset; |
| (*pRdrGlobalInterface)->m_pFctGetPrevRapTime = M4OSA_NULL; /*all AUs are RAP*/ |
| |
| (*pRdrDataInterface)->m_pFctGetNextAu = M4READER_AMR_getNextAu; |
| |
| (*pRdrDataInterface)->m_readerContext = M4OSA_NULL; |
| |
| return M4NO_ERROR; |
| } |
| |