blob: 3343254d851151682a75c8a38f5e3527c1189038 [file] [log] [blame]
/*
* 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 M4PCM_PCMReader.c
* @brief PCM reader implementation
* @note This file implements functions of the PCM reader
************************************************************************
*/
#include "M4OSA_CharStar.h"
#include "M4PCMR_CoreReader.h"
#include "M4OSA_Debug.h"
#include "M4OSA_CharStar.h"
/**
******************************************************************************
* PCM reader version numbers
******************************************************************************
*/
/* CHANGE_VERSION_HERE */
#define M4PCMR_VERSION_MAJOR 1
#define M4PCMR_VERSION_MINOR 0
#define M4PCMR_VERSION_REVISION 0
/**
************************************************************************
* M4OSA_ERR M4PCMR_openRead(M4OSA_Context* pContext, M4OSA_Void* pUrl,
* M4OSA_FileReaderPointer* pFileFunction)
* @brief This function opens a PCM file
* @note This function :
* - opens a PCM file
* - initializes PCM context,
* - verifies PCM file format
* - Fill decoder config structure
* - Changes state of the reader in 'Opening'
* @param pContext: (OUT) Pointer on the PCM Reader context
* @param pUrl: (IN) Name of the PCM file
* @param pFileFunctions: (IN) Pointer on the file access functions
* @return M4NO_ERROR there is no error during the opening
* @return M4ERR_PARAMETER pContext and/or pUrl and/or pFileFunction is NULL
* @return M4ERR_ALLOC there is no more memory available
* @return M4ERR_FILE_NOT_FOUND the file cannot be found
* @return M4PCMC_ERR_PCM_NOT_COMPLIANT the file does not seem to be compliant, no RIFF,
* or lack of any mandatory chunk.
* @return M4PCMC_ERR_PCM_NOT_SUPPORTED the PCM format of this file is not supported by the
* reader
* @return Any M4OSA_FILE errors see OSAL File specification for detailed errors
************************************************************************
*/
M4OSA_ERR M4PCMR_openRead(M4OSA_Context* pContext, M4OSA_Void* pUrl,
M4OSA_FileReadPointer* pFileFunction)
{
M4OSA_ERR err;
M4PCMR_Context *context;
M4OSA_Char* pTempURL;
M4OSA_Char value[6];
/* Check parameters */
if((M4OSA_NULL == pContext)|| (M4OSA_NULL == pUrl) ||(M4OSA_NULL == pFileFunction))
{
return M4ERR_PARAMETER;
}
/* Allocates the context */
context = M4OSA_NULL;
context = (M4PCMR_Context *)M4OSA_32bitAlignedMalloc(sizeof(M4PCMR_Context), M4WAV_READER,
(M4OSA_Char *)"M4PCMR_openRead");
if (M4OSA_NULL == context)
{
return M4ERR_ALLOC;
}
*pContext = (M4OSA_Context)context;
/* Initialize the context */
context->m_offset = 0;
context->m_state = M4PCMR_kInit;
context->m_microState = M4PCMR_kInit;
context->m_pFileReadFunc = M4OSA_NULL;
context->m_fileContext = M4OSA_NULL;
context->m_pAuBuffer = M4OSA_NULL;
context->m_pDecoderSpecInfo = M4OSA_NULL;
/* Set sample frequency */
pTempURL = (M4OSA_Char*)pUrl + (strlen((const char *)pUrl)-11);
M4OSA_chrNCopy(value, pTempURL, 5);
M4OSA_chrGetUInt32(pTempURL, &(context->m_decoderConfig.SampleFrequency),
M4OSA_NULL, M4OSA_kchrDec);
/* Set number of channels */
pTempURL += 6;
M4OSA_chrNCopy(value, pTempURL, 1);
M4OSA_chrGetUInt16(pTempURL, &(context->m_decoderConfig.nbChannels),
M4OSA_NULL, M4OSA_kchrDec);
M4OSA_chrNCopy(pUrl,pUrl, (strlen((const char *)pUrl)-12));
/* Open the file */
context->m_fileContext = M4OSA_NULL;
err = pFileFunction->openRead(&(context->m_fileContext), pUrl, M4OSA_kFileRead);
if(M4NO_ERROR != err)
{
return err;
}
context->m_decoderConfig.BitsPerSample = 16;
context->m_decoderConfig.AvgBytesPerSec = context->m_decoderConfig.SampleFrequency * 2 \
* context->m_decoderConfig.nbChannels;
err = pFileFunction->getOption(context->m_fileContext, M4OSA_kFileReadGetFileSize,
(M4OSA_DataOption*)&(context->m_decoderConfig.DataLength));
if(M4NO_ERROR != err)
{
return err;
}
context->m_blockSize = 2048 * context->m_decoderConfig.nbChannels; // Raw PCM. Hence, get a
// chunk of data
if(context->m_decoderConfig.SampleFrequency == 8000)
{
/* AMR case, no pb */
context->m_blockSize = context->m_decoderConfig.nbChannels *\
(context->m_decoderConfig.SampleFrequency / 50) * \
(context->m_decoderConfig.BitsPerSample / 8);
}
if(context->m_decoderConfig.SampleFrequency == 16000)
{
/* AAC case, we can't read only 20 ms blocks */
context->m_blockSize = 2048 * context->m_decoderConfig.nbChannels;
}
context->m_dataStartOffset = 0;
context->m_pFileReadFunc = pFileFunction;
context->m_pAuBuffer = (M4OSA_MemAddr32)M4OSA_32bitAlignedMalloc(context->m_blockSize, M4WAV_READER,
(M4OSA_Char *)"Core PCM reader Access Unit");
if (M4OSA_NULL == context->m_pAuBuffer)
{
err = M4ERR_ALLOC;
goto cleanup;
}
/* Change state */
context->m_state = M4PCMR_kOpening;
return M4NO_ERROR;
cleanup:
/* Close the file */
if(context->m_pFileReadFunc != M4OSA_NULL)
context->m_pFileReadFunc->closeRead(context->m_fileContext);
/* Free internal context */
free(context);
*pContext = M4OSA_NULL;
return err;
}
/**
************************************************************************
* M4OSA_ERR M4PCMR_getNextStream(M4OSA_Context context, M4SYS_StreamDescription* pStreamDesc)
* @brief This function get the (unique) stream of a PCM file
* @note This function :
* - Allocates and fills the decoder specific info structure
* - Fills decoder specific infos structure
* - Fills pStreamDesc structure allocated by the caller
* @param context: (IN/OUT) PCM Reader context
* @param pStreamDesc: (IN) Stream Description context
* @return M4NO_ERROR there is no error
* @return M4ERR_PARAMETER at least one parameter is NULL
* @return M4ERR_ALLOC there is no more memory available
* @return M4ERR_STATE this function cannot be called now
* @return Any M4OSA_FILE errors see OSAL File specification for detailed errors
************************************************************************
*/
M4OSA_ERR M4PCMR_getNextStream(M4OSA_Context context, M4SYS_StreamDescription* pStreamDesc)
{
M4PCMR_Context *c = (M4PCMR_Context *)context;
/* Check parameters */
if((M4OSA_NULL == context)|| (M4OSA_NULL == pStreamDesc))
{
return M4ERR_PARAMETER;
}
if (c->m_state == M4PCMR_kOpening_streamRetrieved)
{
return M4WAR_NO_MORE_STREAM;
}
/* Check Reader's m_state */
if(c->m_state != M4PCMR_kOpening)
{
return M4ERR_STATE;
}
/* Only one stream is contained in PCM file */
pStreamDesc->streamID = 1;
/* Not used */
pStreamDesc->profileLevel = 0;
pStreamDesc->decoderSpecificInfoSize = sizeof(M4PCMC_DecoderSpecificInfo);
/* Allocates decoder specific info structure */
pStreamDesc->decoderSpecificInfo = M4OSA_NULL;
pStreamDesc->decoderSpecificInfo =
(M4OSA_MemAddr32)M4OSA_32bitAlignedMalloc( sizeof(M4PCMC_DecoderSpecificInfo), M4WAV_READER,
(M4OSA_Char *)"M4PCMR_getNextStream");
if(pStreamDesc->decoderSpecificInfo == M4OSA_NULL)
{
return M4ERR_ALLOC;
}
/* Fill decoderSpecificInfo structure, with decoder config structure filled in 'openread'
function */
memcpy((void *)pStreamDesc->decoderSpecificInfo,
(void *)&c->m_decoderConfig, sizeof(M4PCMC_DecoderSpecificInfo));
/* Fill other fields of pStreamDesc structure */
pStreamDesc->timeScale = 1000;
pStreamDesc->duration = (M4OSA_Time)(((M4OSA_Double)(c->m_decoderConfig.DataLength)\
/ (M4OSA_Double)(c->m_decoderConfig.AvgBytesPerSec))*pStreamDesc->timeScale);
pStreamDesc->averageBitrate = c->m_decoderConfig.AvgBytesPerSec * 8;/* in bits, multiply by 8*/
pStreamDesc->maxBitrate = pStreamDesc->averageBitrate; /* PCM stream has constant bitrate */
/* Determines Stream type */
switch(c->m_decoderConfig.BitsPerSample)
{
case 8:
switch(c->m_decoderConfig.nbChannels)
{
case 1:
pStreamDesc->streamType = M4SYS_kPCM_8bitsU;
break;
// case 2:
// pStreamDesc->streamType = M4SYS_kPCM_8bitsS; /* ??? 8bits stereo not
// defined ? */
// break;
default:
pStreamDesc->streamType = M4SYS_kAudioUnknown;
}
break;
case 16:
switch(c->m_decoderConfig.nbChannels)
{
case 1:
pStreamDesc->streamType = M4SYS_kPCM_16bitsU;
break;
case 2:
pStreamDesc->streamType = M4SYS_kPCM_16bitsS;
break;
default:
pStreamDesc->streamType = M4SYS_kAudioUnknown;
}
break;
default:
pStreamDesc->streamType = M4SYS_kAudioUnknown;
}
c->m_pDecoderSpecInfo = pStreamDesc->decoderSpecificInfo;
c->m_state = M4PCMR_kOpening_streamRetrieved;
return M4NO_ERROR;
}
/**
************************************************************************
* M4OSA_ERR M4PCMR_startReading(M4OSA_Context context, M4SYS_StreamID* pStreamIDs)
* @brief This function starts reading the unique stream of a PCM file
* @note This function :
* - Verifies that the current reader's state allows to start reading a stream
* - Check that provided StreamId is correct (always true, only one stream...)
* In the player application, a StreamId table is initialized as follow:
* M4SYS_StreamID pStreamID[2]={1,0};
* - Change state of the reader in 'Reading'
* @param context: (IN/OUT) PCM Reader context
* @param streamID: (IN) Stream selection
* @return M4NO_ERROR there is no error
* @return M4ERR_PARAMETER at least one parameter is NULL
* @return M4ERR_STATE this function cannot be called now
* @return M4ERR_BAD_STREAM_ID at least one of the streamID does not exist
* (should never happen if table pStreamID is correctly initialized as above)
************************************************************************
*/
M4OSA_ERR M4PCMR_startReading(M4OSA_Context context, M4SYS_StreamID* pStreamIDs)
{
M4PCMR_Context *c = (M4PCMR_Context *)context;
/* Check parameters */
if((M4OSA_NULL == context) || (M4OSA_NULL == pStreamIDs))
{
return M4ERR_PARAMETER;
}
/* Check Reader's state */
if(c->m_state != M4PCMR_kOpening_streamRetrieved)
{
return M4ERR_STATE;
}
/* Check pStreamID and if they're OK, change reader's state */
if(pStreamIDs[0] == 1 || pStreamIDs[0] == 0)
/* First and unique stream contained in PCM file */
{
c->m_state = M4PCMR_kReading;
c->m_microState = M4PCMR_kReading;
}
else
{
return M4ERR_BAD_STREAM_ID;
}
return M4NO_ERROR;
}
/**
************************************************************************
* M4OSA_ERR M4PCMR_nextAU(M4OSA_Context context, M4SYS_StreamID streamID, M4SYS_AccessUnit* pAU)
* @brief This function reads the next AU contained in the PCM file
* @note This function :
* - Verifies that the current reader's state allows to read an AU
* - Allocates memory to store read AU
* - Read data from file and store them into previously allocated memory
* - Fill AU structure fileds (CTS...)
* - Change state of the reader in 'Reading' (not useful...)
* - Change Micro state 'Reading' in M4PCMR_kReading_nextAU
* (AU is read and can be deleted)
* - Check if the last AU has been read or if we're about to read it
* @param context: (IN/OUT) PCM Reader context
* @param streamID: (IN) Stream selection
* @param pAU: (IN/OUT) Acces Unit Structure
* @return M4NO_ERROR there is no error
* @return M4ERR_PARAMETER at least one parameter is NULL
* @return M4ERR_ALLOC there is no more memory available
* @return M4ERR_STATE this function cannot be called now
* @return M4M4WAR_NO_DATA_YET there is no enough data in the file to provide a new access unit.
* @return M4WAR_END_OF_STREAM There is no more access unit in the stream,
* or the sample number is bigger the maximum one.
************************************************************************
*/
M4OSA_ERR M4PCMR_nextAU(M4OSA_Context context, M4SYS_StreamID streamID, M4SYS_AccessUnit* pAU)
{
M4PCMR_Context *c = (M4PCMR_Context *)context;
M4OSA_ERR err = M4NO_ERROR;
M4OSA_UInt32 size_read;
/* Check parameters */
if((M4OSA_NULL == context) || (M4OSA_NULL == pAU))
{
return M4ERR_PARAMETER;
}
/* Check Reader's state */
if(c->m_state != M4PCMR_kReading && c->m_microState != M4PCMR_kReading)
{
return M4ERR_STATE;
}
/* Allocates AU dataAdress */
pAU->dataAddress = c->m_pAuBuffer;
size_read = c->m_blockSize;
if((c->m_offset + size_read) >= c->m_decoderConfig.DataLength)
{
size_read = c->m_decoderConfig.DataLength - c->m_offset;
}
/* Read data in file, and copy it to AU Structure */
err = c->m_pFileReadFunc->readData(c->m_fileContext, (M4OSA_MemAddr8)pAU->dataAddress,
(M4OSA_UInt32 *)&size_read);
if(M4NO_ERROR != err)
{
return err;
}
/* Calculates the new m_offset, used to determine whether we're at end of reading or not */
c->m_offset = c->m_offset + size_read;
/* Fill others parameters of AU structure */
pAU->CTS =
(M4OSA_Time)(((M4OSA_Double)c->m_offset/(M4OSA_Double)c->m_decoderConfig.AvgBytesPerSec)\
*1000);
pAU->DTS = pAU->CTS;
pAU->attribute = 0;
pAU->frag = M4OSA_NULL;
pAU->nbFrag = 0;
pAU->stream = M4OSA_NULL;
pAU->size = size_read;
/* Change states */
c->m_state = M4PCMR_kReading; /* Not changed ... */
c->m_microState = M4PCMR_kReading_nextAU; /* AU is read and can be deleted */
/* Check if there is another AU to read */
/* ie: if decoded nb of bytes = nb of bytes to decode,
it means there is no more AU to decode */
if(c->m_offset >= c->m_decoderConfig.DataLength)
{
return M4WAR_NO_MORE_AU;
}
return M4NO_ERROR;
}
/**
************************************************************************
* M4OSA_ERR M4PCMR_freeAU(M4OSA_Context context, M4SYS_StreamID streamID, M4SYS_AccessUnit* pAU)
* @brief This function frees the AU provided in parameter
* @note This function :
* - Verifies that the current reader's state allows to free an AU
* - Free dataAddress field of AU structure
* - Change state of the reader in 'Reading' (not useful...)
* - Change Micro state 'Reading' in M4PCMR_kReading (another AU can be read)
* @param context: (IN/OUT) PCM Reader context
* @param streamID: (IN) Stream selection
* @param pAU: (IN) Acces Unit Structure
* @return M4NO_ERROR there is no error
* @return M4ERR_PARAMETER at least one parameter is NULL
* @return M4ERR_STATE this function cannot be called now
************************************************************************
*/
M4OSA_ERR M4PCMR_freeAU(M4OSA_Context context, M4SYS_StreamID streamID, M4SYS_AccessUnit* pAU)
{
M4PCMR_Context *c = (M4PCMR_Context *)context;
/* Check parameters */
if((M4OSA_NULL == context ) || (M4OSA_NULL == pAU))
{
return M4ERR_PARAMETER;
}
/* Check Reader's state */
if(c->m_state != M4PCMR_kReading && c->m_microState != M4PCMR_kReading_nextAU)
{
return M4ERR_STATE;
}
pAU->dataAddress = M4OSA_NULL;
/* Change states */
c->m_state = M4PCMR_kReading; /* Not changed ... */
c->m_microState = M4PCMR_kReading; /* AU is deleted, another AU can be read */
return M4NO_ERROR;
}
/**
************************************************************************
* M4OSA_ERR M4PCMR_seek(M4OSA_Context context, M4SYS_StreamID* pStreamID,
M4OSA_Time time, M4SYS_seekAccessMode seekAccessMode,
M4OSA_Time* pObtainCTS[])
* @brief This function seeks into the PCM file at the provided time
* @note This function :
* - Verifies that the current reader's state allows to seek
* - Determines from provided time m_offset to seek in file
* - If m_offset is correct, seek in file
* - Update new m_offset in PCM reader context
* @param context: (IN/OUT) PCM Reader context
* @param pStreamID: (IN) Stream selection (not used, only 1 stream)
* @param time: (IN) Targeted time
* @param seekMode: (IN) Selects the seek access mode
* @param pObtainCTS[]: (OUT) Returned Time (not used)
* @return M4NO_ERROR there is no error
* @return M4ERR_PARAMETER at least one parameter is NULL
* @return M4ERR_ALLOC there is no more memory available
* @return M4ERR_STATE this function cannot be called now
* @return M4WAR_INVALID_TIME Specified time is not reachable
* @param M4ERR_NOT_IMPLEMENTED This seek mode is not implemented yet
************************************************************************
*/
M4OSA_ERR M4PCMR_seek(M4OSA_Context context, M4SYS_StreamID* pStreamID, M4OSA_Time time,
M4SYS_SeekAccessMode seekAccessMode, M4OSA_Time* pObtainCTS)
{
M4PCMR_Context *c = (M4PCMR_Context *)context;
M4OSA_ERR err = M4NO_ERROR;
M4OSA_UInt32 offset;
M4OSA_UInt32 alignment;
M4OSA_UInt32 size_read;
/* Check parameters */
if((M4OSA_NULL == context) || (M4OSA_NULL == pStreamID))
{
return M4ERR_PARAMETER;
}
/* Check Reader's state */
if(c->m_state != M4PCMR_kOpening_streamRetrieved && c->m_state != M4PCMR_kReading)
{
return M4ERR_STATE;
}
switch(seekAccessMode)
{
case M4SYS_kBeginning:
/* Determine m_offset from time*/
offset =
(M4OSA_UInt32)(time * ((M4OSA_Double)(c->m_decoderConfig.AvgBytesPerSec) / 1000));
/** check the alignment on sample boundary */
alignment = c->m_decoderConfig.nbChannels*c->m_decoderConfig.BitsPerSample/8;
if (offset%alignment != 0)
{
offset -= offset%alignment;
}
/*add the header offset*/
offset += c->m_dataStartOffset;
/* If m_offset is over file size -> Invalid time */
if (offset > (c->m_dataStartOffset + c->m_decoderConfig.DataLength))
{
return M4WAR_INVALID_TIME;
}
else
{
/* Seek file */
size_read = offset;
err = c->m_pFileReadFunc->seek(c->m_fileContext, M4OSA_kFileSeekBeginning,
(M4OSA_FilePosition *) &size_read);
if(M4NO_ERROR != err)
{
return err;
}
/* Update m_offset in M4PCMR_context */
c->m_offset = offset - c->m_dataStartOffset;
}
break;
default:
return M4ERR_NOT_IMPLEMENTED;
}
return M4NO_ERROR;
}
/**
************************************************************************
* M4OSA_ERR M4PCMR_closeRead(M4OSA_Context context)
* @brief This function closes PCM file, and frees context
* @note This function :
* - Verifies that the current reader's state allows close the PCM file
* - Closes the file
* - Free structures
* @param context: (IN/OUT) PCM Reader context
* @return M4NO_ERROR there is no error
* @return M4ERR_PARAMETER at least one parameter is NULL
* @return M4ERR_STATE this function cannot be called now
************************************************************************
*/
M4OSA_ERR M4PCMR_closeRead(M4OSA_Context context)
{
M4PCMR_Context *c = (M4PCMR_Context *)context;
M4OSA_ERR err = M4NO_ERROR;
/* Check parameters */
if(M4OSA_NULL == context)
{
return M4ERR_PARAMETER;
}
if(c->m_pDecoderSpecInfo != M4OSA_NULL)
{
free(c->m_pDecoderSpecInfo);
}
/* Check Reader's state */
if(c->m_state != M4PCMR_kReading)
{
return M4ERR_STATE;
}
else if(c->m_microState == M4PCMR_kReading_nextAU)
{
return M4ERR_STATE;
}
if (M4OSA_NULL != c->m_pAuBuffer)
{
free(c->m_pAuBuffer);
}
/* Close the file */
if (M4OSA_NULL != c->m_pFileReadFunc)
{
err = c->m_pFileReadFunc->closeRead(c->m_fileContext);
}
/* Free internal context */
if (M4OSA_NULL != c)
{
free(c);
}
return err;
}
/**
************************************************************************
* M4OSA_ERR M4PCMR_getOption(M4OSA_Context context, M4PCMR_OptionID optionID,
* M4OSA_DataOption* pValue)
* @brief This function get option of the PCM Reader
* @note This function :
* - Verifies that the current reader's state allows to get an option
* - Return corresponding option value
* @param context: (IN/OUT) PCM Reader context
* @param optionID: (IN) ID of the option to get
* @param pValue: (OUT) Variable where the option value is returned
* @return M4NO_ERROR there is no error.
* @return M4ERR_PARAMETER at least one parameter is NULL.
* @return M4ERR_BAD_OPTION_ID the optionID is not a valid one.
* @return M4ERR_STATE this option is not available now.
* @return M4ERR_NOT_IMPLEMENTED this option is not implemented
************************************************************************
*/
M4OSA_ERR M4PCMR_getOption(M4OSA_Context context, M4PCMR_OptionID optionID,
M4OSA_DataOption* pValue)
{
M4PCMR_Context *c =(M4PCMR_Context *)context;
/* Check parameters */
if(M4OSA_NULL == context)
{
return M4ERR_PARAMETER;
}
/* Check reader's state */
if((c->m_state != M4PCMR_kOpening) && (c->m_state != M4PCMR_kOpening_streamRetrieved)\
&& (c->m_state != M4PCMR_kReading))
{
return M4ERR_STATE;
}
/* Depend of the OptionID, the value to return is different */
switch(optionID)
{
case M4PCMR_kPCMblockSize:
*pValue = &c->m_blockSize;
break;
default:
return M4ERR_BAD_OPTION_ID;
}
return M4NO_ERROR;
}
/**
************************************************************************
* M4OSA_ERR M4PCMR_setOption(M4OSA_Context context, M4PCMR_OptionID optionID,
* M4OSA_DataOption Value)
* @brief This function set option of the PCM Reader
* @note This function :
* - Verifies that the current reader's state allows to set an option
* - Set corresponding option value
* @param context: (IN/OUT) PCM Reader context
* @param optionID: (IN) ID of the option to get
* @param Value: (IN) Variable where the option value is stored
* @return M4NO_ERROR there is no error.
* @return M4ERR_PARAMETER at least one parameter is NULL.
* @return M4ERR_BAD_OPTION_ID the optionID is not a valid one.
* @return M4ERR_STATE this option is not available now.
* @return M4ERR_NOT_IMPLEMENTED this option is not implemented
************************************************************************
*/
M4OSA_ERR M4PCMR_setOption(M4OSA_Context context, M4PCMR_OptionID optionID, M4OSA_DataOption Value)
{
M4PCMR_Context *c =(M4PCMR_Context *)context;
/* Check parameters */
if(context == M4OSA_NULL)
{
return M4ERR_PARAMETER;
}
/* Check reader's state */
if((c->m_state != M4PCMR_kOpening) && (c->m_state != M4PCMR_kOpening_streamRetrieved)\
&& (c->m_state != M4PCMR_kReading))
{
return M4ERR_STATE;
}
/* Depend of the OptionID, the value to set is different */
switch(optionID)
{
case M4PCMR_kPCMblockSize:
c->m_blockSize = (M4OSA_UInt32)Value;
break;
default:
return M4ERR_BAD_OPTION_ID;
}
return M4NO_ERROR;
}
/*********************************************************/
M4OSA_ERR M4PCMR_getVersion (M4_VersionInfo *pVersion)
/*********************************************************/
{
M4OSA_TRACE1_1("M4PCMR_getVersion called with pVersion: 0x%x", pVersion);
M4OSA_DEBUG_IF1(((M4OSA_UInt32) pVersion == 0),M4ERR_PARAMETER,
"pVersion is NULL in M4PCMR_getVersion");
pVersion->m_major = M4PCMR_VERSION_MAJOR;
pVersion->m_minor = M4PCMR_VERSION_MINOR;
pVersion->m_revision = M4PCMR_VERSION_REVISION;
return M4NO_ERROR;
}