mmplugins/lib3gp/wrapper/src/c3gpcompose.cpp
changeset 0 40261b775718
equal deleted inserted replaced
-1:000000000000 0:40261b775718
       
     1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <e32debug.h>
       
    17 #include <c3gplibrary.h>
       
    18 
       
    19 #if defined (COMPOSE_DEBUG)
       
    20 #define DEBUG_PRINT RDebug::Print
       
    21 #else
       
    22 #define DEBUG_PRINT
       
    23 #endif
       
    24 
       
    25 const TInt KMinWriteBufferMaxCount = 6;
       
    26 _LIT(K3GPComposePanicName, "C3GPCompose");
       
    27 
       
    28 // This is video base class containing common video properties.
       
    29 T3GPVideoPropertiesBase::T3GPVideoPropertiesBase(T3GPVideoType aType,
       
    30 		TUint aTimescale, const TSize& aSize) :
       
    31 		iType(aType), iTimescale(aTimescale), iSize(aSize)
       
    32 	{
       
    33 	}
       
    34 
       
    35 /**
       
    36 This structure stores the common and MPEG-4 video specific properties of video data.
       
    37  
       
    38 @param	aTimescale				Timescale of the video data.  This is the number of time units that 
       
    39  								pass in one second.
       
    40 @param	aSize					Video width and height in pixels.
       
    41 @param	aMaxBitRate 			Maximum video bit rate.
       
    42 @param	aAvgBitRate				Average video bit rate.
       
    43 @param	aDecoderSpecificInfo	MPEG-4 video DecoderSpecificInfo data stored in an ESDS atom.
       
    44 */
       
    45 EXPORT_C T3GPVideoPropertiesMpeg4Video::T3GPVideoPropertiesMpeg4Video(TUint aTimescale,
       
    46 		const TSize& aSize, TUint aMaxBitRate, TUint aAvgBitRate, const TDesC8& aDecoderSpecificInfo) :
       
    47 		T3GPVideoPropertiesBase(E3GPMpeg4Video, aTimescale, aSize),
       
    48 		iMaxBitRate(aMaxBitRate),
       
    49 		iAvgBitRate(aAvgBitRate),
       
    50 		iDecoderSpecificInfo(aDecoderSpecificInfo)
       
    51 	{
       
    52 	}
       
    53 
       
    54 /**
       
    55 This structure stores the common and H.263 specific properties of video data.
       
    56  
       
    57 @param	aTimescale	Timescale of the video data.  This is the number of time units that 
       
    58 					pass in one second.
       
    59 @param	aSize		Video width and height in pixels.
       
    60 @param	aVideoLevel	Indicates the H263 video level.
       
    61 @param	aProfile	Indicates the H263 profile.
       
    62 */
       
    63 EXPORT_C T3GPVideoPropertiesH263::T3GPVideoPropertiesH263(TUint aTimescale, const TSize& aSize,
       
    64 		TInt aVideoLevel, TProfile aProfile) :
       
    65 T3GPVideoPropertiesBase((aProfile == EProfile0) ? E3GPH263Profile0 : E3GPH263Profile3,
       
    66 		aTimescale, aSize), iVideoLevel(aVideoLevel)
       
    67 	{
       
    68 	}
       
    69 
       
    70 /**
       
    71 This structure stores the common and AVC specific properties of video data.
       
    72  
       
    73 @param	aTimescale				Timescale of the video data.  This is the number of time units that 
       
    74 								pass in one second.
       
    75 @param	aSize					Video width and height in pixels.
       
    76 @param	aDecoderSpecificInfo	AVCDecoderConfigurationRecord data that will be stored in the avcC atom.
       
    77 */
       
    78 EXPORT_C T3GPVideoPropertiesAvc::T3GPVideoPropertiesAvc(TUint aTimescale, const TSize& aSize,
       
    79 		const TDesC8& aDecoderSpecificInfo) :
       
    80 T3GPVideoPropertiesBase(E3GPAvcProfileBaseline, aTimescale, aSize),
       
    81 iDecoderSpecificInfo(aDecoderSpecificInfo)
       
    82 	{
       
    83 	/*
       
    84 		NOTE: Although Baseline profile is being set here, it's just used to indicate
       
    85 		the fact that we have AVC data. The underlying 3GP lib does not differentiate
       
    86 		between profiles when composing a file. It simply writes the contents of
       
    87 		iDecoderSpecificInfo (which contains the profile amongst other things)
       
    88 		verbatim into the "avcC" box.
       
    89 	*/
       
    90 	}
       
    91 
       
    92 // This is audio base class containing common audio properties.
       
    93 T3GPAudioPropertiesBase::T3GPAudioPropertiesBase(T3GPAudioType aType,
       
    94 		TUint aTimescale, TInt aFramesPerSample) :
       
    95 		iType(aType), iTimescale(aTimescale), iFramesPerSample(aFramesPerSample)
       
    96 	{
       
    97 	__ASSERT_ALWAYS((aTimescale > 0) && (aTimescale <= KMaxTUint16), User::Panic(K3GPComposePanicName, KErrOverflow));		
       
    98 	}
       
    99 
       
   100 /**
       
   101 This structure stores the common and MPEG-4 audio-specific properties of audio data.
       
   102  
       
   103 @param	aTimescale			Timescale of the audio data.  This is the number of time units that pass in one 
       
   104  							second. It must be smaller than 65536.
       
   105 @param	aDecoderSpecificInfo MPEG-4 audio DecoderSpecificInfo data stored in an ESDS atom.
       
   106 */
       
   107 EXPORT_C T3GPAudioPropertiesMpeg4Audio::T3GPAudioPropertiesMpeg4Audio(TUint aTimescale,
       
   108 		const TDesC8& aDecoderSpecificInfo) :
       
   109 		T3GPAudioPropertiesBase(E3GPMpeg4Audio, aTimescale, 0), 
       
   110 		iDecoderSpecificInfo(aDecoderSpecificInfo)
       
   111 	{
       
   112 	}
       
   113 
       
   114 /**
       
   115 This structure stores the common and AMR-specific properties of audio data. 
       
   116  
       
   117 @param	aTimescale			Timescale of the audio data.  This is the number of time units that pass in one 
       
   118  							second. It must be smaller than 65536.
       
   119 @param	aFramesPerSample	Frames per sample.  It must be smaller than 256.
       
   120  							MPEG-4 audio has a fixed value of 1.
       
   121 @param	aModeSet			AMR mode set.
       
   122 @param	aCodec				AMR Speech Codec.
       
   123 */
       
   124 EXPORT_C T3GPAudioPropertiesAmr::T3GPAudioPropertiesAmr(TUint aTimescale, TInt aFramesPerSample,
       
   125 		TInt aModeSet, TSpeechCodec aCodec) :
       
   126 		T3GPAudioPropertiesBase((aCodec == EAmrNB) ? E3GPAmrNB : E3GPAmrWB, 
       
   127 		aTimescale, aFramesPerSample), iModeSet(aModeSet)
       
   128 	{	
       
   129 	__ASSERT_ALWAYS((aFramesPerSample > 0) && (aFramesPerSample <= KMaxTUint8), 
       
   130 					User::Panic(K3GPComposePanicName, KErrOverflow));	
       
   131 	}
       
   132 
       
   133 /**
       
   134 This structure stores the common and QCELP-specific properties of MPEG4 audio data. The storage mode is 
       
   135 automatically set to MPEG4 Audio Sample Description Box mode.
       
   136  
       
   137 @param	aTimescale			Timescale of the audio data.  This is the number of time units that pass in one 
       
   138  							second. It must be smaller than 65536.
       
   139 @param	aFramesPerSample	Frames per sample.  It must be smaller than 512.
       
   140  							MPEG-4 audio has a fixed value of 1.
       
   141 @param	aDecoderSpecificInfo MPEG-4 audio decoder specific information data stored in an ESDS atom.
       
   142 */
       
   143 EXPORT_C T3GPAudioPropertiesQcelp::T3GPAudioPropertiesQcelp(TUint aTimescale, TInt aFramesPerSample,
       
   144 		const TDesC8& aDecoderSpecificInfo) :
       
   145 		T3GPAudioPropertiesBase(E3GPQcelp13K, aTimescale, aFramesPerSample),
       
   146 		iMode(E3GPMP4AudioDescriptionBox),
       
   147 		iDecoderSpecificInfo(aDecoderSpecificInfo)
       
   148 	{
       
   149 	__ASSERT_ALWAYS((aFramesPerSample > 0) && (aFramesPerSample <= KMaxTUint8), 
       
   150 					User::Panic(K3GPComposePanicName, KErrOverflow));		
       
   151 	}
       
   152 
       
   153 /**
       
   154 This structure stores the common and QCELP-specific properties of audio data.  
       
   155  
       
   156 @param	aTimescale			Timescale of the audio data.  This is the number of time units that pass in one 
       
   157  							second. It must be smaller than 65536.
       
   158 @param	aFramesPerSample	Frames per sample.  It must be smaller than 512.
       
   159  							MPEG-4 audio has a fixed value of 1.
       
   160 */
       
   161 
       
   162 EXPORT_C T3GPAudioPropertiesQcelp::T3GPAudioPropertiesQcelp(TUint aTimescale, TInt aFramesPerSample) :
       
   163 		T3GPAudioPropertiesBase(E3GPQcelp13K, aTimescale, aFramesPerSample),
       
   164 		iMode(E3GPQcelpSampleEntryBox),
       
   165 		iDecoderSpecificInfo(KNullDesC8)
       
   166 	{
       
   167 	__ASSERT_ALWAYS((aFramesPerSample > 0) && (aFramesPerSample <= KMaxTUint8), 
       
   168 					User::Panic(K3GPComposePanicName, KErrOverflow));		
       
   169 	}
       
   170 
       
   171 /** 
       
   172 Create an instance of 3GP composer using default buffer count and size.
       
   173 
       
   174 The default values for buffer count and size are as follow:
       
   175 Write Buffer Size is 2048 
       
   176 Write Buffer Max Count is 15
       
   177 
       
   178 @return A pointer to the newly created 3gp compose object.
       
   179 
       
   180 @leave	KErrGeneral		General error.
       
   181 @leave	KErrNoMemory	Out of memory.
       
   182 
       
   183 @panic	C3GPCompose	KErrAbort	if clients do not a CActiveScheduler installed already.
       
   184 */
       
   185 EXPORT_C C3GPCompose* C3GPCompose::NewL()
       
   186 	{
       
   187 	// Leave if no scheduler exists
       
   188 	__ASSERT_ALWAYS ((CActiveScheduler::Current() != NULL), Panic(KErrAbort));
       
   189 	C3GPCompose* self = new (ELeave) C3GPCompose(); 
       
   190 	return self;
       
   191 	}
       
   192 
       
   193 /** 
       
   194 Create an instance of 3GP composer, and let the user set a count limit and size of 
       
   195 internal buffer for composition.
       
   196 
       
   197 The default values for buffer count and size are as follow:
       
   198  Write Buffer Size is 2048 
       
   199  Write Buffer Max Count is 15
       
   200 
       
   201 An increase of the buffer count and size will lead to a decrease of file I/O activities, thereby, 
       
   202 improves the performance of the 3GP Composer at the expense of higher memory usage.
       
   203 
       
   204 @param	aMediaWriteBufferSize Size of media data file output buffer (in bytes).
       
   205 @param	aWriteBufferMaxCount	Maximum number of buffers (both media and meta) allowed before file 
       
   206  								output changes to synchronous (by default file writing is asynchronous 
       
   207  								operation).  A minimum value of 6 is enforced.
       
   208 
       
   209 @return A pointer to the newly created 3gp compose object.
       
   210 
       
   211 @leave	KErrGeneral		General error.
       
   212 @leave	KErrNoMemory	Out of memory.
       
   213 
       
   214 @panic	C3GPCompose	KErrAbort	if clients do not a CActiveScheduler installed already.
       
   215 @panic	C3GPCompose	KErrArgument	if Write Buffer Size is less or equal to 0 or Write Buffer Max Count is
       
   216 									less than 6.
       
   217  */
       
   218 EXPORT_C C3GPCompose* C3GPCompose::NewL(TInt aMediaWriteBufferSize, TInt aWriteBufferMaxCount)
       
   219 	{
       
   220 	__ASSERT_ALWAYS ((aMediaWriteBufferSize > 0 && aWriteBufferMaxCount >= KMinWriteBufferMaxCount), 
       
   221 					Panic(KErrArgument));
       
   222 	// Leave if no scheduler exists
       
   223 	__ASSERT_ALWAYS ((CActiveScheduler::Current() != NULL), Panic(KErrAbort));
       
   224 	
       
   225 	C3GPCompose* self = new (ELeave) C3GPCompose(aMediaWriteBufferSize, aWriteBufferMaxCount);
       
   226 	return self;
       
   227 	}
       
   228 
       
   229 // First phase constructor
       
   230 C3GPCompose::C3GPCompose(TInt aMediaWriteBufferSize, TInt aWriteBufferMaxCount) :
       
   231 		iMediaWriteBufferSize(aMediaWriteBufferSize), 
       
   232 		iWriteBufferMaxCount(aWriteBufferMaxCount),
       
   233 		iDuplicateFileHandleCreated(EFalse)
       
   234 	{
       
   235 	}
       
   236 
       
   237 /** 
       
   238 This function initialises the 3GP composer for writing 3GP/3G2/MP4 data into a file.
       
   239 Any combination of one video and one audio type is acceptable.  
       
   240 
       
   241 Note: Ownership of aVideo and aAudio remains with the caller.  Both aVideo and aAudio are ready for 
       
   242 deletion after C3GPCompose::Open returns.
       
   243 
       
   244 @param	aFileFormat	Specifies the file format in which the data will be created.  Refer to 
       
   245  					T3GPFileFormatType for supported file format types.
       
   246 @param 	aVideo 		Specifies the video stream to be used for video data.  The input data given will 
       
   247  					be inserted into 3GP file headers and is ready to be disposed when 
       
   248  					C3GPCompose::Open returns. See Video Properties Classes.
       
   249  					If aVideo is NULL, audio-only file will be composed.
       
   250 @param 	aAudio 		Specifies the audio stream to be used for audio data.  The input data given will 
       
   251  					be inserted into 3GP file headers and is ready to be disposed when 
       
   252  					C3GPCompose::Open returns. See Audio Properties Classes.
       
   253  					If aAudio is NULL, video-only file will be composed.
       
   254 @param	aFilename  	A full path name of the file to save the data to.  An empty path is not allowed.
       
   255 @param	aFlags		Optional flags for composing preferences.  Refer to T3GPComposeFlag for supported flags.
       
   256  					The combined use of flags is acceptable.  For example:
       
   257  					E3GPLongClip | E3GPMetaDataLast 
       
   258 
       
   259 @return KErrNone		if successful. Otherwise, returns one of the system wide error codes.
       
   260  		KErrGeneral		if an error has no specific categorisation;
       
   261   		KErrNoMemory	if an attempt to allocate memory has failed;
       
   262   		KErrArgument	if neither video nor audio stream is specified;  
       
   263   		KErrAccessDenied	if opening file has failed;
       
   264   		KErrUnderflow	if the file name length is not greater than 0;
       
   265   		KErrInUse		if the composer is currently engaged; C3GPCompose::Complete must be called to 
       
   266   		 		 		finish the current composition before the composer can be re-initialised again.
       
   267 */
       
   268 EXPORT_C TInt C3GPCompose::Open(T3GPFileFormatType aFileFormat,
       
   269 		const T3GPVideoPropertiesBase* aVideo,
       
   270 		const T3GPAudioPropertiesBase* aAudio,
       
   271 		const TDesC& aFilename,
       
   272 		TUint aFlags)
       
   273 	{
       
   274 	if (iHandler)
       
   275 		{
       
   276 		return KErrInUse;
       
   277 		}
       
   278 	if (aFilename.Length() <= 0)
       
   279 		{
       
   280 		return KErrUnderflow;
       
   281 		}
       
   282 	if (!aVideo && !aAudio)
       
   283 		{
       
   284 		// if neither video nor audio is supplied
       
   285 		return KErrArgument;
       
   286 		}
       
   287 	
       
   288 	// Create a zero terminated version of the file name
       
   289 	RBuf fileName;	
       
   290 	TInt err = fileName.Create(aFilename.Length() + 1);
       
   291 	if (err == KErrNone)
       
   292 		{
       
   293 		fileName.Copy(aFilename);
       
   294 		mp4_u16* mp4FileName = const_cast<mp4_u16*>(fileName.PtrZ());
       
   295 		MP4Err mp4Err = MP4ComposeOpen(&iHandler, reinterpret_cast<MP4FileName>(mp4FileName), Mp4Type(aVideo, aAudio));
       
   296 		
       
   297 		if (mp4Err == MP4_OK)
       
   298 			{
       
   299 			// Write audio and video properties to the 3GP file 
       
   300 			err = SetComposeProperties(aVideo, aAudio, aFileFormat, aFlags);
       
   301 			if (err != KErrNone)
       
   302 				{
       
   303 				Complete(); // Ingore the error
       
   304 				}
       
   305 			}
       
   306 		else
       
   307 			{
       
   308 			err = SymbianOSError(mp4Err);
       
   309 			}
       
   310 		}
       
   311 	fileName.Close();
       
   312 	return err;
       
   313 	}
       
   314 
       
   315 /**
       
   316 This function initialises the 3GP composer for writing 3GP/3G2/MP4 data into a file.
       
   317 Any combination of one video and one audio type is acceptable.  
       
   318 
       
   319 Note: E3GPMetaDataLast will be defaulted in aFlags if file handle is used for the initialisation 
       
   320 of the 3GP composer.
       
   321 
       
   322 Note: Ownership of aVideo and aAudio remains with the caller.  Both aVideo and aAudio are ready for 
       
   323 deletion after C3GPCompose::Open returns.
       
   324 
       
   325 @param  aFileFormat Specifies the file format in which the data will be created.  Refer to 
       
   326                     T3GPFileFormatType for supported file format types.
       
   327 @param  aVideo      Specifies the video stream to be used for video data.  The input data given will 
       
   328                     be inserted into 3GP file headers and is ready to be disposed when 
       
   329                     C3GPCompose::Open returns. See Video Properties Classes.
       
   330                     If aVideo is NULL, audio-only file will be composed.
       
   331 @param  aAudio      Specifies the audio stream to be used for audio data.  The input data given will 
       
   332                     be inserted into 3GP file headers and is ready to be disposed when 
       
   333                     C3GPCompose::Open returns. See Audio Properties Classes.
       
   334                     If aAudio is NULL, video-only file will be composed.
       
   335 @param  aFile       File handle of the file to save the data to.  E3GPMetaDataLast needs to be set for 
       
   336                     aFlags when this is used.
       
   337 @param  aFlags      Optional flags for composing preferences.  Refer to T3GPComposeFlag for supported flags.
       
   338                     The combined use of flags is acceptable.  For example:
       
   339                     E3GPLongClip | E3GPMetaDataLast 
       
   340 
       
   341 @return KErrNone        if successful. Otherwise, returns one of the system wide error codes.
       
   342         KErrGeneral     if an error has no specific categorisation;
       
   343         KErrNoMemory    if an attempt to allocate memory has failed;
       
   344         KErrArgument    if neither video nor audio stream is specified;         
       
   345         KErrAccessDenied    if opening file has failed;
       
   346         KErrInUse   if the composer is currently engaged; C3GPCompose::Complete must be called to 
       
   347                         finish the current composition before the composer can be re-initialised again.
       
   348 */
       
   349 
       
   350 EXPORT_C TInt C3GPCompose::Open(T3GPFileFormatType aFileFormat,
       
   351 		const T3GPVideoPropertiesBase* aVideo,
       
   352 		const T3GPAudioPropertiesBase* aAudio,
       
   353 		RFile& aFile,
       
   354 		TUint aFlags)
       
   355 	{
       
   356 	TInt err = KErrNone;
       
   357 	if (!iDuplicateFileHandleCreated)
       
   358 		{
       
   359 		iDuplicateFileHandleCreated = ETrue;
       
   360 		iFile.Close();
       
   361 		err = iFile.Duplicate(aFile);
       
   362 		if (err != KErrNone)
       
   363 			{
       
   364 			return err;
       
   365 			}
       
   366 		}
       
   367 
       
   368 	return Open(aFileFormat, aVideo, aAudio, iFile, aFlags);
       
   369 	}
       
   370 
       
   371 /**
       
   372 This function initialises the 3GP composer for writing 3GP/3G2/MP4 data into a file.
       
   373 Any combination of one video and one audio type is acceptable.  
       
   374 
       
   375 Note: E3GPMetaDataLast will be defaulted in aFlags if file handle is used for the initialisation 
       
   376 of the 3GP composer.
       
   377 
       
   378 Note: Ownership of aVideo and aAudio remains with the caller.  Both aVideo and aAudio are ready for 
       
   379 deletion after C3GPCompose::Open returns.
       
   380 
       
   381 @param	aFileFormat Specifies the file format in which the data will be created.  Refer to 
       
   382  					T3GPFileFormatType for supported file format types.
       
   383 @param 	aVideo 		Specifies the video stream to be used for video data.  The input data given will 
       
   384  					be inserted into 3GP file headers and is ready to be disposed when 
       
   385  					C3GPCompose::Open returns. See Video Properties Classes.
       
   386  					If aVideo is NULL, audio-only file will be composed.
       
   387 @param 	aAudio 		Specifies the audio stream to be used for audio data.  The input data given will 
       
   388  					be inserted into 3GP file headers and is ready to be disposed when 
       
   389  					C3GPCompose::Open returns. See Audio Properties Classes.
       
   390  					If aAudio is NULL, video-only file will be composed.
       
   391 @param	aFile  		File handle of the file to save the data to.  E3GPMetaDataLast needs to be set for 
       
   392  					aFlags when this is used.
       
   393 @param	aFlags  	Optional flags for composing preferences.  Refer to T3GPComposeFlag for supported flags.
       
   394  					The combined use of flags is acceptable.  For example:
       
   395  					E3GPLongClip | E3GPMetaDataLast 
       
   396 
       
   397 @return KErrNone		if successful. Otherwise, returns one of the system wide error codes.
       
   398  		KErrGeneral		if an error has no specific categorisation;
       
   399   		KErrNoMemory	if an attempt to allocate memory has failed;
       
   400   		KErrArgument	if neither video nor audio stream is specified;    		
       
   401   		KErrAccessDenied	if opening file has failed;
       
   402   		KErrInUse	if the composer is currently engaged; C3GPCompose::Complete must be called to 
       
   403   		 		 		finish the current composition before the composer can be re-initialised again.
       
   404 */
       
   405 EXPORT_C TInt C3GPCompose::Open(T3GPFileFormatType aFileFormat,
       
   406 		const T3GPVideoPropertiesBase* aVideo,
       
   407 		const T3GPAudioPropertiesBase* aAudio,
       
   408 		RFile64& aFile,
       
   409 		TUint aFlags)
       
   410 	{
       
   411 	if (iHandler)
       
   412 		{
       
   413 		return KErrInUse;
       
   414 		}
       
   415 	if (!aVideo && !aAudio)
       
   416 		{
       
   417 		// if neither video nor audio is supplied
       
   418 		return KErrArgument;
       
   419 		}
       
   420 	
       
   421 	TInt driveNumber = EDriveA;
       
   422 	TDriveInfo driveInfo;
       
   423 	TInt err = aFile.Drive(driveNumber, driveInfo);
       
   424 	if (err == KErrNone)
       
   425 		{
       
   426 		MP4Err mp4Err = MP4ComposeOpenFileHandle64(&iHandler, &aFile, static_cast<TDriveNumber>(driveNumber), Mp4Type(aVideo, aAudio));
       
   427 		if (mp4Err == MP4_OK)
       
   428 			{			
       
   429 			// Write audio and video properties to the 3GP file 
       
   430 			err = SetComposeProperties(aVideo, aAudio, aFileFormat, aFlags);
       
   431 			if (err != KErrNone)
       
   432 				{
       
   433 				Complete(); // Ingore the error
       
   434 				}
       
   435 			}
       
   436 		else
       
   437 			{
       
   438 			err = SymbianOSError(mp4Err);
       
   439 			}
       
   440 		}
       
   441 
       
   442 	return err;
       
   443 	}
       
   444 
       
   445 /**
       
   446 Destructor
       
   447 Deletes all objects and releases all resource owned by this instance.
       
   448 */
       
   449 EXPORT_C C3GPCompose::~C3GPCompose()
       
   450 	{
       
   451 	Complete(); // Ignore the error
       
   452 	}
       
   453 
       
   454 /**
       
   455 This function completes the composing operation. It frees the memory allocated by the library instance 
       
   456 and closes the output file.
       
   457 
       
   458 It is necessary to call this function before the output file is guaranteed to be a valid output file 
       
   459 even though the file may exist prior to the call.
       
   460 
       
   461 The composer can be reused again after this call, following another call to C3GPCompose::Open to 
       
   462 re-initialise the composer. 
       
   463 
       
   464 If C3GPCompose::Complete is called before the composer is initialised, it will be ignored and KErrNone 
       
   465 is returned.
       
   466 
       
   467 Although during destruction of C3GPCompose, this function will be automatically called, and no error 
       
   468 code will be returned.  Therefore, when destroying the Composer object that you have used to compose a 
       
   469 file, you should ensure that data is committed to the file by invoking C3GPCompose::Complete before 
       
   470 destroying the Composer object.
       
   471 
       
   472 @return KErrNone		if successful. Otherwise, returns one of the system wide error codes.
       
   473  		KErrGeneral		if an error has no specific categorisation;
       
   474  		KErrWrite		if metadata could not be written.
       
   475 */
       
   476 EXPORT_C TInt C3GPCompose::Complete()
       
   477 	{
       
   478 	MP4Err mp4Err = MP4_OK;
       
   479 	if (iHandler)
       
   480 		{
       
   481 		mp4Err = MP4ComposeClose(iHandler);
       
   482 		}
       
   483 	// Always reset the class member data even this function returns error
       
   484 	Reset();
       
   485 	return SymbianOSError(mp4Err);
       
   486 	}
       
   487 
       
   488 // Helper function to reset class member data.
       
   489 void C3GPCompose::Reset()
       
   490 	{
       
   491 	iHasVideo = EFalse;
       
   492 	iHasAudio = EFalse;
       
   493 	iHandler = NULL;
       
   494 	iFile.Close();
       
   495 	}
       
   496 
       
   497 /**
       
   498 This function writes one video frame to the output file or buffer.
       
   499 
       
   500 The frames must be inserted according to their causal sequence.  Because the library doesn't analyze 
       
   501 the video bit stream, frames are inserted into the 3GP file in the same order as they are entered 
       
   502 with this function.  Therefore, the frames will not be retrieved from the resulting 3GP file or 
       
   503 buffer correctly if they are not in proper order.
       
   504 
       
   505 A frame inserted with this function call will result in one 3GP sample and one 3GP chunk.
       
   506 
       
   507 The current frame's dependency information which is using default values (E3GPDependencyUnknown & 
       
   508 E3GPRedundancyUnknown) is inserted.
       
   509 
       
   510 The data is available in the output file only after calling C3GPCompose::Complete. C3GPCompose::Complete 
       
   511 should be called exactly once when all audio and video data has been inserted into the library.
       
   512 
       
   513 @param	aBuffer		The descriptor containing the video frame data to be written.
       
   514 @param	aDuration	Duration of video frame in timescale, see T3GPVideoPropertiesBase.
       
   515 @param	aKeyFrame	ETrue to indicate whether this frame is a key frame.  EFalse otherwise.
       
   516 
       
   517 @return	KErrNone		if successful. Otherwise, returns one of the system wide error codes.
       
   518  		KErrGeneral		if an error has no specific categorisation;
       
   519  		KErrNotSupported if the composer is setup for an audio-only file;
       
   520  		KErrUnderflow	if the supplied video frame buffer data is empty;
       
   521  		KErrNotReady	if the composer has not yet been initialised;  See C3GPCompose::Open.
       
   522 */
       
   523 EXPORT_C TInt C3GPCompose::WriteVideoFrame(const TDesC8& aBuffer, TUint aDuration, TBool aKeyFrame)
       
   524 	{
       
   525 	if (!iHandler)
       
   526 		{
       
   527 		return KErrNotReady;
       
   528 		}
       
   529 	if (aBuffer.Length() <= 0)
       
   530 		{
       
   531 		return KErrUnderflow;
       
   532 		}
       
   533 	if (!iHasVideo)
       
   534 		{
       
   535 		return KErrNotSupported;
       
   536 		}
       
   537 
       
   538 	// Insert video frame data
       
   539 	mp4_bool keyFrame = aKeyFrame;
       
   540 	mp4_u32 duration = aDuration;
       
   541 	MP4Err mp4Err = MP4ComposeWriteVideoFrame(iHandler, const_cast<mp4_u8*>(aBuffer.Ptr()), aBuffer.Length(), duration, keyFrame);
       
   542 	
       
   543 	return SymbianOSError(mp4Err);
       
   544 	}
       
   545 
       
   546 /**
       
   547 This function sets the current frame's dependency information to SDTP box and writes one video frame 
       
   548 to the output file.
       
   549 
       
   550 The frames must be inserted according to their causal sequence.  Because the library doesn't analyze 
       
   551 the video bit stream, frames are inserted into the 3GP file in the same order as they are entered 
       
   552 with this function.  Therefore, the frames will not be retrieved from the resulting 3GP file or 
       
   553 buffer correctly if they are not in proper order.
       
   554 
       
   555 A frame inserted with this function call will result in one 3GP sample and one 3GP chunk.
       
   556 
       
   557 The data is available in the output file only after calling C3GPCompose::Complete. C3GPCompose::Complete 
       
   558 should be called exactly once when all audio and video data has been inserted into the library.
       
   559 
       
   560 @param	aBuffer		The descriptor containing the video frame data to be written.
       
   561 @param	aDuration	Duration of video frame in timescale, see T3GPVideoPropertiesBase.
       
   562 @param	aKeyFrame	ETrue to indicate whether this frame is a key frame.  EFalse otherwise.
       
   563 @param	aDependencies   This specifies the current frame's dependency information.  
       
   564 					The information will be supplied into the SDTP box.
       
   565  					See T3GPFrameDependencies.
       
   566 
       
   567 @return	KErrNone		if successful. Otherwise, returns one of the system wide error codes.
       
   568  		KErrGeneral		if an error has no specific categorisation;
       
   569  		KErrNotSupported if the composer is setup for an audio-only file;
       
   570  		KErrUnderflow	if the supplied video frame buffer data is empty;
       
   571  		KErrNotReady	if the composer has not yet been initialised;  See C3GPCompose::Open.
       
   572 */
       
   573 EXPORT_C TInt C3GPCompose::WriteVideoFrame(const TDesC8& aBuffer, TUint aDuration, TBool aKeyFrame,
       
   574 		const T3GPFrameDependencies& aDependencies)
       
   575 	{
       
   576 	if (!iHandler)
       
   577 		{
       
   578 		return KErrNotReady;
       
   579 		}
       
   580 	if (aBuffer.Length() <= 0)
       
   581 		{
       
   582 		return KErrUnderflow;
       
   583 		}
       
   584 	if (!iHasVideo)
       
   585 		{
       
   586 		return KErrNotSupported;
       
   587 		}
       
   588 
       
   589 	// Insert the current frame's dependency information
       
   590 	MP4Err mp4Err = MP4ComposeWriteNextVideoFrameDependencies(iHandler, aDependencies.iDependsOn,
       
   591 			aDependencies.iIsDependedOn, aDependencies.iHasRedundancy);
       
   592 
       
   593 	if (mp4Err == MP4_OK)
       
   594 		{
       
   595 		// Insert video frame data
       
   596 		mp4_bool keyFrame = aKeyFrame;
       
   597 		mp4_u32 duration = aDuration;
       
   598 		mp4Err = MP4ComposeWriteVideoFrame(iHandler, const_cast<mp4_u8*>(aBuffer.Ptr()), 
       
   599 				aBuffer.Length(), duration, keyFrame);
       
   600 		}
       
   601 
       
   602 	return SymbianOSError(mp4Err);
       
   603 	}
       
   604 
       
   605 /**
       
   606 This function writes audio frames into the output file or buffer.  The data is available in the 
       
   607 3GP output file only after calling C3GPCompose::Complete.  C3GPCompose::Complete should be called exactly 
       
   608 once when all audio and video data has been inserted into the library.
       
   609 
       
   610 For MPEG-4 audio:
       
   611 This function writes one MPEG audio frame to the 3GP file. 
       
   612 
       
   613 For other audio types:
       
   614 This function writes a number of audio frames to the 3GP file specified during composer setup 
       
   615 in the input parameter aAudio when calling C3GPCompose::Open.  All audio frames inserted with 
       
   616 one function call will be placed inside one sample in the resulting file.
       
   617 
       
   618 Note: Only the last call can have a different number of frames if the number is less than 
       
   619 the number of frames per sample specified during composer setup.
       
   620 
       
   621 @see T3GPAudioPropertiesAmr
       
   622 @see T3GPAudioPropertiesQcelp  		
       
   623 
       
   624 @param	aBuffer			The descriptor containing the audio data to be written.
       
   625 @param	aDuration		Duration of audio frames in timescale, see T3GPAudioPropertiesBase
       
   626 
       
   627 @return	KErrNone		if successful.  Otherwise, returns one of the system wide error codes.
       
   628  		KErrGeneral		if an error has no specific categorisation;
       
   629  		KErrNotSupported if the composer is setup for a video-only file;
       
   630  		KErrUnderflow	if the supplied audio frames buffer data is empty;
       
   631  		KErrNotReady	if the composer has not yet been initialised;  See C3GPCompose::Open.
       
   632 */
       
   633 EXPORT_C TInt C3GPCompose::WriteAudioFrames(const TDesC8& aBuffer, TUint aDuration)
       
   634 	{
       
   635 	if (!iHandler)
       
   636 		{
       
   637 		return KErrNotReady;
       
   638 		}
       
   639 	if (aBuffer.Length() <= 0)
       
   640 		{
       
   641 		return KErrUnderflow;
       
   642 		}
       
   643 	if (!iHasAudio)
       
   644 		{
       
   645 		return KErrNotSupported;
       
   646 		}
       
   647 
       
   648 	mp4_u32 duration = aDuration;
       
   649     // use 0 for the number of frames since it is being ignored within the mp4 library implementation
       
   650 	MP4Err mp4Err = MP4ComposeWriteAudioFrames(iHandler, const_cast<mp4_u8*>(aBuffer.Ptr()), 
       
   651 			aBuffer.Length(), 0, duration);
       
   652 	
       
   653 	return SymbianOSError(mp4Err);
       
   654 	}
       
   655 
       
   656 /**
       
   657 Writes a buffer containing whole atom to inside of user data atom (UDTA) defined in aLocation.
       
   658 
       
   659 The buffer should contain an atom of structure that conforms to the definition of a "full box" 
       
   660 as specified in ISO/IEC 14496-12:2003: "Information technology – Coding of audio-visual objects
       
   661  – Part 12: ISO base media file format."
       
   662  
       
   663 For more information on user data atoms, see Section 8 – Asset Information of "3GPP TS 26.244 
       
   664 version 6.1.0 – 3GP file format (Rel 6)."
       
   665 
       
   666 @param	aLocation	Specifies the location of user information to be written.  Refer to 
       
   667  					T3GPUdtaLocation for possible values.
       
   668 @param	aBuffer		The descriptor containing the user information to write into file.
       
   669 
       
   670 @return	KErrNone		if successful.  Otherwise, returns one of the system wide error codes.
       
   671  		KErrGeneral		if an error has no specific categorisation;
       
   672  		KErrArgument	if asked aLocation is invalid;
       
   673  		KErrUnderflow	if the supplied buffer data is empty;
       
   674  		KErrNotSupported	if specify video track user data but no video type is specified, 
       
   675  						or specify audio track user data but no audio type is specified
       
   676  		KErrNoMemory	if an attempt to allocate memory has failed;
       
   677  		KErrNotReady	if the composer has not yet been initialised;  See C3GPCompose::Open.
       
   678  		
       
   679 @panic	C3GPCompose	KErrArgument if the location of user information is not of T3GPUdtaLocation. 
       
   680 */
       
   681 EXPORT_C TInt C3GPCompose::SetUserData(T3GPUdtaLocation aLocation, const TDesC8& aBuffer)
       
   682 	{
       
   683 	if (!iHandler)
       
   684 		{
       
   685 		return KErrNotReady;
       
   686 		}
       
   687 	if (aBuffer.Length() <= 0)
       
   688 		{
       
   689 		return KErrUnderflow;
       
   690 		}
       
   691 	if ((!iHasAudio && aLocation == E3GPUdtaAudioTrak) || (!iHasVideo && aLocation == E3GPUdtaVideoTrak))
       
   692 		{
       
   693 		return KErrNotSupported;
       
   694 		}
       
   695 	
       
   696 	mp4_u8 location;
       
   697 	switch (aLocation)
       
   698 		{
       
   699 		case (E3GPUdtaMoov):
       
   700 			location = MP4_UDTA_MOOV;
       
   701 		break;
       
   702 		case (E3GPUdtaVideoTrak):
       
   703 			location = MP4_UDTA_VIDEOTRAK;
       
   704 		break;
       
   705 		case (E3GPUdtaAudioTrak):
       
   706 			location = MP4_UDTA_AUDIOTRAK;
       
   707 		break;
       
   708 		default:
       
   709 			Panic(KErrArgument);
       
   710 		break;
       
   711 		}
       
   712 
       
   713 	mp4_u32 bufferSize = aBuffer.Length();
       
   714 	MP4Err mp4Err = MP4ComposeSetUserDataAtom(iHandler, location, const_cast<mp4_u8*>(aBuffer.Ptr()), bufferSize);
       
   715 	return SymbianOSError(mp4Err);
       
   716 	}
       
   717 
       
   718 // Helper function to convert 3GP/MP4 library specific error codes to system wide error codes
       
   719 TInt C3GPCompose::SymbianOSError(MP4Err aError)
       
   720 	{
       
   721 	TInt error = KErrNone;
       
   722 
       
   723 	switch (aError)
       
   724 		{
       
   725 		case (MP4_OK):
       
   726 		break;
       
   727 		case (MP4_ERROR):
       
   728 			error = KErrGeneral;
       
   729 		break;
       
   730 		case (MP4_OUT_OF_MEMORY):
       
   731 			error = KErrNoMemory;
       
   732 		break;
       
   733 		case (MP4_FILE_ERROR):
       
   734 			error = KErrAccessDenied;
       
   735 		break;
       
   736 		case (MP4_INVALID_TYPE):
       
   737 			error = KErrArgument;
       
   738 		break;
       
   739 		case (MP4_METADATA_ERROR):
       
   740 			error = KErrWrite;
       
   741 		break;
       
   742 		default:
       
   743 			Panic(KErrArgument);
       
   744 		}
       
   745 	return error;
       
   746 	}
       
   747 
       
   748 // Helper function to map 3GP enum type to MP4 audio and video type
       
   749 mp4_u32 C3GPCompose::Mp4Type(const T3GPVideoPropertiesBase* aVideo, const T3GPAudioPropertiesBase* aAudio)
       
   750 	{
       
   751 	mp4_u32 videoType = MP4_TYPE_NONE;
       
   752 	mp4_u32 audioType = MP4_TYPE_NONE;
       
   753 	
       
   754 	if (aVideo)
       
   755 		{
       
   756 		iHasVideo = ETrue;
       
   757 		switch (aVideo->iType)
       
   758 			{
       
   759 			case (E3GPMpeg4Video):
       
   760 				videoType = MP4_TYPE_MPEG4_VIDEO;
       
   761 			break;
       
   762 			case (E3GPH263Profile0):
       
   763 				videoType = MP4_TYPE_H263_PROFILE_0;
       
   764 			break;
       
   765 			case (E3GPH263Profile3):
       
   766 				videoType = MP4_TYPE_H263_PROFILE_3;
       
   767 			break;
       
   768 			
       
   769 			/*
       
   770 			 * NOTE: The underlying 3GP library does
       
   771 			 * not differentiate between the various AVC
       
   772 			 * profiles when composing.
       
   773 			 * 
       
   774 			 * In all cases it will simply copy the data
       
   775 			 * from the iDecoderSpecificInfo member of
       
   776 			 * T3GPVideoPropertiesAvc into the 'avcC' atom.
       
   777 			 * It does not do any checking of that data, so
       
   778 			 * it is the API user's responsibility to ensure
       
   779 			 * that it contains a valid AVCDecoderConfigurationRecord
       
   780 			 * with the correct AVC profile and level.
       
   781 			 * 
       
   782 			 * An interesting side-effect of this is that you can
       
   783 			 * compose AVC data with arbitrary profiles even if they
       
   784 			 * are not "supported" by this API. For example, as long
       
   785 			 * as the AVCDecoderConfigurationRecord says there is
       
   786 			 * High 10 profile data and the AVC data is of that profile
       
   787 			 * then you will still end up with a valid file.
       
   788 			 */
       
   789 			case (E3GPAvcProfileBaseline):
       
   790 				videoType = MP4_TYPE_AVC_PROFILE_BASELINE;
       
   791 			break;
       
   792             case (E3GPAvcProfileMain):
       
   793                 videoType = MP4_TYPE_AVC_PROFILE_MAIN;
       
   794             break;
       
   795             case (E3GPAvcProfileExtended):
       
   796                 videoType = MP4_TYPE_AVC_PROFILE_EXTENDED;
       
   797             break;
       
   798             case (E3GPAvcProfileHigh):
       
   799                 videoType = MP4_TYPE_AVC_PROFILE_HIGH;
       
   800             break;
       
   801 			default:
       
   802 				Panic(KErrArgument);
       
   803 			}
       
   804 		}
       
   805 
       
   806 	if(aAudio)
       
   807 		{
       
   808 		iHasAudio = ETrue;
       
   809 		switch (aAudio->iType)
       
   810 			{
       
   811 			case (E3GPMpeg4Audio):
       
   812 				audioType = MP4_TYPE_MPEG4_AUDIO;
       
   813 			break;
       
   814 			case (E3GPAmrNB):
       
   815 				audioType = MP4_TYPE_AMR_NB;
       
   816 			break;
       
   817 			case (E3GPAmrWB):
       
   818 				audioType = MP4_TYPE_AMR_WB;
       
   819 			break;
       
   820 			case (E3GPQcelp13K):
       
   821 				audioType = MP4_TYPE_QCELP_13K;
       
   822 			break;
       
   823 			default:
       
   824 				Panic(KErrArgument);
       
   825 			}
       
   826 		}
       
   827 	return (videoType | audioType);
       
   828 	}
       
   829 	
       
   830 // Helper function to set compose properties
       
   831 TInt C3GPCompose::SetComposeProperties(const T3GPVideoPropertiesBase* aVideo,
       
   832 		const T3GPAudioPropertiesBase* aAudio, T3GPFileFormatType aFileFormat, TUint aFlag)
       
   833 	{
       
   834 	mp4_u32 writeBufferSize = iMediaWriteBufferSize;
       
   835 	mp4_u32 writeBufferMaxCount = iWriteBufferMaxCount;
       
   836 	MP4Err mp4Err = MP4SetCustomFileBufferSizes(iHandler, writeBufferSize, writeBufferMaxCount, 0);
       
   837 	if ( mp4Err != MP4_OK)
       
   838 		{
       
   839 		return SymbianOSError(mp4Err);
       
   840 		}
       
   841 	
       
   842 	// Set compose flag before other MP4Compose functions
       
   843 	TInt err = SetComposeFlag(aFileFormat, aFlag);
       
   844 	if (err != KErrNone)
       
   845 		{
       
   846 		return err;
       
   847 		}
       
   848 	
       
   849 	if (aVideo)
       
   850 		{
       
   851 		switch (aVideo->iType)
       
   852 			{
       
   853 			case (E3GPMpeg4Video):
       
   854 				err = SetMPeg4VideoProperties(aVideo);
       
   855 			break;
       
   856 			case (E3GPAvcProfileBaseline):
       
   857             case (E3GPAvcProfileMain):
       
   858             case (E3GPAvcProfileExtended):
       
   859             case (E3GPAvcProfileHigh):
       
   860 				err = SetAvcVideoProperties(aVideo);
       
   861 			break;
       
   862 			case (E3GPH263Profile0):
       
   863 			case (E3GPH263Profile3):
       
   864 				err = SetH263VideoProperties(aVideo);
       
   865 			break;
       
   866 			default:
       
   867 				Panic(KErrArgument);
       
   868 			}
       
   869 		}
       
   870 	if (err != KErrNone)
       
   871 		{
       
   872 		return err;
       
   873 		}
       
   874 
       
   875 	if (aAudio)
       
   876 		{
       
   877 		switch (aAudio->iType)
       
   878 			{
       
   879 			case (E3GPMpeg4Audio):
       
   880 				err = SetMpeg4AudioProperties(aAudio);
       
   881 			break;
       
   882 			case (E3GPQcelp13K):
       
   883 				err = SetQcelpAudioProperties(aAudio);
       
   884 			break;
       
   885 			case (E3GPAmrNB):
       
   886 			case (E3GPAmrWB):
       
   887 				err = SetAmrAudioProperties(aAudio);
       
   888 			break;
       
   889 			default:
       
   890 				Panic(KErrArgument);
       
   891 			}
       
   892 		}
       
   893 	return err;
       
   894 	}
       
   895 
       
   896 // Inform the 3GP library about the MPeg4 video data
       
   897 TInt C3GPCompose::SetMPeg4VideoProperties(const T3GPVideoPropertiesBase* aVideo)
       
   898 	{
       
   899 	const T3GPVideoPropertiesMpeg4Video* mpeg4Video = static_cast<const T3GPVideoPropertiesMpeg4Video*>(aVideo);
       
   900 
       
   901 	MP4Err err = MP4ComposeWriteVideoDecoderSpecificInfo(iHandler, const_cast<mp4_u8*>(mpeg4Video->iDecoderSpecificInfo.Ptr()), 
       
   902 			mpeg4Video->iDecoderSpecificInfo.Length());
       
   903 
       
   904 	if ( err == MP4_OK)
       
   905 		{
       
   906 		err = MP4ComposeAddVideoDescription(iHandler, mpeg4Video->iTimescale,
       
   907 				mpeg4Video->iSize.iWidth, mpeg4Video->iSize.iHeight,
       
   908 				mpeg4Video->iMaxBitRate, mpeg4Video->iAvgBitRate);
       
   909 		}
       
   910 
       
   911 	return SymbianOSError(err);
       
   912 	}
       
   913 
       
   914 // Inform the 3GP library about the AVC video data
       
   915 TInt C3GPCompose::SetAvcVideoProperties(const T3GPVideoPropertiesBase* aVideo)
       
   916 	{
       
   917 	const T3GPVideoPropertiesAvc* avcVideo = static_cast<const T3GPVideoPropertiesAvc*>(aVideo);
       
   918 
       
   919 	MP4Err err = MP4ComposeWriteVideoDecoderSpecificInfo(iHandler, const_cast<mp4_u8*>(avcVideo->iDecoderSpecificInfo.Ptr()), 
       
   920 			avcVideo->iDecoderSpecificInfo.Length ());
       
   921 
       
   922 	if ( err == MP4_OK)
       
   923 		{
       
   924 		// aMaxBitRate and aAvgBitRate are MPEG-4 video specific values.  Set 0 for them
       
   925 		err = MP4ComposeAddVideoDescription(iHandler, avcVideo->iTimescale,
       
   926 				avcVideo->iSize.iWidth, avcVideo->iSize.iHeight, 0, 0);
       
   927 		}
       
   928 
       
   929 	return SymbianOSError(err);
       
   930 	}
       
   931 
       
   932 // Inform the 3GP library about the H263 video data
       
   933 TInt C3GPCompose::SetH263VideoProperties(const T3GPVideoPropertiesBase* aVideo)
       
   934 	{
       
   935 	// aMaxBitRate and aAvgBitRate are MPEG-4 video specific values.  Set 0 for H263 video
       
   936 	MP4Err err = MP4ComposeAddVideoDescription(iHandler, aVideo->iTimescale,
       
   937 			aVideo->iSize.iWidth, aVideo->iSize.iHeight, 0, 0);
       
   938 
       
   939 	if ( err == MP4_OK)
       
   940 		{
       
   941 		const T3GPVideoPropertiesH263* h263Video = static_cast<const T3GPVideoPropertiesH263*>(aVideo);
       
   942 		TVideoClipProperties properties;
       
   943 		properties.iH263Level = h263Video->iVideoLevel;
       
   944 		err = MP4ComposeSetVideoClipProperties(iHandler, properties);
       
   945 		}
       
   946 
       
   947 	return SymbianOSError(err);
       
   948 	}
       
   949 
       
   950 // Inform the 3GP library about the MPeg4 audio data
       
   951 TInt C3GPCompose::SetMpeg4AudioProperties(const T3GPAudioPropertiesBase* aAudio)
       
   952 	{
       
   953 	const T3GPAudioPropertiesMpeg4Audio* mpeg4Audio = static_cast<const T3GPAudioPropertiesMpeg4Audio*>(aAudio);
       
   954 
       
   955 	MP4Err err = MP4ComposeWriteAudioDecoderSpecificInfo(iHandler, const_cast<mp4_u8*>(mpeg4Audio->iDecoderSpecificInfo.Ptr()), 
       
   956 			mpeg4Audio->iDecoderSpecificInfo.Length ());
       
   957 
       
   958 	if ( err == MP4_OK)
       
   959 		{
       
   960 		//modeSet is needed only for AMR audio. Set it to 0 for Mpeg4 audio.
       
   961 		err = MP4ComposeAddAudioDescription(iHandler, mpeg4Audio->iTimescale, mpeg4Audio->iFramesPerSample, 0);
       
   962 		}
       
   963 
       
   964 	return SymbianOSError(err);
       
   965 	}
       
   966 
       
   967 // Inform the 3GP library about the Amr audio data
       
   968 TInt C3GPCompose::SetAmrAudioProperties(const T3GPAudioPropertiesBase* aAudio)
       
   969 	{
       
   970 	const T3GPAudioPropertiesAmr* amrAudio = static_cast<const T3GPAudioPropertiesAmr*>(aAudio);
       
   971 	//modeSet is needed only for AMR audio. 
       
   972 	MP4Err err = MP4ComposeAddAudioDescription(iHandler, amrAudio->iTimescale,
       
   973 			amrAudio->iFramesPerSample, amrAudio->iModeSet);
       
   974 	return SymbianOSError(err);
       
   975 	}
       
   976 
       
   977 // Sets the storage mode of storing 13K QCELP data in a 3G2 file
       
   978 TInt C3GPCompose::SetQcelpAudioProperties(const T3GPAudioPropertiesBase* aAudio)
       
   979 	{
       
   980 	const T3GPAudioPropertiesQcelp* qcelpAudio = static_cast<const T3GPAudioPropertiesQcelp*>(aAudio);
       
   981 	MP4Err err = MP4ComposeSetQCELPStorageMode(iHandler, qcelpAudio->iMode);
       
   982 	if ( err == MP4_OK)
       
   983 		{
       
   984 		if ( qcelpAudio->iMode == E3GPMP4AudioDescriptionBox)
       
   985 			{
       
   986 			err = MP4ComposeWriteAudioDecoderSpecificInfo(iHandler, const_cast<mp4_u8*>(qcelpAudio->iDecoderSpecificInfo.Ptr()), qcelpAudio->iDecoderSpecificInfo.Length ());
       
   987 			}
       
   988 		if ( err == MP4_OK)
       
   989 			{
       
   990 			//modeSet is needed only for AMR audio. Set it to 0 for Qcelp audio.
       
   991 			err = MP4ComposeAddAudioDescription(iHandler, qcelpAudio->iTimescale, qcelpAudio->iFramesPerSample, 0);
       
   992 			}
       
   993 		}
       
   994 
       
   995 	return SymbianOSError(err);
       
   996 	}
       
   997 
       
   998 // Set compose flag
       
   999 TInt C3GPCompose::SetComposeFlag(T3GPFileFormatType aFileFormat, TUint aFlag)
       
  1000 	{
       
  1001 	mp4_u32 fileFormat = 0;
       
  1002 	switch (aFileFormat)
       
  1003 		{
       
  1004 		case (E3GPMP4):
       
  1005 			fileFormat = MP4_FLAG_GENERATE_MP4;
       
  1006 		break;
       
  1007 		case (E3GP3G2):
       
  1008 			fileFormat = MP4_FLAG_GENERATE_3G2;
       
  1009 		break;
       
  1010 		case (E3GP3GP):
       
  1011 			fileFormat = MP4_FLAG_NONE;
       
  1012 		break;
       
  1013 		default:
       
  1014 			Panic(KErrArgument);
       
  1015 		}
       
  1016 
       
  1017 	MP4Err err = MP4ComposeSetFlags(iHandler, aFlag | fileFormat);
       
  1018 	return SymbianOSError(err);
       
  1019 	}
       
  1020 
       
  1021 
       
  1022 void C3GPCompose::Panic(TInt aPanic)
       
  1023 // Panic client
       
  1024 	{
       
  1025 	User::Panic(K3GPComposePanicName, aPanic);
       
  1026 	}