videoeditorengine/vedengine/videoprocessor/src/mp4composer.cpp
changeset 0 951a5db380a0
--- /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