--- /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, ×tamp2);
+
+ 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);
+ }