M4PCMR_CoreReader.c revision 947721ba962c19913b76658cdbb19ae8c77c9c50
1/* 2 * Copyright (C) 2004-2011 NXP Software 3 * Copyright (C) 2011 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17/** 18 ************************************************************************ 19 * @file M4PCM_PCMReader.c 20 * @brief PCM reader implementation 21 * @note This file implements functions of the PCM reader 22 ************************************************************************ 23 */ 24#include "M4OSA_CharStar.h" 25#include "M4PCMR_CoreReader.h" 26#include "M4OSA_Debug.h" 27#include "M4OSA_CharStar.h" 28/** 29 ****************************************************************************** 30 * PCM reader version numbers 31 ****************************************************************************** 32 */ 33/* CHANGE_VERSION_HERE */ 34#define M4PCMR_VERSION_MAJOR 1 35#define M4PCMR_VERSION_MINOR 0 36#define M4PCMR_VERSION_REVISION 0 37 38/** 39 ************************************************************************ 40 * M4OSA_ERR M4PCMR_openRead(M4OSA_Context* pContext, M4OSA_Void* pUrl, 41 * M4OSA_FileReaderPointer* pFileFunction) 42 * @brief This function opens a PCM file 43 * @note This function : 44 * - opens a PCM file 45 * - initializes PCM context, 46 * - verifies PCM file format 47 * - Fill decoder config structure 48 * - Changes state of the reader in 'Opening' 49 * @param pContext: (OUT) Pointer on the PCM Reader context 50 * @param pUrl: (IN) Name of the PCM file 51 * @param pFileFunctions: (IN) Pointer on the file access functions 52 * @return M4NO_ERROR there is no error during the opening 53 * @return M4ERR_PARAMETER pContext and/or pUrl and/or pFileFunction is NULL 54 * @return M4ERR_ALLOC there is no more memory available 55 * @return M4ERR_FILE_NOT_FOUND the file cannot be found 56 * @return M4PCMC_ERR_PCM_NOT_COMPLIANT the file does not seem to be compliant, no RIFF, 57 * or lack of any mandatory chunk. 58 * @return M4PCMC_ERR_PCM_NOT_SUPPORTED the PCM format of this file is not supported by the 59 * reader 60 * @return Any M4OSA_FILE errors see OSAL File specification for detailed errors 61 ************************************************************************ 62 */ 63M4OSA_ERR M4PCMR_openRead(M4OSA_Context* pContext, M4OSA_Void* pUrl, 64 M4OSA_FileReadPointer* pFileFunction) 65{ 66 M4OSA_ERR err; 67 M4PCMR_Context *context; 68 M4OSA_Char* pTempURL; 69 M4OSA_Char value[6]; 70 71 /* Check parameters */ 72 if((M4OSA_NULL == pContext)|| (M4OSA_NULL == pUrl) ||(M4OSA_NULL == pFileFunction)) 73 { 74 return M4ERR_PARAMETER; 75 } 76 77 /* Allocates the context */ 78 context = M4OSA_NULL; 79 context = (M4PCMR_Context *)M4OSA_malloc(sizeof(M4PCMR_Context), M4WAV_READER, 80 (M4OSA_Char *)"M4PCMR_openRead"); 81 if (M4OSA_NULL == context) 82 { 83 return M4ERR_ALLOC; 84 } 85 *pContext = (M4OSA_Context)context; 86 87 /* Initialize the context */ 88 context->m_offset = 0; 89 90 context->m_state = M4PCMR_kInit; 91 context->m_microState = M4PCMR_kInit; 92 context->m_pFileReadFunc = M4OSA_NULL; 93 context->m_fileContext = M4OSA_NULL; 94 context->m_pAuBuffer = M4OSA_NULL; 95 context->m_pDecoderSpecInfo = M4OSA_NULL; 96 97 /* Set sample frequency */ 98 pTempURL = (M4OSA_Char*)pUrl + (strlen((const char *)pUrl)-11); 99 M4OSA_chrNCopy(value, pTempURL, 5); 100 M4OSA_chrGetUInt32(pTempURL, &(context->m_decoderConfig.SampleFrequency), 101 M4OSA_NULL, M4OSA_kchrDec); 102 103 /* Set number of channels */ 104 pTempURL += 6; 105 M4OSA_chrNCopy(value, pTempURL, 1); 106 M4OSA_chrGetUInt16(pTempURL, &(context->m_decoderConfig.nbChannels), 107 M4OSA_NULL, M4OSA_kchrDec); 108 109 M4OSA_chrNCopy(pUrl,pUrl, (strlen((const char *)pUrl)-12)); 110 /* Open the file */ 111 context->m_fileContext = M4OSA_NULL; 112 err = pFileFunction->openRead(&(context->m_fileContext), pUrl, M4OSA_kFileRead); 113 if(M4NO_ERROR != err) 114 { 115 return err; 116 } 117 context->m_decoderConfig.BitsPerSample = 16; 118 context->m_decoderConfig.AvgBytesPerSec = context->m_decoderConfig.SampleFrequency * 2 \ 119 * context->m_decoderConfig.nbChannels; 120 err = pFileFunction->getOption(context->m_fileContext, M4OSA_kFileReadGetFileSize, 121 (M4OSA_DataOption*)&(context->m_decoderConfig.DataLength)); 122 if(M4NO_ERROR != err) 123 { 124 return err; 125 } 126 context->m_blockSize = 2048 * context->m_decoderConfig.nbChannels; // Raw PCM. Hence, get a 127 // chunk of data 128 129 if(context->m_decoderConfig.SampleFrequency == 8000) 130 { 131 /* AMR case, no pb */ 132 context->m_blockSize = context->m_decoderConfig.nbChannels *\ 133 (context->m_decoderConfig.SampleFrequency / 50) * \ 134 (context->m_decoderConfig.BitsPerSample / 8); 135 } 136 if(context->m_decoderConfig.SampleFrequency == 16000) 137 { 138 /* AAC case, we can't read only 20 ms blocks */ 139 context->m_blockSize = 2048 * context->m_decoderConfig.nbChannels; 140 } 141 context->m_dataStartOffset = 0; 142 context->m_pFileReadFunc = pFileFunction; 143 144 context->m_pAuBuffer = (M4OSA_MemAddr32)M4OSA_malloc(context->m_blockSize, M4WAV_READER, 145 (M4OSA_Char *)"Core PCM reader Access Unit"); 146 if (M4OSA_NULL == context->m_pAuBuffer) 147 { 148 err = M4ERR_ALLOC; 149 goto cleanup; 150 } 151 152 /* Change state */ 153 context->m_state = M4PCMR_kOpening; 154 155 return M4NO_ERROR; 156 157cleanup: 158 159 /* Close the file */ 160 if(context->m_pFileReadFunc != M4OSA_NULL) 161 context->m_pFileReadFunc->closeRead(context->m_fileContext); 162 163 /* Free internal context */ 164 M4OSA_free((M4OSA_MemAddr32)context); 165 *pContext = M4OSA_NULL; 166 167 return err; 168} 169 170/** 171 ************************************************************************ 172 * M4OSA_ERR M4PCMR_getNextStream(M4OSA_Context context, M4SYS_StreamDescription* pStreamDesc) 173 * @brief This function get the (unique) stream of a PCM file 174 * @note This function : 175 * - Allocates and fills the decoder specific info structure 176 * - Fills decoder specific infos structure 177 * - Fills pStreamDesc structure allocated by the caller 178 * @param context: (IN/OUT) PCM Reader context 179 * @param pStreamDesc: (IN) Stream Description context 180 * @return M4NO_ERROR there is no error 181 * @return M4ERR_PARAMETER at least one parameter is NULL 182 * @return M4ERR_ALLOC there is no more memory available 183 * @return M4ERR_STATE this function cannot be called now 184 * @return Any M4OSA_FILE errors see OSAL File specification for detailed errors 185 ************************************************************************ 186 */ 187M4OSA_ERR M4PCMR_getNextStream(M4OSA_Context context, M4SYS_StreamDescription* pStreamDesc) 188{ 189 M4PCMR_Context *c = (M4PCMR_Context *)context; 190 191 /* Check parameters */ 192 if((M4OSA_NULL == context)|| (M4OSA_NULL == pStreamDesc)) 193 { 194 return M4ERR_PARAMETER; 195 } 196 197 if (c->m_state == M4PCMR_kOpening_streamRetrieved) 198 { 199 return M4WAR_NO_MORE_STREAM; 200 } 201 /* Check Reader's m_state */ 202 if(c->m_state != M4PCMR_kOpening) 203 { 204 return M4ERR_STATE; 205 } 206 207 /* Only one stream is contained in PCM file */ 208 pStreamDesc->streamID = 1; 209 /* Not used */ 210 pStreamDesc->profileLevel = 0; 211 pStreamDesc->decoderSpecificInfoSize = sizeof(M4PCMC_DecoderSpecificInfo); 212 213 /* Allocates decoder specific info structure */ 214 pStreamDesc->decoderSpecificInfo = M4OSA_NULL; 215 pStreamDesc->decoderSpecificInfo = 216 (M4OSA_MemAddr32)M4OSA_malloc( sizeof(M4PCMC_DecoderSpecificInfo), M4WAV_READER, 217 (M4OSA_Char *)"M4PCMR_getNextStream"); 218 if(pStreamDesc->decoderSpecificInfo == M4OSA_NULL) 219 { 220 return M4ERR_ALLOC; 221 } 222 /* Fill decoderSpecificInfo structure, with decoder config structure filled in 'openread' 223 function */ 224 M4OSA_memcpy((M4OSA_MemAddr8)pStreamDesc->decoderSpecificInfo, 225 (M4OSA_MemAddr8)&c->m_decoderConfig, sizeof(M4PCMC_DecoderSpecificInfo)); 226 227 /* Fill other fields of pStreamDesc structure */ 228 pStreamDesc->timeScale = 1000; 229 pStreamDesc->duration = (M4OSA_Time)(((M4OSA_Double)(c->m_decoderConfig.DataLength)\ 230 / (M4OSA_Double)(c->m_decoderConfig.AvgBytesPerSec))*pStreamDesc->timeScale); 231 pStreamDesc->averageBitrate = c->m_decoderConfig.AvgBytesPerSec * 8;/* in bits, multiply by 8*/ 232 pStreamDesc->maxBitrate = pStreamDesc->averageBitrate; /* PCM stream has constant bitrate */ 233 234 /* Determines Stream type */ 235 switch(c->m_decoderConfig.BitsPerSample) 236 { 237 case 8: 238 switch(c->m_decoderConfig.nbChannels) 239 { 240 case 1: 241 pStreamDesc->streamType = M4SYS_kPCM_8bitsU; 242 break; 243// case 2: 244// pStreamDesc->streamType = M4SYS_kPCM_8bitsS; /* ??? 8bits stereo not 245 // defined ? */ 246// break; 247 default: 248 pStreamDesc->streamType = M4SYS_kAudioUnknown; 249 } 250 break; 251 252 case 16: 253 switch(c->m_decoderConfig.nbChannels) 254 { 255 case 1: 256 pStreamDesc->streamType = M4SYS_kPCM_16bitsU; 257 break; 258 case 2: 259 pStreamDesc->streamType = M4SYS_kPCM_16bitsS; 260 break; 261 default: 262 pStreamDesc->streamType = M4SYS_kAudioUnknown; 263 } 264 break; 265 266 default: 267 pStreamDesc->streamType = M4SYS_kAudioUnknown; 268 } 269 270 c->m_pDecoderSpecInfo = pStreamDesc->decoderSpecificInfo; 271 272 c->m_state = M4PCMR_kOpening_streamRetrieved; 273 274 return M4NO_ERROR; 275} 276 277/** 278 ************************************************************************ 279 * M4OSA_ERR M4PCMR_startReading(M4OSA_Context context, M4SYS_StreamID* pStreamIDs) 280 * @brief This function starts reading the unique stream of a PCM file 281 * @note This function : 282 * - Verifies that the current reader's state allows to start reading a stream 283 * - Check that provided StreamId is correct (always true, only one stream...) 284 * In the player application, a StreamId table is initialized as follow: 285 * M4SYS_StreamID pStreamID[2]={1,0}; 286 * - Change state of the reader in 'Reading' 287 * @param context: (IN/OUT) PCM Reader context 288 * @param streamID: (IN) Stream selection 289 * @return M4NO_ERROR there is no error 290 * @return M4ERR_PARAMETER at least one parameter is NULL 291 * @return M4ERR_STATE this function cannot be called now 292 * @return M4ERR_BAD_STREAM_ID at least one of the streamID does not exist 293 * (should never happen if table pStreamID is correctly initialized as above) 294 ************************************************************************ 295 */ 296M4OSA_ERR M4PCMR_startReading(M4OSA_Context context, M4SYS_StreamID* pStreamIDs) 297{ 298 M4PCMR_Context *c = (M4PCMR_Context *)context; 299 300 /* Check parameters */ 301 if((M4OSA_NULL == context) || (M4OSA_NULL == pStreamIDs)) 302 { 303 return M4ERR_PARAMETER; 304 } 305 306 /* Check Reader's state */ 307 if(c->m_state != M4PCMR_kOpening_streamRetrieved) 308 { 309 return M4ERR_STATE; 310 } 311 312 /* Check pStreamID and if they're OK, change reader's state */ 313 if(pStreamIDs[0] == 1 || pStreamIDs[0] == 0) 314 /* First and unique stream contained in PCM file */ 315 { 316 c->m_state = M4PCMR_kReading; 317 c->m_microState = M4PCMR_kReading; 318 } 319 else 320 { 321 return M4ERR_BAD_STREAM_ID; 322 } 323 324 return M4NO_ERROR; 325} 326 327/** 328 ************************************************************************ 329 * M4OSA_ERR M4PCMR_nextAU(M4OSA_Context context, M4SYS_StreamID streamID, M4SYS_AccessUnit* pAU) 330 * @brief This function reads the next AU contained in the PCM file 331 * @note This function : 332 * - Verifies that the current reader's state allows to read an AU 333 * - Allocates memory to store read AU 334 * - Read data from file and store them into previously allocated memory 335 * - Fill AU structure fileds (CTS...) 336 * - Change state of the reader in 'Reading' (not useful...) 337 * - Change Micro state 'Reading' in M4PCMR_kReading_nextAU 338 * (AU is read and can be deleted) 339 * - Check if the last AU has been read or if we're about to read it 340 * @param context: (IN/OUT) PCM Reader context 341 * @param streamID: (IN) Stream selection 342 * @param pAU: (IN/OUT) Acces Unit Structure 343 * @return M4NO_ERROR there is no error 344 * @return M4ERR_PARAMETER at least one parameter is NULL 345 * @return M4ERR_ALLOC there is no more memory available 346 * @return M4ERR_STATE this function cannot be called now 347 * @return M4M4WAR_NO_DATA_YET there is no enough data in the file to provide a new access unit. 348 * @return M4WAR_END_OF_STREAM There is no more access unit in the stream, 349 * or the sample number is bigger the maximum one. 350 ************************************************************************ 351 */ 352M4OSA_ERR M4PCMR_nextAU(M4OSA_Context context, M4SYS_StreamID streamID, M4SYS_AccessUnit* pAU) 353{ 354 M4PCMR_Context *c = (M4PCMR_Context *)context; 355 M4OSA_ERR err = M4NO_ERROR; 356 M4OSA_UInt32 size_read; 357 358 /* Check parameters */ 359 if((M4OSA_NULL == context) || (M4OSA_NULL == pAU)) 360 { 361 return M4ERR_PARAMETER; 362 } 363 364 /* Check Reader's state */ 365 if(c->m_state != M4PCMR_kReading && c->m_microState != M4PCMR_kReading) 366 { 367 return M4ERR_STATE; 368 } 369 370 /* Allocates AU dataAdress */ 371 pAU->dataAddress = c->m_pAuBuffer; 372 size_read = c->m_blockSize; 373 374 if((c->m_offset + size_read) >= c->m_decoderConfig.DataLength) 375 { 376 size_read = c->m_decoderConfig.DataLength - c->m_offset; 377 } 378 379 /* Read data in file, and copy it to AU Structure */ 380 err = c->m_pFileReadFunc->readData(c->m_fileContext, (M4OSA_MemAddr8)pAU->dataAddress, 381 (M4OSA_UInt32 *)&size_read); 382 if(M4NO_ERROR != err) 383 { 384 return err; 385 } 386 387 /* Calculates the new m_offset, used to determine whether we're at end of reading or not */ 388 c->m_offset = c->m_offset + size_read; 389 390 /* Fill others parameters of AU structure */ 391 pAU->CTS = 392 (M4OSA_Time)(((M4OSA_Double)c->m_offset/(M4OSA_Double)c->m_decoderConfig.AvgBytesPerSec)\ 393 *1000); 394 pAU->DTS = pAU->CTS; 395 396 pAU->attribute = 0; 397 pAU->frag = M4OSA_NULL; 398 pAU->nbFrag = 0; 399 pAU->stream = M4OSA_NULL; 400 pAU->size = size_read; 401 402 /* Change states */ 403 c->m_state = M4PCMR_kReading; /* Not changed ... */ 404 c->m_microState = M4PCMR_kReading_nextAU; /* AU is read and can be deleted */ 405 406 /* Check if there is another AU to read */ 407 /* ie: if decoded nb of bytes = nb of bytes to decode, 408 it means there is no more AU to decode */ 409 if(c->m_offset >= c->m_decoderConfig.DataLength) 410 { 411 return M4WAR_NO_MORE_AU; 412 } 413 414 return M4NO_ERROR; 415} 416 417/** 418 ************************************************************************ 419 * M4OSA_ERR M4PCMR_freeAU(M4OSA_Context context, M4SYS_StreamID streamID, M4SYS_AccessUnit* pAU) 420 * @brief This function frees the AU provided in parameter 421 * @note This function : 422 * - Verifies that the current reader's state allows to free an AU 423 * - Free dataAddress field of AU structure 424 * - Change state of the reader in 'Reading' (not useful...) 425 * - Change Micro state 'Reading' in M4PCMR_kReading (another AU can be read) 426 * @param context: (IN/OUT) PCM Reader context 427 * @param streamID: (IN) Stream selection 428 * @param pAU: (IN) Acces Unit Structure 429 * @return M4NO_ERROR there is no error 430 * @return M4ERR_PARAMETER at least one parameter is NULL 431 * @return M4ERR_STATE this function cannot be called now 432 ************************************************************************ 433 */ 434M4OSA_ERR M4PCMR_freeAU(M4OSA_Context context, M4SYS_StreamID streamID, M4SYS_AccessUnit* pAU) 435{ 436 M4PCMR_Context *c = (M4PCMR_Context *)context; 437 438 /* Check parameters */ 439 if((M4OSA_NULL == context ) || (M4OSA_NULL == pAU)) 440 { 441 return M4ERR_PARAMETER; 442 } 443 444 /* Check Reader's state */ 445 if(c->m_state != M4PCMR_kReading && c->m_microState != M4PCMR_kReading_nextAU) 446 { 447 return M4ERR_STATE; 448 } 449 450 pAU->dataAddress = M4OSA_NULL; 451 452 /* Change states */ 453 c->m_state = M4PCMR_kReading; /* Not changed ... */ 454 c->m_microState = M4PCMR_kReading; /* AU is deleted, another AU can be read */ 455 456 return M4NO_ERROR; 457} 458 459/** 460 ************************************************************************ 461 * M4OSA_ERR M4PCMR_seek(M4OSA_Context context, M4SYS_StreamID* pStreamID, 462 M4OSA_Time time, M4SYS_seekAccessMode seekAccessMode, 463 M4OSA_Time* pObtainCTS[]) 464 * @brief This function seeks into the PCM file at the provided time 465 * @note This function : 466 * - Verifies that the current reader's state allows to seek 467 * - Determines from provided time m_offset to seek in file 468 * - If m_offset is correct, seek in file 469 * - Update new m_offset in PCM reader context 470 * @param context: (IN/OUT) PCM Reader context 471 * @param pStreamID: (IN) Stream selection (not used, only 1 stream) 472 * @param time: (IN) Targeted time 473 * @param seekMode: (IN) Selects the seek access mode 474 * @param pObtainCTS[]: (OUT) Returned Time (not used) 475 * @return M4NO_ERROR there is no error 476 * @return M4ERR_PARAMETER at least one parameter is NULL 477 * @return M4ERR_ALLOC there is no more memory available 478 * @return M4ERR_STATE this function cannot be called now 479 * @return M4WAR_INVALID_TIME Specified time is not reachable 480 * @param M4ERR_NOT_IMPLEMENTED This seek mode is not implemented yet 481 ************************************************************************ 482 */ 483M4OSA_ERR M4PCMR_seek(M4OSA_Context context, M4SYS_StreamID* pStreamID, M4OSA_Time time, 484 M4SYS_SeekAccessMode seekAccessMode, M4OSA_Time* pObtainCTS) 485{ 486 M4PCMR_Context *c = (M4PCMR_Context *)context; 487 M4OSA_ERR err = M4NO_ERROR; 488 M4OSA_UInt32 offset; 489 M4OSA_UInt32 alignment; 490 M4OSA_UInt32 size_read; 491 492 /* Check parameters */ 493 if((M4OSA_NULL == context) || (M4OSA_NULL == pStreamID)) 494 { 495 return M4ERR_PARAMETER; 496 } 497 498 /* Check Reader's state */ 499 if(c->m_state != M4PCMR_kOpening_streamRetrieved && c->m_state != M4PCMR_kReading) 500 { 501 return M4ERR_STATE; 502 } 503 504 switch(seekAccessMode) 505 { 506 case M4SYS_kBeginning: 507 /* Determine m_offset from time*/ 508 offset = 509 (M4OSA_UInt32)(time * ((M4OSA_Double)(c->m_decoderConfig.AvgBytesPerSec) / 1000)); 510 /** check the alignment on sample boundary */ 511 alignment = c->m_decoderConfig.nbChannels*c->m_decoderConfig.BitsPerSample/8; 512 if (offset%alignment != 0) 513 { 514 offset -= offset%alignment; 515 } 516 /*add the header offset*/ 517 offset += c->m_dataStartOffset; 518 /* If m_offset is over file size -> Invalid time */ 519 if (offset > (c->m_dataStartOffset + c->m_decoderConfig.DataLength)) 520 { 521 return M4WAR_INVALID_TIME; 522 } 523 else 524 { 525 /* Seek file */ 526 size_read = offset; 527 err = c->m_pFileReadFunc->seek(c->m_fileContext, M4OSA_kFileSeekBeginning, 528 (M4OSA_FilePosition *) &size_read); 529 if(M4NO_ERROR != err) 530 { 531 return err; 532 } 533 /* Update m_offset in M4PCMR_context */ 534 c->m_offset = offset - c->m_dataStartOffset; 535 } 536 break; 537 538 default: 539 return M4ERR_NOT_IMPLEMENTED; 540 } 541 542 return M4NO_ERROR; 543} 544 545/** 546 ************************************************************************ 547 * M4OSA_ERR M4PCMR_closeRead(M4OSA_Context context) 548 * @brief This function closes PCM file, and frees context 549 * @note This function : 550 * - Verifies that the current reader's state allows close the PCM file 551 * - Closes the file 552 * - Free structures 553 * @param context: (IN/OUT) PCM Reader context 554 * @return M4NO_ERROR there is no error 555 * @return M4ERR_PARAMETER at least one parameter is NULL 556 * @return M4ERR_STATE this function cannot be called now 557 ************************************************************************ 558 */ 559M4OSA_ERR M4PCMR_closeRead(M4OSA_Context context) 560{ 561 M4PCMR_Context *c = (M4PCMR_Context *)context; 562 M4OSA_ERR err = M4NO_ERROR; 563 564 /* Check parameters */ 565 if(M4OSA_NULL == context) 566 { 567 return M4ERR_PARAMETER; 568 } 569 570 if(c->m_pDecoderSpecInfo != M4OSA_NULL) 571 { 572 M4OSA_free((M4OSA_MemAddr32)c->m_pDecoderSpecInfo); 573 } 574 575 /* Check Reader's state */ 576 if(c->m_state != M4PCMR_kReading) 577 { 578 return M4ERR_STATE; 579 } 580 else if(c->m_microState == M4PCMR_kReading_nextAU) 581 { 582 return M4ERR_STATE; 583 } 584 585 if (M4OSA_NULL != c->m_pAuBuffer) 586 { 587 M4OSA_free((M4OSA_MemAddr32)c->m_pAuBuffer); 588 } 589 590 /* Close the file */ 591 if (M4OSA_NULL != c->m_pFileReadFunc) 592 { 593 err = c->m_pFileReadFunc->closeRead(c->m_fileContext); 594 } 595 596 /* Free internal context */ 597 if (M4OSA_NULL != c) 598 { 599 M4OSA_free((M4OSA_MemAddr32)c); 600 } 601 602 return err; 603} 604 605/** 606 ************************************************************************ 607 * M4OSA_ERR M4PCMR_getOption(M4OSA_Context context, M4PCMR_OptionID optionID, 608 * M4OSA_DataOption* pValue) 609 * @brief This function get option of the PCM Reader 610 * @note This function : 611 * - Verifies that the current reader's state allows to get an option 612 * - Return corresponding option value 613 * @param context: (IN/OUT) PCM Reader context 614 * @param optionID: (IN) ID of the option to get 615 * @param pValue: (OUT) Variable where the option value is returned 616 * @return M4NO_ERROR there is no error. 617 * @return M4ERR_PARAMETER at least one parameter is NULL. 618 * @return M4ERR_BAD_OPTION_ID the optionID is not a valid one. 619 * @return M4ERR_STATE this option is not available now. 620 * @return M4ERR_NOT_IMPLEMENTED this option is not implemented 621 ************************************************************************ 622 */ 623M4OSA_ERR M4PCMR_getOption(M4OSA_Context context, M4PCMR_OptionID optionID, 624 M4OSA_DataOption* pValue) 625{ 626 M4PCMR_Context *c =(M4PCMR_Context *)context; 627 628 /* Check parameters */ 629 if(M4OSA_NULL == context) 630 { 631 return M4ERR_PARAMETER; 632 } 633 634 /* Check reader's state */ 635 if((c->m_state != M4PCMR_kOpening) && (c->m_state != M4PCMR_kOpening_streamRetrieved)\ 636 && (c->m_state != M4PCMR_kReading)) 637 { 638 return M4ERR_STATE; 639 } 640 641 /* Depend of the OptionID, the value to return is different */ 642 switch(optionID) 643 { 644 case M4PCMR_kPCMblockSize: 645 *pValue = &c->m_blockSize; 646 break; 647 648 default: 649 return M4ERR_BAD_OPTION_ID; 650 } 651 652 return M4NO_ERROR; 653} 654 655/** 656 ************************************************************************ 657 * M4OSA_ERR M4PCMR_setOption(M4OSA_Context context, M4PCMR_OptionID optionID, 658 * M4OSA_DataOption Value) 659 * @brief This function set option of the PCM Reader 660 * @note This function : 661 * - Verifies that the current reader's state allows to set an option 662 * - Set corresponding option value 663 * @param context: (IN/OUT) PCM Reader context 664 * @param optionID: (IN) ID of the option to get 665 * @param Value: (IN) Variable where the option value is stored 666 * @return M4NO_ERROR there is no error. 667 * @return M4ERR_PARAMETER at least one parameter is NULL. 668 * @return M4ERR_BAD_OPTION_ID the optionID is not a valid one. 669 * @return M4ERR_STATE this option is not available now. 670 * @return M4ERR_NOT_IMPLEMENTED this option is not implemented 671 ************************************************************************ 672 */ 673M4OSA_ERR M4PCMR_setOption(M4OSA_Context context, M4PCMR_OptionID optionID, M4OSA_DataOption Value) 674{ 675 M4PCMR_Context *c =(M4PCMR_Context *)context; 676 677 /* Check parameters */ 678 if(context == M4OSA_NULL) 679 { 680 return M4ERR_PARAMETER; 681 } 682 683 /* Check reader's state */ 684 if((c->m_state != M4PCMR_kOpening) && (c->m_state != M4PCMR_kOpening_streamRetrieved)\ 685 && (c->m_state != M4PCMR_kReading)) 686 { 687 return M4ERR_STATE; 688 } 689 690 /* Depend of the OptionID, the value to set is different */ 691 switch(optionID) 692 { 693 case M4PCMR_kPCMblockSize: 694 c->m_blockSize = (M4OSA_UInt32)Value; 695 break; 696 697 default: 698 return M4ERR_BAD_OPTION_ID; 699 } 700 701 return M4NO_ERROR; 702} 703 704/*********************************************************/ 705M4OSA_ERR M4PCMR_getVersion (M4_VersionInfo *pVersion) 706/*********************************************************/ 707{ 708 M4OSA_TRACE1_1("M4PCMR_getVersion called with pVersion: 0x%x", pVersion); 709 M4OSA_DEBUG_IF1(((M4OSA_UInt32) pVersion == 0),M4ERR_PARAMETER, 710 "pVersion is NULL in M4PCMR_getVersion"); 711 712 pVersion->m_major = M4PCMR_VERSION_MAJOR; 713 pVersion->m_minor = M4PCMR_VERSION_MINOR; 714 pVersion->m_revision = M4PCMR_VERSION_REVISION; 715 716 return M4NO_ERROR; 717} 718