--- /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 <e32base.h>
+#include <fbs.h>
+
+#include <ecam/camerasnapshot.h>
+
+#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<TInt>& 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<CFbsBitmap*>( 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<CCamBufferShare*>( 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 <<virtual>>
+// ---------------------------------------------------------------------------
+//
+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 <<virtual>>
+// ---------------------------------------------------------------------------
+//
+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>>
+// ---------------------------------------------------------------------------
+//
+// static
+TInt
+CCamSnapshot::SnapshotReadyCallback( TAny* aSelf )
+ {
+ PRINT( _L("Camera => CCamSnapshot::SnapshotReadyCallback <<static>>") );
+ CCamSnapshot* self( static_cast<CCamSnapshot*>( 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 <<static>>") );
+ 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