blob: a1d83b3e0561ec2dc40e54829edc8cacb9a5d15d [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 A C F I L E P A R S E R
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
/**
* @file aacfileparser.cpp
* @brief This file contains the implementation of the raw AAC file parser.
*/
//----------------------------------------------------------------------------
// INCLUDES
//----------------------------------------------------------------------------
#include "aacfileparser.h"
#include "pv_audio_type_defs.h"
#include "getactualaacconfig.h"
#include "media_clock_converter.h"
#include "pvmp4audiodecoder_api.h"
// Use default DLL entry point for Symbian
#include "oscl_dll.h"
OSCL_DLL_ENTRY_POINT_DEFAULT()
//! specially used in ResetPlayback(), re-poition the file pointer
int32 AACBitstreamObject::reset(int32 filePos)
{
iBytesRead = filePos; // set the initial value
iBytesProcessed = filePos;
if (ipAACFile)
{
ipAACFile->Seek(filePos, Oscl_File::SEEKSET);
}
iPos = AACBitstreamObject::MAIN_BUFF_SIZE;
return refill();
}
//! read data from bitstream, this is the only function to read data from file
int32 AACBitstreamObject::refill()
{
if (iBytesRead > 0 && iFileSize > 0 && iBytesRead >= iFileSize)
{
//At this point we're near the end of data.
//Quit reading data but don't return EOF until all data is processed.
if (iBytesProcessed < iBytesRead)
{
return AACBitstreamObject::EVERYTHING_OK;
}
else
{
return AACBitstreamObject::END_OF_FILE;
}
}
if (!ipAACFile)
{
PVMF_AACPARSER_LOGERROR((0, "AACBitstreamObject::refill- Misc Error"));
return AACBitstreamObject::MISC_ERROR;
}
// Get file size at the very first time
if (iFileSize == 0)
{
if (ipAACFile->Seek(0, Oscl_File::SEEKSET))
{
PVMF_AACPARSER_LOGERROR((0, "AACBitstreamObject::refill- Misc Error"));
return AACBitstreamObject::MISC_ERROR;
}
ipAACFile->GetRemainingBytes((uint32&)iFileSize);
if (iFileSize <= 0)
{
PVMF_AACPARSER_LOGERROR((0, "AACBitstreamObject::refill- Misc Error"));
return AACBitstreamObject::MISC_ERROR;
}
// first-time read, set the initial value of iPos
iPos = AACBitstreamObject::MAIN_BUFF_SIZE;
}
int32 remain_bytes = AACBitstreamObject::MAIN_BUFF_SIZE - iPos;
if (remain_bytes > 0)
{
// move the remaining stuff to the beginning of iBuffer
oscl_memcpy(&iBuffer[0], &iBuffer[iPos], remain_bytes);
}
// read data
if ((iActual_size = ipAACFile->Read(&iBuffer[remain_bytes], 1, iMax_size - remain_bytes)) == 0)
{
return AACBitstreamObject::READ_ERROR;
}
iBytesRead += iActual_size;
iActual_size += remain_bytes;
iPos = 0;
return AACBitstreamObject::EVERYTHING_OK;
}
//! get frame size and number of data blocks for the next frame, in preparation of getNextFrame()
int32 AACBitstreamObject::getNextFrameInfo(int32& frame_size, int32& numDateBlocks)
{
int32 ret_value = AACBitstreamObject::EVERYTHING_OK;
// Need to refill?
if (iFileSize == 0 || iPos + 4 >= iActual_size)
{
ret_value = refill();
if (ret_value)
{
return ret_value;
}
}
// Search the 12 bit sync-word 0xff + 0xf0
while (!(iBuffer[iPos] == 0xff &&
(iBuffer[iPos+1] & 0xf0) == 0xf0 &&
iBuffer[iPos+1] == iAACHeaderBuffer[1] &&
iBuffer[iPos+2] == iAACHeaderBuffer[2] &&
iBuffer[iPos+3] == iAACHeaderBuffer[3]))
{
if (iPos + 4 >= iActual_size)
{
ret_value = refill();
if (ret_value)
{
return ret_value;
}
}
iPos++;
iBytesProcessed++;
}
if (iPos + ADTS_HEADER_LENGTH + 2 >= iActual_size)
{
ret_value = refill();
if (ret_value)
{
return ret_value;
}
}
// parse the header and get frame size plus the number of data blocks
uint8 *pBuffer = &iBuffer[iPos];
frame_size = (int32)((pBuffer[3] & 0x03) << 11) | // take the lowest 2 bits in the 4th byte of the header
(int32)(pBuffer[4] << 3) | // take the whole 5th byte(8 bits) of the header
(int32)((pBuffer[5] & 0xe0) >> 5); // take the highest 3 bits in the 6th byte of the header
if (ibCRC_Check)
{
frame_size -= (ADTS_HEADER_LENGTH + 2);
}
else
{
frame_size -= ADTS_HEADER_LENGTH;
}
numDateBlocks = (pBuffer[6] & 0x03) + 1; // take the lowest 2 bits in the 7th byte of the header
// update CRC check
ibCRC_Check = ((pBuffer[1] & 0x01) ? false : true);
return ret_value;
}
//! most important function to get one frame data plus frame type, used in getNextBundledAccessUnits()
int32 AACBitstreamObject::getNextFrame(uint8* frameBuffer, int32& frame_size, int32& aHdrSize, bool bHeaderIncluded)
{
aHdrSize = 0;
if (!frameBuffer || (frame_size <= 0 || frame_size > MAX_AAC_FRAME_SIZE))
{
PVMF_AACPARSER_LOGERROR((0, "AACBitstreamObject::getNextFrame- Misc Error"));
return AACBitstreamObject::MISC_ERROR;
}
int32 ret_value = AACBitstreamObject::EVERYTHING_OK;
if (iAACFormat == EAACADTS) //ADTS
{
// Need to refill?
if (iFileSize == 0 || iPos + ADTS_HEADER_LENGTH + 2 + frame_size >= iActual_size)
{
ret_value = refill();
if (ret_value)
{
return ret_value;
}
}
// copy the header to the buffer if needed
uint8 *pBuffer = &iBuffer[iPos];
int32 header_size = (ibCRC_Check ? ADTS_HEADER_LENGTH + 2 : ADTS_HEADER_LENGTH);
if (bHeaderIncluded)
{
oscl_memcpy(frameBuffer, pBuffer, header_size);
frameBuffer += header_size;
aHdrSize = header_size;
}
// copy the data to the given buffer
oscl_memcpy(frameBuffer, &pBuffer[header_size], frame_size);
iPos += (header_size + frame_size);
iBytesProcessed += (header_size + frame_size);
}
else if (iAACFormat == EAACADIF || iAACFormat == EAACRaw) //ADIF or raw bitstream
{
if (iFileSize == 0 || iPos + frame_size >= iActual_size)
{
ret_value = refill();
if (ret_value)
{
return ret_value;
}
}
uint8 *pBuffer = &iBuffer[iPos];
if ((iBytesRead >= iFileSize) && (frame_size > (iBytesRead - iBytesProcessed)))
{
frame_size = iBytesRead - iBytesProcessed;
}
// copy the data to the given buffer
oscl_memcpy(frameBuffer, pBuffer, frame_size);
iPos += frame_size;
iBytesProcessed += frame_size;
}
return ret_value;
}
void AACBitstreamObject::parseID3Header(PVFile& aFile)
{
if (!ipAACFile
|| !ipAACFile->IsOpen())
return;//error
int32 curpos = aFile.Tell();
aFile.Seek(0, Oscl_File::SEEKSET);
id3Parser->ParseID3Tag(&aFile);
aFile.Seek(curpos, Oscl_File::SEEKSET);
}
int32 AACBitstreamObject::isAACFile()
{
if (!ipAACFile || !ipAACFile->IsOpen())
{
return AACBitstreamObject::READ_ERROR;
}
int32 retVal = AACBitstreamObject::EVERYTHING_OK;
// save current file pointer location
int32 curPos = ipAACFile->Tell();
ipAACFile->Seek(0, Oscl_File::SEEKSET);
// check for ID3v2 tag at the beginning of file
uint32 tagSize = 0;
if (true == id3Parser->IsID3V2Present(ipAACFile, tagSize))
{
// skip over ID3v2 tag
// move the file read pointer to beginning of audio data
// but first make sure the data is there
uint32 aCurrentSize = 0;
uint32 aRemBytes = 0;
if (ipAACFile->GetRemainingBytes(aRemBytes))
{
uint32 currPos_2 = (uint32)(ipAACFile->Tell());
aCurrentSize = currPos_2 + aRemBytes;
if (aCurrentSize >= tagSize)
{
if (ipAACFile->Seek(tagSize, Oscl_File::SEEKSET) != 0)
{
retVal = AACBitstreamObject::READ_ERROR;
}
}
else
{
// data has not arrived yet
retVal = AACBitstreamObject::INSUFFICIENT_DATA;
}
}
else
{
retVal = AACBitstreamObject::READ_ERROR;
}
}
// file pointer should be at the audio data
// can be ADTS, ADIF or raw AAC
// - it takes 8192 bytes (max AAC frame size) to determine that is is ADTS
// - it takes 4 bytes to determine that it is ADIF
// - it takes 1536 bytes to determine that it is raw AAC
// make sure there are at least 8192 bytes left in the file
if (AACBitstreamObject::EVERYTHING_OK == retVal)
{
uint32 aRemBytes = 0;
if (ipAACFile->GetRemainingBytes(aRemBytes))
{
int32 currPos_2 = ipAACFile->Tell();
retVal = reset(currPos_2);
if (AACBitstreamObject::EVERYTHING_OK == retVal)
{
uint8 *pBuffer = &iBuffer[iPos];
// default to not enough data
retVal = AACBitstreamObject::INSUFFICIENT_DATA;
if (aRemBytes >= MAX_ADTS_PACKET_LENGTH)
{
// check for possible ADTS sync word
int32 index = find_adts_syncword(pBuffer);
if (index != -1)
{
// definitely ADTS
retVal = AACBitstreamObject::EVERYTHING_OK;
}
}
if (AACBitstreamObject::INSUFFICIENT_DATA == retVal)
{
// not enough data to determine if it is ADTS
// see if it is ADIF
if (aRemBytes >= 4)
{
// check for ADIF header
if (pBuffer[0] == 0x41 && // 'A'
pBuffer[1] == 0x44 && // 'D'
pBuffer[2] == 0x49 && // 'I'
pBuffer[3] == 0x46) // 'F'
{
// definitely ADIF
retVal = AACBitstreamObject::EVERYTHING_OK;
}
else
{
// non-recognized format,
retVal = AACBitstreamObject::MISC_ERROR;
}
}
}
}
}
else
{
retVal = AACBitstreamObject::READ_ERROR;
}
}
// retore file pointer
ipAACFile->Seek(curPos, Oscl_File::SEEKSET);
return retVal;
}
//! Search for adts synchronization word
int32 AACBitstreamObject::find_adts_syncword(uint8 *pBuffer)
{
uint32 test_for_syncword = 0;
uint32 i;
uint32 buff_length;
buff_length = OSCL_MIN(MAX_ADTS_PACKET_LENGTH, iActual_size);
for (i = 0; i < buff_length - 1; i++)
{
/*
* Sync word is always byte aligned, sync word == 0xFFF
*/
if (pBuffer[i] == 0xFF)
{
if ((pBuffer[i+1] & 0xF0) == 0xF0)
{
test_for_syncword = 1; /* flag found sync adts word */
break;
}
}
}
if (test_for_syncword) // get here only if match is found
{
uint32 index = i;
// extract the aac frame lenght where the next sync word should be
if ((index + 5) < buff_length)
{
uint32 length = (uint32)((pBuffer[index + 3] & 0x03) << 11); // lowest 2 bits in the 4th byte of the header
length |= (uint32)(pBuffer[index + 4] << 3); // whole 5th byte(8 bits) of the header
length |= (uint32)((pBuffer[index + 5] & 0xe0) >> 5); // highest 3 bits in the 6th byte of the header
// Verify for false sync word in non-adts files, by validating next 2 sync word
if ((length > ADTS_HEADER_LENGTH) &&
(length < buff_length - index) && // buff_length should account for up to 4 aac frames
(pBuffer[index + length ] == 0xff) &&
((pBuffer[index + length + 1] & 0xf0) == 0xf0))
{
// extract the second aac frame lenght to predict next adts header
length += index;
uint32 length_2 = (uint32)((pBuffer[length + 3] & 0x03) << 11);
length_2 |= (uint32)(pBuffer[length + 4] << 3);
length_2 |= (uint32)((pBuffer[length+ 5] & 0xe0) >> 5);
if ((length_2 > ADTS_HEADER_LENGTH) &&
(length_2 < buff_length - length) &&
(pBuffer[length + length_2] == 0xff) &&
((pBuffer[length + length_2 + 1] & 0xf0) == 0xf0))
{
return (index); // sure this is adts
}
iPosSyncAdtsFound = index - 1; // allow overlapping on extended search
return (-1); // false adts synchronization, it is adif or raw
}
else
{
iPosSyncAdtsFound = index - 1; // allow overlapping on extended search
return (-1); // it was a false adts synchronization, it could be adif or raw
}
}
else
{
iPosSyncAdtsFound = index - 1; // allow overlapping on extended search
return (-1); // not enough data to validate synchronization
}
}
else
{
iPosSyncAdtsFound = i - 1; // allow overlapping on extended search
return (-1); // no adts synchronization, it could be adif or raw
}
}
//! get clip information: file size, format(ADTS or ADIF) and sampling rate index
int32 AACBitstreamObject::getFileInfo(int32& fileSize, TAACFormat& format, uint8& sampleFreqIndex, uint32& bitRate, uint32& HeaderLen, OSCL_wString&/*aClip*/)
{
uint32 id;
uint32 bitstreamType;
uint32 numProgConfigElem;
int32 i;
uint32 ADIFHeaderLen;
uint32 numFrontChanElem;
uint32 numSideChanElem;
uint32 numBackChanElem;
uint32 numLfeChanElem;
uint32 numAssocDataElem;
uint32 numValidCCElem;
uint32 commentFieldBytes;
uint32 offset;
uint32 bitIndex;
uint8 tmp;
bitRate = 0;
HeaderLen = 0;
iChannelConfig = 0;
format = EAACUnrecognized;
fileSize = sampleFreqIndex = 0;
int32 ret_value = AACBitstreamObject::EVERYTHING_OK;
if (iFileSize == 0)
{
ret_value = reset(0);
if (ret_value == AACBitstreamObject::EVERYTHING_OK)
{
//retrieve the ID3 meta-data from the file
parseID3Header(*ipAACFile);
if (id3Parser->GetByteOffsetToStartOfAudioFrames() > 0)
{
//skip past the ID3 header.
ret_value = reset(id3Parser->GetByteOffsetToStartOfAudioFrames());
if (ret_value != AACBitstreamObject::EVERYTHING_OK)
{
return ret_value;
}
}
fileSize = iFileSize;
uint8 *pBuffer = &iBuffer[iPos];
// Check for possible adts sync word
int32 index = find_adts_syncword(pBuffer);
if (index != -1)
{
//ADTS format
iAACFormat = format = EAACADTS;
// get sample frequency index
iSampleFreqIndex = sampleFreqIndex = (uint8)((pBuffer[2 + index] & 0x3c) >> 2);
// check the crc_check field
ibCRC_Check = ((pBuffer[1 + index] & 0x01) ? false : true);
// get ADTS fixed header part to iAACHeaderBuffer
oscl_memcpy(iAACHeaderBuffer, &pBuffer[index], PACKET_INDICATOR_LENGTH);
}
else if (iFileSize >= 4 &&
pBuffer[0] == 0x41 && // 'A'
pBuffer[1] == 0x44 && // 'D'
pBuffer[2] == 0x49 && // 'I'
pBuffer[3] == 0x46) // 'F'
{
// ADIF format
iAACFormat = format = EAACADIF;
ADIFHeaderLen = 32; // adif_id 4 bytes
// check copyright_id_present (1 bit)
id = pBuffer[4] & 0x80;
if (id != 0) //copyright ID is presented
{
ADIFHeaderLen += 75; // copyright_id_present 1 bit
// copyright_id 72 bits,
// original_copy 1 bit,
// home 1 bit,
// check bitstream type
bitstreamType = pBuffer[13] & 0x10;
// get number of program config. element
numProgConfigElem = (pBuffer[16] & 0x1E) >> 1;
// get bitrate (max for variable rate bitstream)
iBitrate = bitRate = ((pBuffer[13] & 0xF0) << 15) |
(pBuffer[14] << 11) |
(pBuffer[15] << 3) |
((pBuffer[16] & 0xE0) >> 5);
if (iBitrate == 0) //bitrate is not known
{
PVMF_AACPARSER_LOGERROR((0, "AACBitstreamObject::getFileInfo- Misc Error"));
return AACBitstreamObject::MISC_ERROR;
}
ADIFHeaderLen += 28; // bitstream_type 1 bit,
// bitrate 23 bits
// num_program_config_elements 4 bits
for (i = 0; i < (int32)numProgConfigElem + 1; i++)
{
if (bitstreamType == 0) //bistream type is constant rate bitstream
{
ADIFHeaderLen += 20; //adif_buffer_fullness 20 bits
// get audio object type
iAudioObjectType = (uint8)(((pBuffer[19] & 0x1) << 1) | ((pBuffer[20] & 0x80) >> 7));
// get sampling rate index
iSampleFreqIndex = sampleFreqIndex = (uint8)((pBuffer[20] & 0x78) >> 3);
// get number of front channel elements
numFrontChanElem = (uint32)(((pBuffer[20] & 0x7) << 1) | ((pBuffer[21] & 0x80) >> 7));
// get number of side channel elements
numSideChanElem = (uint32)((pBuffer[21] & 0x78) >> 3);
// get number of back channel elements
numBackChanElem = (uint32)(((pBuffer[21] & 0x7) << 1) | ((pBuffer[22] & 0x80) >> 7));
// get number of LFE channel elements
numLfeChanElem = (uint32)((pBuffer[22] & 0x60) >> 5);
// get number of assoc data elements
numAssocDataElem = (uint32)((pBuffer[22] & 0x1C) >> 2);
// get number of valid CC elements
numValidCCElem = (uint32)(((pBuffer[22] & 0x3) << 2) | ((pBuffer[23] & 0xC0) >> 6));
ADIFHeaderLen += 31; //element_instance_tag 4 bits,
//object_type 2 bits,
//sampling_frequency_index 4 bits,
//num_front_channel_elements 4 bits,
//num_side_channel_elements 4 bits,
//num_back_channel_elements 4 bits,
//num_lfe_channel_elements 2 bits,
//num_assoc_data_elements 3 bits,
//num_valid_cc_elements 4 bits
// check mono_mixdown_present
if ((pBuffer[23] & 0x20) != 0) //mono mixdown is presented
{
ADIFHeaderLen += 5; //mono_mixdown_present 1 bit
//mono_mixdown_element_number 4 bits
//check stereo_mixdown_present
if ((pBuffer[23] & 0x1) != 0) //stereo mixdown is presented
{
ADIFHeaderLen += 5; //stereo_mixdown_present 1 bit
//stereo_mixdown_element_number 4 bits
//check matrix_mixdown_idx_present
if ((pBuffer[24] & 0x8) != 0) //matrix mixdown is presented
{
ADIFHeaderLen += 4; //matrix_mixdown_idx_present 1 bit
//matrix_mixdown_idx 2 bits
//pseudo_surround_enable 1 bit
}
else //matrix mixdown is not presented
{
ADIFHeaderLen += 1; //matrix_mixdown_idx_present 1 bit
}
}
else //stereo mixdown is not presented
{
ADIFHeaderLen += 1; //stereo_mixdown_present 1 bit
//check matrix_mixdown_idx_present
if ((pBuffer[24] & 0x80) != 0) //matrix mixdown is presented
{
ADIFHeaderLen += 4; //matrix_mixdown_idx_present 1 bit
//matrix_mixdown_idx 2 bits
//pseudo_surround_enable 1 bit
}
else //matrix mixdown is not presented
{
ADIFHeaderLen += 1; //matrix_mixdown_idx_present 1 bit
}
}//if ((pBuffer[23] & 0x1) != 0)
}
else //mono mixdown is not presented
{
ADIFHeaderLen += 1; //mono_mixdown_present 1 bit
//check stereo_mixdown_present
if ((pBuffer[23] & 0x10) != 0) //stereo mixdown is presented
{
ADIFHeaderLen += 5; //stereo_mixdown_present 1 bit
//stereo_mixdown_element_number 4 bits
//check matrix_mixdown_idx_present
if ((pBuffer[24] & 0x80) != 0) //matrix mixdown is presented
{
ADIFHeaderLen += 4; //matrix_mixdown_idx_present 1 bit
//matrix_mixdown_idx 2 bits
//pseudo_surround_enable 1 bit
}
else //matrix mixdown is not presented
{
ADIFHeaderLen += 1; //matrix_mixdown_idx_present 1 bit
}
}
else //stereo mixdown is not presented
{
ADIFHeaderLen += 1; //stereo_mixdown_present 1 bit
//check matrix_mixdown_idx_present
if ((pBuffer[23] & 0x8) != 0) //matrix mixdown is presented
{
ADIFHeaderLen += 4; //matrix_mixdown_idx_present 1 bit
//matrix_mixdown_idx 2 bits
//pseudo_surround_enable 1 bit
}
else //matrix mixdown is not presented
{
ADIFHeaderLen += 1; //matrix_mixdown_idx_present 1 bit
}
}//if ((pBuffer[23] & 0x10) != 0)
}//if ((pBuffer[23] & 0x20) != 0)
}
else //bistream type is variable rate bitstream
{
// get audio object type
iAudioObjectType = (uint8)((pBuffer[17] & 0x18) >> 3);
// get sampling rate index
iSampleFreqIndex = sampleFreqIndex = (uint8)(((pBuffer[17] & 0x7) << 1) | ((pBuffer[18] & 0x80) >> 7));
// get number of front channel elements
numFrontChanElem = (uint32)((pBuffer[18] & 0x78) >> 3);
// get number of side channel elements
numSideChanElem = (uint32)(((pBuffer[18] & 0x7) << 1) | ((pBuffer[19] & 0x80) >> 7));
// get number of back channel elements
numBackChanElem = (uint32)((pBuffer[19] & 0x78) >> 3);
// get number of LFE channel elements
numLfeChanElem = (uint32)((pBuffer[19] & 0x6) >> 1);
// get number of assoc data elements
numAssocDataElem = (uint32)(((pBuffer[19] & 0x1) << 2) | ((pBuffer[20] & 0xC0) >> 6));
// get number of valid CC elements
numValidCCElem = (uint32)((pBuffer[20] & 0x3C) >> 2);
ADIFHeaderLen += 31; //element_instance_tag 4 bits,
//object_type 2 bits,
//sampling_frequency_index 4 bits,
//num_front_channel_elements 4 bits,
//num_side_channel_elements 4 bits,
//num_back_channel_elements 4 bits,
//num_lfe_channel_elements 2 bits,
//num_assoc_data_elements 3 bits,
//num_valid_cc_elements 4 bits
// check mono_mixdown_present
if ((pBuffer[20] & 0x2) != 0) //mono mixdown is presented
{
ADIFHeaderLen += 5; //mono_mixdown_present 1 bit
//mono_mixdown_element_number 4 bits
//check stereo_mixdown_present
if ((pBuffer[21] & 0x10) != 0) //stereo mixdown is presented
{
ADIFHeaderLen += 5; //stereo_mixdown_present 1 bit
//stereo_mixdown_element_number 4 bits
//check matrix_mixdown_idx_present
if ((pBuffer[22] & 0x80) != 0) //matrix mixdown is presented
{
ADIFHeaderLen += 4; //matrix_mixdown_idx_present 1 bit
//matrix_mixdown_idx 2 bits
//pseudo_surround_enable 1 bit
}
else //matrix mixdown is not presented
{
ADIFHeaderLen += 1; //matrix_mixdown_idx_present 1 bit
}
}
else //stereo mixdown is not presented
{
ADIFHeaderLen += 1; //stereo_mixdown_present 1 bit
//check matrix_mixdown_idx_present
if ((pBuffer[21] & 0x8) != 0) //matrix mixdown is presented
{
ADIFHeaderLen += 4; //matrix_mixdown_idx_present 1 bit
//matrix_mixdown_idx 2 bits
//pseudo_surround_enable 1 bit
}
else //matrix mixdown is not presented
{
ADIFHeaderLen += 1; //matrix_mixdown_idx_present 1 bit
}
}//if ((pBuffer[21] & 0x10) != 0)
}
else //mono mixdown is not presented
{
ADIFHeaderLen += 1; //mono_mixdown_present 1 bit
//check stereo_mixdown_present
if ((pBuffer[20] & 0x1) != 0) //stereo mixdown is presented
{
ADIFHeaderLen += 5; //stereo_mixdown_present 1 bit
//stereo_mixdown_element_number 4 bits
//check matrix_mixdown_idx_present
if ((pBuffer[21] & 0x8) != 0) //matrix mixdown is presented
{
ADIFHeaderLen += 4; //matrix_mixdown_idx_present 1 bit
//matrix_mixdown_idx 2 bits
//pseudo_surround_enable 1 bit
}
else //matrix mixdown is not presented
{
ADIFHeaderLen += 1; //matrix_mixdown_idx_present 1 bit
}
}
else //stereo mixdown is not presented
{
ADIFHeaderLen += 1; //stereo_mixdown_present 1 bit
//check matrix_mixdown_idx_present
if ((pBuffer[21] & 0x80) != 0) //matrix mixdown is presented
{
ADIFHeaderLen += 4; //matrix_mixdown_idx_present 1 bit
//matrix_mixdown_idx 2 bits
//pseudo_surround_enable 1 bit
}
else //matrix mixdown is not presented
{
ADIFHeaderLen += 1; //matrix_mixdown_idx_present 1 bit
}
}//if ((pBuffer[20] & 0x1) != 0)
}//if ((pBuffer[20] & 0x2) != 0)
}// if (bitstreamType == 0)
for (i = 0; i < (int32)numFrontChanElem; i++)
{
//calculate channel configuration
offset = ADIFHeaderLen >> 3;
bitIndex = ADIFHeaderLen & 0x7;
tmp = (uint8)((pBuffer[offset] << bitIndex) | (pBuffer[offset+1] >> (8 - bitIndex)));
tmp >>= (8 - 1); //front channel element takes 1 bit
iChannelConfig += tmp;
//update ADIF variable header length
ADIFHeaderLen += 5; //front_element_is_cpe[i] 1 bit,
//front_element_tag_select[i] 4 bits
}
for (i = 0; i < (int32)numSideChanElem; i++)
{
//calculate channel configuration
offset = ADIFHeaderLen >> 3;
bitIndex = ADIFHeaderLen & 0x7;
tmp = (uint8)((pBuffer[offset] << bitIndex) | (pBuffer[offset+1] >> (8 - bitIndex)));
tmp >>= (8 - 1); //side channel element takes 1 bit
iChannelConfig += (tmp + 1);
//update ADIF variable header length
ADIFHeaderLen += 5; //side_element_is_cpe[i] 1 bit,
//side_element_tag_select[i] 4 bits
}
for (i = 0; i < (int32)numBackChanElem; i++)
{
//calculate channel configuration
offset = ADIFHeaderLen >> 3;
bitIndex = ADIFHeaderLen & 0x7;
tmp = (uint8)((pBuffer[offset] << bitIndex) | (pBuffer[offset+1] >> (8 - bitIndex)));
tmp >>= (8 - 1); //back channel element takes 1 bit
iChannelConfig += (tmp + 1);
//update ADIF variable header length
ADIFHeaderLen += 5; //back_element_is_cpe[i] 1 bit,
//back_element_tag_select[i] 4 bits
}
if (numLfeChanElem != 0)
{
iChannelConfig++; //1 front low frequency effects speaker
}
for (i = 0; i < (int32)numLfeChanElem; i++)
{
ADIFHeaderLen += 4; //lfe_element_tag_select[i] 4 bits
}
for (i = 0; i < (int32)numAssocDataElem; i++)
{
ADIFHeaderLen += 4; //assoc_data_element_tag_select[i] 4 bits
}
for (i = 0; i < (int32)numValidCCElem; i++)
{
ADIFHeaderLen += 5; //cc_element_is_ind_sw[i] 1 bit,
//valid_cc_element_tag_select[i] 4 bits
}
// byte_allignment
ADIFHeaderLen += 7;
ADIFHeaderLen &= 0xF8;
// comment_field_bytes (8 bits)
offset = ADIFHeaderLen >> 3;
bitIndex = ADIFHeaderLen & 0x7;
commentFieldBytes = (pBuffer[offset] << bitIndex) | (pBuffer[offset+1] >> (8 - bitIndex));
ADIFHeaderLen += 8; //comment_field_bytes 8 bits
for (i = 0; i < (int32)commentFieldBytes; i++)
{
ADIFHeaderLen += 8; //comment_field_data 8 bits
}
}// for (i = 0; i < (int32)numProgConfigElem + 1; i++)
}
else //copyright ID is not presented
{
ADIFHeaderLen += 3; // copyright_id_present 1 bit
// original_copy 1 bit,
// home 1 bit,
// check bitstream type
bitstreamType = pBuffer[4] & 0x10;
// get number of program config. element
numProgConfigElem = (pBuffer[7] & 0x1E) >> 1;
// get bitrate (max for variable rate bitstream)
iBitrate = bitRate = ((pBuffer[4] & 0xF0) << 15) |
(pBuffer[5] << 11) |
(pBuffer[6] << 3) |
((pBuffer[7] & 0xE0) >> 5);
if (iBitrate == 0) //bitrate is not known
{
PVMF_AACPARSER_LOGERROR((0, "AACBitstreamObject::getFileInfo- Misc Error"));
return AACBitstreamObject::MISC_ERROR;
}
ADIFHeaderLen += 28; // bitstream_type 1 bit,
// bitrate 23 bits
// num_program_config_elements 4 bits
for (i = 0; i < (int32)numProgConfigElem + 1; i++)
{
if (bitstreamType == 0) //bistream type is constant rate bitstream
{
ADIFHeaderLen += 20; //adif_buffer_fullness 20 bits
// get audio object type
iAudioObjectType = (uint8)(((pBuffer[10] & 0x1) << 1) | ((pBuffer[11] & 0x80) >> 7));
// get sampling rate index
iSampleFreqIndex = sampleFreqIndex = (uint8)((pBuffer[11] & 0x78) >> 3);
// get number of front channel elements
numFrontChanElem = (uint32)(((pBuffer[11] & 0x7) << 1) | ((pBuffer[12] & 0x80) >> 7));
// get number of side channel elements
numSideChanElem = (uint32)((pBuffer[12] & 0x78) >> 3);
// get number of back channel elements
numBackChanElem = (uint32)(((pBuffer[12] & 0x7) << 1) | ((pBuffer[13] & 0x80) >> 7));
// get number of LFE channel elements
numLfeChanElem = (uint32)((pBuffer[13] & 0x60) >> 5);
// get number of assoc data elements
numAssocDataElem = (uint32)((pBuffer[13] & 0x1C) >> 2);
// get number of valid CC elements
numValidCCElem = (uint32)(((pBuffer[13] & 0x3) << 2) | ((pBuffer[14] & 0xC0) >> 6));
ADIFHeaderLen += 31; //element_instance_tag 4 bits,
//object_type 2 bits,
//sampling_frequency_index 4 bits,
//num_front_channel_elements 4 bits,
//num_side_channel_elements 4 bits,
//num_back_channel_elements 4 bits,
//num_lfe_channel_elements 2 bits,
//num_assoc_data_elements 3 bits,
//num_valid_cc_elements 4 bits
// check mono_mixdown_present
if ((pBuffer[14] & 0x20) != 0) //mono mixdown is presented
{
ADIFHeaderLen += 5; //mono_mixdown_present 1 bit
//mono_mixdown_element_number 4 bits
//check stereo_mixdown_present
if ((pBuffer[14] & 0x1) != 0) //stereo mixdown is presented
{
ADIFHeaderLen += 5; //stereo_mixdown_present 1 bit
//stereo_mixdown_element_number 4 bits
//check matrix_mixdown_idx_present
if ((pBuffer[15] & 0x8) != 0) //matrix mixdown is presented
{
ADIFHeaderLen += 4; //matrix_mixdown_idx_present 1 bit
//matrix_mixdown_idx 2 bits
//pseudo_surround_enable 1 bit
}
else //matrix mixdown is not presented
{
ADIFHeaderLen += 1; //matrix_mixdown_idx_present 1 bit
}
}
else //stereo mixdown is not presented
{
ADIFHeaderLen += 1; //stereo_mixdown_present 1 bit
//check matrix_mixdown_idx_present
if ((pBuffer[15] & 0x80) != 0) //matrix mixdown is presented
{
ADIFHeaderLen += 4; //matrix_mixdown_idx_present 1 bit
//matrix_mixdown_idx 2 bits
//pseudo_surround_enable 1 bit
}
else //matrix mixdown is not presented
{
ADIFHeaderLen += 1; //matrix_mixdown_idx_present 1 bit
}
}//if ((pBuffer[14] & 0x1) != 0)
}
else //mono mixdown is not presented
{
ADIFHeaderLen += 1; //mono_mixdown_present 1 bit
//check stereo_mixdown_present
if ((pBuffer[14] & 0x10) != 0) //stereo mixdown is presented
{
ADIFHeaderLen += 5; //stereo_mixdown_present 1 bit
//stereo_mixdown_element_number 4 bits
//check matrix_mixdown_idx_present
if ((pBuffer[15] & 0x80) != 0) //matrix mixdown is presented
{
ADIFHeaderLen += 4; //matrix_mixdown_idx_present 1 bit
//matrix_mixdown_idx 2 bits
//pseudo_surround_enable 1 bit
}
else //matrix mixdown is not presented
{
ADIFHeaderLen += 1; //matrix_mixdown_idx_present 1 bit
}
}
else //stereo mixdown is not presented
{
ADIFHeaderLen += 1; //stereo_mixdown_present 1 bit
//check matrix_mixdown_idx_present
if ((pBuffer[14] & 0x8) != 0) //matrix mixdown is presented
{
ADIFHeaderLen += 4; //matrix_mixdown_idx_present 1 bit
//matrix_mixdown_idx 2 bits
//pseudo_surround_enable 1 bit
}
else //matrix mixdown is not presented
{
ADIFHeaderLen += 1; //matrix_mixdown_idx_present 1 bit
}
}//if ((pBuffer[14] & 0x10) != 0)
}//if ((pBuffer[14] & 0x20) != 0)
}
else //bistream type is variable rate bitstream
{
// get audio object type
iAudioObjectType = (uint8)((pBuffer[8] & 0x18) >> 3);
// get sampling rate index
iSampleFreqIndex = sampleFreqIndex = (uint8)(((pBuffer[8] & 0x7) << 1) | ((pBuffer[9] & 0x80) >> 7));
// get number of front channel elements
numFrontChanElem = (uint32)((pBuffer[9] & 0x78) >> 3);
// get number of side channel elements
numSideChanElem = (uint32)(((pBuffer[9] & 0x7) << 1) | ((pBuffer[10] & 0x80) >> 7));
// get number of back channel elements
numBackChanElem = (uint32)((pBuffer[10] & 0x78) >> 3);
// get number of LFE channel elements
numLfeChanElem = (uint32)((pBuffer[10] & 0x6) >> 1);
// get number of assoc data elements
numAssocDataElem = (uint32)(((pBuffer[10] & 0x1) << 2) | ((pBuffer[11] & 0xC0) >> 6));
// get number of valid CC elements
numValidCCElem = (uint32)((pBuffer[11] & 0x3C) >> 2);
ADIFHeaderLen += 31; //element_instance_tag 4 bits,
//object_type 2 bits,
//sampling_frequency_index 4 bits,
//num_front_channel_elements 4 bits,
//num_side_channel_elements 4 bits,
//num_back_channel_elements 4 bits,
//num_lfe_channel_elements 2 bits,
//num_assoc_data_elements 3 bits,
//num_valid_cc_elements 4 bits
// check mono_mixdown_present
if ((pBuffer[11] & 0x2) != 0) //mono mixdown is presented
{
ADIFHeaderLen += 5; //mono_mixdown_present 1 bit
//mono_mixdown_element_number 4 bits
//check stereo_mixdown_present
if ((pBuffer[12] & 0x10) != 0) //stereo mixdown is presented
{
ADIFHeaderLen += 5; //stereo_mixdown_present 1 bit
//stereo_mixdown_element_number 4 bits
//check matrix_mixdown_idx_present
if ((pBuffer[13] & 0x80) != 0) //matrix mixdown is presented
{
ADIFHeaderLen += 4; //matrix_mixdown_idx_present 1 bit
//matrix_mixdown_idx 2 bits
//pseudo_surround_enable 1 bit
}
else //matrix mixdown is not presented
{
ADIFHeaderLen += 1; //matrix_mixdown_idx_present 1 bit
}
}
else //stereo mixdown is not presented
{
ADIFHeaderLen += 1; //stereo_mixdown_present 1 bit
//check matrix_mixdown_idx_present
if ((pBuffer[12] & 0x8) != 0) //matrix mixdown is presented
{
ADIFHeaderLen += 4; //matrix_mixdown_idx_present 1 bit
//matrix_mixdown_idx 2 bits
//pseudo_surround_enable 1 bit
}
else //matrix mixdown is not presented
{
ADIFHeaderLen += 1; //matrix_mixdown_idx_present 1 bit
}
}//if ((pBuffer[12] & 0x10) != 0)
}
else //mono mixdown is not presented
{
ADIFHeaderLen += 1; //mono_mixdown_present 1 bit
//check stereo_mixdown_present
if ((pBuffer[11] & 0x1) != 0) //stereo mixdown is presented
{
ADIFHeaderLen += 5; //stereo_mixdown_present 1 bit
//stereo_mixdown_element_number 4 bits
//check matrix_mixdown_idx_present
if ((pBuffer[12] & 0x8) != 0) //matrix mixdown is presented
{
ADIFHeaderLen += 4; //matrix_mixdown_idx_present 1 bit
//matrix_mixdown_idx 2 bits
//pseudo_surround_enable 1 bit
}
else //matrix mixdown is not presented
{
ADIFHeaderLen += 1; //matrix_mixdown_idx_present 1 bit
}
}
else //stereo mixdown is not presented
{
ADIFHeaderLen += 1; //stereo_mixdown_present 1 bit
//check matrix_mixdown_idx_present
if ((pBuffer[12] & 0x80) != 0) //matrix mixdown is presented
{
ADIFHeaderLen += 4; //matrix_mixdown_idx_present 1 bit
//matrix_mixdown_idx 2 bits
//pseudo_surround_enable 1 bit
}
else //matrix mixdown is not presented
{
ADIFHeaderLen += 1; //matrix_mixdown_idx_present 1 bit
}
}//if ((pBuffer[11] & 0x1) != 0)
}//if ((pBuffer[11] & 0x2) != 0)
}// if (bitstreamType == 0)
for (i = 0; i < (int32)numFrontChanElem; i++)
{
//calculate channel configuration
offset = ADIFHeaderLen >> 3;
bitIndex = ADIFHeaderLen & 0x7;
tmp = (uint8)((pBuffer[offset] << bitIndex) | (pBuffer[offset+1] >> (8 - bitIndex)));
tmp >>= (8 - 1); //front channel element takes 1 bit
iChannelConfig += tmp;
//update ADIF variable header length
ADIFHeaderLen += 5; //front_element_is_cpe[i] 1 bit,
//front_element_tag_select[i] 4 bits
}
for (i = 0; i < (int32)numSideChanElem; i++)
{
//calculate channel configuration
offset = ADIFHeaderLen >> 3;
bitIndex = ADIFHeaderLen & 0x7;
tmp = (uint8)((pBuffer[offset] << bitIndex) | (pBuffer[offset+1] >> (8 - bitIndex)));
tmp >>= (8 - 1); //side channel element takes 1 bit
iChannelConfig += (tmp + 1);
//update ADIF variable header length
ADIFHeaderLen += 5; //side_element_is_cpe[i] 1 bit,
//side_element_tag_select[i] 4 bits
}
for (i = 0; i < (int32)numBackChanElem; i++)
{
//calculate channel configuration
offset = ADIFHeaderLen >> 3;
bitIndex = ADIFHeaderLen & 0x7;
tmp = (uint8)((pBuffer[offset] << bitIndex) | (pBuffer[offset+1] >> (8 - bitIndex)));
tmp >>= (8 - 1); //back channel element takes 1 bit
iChannelConfig += (tmp + 1);
//update ADIF variable header length
ADIFHeaderLen += 5; //side_element_is_cpe[i] 1 bit,
//side_element_tag_select[i] 4 bits
}
if (numLfeChanElem != 0)
{
iChannelConfig++; //1 front low frequency effects speaker
}
for (i = 0; i < (int32)numLfeChanElem; i++)
{
ADIFHeaderLen += 4; //lfe_element_tag_select[i] 4 bits
}
for (i = 0; i < (int32)numAssocDataElem; i++)
{
ADIFHeaderLen += 4; //assoc_data_element_tag_select[i] 4 bits
}
for (i = 0; i < (int32)numValidCCElem; i++)
{
ADIFHeaderLen += 5; //cc_element_is_ind_sw[i] 1 bit,
//valid_cc_element_tag_select[i] 4 bits
}
// byte_allignment
ADIFHeaderLen += 7;
ADIFHeaderLen &= 0xF8;
// comment_field_bytes (8 bits)
offset = ADIFHeaderLen >> 3;
bitIndex = ADIFHeaderLen & 0x7;
commentFieldBytes = (pBuffer[offset] << bitIndex) | (pBuffer[offset+1] >> (8 - bitIndex));
ADIFHeaderLen += 8; //comment_field_bytes 8 bits
for (i = 0; i < (int32)commentFieldBytes; i++)
{
ADIFHeaderLen += 8; //comment_field_data 8 bits
}
}// for (i = 0; i < (int32)numProgConfigElem + 1; i++)
} // if(id!=0)
// ADIF header length in bits
iADIFHeaderLen = HeaderLen = ADIFHeaderLen;
// get ADIF id header part to iAACHeaderBuffer (4 bytes)
oscl_memcpy(iAACHeaderBuffer, pBuffer, PACKET_INDICATOR_LENGTH);
}
else // Check if it is AAC raw bitstream file
{
int32 config_header_size = iActual_size;
int32 status = GetActualAacConfig(pBuffer,
&iAudioObjectType, &config_header_size, &sampleFreqIndex, &iChannelConfig);
if (status != SUCCESS) return AACBitstreamObject::MISC_ERROR;
// Retrieve the audio object type
if (iAudioObjectType != 2 &&
iAudioObjectType != 4 &&
iAudioObjectType != 5 &&
iAudioObjectType != 29)
{
// Unsupported object type
PVMF_AACPARSER_LOGERROR((0, "AACBitstreamObject::getFileInfo- Misc Error"));
return AACBitstreamObject::MISC_ERROR;
}
iSampleFreqIndex = sampleFreqIndex;
oscl_memcpy(iAACHeaderBuffer, pBuffer, config_header_size);
iRawAACHeaderLen = (uint32)config_header_size;
HeaderLen = (uint32)config_header_size << 3;
// Raw AAC format
iAACFormat = format = EAACRaw;
}
}
}
else
{
fileSize = iFileSize;
format = iAACFormat;
sampleFreqIndex = iSampleFreqIndex;
}
return ret_value;
}
//! extended search to get clip information only for adts format
int32 AACBitstreamObject::extendedAdtsSearchForFileInfo(TAACFormat& format,
uint8& sampleFreqIndex)
{
sampleFreqIndex = 0;
int32 ret_value = AACBitstreamObject::EVERYTHING_OK;
iPos = iPosSyncAdtsFound; /* overlap only needed data */
ret_value = refill();
if (ret_value == AACBitstreamObject::EVERYTHING_OK)
{
uint8 *pBuffer = &iBuffer[iPos];
// Check for possible adts sync word
int32 index = find_adts_syncword(pBuffer);
if (index != -1)
{
//ADTS format
iAACFormat = format = EAACADTS;
// get sample frequency index
iSampleFreqIndex = sampleFreqIndex = (uint8)((pBuffer[2 + index] & 0x3c) >> 2);
// check the crc_check field
ibCRC_Check = ((pBuffer[1 + index] & 0x01) ? false : true);
// get ADTS fixed header part to iAACHeaderBuffer
oscl_memcpy(iAACHeaderBuffer, &pBuffer[index], PACKET_INDICATOR_LENGTH);
}
else
{
if (iBytesRead > ADTS_SYNC_SEARCH_LENGTH(iFileSize, 5)) // search over 3.13 % of the file
{
return AACBitstreamObject::MISC_ERROR; // break the loop
}
//otherwise keep looking
}
}
return ret_value;
}
int32 AACBitstreamObject::getDecoderConfigHeader(uint8* headerBuffer)
{
if (iAACFormat == EAACADTS) //ADTS
{
if (!headerBuffer ||
!(iAACHeaderBuffer[0] == 0xff &&
(iAACHeaderBuffer[1] & 0xf0) == 0xf0))
{
PVMF_AACPARSER_LOGERROR((0, "AACBitstreamObject::getFileInfo- Misc Error"));
return AACBitstreamObject::MISC_ERROR;
}
// parse the ADTS header of the first frame: iAACHeaderReferenceBuffer[] (got from the bitstream in InitAACFile()
headerBuffer[0] = headerBuffer[1] = 0;
// 1. construct auditoObjectType(bit1-5, 5 bits, MPEG-4) from profile(bit17-18, 2 bits, ADTS)
uint8 profile = (uint8)(iAACHeaderBuffer[2] >> 6); // 2 bits long
headerBuffer[0] |= ++profile << 3; // put it into the highest 5 bits
// 2. construct samplingFrequencyIndex(bit6-9, 4 bits, MPEG-4) from sampling_frequency_index(bit19-22, 4 bits, ADTS)
uint8 sampling_frequency_index = (uint8)((iAACHeaderBuffer[2] >> 2) & 0x0f); // 4 bits long
headerBuffer[0] |= (sampling_frequency_index >> 1); // put 3 bits
headerBuffer[1] |= ((sampling_frequency_index & 0x1) << 7); // put 1 bit
// 3. construct channelConfiguration(bit10-13, 4 bits, MPEG-4) from channel_configuration(bit22-24, 3 bits, ADTS)
uint8 channel_config = (uint8)(((iAACHeaderBuffer[2] & 0x01) << 2) |
(iAACHeaderBuffer[3] >> 6)); // 3 bits long in ADTS => 4 valid bits in MPEG-4
headerBuffer[1] |= (channel_config << 3);
}
else if (iAACFormat == EAACADIF) //ADIF
{
if (!headerBuffer ||
!((iAACHeaderBuffer[0] == 0x41) && // 'A'
(iAACHeaderBuffer[1] == 0x44) && // 'D'
(iAACHeaderBuffer[2] == 0x49) && // 'I'
(iAACHeaderBuffer[3] == 0x46))) // 'F'
{
PVMF_AACPARSER_LOGERROR((0, "AACBitstreamObject::getFileInfo- Misc Error"));
return AACBitstreamObject::MISC_ERROR;
}
// parse the ADIF header
headerBuffer[0] = headerBuffer[1] = 0;
// 1. construct audio object type (2 bits)
headerBuffer[0] |= ((iAudioObjectType + 1) << 3);
// 2. construct sampling frequency index (4 bits)
headerBuffer[0] |= (iSampleFreqIndex >> 1); //put 3 bits in headerBuffer[0]
headerBuffer[1] |= ((iSampleFreqIndex & 0x1) << 7); //put 1 bit in headerBuffer[1]
// 3. construct channel configuration (4 bits)
headerBuffer[1] |= ((iChannelConfig + 1) << 3);
}
else if (iAACFormat == EAACRaw)
{
// Just copy the audio specific config
oscl_memcpy(headerBuffer, iAACHeaderBuffer, iRawAACHeaderLen);
}
return AACBitstreamObject::EVERYTHING_OK;
}
template <class PtrType>
class AutoPtrArrayContainer
{
private:
bool _Ownership;
PtrType *_Ptr;
public:
// default constructors
explicit AutoPtrArrayContainer(PtrType *inPtr = 0) :
_Ownership(inPtr != 0), _Ptr(inPtr) {};
~AutoPtrArrayContainer()
{
if (_Ownership && _Ptr)
{
OSCL_ARRAY_DELETE(_Ptr);
_Ptr = NULL;
}
_Ownership = false;
}
};
//----------------------------------------------------------------------------
// FUNCTION NAME: CAACFileParser::CAACFileParser
//----------------------------------------------------------------------------
// INPUT AND OUTPUT DEFINITIONS
//
// Inputs:
// None
//
// Outputs:
// None
//
// Returns:
// None
//
// Global Variables Used:
// None
//
//----------------------------------------------------------------------------
// FUNCTION DESCRIPTION
//
// Constructor for CAACFileParser class
//
//----------------------------------------------------------------------------
// REQUIREMENTS
//
//----------------------------------------------------------------------------
// REFERENCES
//
//------------------------------------------------------------------------------
// CAUTION
//
//------------------------------------------------------------------------------
OSCL_EXPORT_REF CAACFileParser::CAACFileParser(void) :
iAACDuration(0),
iAACSampleFrequency(0),
iAACBitRate(0),
iAACHeaderLen(0),
iFirstTime(false),
iAACFileSize(0),
iTotalNumFramesRead(0),
iAACFormat(EAACUnrecognized),
iEndOfFileReached(false),
iLogger(PVLogger::GetLoggerObject("pvaacparser")),
iDiagnosticLogger(PVLogger::GetLoggerObject("playerdiagnostics.pvaac_parser")),
ipBSO(NULL)
{
}
//----------------------------------------------------------------------------
// FUNCTION NAME: CAACFileParser::~CAACFileParser
//----------------------------------------------------------------------------
// INPUT AND OUTPUT DEFINITIONS
//
// Inputs:
// None
//
// Outputs:
// None
//
// Returns:
// None
//
// Global Variables Used:
// None
//
//----------------------------------------------------------------------------
// FUNCTION DESCRIPTION
//
// Destructor for CAACFileParser class
//
//----------------------------------------------------------------------------
// REQUIREMENTS
//
//----------------------------------------------------------------------------
// REFERENCES
//
//------------------------------------------------------------------------------
// CAUTION
//
//------------------------------------------------------------------------------
OSCL_EXPORT_REF CAACFileParser::~CAACFileParser(void)
{
if (iAACFile.IsOpen())
{
iAACFile.Close();
}
if (ipBSO != NULL)
{
PV_AAC_FF_DELETE(NULL, AACBitstreamObject, ipBSO);
ipBSO = NULL;
}
}
//----------------------------------------------------------------------------
// FUNCTION NAME: CAACFileParser::InitAACFile
//----------------------------------------------------------------------------
// INPUT AND OUTPUT DEFINITIONS
//
// Inputs:
// aClip = pointer to the AAC 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 AAC file, checks for AAC format type, calculates
// the track duration, and sets the AAC bitrate value.
//
//----------------------------------------------------------------------------
// REQUIREMENTS
//
//----------------------------------------------------------------------------
// REFERENCES
//
//------------------------------------------------------------------------------
// CAUTION
//
//------------------------------------------------------------------------------
OSCL_EXPORT_REF bool CAACFileParser::InitAACFile(OSCL_wString& aClip, bool aInitParsingEnable, Oscl_FileServer* iFileSession, PVMFCPMPluginAccessInterfaceFactory* aCPMAccess, OsclFileHandle*aHandle)
{
uint32 bitRateValue;
uint32 HeaderLenValue;
iAACFile.SetCPM(aCPMAccess);
iAACFile.SetFileHandle(aHandle);
//For aac overwritte pvfile default settings in order to prevent
//audio artifacts when playing files from MMC
//use native cache (if supported by the platform) size 32KB.
PVFileCacheParams cacheParams;
cacheParams.iCacheSize = 32768; //32K
cacheParams.iNativeAccessMode = 1;
iAACFile.SetFileCacheParams(cacheParams);
// Open the file (aClip)
if (iAACFile.Open(aClip.get_cstr(), (Oscl_File::MODE_READ | Oscl_File::MODE_BINARY), *iFileSession) != 0)
{
return false;
}
// create ipBSO
PV_AAC_FF_NEW(NULL, AACBitstreamObject, (&iAACFile), ipBSO);
if (!ipBSO)
{
return false;
}
if (ipBSO->get())
{
return false;
}
// get file info: file size, format, sampling rate
uint8 sampleFreqTableValue;
TAACFormat format;
if (ipBSO->getFileInfo(iAACFileSize, format, sampleFreqTableValue, bitRateValue, HeaderLenValue, aClip))
{
return false;
}
if (format == EAACADTS)
{
// ADTS format
iAACFormat = EAACADTS;
if (sampleFreqTableValue >= 16)
return false;
iAACSampleFrequency = ADTSSampleFreqTable[(uint16)sampleFreqTableValue];
if (iAACSampleFrequency == -1)
return false;
}
else if (format == EAACADIF)
{
// ADIF format
iAACFormat = EAACADIF;
//ADIF and ADTS uses the same sampling frequency lookup table
if (sampleFreqTableValue >= 16)
return false;
iAACSampleFrequency = ADTSSampleFreqTable[(uint16)sampleFreqTableValue];
if (iAACSampleFrequency == -1)
return false;
//bitrate and variable header length for ADIF only
iAACBitRate = (int32)bitRateValue;
iAACHeaderLen = (int32)HeaderLenValue;
iFirstTime = true;
}
else if (format == EAACRaw)
{
// AAC raw format
iAACFormat = EAACRaw;
// Use the same sampling frequency lookup table
if (sampleFreqTableValue >= 16)
return false;
iAACSampleFrequency = ADTSSampleFreqTable[(uint16)sampleFreqTableValue];
if (iAACSampleFrequency == -1)
return false;
//variable header length for raw only
iAACHeaderLen = (int32)HeaderLenValue;
iFirstTime = true;
}
else
{
iAACFormat = EAACUnrecognized;
return false;
}
// Determine file duration and set up random positioning table if needed
if (aInitParsingEnable)
{
if (iAACFormat == EAACADTS)
{
// fully go through each frame to calculate duration
int32 status = AACBitstreamObject::EVERYTHING_OK;
int32 frame_size = 0;
int32 numBlocks;
uint8 *maxAACFrameBuffer = OSCL_ARRAY_NEW(uint8, MAX_AAC_FRAME_SIZE); // MAX_AAC_FRAME_SIZE=8192
if (!maxAACFrameBuffer)
{
return false;
}
AutoPtrArrayContainer<uint8> autoPtr(maxAACFrameBuffer);
iAACDuration = 0;
int32 filePos = 0;
iRPTable.push_back(filePos);
while (status == AACBitstreamObject::EVERYTHING_OK)
{
// get the next frame
status = ipBSO->getNextFrameInfo(frame_size, numBlocks);
if (status == AACBitstreamObject::END_OF_FILE)
{
break;
}
else if (status == AACBitstreamObject::EVERYTHING_OK && frame_size > 0)
{
int32 hdrSize = 0;
status = ipBSO->getNextFrame(maxAACFrameBuffer, frame_size, hdrSize);
if (status == AACBitstreamObject::EVERYTHING_OK)
{
// calulate the number of frames
iAACDuration ++;
// set up the table for randow positioning
int32 frame_length = frame_size + ADTS_HEADER_LENGTH + (ipBSO->isCRCEnabled() ? 2 : 0);
filePos += frame_length;
iRPTable.push_back(filePos);
}
else if (status == AACBitstreamObject::END_OF_FILE)
{
break;
}
else
{
// error happens!
PVMF_AACPARSER_LOGERROR((0, "Error InitAacfile"));
return false;
}
}
else
{
// error happens!
PVMF_AACPARSER_LOGERROR((0, "CAACFileParser::InitAACFile:Error in getting next frame "));
return false;
}
}
// get the duration in millisec
MediaClockConverter mcc;
mcc.set_timescale(iAACSampleFrequency);
mcc.set_clock(iAACDuration*1024, 0);
iAACDuration = mcc.get_converted_ts(1000);
if (ipBSO->reset(0))
return false;
}
else if (iAACFormat == EAACADIF)
{
int32 raw_data_bits;
iAACDuration = 0;
iRPTable.push_back(iAACDuration);
raw_data_bits = iAACFileSize * 8 - iAACHeaderLen;
// rough duration calculation based on max bitrate for variable rate bitstream
MediaClockConverter mcc;
mcc.set_timescale(iAACBitRate);
mcc.set_clock(raw_data_bits, 0);
iAACDuration = mcc.get_converted_ts(1000);
if (ipBSO->reset(ipBSO->GetByteOffsetToStartOfAudioFrames() + (iAACHeaderLen >> 3)))
return false;
}
else if (iAACFormat == EAACRaw)
{
iAACDuration = 0;
iRPTable.push_back(iAACDuration);
// Duration cannot be calculated
int32 hdrsize = iAACHeaderLen >> 3;
if (iAACHeaderLen&0x7)
{
++hdrsize;
}
if (ipBSO->reset(ipBSO->GetByteOffsetToStartOfAudioFrames() + hdrsize))
{
PVMF_AACPARSER_LOGERROR((0, "CAACFileParser::InitAACFile:Error Bitstream object failed to reset"));
return false;
}
}
} // end of: if(aInitParsingEnable)
return true;
}
//----------------------------------------------------------------------------
// FUNCTION NAME: CAACFileParser::RetrieveFileInfo
//----------------------------------------------------------------------------
// INPUT AND OUTPUT DEFINITIONS
//
// Inputs:
//
// Outputs:
// None
//
// Returns:
// false if an error happens, else true
//
// Global Variables Used:
// None
//
//----------------------------------------------------------------------------
// FUNCTION DESCRIPTION
//
// This function opens the AAC file, checks for AAC format type, calculates
// the track duration, and sets the AAC bitrate value.
//
//----------------------------------------------------------------------------
// REQUIREMENTS
//
//----------------------------------------------------------------------------
// REFERENCES
//
//------------------------------------------------------------------------------
// CAUTION
//
//------------------------------------------------------------------------------
OSCL_EXPORT_REF bool CAACFileParser::RetrieveFileInfo(TPVAacFileInfo& aInfo)
{
if (iAACFormat == EAACUnrecognized)
{
// File is not open and parsed
return false;
}
aInfo.iTimescale = 1000;
aInfo.iDuration = iAACDuration;
aInfo.iSampleFrequency = iAACSampleFrequency;
aInfo.iBitrate = iAACBitRate;
aInfo.iFormat = iAACFormat;
aInfo.iFileSize = iAACFileSize;
PVMF_AACPARSER_LOGDIAGNOSTICS((0, "CAACFileParser::RetrieveFileInfo- duration = %d, bitrate = %d, filesize = %d", iAACDuration, iAACBitRate, iAACFileSize));
return true;
}
//----------------------------------------------------------------------------
// FUNCTION NAME: CAACFileParser::RetrieveID3Info
//----------------------------------------------------------------------------
// INPUT AND OUTPUT DEFINITIONS
//
// Inputs:
// aID3MetaData: pointer to data structure for the output.
//
// Outputs:
// None
//
// Returns:
// false if an error happens, else true
//
// Global Variables Used:
// None
//
//----------------------------------------------------------------------------
// FUNCTION DESCRIPTION
//
// This function retrieves the ID3 data if any was found in the file.
//
//----------------------------------------------------------------------------
// REQUIREMENTS
//
//----------------------------------------------------------------------------
// REFERENCES
//
//------------------------------------------------------------------------------
// CAUTION
//
//------------------------------------------------------------------------------
OSCL_EXPORT_REF bool CAACFileParser::RetrieveID3Info(PvmiKvpSharedPtrVector& aID3MetaData)
{
if (ipBSO)
{
ipBSO->ID3MetaData(aID3MetaData);
if (aID3MetaData.size() > 0)
return true;
else
return false;
}
else
{
return false;
}
}
OSCL_EXPORT_REF bool CAACFileParser::IsID3Frame(const OSCL_String &frameType)
{
return ipBSO->IsID3Frame(frameType);
}
OSCL_EXPORT_REF void CAACFileParser::GetID3Frame(const OSCL_String& aFrameType, PvmiKvpSharedPtrVector& aFrame)
{
ipBSO->GetID3Frame(aFrameType, aFrame);
}
//----------------------------------------------------------------------------
// FUNCTION NAME: CAACFileParser::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 CAACFileParser::ResetPlayback(uint32 aStartTime, uint32& aActualStartTime)
{
// Check if the file is opened
int32 result;
if (!iAACFile.IsOpen())
{
PVMF_AACPARSER_LOGERROR((0, "CAACFileParser::ResetPlayback- Misc error-"));
return AACBitstreamObject::MISC_ERROR;
}
// initialize "iTotalNumFramesRead"
// +1 means we choose the next frame(ts>=aStartTime)
//iTotalNumFramesRead = aStartTime/(1024000/iAACSampleFrequency);
iTotalNumFramesRead = (int32)((OsclFloat)aStartTime * iAACSampleFrequency / 1024000.0) + (aStartTime > 0) * 1;
PVMF_AACPARSER_LOGDIAGNOSTICS((0, "CAACFileParser::resetplayback - TotalNumFramesRead=%d", iTotalNumFramesRead));
if (iAACFormat == EAACADTS)
{
// set new file position
int32 newPosition = 0;
if (iAACDuration != 0 && iRPTable.size() <= 0)
{
newPosition = (iAACFileSize * aStartTime) / iAACDuration;
PVMF_AACPARSER_LOGDIAGNOSTICS((0, "CAACFileParser::resetplayback - newPosition=%d", newPosition));
if (newPosition < 0)
{
newPosition = 0; // if we have no duration information, reset the file position at 0.
}
}
else if (iRPTable.size() > 0)
{
// use the randow positioning table to determine the file position
if (iTotalNumFramesRead > (int32)iRPTable.size())
{
iTotalNumFramesRead = ((int32)iRPTable.size()) - 2;
}
newPosition = iRPTable[iTotalNumFramesRead];
}
result = ipBSO->reset(ipBSO->GetByteOffsetToStartOfAudioFrames() + newPosition);
if (newPosition >= 0 && result)
{
PVMF_AACPARSER_LOGERROR((0, "CAACFileParser::ResetPlayback- Misc error-"));
return result;
}
iEndOfFileReached = false;
}
else if (iAACFormat == EAACADIF)
{
int32 newPosition = (iAACHeaderLen >> 3);
if (newPosition >= 0 && ipBSO->reset(ipBSO->GetByteOffsetToStartOfAudioFrames() + newPosition))
{
PVMF_AACPARSER_LOGERROR((0, "CAACFileParser::ResetPlayback- Misc error-"));
return AACBitstreamObject::MISC_ERROR;
}
iEndOfFileReached = false;
iFirstTime = true;
iTotalNumFramesRead = 0; // For ADIF reposition to time 0 always
}
else if (iAACFormat == EAACRaw)
{
int32 newPosition = (iAACHeaderLen >> 3);
if (iAACHeaderLen&0x7)
{
++newPosition;
}
if (newPosition >= 0 && ipBSO->reset(ipBSO->GetByteOffsetToStartOfAudioFrames() + newPosition))
{
PVMF_AACPARSER_LOGERROR((0, "CAACFileParser::ResetPlayback- Misc error-"));
return AACBitstreamObject::MISC_ERROR;
}
iEndOfFileReached = false;
iFirstTime = true;
iTotalNumFramesRead = 0; // For AAC raw bitstream reposition to time 0 always
}
MediaClockConverter mcc;
mcc.set_timescale(iAACSampleFrequency);
mcc.set_clock(iTotalNumFramesRead*1024, 0);
aActualStartTime = mcc.get_converted_ts(1000);
PVMF_AACPARSER_LOGDIAGNOSTICS((0, "CAACFileParser::resetplayback - aActualStartTime=%d", aActualStartTime));
return AACBitstreamObject::EVERYTHING_OK;
}
//----------------------------------------------------------------------------
// FUNCTION NAME: CAACFileParser::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 CAACFileParser::SeekPointFromTimestamp(uint32 aStartTime)
{
// Check if the file is opened
if (!iAACFile.IsOpen())
{
return 0;
}
// Determine the frame number corresponding to timestamp
// note: +1 means we choose the next frame(ts>=aStartTime)
uint32 startframenum = (int32)((OsclFloat)aStartTime * iAACSampleFrequency / 1024000.0) + (aStartTime > 0) * 1;
// Correct the frame number if necessary
if (iAACFormat == EAACADTS)
{
// set new file position
if (iAACDuration != 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;
}
}
}
else if (iAACFormat == EAACADIF || iAACFormat == EAACRaw)
{
// Not enough info in file to reposition so go to time 0
return 0;
}
return (int32)((OsclFloat)startframenum*1024000.0 / iAACSampleFrequency);
}
//----------------------------------------------------------------------------
// FUNCTION NAME: CAACFileParser::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 AAC 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
CAACFileParser::GetNextBundledAccessUnits(uint32 *aNumSamples,
GAU *aGau,
bool bADTSHeaderIncluded)
{
// AMR format has already been identified in InitAMRFile function.
// Check if AMR format is valid as the safeguard
if (iAACFormat == EAACUnrecognized)
{
PVMF_AACPARSER_LOGERROR((0, "CAACFileParser::GetNextBundledAccessUnits- Misc error-"));
return AACBitstreamObject::MISC_ERROR;
}
int32 returnValue = AACBitstreamObject::EVERYTHING_OK;
if (iAACFormat == EAACADTS)
{
if (iEndOfFileReached)
{
*aNumSamples = 0;
return AACBitstreamObject::END_OF_FILE;
}
uint8* pTempGau = (uint8 *)aGau->buf.fragments[0].ptr;
uint32 gauBufferSize = aGau->buf.fragments[0].len;
uint32 i, bytesReadInGau = 0, numSamplesRead = 0;
int32 frame_size = 0, numBlocks;
int32 prev_iTotalNumFramesRead = iTotalNumFramesRead; // BX
for (i = 0; i < *aNumSamples && !iEndOfFileReached; i++)
{
// get the frame size and number of data blocks
returnValue = ipBSO->getNextFrameInfo(frame_size, numBlocks);
PVMF_AACPARSER_LOGDIAGNOSTICS((0, "CAACFileParser::GetNextBundledAccessUnits - frame_size=%d", frame_size));
if (returnValue == AACBitstreamObject::END_OF_FILE)
{
iEndOfFileReached = true;
break;
}
else if (returnValue == AACBitstreamObject::EVERYTHING_OK && frame_size > 0)
{
// Check whether the gau buffer will be overflow or the requested number
// of samples will be met
if (bytesReadInGau + frame_size >= gauBufferSize ||
numSamplesRead + numBlocks > *aNumSamples)
break;
// At this point, we can get the next frame
int32 hdrSize = 0;
returnValue = ipBSO->getNextFrame(pTempGau, frame_size, hdrSize, bADTSHeaderIncluded);
if (returnValue == AACBitstreamObject::END_OF_FILE)
{
iEndOfFileReached = true;
break;
}
else if (returnValue == AACBitstreamObject::EVERYTHING_OK)
{
// update infomation
pTempGau += frame_size;
bytesReadInGau += frame_size;
aGau->info[i].len = frame_size + hdrSize;
aGau->info[i].ts = (int32)(((OsclFloat)(iTotalNumFramesRead++) * 1024000.0) / (OsclFloat)iAACSampleFrequency); // BX
numSamplesRead += numBlocks;
}
else
{ // error happens!!
PVMF_AACPARSER_LOGERROR((0, "CAACFileParser::GetNextBundledAccessUnits- Read error-"));
*aNumSamples = 0;
return AACBitstreamObject::READ_ERROR;
}
}
else
{
// error happens!!
PVMF_AACPARSER_LOGERROR((0, "CAACFileParser::GetNextBundledAccessUnits- Read error-"));
*aNumSamples = 0;
return AACBitstreamObject::READ_ERROR;
}
} // end of: for(i = 0; i < *aNumSamples && !iEndOfFileReached; i++)
aGau->info[0].ts = (int32)(((OsclFloat)prev_iTotalNumFramesRead * 1024000.0) / (OsclFloat)iAACSampleFrequency); // BX
*aNumSamples = numSamplesRead;
}
else if (iAACFormat == EAACADIF || iAACFormat == EAACRaw)
{
*aNumSamples = 0;
uint8* pTempGau = (uint8 *)aGau->buf.fragments[0].ptr; //point to the current data location in StreamingBuffer
uint32 gauBufferSize = aGau->buf.fragments[0].len;
uint32 bytesReadInGau = 0;
uint32 bytestoread = 0;
uint32 i;
if (iFirstTime == true)
{
// read from file to get two guranteed AAC decoder frames in streaming buffer
for (i = 0; i < 2; i++) //AAC Streaming Buffer Max Data Size is 15359 (9*1536 + 1535)
{
// At this point, we can get the next frame
if (bytesReadInGau >= gauBufferSize)
{
// No more buffer space to read
break;
}
bytestoread = gauBufferSize - bytesReadInGau;
if (bytestoread > AAC_DECODER_INPUT_BUFF_SIZE)
{
bytestoread = AAC_DECODER_INPUT_BUFF_SIZE;
}
int32 hdrSize = 0;
returnValue = ipBSO->getNextFrame(pTempGau, (int32 &)bytestoread, hdrSize, bADTSHeaderIncluded);
if (returnValue == AACBitstreamObject::END_OF_FILE)
{
iEndOfFileReached = true;
break;
}
else if (returnValue == AACBitstreamObject::EVERYTHING_OK)
{
// update infomation
pTempGau += bytestoread;
aGau->info[i].len = bytestoread;
aGau->info[i].ts = 0; // First block of AAC data read has timestamp 0
bytesReadInGau += bytestoread;
*aNumSamples += 1;
}
else
{
// error happens!!
PVMF_AACPARSER_LOGERROR((0, "CAACFileParser::GetNextBundledAccessUnits- Read error-"));
return AACBitstreamObject::READ_ERROR;
}
}
iFirstTime = false;
}
else // read from file to get one guranteed AAC decoder frame in streaming buffer
{
// At this point, we can get the next frame
bytestoread = gauBufferSize;
if (bytestoread > AAC_DECODER_INPUT_BUFF_SIZE)
{
bytestoread = AAC_DECODER_INPUT_BUFF_SIZE;
}
int32 hdrSize = 0;
returnValue = ipBSO->getNextFrame(pTempGau, (int32 &)bytestoread, hdrSize, bADTSHeaderIncluded);
if (returnValue == AACBitstreamObject::END_OF_FILE)
{
iEndOfFileReached = true;
}
else if (returnValue == AACBitstreamObject::EVERYTHING_OK)
{
// update infomation
aGau->info[0].len = bytestoread;
aGau->info[0].ts = 0xFFFFFFFF; // Unknown timestamp
// aGau->info[0].ts=(int32)(((OsclFloat)(iTotalNumFramesRead++) * 1024000.0) / (OsclFloat)iAACSampleFrequency); // BX
bytesReadInGau += bytestoread;
*aNumSamples += 1;
}
else
{
// error happens!!
PVMF_AACPARSER_LOGERROR((0, "CAACFileParser::GetNextBundledAccessUnits- Read error-"));
return AACBitstreamObject::READ_ERROR;
}
}
}
//We may have reached EOF but also found some samples.
//don't return EOF until there are no samples left.
if (returnValue == AACBitstreamObject::END_OF_FILE
&& *aNumSamples > 0)
{
return AACBitstreamObject::EVERYTHING_OK;
}
return returnValue;
}
//----------------------------------------------------------------------------
// FUNCTION NAME: CAACFileParser::PeekNextTimestamp
//----------------------------------------------------------------------------
// INPUT AND OUTPUT DEFINITIONS
//
// Inputs:
// None
//
// Outputs:
// None
//
// Returns:
// return = status EVERYTHING_OK.
//
// Global Variables Used:
// None
//
//----------------------------------------------------------------------------
// FUNCTION DESCRIPTION
//
// This function returns the next timestamp without processing any data.
//
//----------------------------------------------------------------------------
// REQUIREMENTS
//
//----------------------------------------------------------------------------
// REFERENCES
//
//------------------------------------------------------------------------------
// CAUTION
//
//------------------------------------------------------------------------------
OSCL_EXPORT_REF int32 CAACFileParser::PeekNextTimestamp(uint32& ts)
{
MediaClockConverter mcc;
mcc.set_timescale(iAACSampleFrequency);
mcc.set_clock((iTotalNumFramesRead + 1)*1024, 0);
ts = mcc.get_converted_ts(1000);
return AACBitstreamObject::EVERYTHING_OK;
}
//----------------------------------------------------------------------------
// FUNCTION NAME: CAACFileParser::GetTrackDecoderSpecificInfoSize
//----------------------------------------------------------------------------
// INPUT AND OUTPUT DEFINITIONS
//
// Inputs:
// None
//
// Outputs:
// None
//
// Returns:
// return = AAC_DECODER_SPECIFIC_INFO_SIZE
//
// Global Variables Used:
// None
//
//----------------------------------------------------------------------------
// FUNCTION DESCRIPTION
//
// This function returns the value defined by AAC_DECODER_SPECIFIC_INFO_SIZE.
//
//----------------------------------------------------------------------------
// REQUIREMENTS
//
//----------------------------------------------------------------------------
// REFERENCES
//
//------------------------------------------------------------------------------
// CAUTION
//
//------------------------------------------------------------------------------
OSCL_EXPORT_REF int32 CAACFileParser::GetTrackDecoderSpecificInfoSize(void)
{
if (iAACFormat == EAACRaw)
{
int32 infosize = iAACHeaderLen >> 3;
if (iAACHeaderLen&0x7)
{
++infosize;
}
return infosize;
}
else
{
return AAC_DECODER_SPECIFIC_INFO_SIZE;
}
}
//----------------------------------------------------------------------------
// FUNCTION NAME: CAACFileParser::GetTrackDecoderSpecificInfoContent
//----------------------------------------------------------------------------
// INPUT AND OUTPUT DEFINITIONS
//
// Inputs:
// None
//
// Outputs:
// None
//
// Returns:
// return = address to location of iAACFrameBuffer[PACKET_INDICATOR_LENGTH]
//
// Global Variables Used:
// None
//
//----------------------------------------------------------------------------
// FUNCTION DESCRIPTION
//
// This function populates iAACFrameBuffer with the two byte of decoder
// specific info and returns the address to the values.
//
//----------------------------------------------------------------------------
// REQUIREMENTS
//
//----------------------------------------------------------------------------
// REFERENCES
//
//------------------------------------------------------------------------------
// CAUTION
//
//------------------------------------------------------------------------------
OSCL_EXPORT_REF uint8* CAACFileParser::GetTrackDecoderSpecificInfoContent(void)
{
iAACFrameBuffer[PACKET_INDICATOR_LENGTH] = 0x12;
iAACFrameBuffer[PACKET_INDICATOR_LENGTH + 1] = 0x10;
ipBSO->getDecoderConfigHeader(&iAACFrameBuffer[PACKET_INDICATOR_LENGTH]);
return &iAACFrameBuffer[PACKET_INDICATOR_LENGTH];
}
//----------------------------------------------------------------------------
// FUNCTION NAME: CAACFileParser::GetAACFormat
//----------------------------------------------------------------------------
// INPUT AND OUTPUT DEFINITIONS
//
// Inputs:
// None
//
// Outputs:
// None
//
// Returns:
// return = iAACFormat
//
// Global Variables Used:
// None
//
//----------------------------------------------------------------------------
// FUNCTION DESCRIPTION
//
// This function returns iAACFormat value.
//
//----------------------------------------------------------------------------
// REQUIREMENTS
//
//----------------------------------------------------------------------------
// REFERENCES
//
//------------------------------------------------------------------------------
// CAUTION
//
//------------------------------------------------------------------------------
OSCL_EXPORT_REF TAACFormat CAACFileParser::GetAACFormat(void)
{
return iAACFormat;
}
OSCL_EXPORT_REF PVID3Version CAACFileParser::GetID3Version() const
{
return ipBSO->GetID3Version();
}
OSCL_EXPORT_REF ParserErrorCode CAACFileParser::getAACHeaderLen(OSCL_wString& aClip,
bool aInitParsingEnable,
Oscl_FileServer* iFileSession,
PVMFCPMPluginAccessInterfaceFactory* aCPMAccess,
OsclFileHandle* aHandle,
uint32* HeaderLenValue)
{
PVFile iAACFileTemp;
OSCL_UNUSED_ARG(aInitParsingEnable);
iAACFileTemp.SetCPM(aCPMAccess);
iAACFileTemp.SetFileHandle(aHandle);
// Open the file (aClip)
if (iAACFileTemp.Open(aClip.get_cstr(), (Oscl_File::MODE_READ | Oscl_File::MODE_BINARY), *iFileSession) != 0)
{
PVMF_AACPARSER_LOGERROR((0, "CAACFileParser::getAACHeaderLen- File open error-"));
return FILE_OPEN_ERROR;
}
AACBitstreamObject *ipBSOTemp;
PV_AAC_FF_NEW(NULL, AACBitstreamObject, (&iAACFileTemp), ipBSOTemp);
if (!ipBSOTemp || ipBSOTemp->get())
{
PVMF_AACPARSER_LOGERROR((0, "CAACFileParser::getAACHeaderLen- Memory allocation failed-"));
// release temp storage, file control block..
iAACFileTemp.Close();
PV_AAC_FF_DELETE(NULL, AACBitstreamObject, ipBSOTemp);
return MEMORY_ERROR;
}
uint32 bitRateValueTemp;
uint32 tempHeaderLenValue = 0;
int32 iAACFileSizeTemp;
uint8 sampleFreqTableValueTemp;
TAACFormat formatTemp;
if (ipBSOTemp->getFileInfo(iAACFileSizeTemp, formatTemp, sampleFreqTableValueTemp, bitRateValueTemp, tempHeaderLenValue, aClip))
{
return FILE_OPEN_ERROR;
}
if (formatTemp == EAACADTS)
{
tempHeaderLenValue = ADTS_HEADER_LENGTH;
}
iAACFileTemp.Close();
PV_AAC_FF_DELETE(NULL, AACBitstreamObject, ipBSOTemp);
ipBSOTemp = NULL;
*HeaderLenValue = tempHeaderLenValue;
return OK;
}
OSCL_EXPORT_REF ParserErrorCode CAACFileParser::IsAACFile(OSCL_wString& aClip, Oscl_FileServer* aFileSession, PVMFCPMPluginAccessInterfaceFactory* aCPMAccess, OsclFileHandle* aHandle)
{
PVFile iAACFileTemp;
iAACFileTemp.SetCPM(aCPMAccess);
iAACFileTemp.SetFileHandle(aHandle);
// Open the file (aClip)
if (iAACFileTemp.Open(aClip.get_cstr(), (Oscl_File::MODE_READ | Oscl_File::MODE_BINARY), *aFileSession) != 0)
{
PVMF_AACPARSER_LOGERROR((0, "CAACFileParser::IsAACFile- File open error-"));
return FILE_OPEN_ERROR;
}
AACBitstreamObject *ipBSOTemp;
PV_AAC_FF_NEW(NULL, AACBitstreamObject, (&iAACFileTemp), ipBSOTemp);
if (!ipBSOTemp || ipBSOTemp->get())
{
PVMF_AACPARSER_LOGERROR((0, "CAACFileParser::IsAACFile- Memory allocation failed-"));
// release temp storage, file control block..
iAACFileTemp.Close();
PV_AAC_FF_DELETE(NULL, AACBitstreamObject, ipBSOTemp);
return MEMORY_ERROR;
}
int32 result = ipBSOTemp->isAACFile();
// release temp storage, file control block and the file
iAACFileTemp.Close();
PV_AAC_FF_DELETE(NULL, AACBitstreamObject, ipBSOTemp);
ipBSOTemp = NULL;
if (AACBitstreamObject::EVERYTHING_OK == result)
{
return OK;
}
else if (AACBitstreamObject::INSUFFICIENT_DATA == result)
{
return INSUFFICIENT_DATA;
}
return GENERIC_ERROR;
}