diff -r 000000000000 -r 951a5db380a0 videoeditorengine/audioeditorengine/codecs/AAC/src/ProcADTSInFileHandler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/videoeditorengine/audioeditorengine/codecs/AAC/src/ProcADTSInFileHandler.cpp Fri Jan 29 14:08:33 2010 +0200 @@ -0,0 +1,1028 @@ +/* +* Copyright (c) 2010 Ixonos Plc. +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - Initial contribution +* +* Contributors: +* Ixonos Plc +* +* Description: +* +*/ + + + +#include +#include +#include "AudCommon.h" +#include "ProcConstants.h" +#include "ProcADTSInFileHandler.h" +//#include "mp4aud.h" +#include "mp4config.h" +#include "audconstants.h" + +#include "ProcTools.h" +#include "ProcAACFrameHandler.h" + + + +CProcADTSInFileHandler* CProcADTSInFileHandler::NewL(const TDesC& aFileName, RFile* aFileHandle, + CAudClip* aClip, TInt aReadBufferSize, + TInt aTargetSampleRate, TChannelMode aChannelMode) + { + + CProcADTSInFileHandler* self = NewLC(aFileName, aFileHandle, aClip, aReadBufferSize, aTargetSampleRate, aChannelMode); + CleanupStack::Pop(self); + return self; + + } + +CProcADTSInFileHandler* CProcADTSInFileHandler::NewLC(const TDesC& aFileName, RFile* aFileHandle, + CAudClip* aClip, TInt aReadBufferSize, TInt aTargetSampleRate, + TChannelMode aChannelMode) + + { + + CProcADTSInFileHandler* self = new (ELeave) CProcADTSInFileHandler(); + CleanupStack::PushL(self); + self->ConstructL(aFileName, aFileHandle, aClip, aReadBufferSize, aTargetSampleRate, aChannelMode); + return self; + + } + +void CProcADTSInFileHandler::GetPropertiesL(TAudFileProperties* aProperties) + { + + if (iProperties != 0) + { + *aProperties = *iProperties; + return; + } + + aProperties->iDuration = 0; + aProperties->iSamplingRate = 0; + aProperties->iBitrate = 0; + aProperties->iChannelMode = EAudChannelModeNotRecognized; + aProperties->iFrameLen = 0; + aProperties->iFrameCount = 0; + + aProperties->iAudioType = EAudTypeUnrecognized; + aProperties->iAudioTypeExtension = EAudExtensionTypeNoExtension; + aProperties->iFileFormat = EAudFormatUnrecognized; + aProperties->iBitrateMode = EAudBitrateModeNotRecognized; + aProperties->iFrameDuration = 0; + aProperties->iNumFramesPerSample = 1; + aProperties->iChannelModeExtension = EAudChannelModeNotRecognized; + aProperties->iAACObjectType = EAudAACObjectTypeNone; + + if (!iSupportedFile) + { + User::Leave(KErrNotSupported); + return; + } + + ReadHeaderInformation(aProperties); + ReadOtherInformationL(aProperties); + + aProperties->iBitrateMode = EAudConstant; + + if (iProperties == 0) + { + iProperties = new (ELeave) TAudFileProperties; + *iProperties = *aProperties; + } + + } + + +TBool CProcADTSInFileHandler::SeekAudioFrame(TInt32 aTime) + { + + if (!iSupportedFile) + { + return EFalse; + } + + if (aTime == 0) + { + FindFirstAACFrame(); + iCurrentTimeMilliseconds = aTime; + return ETrue; + } + + else FindFirstAACFrame(); + + TBuf8<6> header; + + if(BufferedFileRead(header, 6) != 6) + { + return EFalse; + } + + if (header.Length() != 6) + { + return EFalse; + } + + TUint8 byte2 = header[1]; + TBuf8<8> byte2b; + ProcTools::Dec2Bin(byte2, byte2b); + // lets confirm that we have found a legal AAC header + if (header[0] == 0xFF && + byte2b[0] == '1' && + byte2b[1] == '1' && + byte2b[2] == '1' && + byte2b[3] == '1' && + //byte2b[4] == '1' && + byte2b[5] == '0' && + byte2b[6] == '0') + { + } + else + { + return EFalse; + } + + TUint8 byte4 = header[3]; + TUint8 byte5 = header[4]; + TUint8 byte6 = header[5]; + + TUint frameLen = CalculateAACFrameLength(byte4, byte5, byte6); + //aFrame = HBufC8::NewL(frameLen); + + TInt dur = 0; + + while (BufferedFileSetFilePos(iFilePos-6+frameLen)) + { + + dur = dur + ProcTools::MilliSeconds(iProperties->iFrameDuration); + if (dur > aTime) + { + break; + } + + if(BufferedFileRead(header, 6) != 6) + { + break; + } + + if (header.Length() != 6) + { + break; + } + + if (header[0] != 0xFF) break; + byte4 = header[3]; + byte5 = header[4]; + byte6 = header[5]; + + frameLen = CalculateAACFrameLength(byte4, byte5, byte6); + + } + + + aTime = dur; + iCurrentTimeMilliseconds = aTime; + return ETrue; + } + +TBool CProcADTSInFileHandler::SeekCutInFrame() + { + iCurrentTimeMilliseconds = iCutInTime; + return SeekAudioFrame(iCutInTime); + } + + + + +TBool CProcADTSInFileHandler::SetNormalizingGainL(const CProcFrameHandler* aFrameHandler) + { + + + HBufC8* point = 0; + TInt siz; + TInt32 tim = 0; + TInt maxGain = 0; + RArray gains; + TInt maxAverage = 0; + TInt tmpGain = 0; + TInt gainCounter = 0; + TInt timeNow = 0; + while(GetEncAudioFrameL(point, siz, tim)) + { + CleanupStack::PushL(point); + + aFrameHandler->GetGainL(point, gains, maxGain); + timeNow += tim; + + for (TInt a = 0 ; a < gains.Count() ; a++) + { + tmpGain += gains[a]; + gainCounter++; + } + gains.Reset(); + + if (timeNow > 1000) + { + if (tmpGain/gainCounter > maxAverage) + { + maxAverage = tmpGain/gainCounter; + } + + timeNow = 0; + tmpGain = 0; + gainCounter = 0; + } + + CleanupStack::PopAndDestroy(point); + + } + + // bigger value makes normalizing more efficient, but makes + // dynamic compression more likely to occur + TInt NormalizingFactor = 175; + if (iProperties->iBitrate > 20000 && iProperties->iBitrate < 40000) + { + + // 32 kBit/s + NormalizingFactor = 170; + + } + else if (iProperties->iBitrate > 80000 && iProperties->iBitrate < 110000) + { + // 96 kBit/s + NormalizingFactor = 170; + + } + + + else if (iProperties->iBitrate > 110000 && iProperties->iBitrate < 140000) + { + // 128 kBit/s + if (iProperties->iChannelMode == EAudSingleChannel) + NormalizingFactor = 160; + else + NormalizingFactor = 170; + + } + else if (iProperties->iBitrate > 150000) + { + // 256 kBit/s + if (iProperties->iChannelMode == EAudSingleChannel) + NormalizingFactor = 150; + else + NormalizingFactor = 165; + + } + else + { + + if (iProperties->iChannelMode == EAudSingleChannel) + NormalizingFactor = 170; + + } + + + TInt gainBoost = (NormalizingFactor-maxAverage)*3; + + if (gainBoost < 0) gainBoost = 0; + + iNormalizingMargin = static_cast(gainBoost); + + return ETrue; + + } + + +TBool CProcADTSInFileHandler::ReadAudioDecoderSpecificInfoL(HBufC8*& aBytes, TInt aBufferSize) + { + + if (aBufferSize < iMP4DecSpecInfo->Size()) return EFalse; + + if (iMP4DecSpecInfo != 0) + { + aBytes = HBufC8::NewL(iMP4DecSpecInfo->Size()); + aBytes->Des().Append(iMP4DecSpecInfo->Des()); + return ETrue; + } + else + { + aBytes = 0; + return EFalse; + } + + } + + +CProcADTSInFileHandler::~CProcADTSInFileHandler() + { + ResetAndCloseFile(); + + if (iSilentFrame != 0) + { + delete iSilentFrame; + } + + if (iMP4DecSpecInfo != 0) + { + delete iMP4DecSpecInfo; + + } + + + if (iFrameInfo != 0) + { + delete iFrameInfo; + + } + + delete iFrameHandler; + + delete iDecoder; + + } + + +void CProcADTSInFileHandler::ConstructL(const TDesC& aFileName, + RFile* aFileHandle, + CAudClip* aClip, + TInt aReadBufferSize, + TInt aTargetSampleRate, + TChannelMode aChannelMode) + { + + + + iTargetSampleRate = aTargetSampleRate; + iChannelMode = aChannelMode; + + InitAndOpenFileL(aFileName, aFileHandle, aReadBufferSize); + + if (aClip != 0) + { + iCutInTime = ProcTools::MilliSeconds(aClip->CutInTime()); + + } + + TBool frameFound = FindFirstAACFrame(); + + if (!frameFound) + { + iSupportedFile = EFalse; + return; + } + + iClip = aClip; + + TAudFileProperties prop; + iFrameInfo = new (ELeave) TAACFrameHandlerInfo; + GetPropertiesL(&prop); + + if (prop.iAudioTypeExtension != EAudExtensionTypeNoExtension) + { + // AACPlus frame duration is calculated from sampling rate + // the actual sampling rate of AAC plus is twice as high as + // the AAC part + iProperties->iFrameDuration = iProperties->iFrameDuration.Int64()/2; + + } + + // fill in aacInfo for retrieving decoder specific information + //AACStreamInfo aacInfo; + int16 frameLen = 0; + int32 sampleRate = 0; + uint8 profile = 0; + uint8 nChannels = 0; + + // generate a silent frame ------------------> + + if (iProperties->iChannelMode == EAudSingleChannel) + { + + iSilentFrame = HBufC8::NewL(KSilentMonoAACFrameLenght); + + iSilentFrame->Des().Append(KSilentMonoAACFrame, KSilentMonoAACFrameLenght); + + nChannels = 1; + } + else if (iProperties->iChannelMode == EAudStereo) + { + + iSilentFrame = HBufC8::NewL(KSilentStereoAACFrameLenght); + iSilentFrame->Des().Append(KSilentStereoAACFrame, KSilentStereoAACFrameLenght); + + nChannels = 2; + } + else + { + User::Leave(KErrNotSupported); + } + + // Check that the sample rate is supported + if( (iProperties->iSamplingRate != KAedSampleRate8kHz) && + (iProperties->iSamplingRate != KAedSampleRate11kHz) && + (iProperties->iSamplingRate != KAedSampleRate16kHz) && + (iProperties->iSamplingRate != KAedSampleRate22kHz) && + (iProperties->iSamplingRate != KAedSampleRate24kHz) && + (iProperties->iSamplingRate != KAedSampleRate32kHz) && + (iProperties->iSamplingRate != KAedSampleRate44kHz) && + (iProperties->iSamplingRate != KAedSampleRate48kHz) ) + { + User::Leave(KErrNotSupported); + } + + + + uint8 decSpecInfo[16]; + int16 nConfigBytes; + + + frameLen = 1024; + sampleRate = iProperties->iSamplingRate; + if (iFrameInfo->iProfileID == 3) + { + profile = LTP_OBJECT; + } + else if (iFrameInfo->iProfileID == 1) + { + profile = LC_OBJECT; + } + else + { + User::Leave(KErrNotSupported); + } + + //nConfigBytes = AACGetMP4ConfigInfo(&aacInfo, decSpecInfo, 16); + nConfigBytes = AACGetMP4ConfigInfo(sampleRate, profile, + nChannels, frameLen, decSpecInfo, 16); + + + if (nConfigBytes > 0) + { + + iMP4DecSpecInfo = HBufC8::NewL(nConfigBytes); + iMP4DecSpecInfo->Des().Append(decSpecInfo, nConfigBytes); + + } + + + mp4_u32 frameDurationMilli = ProcTools::MilliSeconds(iProperties->iFrameDuration); + + iSilentFrameDuration = frameDurationMilli; + + + // <------------------generate a silent frame + + // Generate a decoder -----------------------> + + iDecoder = CProcDecoder::NewL(); + + iDecodingPossible = iDecoder->InitL(*iProperties, aTargetSampleRate, aChannelMode); + + // <----------------------- Generate a decoder + + // Create a frame handler ---------------------> + + iFrameHandler = CProcAACFrameHandler::NewL(*iFrameInfo); + + if (iClip != 0 && iClip->Normalizing()) + { + SetNormalizingGainL(iFrameHandler); + } + + + } + + + + +TBool CProcADTSInFileHandler::GetEncAudioFrameL(HBufC8*& aFrame, TInt& aSize, TInt32& aTime) + { + + if (!iSupportedFile) + { + return EFalse; + } + + + TBuf8<7> header; + + if(BufferedFileRead(header, 7) != 7) + { + return EFalse; + } + + if (header.Length() != 7) + { + return EFalse; + } + + if (header[0] != 0xFF) return EFalse; + TUint8 byte4 = header[3]; + TUint8 byte5 = header[4]; + TUint8 byte6 = header[5]; +// TUint8 byte7 = header[6]; + + + TInt frameLen = CalculateAACFrameLength(byte4, byte5, byte6); + aFrame = HBufC8::NewL(frameLen); + + BufferedFileSetFilePos(iFilePos-7); + TPtr8 tmpDes((TPtr8)aFrame->Des()); + + if (BufferedFileRead((TPtr8&)tmpDes, frameLen) != frameLen) + { + delete aFrame; + aFrame = 0; + return EFalse; + } + + aSize = frameLen; + aTime = ProcTools::MilliSeconds(iProperties->iFrameDuration); + + // remove ADTS header --------------------------------------------> + + TInt headerLength = 0; // because we need to remove header in case of AAC frame from .aac files + //check Header length to be removed from the frame before writting to 3gp file + TUint8* dtPtr = (TUint8*)(aFrame->Ptr()); + if((dtPtr[1]&& 0x01) == 0x00) //based on bytes decide header length to remove + { + headerLength =9; + } + else if((dtPtr[1]&& 0x01)== 0x01) + { + headerLength =7; + } + else + { + headerLength =0; + } + + aFrame->Des().Delete(0,headerLength); + aSize -= headerLength; + + // <--------------------------------------------- remove ADTS header + + iCurrentTimeMilliseconds += ProcTools::MilliSeconds(iProperties->iFrameDuration); + + + // Fix for synchronizing problem ----------------------------------> + // If the accurate frame length cannot be represented in milliseconds + // store the remainder and increase the output frame lenght by one ms + // when needed. Accuracy depends on sampling rate + + TReal accurateFrameLen = TReal(1024000)/iProperties->iSamplingRate; + + iAACFrameLenRemainderMilli += accurateFrameLen - aTime; + + if (iAACFrameLenRemainderMilli > 1) + { + aTime += 1; + iCurrentTimeMilliseconds += 1; + iAACFrameLenRemainderMilli -= 1; + } + + + // <---------------------------------- Fix for synchronizing problem + + + if (iProperties->iAudioTypeExtension == EAudExtensionTypeNoExtension) + { + + + // AACPlus is handled after decoding + + TRAPD(err, ManipulateGainL(aFrame)); + + if (err != KErrNone) + { + // something went wrong with the gain manipulation + // continue by returning the original frame + } + } + + + aSize = aFrame->Size(); + + return ETrue; + + + } + +CProcADTSInFileHandler::CProcADTSInFileHandler() : CProcInFileHandler(), iFrameInfo(0), + iSupportedFile(ETrue) + { + + + } + + +TBool CProcADTSInFileHandler::FindFirstAACFrame() + { + + TBuf8<8> byte2b; + TUint8 byte2; + TUint8 byte1; + + TBool fileEnded = EFalse; + TUint ind = 0; + TBool frameFound = EFalse; + + BufferedFileSetFilePos(0); + + while (!fileEnded) + { + if (BufferedFileReadChar(ind, byte1) == 0) + { + fileEnded = ETrue; + } + ind++; + + if (byte1 != 0xFF) continue; + + + if (BufferedFileReadChar(ind, byte2) == 0) + { + fileEnded = ETrue; + } + ind++; + ProcTools::Dec2Bin(byte2, byte2b); + + + if (byte1 == 0xFF && + byte2b[0] == '1' && + byte2b[1] == '1' && + byte2b[2] == '1' && + byte2b[3] == '1' && + //byte2b[4] == '1' && + byte2b[5] == '0' && + byte2b[6] == '0') + { + + // this looks like AAC frame header, let's confirm... + TUint8 byte3, byte4, byte5, byte6; + BufferedFileReadChar(ind, byte3); + BufferedFileReadChar(ind+1, byte4); + BufferedFileReadChar(ind+2, byte5); + BufferedFileReadChar(ind+3, byte6); + + ind++; + + TUint frameLength = CalculateAACFrameLength(byte4, byte5, byte6); + + TUint8 testByte1, testByte2, testByte3; + BufferedFileReadChar(ind+frameLength-3, testByte1); + BufferedFileReadChar(ind+frameLength-2, testByte2); + BufferedFileReadChar(ind+frameLength-1, testByte3); + + if (byte1 == testByte1 && byte2 == testByte2 + && byte3 == testByte3) + { + // this must be the header... + iFirstFrame = ind-3; + //FillInHeaderValues(byte2, byte3, byte4); + frameFound = ETrue; + break; + } + + } + + } + if (frameFound) + { + BufferedFileSetFilePos(iFirstFrame); + } + + return frameFound; + } + + +TUint CProcADTSInFileHandler::CalculateAACFrameLength(TUint8 byte4, TUint8 byte5, TUint8 byte6) + { + + TBuf8<13> headerLengthB; + TBuf8<8> byte4b, byte5b, byte6b; + ProcTools::Dec2Bin(byte4, byte4b); + ProcTools::Dec2Bin(byte5, byte5b); + ProcTools::Dec2Bin(byte6, byte6b); + + headerLengthB.Append(byte4b[6]); + headerLengthB.Append(byte4b[7]); + headerLengthB.Append(byte5b); + headerLengthB.Append(byte6b[0]); + headerLengthB.Append(byte6b[1]); + headerLengthB.Append(byte6b[2]); + + + TUint headerLength = 0; + TLex8 leks(headerLengthB); + + if (leks.Val(headerLength, EBinary) != KErrNone) + { + return 0; + } + + return headerLength; + +} + + +TBool CProcADTSInFileHandler::ReadHeaderInformation(TAudFileProperties* aProperties) + { + + TInt origFilePos = iFilePos; + + if (aProperties == 0) + return EFalse; + + TBuf8<4> header; + + if(BufferedFileRead(header, 4) != 4) + { + BufferedFileSetFilePos(origFilePos); + return EFalse; + } + + if (header.Length() != 4) + { + BufferedFileSetFilePos(origFilePos); + return EFalse; + } + + TUint8 byte2 = header[1]; + TBuf8<8> byte2b; + ProcTools::Dec2Bin(byte2, byte2b); + // lets confirm that we have found a legal AAC header + if (header[0] == 0xFF && + byte2b[0] == '1' && + byte2b[1] == '1' && + byte2b[2] == '1' && + byte2b[3] == '1' && + //byte2b[4] == '1' && + byte2b[5] == '0' && + byte2b[6] == '0') + { + // OK + aProperties->iFileFormat = EAudFormatAAC_ADTS; + // aProperties->iFrameDuration = 23000; + } + else + { + return EFalse; + } + /* + if (byte2b[4] == '1') + { + aProperties->iAudioType = EAudAAC_MPEG2; + } + else + { + aProperties->iAudioType = EAudAAC_MPEG4; + } + */ + + // NOTE: call all MPeg audio EAudAAC_MPEG4 + aProperties->iAudioType = EAudAAC_MPEG4; + + + TUint8 byte3 = header[2]; + TUint8 byte4 = header[3]; + + TBuf8<8> byte3b; + TBuf8<8> byte4b; + + ProcTools::Dec2Bin(byte2, byte2b); + ProcTools::Dec2Bin(byte3, byte3b); + ProcTools::Dec2Bin(byte4, byte4b); + + TBuf8<2> profileId(byte3b.Left(2)); + TUint proID = 0; + ProcTools::Bin2Dec(profileId, proID); + + iFrameInfo->iProfileID = static_cast(proID); + aProperties->iAACObjectType = TAudAACObjectType(iFrameInfo->iProfileID); + + + TBuf8<4> samplingRateIndexB; + samplingRateIndexB.Append(byte3b[2]); + samplingRateIndexB.Append(byte3b[3]); + samplingRateIndexB.Append(byte3b[4]); + samplingRateIndexB.Append(byte3b[5]); + + TUint srIndex = 0; + TLex8 lek(samplingRateIndexB); + + if (lek.Val(srIndex, EBinary) != KErrNone) + { + BufferedFileSetFilePos(origFilePos); + return EFalse; + } + // aac sampling rates + + const TInt KAAC_SAMPLING_RATES[16] = {96000,88200,64000,48000,44100,32000,24000 + ,22050,16000,12000,11025,8000,0,0,0,0}; + + iFrameInfo->iSampleRateID = static_cast(srIndex); + aProperties->iSamplingRate = KAAC_SAMPLING_RATES[srIndex]; + samplingRateIndexB.Delete(0, samplingRateIndexB.Length()); + + // channel configuration + + + TUint aacChannels = 0; + TBuf8<3> channelB; + channelB.Append(byte3b[7]); + channelB.Append(byte4b[0]); + channelB.Append(byte4b[1]); + + TLex8 leks2(channelB); + if (leks2.Val(aacChannels, EBinary) != KErrNone) + { + BufferedFileSetFilePos(origFilePos); + return EFalse; + } + + if (aacChannels == 1) + { + aProperties->iChannelMode = EAudSingleChannel; + } + else if (aacChannels == 2) + { + aProperties->iChannelMode = EAudStereo; + } + + iFrameInfo->iNumChannels = static_cast(aacChannels); + iFrameInfo->iNumCouplingChannels = 0; + iFrameInfo->iIs960 = 0; + + + BufferedFileSetFilePos(origFilePos); + return ETrue; + + } + + +TBool CProcADTSInFileHandler::ReadOtherInformationL(TAudFileProperties* aProperties) + { + + TInt origFilePos = iFilePos; + + FindFirstAACFrame(); + + TBuf8<7> header; + + if(BufferedFileRead(header, 7) != 7) + { + return EFalse; + } + + if (header.Length() != 7) + { + return EFalse; + } + + TUint8 byte2 = header[1]; + TBuf8<8> byte2b; + ProcTools::Dec2Bin(byte2, byte2b); + // lets confirm that we have found a legal AAC header + if (header[0] == 0xFF && + byte2b[0] == '1' && + byte2b[1] == '1' && + byte2b[2] == '1' && + byte2b[3] == '1' && + // byte2b[4] == '1' && + byte2b[5] == '0' && + byte2b[6] == '0') + { + // OK + //aProperties->iAudioType = EAudAAC; + //aProperties->iFileFormat = EAudFormatAAC_ADTS; + } + else + { + return EFalse; + } + + TUint8 byte4 = header[3]; + TUint8 byte5 = header[4]; + TUint8 byte6 = header[5]; + + aProperties->iFrameDuration = ((1024*1000)/(aProperties->iSamplingRate))*1000; + + TInt frameLen = CalculateAACFrameLength(byte4, byte5, byte6); + + + + + /*-- Allocate resources and read 1st frame. --*/ + HBufC8 *aFrame = HBufC8::NewL(frameLen); + CleanupStack::PushL(aFrame); + + TPtr8 tmpDes((TPtr8)aFrame->Des()); + + BufferedFileRead((TPtr8&)tmpDes, frameLen - 7); + + + const TInt KShortestAACFrame = 20; + + if (frameLen > KShortestAACFrame) // a silent frame? + { + + + + /* + * Get frame parameters for eAAC+ codec. It is possible that the bitstream + * is plain AAC but we don't know it before the 1st frame is parsed! + */ + + TUint8* buf = const_cast(aFrame->Right(aFrame->Size()).Ptr()); + CProcAACFrameHandler::GetEnhancedAACPlusParametersL(buf, frameLen - 7, aProperties, iFrameInfo); + + } + else + { + iFrameInfo->iIsParametricStereo = EFalse; + iFrameInfo->isSBR = EFalse; + + } + + CleanupStack::Pop(aFrame); + delete aFrame; + aFrame = 0; + + + + + + if(BufferedFileRead(header, 7) != 7) + { + return EFalse; + } + + if (header.Length() != 7) + { + return EFalse; + } + + byte4 = header[3]; + byte5 = header[4]; + byte6 = header[5]; + + TInt dur = ProcTools::MilliSeconds(aProperties->iFrameDuration); + TInt bytes = frameLen; + TInt frames = 1; + + frameLen = CalculateAACFrameLength(byte4, byte5, byte6); + + while (BufferedFileSetFilePos(iFilePos-7+frameLen)) + { + + dur += ProcTools::MilliSeconds(aProperties->iFrameDuration); + bytes += frameLen; + frames++; + + if(BufferedFileRead(header, 7) != 7) + { + break; + } + + if (header.Length() != 7) + { + break; + } + + if (header[0] != 0xFF) break; + byte4 = header[3]; + byte5 = header[4]; + byte6 = header[5]; + + frameLen = CalculateAACFrameLength(byte4, byte5, byte6); + + } + + TTimeIntervalMicroSeconds tmp((TInt64)(TInt)dur*1000); + aProperties->iDuration = tmp; + + aProperties->iFrameCount = frames; + aProperties->iFrameLen = bytes/frames; + aProperties->iBitrate = (iFilePos*1000/(dur))*8; + + + BufferedFileSetFilePos(origFilePos); + + return ETrue; + } + +TBool CProcADTSInFileHandler::GetInfoForFrameHandler(TAACFrameHandlerInfo& aAACInfo) + { + + aAACInfo = *iFrameInfo; + return ETrue; + } +