blob: e8618502ab58a7f89e1ca39afd7bb304f2b735e8 [file] [log] [blame]
/* ------------------------------------------------------------------
* Copyright (C) 1998-2009 PacketVideo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied.
* See the License for the specific language governing permissions
* and limitations under the License.
* -------------------------------------------------------------------
*/
// -*- c++ -*-
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
// A M R F I L E P A R S E R
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
/**
* @file amrfileparser.cpp
* @brief This file contains the implementation of the raw GSM-AMR file parser.
*/
//----------------------------------------------------------------------------
// INCLUDES
//----------------------------------------------------------------------------
#include "amrfileparser.h"
// Use default DLL entry point for Symbian
#include "oscl_dll.h"
OSCL_DLL_ENTRY_POINT_DEFAULT()
/* Table containing the sum of the frame type byte */
/* and the number of speech bytes for each codec mode */
/* for IETF input format */
static const int32 IetfDecInputBytes[NO_POSSIBLE_MODES] =
{
13, /* 4.75 */
14, /* 5.15 */
16, /* 5.90 */
18, /* 6.70 */
20, /* 7.40 */
21, /* 7.95 */
27, /* 10.2 */
32, /* 12.2 */
6, /* GsmAmr comfort noise */
7, /* Gsm-Efr comfort noise */
6, /* IS-641 comfort noise */
6, /* Pdc-Efr comfort noise */
1, /* future use; 0 length but set to 1 to skip the frame type byte */
1, /* future use; 0 length but set to 1 to skip the frame type byte */
1, /* future use; 0 length but set to 1 to skip the frame type byte */
1 /* No transmission */
};
/* Table containing the number of speech bytes for each codec mode */
/* for IF2 input format */
static const int32 If2DecInputBytes[NO_POSSIBLE_MODES] =
{
13, /* 4.75 */
14, /* 5.15 */
16, /* 5.90 */
18, /* 6.70 */
19, /* 7.40 */
21, /* 7.95 */
26, /* 10.2 */
31, /* 12.2 */
6, /* GsmAmr comfort noise */
6, /* Gsm-Efr comfort noise */
6, /* IS-641 comfort noise */
6, /* Pdc-Efr comfort noise */
1, /* future use; 0 length but set to 1 to skip the frame type byte */
1, /* future use; 0 length but set to 1 to skip the frame type byte */
1, /* future use; 0 length but set to 1 to skip the frame type byte */
1 /* No transmission */
};
static const int32 IetfWBDecInputBytes[NO_POSSIBLE_MODES] =
{
18, /* 6.60 */
24, /* 8.85 */
33, /* 12.65 */
37, /* 14.25 */
41, /* 15.85 */
47, /* 18.25 */
51, /* 19.85 */
59, /* 23.05 */
61, /* 23.85 */
6, /* SID */
1, /* For future use : Set to 1 to skip the frame type byte */
1, /* For future use : Set to 1 to skip the frame type byte */
1, /* For future use : Set to 1 to skip the frame type byte */
1, /* For future use : Set to 1 to skip the frame type byte */
1, /* Speech lost */
1 /* No data/transmission */
};
//! specially used in ResetPlayback(), re-position the file pointer
int32 bitstreamObject::reset(int32 filePos)
{
iFrame_type = 0;
iBytesRead = iInitFilePos + filePos; // set the initial value
iBytesProcessed = iBytesRead;
if (ipAMRFile)
{
ipAMRFile->Seek(iInitFilePos + filePos, Oscl_File::SEEKSET);
}
iPos = bitstreamObject::MAIN_BUFF_SIZE + bitstreamObject::SECOND_BUFF_SIZE;
return refill();
}
//! read data from bitstream, this is the only function to read data from file
int32 bitstreamObject::refill()
{
if (iBytesRead > 0 && iFileSize > 0 && iBytesRead >= iFileSize)
{
//At this point we're within 32 bytes of the end of data.
//Quit reading data but don't return EOF until all data is processed.
if (iBytesProcessed < iBytesRead)
return bitstreamObject::EVERYTHING_OK;
else
return bitstreamObject::END_OF_FILE;
}
if (!ipAMRFile)
{
return bitstreamObject::MISC_ERROR;
}
// Get file size at the very first time
if (iFileSize == 0)
{
if (ipAMRFile->Seek(0, Oscl_File::SEEKEND))
{
return bitstreamObject::MISC_ERROR;
}
iFileSize = ipAMRFile->Tell();
if (iFileSize <= 0)
{
return bitstreamObject::MISC_ERROR;
}
if (ipAMRFile->Seek(0, Oscl_File::SEEKSET))
{
return bitstreamObject::MISC_ERROR;
}
// first-time read, set the initial value of iPos
iPos = bitstreamObject::SECOND_BUFF_SIZE;
iBytesProcessed = 0;
}
else if (iPos == bitstreamObject::MAIN_BUFF_SIZE + bitstreamObject::SECOND_BUFF_SIZE)
{
// reset iPos and refill from the beginning of the file
iPos = bitstreamObject::SECOND_BUFF_SIZE;
}
else if (iPos >= iActual_size)
{
// move the remaining stuff to the beginning of iBuffer
if (iActual_size < iMax_size)
{
// memory content will be overlapped
return bitstreamObject::MISC_ERROR;
}
int32 len = bitstreamObject::MAIN_BUFF_SIZE + bitstreamObject::SECOND_BUFF_SIZE - iPos;
oscl_memcpy(&iBuffer[bitstreamObject::SECOND_BUFF_SIZE-len], &iBuffer[iPos], len);
iPos = bitstreamObject::SECOND_BUFF_SIZE - len;
}
// read data
if ((iActual_size = ipAMRFile->Read(&iBuffer[bitstreamObject::SECOND_BUFF_SIZE], 1, iMax_size)) == 0)
{
return bitstreamObject::READ_ERROR;
}
iBytesRead += iActual_size;
return bitstreamObject::EVERYTHING_OK;
}
//! most important function to get one frame data plus frame type, used in getNextBundledAccessUnits()
int32 bitstreamObject::getNextFrame(uint8* frameBuffer, uint8& frame_type, bool bHeaderIncluded)
{
if (!frameBuffer)
{
return bitstreamObject::MISC_ERROR;
}
int32 ret_value = bitstreamObject::EVERYTHING_OK;
// Need to refill?
if (iFileSize == 0 || iPos >= iActual_size)
{
ret_value = refill();
if (ret_value)
{
return ret_value;
}
}
int32 frame_size = 0;
uint8 *pBuffer = &iBuffer[iPos];
if (EAMRIETF_SingleNB == iAmrFormat) // IETF format single channel NB
{
// Search the next IETF frame header (NOT returning error when the error is corrupt)
while ((iBuffer[iPos] & 0x83) != 0)
{
// Wrong IETF frame header(P+FT(4bits)+Q+PP)
if (iPos + 1 >= iActual_size)
{
ret_value = refill();
if (ret_value)
{
return ret_value;
}
}
iPos++;
iBytesProcessed++;
}
pBuffer = &iBuffer[iPos];
frame_type = (uint8)((pBuffer[0] >> 3) & 0x0f);
frame_size = IetfDecInputBytes[(uint16)frame_type];
}
else if (EAMRIETF_SingleWB == iAmrFormat) // IETF format single channel WB
{
frame_type = (uint8)((pBuffer[0] >> 3) & 0x0f);
frame_size = IetfWBDecInputBytes[(uint16)frame_type];
}
else if (iAmrFormat == EAMRIF2) // IF2 format
{
frame_type = (uint8)(pBuffer[0] & 0x0f);
frame_size = If2DecInputBytes[(uint16)frame_type];
}
else
{
return bitstreamObject::MISC_ERROR;
}
if (frame_size > 0)
{
if (bHeaderIncluded)
{
oscl_memcpy(frameBuffer, &pBuffer[0], frame_size); // With frame header
}
else
{
oscl_memcpy(frameBuffer, &pBuffer[1], frame_size - 1); // NO frame header
}
}
iPos += frame_size;
iBytesProcessed += frame_size;
return ret_value;
}
//! parse the IETF bitstream header: "$!AMR" + 0x0a, and get format(IETF, IF2, or WMF)
int32 bitstreamObject::parseIETFHeader()
{
int32 returnValue = reset();
if (returnValue == bitstreamObject::EVERYTHING_OK)
{
iAmrFormat = EAMRUnrecognized;
// first time read, we don't use iSecond_buffer
uint8 *pBuffer = &iBuffer[iPos];
if (iActual_size >= 5 &&
pBuffer[0] == '#' &&
pBuffer[1] == '!' &&
pBuffer[2] == 'A' &&
pBuffer[3] == 'M' &&
pBuffer[4] == 'R')
{
if (pBuffer[5] == 0x0a)
{
// single channel AMR file
iAmrFormat = EAMRIETF_SingleNB;
iInitFilePos = 6;
}
else if (iActual_size >= 11 &&
pBuffer[5] == '_' &&
pBuffer[6] == 'M' &&
pBuffer[7] == 'C' &&
pBuffer[8] == '1' &&
pBuffer[9] == '.' &&
pBuffer[10] == '0' &&
pBuffer[11] == 0x0a)
{
// multi-channel AMR file
iAmrFormat = EAMRIETF_MultiNB;
iInitFilePos = 12;
}
else if (iActual_size >= 8 &&
pBuffer[5] == '-' &&
pBuffer[6] == 'W' &&
pBuffer[7] == 'B')
{
if (pBuffer[8] == 0x0a)
{
// single channel AMR-WB file
iAmrFormat = EAMRIETF_SingleWB;
iInitFilePos = 9;
}
else if (iActual_size >= 14 &&
pBuffer[8] == '_' &&
pBuffer[9] == 'M' &&
pBuffer[10] == 'C' &&
pBuffer[11] == '1' &&
pBuffer[12] == '.' &&
pBuffer[13] == '0' &&
pBuffer[14] == 0x0a)
{
// multi-channel AMR-WB file
iAmrFormat = EAMRIETF_MultiWB;
iInitFilePos = 15;
}
}
}
iPos += iInitFilePos;
iBytesProcessed += iInitFilePos;
// get the frame header
if (iAmrFormat == EAMRUnrecognized)
{
iFrame_type = iBuffer[iPos] & 0xf;
}
else // IETF
{
iFrame_type = (iBuffer[iPos] >> 3) & 0xf;
}
}
return returnValue;
}
//! get clip information: file size, format(IETF or IF2) and frame_type(bitrate)
int32 bitstreamObject::getFileInfo(int32& fileSize, int32& format, int32& frame_type)
{
fileSize = format = 0;
int32 ret_value = bitstreamObject::EVERYTHING_OK;
if (iFileSize == 0)
{
ret_value = parseIETFHeader();
if (ret_value)
{
return ret_value;
}
}
fileSize = iFileSize;
format = iAmrFormat;
frame_type = iFrame_type;
return ret_value;
}
//----------------------------------------------------------------------------
// FUNCTION NAME: CAMRFileParser::CAMRFileParser
//----------------------------------------------------------------------------
// INPUT AND OUTPUT DEFINITIONS
//
// Inputs:
// None
//
// Outputs:
// None
//
// Returns:
// None
//
// Global Variables Used:
// None
//
//----------------------------------------------------------------------------
// FUNCTION DESCRIPTION
//
// Constructor for CAMRFileParser class
//----------------------------------------------------------------------------
// REQUIREMENTS
//
//----------------------------------------------------------------------------
// REFERENCES
//
//------------------------------------------------------------------------------
// CAUTION
//
//------------------------------------------------------------------------------
OSCL_EXPORT_REF CAMRFileParser::CAMRFileParser(void)
{
iAMRDuration = -1;
iAMRBitRate = 0;
iTotalNumFramesRead = 0;
iAMRFormat = EAMRUnrecognized;
iEndOfFileReached = false;
iRandomAccessTimeInterval = 0;
iCountToClaculateRDATimeInterval = 0;
iLogger = PVLogger::GetLoggerObject(" ");
iDiagnosticLogger = PVLogger::GetLoggerObject("playerdiagnostics.pvamr_parser");
ipBSO = NULL;
}
//----------------------------------------------------------------------------
// FUNCTION NAME: CAMRFileParser::~CAMRFileParser
//----------------------------------------------------------------------------
// INPUT AND OUTPUT DEFINITIONS
//
// Inputs:
// None
//
// Outputs:
// None
//
// Returns:
// None
//
// Global Variables Used:
// None
//
//----------------------------------------------------------------------------
// FUNCTION DESCRIPTION
//
// Destructor for CAMRFileParser class
//----------------------------------------------------------------------------
// REQUIREMENTS
//
//----------------------------------------------------------------------------
// REFERENCES
//
//------------------------------------------------------------------------------
// CAUTION
//
//------------------------------------------------------------------------------
OSCL_EXPORT_REF CAMRFileParser::~CAMRFileParser(void)
{
iAMRFile.Close();
OSCL_DELETE(ipBSO);
ipBSO = NULL;
}
//----------------------------------------------------------------------------
// FUNCTION NAME: CAMRFileParser::InitAMRFile
//----------------------------------------------------------------------------
// INPUT AND OUTPUT DEFINITIONS
//
// Inputs:
// iClip = pointer to the AMR file name to be played of type TPtrC
//
// Outputs:
// None
//
// Returns:
// returnValue = true if the init succeeds, else false.
//
// Global Variables Used:
// None
//
//----------------------------------------------------------------------------
// FUNCTION DESCRIPTION
//
// This function opens the AMR file, checks for AMR format type, calculates
// the track duration, and sets the AMR bitrate value.
//
//----------------------------------------------------------------------------
// REQUIREMENTS
//
//----------------------------------------------------------------------------
// REFERENCES
//
//------------------------------------------------------------------------------
// CAUTION
//
//------------------------------------------------------------------------------
OSCL_EXPORT_REF bool CAMRFileParser::InitAMRFile(OSCL_wString& aClip, bool aInitParsingEnable, Oscl_FileServer* aFileSession, PVMFCPMPluginAccessInterfaceFactory*aCPM, OsclFileHandle*aHandle, uint32 countToClaculateRDATimeInterval)
{
iAMRFile.SetCPM(aCPM);
iAMRFile.SetFileHandle(aHandle);
// Open the file (aClip)
if (iAMRFile.Open(aClip.get_cstr(), (Oscl_File::MODE_READ | Oscl_File::MODE_BINARY), *aFileSession) != 0)
{
PVMF_AMRPARSER_LOGERROR((0, "CAMRFileParser::InitAMRFile- File Open failed"));
return false;
}
// create ipBSO
ipBSO = OSCL_NEW(bitstreamObject, (&iAMRFile));
if (!ipBSO)
{
return false;
}
if (!ipBSO->get())
{
return false; // make sure the memory allocation is going well
}
// get file info
int32 frameTypeIndex = 0;
if (ipBSO->getFileInfo(iAMRFileSize, iAMRFormat, frameTypeIndex))
{
PVMF_AMRPARSER_LOGERROR((0, "CAMRFileParser::InitAMRFile- getFileInfo failed "));
return false;
}
// Reject unsupported AMR file types
if (frameTypeIndex >= 16 ||
iAMRFormat == EAMRETS ||
iAMRFormat == EAMRIETF_MultiNB ||
iAMRFormat == EAMRIETF_MultiWB ||
iAMRFormat == EAMRWMF ||
iAMRFormat == EAMRUnrecognized)
{
PVMF_AMRPARSER_LOGERROR((0, "CAMRFileParser::Unsupported AMR type "));
return false;
}
// Set bitrate
if (EAMRIETF_SingleWB != iAMRFormat)
{
AMRFF_Frame_Type_3GPP frameType3GPP = (AMRFF_Frame_Type_3GPP)frameTypeIndex;
SetBitRate(frameType3GPP);
}
else // for wide band
{
AMRFF_WB_Frame_Type_3GPP frameType3GPP = (AMRFF_WB_Frame_Type_3GPP)frameTypeIndex;
SetBitRate(frameType3GPP);
}
// Determine file duration and set up random positioning table if needed
CalculateDuration(aInitParsingEnable, countToClaculateRDATimeInterval);
return true;
}
bool CAMRFileParser::CalculateDuration(bool aInitParsingEnable, uint32 countToClaculateRDATimeInterval)
{
iCountToClaculateRDATimeInterval = countToClaculateRDATimeInterval;
uint32 FrameCount = iCountToClaculateRDATimeInterval;
iRandomAccessTimeInterval = countToClaculateRDATimeInterval * TIME_STAMP_PER_FRAME;
if (aInitParsingEnable)
{
// Go through each frame to calculate AMR file duration.
int32 status = bitstreamObject::EVERYTHING_OK;
uint8 frame_type = 15;
iAMRDuration = 0;
int32 error = 0;
int32 filePos = 0;
OSCL_TRY(error, iRPTable.push_back(filePos));
OSCL_FIRST_CATCH_ANY(error, return false);
while (status == bitstreamObject::EVERYTHING_OK)
{
// get the next frame
status = ipBSO->getNextFrame(iAMRFrameBuffer, frame_type); // NO IETF frame header
if (status == bitstreamObject::EVERYTHING_OK)
{
// calculate the number of frames // BX
iAMRDuration += TIME_STAMP_PER_FRAME;
// set up the table for randow positioning
int32 frame_length = 0;
if (iAMRFormat == EAMRIF2)
{
frame_length = If2DecInputBytes[(uint16)frame_type];
}
else if (iAMRFormat == EAMRIETF_SingleNB)
{
frame_length = IetfDecInputBytes[(uint16)frame_type];
}
else if (EAMRIETF_SingleWB == iAMRFormat)
{
frame_length = IetfWBDecInputBytes[(uint16)frame_type];
}
else
{
PVMF_AMRPARSER_LOGERROR((0, "CAMRFileParser::CalculateDuration- Format unknown"));
return false;
}
filePos += frame_length;
error = 0;
if (!FrameCount)
{
OSCL_TRY(error, iRPTable.push_back(filePos));
OSCL_FIRST_CATCH_ANY(error, return false);
FrameCount = countToClaculateRDATimeInterval;
}
}
else if (status == bitstreamObject::END_OF_FILE)
{
break;
}
else
{
// error happens!
PVMF_AMRPARSER_LOGERROR((0, "CAMRFileParser::getNextFrame Fails Error Code %d", status));
if (ipBSO->reset())
{
return false;
}
return false;
}
FrameCount--;
}
ResetPlayback(0);
}
return true;
}
//----------------------------------------------------------------------------
// FUNCTION NAME: CAMRFileParser::RetrieveAMRFileInfo
//----------------------------------------------------------------------------
// INPUT AND OUTPUT DEFINITIONS
//
// Inputs:
// aMedia = pointer to CPVMedia class
// aTrackId = pointer to the ID specific to the current AMR track
// aTimescale = pointer to the sampling frequency value, for AMR it is 8000 Hz.
//
// Outputs:
// None
//
// Returns:
// false if an error happens, else true
//
// Global Variables Used:
// None
//
//----------------------------------------------------------------------------
// FUNCTION DESCRIPTION
//
// This function opens the AMR file, checks for AMR format type, calculates
// the track duration, and sets the AMR bitrate value.
//
//----------------------------------------------------------------------------
// REQUIREMENTS
//
//----------------------------------------------------------------------------
// REFERENCES
//
//------------------------------------------------------------------------------
// CAUTION
//
//------------------------------------------------------------------------------
OSCL_EXPORT_REF bool CAMRFileParser::RetrieveFileInfo(TPVAmrFileInfo& aInfo)
{
if (iAMRFormat == EAMRUnrecognized)
{
// File is not open and parsed
return false;
}
aInfo.iBitrate = iAMRBitRate;
aInfo.iTimescale = 1000;
aInfo.iDuration = iAMRDuration;
aInfo.iFileSize = iAMRFileSize;
aInfo.iAmrFormat = iAMRFormat;
PVMF_AMRPARSER_LOGDIAGNOSTICS((0, "CAMRFileParser::RetrieveFileInfo- duration = %d, bitrate = %d, filesize = %d", iAMRDuration, iAMRBitRate, iAMRFileSize));
return true;
}
//----------------------------------------------------------------------------
// FUNCTION NAME: CAMRFileParser::SetBitRate
//----------------------------------------------------------------------------
// INPUT AND OUTPUT DEFINITIONS
//
// Inputs:
// aFrameType3GPP = 3GPP frame type for the AMR frame of type AMRFF_Frame_Type_3GPP
//
// Outputs:
// None
//
// Returns:
// None
//
// Global Variables Used:
// None
//
//----------------------------------------------------------------------------
// FUNCTION DESCRIPTION
//
// This function takes in the 3GPP frametype and sets the AMR bitrate value
// depending on the AMR frametype.
//
//----------------------------------------------------------------------------
// REQUIREMENTS
//
//----------------------------------------------------------------------------
// REFERENCES
//
//------------------------------------------------------------------------------
// CAUTION
//
//------------------------------------------------------------------------------
void CAMRFileParser::SetBitRate(AMRFF_Frame_Type_3GPP aFrameType3GPP)
{
switch (aFrameType3GPP)
{
case AMRFF_AMR_475:
{
iAMRBitRate = 4750;
break;
}
case AMRFF_AMR_515:
{
iAMRBitRate = 5150;
break;
}
case AMRFF_AMR_59:
{
iAMRBitRate = 5900;
break;
}
case AMRFF_AMR_67:
{
iAMRBitRate = 6700;
break;
}
case AMRFF_AMR_74:
{
iAMRBitRate = 7400;
break;
}
case AMRFF_AMR_795:
{
iAMRBitRate = 7950;
break;
}
case AMRFF_AMR_102:
{
iAMRBitRate = 10200;
break;
}
case AMRFF_AMR_122:
{
iAMRBitRate = 12200;
break;
}
default:
{
iAMRBitRate = 0;
break;
}
}
return;
}
void CAMRFileParser::SetBitRate(AMRFF_WB_Frame_Type_3GPP aFrameType3GPP)
{
switch (aFrameType3GPP)
{
case AMRFF_WB_660:
{
iAMRBitRate = 6600;
break;
}
case AMRFF_WB_885:
{
iAMRBitRate = 8850;
break;
}
case AMRFF_WB_1265:
{
iAMRBitRate = 12650;
break;
}
case AMRFF_WB_1425:
{
iAMRBitRate = 14250;
break;
}
case AMRFF_WB_1585:
{
iAMRBitRate = 15850;
break;
}
case AMRFF_WB_1825:
{
iAMRBitRate = 18250;
break;
}
case AMRFF_WB_1985:
{
iAMRBitRate = 19850;
break;
}
case AMRFF_WB_2305:
{
iAMRBitRate = 23050;
break;
}
case AMRFF_WB_2385:
{
iAMRBitRate = 23850;
break;
}
default:
{
iAMRBitRate = 0;
break;
}
}
return;
}
//----------------------------------------------------------------------------
// FUNCTION NAME: CAMRFileParser::ResetPlayback
//----------------------------------------------------------------------------
// INPUT AND OUTPUT DEFINITIONS
//
// Inputs:
// aStartTime = integer value as where to move the playback positioning to.
//
// Outputs:
// None
//
// Returns:
// 0 if success, -1 if failure
//
// Global Variables Used:
// None
//
//----------------------------------------------------------------------------
// FUNCTION DESCRIPTION
//
// This function sets the file pointer to the location that aStartTime would
// point to in the file.
//
//----------------------------------------------------------------------------
// REQUIREMENTS
//
//----------------------------------------------------------------------------
// REFERENCES
//
//------------------------------------------------------------------------------
// CAUTION
//
//------------------------------------------------------------------------------
OSCL_EXPORT_REF int32 CAMRFileParser::ResetPlayback(int32 aStartTime)
{
// get file size info, //iAMRFile.Size(fileSize)
int32 result;
if (iAMRFileSize <= 0)
{
int32 frameTypeIndex;
if (ipBSO->getFileInfo(iAMRFileSize, iAMRFormat, frameTypeIndex))
{
PVMF_AMRPARSER_LOGERROR((0, "CAMRFileParser::Reset Playback Failed"));
return bitstreamObject::MISC_ERROR;
}
}
iEndOfFileReached = false;
// initialize "iTotalNumFramesRead"
// note: +1 means we choose the next frame(ts>=aStartTime)
iTotalNumFramesRead = aStartTime / TIME_STAMP_PER_FRAME + (aStartTime > 0) * 1;
uint32 tblIdx = aStartTime / (iRandomAccessTimeInterval);// +(aStartTime>0)*1;
iTotalNumFramesRead = tblIdx * iCountToClaculateRDATimeInterval;
PVMF_AMRPARSER_LOGDIAGNOSTICS((0, "CAMRFileParser::resetplayback - TotalNumFramesRead=%d", iTotalNumFramesRead));
// set new file position
int32 newPosition = 0;
if (iTotalNumFramesRead > 0)
{
// At the first time, don't do reset
if (iAMRDuration != 0 && iRPTable.size() == 0)
{
newPosition = (iAMRFileSize * aStartTime) / iAMRDuration;
PVMF_AMRPARSER_LOGDIAGNOSTICS((0, "CAMRFileParser::resetplayback - newPosition=%d", newPosition));
if (newPosition < 0)
{
// if we have no duration information, reset the file position at 0.
newPosition = 0;
}
}
else if (iRPTable.size() > 0)
{
// use the randow positioning table to determine the file position
if (tblIdx >= iRPTable.size())
{
// Requesting past the end of table so set to (end of table-1)
// to be at the last sample
tblIdx = ((int32)iRPTable.size()) - 2;
}
newPosition = iRPTable[tblIdx];
}
}
result = ipBSO->reset(newPosition);
if (newPosition >= 0 && result)
{
PVMF_AMRPARSER_LOGERROR((0, "AMRBitstreamObject::refill- Misc Error"));
return result;
}
iEndOfFileReached = false;
return bitstreamObject::EVERYTHING_OK;
}
//----------------------------------------------------------------------------
// FUNCTION NAME: CAMRFileParser::SeekPointFromTimestamp
//----------------------------------------------------------------------------
// INPUT AND OUTPUT DEFINITIONS
//
// Inputs:
// aStartTime = integer value as for the specified start time
//
// Outputs:
// None
//
// Returns:
// Timestamp in milliseconds of the actual position
//
// Global Variables Used:
// None
//
//----------------------------------------------------------------------------
// FUNCTION DESCRIPTION
//
// This function returns the timestamp for an actual position corresponding
// to the specified start time
//
//----------------------------------------------------------------------------
// REQUIREMENTS
//
//----------------------------------------------------------------------------
// REFERENCES
//
//------------------------------------------------------------------------------
// CAUTION
//
//------------------------------------------------------------------------------
OSCL_EXPORT_REF uint32 CAMRFileParser::SeekPointFromTimestamp(uint32 aStartTime)
{
// get file size info, //iAMRFile.Size(fileSize)
if (iAMRFileSize <= 0)
{
int32 frameTypeIndex;
if (ipBSO->getFileInfo(iAMRFileSize, iAMRFormat, frameTypeIndex))
{
return 0;
}
}
// Determine the frame number corresponding to timestamp
// note: +1 means we choose the next frame(ts>=aStartTime)
uint32 startframenum = aStartTime / TIME_STAMP_PER_FRAME + (aStartTime > 0) * 1;
// Correct the frame number if necessary
if (startframenum > 0)
{
if (iAMRDuration != 0 && iRPTable.size() <= 0)
{
// Duration not known and reposition table not available so go to first frame
startframenum = 0;
}
else if (iRPTable.size() > 0)
{
if (startframenum >= iRPTable.size())
{
// Requesting past the end of table so set to (end of table-1)
// to be at the last sample
startframenum = ((int32)iRPTable.size()) - 2;
}
}
}
return (startframenum*TIME_STAMP_PER_FRAME);
}
//----------------------------------------------------------------------------
// FUNCTION NAME: CAMRFileParser::GetNextBundledAccessUnits
//----------------------------------------------------------------------------
// INPUT AND OUTPUT DEFINITIONS
//
// Inputs:
// aNumSamples = requested number of frames to be read from file
// aGau = frame information structure of type GAU
//
// Outputs:
// None
//
// Returns:
// 0 if success, -1 if failure
//
// Global Variables Used:
// None
//
//----------------------------------------------------------------------------
// FUNCTION DESCRIPTION
//
// This function attempts to read in the number of AMR frames specified by
// aNumSamples. It formats the read data to WMF bit order and stores it in
// the GAU structure.
//
//----------------------------------------------------------------------------
// REQUIREMENTS
//
//----------------------------------------------------------------------------
// REFERENCES
//
//------------------------------------------------------------------------------
// CAUTION
//
//------------------------------------------------------------------------------
OSCL_EXPORT_REF int32 CAMRFileParser::GetNextBundledAccessUnits(uint32 *aNumSamples, GAU *aGau)
{
// AMR format has already been identified in InitAMRFile function.
// Check if AMR format is valid as the safeguard
if (iAMRFormat == EAMRUnrecognized)
{
PVMF_AMRPARSER_LOGERROR((0, "CAMRFileParser::GetNextBundledAccessUnits Failed - Unrecognized format"));
return bitstreamObject::MISC_ERROR;
}
// Check the requested number of frames is not greater than the max supported
if (*aNumSamples > MAX_NUM_FRAMES_PER_BUFF)
{
PVMF_AMRPARSER_LOGERROR((0, "CAMRFileParser::GetNextBundledAccessUnits Failed - requested number of frames is greater than the max supported"));
return bitstreamObject::MISC_ERROR;
}
int32 returnValue = bitstreamObject::EVERYTHING_OK;
if (iEndOfFileReached)
{
*aNumSamples = 0;
return bitstreamObject::END_OF_FILE;
}
uint8* pTempGau = (uint8 *) aGau->buf.fragments[0].ptr;
uint32 gauBufferSize = aGau->buf.fragments[0].len;
uint32 i, bytesReadInGau = 0, numSamplesRead = 0;
for (i = 0; i < *aNumSamples && !iEndOfFileReached; i++)
{
// get the next frame
bool bHeaderIncluded = true;
returnValue = ipBSO->getNextFrame(iAMRFrameBuffer, iAMRFrameHeaderBuffer[i], bHeaderIncluded);
if (returnValue == bitstreamObject::END_OF_FILE)
{
iEndOfFileReached = true;
break;
}
else if (returnValue == bitstreamObject::EVERYTHING_OK)
{
}
else
{ // error happens!!
*aNumSamples = 0;
return bitstreamObject::READ_ERROR;
}
// Now a frame exists in iAMRFrameBuffer, move it to aGau
int32 frame_size = 0;
if (iAMRFormat == EAMRIF2)
{
frame_size = If2DecInputBytes[(uint16)iAMRFrameHeaderBuffer[i]];
}
else if (iAMRFormat == EAMRIETF_SingleNB)
{
frame_size = IetfDecInputBytes[(uint16)iAMRFrameHeaderBuffer[i]];
}
else if (iAMRFormat == EAMRIETF_SingleWB)
{
frame_size = IetfWBDecInputBytes[(uint16)iAMRFrameHeaderBuffer[i]];
}
else
{
PVMF_AMRPARSER_LOGERROR((0, "AMRBitstreamObject::refill- Misc Error"));
return bitstreamObject::MISC_ERROR;
}
// Check whether the gau buffer will be overflow
if (bytesReadInGau + frame_size >= gauBufferSize)
{
// Undo the read
ipBSO->undoGetNextFrame(frame_size);
break;
}
if (frame_size > 0)
{
oscl_memcpy(pTempGau, iAMRFrameBuffer, frame_size);
pTempGau += frame_size;
bytesReadInGau += frame_size;
}
aGau->info[i].len = frame_size;
aGau->info[i].ts = (iTotalNumFramesRead + (numSamplesRead++)) * TIME_STAMP_PER_FRAME;
} // end of: for(i = 0; i < *aNumSamples && !iEndOfFileReached; i++)
aGau->info[0].ts = iTotalNumFramesRead * TIME_STAMP_PER_FRAME;
*aNumSamples = numSamplesRead;
iTotalNumFramesRead += numSamplesRead;
//We may have reached EOF but also found some samples.
//don't return EOF until there are no samples left.
if (returnValue == bitstreamObject::END_OF_FILE
&& numSamplesRead > 0)
return bitstreamObject::EVERYTHING_OK;
return returnValue;
}
OSCL_EXPORT_REF int32 CAMRFileParser::PeekNextTimestamp(uint32 *aTimestamp)
{
*aTimestamp = iTotalNumFramesRead * TIME_STAMP_PER_FRAME;
return bitstreamObject::EVERYTHING_OK;
}
OSCL_EXPORT_REF uint8 CAMRFileParser::GetFrameTypeInCurrentBundledAccessUnits(uint32 frameIndex)
{
if (frameIndex >= MAX_NUM_FRAMES_PER_BUFF)
{
return 0;
}
return iAMRFrameHeaderBuffer[frameIndex];
}
OSCL_EXPORT_REF int32 CAMRFileParser::getTrackMaxBufferSizeDB()
{
if (ipBSO)
{
return ipBSO->getTrackMaxBufferSizeDB();
}
else
{
return -1;
}
}
OSCL_EXPORT_REF uint8* CAMRFileParser::getCodecSpecificInfo()
{
bool bHeaderIncluded = true;
ipBSO->getNextFrame(iAMRFrameBuffer, iAMRFrameHeaderBuffer[1], bHeaderIncluded);
return iAMRFrameHeaderBuffer;
}