| /* ------------------------------------------------------------------ |
| * Copyright (C) 2008 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.h |
| * @brief This file defines the raw AAC file parser. |
| */ |
| |
| #ifndef AACFILEPARSER_H_INCLUDED |
| #define AACFILEPARSER_H_INCLUDED |
| |
| //---------------------------------------------------------------------------- |
| // INCLUDES |
| //---------------------------------------------------------------------------- |
| |
| #ifndef OSCL_BASE_H_INCLUDED |
| #include "oscl_base.h" |
| #endif |
| |
| #ifndef OSCL_STRING_CONTAINERS_H_INCLUDED |
| #include "oscl_string_containers.h" |
| #endif |
| |
| #ifndef OSCL_FILE_IO_H_INCLUDED |
| #include "oscl_file_io.h" |
| #endif |
| |
| #ifndef OSCL_MEM_H_INCLUDED |
| #include "oscl_mem.h" |
| #endif |
| |
| #ifndef OSCL_VECTOR_H_INCLUDED |
| #include "oscl_vector.h" |
| #endif |
| |
| #ifndef PV_GAU_H |
| #include "pv_gau.h" |
| #endif |
| |
| #ifndef AUDIOMETADATA_H_INCLUDED |
| #include "audiometadata.h" |
| #endif |
| |
| #ifndef PVFILE_H_INCLUDED |
| #include "pvfile.h" |
| #endif |
| |
| #ifndef PV_ID3_PARCOM_H_INCLUDED |
| #include "pv_id3_parcom.h" |
| #endif |
| |
| #ifndef PVLOGGER_H_INCLUDED |
| #include "pvlogger.h" |
| #endif |
| |
| //---------------------------------------------------------------------------- |
| // CONSTANTS |
| //---------------------------------------------------------------------------- |
| |
| #define PACKET_INDICATOR_LENGTH 4 |
| #define ADIF_HEADER_MINUS_INDICTATOR 16 |
| #define ADTS_HEADER_LENGTH 7 |
| #define BYTES_PER_SILENCE_FRAME 23 |
| #define AAC_DECODER_SPECIFIC_INFO_SIZE 2 |
| #define MAX_AAC_FRAME_SIZE 8192 // 8192 = 2^13, 13bit AAC frame size (in bytes) |
| #define MAX_ADTS_PACKET_LENGTH MAX_AAC_FRAME_SIZE |
| #define AAC_DECODER_INPUT_BUFF_SIZE 1536 // 6144 (bits) * 2 (channels) / 8 (bits per byte) |
| |
| // ADTS sync parameters |
| |
| //#define PERCENTAGE_IN_POW_2 6 // 2^(-6) == 1.56 %, search over 1.56% of file size |
| #define PERCENTAGE_IN_POW_2 5 // 2^(-5) == 3.13 %, search over 3.13% of file size |
| //#define PERCENTAGE_IN_POW_2 4 // 2^(-4) == 6.25 %, search over 6.25% of file size |
| //#define PERCENTAGE_IN_POW_2 3 // 2^(-3) == 12.50 %, search over 12.50% of file size |
| |
| #define ADTS_SYNC_SEARCH_LENGTH(m, PERCENTAGE_IN_POW_2) (m>>PERCENTAGE_IN_POW_2) |
| |
| |
| #define PVMF_AACPARSER_LOGDIAGNOSTICS(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG,iDiagnosticLogger,PVLOGMSG_INFO,m); |
| #define PVMF_AACPARSER_LOGERROR(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_REL,iLogger,PVLOGMSG_ERR,m); |
| |
| |
| #define PV_AAC_FF_NEW(auditCB,T,params,ptr)\ |
| {\ |
| ptr = OSCL_NEW(T,params);\ |
| } |
| |
| |
| #define PV_AAC_FF_DELETE(auditCB,T,ptr)\ |
| {\ |
| OSCL_DELETE(ptr);\ |
| } |
| |
| #define PV_AAC_FF_TEMPLATED_DELETE(auditCB,T,Tsimple,ptr)\ |
| {\ |
| OSCL_TEMPLATED_DELETE(ptr, T, Tsimple);\ |
| } |
| |
| #define PV_AAC_FF_ARRAY_MALLOC(auditCB,T,count,ptr)\ |
| {\ |
| ptr = (T*)OSCL_MALLOC(count);\ |
| } |
| |
| |
| #define PV_AAC_ARRAY_FREE(auditCB,ptr)\ |
| {\ |
| OSCL_FREE(ptr);\ |
| } |
| |
| #define PV_AAC_FF_ARRAY_NEW(auditCB, T, count, ptr)\ |
| {\ |
| ptr = OSCL_ARRAY_NEW(T, count);\ |
| } |
| |
| #define PV_AAC_ARRAY_DELETE(auditCB, ptr)\ |
| {\ |
| OSCL_ARRAY_DELETE(ptr);\ |
| } |
| |
| typedef enum |
| { |
| FILE_OPEN_ERROR = -2, |
| MEMEORY_ERROR = -1, |
| OK = 1 |
| |
| } PARSER_ERROR_CODES; |
| |
| /* |
| * AAC format types supported |
| */ |
| enum TAACFormat |
| { |
| EAACADTS, |
| EAACADIF, |
| EAACRaw, |
| EAACUnrecognized |
| }; |
| |
| /* |
| * Sampling Frequency look up table |
| * The look up index is found in the |
| * header of an ADTS packet |
| */ |
| static const int32 ADTSSampleFreqTable[16] = |
| { |
| 96000, /* 96000 Hz */ |
| 88200, /* 88200 Hz */ |
| 64000, /* 64000 Hz */ |
| 48000, /* 48000 Hz */ |
| 44100, /* 44100 Hz */ |
| 32000, /* 32000 Hz */ |
| 24000, /* 24000 Hz */ |
| 22050, /* 22050 Hz */ |
| 16000, /* 16000 Hz */ |
| 12000, /* 12000 Hz */ |
| 11025, /* 11025 Hz */ |
| 8000, /* 8000 Hz */ |
| 7350, /* 7350 Hz */ |
| -1, /* future use */ |
| -1, /* future use */ |
| -1 /* escape value */ |
| }; |
| |
| /* |
| * Table containing silence frame to be generated |
| */ |
| static const uint8 SilenceFrameStereo[BYTES_PER_SILENCE_FRAME] = |
| { |
| 0x21, 0x10, 0x03, 0x20, 0x64, 0x1B, |
| 0xC0, 0x40, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x38 |
| }; |
| |
| typedef struct |
| { |
| int32 iTimescale; |
| int32 iDuration; |
| int32 iSampleFrequency; |
| int32 iBitrate; |
| TAACFormat iFormat; |
| int32 iFileSize; |
| } TPVAacFileInfo; |
| |
| |
| //---------------------------------------------------------------------------- |
| // FORWARD CLASS DECLARATIONS |
| //---------------------------------------------------------------------------- |
| |
| |
| /** |
| * @brief The AACBitstreamObject Class is the class used by the AAC parser to |
| * manipulate the bitstream read from the file. |
| */ |
| |
| class AACBitstreamObject |
| { |
| public: |
| enum |
| { |
| MAIN_BUFF_SIZE = 8192, |
| |
| // error types for GetNextBundledAccessUnits(), |
| // the definition is consistent with MP4_ERROR_CODE in iSucceedFail.h |
| MISC_ERROR = -2, |
| READ_ERROR = -1, |
| EVERYTHING_OK = 0, |
| END_OF_FILE = 62 |
| }; |
| |
| /** |
| * @brief Constructor |
| * |
| * @param pFile Pointer to file pointer containing bitstream |
| * @returns None |
| */ |
| AACBitstreamObject(PVFile* file) |
| { |
| iLogger = PVLogger::GetLoggerObject("pvBitstream object"); |
| oscl_memset(this, 0, sizeof(AACBitstreamObject)); |
| init(file); |
| iBuffer = OSCL_ARRAY_NEW(uint8, AACBitstreamObject::MAIN_BUFF_SIZE); |
| if (!iBuffer) |
| { |
| iStatus = true; |
| } |
| else |
| { |
| iStatus = false; |
| } |
| id3Parser = OSCL_NEW(PVID3ParCom, ()); |
| } |
| |
| /** |
| * @brief Destructor |
| * |
| * @param None |
| * @returns None |
| */ |
| ~AACBitstreamObject() |
| { |
| /*init();*/ |
| if (ipAACFile != NULL) |
| { |
| ipAACFile->Close(); |
| ipAACFile = NULL; |
| } |
| if (iBuffer) |
| { |
| OSCL_ARRAY_DELETE(iBuffer); |
| iBuffer = NULL; |
| } |
| |
| if (id3Parser) |
| { |
| OSCL_DELETE(id3Parser); |
| id3Parser = NULL; |
| } |
| |
| |
| } |
| |
| /** |
| * @brief Returns current bitstream status |
| * |
| * @param None |
| * @returns true=Bitstream instantiated; false=no bitstream |
| */ |
| inline bool get() |
| { |
| return iStatus; |
| } |
| |
| /** |
| * @brief Returns status of CRC |
| * |
| * @param None |
| * @returns true=CRC enabled; false=CRC disabled |
| */ |
| inline bool isCRCEnabled() |
| { |
| return ibCRC_Check; |
| } |
| |
| /** |
| * @brief Re-positions the file pointer. Specially used in ResetPlayback() |
| * |
| * @param filePos Position in file to move to. |
| * @returns Result of operation: EVERYTHING_OK, READ_ERROR etc. |
| */ |
| int32 reset(int32 filePos); |
| |
| /** |
| * @brief Retrieves clip information: file size, format(ADIF or ADTS), |
| * sampling rate index, bitrate and header length |
| * |
| * @param fileSize Size of file |
| * @param format Format of fikle (ADIF or ADTS) |
| * @param sampleFreqInd Sampling frequency index |
| * @param bitRate Bit rate |
| * @param adifHeaderLen Length of header |
| * @returns Result of operation: EVERYTHING_OK, READ_ERROR etc. |
| */ |
| int32 getFileInfo(int32& fileSize, TAACFormat& format, uint8& sampleFreqIndex, uint32& bitRate, uint32& adifHeaderLen, OSCL_wString&); |
| |
| /** |
| * @brief Expanded adts search for file information |
| * sampling rate index, bitrate and header length |
| * |
| * @param fileSize Size of file |
| * @param sampleFreqInd Sampling frequency index |
| * @param bitRate Bit rate |
| * @returns Result of operation: EVERYTHING_OK, READ_ERROR etc. |
| */ |
| int32 extendedAdtsSearchForFileInfo(TAACFormat& format, uint8& sampleFreqIndex); |
| |
| /** |
| * @brief Retrieves frame size and number of data blocks for the next frame, in |
| * preparation of getNextFrame() |
| * |
| * @param frame_size Length of next frame |
| * @param numDateBlocks Number of data blocks of next frame |
| * @returns Result of operation: EVERYTHING_OK, READ_ERROR etc. |
| */ |
| int32 getNextFrameInfo(int32& frame_size, int32& numDateBlocks); |
| |
| /** |
| * @brief get one frame data plus frame size and number of data blocks, |
| * used in getNextBundledAccessUnits() |
| * |
| * @param frameBuffer Buffer containing frame read |
| * @param frame_size Length of frame |
| * @param bHeaderIncluded Indicates whether header is to be included or not |
| * @returns Result of operation: EVERYTHING_OK, READ_ERROR etc. |
| */ |
| int32 getNextFrame(uint8* frameBuffer, int32 &frame_size, int32& header_size, bool bHeaderIncluded = false); |
| |
| /** |
| * @brief Parses the ADTS header and construct MPEG-4 AAC decoder config header |
| * |
| * @param headerBuffer Buffer containing header |
| * @returns Result of operation: EVERYTHING_OK, READ_ERROR etc. |
| */ |
| int32 getDecoderConfigHeader(uint8* headerBuffer); |
| |
| /** |
| * @brief Parses the ID3 header |
| * |
| * @param none |
| * @returns none |
| */ |
| void parseID3Header(PVFile&); |
| |
| /** |
| * @brief Find ADTS sync word |
| * |
| * @param frameBuffer Buffer containing frame read |
| * @returns Result of operation: offset on bytes on success, -1 when no sync word found. |
| */ |
| int32 find_adts_syncword(uint8 *pBuffer); |
| |
| |
| private: |
| |
| /** |
| * @brief Initialization |
| * |
| * @param pFile Pointer to file pointer containing bitstream |
| * @returns None |
| */ |
| inline void init(PVFile* pFile = NULL) |
| { |
| iFileSize = iBytesRead = iBytesProcessed = 0; |
| ipAACFile = pFile; |
| iActual_size = iMax_size = AACBitstreamObject::MAIN_BUFF_SIZE; |
| iPos = AACBitstreamObject::MAIN_BUFF_SIZE; |
| iAACFormat = EAACUnrecognized; |
| if (ipAACFile) |
| { |
| ipAACFile->Seek(0, Oscl_File::SEEKSET); |
| } |
| } |
| |
| /** |
| * @brief Reads data from bitstream, this is the only function to read data from file |
| * |
| * @param None |
| * @returns Result of operation: EVERYTHING_OK, READ_ERROR etc. |
| */ |
| int32 refill(); |
| |
| private: |
| int32 iPos; // pointer for buffer[] |
| int32 iActual_size; // number of bytes read from a file once <= max_size |
| int32 iMax_size; // max_size = bitstreamStruc::MAIN_BUFF_SIZE |
| int32 iBytesRead; // (cumulative) number of bytes read from a file so far |
| int32 iBytesProcessed; // (cumulative) number of bytes processed so far. |
| int32 iFileSize; // file size of the ipAACFile |
| TAACFormat iAACFormat; // 0 : ADTS 1: ADIF 2 : Raw |
| bool ibCRC_Check; // CRC check flag |
| bool iStatus; // 1: ok for memory allocation in constructor |
| // 0: fail in memory allocation in constructor |
| uint8 iSampleFreqIndex; // index for sampling rate |
| int32 iPosSyncAdtsFound;// pointer for where in buffer[] the search algo. found a |
| // possible match, used for extended search |
| |
| uint8 *iBuffer; |
| uint8 iAACHeaderBuffer[PACKET_INDICATOR_LENGTH+12]; |
| PVFile* ipAACFile; // bitstream file |
| |
| uint8 iAudioObjectType; // audio object type |
| uint32 iChannelConfig; // channel configuration |
| uint32 iADIFHeaderLen; // variable length |
| uint32 iRawAACHeaderLen; // Audio specific config size in bytes for raw AAC bitstream files |
| uint32 iBitrate; // max bitrate for variable rate bitstream |
| PVID3ParCom* id3Parser; |
| PVLogger *iLogger; |
| |
| public: |
| uint32 GetByteOffsetToStartOfAudioFrames() |
| { |
| return id3Parser->GetByteOffsetToStartOfAudioFrames(); |
| |
| } |
| |
| void ID3MetaData(PvmiKvpSharedPtrVector &id3Frames) |
| { |
| id3Parser->GetID3Frames(id3Frames); |
| |
| } |
| |
| bool IsID3Frame(const OSCL_String& frameType) |
| { |
| return id3Parser->IsID3FrameAvailable(frameType); |
| } |
| |
| void GetID3Frame(const OSCL_String& aFrameType, PvmiKvpSharedPtrVector& aFrame) |
| { |
| id3Parser->GetID3Frame(aFrameType, aFrame); |
| } |
| |
| PVID3Version GetID3Version() const |
| { |
| return id3Parser->GetID3Version(); |
| } |
| |
| }; |
| |
| |
| /** |
| * @brief The CAACFileParser Class is the class that will construct and maintain all the |
| * necessary data structures to be able to render a valid AAC file to disk. |
| * |
| * This class supports the following AAC file format specs: |
| * 1) ADIF |
| * 2) ADTS |
| * 3) Raw bitstream with audio specific config |
| */ |
| class CAACFileParser |
| { |
| public: |
| typedef OsclMemAllocator alloc_type; |
| |
| /** |
| * @brief Constructor |
| * |
| * @param None |
| * @returns None |
| */ |
| OSCL_IMPORT_REF CAACFileParser(); |
| |
| /** |
| * @brief Destructor |
| * |
| * @param None |
| * @returns None |
| */ |
| OSCL_IMPORT_REF ~CAACFileParser(); |
| |
| /** |
| * @brief Opens the specified file and performs initialization of the parser |
| * |
| * @param aClip Filename to parse |
| * @param aInitParsingEnable Indicates whether to setup random positioning (true) |
| * or not (false) |
| * @param aFileSession Pointer to opened file server session. Used when opening |
| * and reading the file on certain operating systems. |
| * @returns true if the init succeeds, else false. |
| */ |
| OSCL_IMPORT_REF bool InitAACFile(OSCL_wString& aClip, bool aInitParsingEnable = true, Oscl_FileServer* aFileSession = NULL, PVMFCPMPluginAccessInterfaceFactory* aCPMAccess = NULL, OsclFileHandle* aHandle = NULL); |
| |
| /** |
| * @brief Resets the parser variables so playback can be restarted at the |
| * specified time. |
| * |
| * @param aStartTime value as where to start repositioning to |
| * @returns Result of operation: EVERYTHING_OK, |
| */ |
| OSCL_IMPORT_REF int32 ResetPlayback(uint32 aStartTime, uint32& aActualStartTime); |
| |
| /** |
| * @brief Returns the actual starting timestamp for a specified start time |
| * |
| * @param aStartTime Time where to start playback from |
| * @returns Timestamp corresponding to the actual start position |
| */ |
| OSCL_IMPORT_REF uint32 SeekPointFromTimestamp(uint32 aStartTime = 0); |
| |
| /** |
| * @brief Attempts to read in the number of audio frames specified by aNumSamples |
| * |
| * @param aNumSamples Requested number of frames to be read from file |
| * @param aGau Frame information structure of type GAU |
| * @param bADTSHeaderIncluded, set to true in case ADTS headers need to be included |
| * @returns Result of operation: EVERYTHING_OK, |
| */ |
| OSCL_IMPORT_REF int32 GetNextBundledAccessUnits(uint32 *aNumSamples, |
| GAU *aGau, |
| bool bADTSHeaderIncluded = false); |
| |
| /** |
| * @brief Returns the value of the timestamp for the next frame, as would |
| * be returned by GetNextBundledAccessUnits, but does not process any data. |
| * |
| * @param aTimestamp Next timestamp. |
| * @returns Result of operation: EVERYTHING_OK, |
| */ |
| OSCL_IMPORT_REF int32 PeekNextTimestamp(uint32&aTimestamp); |
| |
| /** |
| * @brief Retrieves information about the clip such as bit rate, sampling frequency, etc. |
| * |
| * @param aInfo Storage for information retrieved |
| * @returns True if successful, False otherwise. |
| */ |
| OSCL_IMPORT_REF bool RetrieveFileInfo(TPVAacFileInfo& aInfo); |
| |
| /** |
| * @brief Retrieves information about the clip from the ID3 tags if any. |
| * |
| * @param aInfo Storage for information retrieved |
| * @returns True if successful, False otherwise. |
| */ |
| OSCL_IMPORT_REF bool RetrieveID3Info(PvmiKvpSharedPtrVector& aID3MetaData); |
| /** |
| * @brief checks if ID3 frame is available. |
| * |
| * @param frameType |
| * @returns True if successful, False otherwise. |
| */ |
| OSCL_IMPORT_REF bool IsID3Frame(const OSCL_String &frameType); |
| |
| /** |
| * @brief retrieves ID3 Frame. |
| * |
| * @param frameType ID of the frame to be retrieved |
| * @param aFrame data of the frame of type frametype |
| * @returns True if successful, False otherwise. |
| */ |
| |
| OSCL_IMPORT_REF void GetID3Frame(const OSCL_String& aFrameType, PvmiKvpSharedPtrVector& aFrame); |
| |
| /** |
| * @brief Returns the size of the decoder specific info |
| * |
| * @param None |
| * @returns Length of decoder specific info |
| */ |
| OSCL_IMPORT_REF int32 GetTrackDecoderSpecificInfoSize(void); |
| |
| /** |
| * @brief Returns the content of the decoder specific info |
| * |
| * @param None |
| * @returns Pointer to decoder specific info |
| */ |
| OSCL_IMPORT_REF uint8* GetTrackDecoderSpecificInfoContent(void); |
| |
| /** |
| * @brief Returns the format (ADTS, ADIF) of the file |
| * |
| * @param None |
| * @returns Format type |
| */ |
| OSCL_IMPORT_REF TAACFormat GetAACFormat(void); |
| |
| OSCL_IMPORT_REF uint32 getAACHeaderLen(OSCL_wString& aClip, bool aInitParsingEnable, Oscl_FileServer* iFileSession, PVMFCPMPluginAccessInterfaceFactory* aCPMAccess, OsclFileHandle*aHandle); |
| |
| OSCL_IMPORT_REF PVID3Version GetID3Version() const; |
| |
| |
| private: |
| PVFile iAACFile; |
| |
| int32 iAACDuration; |
| int32 iAACSampleFrequency; |
| |
| int32 iAACBitRate; |
| int32 iAACHeaderLen; |
| bool iFirstTime; |
| |
| int32 iAACFileSize; |
| int32 iTotalNumFramesRead; |
| Oscl_Vector<int32, alloc_type> iRPTable; |
| |
| TAACFormat iAACFormat; |
| bool iEndOfFileReached; |
| |
| // Decoder input buffer for 1 raw encoded speech frame |
| uint8 iAACFrameBuffer[PACKET_INDICATOR_LENGTH + 12]; |
| |
| //uint8 iAACHeaderReferenceBuffer[PACKET_INDICATOR_LENGTH]; |
| PVLogger* iLogger; |
| PVLogger* iDiagnosticLogger; |
| |
| AACBitstreamObject *ipBSO; |
| |
| |
| }; |
| |
| #endif //AACFILEPARSER_H_INCLUDED |