1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/mm/mmplugins/lib3gp/wrapper/src/c3gpparse.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,2161 @@
1.4 +// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +//
1.18 +
1.19 +#include <c3gplibrary.h>
1.20 +
1.21 +/**
1.22 +Creates an instance of a 3GP Parser for reading 3GP/3G2/MP4 data using default buffer size.
1.23 +
1.24 +The default value for read buffer size is 8k.
1.25 +
1.26 +@return A pointer to the newly created 3gp parse object.
1.27 +
1.28 +@leave KErrNoMemory Out of memory.
1.29 +*/
1.30 +EXPORT_C C3GPParse* C3GPParse::NewL()
1.31 + {
1.32 + C3GPParse* self = new (ELeave) C3GPParse();
1.33 + return self;
1.34 + }
1.35 +
1.36 +/**
1.37 +Creates an instance of a 3GP Parser for reading 3GP/3G2/MP4 data, and sets the
1.38 +internal file read buffer size.
1.39 +
1.40 +@param aReadBufferSize Size of file read buffer.
1.41 +
1.42 +@return A pointer to the newly created 3gp parse object.
1.43 +
1.44 +@leave KErrNoMemory Out of memory.
1.45 +@leave KErrGeneral General error.
1.46 +
1.47 +@panic C3GPParse KErrArgument if size of file read buffer is not greater than 0.
1.48 +*/
1.49 +EXPORT_C C3GPParse* C3GPParse::NewL(TInt aReadBufferSize)
1.50 + {
1.51 + __ASSERT_ALWAYS((aReadBufferSize > 0), Panic(KErrArgument));
1.52 + C3GPParse* self = new (ELeave) C3GPParse(aReadBufferSize);
1.53 + return self;
1.54 + }
1.55 +
1.56 +// First phase constructor
1.57 +C3GPParse::C3GPParse(TInt aReadBufferSize) :
1.58 + iReadBufferSize(aReadBufferSize),
1.59 + iDuplicateFileHandleCreated(EFalse),
1.60 + iVideoType(E3GPNoVideo),
1.61 + iAudioType(E3GPNoAudio)
1.62 + {
1.63 + }
1.64 +
1.65 +/**
1.66 +This function initialises the 3GP Parser for reading 3GP/3G2/MP4 data from a buffer and expects data
1.67 +to be inserted through subsequent calls to C3GPParse::InsertData.
1.68 +
1.69 +@see C3GPParse::InsertData
1.70 +
1.71 +@return KErrNone if successful. Otherwise, returns one of the system wide error codes.
1.72 + KErrGeneral if an error has no specific categorisation;
1.73 + KErrNoMemory if an attempt to allocate memory has failed;
1.74 + KErrInUse if the parser is currently engaged; C3GPParse::Complete must be called to
1.75 + finish the parsing activities before the parser can be re-initialised again.
1.76 +*/
1.77 +EXPORT_C TInt C3GPParse::Open()
1.78 + {
1.79 + if (iHandler)
1.80 + {
1.81 + return KErrInUse;
1.82 + }
1.83 +
1.84 + return SymbianOSError(MP4ParseOpen(&iHandler, NULL));
1.85 + }
1.86 +
1.87 +/**
1.88 +This function initialises the 3GP Parser for reading 3GP/3G2/MP4 data from a file.
1.89 +
1.90 +@param aFilename A full path name of the file containing the data.
1.91 +
1.92 +@return KErrNone if successful. Otherwise, returns one of the system wide error codes.
1.93 + KErrGeneral if an error has no specific categorisation;
1.94 + KErrNoMemory if an attempt to allocate memory has failed;
1.95 + KErrAccessDenied if opening file has failed;
1.96 + KErrUnderflow if the file name length is not greater than 0;
1.97 + KErrInUse if the parser is currently engaged; C3GPParse::Complete must be called to
1.98 + finish the parsing activities before the parser can be re-initialised again.
1.99 +*/
1.100 +EXPORT_C TInt C3GPParse::Open(const TDesC& aFilename)
1.101 + {
1.102 + if (iHandler)
1.103 + {
1.104 + return KErrInUse;
1.105 + }
1.106 + if (aFilename.Length() <= 0)
1.107 + {
1.108 + return KErrUnderflow;
1.109 + }
1.110 +
1.111 + // Create a zero terminated version of the file name
1.112 + RBuf fileName;
1.113 + TInt err = fileName.Create(aFilename.Length() + 1);
1.114 + if (err == KErrNone)
1.115 + {
1.116 + fileName.Copy(aFilename);
1.117 + mp4_u16* mp4FileName = const_cast<mp4_u16*>(fileName.PtrZ());
1.118 + MP4Err mp4Err = MP4ParseOpen(&iHandler, reinterpret_cast<MP4FileName>(mp4FileName));
1.119 +
1.120 + if (mp4Err == MP4_OK)
1.121 + {
1.122 + // Set composing related values to 0.
1.123 + mp4Err = MP4SetCustomFileBufferSizes(iHandler, 0, 0, iReadBufferSize);
1.124 + if (mp4Err != MP4_OK)
1.125 + {
1.126 + // Ignore the error
1.127 + Complete();
1.128 + }
1.129 + }
1.130 + err = SymbianOSError(mp4Err);
1.131 + }
1.132 + fileName.Close();
1.133 + return err;
1.134 + }
1.135 +
1.136 +/**
1.137 +This function initialises the 3GP Parser for reading 3GP/3G2/MP4 data from a file.
1.138 +
1.139 +@param aFile File handle of the file containing the data. It is expected to be a valid file handle,
1.140 + opened and will be closed outside of the library.
1.141 +
1.142 +@return KErrNone if successful. Otherwise, returns one of the system wide error codes.
1.143 + KErrNoMemory if an attempt to allocate memory has failed;
1.144 + KErrInUse if the parser is currently engaged; C3GPParse::Complete must be called to
1.145 + finish the parsing activities before the parser can be re-initialised again.
1.146 +*/
1.147 +EXPORT_C TInt C3GPParse::Open(const RFile& aFile)
1.148 + {
1.149 + TInt err = KErrNone;
1.150 + if (!iDuplicateFileHandleCreated)
1.151 + {
1.152 + iDuplicateFileHandleCreated = ETrue;
1.153 + iFile.Close();
1.154 + err = iFile.Duplicate(aFile);
1.155 + if (err != KErrNone)
1.156 + {
1.157 + return err;
1.158 + }
1.159 + }
1.160 +
1.161 + return Open(iFile);
1.162 + }
1.163 +/**
1.164 +This function initialises the 3GP Parser for reading 3GP/3G2/MP4 data from a file.
1.165 +
1.166 +@param aFile File handle of the file containing the data. It is expected to be a valid file handle,
1.167 + opened and will be closed outside of the library.
1.168 +
1.169 +@return KErrNone if successful. Otherwise, returns one of the system wide error codes.
1.170 + KErrNoMemory if an attempt to allocate memory has failed;
1.171 + KErrInUse if the parser is currently engaged; C3GPParse::Complete must be called to
1.172 + finish the parsing activities before the parser can be re-initialised again.
1.173 +*/
1.174 +EXPORT_C TInt C3GPParse::Open(const RFile64& aFile)
1.175 + {
1.176 + if (iHandler)
1.177 + {
1.178 + return KErrInUse;
1.179 + }
1.180 +
1.181 + const RFile64* file = &aFile;
1.182 + MP4Err mp4Err = MP4ParseOpenFileHandle64(&iHandler, (const_cast<RFile64*>(file)));
1.183 + if (mp4Err == MP4_OK)
1.184 + {
1.185 + // Set composing related values to 0.
1.186 + mp4Err = MP4SetCustomFileBufferSizes(iHandler, 0, 0, iReadBufferSize);
1.187 + if (mp4Err != MP4_OK)
1.188 + {
1.189 + // Ignore the error
1.190 + Complete();
1.191 + }
1.192 + }
1.193 +
1.194 + return SymbianOSError(mp4Err);
1.195 + }
1.196 +
1.197 +/**
1.198 +This function initialises the 3GP Parser for reading 3GP/3G2/MP4 data from a CAF object.
1.199 +
1.200 +@param aData A CData object pointing to a CAF object. It is expected to be opened and will be
1.201 + closed outside of the library.
1.202 +
1.203 +@return KErrNone if successful. Otherwise, returns one of the system wide error codes.
1.204 + KErrNoMemory if an attempt to allocate memory has failed;
1.205 + KErrInUse if the parser is currently engaged; C3GPParse::Complete must be called to
1.206 + finish the parsing activities before the parser can be re-initialised again.
1.207 +*/
1.208 +EXPORT_C TInt C3GPParse::Open(const ContentAccess::CData& aData)
1.209 + {
1.210 + if (iHandler)
1.211 + {
1.212 + return KErrInUse;
1.213 + }
1.214 +
1.215 + MP4Err mp4Err = MP4ParseOpenCAF(&iHandler, const_cast<ContentAccess::CData*>(&aData));
1.216 +
1.217 + if (mp4Err == MP4_OK)
1.218 + {
1.219 + // Set composing related values to 0.
1.220 + mp4Err = MP4SetCustomFileBufferSizes(iHandler, 0, 0, iReadBufferSize);
1.221 + if (mp4Err != MP4_OK)
1.222 + {
1.223 + // Ignore the error
1.224 + Complete();
1.225 + }
1.226 + }
1.227 +
1.228 + return SymbianOSError(mp4Err);
1.229 + }
1.230 +
1.231 +/**
1.232 +Destructor. Deletes all objects.
1.233 +*/
1.234 +EXPORT_C C3GPParse::~C3GPParse()
1.235 + {
1.236 + Complete(); // Ignore the error
1.237 + }
1.238 +
1.239 +/**
1.240 +This function completes the parsing operation.
1.241 +
1.242 +If C3GPParse::Complete is called before the parse is initialised, it will be ignored and KErrNone is
1.243 +returned.
1.244 +
1.245 +The parser can be reused again after this call, following another call to C3GPParse::Open to
1.246 +re-initialise the parser.
1.247 +
1.248 +@return KErrNone if successful. Otherwise, returns one of the system wide error codes.
1.249 + KErrGeneral if an error has no specific categorisation;
1.250 +*/
1.251 +EXPORT_C TInt C3GPParse::Complete()
1.252 + {
1.253 + MP4Err mp4Err = MP4_OK;
1.254 + if (iHandler)
1.255 + {
1.256 + mp4Err = MP4ParseClose(iHandler);
1.257 + }
1.258 +
1.259 + if (iAsyncReadBuffer)
1.260 + {
1.261 + CancelReadFrame();
1.262 + }
1.263 +
1.264 + // Always reset the class member data even MP4ParseClose returns error
1.265 + Reset();
1.266 + return SymbianOSError(mp4Err);
1.267 + }
1.268 +
1.269 +// Helper function to reset class member data.
1.270 +void C3GPParse::Reset()
1.271 + {
1.272 + iVideoType = E3GPNoVideo;
1.273 + iAudioType = E3GPNoAudio;
1.274 + iAsyncReadBuffer = NULL;
1.275 + iCallback = NULL; // Parse doesn't own the callback. Set it to NULL.
1.276 + iAudioAvgBitRate = 0;
1.277 + iStreamAvgBitRate = 0;
1.278 + iVideoPropertiesSaved = EFalse;
1.279 + iAudioPropertiesSaved = EFalse;
1.280 + iStreamPropertiesSaved = EFalse;
1.281 + iVideoError = KErrNone;
1.282 + iAudioError = KErrNone;
1.283 + iStreamError = KErrNone;
1.284 + iHandler = NULL;
1.285 + iDuplicateFileHandleCreated = EFalse;
1.286 + iFile.Close();
1.287 + }
1.288 +
1.289 +/**
1.290 +This function inserts MP4/3GP/3G2 data into the parser.
1.291 +
1.292 +It is only necessary to call this function if no parameter has been supplied when
1.293 +C3GPParse::Open is called. Several functions can return KErr3gpLibMoreDataRequired if the library
1.294 +does not have enough data to return the information that the caller requests. In this case, more data
1.295 +needs to be inserted to the library before calling those functions again.
1.296 +
1.297 +This function makes a copy of the data inserted into the library so the caller can use the input buffer
1.298 +for other purposes. If the function returns KErrNoMemory, the buffer contents have not been copied into
1.299 +the library and the caller needs to reduce the buffer content before calling again.
1.300 +
1.301 +If an empty string is supplied for the argument aBuffer, it indicates that there is be no more data
1.302 +to feed through this function. Such a function call must be done to indicate that all 3GP/MP4/3G2
1.303 +data has been written to the library's internal memory.
1.304 +
1.305 +@param aBuffer The descriptor containing the data to be inserted.
1.306 +
1.307 +@return KErrNone if successful. Otherwise, returns one of the system wide error codes.
1.308 + KErrGeneral if an error has no specific categorisation;
1.309 + KErrNoMemory if parser cannot allocate enough memory for the data;
1.310 + KErrNotReady if the parser has not yet been initialised; See C3GPParse::Open.
1.311 +*/
1.312 +EXPORT_C TInt C3GPParse::InsertData(const TDesC8& aBuffer)
1.313 + {
1.314 + if (!iHandler)
1.315 + {
1.316 + return KErrNotReady;
1.317 + }
1.318 +
1.319 + return SymbianOSError(MP4ParseWriteData(iHandler, const_cast<mp4_u8*>(aBuffer.Ptr()), aBuffer.Length()));
1.320 + }
1.321 +
1.322 +/**
1.323 +This function returns the parameters describing the video stream.
1.324 +
1.325 +If no file or CAF object is supplied during parser initialisation, this should be called after
1.326 +enough data has been inserted into the library buffers so that the 3GP headers containing the
1.327 +information can be read.
1.328 +
1.329 +The aFrameRate parameter refers to the frame rate of the original video material.
1.330 +
1.331 +@param aType The type of video stream. Refer to T3GPVideoType for supported video type.
1.332 +@param aLength Duration of video in milliseconds.
1.333 +@param aFrameRate Average frame rate of video (in Hz).
1.334 +@param aAvgBitRate Average bit rate of video.
1.335 +@param aSize Width and height of video image measured in pixels.
1.336 +@param aTimeScale Timescale of video track.
1.337 +
1.338 +@return KErrNone if successful. Otherwise, returns one of the system wide error codes.
1.339 + KErrGeneral if an error has no specific categorisation;
1.340 + KErrNotSupported if the input does not contain video;
1.341 + KErrCorrupt if 3GP stream is invalid;
1.342 + KErrNotReady if the parser has not yet been initialised; See C3GPParse::Open;
1.343 + KErr3gpLibMoreDataRequired if more data is required before the requested information can be
1.344 + retrieved; See C3GPParse::InsertData.
1.345 +*/
1.346 +EXPORT_C TInt C3GPParse::GetVideoProperties(T3GPVideoType& aType, TUint& aLength, TReal& aFrameRate,
1.347 + TUint& aAvgBitRate, TSize& aSize, TUint& aTimeScale) const
1.348 + {
1.349 + if (!iHandler)
1.350 + {
1.351 + return KErrNotReady;
1.352 + }
1.353 +
1.354 + TInt err = DoGetVideoProperties();
1.355 +
1.356 + if (err == KErrNone)
1.357 + {
1.358 + aLength = iVideoLength;
1.359 + aType = iVideoType;
1.360 + aFrameRate = iVideoFrameRate;
1.361 + aSize.iWidth = iVideoSize.iWidth;
1.362 + aSize.iHeight = iVideoSize.iHeight;
1.363 + aTimeScale = iVideoTimeScale;
1.364 + }
1.365 + else
1.366 + {
1.367 + return err;
1.368 + }
1.369 +
1.370 + // Get average bit rate of the stream in bps
1.371 + err = DoGetStreamProperties();
1.372 + if (err != KErrNone)
1.373 + {
1.374 + return err;
1.375 + }
1.376 +
1.377 + // Video average bit rate is calculated from GetStreamDescription’s aAvgBitRate substructs Audio’s aAvgBitRate
1.378 + // GetAudioProperties has not been called
1.379 + err = DoGetAudioProperties();
1.380 + if (err == KErrNone)
1.381 + {
1.382 + aAvgBitRate = iStreamAvgBitRate - iAudioAvgBitRate;
1.383 + }
1.384 + else
1.385 + {
1.386 + // if the audio stream is not usable, ignore the error since the stream
1.387 + // in concern is video stream. The audio stream error can be dealt with by
1.388 + // users when it asks for audio properties.
1.389 + aAvgBitRate = iStreamAvgBitRate;
1.390 + }
1.391 +
1.392 + return KErrNone;
1.393 + }
1.394 +
1.395 +/**
1.396 +This function returns the parameters describing the audio stream.
1.397 +
1.398 +If no file or CAF object is supplied during parser initialisation, this should be called after
1.399 +enough data has been inserted into the library so that the 3GP headers containing the information
1.400 +can be read.
1.401 +
1.402 +@param aType The type of audio stream. Refer to T3GPFrameType for supported audio type values.
1.403 +@param aLength Duration of audio in milliseconds.
1.404 +@param aFramesPerSample Number of audio frames in each sample.
1.405 +@param aAvgBitRate Average bit rate of audio.
1.406 +@param aTimeScale Timescale of audio track.
1.407 +
1.408 +@return KErrNone if successful. Otherwise, returns one of the system wide error codes.
1.409 + KErrGeneral if an error has no specific categorisation;
1.410 + KErrNotSupported if input does not contain audio;
1.411 + KErrCorrupt if 3GP stream is invalid;
1.412 + KErrNotReady if the parser has not yet been initialised; See C3GPParse::Open;
1.413 + KErr3gpLibMoreDataRequired if more data is required before the requested information can be
1.414 + retrieved. See C3GPParse::InsertData.
1.415 +*/
1.416 +EXPORT_C TInt C3GPParse::GetAudioProperties(T3GPAudioType& aType, TUint& aLength, TInt& aFramesPerSample,
1.417 + TUint& aAvgBitRate, TUint& aTimeScale) const
1.418 + {
1.419 + if (!iHandler)
1.420 + {
1.421 + return KErrNotReady;
1.422 + }
1.423 +
1.424 + TInt err = DoGetAudioProperties();
1.425 +
1.426 + if (err == KErrNone)
1.427 + {
1.428 + aLength = iAudioLength;
1.429 + aType = iAudioType;
1.430 + aFramesPerSample = iAudioFramesPerSample;
1.431 + aAvgBitRate = iAudioAvgBitRate;
1.432 + aTimeScale = iAudioTimeScale;
1.433 + iAudioPropertiesSaved = ETrue;
1.434 + }
1.435 +
1.436 + return err;
1.437 + }
1.438 +
1.439 +/**
1.440 +This function returns the parameters that describe the contents of the input file or buffer.
1.441 +
1.442 +If no file or CAF object is supplied during parser initialisation, this should be called after
1.443 +enough data has been inserted into the library so that the headers containing the information can
1.444 +be read.
1.445 +
1.446 +@param aSize Length of the stream in bytes.
1.447 +@param aAvgBitRate Average bit rate of the stream in bps.
1.448 +
1.449 +@return KErrNone if successful. Otherwise, returns one of the system wide error codes.
1.450 + KErrGeneral if an error has no specific categorisation;
1.451 + KErrCorrupt if 3GP stream is invalid;
1.452 + KErrNotReady if the parser has not yet been initialised; See C3GPParse::Open;
1.453 + KErr3gpLibMoreDataRequired if more data is required before the requested information can be
1.454 + retrieved. See C3GPParse::InsertData.
1.455 + */
1.456 +EXPORT_C TInt C3GPParse::GetContainerProperties(TUint& aSize, TUint& aAvgBitRate) const
1.457 + {
1.458 + if (!iHandler)
1.459 + {
1.460 + return KErrNotReady;
1.461 + }
1.462 +
1.463 + TInt err = DoGetStreamProperties();
1.464 + if (err == KErrNone)
1.465 + {
1.466 + aSize = iStreamSize;
1.467 + aAvgBitRate = iStreamAvgBitRate;
1.468 + }
1.469 +
1.470 + return err;
1.471 + }
1.472 +
1.473 +/**
1.474 +This function returns the number of bytes that the library instance has in its allocated buffers.
1.475 +
1.476 +The function is only valid when the parser is initialized without any parameters. Zero is
1.477 +returned when in file mode, that is, the parser has been initialized with a valid filename, file handle
1.478 +or a CAF object.
1.479 +
1.480 +@see C3GPParse::InsertData.
1.481 +
1.482 +@param aNum Number of allocated bytes in the library.
1.483 +
1.484 +@return KErrNone if successful. Otherwise, returns one of the system wide error codes.
1.485 + KErrGeneral if an error has no specific categorisation;
1.486 + KErrNotSupported if the parser has been initialised with a file name or file handle;
1.487 + KErrNotReady if the parser has not yet been initialised; See C3GPParse::Open.
1.488 +*/
1.489 +EXPORT_C TInt C3GPParse::GetNumBufferedBytes(TInt& aNum) const
1.490 + {
1.491 + if (!iHandler)
1.492 + {
1.493 + return KErrNotReady;
1.494 + }
1.495 +
1.496 + mp4_u32 numBytes = 0;
1.497 + MP4Err mp4Err = MP4ParseGetBufferedBytes(iHandler, &numBytes);
1.498 + aNum = numBytes;
1.499 +
1.500 + return SymbianOSError(mp4Err);
1.501 + }
1.502 +
1.503 +/**
1.504 +This function returns the type of the next audio/video frame in the stream.
1.505 +
1.506 +This function has no effect on the parser’s current position.
1.507 +
1.508 +@param aType Type of the next frame. Refer to the definition of T3GPFrameType for all possible values.
1.509 +
1.510 +@return KErrNone if successful. Otherwise, returns one of the system wide error codes.
1.511 + KErrGeneral if an error has no specific categorisation;
1.512 + KErrNotFound if frame does not exist (the previous frame was the last one);
1.513 + KErrNotReady if the parser has not yet been initialised; See C3GPParse::Open;
1.514 + KErrCorrupt if 3GP stream is invalid;
1.515 + KErr3gpLibMoreDataRequired if 3GP library needs more data before the requested
1.516 + information can be returned.
1.517 +*/
1.518 +EXPORT_C TInt C3GPParse::GetFrameType(T3GPFrameType& aType) const
1.519 + {
1.520 + if (!iHandler)
1.521 + {
1.522 + return KErrNotReady;
1.523 + }
1.524 + mp4_u32 frameType = 0;
1.525 + MP4Err mp4Err = MP4ParseNextFrameType(iHandler, &frameType);
1.526 + if (mp4Err == MP4_OK)
1.527 + {
1.528 + if (
1.529 + frameType == MP4_TYPE_MPEG4_VIDEO ||
1.530 + frameType == MP4_TYPE_H263_PROFILE_0 ||
1.531 + frameType == MP4_TYPE_H263_PROFILE_3 ||
1.532 + frameType == MP4_TYPE_AVC_PROFILE_BASELINE ||
1.533 + frameType == MP4_TYPE_AVC_PROFILE_MAIN ||
1.534 + frameType == MP4_TYPE_AVC_PROFILE_EXTENDED ||
1.535 + frameType == MP4_TYPE_AVC_PROFILE_HIGH
1.536 + )
1.537 + {
1.538 + aType = E3GPVideo;
1.539 + }
1.540 + else if (frameType == MP4_TYPE_MPEG4_AUDIO || frameType == MP4_TYPE_AMR_NB ||
1.541 + frameType == MP4_TYPE_AMR_WB || frameType == MP4_TYPE_QCELP_13K)
1.542 + {
1.543 + aType = E3GPAudio;
1.544 + }
1.545 + else
1.546 + {
1.547 + // This should not happen
1.548 + Panic(KErrCorrupt);
1.549 + }
1.550 + }
1.551 + return SymbianOSError(mp4Err);
1.552 + }
1.553 +
1.554 +/**
1.555 +This function returns the size of the immediate next video frame based on the current
1.556 +position of the parser.
1.557 +
1.558 +Calling this function does not change the current position of the parser.
1.559 +
1.560 +@param aSize Size of the next video frame in bytes.
1.561 +
1.562 +@return KErrNone if successful. Otherwise, returns one of the system wide error codes.
1.563 + KErrGeneral if an error has no specific categorisation;
1.564 + KErrNotSupported if the input does not contain video;
1.565 + KErrCorrupt if 3GP stream is invalid;
1.566 + KErrNotReady if the parser has not yet been initialised; See C3GPParse::Open;
1.567 + KErr3gpLibMoreDataRequired if 3GP library needs more data before the requested
1.568 + information can be returned.
1.569 +*/
1.570 +EXPORT_C TInt C3GPParse::GetVideoFrameSize(TUint& aSize) const
1.571 + {
1.572 + if (!iHandler)
1.573 + {
1.574 + return KErrNotReady;
1.575 + }
1.576 +
1.577 + // Check if 3GP input data contains video stream
1.578 + TInt err = DoGetVideoProperties();
1.579 + if (err != KErrNone)
1.580 + {
1.581 + return err;
1.582 + }
1.583 +
1.584 + // video type from 3GP file header has been saved
1.585 + mp4_u32 frameSize = 0;
1.586 + MP4Err mp4Err = MP4ParseNextFrameSize(iHandler, iVideoMp4Type, &frameSize);
1.587 + if (mp4Err == MP4_OK)
1.588 + {
1.589 + aSize = frameSize;
1.590 + }
1.591 +
1.592 + return SymbianOSError(mp4Err);
1.593 + }
1.594 +
1.595 +/**
1.596 +This function returns the total size of the audio frames in the immediate audio sample based on the
1.597 +current position of the parser.
1.598 +
1.599 +This function has no effect on the parser’s current position.
1.600 +
1.601 +@param aSize Size of the next audio sample in bytes.
1.602 +
1.603 +@return KErrNone if successful. Otherwise, returns one of the system wide error codes.
1.604 + KErrGeneral if an error has no specific categorisation;
1.605 + KErrNotSupported if the input does not contain audio;
1.606 + KErrCorrupt if 3GP stream is invalid;
1.607 + KErrNotReady if the parser has not yet been initialised; See C3GPParse::Open;
1.608 + KErr3gpLibMoreDataRequired if 3GP library needs more data before the requested
1.609 + information can be returned.
1.610 +*/
1.611 +EXPORT_C TInt C3GPParse::GetAudioFramesSize(TUint& aSize) const
1.612 + {
1.613 + if (!iHandler)
1.614 + {
1.615 + return KErrNotReady;
1.616 + }
1.617 +
1.618 + // Check if 3GP input data contains audio stream
1.619 + TInt err = DoGetAudioProperties();
1.620 + if (err != KErrNone)
1.621 + {
1.622 + return err;
1.623 + }
1.624 +
1.625 + // audio type from 3GP file header has been saved. Directely use iAudioMp4Type as input
1.626 + mp4_u32 frameSize = 0;
1.627 +
1.628 + MP4Err mp4Err = MP4ParseNextFrameSize(iHandler, iAudioMp4Type, &frameSize);
1.629 + if (mp4Err == MP4_OK)
1.630 + {
1.631 + aSize = frameSize;
1.632 + }
1.633 +
1.634 + return SymbianOSError(mp4Err);
1.635 + }
1.636 +
1.637 +/**
1.638 +This function reads the next video frame from the 3GP file/stream and returns it to the caller.
1.639 +The current position of video stream will be moved forward.
1.640 +
1.641 +The next frame depends on the position in the input 3GP file. C3GPParse::Seek can be used to change
1.642 +the current position in the 3GP file.
1.643 +
1.644 +If the function returns KErr3gpLibMoreDataRequired, the caller needs to call C3GPParse::InsertData
1.645 +to insert more data before calling the function again.
1.646 +
1.647 +Since there are separate cursors for storing current positions of video and audio streams, calling this
1.648 +function does not affect the position of the next audio stream.
1.649 +
1.650 +@param aBuffer Video frame is returned here.
1.651 +@param aKeyFrame Returns ETrue if the current frame is a key frame (intra), otherwise the value is EFalse.
1.652 +@param aTimeStampInMs Video frame presentation time in milliseconds from the beginning of the video sequence.
1.653 +@param aTimeStampInTimescale Video frame presentation time in timescale from the beginning of the video sequence.
1.654 +
1.655 +@return KErrNone if successful. Otherwise, returns one of the system wide error codes.
1.656 + KErrGeneral if an error has no specific categorisation;
1.657 + KErrNotSupported if the 3GP input data contains no video stream;
1.658 + KErrNotFound if frame does not exist (the previous frame was the last one);
1.659 + KErrOverflow if requested frame does not fit into the given buffer; Caller can use
1.660 + C3GPParse::GetVideoFrameSize to retrieve the minimum buffer size needed
1.661 + to fit this video frame;
1.662 + KErrCorrupt if 3GP stream is invalid;
1.663 + KErrNotReady if the parser has not yet been initialised; See C3GPParse::Open;
1.664 + KErr3gpLibMoreDataRequired if 3GP library needs more data before the requested
1.665 + information can be returned.
1.666 +*/
1.667 +EXPORT_C TInt C3GPParse::ReadVideoFrame(TDes8& aBuffer, TBool& aKeyFrame, TUint& aTimeStampInMs,
1.668 + TUint& aTimeStampInTimescale) const
1.669 + {
1.670 + if (!iHandler)
1.671 + {
1.672 + return KErrNotReady;
1.673 + }
1.674 + if (aBuffer.MaxLength() <= 0)
1.675 + {
1.676 + return KErrOverflow;
1.677 + }
1.678 +
1.679 + // Check if 3GP input data contains video stream
1.680 + TInt err = DoGetVideoProperties();
1.681 + if (err != KErrNone)
1.682 + {
1.683 + return err;
1.684 + }
1.685 +
1.686 + mp4_u32 frameSize = 0;
1.687 + mp4_u32 timeStamp = 0;
1.688 + mp4_bool keyFrame = EFalse;
1.689 + mp4_u32 timestamp2 = 0;
1.690 +
1.691 + MP4Err mp4Err = MP4ParseReadVideoFrame(iHandler, const_cast<mp4_u8*>(aBuffer.Ptr()), aBuffer.MaxLength(),
1.692 + &frameSize, &timeStamp, &keyFrame, ×tamp2);
1.693 +
1.694 + if (mp4Err == MP4_OK)
1.695 + {
1.696 + aBuffer.SetLength(frameSize);
1.697 + aKeyFrame = keyFrame;
1.698 + aTimeStampInMs = timeStamp;
1.699 + aTimeStampInTimescale = timestamp2;
1.700 + }
1.701 + return SymbianOSError(mp4Err);
1.702 + }
1.703 +
1.704 +/**
1.705 +Return size of video DecoderSpecificInfo.
1.706 +For files with MPEG-4 video this data is read from the esds atom. For files with AVC video
1.707 +this data is read from the avcC atom.
1.708 +
1.709 +Note: Only MPEG-4 video and H.264/AVC video streams contain DecoderSpecificInfo.
1.710 +
1.711 +@param aSize Size of video DecoderSpecificInfo.
1.712 +
1.713 +@return KErrNone if successful. Otherwise, returns one of the system wide error codes.
1.714 + KErrGeneral if an error has no specific categorisation;
1.715 + KErrNotSupported if the 3GP input data contains no MPEG-4 / AVC video stream;
1.716 + KErrCorrupt if 3GP stream is invalid;
1.717 + KErrNotReady if the parser has not yet been initialised; See C3GPParse::Open;
1.718 + KErr3gpLibMoreDataRequired if 3GP library needs more data before the requested
1.719 + information can be returned.
1.720 +*/
1.721 +EXPORT_C TInt C3GPParse::GetVideoDecoderSpecificInfoSize(TInt& aSize) const
1.722 + {
1.723 + if (!iHandler)
1.724 + {
1.725 + return KErrNotReady;
1.726 + }
1.727 +
1.728 + // Check if 3GP input data contains video stream and the video type is either
1.729 + // MPEG-4 or H.264/AVC
1.730 + TInt err = DoGetVideoProperties();
1.731 + if (err == KErrNone)
1.732 + {
1.733 + if (!(
1.734 + iVideoType == E3GPMpeg4Video ||
1.735 + iVideoType == E3GPAvcProfileBaseline ||
1.736 + iVideoType == E3GPAvcProfileMain ||
1.737 + iVideoType == E3GPAvcProfileExtended ||
1.738 + iVideoType == E3GPAvcProfileHigh
1.739 + ))
1.740 + {
1.741 + return KErrNotSupported;
1.742 + }
1.743 + }
1.744 + else
1.745 + {
1.746 + return err;
1.747 + }
1.748 +
1.749 + mp4_u32 decspecinfosize = 0;
1.750 + MP4Err mp4Err = MP4ParseReadVideoDecoderSpecificInfo(iHandler, NULL, 0, &decspecinfosize);
1.751 +
1.752 + if ( mp4Err == MP4_OK || mp4Err == MP4_BUFFER_TOO_SMALL)
1.753 + {
1.754 + aSize = decspecinfosize;
1.755 + mp4Err = MP4_OK;
1.756 + }
1.757 +
1.758 + return SymbianOSError(mp4Err);
1.759 + }
1.760 +
1.761 +/**
1.762 +This function reads DecoderSpecificInfo data from 3GP metadata and returns it to the caller.
1.763 +For files with MPEG-4 video this data is read from the esds atom. For files with AVC video
1.764 +this data is read from the avcC atom.
1.765 +
1.766 +Note: Only MPEG-4 video and H.264/AVC video streams contain DecoderSpecificInfo.
1.767 +
1.768 +@see C3GPParse::GetVideoDecoderSpecificInfoSize
1.769 +
1.770 +@param aInfo The descriptor to store the video decoder information.
1.771 +
1.772 +@return KErrNone if successful. Otherwise, returns one of the system wide error codes.
1.773 + KErrGeneral if an error has no specific categorisation;
1.774 + KErrNotSupported if the 3GP input data contains no MPEG-4 / AVC video stream;
1.775 + KErrOverflow if requested frame does not fit into the given buffer;
1.776 + KErrCorrupt if 3GP stream is invalid;
1.777 + KErrNotReady if the parser has not yet been initialised; See C3GPParse::Open;
1.778 + KErr3gpLibMoreDataRequired if 3GP library needs more data before the requested
1.779 + information can be returned.
1.780 +*/
1.781 +EXPORT_C TInt C3GPParse::GetVideoDecoderSpecificInfo(TDes8& aInfo) const
1.782 + {
1.783 + if (!iHandler)
1.784 + {
1.785 + return KErrNotReady;
1.786 + }
1.787 + if (aInfo.MaxLength() <= 0)
1.788 + {
1.789 + return KErrOverflow;
1.790 + }
1.791 +
1.792 + // Check if 3GP input data contains video stream and the video type is either
1.793 + // MPEG-4 or H.264/AVC
1.794 + TInt err = DoGetVideoProperties();
1.795 + if (err == KErrNone)
1.796 + {
1.797 + if (!(
1.798 + iVideoType == E3GPMpeg4Video ||
1.799 + iVideoType == E3GPAvcProfileBaseline ||
1.800 + iVideoType == E3GPAvcProfileMain ||
1.801 + iVideoType == E3GPAvcProfileExtended ||
1.802 + iVideoType == E3GPAvcProfileHigh
1.803 + ))
1.804 + {
1.805 + return KErrNotSupported;
1.806 + }
1.807 + }
1.808 + else
1.809 + {
1.810 + return err;
1.811 + }
1.812 +
1.813 + mp4_u32 decspecinfosize = 0;
1.814 + MP4Err mp4Err = MP4ParseReadVideoDecoderSpecificInfo(iHandler, const_cast<mp4_u8*>(aInfo.Ptr()),
1.815 + aInfo.MaxLength(),&decspecinfosize);
1.816 + if (mp4Err == MP4_OK)
1.817 + {
1.818 + aInfo.SetLength(decspecinfosize);
1.819 + }
1.820 + return SymbianOSError(mp4Err);
1.821 + }
1.822 +
1.823 +/**
1.824 +This function reads the audio frames that are stored in the current audio sample from the
1.825 +3GP file/stream and returns them to the caller. The current position of audio stream will be moved forward.
1.826 +
1.827 +Note: The next frame depends on the position in the input 3GP file. C3GPParse::Seek can
1.828 +be used to change the current position in the 3GP file.
1.829 +
1.830 +If the function returns KErr3gpLibMoreDataRequired, the caller needs to call C3GPParse::InsertData
1.831 +to insert more data before calling the function again.
1.832 +
1.833 +Note: aReturnedFrames may differ from the correct value when accessing the last audio sample.
1.834 +
1.835 +Note: Since there are separate cursors for storing current positions for video and audio streams, calling
1.836 +this function does not change current position of the parser for video stream.
1.837 +
1.838 +@param aBuffer Audio frames are returned here.
1.839 +@param aReturnedFrames Number of the returned frames or 0 if not known.
1.840 +@param aTimeStampInMs Audio frame presentation time in milliseconds from the beginning of the
1.841 + audio sequence.
1.842 +@param aTimeStampInTimescale Audio frame presentation time in timescale from the beginning
1.843 + of the audio sequence.
1.844 +
1.845 +@return KErrNone if successful. Otherwise, returns one of the system wide error codes.
1.846 + KErrGeneral if an error has no specific categorisation;
1.847 + KErrNotSupported if the 3GP input data contains no audio stream;
1.848 + KErrOverflow if requested frame does not fit into the given buffer; Caller can use
1.849 + C3GPParse::GetAudioFrameSize to retrieve the minimum size needed to
1.850 + fit this audio frame;
1.851 + KErrCorrupt if 3GP stream is invalid;
1.852 + KErrNotFound if no more frames available;
1.853 + KErrNotReady if the parser has not yet been initialised; See C3GPParse::Open;
1.854 + KErr3gpLibMoreDataRequired if 3GP library needs more data before the requested
1.855 + information can be returned.
1.856 +*/
1.857 +EXPORT_C TInt C3GPParse::ReadAudioFrames(TDes8& aBuffer, TInt& aReturnedFrames, TUint& aTimeStampInMs,
1.858 + TUint& aTimeStampInTimescale) const
1.859 + {
1.860 + if (!iHandler)
1.861 + {
1.862 + return KErrNotReady;
1.863 + }
1.864 + if (aBuffer.MaxLength() <= 0)
1.865 + {
1.866 + return KErrOverflow;
1.867 + }
1.868 +
1.869 + // Check if 3GP input data contains audio stream
1.870 + TInt err = DoGetAudioProperties();
1.871 + if (err != KErrNone)
1.872 + {
1.873 + return err;
1.874 + }
1.875 +
1.876 + mp4_u32 numOfFrames = 0;
1.877 + mp4_u32 timeStampInMs = 0;
1.878 + mp4_u32 timeStampInTimescale = 0;
1.879 + mp4_u32 audioSize = 0;
1.880 + MP4Err mp4Err = MP4ParseReadAudioFrames(iHandler, const_cast<mp4_u8*>(aBuffer.Ptr()), aBuffer.MaxLength(),
1.881 + &audioSize, &timeStampInMs, &numOfFrames, &timeStampInTimescale);
1.882 + if (mp4Err == MP4_OK)
1.883 + {
1.884 + aBuffer.SetLength(audioSize);
1.885 + aReturnedFrames = numOfFrames;
1.886 + aTimeStampInMs = timeStampInMs;
1.887 + aTimeStampInTimescale = timeStampInTimescale;
1.888 + }
1.889 + return SymbianOSError(mp4Err);
1.890 + }
1.891 +
1.892 +/**
1.893 +Returns size of audio DecoderSpecificInfo data from 3GP metadata.
1.894 +
1.895 +@param aSize Size of DecoderSpecificInfo to be returned (in bytes).
1.896 +
1.897 +@return KErrNone if successful. Otherwise, returns one of the system wide error codes.
1.898 + KErrGeneral if an error has no specific categorisation;
1.899 + KErrNotSupported if the stream does not contain audio stream stored in MPEG-4 audio sample boxes.
1.900 + KErrCorrupt if 3GP stream is invalid;
1.901 + KErrNotReady if the parser has not yet been initialised; See C3GPParse::Open;
1.902 + KErr3gpLibMoreDataRequired if 3GP library needs more data before the requested
1.903 + information can be returned.
1.904 +*/
1.905 +EXPORT_C TInt C3GPParse::GetAudioDecoderSpecificInfoSize(TInt& aSize) const
1.906 + {
1.907 + if (!iHandler)
1.908 + {
1.909 + return KErrNotReady;
1.910 + }
1.911 +
1.912 + // Check if 3GP input data contains audio stream
1.913 + TInt err = DoGetAudioProperties();
1.914 + if (err != KErrNone)
1.915 + {
1.916 + return err;
1.917 + }
1.918 +
1.919 + mp4_u32 decspecinfosize = 0;
1.920 + MP4Err mp4Err = MP4ParseReadAudioDecoderSpecificInfo(iHandler, NULL, 0, &decspecinfosize);
1.921 + if ( mp4Err == MP4_OK || mp4Err == MP4_BUFFER_TOO_SMALL)
1.922 + {
1.923 + aSize = decspecinfosize;
1.924 + mp4Err = MP4_OK;
1.925 + }
1.926 + return SymbianOSError(mp4Err);
1.927 + }
1.928 +
1.929 +/**
1.930 +This function reads DecoderSpecificInfo data from 3GP metadata and returns it to the caller.
1.931 +
1.932 +Note: AMR DecoderSpecificInfo data structure is returned in runtime in an architecture-specific
1.933 +Endian format, that is, no Endian conversion is necessary for the data.
1.934 +
1.935 +@see C3GPParse::GetAudioDecoderSpecificInfoSize
1.936 +
1.937 +@param aBuffer DecoderSpecificInfo is returned here.
1.938 +
1.939 +@return KErrNone if successful. Otherwise, returns one of the system wide error codes.
1.940 + KErrGeneral if an error has no specific categorisation;
1.941 + KErrNotSupported if the stream does not contain audio stream stored in MPEG-4 audio sample boxes.
1.942 + KErrOverflow if requested frame does not fit into the given buffer;
1.943 + KErrCorrupt if 3GP stream is invalid;
1.944 + KErrNotReady if the parser has not yet been initialised; See C3GPParse::Open;
1.945 + KErr3gpLibMoreDataRequired if 3GP library needs more data before the requested
1.946 + information can be returned.
1.947 +*/
1.948 +EXPORT_C TInt C3GPParse::GetAudioDecoderSpecificInfo(TDes8& aBuffer) const
1.949 + {
1.950 + if (!iHandler)
1.951 + {
1.952 + return KErrNotReady;
1.953 + }
1.954 + if (aBuffer.MaxLength() <= 0)
1.955 + {
1.956 + return KErrOverflow;
1.957 + }
1.958 +
1.959 + // Check if 3GP input data contains audio stream
1.960 + TInt err = DoGetAudioProperties();
1.961 + if (err != KErrNone)
1.962 + {
1.963 + return err;
1.964 + }
1.965 +
1.966 + mp4_u32 decspecinfosize = 0;
1.967 + MP4Err mp4Err = MP4ParseReadAudioDecoderSpecificInfo(iHandler, const_cast<mp4_u8*>(aBuffer.Ptr()),
1.968 + aBuffer.MaxLength(),&decspecinfosize);
1.969 + if (mp4Err == MP4_OK)
1.970 + {
1.971 + aBuffer.SetLength(decspecinfosize);
1.972 + }
1.973 + return SymbianOSError(mp4Err);
1.974 + }
1.975 +
1.976 +/**
1.977 +Returns the timestamp of the next video frame. The current position of the video stream will be moved forward.
1.978 +
1.979 +The function can be used to find out which frames have been coded to optimize the input frame selection
1.980 +if video frame rate needs to be modified.
1.981 +
1.982 +When this function call returns KErrEof, there are no more video frames left in the 3GP file and
1.983 +the timestamp returned with the previous call was the timestamp of the last video frame.
1.984 +
1.985 +Note: C3GPParse::Seek can be used to change the current position in the 3GP file.
1.986 +
1.987 +@param aTimeStampInMs Timestamp in milliseconds is returned here.
1.988 +@param aTimeStampInTimescale Timestamp in timescale is returned here.
1.989 +
1.990 +@return KErrNone if successful. Otherwise, returns one of the system wide error codes.
1.991 + KErrGeneral if an error has no specific categorisation;
1.992 + KErrNotSupported if the input does not contain video;
1.993 + KErrEof if no more video frames left;
1.994 + KErrCorrupt if 3GP stream is invalid;
1.995 + KErrNotReady if the parser has not yet been initialised; See C3GPParse::Open;
1.996 + KErr3gpLibMoreDataRequired if 3GP library needs more data before the requested
1.997 + information can be returned.
1.998 +*/
1.999 +EXPORT_C TInt C3GPParse::GetVideoTimestamp(TUint& aTimeStampInMs, TUint& aTimeStampInTimescale) const
1.1000 + {
1.1001 + if (!iHandler)
1.1002 + {
1.1003 + return KErrNotReady;
1.1004 + }
1.1005 +
1.1006 + // Check if 3GP input data contains video stream
1.1007 + TInt err = DoGetVideoProperties();
1.1008 + if (err != KErrNone)
1.1009 + {
1.1010 + return err;
1.1011 + }
1.1012 +
1.1013 + mp4_u32 timeStampInMs = 0;
1.1014 + mp4_u32 timeStampInTimescale = 0;
1.1015 + MP4Err mp4Err = MP4ParseGetNextVideoTimestamp(iHandler, &timeStampInMs, &timeStampInTimescale);
1.1016 + if (mp4Err == MP4_OK)
1.1017 + {
1.1018 + aTimeStampInMs = timeStampInMs;
1.1019 + aTimeStampInTimescale = timeStampInTimescale;
1.1020 + }
1.1021 + return SymbianOSError(mp4Err);
1.1022 + }
1.1023 +
1.1024 +/**
1.1025 +This function determines whether the input 3GP stream is streamable, that is, whether the media data is arranged
1.1026 +in such a manner that playback can be started without downloading the entire stream.
1.1027 +
1.1028 +@param aStreamable Returns ETrue if the file is streamable. Otherwise, returns EFalse.
1.1029 +
1.1030 +@return KErrNone if successful. Otherwise, returns one of the system wide error codes.
1.1031 + KErrGeneral if an error has no specific categorisation;
1.1032 + KErrCorrupt if 3GP stream is invalid;
1.1033 + KErrNotReady if the parser has not yet been initialised; See C3GPParse::Open;
1.1034 + KErr3gpLibMoreDataRequired if 3GP library needs more data before the requested
1.1035 + information can be returned.
1.1036 +*/
1.1037 +EXPORT_C TInt C3GPParse::GetStreamable(TBool& aStreamable) const
1.1038 + {
1.1039 + if (!iHandler)
1.1040 + {
1.1041 + return KErrNotReady;
1.1042 + }
1.1043 +
1.1044 + MP4Err mp4Err = MP4ParseIsStreamable(iHandler);
1.1045 + if (mp4Err == MP4_OK)
1.1046 + {
1.1047 + aStreamable = ETrue;
1.1048 + }
1.1049 + else
1.1050 + {
1.1051 + aStreamable = EFalse;
1.1052 + }
1.1053 + return SymbianOSError(mp4Err);
1.1054 + }
1.1055 +
1.1056 +/**
1.1057 +This function seeks the position specified by the aPosition parameter in the input 3GP file/stream.
1.1058 +
1.1059 +The position is considered to start from the beginning of the presentation time line in the 3GP file.
1.1060 +Thus audio and video positions cannot be given separately.
1.1061 +
1.1062 +The function will set the current audio and video positions in the following manner:
1.1063 +
1.1064 + If there is only audio data in the file, the current position is set to the audio frame at or just
1.1065 + before the given position.
1.1066 +
1.1067 + If there is only video in the file and the key frame is EFalse, the current position is set to the
1.1068 + video frame at or just before the given position. If the key frame is set to ETrue, the current
1.1069 + position is set to the first key frame at or before the current position.
1.1070 +
1.1071 + If there are both audio and video in the file, video is first positioned as explained above and then
1.1072 + audio is sought to the closest position in relation to video.
1.1073 +
1.1074 +If the position to seek is greater than the duration of video or audio, the video or audio position is
1.1075 +set to the position of the last video or audio frame as explained above.
1.1076 +
1.1077 +If the function returns KErr3gpLibMoreDataRequired, the caller needs to call C3GPParse::InsertData
1.1078 +to insert more data before calling the function again.
1.1079 +
1.1080 +@param aPosition Position to seek in milliseconds in the 3GP presentation time line.
1.1081 +@param aKeyFrame If set to ETrue, the first video key frame before a given point is sought. If
1.1082 + set to EFalse, the first video frame before a given point is sought.
1.1083 +@param aAudioPosition Position of audio after seeking (in milliseconds).
1.1084 +@param aVideoPosition Position of video after seeking (in milliseconds).
1.1085 +
1.1086 +@return KErrNone if successful. Otherwise, returns one of the system wide error codes.
1.1087 + KErrGeneral if an error has no specific categorisation;
1.1088 + KErrNotFound if cannot seek the requested position;
1.1089 + KErr3gpLibMoreDataRequired if 3GP library needs more data before the requested
1.1090 + information can be returned.
1.1091 + KErrNotReady if the parser has not yet been initialised; See C3GPParse::Open;
1.1092 +*/
1.1093 +EXPORT_C TInt C3GPParse::Seek(TUint aPosition, TBool aKeyFrame, TUint& aAudioPosition, TUint& aVideoPosition) const
1.1094 + {
1.1095 + if (!iHandler)
1.1096 + {
1.1097 + return KErrNotReady;
1.1098 + }
1.1099 +
1.1100 + mp4_u32 audioPosition = 0;
1.1101 + mp4_u32 videoPosition = 0;
1.1102 + mp4_bool keyFrame = aKeyFrame;
1.1103 + MP4Err mp4Err = MP4ParseSeek(iHandler, aPosition, &audioPosition, &videoPosition, keyFrame);
1.1104 + if (mp4Err == MP4_OK)
1.1105 + {
1.1106 + aAudioPosition = audioPosition;
1.1107 + aVideoPosition = videoPosition;
1.1108 + }
1.1109 + return SymbianOSError(mp4Err);
1.1110 + }
1.1111 +
1.1112 +/**
1.1113 +This function determines whether the next frame of the type aType is available.
1.1114 +
1.1115 +This function has no effect on the parser’s current position.
1.1116 +
1.1117 +@param aType The type of frame to check for. Refer to T3GPFrameType for supported types.
1.1118 +@param aAvailable Return ETrue if the type of frame specified by aType is available.
1.1119 +
1.1120 +@return KErrNone if successful. Otherwise, returns one of the system wide error codes.
1.1121 + KErrGeneral if an error has no specific categorisation;
1.1122 + KErrNotFound if frame of the requested type is not available;
1.1123 + KErrCorrupt if 3GP stream is invalid;
1.1124 + KErrNotReady if the parser has not yet been initialised; See C3GPParse::Open;
1.1125 + KErr3gpLibMoreDataRequired if 3GP library needs more data before the requested
1.1126 + information can be returned.
1.1127 +*/
1.1128 +EXPORT_C TInt C3GPParse::GetFrameAvailability(T3GPFrameType aType, TBool& aAvailable) const
1.1129 + {
1.1130 + if (!iHandler)
1.1131 + {
1.1132 + return KErrNotReady;
1.1133 + }
1.1134 +
1.1135 + aAvailable = EFalse;
1.1136 + TInt err = KErrNone;
1.1137 + MP4Err mp4Err = MP4_OK;
1.1138 + if (aType == E3GPAudio)
1.1139 + {
1.1140 + // Check if 3GP input data contains audio stream
1.1141 + err = DoGetAudioProperties();
1.1142 + if (err == KErrNotSupported)
1.1143 + {
1.1144 + // If there is no requested type, err will be KErrNotSupported. But in here, KErrNotFound is
1.1145 + // more proper.
1.1146 + err = KErrNotFound;
1.1147 + }
1.1148 + else if (err == KErrNone)
1.1149 + {
1.1150 + mp4Err = MP4ParseIsFrameAvailable(iHandler, iAudioMp4Type);
1.1151 + err = SymbianOSError(mp4Err);
1.1152 + }
1.1153 + }
1.1154 + else if (aType == E3GPVideo)
1.1155 + {
1.1156 + // Check if 3GP input data contains video stream
1.1157 + err = DoGetVideoProperties();
1.1158 + if (err == KErrNotSupported)
1.1159 + {
1.1160 + // If there is no requested type, err will be KErrNotSupported. But in here, KErrNotFound is
1.1161 + // more proper.
1.1162 + err = KErrNotFound;
1.1163 + }
1.1164 + else if (err == KErrNone)
1.1165 + {
1.1166 + mp4Err = MP4ParseIsFrameAvailable(iHandler, iVideoMp4Type);
1.1167 + err = SymbianOSError(mp4Err);
1.1168 + }
1.1169 + }
1.1170 + else
1.1171 + {
1.1172 + Panic(KErrArgument); // This should not happen.
1.1173 + }
1.1174 +
1.1175 + if (err == KErrNone)
1.1176 + {
1.1177 + aAvailable = ETrue;
1.1178 + }
1.1179 + return err;
1.1180 + }
1.1181 +
1.1182 +/**
1.1183 +Returns the number of video frames.
1.1184 +
1.1185 +@param aNum Number of video frames.
1.1186 +
1.1187 +@return KErrNone if successful. Otherwise, returns one of the system wide error codes.
1.1188 + KErrGeneral if an error has no specific categorisation;
1.1189 + KErrNotSupported if the input does not contain video;
1.1190 + KErrNotReady if the parser has not yet been initialised; See C3GPParse::Open.
1.1191 +*/
1.1192 +EXPORT_C TInt C3GPParse::GetNumberOfVideoFrames(TUint& aNum) const
1.1193 + {
1.1194 + if (!iHandler)
1.1195 + {
1.1196 + return KErrNotReady;
1.1197 + }
1.1198 +
1.1199 + // Check if 3GP input data contains video stream
1.1200 + TInt err = DoGetVideoProperties();
1.1201 + if (err != KErrNone)
1.1202 + {
1.1203 + return err;
1.1204 + }
1.1205 +
1.1206 + mp4_u32 numVideoFrame = 0;
1.1207 + MP4Err mp4Err = MP4ParseGetNumberOfVideoFrames(iHandler, &numVideoFrame);
1.1208 + if (mp4Err == MP4_OK)
1.1209 + {
1.1210 + aNum = numVideoFrame;
1.1211 + }
1.1212 + return SymbianOSError(mp4Err);
1.1213 + }
1.1214 +
1.1215 +/**
1.1216 +This function gives the video sample entry index of the next video frame to be read.
1.1217 +
1.1218 +The smallest index value is 1.
1.1219 +
1.1220 +@param aIndex Returns the Visual Sample Entry index of the next video frame to be read.
1.1221 +
1.1222 +@return KErrNone if successful. Otherwise, returns one of the system wide error codes.
1.1223 + KErrGeneral if an error has no specific categorisation;
1.1224 + KErrNotSupported if the input does not contain video;
1.1225 + KErrNotReady if the parser has not yet been initialised; See C3GPParse::Open.
1.1226 +*/
1.1227 +EXPORT_C TInt C3GPParse::GetVideoSampleEntryIndex(TUint& aIndex) const
1.1228 + {
1.1229 + if (!iHandler)
1.1230 + {
1.1231 + return KErrNotReady;
1.1232 + }
1.1233 +
1.1234 + // Check if 3GP input data contains video stream
1.1235 + TInt err = DoGetVideoProperties();
1.1236 + if (err != KErrNone)
1.1237 + {
1.1238 + return err;
1.1239 + }
1.1240 +
1.1241 + mp4_u32 index = 0;
1.1242 + MP4Err mp4Err = MP4ParseGetVideoSampleEntryIndex(iHandler, &index);
1.1243 + if (mp4Err == MP4_OK)
1.1244 + {
1.1245 + aIndex = index;
1.1246 + }
1.1247 + return SymbianOSError(mp4Err);
1.1248 + }
1.1249 +
1.1250 +/**
1.1251 +Returns video frame size.
1.1252 +
1.1253 +@param aIndex Index of video frame.
1.1254 +@param aSize Return the size of the video frame.
1.1255 +
1.1256 +@return KErrNone if successful. Otherwise, returns one of the system wide error codes.
1.1257 + KErrGeneral if an error has no specific categorisation;
1.1258 + KErrNotSupported if the input does not contain video;
1.1259 + KErrNotReady if the parser has not yet been initialised; See C3GPParse::Open.
1.1260 +*/
1.1261 +EXPORT_C TInt C3GPParse::GetVideoFrameSize(TUint aIndex, TUint& aSize) const
1.1262 + {
1.1263 + if (!iHandler)
1.1264 + {
1.1265 + return KErrNotReady;
1.1266 + }
1.1267 +
1.1268 + // Check if 3GP input data contains video stream
1.1269 + TInt err = DoGetVideoProperties();
1.1270 + if (err != KErrNone)
1.1271 + {
1.1272 + return err;
1.1273 + }
1.1274 +
1.1275 + mp4_u32 videoFrameSize = 0;
1.1276 + MP4Err mp4Err = MP4ParseGetVideoFrameSize(iHandler, aIndex, &videoFrameSize);
1.1277 + if (mp4Err == MP4_OK)
1.1278 + {
1.1279 + aSize = videoFrameSize;
1.1280 + }
1.1281 + return SymbianOSError(mp4Err);
1.1282 + }
1.1283 +
1.1284 +/**
1.1285 +Returns video frame start time.
1.1286 +
1.1287 +@param aIndex Index of video frame.
1.1288 +@param aTimeStampInMs Result in milliseconds.
1.1289 +@param aTimeStampInTimescale Result is returned here.
1.1290 +
1.1291 +@return KErrNone if successful. Otherwise, returns one of the system wide error codes.
1.1292 + KErrGeneral if an error has no specific categorisation;
1.1293 + KErrNotSupported if the input does not contain video;
1.1294 + KErrNotReady if the parser has not yet been initialised; See C3GPParse::Open.
1.1295 +*/
1.1296 +EXPORT_C TInt C3GPParse::GetVideoFrameStartTime(TUint aIndex, TUint& aTimeStampInMs, TUint& aTimeStampInTimescale) const
1.1297 + {
1.1298 + if (!iHandler)
1.1299 + {
1.1300 + return KErrNotReady;
1.1301 + }
1.1302 +
1.1303 + // Check if 3GP input data contains video stream
1.1304 + TInt err = DoGetVideoProperties();
1.1305 + if (err != KErrNone)
1.1306 + {
1.1307 + return err;
1.1308 + }
1.1309 +
1.1310 + mp4_u32 timeStampInMs = 0;
1.1311 + mp4_u32 timeStampInTimescale = 0;
1.1312 + MP4Err mp4Err = MP4ParseGetVideoFrameStartTime(iHandler, aIndex, &timeStampInTimescale, &timeStampInMs);
1.1313 + if (mp4Err == MP4_OK)
1.1314 + {
1.1315 + aTimeStampInMs = timeStampInMs;
1.1316 + aTimeStampInTimescale = timeStampInTimescale;
1.1317 + }
1.1318 + return SymbianOSError(mp4Err);
1.1319 + }
1.1320 +
1.1321 +/**
1.1322 +Checks if a video frame of with index aIndex exists.
1.1323 +
1.1324 +@param aIndex Index of video frame.
1.1325 +@param aKeyFrame Return ETrue if the video frame is a key frame.
1.1326 +
1.1327 +@return KErrNone if successful. Otherwise, returns one of the system wide error codes.
1.1328 + KErrGeneral if an error has no specific categorisation;
1.1329 + KErrNotSupported if the input does not contain video;
1.1330 + KErrNotReady if the parser has not yet been initialised; See C3GPParse::Open.
1.1331 +*/
1.1332 +EXPORT_C TInt C3GPParse::GetVideoFrameKeyType(TUint aIndex, TBool& aKeyFrame) const
1.1333 + {
1.1334 + if (!iHandler)
1.1335 + {
1.1336 + return KErrNotReady;
1.1337 + }
1.1338 +
1.1339 + // Check if 3GP input data contains video stream
1.1340 + TInt err = DoGetVideoProperties();
1.1341 + if (err != KErrNone)
1.1342 + {
1.1343 + return err;
1.1344 + }
1.1345 +
1.1346 + mp4_bool keyFrame = EFalse;
1.1347 + MP4Err mp4Err = MP4ParseGetVideoFrameType(iHandler, aIndex, &keyFrame);
1.1348 + if (mp4Err == MP4_OK)
1.1349 + {
1.1350 + aKeyFrame = keyFrame;
1.1351 + }
1.1352 + return SymbianOSError(mp4Err);
1.1353 + }
1.1354 +
1.1355 +/**
1.1356 +This function gives the audio sample entry index of the next audio frame to be read.
1.1357 +
1.1358 +The smallest index value is 1.
1.1359 +
1.1360 +@param aIndex Returns the Audio Sample Entry index of the next video frame to be read.
1.1361 +
1.1362 +@return KErrNone if successful. Otherwise, returns one of the system wide error codes.
1.1363 + KErrGeneral if an error has no specific categorisation;
1.1364 + KErrNotSupported if the input does not contain audio;
1.1365 + KErrNotReady if the parser has not yet been initialised; See C3GPParse::Open.
1.1366 +*/
1.1367 +EXPORT_C TInt C3GPParse::GetAudioSampleEntryIndex(TUint& aIndex) const
1.1368 + {
1.1369 + if (!iHandler)
1.1370 + {
1.1371 + return KErrNotReady;
1.1372 + }
1.1373 +
1.1374 + // Check if 3GP input data contains audio stream
1.1375 + TInt err = DoGetAudioProperties();
1.1376 + if (err != KErrNone)
1.1377 + {
1.1378 + return err;
1.1379 + }
1.1380 +
1.1381 + mp4_u32 audioSampleEntryIndex = 0;
1.1382 + MP4Err mp4Err = MP4ParseGetAudioSampleEntryIndex(iHandler, &audioSampleEntryIndex);
1.1383 + if (mp4Err == MP4_OK)
1.1384 + {
1.1385 + aIndex = audioSampleEntryIndex;
1.1386 + }
1.1387 + return SymbianOSError(mp4Err);
1.1388 + }
1.1389 +
1.1390 +/**
1.1391 +This function provides the storage mode of 13K QCELP in 3G2 file.
1.1392 +
1.1393 +In 3G2 files, QCELP can be registered to be stored in two ways:
1.1394 + using the QCELP Sample Entry ('sqcp') Box or
1.1395 + using the MPEG4 Audio Sample Description ('esds') Box.
1.1396 +
1.1397 +@param aMode Returns the QCELP storage mode. See T3GPQcelpStorageMode.
1.1398 +
1.1399 +@return KErrNone if successful. Otherwise, returns one of the system wide error codes.
1.1400 + KErrGeneral if an error has no specific categorisation;
1.1401 + KErrNotSupported if the 3GP input data does not contain any QCELP audio stream;
1.1402 + KErrNotReady if the parser has not yet been initialised; See C3GPParse::Open.
1.1403 +*/
1.1404 +EXPORT_C TInt C3GPParse::GetQcelpStorageMode(T3GPQcelpStorageMode& aMode) const
1.1405 + {
1.1406 + if (!iHandler)
1.1407 + {
1.1408 + return KErrNotReady;
1.1409 + }
1.1410 +
1.1411 + // Check if 3GP input data contains any QCELP audio stream
1.1412 + TInt err = DoGetAudioProperties();
1.1413 + if (err == KErrNone)
1.1414 + {
1.1415 + if (iAudioType != E3GPQcelp13K)
1.1416 + {
1.1417 + return KErrNotSupported;
1.1418 + }
1.1419 + }
1.1420 + else
1.1421 + {
1.1422 + return err;
1.1423 + }
1.1424 +
1.1425 + mp4_u8 audioQcelpStorageMode = 0;
1.1426 + MP4Err mp4Err = MP4ParseGetQCELPStorageMode(iHandler, &audioQcelpStorageMode);
1.1427 + if (mp4Err == MP4_OK)
1.1428 + {
1.1429 + if (audioQcelpStorageMode == 1)
1.1430 + {
1.1431 + aMode = E3GPMP4AudioDescriptionBox;
1.1432 + }
1.1433 + else
1.1434 + {
1.1435 + aMode = E3GPQcelpSampleEntryBox;
1.1436 + }
1.1437 + }
1.1438 + return SymbianOSError(mp4Err);
1.1439 + }
1.1440 +
1.1441 +/**
1.1442 +This function provides the video level of the H263 video stream contained in the 3GP data.
1.1443 +
1.1444 +@param aLevel Returns the H263 video level.
1.1445 +
1.1446 +@return KErrNone if successful. Otherwise, returns one of the system wide error codes.
1.1447 + KErrGeneral if an error has no specific categorisation;
1.1448 + KErrNotSupported if the 3GP input data does not contain any H263 video stream;
1.1449 + KErrNotReady if the parser has not yet been initialised; See C3GPParse::Open.
1.1450 +*/
1.1451 +EXPORT_C TInt C3GPParse::GetH263VideoLevel(TInt& aLevel) const
1.1452 + {
1.1453 + if (!iHandler)
1.1454 + {
1.1455 + return KErrNotReady;
1.1456 + }
1.1457 +
1.1458 + // Check if 3GP input data contains any H263 video stream
1.1459 + TInt err = DoGetVideoProperties();
1.1460 + if (err == KErrNone)
1.1461 + {
1.1462 + if (!(iVideoType == E3GPH263Profile0 || iVideoType == E3GPH263Profile3))
1.1463 + {
1.1464 + return KErrNotSupported;
1.1465 + }
1.1466 + }
1.1467 + else
1.1468 + {
1.1469 + return err;
1.1470 + }
1.1471 +
1.1472 + TVideoClipProperties videoClipProperties;
1.1473 + MP4Err mp4Err = MP4ParseGetVideoClipProperties(iHandler, videoClipProperties);
1.1474 + if (mp4Err == MP4_OK)
1.1475 + {
1.1476 + aLevel = videoClipProperties.iH263Level;
1.1477 + }
1.1478 + return SymbianOSError(mp4Err);
1.1479 + }
1.1480 +
1.1481 +/**
1.1482 +Returns the needed size for memory buffer to store an atom of given type from user data atom (UDTA).
1.1483 +
1.1484 +@param aType Type of atom to be read from UDTA. Hex value of 4 chars representing atom type
1.1485 + defined in standard. For example, 0x7469746c is 'titl', title for the media atom.
1.1486 +@param aLocation Specifies the location of user information to be retrieved. Refer to
1.1487 + T3GPUdtaLocation for supported values.
1.1488 +@param aAtomIndex Specifies the index of atom if UDTA contains multiple sub-atoms of the same
1.1489 + aUdtaAtomType to retrieve when supplied as input parameter. Returns the
1.1490 + highest index of the matching sub-atom found in the specified location as
1.1491 + output parameter.
1.1492 +@param aSize This contains the needed size for memory buffer.
1.1493 +
1.1494 +@return KErrNone if successful. Otherwise, returns one of the system wide error codes.
1.1495 + KErrGeneral if an error has no specific categorisation;
1.1496 + KErrNotFound if UDTA or wanted sub-atom is not available in asked location;
1.1497 + KErrAccessDenied if cannot seek to UDTA atom location;
1.1498 + KErrArgument if asked aLocation is invalid;
1.1499 + KErrNotReady if the parser has not yet been initialised; See C3GPParse::Open.
1.1500 +
1.1501 +@panic C3GPParse KErrArgument if the location of user information is not in the range of T3GPUdtaLocation
1.1502 +*/
1.1503 +EXPORT_C TInt C3GPParse::GetUserDataAtomSize(TUint32 aType, T3GPUdtaLocation aLocation,
1.1504 + TUint& aAtomIndex, TInt& aSize) const
1.1505 + {
1.1506 + if (!iHandler)
1.1507 + {
1.1508 + return KErrNotReady;
1.1509 + }
1.1510 +
1.1511 + mp4_u32 userDataAtomSize = 0;
1.1512 + mp4_u32 atomIndex = aAtomIndex;
1.1513 + mp4_u32 type = aType;
1.1514 + mp4_u8 location = UdtaLocation(aLocation);
1.1515 + MP4Err mp4Err = MP4ParseGetUserDataAtom(iHandler, location, type,
1.1516 + NULL, userDataAtomSize, atomIndex);
1.1517 + if ( mp4Err == MP4_OK || mp4Err == MP4_OUTPUT_BUFFER_TOO_SMALL)
1.1518 + {
1.1519 + aSize = userDataAtomSize;
1.1520 + aAtomIndex = atomIndex;
1.1521 + mp4Err = MP4_OK;
1.1522 + }
1.1523 + return SymbianOSError(mp4Err);
1.1524 + }
1.1525 +
1.1526 +/**
1.1527 +Retrieves an atom of given type from user data atom (UDTA) to the given buffer.
1.1528 +
1.1529 +The buffer returned stores an atom of structure that conforms to the definition of
1.1530 +a "full box" as specified in ISO/IEC 14496-12:2003: "Information technology – Coding
1.1531 +of audio-visual objects – Part 12: ISO base media file format."
1.1532 +
1.1533 +For more information on user data atoms, see Section 8 – Asset Information of "3GPP
1.1534 +TS 26.244 version 6.1.0 – 3GP file format (Rel 6)."
1.1535 +
1.1536 +@param aType Type of atom to be read from UDTA. Hex value of 4 chars representing atom type
1.1537 + defined in standard. For example, 0x7469746c is 'titl', title for the media atom.
1.1538 +@param aLocation Specifies the location of user information to be retrieved. Refer to
1.1539 + T3GPUdtaLocation for supported values.
1.1540 +@param aBuffer The descriptor to store the requested user data atom.
1.1541 +@param aAtomIndex Specifies the index of atom if UDTA contains multiple sub-atoms of the same
1.1542 + aUdtaAtomType to retrieve when supplied as input parameter. Returns the
1.1543 + highest index of the matching sub-atom found in the specified location as
1.1544 + output parameter. Only matching sub-atoms are counted when calculating the highest
1.1545 + index.
1.1546 +
1.1547 +@return KErrNone if successful. Otherwise, returns one of the system wide error codes.
1.1548 + KErrGeneral if an error has no specific categorisation;
1.1549 + KErrNotFound if UDTA or wanted sub-atom is not available in asked location;
1.1550 + KErrAccessDenied if cannot seek to UDTA atom location;
1.1551 + KErrArgument if asked aUdtaLocation is invalid;
1.1552 + KErrOverflow if the buffer to write atom to is too small. Use C3GPParse::GetUserDataAtomSize
1.1553 + to retrieve the proper size.
1.1554 + KErrNotReady if the parser has not yet been initialised; See C3GPParse::Open;
1.1555 + KErr3gpLibMoreDataRequired if if 3GP library needs more data before the requested
1.1556 + information can be returned.
1.1557 +
1.1558 +@panic C3GPParse KErrArgument if the location of user information is not in the range of T3GPUdtaLocation
1.1559 +*/
1.1560 +EXPORT_C TInt C3GPParse::GetUserDataAtom(TUint32 aType, T3GPUdtaLocation aLocation, TDes8& aBuffer, TUint& aAtomIndex) const
1.1561 + {
1.1562 + if (!iHandler)
1.1563 + {
1.1564 + return KErrNotReady;
1.1565 + }
1.1566 + if (aBuffer.MaxLength() <= 0)
1.1567 + {
1.1568 + return KErrOverflow;
1.1569 + }
1.1570 +
1.1571 + mp4_u32 userDataAtomSize = aBuffer.MaxLength();
1.1572 + mp4_u32 atomIndex = aAtomIndex;
1.1573 + mp4_u32 type = aType;
1.1574 + mp4_u8 location = UdtaLocation(aLocation);
1.1575 + MP4Err mp4Err = MP4ParseGetUserDataAtom(iHandler, location, type,
1.1576 + const_cast<mp4_u8*>(aBuffer.Ptr()), userDataAtomSize, atomIndex);
1.1577 + if ( mp4Err == MP4_OK )
1.1578 + {
1.1579 + aType = type;
1.1580 + aBuffer.SetLength(userDataAtomSize);
1.1581 + aAtomIndex = atomIndex;
1.1582 + }
1.1583 + return SymbianOSError(mp4Err);
1.1584 + }
1.1585 +
1.1586 +/**
1.1587 +This function gets the next frame's dependency information from SDTP box.
1.1588 +
1.1589 +@param aDependencies Returns the next frame's dependency information. See T3GPFrameDependencies.
1.1590 +
1.1591 +@return KErrNone if successful. Otherwise, returns one of the system wide error codes.
1.1592 + KErrGeneral if an error has no specific categorisation;
1.1593 + KErrNotSupported if the input does not contain video stream;
1.1594 + KErrNotReady if the parser has not yet been initialised; See C3GPParse::Open;
1.1595 + KErr3gpLibMoreDataRequired if if 3GP library needs more data before the requested
1.1596 + information can be returned.
1.1597 +*/
1.1598 +EXPORT_C TInt C3GPParse::GetVideoFrameDependencies(T3GPFrameDependencies& aDependencies) const
1.1599 + {
1.1600 + if (!iHandler)
1.1601 + {
1.1602 + return KErrNotReady;
1.1603 + }
1.1604 +
1.1605 + // Check if 3GP input data contains video stream
1.1606 + TInt err = DoGetVideoProperties();
1.1607 + if (err != KErrNone)
1.1608 + {
1.1609 + return err;
1.1610 + }
1.1611 +
1.1612 + mp4_u8 dependsOn;
1.1613 + mp4_u8 isDependedOn;
1.1614 + mp4_u8 hasRedundancy;
1.1615 + MP4Err mp4Err = MP4ParseNextVideoFrameDependencies(iHandler, &dependsOn, &isDependedOn, &hasRedundancy);
1.1616 + if (mp4Err == MP4_OK)
1.1617 + {
1.1618 + switch (dependsOn)
1.1619 + {
1.1620 + case 1:
1.1621 + aDependencies.iDependsOn = E3GPDependencyExists;
1.1622 + break;
1.1623 + case 2:
1.1624 + aDependencies.iDependsOn = E3GPDependencyNone;
1.1625 + break;
1.1626 + case 0:
1.1627 + aDependencies.iDependsOn = E3GPDependencyUnknown;
1.1628 + break;
1.1629 + default:
1.1630 + Panic(KErrCorrupt);
1.1631 + }
1.1632 +
1.1633 + switch (isDependedOn)
1.1634 + {
1.1635 + case 1:
1.1636 + aDependencies.iIsDependedOn = E3GPDependencyExists;
1.1637 + break;
1.1638 + case 2:
1.1639 + aDependencies.iIsDependedOn = E3GPDependencyNone;
1.1640 + break;
1.1641 + case 0:
1.1642 + aDependencies.iIsDependedOn = E3GPDependencyUnknown;
1.1643 + break;
1.1644 + default:
1.1645 + Panic(KErrCorrupt);
1.1646 + }
1.1647 +
1.1648 + switch (hasRedundancy)
1.1649 + {
1.1650 + case 1:
1.1651 + aDependencies.iHasRedundancy = E3GPRedundancyExists;
1.1652 + break;
1.1653 + case 2:
1.1654 + aDependencies.iHasRedundancy = E3GPRedundancyNone;
1.1655 + break;
1.1656 + case 0:
1.1657 + aDependencies.iHasRedundancy = E3GPRedundancyUnknown;
1.1658 + break;
1.1659 + default:
1.1660 + Panic(KErrCorrupt);
1.1661 + }
1.1662 + }
1.1663 + return SymbianOSError(mp4Err);
1.1664 + }
1.1665 +
1.1666 +/**
1.1667 +This function gets frame properties, from aStartIndex for a count of aNumberOfFrames frames.
1.1668 +
1.1669 +Properties obtained are start time, frame type, and frame size, stored in the T3GPFrameInfoParameters
1.1670 +struct.
1.1671 +
1.1672 +@param aStartIndex Index to start getting info for the array.
1.1673 +@param aNumberOfFrames Number of frames to retrieve frame info.
1.1674 +@param aArray An array of T3GPFrameInfoParameters struct to store video frame properties.
1.1675 + The input array will be flushed of all existing elements before use.
1.1676 +
1.1677 +@return KErrNone if successful. Otherwise, returns one of the system wide error codes.
1.1678 + KErrGeneral if an error has no specific categorisation;
1.1679 + KErrNotSupported if the input does not contain video stream;
1.1680 + KErrNoMemory if an attempt to allocate memory has failed;
1.1681 + KErrAccessDenied if opening file has failed;
1.1682 + KErrNotReady if the parser has not yet been initialised; See C3GPParse::Open.
1.1683 +*/
1.1684 +EXPORT_C TInt C3GPParse:: GetVideoFrameProperties(TUint aStartIndex, TUint aNumberOfFrames,
1.1685 + RArray<T3GPFrameInfoParameters>& aArray) const
1.1686 + {
1.1687 + if (!iHandler)
1.1688 + {
1.1689 + return KErrNotReady;
1.1690 + }
1.1691 +
1.1692 + // Check if 3GP input data contains video stream
1.1693 + TInt err = DoGetVideoProperties();
1.1694 + if (err != KErrNone)
1.1695 + {
1.1696 + return err;
1.1697 + }
1.1698 +
1.1699 + // Check if the input parameters are valid before retrieving video frame properties.
1.1700 + TUint totalNumOfVideoFrames;
1.1701 + err = GetNumberOfVideoFrames(totalNumOfVideoFrames);
1.1702 + if (err != KErrNone)
1.1703 + {
1.1704 + return err;
1.1705 + }
1.1706 +
1.1707 + if (aStartIndex >= totalNumOfVideoFrames || aNumberOfFrames > totalNumOfVideoFrames)
1.1708 + {
1.1709 + return KErrGeneral;
1.1710 + }
1.1711 +
1.1712 + TFrameInfoParameters* infoArray = new TFrameInfoParameters[aNumberOfFrames];
1.1713 +
1.1714 + if (!infoArray)
1.1715 + {
1.1716 + return KErrNoMemory;
1.1717 + }
1.1718 +
1.1719 + mp4_u32 startIndex = aStartIndex;
1.1720 + mp4_u32 numberOfFrames = aNumberOfFrames;
1.1721 + MP4Err mp4Err = MP4GetVideoFrameProperties(iHandler, startIndex, numberOfFrames, infoArray);
1.1722 +
1.1723 + if ( mp4Err == MP4_OK )
1.1724 + {
1.1725 + aArray.Reset();
1.1726 + T3GPFrameInfoParameters infoParams;
1.1727 +
1.1728 + for (TInt i=0; i<aNumberOfFrames; ++i)
1.1729 + {
1.1730 + infoParams.iSize = infoArray[i].iSize;
1.1731 + infoParams.iStartTime = infoArray[i].iStartTime;
1.1732 + infoParams.iIsRandomAccessPoint = infoArray[i].iType;
1.1733 + err = aArray.Append(infoParams);
1.1734 + if (err != KErrNone)
1.1735 + {
1.1736 + delete [] infoArray;
1.1737 + infoArray = NULL;
1.1738 + return err;
1.1739 + }
1.1740 + }
1.1741 + }
1.1742 + else
1.1743 + {
1.1744 + err = SymbianOSError(mp4Err);
1.1745 + }
1.1746 + delete [] infoArray;
1.1747 + infoArray = NULL;
1.1748 + return err;
1.1749 + }
1.1750 +
1.1751 +/**
1.1752 +This function reads the current video frame from an input file and returns it to the caller asynchronously.
1.1753 +The current position of video stream will be moved forward.
1.1754 +
1.1755 +This function is not supported when the parser is in buffer mode.
1.1756 +
1.1757 +C3GPParse::CancelReadFrame can be used to cancel an outstanding asynchronous frame read request.
1.1758 +
1.1759 +Note: Only one asynchronous parse audio or video frame(s) operation can be ongoing at any given time.
1.1760 +
1.1761 +Upon completion, successfully or otherwise, the callback function M3GPParseCallback::VideoFrameAvailable is called.
1.1762 +
1.1763 +@param aCallback Reference to class derived from M3GPAsyncObserver designed to receive notification of
1.1764 + asynchronous event completion.
1.1765 +@param aBuffer The descriptor to store the video frames.
1.1766 +*/
1.1767 +EXPORT_C void C3GPParse::ReadVideoFrame(M3GPParseCallback& aCallback, TDes8& aBuffer)
1.1768 + {
1.1769 + if (!iHandler)
1.1770 + {
1.1771 + aCallback.VideoFrameAvailable(KErrNotReady, EFalse, 0, 0);
1.1772 + return;
1.1773 + }
1.1774 + if (aBuffer.MaxLength() <= 0)
1.1775 + {
1.1776 + aCallback.VideoFrameAvailable(KErrOverflow, EFalse, 0, 0);
1.1777 + return;
1.1778 + }
1.1779 + if (iAsyncReadBuffer)
1.1780 + {
1.1781 + aCallback.VideoFrameAvailable(KErrInUse, EFalse, 0, 0);
1.1782 + return;
1.1783 + }
1.1784 +
1.1785 + // Check if 3GP input data contains video stream
1.1786 + TInt err = DoGetVideoProperties();
1.1787 + if (err != KErrNone)
1.1788 + {
1.1789 + aCallback.VideoFrameAvailable(err, EFalse, 0, 0);
1.1790 + return;
1.1791 + }
1.1792 +
1.1793 + iCallback = &aCallback;
1.1794 + mp4_u32 bufferSize = aBuffer.MaxLength();
1.1795 + MP4Err mp4Err = MP4ParseReadVideoFrameAsync(iHandler, this,
1.1796 + const_cast<mp4_u8*>(aBuffer.Ptr()), &bufferSize);
1.1797 + if (mp4Err != MP4_OK)
1.1798 + {
1.1799 + aCallback.VideoFrameAvailable(SymbianOSError(mp4Err), EFalse, 0, 0);
1.1800 + }
1.1801 + else
1.1802 + {
1.1803 + // MP4ParseReadVideoFrameAsync success. Store aBuffer since its length has
1.1804 + // not been set.
1.1805 + iAsyncReadBuffer = &aBuffer;
1.1806 + }
1.1807 + }
1.1808 +
1.1809 +/**
1.1810 +This function reads the audio frames that are stored in the current audio sample from the input
1.1811 +file and returns them to the caller asynchronously. The current position of audio stream
1.1812 +will be moved forward.
1.1813 +
1.1814 +This function is not supported when the parser is in buffer mode.
1.1815 +
1.1816 +C3GPParse::CancelReadFrame can be used to cancel an outstanding asynchronous frame read request.
1.1817 +
1.1818 +Note: Only one asynchronous parse audio or video frame(s) operation can be ongoing at any given time.
1.1819 +
1.1820 +Upon completion, successfully or otherwise, the callback function M3GPParseCallback::AudioFramesAvailable is called.
1.1821 +
1.1822 +@param aCallback Reference to class derived from M3GPAsyncObserver designed to receive notification of
1.1823 + asynchronous event completion.
1.1824 +@param aBuffer The descriptor to store the audio frames.
1.1825 +*/
1.1826 +EXPORT_C void C3GPParse::ReadAudioFrames(M3GPParseCallback& aCallback, TDes8& aBuffer)
1.1827 + {
1.1828 + if (!iHandler)
1.1829 + {
1.1830 + aCallback.AudioFramesAvailable(KErrNotReady, 0, 0, 0);
1.1831 + return;
1.1832 + }
1.1833 + if (aBuffer.MaxLength() <= 0)
1.1834 + {
1.1835 + aCallback.AudioFramesAvailable(KErrOverflow, 0, 0, 0);
1.1836 + return;
1.1837 + }
1.1838 + if (iAsyncReadBuffer)
1.1839 + {
1.1840 + aCallback.AudioFramesAvailable(KErrInUse, 0, 0, 0);
1.1841 + return;
1.1842 + }
1.1843 +
1.1844 + // Check if 3GP input data contains audio stream
1.1845 + TInt err = DoGetAudioProperties();
1.1846 + if (err != KErrNone)
1.1847 + {
1.1848 + aCallback.AudioFramesAvailable(err, 0, 0, 0);
1.1849 + return;
1.1850 + }
1.1851 +
1.1852 + iCallback = &aCallback;
1.1853 + mp4_u32 bufferSize = aBuffer.MaxLength();
1.1854 + MP4Err mp4Err = MP4ParseReadAudioFramesAsync(iHandler, this,
1.1855 + const_cast<mp4_u8*>(aBuffer.Ptr()), &bufferSize);
1.1856 + if (mp4Err != MP4_OK)
1.1857 + {
1.1858 + aCallback.AudioFramesAvailable(SymbianOSError(mp4Err), 0, 0, 0);
1.1859 + }
1.1860 + else
1.1861 + {
1.1862 + // MP4ParseReadAudioFramesAsync success. Store aBuffer since its length has
1.1863 + // not been set.
1.1864 + iAsyncReadBuffer = &aBuffer;
1.1865 + }
1.1866 + }
1.1867 +
1.1868 +/**
1.1869 +This function cancels the outstanding asynchronous read audio/video frame request.
1.1870 +
1.1871 +No callback function will be called.
1.1872 +
1.1873 +Note: As only one asynchronous parse audio or video frame(s) operation can be ongoing at any given time,
1.1874 +this function can be used to cancel audio or video read request.
1.1875 +*/
1.1876 +EXPORT_C void C3GPParse::CancelReadFrame()
1.1877 + {
1.1878 + if (!iHandler)
1.1879 + {
1.1880 + return;
1.1881 + }
1.1882 + if (iAsyncReadBuffer)
1.1883 + {
1.1884 + MP4CancelReadFrame(iHandler);
1.1885 + iAsyncReadBuffer = NULL;
1.1886 + iCallback = NULL;
1.1887 + }
1.1888 + }
1.1889 +
1.1890 +// Receive asynchronous parse video frames operation completion notification.
1.1891 +void C3GPParse::M3GPMP4LibVideoFrameAvailable(MP4Err aError, mp4_u32 aFrameSize, mp4_u32 aTimeStamp,
1.1892 + mp4_bool aKeyFrame, mp4_u32 aTimestamp2)
1.1893 + {
1.1894 + // Check if there is an outstanding asynchronous request
1.1895 + if (iAsyncReadBuffer)
1.1896 + {
1.1897 + if (aError == MP4_OK)
1.1898 + {
1.1899 + // Set the buffer length for the asynchronous read video frame
1.1900 + iAsyncReadBuffer->SetLength(aFrameSize);
1.1901 + }
1.1902 + iAsyncReadBuffer = NULL;
1.1903 + // Parser can send out the callback to the client
1.1904 + TBool keyFrame = aKeyFrame;
1.1905 + TUint timeStampInMs = aTimeStamp;
1.1906 + TUint timeStampInTimescale = aTimestamp2;
1.1907 + iCallback->VideoFrameAvailable(SymbianOSError(aError), keyFrame, timeStampInMs, timeStampInTimescale);
1.1908 + }
1.1909 +
1.1910 + iCallback = NULL;
1.1911 + }
1.1912 +
1.1913 +// Receive asyncronous parse audio frames operation completion notification.
1.1914 +void C3GPParse::M3GPMP4LibAudioFramesAvailable(MP4Err aError, mp4_u32 aAudioSize, mp4_u32 aTimeStamp,
1.1915 + mp4_u32 aReturnedFrames, mp4_u32 aTimestamp2)
1.1916 + {
1.1917 + // Check if there is an outstanding asynchronous request
1.1918 + if (iAsyncReadBuffer)
1.1919 + {
1.1920 + if (aError == MP4_OK)
1.1921 + {
1.1922 + // Set the buffer length for the asynchronous read audio frame
1.1923 + iAsyncReadBuffer->SetLength(aAudioSize);
1.1924 + }
1.1925 + iAsyncReadBuffer = NULL;
1.1926 + // Parser can send out the callback to the client
1.1927 + TUint returnedFrames = aReturnedFrames;
1.1928 + TUint timeStampInMs = aTimeStamp;
1.1929 + TUint timeStampInTimescale = aTimestamp2;
1.1930 + iCallback->AudioFramesAvailable(SymbianOSError(aError), returnedFrames, timeStampInMs, timeStampInTimescale);
1.1931 + }
1.1932 +
1.1933 + iCallback = NULL;
1.1934 + }
1.1935 +
1.1936 +// Helper function to convert c style error code to Symbian OS standard error code
1.1937 +TInt C3GPParse::SymbianOSError(MP4Err aError) const
1.1938 + {
1.1939 + TInt error = KErrNone;
1.1940 +
1.1941 + switch (aError)
1.1942 + {
1.1943 + case (MP4_OK):
1.1944 + break;
1.1945 + case (MP4_ERROR):
1.1946 + error = KErrGeneral;
1.1947 + break;
1.1948 + case (MP4_OUT_OF_MEMORY):
1.1949 + error = KErrNoMemory;
1.1950 + break;
1.1951 + case (MP4_NOT_AVAILABLE):
1.1952 + error = KErr3gpLibMoreDataRequired;
1.1953 + break;
1.1954 + case (MP4_FILE_MODE):
1.1955 + case (MP4_NOT_STREAMABLE):
1.1956 + case (MP4_NO_VIDEO):
1.1957 + case (MP4_NO_AUDIO):
1.1958 + error = KErrNotSupported;
1.1959 + break;
1.1960 + case (MP4_BUFFER_TOO_SMALL):
1.1961 + case (MP4_OUTPUT_BUFFER_TOO_SMALL):
1.1962 + error = KErrOverflow;
1.1963 + break;
1.1964 + case (MP4_END_OF_VIDEO):
1.1965 + error = KErrEof;
1.1966 + break;
1.1967 + case (MP4_CANT_SEEK):
1.1968 + case (MP4_NO_FRAME):
1.1969 + case (MP4_NO_REQUESTED_FRAME):
1.1970 + case (MP4_UDTA_NOT_FOUND):
1.1971 + error = KErrNotFound;
1.1972 + break;
1.1973 + case (MP4_FILE_ERROR):
1.1974 + error = KErrAccessDenied;
1.1975 + break;
1.1976 + case (MP4_INVALID_INPUT_STREAM):
1.1977 + error = KErrCorrupt;
1.1978 + break;
1.1979 + case (MP4_INVALID_TYPE):
1.1980 + error = KErrArgument;
1.1981 + break;
1.1982 + default:
1.1983 + // Mapped all possible errors returned by the MP4_library. Anything else should NOT happen
1.1984 + Panic(KErrArgument);
1.1985 + }
1.1986 + return error;
1.1987 + }
1.1988 +
1.1989 +// Help function to get video properties
1.1990 +TInt C3GPParse::DoGetVideoProperties() const
1.1991 + {
1.1992 + if (!iVideoPropertiesSaved || iVideoError == KErr3gpLibMoreDataRequired)
1.1993 + {
1.1994 + MP4Err mp4Err = MP4_OK;
1.1995 + mp4_u32 length = 0;
1.1996 + mp4_u32 type = 0;
1.1997 + mp4_u32 width = 0;
1.1998 + mp4_u32 height = 0;
1.1999 + mp4_u32 timeScale = 0;
1.2000 + mp4_double frameRate = 0;
1.2001 +
1.2002 + mp4Err = MP4ParseRequestVideoDescription(iHandler, &length, &frameRate, &type, &width, &height, &timeScale);
1.2003 + iVideoPropertiesSaved = ETrue;
1.2004 + if (mp4Err == MP4_OK)
1.2005 + {
1.2006 + iVideoType = WrapperVideoType(type);
1.2007 + if (iVideoType == E3GPNoVideo)
1.2008 + {
1.2009 + iVideoError = KErrNotSupported;
1.2010 + return KErrNotSupported;
1.2011 + }
1.2012 + iVideoLength = length;
1.2013 + iVideoMp4Type = type; // Type of video stream
1.2014 + iVideoSize.iWidth = width;
1.2015 + iVideoSize.iHeight = height;
1.2016 + iVideoTimeScale = timeScale;
1.2017 + iVideoFrameRate = frameRate;
1.2018 + }
1.2019 + iVideoError = SymbianOSError(mp4Err);
1.2020 + }
1.2021 + return iVideoError;
1.2022 + }
1.2023 +
1.2024 +// Help function to get audio properties
1.2025 +TInt C3GPParse::DoGetAudioProperties() const
1.2026 + {
1.2027 + if (!iAudioPropertiesSaved || iAudioError == KErr3gpLibMoreDataRequired)
1.2028 + {
1.2029 + MP4Err mp4Err = MP4_OK;
1.2030 + mp4_u32 audioLength = 0;
1.2031 + mp4_u32 audioType = 0;
1.2032 + mp4_u32 averateBitRate = 0;
1.2033 + mp4_u32 timeScale = 0;
1.2034 + mp4_u8 framesPerSample = 0;
1.2035 +
1.2036 + mp4Err = MP4ParseRequestAudioDescription(iHandler, &audioLength, &audioType,
1.2037 + &framesPerSample, &timeScale, &averateBitRate);
1.2038 + iAudioPropertiesSaved = ETrue;
1.2039 + if (mp4Err == MP4_OK)
1.2040 + {
1.2041 + iAudioLength = audioLength;
1.2042 + iAudioMp4Type = audioType; // Type of audio stream
1.2043 + iAudioType = WrapperAudioType(audioType);
1.2044 + iAudioFramesPerSample = framesPerSample;
1.2045 + iAudioAvgBitRate = averateBitRate;
1.2046 + iAudioTimeScale = timeScale;
1.2047 + }
1.2048 + iAudioError = SymbianOSError(mp4Err);
1.2049 + }
1.2050 + return iAudioError;
1.2051 + }
1.2052 +
1.2053 +// Help function to get stream properties
1.2054 +TInt C3GPParse::DoGetStreamProperties() const
1.2055 + {
1.2056 + if (!iStreamPropertiesSaved || iStreamError == KErr3gpLibMoreDataRequired)
1.2057 + {
1.2058 + MP4Err mp4Err = MP4_OK;
1.2059 + mp4_u32 streamSize = 0;
1.2060 + mp4_u32 streamAvgBitRate;
1.2061 + mp4Err = MP4ParseRequestStreamDescription(iHandler,&streamSize, &streamAvgBitRate);
1.2062 + iStreamPropertiesSaved = ETrue;
1.2063 + if (mp4Err == MP4_OK)
1.2064 + {
1.2065 + iStreamSize = streamSize;
1.2066 + iStreamAvgBitRate = streamAvgBitRate;
1.2067 + }
1.2068 + iStreamError = SymbianOSError(mp4Err);
1.2069 + }
1.2070 + return iStreamError;
1.2071 + }
1.2072 +
1.2073 +// Helper function to map Mp4 enum type to T3GPVideoType for video
1.2074 +T3GPVideoType C3GPParse::WrapperVideoType(TUint aType) const
1.2075 + {
1.2076 + T3GPVideoType videoType = E3GPNoVideo;
1.2077 + switch (aType)
1.2078 + {
1.2079 + case (MP4_TYPE_MPEG4_VIDEO):
1.2080 + videoType = E3GPMpeg4Video;
1.2081 + break;
1.2082 + case (MP4_TYPE_H263_PROFILE_0):
1.2083 + videoType = E3GPH263Profile0;
1.2084 + break;
1.2085 + case (MP4_TYPE_H263_PROFILE_3):
1.2086 + videoType = E3GPH263Profile3;
1.2087 + break;
1.2088 + case (MP4_TYPE_AVC_PROFILE_BASELINE):
1.2089 + videoType = E3GPAvcProfileBaseline;
1.2090 + break;
1.2091 + case (MP4_TYPE_AVC_PROFILE_MAIN):
1.2092 + videoType = E3GPAvcProfileMain;
1.2093 + break;
1.2094 + case (MP4_TYPE_AVC_PROFILE_EXTENDED):
1.2095 + videoType = E3GPAvcProfileExtended;
1.2096 + break;
1.2097 +
1.2098 + case (MP4_TYPE_AVC_PROFILE_HIGH):
1.2099 + videoType = E3GPAvcProfileHigh;
1.2100 + break;
1.2101 + case MP4_TYPE_NONE:
1.2102 + break;
1.2103 + default:
1.2104 + Panic(KErrCorrupt); // This should not happen.
1.2105 + break;
1.2106 + }
1.2107 + return videoType;
1.2108 + }
1.2109 +
1.2110 +// Helper function to map Mp4 enum type to T3GPAudioType for audio
1.2111 +T3GPAudioType C3GPParse::WrapperAudioType(TUint aType) const
1.2112 + {
1.2113 + T3GPAudioType audioType = E3GPNoAudio;
1.2114 + switch (aType)
1.2115 + {
1.2116 + case (MP4_TYPE_MPEG4_AUDIO):
1.2117 + audioType = E3GPMpeg4Audio;
1.2118 + break;
1.2119 + case (MP4_TYPE_AMR_NB):
1.2120 + audioType = E3GPAmrNB;
1.2121 + break;
1.2122 + case (MP4_TYPE_AMR_WB):
1.2123 + audioType = E3GPAmrWB;
1.2124 + break;
1.2125 + case (MP4_TYPE_QCELP_13K):
1.2126 + audioType = E3GPQcelp13K;
1.2127 + break;
1.2128 + default:
1.2129 + Panic(KErrCorrupt); // This should not happen.
1.2130 + }
1.2131 + return audioType;
1.2132 + }
1.2133 +
1.2134 +// Helper function to map enum type of the location of the user data in the file
1.2135 +mp4_u8 C3GPParse::UdtaLocation(T3GPUdtaLocation aLocation) const
1.2136 + {
1.2137 + mp4_u8 location = MP4_UDTA_NONE;
1.2138 +
1.2139 + switch (aLocation )
1.2140 + {
1.2141 + case (E3GPUdtaMoov):
1.2142 + location = MP4_UDTA_MOOV;
1.2143 + break;
1.2144 + case (E3GPUdtaVideoTrak):
1.2145 + location = MP4_UDTA_VIDEOTRAK;
1.2146 + break;
1.2147 + case (E3GPUdtaAudioTrak):
1.2148 + location = MP4_UDTA_AUDIOTRAK;
1.2149 + break;
1.2150 + default:
1.2151 + Panic(KErrArgument);
1.2152 + }
1.2153 + return location;
1.2154 + }
1.2155 +
1.2156 +
1.2157 +void C3GPParse::Panic(TInt aPanic)
1.2158 + // Panic client
1.2159 + {
1.2160 + _LIT(K3GPParsePanicName, "C3GPParse");
1.2161 + User::Panic(K3GPParsePanicName, aPanic);
1.2162 + }
1.2163 +
1.2164 +