1 /* ------------------------------------------------------------------ 2 * Copyright (C) 1998-2009 PacketVideo 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 13 * express or implied. 14 * See the License for the specific language governing permissions 15 * and limitations under the License. 16 * ------------------------------------------------------------------- 17 */ 18 // -*- c++ -*- 19 // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 20 21 // A M R F I L E P A R S E R 22 23 // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 24 25 26 /** 27 * @file amrfileparser.cpp 28 * @brief This file contains the implementation of the raw GSM-AMR file parser. 29 */ 30 31 //---------------------------------------------------------------------------- 32 // INCLUDES 33 //---------------------------------------------------------------------------- 34 #include "amrfileparser.h" 35 36 // Use default DLL entry point for Symbian 37 #include "oscl_dll.h" 38 OSCL_DLL_ENTRY_POINT_DEFAULT() 39 40 41 /* Table containing the sum of the frame type byte */ 42 /* and the number of speech bytes for each codec mode */ 43 /* for IETF input format */ 44 static const int32 IetfDecInputBytes[NO_POSSIBLE_MODES] = 45 { 46 13, /* 4.75 */ 47 14, /* 5.15 */ 48 16, /* 5.90 */ 49 18, /* 6.70 */ 50 20, /* 7.40 */ 51 21, /* 7.95 */ 52 27, /* 10.2 */ 53 32, /* 12.2 */ 54 6, /* GsmAmr comfort noise */ 55 7, /* Gsm-Efr comfort noise */ 56 6, /* IS-641 comfort noise */ 57 6, /* Pdc-Efr comfort noise */ 58 1, /* future use; 0 length but set to 1 to skip the frame type byte */ 59 1, /* future use; 0 length but set to 1 to skip the frame type byte */ 60 1, /* future use; 0 length but set to 1 to skip the frame type byte */ 61 1 /* No transmission */ 62 }; 63 64 /* Table containing the number of speech bytes for each codec mode */ 65 /* for IF2 input format */ 66 static const int32 If2DecInputBytes[NO_POSSIBLE_MODES] = 67 { 68 13, /* 4.75 */ 69 14, /* 5.15 */ 70 16, /* 5.90 */ 71 18, /* 6.70 */ 72 19, /* 7.40 */ 73 21, /* 7.95 */ 74 26, /* 10.2 */ 75 31, /* 12.2 */ 76 6, /* GsmAmr comfort noise */ 77 6, /* Gsm-Efr comfort noise */ 78 6, /* IS-641 comfort noise */ 79 6, /* Pdc-Efr comfort noise */ 80 1, /* future use; 0 length but set to 1 to skip the frame type byte */ 81 1, /* future use; 0 length but set to 1 to skip the frame type byte */ 82 1, /* future use; 0 length but set to 1 to skip the frame type byte */ 83 1 /* No transmission */ 84 }; 85 86 static const int32 IetfWBDecInputBytes[NO_POSSIBLE_MODES] = 87 { 88 18, /* 6.60 */ 89 24, /* 8.85 */ 90 33, /* 12.65 */ 91 37, /* 14.25 */ 92 41, /* 15.85 */ 93 47, /* 18.25 */ 94 51, /* 19.85 */ 95 59, /* 23.05 */ 96 61, /* 23.85 */ 97 6, /* SID */ 98 1, /* For future use : Set to 1 to skip the frame type byte */ 99 1, /* For future use : Set to 1 to skip the frame type byte */ 100 1, /* For future use : Set to 1 to skip the frame type byte */ 101 1, /* For future use : Set to 1 to skip the frame type byte */ 102 1, /* Speech lost */ 103 1 /* No data/transmission */ 104 }; 105 106 //! specially used in ResetPlayback(), re-position the file pointer 107 int32 bitstreamObject::reset(int32 filePos) 108 { 109 iFrame_type = 0; 110 iBytesRead = iInitFilePos + filePos; // set the initial value 111 iBytesProcessed = iBytesRead; 112 if (ipAMRFile) 113 { 114 ipAMRFile->Seek(iInitFilePos + filePos, Oscl_File::SEEKSET); 115 } 116 iPos = bitstreamObject::MAIN_BUFF_SIZE + bitstreamObject::SECOND_BUFF_SIZE; 117 return refill(); 118 } 119 120 //! read data from bitstream, this is the only function to read data from file 121 int32 bitstreamObject::refill() 122 { 123 PVMF_AMRPARSER_LOGDEBUG((0, "Refill In ipos=%d, iBytesRead=%d, iBytesProcessed=%d, iActualSize=%d, iFileSize=%d", iPos, iBytesRead, iBytesProcessed, iActual_size, iFileSize)); 124 125 if (iBytesRead > 0 && iFileSize > 0 && iBytesRead >= iFileSize) 126 { 127 // if number of bytes read so far exceed the file size, 128 // then first update the file size (PDL case). 129 if (!UpdateFileSize()) return bitstreamObject::MISC_ERROR; 130 131 //At this point we're within 32 bytes of the end of data. 132 //Quit reading data but don't return EOF until all data is processed. 133 if (iBytesProcessed < iBytesRead) 134 { 135 return bitstreamObject::EVERYTHING_OK; 136 } 137 else 138 { 139 //there is no more data to read. 140 if (iBytesRead >= iFileSize || iBytesProcessed >= iFileSize) 141 return bitstreamObject::DATA_INSUFFICIENT; 142 } 143 } 144 145 if (!ipAMRFile) 146 { 147 return bitstreamObject::MISC_ERROR; 148 } 149 150 // Get file size at the very first time 151 if (iFileSize == 0) 152 { 153 if (ipAMRFile->Seek(0, Oscl_File::SEEKEND)) 154 { 155 return bitstreamObject::MISC_ERROR; 156 } 157 158 iFileSize = ipAMRFile->Tell(); 159 160 if (iFileSize <= 0) 161 { 162 return bitstreamObject::MISC_ERROR; 163 } 164 165 if (ipAMRFile->Seek(0, Oscl_File::SEEKSET)) 166 { 167 return bitstreamObject::MISC_ERROR; 168 } 169 170 // first-time read, set the initial value of iPos 171 iPos = bitstreamObject::SECOND_BUFF_SIZE; 172 iBytesProcessed = 0; 173 } 174 // we are currently positioned at the end of the data buffer. 175 else if (iPos == bitstreamObject::MAIN_BUFF_SIZE + bitstreamObject::SECOND_BUFF_SIZE) 176 { 177 // reset iPos and refill from the beginning of the buffer. 178 iPos = bitstreamObject::SECOND_BUFF_SIZE; 179 } 180 181 else if (iPos >= iActual_size) 182 { 183 int32 len = 0; 184 // move the remaining stuff to the beginning of iBuffer 185 if (iActual_size + bitstreamObject::SECOND_BUFF_SIZE > iPos) 186 { 187 // we are currently positioned within SECOND_BUFF_SIZE bytes from the end of the buffer. 188 len = iActual_size + bitstreamObject::SECOND_BUFF_SIZE - iPos; 189 } 190 else 191 { 192 // no leftover data. 193 len = 0; 194 } 195 196 oscl_memcpy(&iBuffer[bitstreamObject::SECOND_BUFF_SIZE-len], &iBuffer[iPos], len); 197 iPos = bitstreamObject::SECOND_BUFF_SIZE - len; 198 199 // update the file size for the PDL scenario where more data has been downloaded 200 // into the file but the file size has not been updated yet. 201 if (iBytesRead + iMax_size > iFileSize) 202 { 203 if (!UpdateFileSize()) return bitstreamObject::MISC_ERROR; 204 } 205 } 206 207 // read data 208 if ((iActual_size = ipAMRFile->Read(&iBuffer[bitstreamObject::SECOND_BUFF_SIZE], 1, iMax_size)) == 0) 209 { 210 return bitstreamObject::READ_ERROR; 211 } 212 213 iBytesRead += iActual_size; 214 215 PVMF_AMRPARSER_LOGDEBUG((0, "Refill Out ipos=%d, iBytesRead=%d, iBytesProcessed=%d, iActualSize=%d, iFileSize=%d", iPos, iBytesRead, iBytesProcessed, iActual_size, iFileSize)); 216 217 return bitstreamObject::EVERYTHING_OK; 218 } 219 220 //! most important function to get one frame data plus frame type, used in getNextBundledAccessUnits() 221 int32 bitstreamObject::getNextFrame(uint8* frameBuffer, uint8& frame_type, bool bHeaderIncluded) 222 { 223 PVMF_AMRPARSER_LOGDEBUG((0, "GetNextFrame In ipos=%d, iBytesRead=%d, iBytesProcessed=%d, iActualSize=%d, iFileSize=%d", iPos, iBytesRead, iBytesProcessed, iActual_size, iFileSize)); 224 if (!frameBuffer) 225 { 226 return bitstreamObject::MISC_ERROR; 227 } 228 229 int32 ret_value = bitstreamObject::EVERYTHING_OK; 230 231 // Need to refill? 232 if (iFileSize == 0 || iPos >= iActual_size) 233 { 234 ret_value = refill(); 235 if (ret_value) 236 { 237 return ret_value; 238 } 239 } 240 241 int32 frame_size = 0; 242 uint8 *pBuffer = &iBuffer[iPos]; 243 244 if (EAMRIETF_SingleNB == iAmrFormat) // IETF format single channel NB 245 { 246 // Search the next IETF frame header (NOT returning error when the error is corrupt) 247 while ((iBuffer[iPos] & 0x83) != 0) 248 { 249 // Wrong IETF frame header(P+FT(4bits)+Q+PP) 250 if (iPos + 1 >= iActual_size) 251 { 252 ret_value = refill(); 253 if (ret_value) 254 { 255 return ret_value; 256 } 257 } 258 iPos++; 259 iBytesProcessed++; 260 } 261 pBuffer = &iBuffer[iPos]; 262 frame_type = (uint8)((pBuffer[0] >> 3) & 0x0f); 263 frame_size = IetfDecInputBytes[(uint16)frame_type]; 264 } 265 else if (EAMRIETF_SingleWB == iAmrFormat) // IETF format single channel WB 266 { 267 frame_type = (uint8)((pBuffer[0] >> 3) & 0x0f); 268 frame_size = IetfWBDecInputBytes[(uint16)frame_type]; 269 } 270 else if (iAmrFormat == EAMRIF2) // IF2 format 271 { 272 frame_type = (uint8)(pBuffer[0] & 0x0f); 273 frame_size = If2DecInputBytes[(uint16)frame_type]; 274 } 275 else 276 { 277 return bitstreamObject::MISC_ERROR; 278 } 279 280 PVMF_AMRPARSER_LOGDEBUG((0, "GetNextFrame Before Read frame ipos=%d, iBytesRead=%d, iBytesProcessed=%d, iActualSize=%d, iFileSize=%d", iPos, iBytesRead, iBytesProcessed, iActual_size, iFileSize)); 281 282 if (frame_size > 0) 283 { 284 if (bHeaderIncluded) 285 { 286 oscl_memcpy(frameBuffer, &pBuffer[0], frame_size); // With frame header 287 } 288 else 289 { 290 oscl_memcpy(frameBuffer, &pBuffer[1], frame_size - 1); // NO frame header 291 } 292 } 293 iPos += frame_size; 294 iBytesProcessed += frame_size; 295 296 PVMF_AMRPARSER_LOGDEBUG((0, "GetNextFrame Out ipos=%d, iBytesRead=%d, iBytesProcessed=%d, iActualSize=%d, iFileSize=%d", iPos, iBytesRead, iBytesProcessed, iActual_size, iFileSize)); 297 return ret_value; 298 } 299 300 //! parse the IETF bitstream header: "$!AMR" + 0x0a, and get format(IETF, IF2, or WMF) 301 int32 bitstreamObject::parseIETFHeader() 302 { 303 int32 returnValue = reset(); 304 if (returnValue == bitstreamObject::EVERYTHING_OK) 305 { 306 iAmrFormat = EAMRUnrecognized; 307 308 // first time read, we don't use iSecond_buffer 309 uint8 *pBuffer = &iBuffer[iPos]; 310 if (iActual_size >= 5 && 311 pBuffer[0] == '#' && 312 pBuffer[1] == '!' && 313 pBuffer[2] == 'A' && 314 pBuffer[3] == 'M' && 315 pBuffer[4] == 'R') 316 { 317 318 if (pBuffer[5] == 0x0a) 319 { 320 // single channel AMR file 321 iAmrFormat = EAMRIETF_SingleNB; 322 iInitFilePos = 6; 323 } 324 325 else if (iActual_size >= 11 && 326 pBuffer[5] == '_' && 327 pBuffer[6] == 'M' && 328 pBuffer[7] == 'C' && 329 pBuffer[8] == '1' && 330 pBuffer[9] == '.' && 331 pBuffer[10] == '0' && 332 pBuffer[11] == 0x0a) 333 { 334 // multi-channel AMR file 335 iAmrFormat = EAMRIETF_MultiNB; 336 iInitFilePos = 12; 337 } 338 else if (iActual_size >= 8 && 339 pBuffer[5] == '-' && 340 pBuffer[6] == 'W' && 341 pBuffer[7] == 'B') 342 { 343 344 if (pBuffer[8] == 0x0a) 345 { 346 // single channel AMR-WB file 347 iAmrFormat = EAMRIETF_SingleWB; 348 iInitFilePos = 9; 349 } 350 else if (iActual_size >= 14 && 351 pBuffer[8] == '_' && 352 pBuffer[9] == 'M' && 353 pBuffer[10] == 'C' && 354 pBuffer[11] == '1' && 355 pBuffer[12] == '.' && 356 pBuffer[13] == '0' && 357 pBuffer[14] == 0x0a) 358 { 359 // multi-channel AMR-WB file 360 iAmrFormat = EAMRIETF_MultiWB; 361 iInitFilePos = 15; 362 } 363 } 364 } 365 iPos += iInitFilePos; 366 iBytesProcessed += iInitFilePos; 367 368 // get the frame header 369 if (iAmrFormat == EAMRUnrecognized) 370 { 371 iFrame_type = iBuffer[iPos] & 0xf; 372 } 373 else // IETF 374 { 375 iFrame_type = (iBuffer[iPos] >> 3) & 0xf; 376 } 377 } 378 379 return returnValue; 380 } 381 382 //! get clip information: file size, format(IETF or IF2) and frame_type(bitrate) 383 int32 bitstreamObject::getFileInfo(int32& fileSize, int32& format, int32& frame_type) 384 { 385 fileSize = format = 0; 386 int32 ret_value = bitstreamObject::EVERYTHING_OK; 387 if (iFileSize == 0) 388 { 389 ret_value = parseIETFHeader(); 390 if (ret_value) 391 { 392 return ret_value; 393 } 394 } 395 396 fileSize = iFileSize; 397 format = iAmrFormat; 398 frame_type = iFrame_type; 399 return ret_value; 400 } 401 402 //! get the updated file size 403 bool bitstreamObject::UpdateFileSize() 404 { 405 if (ipAMRFile != NULL) 406 { 407 uint32 aRemBytes = 0; 408 if (ipAMRFile->GetRemainingBytes(aRemBytes)) 409 { 410 uint32 currPos = (uint32)(ipAMRFile->Tell()); 411 iFileSize = currPos + aRemBytes; 412 return true; 413 } 414 } 415 return false; 416 } 417 418 419 //---------------------------------------------------------------------------- 420 // FUNCTION NAME: CAMRFileParser::CAMRFileParser 421 //---------------------------------------------------------------------------- 422 // INPUT AND OUTPUT DEFINITIONS 423 // 424 // Inputs: 425 // None 426 // 427 // Outputs: 428 // None 429 // 430 // Returns: 431 // None 432 // 433 // Global Variables Used: 434 // None 435 // 436 //---------------------------------------------------------------------------- 437 // FUNCTION DESCRIPTION 438 // 439 // Constructor for CAMRFileParser class 440 //---------------------------------------------------------------------------- 441 // REQUIREMENTS 442 // 443 //---------------------------------------------------------------------------- 444 // REFERENCES 445 // 446 //------------------------------------------------------------------------------ 447 // CAUTION 448 // 449 //------------------------------------------------------------------------------ 450 OSCL_EXPORT_REF CAMRFileParser::CAMRFileParser(void) 451 { 452 iAMRDuration = -1; 453 iAMRBitRate = 0; 454 iTotalNumFramesRead = 0; 455 iAMRFormat = EAMRUnrecognized; 456 iEndOfFileReached = false; 457 iRandomAccessTimeInterval = 0; 458 iCountToClaculateRDATimeInterval = 0; 459 iLogger = PVLogger::GetLoggerObject("pvamr_parser"); 460 iDiagnosticLogger = PVLogger::GetLoggerObject("playerdiagnostics.pvamr_parser"); 461 462 ipBSO = NULL; 463 } 464 465 //---------------------------------------------------------------------------- 466 // FUNCTION NAME: CAMRFileParser::~CAMRFileParser 467 //---------------------------------------------------------------------------- 468 // INPUT AND OUTPUT DEFINITIONS 469 // 470 // Inputs: 471 // None 472 // 473 // Outputs: 474 // None 475 // 476 // Returns: 477 // None 478 // 479 // Global Variables Used: 480 // None 481 // 482 //---------------------------------------------------------------------------- 483 // FUNCTION DESCRIPTION 484 // 485 // Destructor for CAMRFileParser class 486 //---------------------------------------------------------------------------- 487 // REQUIREMENTS 488 // 489 //---------------------------------------------------------------------------- 490 // REFERENCES 491 // 492 //------------------------------------------------------------------------------ 493 // CAUTION 494 // 495 //------------------------------------------------------------------------------ 496 OSCL_EXPORT_REF CAMRFileParser::~CAMRFileParser(void) 497 { 498 iAMRFile.Close(); 499 OSCL_DELETE(ipBSO); 500 ipBSO = NULL; 501 } 502 503 //---------------------------------------------------------------------------- 504 // FUNCTION NAME: CAMRFileParser::InitAMRFile 505 //---------------------------------------------------------------------------- 506 // INPUT AND OUTPUT DEFINITIONS 507 // 508 // Inputs: 509 // iClip = pointer to the AMR file name to be played of type TPtrC 510 // 511 // Outputs: 512 // None 513 // 514 // Returns: 515 // returnValue = true if the init succeeds, else false. 516 // 517 // Global Variables Used: 518 // None 519 // 520 //---------------------------------------------------------------------------- 521 // FUNCTION DESCRIPTION 522 // 523 // This function opens the AMR file, checks for AMR format type, calculates 524 // the track duration, and sets the AMR bitrate value. 525 // 526 //---------------------------------------------------------------------------- 527 // REQUIREMENTS 528 // 529 //---------------------------------------------------------------------------- 530 // REFERENCES 531 // 532 //------------------------------------------------------------------------------ 533 // CAUTION 534 // 535 //------------------------------------------------------------------------------ 536 OSCL_EXPORT_REF bool CAMRFileParser::InitAMRFile(OSCL_wString& aClip, bool aInitParsingEnable, Oscl_FileServer* aFileSession, PVMFCPMPluginAccessInterfaceFactory*aCPM, OsclFileHandle*aHandle, uint32 countToClaculateRDATimeInterval) 537 { 538 iAMRFile.SetCPM(aCPM); 539 iAMRFile.SetFileHandle(aHandle); 540 541 // Open the file (aClip) 542 if (iAMRFile.Open(aClip.get_cstr(), (Oscl_File::MODE_READ | Oscl_File::MODE_BINARY), *aFileSession) != 0) 543 { 544 PVMF_AMRPARSER_LOGERROR((0, "CAMRFileParser::InitAMRFile- File Open failed")); 545 return false; 546 } 547 548 // create ipBSO 549 ipBSO = OSCL_NEW(bitstreamObject, (iLogger, &iAMRFile)); 550 if (!ipBSO) 551 { 552 return false; 553 } 554 if (!ipBSO->get()) 555 { 556 return false; // make sure the memory allocation is going well 557 } 558 559 // get file info 560 int32 frameTypeIndex = 0; 561 if (ipBSO->getFileInfo(iAMRFileSize, iAMRFormat, frameTypeIndex)) 562 { 563 PVMF_AMRPARSER_LOGERROR((0, "CAMRFileParser::InitAMRFile- getFileInfo failed ")); 564 return false; 565 } 566 567 // Reject unsupported AMR file types 568 if (frameTypeIndex >= 16 || 569 iAMRFormat == EAMRETS || 570 iAMRFormat == EAMRIETF_MultiNB || 571 iAMRFormat == EAMRIETF_MultiWB || 572 iAMRFormat == EAMRWMF || 573 iAMRFormat == EAMRUnrecognized) 574 { 575 PVMF_AMRPARSER_LOGERROR((0, "CAMRFileParser::Unsupported AMR type ")); 576 return false; 577 } 578 579 // Set bitrate 580 if (EAMRIETF_SingleWB != iAMRFormat) 581 { 582 AMRFF_Frame_Type_3GPP frameType3GPP = (AMRFF_Frame_Type_3GPP)frameTypeIndex; 583 SetBitRate(frameType3GPP); 584 } 585 else // for wide band 586 { 587 AMRFF_WB_Frame_Type_3GPP frameType3GPP = (AMRFF_WB_Frame_Type_3GPP)frameTypeIndex; 588 SetBitRate(frameType3GPP); 589 } 590 591 // Determine file duration and set up random positioning table if needed 592 CalculateDuration(aInitParsingEnable, countToClaculateRDATimeInterval); 593 return true; 594 } 595 596 bool CAMRFileParser::CalculateDuration(bool aInitParsingEnable, uint32 countToClaculateRDATimeInterval) 597 { 598 iCountToClaculateRDATimeInterval = countToClaculateRDATimeInterval; 599 uint32 FrameCount = iCountToClaculateRDATimeInterval; 600 iRandomAccessTimeInterval = countToClaculateRDATimeInterval * TIME_STAMP_PER_FRAME; 601 602 if (aInitParsingEnable) 603 { 604 // Go through each frame to calculate AMR file duration. 605 int32 status = bitstreamObject::EVERYTHING_OK; 606 uint8 frame_type = 15; 607 iAMRDuration = 0; 608 609 int32 error = 0; 610 611 int32 filePos = 0; 612 613 OSCL_TRY(error, iRPTable.push_back(filePos)); 614 OSCL_FIRST_CATCH_ANY(error, return false); 615 616 while (status == bitstreamObject::EVERYTHING_OK) 617 { 618 // get the next frame 619 620 status = ipBSO->getNextFrame(iAMRFrameBuffer, frame_type); // NO IETF frame header 621 622 if (status == bitstreamObject::EVERYTHING_OK) 623 { 624 // calculate the number of frames // BX 625 iAMRDuration += TIME_STAMP_PER_FRAME; 626 627 // set up the table for randow positioning 628 int32 frame_length = 0; 629 630 if (iAMRFormat == EAMRIF2) 631 { 632 frame_length = If2DecInputBytes[(uint16)frame_type]; 633 } 634 else if (iAMRFormat == EAMRIETF_SingleNB) 635 { 636 frame_length = IetfDecInputBytes[(uint16)frame_type]; 637 } 638 else if (EAMRIETF_SingleWB == iAMRFormat) 639 { 640 frame_length = IetfWBDecInputBytes[(uint16)frame_type]; 641 } 642 else 643 { 644 PVMF_AMRPARSER_LOGERROR((0, "CAMRFileParser::CalculateDuration- Format unknown")); 645 return false; 646 } 647 648 filePos += frame_length; 649 650 error = 0; 651 if (!FrameCount) 652 { 653 OSCL_TRY(error, iRPTable.push_back(filePos)); 654 OSCL_FIRST_CATCH_ANY(error, return false); 655 FrameCount = countToClaculateRDATimeInterval; 656 } 657 } 658 659 else if (status == bitstreamObject::END_OF_FILE) 660 { 661 break; 662 } 663 664 else 665 { 666 // error happens! 667 PVMF_AMRPARSER_LOGERROR((0, "CAMRFileParser::getNextFrame Fails Error Code %d", status)); 668 if (ipBSO->reset()) 669 { 670 return false; 671 } 672 673 return false; 674 } 675 FrameCount--; 676 } 677 678 ResetPlayback(0); 679 } 680 return true; 681 } 682 683 //---------------------------------------------------------------------------- 684 // FUNCTION NAME: CAMRFileParser::RetrieveAMRFileInfo 685 //---------------------------------------------------------------------------- 686 // INPUT AND OUTPUT DEFINITIONS 687 // 688 // Inputs: 689 // aMedia = pointer to CPVMedia class 690 // aTrackId = pointer to the ID specific to the current AMR track 691 // aTimescale = pointer to the sampling frequency value, for AMR it is 8000 Hz. 692 // 693 // Outputs: 694 // None 695 // 696 // Returns: 697 // false if an error happens, else true 698 // 699 // Global Variables Used: 700 // None 701 // 702 //---------------------------------------------------------------------------- 703 // FUNCTION DESCRIPTION 704 // 705 // This function opens the AMR file, checks for AMR format type, calculates 706 // the track duration, and sets the AMR bitrate value. 707 // 708 //---------------------------------------------------------------------------- 709 // REQUIREMENTS 710 // 711 //---------------------------------------------------------------------------- 712 // REFERENCES 713 // 714 //------------------------------------------------------------------------------ 715 // CAUTION 716 // 717 //------------------------------------------------------------------------------ 718 OSCL_EXPORT_REF bool CAMRFileParser::RetrieveFileInfo(TPVAmrFileInfo& aInfo) 719 { 720 if (iAMRFormat == EAMRUnrecognized) 721 { 722 // File is not open and parsed 723 return false; 724 } 725 726 aInfo.iBitrate = iAMRBitRate; 727 aInfo.iTimescale = 1000; 728 aInfo.iDuration = iAMRDuration; 729 aInfo.iFileSize = iAMRFileSize; 730 aInfo.iAmrFormat = iAMRFormat; 731 PVMF_AMRPARSER_LOGDIAGNOSTICS((0, "CAMRFileParser::RetrieveFileInfo- duration = %d, bitrate = %d, filesize = %d", iAMRDuration, iAMRBitRate, iAMRFileSize)); 732 733 return true; 734 } 735 736 737 //---------------------------------------------------------------------------- 738 // FUNCTION NAME: CAMRFileParser::SetBitRate 739 //---------------------------------------------------------------------------- 740 // INPUT AND OUTPUT DEFINITIONS 741 // 742 // Inputs: 743 // aFrameType3GPP = 3GPP frame type for the AMR frame of type AMRFF_Frame_Type_3GPP 744 // 745 // Outputs: 746 // None 747 // 748 // Returns: 749 // None 750 // 751 // Global Variables Used: 752 // None 753 // 754 //---------------------------------------------------------------------------- 755 // FUNCTION DESCRIPTION 756 // 757 // This function takes in the 3GPP frametype and sets the AMR bitrate value 758 // depending on the AMR frametype. 759 // 760 //---------------------------------------------------------------------------- 761 // REQUIREMENTS 762 // 763 //---------------------------------------------------------------------------- 764 // REFERENCES 765 // 766 //------------------------------------------------------------------------------ 767 // CAUTION 768 // 769 //------------------------------------------------------------------------------ 770 void CAMRFileParser::SetBitRate(AMRFF_Frame_Type_3GPP aFrameType3GPP) 771 { 772 switch (aFrameType3GPP) 773 { 774 case AMRFF_AMR_475: 775 { 776 iAMRBitRate = 4750; 777 break; 778 } 779 case AMRFF_AMR_515: 780 { 781 iAMRBitRate = 5150; 782 break; 783 } 784 case AMRFF_AMR_59: 785 { 786 iAMRBitRate = 5900; 787 break; 788 } 789 case AMRFF_AMR_67: 790 { 791 iAMRBitRate = 6700; 792 break; 793 } 794 case AMRFF_AMR_74: 795 { 796 iAMRBitRate = 7400; 797 break; 798 } 799 case AMRFF_AMR_795: 800 { 801 iAMRBitRate = 7950; 802 break; 803 } 804 case AMRFF_AMR_102: 805 { 806 iAMRBitRate = 10200; 807 break; 808 } 809 case AMRFF_AMR_122: 810 { 811 iAMRBitRate = 12200; 812 break; 813 } 814 default: 815 { 816 iAMRBitRate = 0; 817 break; 818 } 819 } 820 return; 821 } 822 823 824 void CAMRFileParser::SetBitRate(AMRFF_WB_Frame_Type_3GPP aFrameType3GPP) 825 { 826 switch (aFrameType3GPP) 827 { 828 case AMRFF_WB_660: 829 { 830 iAMRBitRate = 6600; 831 break; 832 } 833 case AMRFF_WB_885: 834 { 835 iAMRBitRate = 8850; 836 break; 837 } 838 case AMRFF_WB_1265: 839 { 840 iAMRBitRate = 12650; 841 break; 842 } 843 case AMRFF_WB_1425: 844 { 845 iAMRBitRate = 14250; 846 break; 847 } 848 case AMRFF_WB_1585: 849 { 850 iAMRBitRate = 15850; 851 break; 852 } 853 case AMRFF_WB_1825: 854 { 855 iAMRBitRate = 18250; 856 break; 857 } 858 case AMRFF_WB_1985: 859 { 860 iAMRBitRate = 19850; 861 break; 862 } 863 case AMRFF_WB_2305: 864 { 865 iAMRBitRate = 23050; 866 break; 867 } 868 case AMRFF_WB_2385: 869 { 870 iAMRBitRate = 23850; 871 break; 872 } 873 default: 874 { 875 iAMRBitRate = 0; 876 break; 877 } 878 } 879 return; 880 } 881 882 883 884 //---------------------------------------------------------------------------- 885 // FUNCTION NAME: CAMRFileParser::ResetPlayback 886 //---------------------------------------------------------------------------- 887 // INPUT AND OUTPUT DEFINITIONS 888 // 889 // Inputs: 890 // aStartTime = integer value as where to move the playback positioning to. 891 // 892 // Outputs: 893 // None 894 // 895 // Returns: 896 // 0 if success, -1 if failure 897 // 898 // Global Variables Used: 899 // None 900 // 901 //---------------------------------------------------------------------------- 902 // FUNCTION DESCRIPTION 903 // 904 // This function sets the file pointer to the location that aStartTime would 905 // point to in the file. 906 // 907 //---------------------------------------------------------------------------- 908 // REQUIREMENTS 909 // 910 //---------------------------------------------------------------------------- 911 // REFERENCES 912 // 913 //------------------------------------------------------------------------------ 914 // CAUTION 915 // 916 //------------------------------------------------------------------------------ 917 OSCL_EXPORT_REF int32 CAMRFileParser::ResetPlayback(int32 aStartTime) 918 { 919 // get file size info, //iAMRFile.Size(fileSize) 920 int32 result; 921 if (iAMRFileSize <= 0) 922 { 923 int32 frameTypeIndex; 924 if (ipBSO->getFileInfo(iAMRFileSize, iAMRFormat, frameTypeIndex)) 925 { 926 PVMF_AMRPARSER_LOGERROR((0, "CAMRFileParser::Reset Playback Failed")); 927 return bitstreamObject::MISC_ERROR; 928 } 929 } 930 931 iEndOfFileReached = false; 932 // initialize "iTotalNumFramesRead" 933 // note: +1 means we choose the next frame(ts>=aStartTime) 934 iTotalNumFramesRead = aStartTime / TIME_STAMP_PER_FRAME + (aStartTime > 0) * 1; 935 936 uint32 tblIdx = aStartTime / (iRandomAccessTimeInterval);// +(aStartTime>0)*1; 937 iTotalNumFramesRead = tblIdx * iCountToClaculateRDATimeInterval; 938 939 PVMF_AMRPARSER_LOGDIAGNOSTICS((0, "CAMRFileParser::resetplayback - TotalNumFramesRead=%d", iTotalNumFramesRead)); 940 // set new file position 941 int32 newPosition = 0; 942 if (iTotalNumFramesRead > 0) 943 { 944 // At the first time, don't do reset 945 if (iAMRDuration != 0 && iRPTable.size() == 0) 946 { 947 newPosition = (iAMRFileSize * aStartTime) / iAMRDuration; 948 PVMF_AMRPARSER_LOGDIAGNOSTICS((0, "CAMRFileParser::resetplayback - newPosition=%d", newPosition)); 949 if (newPosition < 0) 950 { 951 // if we have no duration information, reset the file position at 0. 952 newPosition = 0; 953 } 954 } 955 else if (iRPTable.size() > 0) 956 { 957 // use the randow positioning table to determine the file position 958 if (tblIdx >= iRPTable.size()) 959 { 960 // Requesting past the end of table so set to (end of table-1) 961 // to be at the last sample 962 tblIdx = ((int32)iRPTable.size()) - 2; 963 } 964 newPosition = iRPTable[tblIdx]; 965 } 966 } 967 result = ipBSO->reset(newPosition); 968 if (newPosition >= 0 && result) 969 { 970 PVMF_AMRPARSER_LOGERROR((0, "AMRBitstreamObject::refill- Misc Error")); 971 return result; 972 } 973 iEndOfFileReached = false; 974 975 return bitstreamObject::EVERYTHING_OK; 976 } 977 978 979 //---------------------------------------------------------------------------- 980 // FUNCTION NAME: CAMRFileParser::SeekPointFromTimestamp 981 //---------------------------------------------------------------------------- 982 // INPUT AND OUTPUT DEFINITIONS 983 // 984 // Inputs: 985 // aStartTime = integer value as for the specified start time 986 // 987 // Outputs: 988 // None 989 // 990 // Returns: 991 // Timestamp in milliseconds of the actual position 992 // 993 // Global Variables Used: 994 // None 995 // 996 //---------------------------------------------------------------------------- 997 // FUNCTION DESCRIPTION 998 // 999 // This function returns the timestamp for an actual position corresponding 1000 // to the specified start time 1001 // 1002 //---------------------------------------------------------------------------- 1003 // REQUIREMENTS 1004 // 1005 //---------------------------------------------------------------------------- 1006 // REFERENCES 1007 // 1008 //------------------------------------------------------------------------------ 1009 // CAUTION 1010 // 1011 //------------------------------------------------------------------------------ 1012 OSCL_EXPORT_REF uint32 CAMRFileParser::SeekPointFromTimestamp(uint32 aStartTime) 1013 { 1014 // get file size info, //iAMRFile.Size(fileSize) 1015 if (iAMRFileSize <= 0) 1016 { 1017 int32 frameTypeIndex; 1018 if (ipBSO->getFileInfo(iAMRFileSize, iAMRFormat, frameTypeIndex)) 1019 { 1020 return 0; 1021 } 1022 } 1023 1024 // Determine the frame number corresponding to timestamp 1025 // note: +1 means we choose the next frame(ts>=aStartTime) 1026 uint32 startframenum = aStartTime / TIME_STAMP_PER_FRAME + (aStartTime > 0) * 1; 1027 1028 // Correct the frame number if necessary 1029 if (startframenum > 0) 1030 { 1031 if (iAMRDuration != 0 && iRPTable.size() <= 0) 1032 { 1033 // Duration not known and reposition table not available so go to first frame 1034 startframenum = 0; 1035 } 1036 else if (iRPTable.size() > 0) 1037 { 1038 if (startframenum >= iRPTable.size()) 1039 { 1040 // Requesting past the end of table so set to (end of table-1) 1041 // to be at the last sample 1042 startframenum = ((int32)iRPTable.size()) - 2; 1043 } 1044 } 1045 } 1046 1047 return (startframenum*TIME_STAMP_PER_FRAME); 1048 } 1049 1050 //---------------------------------------------------------------------------- 1051 // FUNCTION NAME: CAMRFileParser::GetNextBundledAccessUnits 1052 //---------------------------------------------------------------------------- 1053 // INPUT AND OUTPUT DEFINITIONS 1054 // 1055 // Inputs: 1056 // aNumSamples = requested number of frames to be read from file 1057 // aGau = frame information structure of type GAU 1058 // 1059 // Outputs: 1060 // None 1061 // 1062 // Returns: 1063 // 0 if success, -1 if failure 1064 // 1065 // Global Variables Used: 1066 // None 1067 // 1068 //---------------------------------------------------------------------------- 1069 // FUNCTION DESCRIPTION 1070 // 1071 // This function attempts to read in the number of AMR frames specified by 1072 // aNumSamples. It formats the read data to WMF bit order and stores it in 1073 // the GAU structure. 1074 // 1075 //---------------------------------------------------------------------------- 1076 // REQUIREMENTS 1077 // 1078 //---------------------------------------------------------------------------- 1079 // REFERENCES 1080 // 1081 //------------------------------------------------------------------------------ 1082 // CAUTION 1083 // 1084 //------------------------------------------------------------------------------ 1085 OSCL_EXPORT_REF int32 CAMRFileParser::GetNextBundledAccessUnits(uint32 *aNumSamples, GAU *aGau) 1086 { 1087 // AMR format has already been identified in InitAMRFile function. 1088 // Check if AMR format is valid as the safeguard 1089 if (iAMRFormat == EAMRUnrecognized) 1090 { 1091 PVMF_AMRPARSER_LOGERROR((0, "CAMRFileParser::GetNextBundledAccessUnits Failed - Unrecognized format")); 1092 return bitstreamObject::MISC_ERROR; 1093 } 1094 1095 // Check the requested number of frames is not greater than the max supported 1096 if (*aNumSamples > MAX_NUM_FRAMES_PER_BUFF) 1097 { 1098 PVMF_AMRPARSER_LOGERROR((0, "CAMRFileParser::GetNextBundledAccessUnits Failed - requested number of frames is greater than the max supported")); 1099 return bitstreamObject::MISC_ERROR; 1100 } 1101 1102 int32 returnValue = bitstreamObject::EVERYTHING_OK; 1103 1104 if (iEndOfFileReached) 1105 { 1106 *aNumSamples = 0; 1107 return bitstreamObject::END_OF_FILE; 1108 } 1109 1110 uint8* pTempGau = (uint8 *) aGau->buf.fragments[0].ptr; 1111 uint32 gauBufferSize = aGau->buf.fragments[0].len; 1112 uint32 i, bytesReadInGau = 0, numSamplesRead = 0; 1113 1114 for (i = 0; i < *aNumSamples && !iEndOfFileReached; i++) 1115 { 1116 // get the next frame 1117 bool bHeaderIncluded = true; 1118 returnValue = ipBSO->getNextFrame(iAMRFrameBuffer, iAMRFrameHeaderBuffer[i], bHeaderIncluded); 1119 if (returnValue == bitstreamObject::END_OF_FILE) 1120 { 1121 iEndOfFileReached = true; 1122 break; 1123 } 1124 else if (returnValue == bitstreamObject::EVERYTHING_OK) 1125 1126 { 1127 } 1128 else if (returnValue == bitstreamObject::DATA_INSUFFICIENT) 1129 { 1130 *aNumSamples = 0; 1131 return returnValue; 1132 } 1133 else 1134 { // error happens!! 1135 *aNumSamples = 0; 1136 return bitstreamObject::READ_ERROR; 1137 } 1138 1139 // Now a frame exists in iAMRFrameBuffer, move it to aGau 1140 int32 frame_size = 0; 1141 if (iAMRFormat == EAMRIF2) 1142 { 1143 frame_size = If2DecInputBytes[(uint16)iAMRFrameHeaderBuffer[i]]; 1144 } 1145 else if (iAMRFormat == EAMRIETF_SingleNB) 1146 { 1147 frame_size = IetfDecInputBytes[(uint16)iAMRFrameHeaderBuffer[i]]; 1148 } 1149 else if (iAMRFormat == EAMRIETF_SingleWB) 1150 { 1151 frame_size = IetfWBDecInputBytes[(uint16)iAMRFrameHeaderBuffer[i]]; 1152 } 1153 else 1154 { 1155 PVMF_AMRPARSER_LOGERROR((0, "AMRBitstreamObject::refill- Misc Error")); 1156 return bitstreamObject::MISC_ERROR; 1157 } 1158 1159 // Check whether the gau buffer will be overflow 1160 if (bytesReadInGau + frame_size >= gauBufferSize) 1161 { 1162 // Undo the read 1163 ipBSO->undoGetNextFrame(frame_size); 1164 break; 1165 } 1166 1167 if (frame_size > 0) 1168 { 1169 oscl_memcpy(pTempGau, iAMRFrameBuffer, frame_size); 1170 1171 pTempGau += frame_size; 1172 bytesReadInGau += frame_size; 1173 } 1174 aGau->info[i].len = frame_size; 1175 aGau->info[i].ts = (iTotalNumFramesRead + (numSamplesRead++)) * TIME_STAMP_PER_FRAME; 1176 1177 } // end of: for(i = 0; i < *aNumSamples && !iEndOfFileReached; i++) 1178 1179 aGau->info[0].ts = iTotalNumFramesRead * TIME_STAMP_PER_FRAME; 1180 1181 *aNumSamples = numSamplesRead; 1182 iTotalNumFramesRead += numSamplesRead; 1183 1184 //We may have reached EOF but also found some samples. 1185 //don't return EOF until there are no samples left. 1186 if (returnValue == bitstreamObject::END_OF_FILE 1187 && numSamplesRead > 0) 1188 return bitstreamObject::EVERYTHING_OK; 1189 1190 return returnValue; 1191 } 1192 1193 OSCL_EXPORT_REF int32 CAMRFileParser::PeekNextTimestamp(uint32 *aTimestamp) 1194 { 1195 1196 *aTimestamp = iTotalNumFramesRead * TIME_STAMP_PER_FRAME; 1197 1198 return bitstreamObject::EVERYTHING_OK; 1199 } 1200 1201 1202 OSCL_EXPORT_REF uint8 CAMRFileParser::GetFrameTypeInCurrentBundledAccessUnits(uint32 frameIndex) 1203 { 1204 if (frameIndex >= MAX_NUM_FRAMES_PER_BUFF) 1205 { 1206 return 0; 1207 } 1208 return iAMRFrameHeaderBuffer[frameIndex]; 1209 } 1210 1211 OSCL_EXPORT_REF int32 CAMRFileParser::getTrackMaxBufferSizeDB() 1212 { 1213 if (ipBSO) 1214 { 1215 return ipBSO->getTrackMaxBufferSizeDB(); 1216 } 1217 else 1218 { 1219 return -1; 1220 } 1221 } 1222 1223 1224 OSCL_EXPORT_REF uint8* CAMRFileParser::getCodecSpecificInfo() 1225 { 1226 1227 bool bHeaderIncluded = true; 1228 ipBSO->getNextFrame(iAMRFrameBuffer, iAMRFrameHeaderBuffer[1], bHeaderIncluded); 1229 return iAMRFrameHeaderBuffer; 1230 } 1231 1232 1233