diff -r e5618cc85d74 -r 6c158198356e javauis/mmapi_akn/baseline/src.dsa/cmmacameraplayer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javauis/mmapi_akn/baseline/src.dsa/cmmacameraplayer.cpp Thu Aug 19 09:48:13 2010 +0300 @@ -0,0 +1,672 @@ +/* +* Copyright (c) 2002-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: This class is used for playing camera. +* +*/ + + +// INCLUDE FILES +#include +#include +#include +#include "cmmacameraplayer.h" +#include "tmmaparametervalidator.h" +#include "mmmadisplay.h" +#include "cmmacamerasound.h" + +#if defined( __WINS__ ) +#include +#endif + +// CONSTANTS +_LIT8(KImageJpegMime, "image/jpeg"); +_LIT8(KJpegMime, "jpeg"); +_LIT(KVideoControlName, "VideoControl"); + +CMMACameraPlayer* CMMACameraPlayer::NewLC(TInt aCameraIndex) +{ + CMMACameraPlayer* self = new(ELeave) CMMACameraPlayer; + CleanupStack::PushL(self); + self->ConstructL(aCameraIndex); + return self; +} + +CMMACameraPlayer::~CMMACameraPlayer() +{ + DEBUG("CMMACameraPlayer::~CMMACameraPlayer"); + + // Free (duplicated) UI camera resources first. + // Window is not able to send any + // callback requests to UI from now. + if (iWindow) + { + iWindow->SetDisplay(NULL); + } + + if (iCamera) + { + iCamera->CancelCaptureImage(); + iCamera->Release(); + delete iCamera; + } + + delete iSnapshotEncoded; + delete iSnapshotBitmap; + delete iRealizeWait; + + if (iDisplay && iDisplay->HasContainer()) + { + // Window will delete itself + // after all pending events are processed + // (lazy delete) + iDisplay->UIGetCallback( + *iWindow, CMMACameraWindow::EDestroyWindow); + } + else + { + delete iWindow; + } + iWindow = NULL; +} + + +CMMACameraPlayer::CMMACameraPlayer(): + iDisplay(NULL), + iSourceSizeIndex(KErrNotFound), + iStartTime(KErrNotFound) +{ + iStopViewFinder = ETrue; +} + + +void CMMACameraPlayer::ConstructL(TInt aCameraIndex) +{ + CMMAPlayer::ConstructL(); + + if (aCameraIndex >= CCamera::CamerasAvailable()) + { + // image capture is not supported + User::Leave(KErrNotFound); + } + + iCamera = CCamera::NewL(*this, aCameraIndex); + + iWindow = CMMACameraWindow::NewL(iCamera->Handle()); + + TCameraInfo cameraInfo; + iCamera->CameraInfo(cameraInfo); + + if (cameraInfo.iNumImageSizesSupported < 1) + { + // image capture is not supported + User::Leave(KErrNotFound); + } + + // default snapshot size + iSourceSizeIndex = cameraInfo.iNumImageSizesSupported - 1; + + iRealizeWait = new(ELeave)CRealizeWait; +} + +TInt64 CMMACameraPlayer::CurrentTime() +{ + TTime time; + time.HomeTime(); + return time.Int64(); +} + +void CMMACameraPlayer::ResolveViewFinderSizeL(TSize& aSize) +{ + DEBUG("CMMACameraPlayer::ResolveViewFinderSizeL"); + + TSize resultSize; + + // The only way to find out the size is to start the view finder + // with a proper size (screen size). + + ResolveScreenSizeL(resultSize); + + // StartViewFinderBitmapsL changes resultSize to + // the used view finder size. + // Used to get the source size only. + iCamera->StartViewFinderBitmapsL(resultSize); + + // Bitmap viewfinder is not used anymore. + iCamera->StopViewFinder(); + + aSize = resultSize; +} + +void CMMACameraPlayer::ResolveScreenSizeL(TSize& aSize) +{ + DEBUG("CMMACameraPlayer::ResolveScreenSizeL"); + +#if defined( __WINS__ ) + TSize size(0,0); + RWsSession ws; + + if (ws.Connect() == KErrNone) + { + CleanupClosePushL(ws); + + CWsScreenDevice* wsScreenDevice = new(ELeave)CWsScreenDevice(ws); + CleanupStack::PushL(wsScreenDevice); + + User::LeaveIfError(wsScreenDevice->Construct()); + + size = wsScreenDevice->SizeInPixels(); + + CleanupStack::PopAndDestroy(2); // wsScreenDevice, ws.Close() + } + + aSize = size; + +#else + TScreenInfoV01 info; + TPckgBuf< TScreenInfoV01 > buf(info); + + UserSvr::ScreenInfo(buf); + info = buf(); + + aSize = info.iScreenSize; +#endif +} + +void CMMACameraPlayer::ResolveCaptureSizes(const CCamera::TFormat aFormat, + const TInt aNumImageSizesSupported, + const TSize& aRequestSize, + TSize& aSourceSize, + TInt& aSourceIndex, + TInt& aLargestIndex) +{ + // Largest image size + TSize largestSize; + // Index to largest image size + TInt largestSizeIndex = 0; + // Source size + TSize sourceSize; + // Default source size index not set + TInt sourceSizeIndex = KErrNotFound; + // Temporary size for iterating capture sizes + TSize tmpSize; + + DEBUG_INT("MMA::CMMACameraPlayer::ResolveCaptureSizes: aFormat = 0x%x", aFormat); + + // go through all supported sizes. + // Notice: Capture sizes are assumed to be in order from smaller to larger sizes + for (TInt i = 0; i < aNumImageSizesSupported; i++) + { + iCamera->EnumerateCaptureSizes(tmpSize, + i, + aFormat); + + DEBUG_INT("MMA::CMMACameraPlayer::ResolveCaptureSizes: tmpSize.iWidth = %d", tmpSize.iWidth); + DEBUG_INT("MMA::CMMACameraPlayer::ResolveCaptureSizes: tmpSize.iHeight = %d", tmpSize.iHeight); + + // Check if current is the largest + if ((largestSize.iWidth < tmpSize.iWidth) && + (largestSize.iHeight < tmpSize.iHeight)) + { + largestSize = tmpSize; + largestSizeIndex = i; + } + + // If wanted size is smaller than tmpSize we can use it + if ((aRequestSize.iWidth <= tmpSize.iWidth) && + (aRequestSize.iHeight <= tmpSize.iHeight)) + { + sourceSize = tmpSize; + sourceSizeIndex = i; + } + } + + DEBUG_INT("MMA::CMMACameraPlayer::ResolveCaptureSizes: sourceSizeIndex = %d", sourceSizeIndex); + DEBUG_INT("MMA::CMMACameraPlayer::ResolveCaptureSizes: largestSizeIndex = %d", largestSizeIndex); + + aSourceSize = sourceSize; + aSourceIndex = sourceSizeIndex; + aLargestIndex = largestSizeIndex; +} + +void CMMACameraPlayer::StartL(TBool aPostEvent) +{ + DEBUG_INT("CMMACameraPlayer:StartL iState %d", iState); + + // start can't be called to not ready player + if (iState == EPrefetched) + { + // camera passes ready images through + // ViewFinderFrameReady method + + // set time when started + iStartTime = CurrentTime(); + + // inform java side + ChangeState(EStarted); + + TInt64 time; + GetMediaTime(&time); + + // Notify the camera window + // about the status change + iWindow->SetStarted(ETrue); + + if (aPostEvent) + { + // inform java side + PostLongEvent(CMMAPlayerEvent::EStarted, time); + } + } + PostActionCompleted(KErrNone); // java start return +} + +void CMMACameraPlayer::StopL(TBool aPostEvent) +{ + DEBUG_INT("CMMACameraPlayer::StopL", iState); + if (iState == EStarted) + { + TInt64 time; + GetMediaTime(&time); // add played time to media time + + if (iStopViewFinder && iWindow->ViewFinderActive()) + { + iWindow->SetStarted(EFalse); + } + iStartTime = KErrNotFound; + + if (aPostEvent) + { + PostLongEvent(CMMAPlayerEvent::EStopped, time); + } + + // go back to prefetched state + ChangeState(EPrefetched); + } +} + +void CMMACameraPlayer::DeallocateL() +{ + // If player is started when deallocate is called, + // player is stopped from java side -> state is changed to + // prefetched. + // In prefetched state only reserved resource is + // camera reserve( released with iCamera->Release() ) + // In realized state no resources have been reserved. + // CHANGED: not releasing camera anymore, since it is already + // done in realized state + if (iState == EPrefetched) + { + ChangeState(ERealized); + } +} + + +void CMMACameraPlayer::RealizeL() +{ + iCamera->Reserve(); + // this lock will be released when power on is completed (or error) + if (!iRealizeWait->IsStarted()) + { + iRealizeWait->Start(); + } + User::LeaveIfError(iRealizeWait->iError); + CMMAPlayer::RealizeL(); +} + + +void CMMACameraPlayer::PrefetchL() +{ + DEBUG("MMA::CMMACameraPlayer::PrefetchL"); + // nothing to do here + ChangeState(EPrefetched); + PostActionCompleted(KErrNone); +} + + +void CMMACameraPlayer::GetDuration(TInt64* aDuration) +{ + // camera viewer has no duration. + *aDuration = KTimeUnknown; +} + + +void CMMACameraPlayer::SetMediaTimeL(TInt64* /*aTime*/) +{ + DEBUG("MMA::CMMACameraPlayer::SetMediaTimeL "); + // with camera media time is not supported. +} + + +void CMMACameraPlayer::GetMediaTime(TInt64* aMediaTime) +{ + if (iState == EStarted) + { + // add play time to media time + iMediaTime += CurrentTime() - iStartTime; + // set new start time + iStartTime = CurrentTime(); + } + + // set value to parameter + (*aMediaTime) = iMediaTime; +} + +void CMMACameraPlayer::CloseL() +{ + DEBUG("MMA::CMMACameraPlayer::CloseL()"); + + // cancel all activity + iCamera->CancelCaptureImage(); + + // Stop and release UI Camera instance + iWindow->SetDisplay(NULL); + + // we don't need reserve camera anymore + iCamera->Release(); + + CMMAPlayer::CloseL(); +} + +const TDesC& CMMACameraPlayer::Type() +{ + return KMMACameraPlayer; +} + +// MCameraObserver +void CMMACameraPlayer::ReserveComplete(TInt aError) +{ + DEBUG_INT("MMA::CMMACameraPlayer::ReserveComplete %d", aError); + if (aError == KErrNone) + { + // camera will notify completion with PowerOnComplete method. + iCamera->PowerOn(); + } + else + { + // release lock and store error. State doesn't change. + iRealizeWait->iError = aError; + iRealizeWait->AsyncStop(); + } + +} + +void CMMACameraPlayer::PowerOnComplete(TInt aError) +{ + DEBUG_INT("MMA::CMMACameraPlayer::PowerOnComplete %d", aError); + + TSize viewFinderSize; + TInt error = aError; + + if (error == KErrNone) + { + // The view finder size must be known after prefetching. + TRAP(error, ResolveViewFinderSizeL(viewFinderSize)); + } + + if (error == KErrNone) + { + iSize = viewFinderSize; + + if (iDisplay) + { + iDisplay->SourceSizeChanged(iSize); + NotifyWithStringEvent(CMMAPlayerEvent::ESizeChanged, KVideoControlName); + } + } + + iRealizeWait->iError = error; + iRealizeWait->AsyncStop(); +} + +void CMMACameraPlayer::ViewFinderFrameReady(CFbsBitmap& /*aFrame*/) +{ + // Empty implementation of an interface method. + // DirectViewFinder is used + // instead of BitmapViewFinder +} + +void CMMACameraPlayer::ImageReady(CFbsBitmap* aBitmap, + HBufC8* aData, + TInt aError) +{ + DEBUG_INT("MMA::CMMACameraPlayer::ImageReady %d", aError); + + // This method should never be called, + // unless we are taking snapshot + __ASSERT_DEBUG(iSnapshotStatus, User::Invariant()); + + __ASSERT_DEBUG(!iSnapshotBitmap, User::Invariant()); + __ASSERT_DEBUG(!iSnapshotEncoded, User::Invariant()); + + if (aError == KErrNone) + { + // this class has ownership of the bitmap until + // snapshot bitmap is got from this class. + iSnapshotBitmap = aBitmap; + iSnapshotEncoded = aData; + } + + // notify the caller, error code or KErrNone + User::RequestComplete(iSnapshotStatus, aError); + iWindow->SetStarted(ETrue); + // Status is not needed anymore + // and this class don't own the status. + iSnapshotStatus = NULL; +} + +void CMMACameraPlayer::FrameBufferReady(MFrameBuffer* /*aFrameBuffer*/, + TInt /*aError*/) +{ + DEBUG("MMA::CMMACameraPlayer::FrameBufferReady"); + // this callback will never be called + // Asserted in debug build to be sure. + __ASSERT_DEBUG(EFalse, User::Invariant()); +} + +void CMMACameraPlayer::SetDisplayL(MMMADisplay* aDisplay) +{ + DEBUG("MMA::CMMACameraPlayer::SetDisplay"); + + // now it is ready to draw + iDisplay = aDisplay; + + // Passes display into iWindow. + // Allocates all resources needed to use a camera DirectViewFinder. + iWindow->SetDisplay(aDisplay); + + iDisplay->SetWindowL(iWindow); + + // Set view finder size to the display only if the view finder + // size has been resolved. + if (iSize != TSize(0, 0)) + { + iDisplay->SourceSizeChanged(iSize); + NotifyWithStringEvent(CMMAPlayerEvent::ESizeChanged, KVideoControlName); + } +} + +TSize CMMACameraPlayer::SourceSize() +{ + return iSize; +} + +MMMASnapshot::TEncoding CMMACameraPlayer::TakeSnapshotL(TRequestStatus* aStatus, + const TSize& aSize, + const CMMAImageSettings& aSettings) +{ + __ASSERT_DEBUG(!iSnapshotStatus, User::Invariant()); + __ASSERT_DEBUG(!iSnapshotBitmap, User::Invariant()); + __ASSERT_DEBUG(!iSnapshotEncoded, User::Invariant()); + + // snapshots can not be taken if player is not realized + if (iState < ERealized) + { + User::Leave(KErrNotReady); + } + // save status which will be notified + iSnapshotStatus = aStatus; + + // changing status to pending + *iSnapshotStatus = KRequestPending; + + // Source size not set in the beginning + TSize sourceSize; + + // Use default if size is not specified. + TInt sourceSizeIndex = iSourceSizeIndex; + + // Largest image size index + TInt largestSizeIndex = 0; + + // Get camera characteristics + TCameraInfo cameraInfo; + iCamera->CameraInfo(cameraInfo); + + // Set default snapshot encoding type + TEncoding encoding = EBitmap; + + // Set default image capture format + CCamera::TFormat format = CCamera::EFormatFbsBitmapColor16M; + + DEBUG_INT("MMA::CMMACameraPlayer::TakeSnapshotL: cameraInfo.iImageFormatsSupported = 0x%x", cameraInfo.iImageFormatsSupported); + DEBUG_INT("MMA::CMMACameraPlayer::TakeSnapshotL: cameraInfo.iNumImageSizesSupported = %d", cameraInfo.iNumImageSizesSupported); + + // Check if size was set in Java + if (aSize.iWidth != KErrNotFound && + aSize.iHeight != KErrNotFound) + { + // Determine if jpeg capture was requested + if ((*aSettings.iMimeType == KJpegMime) || + (*aSettings.iMimeType == KImageJpegMime)) + { + // Shortcut for supported image formats + TUint32 imageFormats = cameraInfo.iImageFormatsSupported; + + // Jpeg subtype constants + _LIT8(KJpegJfif, "jfif"); + _LIT8(KJpegExif, "exif"); + + // Resolve requested jpeg subtype from settings and camerainfo + if ((imageFormats & CCamera::EFormatJpeg) && + (*aSettings.iType == KJpegJfif)) + { + // JFIF JPEG + format = CCamera::EFormatJpeg; + encoding = EEncoded; + } + else if ((imageFormats & CCamera::EFormatExif) && + (*aSettings.iType == KJpegExif)) + { + // EXIF JPEG + format = CCamera::EFormatExif; + encoding = EEncoded; + } + } + + // Try to resolve nearest source size to the one requested, + // except for the JFIF and EXIF jpeg subtypes the match has + // to be exact otherwise non-encode capture format will be + // used + ResolveCaptureSizes(format, + cameraInfo.iNumImageSizesSupported, + aSize, + sourceSize, + sourceSizeIndex, + largestSizeIndex); + + // Format was either of the jpeg formats and requested size + // didn't match the source size + if ((format >= CCamera::EFormatJpeg && + format <= CCamera::EFormatExif) && + (aSize != sourceSize)) + { + // Try again with an non-encoded format + format = CCamera::EFormatFbsBitmapColor16M; + encoding = EBitmap; + ResolveCaptureSizes(format, + cameraInfo.iNumImageSizesSupported, + aSize, + sourceSize, + sourceSizeIndex, + largestSizeIndex); + } + + if (sourceSizeIndex == KErrNotFound) + { + // If correct index was not found use the largest. + sourceSizeIndex = largestSizeIndex; + } + } + // else use default iSourceSizeIndex and default image capture format + + iCamera->PrepareImageCaptureL(format, + sourceSizeIndex); + + // play sound when capturing image + CMMACameraSound::PlayImageCaptureSoundL(); + + // start capture, ImageReady will be called when ready + iWindow->SetStarted(EFalse); + + iCamera->CaptureImage(); + + DEBUG_INT("MMA::CMMACameraPlayer::TakeSnapshotL: format = 0x%x", format); + DEBUG_INT("MMA::CMMACameraPlayer::TakeSnapshotL: sourceSizeIndex = %d", sourceSizeIndex); + DEBUG_INT("MMA::CMMACameraPlayer::TakeSnapshotL: encoding = %d", encoding); + + // Inform caller which snapshot encoding was ultimately used + return encoding; +} + +CFbsBitmap* CMMACameraPlayer::SnapshotBitmap() +{ + CFbsBitmap* bitmap = iSnapshotBitmap; + + // ownership transfers to the caller + iSnapshotBitmap = NULL; + return bitmap; +} + +HBufC8* CMMACameraPlayer::SnapshotEncoded() +{ + HBufC8* encoded = iSnapshotEncoded; + + // ownership transfers to the caller + iSnapshotEncoded = NULL; + return encoded; +} + +void CMMACameraPlayer::NotifyWithStringEvent( + CMMAPlayerEvent::TEventType aEventType, + const TDesC& aStringEventData) +{ + PostStringEvent(aEventType, aStringEventData); +} + +MMMASnapshot* CMMACameraPlayer::SnapshoterL() +{ + return this; +} + +TInt CMMACameraPlayer::CameraHandle() +{ + return iCamera->Handle(); +} + +void CMMACameraPlayer::SetViewFinderMode(TBool aStopViewFinder) +{ + iStopViewFinder = aStopViewFinder; +} + +// END OF FILE