mmplugins/lib3gp/wrapper/src/c3gpparse.cpp
changeset 0 40261b775718
child 11 d5f04de580b7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mmplugins/lib3gp/wrapper/src/c3gpparse.cpp	Tue Feb 02 01:56:55 2010 +0200
@@ -0,0 +1,2159 @@
+// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "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:
+//
+// Description:
+//
+
+#include <c3gplibrary.h>
+
+/**
+Creates an instance of a 3GP Parser for reading 3GP/3G2/MP4 data using default buffer size.
+
+The default value for read buffer size is 8k. 
+
+@return A pointer to the newly created 3gp parse object. 
+
+@leave	KErrNoMemory	Out of memory.
+*/
+EXPORT_C C3GPParse* C3GPParse::NewL()
+	{
+	C3GPParse* self = new (ELeave) C3GPParse();
+	return self;
+	}
+
+/**
+Creates an instance of a 3GP Parser for reading 3GP/3G2/MP4 data, and sets the 
+internal file read buffer size.  
+
+@param	aReadBufferSize	Size of file read buffer.
+
+@return A pointer to the newly created 3gp parse object. 
+
+@leave	KErrNoMemory	Out of memory.
+@leave	KErrGeneral		General error.
+
+@panic	C3GPParse	KErrArgument	if size of file read buffer is not greater than 0.
+*/
+EXPORT_C C3GPParse* C3GPParse::NewL(TInt aReadBufferSize)
+	{
+	__ASSERT_ALWAYS((aReadBufferSize > 0), Panic(KErrArgument));
+	C3GPParse* self = new (ELeave) C3GPParse(aReadBufferSize);
+	return self;
+	}
+
+// First phase constructor
+C3GPParse::C3GPParse(TInt aReadBufferSize) : 
+		iReadBufferSize(aReadBufferSize),
+		iDuplicateFileHandleCreated(EFalse),
+		iVideoType(E3GPNoVideo),
+		iAudioType(E3GPNoAudio)
+	{
+	}
+
+/**
+This function initialises the 3GP Parser for reading 3GP/3G2/MP4 data from a buffer and expects data 
+to be inserted through subsequent calls to C3GPParse::InsertData.  
+
+@see C3GPParse::InsertData
+
+@return	KErrNone 		if successful. Otherwise, returns one of the system wide error codes.
+		KErrGeneral		if an error has no specific categorisation;
+		KErrNoMemory	if an attempt to allocate memory has failed;
+		KErrInUse		if the parser is currently engaged; C3GPParse::Complete must be called to 
+						finish the parsing activities before the parser can be re-initialised again.
+*/	
+EXPORT_C TInt C3GPParse::Open()
+	{
+	if (iHandler)
+		{
+		return KErrInUse;
+		}
+	
+	return SymbianOSError(MP4ParseOpen(&iHandler, NULL));
+	}
+
+/**
+This function initialises the 3GP Parser for reading 3GP/3G2/MP4 data from a file.
+
+@param	aFilename	A full path name of the file containing the data. 
+
+@return	KErrNone 		if successful.  Otherwise, returns one of the system wide error codes.
+		KErrGeneral		if an error has no specific categorisation;
+		KErrNoMemory	if an attempt to allocate memory has failed;
+		KErrAccessDenied	if opening file has failed;
+		KErrUnderflow	if the file name length is not greater than 0;
+		KErrInUse		if the parser is currently engaged;  C3GPParse::Complete must be called to 
+						finish the parsing activities before the parser can be re-initialised again.
+*/	
+EXPORT_C TInt C3GPParse::Open(const TDesC& aFilename)
+	{
+	if (iHandler)
+		{
+		return KErrInUse;
+		}
+	if (aFilename.Length() <= 0)
+		{
+		return KErrUnderflow;
+		}
+	
+	// Create a zero terminated version of the file name
+	RBuf fileName;	
+	TInt err = fileName.Create(aFilename.Length() + 1);
+	if (err == KErrNone)
+		{
+		fileName.Copy(aFilename);
+		mp4_u16* mp4FileName = const_cast<mp4_u16*>(fileName.PtrZ());
+		MP4Err mp4Err = MP4ParseOpen(&iHandler, reinterpret_cast<MP4FileName>(mp4FileName));
+		
+		if (mp4Err == MP4_OK)
+			{
+			// Set composing related values to 0.
+			mp4Err = MP4SetCustomFileBufferSizes(iHandler, 0, 0, iReadBufferSize);
+			if (mp4Err != MP4_OK)
+				{
+				// Ignore the error
+				Complete();
+				}
+			}
+		err = SymbianOSError(mp4Err);
+		}
+	fileName.Close();
+	return err;
+	}
+
+/**
+This function initialises the 3GP Parser for reading 3GP/3G2/MP4 data from a file.
+
+@param  aFile   File handle of the file containing the data.  It is expected to be a valid file handle, 
+                opened and will be closed outside of the library.
+
+@return KErrNone        if successful.  Otherwise, returns one of the system wide error codes.
+        KErrNoMemory    if an attempt to allocate memory has failed;
+        KErrInUse       if the parser is currently engaged;  C3GPParse::Complete must be called to 
+                        finish the parsing activities before the parser can be re-initialised again.
+*/
+EXPORT_C TInt C3GPParse::Open(const RFile& aFile)
+	{
+	TInt err = KErrNone;
+	if (!iDuplicateFileHandleCreated)
+		{
+		iDuplicateFileHandleCreated = ETrue;
+		iFile.Close();
+		err = iFile.Duplicate(aFile);
+		if (err != KErrNone)
+			{
+			return err;
+			}
+		}
+
+	return Open(iFile);
+	}
+/**
+This function initialises the 3GP Parser for reading 3GP/3G2/MP4 data from a file.
+
+@param	aFile	File handle of the file containing the data.  It is expected to be a valid file handle, 
+				opened and will be closed outside of the library.
+
+@return	KErrNone 		if successful.  Otherwise, returns one of the system wide error codes.
+		KErrNoMemory	if an attempt to allocate memory has failed;
+		KErrInUse		if the parser is currently engaged;  C3GPParse::Complete must be called to 
+						finish the parsing activities before the parser can be re-initialised again.
+*/
+EXPORT_C TInt C3GPParse::Open(const RFile64& aFile)
+	{
+	if (iHandler)
+		{
+		return KErrInUse;
+		}
+	
+	const RFile64* file = &aFile;
+	MP4Err mp4Err = MP4ParseOpenFileHandle64(&iHandler, (const_cast<RFile64*>(file)));
+	if (mp4Err == MP4_OK)
+		{
+		// Set composing related values to 0.
+		mp4Err = MP4SetCustomFileBufferSizes(iHandler, 0, 0, iReadBufferSize);
+		if (mp4Err != MP4_OK)
+			{
+			// Ignore the error
+			Complete();
+			}
+		}
+
+	return SymbianOSError(mp4Err);
+	}
+
+/**
+This function initialises the 3GP Parser for reading 3GP/3G2/MP4 data from a CAF object.
+
+@param	aData	A CData object pointing to a CAF object.  It is expected to be opened and will be 
+				closed outside of the library.
+
+@return	KErrNone 		if successful.  Otherwise, returns one of the system wide error codes.
+		KErrNoMemory	if an attempt to allocate memory has failed;
+		KErrInUse		if the parser is currently engaged;  C3GPParse::Complete must be called to 
+						finish the parsing activities before the parser can be re-initialised again.
+*/
+EXPORT_C TInt C3GPParse::Open(const ContentAccess::CData& aData)
+	{
+	if (iHandler)
+		{
+		return KErrInUse;
+		}
+	
+	MP4Err mp4Err = MP4ParseOpenCAF(&iHandler, const_cast<ContentAccess::CData*>(&aData));
+
+	if (mp4Err  == MP4_OK)
+		{
+		// Set composing related values to 0.
+		mp4Err = MP4SetCustomFileBufferSizes(iHandler, 0, 0, iReadBufferSize);
+		if (mp4Err != MP4_OK)
+			{
+			// Ignore the error
+			Complete();
+			}
+		}
+	
+	return SymbianOSError(mp4Err);
+	}
+
+/**
+Destructor. Deletes all objects.
+*/
+EXPORT_C C3GPParse::~C3GPParse()
+	{
+	Complete(); // Ignore the error
+	}
+
+/**
+This function completes the parsing operation.
+
+If C3GPParse::Complete is called before the parse is initialised, it will be ignored and KErrNone is 
+returned.
+
+The parser can be reused again after this call, following another call to C3GPParse::Open to 
+re-initialise the parser. 
+
+@return	KErrNone 		if successful.  Otherwise, returns one of the system wide error codes.
+		KErrGeneral		if an error has no specific categorisation;
+*/
+EXPORT_C TInt C3GPParse::Complete()
+	{
+	MP4Err mp4Err = MP4_OK;
+	if (iHandler)
+		{
+		mp4Err = MP4ParseClose(iHandler);
+		}
+		
+	if (iAsyncReadBuffer)
+		{
+		CancelReadFrame();
+		}
+	
+	// Always reset the class member data even MP4ParseClose returns error
+	Reset();
+	return SymbianOSError(mp4Err);
+	}
+
+// Helper function to reset class member data.
+void C3GPParse::Reset()
+	{
+	iVideoType = E3GPNoVideo;
+	iAudioType = E3GPNoAudio;
+	iAsyncReadBuffer = NULL;
+	iCallback = NULL; // Parse doesn't own the callback. Set it to NULL.
+	iAudioAvgBitRate = 0;
+	iStreamAvgBitRate = 0;
+	iVideoPropertiesSaved = EFalse;
+	iAudioPropertiesSaved = EFalse;
+	iStreamPropertiesSaved = EFalse;
+	iVideoError = KErrNone;
+	iAudioError = KErrNone;
+	iStreamError = KErrNone;
+	iHandler = NULL;
+	iDuplicateFileHandleCreated = EFalse;
+	iFile.Close();
+	}
+
+/**
+This function inserts MP4/3GP/3G2 data into the parser.
+
+It is only necessary to call this function if no parameter has been supplied when 
+C3GPParse::Open is called.  Several functions can return KErr3gpLibMoreDataRequired if the library 
+does not have enough data to return the information that the caller requests. In this case, more data 
+needs to be inserted to the library before calling those functions again.
+
+This function makes a copy of the data inserted into the library so the caller can use the input buffer 
+for other purposes. If the function returns KErrNoMemory, the buffer contents have not been copied into 
+the library and the caller needs to reduce the buffer content before calling again.
+
+If an empty string is supplied for the argument aBuffer, it indicates that there is be no more data 
+to feed through this function.  Such a function call must be done to indicate that all 3GP/MP4/3G2 
+data has been written to the library's internal memory.
+
+@param	aBuffer	The descriptor containing the data to be inserted.
+
+@return	KErrNone 		if successful.  Otherwise, returns one of the system wide error codes.
+		KErrGeneral		if an error has no specific categorisation;
+		KErrNoMemory	if parser cannot allocate enough memory for the data;
+		KErrNotReady	if the parser has not yet been initialised; See C3GPParse::Open.
+*/
+EXPORT_C TInt C3GPParse::InsertData(const TDesC8& aBuffer)
+	{
+	if (!iHandler)
+		{
+		return KErrNotReady;
+		}
+
+	return SymbianOSError(MP4ParseWriteData(iHandler, const_cast<mp4_u8*>(aBuffer.Ptr()), aBuffer.Length()));
+	}
+
+/**
+This function returns the parameters describing the video stream. 
+
+If no file or CAF object is supplied during parser initialisation, this should be called after 
+enough data has been inserted into the library buffers so that the 3GP headers containing the 
+information can be read.
+
+The aFrameRate parameter refers to the frame rate of the original video material.
+
+@param	aType			The type of video stream.  Refer to T3GPVideoType for supported video type.
+@param	aLength			Duration of video in milliseconds.
+@param	aFrameRate		Average frame rate of video (in Hz).
+@param	aAvgBitRate		Average bit rate of video.
+@param	aSize			Width and height of video image measured in pixels.
+@param	aTimeScale		Timescale of video track.  
+
+@return	KErrNone 			if successful.  Otherwise, returns one of the system wide error codes.
+		KErrGeneral			if an error has no specific categorisation;
+		KErrNotSupported	if the input does not contain video;
+		KErrCorrupt			if 3GP stream is invalid;
+		KErrNotReady		if the parser has not yet been initialised; See C3GPParse::Open;
+		KErr3gpLibMoreDataRequired	if more data is required before the requested information can be 
+							retrieved;  See C3GPParse::InsertData.
+*/
+EXPORT_C TInt C3GPParse::GetVideoProperties(T3GPVideoType& aType, TUint& aLength, TReal& aFrameRate, 
+		TUint& aAvgBitRate, TSize& aSize, TUint& aTimeScale) const
+	{
+	if (!iHandler)
+		{
+		return KErrNotReady;
+		}
+	
+	TInt err = DoGetVideoProperties();
+	
+	if (err == KErrNone)
+		{
+		aLength = iVideoLength;
+		aType = iVideoType;
+		aFrameRate = iVideoFrameRate;
+		aSize.iWidth = iVideoSize.iWidth;
+		aSize.iHeight = iVideoSize.iHeight;
+		aTimeScale = iVideoTimeScale;
+		}
+	else 
+		{
+		return err;
+		}
+
+	// Get average bit rate of the stream in bps
+	err = DoGetStreamProperties();
+	if (err != KErrNone)
+		{
+		return err;
+		}
+	
+	// Video average bit rate is calculated from GetStreamDescription’s aAvgBitRate substructs Audio’s aAvgBitRate
+	// GetAudioProperties has not been called
+	err = DoGetAudioProperties();
+	if (err == KErrNone)
+		{
+		aAvgBitRate = iStreamAvgBitRate - iAudioAvgBitRate;
+		}
+	else
+		{
+		// if the audio stream is not usable, ignore the error since the stream
+		// in concern is video stream.  The audio stream error can be dealt with by
+		// users when it asks for audio properties. 
+		aAvgBitRate = iStreamAvgBitRate;
+		}
+	
+	return KErrNone;
+	}
+
+/**
+This function returns the parameters describing the audio stream. 
+ 
+If no file or CAF object is supplied during parser initialisation, this should be called after 
+enough data has been inserted into the library so that the 3GP headers containing the information 
+can be read.
+
+@param	aType		The type of audio stream.  Refer to T3GPFrameType for supported audio type values.
+@param	aLength		Duration of audio in milliseconds.
+@param	aFramesPerSample	Number of audio frames in each sample.
+@param	aAvgBitRate	Average bit rate of audio.
+@param	aTimeScale	Timescale of audio track. 
+
+@return	KErrNone 		if successful.  Otherwise, returns one of the system wide error codes.
+		KErrGeneral		if an error has no specific categorisation;
+		KErrNotSupported	if input does not contain audio;
+		KErrCorrupt		if 3GP stream is invalid;
+		KErrNotReady	if the parser has not yet been initialised; See C3GPParse::Open;
+		KErr3gpLibMoreDataRequired	if more data is required before the requested information can be 
+						retrieved.  See C3GPParse::InsertData.
+*/
+EXPORT_C TInt C3GPParse::GetAudioProperties(T3GPAudioType& aType, TUint& aLength, TInt& aFramesPerSample, 
+		TUint& aAvgBitRate, TUint& aTimeScale) const
+	{
+	if (!iHandler)
+		{
+		return KErrNotReady;
+		}
+	
+	TInt err = DoGetAudioProperties();
+	
+	if (err == KErrNone)
+		{
+		aLength = iAudioLength;
+		aType = iAudioType;
+		aFramesPerSample = iAudioFramesPerSample;
+		aAvgBitRate = iAudioAvgBitRate;
+		aTimeScale = iAudioTimeScale;
+		iAudioPropertiesSaved = ETrue;
+		}
+
+	return err;
+	}
+
+/**
+This function returns the parameters that describe the contents of the input file or buffer. 
+
+If no file or CAF object is supplied during parser initialisation, this should be called after 
+enough data has been inserted into the library so that the headers containing the information can 
+be read.
+
+@param	aSize		Length of the stream in bytes.
+@param	aAvgBitRate	Average bit rate of the stream in bps.
+
+@return	KErrNone 		if successful.  Otherwise, returns one of the system wide error codes.
+		KErrGeneral		if an error has no specific categorisation;
+		KErrCorrupt		if 3GP stream is invalid;
+		KErrNotReady	if the parser has not yet been initialised; See C3GPParse::Open;
+		KErr3gpLibMoreDataRequired	if more data is required before the requested information can be 
+						retrieved.  See C3GPParse::InsertData.
+ */
+EXPORT_C TInt C3GPParse::GetContainerProperties(TUint& aSize, TUint& aAvgBitRate) const
+	{
+	if (!iHandler)
+		{
+		return KErrNotReady;
+		}
+	
+	TInt err = DoGetStreamProperties();
+	if (err == KErrNone)
+		{
+		aSize = iStreamSize;
+		aAvgBitRate = iStreamAvgBitRate;
+		}
+
+	return err;
+	}
+
+/**
+This function returns the number of bytes that the library instance has in its allocated buffers.
+
+The function is only valid when the parser is initialized without any parameters. Zero is 
+returned when in file mode, that is, the parser has been initialized with a valid filename, file handle 
+or a CAF object.
+
+@see C3GPParse::InsertData.
+
+@param	aNum	Number of allocated bytes in the library.
+
+@return	KErrNone 		if successful.  Otherwise, returns one of the system wide error codes.
+		KErrGeneral		if an error has no specific categorisation;
+		KErrNotSupported	if the parser has been initialised with a file name or file handle;
+		KErrNotReady	if the parser has not yet been initialised; See C3GPParse::Open.
+*/
+EXPORT_C TInt C3GPParse::GetNumBufferedBytes(TInt& aNum) const
+	{
+	if (!iHandler)
+		{
+		return KErrNotReady;
+		}
+		
+	mp4_u32 numBytes = 0;
+	MP4Err mp4Err = MP4ParseGetBufferedBytes(iHandler, &numBytes);
+	aNum = numBytes;
+	
+	return SymbianOSError(mp4Err);
+	}
+
+/**
+This function returns the type of the next audio/video frame in the stream.
+
+This function has no effect on the parser’s current position.
+
+@param	aType	Type of the next frame.  Refer to the definition of T3GPFrameType for all possible values.
+
+@return	KErrNone 		if successful.  Otherwise, returns one of the system wide error codes.
+		KErrGeneral		if an error has no specific categorisation;
+		KErrNotFound	if frame does not exist (the previous frame was the last one);
+		KErrNotReady	if the parser has not yet been initialised; See C3GPParse::Open;
+		KErrCorrupt		if 3GP stream is invalid;
+		KErr3gpLibMoreDataRequired		if 3GP library needs more data before the requested 
+						information can be returned.
+*/
+EXPORT_C TInt C3GPParse::GetFrameType(T3GPFrameType& aType) const
+	{
+	if (!iHandler)
+		{
+		return KErrNotReady;
+		}
+	mp4_u32 frameType = 0;
+	MP4Err mp4Err = MP4ParseNextFrameType(iHandler, &frameType);
+	if (mp4Err == MP4_OK)
+		{
+		if (
+		        frameType == MP4_TYPE_MPEG4_VIDEO ||
+		        frameType == MP4_TYPE_H263_PROFILE_0 || 
+		        frameType == MP4_TYPE_H263_PROFILE_3 ||
+		        frameType == MP4_TYPE_AVC_PROFILE_BASELINE ||
+                frameType == MP4_TYPE_AVC_PROFILE_MAIN ||
+                frameType == MP4_TYPE_AVC_PROFILE_EXTENDED ||
+                frameType == MP4_TYPE_AVC_PROFILE_HIGH
+		   )
+			{
+			aType = E3GPVideo;
+			}
+		else if (frameType == MP4_TYPE_MPEG4_AUDIO || frameType == MP4_TYPE_AMR_NB || 
+			frameType == MP4_TYPE_AMR_WB || frameType == MP4_TYPE_QCELP_13K)
+			{
+			aType = E3GPAudio;
+			}
+		else
+			{
+			// This should not happen
+			Panic(KErrCorrupt);
+			}
+		}
+	return SymbianOSError(mp4Err);
+	}
+
+/**
+This function returns the size of the immediate next video frame based on the current 
+position of the parser.
+
+Calling this function does not change the current position of the parser.
+
+@param	aSize	Size of the next video frame in bytes.
+
+@return	KErrNone 		if successful.  Otherwise, returns one of the system wide error codes.
+		KErrGeneral		if an error has no specific categorisation;
+		KErrNotSupported	if the input does not contain video;		
+		KErrCorrupt		if 3GP stream is invalid;
+		KErrNotReady	if the parser has not yet been initialised; See C3GPParse::Open;
+		KErr3gpLibMoreDataRequired	if 3GP library needs more data before the requested 
+						information can be returned.
+*/
+EXPORT_C TInt C3GPParse::GetVideoFrameSize(TUint& aSize) const
+	{
+	if (!iHandler)
+		{
+		return KErrNotReady;
+		}
+	
+	// Check if 3GP input data contains video stream
+	TInt err = DoGetVideoProperties(); 
+	if (err != KErrNone)
+		{
+		return err;
+		}
+	
+	// video type from 3GP file header has been saved
+	mp4_u32 frameSize = 0;	
+	MP4Err mp4Err = MP4ParseNextFrameSize(iHandler, iVideoMp4Type, &frameSize);
+	if (mp4Err == MP4_OK)
+		{		
+		aSize = frameSize;
+		}
+	
+	return SymbianOSError(mp4Err);	
+	}
+
+/**
+This function returns the total size of the audio frames in the immediate audio sample based on the 
+current position of the parser.
+
+This function has no effect on the parser’s current position.
+
+@param	aSize	Size of the next audio sample in bytes.
+
+@return	KErrNone 		if successful.  Otherwise, returns one of the system wide error codes.
+		KErrGeneral		if an error has no specific categorisation;
+		KErrNotSupported	if the input does not contain audio;
+		KErrCorrupt		if 3GP stream is invalid;
+		KErrNotReady	if the parser has not yet been initialised; See C3GPParse::Open;
+		KErr3gpLibMoreDataRequired	if 3GP library needs more data before the requested 
+						information can be returned.
+*/
+EXPORT_C TInt C3GPParse::GetAudioFramesSize(TUint& aSize) const
+	{
+	if (!iHandler)
+		{
+		return KErrNotReady;
+		}
+	
+	// Check if 3GP input data contains audio stream
+	TInt err = DoGetAudioProperties(); 
+	if (err != KErrNone)
+		{
+		return err;
+		}
+	
+	// audio type from 3GP file header has been saved. Directely use iAudioMp4Type as input
+	mp4_u32 frameSize = 0;
+	
+	MP4Err mp4Err = MP4ParseNextFrameSize(iHandler, iAudioMp4Type, &frameSize);
+	if (mp4Err == MP4_OK)
+		{
+		aSize = frameSize;
+		}
+	
+	return SymbianOSError(mp4Err);	
+	}
+
+/**
+This function reads the next video frame from the 3GP file/stream and returns it to the caller.  
+The current position of video stream will be moved forward.
+
+The next frame depends on the position in the input 3GP file.  C3GPParse::Seek can be used to change 
+the current position in the 3GP file.
+
+If the function returns KErr3gpLibMoreDataRequired, the caller needs to call C3GPParse::InsertData 
+to insert more data before calling the function again.
+
+Since there are separate cursors for storing current positions of video and audio streams, calling this 
+function does not affect the position of the next audio stream.
+
+@param	aBuffer		Video frame is returned here.
+@param	aKeyFrame	Returns ETrue if the current frame is a key frame (intra), otherwise the value is EFalse.
+@param	aTimeStampInMs	Video frame presentation time in milliseconds from the beginning of the video sequence.
+@param	aTimeStampInTimescale	Video frame presentation time in timescale from the beginning of the video sequence.  
+
+@return	KErrNone 		if successful.  Otherwise, returns one of the system wide error codes. 
+		KErrGeneral		if an error has no specific categorisation;
+		KErrNotSupported	if the 3GP input data contains no video stream;
+		KErrNotFound	if frame does not exist (the previous frame was the last one);
+		KErrOverflow	if requested frame does not fit into the given buffer; Caller can use 
+						C3GPParse::GetVideoFrameSize to retrieve the minimum buffer size needed 
+						to fit this video frame;
+		KErrCorrupt		if 3GP stream is invalid;
+		KErrNotReady	if the parser has not yet been initialised; See C3GPParse::Open;
+		KErr3gpLibMoreDataRequired	if 3GP library needs more data before the requested 
+						information can be returned.
+*/
+EXPORT_C TInt C3GPParse::ReadVideoFrame(TDes8& aBuffer, TBool& aKeyFrame, TUint& aTimeStampInMs, 
+										TUint& aTimeStampInTimescale) const
+	{
+	if (!iHandler)
+		{
+		return KErrNotReady;
+		}
+	if (aBuffer.MaxLength() <= 0)
+		{
+		return KErrOverflow;
+		}
+	
+	// Check if 3GP input data contains video stream
+	TInt err = DoGetVideoProperties();	
+	if (err != KErrNone)
+		{
+		return err;
+		}
+	
+	mp4_u32 frameSize = 0;
+	mp4_u32 timeStamp = 0;
+	mp4_bool keyFrame = EFalse; 
+	mp4_u32 timestamp2 = 0;
+	
+	MP4Err mp4Err = MP4ParseReadVideoFrame(iHandler, const_cast<mp4_u8*>(aBuffer.Ptr()), aBuffer.MaxLength(), 
+			&frameSize, &timeStamp, &keyFrame, &timestamp2);
+	
+	if (mp4Err == MP4_OK)
+		{
+		aBuffer.SetLength(frameSize);
+		aKeyFrame = keyFrame;
+		aTimeStampInMs = timeStamp;
+		aTimeStampInTimescale = timestamp2;
+		}
+	return SymbianOSError(mp4Err);
+	}
+
+/**
+Return size of video DecoderSpecificInfo.
+For files with MPEG-4 video this data is read from the esds atom. For files with AVC video
+this data is read from the avcC atom.
+
+Note: Only MPEG-4 video and H.264/AVC video streams contain DecoderSpecificInfo.
+
+@param	aSize	Size of video DecoderSpecificInfo.
+
+@return	KErrNone 		if successful.  Otherwise, returns one of the system wide error codes. 
+		KErrGeneral		if an error has no specific categorisation;
+		KErrNotSupported	if the 3GP input data contains no MPEG-4 / AVC video stream;
+		KErrCorrupt		if 3GP stream is invalid;
+		KErrNotReady	if the parser has not yet been initialised; See C3GPParse::Open;
+		KErr3gpLibMoreDataRequired	if 3GP library needs more data before the requested 
+						information can be returned.
+*/
+EXPORT_C TInt C3GPParse::GetVideoDecoderSpecificInfoSize(TInt& aSize) const
+	{
+	if (!iHandler)
+		{
+		return KErrNotReady;
+		}
+
+	// Check if 3GP input data contains video stream and the video type is either
+	// MPEG-4 or H.264/AVC
+	TInt err = DoGetVideoProperties();	
+	if (err == KErrNone)
+		{
+		if (!(
+		        iVideoType == E3GPMpeg4Video ||
+		        iVideoType == E3GPAvcProfileBaseline ||
+				iVideoType == E3GPAvcProfileMain ||
+				iVideoType == E3GPAvcProfileExtended ||
+                iVideoType == E3GPAvcProfileHigh
+        ))
+			{
+			return KErrNotSupported;
+			}
+		}
+	else
+		{
+		return err;
+		}
+	
+	mp4_u32 decspecinfosize = 0;
+	MP4Err mp4Err = MP4ParseReadVideoDecoderSpecificInfo(iHandler, NULL, 0, &decspecinfosize);
+	
+	if ( mp4Err == MP4_OK || mp4Err == MP4_BUFFER_TOO_SMALL)
+		{
+		aSize = decspecinfosize;
+		mp4Err = MP4_OK;
+		}
+
+	return SymbianOSError(mp4Err);
+	}
+
+/**
+This function reads DecoderSpecificInfo data from 3GP metadata and returns it to the caller.
+For files with MPEG-4 video this data is read from the esds atom. For files with AVC video
+this data is read from the avcC atom.
+
+Note: Only MPEG-4 video and H.264/AVC video streams contain DecoderSpecificInfo.
+
+@see C3GPParse::GetVideoDecoderSpecificInfoSize
+
+@param	aInfo			The descriptor to store the video decoder information.
+
+@return	KErrNone 		if successful.  Otherwise, returns one of the system wide error codes. 
+		KErrGeneral		if an error has no specific categorisation;
+		KErrNotSupported	if the 3GP input data contains no MPEG-4 / AVC video stream;
+		KErrOverflow	if requested frame does not fit into the given buffer;
+		KErrCorrupt		if 3GP stream is invalid;
+		KErrNotReady	if the parser has not yet been initialised; See C3GPParse::Open;
+		KErr3gpLibMoreDataRequired	if 3GP library needs more data before the requested 
+						information can be returned.
+*/
+EXPORT_C TInt C3GPParse::GetVideoDecoderSpecificInfo(TDes8& aInfo) const
+	{
+	if (!iHandler)
+		{
+		return KErrNotReady;
+		}
+	if (aInfo.MaxLength() <= 0)
+		{
+		return KErrOverflow;
+		}
+	
+	// Check if 3GP input data contains video stream and the video type is either
+	// MPEG-4 or H.264/AVC
+	TInt err = DoGetVideoProperties();	
+	if (err == KErrNone)
+		{
+		if (!(
+		        iVideoType == E3GPMpeg4Video ||
+		        iVideoType == E3GPAvcProfileBaseline ||
+		        iVideoType == E3GPAvcProfileMain ||
+		        iVideoType == E3GPAvcProfileExtended ||
+                iVideoType == E3GPAvcProfileHigh
+		))
+			{
+			return KErrNotSupported;
+			}
+		}
+	else
+		{
+		return err;
+		}
+	
+	mp4_u32 decspecinfosize = 0;
+	MP4Err mp4Err = MP4ParseReadVideoDecoderSpecificInfo(iHandler, const_cast<mp4_u8*>(aInfo.Ptr()), 
+			aInfo.MaxLength(),&decspecinfosize);
+	if (mp4Err == MP4_OK)
+		{
+		aInfo.SetLength(decspecinfosize);
+		}	
+	return SymbianOSError(mp4Err);
+	}
+
+/**
+This function reads the audio frames that are stored in the current audio sample from the 
+3GP file/stream and returns them to the caller.  The current position of audio stream will be moved forward. 
+
+Note: The next frame depends on the position in the input 3GP file.  C3GPParse::Seek can 
+be used to change the current position in the 3GP file.
+
+If the function returns KErr3gpLibMoreDataRequired, the caller needs to call C3GPParse::InsertData 
+to insert more data before calling the function again.
+
+Note: aReturnedFrames may differ from the correct value when accessing the last audio sample.
+
+Note: Since there are separate cursors for storing current positions for video and audio streams, calling 
+this function does not change current position of the parser for video stream.
+
+@param	aBuffer			Audio frames are returned here.
+@param	aReturnedFrames	Number of the returned frames or 0 if not known.
+@param	aTimeStampInMs	Audio frame presentation time in milliseconds from the beginning of the 
+						audio sequence.
+@param	aTimeStampInTimescale	Audio frame presentation time in timescale from the beginning 
+						of the audio sequence.  
+					
+@return	KErrNone 		if successful.  Otherwise, returns one of the system wide error codes. 
+		KErrGeneral		if an error has no specific categorisation;
+		KErrNotSupported	if the 3GP input data contains no audio stream; 
+		KErrOverflow	if requested frame does not fit into the given buffer; Caller can use 
+						C3GPParse::GetAudioFrameSize to retrieve the minimum size needed to 
+						fit this audio frame;
+		KErrCorrupt		if 3GP stream is invalid;
+		KErrNotFound	if no more frames available;
+		KErrNotReady	if the parser has not yet been initialised; See C3GPParse::Open;
+		KErr3gpLibMoreDataRequired	if 3GP library needs more data before the requested 
+						information can be returned.
+*/
+EXPORT_C TInt C3GPParse::ReadAudioFrames(TDes8& aBuffer, TInt& aReturnedFrames, TUint& aTimeStampInMs, 
+		TUint& aTimeStampInTimescale) const
+	{
+	if (!iHandler)
+		{
+		return KErrNotReady;
+		}
+	if (aBuffer.MaxLength() <= 0)
+		{
+		return KErrOverflow;
+		}
+	
+	// Check if 3GP input data contains audio stream
+	TInt err = DoGetAudioProperties();	
+	if (err != KErrNone)
+		{
+		return err;
+		}
+	
+	mp4_u32 numOfFrames = 0;
+	mp4_u32 timeStampInMs = 0;
+	mp4_u32 timeStampInTimescale = 0;
+	mp4_u32 audioSize = 0;
+	MP4Err mp4Err = MP4ParseReadAudioFrames(iHandler, const_cast<mp4_u8*>(aBuffer.Ptr()), aBuffer.MaxLength(), 
+			&audioSize, &timeStampInMs, &numOfFrames, &timeStampInTimescale);
+	if (mp4Err == MP4_OK)
+		{
+		aBuffer.SetLength(audioSize);
+		aReturnedFrames = numOfFrames;
+		aTimeStampInMs = timeStampInMs;
+		aTimeStampInTimescale = timeStampInTimescale;	
+		}
+	return SymbianOSError(mp4Err);
+	}
+
+/**
+Returns size of audio DecoderSpecificInfo data from 3GP metadata.
+
+@param	aSize	Size of DecoderSpecificInfo to be returned (in bytes).
+
+@return	KErrNone 		if successful.  Otherwise, returns one of the system wide error codes. 
+		KErrGeneral		if an error has no specific categorisation;
+		KErrNotSupported	if the stream does not contain audio stream stored in MPEG-4 audio sample boxes.
+		KErrCorrupt		if 3GP stream is invalid;
+		KErrNotReady	if the parser has not yet been initialised; See C3GPParse::Open;
+		KErr3gpLibMoreDataRequired	if 3GP library needs more data before the requested 
+						information can be returned.
+*/
+EXPORT_C TInt C3GPParse::GetAudioDecoderSpecificInfoSize(TInt& aSize) const
+	{
+	if (!iHandler)
+		{
+		return KErrNotReady;
+		}
+
+	// Check if 3GP input data contains audio stream
+	TInt err = DoGetAudioProperties();	
+	if (err != KErrNone)
+		{
+		return err;
+		}
+	
+	mp4_u32 decspecinfosize = 0;
+	MP4Err mp4Err = MP4ParseReadAudioDecoderSpecificInfo(iHandler, NULL, 0, &decspecinfosize);	
+	if ( mp4Err == MP4_OK  || mp4Err == MP4_BUFFER_TOO_SMALL)
+		{
+		aSize = decspecinfosize;
+		mp4Err = MP4_OK;
+		}	
+	return SymbianOSError(mp4Err);
+	}
+
+/**
+This function reads DecoderSpecificInfo data from 3GP metadata and returns it to the caller.
+
+Note: AMR DecoderSpecificInfo data structure is returned in runtime in an architecture-specific 
+Endian format, that is, no Endian conversion is necessary for the data.
+
+@see C3GPParse::GetAudioDecoderSpecificInfoSize
+
+@param	aBuffer				DecoderSpecificInfo is returned here.
+
+@return	KErrNone 		if successful.  Otherwise, returns one of the system wide error codes.
+		KErrGeneral		if an error has no specific categorisation;
+		KErrNotSupported	if the stream does not contain audio stream stored in MPEG-4 audio sample boxes.		
+		KErrOverflow	if requested frame does not fit into the given buffer;
+		KErrCorrupt		if 3GP stream is invalid;
+		KErrNotReady	if the parser has not yet been initialised; See C3GPParse::Open;
+		KErr3gpLibMoreDataRequired	if 3GP library needs more data before the requested 
+						information can be returned.
+*/
+EXPORT_C TInt C3GPParse::GetAudioDecoderSpecificInfo(TDes8& aBuffer) const
+	{
+	if (!iHandler)
+		{
+		return KErrNotReady;
+		}
+	if (aBuffer.MaxLength() <= 0)
+		{
+		return KErrOverflow;
+		}
+	
+	// Check if 3GP input data contains audio stream
+	TInt err = DoGetAudioProperties();	
+	if (err != KErrNone)
+		{
+		return err;
+		}
+	
+	mp4_u32 decspecinfosize = 0;
+	MP4Err mp4Err = MP4ParseReadAudioDecoderSpecificInfo(iHandler, const_cast<mp4_u8*>(aBuffer.Ptr()), 
+			aBuffer.MaxLength(),&decspecinfosize);
+	if (mp4Err == MP4_OK)
+		{
+		aBuffer.SetLength(decspecinfosize);
+		}
+	return SymbianOSError(mp4Err);
+	}
+
+/**
+Returns the timestamp of the next video frame.  The current position of the video stream will be moved forward.
+
+The function can be used to find out which frames have been coded to optimize the input frame selection 
+if video frame rate needs to be modified.
+
+When this function call returns KErrEof, there are no more video frames left in the 3GP file and 
+the timestamp returned with the previous call was the timestamp of the last video frame.
+
+Note:  C3GPParse::Seek can be used to change the current position in the 3GP file. 
+
+@param	aTimeStampInMs			Timestamp in milliseconds is returned here.
+@param	aTimeStampInTimescale	Timestamp in timescale is returned here.  
+
+@return	KErrNone 		if successful.  Otherwise, returns one of the system wide error codes. 
+		KErrGeneral		if an error has no specific categorisation;
+		KErrNotSupported	if the input does not contain video;		
+		KErrEof			if no more video frames left;
+		KErrCorrupt		if 3GP stream is invalid;
+		KErrNotReady	if the parser has not yet been initialised; See C3GPParse::Open;
+		KErr3gpLibMoreDataRequired	if 3GP library needs more data before the requested 
+						information can be returned.
+*/
+EXPORT_C TInt C3GPParse::GetVideoTimestamp(TUint& aTimeStampInMs, TUint& aTimeStampInTimescale) const
+	{
+	if (!iHandler)
+		{
+		return KErrNotReady;
+		}
+	
+	// Check if 3GP input data contains video stream
+	TInt err = DoGetVideoProperties();	
+	if (err != KErrNone)
+		{
+		return err;
+		}
+	
+	mp4_u32 timeStampInMs = 0;
+	mp4_u32 timeStampInTimescale = 0;
+	MP4Err mp4Err = MP4ParseGetNextVideoTimestamp(iHandler, &timeStampInMs, &timeStampInTimescale);
+	if (mp4Err == MP4_OK)
+		{
+		aTimeStampInMs = timeStampInMs;
+		aTimeStampInTimescale = timeStampInTimescale;
+		}
+	return SymbianOSError(mp4Err);
+	}
+
+/**
+This function determines whether the input 3GP stream is streamable, that is, whether the media data is arranged 
+in such a manner that playback can be started without downloading the entire stream.
+
+@param	aStreamable	Returns ETrue if the file is streamable.  Otherwise, returns EFalse.
+
+@return	KErrNone 		if successful.  Otherwise, returns one of the system wide error codes. 
+		KErrGeneral		if an error has no specific categorisation;
+		KErrCorrupt		if 3GP stream is invalid;
+		KErrNotReady	if the parser has not yet been initialised; See C3GPParse::Open;
+		KErr3gpLibMoreDataRequired	if 3GP library needs more data before the requested 
+						information can be returned.
+*/
+EXPORT_C TInt C3GPParse::GetStreamable(TBool& aStreamable) const
+	{
+	if (!iHandler)
+		{
+		return KErrNotReady;
+		}
+	
+	MP4Err mp4Err = MP4ParseIsStreamable(iHandler);
+	if (mp4Err == MP4_OK)
+		{
+		aStreamable = ETrue;
+		}
+	else
+		{
+		aStreamable = EFalse;
+		}
+	return SymbianOSError(mp4Err);
+	}
+
+/**
+This function seeks the position specified by the aPosition parameter in the input 3GP file/stream. 
+
+The position is considered to start from the beginning of the presentation time line in the 3GP file. 
+Thus audio and video positions cannot be given separately.
+
+The function will set the current audio and video positions in the following manner:
+
+	If there is only audio data in the file, the current position is set to the audio frame at or just 
+	before the given position.
+
+	If there is only video in the file and the key frame is EFalse, the current position is set to the 
+	video frame at or just before the given position. If the key frame is set to ETrue, the current 
+	position is set to the first key frame at or before the current position.
+
+	If there are both audio and video in the file, video is first positioned as explained above and then 
+	audio is sought to the closest position in relation to video.	
+	
+If the position to seek is greater than the duration of video or audio, the video or audio position is 
+set to the position of the last video or audio frame as explained above.
+
+If the function returns KErr3gpLibMoreDataRequired, the caller needs to call C3GPParse::InsertData 
+to insert more data before calling the function again.
+
+@param	aPosition		Position to seek in milliseconds in the 3GP presentation time line.
+@param	aKeyFrame		If set to ETrue, the first video key frame before a given point is sought.  If 
+						set to EFalse, the first video frame before a given point is sought.
+@param	aAudioPosition	Position of audio after seeking (in milliseconds).
+@param	aVideoPosition	Position of video after seeking (in milliseconds).
+
+@return	KErrNone 		if successful.  Otherwise, returns one of the system wide error codes. 
+		KErrGeneral		if an error has no specific categorisation;
+		KErrNotFound	if cannot seek the requested position;
+		KErr3gpLibMoreDataRequired	if 3GP library needs more data before the requested 
+						information can be returned.
+		KErrNotReady	if the parser has not yet been initialised; See C3GPParse::Open;
+*/
+EXPORT_C TInt C3GPParse::Seek(TUint aPosition, TBool aKeyFrame, TUint& aAudioPosition, TUint& aVideoPosition) const
+	{
+	if (!iHandler)
+		{
+		return KErrNotReady;
+		}
+	
+	mp4_u32 audioPosition = 0;
+	mp4_u32 videoPosition = 0;
+	mp4_bool keyFrame = aKeyFrame;
+	MP4Err mp4Err = MP4ParseSeek(iHandler, aPosition, &audioPosition, &videoPosition, keyFrame);
+	if (mp4Err == MP4_OK)
+		{
+		aAudioPosition = audioPosition;
+		aVideoPosition = videoPosition;
+		}
+	return SymbianOSError(mp4Err);
+	}
+
+/**
+This function determines whether the next frame of the type aType is available.
+
+This function has no effect on the parser’s current position.
+
+@param	aType		The type of frame to check for.  Refer to T3GPFrameType for supported types.
+@param	aAvailable	Return ETrue if the type of frame specified by aType is available.
+
+@return	KErrNone 		if successful.  Otherwise, returns one of the system wide error codes. 
+		KErrGeneral		if an error has no specific categorisation;
+		KErrNotFound	if frame of the requested type is not available;
+		KErrCorrupt		if 3GP stream is invalid;
+		KErrNotReady	if the parser has not yet been initialised; See C3GPParse::Open;
+		KErr3gpLibMoreDataRequired	if 3GP library needs more data before the requested 
+						information can be returned.
+*/
+EXPORT_C TInt C3GPParse::GetFrameAvailability(T3GPFrameType aType, TBool& aAvailable) const
+	{
+	if (!iHandler)
+		{
+		return KErrNotReady;
+		}
+	
+	aAvailable = EFalse;
+	TInt err = KErrNone;
+	MP4Err mp4Err = MP4_OK;
+	if (aType == E3GPAudio)
+		{
+		// Check if 3GP input data contains audio stream
+		err = DoGetAudioProperties();	
+		if (err == KErrNotSupported)
+			{
+			// If there is no requested type, err will be KErrNotSupported. But in here, KErrNotFound is 
+			// more proper.
+			err = KErrNotFound;
+			}
+		else if (err == KErrNone)
+			{
+			mp4Err = MP4ParseIsFrameAvailable(iHandler, iAudioMp4Type);
+			err = SymbianOSError(mp4Err);
+			}
+		}
+	else if (aType == E3GPVideo) 
+		{
+		// Check if 3GP input data contains video stream
+		err = DoGetVideoProperties();	
+		if (err == KErrNotSupported)
+			{
+			// If there is no requested type, err will be KErrNotSupported. But in here, KErrNotFound is 
+			// more proper.
+			err = KErrNotFound;
+			}
+		else if (err == KErrNone)
+			{
+			mp4Err = MP4ParseIsFrameAvailable(iHandler, iVideoMp4Type);
+			err = SymbianOSError(mp4Err);
+			}
+		}
+	else
+		{
+		Panic(KErrArgument); // This should not happen.
+		}
+	
+	if (err == KErrNone)
+		{
+		aAvailable = ETrue;
+		}
+	return err;
+	}
+
+/**
+Returns the number of video frames.
+
+@param	aNum	Number of video frames.
+
+@return	KErrNone 		if successful.  Otherwise, returns one of the system wide error codes. 
+		KErrGeneral		if an error has no specific categorisation;
+		KErrNotSupported	if the input does not contain video;		
+		KErrNotReady	if the parser has not yet been initialised; See C3GPParse::Open.
+*/
+EXPORT_C TInt C3GPParse::GetNumberOfVideoFrames(TUint& aNum) const
+	{
+	if (!iHandler)
+		{
+		return KErrNotReady;
+		}
+	
+	// Check if 3GP input data contains video stream
+	TInt err = DoGetVideoProperties(); 
+	if (err != KErrNone)
+		{
+		return err;
+		}
+	
+	mp4_u32 numVideoFrame = 0;
+	MP4Err mp4Err = MP4ParseGetNumberOfVideoFrames(iHandler, &numVideoFrame);
+	if (mp4Err == MP4_OK)
+		{
+		aNum = numVideoFrame;
+		}
+	return SymbianOSError(mp4Err);
+	}
+
+/**
+This function gives the video sample entry index of the next video frame to be read.
+
+The smallest index value is 1.
+
+@param	aIndex	Returns the Visual Sample Entry index of the next video frame to be read.
+
+@return	KErrNone 		if successful.  Otherwise, returns one of the system wide error codes. 
+		KErrGeneral		if an error has no specific categorisation;
+		KErrNotSupported	if the input does not contain video;		
+		KErrNotReady	if the parser has not yet been initialised; See C3GPParse::Open.
+*/
+EXPORT_C TInt C3GPParse::GetVideoSampleEntryIndex(TUint& aIndex) const
+	{
+	if (!iHandler)
+		{
+		return KErrNotReady;
+		}
+	
+	// Check if 3GP input data contains video stream
+	TInt err = DoGetVideoProperties(); 
+	if (err != KErrNone)
+		{
+		return err;
+		}
+	
+	mp4_u32 index = 0;
+	MP4Err mp4Err = MP4ParseGetVideoSampleEntryIndex(iHandler, &index);
+	if (mp4Err == MP4_OK)
+		{
+		aIndex = index;
+		}
+	return SymbianOSError(mp4Err);
+	}
+
+/**
+Returns video frame size.
+
+@param	aIndex	Index of video frame.
+@param	aSize	Return the size of the video frame.
+
+@return	KErrNone 		if successful.  Otherwise, returns one of the system wide error codes. 
+		KErrGeneral		if an error has no specific categorisation;
+		KErrNotSupported	if the input does not contain video;		
+		KErrNotReady	if the parser has not yet been initialised; See C3GPParse::Open.
+*/
+EXPORT_C TInt C3GPParse::GetVideoFrameSize(TUint aIndex, TUint& aSize) const
+	{
+	if (!iHandler)
+		{
+		return KErrNotReady;
+		}
+	
+	// Check if 3GP input data contains video stream
+	TInt err = DoGetVideoProperties(); 
+	if (err != KErrNone)
+		{
+		return err;
+		}
+	
+	mp4_u32 videoFrameSize = 0;
+	MP4Err mp4Err = MP4ParseGetVideoFrameSize(iHandler, aIndex, &videoFrameSize);
+	if (mp4Err == MP4_OK)
+		{
+		aSize = videoFrameSize;
+		}
+	return SymbianOSError(mp4Err);
+	}
+
+/**
+Returns video frame start time.
+
+@param	aIndex					Index of video frame.
+@param	aTimeStampInMs			Result in milliseconds.
+@param	aTimeStampInTimescale	Result is returned here.
+
+@return	KErrNone 		if successful.  Otherwise, returns one of the system wide error codes. 
+		KErrGeneral		if an error has no specific categorisation;
+		KErrNotSupported	if the input does not contain video;		
+		KErrNotReady	if the parser has not yet been initialised; See C3GPParse::Open.
+*/
+EXPORT_C TInt C3GPParse::GetVideoFrameStartTime(TUint aIndex, TUint& aTimeStampInMs, TUint& aTimeStampInTimescale) const
+	{
+	if (!iHandler)
+		{
+		return KErrNotReady;
+		}
+	
+	// Check if 3GP input data contains video stream
+	TInt err = DoGetVideoProperties(); 
+	if (err != KErrNone)
+		{
+		return err;
+		}
+	
+	mp4_u32 timeStampInMs = 0;
+	mp4_u32 timeStampInTimescale = 0;
+	MP4Err mp4Err = MP4ParseGetVideoFrameStartTime(iHandler, aIndex, &timeStampInTimescale, &timeStampInMs);
+	if (mp4Err == MP4_OK)
+		{
+		aTimeStampInMs = timeStampInMs;
+		aTimeStampInTimescale = timeStampInTimescale;
+		}
+	return SymbianOSError(mp4Err);
+	}
+
+/**
+Checks if a video frame of with index aIndex exists.
+
+@param	aIndex		Index of video frame.
+@param	aKeyFrame	Return ETrue if the video frame is a key frame.
+
+@return	KErrNone 		if successful.  Otherwise, returns one of the system wide error codes. 
+		KErrGeneral		if an error has no specific categorisation;
+		KErrNotSupported	if the input does not contain video;		
+		KErrNotReady	if the parser has not yet been initialised; See C3GPParse::Open.
+*/
+EXPORT_C TInt C3GPParse::GetVideoFrameKeyType(TUint aIndex, TBool& aKeyFrame) const
+	{
+	if (!iHandler)
+		{
+		return KErrNotReady;
+		}
+	
+	// Check if 3GP input data contains video stream
+	TInt err = DoGetVideoProperties(); 
+	if (err != KErrNone)
+		{
+		return err;
+		}
+	
+	mp4_bool keyFrame = EFalse;
+	MP4Err mp4Err = MP4ParseGetVideoFrameType(iHandler, aIndex, &keyFrame);
+	if (mp4Err == MP4_OK)
+		{
+		aKeyFrame = keyFrame;
+		}
+	return SymbianOSError(mp4Err);
+	}
+
+/**
+This function gives the audio sample entry index of the next audio frame to be read.
+
+The smallest index value is 1. 
+
+@param	aIndex	Returns the Audio Sample Entry index of the next video frame to be read.
+
+@return	KErrNone 		if successful.  Otherwise, returns one of the system wide error codes. 
+		KErrGeneral		if an error has no specific categorisation;
+		KErrNotSupported	if the input does not contain audio;		
+		KErrNotReady	if the parser has not yet been initialised; See C3GPParse::Open.
+*/
+EXPORT_C TInt C3GPParse::GetAudioSampleEntryIndex(TUint& aIndex) const
+	{
+	if (!iHandler)
+		{
+		return KErrNotReady;
+		}
+	
+	// Check if 3GP input data contains audio stream
+	TInt err = DoGetAudioProperties(); 
+	if (err != KErrNone)
+		{
+		return err;
+		}
+	
+	mp4_u32 audioSampleEntryIndex = 0;
+	MP4Err mp4Err = MP4ParseGetAudioSampleEntryIndex(iHandler, &audioSampleEntryIndex);
+	if (mp4Err == MP4_OK)
+		{
+		aIndex = audioSampleEntryIndex;
+		}
+	return SymbianOSError(mp4Err);
+	}
+
+/**
+This function provides the storage mode of 13K QCELP in 3G2 file. 
+
+In 3G2 files, QCELP can be registered to be stored in two ways:
+	using the QCELP Sample Entry ('sqcp') Box or
+	using the MPEG4 Audio Sample Description ('esds') Box.
+
+@param	aMode	Returns the QCELP storage mode.  See T3GPQcelpStorageMode.
+
+@return	KErrNone 		if successful.  Otherwise, returns one of the system wide error codes. 
+		KErrGeneral		if an error has no specific categorisation;
+		KErrNotSupported	if the 3GP input data does not contain any QCELP audio stream;
+		KErrNotReady	if the parser has not yet been initialised; See C3GPParse::Open.
+*/
+EXPORT_C TInt C3GPParse::GetQcelpStorageMode(T3GPQcelpStorageMode& aMode) const
+	{
+	if (!iHandler)
+		{
+		return KErrNotReady;
+		}
+	
+	// Check if 3GP input data contains any QCELP audio stream
+	TInt err = DoGetAudioProperties();	
+	if (err == KErrNone)
+		{
+		if (iAudioType != E3GPQcelp13K)
+			{
+			return KErrNotSupported;
+			}
+		}
+	else
+		{
+		return err;
+		}
+
+	mp4_u8 audioQcelpStorageMode = 0;
+	MP4Err mp4Err = MP4ParseGetQCELPStorageMode(iHandler, &audioQcelpStorageMode);
+	if (mp4Err == MP4_OK)
+		{
+		if (audioQcelpStorageMode == 1)
+			{
+			aMode = E3GPMP4AudioDescriptionBox;
+			}
+		else
+			{
+			aMode = E3GPQcelpSampleEntryBox;
+			}
+		}
+	return SymbianOSError(mp4Err);
+	}
+
+/**
+This function provides the video level of the H263 video stream contained in the 3GP data. 
+
+@param	aLevel	Returns the H263 video level.
+
+@return	KErrNone 		if successful.  Otherwise, returns one of the system wide error codes. 
+		KErrGeneral		if an error has no specific categorisation;
+		KErrNotSupported	if the 3GP input data does not contain any H263 video stream; 
+		KErrNotReady	if the parser has not yet been initialised; See C3GPParse::Open.
+*/
+EXPORT_C TInt C3GPParse::GetH263VideoLevel(TInt& aLevel) const
+	{
+	if (!iHandler)
+		{
+		return KErrNotReady;
+		}
+	
+	// Check if 3GP input data contains any H263 video stream
+	TInt err = DoGetVideoProperties();	
+	if (err == KErrNone)
+		{
+		if (!(iVideoType == E3GPH263Profile0 || iVideoType == E3GPH263Profile3))
+			{
+			return KErrNotSupported;
+			}
+		}
+	else
+		{
+		return err;
+		}
+	
+	TVideoClipProperties videoClipProperties;
+	MP4Err mp4Err = MP4ParseGetVideoClipProperties(iHandler, videoClipProperties);
+	if (mp4Err == MP4_OK)
+		{
+		aLevel = videoClipProperties.iH263Level;
+		}
+	return SymbianOSError(mp4Err);
+	}
+
+/**
+Returns the needed size for memory buffer to store an atom of given type from user data atom (UDTA).
+
+@param	aType		Type of atom to be read from UDTA. Hex value of 4 chars representing atom type 
+					defined in standard. For example, 0x7469746c is 'titl', title for the media atom.
+@param	aLocation	Specifies the location of user information to be retrieved.  Refer to 
+					T3GPUdtaLocation for supported values.
+@param	aAtomIndex	Specifies the index of atom if UDTA contains multiple sub-atoms of the same 
+					aUdtaAtomType to retrieve when supplied as input parameter.  Returns the 
+					highest index of the matching sub-atom found in the specified location as 
+					output parameter.
+@param	aSize		This contains the needed size for memory buffer.
+
+@return	KErrNone 		if successful.  Otherwise, returns one of the system wide error codes. 
+		KErrGeneral		if an error has no specific categorisation;
+		KErrNotFound	if UDTA or wanted sub-atom is not available in asked location;
+		KErrAccessDenied	if cannot seek to UDTA atom location;
+		KErrArgument	if asked aLocation is invalid;
+		KErrNotReady	if the parser has not yet been initialised; See C3GPParse::Open.
+
+@panic C3GPParse	KErrArgument	if the location of user information is not in the range of T3GPUdtaLocation
+*/
+EXPORT_C TInt C3GPParse::GetUserDataAtomSize(TUint32 aType, T3GPUdtaLocation aLocation, 
+		TUint& aAtomIndex, TInt& aSize) const
+	{
+	if (!iHandler)
+		{
+		return KErrNotReady;
+		}
+	
+	mp4_u32 userDataAtomSize = 0;
+	mp4_u32 atomIndex = aAtomIndex;
+	mp4_u32 type = aType;
+	mp4_u8 location = UdtaLocation(aLocation);
+	MP4Err mp4Err = MP4ParseGetUserDataAtom(iHandler, location, type, 
+			NULL, userDataAtomSize, atomIndex);
+	if ( mp4Err == MP4_OK  || mp4Err == MP4_OUTPUT_BUFFER_TOO_SMALL)
+		{
+		aSize = userDataAtomSize;
+		aAtomIndex = atomIndex;
+		mp4Err = MP4_OK;
+		}
+	return SymbianOSError(mp4Err);
+	}
+
+/**
+Retrieves an atom of given type from user data atom (UDTA) to the given buffer.
+
+The buffer returned stores an atom of structure that conforms to the definition of 
+a "full box" as specified in ISO/IEC 14496-12:2003: "Information technology – Coding 
+of audio-visual objects – Part 12: ISO base media file format."					
+
+For more information on user data atoms, see Section 8 – Asset Information of "3GPP 
+TS 26.244 version 6.1.0 – 3GP file format (Rel 6)."
+
+@param	aType		Type of atom to be read from UDTA. Hex value of 4 chars representing atom type 
+					defined in standard. For example, 0x7469746c is 'titl', title for the media atom.
+@param	aLocation	Specifies the location of user information to be retrieved.  Refer to 
+					T3GPUdtaLocation for supported values.
+@param	aBuffer		The descriptor to store the requested user data atom.  
+@param	aAtomIndex	Specifies the index of atom if UDTA contains multiple sub-atoms of the same 
+					aUdtaAtomType to retrieve when supplied as input parameter.  Returns the 
+					highest index of the matching sub-atom found in the specified location as 
+					output parameter.  Only matching sub-atoms are counted when calculating the highest
+					index.  
+
+@return	KErrNone 		if successful.  Otherwise, returns one of the system wide error codes. 
+		KErrGeneral		if an error has no specific categorisation;
+		KErrNotFound	if UDTA or wanted sub-atom is not available in asked location;
+		KErrAccessDenied	if cannot seek to UDTA atom location;
+		KErrArgument	if asked aUdtaLocation is invalid;
+		KErrOverflow	if the buffer to write atom to is too small. Use C3GPParse::GetUserDataAtomSize 
+						to retrieve the proper size.
+		KErrNotReady	if the parser has not yet been initialised; See C3GPParse::Open;
+		KErr3gpLibMoreDataRequired	if if 3GP library needs more data before the requested 
+						information can be returned.
+
+@panic C3GPParse	KErrArgument	if the location of user information is not in the range of T3GPUdtaLocation
+*/
+EXPORT_C TInt C3GPParse::GetUserDataAtom(TUint32 aType, T3GPUdtaLocation aLocation, TDes8& aBuffer, TUint& aAtomIndex) const
+	{
+	if (!iHandler)
+		{
+		return KErrNotReady;
+		}
+	if (aBuffer.MaxLength() <= 0)
+		{
+		return KErrOverflow;
+		}
+	
+	mp4_u32 userDataAtomSize = aBuffer.MaxLength();
+	mp4_u32 atomIndex = aAtomIndex;
+	mp4_u32 type = aType;
+	mp4_u8 location = UdtaLocation(aLocation);
+	MP4Err mp4Err = MP4ParseGetUserDataAtom(iHandler, location, type, 
+			const_cast<mp4_u8*>(aBuffer.Ptr()), userDataAtomSize, atomIndex);	
+	if ( mp4Err == MP4_OK )
+		{
+		aType = type;
+		aBuffer.SetLength(userDataAtomSize);
+		aAtomIndex = atomIndex;
+		}
+	return SymbianOSError(mp4Err);
+	}
+
+/**
+This function gets the next frame's dependency information from SDTP box.
+
+@param	aDependencies	Returns the next frame's dependency information. See T3GPFrameDependencies.
+
+@return	KErrNone 		if successful.  Otherwise, returns one of the system wide error codes. 
+		KErrGeneral		if an error has no specific categorisation;
+		KErrNotSupported	if the input does not contain video stream;
+		KErrNotReady	if the parser has not yet been initialised; See C3GPParse::Open;
+		KErr3gpLibMoreDataRequired	if if 3GP library needs more data before the requested 
+						information can be returned.
+*/
+EXPORT_C TInt C3GPParse::GetVideoFrameDependencies(T3GPFrameDependencies& aDependencies) const
+	{
+	if (!iHandler)
+		{
+		return KErrNotReady;
+		}
+	
+	// Check if 3GP input data contains video stream
+	TInt err = DoGetVideoProperties();	
+	if (err != KErrNone)
+		{
+		return err;
+		}
+	
+	mp4_u8 dependsOn;
+	mp4_u8 isDependedOn;
+	mp4_u8 hasRedundancy;	
+	MP4Err mp4Err = MP4ParseNextVideoFrameDependencies(iHandler, &dependsOn, &isDependedOn, &hasRedundancy);
+	if (mp4Err == MP4_OK)
+		{
+		switch (dependsOn)
+			{
+			case 1:
+				aDependencies.iDependsOn = E3GPDependencyExists;
+			break;
+			case 2:
+				aDependencies.iDependsOn = E3GPDependencyNone;
+			break;
+			case 0:
+				aDependencies.iDependsOn = E3GPDependencyUnknown;
+			break;
+			default:
+				Panic(KErrCorrupt);
+			}
+		
+		switch (isDependedOn)
+			{
+			case 1:
+				aDependencies.iIsDependedOn = E3GPDependencyExists;
+			break;
+			case 2:
+				aDependencies.iIsDependedOn = E3GPDependencyNone;
+			break;
+			case 0:
+				aDependencies.iIsDependedOn = E3GPDependencyUnknown;
+			break;
+			default:
+				Panic(KErrCorrupt);
+			}
+		
+		switch (hasRedundancy)
+			{
+			case 1:
+				aDependencies.iHasRedundancy = E3GPRedundancyExists;
+			break;
+			case 2:
+				aDependencies.iHasRedundancy = E3GPRedundancyNone;
+			break;
+			case 0:
+				aDependencies.iHasRedundancy = E3GPRedundancyUnknown;
+			break;
+			default:
+				Panic(KErrCorrupt);
+			}
+		}
+	return SymbianOSError(mp4Err);
+	}
+
+/**
+This function gets frame properties, from aStartIndex for a count of aNumberOfFrames frames.
+
+Properties obtained are start time, frame type, and frame size, stored in the T3GPFrameInfoParameters 
+struct.
+
+@param	aStartIndex		Index to start getting info for the array.
+@param	aNumberOfFrames	Number of frames to retrieve frame info.
+@param	aArray			An array of T3GPFrameInfoParameters struct to store video frame properties.  
+						The input array will be flushed of all existing elements before use.
+
+@return	KErrNone 		if successful.  Otherwise, returns one of the system wide error codes.
+		KErrGeneral		if an error has no specific categorisation;
+		KErrNotSupported	if the input does not contain video stream;		
+		KErrNoMemory	if an attempt to allocate memory has failed;
+		KErrAccessDenied	if opening file has failed;		
+		KErrNotReady	if the parser has not yet been initialised; See C3GPParse::Open.
+*/
+EXPORT_C TInt C3GPParse:: GetVideoFrameProperties(TUint aStartIndex, TUint aNumberOfFrames, 
+		RArray<T3GPFrameInfoParameters>& aArray) const
+	{
+	if (!iHandler)
+		{
+		return KErrNotReady;
+		}
+	
+	// Check if 3GP input data contains video stream
+	TInt err = DoGetVideoProperties();	
+	if (err != KErrNone)
+		{
+		return err;
+		}
+	
+	// Check if the input parameters are valid before retrieving video frame properties.
+	TUint totalNumOfVideoFrames;
+	err = GetNumberOfVideoFrames(totalNumOfVideoFrames);
+	if (err != KErrNone)
+		{
+		return err;
+		}
+	
+	if (aStartIndex >= totalNumOfVideoFrames || aNumberOfFrames > totalNumOfVideoFrames)	
+		{
+		return KErrGeneral;
+		}
+	
+	TFrameInfoParameters* infoArray = new TFrameInfoParameters[aNumberOfFrames];
+	
+	if (!infoArray)
+		{
+		return KErrNoMemory;
+		}
+
+	mp4_u32 startIndex = aStartIndex;
+	mp4_u32 numberOfFrames = aNumberOfFrames;
+	MP4Err mp4Err = MP4GetVideoFrameProperties(iHandler, startIndex, numberOfFrames, infoArray);
+
+	if ( mp4Err == MP4_OK )
+		{
+		aArray.Reset();
+		T3GPFrameInfoParameters infoParams; 
+		
+		for (TInt i=0; i<aNumberOfFrames; ++i)
+			{
+			infoParams.iSize = infoArray[i].iSize;
+			infoParams.iStartTime = infoArray[i].iStartTime;
+			infoParams.iIsRandomAccessPoint = infoArray[i].iType;
+			err = aArray.Append(infoParams);
+			if (err != KErrNone)
+				{
+				delete [] infoArray;
+				infoArray = NULL;
+				return err;
+				}
+			}		
+		}
+	else
+		{
+		err = SymbianOSError(mp4Err);
+		}
+	delete [] infoArray;
+	infoArray = NULL;
+	return err;
+	}
+
+/**
+This function reads the current video frame from an input file and returns it to the caller asynchronously.  
+The current position of video stream will be moved forward.
+
+This function is not supported when the parser is in buffer mode.
+
+C3GPParse::CancelReadFrame can be used to cancel an outstanding asynchronous frame read request.
+
+Note:  Only one asynchronous parse audio or video frame(s) operation can be ongoing at any given time.
+
+Upon completion, successfully or otherwise, the callback function M3GPParseCallback::VideoFrameAvailable is called.
+
+@param	aCallback	Reference to class derived from M3GPAsyncObserver designed to receive notification of 
+					asynchronous event completion.
+@param	aBuffer		The descriptor to store the video frames.
+*/
+EXPORT_C void C3GPParse::ReadVideoFrame(M3GPParseCallback& aCallback, TDes8& aBuffer)
+	{
+	if (!iHandler)
+		{
+		aCallback.VideoFrameAvailable(KErrNotReady, EFalse, 0, 0);
+		return;
+		}
+	if (aBuffer.MaxLength() <= 0)
+		{
+		aCallback.VideoFrameAvailable(KErrOverflow, EFalse, 0, 0);
+		return;
+		}
+	if (iAsyncReadBuffer)
+		{
+		aCallback.VideoFrameAvailable(KErrInUse, EFalse, 0, 0);
+		return;
+		}
+	
+	// Check if 3GP input data contains video stream
+	TInt err = DoGetVideoProperties();	
+	if (err != KErrNone)
+		{
+		aCallback.VideoFrameAvailable(err, EFalse, 0, 0);
+		return;
+		}
+	
+	iCallback = &aCallback;
+	mp4_u32 bufferSize = aBuffer.MaxLength();
+	MP4Err mp4Err = MP4ParseReadVideoFrameAsync(iHandler, this, 
+			const_cast<mp4_u8*>(aBuffer.Ptr()), &bufferSize);	
+	if (mp4Err != MP4_OK)
+		{
+		aCallback.VideoFrameAvailable(SymbianOSError(mp4Err), EFalse, 0, 0);
+		}
+	else
+		{
+		// MP4ParseReadVideoFrameAsync success. Store aBuffer since its length has
+		// not been set.
+		iAsyncReadBuffer = &aBuffer;
+		}
+	}
+
+/**
+This function reads the audio frames that are stored in the current audio sample from the input 
+file and returns them to the caller asynchronously.  The current position of audio stream 
+will be moved forward. 
+
+This function is not supported when the parser is in buffer mode.
+
+C3GPParse::CancelReadFrame can be used to cancel an outstanding asynchronous frame read request.
+
+Note:  Only one asynchronous parse audio or video frame(s) operation can be ongoing at any given time.
+
+Upon completion, successfully or otherwise, the callback function M3GPParseCallback::AudioFramesAvailable is called.
+
+@param	aCallback	Reference to class derived from M3GPAsyncObserver designed to receive notification of 
+					asynchronous event completion.
+@param	aBuffer		The descriptor to store the audio frames.
+*/
+EXPORT_C void C3GPParse::ReadAudioFrames(M3GPParseCallback& aCallback, TDes8& aBuffer)
+	{
+	if (!iHandler)
+		{
+		aCallback.AudioFramesAvailable(KErrNotReady, 0, 0, 0);
+		return;
+		}
+	if (aBuffer.MaxLength() <= 0)
+		{
+		aCallback.AudioFramesAvailable(KErrOverflow, 0, 0, 0);
+		return;
+		}
+	if (iAsyncReadBuffer)
+		{
+		aCallback.AudioFramesAvailable(KErrInUse, 0, 0, 0);
+		return;
+		}
+	
+	// Check if 3GP input data contains audio stream
+	TInt err = DoGetAudioProperties();	
+	if (err != KErrNone)
+		{
+		aCallback.AudioFramesAvailable(err, 0, 0, 0);
+		return;
+		}
+	
+	iCallback = &aCallback;
+	mp4_u32 bufferSize = aBuffer.MaxLength(); 
+	MP4Err mp4Err = MP4ParseReadAudioFramesAsync(iHandler, this, 
+			const_cast<mp4_u8*>(aBuffer.Ptr()), &bufferSize);	
+	if (mp4Err != MP4_OK)
+		{
+		aCallback.AudioFramesAvailable(SymbianOSError(mp4Err), 0, 0, 0);
+		}
+	else
+		{
+		// MP4ParseReadAudioFramesAsync success. Store aBuffer since its length has
+		// not been set.
+		iAsyncReadBuffer = &aBuffer;
+		}
+	}
+
+/**
+This function cancels the outstanding asynchronous read audio/video frame request. 
+
+No callback function will be called.
+
+Note:  As only one asynchronous parse audio or video frame(s) operation can be ongoing at any given time, 
+this function can be used to cancel audio or video read request.
+*/
+EXPORT_C void C3GPParse::CancelReadFrame()
+	{
+	if (!iHandler)
+		{
+		return;
+		}
+	if (iAsyncReadBuffer)
+		{
+		MP4CancelReadFrame(iHandler);
+		iAsyncReadBuffer = NULL;
+		iCallback = NULL;
+		}	
+	}
+
+// Receive asynchronous parse video frames operation completion notification.
+void C3GPParse::M3GPMP4LibVideoFrameAvailable(MP4Err aError, mp4_u32 aFrameSize, mp4_u32 aTimeStamp, 
+		mp4_bool aKeyFrame, mp4_u32 aTimestamp2)
+	{	
+	// Check if there is an outstanding asynchronous request
+	if (iAsyncReadBuffer)
+		{
+		if (aError == MP4_OK)
+			{
+			// Set the buffer length for the asynchronous read video frame
+			iAsyncReadBuffer->SetLength(aFrameSize);
+			}
+		iAsyncReadBuffer = NULL;
+		// Parser can send out the callback to the client
+		TBool keyFrame = aKeyFrame;
+		TUint timeStampInMs = aTimeStamp;
+		TUint timeStampInTimescale = aTimestamp2;	
+		iCallback->VideoFrameAvailable(SymbianOSError(aError), keyFrame, timeStampInMs, timeStampInTimescale);
+		}
+
+	iCallback = NULL;
+	}
+
+// Receive asyncronous parse audio frames operation completion notification.
+void C3GPParse::M3GPMP4LibAudioFramesAvailable(MP4Err aError, mp4_u32 aAudioSize, mp4_u32 aTimeStamp, 
+		mp4_u32 aReturnedFrames, mp4_u32 aTimestamp2)
+	{	
+	// Check if there is an outstanding asynchronous request	
+	if (iAsyncReadBuffer)
+		{
+		if (aError == MP4_OK)
+			{
+			// Set the buffer length for the asynchronous read audio frame
+			iAsyncReadBuffer->SetLength(aAudioSize);
+			}
+		iAsyncReadBuffer = NULL;
+		// Parser can send out the callback to the client
+		TUint returnedFrames = aReturnedFrames;
+		TUint timeStampInMs = aTimeStamp;
+		TUint timeStampInTimescale = aTimestamp2;
+		iCallback->AudioFramesAvailable(SymbianOSError(aError), returnedFrames, timeStampInMs, timeStampInTimescale);	
+		}
+
+	iCallback = NULL;
+	}
+
+// Helper function to convert c style error code to Symbian OS standard error code
+TInt C3GPParse::SymbianOSError(MP4Err aError) const
+	{
+	TInt error = KErrNone;
+	
+	switch (aError)
+		{
+		case (MP4_OK):
+		break;
+		case (MP4_ERROR):
+			error = KErrGeneral;
+		break;
+		case (MP4_OUT_OF_MEMORY):
+			error = KErrNoMemory;
+		break;
+		case (MP4_NOT_AVAILABLE):
+			error = KErr3gpLibMoreDataRequired;
+		break;
+		case (MP4_FILE_MODE):
+		case (MP4_NOT_STREAMABLE):
+		case (MP4_NO_VIDEO):
+		case (MP4_NO_AUDIO):
+			error = KErrNotSupported;
+		break;
+		case (MP4_BUFFER_TOO_SMALL):
+		case (MP4_OUTPUT_BUFFER_TOO_SMALL):
+			error = KErrOverflow;
+		break;
+		case (MP4_END_OF_VIDEO):
+			error = KErrEof;
+		break;
+		case (MP4_CANT_SEEK):
+		case (MP4_NO_FRAME):
+		case (MP4_NO_REQUESTED_FRAME):
+		case (MP4_UDTA_NOT_FOUND):
+			error = KErrNotFound;
+		break;
+		case (MP4_FILE_ERROR):
+			error = KErrAccessDenied;
+		break;
+		case (MP4_INVALID_INPUT_STREAM):
+			error = KErrCorrupt;
+		break;
+		case (MP4_INVALID_TYPE):
+			error = KErrArgument;
+		break;
+		default:
+		// Mapped all possible errors returned by the MP4_library. Anything else should NOT happen
+			Panic(KErrArgument);
+		}
+	return error;
+	}
+
+// Help function to get video properties
+TInt C3GPParse::DoGetVideoProperties() const
+	{
+	if (!iVideoPropertiesSaved || iVideoError == KErr3gpLibMoreDataRequired)
+		{
+		MP4Err mp4Err = MP4_OK;
+		mp4_u32 length = 0;
+		mp4_u32 type = 0;
+		mp4_u32 width = 0;
+		mp4_u32 height = 0;
+		mp4_u32 timeScale = 0;
+		mp4_double frameRate = 0;
+
+		mp4Err = MP4ParseRequestVideoDescription(iHandler, &length, &frameRate, &type, &width, &height, &timeScale);
+		iVideoPropertiesSaved = ETrue;
+		if (mp4Err == MP4_OK)
+			{
+			iVideoType = WrapperVideoType(type);
+			if (iVideoType == E3GPNoVideo)
+				{
+				iVideoError = KErrNotSupported;
+				return KErrNotSupported;
+				}
+			iVideoLength = length;
+			iVideoMp4Type = type; // Type of video stream			
+			iVideoSize.iWidth = width;
+			iVideoSize.iHeight = height;
+			iVideoTimeScale = timeScale;
+			iVideoFrameRate = frameRate;	
+			}
+		iVideoError = SymbianOSError(mp4Err);
+		}
+	return iVideoError;
+	}
+
+// Help function to get audio properties
+TInt C3GPParse::DoGetAudioProperties() const
+	{
+	if (!iAudioPropertiesSaved || iAudioError == KErr3gpLibMoreDataRequired)
+		{
+		MP4Err mp4Err = MP4_OK;
+		mp4_u32 audioLength = 0;
+		mp4_u32 audioType = 0;
+		mp4_u32 averateBitRate = 0;
+		mp4_u32 timeScale = 0;
+		mp4_u8 framesPerSample = 0;
+		
+		mp4Err = MP4ParseRequestAudioDescription(iHandler, &audioLength, &audioType, 
+				&framesPerSample, &timeScale, &averateBitRate);
+		iAudioPropertiesSaved = ETrue;
+		if (mp4Err == MP4_OK)
+			{
+			iAudioLength = audioLength;
+			iAudioMp4Type = audioType; // Type of audio stream
+			iAudioType = WrapperAudioType(audioType);
+			iAudioFramesPerSample = framesPerSample;
+			iAudioAvgBitRate = averateBitRate;
+			iAudioTimeScale = timeScale;
+			}
+		iAudioError = SymbianOSError(mp4Err);
+		}
+	return iAudioError;
+	}
+
+// Help function to get stream properties
+TInt C3GPParse::DoGetStreamProperties() const
+	{
+	if (!iStreamPropertiesSaved || iStreamError == KErr3gpLibMoreDataRequired)
+		{
+		MP4Err mp4Err = MP4_OK;
+		mp4_u32 streamSize = 0;
+		mp4_u32 streamAvgBitRate;
+		mp4Err = MP4ParseRequestStreamDescription(iHandler,&streamSize, &streamAvgBitRate);
+		iStreamPropertiesSaved = ETrue;
+		if (mp4Err == MP4_OK)
+			{
+			iStreamSize = streamSize;
+			iStreamAvgBitRate = streamAvgBitRate;
+			}
+		iStreamError = SymbianOSError(mp4Err);	
+		}
+	return iStreamError;
+	}
+
+// Helper function to map Mp4 enum type to T3GPVideoType for video
+T3GPVideoType C3GPParse::WrapperVideoType(TUint aType) const
+	{
+	T3GPVideoType videoType = E3GPNoVideo;
+	switch (aType)
+		{
+		case (MP4_TYPE_MPEG4_VIDEO):
+			videoType = E3GPMpeg4Video;
+		break;
+		case (MP4_TYPE_H263_PROFILE_0):
+			videoType = E3GPH263Profile0;
+		break;
+		case (MP4_TYPE_H263_PROFILE_3):
+			videoType = E3GPH263Profile3;
+		break;
+		case (MP4_TYPE_AVC_PROFILE_BASELINE):
+			videoType = E3GPAvcProfileBaseline;
+		break;
+		case (MP4_TYPE_AVC_PROFILE_MAIN):
+			videoType = E3GPAvcProfileMain;
+		break;
+		case (MP4_TYPE_AVC_PROFILE_EXTENDED):
+			videoType = E3GPAvcProfileExtended;
+		break;
+		
+		case (MP4_TYPE_AVC_PROFILE_HIGH):
+			videoType = E3GPAvcProfileHigh;
+		break;
+		case MP4_TYPE_NONE:
+		break;
+		default:
+			Panic(KErrCorrupt); // This should not happen.
+		break;
+		}
+	return videoType;
+	}
+
+// Helper function to map Mp4 enum type to T3GPAudioType for audio
+T3GPAudioType C3GPParse::WrapperAudioType(TUint aType) const
+	{
+	T3GPAudioType audioType = E3GPNoAudio;
+	switch (aType)
+		{
+		case (MP4_TYPE_MPEG4_AUDIO):
+			audioType = E3GPMpeg4Audio;
+		break;
+		case (MP4_TYPE_AMR_NB):
+			audioType = E3GPAmrNB;
+		break;
+		case (MP4_TYPE_AMR_WB):
+			audioType = E3GPAmrWB;
+		break;
+		case (MP4_TYPE_QCELP_13K):
+			audioType = E3GPQcelp13K;
+		break;
+		default:
+			Panic(KErrCorrupt); // This should not happen.
+		}
+	return audioType;
+	}
+
+// Helper function to map enum type of the location of the user data in the file
+mp4_u8 C3GPParse::UdtaLocation(T3GPUdtaLocation aLocation) const
+	{
+	mp4_u8 location  = MP4_UDTA_NONE;
+	
+	switch (aLocation )
+		{
+		case (E3GPUdtaMoov):
+			location = MP4_UDTA_MOOV;
+		break;
+		case (E3GPUdtaVideoTrak):
+			location = MP4_UDTA_VIDEOTRAK;
+		break;
+		case (E3GPUdtaAudioTrak):
+			location = MP4_UDTA_AUDIOTRAK;
+		break;
+		default:
+			Panic(KErrArgument);
+		}
+	return location;
+	}
+
+
+void C3GPParse::Panic(TInt aPanic)
+	// Panic client
+	{
+	_LIT(K3GPParsePanicName, "C3GPParse");
+	User::Panic(K3GPParsePanicName, aPanic);
+	}