diff -r 61bc0f252b2b -r bac7acad7cb3 camerauis/cameraapp/generic/src/cameracontroller/camsnapshot.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/camerauis/cameraapp/generic/src/cameracontroller/camsnapshot.cpp Wed Sep 01 12:30:54 2010 +0100 @@ -0,0 +1,695 @@ +/* +* Copyright (c) 2007-2010 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: Implemantation of CCamSnapshot class. +* Temporary own implementation of MCameraSnapshot. +* To be replaced by ECam CCamera::CCameraSnapshot. +* +*/ + + +#include "camcameracontrollerflags.hrh" + +#include +#include + +#include + +#include "camlogging.h" +#include "mcamcameraobserver.h" +#include "camcameraevents.h" +#include "cambuffer.h" +#include "cambuffershare.h" +#include "camimagedecoder.h" +#include "cambitmapscaler.h" +#include "camsnapshot.h" + + + + + + +// =========================================================================== +// Local constants +static const TPoint KDefaultPosition = TPoint(0,0); +static const TRgb KDefaultBackgroudColor = KRgbWhite; +static const TUint32 KSupportedSnapshotFormats = + ( CCamera::EFormatFbsBitmapColor4K + | CCamera::EFormatFbsBitmapColor64K + | CCamera::EFormatFbsBitmapColor16M + | CCamera::EFormatFbsBitmapColor16MU + ); +static const TInt KCallbackPriority = CActive::EPriorityIdle; + +static const TUint KEventInterest = ( ECamCameraEventClassImage + | ECamCameraEventClassVideo + | ECamCameraEventClassVfData + ); + +// =========================================================================== +// Local methods + +#ifndef CAMERAAPP_CAPI_V2 + +// Not needed when new CAPI support ready. +TECAMEvent::TECAMEvent( TUid aEventType, + TInt aErrorCode ) + : iErrorCode( aErrorCode ) + { + iEventType.iUid = aEventType.iUid; + #pragma message("camsnapshot.cpp, temporarily define TECAMEvent constructor") + } +#endif + + +#include "campointerutility.inl" +using namespace NCamCameraController; + + +// =========================================================================== +// public constructors and destructor + +// --------------------------------------------------------------------------- +// static 2-phase constructor +// --------------------------------------------------------------------------- +// +CCamSnapshot* +CCamSnapshot::NewL( CCamera& aCamera, + MCameraObserver2& aObserver, + MCamCameraObservable& aObservable ) + { + CCamSnapshot* self = + new (ELeave) CCamSnapshot( aCamera, aObserver, aObservable ); + + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + + return self; + } + +// --------------------------------------------------------------------------- +// Destructor +// --------------------------------------------------------------------------- +// +CCamSnapshot::~CCamSnapshot() + { + PRINT( _L("Camera => ~CCamSnapshot") ); + iObservable.DetachObserver( this ); + + delete iSnapshotBitmap; + + // No need to Cancel(), destructors do it already. + delete iIdle; + delete iDecoder; + delete iScaler; + + SetImageData( NULL ); + + PRINT( _L("Camera <= ~CCamSnapshot") ); + } + +// =========================================================================== +// from MCameraSnapshot + +// --------------------------------------------------------------------------- +// SupportedFormats +// --------------------------------------------------------------------------- +// +TUint32 +CCamSnapshot::SupportedFormats() + { + return KSupportedSnapshotFormats; + } + + +// --------------------------------------------------------------------------- +// PrepareSnapshotL +// --------------------------------------------------------------------------- +// +void +CCamSnapshot::PrepareSnapshotL( CCamera::TFormat aFormat, + const TPoint& aPosition, + const TSize& aSize, + const TRgb& aBgColor, + TBool aMaintainAspectRatio ) + { + PRINT( _L("Camera => CCamSnapshot::PrepareSnapshotL") ); + + if( !(KSupportedSnapshotFormats & aFormat) ) + { + PRINT( _L("Camera <> Not supported format, LEAVE") ); + User::Leave( KErrNotSupported ); + } + else + { + PRINT( _L("Camera <> do prepare..") ); + iSnapshotOn = EFalse; + iStatus = KErrNotReady; + iDecoder->Cancel(); + iScaler->Cancel(); + iSnapshotBitmap->Reset(); + + PRINT( _L("Camera <> Init bitmap scaler..") ); + iScaler->InitScalingL( aSize, + Format2DisplayMode( iFormat ), + aMaintainAspectRatio ); + + PRINT1( _L("Camera <> Attach as controller observer, interest: %032b"), KEventInterest ); + iObservable.AttachObserverL( this, KEventInterest ); + + PRINT( _L("Camera <> Store parameters..") ); + iFormat = aFormat; + iPosition = aPosition; + iSize = aSize; + iBackgroundColor = aBgColor; + iMaintainAspectRatio = aMaintainAspectRatio; + } + + PRINT( _L("Camera <= CCamSnapshot::PrepareSnapshotL") ); + } + + +// --------------------------------------------------------------------------- +// PrepareSnapshotL +// --------------------------------------------------------------------------- +// +void +CCamSnapshot::PrepareSnapshotL( CCamera::TFormat aFormat, + const TSize& aSize, + TBool aMaintainAspectRatio ) + { + PrepareSnapshotL( aFormat, + KDefaultPosition, + aSize, + KDefaultBackgroudColor, + aMaintainAspectRatio ); + } + + +// --------------------------------------------------------------------------- +// SetBgColorL +// --------------------------------------------------------------------------- +// +void +CCamSnapshot::SetBgColorL( const TRgb& aBgColor ) + { + iBackgroundColor = aBgColor; + } + + +// --------------------------------------------------------------------------- +// SetPositionL +// --------------------------------------------------------------------------- +// +void +CCamSnapshot::SetPositionL( const TPoint& aPosition ) + { + iPosition = aPosition; + } + + +// --------------------------------------------------------------------------- +// IsSnapshotActive +// --------------------------------------------------------------------------- +// +TBool +CCamSnapshot::IsSnapshotActive() const + { + return iSnapshotOn; + } + +// --------------------------------------------------------------------------- +// StartSnapshot +// --------------------------------------------------------------------------- +// +void +CCamSnapshot::StartSnapshot() + { + iSnapshotOn = ETrue; + } + + +// --------------------------------------------------------------------------- +// StopSnapshot +// --------------------------------------------------------------------------- +// +void +CCamSnapshot::StopSnapshot() + { + iSnapshotOn = EFalse; + + iUseNextVfFrame = EFalse; + } + + +// --------------------------------------------------------------------------- +// SnapshotDataL +// --------------------------------------------------------------------------- +// +MCameraBuffer& +CCamSnapshot::SnapshotDataL( RArray& aFrameIndexOrder ) + { + PRINT( _L("Camera => CCamSnapshot::SnapshotDataL") ); + + // Leave if not ready or other error. + User::LeaveIfError( iStatus ); + + if( !iSnapshotOn || !iSnapshotBitmap ) + { + User::Leave( KErrNotReady ); + } + + // Set the frame order + aFrameIndexOrder.Reset(); + User::LeaveIfError( aFrameIndexOrder.Append( 0 ) ); + + // Client *must* call Release() for the buffer + CCamBuffer* buffer = CCamBuffer::NewL( *iSnapshotBitmap, NULL ); + + PRINT( _L("Camera <= CCamSnapshot::SnapshotDataL") ); + return *buffer; + } + + +// =========================================================================== +// From MCamCameraObserver + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void +CCamSnapshot::HandleCameraEventL( TInt aStatus, + TCamCameraEventId aEventId, + TAny* aEventData /*= NULL*/ ) + { + if( iSnapshotOn ) + { + switch( aEventId ) + { + // --------------------------------------------------- + // Viewfinder frame ready event + // + case ECamCameraEventVfFrameReady: + { + if( iUseNextVfFrame ) + { + iUseNextVfFrame = EFalse; + + // Take the viewfinder frame just as it would be + // a still image, just in bitmap format. + PRINT( _L("Camera <> CCamSnapshot: Storing VF frame as snapshot") ); + + + // TEMP ==> + CCamBufferShare* share = NULL; + TRAPD( error, + { + if( KErrNone == aStatus ) + { + CFbsBitmap* bitmap = new (ELeave) CFbsBitmap; + CleanupStack::PushL( bitmap ); + User::LeaveIfError( bitmap->Duplicate( static_cast( aEventData )->Handle() ) ); + + CCamBuffer* buffer = CCamBuffer::NewL( bitmap, NULL ); + CleanupStack::Pop( bitmap ); + + CleanupStack::PushL( buffer ); + share = new (ELeave) CCamBufferShare( buffer ); + CleanupStack::Pop( buffer ); + } + }); + if( KErrNone != error ) + { + aStatus = error; + } + if( share ) share->Reserve(); + // <== TEMP + + + StartSnapshotProcessing( share, aStatus ); + + // TEMP ==> + if( share ) share->Release(); + // <== TEMP + } + break; + } + // --------------------------------------------------- + // Image captured event + // + // Need to decode the snapshot from the image data. + case ECamCameraEventImageData: + { + if( !iVideoMode ) + { + PRINT( _L("Camera <> CCamSnapshot: Starting to decode snapshot") ); + CCamBufferShare* share = static_cast( aEventData ); + StartSnapshotProcessing( share, aStatus ); + } + break; + } + // --------------------------------------------------- + // Video init might come before snapshot is + // initialized, so we do not rely on this event + // case ECamCameraEventVideoInit: + // { + // PRINT( _L("Camera <> CCamSnapshot: Video mode entered") ); + // break; + // } + // --------------------------------------------------- + case ECamCameraEventVideoRelease: + { + PRINT( _L("Camera <> CCamSnapshot: Video mode left") ); + iVideoMode = EFalse; + break; + } + // --------------------------------------------------- + // Video started event + // + // Use next vf frame as snapshot. + case ECamCameraEventVideoStart: + { + PRINT( _L("Camera <> CCamSnapshot: Video started, will use next VF frame as snapshot") ); + SetImageData( NULL ); + if( KErrNone == aStatus ) + { + iVideoMode = ETrue; + iUseNextVfFrame = ETrue; + } + break; + } + // --------------------------------------------------- + // Video stopped. + // + // Provide the vf frame as snapshot. + case ECamCameraEventVideoStop: + { + if( iVideoMode ) + { + PRINT( _L("Camera <> CCamSnapshot: Video stopped, provide the VF frame snapshot..") ); + + // Cancel any activity, if not ready for some reason. + if( iIdle ) iIdle->Cancel(); + if( iScaler ) iScaler->Cancel(); + if( iDecoder ) iDecoder->Cancel(); + + // Snapshot is in iSnapshotBitmap + SetImageData( NULL ); + + // Need to clear this flag as no events are notified + // when this flag is on. + iVideoMode = EFalse; + + PRINT( _L("Camera <> CCamSnapshot: Start snapshot callback") ); + iIdle->Start( TCallBack( SnapshotReadyCallback, this ) ); + } + break; + } + // --------------------------------------------------- + default: + { + // Other events ignored + break; + } + // --------------------------------------------------- + } + } + } + + + + +// =========================================================================== +// from MCamImageDecoderObserver + +// --------------------------------------------------------------------------- +// ImageDecodedL <> +// --------------------------------------------------------------------------- +// +void +CCamSnapshot::ImageDecodedL( TInt aStatus, const CFbsBitmap* aBitmap, const CFbsBitmap* /*aMask*/ ) + { + PRINT1( _L("Camera => CCamSnapshot::ImageDecoded, status in: %d"), aStatus ); + if( iSnapshotOn ) + { + iStatus = aStatus; + + iSnapshotBitmap->Reset(); + + if( iStatus == KErrNone ) + { + iStatus = iSnapshotBitmap->Duplicate( aBitmap->Handle() ); + } + PRINT1( _L("Camera <> status after bitmap duplicate: %d"), iStatus ); + + // Release image data, as not used anymore. + // All that is needed is iSnapshotBitmap. + SetImageData( NULL ); + + if( iStatus == KErrNone ) + { + iScaler->StartScaling( *iSnapshotBitmap ); + } + else + { + iIdle->Start( TCallBack( SnapshotReadyCallback, this ) ); + } + } + PRINT( _L("Camera <= CCamSnapshot::ImageDecoded") ); + } + +// =========================================================================== +// from MCamBitmapScalerObserver + +// --------------------------------------------------------------------------- +// BitmapScaled <> +// --------------------------------------------------------------------------- +// +void +CCamSnapshot::BitmapScaled( TInt aStatus, const CFbsBitmap* aBitmap ) + { + // Release any data we hold, as it's not needed anymore. + SetImageData( NULL ); + + if( iSnapshotOn ) + { + iStatus = aStatus; + iSnapshotBitmap->Reset(); + + if( KErrNone == iStatus ) + { + iStatus = iSnapshotBitmap->Duplicate( aBitmap->Handle() ); + } + + TECAMEvent event( KUidECamEventCameraSnapshot, iStatus ); + iObserver.HandleEvent( event ); + } + } + + +// =========================================================================== +// public new methods + +// --------------------------------------------------------------------------- +// StartSnapshotProcessing +// --------------------------------------------------------------------------- +// +void +CCamSnapshot::StartSnapshotProcessing( CCamBufferShare* aBuffer, + TInt aError ) + { + PRINT1( _L("Camera => CCamSnapshot::StartSnapshotProcessing, status in:%d"), aError ); + + if( iSnapshotOn ) + { + TRAP( iStatus, DoStartSnapshotProcessingL( aBuffer, aError ) ); + + if( iStatus != KErrNone ) + { + iIdle->Start( TCallBack( SnapshotReadyCallback, this ) ); + } + } + + PRINT1( _L("Camera <= CCamSnapshot::StartSnapshotProcessing, status out:%d"), aError ); + } + + +// --------------------------------------------------------------------------- +// SnapshotReadyCallback <> +// --------------------------------------------------------------------------- +// +// static +TInt +CCamSnapshot::SnapshotReadyCallback( TAny* aSelf ) + { + PRINT( _L("Camera => CCamSnapshot::SnapshotReadyCallback <>") ); + CCamSnapshot* self( static_cast( aSelf ) ); + + if( !self->iVideoMode ) + { + TECAMEvent event( KUidECamEventCameraSnapshot, self->iStatus ); + self->iObserver.HandleEvent( event ); + } + else + { + // In video mode we must wait for the video stopped event + // even to report error. + PRINT( _L("Camera <> CCamSnapshot: Video mode, wait until video stopped.") ); + } + + PRINT( _L("Camera <= CCamSnapshot::SnapshotReadyCallback <>") ); + return EFalse; + } + + + +// =========================================================================== +// private methods + +// --------------------------------------------------------------------------- +// DoStartSnapshotProcessingL +// +// Helper method for StartSnapshotProcessing. +// --------------------------------------------------------------------------- +// +void +CCamSnapshot::DoStartSnapshotProcessingL( CCamBufferShare* aBuffer, + TInt aError ) + { + PRINT1( _L("Camera => CCamSnapshot::DoStartSnapshotProcessingL, status in:%d"), aError ); + + // Cancel all ongoing activity. + iDecoder->Cancel(); + iScaler->Cancel(); + SetImageData( NULL ); // Release any old. + + // Check that we have the data needed. + CheckNonNullL( aBuffer, KErrNotFound ); + CheckNonNullL( aBuffer->SharedBuffer(), KErrNotFound ); + User::LeaveIfError( aError ); + + + SetImageData( aBuffer ); + MCameraBuffer* buffer = iImageData->SharedBuffer(); + + // First try to use bitmap data if available + TRAP( aError, + { + CFbsBitmap& bitmap = buffer->BitmapL( 0 ); + PRINT( _L("Camera <> Using bitmap data, just scale..") ); + // Simulate that the bitmap has been decoded now. + ImageDecodedL( aError, &bitmap, NULL ); + }); + + // If problems with bitmap data, try encoded data. + if( KErrNone != aError ) + { + PRINT( _L("Camera <> Using encoded data, decode first") ); + // If not able to use bitmap (or there is none), + // start converting bitmap from encoded image data. + TRAP( aError, iDecoder->StartConversionL( iImageData ) ); + } + + + // Neither of the formats could be used. + // Release the image data. + if( KErrNone != aError ) + { + SetImageData( NULL ); + User::Leave( aError ); + } + PRINT( _L("Camera <= CCamSnapshot::DoStartSnapshotProcessingL") ); + } + + +// --------------------------------------------------------------------------- +// Format2DisplayMode +// --------------------------------------------------------------------------- +// +TDisplayMode +CCamSnapshot::Format2DisplayMode( CCamera::TFormat aFormat ) const + { + switch( aFormat ) + { + case CCamera::EFormatFbsBitmapColor4K: return EColor4K; + case CCamera::EFormatFbsBitmapColor64K: return EColor64K; + case CCamera::EFormatFbsBitmapColor16M: return EColor16M; + case CCamera::EFormatFbsBitmapColor16MU: return EColor16MU; + default: return EColor16MU; + } + } + + + +// --------------------------------------------------------------------------- +// SetImageData +// +// Release old shared buffer (if any exists) and store pointer to new one and +// reserve it (if any provided). Can be used to just release any existing +// share with NULL parameter. +// --------------------------------------------------------------------------- +// +void +CCamSnapshot::SetImageData( CCamBufferShare* aImageData ) + { + if( iImageData ) + { + iImageData->Release(); + } + + iImageData = aImageData; + + if( iImageData ) + { + iImageData->Reserve(); + } + } + + + +// =========================================================================== +// private constructors + +// --------------------------------------------------------------------------- +// 2nd phase constructor +// --------------------------------------------------------------------------- +// +void +CCamSnapshot::ConstructL() + { + iSnapshotBitmap = new (ELeave) CFbsBitmap; + + iDecoder = CCamImageDecoder::NewL( *this ); + iScaler = CCamBitmapScaler::NewL( *this ); + + iIdle = CIdle::NewL( KCallbackPriority ); + } + +// --------------------------------------------------------------------------- +// 1st phase constructor +// --------------------------------------------------------------------------- +// +CCamSnapshot::CCamSnapshot( CCamera& aCamera, + MCameraObserver2& aObserver, + MCamCameraObservable& aObservable ) + : iObserver( aObserver ), + iObservable( aObservable ), + iCameraHandle( aCamera.Handle() ), + iSnapshotOn( EFalse ), + iStatus( KErrNotReady ) + { + } + +// end of file