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 ****************************************************************************** 19 * @file M4AMRR_CoreReader.c 20 * @brief Implementation of AMR parser 21 * @note This file contains the API Implementation for 22 * AMR Parser. 23 ****************************************************************************** 24 */ 25 #include "M4AMRR_CoreReader.h" 26 #include "M4OSA_Debug.h" 27 #include "M4OSA_CoreID.h" 28 29 /** 30 ****************************************************************************** 31 * Maximum bitrate per amr type 32 ****************************************************************************** 33 */ 34 #define M4AMRR_NB_MAX_BIT_RATE 12200 35 #define M4AMRR_WB_MAX_BIT_RATE 23850 36 37 /** 38 ****************************************************************************** 39 * AMR reader context ID 40 ****************************************************************************** 41 */ 42 #define M4AMRR_CONTEXTID 0x414d5252 43 44 /** 45 ****************************************************************************** 46 * An AMR frame is 20ms 47 ****************************************************************************** 48 */ 49 #define M4AMRR_FRAME_LENGTH 20 50 51 /** 52 ****************************************************************************** 53 * For the seek, the file is splitted in 40 segments for faster search 54 ****************************************************************************** 55 */ 56 #define M4AMRR_NUM_SEEK_ENTRIES 40 57 58 #define M4AMRR_NB_SAMPLE_FREQUENCY 8000 /**< Narrow band sampling rate */ 59 #define M4AMRR_WB_SAMPLE_FREQUENCY 16000 /**< Wide band sampling rate */ 60 61 /** 62 ****************************************************************************** 63 * AMR reader version numbers 64 ****************************************************************************** 65 */ 66 /* CHANGE_VERSION_HERE */ 67 #define M4AMRR_VERSION_MAJOR 1 68 #define M4AMRR_VERSION_MINOR 11 69 #define M4AMRR_VERSION_REVISION 3 70 71 /** 72 ****************************************************************************** 73 * structure M4_AMRR_Context 74 * @brief Internal AMR reader context structure 75 ****************************************************************************** 76 */ 77 typedef struct 78 { 79 M4OSA_UInt32 m_contextId ; /* Fixed Id. to check for valid Context*/ 80 M4OSA_FileReadPointer* m_pOsaFilePtrFct; /* File function pointer */ 81 M4SYS_StreamDescription* m_pStreamHandler; /* Stream Description */ 82 M4OSA_UInt32* m_pSeekIndex; /* Seek Index Table */ 83 M4OSA_UInt32 m_seekInterval; /* Stores the seek Interval stored in the Index */ 84 M4OSA_UInt32 m_maxAuSize; /* Stores the max Au Size */ 85 M4OSA_MemAddr32 m_pdataAddress; /* Pointer to store AU data */ 86 M4SYS_StreamType m_streamType; /* Stores the stream type AMR NB or WB */ 87 M4OSA_Context m_pAMRFile; /* Data storage */ 88 M4AMRR_State m_status; /* AMR Reader Status */ 89 M4OSA_Int32 m_structSize; /* size of structure*/ 90 } M4_AMRR_Context; 91 92 /** 93 ****************************************************************************** 94 * Parser internal functions, not usable from outside the reader context 95 ****************************************************************************** 96 */ 97 M4OSA_UInt32 M4AMRR_getAuSize(M4OSA_UInt32 frameType, M4SYS_StreamType streamType); 98 M4OSA_UInt32 M4AMRR_getBitrate(M4OSA_UInt32 frameType, M4SYS_StreamType streamType); 99 100 /** 101 ****************************************************************************** 102 * M4OSA_UInt32 M4AMRR_getAuSize(M4OSA_UInt32 frameType, M4SYS_StreamType streamType) 103 * @brief Internal function to the AMR Parser, returns the AU size of the Frame 104 * @note This function takes the stream type and the frametype and returns the 105 * frame lenght 106 * @param frameType(IN) : AMR frame type 107 * @param streamType(IN) : AMR stream type NB or WB 108 * @returns The frame size based on the frame type. 109 ****************************************************************************** 110 */ 111 M4OSA_UInt32 M4AMRR_getAuSize(M4OSA_UInt32 frameType, M4SYS_StreamType streamType) 112 { 113 const M4OSA_UInt32 M4AMRR_NB_AUSIZE[]={13,14,16,18,20,21,27,32,6,6,6}; 114 const M4OSA_UInt32 M4AMRR_WB_AUSIZE[]={18,24,33,37,41,47,51,59,61,6}; 115 116 if ( streamType == M4SYS_kAMR ) 117 { 118 return M4AMRR_NB_AUSIZE[frameType]; 119 } 120 else /* M4SYS_kAMR_WB */ 121 { 122 return M4AMRR_WB_AUSIZE[frameType]; 123 } 124 } 125 126 /** 127 ****************************************************************************** 128 * M4OSA_UInt32 M4AMRR_getBitrate(M4OSA_UInt32 frameType, M4SYS_StreamType streamType) 129 * @brief Internal function to the AMR Parser, returns the Bit rate of the Frame 130 * @note This function takes the stream type and the frametype and returns the 131 * bit rate for the given frame. 132 * @param frameType(IN) : AMR frame type 133 * @param streamType(IN) : AMR stream type NB or WB 134 * @returns The frame's bit rate based on the frame type. 135 ****************************************************************************** 136 */ 137 M4OSA_UInt32 M4AMRR_getBitrate(M4OSA_UInt32 frameType, M4SYS_StreamType streamType) 138 { 139 const M4OSA_UInt32 M4AMRR_NB_BITRATE[]= 140 {4750,5150,5900,6700,7400,7950,10200,12200,12200,12200,12200}; 141 const M4OSA_UInt32 M4AMRR_WB_BITRATE[]= 142 {6600,8850,12650,14250,15850,18250,19850,23050,23850,12200}; 143 144 if ( streamType == M4SYS_kAMR ) 145 { 146 return M4AMRR_NB_BITRATE[frameType]; 147 } 148 else /* M4SYS_kAMR_WB */ 149 { 150 return M4AMRR_WB_BITRATE[frameType]; 151 } 152 } 153 154 /*********************************************************/ 155 M4OSA_ERR M4AMRR_openRead(M4OSA_Context* pContext, M4OSA_Void* pFileDescriptor, 156 M4OSA_FileReadPointer* pFileFunction) 157 /*********************************************************/ 158 { 159 M4_AMRR_Context* pStreamContext; 160 M4OSA_FilePosition filePos; 161 162 M4OSA_ERR err = M4ERR_FILE_NOT_FOUND ; 163 M4OSA_UInt32 size ; 164 M4OSA_UInt32 data ; 165 M4OSA_Char *M4_Token; 166 M4OSA_UInt32 *tokenPtr; 167 168 /* Header for AMR NB */ 169 M4OSA_UInt32 M4_AMR_1 = 0x4d412123; 170 M4OSA_UInt32 M4_AMR_NB_2 = 0x00000a52; 171 172 /* Header for AMR WB */ 173 M4OSA_UInt32 M4_AMR_WB_2 = 0x42572d52; 174 M4OSA_UInt32 M4_AMR_WB_3 = 0x0000000a; 175 *pContext = M4OSA_NULL ; 176 177 M4OSA_DEBUG_IF2((M4OSA_NULL == pContext),M4ERR_PARAMETER,"Context M4OSA_NULL"); 178 M4OSA_DEBUG_IF2((M4OSA_NULL == pFileDescriptor),M4ERR_PARAMETER,"File Desc. M4OSA_NULL"); 179 180 M4_Token = (M4OSA_Char*)M4OSA_32bitAlignedMalloc(sizeof(M4OSA_MemAddr32)*3, M4AMR_READER, 181 (M4OSA_Char *)("M4_Token")); 182 if(M4OSA_NULL == M4_Token) 183 { 184 M4OSA_DEBUG_IF3((M4OSA_NULL == M4_Token),M4ERR_ALLOC,"Mem Alloc failed - M4_Token"); 185 return M4ERR_ALLOC ; 186 } 187 188 pStreamContext= (M4_AMRR_Context*)M4OSA_32bitAlignedMalloc(sizeof(M4_AMRR_Context), M4AMR_READER, 189 (M4OSA_Char *)("pStreamContext")); 190 if(M4OSA_NULL == pStreamContext) 191 { 192 free(M4_Token); 193 *pContext = M4OSA_NULL ; 194 return M4ERR_ALLOC ; 195 } 196 197 /* Initialize the context */ 198 pStreamContext->m_contextId = M4AMRR_CONTEXTID; 199 pStreamContext->m_structSize=sizeof(M4_AMRR_Context); 200 pStreamContext->m_pOsaFilePtrFct=pFileFunction ; 201 pStreamContext->m_pStreamHandler = M4OSA_NULL ; 202 pStreamContext->m_pAMRFile = M4OSA_NULL ; 203 pStreamContext->m_status = M4AMRR_kOpening ; 204 pStreamContext->m_pSeekIndex = M4OSA_NULL ; 205 pStreamContext->m_seekInterval = 0; 206 pStreamContext->m_maxAuSize = 0 ; 207 pStreamContext->m_pdataAddress = M4OSA_NULL; 208 err=pStreamContext->m_pOsaFilePtrFct->openRead(&pStreamContext->m_pAMRFile, 209 (M4OSA_Char*)pFileDescriptor,M4OSA_kFileRead ); 210 if ( err != M4NO_ERROR ) 211 { 212 /* M4OSA_DEBUG_IF3((err != M4NO_ERROR),err,"File open failed"); */ 213 free(pStreamContext); 214 free(M4_Token); 215 *pContext = M4OSA_NULL ; 216 return err ; 217 } 218 219 pStreamContext->m_status = M4AMRR_kOpening ; 220 221 size = 6; 222 pStreamContext->m_pOsaFilePtrFct->readData(pStreamContext->m_pAMRFile, 223 (M4OSA_MemAddr8)M4_Token, &size); 224 if(size != 6) 225 { 226 goto cleanup; 227 } 228 229 tokenPtr = (M4OSA_UInt32*)M4_Token ; 230 /* Check for the first 4 bytes of the header common to WB and NB*/ 231 if (*tokenPtr != M4_AMR_1) 232 { 233 goto cleanup; 234 } 235 236 tokenPtr++; 237 data = *tokenPtr & 0x0000FFFF ; 238 /* Check if the next part is Narrow band header */ 239 if (data!= M4_AMR_NB_2) 240 { 241 /* Stream is AMR Wide Band */ 242 filePos = 4; 243 pStreamContext->m_pOsaFilePtrFct->seek(pStreamContext->m_pAMRFile, 244 M4OSA_kFileSeekBeginning, &filePos); 245 size = 5; 246 pStreamContext->m_pOsaFilePtrFct->readData(pStreamContext->m_pAMRFile, 247 (M4OSA_MemAddr8)M4_Token, &size); 248 if(size != 5) 249 goto cleanup; 250 tokenPtr=(M4OSA_UInt32*)M4_Token; 251 /* Check for the Wide band hader */ 252 if(*tokenPtr!= M4_AMR_WB_2) 253 goto cleanup; 254 tokenPtr++; 255 data = *tokenPtr & 0x000000FF ; 256 if(data!= M4_AMR_WB_3) 257 goto cleanup; 258 pStreamContext->m_streamType = M4SYS_kAMR_WB ; 259 } 260 else 261 { 262 /* Stream is a Narrow band stream */ 263 pStreamContext->m_streamType = M4SYS_kAMR ; 264 } 265 /* No Profile level defined */ 266 pStreamContext->m_status = M4AMRR_kOpened; 267 268 free(M4_Token); 269 *pContext = pStreamContext ; 270 return M4NO_ERROR; 271 272 cleanup: 273 274 if(M4OSA_NULL != pStreamContext->m_pAMRFile) 275 { 276 pStreamContext->m_pOsaFilePtrFct->closeRead(pStreamContext->m_pAMRFile); 277 } 278 279 free(M4_Token); 280 free(pStreamContext); 281 282 *pContext = M4OSA_NULL ; 283 284 return (M4OSA_ERR)M4ERR_AMR_NOT_COMPLIANT; 285 } 286 287 288 /*********************************************************/ 289 M4OSA_ERR M4AMRR_getNextStream(M4OSA_Context Context, M4SYS_StreamDescription* pStreamDesc ) 290 /*********************************************************/ 291 { 292 M4_AMRR_Context* pStreamContext=(M4_AMRR_Context*)Context; 293 M4OSA_Char frameHeader, frameType ; 294 M4OSA_UInt32 size, auCount=0; 295 M4OSA_FilePosition filePos; 296 297 M4OSA_DEBUG_IF2((M4OSA_NULL == Context),M4ERR_PARAMETER,"Context M4OSA_NULL"); 298 M4OSA_DEBUG_IF2((M4OSA_NULL == pStreamDesc),M4ERR_PARAMETER,"Stream Desc. M4OSA_NULL"); 299 M4OSA_DEBUG_IF2((pStreamContext->m_contextId != M4AMRR_CONTEXTID),M4ERR_BAD_CONTEXT, 300 "Bad Context"); 301 M4OSA_DEBUG_IF1(( pStreamContext->m_status != M4AMRR_kOpened), M4ERR_STATE, "Invalid State"); 302 303 if (M4OSA_NULL != pStreamContext->m_pStreamHandler) 304 { 305 return M4WAR_NO_MORE_STREAM ; 306 } 307 308 size = 1; 309 pStreamContext->m_pOsaFilePtrFct->readData(pStreamContext->m_pAMRFile, 310 (M4OSA_MemAddr8)&frameHeader, &size); 311 312 /* XFFF FXXX -> F is the Frame type */ 313 frameType = ( frameHeader & 0x78 ) >> 3 ; 314 315 if ( frameType == 15 ) 316 { 317 return M4WAR_NO_DATA_YET ; 318 } 319 320 if (( pStreamContext->m_streamType == M4SYS_kAMR ) && ( frameType > 11 )) 321 { 322 return (M4OSA_ERR)M4ERR_AMR_INVALID_FRAME_TYPE; 323 } 324 325 if (( pStreamContext->m_streamType == M4SYS_kAMR_WB ) && ( frameType > 9 )) 326 { 327 return (M4OSA_ERR)M4ERR_AMR_INVALID_FRAME_TYPE; 328 } 329 330 /* Average bit rate is assigned the bitrate of the first frame */ 331 pStreamDesc->averageBitrate = M4AMRR_getBitrate(frameType,pStreamContext->m_streamType); 332 333 filePos = -1; 334 pStreamContext->m_pOsaFilePtrFct->seek(pStreamContext->m_pAMRFile, M4OSA_kFileSeekCurrent, 335 &filePos); 336 337 /* Initialize pStreamDesc */ 338 pStreamDesc->profileLevel = 0xFF ; 339 pStreamDesc->decoderSpecificInfoSize = 0 ; 340 pStreamDesc->decoderSpecificInfo = M4OSA_NULL ; 341 pStreamDesc->maxBitrate = (pStreamContext->m_streamType == 342 M4SYS_kAMR )?M4AMRR_NB_MAX_BIT_RATE:M4AMRR_WB_MAX_BIT_RATE; 343 pStreamDesc->profileLevel = 0xFF ; 344 pStreamDesc->streamID = 1; 345 pStreamDesc->streamType = pStreamContext->m_streamType; 346 347 /* Timescale equals Sampling Frequency: NB-8000 Hz, WB-16000 Hz */ 348 pStreamDesc->timeScale = (pStreamContext->m_streamType == M4SYS_kAMR )?8000:16000; 349 pStreamDesc->duration = M4OSA_TIME_UNKNOWN; 350 351 pStreamContext->m_pStreamHandler = 352 (M4SYS_StreamDescription*)M4OSA_32bitAlignedMalloc(sizeof(M4SYS_StreamDescription), 353 M4AMR_READER, (M4OSA_Char *)("pStreamContext->m_pStreamHandler")); 354 if(M4OSA_NULL == pStreamContext->m_pStreamHandler) 355 { 356 return M4ERR_ALLOC; 357 } 358 359 /* Copy the Stream Desc. into the Context */ 360 pStreamContext->m_pStreamHandler->averageBitrate = pStreamDesc->averageBitrate; 361 pStreamContext->m_pStreamHandler->decoderSpecificInfo = M4OSA_NULL ; 362 pStreamContext->m_pStreamHandler->decoderSpecificInfoSize = 0 ; 363 pStreamContext->m_pStreamHandler->duration = M4OSA_TIME_UNKNOWN; 364 pStreamContext->m_pStreamHandler->profileLevel = 0xFF ; 365 pStreamContext->m_pStreamHandler->streamID = 1; 366 pStreamContext->m_pStreamHandler->streamType = pStreamDesc->streamType ; 367 pStreamContext->m_pStreamHandler->timeScale = pStreamDesc->timeScale ; 368 369 /* Count the number of Access Unit in the File to get the */ 370 /* duration of the stream = 20 ms * number of access unit */ 371 while(1) 372 { 373 size = 1; 374 pStreamContext->m_pOsaFilePtrFct->readData(pStreamContext->m_pAMRFile, 375 (M4OSA_MemAddr8)&frameHeader, &size); 376 if ( size == 0) 377 break ; 378 frameType = (frameHeader & 0x78) >> 3 ; 379 /* Get the frame size and skip so many bytes */ 380 if(frameType != 15){ 381 /* GLA 20050628 when frametype is >10 we read over a table */ 382 if(frameType > 10) 383 continue ; 384 385 size = M4AMRR_getAuSize(frameType, pStreamContext->m_streamType); 386 if(size > pStreamContext->m_maxAuSize ) 387 { 388 pStreamContext->m_maxAuSize = size ; 389 } 390 filePos = size-1; 391 pStreamContext->m_pOsaFilePtrFct->seek(pStreamContext->m_pAMRFile, 392 M4OSA_kFileSeekCurrent, &filePos); 393 auCount++; 394 } 395 } 396 397 /* Each Frame is 20 m Sec. */ 398 pStreamContext->m_pStreamHandler->duration = auCount * M4AMRR_FRAME_LENGTH ; 399 pStreamDesc->duration = pStreamContext->m_pStreamHandler->duration ; 400 401 /* Put the file pointer back at the first Access unit */ 402 if( pStreamContext->m_streamType == M4SYS_kAMR ) 403 { 404 filePos = 6; 405 pStreamContext->m_pOsaFilePtrFct->seek(pStreamContext->m_pAMRFile, 406 M4OSA_kFileSeekBeginning, &filePos); 407 } 408 if ( pStreamContext->m_streamType == M4SYS_kAMR_WB ) 409 { 410 filePos = 9; 411 pStreamContext->m_pOsaFilePtrFct->seek(pStreamContext->m_pAMRFile, 412 M4OSA_kFileSeekBeginning, &filePos); 413 } 414 return M4NO_ERROR ; 415 } 416 417 /*********************************************************/ 418 M4OSA_ERR M4AMRR_startReading(M4OSA_Context Context, M4SYS_StreamID* pStreamIDs ) 419 /*********************************************************/ 420 { 421 M4_AMRR_Context* pStreamContext=(M4_AMRR_Context*)Context; 422 M4OSA_Int32 size = 0 ; 423 424 M4OSA_DEBUG_IF2((M4OSA_NULL == Context),M4ERR_PARAMETER,"Context M4OSA_NULL"); 425 M4OSA_DEBUG_IF2((M4OSA_NULL == pStreamIDs),M4ERR_PARAMETER,"Stream Ids. M4OSA_NULL"); 426 M4OSA_DEBUG_IF2((pStreamContext->m_contextId != M4AMRR_CONTEXTID),M4ERR_BAD_CONTEXT, 427 "Bad Context"); 428 M4OSA_DEBUG_IF1(( pStreamContext->m_status != M4AMRR_kOpened), M4ERR_STATE, "Invalid State"); 429 430 while( pStreamIDs[size] != 0 ) 431 { 432 if( pStreamIDs[size++] != 1 ) 433 { 434 return M4ERR_BAD_STREAM_ID ; 435 } 436 } 437 438 /* Allocate memory for data Address for use in NextAU() */ 439 if(M4OSA_NULL == pStreamContext->m_pdataAddress) 440 { 441 size = pStreamContext->m_maxAuSize ; 442 /* dataAddress is owned by Parser, application should not delete or free it */ 443 pStreamContext->m_pdataAddress =(M4OSA_MemAddr32)M4OSA_32bitAlignedMalloc(size + (4 - size % 4), 444 M4AMR_READER, (M4OSA_Char *)("pStreamContext->m_pdataAddress")); 445 if(M4OSA_NULL == pStreamContext->m_pdataAddress) 446 { 447 M4OSA_DEBUG_IF3((M4OSA_NULL == pStreamContext->m_pdataAddress),M4ERR_ALLOC, 448 "Mem Alloc failed - dataAddress"); 449 return M4ERR_ALLOC; 450 } 451 } 452 453 /* Set the state of context to Reading */ 454 pStreamContext->m_status = M4AMRR_kReading ; 455 456 return M4NO_ERROR ; 457 } 458 459 460 /*********************************************************/ 461 M4OSA_ERR M4AMRR_nextAU(M4OSA_Context Context, M4SYS_StreamID StreamID, M4SYS_AccessUnit* pAu) 462 /*********************************************************/ 463 { 464 M4_AMRR_Context* pStreamContext=(M4_AMRR_Context*)Context; 465 M4OSA_Char frameHeader ; 466 M4OSA_Char frameType ; 467 M4OSA_Int32 auSize; 468 M4OSA_UInt32 size ; 469 M4OSA_FilePosition filePos; 470 471 M4OSA_DEBUG_IF2((M4OSA_NULL == Context),M4ERR_PARAMETER,"Context M4OSA_NULL"); 472 M4OSA_DEBUG_IF2((M4OSA_NULL == pAu),M4ERR_PARAMETER,"Access Unit . M4OSA_NULL"); 473 M4OSA_DEBUG_IF2((pStreamContext->m_contextId != M4AMRR_CONTEXTID),M4ERR_BAD_CONTEXT, 474 "Bad Context"); 475 M4OSA_DEBUG_IF1(( pStreamContext->m_status != M4AMRR_kReading), M4ERR_STATE, "Invalid State"); 476 477 if ( StreamID != 1 ) 478 { 479 return M4ERR_BAD_STREAM_ID; 480 } 481 482 /* Read the frame header byte */ 483 size = pStreamContext->m_maxAuSize; 484 pStreamContext->m_pOsaFilePtrFct->readData(pStreamContext->m_pAMRFile, 485 (M4OSA_MemAddr8)pStreamContext->m_pdataAddress, &size); 486 if(size != pStreamContext->m_maxAuSize) 487 { 488 return M4WAR_NO_MORE_AU; 489 } 490 491 frameHeader = ((M4OSA_MemAddr8)pStreamContext->m_pdataAddress)[0]; 492 493 frameType = ( frameHeader & 0x78 ) >> 3 ; 494 495 if (( pStreamContext->m_streamType == M4SYS_kAMR ) && 496 ( frameType > 11 ) && ( frameType != 15 )) 497 { 498 return (M4OSA_ERR)M4ERR_AMR_INVALID_FRAME_TYPE; 499 } 500 501 if (( pStreamContext->m_streamType == M4SYS_kAMR_WB ) && 502 ( frameType > 9 ) && ( frameType != 15 )) 503 { 504 return (M4OSA_ERR)M4ERR_AMR_INVALID_FRAME_TYPE; 505 } 506 507 /* Get the frame size */ 508 if(frameType == 15) 509 { 510 auSize = 1; 511 } 512 else 513 { 514 auSize = M4AMRR_getAuSize(frameType, pStreamContext->m_streamType); 515 } 516 517 size -= auSize ; 518 if(size != 0) 519 { 520 filePos = -((M4OSA_FilePosition)size); 521 pStreamContext->m_pOsaFilePtrFct->seek(pStreamContext->m_pAMRFile, 522 M4OSA_kFileSeekCurrent, &filePos); 523 } 524 525 pAu->size = auSize ; 526 527 /* even when frameType == 15 (no data frame), ARM core decoder outputs full PCM buffer */ 528 /*if(frameType == 15 ) 529 { 530 pAu->CTS += 0; 531 }*/ 532 /*else*/ 533 { 534 pAu->CTS += M4AMRR_FRAME_LENGTH ; 535 } 536 537 538 pAu->DTS = pAu->CTS ; 539 pAu->attribute = M4SYS_kFragAttrOk; 540 541 pAu->stream = pStreamContext->m_pStreamHandler; 542 pAu->dataAddress = pStreamContext->m_pdataAddress ; 543 544 if(frameHeader & 0x80) 545 { 546 return M4WAR_NO_MORE_AU; 547 } 548 549 /* Change the state to implement NextAu->freeAu->NextAu FSM */ 550 pStreamContext->m_status = M4AMRR_kReading_nextAU ; 551 552 return M4NO_ERROR ; 553 } 554 555 /*********************************************************/ 556 M4OSA_ERR M4AMRR_freeAU(M4OSA_Context Context, M4SYS_StreamID StreamID, M4SYS_AccessUnit* pAu) 557 /*********************************************************/ 558 { 559 M4_AMRR_Context* pStreamContext=(M4_AMRR_Context*)Context; 560 M4OSA_DEBUG_IF2((M4OSA_NULL == Context),M4ERR_PARAMETER,"Context M4OSA_NULL"); 561 M4OSA_DEBUG_IF2((M4OSA_NULL == pAu),M4ERR_PARAMETER,"Access Unit . M4OSA_NULL"); 562 M4OSA_DEBUG_IF2((pStreamContext->m_contextId != M4AMRR_CONTEXTID),M4ERR_BAD_CONTEXT, 563 "Bad Context"); 564 M4OSA_DEBUG_IF1(( pStreamContext->m_status != M4AMRR_kReading_nextAU), M4ERR_STATE, 565 "Invalid State"); 566 567 if (( StreamID != 1 ) && ( StreamID != 0)) 568 { 569 return M4ERR_BAD_STREAM_ID; 570 } 571 572 /* Change the state to Reading so as to allow access to next AU */ 573 pStreamContext->m_status = M4AMRR_kReading ; 574 575 return M4NO_ERROR ; 576 } 577 578 /*********************************************************/ 579 M4OSA_ERR M4AMRR_seek(M4OSA_Context Context, M4SYS_StreamID* pStreamID, M4OSA_Time time, 580 M4SYS_SeekAccessMode seekMode, M4OSA_Time* pObtainCTS) 581 /*********************************************************/ 582 { 583 M4_AMRR_Context* pStreamContext=(M4_AMRR_Context*)Context; 584 M4OSA_UInt32 count, prevAU, nextAU ; 585 M4OSA_UInt32 size ; 586 M4OSA_UInt32 auSize ; 587 M4OSA_UInt32 position, partSeekTime; 588 M4OSA_UInt32 auCount = 0, skipAuCount = 0 ; 589 M4OSA_Char frameHeader ; 590 M4OSA_Char frameType ; 591 M4OSA_FilePosition filePos; 592 M4OSA_Double time_double; 593 594 /*Make explicit time cast, but take care that timescale is not used !!!*/ 595 M4OSA_TIME_TO_MS(time_double, time, 1000); 596 597 *pObtainCTS = 0; 598 599 M4OSA_DEBUG_IF2((M4OSA_NULL == Context),M4ERR_PARAMETER,"Context M4OSA_NULL"); 600 M4OSA_DEBUG_IF2((pStreamContext->m_contextId != M4AMRR_CONTEXTID),M4ERR_BAD_CONTEXT, 601 "Bad Context"); 602 M4OSA_DEBUG_IF1(( pStreamContext->m_status != M4AMRR_kReading) && \ 603 ( pStreamContext->m_status != M4AMRR_kOpened), M4ERR_STATE, "Invalid State"); 604 M4OSA_DEBUG_IF1((time_double < 0),M4ERR_PARAMETER,"negative time"); 605 606 /* Coming to seek for the first time, need to build the seekIndex Table */ 607 if(M4OSA_NULL == pStreamContext->m_pSeekIndex) 608 { 609 M4OSA_Double duration_double; 610 611 count = 0 ; 612 pStreamContext->m_pSeekIndex = 613 (M4OSA_UInt32*)M4OSA_32bitAlignedMalloc(M4AMRR_NUM_SEEK_ENTRIES * sizeof(M4OSA_UInt32), 614 M4AMR_READER, (M4OSA_Char *)("pStreamContext->m_pSeekIndex")); 615 616 if(M4OSA_NULL == pStreamContext->m_pSeekIndex) 617 { 618 M4OSA_DEBUG_IF3((M4OSA_NULL == pStreamContext->m_pSeekIndex),M4ERR_ALLOC, 619 "Mem Alloc Failed - SeekIndex"); 620 return M4ERR_ALLOC ; 621 } 622 623 /* point to the first AU */ 624 if( pStreamContext->m_streamType == M4SYS_kAMR ) 625 { 626 filePos = 6; 627 } 628 else /*if ( pStreamContext->m_streamType == M4SYS_kAMR_WB )*/ 629 { 630 filePos = 9; 631 } 632 633 pStreamContext->m_pOsaFilePtrFct->seek(pStreamContext->m_pAMRFile, 634 M4OSA_kFileSeekBeginning, &filePos); 635 636 /* Set the postion to begining of first AU */ 637 position = (pStreamContext->m_streamType != M4SYS_kAMR)?9:6; 638 639 /*Make explicit time cast, but take care that timescale is not used !!!*/ 640 M4OSA_TIME_TO_MS(duration_double, pStreamContext->m_pStreamHandler->duration, 1000); 641 642 /* Calculate the seek Interval duration based on total dutation */ 643 /* Interval = (duration / ENTRIES) in multiples of AU frame length */ 644 pStreamContext->m_seekInterval = 645 (M4OSA_UInt32)(duration_double / M4AMRR_NUM_SEEK_ENTRIES) ; 646 pStreamContext->m_seekInterval /= M4AMRR_FRAME_LENGTH ; 647 pStreamContext->m_seekInterval *= M4AMRR_FRAME_LENGTH ; 648 skipAuCount = pStreamContext->m_seekInterval / M4AMRR_FRAME_LENGTH ; 649 650 pStreamContext->m_pSeekIndex[count++]=position; 651 while(count < M4AMRR_NUM_SEEK_ENTRIES ) 652 { 653 size = 1; 654 pStreamContext->m_pOsaFilePtrFct->readData(pStreamContext->m_pAMRFile, 655 (M4OSA_MemAddr8)&frameHeader, &size); 656 if ( size == 0) 657 { 658 break ; 659 } 660 frameType = (frameHeader & 0x78) >> 3 ; 661 if(frameType != 15) 662 { 663 /**< bugfix Ronan Cousyn 05/04/2006: In the core reader AMR, the 664 * function M4AMRR_seek doesn't check the frameType */ 665 if (( pStreamContext->m_streamType == M4SYS_kAMR ) && ( frameType > 10 )) 666 { 667 return M4ERR_AMR_INVALID_FRAME_TYPE; 668 } 669 if (( pStreamContext->m_streamType == M4SYS_kAMR_WB ) && ( frameType > 9 )) 670 { 671 return M4ERR_AMR_INVALID_FRAME_TYPE; 672 } 673 auSize = M4AMRR_getAuSize(frameType, pStreamContext->m_streamType); 674 position += auSize ; 675 filePos = auSize-1; 676 pStreamContext->m_pOsaFilePtrFct->seek(pStreamContext->m_pAMRFile, 677 M4OSA_kFileSeekCurrent, &filePos); 678 auCount++; 679 } 680 else 681 { 682 position ++; 683 } 684 /* Skip the number of AU's as per interval and store in the Index table */ 685 if ( (skipAuCount != 0) && !(auCount % skipAuCount)) 686 { 687 pStreamContext->m_pSeekIndex[count++] = position; 688 } 689 } 690 }/* End of Building the seek table */ 691 692 /* Use the seek table to seek the required time in the stream */ 693 694 /* If we are seeking the begining of the file point to first AU */ 695 if ( seekMode == M4SYS_kBeginning ) 696 { 697 if( pStreamContext->m_streamType == M4SYS_kAMR ) 698 { 699 filePos = 6; 700 } 701 else /*if ( pStreamContext->m_streamType == M4SYS_kAMR_WB )*/ 702 { 703 filePos = 9; 704 } 705 pStreamContext->m_pOsaFilePtrFct->seek(pStreamContext->m_pAMRFile, 706 M4OSA_kFileSeekBeginning, &filePos ); 707 return M4NO_ERROR ; 708 } 709 710 /* Get the Nearest Second */ 711 if (0 != pStreamContext->m_seekInterval) 712 { 713 position = (M4OSA_UInt32)(time_double / pStreamContext->m_seekInterval); 714 } 715 else 716 { 717 /*avoid division by 0*/ 718 position = 0; 719 } 720 721 /* We have only 40 seek Index. */ 722 position=(position >= M4AMRR_NUM_SEEK_ENTRIES)?M4AMRR_NUM_SEEK_ENTRIES-1:position; 723 724 /* SeekIndex will point to nearest Au, we need to search for the 725 required time form that position */ 726 partSeekTime = (M4OSA_UInt32)time_double - position * pStreamContext->m_seekInterval; 727 728 position = pStreamContext->m_pSeekIndex[position]; 729 730 if(!position) 731 { 732 return M4WAR_INVALID_TIME ; 733 } 734 735 /* point the file pointer to nearest AU */ 736 filePos = position; 737 pStreamContext->m_pOsaFilePtrFct->seek(pStreamContext->m_pAMRFile, M4OSA_kFileSeekBeginning, 738 &filePos ); 739 740 if ( partSeekTime == 0) 741 { 742 *pObtainCTS = time; 743 return M4NO_ERROR; 744 } 745 746 *pObtainCTS = (M4OSA_Time)(time_double - (M4OSA_Double)partSeekTime); 747 748 switch(seekMode) 749 { 750 /* Get the AU before the target time */ 751 case M4SYS_kPreviousRAP: 752 case M4SYS_kNoRAPprevious: 753 position = partSeekTime / M4AMRR_FRAME_LENGTH ; 754 if ( !(partSeekTime % M4AMRR_FRAME_LENGTH) ) 755 { 756 position -- ; 757 } 758 break; 759 /* Get the Closest AU following the target time */ 760 case M4SYS_kNextRAP: 761 case M4SYS_kNoRAPnext: 762 position = (partSeekTime + M4AMRR_FRAME_LENGTH )/ M4AMRR_FRAME_LENGTH ; 763 break; 764 /* Get the closest AU to target time */ 765 case M4SYS_kClosestRAP: 766 case M4SYS_kNoRAPclosest: 767 prevAU = partSeekTime-(partSeekTime/M4AMRR_FRAME_LENGTH)*M4AMRR_FRAME_LENGTH; 768 nextAU = 769 ((partSeekTime+M4AMRR_FRAME_LENGTH)/M4AMRR_FRAME_LENGTH)*M4AMRR_FRAME_LENGTH -\ 770 partSeekTime ; 771 if(prevAU < nextAU) 772 { 773 position = partSeekTime / M4AMRR_FRAME_LENGTH ; 774 } 775 else 776 { 777 position = (partSeekTime + M4AMRR_FRAME_LENGTH )/ M4AMRR_FRAME_LENGTH ; 778 } 779 break; 780 case M4SYS_kBeginning: 781 break; 782 } 783 784 count = 0 ; 785 /* Skip the Access unit in the stream to skip the part seek time, 786 to reach the required target time */ 787 while(count < position ) 788 { 789 size = 1; 790 pStreamContext->m_pOsaFilePtrFct->readData(pStreamContext->m_pAMRFile, 791 (M4OSA_MemAddr8)&frameHeader, &size); 792 if ( size == 0) 793 { 794 /* If the target time is invalid, point to begining and return */ 795 *pObtainCTS = 0; 796 filePos = pStreamContext->m_pSeekIndex[0]; 797 pStreamContext->m_pOsaFilePtrFct->seek(pStreamContext->m_pAMRFile, 798 M4OSA_kFileSeekBeginning, &filePos); 799 return M4WAR_INVALID_TIME ; 800 } 801 *pObtainCTS += M4AMRR_FRAME_LENGTH; /*Should use M4OSA_INT64_ADD !!*/ 802 count++; 803 frameType = (frameHeader & 0x78) >> 3 ; 804 if(frameType == 15) 805 { 806 auSize = 1 ; 807 } 808 else 809 { 810 auSize = M4AMRR_getAuSize(frameType, pStreamContext->m_streamType); 811 } 812 813 filePos = auSize-1; 814 pStreamContext->m_pOsaFilePtrFct->seek(pStreamContext->m_pAMRFile, 815 M4OSA_kFileSeekCurrent, &filePos); 816 } 817 818 return M4NO_ERROR; 819 } 820 821 /*********************************************************/ 822 M4OSA_ERR M4AMRR_closeRead(M4OSA_Context Context) 823 /*********************************************************/ 824 { 825 M4_AMRR_Context* pStreamContext=(M4_AMRR_Context*)Context; 826 M4OSA_DEBUG_IF2((M4OSA_NULL == Context),M4ERR_PARAMETER,"Context M4OSA_NULL"); 827 828 /* Close the AMR stream */ 829 pStreamContext->m_pOsaFilePtrFct->closeRead(pStreamContext->m_pAMRFile); 830 831 pStreamContext->m_status=M4AMRR_kClosed ; 832 833 /* Check if AU data Address is allocated memory and free it */ 834 if(M4OSA_NULL != pStreamContext->m_pdataAddress) 835 { 836 free(pStreamContext->m_pdataAddress); 837 } 838 839 /* Check if the stream handler is allocated memory */ 840 if(M4OSA_NULL != pStreamContext->m_pStreamHandler) 841 { 842 free(pStreamContext->m_pStreamHandler); 843 } 844 845 /* Seek table is created only when seek is used, so check if memory is allocated */ 846 if(M4OSA_NULL != pStreamContext->m_pSeekIndex) 847 { 848 free(pStreamContext->m_pSeekIndex); 849 } 850 851 /* Free the context */ 852 free(pStreamContext); 853 854 return M4NO_ERROR ; 855 } 856 857 /*********************************************************/ 858 M4OSA_ERR M4AMRR_getState(M4OSA_Context Context, M4AMRR_State* pState, M4SYS_StreamID streamId) 859 /*********************************************************/ 860 { 861 M4_AMRR_Context* pStreamContext=(M4_AMRR_Context*)Context; 862 M4OSA_DEBUG_IF2((M4OSA_NULL == Context),M4ERR_PARAMETER,"Context M4OSA_NULL"); 863 M4OSA_DEBUG_IF2((pStreamContext->m_contextId != M4AMRR_CONTEXTID),M4ERR_BAD_CONTEXT, 864 "Bad Context"); 865 866 if (( streamId != 1 ) && ( streamId != 0)) 867 { 868 return M4ERR_BAD_STREAM_ID; 869 } 870 871 *pState = pStreamContext->m_status ; 872 873 return M4NO_ERROR ; 874 } 875 876 877 /*********************************************************/ 878 M4OSA_ERR M4AMRR_getVersion (M4_VersionInfo *pVersion) 879 /*********************************************************/ 880 { 881 M4OSA_TRACE1_1("M4AMRR_getVersion called with pVersion: 0x%x\n", pVersion); 882 M4OSA_DEBUG_IF1(((M4OSA_UInt32) pVersion == 0),M4ERR_PARAMETER, 883 "pVersion is NULL in M4AMRR_getVersion"); 884 885 pVersion->m_major = M4AMRR_VERSION_MAJOR; 886 pVersion->m_minor = M4AMRR_VERSION_MINOR; 887 pVersion->m_revision = M4AMRR_VERSION_REVISION; 888 889 return M4NO_ERROR; 890 } 891 892 /*********************************************************/ 893 M4OSA_ERR M4AMRR_getmaxAUsize(M4OSA_Context Context, M4OSA_UInt32 *pMaxAuSize) 894 /*********************************************************/ 895 { 896 M4_AMRR_Context* pStreamContext=(M4_AMRR_Context*)Context; 897 898 /** 899 * Check input parameters */ 900 M4OSA_DEBUG_IF1((M4OSA_NULL == Context), M4ERR_PARAMETER, 901 "M4AMRR_getmaxAUsize: Context is M4OSA_NULL"); 902 M4OSA_DEBUG_IF1((M4OSA_NULL == pMaxAuSize),M4ERR_PARAMETER, 903 "M4AMRR_getmaxAUsize: pMaxAuSize is M4OSA_NULL"); 904 905 *pMaxAuSize = pStreamContext->m_maxAuSize; 906 907 return M4NO_ERROR; 908 } 909 910