sl@0: // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: #include "testrenderer.h" sl@0: #include "videoframebuffer.h" sl@0: #include "testgceharness.h" sl@0: sl@0: RTestRendererStep* RTestRendererStep::NewL(const TDesC& aStepName, TBool aTimed) sl@0: { sl@0: RTestRendererStep* self = new (ELeave) RTestRendererStep(aStepName, aTimed); sl@0: return self; sl@0: } sl@0: sl@0: RTestRendererStep::RTestRendererStep(const TDesC& aStepName, TBool aTimed) : sl@0: iVideoRenderer(NULL), sl@0: iTimed(aTimed) sl@0: { sl@0: iTestStepName = aStepName; sl@0: sl@0: // size for buffer created sl@0: iSize.iWidth = 1024; sl@0: iSize.iHeight = 768; sl@0: iVideoFormat.iDataFormat = ERgbRawData; sl@0: iVideoFormat.iRgbFormat = ERgb32bit888; sl@0: } sl@0: sl@0: void RTestRendererStep::MvroVideoBufferAvailable() sl@0: { sl@0: INFO_PRINTF1(_L("MvroVideoBufferAvailable() callback received")); sl@0: TRAPD(err, FsmL(EBufferAvailable)); sl@0: if (err != KErrNone) sl@0: { sl@0: ERR_PRINTF2(_L("FsmL(EBufferAvailable) failed with %d"), err); sl@0: EndTest(EFail); sl@0: } sl@0: } sl@0: sl@0: void RTestRendererStep::MvroBufferDisplayed(TInt aBufferId, const TTime& aTime) sl@0: { sl@0: INFO_PRINTF2(_L("MvroBufferDisplayed() callback received aBufferId=%d"), aBufferId); sl@0: iBufferId = aBufferId; sl@0: iDisplayedTime = aTime; sl@0: TRAPD(err, FsmL(EBufferDisplayed)); sl@0: if (err != KErrNone) sl@0: { sl@0: ERR_PRINTF2(_L("FsmL(EBufferDisplayed) failed with %d"), err); sl@0: EndTest(EFail); sl@0: } sl@0: } sl@0: sl@0: void RTestRendererStep::MvroBufferSkipped(TInt aBufferId) sl@0: { sl@0: INFO_PRINTF2(_L("MvroBufferSkipped() callback received aBufferId=%d"), aBufferId); sl@0: iBufferId = aBufferId; sl@0: TRAPD(err, FsmL(EBufferSkipped)); sl@0: if (err != KErrNone) sl@0: { sl@0: ERR_PRINTF2(_L("FsmL(EBufferSkipped) failed with %d"), err); sl@0: EndTest(EFail); sl@0: } sl@0: } sl@0: sl@0: TVerdict RTestRendererStep::DoTestStepPreambleL() sl@0: { sl@0: // Install the Active Scheduler sl@0: iActiveScheduler = new(ELeave) CActiveScheduler; sl@0: CActiveScheduler::Install(iActiveScheduler); sl@0: iActiveSchedulerStarted = EFalse; sl@0: sl@0: iBuffAvailCallback = 0; sl@0: iBuffDisplayCallback = 0; sl@0: iBuffSkipCallback = 0; sl@0: sl@0: // The following is required because of the panic tests. sl@0: // When a thread panics the global pointer is not reset to NULL sl@0: // and the following test fails because the pointer is hanging. sl@0: // When testframework creates a thread to run the test step it also sl@0: // defines a heap and the default process heap is not used. Therefore sl@0: // when the thread dies the heap is no longer available. sl@0: CTestGCEHarness::ResetGlobalPointer(); sl@0: sl@0: // Initialise Window server objects sl@0: InitWservL(); sl@0: sl@0: return EPass; sl@0: } sl@0: sl@0: TVerdict RTestRendererStep::DoTestStepPostambleL() sl@0: { sl@0: CActiveScheduler::Install(NULL); sl@0: delete iActiveScheduler; sl@0: iActiveScheduler = NULL; sl@0: sl@0: // Destroy Window server objects sl@0: DeInitWserv(); sl@0: sl@0: return EPass; sl@0: } sl@0: sl@0: void RTestRendererStep::InitWservL() sl@0: { sl@0: TInt err = iWs.Connect(); sl@0: if (err != KErrNone) sl@0: { sl@0: // Access violation if ws is null sl@0: ERR_PRINTF1(_L("Cannot test, no window server available")); sl@0: User::Leave(err); sl@0: } sl@0: sl@0: iScreen = new (ELeave) CWsScreenDevice(iWs); // make device for this session sl@0: User::LeaveIfError(iScreen->Construct()); // and complete its construction sl@0: sl@0: iRootWindow = RWindowGroup(iWs); sl@0: User::LeaveIfError(iRootWindow.Construct((TUint32)this, ETrue)); sl@0: sl@0: iWindow = new(ELeave) RWindow(iWs); sl@0: User::LeaveIfError(((RWindow*)iWindow)->Construct(iRootWindow,((TUint32)(this)) + 1)); sl@0: iWindow->SetExtent(TPoint(0,0), TSize(100,100)); sl@0: iWindow->SetVisible(ETrue); sl@0: iWindow->SetRequiredDisplayMode(EColor16MA); sl@0: iWindow->Activate(); sl@0: } sl@0: sl@0: void RTestRendererStep::DeInitWserv() sl@0: { sl@0: if (iWindow) sl@0: { sl@0: iWindow->Close(); sl@0: delete iWindow; sl@0: iWindow = NULL; sl@0: } sl@0: iRootWindow.Close(); sl@0: delete iScreen; sl@0: iScreen = NULL; sl@0: iWs.Flush(); sl@0: iWs.Close(); sl@0: } sl@0: sl@0: TInt RTestRendererStep::SetBackgroundSurface(TSurfaceId& id) sl@0: { sl@0: TInt err = iWindow->SetBackgroundSurface(id); sl@0: iWs.Finish(); sl@0: return err; sl@0: } sl@0: sl@0: void RTestRendererStep::RemoveBackgroundSurface() sl@0: { sl@0: iWindow->RemoveBackgroundSurface(ETrue); sl@0: } sl@0: sl@0: TVerdict RTestRendererStep::DoTestStepL() sl@0: { sl@0: __UHEAP_MARK; sl@0: sl@0: // Call the state handler from IDLE state sl@0: TRAPD(err, FsmL(EStartTest)); sl@0: if (err == KErrNone && iTestStepResult == EPass) sl@0: { sl@0: // Start the scheduler - Done only once ! sl@0: iActiveSchedulerStarted = ETrue; sl@0: CActiveScheduler::Start(); sl@0: } sl@0: else if (err != KErrNone) sl@0: { sl@0: ERR_PRINTF2(_L("FsmL(EStartTest) leave with %d"), err); sl@0: iTestStepResult = EFail; sl@0: } sl@0: sl@0: delete iVideoRenderer; sl@0: iVideoRenderer = NULL; sl@0: sl@0: // cleanup test harness sl@0: CTestGCEHarness::Remove(); sl@0: sl@0: __UHEAP_MARKEND; sl@0: sl@0: return iTestStepResult; sl@0: } sl@0: sl@0: void RTestRendererStep::FsmL(TTestRendererEvents aEventCode) sl@0: { sl@0: switch (aEventCode) sl@0: { sl@0: case EStartTest: sl@0: { sl@0: iFsmState = EStateCreate; sl@0: TInt numBuffers = 1; sl@0: sl@0: INFO_PRINTF2(_L("CVideoRenderer::NewL() Timed=%d"), iTimed); sl@0: CTestGCEHarness::NewL(numBuffers); sl@0: iVideoRenderer = CVideoRenderer::NewL(*this, iTimed); sl@0: sl@0: INFO_PRINTF1(_L("iVideoRenderer->GetSupportedFormatsL()")); sl@0: RArray expectedArray; sl@0: CleanupClosePushL(expectedArray); sl@0: TUncompressedVideoFormat format; sl@0: format.iDataFormat = ERgbRawData; sl@0: format.iRgbFormat = ERgb16bit444; sl@0: expectedArray.AppendL(format); // append EVideoRendererPixelFormatXRGB_4444 sl@0: format.iDataFormat = ERgbRawData; sl@0: format.iRgbFormat = ERgb16bit565; sl@0: expectedArray.AppendL(format); // append EVideoRendererPixelFormatRGB_565 sl@0: format.iDataFormat = ERgbRawData; sl@0: format.iRgbFormat = ERgb32bit888; sl@0: expectedArray.AppendL(format); // append EVideoRendererPixelFormatXRGB_8888: sl@0: sl@0: RArray array; sl@0: CleanupClosePushL(array); sl@0: iVideoRenderer->GetSupportedFormatsL(array); sl@0: TInt expectedCount = expectedArray.Count(); sl@0: TESTL(array.Count() == expectedCount); sl@0: for (TInt i = 0; i < expectedCount; i++) sl@0: { sl@0: TESTL(expectedArray[i] == array[i]); sl@0: } sl@0: sl@0: CleanupStack::PopAndDestroy(2, &expectedArray); sl@0: CreateSurfaceL(numBuffers); sl@0: sl@0: break; sl@0: } sl@0: case EBufferAvailable: sl@0: iBuffAvailCallback++; sl@0: if (iFsmState == EStateCreate && iBuffAvailCallback == 1) sl@0: { sl@0: iFsmState = EStateUpdate; sl@0: sl@0: // map surface to display sl@0: TInt err = SetBackgroundSurface(iSurfaceId); sl@0: if (err != KErrNone) sl@0: { sl@0: ERR_PRINTF2(_L("RWindow::SetBackgroundSurface() returned %d"), err); sl@0: EndTest(EFail); sl@0: break; sl@0: } sl@0: sl@0: TTime presentationTime; sl@0: presentationTime.UniversalTime(); sl@0: TTimeIntervalMicroSeconds microsec(500000); // use half a second delay sl@0: presentationTime += microsec; sl@0: GetNextBufferAndSubmitUpdateL(0, KRgbGreen, presentationTime); sl@0: } sl@0: else if (iFsmState == EStateUpdate && iBuffAvailCallback == 2) sl@0: { sl@0: iFsmState = EStateReleaseBuffer; sl@0: sl@0: // buffer is available again after update; sl@0: // try to get next buffer sl@0: TVideoFrameBuffer* buffer; sl@0: INFO_PRINTF1(_L("iVideoRenderer->NextBuffer() after update")); sl@0: buffer = iVideoRenderer->NextBuffer(); sl@0: TESTL(buffer != NULL); sl@0: INFO_PRINTF1(_L("iVideoRenderer->ReleaseBuffer()")); sl@0: iVideoRenderer->ReleaseBuffer(buffer); sl@0: } sl@0: else if (iFsmState == EStateReleaseBuffer) sl@0: { sl@0: if (iBuffDisplayCallback == 1) sl@0: { sl@0: // both release buffer callback and display callback are received, test complete with pass sl@0: EndTest(EPass); sl@0: } sl@0: // else continue waiting for more callback sl@0: } sl@0: else sl@0: { sl@0: ERR_PRINTF2(_L("State %d was not expected when handling buffer available event."), iFsmState); sl@0: EndTest(EFail); sl@0: } sl@0: sl@0: break; sl@0: case EBufferDisplayed: sl@0: iBuffDisplayCallback++; sl@0: if ((iFsmState != EStateUpdate && iFsmState != EStateReleaseBuffer) || sl@0: iBufferId != 0) sl@0: { sl@0: // not in a valid state sl@0: ERR_PRINTF2(_L("State %d was not expected when handing buffer displayed event."), iFsmState); sl@0: EndTest(EFail); sl@0: } sl@0: if (iFsmState == EStateReleaseBuffer && iBuffAvailCallback == 3) sl@0: { sl@0: // both release buffer callback and display callback are received, test complete with pass sl@0: EndTest(EPass); sl@0: } sl@0: // otherwise, haven't received release callback yet, continue waiting sl@0: break; sl@0: default: sl@0: // unexpected event sl@0: ERR_PRINTF2(_L("Unexpected event code %d in RTestRendererStep::FsmL"), aEventCode); sl@0: EndTest(EFail); sl@0: break; sl@0: } sl@0: } sl@0: sl@0: void RTestRendererStep::EndTest(TVerdict aVerdict) sl@0: { sl@0: iTestStepResult = aVerdict; sl@0: if (iActiveSchedulerStarted) sl@0: { sl@0: CActiveScheduler::Stop(); sl@0: } sl@0: } sl@0: sl@0: void RTestRendererStep::CreateRendererAndSurfaceL(TInt aNumBuffers) sl@0: { sl@0: INFO_PRINTF2(_L("CVideoRenderer::NewL() Timed=%d"), iTimed); sl@0: CTestGCEHarness::NewL(aNumBuffers); sl@0: iVideoRenderer = CVideoRenderer::NewL(*this, iTimed); sl@0: CreateSurfaceL(aNumBuffers); sl@0: } sl@0: sl@0: void RTestRendererStep::CreateSurfaceL(TInt aNumBuffers) sl@0: { sl@0: INFO_PRINTF1(_L("iVideoRenderer->CreateSurfaceL()")); sl@0: iVideoRenderer->CreateSurfaceL(iSize, aNumBuffers, iVideoFormat, iSurfaceId); sl@0: } sl@0: sl@0: void RTestRendererStep::GetNextBufferAndSubmitUpdateL(TInt aExpectedBufId, TRgb aColor, const TTime& aPresentationTime) sl@0: { sl@0: TVideoFrameBuffer* buffer = GetNextBufferL(aExpectedBufId, aColor); sl@0: INFO_PRINTF1(_L("iVideoRenderer->UpdateBuffer()")); sl@0: iVideoRenderer->UpdateBuffer(buffer, aPresentationTime); sl@0: } sl@0: sl@0: TVideoFrameBuffer* RTestRendererStep::GetNextBufferL(TInt aExpectedBufId, TRgb aColor) sl@0: { sl@0: INFO_PRINTF1(_L("iVideoRenderer->NextBuffer()")); sl@0: TVideoFrameBuffer* buffer; sl@0: buffer = iVideoRenderer->NextBuffer(); sl@0: TESTL(buffer != NULL); sl@0: TESTL(buffer->Format() == iVideoFormat); sl@0: TESTL(buffer->Stride() == iSize.iWidth * 4); // 4 bite per pixel for ERgb32bit888 sl@0: TESTL(buffer->BufferId() == aExpectedBufId); sl@0: TESTL(buffer->Buffer() != NULL); sl@0: sl@0: TInt bufSize = buffer->Stride() * iSize.iHeight; sl@0: Mem::Fill(buffer->Buffer(), bufSize, aColor.Internal()); sl@0: return buffer; sl@0: } sl@0: sl@0: RTestRendererReplaceStep* RTestRendererReplaceStep::NewL(const TDesC& aStepName, TBool aTimed) sl@0: { sl@0: RTestRendererReplaceStep* self = new (ELeave) RTestRendererReplaceStep(aStepName, aTimed); sl@0: return self; sl@0: } sl@0: sl@0: RTestRendererReplaceStep::RTestRendererReplaceStep(const TDesC& aStepName, TBool aTimed) : sl@0: RTestRendererStep(aStepName, aTimed) sl@0: { sl@0: } sl@0: sl@0: void RTestRendererReplaceStep::FsmL(TTestRendererEvents aEventCode) sl@0: { sl@0: switch (aEventCode) sl@0: { sl@0: case EStartTest: sl@0: iFsmState = EStateCreate; sl@0: CreateRendererAndSurfaceL(1); sl@0: break; sl@0: case EBufferAvailable: sl@0: iBuffAvailCallback++; sl@0: if (iFsmState == EStateCreate && iBuffAvailCallback == 1) sl@0: { sl@0: iFsmState = EStateUpdate; sl@0: sl@0: // received the first callback, map surface to display sl@0: TInt err = SetBackgroundSurface(iSurfaceId); sl@0: TESTL(err == KErrNone); sl@0: sl@0: // send the buffer sl@0: TTime presentationTime(0); sl@0: GetNextBufferAndSubmitUpdateL(0, KRgbGreen, presentationTime); sl@0: } sl@0: else if (iFsmState == EStateUpdate) sl@0: { sl@0: if (iBuffDisplayCallback == 1 && iBuffAvailCallback == 2) sl@0: { sl@0: iFsmState = EStateReplaceSurface; sl@0: ReplaceSurfaceL(); sl@0: } sl@0: } sl@0: else if (iFsmState == EStateReplaceSurface && iBuffAvailCallback == 1) sl@0: { sl@0: // received the first callback, map surface to display sl@0: TInt err = SetBackgroundSurface(iSurfaceId); sl@0: if (err != KErrNone) sl@0: { sl@0: ERR_PRINTF2(_L("RWindow::SetBackgroundSurface() returned %d"), err); sl@0: EndTest(EFail); sl@0: } sl@0: } sl@0: else if (iFsmState == EStateReplaceSurface && iBuffAvailCallback == 2) sl@0: { sl@0: iFsmState = EStateUpdateAfterReplace; sl@0: sl@0: // send the buffer sl@0: sl@0: TTime presentationTime1; sl@0: presentationTime1.UniversalTime(); sl@0: TTimeIntervalMicroSeconds delay(500); sl@0: TTime presentationTime2 = presentationTime1 + delay; sl@0: sl@0: GetNextBufferAndSubmitUpdateL(0, KRgbGreen, presentationTime1); sl@0: GetNextBufferAndSubmitUpdateL(1, KRgbGreen, presentationTime2); sl@0: } sl@0: else if (iFsmState == EStateUpdateAfterReplace) sl@0: { sl@0: if (iBuffDisplayCallback == 2 && iBuffAvailCallback == 3) sl@0: { sl@0: EndTest(EPass); sl@0: } sl@0: // else continue waiting for more callback sl@0: } sl@0: else sl@0: { sl@0: // unexpected state, fail test sl@0: ERR_PRINTF2(_L("State %d was not expected when handling buffer available event."), iFsmState); sl@0: EndTest(EFail); sl@0: } sl@0: sl@0: break; sl@0: case EBufferDisplayed: sl@0: iBuffDisplayCallback++; sl@0: if (iFsmState == EStateUpdate && iBuffDisplayCallback == 1 && iBufferId == 0) sl@0: { sl@0: // receive display callback sl@0: if (iBuffAvailCallback == 2) sl@0: { sl@0: iFsmState = EStateReplaceSurface; sl@0: ReplaceSurfaceL(); sl@0: } sl@0: } sl@0: else if (iFsmState == EStateUpdateAfterReplace && iBuffDisplayCallback == 1 && iBufferId == 0) sl@0: { sl@0: // receive display callback sl@0: } sl@0: else if (iFsmState == EStateUpdateAfterReplace && iBuffDisplayCallback == 2 && iBufferId == 1) sl@0: { sl@0: if (iBuffAvailCallback == 3) sl@0: { sl@0: EndTest(EPass); sl@0: } sl@0: // else haven't received all callback, continue waiting sl@0: } sl@0: else sl@0: { sl@0: // not in a valid state sl@0: ERR_PRINTF2(_L("State %d was not expected when handling buffer displayed event."), iFsmState); sl@0: EndTest(EFail); sl@0: } sl@0: break; sl@0: case EBufferSkipped: sl@0: ERR_PRINTF1(_L("Frame unexpectedly skipped")); sl@0: EndTest(EFail); sl@0: break; sl@0: } sl@0: } sl@0: sl@0: void RTestRendererReplaceStep::ReplaceSurfaceL() sl@0: { sl@0: // reset the number of callback sl@0: iBuffDisplayCallback = 0; sl@0: iBuffAvailCallback = 0; sl@0: sl@0: RemoveBackgroundSurface(); sl@0: sl@0: // received all expected callback for update sl@0: // destroy surface and create new one for testing replace surface sl@0: INFO_PRINTF1(_L("iVideoRenderer->DestroySurface()")); sl@0: iVideoRenderer->DestroySurface(iSurfaceId); sl@0: TInt buffers = 2; sl@0: CTestGCEHarness::ResetBuffersL(buffers); sl@0: CreateSurfaceL(buffers); sl@0: } sl@0: sl@0: /** sl@0: Standard static NewL() taking a callback function sl@0: */ sl@0: CCallBackTimer* CCallBackTimer::NewL(TCallBack aCallBack, TPriority aPriority) sl@0: { sl@0: CCallBackTimer* self = new(ELeave) CCallBackTimer(aCallBack, aPriority); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(); sl@0: CleanupStack::Pop(self); sl@0: return self; sl@0: } sl@0: sl@0: /** sl@0: Private c'tor sl@0: */ sl@0: CCallBackTimer::CCallBackTimer(TCallBack aCallBack, TPriority aPriority) : sl@0: CTimer(aPriority), iCallBack(aCallBack) sl@0: { sl@0: CActiveScheduler::Add(this); sl@0: } sl@0: sl@0: /* sl@0: Callback on timer complete sl@0: */ sl@0: void CCallBackTimer::RunL() sl@0: { sl@0: iCallBack.CallBack(); sl@0: }