--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/videoeditorengine/vedengine/videoprocessor/src/mp4composer.cpp Fri Jan 29 14:08:33 2010 +0200
@@ -0,0 +1,796 @@
+/*
+* 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:
+*
+*/
+
+
+//FC Based on Cmp4parser
+
+
+// INCLUDE FILES
+#include <f32file.h>
+#include "mp4composer.h"
+#include "vedvideosettings.h"
+#include "vedavcedit.h"
+
+
+// ASSERTIONS
+//#define MPASSERT(x) __ASSERT_DEBUG(x, User::Panic(_L("CVideoProcessorImpl"), EInternalAssertionFailure))
+
+
+// MACROS
+//#define ?macro ?macro_def
+
+#ifdef _DEBUG
+#include <e32svr.h>
+#define PRINT(x) RDebug::Print x;
+#else
+#define PRINT(x)
+#endif
+
+// LOCAL CONSTANTS AND MACROS
+
+const TUint KFreeDiskSpaceCounter = 10; // Interval when to find out real free disk space
+const TUint KMaxComposeBufferSize = 512000; // : Adjust buffer size dynamically
+
+#ifdef _DEBUG
+const TInt KLeaveCode = CComposer::EComposerFailure;
+#else
+const TInt KLeaveCode = KErrGeneral;
+#endif
+
+// ============================= LOCAL FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// RateIndex: converts sample rate to rate index used in decoder config info
+// -----------------------------------------------------------------------------
+//
+static TUint8 RateIndex(TInt aRate)
+ {
+ switch ( aRate )
+ {
+ case 96000:
+ return 0x0;
+ case 88200:
+ return 0x1;
+ case 64000:
+ return 0x2;
+ case 48000:
+ return 0x3;
+ case 44100:
+ return 0x4;
+ case 32000:
+ return 0x5;
+ case 24000:
+ return 0x6;
+ case 22050:
+ return 0x7;
+ case 16000:
+ return 0x8;
+ case 12000:
+ return 0x9;
+ case 11025:
+ return 0xa;
+ case 8000:
+ return 0xb;
+ case 7350:
+ return 0xc;
+ default:
+ return 0xf;
+ }
+ }
+
+
+// ================= MEMBER FUNCTIONS =======================
+
+// C++ default constructor can NOT contain any code, that
+// might leave.
+//
+
+CMP4Composer::CMP4Composer()
+{
+ iMP4Handle = 0;
+ iFreeDiskSpace = 0;
+ iFreeDiskSpaceCounter = 0;
+ iFirstWrite = ETrue;
+ iFsOpened = EFalse;
+}
+
+// Two-phased constructor.
+CMP4Composer* CMP4Composer::NewL(const TDesC &aFileName,
+ CParser::TVideoFormat aVideoFormat,
+ CParser::TAudioFormat aAudioFormat,
+ CVedAVCEdit *aAvcEdit)
+{
+ CMP4Composer *self = new (ELeave) CMP4Composer;
+ CleanupStack::PushL(self);
+ self->ConstructL(aFileName, aVideoFormat, aAudioFormat, aAvcEdit);
+ CleanupStack::Pop(); // self
+ return self;
+}
+
+CMP4Composer* CMP4Composer::NewL(RFile* aFileHandle,
+ CParser::TVideoFormat aVideoFormat,
+ CParser::TAudioFormat aAudioFormat,
+ CVedAVCEdit *aAvcEdit)
+{
+ CMP4Composer *self = new (ELeave) CMP4Composer;
+ CleanupStack::PushL(self);
+ self->ConstructL(aFileHandle, aVideoFormat, aAudioFormat, aAvcEdit);
+ CleanupStack::Pop(); // self
+ return self;
+}
+
+// Symbian OS default constructor can leave.
+void CMP4Composer::ConstructL(const TDesC &aFileName,
+ CParser::TVideoFormat aVideoFormat,
+ CParser::TAudioFormat aAudioFormat,
+ CVedAVCEdit *aAvcEdit)
+{
+ TUint mediaType = 0;
+
+ iOutputMovieFileName = TFileName(aFileName);
+ iFileHandle = NULL;
+
+ iAvcEdit = aAvcEdit;
+
+ // open MP4 library
+
+ TBuf<258> temp(aFileName);
+ temp.ZeroTerminate();
+
+ MP4FileName name = reinterpret_cast<MP4FileName>( const_cast<TUint16*>(temp.Ptr()) );
+
+ SetMediaOptions(aVideoFormat, aAudioFormat, mediaType);
+
+ MP4Err error;
+
+ // if the filename length is greater 0, then compose to file else buffer
+ if(aFileName.Length() > 0)
+ {
+ error = MP4ComposeOpen(&iMP4Handle, name, mediaType);
+ }
+ else
+ {
+ // initialize to compose to buffer
+ iComposeBuffer = (TUint8*)HBufC::NewL( KMaxComposeBufferSize );
+ iComposedSize = KMaxComposeBufferSize;
+ error = MP4ComposeOpenToBuffer(&iMP4Handle, mediaType,(mp4_u8*)iComposeBuffer,&iComposedSize);
+ }
+
+ if ( error != MP4_OK )
+ User::Leave(KLeaveCode);
+
+ SetComposerOptionsL(aVideoFormat, aAudioFormat);
+
+}
+
+void CMP4Composer::ConstructL(RFile* aFileHandle,
+ CParser::TVideoFormat aVideoFormat,
+ CParser::TAudioFormat aAudioFormat,
+ CVedAVCEdit *aAvcEdit)
+{
+ TUint mediaType = 0;
+
+ iOutputMovieFileName.Zero();
+ iFileHandle = aFileHandle;
+
+ iAvcEdit = aAvcEdit;
+
+ SetMediaOptions(aVideoFormat, aAudioFormat, mediaType);
+
+ // open MP4 library
+ MP4Err error;
+
+ error = MP4ComposeOpenFileHandle(&iMP4Handle, aFileHandle, EDriveC, mediaType);
+
+ if ( error != MP4_OK )
+ User::Leave(KLeaveCode);
+
+ SetComposerOptionsL(aVideoFormat, aAudioFormat);
+
+}
+
+
+void CMP4Composer::SetMediaOptions(CParser::TVideoFormat aVideoFormat,
+ CParser::TAudioFormat aAudioFormat,
+ TUint& aMediaFlags)
+
+{
+
+ if ( (aVideoFormat == CParser::EVideoFormatH263Profile0Level10) ||
+ (aVideoFormat == CParser::EVideoFormatH263Profile0Level45) )
+ {
+ aMediaFlags = MP4_TYPE_H263_PROFILE_0;
+ iVideoType = MP4_TYPE_H263_PROFILE_0;
+ }
+
+#ifdef VIDEOEDITORENGINE_AVC_EDITING
+ else if (aVideoFormat == CParser::EVideoFormatAVCProfileBaseline)
+ {
+ aMediaFlags = MP4_TYPE_AVC_PROFILE_BASELINE;
+ iVideoType = MP4_TYPE_AVC_PROFILE_BASELINE;
+ }
+#endif
+ else
+ {
+ aMediaFlags = MP4_TYPE_MPEG4_VIDEO;
+ iVideoType = MP4_TYPE_MPEG4_VIDEO;
+ }
+
+ if ( aAudioFormat == CParser::EAudioFormatAMR )
+ {
+ aMediaFlags |= MP4_TYPE_AMR_NB;
+ iAudioType = MP4_TYPE_AMR_NB;
+ }
+
+ else if ( aAudioFormat == CParser::EAudioFormatAAC )
+ {
+ aMediaFlags |= MP4_TYPE_MPEG4_AUDIO; // added for AAC support.
+ iAudioType = MP4_TYPE_MPEG4_AUDIO;
+ }
+
+}
+
+void CMP4Composer::SetComposerOptionsL(CParser::TVideoFormat aVideoFormat,
+ CParser::TAudioFormat aAudioFormat)
+{
+
+ MP4Err error;
+
+ TBool videoMpeg4OrAvc = ( aVideoFormat == CParser::EVideoFormatMPEG4 ||
+ aVideoFormat == CParser::EVideoFormatAVCProfileBaseline );
+
+ mp4_u32 flags = 0;
+ flags |= MP4_FLAG_LARGEFILEBUFFER; // Note: What does this do when using RFile ?
+ flags |= MP4_FLAG_METADATALAST;
+
+ // generate MP4 file format if MPEG-4/AVC video & AAC audio
+ if ( (videoMpeg4OrAvc && aAudioFormat == CParser::EAudioFormatAAC) ||
+ (videoMpeg4OrAvc && aAudioFormat == CParser::EAudioFormatNone) ||
+ (aVideoFormat == CParser::EVideoFormatNone && aAudioFormat == CParser::EAudioFormatAAC) )
+ {
+ flags |= MP4_FLAG_GENERATE_MP4;
+ }
+
+ error = MP4ComposeSetFlags(iMP4Handle, flags);
+
+ if (error != MP4_OK)
+ if (error == MP4_OUT_OF_MEMORY)
+ {
+ User::LeaveNoMemory();
+ }
+ else
+ {
+ User::Leave(KLeaveCode);
+ }
+
+ // set buffer sizes; only composer buffer settings are effective for this instance
+ error = MP4SetCustomFileBufferSizes(iMP4Handle, K3gpMp4ComposerWriteBufferSize, K3gpMp4ComposerNrOfWriteBuffers, K3gpMp4ParserReadBufferSize );
+
+ if (error == MP4_OUT_OF_MEMORY)
+ {
+ User::Leave(KErrNoMemory);
+ }
+ else if ( error != MP4_OK )
+ {
+ User::Leave(KLeaveCode);
+ }
+}
+
+
+// Destructor
+CMP4Composer::~CMP4Composer()
+{
+ if (iMP4Handle)
+ {
+ MP4ComposeClose(iMP4Handle);
+ }
+
+ if(iComposeBuffer) // added for Buffer support
+ {
+ User::Free(iComposeBuffer);
+ iComposeBuffer=0;
+ }
+
+ iMP4Handle = 0;
+
+ if (iFsOpened)
+ {
+ iFS.Close();
+ iFsOpened = EFalse;
+ }
+
+
+}
+
+// ---------------------------------------------------------
+// CMP4Composer::WriteFrames
+// Write the next frame(s) to file
+// ---------------------------------------------------------
+//
+TInt CMP4Composer::WriteFrames(TDesC8& aSrcBuffer, TInt aFrameSize,
+ TInt aDuration, TInt aKeyFrame,
+ TInt aNumberOfFrames, TInt aFrameType)
+{
+ MP4Err error = KErrNone;
+
+ // get the parameters
+ TUint32 frameSize = aFrameSize;
+ TUint32 duration = aDuration;
+ mp4_bool keyframe = (mp4_bool)aKeyFrame;
+ TInt numberOfFrames = aNumberOfFrames;
+ TFrameType frameType = (aFrameType>0 ? (aFrameType==1 ? EFrameTypeAudio : EFrameTypeVideo)
+ : EFrameTypeNone);
+
+ if (frameType == EFrameTypeVideo)
+ {
+ error = MP4ComposeWriteVideoFrame(iMP4Handle, (mp4_u8*)(aSrcBuffer.Ptr()),
+ frameSize, duration, keyframe);
+ if ( error != MP4_OK )
+ return KLeaveCode;
+ }
+
+ else if (frameType == EFrameTypeAudio)
+ {
+ error = MP4ComposeWriteAudioFrames(iMP4Handle,(mp4_u8*)(aSrcBuffer.Ptr()),
+ frameSize, numberOfFrames, duration);
+ if ( error != MP4_OK )
+ return KLeaveCode;
+ }
+ else
+ User::Panic(_L("CMovieProcessorImpl"), EComposerFailure);
+
+ return KErrNone;
+
+}
+
+
+TInt CMP4Composer::WriteFrames(TDesC8& aSrcBuffer, TInt aFrameSize,
+ TInt aDuration, TInt aKeyFrame,
+ TInt aNumberOfFrames, TInt aFrameType,
+ TInt& aMP4Size, TBool aModeChanged,
+ TBool aFirstFrameOfClip, TInt aMode, TBool /*aFromEncoder*/)
+{
+ MP4Err error = KErrNone;
+
+ // get the parameters
+ TUint32 frameSize = aFrameSize;
+ TUint32 duration = aDuration;
+ mp4_bool keyframe = ( aKeyFrame ) ? ETrue : EFalse;
+ TInt numberOfFrames = aNumberOfFrames;
+ TFrameType frameType = (aFrameType > 0 ? (aFrameType == 1 ? EFrameTypeAudio : EFrameTypeVideo)
+ : EFrameTypeNone);
+ TUint8* dataPtr = (TUint8*)(aSrcBuffer.Ptr());
+ TInt tmpSize = 0;
+
+ // call this only for the first frame of every clip
+ if ( aFirstFrameOfClip && (iVideoType == MP4_TYPE_MPEG4_VIDEO) && (aMP4Size == 0))
+ {
+ if ((tmpSize = GetMp4SpecificSize(aSrcBuffer,aModeChanged,aMode)) != 0)
+ aMP4Size = tmpSize; //This will be the new Mp4Size as it will be consider and since by reference it is maintained
+ }
+
+ if (frameType == EFrameTypeVideo)
+ {
+ if ( iVideoType == MP4_TYPE_MPEG4_VIDEO )
+ {
+ if ( iFirstWrite )
+ {
+ // VOS
+ error = MP4ComposeWriteVideoDecoderSpecificInfo( iMP4Handle,
+ (mp4_u8*)(dataPtr/*aSrcBuffer.Ptr()*/), aMP4Size );
+ iFirstWrite = EFalse;
+
+ error = MP4ComposeWriteVideoFrame(iMP4Handle, (mp4_u8*)(dataPtr/*aSrcBuffer.Ptr()*/ + aMP4Size),
+ ( frameSize - aMP4Size ), duration, keyframe);
+ }
+ else
+ {
+ // for MPEG4 - check the first 32 bits to make sure we don't
+ // have VOS pre-pended to VOP data
+ if (dataPtr[0] == 0x00 && dataPtr[1] == 0x00 && dataPtr[2] == 0x01 && dataPtr[3] == 0xb0)
+ { // since intermediate Vos set to proper value
+ // Not Short Header may have User Data space problem with PSC
+ if ((tmpSize = GetMp4SpecificSize(aSrcBuffer,aModeChanged,aMode)) != 0)
+ aMP4Size = tmpSize; //This will be the new Mp4Size as it will be considered
+ dataPtr += aMP4Size;
+ frameSize -= aMP4Size;
+ }
+
+ if (frameSize == 0)
+ return KErrWrite;
+
+ error = MP4ComposeWriteVideoFrame(iMP4Handle, (mp4_u8*)(dataPtr),
+ frameSize, duration, keyframe);
+ }
+ }
+
+#ifdef VIDEOEDITORENGINE_AVC_EDITING
+ else if ( iVideoType == MP4_TYPE_AVC_PROFILE_BASELINE )
+ {
+
+ if ( iFirstWrite || aFirstFrameOfClip)
+ {
+ if(iFirstWrite)
+ {
+ iFrameNumber = 0;
+ iFirstWrite = EFalse;
+ }
+
+ aMP4Size = 0;
+ error = MP4ComposeWriteVideoFrame(iMP4Handle, (mp4_u8*)(dataPtr/*aSrcBuffer.Ptr()*/ + aMP4Size),
+ ( frameSize - aMP4Size ), duration, keyframe);
+ }
+ else
+ {
+ error = MP4ComposeWriteVideoFrame(iMP4Handle, (mp4_u8*)(dataPtr),
+ frameSize, duration, keyframe);
+ }
+
+ iFrameNumber++;
+ }
+#endif
+
+ else // H.263
+ {
+ error = MP4ComposeWriteVideoFrame(iMP4Handle, (mp4_u8*)(dataPtr/*aSrcBuffer.Ptr()*/),
+ frameSize, duration, keyframe);
+
+ }
+ if ( error != MP4_OK )
+ return KLeaveCode;
+ }
+ else if (frameType == EFrameTypeAudio)
+ {
+ error = MP4ComposeWriteAudioFrames(iMP4Handle,(mp4_u8*)(dataPtr/*aSrcBuffer.Ptr()*/),
+ frameSize, numberOfFrames, duration);
+ if ( error != MP4_OK )
+ return KLeaveCode;
+ }
+ else
+ User::Panic(_L("CMovieProcessorImpl"), EComposerFailure);
+
+ return KErrNone;
+}
+
+
+
+// ---------------------------------------------------------
+// CMP4Composer::ComposeHeaderL
+// Get relevant stream parameters by calling mp4 library functions
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+
+
+void CMP4Composer::ComposeHeaderL(CComposer::TStreamParameters& aStreamParameters, TInt aOutputVideoTimeScale,
+ TInt aOutputAudioTimeScale, TInt aAudioFramesInSample)
+{
+ MP4Err iError=KErrNone;
+
+ TInt width = aStreamParameters.iVideoWidth;
+ TInt height = aStreamParameters.iVideoHeight;
+ TInt avgbitrate = aStreamParameters.iStreamBitrate;
+ TInt maxbitrate = avgbitrate;
+ TInt audioFramesPerSample = aAudioFramesInSample;//aStreamParameters.iAudioFramesInSample;
+ TInt audioTimescale = aOutputAudioTimeScale;
+ TInt modeSet=0x8180;
+
+ if(iAudioType == MP4_TYPE_MPEG4_AUDIO) // added for AAC support
+ {
+ // reset for AAC audio according to the code sent for AAC support.
+ audioFramesPerSample = 0;
+ modeSet = 0;
+ }
+
+ // set this to first clip's time scale
+ TInt timescale = aOutputVideoTimeScale;
+
+ iError = MP4ComposeAddAudioDescription(iMP4Handle,(mp4_u32)audioTimescale,
+ (mp4_u8)audioFramesPerSample,(mp4_u16)modeSet);
+ if (iError != MP4_OK)
+ User::Leave(KLeaveCode);
+
+ // write video description
+ iError = MP4ComposeAddVideoDescription(iMP4Handle,(mp4_u32)timescale,
+ (mp4_u16)width,(mp4_u16)height,(mp4_u32)maxbitrate,(mp4_u32)avgbitrate);
+
+ if (iError != MP4_OK)
+ User::Leave(KLeaveCode);
+
+ if ( aStreamParameters.iVideoFormat == EVideoFormatH263Profile0Level10 )
+ {
+ TVideoClipProperties prop;
+ prop.iH263Level = 10;
+ MP4ComposeSetVideoClipProperties(iMP4Handle, prop);
+ }
+
+ else if ( aStreamParameters.iVideoFormat == EVideoFormatH263Profile0Level45 )
+ {
+ TVideoClipProperties prop;
+ prop.iH263Level = 45;
+ MP4ComposeSetVideoClipProperties(iMP4Handle, prop);
+ }
+
+ if (!iFsOpened) // Check if file server is open already
+ {
+ User::LeaveIfError(iFS.Connect());
+ iFsOpened = ETrue;
+ }
+
+ if (iFileHandle == 0)
+ {
+ // get target drive number
+ TParse fp;
+ User::LeaveIfError(iFS.Parse(iOutputMovieFileName, fp));
+ TPtrC driveletter = fp.Drive();
+ TChar drl = driveletter[0];
+ User::LeaveIfError(RFs::CharToDrive(drl, iDriveNumber));
+ }
+ else
+ {
+ // get target drive number
+ TDriveInfo info;
+ TInt error = iFileHandle->Drive(iDriveNumber, info);
+ }
+}
+
+// -----------------------------------------------------------------------------
+// CMP4Composer::DriveFreeSpaceL
+// Calculate free space on a drive in bytes.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt64 CMP4Composer::DriveFreeSpaceL()
+{
+ TVolumeInfo volumeinfo;
+
+ if (iFreeDiskSpaceCounter % KFreeDiskSpaceCounter == 0)
+ {
+ User::LeaveIfError(iFS.Volume(volumeinfo, iDriveNumber));
+ iFreeDiskSpace = volumeinfo.iFree;
+ }
+
+ iFreeDiskSpaceCounter++;
+ return iFreeDiskSpace;
+
+}
+
+// -----------------------------------------------------------------------------
+// CMP4Composer::GetComposedBuffer New Function added for Buffer support
+// Gets the Composed buffer from the composer
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TUint8* CMP4Composer::GetComposedBuffer()
+{
+ return iComposeBuffer;
+}
+
+// -----------------------------------------------------------------------------
+// CMP4Composer::GetComposedBufferSize New Function added for Buffer support
+// Gets the Composed buffer size from the composer
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TUint CMP4Composer::GetComposedBufferSize()
+{
+ return iComposedSize;
+}
+
+// ---------------------------------------------------------
+// CMP4Composer::Close
+// Closes the composer instance & creates the output 3gp file
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt CMP4Composer::Close()
+{
+
+#ifdef VIDEOEDITORENGINE_AVC_EDITING
+
+ if (iVideoType == MP4_TYPE_AVC_PROFILE_BASELINE)
+ {
+ HBufC8* AVCDCR = NULL;
+ TInt error;
+
+ TRAP(error, AVCDCR = (HBufC8*) HBufC8::NewL(16384));
+ if (error != KErrNone)
+ return error;
+
+ TPtr8 ptr = AVCDCR->Des();
+
+ // Construct AVC Decoder Configuration Record from the SPS / PPS sets
+ TRAP(error, iAvcEdit->ConstructAVCDecoderConfigurationRecordL(ptr));
+ if (error != KErrNone)
+ {
+ delete AVCDCR;
+ return error;
+ }
+
+ // Pass the AVC Decoder Configuration Record to the 3GPMP4 library
+ MP4Err mp4Error = MP4ComposeWriteVideoDecoderSpecificInfo( iMP4Handle,
+ (mp4_u8*)(ptr.Ptr()), ptr.Length());
+
+ delete AVCDCR;
+
+ if (mp4Error != MP4_OK)
+ return EComposerFailure;
+ }
+
+#endif
+
+ MP4Err error = MP4ComposeClose(iMP4Handle);
+
+ iMP4Handle = 0;
+
+ if (error != MP4_OK)
+ return EComposerFailure;
+
+ if (iFsOpened)
+ {
+ iFS.Close();
+ iFsOpened = EFalse;
+ }
+
+ return KErrNone;
+}
+
+
+// -----------------------------------------------------------------------------
+// CMP4Composer::GetMp4SpecificSize
+// Gets the length of MPEG-4 decoder specific info in aSrcBuf
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CMP4Composer::GetMp4SpecificSize(TDesC8& aSrcBuf,TBool aModeChange,TInt aStreamMode)
+{
+ TUint8* dtPtr = (TUint8*)(aSrcBuf.Ptr());
+ TInt mp4size =0;
+ TInt bufSize;
+ TInt flag;
+
+ if (!aModeChange && (aStreamMode == 2)) //2 indicates short header in VedCommon
+ {
+ bufSize = aSrcBuf.Size()-3;
+ for(TInt i=0;i<bufSize;i++)
+ {
+ flag = (dtPtr[i+2]>>2)<<2;
+ if (dtPtr[i] == 0x00 && dtPtr[i+1] == 0x00 && flag == 0x80) // user data ????????????
+ {
+ mp4size=i;
+ break;
+ }
+ }
+ }
+ else
+ {
+ bufSize = aSrcBuf.Size()-4;
+ for(TInt i=0;i<bufSize;i++)
+ {
+ if ((dtPtr[i] == 0x00 && dtPtr[i+1] == 0x00 && dtPtr[i+2] == 0x01 && dtPtr[i+3] == 0xb3) ||
+ (dtPtr[i] == 0x00 && dtPtr[i+1] == 0x00 && dtPtr[i+2] == 0x01 && dtPtr[i+3] == 0xb6))
+ {
+ mp4size=i;
+ break;
+ }
+ }
+ }
+
+ // MP4 specific size will be zero, if there is a GOV or VOP header in the
+ // very beginning of the buffer
+
+ return mp4size;
+}
+
+
+// ---------------------------------------------------------
+// CMP4Composer::WriteAudioSpecificInfo
+// Writes the Audio decoder Specific info required in case of AAC
+// Decoder specific info is provided externally
+// (other items were commented in a header).
+// decoder info is provided externally
+// ---------------------------------------------------------
+//
+// added to Support AAC audio files
+TInt CMP4Composer::WriteAudioSpecificInfo(HBufC8*& aSrcBuf)
+{
+ TInt error = KErrNone;
+ mp4_u8* aSrcB = const_cast<mp4_u8*>(aSrcBuf->Ptr());
+ error = MP4ComposeWriteAudioDecoderSpecificInfo(iMP4Handle, aSrcB, aSrcBuf->Size());
+
+ if (error != MP4_OK)
+ return KErrGeneral;
+
+ return KErrNone;
+}
+
+// ---------------------------------------------------------
+// CMP4Composer::WriteAudioSpecificInfo
+// Writes the Audio decoder Specific info required in case of AAC
+// Decoder specific info is derived from samplerate and # of channels
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+// added to Support AAC audio files
+TInt CMP4Composer::WriteAudioSpecificInfo(TInt aSampleRate, TInt aNumChannels)
+{
+ TInt error = KErrNone;
+
+ TUint8 data[2];
+
+ data[0] = 2<<3; // AAC-LC
+ TUint8 rate = RateIndex(aSampleRate);
+ data[0] |= rate>>1;
+ data[1] = TUint8(rate<<7);
+ data[1] |= TUint8(aNumChannels<<3);
+
+ error = MP4ComposeWriteAudioDecoderSpecificInfo(iMP4Handle, data, 2);
+
+ if (error != MP4_OK)
+ return KErrGeneral;
+
+ return KErrNone;
+}
+
+
+// -----------------------------------------------------------------------------
+// CMP4Composer::GetAVCDecoderSpecificInfoSize
+// Gets the length of AVC decoder specific info in aSrcBuf
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CMP4Composer::GetAVCDecoderSpecificInfoSize(TDesC8& aSrcBuf)
+{
+ TUint8* srcPtr = (TUint8*)(aSrcBuf.Ptr());
+ TInt skip = 0;
+// TInt error = KErrNone;
+
+ // skip 4 bytes for
+ // configVersion, profile, profile compatibility and Level
+ skip += 4;
+
+ // skip 1 bytes for lengthSizeMinusOne
+ skip += 1;
+
+ // skip 1 bytes for num of seq Param sets
+ TInt numOfSSP = 0x1F & srcPtr[skip];
+ skip += 1;
+
+ for (TInt i = 0; i < numOfSSP; i++)
+ {
+ TInt sspSize = srcPtr[skip]*256 + srcPtr[skip+1];
+ skip += 2;
+ skip += sspSize;
+ }
+
+ TInt numOfPSP = srcPtr[skip];
+ skip += 1;
+
+ for (TInt i = 0; i < numOfPSP; i++)
+ {
+ TInt pspSize = srcPtr[skip]*256 + srcPtr[skip+1];
+ skip += 2;
+ skip += pspSize;
+ }
+
+ return skip;
+}
+
+
+
+// End of File