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