diff -r 000000000000 -r 951a5db380a0 videoeditorengine/audioeditorengine/codecs/MP4/src/ProcMP4InFileHandler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/videoeditorengine/audioeditorengine/codecs/MP4/src/ProcMP4InFileHandler.cpp Fri Jan 29 14:08:33 2010 +0200 @@ -0,0 +1,1365 @@ +/* +* 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 "AWBConstants.h" +#include "ProcMP4InFileHandler.h" +#include "mp4aud.h" +#include "ProcAACFrameHandler.h" +#include "ProcAMRFrameHandler.h" +#include "ProcAWBFrameHandler.h" +#include "audconstants.h" + + + +#include "ProcTools.h" +//#include "aacenc_interface.h" + +// Debug print macro +#if defined _DEBUG +#include +#define PRINT(x) RDebug::Print x; +#else +#define PRINT(x) +#endif + +// Max coded AAC frame size (768 bytes per channel) +const TUint KMaxAACFrameSize(1536); + + +CProcMP4InFileHandler* CProcMP4InFileHandler::NewL(const TDesC& aFileName, + RFile* aFileHandle, + CAudClip* aClip, TInt aReadBufferSize, + TInt aTargetSampleRate, + TChannelMode aChannelMode) + { + + CProcMP4InFileHandler* self = NewLC(aFileName, aFileHandle, aClip, aReadBufferSize, + aTargetSampleRate, aChannelMode); + CleanupStack::Pop(self); + return self; + + } + +CProcMP4InFileHandler* CProcMP4InFileHandler::NewLC(const TDesC& aFileName, + RFile* aFileHandle, + CAudClip* aClip, TInt aReadBufferSize, + TInt aTargetSampleRate, + TChannelMode aChannelMode) + + { + + CProcMP4InFileHandler* self = new (ELeave) CProcMP4InFileHandler(); + CleanupStack::PushL(self); + self->ConstructL(aFileName, aFileHandle, aClip, aReadBufferSize, + aTargetSampleRate, aChannelMode); + return self; + + } + +void CProcMP4InFileHandler::GetPropertiesL(TAudFileProperties* aProperties) + { + PRINT((_L("CProcMP4InFileHandler::GetPropertiesL in") )); + if (iProperties != 0) + { + *aProperties = *iProperties; + PRINT((_L("CProcMP4InFileHandler::GetPropertiesL use cached properties, out") )); + return; + } + + if (iProperties == 0) + { + iProperties = new (ELeave) TAudFileProperties; + } + + mp4_u32 audiolength = 0; + mp4_u32 audiotype = 0; + mp4_u8 framespersample = 0; + mp4_u32 timescale = 0; + mp4_u32 averagebitrate = 0; + + aProperties->iFileFormat = EAudFormatUnrecognized; + aProperties->iAudioType = EAudTypeUnrecognized; + aProperties->iDuration = 0; + aProperties->iSamplingRate = 0; + aProperties->iBitrate = 0; + aProperties->iChannelMode = EAudChannelModeNotRecognized; + aProperties->iBitrateMode = EAudBitrateModeNotRecognized; + aProperties->iAudioTypeExtension = EAudExtensionTypeNoExtension; + aProperties->iFrameLen = 0; + aProperties->iFrameDuration = 0; + aProperties->iFrameCount = 0; + aProperties->iNumFramesPerSample = 1; + aProperties->iAACObjectType = EAudAACObjectTypeNone; + + MP4Err err = MP4ParseRequestAudioDescription(iParser, + &audiolength, + &audiotype, + &framespersample, + ×cale, + &averagebitrate); + + + if (err == MP4_OK) + { + if (audiotype == MP4_TYPE_MPEG4_AUDIO) + { + + aProperties->iAudioType = EAudAAC_MPEG4; + aProperties->iBitrateMode = EAudVariable; + + } + else if (audiotype == MP4_TYPE_AMR_NB) + { + aProperties->iAudioType = EAudAMR; + aProperties->iBitrateMode = EAudVariable; + + } + else if (audiotype == MP4_TYPE_AMR_WB) + { + aProperties->iAudioType = EAudAMRWB; + aProperties->iBitrateMode = EAudVariable; + + } + aProperties->iBitrate = averagebitrate; + + // casting for PC-Lint + TInt64 ti = (TInt64)(TInt)(audiolength*1000); + TTimeIntervalMicroSeconds TTaudiolength(ti); + + aProperties->iDuration = TTaudiolength; + aProperties->iFileFormat = EAudFormatMP4; + //aProperties->iFrameLen = framespersample; + + + } + else if (err == MP4_NO_AUDIO) + { + aProperties->iAudioType = EAudNoAudio; + *iProperties = *aProperties; + return; + + //User::Leave(KErrGeneral); + } + else + { + // a special case: there may be audio track but it is empty; if type was recognized, mark as no audio + if ( (audiotype == MP4_TYPE_MPEG4_AUDIO) || (audiotype == MP4_TYPE_AMR_NB) || (audiotype == MP4_TYPE_AMR_WB)) + { + PRINT((_L("CProcMP4InFileHandler::GetPropertiesL problems with getting audio description, mark no audio since audio type was recognized"))); + aProperties->iAudioType = EAudNoAudio; + *iProperties = *aProperties; + } + PRINT((_L("CProcMP4InFileHandler::GetPropertiesL out with MP4Err %d"), err )); + return; + + } + + const TInt KMaxBufferSize = 128; + + mp4_u8 *buffer = new (ELeave) mp4_u8[KMaxBufferSize]; + CleanupStack::PushL(buffer); + + mp4_u32 decspecinfosize = 0; + + err = MP4ParseReadAudioDecoderSpecificInfo( + iParser, + buffer, + KMaxBufferSize, + &decspecinfosize); + + + mp4AACTransportHandle mp4AAC_ff; + + if (err == MP4_OK && aProperties->iAudioType == EAudAAC_MPEG4) + { + + PRINT((_L("CProcMP4InFileHandler::GetPropertiesL AAC found") )); + + TInt ret = ReadMP4AudioConfig(buffer, + decspecinfosize, + &mp4AAC_ff); + if (ret != TRUE) + { + aProperties->iFileFormat = EAudFormatUnrecognized; + aProperties->iAudioType = EAudTypeUnrecognized; + User::Leave(KErrNotSupported); + } + + // ProgConfig progCfg = mp4AAC_ff.progCfg; + AudioSpecificInfo audioInfo = mp4AAC_ff.audioInfo; + aProperties->iSamplingRate = audioInfo.samplingFrequency; + // TInt tmp = mp4AAC_ff.progCfg.coupling.num_ele; + + // Check that the sample rate is supported + if( (aProperties->iSamplingRate != KAedSampleRate8kHz) && + (aProperties->iSamplingRate != KAedSampleRate11kHz) && + (aProperties->iSamplingRate != KAedSampleRate16kHz) && + (aProperties->iSamplingRate != KAedSampleRate22kHz) && + (aProperties->iSamplingRate != KAedSampleRate24kHz) && + (aProperties->iSamplingRate != KAedSampleRate32kHz) && + (aProperties->iSamplingRate != KAedSampleRate44kHz) && + (aProperties->iSamplingRate != KAedSampleRate48kHz) ) + { + User::Leave(KErrNotSupported); + } + + if (audioInfo.channelConfiguration == 2) + { + aProperties->iChannelMode = EAudStereo; + } + else if (audioInfo.channelConfiguration == 1) + { + + aProperties->iChannelMode = EAudSingleChannel; + } + else + { + aProperties->iChannelMode = EAudChannelModeNotRecognized; + } + + if (mp4AAC_ff.audioInfo.samplingFreqIdx != + mp4AAC_ff.progCfg.sample_rate_idx) + { + aProperties->iFileFormat = EAudFormatUnrecognized; + aProperties->iAudioType = EAudTypeUnrecognized; + aProperties->iDuration = 0; + aProperties->iSamplingRate = 0; + aProperties->iBitrate = 0; + aProperties->iChannelMode = EAudChannelModeNotRecognized; + aProperties->iBitrateMode = EAudBitrateModeNotRecognized; + aProperties->iFrameLen = 0; + aProperties->iFrameDuration = 0; + aProperties->iFrameCount = 0; + aProperties->iNumFramesPerSample = 1; + CleanupStack::PopAndDestroy(buffer); + PRINT((_L("CProcMP4InFileHandler::GetPropertiesL audio not recognized, out") )); + User::Leave(KErrNotSupported); + return; + } + + + + iFrameInfo->iSampleRateID = static_cast(mp4AAC_ff.progCfg.sample_rate_idx); + iFrameInfo->iSampleRateID = static_cast(mp4AAC_ff.audioInfo.samplingFreqIdx); + + + iFrameInfo->iProfileID = static_cast(mp4AAC_ff.progCfg.profile); + + aProperties->iAACObjectType = TAudAACObjectType(iFrameInfo->iProfileID); + + if (aProperties->iChannelMode == EAudStereo) + { + iFrameInfo->iNumChannels = 2; + } + else if (aProperties->iChannelMode == EAudSingleChannel) + { + iFrameInfo->iNumChannels = 1; + } + else + { + iFrameInfo->iNumChannels = 0; + } + + + iFrameInfo->iIs960 = mp4AAC_ff.audioInfo.gaInfo.FrameLengthFlag; + + iFrameInfo->iNumCouplingChannels = 0; + + iFrameInfo->isSBR = 0; + iFrameInfo->iIsParametricStereo = 0; + + /* + * 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! + */ + + HBufC8* frame = 0; + TInt size = 0; + + TInt32 time = 0; + + // Set the iProperties as GetEncAudioFrameL is using it!! + *iProperties = *aProperties; + if(GetEncAudioFrameL(frame, size, time)) + { + PRINT((_L("CProcMP4InFileHandler::GetPropertiesL check AAC+ parameters") )); + + TUint8* buf = const_cast(frame->Right(frame->Size()).Ptr()); + CProcAACFrameHandler::GetEnhancedAACPlusParametersL(buf, frame->Size(), aProperties, iFrameInfo); + delete frame; + frame = 0; + } + + } + else if (err == MP4_OK && aProperties->iAudioType == EAudAMR) + { + aProperties->iChannelMode = EAudSingleChannel; + aProperties->iSamplingRate = 8000; + + } + else if (err == MP4_OK && aProperties->iAudioType == EAudAMRWB) + { + aProperties->iChannelMode = EAudSingleChannel; + aProperties->iSamplingRate = 16000; + + } + + TInt frameAmount = 0; + TInt frameSize = 0; + TInt frameDuration = 0; + + + TInt rv = ETrue; + + *iProperties = *aProperties; + rv = GetAudioFrameInfoL(frameAmount, frameDuration, frameSize, aProperties); + + if (rv) + { + aProperties->iFrameCount = frameAmount; + aProperties->iFrameLen = frameSize; + + // casting for PC-Lint + TInt64 durMicro = (TInt64) (TInt) frameDuration*1000; + aProperties->iFrameDuration = durMicro; + + } + + + + + + *iProperties = *aProperties; + + + CleanupStack::PopAndDestroy(buffer); + + PRINT((_L("CProcMP4InFileHandler::GetPropertiesL out") )); + } + + +TBool CProcMP4InFileHandler::SeekAudioFrame(TInt32 aTime) + { + + mp4_u32 position = static_cast(aTime); + mp4_u32 audioPosition = 0; + + mp4_u32 videoPosition = 0; + mp4_bool keyframe = EFalse; + + if (iMP4ReadBuffer != 0) + { + delete[] iMP4ReadBuffer; + iMP4ReadBuffer = 0; + iMP4ReadBufferPos = 0; + iMP4ReadBufferSize = 0; + } + + MP4Err err = MP4ParseSeek(iParser, + position, + &audioPosition, + &videoPosition, + keyframe); + + if (err == MP4_OK) + { + + iCurrentTimeMilliseconds = audioPosition; + iLastTimeStamp = audioPosition - I64INT(iProperties->iFrameDuration.Int64()/1000); + aTime = audioPosition; + return ETrue; + } + else + { + return EFalse; + } + } + +TBool CProcMP4InFileHandler::SeekCutInFrame() + { + + iCurrentTimeMilliseconds = iCutInTime; + return SeekAudioFrame(iCutInTime); + } + + + +TBool CProcMP4InFileHandler::SetNormalizingGainL(const CProcFrameHandler* aFrameHandler) +{ + + + if (iProperties->iAudioType == EAudAAC_MPEG4) + { + + 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)) + { + + 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; + } + + delete 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); + + + } + + else if (iProperties->iAudioType == EAudAMR) + { + HBufC8* point = 0; + TInt siz; + TInt32 tim = 0; + TInt8 margin = 0; + TInt minMargin = KMaxTInt; + TInt tmpGain = 0; + TInt frameCounter = 0; + while(GetEncAudioFrameL(point, siz, tim)) + + { + aFrameHandler->GetNormalizingMargin(point, margin); + tmpGain += margin; + + delete point; + point = 0; + frameCounter++; + if (frameCounter > 1) + { + tmpGain = tmpGain/3; + + if (tmpGain < minMargin) + { + minMargin = tmpGain; + } + + frameCounter = 0; + tmpGain = 0; + } + } + + iNormalizingMargin = static_cast(minMargin); + } + return ETrue; + +} + +TBool CProcMP4InFileHandler::ReadAudioDecoderSpecificInfoL(HBufC8*& aBytes, TInt aBufferSize) + { + + + aBytes = HBufC8::NewL(aBufferSize); + + CleanupStack::PushL(aBytes); + + mp4_u8 *buffer = new (ELeave) mp4_u8[aBufferSize]; + mp4_u32 decspecinfosize = 0; + + MP4Err err = MP4ParseReadAudioDecoderSpecificInfo( + iParser, + buffer, + aBufferSize, + &decspecinfosize); + + if (err == MP4_OK) + { + + for (TUint a = 0 ; a < decspecinfosize ; a++) + { + aBytes->Des().Append(buffer[a]); + } + } + else + { + delete[] buffer; + buffer = 0; + CleanupStack::PopAndDestroy(aBytes); + aBytes = 0; + return EFalse;; + } + + delete[] buffer; + buffer = 0; + + CleanupStack::Pop(aBytes); + return ETrue; + + + } + + +CProcMP4InFileHandler::~CProcMP4InFileHandler() + { + if (iFileOpen) + { + MP4ParseClose(iParser); + } + if (iSilentFrame != 0) + { + delete iSilentFrame; + } + + if (iFrameInfo != 0) + { + delete iFrameInfo; + iFrameInfo = 0; + } + + if (iMP4ReadBuffer != 0) + { + delete[] iMP4ReadBuffer; + } + + delete iDecoder; + + delete iFrameHandler; + + } + + +void CProcMP4InFileHandler::ConstructL(const TDesC& aFileName, + RFile* aFileHandle, + CAudClip* aClip, + TInt /*aReadBufferSize*/, + TInt aTargetSampleRate, + TChannelMode aChannelMode) + { + //InitAndOpenFileL(aFileName, aCutInTime, aReadBufferSize); + + iFrameInfo = new (ELeave) TAACFrameHandlerInfo; + + + // init a raw silent frame + // in other in file handlers it is created in CProcInFileHandler + + const TInt KBitsPerSample = 16; + + TInt samplesIn20ms = ((iTargetSampleRate) * + (KBitsPerSample)/8)/50; + + if (iChannelMode == EAudStereo) + { + samplesIn20ms *= 2; + + } + if (samplesIn20ms % 2 != 0) samplesIn20ms--; + + iRawSilentFrame = HBufC8::NewL(samplesIn20ms); + + iRawSilentFrame->Des().SetLength(samplesIn20ms); + iRawSilentFrame->Des().Fill(0); + + iRawSilentFrameDuration = 20; + + + iClip = aClip; + + iTargetSampleRate = aTargetSampleRate; + iChannelMode = aChannelMode; + + if (iParser == 0) + { + + MP4Err err; + if (aFileHandle) + { + err = MP4ParseOpenFileHandle(&iParser, aFileHandle); + } + else + { + TBuf<258> temp(aFileName); + temp.ZeroTerminate(); + MP4FileName name = (MP4FileName)(temp.Ptr()); + err = MP4ParseOpen(&iParser , name); + } + + if (err == MP4_FILE_ERROR) + { + User::Leave(KErrNotFound); + } + else if (err != MP4_OK) + { + User::Leave(KErrGeneral); + } + iFileOpen = ETrue; + + } + + TAudFileProperties prop; + GetPropertiesL(&prop); + + if (prop.iAudioType == EAudAAC_MPEG4) + { + // generate a silent frame ------------------> + + if (iProperties->iChannelMode == EAudSingleChannel) + { + + iSilentFrame = HBufC8::NewL(KSilentMonoAACFrameLenght); + iSilentFrame->Des().Append(KSilentMonoAACFrame, KSilentMonoAACFrameLenght); + + } + else if (iProperties->iChannelMode == EAudStereo) + { + + iSilentFrame = HBufC8::NewL(KSilentStereoAACFrameLenght); + iSilentFrame->Des().Append(KSilentStereoAACFrame, KSilentStereoAACFrameLenght); + + + } + else + { + User::Leave(KErrNotSupported); + } + + + mp4_u32 frameDurationMilli = ProcTools::MilliSeconds(iProperties->iFrameDuration); + + + iSilentFrameDuration = frameDurationMilli; + + + + // <------------------generate a silent frame + + iFrameHandler = CProcAACFrameHandler::NewL(*iFrameInfo); + + } + else if (prop.iAudioType == EAudAMR) + { + const TInt KSilentFrameSize = 13; + + TUint8 silentFrame[KSilentFrameSize]= + { + 0x04,0x63,0x3C,0xC7,0xF0,0x03,0x04,0x39,0xFF,0xE0, + 0x00,0x00,0x00 + }; + + + iSilentFrame = HBufC8::NewL(KSilentFrameSize); + iSilentFrame->Des().Append(silentFrame, KSilentFrameSize); + iSilentFrameDuration = 20; + + + iFrameHandler = CProcAMRFrameHandler::NewL(); + + } + else if (prop.iAudioType == EAudAMRWB) + { + TUint8 sf[18] = {0x04,0x10,0x20,0x00,0x21, + 0x1C,0x14,0xD0,0x11,0x40,0x4C,0xC1,0xA0, + 0x50,0x00,0x00,0x44,0x30}; + iSilentFrame = HBufC8::NewL(18); + iSilentFrame->Des().Append(sf,18); + iSilentFrameDuration = 20; + + iFrameHandler = CProcAWBFrameHandler::NewL(); + + } + else if (prop.iAudioType == EAudNoAudio ) + { + iDecodingPossible = EFalse; + return; + } + + if (aClip != 0) + { + iCutInTime = ProcTools::MilliSeconds(aClip->CutInTime()); + + } + + iDecoder = CProcDecoder::NewL(); + + iDecodingPossible = iDecoder->InitL(*iProperties, aTargetSampleRate, aChannelMode); + + if (iClip != 0 && iClip->Normalizing()) + { + SetNormalizingGainL(iFrameHandler); + } + + + } + +CProcMP4InFileHandler::CProcMP4InFileHandler() : CProcInFileHandler(), iParser(0), + iLastTimeStamp(0), iFrameInfo(0) + { + + } + +TBool CProcMP4InFileHandler::GetAudioFrameInfoL(TInt& aFrameAmount, + TInt& aAverageFrameDuration, + TInt& aAverageFrameSize, + TAudFileProperties* aProperties) + { + + PRINT((_L("CProcMP4InFileHandler::GetAudioFrameInfoL in"))); + mp4_u32 audiolength = 0; + mp4_u32 audiotype = 0; + + mp4_u8 framespersample = 0; + mp4_u32 timescale = 0; + mp4_u32 averagebitrate = 0; + + if (aProperties->iSamplingRate == 0) return KErrNotSupported; + + MP4Err err = MP4ParseRequestAudioDescription(iParser, &audiolength, &audiotype, + &framespersample, ×cale, &averagebitrate); + + + if (aProperties->iAudioType == EAudAMR) + { + aAverageFrameDuration = 20; + + } + else if(aProperties->iAudioType == EAudAMRWB) + { + aAverageFrameDuration = 20; + + } + else if(aProperties->iAudioType == EAudAAC_MPEG4) + { + + aAverageFrameDuration = (1024*1000)/(aProperties->iSamplingRate); + + } + else + { + User::Leave(KErrNotSupported); + } + + aFrameAmount = TInt((TInt)audiolength/aAverageFrameDuration); + + mp4_u32 lastPosition = 0; + + err = MP4ParseGetLastPosition(iParser, &lastPosition); + + SeekAudioFrame(0); + + + if (err != MP4_OK) + { + return EFalse; + + } + + // ignore the first 2 frames + HBufC8* frame; + TInt size = 0; + TInt32 time = 0; + + + if(GetEncAudioFrameL(frame, size, time)) + { + + if (aProperties->iAudioType == EAudAAC_MPEG4) + { + + /* + * Read the eAAC+ parameters. Please note that the decoder specific + * configuration information does, in case of explicit signalling, + * signal the presence of SBR bitstream elements but not completely + * the configuration of the SBR. For example, parametric stereo is + * signalled only at the bitstream level (due to backwards comptibility + * reasons). + */ + + TUint8* buf = const_cast(frame->Right(frame->Size()).Ptr()); + CProcAACFrameHandler::GetEnhancedAACPlusParametersL(buf, size, aProperties, iFrameInfo); + + } + delete frame; + frame = 0; + } + + if (GetEncAudioFrameL(frame, size, time)) + { + delete frame; + frame = 0; + } + + // calculate the average of the next 100 frames + + TInt32 timeSum = 0; + TInt32 sizeSum = 0; + TInt divider = 0; + TInt maxFrameNr = 100; + if ( aFrameAmount < 100 ) + { + maxFrameNr = aFrameAmount; + } + + + for (TInt a = 0 ; a < maxFrameNr ; a++) + { + if (GetEncAudioFrameL(frame, size, time)) + { + timeSum += time; + sizeSum += size; + divider++; + delete frame; + frame = 0; + } + else + { + + if ( a > 0 ) + { + PRINT((_L("CProcMP4InFileHandler::GetAudioFrameInfoL breaking the loop since less than 100 frames in input (%d)"),a)); + break; + } + else + { + PRINT((_L("CProcMP4InFileHandler::GetAudioFrameInfoL can't get any frames from input"))); + SeekAudioFrame(lastPosition); + return EFalse; + } + } + + } + + if (divider > 0) + { + aAverageFrameDuration = static_cast(timeSum/divider); + aAverageFrameSize = static_cast(sizeSum/divider); + } + + SeekAudioFrame(lastPosition); + + PRINT((_L("CProcMP4InFileHandler::GetAudioFrameInfoL out"))); + return ETrue; + } + + +TBool CProcMP4InFileHandler::GetEncAudioFrameL(HBufC8*& aFrame, TInt& aSize, TInt32& aTime) + { + PRINT((_L("CProcMP4InFileHandler::GetEncAudioFrameL in"))); + if (iParser == 0) + { + aFrame = 0; + return EFalse; + } + + mp4_u32 type = 0; + if (iProperties->iAudioType == EAudAAC_MPEG4) + type = MP4_TYPE_MPEG4_AUDIO; + else if (iProperties->iAudioType == EAudAMR) + { + type = MP4_TYPE_AMR_NB; + if (iMP4ReadBuffer != 0 && iMP4ReadBufferSize > 0 && iMP4ReadBufferPos < iMP4ReadBufferSize) + { + // we can just read a frame from in-buffer + aTime = 20; + TBool ret = ReadOneAMRFrameL(aFrame); + + if (iClip != 0 && iFrameHandler != 0) + { + TRAPD(err0, ManipulateGainL(aFrame)); + if (err0 != KErrNone) + { + // something went wrong with the gain manipulation + // continue by returning the original frame + } + + } + PRINT((_L("CProcMP4InFileHandler::GetEncAudioFrameL out from AMRNB branch"))); + return ret; + } + else + { + // if nothing more to read in the inBuffer + delete[] iMP4ReadBuffer; + iMP4ReadBuffer = 0; + iMP4ReadBufferPos = 0; + iMP4ReadBufferSize = 0; + } + + + // see if stuff left in the read buffer + } + + else if (iProperties->iAudioType == EAudAMRWB) + { + type = MP4_TYPE_AMR_WB; + + if (iMP4ReadBuffer != 0 && iMP4ReadBufferSize > 0 && iMP4ReadBufferPos < iMP4ReadBufferSize) + { + // we can just read a frame from in-buffer + aTime = 20; + TBool ret = ReadOneAWBFrameL(aFrame); + + if (iClip != 0 && iFrameHandler != 0) + { + TRAPD(err0, ManipulateGainL(aFrame)); + if (err0 != KErrNone) + { + // something went wrong with the gain manipulation + // continue by returning the original frame + } + + } + PRINT((_L("CProcMP4InFileHandler::GetEncAudioFrameL out from AMRWB branch"))); + return ret; + } + + } + + + + mp4_u32 framesize = 0; + mp4_u32 audiosize = 0; + mp4_u32 timestamp = 0; + mp4_u32 returnedframes = 0; + mp4_u32 timestamp2 = 0; + + MP4Err err =MP4ParseNextFrameSize(iParser, type, &framesize); + if (err == MP4_OK) + { + + // some error handling + if (type == MP4_TYPE_MPEG4_AUDIO && (framesize > KMaxAACFrameSize)) + { + // we got too many bytes for some reason... + delete[] iMP4ReadBuffer; + iMP4ReadBuffer = 0; + iMP4ReadBufferSize = 0; + iMP4ReadBufferPos = 0; + PRINT((_L("CProcClipInfoAO::CProcMP4InFileHandler::GetEncAudioFrameL out, too many bytes for AAC %d"), framesize )); + return EFalse; + + } + + + iMP4ReadBufferSize = framesize; + delete[] iMP4ReadBuffer; + iMP4ReadBuffer = 0; + iMP4ReadBuffer = new (ELeave) mp4_u8[framesize]; + iMP4ReadBufferPos = 0; + + err = MP4ParseReadAudioFrames(iParser, + iMP4ReadBuffer, + framesize, + &audiosize, + ×tamp, + &returnedframes, + ×tamp2); + + if (err == MP4_OK) + { + aSize = framesize; + aTime = timestamp - iLastTimeStamp; + iCurrentTimeMilliseconds = timestamp; + iLastTimeStamp = timestamp; + + if (type == MP4_TYPE_MPEG4_AUDIO) + { + aFrame = HBufC8::NewL(audiosize); + aFrame->Des().Append(iMP4ReadBuffer, audiosize); + + } + else if (type == MP4_TYPE_AMR_NB) + { + aTime = 20; + ReadOneAMRFrameL(aFrame); + } + else if (type == MP4_TYPE_AMR_WB) + { + aTime = 20; + ReadOneAWBFrameL(aFrame); + } + } + else + { + delete[] iMP4ReadBuffer; + iMP4ReadBuffer = 0; + iMP4ReadBufferSize = 0; + iMP4ReadBufferPos = 0; + PRINT((_L("CProcMP4InFileHandler::GetEncAudioFrameL out since MP4ParseReadAudioFrames failed"))); + return EFalse; + + } + + // delete if MP4AUDIO. + // AMR frames will be read from buffer as MP4 library + // might have returned more than one AMR-frames + if (type == MP4_TYPE_MPEG4_AUDIO) + { + delete[] iMP4ReadBuffer; + iMP4ReadBuffer = 0; + iMP4ReadBufferSize = 0; + iMP4ReadBufferPos = 0; + } + + } + else + { + PRINT((_L("CProcMP4InFileHandler::GetEncAudioFrameL out since MP4ParseNextFrameSize failed, error %d"),err)); + return EFalse; + + } + + TInt err2 = KErrNone; + + if (iProperties->iAudioTypeExtension == EAudExtensionTypeNoExtension) + { + + // AAC Plus is manipulated in time domain + + if (iClip != 0 && iFrameHandler != 0) + { + TRAP(err2, ManipulateGainL(aFrame)); + } + + } + + if (err2 != KErrNone) + { + // something went wrong with the gain manipulation + // continue by returning the original frame + } + aSize = aFrame->Size(); + + PRINT((_L("CProcMP4InFileHandler::GetEncAudioFrameL out successfully"))); + return ETrue; + } + + +TBool CProcMP4InFileHandler::ReadTimeScale(mp4_u32& aTimescale) + { + + mp4_u32 audiolength = 0; + mp4_u32 audiotype = 0; + mp4_u8 framespersample = 0; + mp4_u32 timescale = 0; + mp4_u32 averagebitrate = 0; + + MP4Err err = MP4ParseRequestAudioDescription(iParser, + &audiolength, + &audiotype, + &framespersample, + ×cale, + &averagebitrate); + + + + if (err == MP4_OK) + { + aTimescale = timescale; + return ETrue; + } + else + { + return EFalse; + } + + } + + +MP4Err CProcMP4InFileHandler::ParseRequestAudioDescription( + mp4_u32 *aAudiolength, + mp4_u32 *aAudiotype, + mp4_u8 *aFramespersample, + mp4_u32 *aTimescale, + mp4_u32 *aAveragebitrate) + + { + + return MP4ParseRequestAudioDescription(iParser, + aAudiolength, + aAudiotype, + aFramespersample, + aTimescale, + aAveragebitrate); + + } + + +TBool CProcMP4InFileHandler::GetInfoForFrameHandler(TAACFrameHandlerInfo& aAACInfo) + { + if (iParser == 0) + { + return EFalse; + } + + aAACInfo.iIs960 = iFrameInfo->iIs960; + aAACInfo.iIsParametricStereo = iFrameInfo->iIsParametricStereo; + aAACInfo.iNumChannels = iFrameInfo->iNumChannels; + aAACInfo.iNumCouplingChannels = iFrameInfo->iNumCouplingChannels; + aAACInfo.iProfileID = iFrameInfo->iProfileID; + aAACInfo.iSampleRateID = iFrameInfo->iSampleRateID; + aAACInfo.isSBR = iFrameInfo->isSBR; + + + mp4_u8 *buffer = 0; + + const TInt bufSize = 64; + TRAPD(nerr, buffer = new (ELeave) mp4_u8[bufSize]) + + if (nerr != KErrNone) + { + delete[] buffer; + return EFalse; + } + + + mp4_u32 decspecinfosize = 0; + + MP4Err err = MP4ParseReadAudioDecoderSpecificInfo( + iParser, + buffer, + 64, + &decspecinfosize); + + + if (err == MP4_OK) + { + + mp4AACTransportHandle mp4AAC_ff; + int16 err2 = ReadMP4AudioConfig(buffer, + decspecinfosize, + &mp4AAC_ff); + if (err2 != TRUE) + { + + delete[] buffer; + return EFalse; + + } + + aAACInfo.iSampleRateID = static_cast(mp4AAC_ff.progCfg.sample_rate_idx); + aAACInfo.iSampleRateID = static_cast(mp4AAC_ff.audioInfo.samplingFreqIdx); + + aAACInfo.iProfileID = static_cast(mp4AAC_ff.progCfg.profile); + + if (iProperties->iChannelMode == EAudStereo) + { + aAACInfo.iNumChannels = 2; + } + else if (iProperties->iChannelMode == EAudSingleChannel) + { + aAACInfo.iNumChannels = 1; + } + else + { + aAACInfo.iNumChannels = 0; + } + + + aAACInfo.iIs960 = mp4AAC_ff.audioInfo.gaInfo.FrameLengthFlag; + + aAACInfo.iNumCouplingChannels = 0; + + aAACInfo.iIsParametricStereo = 0; + aAACInfo.isSBR = 0; + + } + + else + { + + delete[] buffer; + return EFalse; + + } + + delete[] buffer; + return ETrue; + + + + } + + + + +TBool CProcMP4InFileHandler::ReadOneAMRFrameL(HBufC8*& aOneAMRFrame) + { + if (iMP4ReadBuffer == 0 || iMP4ReadBufferSize < 1 + || iMP4ReadBufferPos >= iMP4ReadBufferSize) + { + aOneAMRFrame = 0; + return EFalse; + } + + + TInt readSize = 0; + TUint8 dec_mode = (enum Mode)((iMP4ReadBuffer[iMP4ReadBufferPos] & 0x0078) >> 3); + + switch (dec_mode) + { + case 0: + readSize = 12; + break; + case 1: + readSize = 13; + break; + case 2: + readSize = 15; + break; + case 3: + readSize = 17; + break; + case 4: + readSize = 19; + break; + case 5: + readSize = 20; + break; + case 6: + readSize = 26; + break; + case 7: + readSize = 31; + break; + case 8: + readSize = 5; + break; + case 15: + readSize = 0; + break; + default: + readSize = 0; + break; + }; + + aOneAMRFrame = HBufC8::NewL(readSize+1); + +// TPtr8 tmpDes((TPtr8)aOneAMRFrame->Des()); + + TInt lastByte = iMP4ReadBufferPos + readSize; + + for (; iMP4ReadBufferPos <= lastByte ; iMP4ReadBufferPos++) + { + + aOneAMRFrame->Des().Append(iMP4ReadBuffer[iMP4ReadBufferPos]); + } +// iMP4ReadBufferPos++; + + return ETrue; + + } + +TBool CProcMP4InFileHandler::ReadOneAWBFrameL(HBufC8*& aOneAWBFrame) + { + if (iMP4ReadBuffer == 0 || iMP4ReadBufferSize < 1 + || iMP4ReadBufferPos >= iMP4ReadBufferSize) + { + aOneAWBFrame = 0; + return EFalse; + } + TUint8 toc = iMP4ReadBuffer[iMP4ReadBufferPos]; + TUint8 mode = static_cast((toc >> 3) & 0x0F); + + TInt readSize = KAWBPacked_size[mode]; + + aOneAWBFrame = HBufC8::NewL(readSize+1); + + TInt lastByte = iMP4ReadBufferPos + readSize; + + for (; iMP4ReadBufferPos <= lastByte ; iMP4ReadBufferPos++) + { + + aOneAWBFrame->Des().Append(iMP4ReadBuffer[iMP4ReadBufferPos]); + } + + return ETrue; + + } +