os/mm/mmplugins/lib3gpunittest/src/tsu_3gplibrary_parse_compose.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
//
sl@0
    15
sl@0
    16
#include "tsu_3gplibrary_parse_compose.h"
sl@0
    17
sl@0
    18
const TUint16 KAudioModeSet = 0x81ff;
sl@0
    19
const TReal KMillisecondsInSecond = 1000;
sl@0
    20
const TReal KOneHalf = 0.5;
sl@0
    21
const TInt KLargeFileWriteBufferSize = 16384;  // 16K
sl@0
    22
const TInt KLargeFileWriteBufferMaxCount = 15;
sl@0
    23
sl@0
    24
_LIT( KAvcBaseline, "Baseline" );
sl@0
    25
_LIT( KAvcMain, "Main" );
sl@0
    26
_LIT( KAvcExtended, "Extended" );
sl@0
    27
_LIT( KAvcHigh, "High" );
sl@0
    28
sl@0
    29
const static TDesC* KAvcProfileNames[] = {
sl@0
    30
        &KAvcBaseline,
sl@0
    31
        &KAvcMain,
sl@0
    32
        &KAvcExtended,
sl@0
    33
        &KAvcHigh
sl@0
    34
    };
sl@0
    35
sl@0
    36
sl@0
    37
C3GPLibParseComposeFile::C3GPLibParseComposeFile() :
sl@0
    38
	iCompareOriginal(EFalse),
sl@0
    39
	iLargeFile(EFalse)	
sl@0
    40
	{
sl@0
    41
	}
sl@0
    42
sl@0
    43
TVerdict C3GPLibParseComposeFile::doTestStepPreambleL()
sl@0
    44
	{
sl@0
    45
	#ifdef __WINSCW__
sl@0
    46
	_LIT(KInputDir, "inputDirEmul");
sl@0
    47
	_LIT(KOutputDir, "outputDirEmul");
sl@0
    48
	#else
sl@0
    49
	_LIT(KInputDir, "inputDirHw");
sl@0
    50
	_LIT(KOutputDir, "outputDirHw");
sl@0
    51
	#endif
sl@0
    52
	// ensure test always starts with clean results
sl@0
    53
	SetTestStepResult(EPass);
sl@0
    54
	SetTestStepError(KErrNone);
sl@0
    55
	
sl@0
    56
	// ensure there's always a Active Scheduler for the Composer
sl@0
    57
	if (!CActiveScheduler::Current())
sl@0
    58
		{
sl@0
    59
		iScheduler = new (ELeave) CActiveScheduler;
sl@0
    60
		CActiveScheduler::Install(iScheduler);	
sl@0
    61
		}
sl@0
    62
	
sl@0
    63
	User::LeaveIfError(iFs.Connect());
sl@0
    64
	// retrieve the input files' directory 
sl@0
    65
	TPtrC inputFileDir;
sl@0
    66
	TBool composeFile = EFalse;
sl@0
    67
	TPtrC outputFileDir;					
sl@0
    68
	if (GetStringFromConfig(ConfigSection(), KInputDir, inputFileDir))
sl@0
    69
		{
sl@0
    70
		if (inputFileDir.Length() == 0)
sl@0
    71
			{
sl@0
    72
			ERR_PRINTF1(_L("Ensure input directory is specified."));
sl@0
    73
			SetTestStepResult(EInconclusive);			
sl@0
    74
			return TestStepResult();
sl@0
    75
			}
sl@0
    76
		else 
sl@0
    77
			{
sl@0
    78
			iInputDir.CreateL(inputFileDir);
sl@0
    79
			}
sl@0
    80
		
sl@0
    81
		GetIntFromConfig(ConfigSection(), _L("expectedFailure"), iExpectedNumberOfFailure);
sl@0
    82
		
sl@0
    83
		if (GetBoolFromConfig(ConfigSection(), _L("composeFile"), composeFile))
sl@0
    84
			{
sl@0
    85
			if (composeFile)
sl@0
    86
				{
sl@0
    87
				if (GetStringFromConfig(ConfigSection(), KOutputDir, outputFileDir))
sl@0
    88
					{
sl@0
    89
					if (outputFileDir.Length() == 0)
sl@0
    90
						{
sl@0
    91
						ERR_PRINTF1(_L("Ensure output directory is specified."));
sl@0
    92
						SetTestStepResult(EInconclusive);			
sl@0
    93
						return TestStepResult();
sl@0
    94
						}
sl@0
    95
					else if (outputFileDir == inputFileDir)
sl@0
    96
						{
sl@0
    97
						ERR_PRINTF1(_L("Ensure output directory is not the same as input directory."));
sl@0
    98
						SetTestStepResult(EInconclusive);			
sl@0
    99
						return TestStepResult();						
sl@0
   100
						}
sl@0
   101
					else if (!GetIntFromConfig(ConfigSection(), _L("fileFormat"), iFileFormat))
sl@0
   102
						{
sl@0
   103
						ERR_PRINTF1(_L("Ensure a output file format is specified."));
sl@0
   104
						SetTestStepResult(EInconclusive);			
sl@0
   105
						return TestStepResult();												
sl@0
   106
						}
sl@0
   107
					
sl@0
   108
					GetIntFromConfig(ConfigSection(), _L("composeFlag"), iComposeFlag);
sl@0
   109
					GetBoolFromConfig(ConfigSection(), _L("compareOriginal"), iCompareOriginal);
sl@0
   110
					GetBoolFromConfig(ConfigSection(), _L("largeFile"), iLargeFile);					
sl@0
   111
					}
sl@0
   112
				else
sl@0
   113
					{
sl@0
   114
					ERR_PRINTF1(_L("Ensure output directory is specified."));
sl@0
   115
					SetTestStepResult(EInconclusive);
sl@0
   116
					}
sl@0
   117
				}
sl@0
   118
			}
sl@0
   119
		}
sl@0
   120
	else
sl@0
   121
		{
sl@0
   122
		ERR_PRINTF1(_L("Ensure input directory is specified."));
sl@0
   123
		SetTestStepResult(EInconclusive);
sl@0
   124
		}
sl@0
   125
	
sl@0
   126
	if (TestStepResult() == EPass)
sl@0
   127
		{
sl@0
   128
		// Create a list of all files contained in the input directory
sl@0
   129
		User::LeaveIfError(iFs.GetDir(inputFileDir, KEntryAttNormal, ESortNone, iDirList));			
sl@0
   130
		
sl@0
   131
		if (!iDirList || iDirList->Count() == 0)
sl@0
   132
			{
sl@0
   133
			ERR_PRINTF1(_L("Input directory is empty."));
sl@0
   134
			SetTestStepResult(EInconclusive);		
sl@0
   135
			}
sl@0
   136
		}
sl@0
   137
	
sl@0
   138
	if (TestStepResult() == EPass)
sl@0
   139
		{
sl@0
   140
		iParser = C3GPParse::NewL();
sl@0
   141
		if (composeFile)
sl@0
   142
			{
sl@0
   143
			if (iLargeFile)
sl@0
   144
				{
sl@0
   145
				iComposer = C3GPCompose::NewL(KLargeFileWriteBufferSize, KLargeFileWriteBufferMaxCount);				
sl@0
   146
				}
sl@0
   147
			else
sl@0
   148
				{
sl@0
   149
				iComposer = C3GPCompose::NewL();				
sl@0
   150
				}
sl@0
   151
sl@0
   152
			iOutputDir.CreateL(outputFileDir);
sl@0
   153
			TInt err = iFs.MkDirAll(iOutputDir);
sl@0
   154
			if (err != KErrNone && err != KErrAlreadyExists)
sl@0
   155
				{
sl@0
   156
				User::Leave(err);
sl@0
   157
				}
sl@0
   158
			}
sl@0
   159
		}
sl@0
   160
	
sl@0
   161
	return TestStepResult();
sl@0
   162
	}		
sl@0
   163
sl@0
   164
TVerdict C3GPLibParseComposeFile::doTestStepL()
sl@0
   165
	{
sl@0
   166
	if( TestStepResult() == EPass)
sl@0
   167
		{
sl@0
   168
		TInt failCount = 0;
sl@0
   169
		TInt fileCount = 0;
sl@0
   170
		RBuf filePath;
sl@0
   171
		CleanupClosePushL(filePath);
sl@0
   172
		filePath.CreateL(KMaxFileName);
sl@0
   173
		
sl@0
   174
		for (TInt i = 0; i < iDirList->Count(); i++)
sl@0
   175
			{
sl@0
   176
			const TEntry& entry = (*iDirList)[i];
sl@0
   177
			if (!entry.IsDir())
sl@0
   178
				{
sl@0
   179
				fileCount++;
sl@0
   180
				
sl@0
   181
				filePath.Copy(iInputDir);
sl@0
   182
				filePath.Append(entry.iName);
sl@0
   183
				
sl@0
   184
				INFO_PRINTF2(_L("ParseAndComposeL: file=%S"), &filePath);				
sl@0
   185
				TRAPD(err, ParseFileL(filePath));
sl@0
   186
				INFO_PRINTF2(_L("ParseAndComposeL returns: err = %d"), err);
sl@0
   187
				if( err != KErrNone )
sl@0
   188
					{
sl@0
   189
					iParser->Complete();
sl@0
   190
					if (iComposer)
sl@0
   191
						{
sl@0
   192
						iComposer->Complete();
sl@0
   193
						}
sl@0
   194
					failCount++;
sl@0
   195
					}
sl@0
   196
				else
sl@0
   197
					{
sl@0
   198
					if (iCompareOriginal && iComposer)
sl@0
   199
						{
sl@0
   200
						if (!CompareInputOuputFileL(filePath))
sl@0
   201
							{
sl@0
   202
							ERR_PRINTF1(_L("Input & output file is not the same"));
sl@0
   203
							failCount ++;
sl@0
   204
							}
sl@0
   205
						else
sl@0
   206
							{
sl@0
   207
							INFO_PRINTF1(_L("Input & output file is the same."));
sl@0
   208
							}
sl@0
   209
						}
sl@0
   210
					}				
sl@0
   211
				}
sl@0
   212
			}
sl@0
   213
		
sl@0
   214
		// clean up
sl@0
   215
		CleanupStack::PopAndDestroy(&filePath);
sl@0
   216
		
sl@0
   217
		INFO_PRINTF3(_L("%d of %d files failed"), failCount, fileCount);
sl@0
   218
		if (failCount != iExpectedNumberOfFailure)
sl@0
   219
			{
sl@0
   220
			ERR_PRINTF2(_L("Expected failure: %d - Test Failed"), iExpectedNumberOfFailure);
sl@0
   221
			SetTestStepResult(EFail);
sl@0
   222
			}		
sl@0
   223
		}
sl@0
   224
	
sl@0
   225
	return TestStepResult();
sl@0
   226
	}
sl@0
   227
sl@0
   228
TVerdict C3GPLibParseComposeFile::doTestStepPostambleL()
sl@0
   229
	{
sl@0
   230
	if( iScheduler )
sl@0
   231
		{
sl@0
   232
		CActiveScheduler::Install(NULL);
sl@0
   233
		delete iScheduler;
sl@0
   234
		}
sl@0
   235
	
sl@0
   236
	iOutputDir.Close();
sl@0
   237
	iInputDir.Close();
sl@0
   238
	iComposedFile.Close();
sl@0
   239
	
sl@0
   240
	delete iDirList;
sl@0
   241
	
sl@0
   242
	iParsedFileHandle64.Close();
sl@0
   243
	iComposedFileHandle64.Close();
sl@0
   244
	iFs.Close();
sl@0
   245
			
sl@0
   246
	delete iParser;	
sl@0
   247
	if (iComposer)
sl@0
   248
		{
sl@0
   249
		delete iComposer;
sl@0
   250
		}	
sl@0
   251
	
sl@0
   252
	return TestStepResult();
sl@0
   253
	}
sl@0
   254
sl@0
   255
void C3GPLibParseComposeFile::ParseFileL(const TDesC& aInputFile)
sl@0
   256
	{
sl@0
   257
	ASSERT(iParser);
sl@0
   258
	TInt err = 0;
sl@0
   259
	
sl@0
   260
	if (iLargeFile)
sl@0
   261
		{
sl@0
   262
		iParsedFileHandle64.Close();
sl@0
   263
		err = iParsedFileHandle64.Open(iFs, aInputFile, EFileShareReadersOrWriters);
sl@0
   264
		if (err == KErrNone)
sl@0
   265
			{
sl@0
   266
			err = iParser->Open(iParsedFileHandle64);		
sl@0
   267
			}
sl@0
   268
		}
sl@0
   269
	else
sl@0
   270
		{
sl@0
   271
		err = iParser->Open(aInputFile);		
sl@0
   272
		}
sl@0
   273
	
sl@0
   274
	if (err != KErrNone)
sl@0
   275
		{
sl@0
   276
		ERR_PRINTF2(_L("C3GPParse::Open() returns %d"), err);
sl@0
   277
		User::Leave(err);
sl@0
   278
		}
sl@0
   279
	
sl@0
   280
	//
sl@0
   281
	// Retrieve Video Properties
sl@0
   282
	//	
sl@0
   283
	T3GPVideoPropertiesBase* videoProperties = NULL;
sl@0
   284
	CleanupStack::PushL(videoProperties);
sl@0
   285
	
sl@0
   286
	RBuf8 videoDecoderSpecificInfo;
sl@0
   287
	CleanupClosePushL(videoDecoderSpecificInfo);
sl@0
   288
	
sl@0
   289
	TUint videoLengthInMs = 0;
sl@0
   290
		
sl@0
   291
	err = ParseVideoProperties(*iParser, videoDecoderSpecificInfo, videoProperties, videoLengthInMs);
sl@0
   292
	if (err != KErrNone && err != KErrNotSupported)
sl@0
   293
		{
sl@0
   294
		ERR_PRINTF2(_L("ParseVideoProperties failed: err = %d"), err);
sl@0
   295
		User::Leave(err);
sl@0
   296
		}
sl@0
   297
	
sl@0
   298
	//
sl@0
   299
	// Retrieve Audio Properties
sl@0
   300
	//
sl@0
   301
	T3GPAudioPropertiesBase* audioProperties = NULL;
sl@0
   302
	CleanupStack::PushL(audioProperties);	
sl@0
   303
sl@0
   304
	RBuf8 audioDecoderSpecificInfo;
sl@0
   305
	CleanupClosePushL(audioDecoderSpecificInfo);
sl@0
   306
	
sl@0
   307
	TUint audioLengthInMs = 0;
sl@0
   308
	err = ParseAudioProperties(*iParser, audioDecoderSpecificInfo, audioProperties, audioLengthInMs);
sl@0
   309
	if( err != KErrNone && err != KErrNotSupported)
sl@0
   310
		{
sl@0
   311
		ERR_PRINTF2(_L("ParseAudioProperties failed: err = %d"), err);		
sl@0
   312
		User::Leave(err);
sl@0
   313
		}
sl@0
   314
sl@0
   315
	if (!videoProperties && !audioProperties)
sl@0
   316
		{
sl@0
   317
		ERR_PRINTF1(_L("File contains neither video nor audio data"));
sl@0
   318
		User::Leave(KErrNotFound);		
sl@0
   319
		}
sl@0
   320
	
sl@0
   321
	//
sl@0
   322
	// Prepare for the Composer if file output is expected 
sl@0
   323
	//	
sl@0
   324
	if (iComposer)
sl@0
   325
		{
sl@0
   326
		RBuf outputFile;
sl@0
   327
		CleanupClosePushL(outputFile);
sl@0
   328
		
sl@0
   329
		outputFile.CreateL(KMaxFileName);
sl@0
   330
		outputFile.Copy(iOutputDir);
sl@0
   331
		
sl@0
   332
		TParsePtrC parsePtr(aInputFile);
sl@0
   333
		TPtrC name = parsePtr.NameAndExt();
sl@0
   334
				
sl@0
   335
		outputFile.Append(parsePtr.NameAndExt());
sl@0
   336
sl@0
   337
		if (iLargeFile)
sl@0
   338
			{
sl@0
   339
			iComposedFileHandle64.Close();
sl@0
   340
			err = iComposedFileHandle64.Create(iFs, outputFile, EFileShareAny|EFileStream|EFileWrite);
sl@0
   341
			if (err == KErrAlreadyExists)
sl@0
   342
				{
sl@0
   343
				err = iComposedFileHandle64.Replace(iFs, outputFile, EFileShareAny|EFileStream|EFileWrite);
sl@0
   344
				}
sl@0
   345
			
sl@0
   346
			if (err == KErrNone)
sl@0
   347
				{
sl@0
   348
				err = iComposer->Open((T3GPFileFormatType)iFileFormat, videoProperties, audioProperties, iComposedFileHandle64, iComposeFlag);
sl@0
   349
				}
sl@0
   350
			}
sl@0
   351
		else
sl@0
   352
			{			
sl@0
   353
			err = iComposer->Open((T3GPFileFormatType)iFileFormat, videoProperties, audioProperties, outputFile, iComposeFlag);
sl@0
   354
			}
sl@0
   355
				
sl@0
   356
		if (err != KErrNone)
sl@0
   357
			{
sl@0
   358
			ERR_PRINTF2(_L("C3GPCompose::Open failed: err = %d"), err);		
sl@0
   359
			User::Leave(err);			
sl@0
   360
			}
sl@0
   361
		
sl@0
   362
		CleanupStack::PopAndDestroy(&outputFile);
sl@0
   363
		}
sl@0
   364
	
sl@0
   365
	//
sl@0
   366
	// Parse and compose (if specified) video / audio frame data 
sl@0
   367
	//
sl@0
   368
	ReadWriteAudioVideoFramesL(videoProperties, audioProperties, videoLengthInMs, audioLengthInMs);
sl@0
   369
	
sl@0
   370
	//
sl@0
   371
	// Clean up
sl@0
   372
	//
sl@0
   373
	CleanupStack::PopAndDestroy(4);	 
sl@0
   374
									// audioDecoderSpecificInfo
sl@0
   375
									// audioProperties 
sl@0
   376
									// videoDecoderSpecificInfo 
sl@0
   377
									// videoProperties
sl@0
   378
	
sl@0
   379
	if (iComposer)
sl@0
   380
		{
sl@0
   381
		err = iComposer->Complete();
sl@0
   382
		if (err != KErrNone)
sl@0
   383
			{
sl@0
   384
			ERR_PRINTF1(_L("aComposer->Complete() failed"));
sl@0
   385
			User::Leave(err);
sl@0
   386
			}
sl@0
   387
			
sl@0
   388
		if (iLargeFile)
sl@0
   389
			{
sl@0
   390
			iComposedFileHandle64.Close();
sl@0
   391
			}
sl@0
   392
		}
sl@0
   393
	
sl@0
   394
	err = iParser->Complete();
sl@0
   395
	if (err != KErrNone)
sl@0
   396
		{
sl@0
   397
		ERR_PRINTF1(_L("aParser->Complete() failed"));
sl@0
   398
		User::Leave(err);
sl@0
   399
		}
sl@0
   400
sl@0
   401
	if (iLargeFile)
sl@0
   402
		{
sl@0
   403
		iParsedFileHandle64.Close();
sl@0
   404
		}
sl@0
   405
	
sl@0
   406
	INFO_PRINTF1(_L("C3GPLibParseComposeFile::ParseAndComposeL OUT"));		
sl@0
   407
	}
sl@0
   408
sl@0
   409
void C3GPLibParseComposeFile::ReadWriteAudioVideoFramesL(const T3GPVideoPropertiesBase* aVideoProperties, 
sl@0
   410
														 const T3GPAudioPropertiesBase* aAudioProperties,
sl@0
   411
														 TUint aVideoLengthInMs,
sl@0
   412
														 TUint aAudioLengthInMs)
sl@0
   413
	{
sl@0
   414
	ASSERT(iParser);
sl@0
   415
sl@0
   416
	TUint videoLengthInTS = 0;
sl@0
   417
	TUint audioLengthInTS = 0;
sl@0
   418
	if (aVideoProperties)
sl@0
   419
		{
sl@0
   420
        // The "+KOneHalf" in the following calculation has the effect of rounding
sl@0
   421
        // to the nearest integer instead of just flooring it when converting from
sl@0
   422
        // TReal to TUint.
sl@0
   423
        // This is to avoid videoLengthInTS being off by one and leading to false
sl@0
   424
        // positives when the video properties are compared later on.
sl@0
   425
		videoLengthInTS = (TUint) ((TReal)(aVideoLengthInMs * aVideoProperties->iTimescale) / KMillisecondsInSecond + KOneHalf );
sl@0
   426
		}
sl@0
   427
	if (aAudioProperties)
sl@0
   428
		{
sl@0
   429
		// The "+KOneHalf" in the following calculation has the effect of rounding
sl@0
   430
		// to the nearest integer instead of just flooring it when converting from
sl@0
   431
		// TReal to TUint.
sl@0
   432
		// This is to avoid audioLengthInTS being off by one and leading to false
sl@0
   433
		// positives when the audio properties are compared later on.
sl@0
   434
		audioLengthInTS = (TUint) ((TReal)(aAudioLengthInMs * aAudioProperties->iTimescale) / KMillisecondsInSecond + KOneHalf );
sl@0
   435
		}
sl@0
   436
	
sl@0
   437
	TInt framePerSample1 = 0;
sl@0
   438
	TInt framePerSample2 = 0;
sl@0
   439
	TUint audioTS1 = 0;
sl@0
   440
	TUint audioTS2 = 0;
sl@0
   441
	RBuf8 audioBuf1;	
sl@0
   442
	RBuf8 audioBuf2;
sl@0
   443
	CleanupClosePushL(audioBuf1);
sl@0
   444
	CleanupClosePushL(audioBuf2);
sl@0
   445
sl@0
   446
	TUint videoTS1;
sl@0
   447
	TUint videoTS2;
sl@0
   448
	TBool keyFrame1;
sl@0
   449
	TBool keyFrame2;
sl@0
   450
	T3GPFrameDependencies dep1;
sl@0
   451
	T3GPFrameDependencies dep2;
sl@0
   452
	RBuf8 videoBuf1;
sl@0
   453
	RBuf8 videoBuf2;
sl@0
   454
	CleanupClosePushL(videoBuf1);		
sl@0
   455
	CleanupClosePushL(videoBuf2);	
sl@0
   456
sl@0
   457
	TInt err = KErrNone;
sl@0
   458
	T3GPFrameType frameType;
sl@0
   459
	
sl@0
   460
	RArray<T3GPFrameType> frameTypeArray(10);
sl@0
   461
	CleanupClosePushL(frameTypeArray);
sl@0
   462
	
sl@0
   463
	TInt videoFrameCount = 0;
sl@0
   464
	TInt audioFrameCount = 0;
sl@0
   465
	
sl@0
   466
	while (err == KErrNone)
sl@0
   467
		{
sl@0
   468
		err = iParser->GetFrameType(frameType);
sl@0
   469
		if (err == KErrNone)
sl@0
   470
			{		
sl@0
   471
			switch(frameType)
sl@0
   472
				{
sl@0
   473
				case E3GPAudio:
sl@0
   474
					audioFrameCount++;
sl@0
   475
					frameTypeArray.AppendL(frameType);		
sl@0
   476
					err = ReadAudioFrames(*iParser, audioBuf1, framePerSample1, audioTS1);
sl@0
   477
					audioBuf1.Close();				
sl@0
   478
					break;
sl@0
   479
					
sl@0
   480
				case E3GPVideo:
sl@0
   481
					videoFrameCount++;
sl@0
   482
					frameTypeArray.AppendL(frameType);
sl@0
   483
					err = ReadVideoFrame(*iParser, videoBuf1, keyFrame1, videoTS1, dep1);
sl@0
   484
					videoBuf1.Close();				
sl@0
   485
					break;
sl@0
   486
					
sl@0
   487
				default:
sl@0
   488
					ERR_PRINTF1(_L("GetFrameType retrieves an unsupported frame type"));
sl@0
   489
					User::Leave(KErrUnknown);
sl@0
   490
					break;
sl@0
   491
				}
sl@0
   492
			
sl@0
   493
			// if there's anything wrong w/ retrieving the frame, exit the function now
sl@0
   494
			User::LeaveIfError(err);
sl@0
   495
			}
sl@0
   496
		}
sl@0
   497
	
sl@0
   498
	INFO_PRINTF2(_L("ReadWriteAudioVideoFramesL read %d video frames."), videoFrameCount);
sl@0
   499
	INFO_PRINTF2(_L("ReadWriteAudioVideoFramesL read %d audio frames."), audioFrameCount);
sl@0
   500
		
sl@0
   501
	// reset the video and audio cursor at the beginning of the clip 
sl@0
   502
	TUint videoPos = 0;
sl@0
   503
	TUint audioPos = 0;
sl@0
   504
	iParser->Seek(0, EFalse, videoPos, audioPos);
sl@0
   505
	
sl@0
   506
	videoFrameCount = 0;
sl@0
   507
	audioFrameCount = 0;
sl@0
   508
	
sl@0
   509
	if (iComposer)
sl@0
   510
		{	
sl@0
   511
		// if the data should be supplied into a composer to construct an output file
sl@0
   512
		TInt index = 0;	
sl@0
   513
		while (index < frameTypeArray.Count())
sl@0
   514
			{
sl@0
   515
			frameType = frameTypeArray[index++]; 
sl@0
   516
			switch (frameType)
sl@0
   517
				{
sl@0
   518
				case E3GPAudio:
sl@0
   519
					if (audioBuf1.Length() == 0)
sl@0
   520
						{					
sl@0
   521
						User::LeaveIfError(ReadAudioFrames(*iParser, audioBuf1, framePerSample1, audioTS1));
sl@0
   522
						}
sl@0
   523
					err = ReadAudioFrames(*iParser, audioBuf2, framePerSample2, audioTS2);
sl@0
   524
					
sl@0
   525
					if (audioBuf1.Length() > 0 && audioBuf2.Length() > 0 || 
sl@0
   526
						audioBuf1.Length() > 0 && err == KErrNotFound)
sl@0
   527
						{
sl@0
   528
						TUint duration = 0;
sl@0
   529
						if (audioBuf2.Length() == 0)
sl@0
   530
							{
sl@0
   531
							// duration for the last batch of audio frames = total audio length - the 2nd last audio frame
sl@0
   532
							duration = audioLengthInTS - audioTS1;
sl@0
   533
							}
sl@0
   534
						else
sl@0
   535
							{
sl@0
   536
							duration = audioTS2 - audioTS1;			
sl@0
   537
							}	
sl@0
   538
							
sl@0
   539
						User::LeaveIfError(iComposer->WriteAudioFrames(audioBuf1, duration));
sl@0
   540
						audioFrameCount++;
sl@0
   541
						
sl@0
   542
						audioBuf1.Close();
sl@0
   543
						audioBuf1.Swap(audioBuf2);
sl@0
   544
						framePerSample1 = framePerSample2;
sl@0
   545
						audioTS1 = audioTS2;
sl@0
   546
						}
sl@0
   547
					break;
sl@0
   548
					
sl@0
   549
				case E3GPVideo:
sl@0
   550
					if (videoBuf1.Length() == 0)
sl@0
   551
						{
sl@0
   552
						User::LeaveIfError(ReadVideoFrame(*iParser, videoBuf1, keyFrame1, videoTS1, dep1));
sl@0
   553
						}					
sl@0
   554
					err = ReadVideoFrame(*iParser, videoBuf2, keyFrame2, videoTS2, dep2);
sl@0
   555
					
sl@0
   556
					if (videoBuf1.Length() > 0 && videoBuf2.Length() > 0 || 
sl@0
   557
						videoBuf1.Length() > 0 && err == KErrNotFound)
sl@0
   558
						{
sl@0
   559
						TUint duration = 0;
sl@0
   560
						if (videoBuf2.Length() == 0)
sl@0
   561
							{
sl@0
   562
							// duration for the last batch of audio frames = total audio length - the 2nd last audio frame
sl@0
   563
							duration = videoLengthInTS - videoTS1;
sl@0
   564
							}
sl@0
   565
						else
sl@0
   566
							{
sl@0
   567
							duration = videoTS2 - videoTS1;			
sl@0
   568
							}	
sl@0
   569
							
sl@0
   570
						User::LeaveIfError(iComposer->WriteVideoFrame(videoBuf1, duration, keyFrame1, dep1));
sl@0
   571
						videoFrameCount++;
sl@0
   572
						
sl@0
   573
						videoBuf1.Close();
sl@0
   574
						videoBuf1.Swap(videoBuf2);
sl@0
   575
						keyFrame1 = keyFrame2;
sl@0
   576
						videoTS1 = videoTS2;
sl@0
   577
						dep1.iDependsOn = dep2.iDependsOn;
sl@0
   578
						dep1.iIsDependedOn = dep2.iIsDependedOn;
sl@0
   579
						dep1.iHasRedundancy = dep2.iHasRedundancy;		
sl@0
   580
						}
sl@0
   581
					break;
sl@0
   582
					
sl@0
   583
				default:
sl@0
   584
					ERR_PRINTF1(_L("Unknown frame type detected."));
sl@0
   585
					User::Leave(KErrUnknown);
sl@0
   586
					break;
sl@0
   587
				}
sl@0
   588
			}	// end of while loop
sl@0
   589
		}	// if (iComposer)
sl@0
   590
	
sl@0
   591
	CleanupStack::PopAndDestroy(5);
sl@0
   592
	
sl@0
   593
	INFO_PRINTF2(_L("ReadWriteAudioVideoFramesL wrote %d video frames."), videoFrameCount);
sl@0
   594
	INFO_PRINTF2(_L("ReadWriteAudioVideoFramesL wrote %d audio frames."), audioFrameCount);	
sl@0
   595
	}
sl@0
   596
sl@0
   597
TInt C3GPLibParseComposeFile::GetAudioDecoderSpecificInfo(RBuf8& aBuffer)
sl@0
   598
	{
sl@0
   599
	ASSERT(iParser);
sl@0
   600
	
sl@0
   601
	TInt size;
sl@0
   602
	TInt err = iParser->GetAudioDecoderSpecificInfoSize(size);
sl@0
   603
	if( err != KErrNone )
sl@0
   604
		{
sl@0
   605
		ERR_PRINTF2(_L("GetAudioDecoderSpecificInfoSize() failed: %d"), err);
sl@0
   606
		return err;
sl@0
   607
		}
sl@0
   608
sl@0
   609
	err = aBuffer.Create(size);
sl@0
   610
	if( err != KErrNone )
sl@0
   611
		{
sl@0
   612
		ERR_PRINTF1(_L("Create buffer failed"));
sl@0
   613
		return err;
sl@0
   614
		}
sl@0
   615
sl@0
   616
	err = iParser->GetAudioDecoderSpecificInfo(aBuffer);
sl@0
   617
	if( err != KErrNone )
sl@0
   618
		{
sl@0
   619
		ERR_PRINTF2(_L("GetAudioDecoderSpecificInfo() failed: %d"), err);
sl@0
   620
		}
sl@0
   621
	
sl@0
   622
	return err;
sl@0
   623
	}
sl@0
   624
sl@0
   625
TInt C3GPLibParseComposeFile::ParseVideoProperties(C3GPParse& aParser,
sl@0
   626
												   RBuf8& aDecoderSpecificInfo,
sl@0
   627
												   T3GPVideoPropertiesBase*& aProperties,
sl@0
   628
												   TUint& aLengthInMs) 
sl@0
   629
	{
sl@0
   630
	ASSERT(iParser);
sl@0
   631
	
sl@0
   632
	T3GPVideoType type; 
sl@0
   633
	TReal frameRate;
sl@0
   634
	TUint avgBitRate;
sl@0
   635
	TSize size;
sl@0
   636
	TUint timeScale;	
sl@0
   637
	
sl@0
   638
	TInt err = aParser.GetVideoProperties(type, aLengthInMs, frameRate, avgBitRate, size, timeScale);
sl@0
   639
	if ((err != KErrNone) && (err != KErrNotSupported))
sl@0
   640
		{
sl@0
   641
		ERR_PRINTF2(_L("aParser->GetVideoProperties failed: %d"), err);
sl@0
   642
		return err;
sl@0
   643
		}
sl@0
   644
sl@0
   645
	switch(type)
sl@0
   646
		{
sl@0
   647
		case E3GPMpeg4Video:
sl@0
   648
			{
sl@0
   649
			INFO_PRINTF1(_L("Video Type: Mpeg4"));			
sl@0
   650
			err = GetVideoDecoderSpecificInfo(aDecoderSpecificInfo);		
sl@0
   651
			if (err == KErrNone)
sl@0
   652
				{
sl@0
   653
				aProperties = new T3GPVideoPropertiesMpeg4Video(timeScale, size,
sl@0
   654
						64000, avgBitRate, aDecoderSpecificInfo);
sl@0
   655
				if (!aProperties)
sl@0
   656
					{
sl@0
   657
					ERR_PRINTF1(_L("T3GPVideoPropertiesMpeg4Video allocation failed"));
sl@0
   658
					err = KErrNoMemory;
sl@0
   659
					}
sl@0
   660
				}
sl@0
   661
			break;			
sl@0
   662
			}
sl@0
   663
		
sl@0
   664
		case E3GPAvcProfileBaseline:
sl@0
   665
		case E3GPAvcProfileMain:
sl@0
   666
		case E3GPAvcProfileExtended:
sl@0
   667
		case E3GPAvcProfileHigh:
sl@0
   668
			{
sl@0
   669
			err = GetVideoDecoderSpecificInfo(aDecoderSpecificInfo);
sl@0
   670
			if (err == KErrNone)
sl@0
   671
				{
sl@0
   672
				INFO_PRINTF2(_L("Video Type: Avc Profile %S"), KAvcProfileNames[type-E3GPAvcProfileBaseline] );
sl@0
   673
				aProperties = new T3GPVideoPropertiesAvc(timeScale, size, aDecoderSpecificInfo);
sl@0
   674
				if (!aProperties)
sl@0
   675
					{
sl@0
   676
					ERR_PRINTF1(_L("T3GPVideoPropertiesAvc allocation failed"));
sl@0
   677
					err = KErrNoMemory;
sl@0
   678
					}
sl@0
   679
                else
sl@0
   680
                    {
sl@0
   681
                    // T3GPVideoPropertiesAvc defaults the video type to AVC baseline profile.
sl@0
   682
                    // Need to override that here because we want to check for the specific
sl@0
   683
                    // profile in this test.
sl@0
   684
                    aProperties->iType = type;
sl@0
   685
                    }
sl@0
   686
				}
sl@0
   687
			break;
sl@0
   688
			}
sl@0
   689
			
sl@0
   690
		case E3GPH263Profile0:
sl@0
   691
		case E3GPH263Profile3:
sl@0
   692
			{
sl@0
   693
			INFO_PRINTF1(_L("Video Type: H263"));			
sl@0
   694
			T3GPVideoPropertiesH263::TProfile profile = T3GPVideoPropertiesH263::EProfile0;
sl@0
   695
			if (type == E3GPH263Profile3)
sl@0
   696
				{
sl@0
   697
				profile = T3GPVideoPropertiesH263::EProfile3;
sl@0
   698
				}
sl@0
   699
			
sl@0
   700
			TInt videoLevel;
sl@0
   701
			err = iParser->GetH263VideoLevel(videoLevel);
sl@0
   702
			if( err != KErrNone )
sl@0
   703
				{
sl@0
   704
				ERR_PRINTF1(_L("aParser->GetH263VideoLevel() failed"));
sl@0
   705
				}
sl@0
   706
			else
sl@0
   707
				{			
sl@0
   708
				aProperties = new T3GPVideoPropertiesH263(timeScale, size, videoLevel, profile);
sl@0
   709
				if( !aProperties )
sl@0
   710
					{
sl@0
   711
					ERR_PRINTF1(_L("T3GPVideoPropertiesH263 allocation failed"));
sl@0
   712
					err = KErrNoMemory;
sl@0
   713
					}
sl@0
   714
				}
sl@0
   715
			break;			
sl@0
   716
			}
sl@0
   717
		
sl@0
   718
		case E3GPNoVideo:
sl@0
   719
			INFO_PRINTF1(_L("Video Type: None"));
sl@0
   720
			break;
sl@0
   721
			
sl@0
   722
		default:
sl@0
   723
			err = KErrNotSupported;
sl@0
   724
			break;
sl@0
   725
		}
sl@0
   726
	
sl@0
   727
	return err;
sl@0
   728
	}
sl@0
   729
sl@0
   730
TInt C3GPLibParseComposeFile::GetVideoDecoderSpecificInfo(RBuf8& aBuffer)
sl@0
   731
	{	
sl@0
   732
	TInt size;
sl@0
   733
	TInt err = iParser->GetVideoDecoderSpecificInfoSize(size);
sl@0
   734
	if (err != KErrNone)
sl@0
   735
		{
sl@0
   736
		ERR_PRINTF1(_L("GetVideoDecoderSpecificInfoSize() failed"));
sl@0
   737
		return err;
sl@0
   738
		}
sl@0
   739
	
sl@0
   740
	err = aBuffer.Create(size);
sl@0
   741
	if (err != KErrNone)
sl@0
   742
		{
sl@0
   743
		ERR_PRINTF1(_L("Create buffer failed"));
sl@0
   744
		return err;
sl@0
   745
		}
sl@0
   746
sl@0
   747
	err = iParser->GetVideoDecoderSpecificInfo(aBuffer);
sl@0
   748
	if( err != KErrNone )
sl@0
   749
		{
sl@0
   750
		ERR_PRINTF1(_L("GetVideoDecoderSpecificInfo() failed"));
sl@0
   751
		}
sl@0
   752
	
sl@0
   753
	return err;
sl@0
   754
	}
sl@0
   755
sl@0
   756
TInt C3GPLibParseComposeFile::ParseAudioProperties(C3GPParse& aParser, 
sl@0
   757
												   RBuf8& aAudioDecoderSpecificInfo,
sl@0
   758
												   T3GPAudioPropertiesBase*& aAudioProperties,
sl@0
   759
												   TUint& aLength)
sl@0
   760
	{
sl@0
   761
	
sl@0
   762
	ASSERT(iParser);
sl@0
   763
	
sl@0
   764
	T3GPAudioType type; 
sl@0
   765
	TInt audioFPS; 
sl@0
   766
	TUint audioAvgBitRate; 
sl@0
   767
	TUint timeScale;	
sl@0
   768
	
sl@0
   769
	TInt err = aParser.GetAudioProperties(type, aLength, audioFPS, audioAvgBitRate, timeScale);
sl@0
   770
	if(( err != KErrNone ) && ( err != KErrNotSupported ))
sl@0
   771
		{
sl@0
   772
		ERR_PRINTF2(_L("GetAudioProperties() failed: %d"), err);
sl@0
   773
		return err;
sl@0
   774
		}
sl@0
   775
sl@0
   776
	switch(type)
sl@0
   777
		{
sl@0
   778
		case E3GPMpeg4Audio:
sl@0
   779
			{
sl@0
   780
			INFO_PRINTF1(_L("Audio Type: Mpeg4"));
sl@0
   781
			err = GetAudioDecoderSpecificInfo(aAudioDecoderSpecificInfo);
sl@0
   782
			if (err == KErrNone)
sl@0
   783
				{
sl@0
   784
				aAudioProperties = new T3GPAudioPropertiesMpeg4Audio(timeScale, aAudioDecoderSpecificInfo);
sl@0
   785
				if( !aAudioProperties )
sl@0
   786
					{
sl@0
   787
					ERR_PRINTF1(_L("T3GPAudioPropertiesMpeg4Audio allocation failed"));
sl@0
   788
					err = KErrNoMemory;
sl@0
   789
					}
sl@0
   790
				}
sl@0
   791
			break;
sl@0
   792
			}
sl@0
   793
			
sl@0
   794
		case E3GPQcelp13K:
sl@0
   795
			{
sl@0
   796
			INFO_PRINTF1(_L("Audio Type: Qcelp13K"));
sl@0
   797
			T3GPQcelpStorageMode mode;
sl@0
   798
			err = iParser->GetQcelpStorageMode(mode);
sl@0
   799
			if (err != KErrNone)
sl@0
   800
				{
sl@0
   801
				ERR_PRINTF1(_L("GetQcelpStorageMode failed"));
sl@0
   802
				}
sl@0
   803
			else 
sl@0
   804
				{
sl@0
   805
				if( mode == E3GPMP4AudioDescriptionBox)
sl@0
   806
					{
sl@0
   807
					err = GetAudioDecoderSpecificInfo(aAudioDecoderSpecificInfo);
sl@0
   808
					aAudioProperties = new T3GPAudioPropertiesQcelp(timeScale, audioFPS, aAudioDecoderSpecificInfo);
sl@0
   809
					}
sl@0
   810
				else
sl@0
   811
					{
sl@0
   812
					aAudioProperties = new T3GPAudioPropertiesQcelp(timeScale, audioFPS);
sl@0
   813
					}
sl@0
   814
				
sl@0
   815
				if( !aAudioProperties )
sl@0
   816
					{
sl@0
   817
					ERR_PRINTF1(_L("T3GPAudioPropertiesQcelp allocation failed"));
sl@0
   818
					err = KErrNoMemory;
sl@0
   819
					}
sl@0
   820
				}
sl@0
   821
			break;
sl@0
   822
			}
sl@0
   823
			
sl@0
   824
		case E3GPAmrNB:
sl@0
   825
			{
sl@0
   826
			INFO_PRINTF1(_L("Audio Type: AMR NB"));
sl@0
   827
			aAudioProperties = new T3GPAudioPropertiesAmr(timeScale, audioFPS, KAudioModeSet, T3GPAudioPropertiesAmr::EAmrNB);
sl@0
   828
			if( !aAudioProperties )
sl@0
   829
				{
sl@0
   830
				ERR_PRINTF1(_L("T3GPAudioPropertiesAmr allocation failed"));
sl@0
   831
				err = KErrNoMemory;
sl@0
   832
				}
sl@0
   833
			break;
sl@0
   834
			}
sl@0
   835
			
sl@0
   836
		case E3GPAmrWB:
sl@0
   837
			{
sl@0
   838
			INFO_PRINTF1(_L("Audio Type: AMR WB"));
sl@0
   839
			aAudioProperties = new T3GPAudioPropertiesAmr(timeScale, audioFPS, KAudioModeSet, T3GPAudioPropertiesAmr::EAmrWB);
sl@0
   840
			if( !aAudioProperties )
sl@0
   841
				{
sl@0
   842
				ERR_PRINTF1(_L("T3GPAudioPropertiesAmr allocation failed"));
sl@0
   843
				err = KErrNoMemory;
sl@0
   844
				}
sl@0
   845
			break;
sl@0
   846
			}
sl@0
   847
			
sl@0
   848
		case E3GPNoAudio:
sl@0
   849
			INFO_PRINTF1(_L("Audio Type: None"));			
sl@0
   850
			break;
sl@0
   851
			
sl@0
   852
		default:
sl@0
   853
			INFO_PRINTF1(_L("Audio Type: Unrecognized!"));
sl@0
   854
			err = KErrNotSupported;
sl@0
   855
			break;
sl@0
   856
		}
sl@0
   857
	
sl@0
   858
	return err;
sl@0
   859
	}
sl@0
   860
sl@0
   861
TInt C3GPLibParseComposeFile::ReadVideoFrame(C3GPParse& aParser,
sl@0
   862
											 RBuf8& aVideoBuffer, 
sl@0
   863
											 TBool& aVideoKeyFrame, 
sl@0
   864
											 TUint& aVideoTimestampInTS, 
sl@0
   865
											 T3GPFrameDependencies& aDependencies)
sl@0
   866
	{
sl@0
   867
	ASSERT(iParser);
sl@0
   868
	
sl@0
   869
	// flush all data in the buffer
sl@0
   870
	aVideoBuffer.Close();
sl@0
   871
	
sl@0
   872
	TInt err = aParser.GetVideoFrameDependencies(aDependencies);
sl@0
   873
	if (err != KErrNone)
sl@0
   874
		{
sl@0
   875
		aDependencies.iDependsOn = E3GPDependencyUnknown;
sl@0
   876
		aDependencies.iIsDependedOn = E3GPDependencyUnknown;
sl@0
   877
		aDependencies.iHasRedundancy = E3GPRedundancyUnknown;
sl@0
   878
		}
sl@0
   879
	
sl@0
   880
	TUint frameSize = 0;
sl@0
   881
	err = aParser.GetVideoFrameSize(frameSize);
sl@0
   882
	if (err == KErrNone)
sl@0
   883
		{
sl@0
   884
		if (frameSize > KMaxTInt / 2)
sl@0
   885
			{
sl@0
   886
			ERR_PRINTF1(_L("Video Frame too large!"));
sl@0
   887
			err = KErrOverflow;
sl@0
   888
			}
sl@0
   889
		else
sl@0
   890
			{
sl@0
   891
			err = aVideoBuffer.Create((TInt)frameSize);
sl@0
   892
			if (err == KErrNone)
sl@0
   893
				{
sl@0
   894
				TUint videoTimestampMS = 0;
sl@0
   895
				err = aParser.ReadVideoFrame(aVideoBuffer, aVideoKeyFrame, videoTimestampMS, aVideoTimestampInTS);				
sl@0
   896
				if (err == KErrNone)
sl@0
   897
					{
sl@0
   898
					if (err == KErrNotSupported)
sl@0
   899
						{
sl@0
   900
						// Not supported error is OK
sl@0
   901
						err = KErrNone;
sl@0
   902
						}
sl@0
   903
					else if (err != KErrNone)
sl@0
   904
						{
sl@0
   905
						ERR_PRINTF2(_L("GetVideoFrameDependencies failed with err = %d"), err);					
sl@0
   906
						}
sl@0
   907
					}
sl@0
   908
				else
sl@0
   909
					{
sl@0
   910
					ERR_PRINTF2(_L("ReadVideoFrame failed with err = %d"), err);					
sl@0
   911
					}
sl@0
   912
				}
sl@0
   913
			}
sl@0
   914
		}
sl@0
   915
	else
sl@0
   916
		{
sl@0
   917
		ERR_PRINTF2(_L("GetVideoFrameSize fails with %d"), err);		
sl@0
   918
		}
sl@0
   919
	
sl@0
   920
	return err;	
sl@0
   921
	}
sl@0
   922
sl@0
   923
TInt C3GPLibParseComposeFile::ReadAudioFrames(C3GPParse& aParser, 
sl@0
   924
											  RBuf8& aBuffer, 
sl@0
   925
											  TInt& aFramesInSample, 
sl@0
   926
											  TUint& aTimestampInTS)
sl@0
   927
	{
sl@0
   928
	// flush all existing data
sl@0
   929
	aBuffer.Close();
sl@0
   930
	
sl@0
   931
	TUint size = 0;
sl@0
   932
	TInt err = aParser.GetAudioFramesSize(size);
sl@0
   933
	if (err == KErrNone)
sl@0
   934
		{
sl@0
   935
		if (size > KMaxTInt / 2)	
sl@0
   936
			{
sl@0
   937
			// cannot create RBuf of size > KMaxTInt / 2 
sl@0
   938
			ERR_PRINTF1(_L("Audio Frames too large!"));
sl@0
   939
			err = KErrOverflow;
sl@0
   940
			}
sl@0
   941
		else
sl@0
   942
			{
sl@0
   943
			err = aBuffer.Create((TInt)size);
sl@0
   944
			if (err == KErrNone)
sl@0
   945
				{
sl@0
   946
				TUint audioTimestampMS = 0;
sl@0
   947
				err = aParser.ReadAudioFrames(aBuffer, aFramesInSample, audioTimestampMS, aTimestampInTS);
sl@0
   948
				if (err != KErrNone)
sl@0
   949
					{
sl@0
   950
					ERR_PRINTF2(_L("ReadAudioFrames failed with err = %d"), err);							
sl@0
   951
					}
sl@0
   952
				}
sl@0
   953
			}
sl@0
   954
		}
sl@0
   955
	else
sl@0
   956
		{
sl@0
   957
		ERR_PRINTF2(_L("GetAudioFramesSize failed with err = %d"), err);		
sl@0
   958
		}
sl@0
   959
	
sl@0
   960
	return err;
sl@0
   961
	}
sl@0
   962
sl@0
   963
TBool C3GPLibParseComposeFile::CompareInputOuputFileL(const TDesC& aInputFile)
sl@0
   964
	{
sl@0
   965
	ASSERT(iParser);
sl@0
   966
	TInt err = 0;
sl@0
   967
sl@0
   968
	if (iLargeFile)
sl@0
   969
		{
sl@0
   970
		iParsedFileHandle64.Close();
sl@0
   971
		err = iParsedFileHandle64.Open(iFs, aInputFile, EFileShareReadersOrWriters);
sl@0
   972
		if (err == KErrNone)
sl@0
   973
			{
sl@0
   974
			err = iParser->Open(iParsedFileHandle64);		
sl@0
   975
			}
sl@0
   976
		}
sl@0
   977
	else
sl@0
   978
		{
sl@0
   979
		err = iParser->Open(aInputFile);		
sl@0
   980
		}
sl@0
   981
sl@0
   982
	if (err != KErrNone)
sl@0
   983
		{
sl@0
   984
		ERR_PRINTF2(_L("C3GPParse 1 Open() returns %d"), err);
sl@0
   985
		User::Leave(err);
sl@0
   986
		}
sl@0
   987
	
sl@0
   988
	RBuf outputFile;
sl@0
   989
	CleanupClosePushL(outputFile);
sl@0
   990
	
sl@0
   991
	outputFile.CreateL(KMaxFileName);
sl@0
   992
	outputFile.Copy(iOutputDir);
sl@0
   993
	
sl@0
   994
	TParsePtrC parsePtr(aInputFile);
sl@0
   995
	TPtrC name = parsePtr.NameAndExt();	
sl@0
   996
	outputFile.Append(parsePtr.NameAndExt());
sl@0
   997
sl@0
   998
	C3GPParse* parser2 = C3GPParse::NewL();
sl@0
   999
	CleanupStack::PushL(parser2);
sl@0
  1000
sl@0
  1001
	RFile64 file2;
sl@0
  1002
	if (iLargeFile)
sl@0
  1003
		{
sl@0
  1004
		err = file2.Open(iFs, outputFile, EFileShareReadersOrWriters);
sl@0
  1005
		if (err == KErrNone)
sl@0
  1006
			{
sl@0
  1007
			err = parser2->Open(file2);		
sl@0
  1008
			}
sl@0
  1009
		}
sl@0
  1010
	else
sl@0
  1011
		{
sl@0
  1012
		err = parser2->Open(outputFile);		
sl@0
  1013
		}
sl@0
  1014
		
sl@0
  1015
	if (err != KErrNone)
sl@0
  1016
		{
sl@0
  1017
		ERR_PRINTF2(_L("C3GPParse 2 Open() returns %d"), err);
sl@0
  1018
		User::Leave(err);
sl@0
  1019
		}
sl@0
  1020
	
sl@0
  1021
	TBool result = EFalse;	
sl@0
  1022
	if (CompareVideoPropertiesL(*iParser, *parser2))
sl@0
  1023
		{
sl@0
  1024
		if (CompareAudioPropertiesL(*iParser, *parser2))
sl@0
  1025
			{
sl@0
  1026
			if (CompareAudioVideoData(*iParser, *parser2))
sl@0
  1027
				{
sl@0
  1028
				result = ETrue;
sl@0
  1029
				}			
sl@0
  1030
			else
sl@0
  1031
				{
sl@0
  1032
				ERR_PRINTF1(_L("Audio/Video Data not matching"));
sl@0
  1033
				}					
sl@0
  1034
			}
sl@0
  1035
		else
sl@0
  1036
			{
sl@0
  1037
			ERR_PRINTF1(_L("Audio Properites not matching"));
sl@0
  1038
			}		
sl@0
  1039
		}
sl@0
  1040
	else
sl@0
  1041
		{
sl@0
  1042
		ERR_PRINTF1(_L("Video Properites not matching"));
sl@0
  1043
		}
sl@0
  1044
	
sl@0
  1045
	parser2->Complete();
sl@0
  1046
	iParser->Complete();
sl@0
  1047
	
sl@0
  1048
	if (iLargeFile)
sl@0
  1049
		{
sl@0
  1050
		file2.Close();
sl@0
  1051
		iParsedFileHandle64.Close();
sl@0
  1052
		}
sl@0
  1053
	
sl@0
  1054
	CleanupStack::PopAndDestroy(2);		// outputFile, parser2
sl@0
  1055
	
sl@0
  1056
	return result;
sl@0
  1057
	}
sl@0
  1058
sl@0
  1059
TBool C3GPLibParseComposeFile::CompareVideoPropertiesL(C3GPParse& aParser1, 
sl@0
  1060
													   C3GPParse& aParser2)
sl@0
  1061
	{
sl@0
  1062
	//
sl@0
  1063
	// Retrieve Video Properties from Parser 1
sl@0
  1064
	//	
sl@0
  1065
	T3GPVideoPropertiesBase* videoProperties1 = NULL;
sl@0
  1066
	CleanupStack::PushL(videoProperties1);
sl@0
  1067
	
sl@0
  1068
	RBuf8 videoDecoderSpecificInfo1;
sl@0
  1069
	CleanupClosePushL(videoDecoderSpecificInfo1);
sl@0
  1070
	
sl@0
  1071
	TUint videoLengthInMs1 = 0;
sl@0
  1072
		
sl@0
  1073
	TInt err1 = ParseVideoProperties(aParser1, videoDecoderSpecificInfo1, videoProperties1, videoLengthInMs1);
sl@0
  1074
	if (err1 != KErrNone && err1 != KErrNotSupported)
sl@0
  1075
		{
sl@0
  1076
		ERR_PRINTF2(_L("ParseVideoProperties 1 failed: err = %d"), err1);
sl@0
  1077
		User::Leave(err1);
sl@0
  1078
		}
sl@0
  1079
	
sl@0
  1080
	//
sl@0
  1081
	// Retrieve Video Properties from Parser 2
sl@0
  1082
	//	
sl@0
  1083
	T3GPVideoPropertiesBase* videoProperties2 = NULL;
sl@0
  1084
	CleanupStack::PushL(videoProperties2);
sl@0
  1085
	
sl@0
  1086
	RBuf8 videoDecoderSpecificInfo2;
sl@0
  1087
	CleanupClosePushL(videoDecoderSpecificInfo2);
sl@0
  1088
	
sl@0
  1089
	TUint videoLengthInMs2 = 0;
sl@0
  1090
		
sl@0
  1091
	TInt err2 = ParseVideoProperties(aParser2, videoDecoderSpecificInfo2, videoProperties2, videoLengthInMs2);
sl@0
  1092
	if (err2 != KErrNone && err2 != KErrNotSupported)
sl@0
  1093
		{
sl@0
  1094
		ERR_PRINTF2(_L("ParseVideoProperties 2 failed: err = %d"), err2);
sl@0
  1095
		User::Leave(err2);
sl@0
  1096
		}
sl@0
  1097
sl@0
  1098
	TBool result = EFalse;
sl@0
  1099
	if (err1 == err2 && err1 != KErrNotSupported)
sl@0
  1100
		{
sl@0
  1101
		if (videoLengthInMs1 == videoLengthInMs2)
sl@0
  1102
			{
sl@0
  1103
			if (videoProperties1 && videoProperties2)
sl@0
  1104
				{
sl@0
  1105
				result = (videoProperties1->iType == videoProperties2->iType) &&
sl@0
  1106
						 (videoProperties1->iSize == videoProperties2->iSize) &&
sl@0
  1107
						 (videoProperties1->iTimescale == videoProperties2->iTimescale);
sl@0
  1108
					
sl@0
  1109
				if (result)
sl@0
  1110
					{
sl@0
  1111
					switch(videoProperties1->iType)
sl@0
  1112
						{
sl@0
  1113
						case E3GPMpeg4Video:
sl@0
  1114
							{
sl@0
  1115
							T3GPVideoPropertiesMpeg4Video* video1 = (T3GPVideoPropertiesMpeg4Video*)videoProperties1;
sl@0
  1116
							T3GPVideoPropertiesMpeg4Video* video2 = (T3GPVideoPropertiesMpeg4Video*)videoProperties2;
sl@0
  1117
							
sl@0
  1118
							// NOTE: Comparison of the avg bit rate is omitted.  The reason is that the avg. bit 
sl@0
  1119
							//       rate is calculated by: 
sl@0
  1120
							//       video avg bit rate = stream avg bit rate - audio avg bit rate
sl@0
  1121
							//       However, stream avg. bit rate is not be properly set by the 3GP composer
sl@0
  1122
							//       as it is not very important.  Thus leading to the video avg. bit rate  
sl@0
  1123
							//       retrieved from the output file to NOT match the original.
sl@0
  1124
							result = ((video1->iMaxBitRate == video2->iMaxBitRate) && 
sl@0
  1125
									 //(video1->iAvgBitRate == video2->iAvgBitRate) &&
sl@0
  1126
									 (video1->iDecoderSpecificInfo == video2->iDecoderSpecificInfo)); 
sl@0
  1127
							break;			
sl@0
  1128
							}
sl@0
  1129
								
sl@0
  1130
						case E3GPAvcProfileBaseline:
sl@0
  1131
						case E3GPAvcProfileMain:
sl@0
  1132
						case E3GPAvcProfileExtended:
sl@0
  1133
						case E3GPAvcProfileHigh:
sl@0
  1134
							{
sl@0
  1135
							T3GPVideoPropertiesAvc* video1 = (T3GPVideoPropertiesAvc*)videoProperties1;
sl@0
  1136
							T3GPVideoPropertiesAvc* video2 = (T3GPVideoPropertiesAvc*)videoProperties2;
sl@0
  1137
							
sl@0
  1138
							result = (video1->iDecoderSpecificInfo == video2->iDecoderSpecificInfo); 
sl@0
  1139
							break;
sl@0
  1140
							}
sl@0
  1141
									
sl@0
  1142
						case E3GPH263Profile0:
sl@0
  1143
						case E3GPH263Profile3:
sl@0
  1144
							{
sl@0
  1145
							T3GPVideoPropertiesH263* video1 = (T3GPVideoPropertiesH263*)videoProperties1;
sl@0
  1146
							T3GPVideoPropertiesH263* video2 = (T3GPVideoPropertiesH263*)videoProperties2;
sl@0
  1147
sl@0
  1148
							result = (video1->iVideoLevel == video2->iVideoLevel);
sl@0
  1149
							break;			
sl@0
  1150
							}
sl@0
  1151
						}
sl@0
  1152
					}
sl@0
  1153
				}			
sl@0
  1154
			}		
sl@0
  1155
		}	
sl@0
  1156
	else if (err1 == KErrNotSupported && err2 == err1)
sl@0
  1157
		{
sl@0
  1158
		result = ETrue;
sl@0
  1159
		}
sl@0
  1160
sl@0
  1161
	CleanupStack::PopAndDestroy(4);		// videoProperties1, 
sl@0
  1162
										// videoProperties2, 
sl@0
  1163
										// videoDecoderSpecificInfo1, 
sl@0
  1164
										// videoDecoderSpecificInfo2
sl@0
  1165
	
sl@0
  1166
	return result;
sl@0
  1167
	}
sl@0
  1168
sl@0
  1169
TBool C3GPLibParseComposeFile::CompareAudioPropertiesL(C3GPParse& aParser1, 
sl@0
  1170
													   C3GPParse& aParser2)
sl@0
  1171
	{
sl@0
  1172
	//
sl@0
  1173
	// Retrieve Audio Properties 1
sl@0
  1174
	//
sl@0
  1175
	T3GPAudioPropertiesBase* audioProperties1 = NULL;
sl@0
  1176
	CleanupStack::PushL(audioProperties1);	
sl@0
  1177
sl@0
  1178
	RBuf8 audioDecoderSpecificInfo1;
sl@0
  1179
	CleanupClosePushL(audioDecoderSpecificInfo1);
sl@0
  1180
	
sl@0
  1181
	TUint audioLengthInMs1 = 0;
sl@0
  1182
	TInt err1 = ParseAudioProperties(aParser1, audioDecoderSpecificInfo1, audioProperties1, audioLengthInMs1);
sl@0
  1183
	if( err1 != KErrNone && err1 != KErrNotSupported)
sl@0
  1184
		{
sl@0
  1185
		ERR_PRINTF2(_L("ParseAudioProperties failed: err = %d"), err1);		
sl@0
  1186
		User::Leave(err1);
sl@0
  1187
		}
sl@0
  1188
sl@0
  1189
	//
sl@0
  1190
	// Retrieve Audio Properties 2
sl@0
  1191
	//
sl@0
  1192
	T3GPAudioPropertiesBase* audioProperties2 = NULL;
sl@0
  1193
	CleanupStack::PushL(audioProperties2);	
sl@0
  1194
sl@0
  1195
	RBuf8 audioDecoderSpecificInfo2;
sl@0
  1196
	CleanupClosePushL(audioDecoderSpecificInfo2);
sl@0
  1197
	
sl@0
  1198
	TUint audioLengthInMs2 = 0;
sl@0
  1199
	TInt err2 = ParseAudioProperties(aParser2, audioDecoderSpecificInfo2, audioProperties2, audioLengthInMs2);
sl@0
  1200
	if( err2 != KErrNone && err2 != KErrNotSupported)
sl@0
  1201
		{
sl@0
  1202
		ERR_PRINTF2(_L("ParseAudioProperties failed: err = %d"), err2);		
sl@0
  1203
		User::Leave(err2);
sl@0
  1204
		}
sl@0
  1205
	
sl@0
  1206
	TBool result = EFalse;
sl@0
  1207
	if (err1 == err2 && err1 != KErrNotSupported)
sl@0
  1208
		{
sl@0
  1209
		if (audioLengthInMs2 == audioLengthInMs1)
sl@0
  1210
			{
sl@0
  1211
			if (audioProperties1 && audioProperties2)
sl@0
  1212
				{
sl@0
  1213
				result = (audioProperties1->iType == audioProperties2->iType) &&
sl@0
  1214
						 (audioProperties1->iFramesPerSample == audioProperties2->iFramesPerSample) &&
sl@0
  1215
						 (audioProperties1->iTimescale == audioProperties2->iTimescale);
sl@0
  1216
				
sl@0
  1217
				if (result)
sl@0
  1218
					{
sl@0
  1219
					switch(audioProperties1->iType)
sl@0
  1220
						{
sl@0
  1221
						case E3GPMpeg4Audio:
sl@0
  1222
							{
sl@0
  1223
							T3GPAudioPropertiesMpeg4Audio* audio1 = (T3GPAudioPropertiesMpeg4Audio*) audioProperties1;
sl@0
  1224
							T3GPAudioPropertiesMpeg4Audio* audio2 = (T3GPAudioPropertiesMpeg4Audio*) audioProperties2;
sl@0
  1225
							result = (audio1->iDecoderSpecificInfo == audio2->iDecoderSpecificInfo);
sl@0
  1226
							}
sl@0
  1227
							break;							
sl@0
  1228
							
sl@0
  1229
						case E3GPAmrNB:
sl@0
  1230
						case E3GPAmrWB:
sl@0
  1231
							{
sl@0
  1232
							T3GPAudioPropertiesAmr* audio1 = (T3GPAudioPropertiesAmr*) audioProperties1;
sl@0
  1233
							T3GPAudioPropertiesAmr* audio2 = (T3GPAudioPropertiesAmr*) audioProperties2;
sl@0
  1234
							result = (audio1->iModeSet == audio2->iModeSet);
sl@0
  1235
							}
sl@0
  1236
							break;														
sl@0
  1237
							
sl@0
  1238
						case E3GPQcelp13K:
sl@0
  1239
							{
sl@0
  1240
							T3GPAudioPropertiesQcelp* audio1 = (T3GPAudioPropertiesQcelp*) audioProperties1;
sl@0
  1241
							T3GPAudioPropertiesQcelp* audio2 = (T3GPAudioPropertiesQcelp*) audioProperties2;
sl@0
  1242
							result = ((audio1->iDecoderSpecificInfo == audio2->iDecoderSpecificInfo) &&
sl@0
  1243
									 (audio1->iMode == audio2->iMode));
sl@0
  1244
							}
sl@0
  1245
							break;														
sl@0
  1246
						}
sl@0
  1247
					}
sl@0
  1248
				}
sl@0
  1249
			}
sl@0
  1250
		}	
sl@0
  1251
	else if (err1 == KErrNotSupported && err2 == err1)
sl@0
  1252
		{
sl@0
  1253
		result = ETrue;
sl@0
  1254
		}
sl@0
  1255
sl@0
  1256
	CleanupStack::PopAndDestroy(4);		// audioProperties1, audioProperties2, audioDecoderSpecificInfo1, audioDecoderSpecificInfo2
sl@0
  1257
	
sl@0
  1258
	return result;
sl@0
  1259
	}
sl@0
  1260
sl@0
  1261
TBool C3GPLibParseComposeFile::CompareAudioVideoData(C3GPParse& aParser1, C3GPParse& aParser2)
sl@0
  1262
	{
sl@0
  1263
	T3GPFrameType frameType1;
sl@0
  1264
	T3GPFrameType frameType2;
sl@0
  1265
	TInt err1 = KErrNone;
sl@0
  1266
	TInt err2 = KErrNone;
sl@0
  1267
	TBool keepLooping = ETrue;
sl@0
  1268
	TBool result = EFalse;
sl@0
  1269
	
sl@0
  1270
	while (keepLooping)
sl@0
  1271
		{
sl@0
  1272
		err1 = aParser1.GetFrameType(frameType1);
sl@0
  1273
		err2 = aParser2.GetFrameType(frameType2);
sl@0
  1274
		
sl@0
  1275
		if (err1 != err2)
sl@0
  1276
			{
sl@0
  1277
			break;
sl@0
  1278
			}		
sl@0
  1279
		else
sl@0
  1280
			{
sl@0
  1281
			if (err1 == KErrNotFound)
sl@0
  1282
				{
sl@0
  1283
				// completed looping thru all the frames
sl@0
  1284
				break;
sl@0
  1285
				}
sl@0
  1286
			
sl@0
  1287
			if (err1 != KErrNone)
sl@0
  1288
				{
sl@0
  1289
				// if the error is not KErrNotFound, something's wrong!
sl@0
  1290
				result = EFalse;
sl@0
  1291
				}			
sl@0
  1292
			else if (frameType1 != frameType2)
sl@0
  1293
				{			
sl@0
  1294
				result = EFalse;
sl@0
  1295
				}		
sl@0
  1296
			else if (frameType1 == E3GPVideo)
sl@0
  1297
				{
sl@0
  1298
				result = CompareVideoFrame(aParser1, aParser2);
sl@0
  1299
				}				
sl@0
  1300
			else if (frameType1 == E3GPAudio)			
sl@0
  1301
				{
sl@0
  1302
				result = CompareAudioFrames(aParser1, aParser2);
sl@0
  1303
				}
sl@0
  1304
			
sl@0
  1305
			if (!result)
sl@0
  1306
				{
sl@0
  1307
				break;
sl@0
  1308
				}
sl@0
  1309
			}
sl@0
  1310
		} 
sl@0
  1311
	
sl@0
  1312
	return result;
sl@0
  1313
	}
sl@0
  1314
sl@0
  1315
TBool C3GPLibParseComposeFile::CompareVideoFrame(C3GPParse& aParser1, C3GPParse& aParser2)
sl@0
  1316
	{
sl@0
  1317
	TUint timestamp1 = 0;
sl@0
  1318
	TUint timestamp2 = 0;
sl@0
  1319
	RBuf8 buf1;
sl@0
  1320
	RBuf8 buf2;
sl@0
  1321
	TBool keyFrame1 = EFalse;
sl@0
  1322
	TBool keyFrame2 = EFalse;
sl@0
  1323
	T3GPFrameDependencies dep1;
sl@0
  1324
	T3GPFrameDependencies dep2;
sl@0
  1325
	
sl@0
  1326
	TInt err1 = ReadVideoFrame(aParser1, buf1, keyFrame1, timestamp1, dep1);
sl@0
  1327
	TInt err2 = ReadVideoFrame(aParser2, buf2, keyFrame2, timestamp2, dep2);
sl@0
  1328
sl@0
  1329
	TBool result = EFalse;
sl@0
  1330
	if (err1 == err2)
sl@0
  1331
		{
sl@0
  1332
		if (keyFrame1 == keyFrame2 && timestamp1 == timestamp2)
sl@0
  1333
			{
sl@0
  1334
			if (dep1.iDependsOn == dep2.iDependsOn && 
sl@0
  1335
				dep1.iHasRedundancy == dep2.iHasRedundancy && 
sl@0
  1336
				dep1.iIsDependedOn == dep2.iIsDependedOn)
sl@0
  1337
				{
sl@0
  1338
				if (buf1 == buf2)
sl@0
  1339
					{
sl@0
  1340
					result = ETrue;
sl@0
  1341
					}
sl@0
  1342
				else 
sl@0
  1343
					{
sl@0
  1344
					result = EFalse;
sl@0
  1345
					}
sl@0
  1346
				}
sl@0
  1347
			else 
sl@0
  1348
				{
sl@0
  1349
				result = EFalse;
sl@0
  1350
				}			
sl@0
  1351
			}
sl@0
  1352
		else 
sl@0
  1353
			{
sl@0
  1354
			result = EFalse;
sl@0
  1355
			}		
sl@0
  1356
		}
sl@0
  1357
	else 
sl@0
  1358
		{
sl@0
  1359
		result = EFalse;
sl@0
  1360
		}	
sl@0
  1361
sl@0
  1362
	// cleanup
sl@0
  1363
	buf1.Close();
sl@0
  1364
	buf2.Close();
sl@0
  1365
	
sl@0
  1366
	return result;
sl@0
  1367
	}
sl@0
  1368
sl@0
  1369
TBool C3GPLibParseComposeFile::CompareAudioFrames(C3GPParse& aParser1, C3GPParse& aParser2)
sl@0
  1370
	{
sl@0
  1371
	TInt fps1 = 0;
sl@0
  1372
	TInt fps2 = 0;
sl@0
  1373
	TUint timestamp1 = 0;
sl@0
  1374
	TUint timestamp2 = 0;
sl@0
  1375
	RBuf8 buf1;
sl@0
  1376
	RBuf8 buf2;
sl@0
  1377
	
sl@0
  1378
	TInt err1 = ReadAudioFrames(aParser1, buf1, fps1, timestamp1);
sl@0
  1379
	TInt err2 = ReadAudioFrames(aParser2, buf2, fps2, timestamp2);
sl@0
  1380
sl@0
  1381
	TBool result = EFalse;
sl@0
  1382
	if (err1 == err2)
sl@0
  1383
		{
sl@0
  1384
		if (fps1 == fps2 && timestamp1 == timestamp2)
sl@0
  1385
			{
sl@0
  1386
			if (buf1 == buf2)
sl@0
  1387
				{
sl@0
  1388
				result = ETrue;
sl@0
  1389
				}
sl@0
  1390
			else 
sl@0
  1391
				{
sl@0
  1392
				result = EFalse;
sl@0
  1393
				}			
sl@0
  1394
			}
sl@0
  1395
		else 
sl@0
  1396
			{
sl@0
  1397
			result = EFalse;
sl@0
  1398
			}		
sl@0
  1399
		}
sl@0
  1400
	else 
sl@0
  1401
		{
sl@0
  1402
		result = EFalse;
sl@0
  1403
		}
sl@0
  1404
	
sl@0
  1405
	// cleanup	
sl@0
  1406
	buf1.Close();
sl@0
  1407
	buf2.Close();
sl@0
  1408
	
sl@0
  1409
	return result;
sl@0
  1410
	}