videoeditorengine/vedengine/videoprocessor/src/mp4parser.cpp
changeset 0 951a5db380a0
equal deleted inserted replaced
-1:000000000000 0:951a5db380a0
       
     1 /*
       
     2 * Copyright (c) 2010 Ixonos Plc.
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - Initial contribution
       
    11 *
       
    12 * Contributors:
       
    13 * Ixonos Plc
       
    14 *
       
    15 * Description:  
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 
       
    21 // INCLUDE FILES
       
    22 
       
    23 #include    "movieprocessorimpl.h"
       
    24 #include    "mp4parser.h"
       
    25 #include    "vedvideosettings.h"
       
    26 #include    "vedaudiosettings.h"
       
    27 #include    "vedvolreader.h"
       
    28 #include    "vedavcedit.h"
       
    29 
       
    30 // ASSERTIONS
       
    31 #define MPASSERT(x) __ASSERT_DEBUG(x, User::Panic(_L("CMovieProcessorImpl"), EInternalAssertionFailure))
       
    32 
       
    33 #ifdef _DEBUG
       
    34 #include <e32svr.h>
       
    35 #define PRINT(x) RDebug::Print x;
       
    36 #else
       
    37 #define PRINT(x)
       
    38 #endif
       
    39 
       
    40 // LOCAL CONSTANTS AND MACROS
       
    41 #ifdef _DEBUG
       
    42 const TInt KErrorCode = CParser::EParserFailure;
       
    43 #else
       
    44 const TInt KErrorCode = KErrGeneral;
       
    45 #endif
       
    46 
       
    47 //const TUint KNumFramesInOneRun = 10;
       
    48 const TUint KVOLHeaderBufferSize = 256;
       
    49 const TUint KAVCDCRBufferSize = 1024;
       
    50 const TUint KMinBitrate = 128;
       
    51 
       
    52 // ================= MEMBER FUNCTIONS =======================
       
    53 
       
    54 // C++ default constructor can NOT contain any code, that
       
    55 // might leave.
       
    56 //
       
    57 
       
    58 CMP4Parser::CMP4Parser()
       
    59 {       
       
    60 	iMP4Handle = 0;
       
    61 	iVideoType = 0;
       
    62 	iAudioType = 0; 
       
    63 	iBytesRead = 0;
       
    64 	iFirstRead = ETrue;		// added for Mp4
       
    65 	iFirstFrameInfo = ETrue;  // added for Mp4
       
    66 	iOutputNumberOfFrames = 0; 
       
    67     iStreamSource = ESourceNone;
       
    68 	iFrameNumber=0;
       
    69 	iFirstTimeClipParsing=ETrue;
       
    70     iStartFrameIndex=0;		
       
    71 }
       
    72 
       
    73 // Two-phased constructor.
       
    74 
       
    75 CMP4Parser* CMP4Parser::NewL(CMovieProcessorImpl* aProcessor, const TDesC &aFileName)
       
    76 {
       
    77 	CMP4Parser *self = new (ELeave) CMP4Parser;
       
    78 	CleanupStack::PushL(self);    
       
    79 	
       
    80 	if ( aFileName.Length() > 0 )   
       
    81 		self->iStreamSource = ESourceFile;
       
    82 	else
       
    83 		self->iStreamSource = ESourceUser;
       
    84 	
       
    85 	self->ConstructL(aProcessor,aFileName);
       
    86 
       
    87 	CleanupStack::Pop();  // self
       
    88 	
       
    89 	return self;
       
    90 }
       
    91 
       
    92 CMP4Parser* CMP4Parser::NewL(CMovieProcessorImpl* aProcessor, RFile* aFileHandle)
       
    93 {
       
    94 	CMP4Parser *self = new (ELeave) CMP4Parser;
       
    95 	CleanupStack::PushL(self);    
       
    96 	
       
    97 	self->iStreamSource = ESourceFile;	
       
    98 	
       
    99 	self->ConstructL(aProcessor,aFileHandle);
       
   100 
       
   101 	CleanupStack::Pop();  // self
       
   102 	
       
   103 	return self;
       
   104 }
       
   105 
       
   106 // Symbian OS default constructor can leave.
       
   107 
       
   108 void CMP4Parser::ConstructL(CMovieProcessorImpl* aProcessor, const TDesC &aFileName)
       
   109 {
       
   110 	MP4Err error;
       
   111 	iProcessor = aProcessor; 
       
   112 
       
   113 	// open MP4 library
       
   114     if ( iStreamSource == ESourceFile )
       
   115         {        
       
   116         TBuf<258> temp(aFileName);
       
   117         temp.ZeroTerminate();			
       
   118 
       
   119         MP4FileName name = reinterpret_cast<MP4FileName>( const_cast<TUint16*>(temp.Ptr()) );
       
   120 
       
   121         error = MP4ParseOpen(&iMP4Handle, name);
       
   122         if ( error == MP4_OK )
       
   123             {
       
   124             // set buffer sizes; only parser buffer size is effective for this instance
       
   125             error = MP4SetCustomFileBufferSizes(iMP4Handle, K3gpMp4ComposerWriteBufferSize, K3gpMp4ComposerNrOfWriteBuffers, K3gpMp4ParserReadBufferSize );
       
   126             }
       
   127         }
       
   128     else
       
   129         {
       
   130         // buffer
       
   131         error = MP4ParseOpen(&iMP4Handle, 0);        
       
   132         }        
       
   133 		
       
   134     if (error == MP4_OUT_OF_MEMORY)
       
   135         {
       
   136         User::Leave(KErrNoMemory);
       
   137         }
       
   138     else if ( error != MP4_OK )
       
   139         {
       
   140         User::Leave(KErrorCode);
       
   141 		}
       
   142 }
       
   143 
       
   144 void CMP4Parser::ConstructL(CMovieProcessorImpl* aProcessor, RFile* aFileHandle)
       
   145 {
       
   146 	MP4Err error;
       
   147 	iProcessor = aProcessor;
       
   148 
       
   149 	// open MP4 library
       
   150     error = MP4ParseOpenFileHandle(&iMP4Handle, aFileHandle);
       
   151     
       
   152     if ( error == MP4_OK )
       
   153         {
       
   154         // set buffer sizes; only parser buffer size is effective for this instance
       
   155         error = MP4SetCustomFileBufferSizes(iMP4Handle, K3gpMp4ComposerWriteBufferSize, K3gpMp4ComposerNrOfWriteBuffers, K3gpMp4ParserReadBufferSize );
       
   156         }
       
   157         
       
   158     if (error == MP4_OUT_OF_MEMORY)
       
   159         {
       
   160         User::Leave(KErrNoMemory);
       
   161         }
       
   162     else if ( error != MP4_OK )
       
   163         {
       
   164         User::Leave(KErrorCode);
       
   165 		}
       
   166 }
       
   167 
       
   168 // Destructor
       
   169 CMP4Parser::~CMP4Parser()
       
   170 {
       
   171     if (iMP4Handle)
       
   172         MP4ParseClose(iMP4Handle);
       
   173 
       
   174     iMP4Handle = 0;
       
   175 }
       
   176 
       
   177 
       
   178 
       
   179 // ---------------------------------------------------------
       
   180 // CMP4Parser::WriteDataBlockL
       
   181 // Write a block of data to parser
       
   182 // (other items were commented in a header).
       
   183 // ---------------------------------------------------------
       
   184 //
       
   185 
       
   186 TInt CMP4Parser::WriteDataBlock(const TDes8& aBlock)
       
   187 {               
       
   188 	
       
   189 	MPASSERT(iStreamSource != ESourceFile);    
       
   190 	MP4Err error = MP4ParseWriteData(iMP4Handle, (mp4_u8*)(aBlock.Ptr()), mp4_u32(aBlock.Length()) );
       
   191 	
       
   192 	if ( error == MP4_OUT_OF_MEMORY )
       
   193 		return KErrNoMemory;
       
   194 	else if ( error == MP4_ERROR )
       
   195 		return KErrorCode;
       
   196     else
       
   197         return KErrNone;
       
   198 	
       
   199 }
       
   200 
       
   201 // ---------------------------------------------------------
       
   202 // CMP4Parser::GetNextFrameInformation
       
   203 // Get type (streaming-case), length and availability of next frame to be fetched
       
   204 // using MP4 library API functions
       
   205 // (other items were commented in a header).
       
   206 // ---------------------------------------------------------
       
   207 //
       
   208 
       
   209 TInt CMP4Parser::GetNextFrameInformation(TFrameType& aType, TUint& aLength, TBool& aIsAvailable)
       
   210 {   
       
   211 	
       
   212 	// If aType == EFrameTypeNone, the type of next frame is retrieved 
       
   213 	// (valid only in streaming case)
       
   214 	// Otherwise, only the length of next specified type of frame is retrieved
       
   215 	MPASSERT(iStreamSource != ESourceNone);            
       
   216 	
       
   217 	mp4_u32 type = MP4_TYPE_NONE;
       
   218 	MP4Err error;
       
   219 
       
   220 	aIsAvailable = 0;    
       
   221 	if ( iNextFrameType == EFrameTypeNone )
       
   222 		// if the mp4 library is reading a file, a frame has always been read when 
       
   223 		// we come here
       
   224 		// otherwise it might be that a complete frame was not available yet
       
   225 		// and we come here to ask again        
       
   226 	{
       
   227 		if ( aType == EFrameTypeNone ) 
       
   228 		{
       
   229 			MPASSERT(iStreamSource == ESourceUser);
       
   230 			
       
   231 			// get next frame type
       
   232 			error = MP4ParseNextFrameType(iMP4Handle, &type);
       
   233 
       
   234 			if ( error == MP4_NOT_AVAILABLE )
       
   235 				return KErrNone;                
       
   236 			else if ( error == MP4_NO_FRAME )                
       
   237 				return EParserEndOfStream; // no video or audio frames left, stream ended
       
   238 			else if ( error == MP4_INVALID_INPUT_STREAM )
       
   239 				return KErrCorrupt;
       
   240 			else if ( error != MP4_OK )
       
   241 				return KErrorCode;
       
   242             else
       
   243             {
       
   244                 MPASSERT(error == MP4_OK);
       
   245             }
       
   246 			
       
   247 			switch ( type ) 
       
   248 			{
       
   249 			case MP4_TYPE_H263_PROFILE_0:
       
   250 		    case MP4_TYPE_MPEG4_VIDEO:
       
   251           
       
   252 				MPASSERT( type == iVideoType );
       
   253 				iNextFrameType = EFrameTypeVideo;         
       
   254 				break;
       
   255 				
       
   256 			case MP4_TYPE_AMR_NB:
       
   257 				MPASSERT( type == iAudioType );
       
   258 				iNextFrameType = EFrameTypeAudio;                    
       
   259 				break;        
       
   260 
       
   261 			default:
       
   262 				return KErrNotSupported;
       
   263 			}
       
   264 		}
       
   265 		else 
       
   266 		{
       
   267 			// library reads the file            
       
   268 			//MPASSERT(iStreamSource == ESourceFile);
       
   269 			type = ( aType == EFrameTypeVideo ) ? iVideoType : iAudioType;
       
   270 			iNextFrameType = aType;
       
   271 		}
       
   272 		
       
   273 		// get length for the frame
       
   274 		mp4_u32 length = 0, mp4Specific = 0;
       
   275 		MPASSERT( type != MP4_TYPE_NONE );
       
   276 		if ( (iFirstFrameInfo) &&
       
   277 		     ((iVideoType == MP4_TYPE_MPEG4_VIDEO) || (iVideoType == MP4_TYPE_AVC_PROFILE_BASELINE)) ) 		   
       
   278 		{
       
   279 			error = MP4ParseReadVideoDecoderSpecificInfo( iMP4Handle, 0, 0, &mp4Specific );
       
   280 			iFirstFrameInfo = EFalse;
       
   281 		}
       
   282 		error = MP4ParseNextFrameSize(iMP4Handle, type, &length);
       
   283 		MPASSERT( error != MP4_NOT_AVAILABLE );
       
   284 		
       
   285 		if ( length == 0 || error == MP4_NO_REQUESTED_FRAME )
       
   286 		{            
       
   287 			// file-reading case: all frames of this type have been read
       
   288 			//   and the caller should try with the other type
       
   289 			MPASSERT( length == 0 );
       
   290 			iNextFrameType = EFrameTypeNone;
       
   291 			aLength = 0;            
       
   292 			return KErrNone;            
       
   293 		}
       
   294 		else if ( error == MP4_INVALID_INPUT_STREAM )
       
   295 			return KErrCorrupt;
       
   296 		else if ( error != MP4_OK )
       
   297 			return KErrorCode;
       
   298        else if ( length > iMaxVideoFrameLength )
       
   299             {
       
   300             PRINT((_L("CMP4Parser::GetNextFrameInformation() too large video frame size %d, return KErrCorrupt"),length));
       
   301 			return KErrCorrupt;
       
   302             }
       
   303         else
       
   304             iNextFrameLength = TUint(length + mp4Specific);
       
   305 
       
   306 	}
       
   307 	MPASSERT(iNextFrameType != EFrameTypeNone);
       
   308 	MPASSERT(iNextFrameLength != 0);
       
   309 	
       
   310 	// check if frame is available
       
   311 	if ( iStreamSource == ESourceUser )
       
   312 	{
       
   313 		error = MP4ParseIsFrameAvailable(iMP4Handle, type);
       
   314 		if ( error != MP4_OK && error != MP4_NOT_AVAILABLE )
       
   315 			return KErrorCode;
       
   316 		aIsAvailable = ( error == MP4_NOT_AVAILABLE ) ? EFalse : ETrue;
       
   317 	}
       
   318 	else 
       
   319 		aIsAvailable = ETrue;
       
   320 	
       
   321 	aType = iNextFrameType;
       
   322 	aLength = iNextFrameLength;	
       
   323 	
       
   324 	return KErrNone;
       
   325 }   
       
   326 
       
   327 // ---------------------------------------------------------
       
   328 // CMP4Parser::ReadFrames
       
   329 // Read the next frame(s) from file / stream
       
   330 // (other items were commented in a header).
       
   331 // ---------------------------------------------------------
       
   332 //
       
   333 
       
   334 TInt CMP4Parser::ReadFrames(TDes8& aDstBuffer, TFrameType aType, TUint32& aNumRead, 
       
   335 														TUint32& aTimeStamp)
       
   336 {
       
   337 	MP4Err error;
       
   338 	mp4_u32 returnedSize = 0;    
       
   339 	mp4_bool keyFrame = 0;
       
   340 
       
   341 	MPASSERT( iNextFrameType != EFrameTypeNone && aType == iNextFrameType ); 
       
   342 	MPASSERT( iNextFrameLength != 0 );
       
   343 
       
   344 #ifdef _DEBUG
       
   345 	mp4_u32 type = MP4_TYPE_NONE; // buffer support
       
   346 	type = ( aType == EFrameTypeVideo ) ? iVideoType : iAudioType; // buffer support
       
   347 	if (iStreamSource == ESourceUser)
       
   348 		MPASSERT( MP4ParseIsFrameAvailable(iMP4Handle, type) == MP4_OK );
       
   349 #endif
       
   350 
       
   351 
       
   352 	if (aType == EFrameTypeVideo) 
       
   353 	{	
       
   354 		TUint32 iTimeStampInTicks=0;
       
   355 		mp4_u32 mp4Specific = 0;
       
   356 
       
   357 		if ( (iFirstRead) &&
       
   358 		     ((iVideoType == MP4_TYPE_MPEG4_VIDEO) || (iVideoType == MP4_TYPE_AVC_PROFILE_BASELINE)) ) 		   
       
   359 		{
       
   360 			error = MP4ParseReadVideoDecoderSpecificInfo( iMP4Handle, (mp4_u8*)(aDstBuffer.Ptr() + aDstBuffer.Length()), 
       
   361 				mp4_u32( aDstBuffer.MaxLength() ), &mp4Specific );
       
   362 			iFirstRead = EFalse;
       
   363 		}
       
   364 		
       
   365 		error = MP4ParseReadVideoFrame(iMP4Handle, (mp4_u8*)(aDstBuffer.Ptr() + aDstBuffer.Length()+ mp4Specific), 
       
   366 			mp4_u32( aDstBuffer.MaxLength() ), &returnedSize, (mp4_u32*)&aTimeStamp,
       
   367 			&keyFrame, &iTimeStampInTicks);					    
       
   368 
       
   369 		returnedSize += mp4Specific;
       
   370 		iFrameNumber++;
       
   371 		aNumRead = 1;
       
   372 	}
       
   373 	else 
       
   374 	{       
       
   375 		error = MP4ParseReadAudioFrames(iMP4Handle, (mp4_u8*)(aDstBuffer.Ptr()), 
       
   376 			mp4_u32(aDstBuffer.MaxLength()), &returnedSize, (mp4_u32*)&aTimeStamp, 
       
   377 			(mp4_u32*)&aNumRead, NULL);               
       
   378 		
       
   379 		//PRINT((_L("audio TS:%d, "), aTimeStamp));
       
   380 	}
       
   381 	
       
   382 	MPASSERT(error != MP4_BUFFER_TOO_SMALL);    
       
   383 	aDstBuffer.SetLength(aDstBuffer.Length() + TInt(returnedSize));
       
   384 	iBytesRead += returnedSize;
       
   385 	iNextFrameType = EFrameTypeNone;
       
   386 	iNextFrameLength = 0;
       
   387 		
       
   388 	//PRINT((_L("error=%d, numReturned=%d, returnedSize=%d, bufferSize=%d\n"), 
       
   389 	//	error, aNumRead, returnedSize, aDstBuffer.MaxLength()));
       
   390 		
       
   391 	if (error == MP4_NOT_AVAILABLE)
       
   392 		return EParserNotEnoughData;    
       
   393 	else if ( error == MP4_INVALID_INPUT_STREAM )
       
   394 		return KErrCorrupt;
       
   395 	else if ( error != MP4_OK )
       
   396 		return KErrorCode;
       
   397     else
       
   398         return KErrNone;
       
   399 }
       
   400 
       
   401 
       
   402 // ---------------------------------------------------------
       
   403 // CMP4Parser::Reset
       
   404 // Resets the parser to its initial state
       
   405 // (other items were commented in a header).
       
   406 // ---------------------------------------------------------
       
   407 //
       
   408 
       
   409 TInt CMP4Parser::Reset()
       
   410 {
       
   411 	MP4Err error;
       
   412 	
       
   413 	if ( iStreamSource == ESourceFile )
       
   414 	{
       
   415 		mp4_u32 audioPos, videoPos;
       
   416 		
       
   417 		// seek to very beginning
       
   418 		error = MP4ParseSeek(iMP4Handle, 0, &audioPos, &videoPos, EFalse);
       
   419 		if ( error != MP4_OK )
       
   420 			return KErrorCode;
       
   421 		
       
   422 		MPASSERT( videoPos == 0 && (iAudioType == 0 || audioPos == 0) );		
       
   423 		
       
   424 	}
       
   425 	else 
       
   426 	{
       
   427 		// close & open library to make sure old data is flushed
       
   428 		error = MP4ParseClose(iMP4Handle);
       
   429 		
       
   430 		if ( error != MP4_OK )
       
   431 			return KErrorCode;
       
   432 		error = MP4ParseOpen(&iMP4Handle, 0);
       
   433 		if ( error != MP4_OK )
       
   434 			return KErrorCode;                    
       
   435 	}
       
   436 	
       
   437 	iBytesRead = 0;
       
   438 	iNextFrameType = EFrameTypeNone;
       
   439 	iNextFrameLength = 0;
       
   440 	
       
   441 	return KErrNone;
       
   442 }
       
   443 
       
   444 
       
   445 // ---------------------------------------------------------
       
   446 // CMP4Parser::ParseHeaderL
       
   447 // Get relevant stream parameters by calling mp4 library functions
       
   448 // (other items were commented in a header).
       
   449 // ---------------------------------------------------------
       
   450 //
       
   451 
       
   452 TInt CMP4Parser::ParseHeaderL(CParser::TStreamParameters& aStreamParameters)
       
   453 {
       
   454 
       
   455     PRINT((_L("CMP4Parser::ParseHeaderL() begin")));
       
   456 
       
   457 	MP4Err error;
       
   458 	mp4_double frameRate = 0;    
       
   459 	TBool hasVideo = ETrue;
       
   460 	
       
   461 	// Reset channel info
       
   462 	aStreamParameters.iHaveVideo = EFalse;
       
   463 	aStreamParameters.iHaveAudio = EFalse;
       
   464 	aStreamParameters.iNumDemuxChannels = 0;
       
   465 	aStreamParameters.iFileFormat = EFileFormatUnrecognized;
       
   466 	aStreamParameters.iVideoFormat = EVideoFormatNone;
       
   467 	aStreamParameters.iAudioFormat = EAudioFormatNone;
       
   468 	aStreamParameters.iVideoLength = 0;
       
   469 	aStreamParameters.iAudioLength = 0;
       
   470 	aStreamParameters.iStreamLength = 0;
       
   471 	aStreamParameters.iAudioFramesInSample = 0;
       
   472 	aStreamParameters.iVideoPicturePeriodNsec = 0;
       
   473 	aStreamParameters.iCanSeek = EFalse;
       
   474 	aStreamParameters.iFrameRate=0;
       
   475 	aStreamParameters.iVideoTimeScale=0; 
       
   476 	aStreamParameters.iAudioTimeScale=0; 
       
   477 	iAudioType = 0;
       
   478 	iVideoType = 0;
       
   479 	iNumberOfFrames=0;
       
   480 	
       
   481 	// get video description
       
   482 	error = MP4ParseRequestVideoDescription(iMP4Handle, (mp4_u32 *)&aStreamParameters.iVideoLength,
       
   483 		&frameRate, &iVideoType, (mp4_u32 *)&aStreamParameters.iVideoWidth, 
       
   484 		(mp4_u32 *)&aStreamParameters.iVideoHeight, (mp4_u32 *)&aStreamParameters.iVideoTimeScale);
       
   485 
       
   486 	if ( error == MP4_NOT_AVAILABLE )
       
   487 		User::Leave(KErrorCode);
       
   488 	else if ( error == MP4_INVALID_INPUT_STREAM )
       
   489 		User::Leave(KErrCorrupt);
       
   490 	else if ( error == MP4_NO_VIDEO )  
       
   491 	{
       
   492 		hasVideo = EFalse;
       
   493 		aStreamParameters.iVideoWidth = aStreamParameters.iVideoHeight = 0;
       
   494 	}
       
   495 	else if ( error != MP4_OK )
       
   496 		User::Leave(KErrorCode);
       
   497     else
       
   498     {
       
   499         MPASSERT(error == MP4_OK);
       
   500     }
       
   501 
       
   502 	// get audio description. ask also for averagebitrate to get error if the track is empty; the information is needed later on
       
   503     mp4_u32 averagebitrate = 0;
       
   504 
       
   505 	error = MP4ParseRequestAudioDescription(iMP4Handle, (mp4_u32 *)&aStreamParameters.iAudioLength, 
       
   506 		&iAudioType, (mp4_u8*)&aStreamParameters.iAudioFramesInSample, (mp4_u32 *)&aStreamParameters.iAudioTimeScale, &averagebitrate );
       
   507 
       
   508     if ( (error == MP4_ERROR) && ((iAudioType == MP4_TYPE_MPEG4_AUDIO) || (iAudioType == MP4_TYPE_AMR_NB) || (iAudioType == MP4_TYPE_AMR_WB)))
       
   509         {
       
   510         // a special case: there may be audio track but it is empty; if type was recognized, mark as no audio
       
   511         PRINT((_L("CMP4Parser::ParseHeaderL() problems with getting audio description, mark no audio since audio type was recognized")));
       
   512         iAudioType = MP4_NO_AUDIO;
       
   513         error = MP4_NO_AUDIO;
       
   514         }
       
   515 	if(error == MP4_NOT_AVAILABLE)     
       
   516 		User::Leave(EParserNotEnoughData);        
       
   517 	else if ( error == MP4_INVALID_INPUT_STREAM )
       
   518 		User::Leave(KErrCorrupt);
       
   519 	else if ( error != MP4_NO_AUDIO && error != MP4_OK )
       
   520 		User::Leave(KErrorCode);
       
   521     else
       
   522     {
       
   523         MPASSERT(error == MP4_OK || error == MP4_NO_AUDIO);
       
   524     }
       
   525 
       
   526     // store the sample size for sanity checking purposes
       
   527     iMaxAMRSampleSize = KVedMaxAMRFrameSize * aStreamParameters.iAudioFramesInSample;
       
   528 
       
   529 	if (aStreamParameters.iVideoLength > 0)
       
   530 		aStreamParameters.iStreamLength = aStreamParameters.iVideoLength;
       
   531 
       
   532 	if (aStreamParameters.iAudioLength > aStreamParameters.iVideoLength)
       
   533 		aStreamParameters.iStreamLength = aStreamParameters.iAudioLength;	
       
   534 	
       
   535 	aStreamParameters.iFrameRate = frameRate;
       
   536 
       
   537 	if(hasVideo)
       
   538 	{
       
   539 		    
       
   540 	    if ( iVideoType == MP4_TYPE_MPEG4_VIDEO )
       
   541 	    {
       
   542 	        // read video resolution from VOL header
       
   543 	        
       
   544 	        HBufC8* tmpBuffer = (HBufC8*) HBufC8::NewLC(KVOLHeaderBufferSize);
       
   545             TPtr8 tmpPtr = tmpBuffer->Des();
       
   546             mp4_u32 volSize = 0;
       
   547             MP4Err volError = 0;
       
   548             
       
   549             volError = MP4ParseReadVideoDecoderSpecificInfo( iMP4Handle, 
       
   550                                                             (mp4_u8*)(tmpPtr.Ptr()),
       
   551                                                             KVOLHeaderBufferSize,
       
   552                                                             &volSize );
       
   553                                                             
       
   554             if ( volError != MP4_OK )
       
   555             {
       
   556                 User::Leave(KErrorCode);
       
   557             }
       
   558             tmpPtr.SetLength(volSize);
       
   559             
       
   560             CVedVolReader* tmpVolReader = CVedVolReader::NewL();
       
   561             CleanupStack::PushL(tmpVolReader);
       
   562 
       
   563             tmpVolReader->ParseVolHeaderL(tmpPtr);
       
   564 
       
   565             aStreamParameters.iVideoWidth = tmpVolReader->Width();
       
   566             aStreamParameters.iVideoHeight = tmpVolReader->Height();
       
   567 
       
   568             CleanupStack::PopAndDestroy(tmpVolReader);
       
   569             CleanupStack::PopAndDestroy(tmpBuffer);		
       
   570 
       
   571 	    }		
       
   572 	    	    
       
   573 	    else if ( iVideoType == MP4_TYPE_AVC_PROFILE_BASELINE )
       
   574 	    {
       
   575 	        // read resolution from SPS
       
   576 
       
   577 	        HBufC8* tmpBuffer = (HBufC8*) HBufC8::NewLC(KAVCDCRBufferSize);	        	        
       
   578             TPtr8 ptr = tmpBuffer->Des();
       
   579             
       
   580             // read decoder specific info
       
   581             User::LeaveIfError( ReadAVCDecoderSpecificInfo(ptr) );
       
   582             
       
   583             // create AVC editing instance
       
   584             CVedAVCEdit* avcEdit = CVedAVCEdit::NewL();
       
   585             CleanupStack::PushL(avcEdit);
       
   586             
       
   587             TSize resolution(0,0);
       
   588             User::LeaveIfError( avcEdit->GetResolution(ptr, resolution) );
       
   589             
       
   590             CleanupStack::PopAndDestroy(avcEdit);
       
   591             CleanupStack::PopAndDestroy(tmpBuffer);
       
   592 
       
   593             aStreamParameters.iVideoWidth = resolution.iWidth;
       
   594             aStreamParameters.iVideoHeight = resolution.iHeight;
       
   595 	    }
       
   596 
       
   597 
       
   598 		iNumberOfFrames = GetNumberOfVideoFrames();
       
   599 		MPASSERT(iNumberOfFrames);
       
   600     
       
   601 		if (iFirstTimeClipParsing)	// update only at the first parsing of a clip
       
   602 		{
       
   603 			// update the frame numbers
       
   604 			
       
   605 			iOutputNumberOfFrames = iProcessor->GetOutputNumberOfFrames();		
       
   606 			
       
   607 			if (iOutputNumberOfFrames == 0)
       
   608 			{
       
   609 				iOutputNumberOfFrames += iNumberOfFrames;  // total number of frames in all clips	
       
   610 			}
       
   611 			else if (!iProcessor->IsThumbnailInProgress())
       
   612 			{
       
   613     			iOutputNumberOfFrames += iNumberOfFrames; 
       
   614 			}
       
   615 		}
       
   616 		
       
   617 		MPASSERT(frameRate > 0);
       
   618 		if (frameRate > 0)
       
   619 			aStreamParameters.iVideoPicturePeriodNsec = TInt64( TReal(1000000000) / TReal(frameRate) );
       
   620 		else
       
   621 			aStreamParameters.iVideoPicturePeriodNsec = TInt64(33366667);
       
   622 		
       
   623 		if ( iVideoType == MP4_TYPE_H263_PROFILE_0 || iVideoType == MP4_TYPE_H263_PROFILE_3 )
       
   624 		{
       
   625 			TVideoClipProperties prop;
       
   626 			prop.iH263Level = 0;
       
   627 			MP4ParseGetVideoClipProperties(iMP4Handle, prop);
       
   628 
       
   629             iMaxVideoFrameLength = KMaxCodedPictureSizeQCIF;
       
   630 			if (prop.iH263Level == 45)
       
   631                 {
       
   632 				aStreamParameters.iVideoFormat = EVideoFormatH263Profile0Level45;
       
   633                 }
       
   634 			else 
       
   635                 {
       
   636 				aStreamParameters.iVideoFormat = EVideoFormatH263Profile0Level10;
       
   637                 }
       
   638 		}
       
   639 		else if ( iVideoType == MP4_TYPE_MPEG4_VIDEO )
       
   640             {
       
   641 			aStreamParameters.iVideoFormat = EVideoFormatMPEG4;		
       
   642             if ( aStreamParameters.iVideoWidth <= KVedResolutionQCIF.iWidth )
       
   643                 {
       
   644                 iMaxVideoFrameLength = KMaxCodedPictureSizeMPEG4L0BQCIF;//distinction between L0 and L0B not possible here
       
   645                 }
       
   646             else if (aStreamParameters.iVideoWidth <= KVedResolutionCIF.iWidth )
       
   647                 {
       
   648                 iMaxVideoFrameLength = KMaxCodedPictureSizeMPEG4CIF;
       
   649                 }
       
   650             else
       
   651                 {
       
   652                 // VGA
       
   653                 iMaxVideoFrameLength = KMaxCodedPictureSizeVGA;
       
   654                 }
       
   655             }
       
   656             
       
   657         else if ( iVideoType == MP4_TYPE_AVC_PROFILE_BASELINE )
       
   658             {
       
   659 
       
   660             // : Is it possible to dig up the level here ??
       
   661 			aStreamParameters.iVideoFormat = EVideoFormatAVCProfileBaseline;
       
   662 			
       
   663             if ( aStreamParameters.iVideoWidth <= KVedResolutionQCIF.iWidth )
       
   664                 {
       
   665                 iMaxVideoFrameLength = KMaxCodedPictureSizeAVCLevel1B;  //distinction between L0 and L0B not possible here ??
       
   666                 }
       
   667             else if (aStreamParameters.iVideoWidth <= KVedResolutionCIF.iWidth )
       
   668                 {
       
   669                 iMaxVideoFrameLength = KMaxCodedPictureSizeAVCLevel1_2;
       
   670                 }
       
   671             else
       
   672                 {
       
   673                 // default
       
   674                 iMaxVideoFrameLength = KMaxCodedPictureSizeAVCLevel1_2;
       
   675                 }
       
   676             }
       
   677 	}	
       
   678 
       
   679 	if ( error == MP4_OK )
       
   680 	{
       
   681 		// stream contains audio 
       
   682 		if ( iAudioType == MP4_TYPE_AMR_NB )
       
   683 			aStreamParameters.iAudioFormat = EAudioFormatAMR;
       
   684 		else
       
   685 		{
       
   686 			if ( iAudioType == MP4_TYPE_MPEG4_AUDIO )
       
   687 				aStreamParameters.iAudioFormat = EAudioFormatAAC;
       
   688 		}		
       
   689 	}
       
   690 	
       
   691 	TBool videoMpeg4OrAVC = ( iVideoType == MP4_TYPE_MPEG4_VIDEO || 
       
   692 	                          iVideoType == MP4_TYPE_AVC_PROFILE_BASELINE );
       
   693 
       
   694 	if ( (videoMpeg4OrAVC && iAudioType == MP4_TYPE_MPEG4_AUDIO) ||
       
   695 		 (videoMpeg4OrAVC && iAudioType == MP4_TYPE_NONE) ||
       
   696 		 (iVideoType == MP4_TYPE_NONE && iAudioType == MP4_TYPE_MPEG4_AUDIO) )
       
   697 		aStreamParameters.iFileFormat = EFileFormatMP4;
       
   698 
       
   699 	else if (iVideoType != MP4_TYPE_NONE || iAudioType != MP4_TYPE_NONE)
       
   700 		aStreamParameters.iFileFormat = EFileFormat3GP;
       
   701 
       
   702 	if ( aStreamParameters.iStreamLength == 0 )
       
   703 		aStreamParameters.iFileFormat = EFileFormatUnrecognized;
       
   704 	
       
   705 	if ( aStreamParameters.iVideoFormat != EVideoFormatNone ) 
       
   706 	{
       
   707 		aStreamParameters.iHaveVideo = ETrue;
       
   708 		aStreamParameters.iNumDemuxChannels++;
       
   709 	}
       
   710 	
       
   711 	if ( aStreamParameters.iAudioFormat != EAudioFormatNone )
       
   712 	{
       
   713 		aStreamParameters.iHaveAudio = ETrue;
       
   714 		aStreamParameters.iNumDemuxChannels++;
       
   715 	}	
       
   716 	
       
   717 	aStreamParameters.iMaxPacketSize = 0;  // N/A
       
   718 	aStreamParameters.iLogicalChannelNumberVideo = 0;  // N/A
       
   719 	aStreamParameters.iLogicalChannelNumberAudio = 0;  // N/A
       
   720 	
       
   721 	// get stream description
       
   722 	error = MP4ParseRequestStreamDescription(iMP4Handle, (mp4_u32 *)&aStreamParameters.iStreamSize, 
       
   723 		(mp4_u32 *)&aStreamParameters.iStreamBitrate);    
       
   724 	if ( error != MP4_OK )     
       
   725 		User::Leave(KErrorCode);
       
   726 	
       
   727 	// do sanity-check for bitrate
       
   728 	if (aStreamParameters.iStreamBitrate < KMinBitrate)
       
   729 	    User::Leave(KErrCorrupt);
       
   730 	
       
   731 	aStreamParameters.iReferencePicturesNeeded = 0;     
       
   732 	aStreamParameters.iNumScalabilityLayers = 0;
       
   733 	
       
   734 	// determine if the stream contains INTRA frames so seeking is possible
       
   735 	// If the stream contains more than one INTRA frame, seeking is 
       
   736 	// allowed. 
       
   737 	
       
   738 	if (hasVideo)
       
   739 	{
       
   740 		mp4_u32 position = aStreamParameters.iStreamLength + 1000;
       
   741 		mp4_u32 audioTime, videoTime;
       
   742 		
       
   743 		// Seek past stream duration to find out the position of last INTRA frame
       
   744 		error = MP4ParseSeek(iMP4Handle, position, &audioTime, &videoTime, ETrue);
       
   745 		if ( error != MP4_OK )     
       
   746 			User::Leave(KErrorCode);
       
   747 		
       
   748 		if (videoTime != 0) 
       
   749 		{
       
   750 			// at least two INTRAs
       
   751 			aStreamParameters.iCanSeek = ETrue;
       
   752 		}
       
   753 		
       
   754 		// rewind file back to beginning
       
   755 		error = MP4ParseSeek(iMP4Handle, 0, &audioTime, &videoTime, EFalse);
       
   756 		if ( error != MP4_OK )     
       
   757 			User::Leave(KErrorCode);
       
   758 	}
       
   759 
       
   760     PRINT((_L("CMP4Parser::ParseHeaderL() end")));
       
   761 
       
   762 	return KErrNone; 
       
   763 }
       
   764 
       
   765 
       
   766 // ---------------------------------------------------------
       
   767 // CMP4Parser::IsStreamable
       
   768 // Finds out whether input stream is multiplexed so that
       
   769 // it can be streamed, i.e. played while receiving the stream.
       
   770 // (other items were commented in a header).
       
   771 // ---------------------------------------------------------
       
   772 //
       
   773 
       
   774 TInt CMP4Parser::IsStreamable()
       
   775 {
       
   776 	MP4Err error;
       
   777 	
       
   778 	error = MP4ParseIsStreamable(iMP4Handle);
       
   779 	if ( error == MP4_NOT_AVAILABLE )
       
   780 		return EParserNotEnoughData;
       
   781 	else if ( error == MP4_INVALID_INPUT_STREAM )
       
   782 		return KErrNotSupported;
       
   783 	else if ( error == MP4_ERROR )
       
   784 		return KErrorCode;    
       
   785 	else
       
   786 		return ( error == MP4_OK ) ? 1 : 0;
       
   787 }
       
   788 
       
   789 
       
   790 // ---------------------------------------------------------
       
   791 // CMP4Parser::Seek
       
   792 // Seeks the file to desired position in milliseconds
       
   793 // (other items were commented in a header).
       
   794 // ---------------------------------------------------------
       
   795 //
       
   796 TInt CMP4Parser::Seek(TUint32 aPositionInMs, TUint32& anAudioTimeAfter, TUint32& aVideoTimeAfter)
       
   797 {
       
   798 	
       
   799 	MP4Err error = MP4_OK;
       
   800 	MPASSERT(iStreamSource == ESourceFile);
       
   801 	error = MP4ParseSeek(iMP4Handle, aPositionInMs, &anAudioTimeAfter, &aVideoTimeAfter, ETrue);
       
   802 	if (error != MP4_OK)
       
   803 		return KErrorCode;    
       
   804 	
       
   805 	return KErrNone;
       
   806 }
       
   807 
       
   808 
       
   809 
       
   810 TInt CMP4Parser::GetNumberOfFrames()
       
   811 {
       
   812 	return iNumberOfFrames;
       
   813 }
       
   814 
       
   815 // ---------------------------------------------------------
       
   816 // CMP4Parser::SeekOptimalIntraFrame
       
   817 // Seeks to INTRA frame position before given time
       
   818 // (other items were commented in a header).
       
   819 // ---------------------------------------------------------
       
   820 //
       
   821 TInt CMP4Parser::SeekOptimalIntraFrame(TTimeIntervalMicroSeconds aStartTime, TInt /*aIndex*/, TBool aFirstTime)
       
   822 {
       
   823 	MP4Err error = KErrNone; 
       
   824 	TInt revisedNumberOfFrames = 0;
       
   825 	mp4_u32 audioTime = 0; 
       
   826 	mp4_u32 videoTime = 0; 
       
   827 //	mp4_u32 timeScale = 0; 
       
   828  
       
   829 	// calculate the start time of the cut operation
       
   830 	TInt64 startTime = aStartTime.Int64() / TInt64(1000);    
       
   831 	mp4_u32 startPosition = (mp4_u32)( I64INT(startTime) ); // in milliseconds
       
   832 
       
   833 	TBool intraFound = (startPosition == 0);
       
   834 	
       
   835 	if (!aFirstTime)	
       
   836 	    intraFound = 0;
       
   837 		
       
   838 	// First check if the first included frame is intra	
       
   839 	if (!intraFound)
       
   840 	{
       
   841 	    // seek to previous frame preceding start time or at start time
       
   842 	    error = MP4ParseSeek(iMP4Handle, startPosition, &audioTime, &videoTime, EFalse);
       
   843 	    if (error != MP4_OK)
       
   844 	    {		
       
   845 		    return KErrorCode; 
       
   846 	    }
       
   847 	    MPASSERT(videoTime <= startPosition);
       
   848 
       
   849 	    // get index of the frame
       
   850 	    TInt index = iProcessor->GetVideoFrameIndex(TTimeIntervalMicroSeconds(videoTime*1000));
       
   851 	    
       
   852 	    if (videoTime < startPosition)	    
       
   853 	    {
       
   854 	        // if there was no frame at start time, seek 
       
   855 	        // one frame forward to the first included frame
       
   856             index++;
       
   857 	    }
       
   858 	    
       
   859         // get frame type
       
   860         mp4_bool frameType;
       
   861 	    error = MP4ParseGetVideoFrameType(iMP4Handle, index, &frameType);	    
       
   862 	    if (error != MP4_OK)
       
   863 	    {		
       
   864             return KErrorCode; 
       
   865 	    }
       
   866 	    if (frameType == 1)
       
   867 	    {
       
   868 	        intraFound = ETrue;
       
   869 	        iStartFrameIndex = index;
       
   870 	        
       
   871 	        mp4_u32 timeInTicks;
       
   872 	        // get timestamp of matched frame to startPosition
       
   873 	        error = MP4ParseGetVideoFrameStartTime(iMP4Handle, index, &timeInTicks, &startPosition);
       
   874 	        if (error != MP4_OK)
       
   875 	        {		
       
   876 		        return KErrorCode; 
       
   877 	        }	        
       
   878 	        
       
   879 	        // Now seek to found Intra in 1 ms increments. The loop is needed 
       
   880 	        // because due to rounding error, MP4Parser may seek to previous
       
   881 	        // frame instead of the I-frame at startPosition
       
   882 	        TInt seekTime = startPosition;
       
   883 	        videoTime = 0;
       
   884 	        
       
   885 	        while (videoTime != startPosition)
       
   886 	        {	            	        
       
   887     	        error = MP4ParseSeek(iMP4Handle, seekTime, &audioTime, &videoTime, EFalse);
       
   888         	    if (error != MP4_OK)
       
   889         	    {		
       
   890         		    return KErrorCode; 
       
   891         	    }
       
   892         	    MPASSERT(videoTime <= startPosition);
       
   893         	    seekTime++;  // add 1 ms
       
   894 	        }
       
   895         	
       
   896 	    }                
       
   897 	}	
       
   898 	
       
   899 	if (!intraFound)
       
   900 	{	    
       
   901     	// seek to the I-frame preceding the start time
       
   902     	error = MP4ParseSeek(iMP4Handle, startPosition, &audioTime, &videoTime, ETrue);
       
   903     	if (error != MP4_OK)
       
   904     	{		
       
   905     		return KErrorCode; 
       
   906     	}
       
   907 	}
       
   908 	
       
   909 	if (videoTime != 0) 
       
   910 	{
       
   911 	    if (!intraFound)
       
   912         {                
       
   913             // get index of the intra frame
       
   914             TInt64 time = TInt64(TUint(videoTime)) * TInt64(1000);
       
   915             iStartFrameIndex = iProcessor->GetVideoFrameIndex(TTimeIntervalMicroSeconds( time ));            
       
   916         }        		
       
   917 		
       
   918 		if (aFirstTime)
       
   919 		{	
       
   920 		    revisedNumberOfFrames = iNumberOfFrames - iStartFrameIndex;	    
       
   921 		    // update movie and clip number of frames
       
   922             iOutputNumberOfFrames -= iStartFrameIndex;            
       
   923             iNumberOfFrames = revisedNumberOfFrames; 
       
   924 		}
       
   925 				
       
   926 		PRINT((_L("CMP4Parser::SeekOptimalIntraFrame() revised = %d"),revisedNumberOfFrames));
       
   927         PRINT((_L("CMP4Parser::SeekOptimalIntraFrame() iNumberOfFrames = %d"),iNumberOfFrames));
       
   928         PRINT((_L("CMP4Parser::SeekOptimalIntraFrame() iStartFrameIndex = %d"),iStartFrameIndex));                                
       
   929         PRINT((_L("CMP4Parser::SeekOptimalIntraFrame() iOutputNumberOfFrames = %d"),iOutputNumberOfFrames));        				
       
   930         iFrameNumber = iStartFrameIndex;
       
   931 	}
       
   932 	return KErrNone;
       
   933 }
       
   934 
       
   935 // ---------------------------------------------------------
       
   936 // CMP4Parser::GetNumberOfVideoFrames
       
   937 // Gets the number of video frames in clip
       
   938 // (other items were commented in a header).
       
   939 // ---------------------------------------------------------
       
   940 //
       
   941 TInt CMP4Parser::GetNumberOfVideoFrames()
       
   942 {
       
   943     mp4_u32 numberOfFrames = 0;
       
   944     MP4Err error = 0;    
       
   945 
       
   946     error = MP4ParseGetNumberOfVideoFrames(iMP4Handle, &numberOfFrames);
       
   947 
       
   948     if (error != MP4_OK)
       
   949         return 0;
       
   950 
       
   951     return numberOfFrames;
       
   952   
       
   953 }
       
   954 
       
   955 // ---------------------------------------------------------
       
   956 // CMP4Parser::GetVideoFrameSize
       
   957 // Gets the size of video frame at given index
       
   958 // (other items were commented in a header).
       
   959 // ---------------------------------------------------------
       
   960 //
       
   961 TInt CMP4Parser::GetVideoFrameSize(TInt aIndex)
       
   962 {
       
   963     mp4_u32 frameSize = 0;
       
   964 	mp4_u32 mp4Specific = 0;
       
   965     MP4Err error = 0;
       
   966 
       
   967 	if ( aIndex == 0 && iVideoType == MP4_TYPE_MPEG4_VIDEO )
       
   968 	{
       
   969 		error = MP4ParseReadVideoDecoderSpecificInfo( iMP4Handle, 0, 0, &mp4Specific );
       
   970 		
       
   971 		if ( error != MP4_OK && error != MP4_BUFFER_TOO_SMALL )
       
   972 			return KErrorCode;
       
   973 	}
       
   974 
       
   975     error = MP4ParseGetVideoFrameSize(iMP4Handle, aIndex, &frameSize);
       
   976 
       
   977     if (error != MP4_OK)
       
   978         return KErrorCode;
       
   979 
       
   980     return frameSize + mp4Specific;
       
   981 	
       
   982 }
       
   983 
       
   984 
       
   985 
       
   986 // ---------------------------------------------------------
       
   987 // CMP4Parser::GetVideoFrameStartTime
       
   988 // Returns frame start time in millisec - optional iTimestamp for start time in ticks
       
   989 // (other items were commented in a header).
       
   990 // ---------------------------------------------------------
       
   991 //
       
   992 TInt CMP4Parser::GetVideoFrameStartTime(TInt aIndex, TInt* aTimeStampInTicks)
       
   993 {
       
   994 
       
   995     MP4Err error = 0;
       
   996     mp4_u32 timeStampInMs = 0;
       
   997 
       
   998     MPASSERT(aTimeStampInTicks);
       
   999   
       
  1000     PRINT((_L("CMP4Parser::GetVideoFrameStartTime(), get time for index %d"), aIndex));
       
  1001     error = MP4ParseGetVideoFrameStartTime(iMP4Handle, aIndex, (mp4_u32*)aTimeStampInTicks, &timeStampInMs);
       
  1002 
       
  1003     if (error != MP4_OK)
       
  1004         {
       
  1005         PRINT((_L("CMP4Parser::GetVideoFrameStartTime(), error from MP4 parser %d"), error));
       
  1006         return KErrorCode;
       
  1007         }
       
  1008 
       
  1009     PRINT((_L("CMP4Parser::GetVideoFrameStartTime(), time in ms %d"), timeStampInMs));
       
  1010     return timeStampInMs;
       
  1011   
       
  1012 }
       
  1013 
       
  1014 
       
  1015 // ---------------------------------------------------------
       
  1016 // CMP4Parser::GetVideoFrameType
       
  1017 // Gets the type of video frame at given index
       
  1018 // (other items were commented in a header).
       
  1019 // ---------------------------------------------------------
       
  1020 //
       
  1021 TInt8 CMP4Parser::GetVideoFrameType(TInt aIndex)
       
  1022 {
       
  1023 
       
  1024     MP4Err error = 0;
       
  1025     mp4_bool frameType;
       
  1026     
       
  1027     error = MP4ParseGetVideoFrameType(iMP4Handle, aIndex, &frameType);
       
  1028 
       
  1029     if (error != MP4_OK)
       
  1030         return KErrGeneral;
       
  1031  
       
  1032 	return TInt8(frameType);
       
  1033 }
       
  1034 
       
  1035 
       
  1036 // ---------------------------------------------------------
       
  1037 // CMP4Parser::GetVideoFrameProperties
       
  1038 // Gets frame properties
       
  1039 // (other items were commented in a header).
       
  1040 // ---------------------------------------------------------
       
  1041 //
       
  1042 TInt CMP4Parser::GetVideoFrameProperties(TFrameInfoParameters* aVideoFrameInfoArray,
       
  1043 										 TUint32 aStartIndex, TUint32 aSizeOfArray)
       
  1044 {	
       
  1045 	MP4Err error;
       
  1046 	error = MP4GetVideoFrameProperties(iMP4Handle,aStartIndex,aSizeOfArray,aVideoFrameInfoArray);
       
  1047 
       
  1048 	if (error != MP4_OK)
       
  1049 		return KErrorCode;
       
  1050 
       
  1051 	return KErrNone;
       
  1052 }
       
  1053 
       
  1054 
       
  1055 // ---------------------------------------------------------
       
  1056 // CMP4Parser::ParseAudioInfo
       
  1057 // Gets the frame information (frame size) for audio in the current clip
       
  1058 // (other items were commented in a header).
       
  1059 // ---------------------------------------------------------
       
  1060 //
       
  1061 TInt CMP4Parser::ParseAudioInfo(TInt& aAudioFrameSize)
       
  1062 {
       
  1063 	MP4Err error;
       
  1064 	mp4_u32 audioLength=0;
       
  1065 	mp4_u32 audioType=0;
       
  1066 	mp4_u32 audioFramesInSample=0;
       
  1067 	mp4_u32 audioTimeScale=0;
       
  1068     mp4_u32 avgBitRate=0;
       
  1069 	mp4_double frameLength = 0.02; // 20 ms
       
  1070 
       
  1071 	error = MP4ParseRequestAudioDescription(iMP4Handle, (mp4_u32 *)&audioLength, 
       
  1072 		&audioType, (mp4_u8*)&audioFramesInSample, (mp4_u32 *)&audioTimeScale, (mp4_u32*)&avgBitRate);
       
  1073     aAudioFrameSize = ((mp4_u32)((mp4_double)avgBitRate*frameLength)>>3); 
       
  1074 
       
  1075 	return error;
       
  1076 }
       
  1077 
       
  1078 TInt CMP4Parser::GetMP4SpecificSize()
       
  1079 {
       
  1080 	MP4Err error = 0;
       
  1081 	mp4_u32 mp4Specific = 0;
       
  1082 	if ( iVideoType == MP4_TYPE_MPEG4_VIDEO )
       
  1083 	{
       
  1084 		error = MP4ParseReadVideoDecoderSpecificInfo( iMP4Handle, 0, 0, &mp4Specific );
       
  1085 		if ( error != MP4_OK && error != MP4_BUFFER_TOO_SMALL )
       
  1086 			return KErrGeneral;
       
  1087 	}
       
  1088 	return mp4Specific;
       
  1089 }
       
  1090 
       
  1091 // ---------------------------------------------------------
       
  1092 // CMP4Parser::ReadAudioDecoderSpecificInfoL
       
  1093 // Gets the decoder specific info from the current file filled so that it can be composed to output file
       
  1094 // (other items were commented in a header).
       
  1095 // ---------------------------------------------------------
       
  1096 //
       
  1097 TInt CMP4Parser::ReadAudioDecoderSpecificInfoL(HBufC8*& aBytes, TInt aBufferSize)
       
  1098 {
       
  1099 	aBytes = HBufC8::NewL(aBufferSize);
       
  1100 	CleanupStack::PushL(aBytes);
       
  1101 	mp4_u8 *buffer = new (ELeave) mp4_u8[aBufferSize];
       
  1102 	mp4_u32 decspecinfosize = 0;
       
  1103 	
       
  1104 	MP4Err err = MP4ParseReadAudioDecoderSpecificInfo(
       
  1105 		iMP4Handle,
       
  1106 		buffer,
       
  1107 		aBufferSize,
       
  1108 		&decspecinfosize);
       
  1109 	if (err == MP4_OK)
       
  1110 	{
       
  1111 		for (TInt a = 0 ; a < (TInt)decspecinfosize ; a++)
       
  1112 		{
       
  1113 			aBytes->Des().Append(buffer[a]);
       
  1114 		}
       
  1115 	}
       
  1116 	else
       
  1117 	{
       
  1118 		delete[] buffer;
       
  1119 		buffer = 0;
       
  1120 		CleanupStack::PopAndDestroy(aBytes);
       
  1121 		aBytes = 0;
       
  1122 		User::Leave(KErrGeneral);
       
  1123 	}
       
  1124 	delete[] buffer;
       
  1125 	buffer = 0;
       
  1126 	CleanupStack::Pop(aBytes);
       
  1127 	return ETrue;
       
  1128 }
       
  1129 
       
  1130 // ---------------------------------------------------------
       
  1131 // CMP4Parser::SetDefaultAudioDecoderSpecificInfoL
       
  1132 // Gets the default decoder specific info filled so that it can be composed to output file
       
  1133 // the default info is for a 16 KHz, mono LC type AAC only
       
  1134 // (other items were commented in a header).
       
  1135 // ---------------------------------------------------------
       
  1136 //
       
  1137 TInt CMP4Parser::SetDefaultAudioDecoderSpecificInfoL(HBufC8*& aBytes, TInt aBufferSize)
       
  1138 {
       
  1139 	aBytes = HBufC8::NewL(aBufferSize);
       
  1140 	CleanupStack::PushL(aBytes);
       
  1141 	
       
  1142 	const TUint8 frameDecSpecInfo[] = {0x14,0x08};	//the decoder specific 
       
  1143 	const TInt frameSize = 2;  //constant as maximum size of decoderspecific info is 2
       
  1144 	
       
  1145 		for (TInt a = 0 ; a < frameSize ; a++)
       
  1146 		{
       
  1147 			aBytes->Des().Append(frameDecSpecInfo[a]);
       
  1148 		}
       
  1149 	CleanupStack::Pop(aBytes);
       
  1150 	return ETrue;
       
  1151 }
       
  1152 
       
  1153 
       
  1154 TInt CMP4Parser::GetAudioBitrate(TInt& aBitrate)
       
  1155 {
       
  1156 
       
  1157     mp4_u32 length;
       
  1158     mp4_u32 type;
       
  1159     mp4_u8 framesPerSample;
       
  1160     mp4_u32 timeScale;
       
  1161     mp4_u32 averageBitrate;
       
  1162 
       
  1163     MP4Err error = 0;
       
  1164     
       
  1165     error = MP4ParseRequestAudioDescription(iMP4Handle, &length, 
       
  1166         &type, &framesPerSample, &timeScale, &averageBitrate);
       
  1167 
       
  1168     if ( error != 0 )
       
  1169         return KErrGeneral;
       
  1170 
       
  1171     aBitrate = averageBitrate;
       
  1172 
       
  1173     return KErrNone;
       
  1174 
       
  1175 
       
  1176 }
       
  1177 
       
  1178 TInt CMP4Parser::GetVideoFrameRate(TReal& aFrameRate)
       
  1179 {
       
  1180 
       
  1181     mp4_u32 length;
       
  1182     mp4_double frameRate; 
       
  1183     mp4_u32 videoType;
       
  1184     mp4_u32 width;
       
  1185     mp4_u32 height;
       
  1186     mp4_u32 timeScale;
       
  1187 
       
  1188     MP4Err error = 0;
       
  1189 
       
  1190     // get video description
       
  1191 	error = MP4ParseRequestVideoDescription(iMP4Handle, &length, &frameRate, 
       
  1192         &videoType, &width, &height, &timeScale);		
       
  1193 
       
  1194     if ( error != 0 )
       
  1195         return KErrGeneral;
       
  1196     
       
  1197     TReal temp = frameRate * 2.0;
       
  1198     TInt temp2 = TInt(temp + 0.5);
       
  1199 
       
  1200     aFrameRate = temp2 / 2.0;
       
  1201 
       
  1202     return KErrNone;
       
  1203 }
       
  1204 
       
  1205 TInt CMP4Parser::GetDecoderSpecificInfoSize()
       
  1206 {
       
  1207 
       
  1208     MPASSERT(iMP4Handle);
       
  1209 
       
  1210     mp4_u32 mp4Specific = 0;
       
  1211         
       
  1212     MP4Err error = MP4ParseReadVideoDecoderSpecificInfo( iMP4Handle, 0, 0, &mp4Specific );        
       
  1213     
       
  1214     if ( error != MP4_OK && error != MP4_BUFFER_TOO_SMALL )
       
  1215         return KErrGeneral;
       
  1216     
       
  1217     return mp4Specific;
       
  1218 }
       
  1219 
       
  1220 TInt CMP4Parser::ReadAVCDecoderSpecificInfo(TDes8& buf)
       
  1221 {
       
  1222 
       
  1223     mp4_u32 mp4Specific = 0;
       
  1224     
       
  1225     MP4Err error = MP4ParseReadVideoDecoderSpecificInfo( iMP4Handle, (mp4_u8*)(buf.Ptr()), 
       
  1226 				mp4_u32( buf.MaxLength() ), &mp4Specific );
       
  1227         
       
  1228         
       
  1229     if (error != MP4_OK)
       
  1230 	    return KErrorCode;
       
  1231     
       
  1232     buf.SetLength(mp4Specific);
       
  1233     
       
  1234     return KErrNone;
       
  1235     
       
  1236 }
       
  1237 
       
  1238 TInt CMP4Parser::GetVideoDuration(TInt& aDurationInMs)
       
  1239 {
       
  1240 
       
  1241     mp4_u32 length;
       
  1242     mp4_double frameRate; 
       
  1243     mp4_u32 videoType;
       
  1244     mp4_u32 width;
       
  1245     mp4_u32 height;
       
  1246     mp4_u32 timeScale;
       
  1247 
       
  1248     MP4Err error = 0;
       
  1249 
       
  1250     // get video description
       
  1251 	error = MP4ParseRequestVideoDescription(iMP4Handle, &length, &frameRate, 
       
  1252         &videoType, &width, &height, &timeScale);		
       
  1253 
       
  1254     if ( error != MP4_OK )
       
  1255         return KErrGeneral;
       
  1256     
       
  1257     aDurationInMs = length;
       
  1258 
       
  1259     return KErrNone;
       
  1260     
       
  1261 }
       
  1262 
       
  1263 
       
  1264 // End of File