diff -r 000000000000 -r 40261b775718 mmplugins/lib3gpunittest/src/tsu_3gplibrary_composer_api.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mmplugins/lib3gpunittest/src/tsu_3gplibrary_composer_api.cpp Tue Feb 02 01:56:55 2010 +0200 @@ -0,0 +1,2354 @@ +// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +#include +#include "tsu_3gplibrary_composer_api.h" + +_LIT8(KDummyData, "DummyData"); +_LIT8(KFtypAtom, "ftyp"); +_LIT8(K3g2Brand, "3g2a"); // 3g2a +_LIT8(K3gpBrand, "3gp"); // 3gp4, 3gp6 +_LIT8(KMp4Brand, "mp42"); // mp42 + +_LIT(KLargeVideoFile, "c:\\3gplibrary\\cube-xvid-640x480-10fps-10s.3gp"); +const TInt KLargeFileWriteBufferSize = 16384; // 16K +const TInt KLargeFileWriteBufferMaxCount = 15; +const TInt64 K3GigaBytes = 0xC0000000; + +// ----------------------------------------------------------------------------- +// C3GPLibComposeBase - this should not be used directly +// ----------------------------------------------------------------------------- +// +C3GPLibComposeBase::C3GPLibComposeBase() + { + } + +TVerdict C3GPLibComposeBase::doTestStepPreambleL() + { + // ensure there's always a Active Scheduler for the Composer + if (!CActiveScheduler::Current()) + { + iScheduler = new (ELeave) CActiveScheduler; + CActiveScheduler::Install(iScheduler); + } + + SetTestStepResult(EPass); + return TestStepResult(); + } + +TVerdict C3GPLibComposeBase::doTestStepPostambleL() + { + if (iScheduler) + { + CActiveScheduler::Install(NULL); + delete iScheduler; + } + + return TestStepResult(); + } + +TVerdict C3GPLibComposeBase::doTestStepL() + { + if (TestStepResult() != EPass) + { + return TestStepResult(); + } + SetTestStepError(KErrNone); + + C3GPCompose* composer = doTestStepCreateComposerL(); + CleanupStack::PushL(composer); + + doTestStepComposeOpenL(*composer); + if (TestStepResult() == EPass) + { + // set it to EFail, if both calls below does not leave, then it will be reset + // back to EPass + SetTestStepResult(EFail); + doTestStepComposeWriteVideoAudioL(*composer); + doTestStepComposeSetUserDataL(*composer); + SetTestStepResult(EPass); + } + + TInt err = composer->Complete(); + if (err != KErrNone) + { + SetTestStepResult(EFail); + User::Leave(err); + } + CleanupStack::PopAndDestroy(composer); + + return TestStepResult(); + } + +C3GPCompose* C3GPLibComposeBase::doTestStepCreateComposerL() + { + return C3GPCompose::NewL(); + } + +void C3GPLibComposeBase::doTestStepComposeWriteVideoAudioL(C3GPCompose& /* aComposer */) + { + } + +void C3GPLibComposeBase::doTestStepComposeSetUserDataL(C3GPCompose& /* aComposer */) + { + } + +// ----------------------------------------------------------------------------- +// C3GPLibComposeFilename +// ----------------------------------------------------------------------------- +// +C3GPLibComposeFilename::C3GPLibComposeFilename() + { + } + +TVerdict C3GPLibComposeFilename::doTestStepPreambleL() + { + // ensure all basic setup is completed first + C3GPLibComposeBase::doTestStepPreambleL(); + if (TestStepResult() == EPass) + { + TPtrC fileNamePtr; + if (GetStringFromConfig(ConfigSection(), _L("filename"), fileNamePtr)) + { + // save a copy of the filename specified for the test + iFilename.CreateL(fileNamePtr); + } + else + { + // cannot find filename! + ERR_PRINTF1(_L("Filename not specified. Test cannot proceed.")); + SetTestStepResult(ETestSuiteError); + } + } + + return TestStepResult(); + } + +TVerdict C3GPLibComposeFilename::doTestStepPostambleL() + { + iFilename.Close(); + + // clean up all composer test base setups + C3GPLibComposeBase::doTestStepPostambleL(); + + return TestStepResult(); + } + +void C3GPLibComposeFilename::doTestStepComposeOpenL(C3GPCompose& aComposer) + { + T3GPAudioPropertiesMpeg4Audio audio(100, KDummyData); + T3GPVideoPropertiesAvc video(100, TSize(100, 100), KDummyData); + + TInt err = aComposer.Open(E3GP3GP, &video, &audio, iFilename); + if (err != KErrNone) + { + if (!ShouldRunOOMTest()) + { + ERR_PRINTF2(_L("C3GPCompose::Open failed with error = %d"), err); + } + SetTestStepError(err); + SetTestStepResult(EFail); + } + else + { + INFO_PRINTF1(_L("C3GPCompose::Open completes with no error")); + SetTestStepResult(EPass); + } + } + +// ----------------------------------------------------------------------------- +// C3GPLibComposeWithoutOpen +// ----------------------------------------------------------------------------- +// +C3GPLibComposeWithoutOpen::C3GPLibComposeWithoutOpen() + { + } + +void C3GPLibComposeWithoutOpen::doTestStepComposeOpenL(C3GPCompose& /* aComposer */) + { + // This test needs the composer NOT initialised. Do nothing here + } + +void C3GPLibComposeWithoutOpen::doTestStepComposeWriteVideoAudioL(C3GPCompose& aComposer) + { + if (TestStepResult() != EPass) + { + return; + } + + TInt err = aComposer.WriteVideoFrame(KDummyData, 100, ETrue); + if (err != KErrNotReady) + { + ERR_PRINTF2(_L("C3GPCompose::WriteVideoFrame failed with error = %d instead of KErrNotReady"), err); + SetTestStepResult(EFail); + } + + if (TestStepResult() == EPass) + { + T3GPFrameDependencies dependencies; + err = aComposer.WriteVideoFrame(KDummyData, 100, ETrue, dependencies); + if (err != KErrNotReady) + { + ERR_PRINTF2(_L("C3GPCompose::WriteVideoFrame failed with error = %d instead of KErrNotReady"), err); + SetTestStepResult(EFail); + } + } + + if (TestStepResult() == EPass) + { + err = aComposer.WriteAudioFrames(KDummyData, 100); + if (err != KErrNotReady) + { + ERR_PRINTF2(_L("C3GPCompose::WriteAudioFrames failed with error = %d instead of KErrNotReady"), err); + SetTestStepResult(EFail); + } + } + } + +void C3GPLibComposeWithoutOpen::doTestStepComposeSetUserDataL(C3GPCompose& aComposer) + { + if (TestStepResult() != EPass) + { + return; + } + + TInt err = aComposer.SetUserData(E3GPUdtaMoov, KDummyData); + if (err != KErrNotReady) + { + ERR_PRINTF2(_L("C3GPCompose::SetUserData failed with error = %d instead of KErrNotReady"), err); + SetTestStepResult(EFail); + } + + if (TestStepResult() == EPass) + { + err = aComposer.SetUserData(E3GPUdtaVideoTrak, KDummyData); + if (err != KErrNotReady) + { + ERR_PRINTF2(_L("C3GPCompose::SetUserData failed with error = %d instead of KErrNotReady"), err); + SetTestStepResult(EFail); + } + } + + if (TestStepResult() == EPass) + { + err = aComposer.SetUserData(E3GPUdtaAudioTrak, KDummyData); + if (err != KErrNotReady) + { + ERR_PRINTF2(_L("C3GPCompose::SetUserData failed with error = %d instead of KErrNotReady"), err); + SetTestStepResult(EFail); + } + } + } + +// ----------------------------------------------------------------------------- +// C3GPLibComposeFile +// ----------------------------------------------------------------------------- +// +C3GPLibComposeFile::C3GPLibComposeFile() : + iInputFileFormat(E3GP3GP), + iVideoType(E3GPNoVideo), + iAudioType(E3GPNoAudio) + { + } + +TVerdict C3GPLibComposeFile::doTestStepPreambleL() + { + // ensure the base class setup is completed first + C3GPLibComposeBase::doTestStepPreambleL(); + if (TestStepResult() == EPass) + { + TInt temp; + if (GetIntFromConfig(ConfigSection(), _L("inputFormat"), temp)) + { + iInputFileFormat = (T3GPFileFormatType)temp; + + if (GetIntFromConfig(ConfigSection(), _L("video"), temp)) + { + iVideoType = (T3GPVideoType)temp; + } + + if (GetIntFromConfig(ConfigSection(), _L("audio"), temp)) + { + iAudioType = (T3GPAudioType)temp; + } + + if (iVideoType == E3GPNoVideo && iAudioType == E3GPNoAudio) + { + // At least audio or video should be specified + ERR_PRINTF1(_L("Specify at least video or audio")); + SetTestStepResult(ETestSuiteError); + } + else + { + #ifdef __WINSCW__ + _LIT(KTestFolderName, "testFolderNameEmu"); + #else + _LIT(KTestFolderName, "testFolderNameHw"); + #endif + + TPtrC testFolderName; + if (GetStringFromConfig(_L("general"), KTestFolderName, testFolderName)) + { + TInt err = iFs.Connect(); + if (err == KErrNone) + { + iFs.MkDirAll(testFolderName); + + TFileName fileName; + // Create a temp file for the composer to write data into + err = iFile.Temp(iFs, testFolderName, fileName, EFileShareExclusive); + if (err == KErrNone) + { + iFileName.CreateL(fileName); + } + } + + if (err != KErrNone) + { + ERR_PRINTF1(_L("Fail to create temp file for testing.")); + SetTestStepResult(ETestSuiteError); + } + } + else + { + ERR_PRINTF1(_L("Fail to provide test directory.")); + SetTestStepResult(ETestSuiteError); + } + } + } + else + { + // file format has to be specified + ERR_PRINTF1(_L("Specify file format of the file to be composed")); + SetTestStepResult(ETestSuiteError); + } + } + + return TestStepResult(); + } + +TVerdict C3GPLibComposeFile::doTestStepPostambleL() + { + // clean up of temp file + iFile.Close(); + iFs.Delete(iFileName); + iFs.Close(); + + iFileName.Close(); + + // clean up all composer test base setups + C3GPLibComposeBase::doTestStepPostambleL(); + + return TestStepResult(); + } + +void C3GPLibComposeFile::doTestStepComposeOpenL(C3GPCompose& aComposer) + { + T3GPVideoPropertiesBase* video = SetupVideoPropertiesL(); + CleanupStack::PushL(video); + + T3GPAudioPropertiesBase* audio = SetupAudioPropertiesL(); + CleanupStack::PushL(audio); + + TInt err = aComposer.Open(iInputFileFormat, video, audio, iFile); + if (err == KErrNone) + { + SetTestStepResult(EPass); + } + else + { + if (!ShouldRunOOMTest()) + { + ERR_PRINTF2(_L("C3GPLibComposeFile::doTestStepComposeOpenL => C3GPComposer::Open returns = %d"), err); + } + SetTestStepError(err); + SetTestStepResult(EInconclusive); + } + + CleanupStack::PopAndDestroy(2); // audio, video + } + +void C3GPLibComposeFile::doTestStepComposeWriteVideoAudioL(C3GPCompose& aComposer) + { + // add a dummy video frame. The content is of no importance for this test case, + // only the file format is of interest + TInt err = KErrNone; + + if (iVideoType != E3GPNoVideo) + { + err = aComposer.WriteVideoFrame(KDummyData, 10, ETrue); + if (err != KErrNone) + { + ERR_PRINTF2(_L("Fail to write video frame, err = %d"), err); + } + } + + if (err == KErrNone && iAudioType != E3GPNoAudio) + { + // add a dummy audio frame. The content is of no importance for this test case, + // only the file format is of interest + err = aComposer.WriteAudioFrames(KDummyData, 10); + if (err != KErrNone) + { + ERR_PRINTF2(_L("Fail to write audio frame, err = %d"), err); + } + } + + if (err != KErrNone) + { + SetTestStepResult(EInconclusive); + } + } + +T3GPVideoPropertiesBase* C3GPLibComposeFile::SetupVideoPropertiesL() + { + if (iVideoType == E3GPNoVideo) + { + return NULL; + } + + // create a dummy video property for setting the composer + T3GPVideoPropertiesBase* video = NULL; + switch(iVideoType) + { + case E3GPMpeg4Video: + video = SetupMpeg4VideoL(); + break; + + case E3GPAvcProfileBaseline: + case E3GPAvcProfileMain: + case E3GPAvcProfileExtended: + case E3GPAvcProfileHigh: + video = SetupAvcVideoL(); + break; + + case E3GPH263Profile0: + case E3GPH263Profile3: + video = SetupH263VideoL(); + break; + + default: + User::Leave(KErrUnknown); + } + + return video; + } + +T3GPVideoPropertiesBase* C3GPLibComposeFile::SetupAvcVideoL() + { + T3GPVideoPropertiesBase* video = new (ELeave) T3GPVideoPropertiesAvc(1000, TSize(100, 100), KDummyData); + return video; + } + +T3GPVideoPropertiesBase* C3GPLibComposeFile::SetupH263VideoL() + { + T3GPVideoPropertiesH263::TProfile profile = T3GPVideoPropertiesH263::EProfile0; + if (iVideoType == E3GPH263Profile3) + { + profile = T3GPVideoPropertiesH263::EProfile3; + } + T3GPVideoPropertiesBase* video = new (ELeave) T3GPVideoPropertiesH263(1000, TSize(100, 100), 10, profile); + return video; + } + +T3GPVideoPropertiesBase* C3GPLibComposeFile::SetupMpeg4VideoL() + { + T3GPVideoPropertiesBase* video = new (ELeave) T3GPVideoPropertiesMpeg4Video(1000, TSize(100, 100), 4000, 400, KDummyData); + return video; + } + +T3GPAudioPropertiesBase* C3GPLibComposeFile::SetupAudioPropertiesL() + { + if (iAudioType == E3GPNoAudio) + { + return NULL; + } + + // create a dummy audio property for setting the composer + T3GPAudioPropertiesBase* audio = NULL; + switch(iAudioType) + { + case E3GPMpeg4Video: + audio = SetupMpeg4AudioL(); + break; + + case E3GPQcelp13K: + audio = SetupQcelpAudioL(); + break; + + case E3GPAmrNB: + case E3GPAmrWB: + audio = SetupAmrAudioL(); + break; + + default: + User::Leave(KErrUnknown); + break; + } + + return audio; + } + +T3GPAudioPropertiesBase* C3GPLibComposeFile::SetupQcelpAudioL() + { + // for this test's purpose, just use the default QCELP sample entry storage mode + T3GPAudioPropertiesBase* audio = new (ELeave) T3GPAudioPropertiesQcelp(1000, 10); + return audio; + } + +T3GPAudioPropertiesBase* C3GPLibComposeFile::SetupAmrAudioL() + { + T3GPAudioPropertiesAmr::TSpeechCodec codec = T3GPAudioPropertiesAmr::EAmrWB; + if (iAudioType == E3GPAmrNB) + { + codec = T3GPAudioPropertiesAmr::EAmrNB; + } + T3GPAudioPropertiesBase* audio = new (ELeave) T3GPAudioPropertiesAmr(1000, 10, 150, codec); + return audio; + } + +T3GPAudioPropertiesBase* C3GPLibComposeFile::SetupMpeg4AudioL() + { + T3GPAudioPropertiesBase* audio = new (ELeave)T3GPAudioPropertiesMpeg4Audio(1000, KDummyData); + return audio; + } + +// ----------------------------------------------------------------------------- +// C3GPLibComposeFileWithFileFormatCheck +// ----------------------------------------------------------------------------- +// +C3GPLibComposeFileWithFileFormatCheck::C3GPLibComposeFileWithFileFormatCheck() : + iOutputFileFormat(E3GP3GP) + { + } + +TVerdict C3GPLibComposeFileWithFileFormatCheck::doTestStepPreambleL() + { + // ensure base class setup is completed first + C3GPLibComposeFile::doTestStepPreambleL(); + + if (TestStepResult() == EPass) + { + TInt temp; + if (!GetIntFromConfig(ConfigSection(), _L("outputFormat"), temp)) + { + ERR_PRINTF1(_L("outputFormat not specified")); + SetTestStepResult(ETestSuiteError); + } + else + { + iOutputFileFormat = (T3GPFileFormatType)temp; + } + } + + return TestStepResult(); + } + +TVerdict C3GPLibComposeFileWithFileFormatCheck::doTestStepL() + { + if (TestStepResult() != EPass) + { + return TestStepResult(); + } + + // this triggers: + // 1. Create a composer + // 2. Open the composer - C3GPLibComposeFileFormatCheck::doTestStepComposeOpenL + // 3. Write Video & Audio Data - C3GPLibComposeFileFormatCheck::doTestStepComposeWriteVideoAudioL + // 4. Write User Data - C3GPLibComposeFileFormatCheck::doTestStepComposeSetUserDataL + // 5. Complete the composer + TVerdict verdict = C3GPLibComposeFile::doTestStepL(); + if (verdict == EPass) + { + // once the file is composed, it can be verified if the file composed is the same as the + // expected file format + verdict = VerifyFileFormatL(iFile); + } + else + { + INFO_PRINTF1(_L(" C3GPLibComposeFile::doTestStepL returns failed result")); + } + SetTestStepResult(verdict); + + if (!ShouldRunOOMTest()) + { + INFO_PRINTF2(_L("C3GPLibComposeFile::doTestStepL returns %d"), TestStepResult()); + } + return TestStepResult(); + } + +TVerdict C3GPLibComposeFileWithFileFormatCheck::VerifyFileFormatL(const RFile& aFile) + { + // Seek to the beginning of the file + TInt pos = 0; + User::LeaveIfError(aFile.Seek(ESeekStart, pos)); + + TVerdict verdict = EFail; + TBuf8<4> atom; + + while(ETrue) + { + // read the file content and search for the 'ftyp' atom to check + // the 32bit value of brand attribute immediately following the 'ftyp' type. + User::LeaveIfError(aFile.Read(atom)); + if (atom.Length() < atom.MaxLength()) + { + break; + } + + // read 4 bytes at a time, if 'ftyp' is found + if (Mem::Compare((&KFtypAtom)->Ptr(), (&KFtypAtom)->Length(), atom.Ptr(), atom.Length()) == 0) + { + // read 4 more bytes, and it should contain the brand value + User::LeaveIfError(aFile.Read(atom)); + if (atom.Length() < atom.MaxLength()) + { + // cannot read brand value, test failed. + ERR_PRINTF1(_L("Failed to read enough data for comparison.")); + break; + } + + switch(iOutputFileFormat) + { + case E3GP3G2: + { + // check if file type is 3G2 + if (!ShouldRunOOMTest()) + { + INFO_PRINTF1(_L("Check 3GP2 file format.")); + } + if (Mem::Compare((&K3g2Brand)->Ptr(), (&K3g2Brand)->Length(), atom.Ptr(), atom.Length()) == 0) + { + verdict = EPass; + break; + } + } + break; + + case E3GPMP4: + { + if (!ShouldRunOOMTest()) + { + INFO_PRINTF1(_L("Check MP4 file format.")); + } + // check if file type is MP4 + if (Mem::Compare((&KMp4Brand)->Ptr(), (&KMp4Brand)->Length(), atom.Ptr(), atom.Length()) == 0) + { + verdict = EPass; + } + } + break; + + case E3GP3GP: + { + if (!ShouldRunOOMTest()) + { + INFO_PRINTF1(_L("Check 3GP file format.")); + } + // check if file type is 3GP + // Both 3gp4 & 3gp6 are valid brands, thus checking ONLY "3gp" instead of the full atom size + if (Mem::Compare((&K3gpBrand)->Ptr(), (&K3gpBrand)->Length(), atom.Ptr(), (&K3gpBrand)->Length()) == 0) + { + verdict = EPass; + } + } + break; + + default: + INFO_PRINTF1(_L("Unknown format expected.")); + verdict = EInconclusive; + break; + } + + // ftyp is found, regardless of the result, finish reading the file + break; + } + } + + return verdict; + } + +// ----------------------------------------------------------------------------- +// C3GPLibComposeFrameDependency +// ----------------------------------------------------------------------------- +// +C3GPLibComposeFrameDependency::C3GPLibComposeFrameDependency() + { + } + +void C3GPLibComposeFrameDependency::doTestStepComposeWriteVideoAudioL(C3GPCompose& aComposer) + { + TInt err = KErrNone; + T3GPFrameDependencies dep; + + for (TInt i = 0; i <= (TInt)E3GPDependencyNone; i++) + { + for (TInt j = 0; j <= (TInt)E3GPDependencyNone; j++) + { + for (TInt k = 0; k <= (TInt)E3GPRedundancyNone; k++) + { + dep.iDependsOn = (T3GPVideoFrameDependency)i; + dep.iIsDependedOn = (T3GPVideoFrameDependency)j; + dep.iHasRedundancy = (T3GPVideoFrameRedundancy)k; + + // add a dummy video frame. The content is of no importance for this test case, + // only the different dependency/redundancy is the focus of this test + err = aComposer.WriteVideoFrame(KDummyData, 100, ETrue, dep); + if (err != KErrNone) + { + ERR_PRINTF2(_L("C3GPCompose::WriteVideoFrame (with frame dependency) failed with error = %d"), err); + SetTestStepResult(EFail); + break; + } + } + } + } + } + +// ----------------------------------------------------------------------------- +// C3GPLibComposeVideoProperties +// ----------------------------------------------------------------------------- +// +C3GPLibComposeVideoProperties::C3GPLibComposeVideoProperties() + { + } + +TVerdict C3GPLibComposeVideoProperties::doTestStepPreambleL() + { + C3GPLibComposeFile::doTestStepPreambleL(); + if (TestStepResult() != EPass) + { + return TestStepResult(); + } + + TInt temp; + TBool result = ETrue; + result = GetIntFromConfig(ConfigSection(), _L("width"), temp); + if (result) + { + iSize.iWidth = temp; + result = GetIntFromConfig(ConfigSection(), _L("height"), temp); + if (result) + { + iSize.iHeight = temp; + result = GetIntFromConfig(ConfigSection(), _L("timescale"), temp); + if (result) + { + iTimescale = temp; + } + } + } + + if (result && + (iVideoType == E3GPMpeg4Video || + iVideoType == E3GPAvcProfileBaseline || + iVideoType == E3GPAvcProfileMain || + iVideoType == E3GPAvcProfileExtended || + iVideoType == E3GPAvcProfileHigh ) + ) + { + TPtrC decoder; + result = GetStringFromConfig(ConfigSection(), _L("decoderSpecInfo"), decoder); + if (result) + { + iDecoderSpecInfo.CreateL(decoder.Length()); + iDecoderSpecInfo.Copy(decoder); + } + } + + if (result && (iVideoType == E3GPMpeg4Video)) + { + result = GetIntFromConfig(ConfigSection(), _L("avgBR"), temp); + if (result) + { + iAvgBitRate = temp; + result = GetIntFromConfig(ConfigSection(), _L("maxBR"), temp); + if (result) + { + iMaxBitRate = temp; + } + } + } + + if (result && (iVideoType == E3GPH263Profile0 || iVideoType == E3GPH263Profile3)) + { + result = GetIntFromConfig(ConfigSection(), _L("level"), temp); + if (result) + { + iVideoLevel = temp; + } + } + + if (!result) + { + ERR_PRINTF1(_L("Cannot retrieve necessary video properties to complete this test.")); + SetTestStepResult(ETestSuiteError); + } + + return TestStepResult(); + } + +TVerdict C3GPLibComposeVideoProperties::doTestStepPostambleL() + { + iDecoderSpecInfo.Close(); + + // clean up base class setups + C3GPLibComposeFile::doTestStepPostambleL(); + + return TestStepResult(); + } + +T3GPVideoPropertiesBase* C3GPLibComposeVideoProperties::SetupAvcVideoL() + { + T3GPVideoPropertiesBase* video = new (ELeave) T3GPVideoPropertiesAvc(iTimescale, iSize, iDecoderSpecInfo); + return video; + } + +T3GPVideoPropertiesBase* C3GPLibComposeVideoProperties::SetupH263VideoL() + { + T3GPVideoPropertiesH263::TProfile profile = T3GPVideoPropertiesH263::EProfile0; + if (iVideoType == E3GPH263Profile3) + { + profile = T3GPVideoPropertiesH263::EProfile3; + } + T3GPVideoPropertiesBase* video = new (ELeave) T3GPVideoPropertiesH263(iTimescale, iSize, iVideoLevel, profile); + return video; + } + +T3GPVideoPropertiesBase* C3GPLibComposeVideoProperties::SetupMpeg4VideoL() + { + T3GPVideoPropertiesBase* video = new (ELeave) T3GPVideoPropertiesMpeg4Video(iTimescale, + iSize, + iMaxBitRate, + iAvgBitRate, + iDecoderSpecInfo); + return video; + } + +// ----------------------------------------------------------------------------- +// C3GPLibComposeWithSpecificBufferSize +// ----------------------------------------------------------------------------- +// +C3GPLibComposeWithSpecificBufferSize::C3GPLibComposeWithSpecificBufferSize() + { + } + +TVerdict C3GPLibComposeWithSpecificBufferSize::doTestStepPreambleL() + { + TVerdict verdict = C3GPLibComposeFile::doTestStepPreambleL(); + if (verdict != EPass) + { + return verdict; + } + + TInt temp; + if (GetIntFromConfig(ConfigSection(), _L("bufferSize"), temp)) + { + iBufferSize = temp; + if (GetIntFromConfig(ConfigSection(), _L("bufferCount"), temp)) + { + iBufferMaxCount = temp; + } + else + { + ERR_PRINTF1(_L("C3GPLibComposeWithSpecificBufferSize cannot read Buffer Max Count")); + SetTestStepResult(ETestSuiteError); + } + } + else + { + ERR_PRINTF1(_L("C3GPLibComposeWithSpecificBufferSize cannot read Buffer Size")); + SetTestStepResult(ETestSuiteError); + } + + return TestStepResult(); + } + +C3GPCompose* C3GPLibComposeWithSpecificBufferSize::doTestStepCreateComposerL() + { + return C3GPCompose::NewL(iBufferSize, iBufferMaxCount); + } + +// ----------------------------------------------------------------------------- +// C3GPLibComposeUserData +// ----------------------------------------------------------------------------- +// +C3GPLibComposeUserData::C3GPLibComposeUserData() : + iUdtaLocation(-1) + { + } + +TVerdict C3GPLibComposeUserData::doTestStepPreambleL() + { + // ensure all basic setup is completed first + C3GPLibComposeFile::doTestStepPreambleL(); + if (TestStepResult() == EPass) + { + GetBoolFromConfig(ConfigSection(), _L("udtaMoov"), iUdtaMoov); + GetBoolFromConfig(ConfigSection(), _L("udtaVideo"), iUdtaVideo); + GetBoolFromConfig(ConfigSection(), _L("udtaAudio"), iUdtaAudio); + GetIntFromConfig(ConfigSection(), _L("udtaLocation"), iUdtaLocation); + + if (!iUdtaMoov && !iUdtaVideo && !iUdtaAudio && iUdtaLocation == -1) + { + ERR_PRINTF1(_L("No user data location is specified. Test cannot proceed.")); + SetTestStepResult(ETestSuiteError); + } + else + { + TPtrC userDataPtr; + if (GetStringFromConfig(ConfigSection(), _L("userData"), userDataPtr)) + { + iUserData.CreateL(userDataPtr.Length()); + iUserData.Copy(userDataPtr); + } + else + { + // user data not specified, use dummy data + iUserData.CreateL(KDummyData); + } + } + } + + return TestStepResult(); + } + +TVerdict C3GPLibComposeUserData::doTestStepPostambleL() + { + iUserData.Close(); + + // clean up base class setups + C3GPLibComposeFile::doTestStepPostambleL(); + + return TestStepResult(); + } + +void C3GPLibComposeUserData::doTestStepComposeSetUserDataL(C3GPCompose& aComposer) + { + TInt err = KErrNone; + if (iUdtaVideo) + { + err = aComposer.SetUserData(E3GPUdtaVideoTrak, iUserData); + if (err != KErrNone) + { + ERR_PRINTF2(_L("C3GPComposer::SetUserData(E3GPUdtaVideoTrak) fails with %d"), err); + SetTestStepError(err); + } + } + if (iUdtaAudio) + { + err = aComposer.SetUserData(E3GPUdtaAudioTrak, iUserData); + if (err != KErrNone) + { + ERR_PRINTF2(_L("C3GPComposer::SetUserData(E3GPUdtaAudioTrak) fails with %d"), err); + SetTestStepError(err); + } + } + if (iUdtaMoov) + { + err = aComposer.SetUserData(E3GPUdtaMoov, iUserData); + if (err != KErrNone) + { + ERR_PRINTF2(_L("C3GPComposer::SetUserData(E3GPUdtaMoov) fails with %d"), err); + SetTestStepError(err); + } + } + + if (iUdtaLocation != -1) + { + // if a specific user data location has been specified, try it! + err = aComposer.SetUserData((T3GPUdtaLocation)iUdtaLocation, iUserData); + if (err != KErrNone) + { + ERR_PRINTF3(_L("C3GPComposer::SetUserData(%d) fails with %d"), iUdtaLocation, err); + SetTestStepError(err); + } + } + } + +// ----------------------------------------------------------------------------- +// C3GPLibComposeWithFlag +// ----------------------------------------------------------------------------- +// +C3GPLibComposeWithFlag::C3GPLibComposeWithFlag() + { + } + +TVerdict C3GPLibComposeWithFlag::doTestStepPreambleL() + { + // ensure the base class setup is completed first + C3GPLibComposeFile::doTestStepPreambleL(); + if (TestStepResult() == EPass) + { + if (!GetIntFromConfig(ConfigSection(), _L("flag"), iComposeFlag)) + { + ERR_PRINTF1(_L("C3GPLibComposeWithFlag::doTestStepPreambleL cannot retrieve any composer flags.")); + SetTestStepResult(ETestSuiteError); + } + } + return TestStepResult(); + } + +void C3GPLibComposeWithFlag::doTestStepComposeOpenL(C3GPCompose& aComposer) + { + T3GPVideoPropertiesBase* video = SetupVideoPropertiesL(); + CleanupStack::PushL(video); + + T3GPAudioPropertiesBase* audio = SetupAudioPropertiesL(); + CleanupStack::PushL(audio); + + TInt err = aComposer.Open(iInputFileFormat, video, audio, iFile, iComposeFlag); + if (err == KErrNone) + { + SetTestStepResult(EPass); + } + else + { + ERR_PRINTF2(_L("C3GPLibComposeFile::doTestStepComposeOpenL => C3GPComposer::Open returns = %d"), err); + SetTestStepResult(EInconclusive); + } + + CleanupStack::PopAndDestroy(2); // audio, video + } + +// ----------------------------------------------------------------------------- +// C3GPLibComposeAudioProperties +// ----------------------------------------------------------------------------- +// +C3GPLibComposeAudioProperties::C3GPLibComposeAudioProperties() + { + } + +TVerdict C3GPLibComposeAudioProperties::doTestStepPreambleL() + { + C3GPLibComposeFile::doTestStepPreambleL(); + if (TestStepResult() != EPass) + { + return TestStepResult(); + } + + TInt temp; + TBool result = ETrue; + result = GetIntFromConfig(ConfigSection(), _L("timescale"), temp); + if (result) + { + iTimescale = temp; + } + + if (result && (iAudioType == E3GPQcelp13K)) + { + result = GetIntFromConfig(ConfigSection(), _L("storage"), temp); + if (result) + { + iQCelpMode = (T3GPQcelpStorageMode) temp; + if (iQCelpMode == E3GPMP4AudioDescriptionBox) + { + TPtrC decoder; + result = GetStringFromConfig(ConfigSection(), _L("decoderSpecInfo"), decoder); + if (result) + { + iDecoderSpecInfo.CreateL(decoder.Length()); + iDecoderSpecInfo.Copy(decoder); + } + } + } + + if (result) + { + result = GetIntFromConfig(ConfigSection(), _L("fps"), iFps); + } + } + + if (result && (iAudioType == E3GPMpeg4Audio)) + { + TPtrC decoder; + result = GetStringFromConfig(ConfigSection(), _L("decoderSpecInfo"), decoder); + if (result) + { + iDecoderSpecInfo.CreateL(decoder.Length()); + iDecoderSpecInfo.Copy(decoder); + } + } + + if (result && (iAudioType == E3GPAmrNB || iAudioType == E3GPAmrWB)) + { + result = GetIntFromConfig(ConfigSection(), _L("modeSet"), iModeSet); + if (result) + { + result = GetIntFromConfig(ConfigSection(), _L("fps"), iFps); + } + } + + if (!result) + { + // + ERR_PRINTF1(_L("Cannot retrieve necessary a properties to complete this test.")); + SetTestStepResult(ETestSuiteError); + } + + return TestStepResult(); + } + +TVerdict C3GPLibComposeAudioProperties::doTestStepPostambleL() + { + iDecoderSpecInfo.Close(); + + // clean up base class setups + C3GPLibComposeFile::doTestStepPostambleL(); + + return TestStepResult(); + } + +T3GPAudioPropertiesBase* C3GPLibComposeAudioProperties::SetupQcelpAudioL() + { + T3GPAudioPropertiesBase* audio = NULL; + + if (iQCelpMode == E3GPQcelpSampleEntryBox) + { + audio = new (ELeave) T3GPAudioPropertiesQcelp(iTimescale, iFps); + } + else if (iQCelpMode == E3GPMP4AudioDescriptionBox) + { + audio = new (ELeave) T3GPAudioPropertiesQcelp(iTimescale, iFps, iDecoderSpecInfo); + } + else + { + User::Leave(KErrNotFound); + } + + return audio; + } + +T3GPAudioPropertiesBase* C3GPLibComposeAudioProperties::SetupAmrAudioL() + { + T3GPAudioPropertiesAmr::TSpeechCodec codec = T3GPAudioPropertiesAmr::EAmrWB; + if (iAudioType == E3GPAmrNB) + { + codec = T3GPAudioPropertiesAmr::EAmrNB; + } + T3GPAudioPropertiesBase* audio = new (ELeave) T3GPAudioPropertiesAmr(iTimescale, iFps, iModeSet, codec); + return audio; + } + +T3GPAudioPropertiesBase* C3GPLibComposeAudioProperties::SetupMpeg4AudioL() + { + T3GPAudioPropertiesBase* audio = new (ELeave)T3GPAudioPropertiesMpeg4Audio(iTimescale, iDecoderSpecInfo); + return audio; + } + +// ----------------------------------------------------------------------------- +// C3GPLibComposeWithNoAudioVideo +// ----------------------------------------------------------------------------- +// +C3GPLibComposeWithNoAudioVideo::C3GPLibComposeWithNoAudioVideo() + { + } + +TVerdict C3GPLibComposeWithNoAudioVideo::doTestStepPreambleL() + { + // ensure the base class setup is completed first + C3GPLibComposeFile::doTestStepPreambleL(); + if (TestStepResult() == EPass) + { + // reset the video / audio type both of No Video & No Audio + iVideoType = E3GPNoVideo; + iAudioType = E3GPNoAudio; + } + + return TestStepResult(); + } + +// ----------------------------------------------------------------------------- +// C3GPLibComposeAudioFrames +// ----------------------------------------------------------------------------- +// +C3GPLibComposeAudioFrames::C3GPLibComposeAudioFrames() + { + } + +TVerdict C3GPLibComposeAudioFrames::doTestStepPreambleL() + { + // ensure all basic setup is completed first + C3GPLibComposeFile::doTestStepPreambleL(); + if (TestStepResult() == EPass) + { + if (GetIntFromConfig(ConfigSection(), _L("duration"), iDuration)) + { + TPtrC audioFramePtr; + if (GetStringFromConfig(ConfigSection(), _L("audioFrame"), audioFramePtr)) + { + iAudioFrames.CreateL(audioFramePtr.Length()); + iAudioFrames.Copy(audioFramePtr); + } + else + { + // cannot find expected error! + ERR_PRINTF1(_L("audioFrame not specified. Test cannot proceed.")); + SetTestStepResult(ETestSuiteError); + } + } + else + { + // cannot find expected error! + ERR_PRINTF1(_L("duration not specified. Test cannot proceed.")); + SetTestStepResult(ETestSuiteError); + } + } + + return TestStepResult(); + } + +TVerdict C3GPLibComposeAudioFrames::doTestStepPostambleL() + { + // cleanup + iAudioFrames.Close(); + + // ensure all base cleanup is done + C3GPLibComposeFile::doTestStepPostambleL(); + + return TestStepResult(); + } + +void C3GPLibComposeAudioFrames::doTestStepComposeWriteVideoAudioL(C3GPCompose& aComposer) + { + // add the audio frame + TInt err = aComposer.WriteAudioFrames(iAudioFrames, iDuration); + if (err != KErrNone) + { + if (!ShouldRunOOMTest()) + { + INFO_PRINTF2(_L("C3GPCompose::WriteAudioFrames returns %d"), err); + } + SetTestStepError(err); + } + } + +// ----------------------------------------------------------------------------- +// C3GPLibComposeVideoFrame +// ----------------------------------------------------------------------------- +// +C3GPLibComposeVideoFrame::C3GPLibComposeVideoFrame() + { + } + +TVerdict C3GPLibComposeVideoFrame::doTestStepPreambleL() + { + // ensure all basic setup is completed first + C3GPLibComposeFile::doTestStepPreambleL(); + if (TestStepResult() == EPass) + { + if (GetBoolFromConfig(ConfigSection(), _L("keyFrame"), iKeyFrame)) + { + if (GetIntFromConfig(ConfigSection(), _L("duration"), iDuration)) + { + TPtrC framePtr; + if (GetStringFromConfig(ConfigSection(), _L("videoFrame"), framePtr)) + { + iVideoFrame.CreateL(framePtr.Length()); + iVideoFrame.Copy(framePtr); + + TInt dependsOn; + TInt isDependedOn; + TInt hasRedundancy; + if (GetIntFromConfig(ConfigSection(), _L("dependsOn"), dependsOn) && + GetIntFromConfig(ConfigSection(), _L("isDependedOn"), isDependedOn) && + GetIntFromConfig(ConfigSection(), _L("hasRedundancy"), hasRedundancy)) + { + iDependencies = new (ELeave) T3GPFrameDependencies(); + iDependencies->iDependsOn = (T3GPVideoFrameDependency) dependsOn; + iDependencies->iIsDependedOn = (T3GPVideoFrameDependency) isDependedOn; + iDependencies->iHasRedundancy = (T3GPVideoFrameRedundancy) hasRedundancy; + } + } + else + { + // cannot find expected error! + ERR_PRINTF1(_L("videoFrame not specified. Test cannot proceed.")); + SetTestStepResult(ETestSuiteError); + } + } + else + { + // cannot find expected error! + ERR_PRINTF1(_L("duration not specified. Test cannot proceed.")); + SetTestStepResult(ETestSuiteError); + } + } + else + { + // cannot find expected error! + ERR_PRINTF1(_L("keyFrame not specified. Test cannot proceed.")); + SetTestStepResult(ETestSuiteError); + } + } + + return TestStepResult(); + } + +TVerdict C3GPLibComposeVideoFrame::doTestStepPostambleL() + { + // cleanup + iVideoFrame.Close(); + delete iDependencies; + + // ensure all base cleanup is done + C3GPLibComposeFile::doTestStepPostambleL(); + + return TestStepResult(); + } + +void C3GPLibComposeVideoFrame::doTestStepComposeWriteVideoAudioL(C3GPCompose& aComposer) + { + // add the video frame + TInt err = KErrNone; + if (iDependencies) + { + err = aComposer.WriteVideoFrame(iVideoFrame, iDuration, iKeyFrame, *iDependencies); + } + else + { + err = aComposer.WriteVideoFrame(iVideoFrame, iDuration, iKeyFrame); + } + + if (err != KErrNone) + { + INFO_PRINTF2(_L("C3GPCompose::WriteVideoFrame returns %d"), err); + SetTestStepError(err); + } + } + +// ----------------------------------------------------------------------------- +// C3GPLibComposeOpenAgain +// ----------------------------------------------------------------------------- +// +C3GPLibComposeOpenAgain::C3GPLibComposeOpenAgain() + { + } + +void C3GPLibComposeOpenAgain::doTestStepComposeOpenL(C3GPCompose& aComposer) + { + C3GPLibComposeFile::doTestStepComposeOpenL(aComposer); + if (TestStepResult() == EPass) + { + // ensure the composer is opened, then try open it again! + T3GPVideoPropertiesBase* video = SetupVideoPropertiesL(); + CleanupStack::PushL(video); + + T3GPAudioPropertiesBase* audio = SetupAudioPropertiesL(); + CleanupStack::PushL(audio); + + // retrieve the current location of the temp file created when + // opening the composer the first time in C3GPLibComposeFile::doTestStepComposeOpenL + RBuf folderName; + folderName.CreateL(KMaxFileName); + CleanupClosePushL(folderName); + User::LeaveIfError(iFile.FullName(folderName)); + + TParsePtrC folderParse(folderName); + TPtrC folder = folderParse.DriveAndPath(); + + // create another file temp file within the same folder + RFile file; + TFileName fileName; + User::LeaveIfError(file.Temp(iFs, folder, fileName, EFileWrite)); + + TInt err = aComposer.Open(iInputFileFormat, video, audio, file); + TInt err2 = aComposer.Open(iInputFileFormat, video, audio, fileName); + if (err != KErrNone && err == err2) + { + SetTestStepError(err); + } + else + { + INFO_PRINTF1(_L("C3GPLibComposeOpenAgain C3GPCompose::Open returns inconsistent error.")); + } + + // clean up + file.Close(); + iFs.Delete(fileName); + + CleanupStack::PopAndDestroy(3); // audio, video, folderName + } + } + +// ----------------------------------------------------------------------------- +// C3GPLibComposeOpenReadOnlyFile +// ----------------------------------------------------------------------------- +// +C3GPLibComposeOpenReadOnlyFile::C3GPLibComposeOpenReadOnlyFile() + { + } + +void C3GPLibComposeOpenReadOnlyFile::doTestStepComposeOpenL(C3GPCompose& aComposer) + { + RBuf fileName; + fileName.CreateL(KMaxFilename); + CleanupClosePushL(fileName); + + // change the file to be opened to be a READ-ONLY file + User::LeaveIfError(iFile.FullName(fileName)); + iFile.Close(); + + User::LeaveIfError(iFile.Open(iFs, fileName, EFileShareReadersOnly)); + CleanupStack::PopAndDestroy(&fileName); + + C3GPLibComposeWithFlag::doTestStepComposeOpenL(aComposer); + } + +TVerdict C3GPLibComposeOpenReadOnlyFile::doTestStepL() + { + TVerdict verdict(EFail); + + TRAP_IGNORE(verdict = C3GPLibComposeWithFlag::doTestStepL()); + + return verdict; + } + +// ----------------------------------------------------------------------------- +// C3GPLibComposeOpenedFile +// ----------------------------------------------------------------------------- +// +C3GPLibComposeOpenedFile::C3GPLibComposeOpenedFile() + { + } + +void C3GPLibComposeOpenedFile::doTestStepComposeOpenL(C3GPCompose& aComposer) + { + RBuf fileName; + fileName.CreateL(KMaxFilename); + CleanupClosePushL(fileName); + + // change the file to be opened to be a READ-ONLY file + User::LeaveIfError(iFile.FullName(fileName)); + iFile.Close(); + + User::LeaveIfError(iFile.Open(iFs, fileName, EFileShareAny)); + + T3GPVideoPropertiesBase* video = SetupVideoPropertiesL(); + CleanupStack::PushL(video); + + T3GPAudioPropertiesBase* audio = SetupAudioPropertiesL(); + CleanupStack::PushL(audio); + + TInt err1 = aComposer.Open(iInputFileFormat, video, audio, fileName); + if (err1 != KErrNone) + { + if (!ShouldRunOOMTest()) + { + ERR_PRINTF2(_L("C3GPLibComposeOpenedFile::doTestStepComposeOpenL => C3GPComposer::Open returns = %d"), err1); + } + + iFile.Close(); + User::LeaveIfError(iFile.Open(iFs, fileName, EFileShareReadersOrWriters)); + TInt err2 = aComposer.Open(iInputFileFormat, video, audio, fileName); + + if (err1 == err2) + { + SetTestStepError(err1); + } + } + + CleanupStack::PopAndDestroy(3); // audio, video, fileName + } + +// ----------------------------------------------------------------------------- +// C3GPLibComposeMultiComposeOnSameFile +// ----------------------------------------------------------------------------- +// +C3GPLibComposeMultiComposeOnSameFile::C3GPLibComposeMultiComposeOnSameFile() + { + } + +void C3GPLibComposeMultiComposeOnSameFile::doTestStepComposeOpenL(C3GPCompose& aComposer) + { + C3GPLibComposeFilename::doTestStepComposeOpenL(aComposer); + if (TestStepError() == KErrNone && TestStepResult() == EPass) + { + T3GPAudioPropertiesMpeg4Audio audio(100, KDummyData); + T3GPVideoPropertiesAvc video(100, TSize(100, 100), KDummyData); + C3GPCompose* composer2 = C3GPCompose::NewL(); + + TInt err = composer2->Open(E3GP3GP, &video, &audio, iFilename); + if (err != KErrNone) + { + SetTestStepError(err); + } + + // close the composer + composer2->Complete(); + delete composer2; + } + } + +// ----------------------------------------------------------------------------- +// C3GPLibComposeMultiComposers +// ----------------------------------------------------------------------------- +// +C3GPLibComposeMultiComposers::C3GPLibComposeMultiComposers() + { + } + +void C3GPLibComposeMultiComposers::doTestStepComposeOpenL(C3GPCompose& aComposer) + { + C3GPLibComposeFilename::doTestStepComposeOpenL(aComposer); + if (TestStepError() == KErrNone && TestStepResult() == EPass) + { + #ifdef __WINSCW__ + _LIT(KTestFolderName, "testFolderNameEmu"); + #else + _LIT(KTestFolderName, "testFolderNameHw"); + #endif + + TPtrC testFolderName; + if (!GetStringFromConfig(_L("general"), KTestFolderName, testFolderName)) + { + User::Leave(KErrNotFound); + } + + TFileName fileName; + RFs fs; + User::LeaveIfError(fs.Connect()); + CleanupClosePushL(fs); + + // Composer 2 + T3GPAudioPropertiesMpeg4Audio audio1(100, KDummyData); + T3GPVideoPropertiesAvc video1(100, TSize(100, 100), KDummyData); + + RFile file1; + CleanupClosePushL(file1); + User::LeaveIfError(file1.Temp(fs, testFolderName, fileName, EFileShareExclusive)); + + C3GPCompose* composer2 = C3GPCompose::NewL(); + CleanupStack::PushL(composer2); + User::LeaveIfError(composer2->Open(E3GP3GP, &video1, &audio1, file1)); + + // composer 3 + T3GPAudioPropertiesMpeg4Audio audio2(50, KDummyData); + T3GPVideoPropertiesAvc video2(50, TSize(20, 20), KDummyData); + + RFile file2; + CleanupClosePushL(file2); + User::LeaveIfError(file2.Temp(fs, testFolderName, fileName, EFileShareExclusive)); + + C3GPCompose* composer3 = C3GPCompose::NewL(); + CleanupStack::PushL(composer3); + User::LeaveIfError(composer3->Open(E3GP3GP, &video2, &audio2, file2)); + + // write some data into composer 1, then 2, then 3 + User::LeaveIfError(aComposer.WriteVideoFrame(KDummyData, 10, EFalse)); + User::LeaveIfError(composer2->WriteVideoFrame(KDummyData, 10, EFalse)); + User::LeaveIfError(composer3->WriteVideoFrame(KDummyData, 10, EFalse)); + + // clean up for composer 3 + User::LeaveIfError(composer3->Complete()); + CleanupStack::PopAndDestroy(composer3); + CleanupStack::PopAndDestroy(&file2); + + // Parse file2 + C3GPParse* parser = C3GPParse::NewL(); + CleanupStack::PushL(parser); + User::LeaveIfError(parser->Open(fileName)); + + // write some data into composer 1 & 2 + User::LeaveIfError(aComposer.WriteVideoFrame(KDummyData, 10, EFalse)); + User::LeaveIfError(composer2->WriteVideoFrame(KDummyData, 10, EFalse)); + + // close parser and delete the file + User::LeaveIfError(parser->Complete()); + CleanupStack::PopAndDestroy(parser); + User::LeaveIfError(fs.Delete(fileName)); // delete the temp file created + + // clean up for composer 2 + User::LeaveIfError(composer2->Complete()); + file1.FullName(fileName); // retrieve the full name of file1 + CleanupStack::PopAndDestroy(composer2); + CleanupStack::PopAndDestroy(&file1); + User::LeaveIfError(fs.Delete(fileName)); // delete the temp file created + + // cleanup + CleanupStack::PopAndDestroy(&fs); + + // write some data into composer 1 + User::LeaveIfError(aComposer.WriteVideoFrame(KDummyData, 10, EFalse)); + } + } + +// ----------------------------------------------------------------------------- +// C3GPLibComposeCloseComposerWithoutComplete +// ----------------------------------------------------------------------------- +// +C3GPLibComposeCloseComposerWithoutComplete::C3GPLibComposeCloseComposerWithoutComplete() + { + } + +void C3GPLibComposeCloseComposerWithoutComplete::doTestStepComposeOpenL(C3GPCompose& aComposer) + { + // close the composer, then delete the file + aComposer.Complete(); + + RFs fs; + User::LeaveIfError(fs.Connect()); + CleanupClosePushL(fs); + + // ignore any error + fs.Delete(iFilename); + + // Reopens it + T3GPAudioPropertiesMpeg4Audio audio1(100, KDummyData); + T3GPVideoPropertiesAvc video1(100, TSize(100, 100), KDummyData); + + C3GPCompose* composer = C3GPCompose::NewL(); + CleanupStack::PushL(composer); + User::LeaveIfError(composer->Open(E3GP3GP, &video1, &audio1, iFilename)); + + // write some data into composer 1, then 2, then 3 + User::LeaveIfError(composer->WriteVideoFrame(KDummyData, 10, EFalse)); + + // delete the composer before calling Complete + CleanupStack::PopAndDestroy(composer); + + RFile file; + CleanupClosePushL(file); + User::LeaveIfError(file.Open(fs, iFilename, EFileRead)); + + TInt fileSize = 0; + User::LeaveIfError(file.Size(fileSize)); + + if (fileSize == 0) + { + SetTestStepResult(EFail); + } + + CleanupStack::PopAndDestroy(2); // file, fs + + // continue the test + C3GPLibComposeFilename::doTestStepComposeOpenL(aComposer); + } + +// ----------------------------------------------------------------------------- +// C3GPLibComposePanic +// ----------------------------------------------------------------------------- +// +C3GPLibComposePanic::C3GPLibComposePanic() + { + } + +TVerdict C3GPLibComposePanic::doTestStepPreambleL() + { + TVerdict verdict = C3GPLibComposeFilename::doTestStepPreambleL(); + if (TestStepResult() == EPass) + { + if (!GetBoolFromConfig(ConfigSection(), _L("panic"), iPanic)) + { + ERR_PRINTF1(_L("Test setting panic not specified. Test cannot proceed.")); + SetTestStepResult(ETestSuiteError); + } + else + { + TPtrC strPtr; + if (GetStringFromConfig(ConfigSection(), _L("dir"), strPtr)) + { + // save a copy of the dir specified for the test + iDir.CreateL(strPtr); + } + else + { + // cannot find filename! + ERR_PRINTF1(_L("Dir not specified. Test cannot proceed.")); + SetTestStepResult(ETestSuiteError); + } + } + } + + return TestStepResult(); + } + +void C3GPLibComposePanic::doTestStepComposeOpenL(C3GPCompose& aComposer) + { + // close the composer, then delete the file + aComposer.Complete(); + + RFs fs; + User::LeaveIfError(fs.Connect()); + CleanupClosePushL(fs); + + // retrieve the number of items in the directory + CDir* dirList = NULL; + User::LeaveIfError(fs.GetDir(iDir, KEntryAttNormal, ESortNone, dirList)); + TInt orgCount = dirList->Count(); + delete dirList; + + // Reopens it + T3GPAudioPropertiesMpeg4Audio audio1(100, KDummyData); + T3GPVideoPropertiesAvc video1(100, TSize(100, 100), KDummyData); + + C3GPCompose* composer = C3GPCompose::NewL(); + CleanupStack::PushL(composer); + User::LeaveIfError(composer->Open(E3GP3GP, &video1, &audio1, iFilename)); + + // write some data into composer 1, then 2, then 3 + User::LeaveIfError(composer->WriteVideoFrame(KDummyData, 10, EFalse)); + + if (iPanic) + { + // force a panic so that the composed file and the temporary file is left in the + // directory + User::Panic(_L("Testing"), KErrArgument); + } + + // delete the composer before calling Complete + composer->Complete(); + CleanupStack::PopAndDestroy(composer); + + User::LeaveIfError(fs.GetDir(iDir, KEntryAttNormal, ESortNone, dirList)); + TInt newCount = dirList->Count(); + delete dirList; + + // When cleaned up properly, only the composed file should be left within the directory. + if (!(newCount == 1 && orgCount > 0)) + { + SetTestStepResult(EFail); + } + + CleanupStack::PopAndDestroy(); // fs + + // continue the test + C3GPLibComposeFilename::doTestStepComposeOpenL(aComposer); + } + +TVerdict C3GPLibComposePanic::doTestStepPostambleL() + { + iDir.Close(); + return C3GPLibComposeFilename::doTestStepPostambleL(); + } + +// ----------------------------------------------------------------------------- +// C3GPLibComposeLargeFile +// ----------------------------------------------------------------------------- +// +C3GPLibComposeLargeFile::C3GPLibComposeLargeFile() + { + } + +TVerdict C3GPLibComposeLargeFile::doTestStepPreambleL() + { + // ensure the base class setup is completed first + C3GPLibComposeBase::doTestStepPreambleL(); + if (TestStepResult() == EPass) + { + TInt temp; + if (GetIntFromConfig(ConfigSection(), _L("inputFormat"), temp)) + { + iInputFileFormat = (T3GPFileFormatType)temp; + + if (GetIntFromConfig(ConfigSection(), _L("video"), temp)) + { + iVideoType = (T3GPVideoType)temp; + } + + if (GetIntFromConfig(ConfigSection(), _L("audio"), temp)) + { + iAudioType = (T3GPAudioType)temp; + } + + if (iVideoType == E3GPNoVideo && iAudioType == E3GPNoAudio) + { + // At least audio or video should be specified + ERR_PRINTF1(_L("Specify at least video or audio")); + SetTestStepResult(ETestSuiteError); + } + else + { + #ifdef __WINSCW__ + _LIT(KOutputDir, "filenameEmu"); + #else + _LIT(KOutputDir, "filenameHw"); + #endif + + TPtrC fileNamePtr; + if (GetStringFromConfig(ConfigSection(), KOutputDir, fileNamePtr)) + { + iFileName.CreateL(fileNamePtr); + User::LeaveIfError(iFs.Connect()); + + TInt err = iFs.MkDirAll(iFileName); + if (err != KErrNone && err != KErrAlreadyExists) + { + User::Leave(err); + } + + err = iFile64.Create(iFs, iFileName, EFileShareAny|EFileStream|EFileWrite); + if (err == KErrAlreadyExists) + { + User::LeaveIfError(iFile64.Replace(iFs, iFileName, EFileShareAny|EFileStream|EFileWrite)); + } + else + { + User::LeaveIfError(err); + } + } + else + { + // cannot find filename! + ERR_PRINTF1(_L("Filename not specified. Test cannot proceed.")); + SetTestStepResult(ETestSuiteError); + } + } + } + else + { + // file format has to be specified + ERR_PRINTF1(_L("Specify file format of the file to be composed")); + SetTestStepResult(ETestSuiteError); + } + + if (!GetIntFromConfig(ConfigSection(), _L("flag"), iComposeFlag)) + { + iComposeFlag = E3GPNoFlag; + } + } + + return TestStepResult(); + } + +TVerdict C3GPLibComposeLargeFile::doTestStepPostambleL() + { + // clean up of temp file + iFile64.Close(); + iFs.Delete(iFileName); + iFs.Close(); + + iFileName.Close(); + + // clean up all composer test base setups + C3GPLibComposeBase::doTestStepPostambleL(); + + return TestStepResult(); + } + +C3GPCompose* C3GPLibComposeLargeFile::doTestStepCreateComposerL() + { + return C3GPCompose::NewL(KLargeFileWriteBufferSize, KLargeFileWriteBufferMaxCount); + } + +void C3GPLibComposeLargeFile::doTestStepComposeOpenL(C3GPCompose& aComposer) + { + T3GPVideoPropertiesBase* video = SetupVideoPropertiesL(); + CleanupStack::PushL(video); + + T3GPAudioPropertiesBase* audio = SetupAudioPropertiesL(); + CleanupStack::PushL(audio); + + TInt err = aComposer.Open(iInputFileFormat, video, audio, iFile64, iComposeFlag); + if (err == KErrNone) + { + SetTestStepResult(EPass); + } + else + { + if (!ShouldRunOOMTest()) + { + ERR_PRINTF2(_L("C3GPLibComposeFile::doTestStepComposeOpenL => C3GPComposer::Open returns = %d"), err); + } + SetTestStepError(err); + SetTestStepResult(EInconclusive); + } + + CleanupStack::PopAndDestroy(2); // audio, video + } + +void C3GPLibComposeLargeFile::doTestStepComposeWriteVideoAudioL(C3GPCompose& aComposer) + { + RBuf8 videoBuf1; + CleanupClosePushL(videoBuf1); + TBool keyFrame1; + TUint videoTimestampMS = 0; + TUint videoTS1; + TUint frameSize = 0; + T3GPFrameDependencies aDependencies; + + RFile fileName; + CleanupClosePushL(fileName); + User::LeaveIfError(fileName.Open(iFs, KLargeVideoFile(), EFileRead)); + + C3GPParse* parser = C3GPParse::NewL(); + CleanupStack::PushL(parser); + User::LeaveIfError(parser->Open(fileName)); + User::LeaveIfError(parser->GetVideoFrameSize(frameSize)); + User::LeaveIfError(videoBuf1.Create((TInt)frameSize)); + User::LeaveIfError(parser->ReadVideoFrame(videoBuf1, keyFrame1, videoTimestampMS, videoTS1)); + + TInt error = parser->GetVideoFrameDependencies(aDependencies); + if (error != KErrNone) + { + aDependencies.iDependsOn = E3GPDependencyUnknown; + aDependencies.iIsDependedOn = E3GPDependencyUnknown; + aDependencies.iHasRedundancy = E3GPRedundancyUnknown; + } + + TInt err = KErrNone; + TInt64 size = 0; + TTime startTime; + TTime endTime; + startTime.UniversalTime(); + + // create a 3GB video file + TInt videoLength = videoBuf1.Length(); + while (size + videoLength < K3GigaBytes) + { + err = aComposer.WriteVideoFrame(videoBuf1, 100, keyFrame1, aDependencies); + if (err != KErrNone) + { + ERR_PRINTF2(_L("Fail to write video frame, err = %d"), err); + break; + } + iFile64.Size(size); + } + + endTime.UniversalTime(); + TTimeIntervalMinutes composeTime; + endTime.MinutesFrom(startTime, composeTime); + INFO_PRINTF3(_L("Took %d minutes to compose a video file of size %d bytes"), composeTime.Int(), size); + + if (err != KErrNone) + { + SetTestStepResult(EFail); + } + + User::LeaveIfError(parser->Complete()); + CleanupStack::PopAndDestroy(3, &videoBuf1); + } + +// ----------------------------------------------------------------------------- +// C3GPLibComposeLargeFileUserData +// ----------------------------------------------------------------------------- +// +C3GPLibComposeLargeFileUserData::C3GPLibComposeLargeFileUserData() + { + } + +void C3GPLibComposeLargeFileUserData::doTestStepComposeSetUserDataL(C3GPCompose& aComposer) + { + TInt bufferUdtaSize = 0; + TBuf8<256> bufferUdta; + TUint8* ptr = const_cast(bufferUdta.Ptr()); + TInt size = 0; + + _LIT8(KTitle,"titl"); + _LIT8(KData1,"This Udta titl test data 01!!"); + size = KTitle().Length() + KData1().Length() + 4; + WriteInt32(ptr, size); + ptr += 4; + Mem::Copy(ptr, KTitle().Ptr(), KTitle().Length()); + ptr += KTitle().Length(); + Mem::Copy(ptr, KData1().Ptr(), KData1().Length()); + ptr += KData1().Length(); + bufferUdtaSize += size; + + _LIT8(KTitle1,"titl"); + _LIT8(KData2,"This Udta titl test data 02!!blahblahblahbla"); + size = KTitle1().Length() + KData2().Length() + 4; + WriteInt32(ptr, size); + ptr += 4; + Mem::Copy(ptr, KTitle1().Ptr(), KTitle1().Length()); + ptr += KTitle1().Length(); + Mem::Copy(ptr, KData2().Ptr(), KData2().Length()); + ptr += KData2().Length(); + bufferUdtaSize += size; + + _LIT8(KTitle2,"titl"); + _LIT8(KData3,"This Udta titl test data 03!!Moreblahblahblahblahblahblahblahblahblah"); + size = KTitle2().Length() + KData3().Length() + 4; + WriteInt32(ptr, size); + ptr += 4; + Mem::Copy(ptr, KTitle2().Ptr(), KTitle2().Length()); + ptr += KTitle2().Length(); + Mem::Copy(ptr, KData3().Ptr(), KData3().Length()); + ptr += KData3().Length(); + bufferUdtaSize += size; + + bufferUdta.SetLength(bufferUdtaSize); + TInt error = aComposer.SetUserData(E3GPUdtaVideoTrak, bufferUdta); + + if (error != KErrNone) + { + ERR_PRINTF2(_L("C3GPComposer::SetUserData failed with %d"), error); + SetTestStepError(error); + } + } + +void C3GPLibComposeLargeFileUserData::WriteInt32(TUint8* aPtr, TInt32 aData) + { + aPtr[0] = TUint8(aData>>24); + aPtr[1] = TUint8(aData>>16); + aPtr[2] = TUint8(aData>>8); + aPtr[3] = TUint8(aData); + } + +// ----------------------------------------------------------------------------- +// C3GPLibComposeLargeFile32bitAPI +// ----------------------------------------------------------------------------- +// +C3GPLibComposeLargeFile32bitAPI::C3GPLibComposeLargeFile32bitAPI() + { + } + +C3GPCompose* C3GPLibComposeLargeFile32bitAPI::doTestStepCreateComposerL() + { + return C3GPCompose::NewL(KLargeFileWriteBufferSize, KLargeFileWriteBufferMaxCount); + } + +void C3GPLibComposeLargeFile32bitAPI::doTestStepComposeWriteVideoAudioL(C3GPCompose& aComposer) + { + RBuf8 videoBuf1; + CleanupClosePushL(videoBuf1); + TBool keyFrame1; + TUint videoTimestampMS = 0; + TUint videoTS1; + TUint frameSize = 0; + T3GPFrameDependencies aDependencies; + + RFile fileName; + CleanupClosePushL(fileName); + User::LeaveIfError(fileName.Open(iFs, KLargeVideoFile(), EFileRead)); + + C3GPParse* parser = C3GPParse::NewL(); + CleanupStack::PushL(parser); + User::LeaveIfError(parser->Open(fileName)); + User::LeaveIfError(parser->GetVideoFrameSize(frameSize)); + User::LeaveIfError(videoBuf1.Create((TInt)frameSize)); + User::LeaveIfError(parser->ReadVideoFrame(videoBuf1, keyFrame1, videoTimestampMS, videoTS1)); + + TInt error = parser->GetVideoFrameDependencies(aDependencies); + if (error != KErrNone) + { + aDependencies.iDependsOn = E3GPDependencyUnknown; + aDependencies.iIsDependedOn = E3GPDependencyUnknown; + aDependencies.iHasRedundancy = E3GPRedundancyUnknown; + } + + TInt err = KErrNone; + TInt size = 0; + TTime startTime; + TTime endTime; + startTime.UniversalTime(); + + // create a 3GB video file + TInt videoLength = videoBuf1.Length(); + while (size + videoLength < K3GigaBytes) + { + err = aComposer.WriteVideoFrame(videoBuf1, 100, keyFrame1, aDependencies); + if (err != KErrNone) + { + ERR_PRINTF2(_L("Fail to write video frame, err = %d"), err); + break; + } + iFile.Size(size); + } + + endTime.UniversalTime(); + TTimeIntervalMinutes composeTime; + endTime.MinutesFrom(startTime, composeTime); + INFO_PRINTF3(_L("Took %d minutes to compose a video file of size %d bytes"), composeTime.Int(), size); + + err = aComposer.Complete(); + if (err != KErrNone) + { + SetTestStepError(err); + } + + User::LeaveIfError(parser->Complete()); + CleanupStack::PopAndDestroy(3, &videoBuf1); + } + +// ----------------------------------------------------------------------------- +// C3GPLibComposeLargeFileDiskFull +// ----------------------------------------------------------------------------- +// +C3GPLibComposeLargeFileDiskFull::C3GPLibComposeLargeFileDiskFull() + { + } + +void C3GPLibComposeLargeFileDiskFull::doTestStepComposeWriteVideoAudioL(C3GPCompose& aComposer) + { + RBuf8 videoBuf1; + CleanupClosePushL(videoBuf1); + TBool keyFrame1; + TUint videoTimestampMS = 0; + TUint videoTS1; + TUint frameSize = 0; + T3GPFrameDependencies aDependencies; + + RFile fileName; + CleanupClosePushL(fileName); + User::LeaveIfError(fileName.Open(iFs, KLargeVideoFile(), EFileRead)); + + C3GPParse* parser = C3GPParse::NewL(); + CleanupStack::PushL(parser); + User::LeaveIfError(parser->Open(fileName)); + User::LeaveIfError(parser->GetVideoFrameSize(frameSize)); + User::LeaveIfError(videoBuf1.Create((TInt)frameSize)); + User::LeaveIfError(parser->ReadVideoFrame(videoBuf1, keyFrame1, videoTimestampMS, videoTS1)); + + TInt error = parser->GetVideoFrameDependencies(aDependencies); + if (error != KErrNone) + { + aDependencies.iDependsOn = E3GPDependencyUnknown; + aDependencies.iIsDependedOn = E3GPDependencyUnknown; + aDependencies.iHasRedundancy = E3GPRedundancyUnknown; + } + + TInt err = KErrNone; + TInt64 size = 0; + TTime startTime; + TTime endTime; + startTime.UniversalTime(); + + // create a 3GB video file + TInt videoLength = videoBuf1.Length(); + while (size + videoLength < K3GigaBytes) + { + err = aComposer.WriteVideoFrame(videoBuf1, 100, keyFrame1, aDependencies); + if (err != KErrNone) + { + ERR_PRINTF2(_L("Fail to write video frame, err = %d"), err); + break; + } + iFile64.Size(size); + } + + endTime.UniversalTime(); + TTimeIntervalMinutes composeTime; + endTime.MinutesFrom(startTime, composeTime); + INFO_PRINTF3(_L("Took %d minutes to compose a video file of size %d bytes"), composeTime.Int(), size); + + if (err != KErrNone) + { + SetTestStepError(err); + } + + User::LeaveIfError(parser->Complete()); + CleanupStack::PopAndDestroy(3, &videoBuf1); + + // ignore the error + aComposer.Complete(); + } + +// ----------------------------------------------------------------------------- +// C3GPLibComposeFileWithAvcProfileCheck +// ----------------------------------------------------------------------------- +// + +const TInt KAvcDecoderConfigRecordLength = 7; + +_LIT8(KAvcCTag, "avcC"); + +const TUint8 KAvcConfigVersion = 1; + +const TUint8 KAvcProfileByteBaseline = 66; +const TUint8 KAvcProfileByteExtended = 77; +const TUint8 KAvcProfileByteMain = 88; +const TUint8 KAvcProfileByteHigh = 100; + +C3GPLibComposeFileWithAvcProfileCheck::C3GPLibComposeFileWithAvcProfileCheck() + : iAvcDecoderConfigRecord( KAvcDecoderConfigRecordLength ) + { + } + +TVerdict C3GPLibComposeFileWithAvcProfileCheck::doTestStepL() + { + if (TestStepResult() != EPass) + { + return TestStepResult(); + } + + // this triggers: + // 1. Create a composer + // 2. Open the composer - C3GPLibComposeFileFormatCheck::doTestStepComposeOpenL + // 3. Write Video & Audio Data - C3GPLibComposeFileFormatCheck::doTestStepComposeWriteVideoAudioL + // 4. Write User Data - C3GPLibComposeFileFormatCheck::doTestStepComposeSetUserDataL + // 5. Complete the composer + TVerdict verdict = C3GPLibComposeFile::doTestStepL(); + if (verdict == EPass) + { + // once the file is composed, it can be verified if the file composed has the same + // AVC profile. + verdict = VerifyAvcProfileL(iFile); + } + else + { + INFO_PRINTF1(_L(" C3GPLibComposeFile::doTestStepL returns failed result")); + } + SetTestStepResult(verdict); + + if (!ShouldRunOOMTest()) + { + INFO_PRINTF2(_L("C3GPLibComposeFileWithAvcProfileCheck::doTestStepL returns %d"), TestStepResult()); + } + return TestStepResult(); + } + +/* + * The aDecoderSpecificInfo argument is used by 3GPlib to populate the + * avcC box. As this contains details of the AVC profile which is being + * checked by this test we cannot use KDummyData as the other tests do. + * + */ +T3GPVideoPropertiesBase* C3GPLibComposeFileWithAvcProfileCheck::SetupAvcVideoL() + { + // See ISO 14496-15, chapter 5.2.4.1.1 for details of these... + // config version (always 1) + iAvcDecoderConfigRecord[0] = KAvcConfigVersion; + // constraint flags + iAvcDecoderConfigRecord[2] = 0; // dummy data + // level + iAvcDecoderConfigRecord[3] = 0; // dummy data + // reserved (6bits) + lengthSizeMinusOne (2bits) + iAvcDecoderConfigRecord[4] = 0xFC; // 111111 00 + // reserved (3bits) + numOfSeqParamSets (5bits) + iAvcDecoderConfigRecord[5] = 0xE0; // 111 00000 + // numOfPicParamSets + iAvcDecoderConfigRecord[6] = 0; + + switch( iVideoType ) + { + case E3GPAvcProfileBaseline: + iAvcDecoderConfigRecord[1] = KAvcProfileByteBaseline; + break; + + case E3GPAvcProfileMain: + iAvcDecoderConfigRecord[1] = KAvcProfileByteMain; + break; + + case E3GPAvcProfileExtended: + iAvcDecoderConfigRecord[1] = KAvcProfileByteExtended; + break; + + case E3GPAvcProfileHigh: + iAvcDecoderConfigRecord[1] = KAvcProfileByteHigh; + break; + + default: + User::Leave(KErrUnknown); + } + T3GPVideoPropertiesBase* video = new (ELeave) T3GPVideoPropertiesAvc(1000, TSize(100, 100), iAvcDecoderConfigRecord ); + return video; + } + +TVerdict C3GPLibComposeFileWithAvcProfileCheck::VerifyAvcProfileL(const RFile& aFile) + { + // Seek to the beginning of the file + TInt pos = 0; + User::LeaveIfError(aFile.Seek(ESeekStart, pos)); + + TVerdict verdict = EFail; + TBuf8<4> atom; + TBuf8<1> byte; + TInt rewind = -1 * ( atom.MaxLength() - 1 ); + TInt tmp = rewind; + + while(ETrue) + { + // Search for the 'avcC' atom to check the profile that follows it. + + // Read in next 4 bytes + User::LeaveIfError(aFile.Read(atom)); + if (atom.Length() < atom.MaxLength()) + { + break; + } + + // Check if 'avcC' was found + if (Mem::Compare((&KAvcCTag)->Ptr(), (&KAvcCTag)->Length(), atom.Ptr(), atom.Length()) == 0) + { + // read next byte, and it should contain config version (always 1) + User::LeaveIfError(aFile.Read(byte)); + if( byte[0] != KAvcConfigVersion ) + { + ERR_PRINTF2(_L("avcC atom config type not as expected! (%d instead of 1)"), byte[0] ); + break; + } + + // read next byte, and it should contain profile indication + User::LeaveIfError(aFile.Read(byte)); + switch( iVideoType ) + { + case E3GPAvcProfileBaseline: + if( byte[0] == KAvcProfileByteBaseline ) + { + verdict = EPass; + } + else + { + ERR_PRINTF3(_L("avcC atom config type not as expected! (%d instead of %d)"), byte[0], KAvcProfileByteBaseline ); + } + break; + + + case E3GPAvcProfileMain: + if( byte[0] == KAvcProfileByteMain ) + { + verdict = EPass; + } + else + { + ERR_PRINTF3(_L("avcC atom config type not as expected! (%d instead of %d)"), byte[0], KAvcProfileByteMain ); + } + break; + + + case E3GPAvcProfileExtended: + if( byte[0] == KAvcProfileByteExtended ) + { + verdict = EPass; + } + else + { + ERR_PRINTF3(_L("avcC atom config type not as expected! (%d instead of %d)"), byte[0], KAvcProfileByteExtended ); + } + break; + + + case E3GPAvcProfileHigh: + if( byte[0] == KAvcProfileByteHigh ) + { + verdict = EPass; + } + else + { + ERR_PRINTF3(_L("avcC atom config type not as expected! (%d instead of %d)"), byte[0], KAvcProfileByteHigh ); + } + break; + + default: + ERR_PRINTF2(_L("avcC has unknown profile indication: %d"), byte[0] ); + } + + // 'avcC' was found, regardless of the result, finish reading the file + break; + } + else + { + // The 4 bytes read were not 'avcC'. + // Need to rewind by 3 bytes since we need to step through the file + // byte-by-byte... + tmp = rewind; // Avoid rewind value being changed by Seek() function + User::LeaveIfError( aFile.Seek( ESeekCurrent, tmp ) ); + } + } + + return verdict; + } +