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