diff -r 3075d9b614e6 -r 0e652f8f1fbd camerauis/cameraxui/cxengine/src/cxestillcapturecontrolsymbian.cpp --- a/camerauis/cameraxui/cxengine/src/cxestillcapturecontrolsymbian.cpp Thu May 13 21:30:19 2010 +0300 +++ b/camerauis/cameraxui/cxengine/src/cxestillcapturecontrolsymbian.cpp Thu Jul 15 01:55:05 2010 +0300 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +* Copyright (c) 2009-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" @@ -18,11 +18,9 @@ #include #include -#include #include #include #include -#include #include #include "cxestillcapturecontrolsymbian.h" @@ -34,8 +32,8 @@ #include "cxecameradevice.h" #include "cxesoundplayersymbian.h" #include "cxestillimagesymbian.h" -#include "cxeviewfindercontrol.h" #include "cxeviewfindercontrolsymbian.h" +#include "cxesnapshotcontrol.h" #include "cxesettingsmappersymbian.h" #include "cxestate.h" #include "cxesettings.h" @@ -53,16 +51,18 @@ // constants -const int KMaintainAspectRatio = false; -const TInt64 KMinRequiredSpaceImage = 2000000; +namespace +{ + const TInt64 KMinRequiredSpaceImage = 2000000; +} - -/** +/*! * Constructor. */ CxeStillCaptureControlSymbian::CxeStillCaptureControlSymbian( CxeCameraDevice &cameraDevice, CxeViewfinderControl &viewfinderControl, + CxeSnapshotControl &snapshotControl, CxeCameraDeviceControl &cameraDeviceControl, CxeFilenameGenerator &nameGenerator, CxeSensorEventHandler &sensorEventHandler, @@ -74,6 +74,7 @@ : CxeStateMachine("CxeStillCaptureControlSymbian"), mCameraDevice(cameraDevice), mViewfinderControl(viewfinderControl), + mSnapshotControl(snapshotControl), mCameraDeviceControl(cameraDeviceControl), mFilenameGenerator(nameGenerator), mSensorEventHandler(sensorEventHandler), @@ -116,21 +117,21 @@ // Connect ECam image buffer ready event connect(&mCameraDeviceControl, SIGNAL(imageBufferReady(MCameraBuffer*,int)), this, SLOT(handleImageData(MCameraBuffer*,int))); - // Connect signals for ECam events - connect(&mCameraDeviceControl, SIGNAL(cameraEvent(int,int)), - this, SLOT(handleCameraEvent(int,int))); + // connect snapshot ready signal + connect(&mSnapshotControl, SIGNAL(snapshotReady(CxeError::Id, const QImage&)), + this, SLOT(handleSnapshotReady(CxeError::Id, const QImage&))); OstTrace0(camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_CREATE_MID2, "msg: e_CX_ENGINE_CONNECT_SIGNALS 0"); mImageDataQueue = new CxeImageDataQueueSymbian(); - mAutoFocusSoundPlayer = new CxeSoundPlayerSymbian(CxeSoundPlayerSymbian::AutoFocus); - mCaptureSoundPlayer = new CxeSoundPlayerSymbian(CxeSoundPlayerSymbian::StillCapture); + mAutoFocusSoundPlayer = new CxeSoundPlayerSymbian(CxeSoundPlayerSymbian::AutoFocus, mSettings); + mCaptureSoundPlayer = new CxeSoundPlayerSymbian(CxeSoundPlayerSymbian::StillCapture, mSettings); OstTrace0(camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_CREATE_OUT, "msg: e_CX_STILLCAPTURECONTROL_NEW 0"); CX_DEBUG_EXIT_FUNCTION(); } -/** +/*! * Destructor. */ CxeStillCaptureControlSymbian::~CxeStillCaptureControlSymbian() @@ -148,7 +149,7 @@ CX_DEBUG_EXIT_FUNCTION(); } -/** +/*! * Return the current state. */ CxeStillCaptureControl::State CxeStillCaptureControlSymbian::state() const @@ -156,7 +157,7 @@ return static_cast( stateId() ); } -/** +/*! * Handle state changed event. Normally just emits the signal * for observers to react appropriately. */ @@ -165,7 +166,7 @@ emit stateChanged( static_cast( newStateId ), error ); } -/** +/*! * Initialize the control states. */ void CxeStillCaptureControlSymbian::initializeStates() @@ -178,7 +179,7 @@ setInitialState(Uninitialized); } -/** +/*! * Initialize the still image capture control. */ void CxeStillCaptureControlSymbian::init() @@ -196,7 +197,7 @@ CX_DEBUG_EXIT_FUNCTION(); } -/** +/*! * Un-initialize the image mode. */ void CxeStillCaptureControlSymbian::deinit() @@ -208,7 +209,7 @@ return; } - OstTrace0( camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_DEINIT_IN, "msg: e_CX_STILL_CAPCONT_DEINIT 1" ); + OstTrace0( camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_DEINIT_IN, "msg: e_CX_STILLCAPCONT_DEINIT 1" ); // Stop monitoring disk space. mDiskMonitor.stop(); @@ -217,24 +218,23 @@ //stop viewfinder mViewfinderControl.stop(); + if (state() == Capturing) { + mCameraDevice.camera()->CancelCaptureImage(); + } + // disable sensor event handler. mSensorEventHandler.deinit(); - if (mCameraDevice.cameraSnapshot()) { - mCameraDevice.cameraSnapshot()->StopSnapshot(); - } + mSnapshotControl.stop(); - if (state() == Capturing) { - mCameraDevice.camera()->CancelCaptureImage(); - } setState(Uninitialized); - OstTrace0( camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_DEINIT_OUT, "msg: e_CX_STILL_CAPCONT_DEINIT 0" ); + OstTrace0( camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_DEINIT_OUT, "msg: e_CX_STILLCAPCONT_DEINIT 0" ); CX_DEBUG_EXIT_FUNCTION(); } -/**! +/*! * Prepare still capture mode. */ void CxeStillCaptureControlSymbian::prepare() @@ -246,7 +246,7 @@ return; } - OstTrace0( camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_PREPARE_IN, "msg: e_CX_STILLCAPCONT_PREPARE 1" ); + OstTrace0(camerax_performance, CXESTILLCAPTURECONTROL_PREPARE_IN, "msg: e_CX_STILLCAPCONT_PREPARE 1"); int err = KErrNone; CxeError::Id cxErr = getImageQualityDetails(mCurrentImageDetails); @@ -271,9 +271,9 @@ // Prepare Image capture CCamera::TFormat imgFormat = supportedStillFormat(mCameraDeviceControl.cameraIndex()); - OstTrace0(camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_PREPARE_MID1, "msg: e_CX_PREPARE_IMAGE_CAPTURE 1"); + OstTrace0(camerax_performance, CXESTILLCAPTURECONTROL_PREPARE_MID1, "msg: e_CX_PREPARE_IMAGE_CAPTURE 1"); TRAP(err, mCameraDevice.camera()->PrepareImageCaptureL(imgFormat, ecamStillResolutionIndex)); - OstTrace0(camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_PREPARE_MID2, "msg: e_CX_PREPARE_IMAGE_CAPTURE 0"); + OstTrace0(camerax_performance, CXESTILLCAPTURECONTROL_PREPARE_MID2, "msg: e_CX_PREPARE_IMAGE_CAPTURE 0"); CX_DEBUG(("PrepareImageCaptureL done, err=%d, resolution index = %d", err, ecamStillResolutionIndex)); @@ -318,63 +318,47 @@ // Inform interested parties that image mode has been prepared for capture emit imagePrepareComplete(CxeErrorHandlingSymbian::map(err)); - OstTrace0( camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_PREPARE_OUT, "msg: e_CX_STILLCAPCONT_PREPARE 0" ); + OstTrace0(camerax_performance, CXESTILLCAPTURECONTROL_GOTOSTILL, "msg: e_CX_GO_TO_STILL_MODE 0"); + OstTrace0(camerax_performance, CXESTILLCAPTURECONTROL_PREPARE_OUT, "msg: e_CX_STILLCAPCONT_PREPARE 0"); CX_DEBUG_EXIT_FUNCTION(); } -/**! +/*! Prepare still snapshot Returns symbian error code. */ int CxeStillCaptureControlSymbian::prepareStillSnapshot() { CX_DEBUG_ENTER_FUNCTION(); - - CCamera::CCameraSnapshot *cameraSnapshot = mCameraDevice.cameraSnapshot(); - CX_ASSERT_ALWAYS(cameraSnapshot); - - int err = KErrNone; - // Whether or not we have postcapture on, we need the snapshot for Thumbnail Manager. - if (cameraSnapshot) { - // Cancel active snapshot - cameraSnapshot->StopSnapshot(); + OstTrace0( camerax_performance, CXESTILLCAPTURECONTROL_PREPARESNAP_1, "msg: e_CX_PREPARE_SNAPSHOT 1" ); - // Prepare snapshot - CCamera::TFormat snapFormat = CCamera::EFormatFbsBitmapColor16MU; - OstTrace0( camerax_performance, DUP4_CXESTILLCAPTURECONTROLSYMBIAN_PREPARE, "msg: e_CX_PREPARE_SNAPSHOT 1" ); - TRAP(err, cameraSnapshot->PrepareSnapshotL(snapFormat, - getSnapshotSize(), - KMaintainAspectRatio)); - OstTrace0( camerax_performance, DUP5_CXESTILLCAPTURECONTROLSYMBIAN_PREPARE, "msg: e_CX_PREPARE_SNAPSHOT 0" ); - CX_DEBUG(("PrepareSnapshotL done, err=%d", err)); - - // Start snapshot if no errors encountered. - if (err == KErrNone) { - CX_DEBUG(("Start still snapshot")); - cameraSnapshot->StartSnapshot(); - } - } else { - // No snapshot interface available. Report error. - // Assert above takes care of this, but keeping this as an option. - err = KErrNotReady; + int status(KErrNone); + try { + QSize snapshotSize = mSnapshotControl.calculateSnapshotSize( + mViewfinderControl.deviceDisplayResolution(), + mCurrentImageDetails.mAspectRatio); + mSnapshotControl.start(snapshotSize); + } catch (...) { + status = KErrGeneral; } + OstTrace0( camerax_performance, CXESTILLCAPTURECONTROL_PREPARESNAP_2, "msg: e_CX_PREPARE_SNAPSHOT 0" ); CX_DEBUG_EXIT_FUNCTION(); - - return err; + return status; } -/**! +/*! imageInfo contains image qualities details Returns CxeError error code. */ CxeError::Id CxeStillCaptureControlSymbian::getImageQualityDetails(CxeImageDetails &imageInfo) { CX_DEBUG_ENTER_FUNCTION(); + OstTrace0( camerax_performance, CXESTILLCAPTURECONTROL_GETQUALITYDETAILS_1, "msg: e_CX_GET_QUALITY_DETAILS 1" ); int imageQuality = 0; CxeError::Id err = CxeError::None; @@ -396,37 +380,14 @@ imageInfo = mIcmSupportedImageResolutions.at(imageQuality); } + OstTrace0( camerax_performance, CXESTILLCAPTURECONTROL_GETQUALITYDETAILS_2, "msg: e_CX_GET_QUALITY_DETAILS 0" ); CX_DEBUG_EXIT_FUNCTION(); return err; } - /*! -* Returns snapshot size. Snapshot size is calculated based on the -* display resolution and current image aspect ratio. -*/ -TSize CxeStillCaptureControlSymbian::getSnapshotSize() const -{ - CX_DEBUG_ENTER_FUNCTION(); - - TSize snapshotSize; - - QSize deviceResolution = mViewfinderControl.deviceDisplayResolution(); - QSize size = QSize(mCurrentImageDetails.mWidth, mCurrentImageDetails.mHeight); - - // scale according to aspect ratio. - size.scale(deviceResolution.width(), deviceResolution.height(), Qt::KeepAspectRatio); - CX_DEBUG(("Still Snapshot size, (%d,%d)", size.width(), size.height())); - snapshotSize.SetSize(size.width(), deviceResolution.height()); - - CX_DEBUG_EXIT_FUNCTION(); - - return snapshotSize; -} - - -/** * Command to start image capture now. + * @sa handleCameraEvent */ void CxeStillCaptureControlSymbian::capture() { @@ -435,10 +396,10 @@ // Start the image capture as fast as possible to minimize lag. // Check e.g. space available *after* this. + // Capture sound will be played when we receive "image capture event" from ECAM. mCameraDevice.camera()->CaptureImage(); if (imagesLeft() > 0) { - mCaptureSoundPlayer->play(); setState(Capturing); //! @todo: NOTE: This call may not stay here. It can move depending on the implementation for burst capture. @@ -464,7 +425,7 @@ } -/* ! +/*! @Param cameraIndex indicates which camera we are in use, primary/secondary Returns the format we use for specific camera index. */ @@ -481,115 +442,62 @@ return imgFormat; } - -/** - * Camera events. Only relevant one(s) are handled. +/*! + * Snapshot ready notification. Ask the snapshot from snapshot interface. + * NB: Typically snapshot arrives before image data but can be in reverse + * order as well. + * + * @param status Status of snapshot creation. CxeError::None if no error, otherwise contains the error code. + * @param snapshot Snapshot as QImage */ -void CxeStillCaptureControlSymbian::handleCameraEvent(int eventUid, int error) +void CxeStillCaptureControlSymbian::handleSnapshotReady(CxeError::Id status, const QImage &snapshot) { CX_DEBUG_ENTER_FUNCTION(); + if (mCameraDeviceControl.mode() == Cxe::ImageMode) { - if (eventUid == KUidECamEventSnapshotUidValue && - mCameraDeviceControl.mode() == Cxe::ImageMode) { - handleSnapshotEvent(CxeErrorHandlingSymbian::map(error)); + OstTrace0(camerax_performance, CXESTILLCAPTURECONTROL_HANDLESNAPSHOT_1, "msg: e_CX_HANDLE_SNAPSHOT 1"); + + QPixmap ss = QPixmap::fromImage(snapshot); + // Get image container for current snapshot index. + // Remember to increment counter. + CxeStillImageSymbian* stillImage = getImageForIndex(mNextSnapshotIndex++); + if (status == CxeError::None) { + stillImage->setSnapshot(ss); + } + + // Emit snapshotReady signal in all cases (error or not) + emit snapshotReady(status, snapshot, stillImage->id()); + + // When the snapshot ready event is handled, prepare new filename. + if (stillImage->filename().isEmpty()) { + // Error ignored at this point, try again when image data arrives. + prepareFilename(stillImage); + } + + OstTrace0(camerax_performance, CXESTILLCAPTURECONTROL_HANDLESNAPSHOT_2, "msg: e_CX_HANDLE_SNAPSHOT 0"); } CX_DEBUG_EXIT_FUNCTION(); } -/** - * Snapshot ready notification. Ask the snapshot from snapshot interface. - * NB: Typically snapshot arrives before image data but can be in reverse - * order as well. - */ -void CxeStillCaptureControlSymbian::handleSnapshotEvent(CxeError::Id error) +/*! +* Handle ECAM events. +* Needed only for capture sound synchronization. +* @param eventUid ECAM event id. +* @param error Error code. KErrNone if operation has been successful. +*/ +void CxeStillCaptureControlSymbian::handleCameraEvent(int eventUid, int error) { - CX_DEBUG_ENTER_FUNCTION(); - - if (state() == CxeStillCaptureControl::Uninitialized) { - // we ignore this event, when we are not active - return; - } - - OstTrace0( camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_HANDLESNAPSHOTEVENT, "msg: e_CX_HANDLE_SNAPSHOT 1" ); - - // Get image container for current snapshot index. - // Remember to increment counter. - CxeStillImageSymbian* stillImage = getImageForIndex(mNextSnapshotIndex++); - - if (error == CxeError::None) { - try { - stillImage->setSnapshot(extractSnapshot()); - } catch (const std::exception& ex) { - error = CxeError::General; + if (eventUid == KUidECamEventImageCaptureEventUidValue && error == KErrNone) { + CX_DEBUG(("CxeStillCaptureControlSymbian::handleCameraEvent - image capture event")); + if (state() == CxeStillCaptureControl::Capturing) { + mCaptureSoundPlayer->play(); } } - - // Emit snapshotReady signal in all cases (error or not) - emit snapshotReady(error, stillImage->snapshot(), stillImage->id()); - - // When the snapshot ready event is handled, prepare new filename. - if (stillImage->filename().isEmpty()) { - // Error ignored at this point, try again when image data arrives. - prepareFilename(stillImage); - } - - OstTrace0( camerax_performance, DUP1_CXESTILLCAPTURECONTROLSYMBIAN_HANDLESNAPSHOTEVENT, "msg: e_CX_HANDLE_SNAPSHOT 0" ); - CX_DEBUG_EXIT_FUNCTION(); } -/** -* Gets QPixmap snapshot from ECAM buffer, if available. -* @param buffer ECAM buffer containing the snapshot data. Will be released when this -* method returns, even on exception. -*/ -QPixmap CxeStillCaptureControlSymbian::extractSnapshot() -{ - CX_DEBUG_ENTER_FUNCTION(); - QPixmap pixmap; - if (mCameraDevice.cameraSnapshot()) { - - QT_TRAP_THROWING({ - RArray frameIndex; - CleanupClosePushL(frameIndex); - - MCameraBuffer &buffer(mCameraDevice.cameraSnapshot()->SnapshotDataL(frameIndex)); - - // Make sure buffer is released on leave / exception - CxeCameraBufferCleanup cleaner(&buffer); - TInt firstImageIndex(frameIndex.Find(0)); - CFbsBitmap &snapshot(buffer.BitmapL(firstImageIndex)); - - CleanupStack::PopAndDestroy(); // frameIndex - - TSize size = snapshot.SizeInPixels(); - TInt sizeInWords = size.iHeight * CFbsBitmap::ScanLineLength(size.iWidth, EColor16MU) / sizeof(TUint32); - CX_DEBUG(("size %d x %d, sizeInWords = %d", size.iWidth, size.iHeight, sizeInWords )); - - TUint32* pixelData = new (ELeave) TUint32[ sizeInWords ]; - // Convert to QImage - snapshot.LockHeap(); - TUint32* dataPtr = snapshot.DataAddress(); - memcpy(pixelData, dataPtr, sizeof(TUint32)*sizeInWords); - snapshot.UnlockHeap(); - - CX_DEBUG(("Creating QImage")); - QImage *snapImage = new QImage((uchar*)pixelData, size.iWidth, size.iHeight, - CFbsBitmap::ScanLineLength(size.iWidth, EColor16MU), - QImage::Format_RGB32); - - pixmap = QPixmap::fromImage(*snapImage); - delete [] pixelData; - delete snapImage; - }); - } - - CX_DEBUG_EXIT_FUNCTION(); - return pixmap; -} - -/** +/*! * handleImageData: Image data received from ECam */ void CxeStillCaptureControlSymbian::handleImageData(MCameraBuffer* cameraBuffer, int error) @@ -638,8 +546,15 @@ QByteArray byteArray( reinterpret_cast( data->Ptr() ), data->Size() ); data = NULL; + // get geotagging setting value and check if we have to add location trail to image data. + int value = Cxe::GeoTaggingOff; + mSettings.get(CxeSettingIds::GEOTAGGING, value); + // Save the image data - CxeImageDataItemSymbian* dataItem = mImageDataQueue->startSave(byteArray, stillImage->filename(), stillImage->id()); + CxeImageDataItemSymbian* dataItem = mImageDataQueue->startSave(byteArray, + stillImage->filename(), + stillImage->id(), + value == Cxe::GeoTaggingOn); stillImage->setDataItem(dataItem); mFileSaveThread.save(dataItem); // Saving thread takes ownership of dataItem. } @@ -660,7 +575,7 @@ } -/** +/*! * Settings changed, needs updated */ void CxeStillCaptureControlSymbian::handleSettingValueChanged(const QString& settingId, QVariant newValue) @@ -705,7 +620,7 @@ CX_DEBUG_EXIT_FUNCTION(); } -/** +/*! * ECam reference changing, release resources */ void CxeStillCaptureControlSymbian::prepareForCameraDelete() @@ -715,7 +630,7 @@ CX_DEBUG_EXIT_FUNCTION(); } -/** +/*! * Camera being released. Cancel ongoing capture, if any. */ void CxeStillCaptureControlSymbian::prepareForRelease() @@ -725,7 +640,7 @@ CX_DEBUG_EXIT_FUNCTION(); } -/** +/*! * New camera available, */ void CxeStillCaptureControlSymbian::handleCameraAllocated(CxeError::Id error) @@ -759,7 +674,7 @@ CX_DEBUG_EXIT_FUNCTION(); } -/** +/*! * Return number of images captured (during current capture operation only). */ int CxeStillCaptureControlSymbian::imageCount() const @@ -767,7 +682,7 @@ return mImages.count(); } -/** +/*! * Reset the image array. */ void CxeStillCaptureControlSymbian::reset() @@ -783,7 +698,7 @@ CX_DEBUG_EXIT_FUNCTION(); } -/** +/*! * This should cancel any ongoing image captures. */ void CxeStillCaptureControlSymbian::cancelAll() @@ -792,7 +707,7 @@ reset(); } -/** +/*! * Sets the current capture mode: SingleImageCapture / BurstCapture. */ void CxeStillCaptureControlSymbian::setMode( CaptureMode mode ) @@ -800,7 +715,7 @@ mMode = mode; } -/** +/*! * Returns the current capture mode. */ CxeStillCaptureControl::CaptureMode CxeStillCaptureControlSymbian::mode() const @@ -808,7 +723,7 @@ return mMode; } -/** +/*! * Operator [] - returns the indexed image from capture array. */ CxeStillImage &CxeStillCaptureControlSymbian::operator[]( int index ) @@ -816,7 +731,7 @@ return *mImages[ index ]; } -/** +/*! * Getter for image data queue. */ CxeImageDataQueue &CxeStillCaptureControlSymbian::imageDataQueue() @@ -824,7 +739,7 @@ return *mImageDataQueue; } -/** +/*! * Generates a filename and sets it in the still image object. * Skips the process if filename already copied exists in the object. This * behaviour is required in rare cases where image data arrives before snapshot. @@ -832,6 +747,8 @@ CxeError::Id CxeStillCaptureControlSymbian::prepareFilename(CxeStillImageSymbian *stillImage) { + OstTrace0(camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_PREPAREFILENAME_1, "msg: e_CX_PREPARE_FILENAME 1" ); + CxeError::Id err = CxeError::None; if (stillImage->filename().isEmpty()) { QString path; @@ -855,6 +772,8 @@ CX_DEBUG(("ERROR in filename generation. err:%d", err)); } } + + OstTrace0(camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_PREPAREFILENAME_2, "msg: e_CX_PREPARE_FILENAME 0" ); return err; } @@ -887,7 +806,7 @@ CX_DEBUG_EXIT_FUNCTION(); } -/** +/*! * Get the image container at given index or create a new one if needed. */ CxeStillImageSymbian* CxeStillCaptureControlSymbian::getImageForIndex(int index) @@ -921,8 +840,7 @@ // if focused and in correct mode, play sound if (newState == CxeAutoFocusControl::Ready && - mode != CxeAutoFocusControl::Hyperfocal && - mode != CxeAutoFocusControl::Infinity && + !mAutoFocusControl.isFixedFocusMode(mode) && mAutoFocusControl.isSoundEnabled()) { mAutoFocusSoundPlayer->play(); }