camerauis/cameraxui/cxengine/src/cxevideocapturecontrolsymbian.cpp
changeset 38 0f0b4c1d7744
parent 28 3075d9b614e6
child 39 c5025ea871a1
--- a/camerauis/cameraxui/cxengine/src/cxevideocapturecontrolsymbian.cpp	Thu May 13 21:30:19 2010 +0300
+++ b/camerauis/cameraxui/cxengine/src/cxevideocapturecontrolsymbian.cpp	Thu Jul 15 01:44:30 2010 +0300
@@ -14,19 +14,22 @@
 * Description:
 *
 */
+
+#include <algorithm>
+#include <exception>
 #include <QTime>
-#include <fbs.h>
 #include <QPixmap>
 #include <coemain.h>
 #include <QStringList>
-#include <AudioPreference.h>
 
+#include "cxeexception.h"
 #include "cxevideocapturecontrolsymbian.h"
 #include "cxevideorecorderutilitysymbian.h"
 #include "cxecameradevicecontrolsymbian.h"
 #include "cxefilenamegeneratorsymbian.h"
 #include "cxeerrormappingsymbian.h"
 #include "cxeviewfindercontrol.h"
+#include "cxesnapshotcontrol.h"
 #include "cxestillimagesymbian.h"
 #include "cxecameradevice.h"
 #include "cxutils.h"
@@ -47,26 +50,11 @@
 // constants
 namespace
 {
-    // Controller UId, can be used by the client to identify the controller, e.g. if the custom command can be used
-    const TUid KCamCControllerImplementationUid = {0x101F8503};
     // TMMFEvent UIDs for Async stop
     const TUid KCamCControllerCCVideoRecordStopped = {0x2000E546};
     const TUid KCamCControllerCCVideoFileComposed = {0x2000E547};
 
-    // Custom command for setting a new filename without closing & reopening the controller
-    enum TCamCControllerCustomCommands
-        {
-        ECamCControllerCCNewFilename = 0,
-        ECamCControllerCCVideoStopAsync
-        };
-
-    const TInt    KOneSecond                  = 1000000;
-    const int     KMaintainAspectRatio        = false;
     const TInt64  KMinRequiredSpaceVideo      = 4000000;
-    const uint    KOneMillion                 = 1000000;
-    const qreal   KMetaDataCoeff              = 1.03;      // Coefficient to estimate metadata amount
-    const uint    KCamCMaxClipDurationInSecs  = 5400;      // Maximun video clip duration in seconds
-    const qreal   KCMRAvgVideoBitRateScaler   = 0.9;       // avg video bit rate scaler
 }
 
 
@@ -76,6 +64,7 @@
 CxeVideoCaptureControlSymbian::CxeVideoCaptureControlSymbian(
     CxeCameraDevice &cameraDevice,
     CxeViewfinderControl &viewfinderControl,
+    CxeSnapshotControl &snapshotControl,
     CxeCameraDeviceControl &cameraDeviceControl,
     CxeFilenameGenerator &nameGenerator,
     CxeSettings &settings,
@@ -86,12 +75,14 @@
       mCameraDevice(cameraDevice),
       mCameraDeviceControl(cameraDeviceControl),
       mViewfinderControl(viewfinderControl),
+      mSnapshotControl(snapshotControl),
       mFilenameGenerator(nameGenerator),
       mSettings(settings),
       mQualityPresets(qualityPresets),
       mDiskMonitor(diskMonitor),
       mSnapshot(),
-      mNewFileName(""),
+      mVideoStartSoundPlayer(NULL),
+      mVideoStopSoundPlayer(NULL),
       mCurrentFilename("")
 {
     CX_DEBUG_ENTER_FUNCTION();
@@ -118,23 +109,26 @@
             this, SLOT(prepareForRelease()) );
     connect(&cameraDevice, SIGNAL(cameraAllocated(CxeError::Id)),
             this, SLOT(handleCameraAllocated(CxeError::Id)));
+
     // connect playing sound signals
     connect(mVideoStartSoundPlayer, SIGNAL(playComplete(int)),
             this, SLOT(handleSoundPlayed()));
 
+    // connect snapshot ready signal
+    connect(&mSnapshotControl, SIGNAL(snapshotReady(CxeError::Id, const QPixmap&)),
+            this, SLOT(handleSnapshotReady(CxeError::Id, const QPixmap&)));
+
     // enabling setting change callbacks to videocapturecontrol
     connect(&mSettings, SIGNAL(settingValueChanged(const QString&,QVariant)),
             this, SLOT(handleSettingValueChanged(const QString&,QVariant)));
-
-    connect(&mSettings, SIGNAL(sceneChanged(CxeScene&)), this, SLOT(handleSceneChanged(CxeScene&)));
-
+    connect(&mSettings, SIGNAL(sceneChanged(CxeScene&)),
+            this, SLOT(handleSceneChanged(CxeScene&)));
     OstTrace0(camerax_performance, CXEVIDEOCAPTURECONTROLSYMBIAN_CREATE_M2, "msg: e_CX_ENGINE_CONNECT_SIGNALS 0");
 
     OstTrace0(camerax_performance, CXEVIDEOCAPTURECONTROLSYMBIAN_CREATE_OUT, "msg: e_CX_VIDEOCAPTURECONTROL_NEW 0");
     CX_DEBUG_EXIT_FUNCTION();
 }
 
-
 /*!
 * CxeVideoCaptureControlSymbian::~CxeVideoCaptureControlSymbian()
 */
@@ -150,7 +144,6 @@
     CX_DEBUG_EXIT_FUNCTION();
 }
 
-
 /*!
 * Initializes resources for video recording.
 */
@@ -168,11 +161,9 @@
     }
 
     OstTrace0( camerax_performance, DUP1_CXEVIDEOCAPTURECONTROLSYMBIAN_INIT, "msg: e_CX_VIDEO_CAPCONT_INIT 0" );
-
     CX_DEBUG_EXIT_FUNCTION();
 }
 
-
 /*
 * Releases all resources
 */
@@ -180,39 +171,31 @@
 {
     CX_DEBUG_ENTER_FUNCTION();
 
-    if(state() == Idle) {
-        // nothing to do
-        return;
-    }
+    // Nothing to do if already idle.
+    if(state() != Idle) {
+        OstTrace0( camerax_performance, CXEVIDEOCAPTURECONTROLSYMBIAN_DEINIT, "msg: e_CX_VIDEO_CAPCONT_DEINIT 1" );
 
-    OstTrace0( camerax_performance, CXEVIDEOCAPTURECONTROLSYMBIAN_DEINIT, "msg: e_CX_VIDEO_CAPCONT_DEINIT 1" );
+        // first stop viewfinder
+        mViewfinderControl.stop();
 
-    // first stop viewfinder
-    mViewfinderControl.stop();
-
-    // stop video-recording in-case if its ongoing.
-    stop();
+        // stop video-recording in-case if its ongoing.
+        stop();
 
-    if (mCameraDevice.cameraSnapshot()) {
-        mCameraDevice.cameraSnapshot()->StopSnapshot();
-    }
+        mSnapshotControl.stop();
 
-    if (mVideoRecorder) {
-        mVideoRecorder->Close();
-    }
+        if (mVideoRecorder) {
+            mVideoRecorder->close();
+        }
 
-    // revert back the new filename to empty string so that we generate a new file name
-    // when we init again
-    mNewFileName = QString("");
+        mCurrentFilename = QString("");
 
-    setState(Idle);
+        setState(Idle);
 
-    OstTrace0( camerax_performance, DUP1_CXEVIDEOCAPTURECONTROLSYMBIAN_DEINIT, "msg: e_CX_VIDEO_CAPCONT_DEINIT 0" );
-
+        OstTrace0( camerax_performance, DUP1_CXEVIDEOCAPTURECONTROLSYMBIAN_DEINIT, "msg: e_CX_VIDEO_CAPCONT_DEINIT 0" );
+    }
     CX_DEBUG_EXIT_FUNCTION();
 }
 
-
 /*!
 * Intializes VideoRecorder for recording.
 */
@@ -220,52 +203,28 @@
 {
     CX_DEBUG_ENTER_FUNCTION();
 
-    if (state() != Idle) {
-        // not valid state to start "open" operation
-        return;
-    }
-
-    if(!mVideoRecorder) {
-        // if video recorder is not created, do it now.
-        createVideoRecorder();
-    }
-
-    // update current video quality details from icm
-    CxeError::Id err = getVideoQualityDetails(mCurrentVideoDetails);
+    // Init needed only in Idle state
+    if (state() == Idle) {
+        try {
+            // if video recorder is not created, do it now.
+            createVideoRecorder();
 
-    if (!err) {
-        // read videofile mime type
-        QByteArray videoFileData =
-                    mCurrentVideoDetails.mVideoFileMimeType.toLatin1();
-        TPtrC8 videoFileMimeType(reinterpret_cast<const TUint8*>
-                           (videoFileData.constData()), videoFileData.size());
+            // update current video quality details from icm.
+            // Throws an error if unable to get the quality.
+            getVideoQualityDetails(mCurrentVideoDetails);
 
-        // read preferred supplier
-        TPtrC16 supplier(reinterpret_cast<const TUint16*>
-                           (mCurrentVideoDetails.mPreferredSupplier.utf16()));
-
-        err = findVideoController(videoFileMimeType, supplier);
-
-        if (!err) {
-            // video recorder is ready to open video file for recording.
+            // Video recorder is ready to open video file for recording.
             setState(Initialized);
             open();
+        } catch (const std::exception &e) {
+            // Handle error
+            handlePrepareFailed();
         }
-    } else {
-        err = CxeErrorHandlingSymbian::map(KErrNotReady);
-    }
-
-    if (err) {
-        // In case of error
-        emit videoPrepareComplete(err);
-        deinit();
     }
 
     CX_DEBUG_EXIT_FUNCTION();
 }
 
-
-
 /*!
 * Opens file for video recording.
 */
@@ -273,92 +232,53 @@
 {
     CX_DEBUG_ENTER_FUNCTION();
 
-    if (state() != Initialized) {
-        // not valid state to start "open" operation
-        return;
-    }
-
-    CxeError::Id err = CxeError::None;
+    // Check valid state to start "open" operation
+    if (state() == Initialized) {
+        try {
+            // generate video file name, if necessary
+            generateFilename();
+            CX_DEBUG(( "Next video file path: %s", mCurrentFilename.toAscii().constData() ));
 
-    // generate video file name, if necessary
-    if (mNewFileName.isEmpty()) {
-        QStringList list = mCurrentVideoDetails.mVideoFileMimeType.split("/");
-        QString fileExt(".");
-        if (list.count() == 2) {
-            fileExt = fileExt + list[1];
-        }
-        // Generate new filename and open the file for writing video data
-        err = mFilenameGenerator.generateFilename(mNewFileName, fileExt);
-        if (err == CxeError::None) {
-            mCurrentFilename = mNewFileName;
-        } else {
-            // file name is not valid, re-initialize the value of current string
-            // back to empty string
-            mCurrentFilename = QString("");
-        }
-    }
+            // Start preparing..
+            setState(CxeVideoCaptureControl::Preparing);
 
-    if (!err &&
-        mVideoRecorder &&
-        !mCurrentFilename.isEmpty()) {
-
-        TPtrC16 fName(reinterpret_cast<const TUint16*>(mCurrentFilename.utf16()));
-        CX_DEBUG(( "Next video file path: %s", mCurrentFilename.toAscii().constData() ));
-
-        // read video codec mime type
-        QByteArray videoCodecData =
-                    mCurrentVideoDetails.mVideoCodecMimeType.toLatin1();
-        TPtrC8 videoCodecMimeType(reinterpret_cast<const TUint8*>
-                           (videoCodecData.constData()), videoCodecData.size());
-
-        setState(CxeVideoCaptureControl::Preparing);
-
-        TRAPD(openErr, mVideoRecorder->OpenFileL(fName,
-                       mCameraDevice.camera()->Handle(),
-                       mVideoControllerUid,
-                       mVideoFormatUid,
-                       videoCodecMimeType,
-                       audioType(mCurrentVideoDetails.mAudioType)));
-
-        err = CxeErrorHandlingSymbian::map(openErr);
-    }
-    if (err) {
-        // error occured.
-        deinit();
-        emit videoPrepareComplete(err);
+            // Exception thrown if open fails.
+            mVideoRecorder->open(mCameraDevice.camera()->Handle(),
+                                 mCurrentFilename,
+                                 mCurrentVideoDetails.mVideoFileMimeType,
+                                 mCurrentVideoDetails.mPreferredSupplier,
+                                 mCurrentVideoDetails.mVideoCodecMimeType,
+                                 mCurrentVideoDetails.mAudioType);
+        } catch (const std::exception &e) {
+            handlePrepareFailed();
+        }
     }
     CX_DEBUG_EXIT_FUNCTION();
 }
 
-
 /*!
-* Prepare Video Recorder with necessary settings for video capture.
+* Helper method for generating filename.
+* Throws exception, if file type mime is formatted wrong or
+* filename generation fails.
 */
-TFourCC CxeVideoCaptureControlSymbian::audioType(const QString& str)
+void CxeVideoCaptureControlSymbian::generateFilename()
 {
     CX_DEBUG_ENTER_FUNCTION();
-
-    QByteArray audioType = str.toAscii();
-
-    quint8 char1(' ');
-    quint8 char2(' ');
-    quint8 char3(' ');
-    quint8 char4(' ');
+    mCurrentFilename = QString("");
 
-    if (audioType.count() > 3) {
-        char1 = audioType[0];
-        char2 = audioType[1];
-        char3 = audioType[2];
+    QStringList list = mCurrentVideoDetails.mVideoFileMimeType.split("/");
+    // Throw exception if mime string is formatted wrong.
+    if (list.count() != 2) {
+        throw new CxeException(CxeError::General);
+    }
+    QString fileExt = "." + list[1];
 
-        if (audioType.count() == 4) {
-            char4 = audioType[3];
-        }
-    }
+    // Generate new filename and open the file for writing video data
+    CxeException::throwIfError(mFilenameGenerator.generateFilename(mCurrentFilename, fileExt));
 
-    return TFourCC(char1, char2, char3, char4);
+    CX_DEBUG_EXIT_FUNCTION();
 }
 
-
 /*!
 * Prepare Video Recorder with necessary settings for video capture.
 */
@@ -371,13 +291,8 @@
         return;
     }
 
-    CX_DEBUG(("Video resoulution (%d,%d)", mCurrentVideoDetails.mWidth,
-                                           mCurrentVideoDetails.mHeight));
-    CX_DEBUG(("Video bitrate = %d)", mCurrentVideoDetails.mVideoBitRate));
-
     OstTrace0(camerax_performance, CXEVIDEOCAPTURECONTROLSYMBIAN_PREPARE, "msg: e_CX_VIDCAPCONT_PREPARE 1");
-    TSize frameSize;
-    frameSize.SetSize(mCurrentVideoDetails.mWidth, mCurrentVideoDetails.mHeight);
+    QSize frameSize(mCurrentVideoDetails.mWidth, mCurrentVideoDetails.mHeight);
 
     int muteSetting = 0; // audio enabled
     mSettings.get(CxeSettingIds::VIDEO_MUTE_SETTING, muteSetting);
@@ -390,227 +305,65 @@
         frameRate = mCurrentVideoDetails.mVideoFrameRate;
     }
 
+    CX_DEBUG(("Video resolution (%d,%d)", mCurrentVideoDetails.mWidth,
+                                           mCurrentVideoDetails.mHeight));
+    CX_DEBUG(("Video bitrate = %d)", mCurrentVideoDetails.mVideoBitRate));
     CX_DEBUG(("Video frame rate = %d)", frameRate));
 
-    TRAPD(err,
-              {
-              mVideoRecorder->SetVideoFrameSizeL(frameSize);
-              mVideoRecorder->SetVideoFrameRateL(frameRate);
-              mVideoRecorder->SetVideoBitRateL(mCurrentVideoDetails.mVideoBitRate);
-              mVideoRecorder->SetAudioEnabledL(muteSetting == 0);
-              // "No limit" value is handled in video recorder wrapper.
-              mVideoRecorder->SetMaxClipSizeL(mCurrentVideoDetails.mMaximumSizeInBytes);
-              }
-         );
+    try {
+        mVideoRecorder->setVideoFrameSize(frameSize);
+        mVideoRecorder->setVideoFrameRate(frameRate);
+        mVideoRecorder->setVideoBitRate(mCurrentVideoDetails.mVideoBitRate);
+        mVideoRecorder->setAudioEnabled(muteSetting == 0);
+        // "No limit" value is handled in video recorder wrapper.
+        mVideoRecorder->setVideoMaxSize(mCurrentVideoDetails.mMaximumSizeInBytes);
+
+        // Settings have been applied successfully, start to prepare.
+        mVideoRecorder->prepare();
 
-    if (!err) {
-        // settings have been applied successfully, start to prepare
-        mVideoRecorder->Prepare();
-        // prepare snapshot
-        err = prepareVideoSnapshot();
+        // Prepare snapshot. Snapshot control throws error if problems.
+        QSize snapshotSize = mSnapshotControl.calculateSnapshotSize(
+                                mViewfinderControl.deviceDisplayResolution(),
+                                QSize(mCurrentVideoDetails.mWidth, mCurrentVideoDetails.mHeight));
+        mSnapshotControl.start(snapshotSize);
+
+        // Prepare zoom only when there are no errors during prepare.
+        emit prepareZoomForVideo();
+        emit videoPrepareComplete(CxeError::None);
+    } catch (const std::exception &e) {
+        // Handle error.
+        handlePrepareFailed();
     }
 
-    if (!err) {
-        // prepare zoom only when there are no errors during prepare.
-        emit prepareZoomForVideo();
-    }
-    // emit video prepare status
-    emit videoPrepareComplete(CxeErrorHandlingSymbian::map(err));
-
     OstTrace0(camerax_performance, DUP1_CXEVIDEOCAPTURECONTROLSYMBIAN_PREPARE, "msg: e_CX_VIDCAPCONT_PREPARE 0");
-
     CX_DEBUG_EXIT_FUNCTION();
 }
 
-
-
 /*!
-Fetches video qualites details based on video quality setting.
-Returns CxeError codes if any.
+* Fetches video qualites details based on video quality setting.
 */
-CxeError::Id
+void
 CxeVideoCaptureControlSymbian::getVideoQualityDetails(CxeVideoDetails &videoInfo)
 {
     CX_DEBUG_ENTER_FUNCTION();
 
-    int videoQuality = 0;
-    CxeError::Id err = CxeError::None;
-
-    if (mCameraDeviceControl.cameraIndex() == Cxe::PrimaryCameraIndex) {
-        err = mSettings.get(CxeSettingIds::VIDEO_QUALITY, videoQuality);
-
-        bool validQuality = (videoQuality >= 0 &&
-                             videoQuality < mIcmSupportedVideoResolutions.count());
-        if (err == CxeError::None && validQuality) {
-            // get video quality details
-            videoInfo = mIcmSupportedVideoResolutions.at(videoQuality);
-        } else {
-            // not valid video quality
-            err = CxeError::NotFound;
-        }
-    } else {
-        // get secondary camera video quality index
-        if (mIcmSupportedVideoResolutions.count() > 0) {
-            videoInfo = mIcmSupportedVideoResolutions.at(videoQuality);
-        } else {
-            // not valid video quality
-            err = CxeError::NotFound;
-        }
-    }
-
-    CX_DEBUG_EXIT_FUNCTION();
-
-    return err;
-}
-
+    int quality(0);
 
-/**!
- Prepare snapshot
- Returns symbian error code.
- */
-int CxeVideoCaptureControlSymbian::prepareVideoSnapshot()
-{
-    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();
-
-        // Prepare snapshot
-        CCamera::TFormat snapFormat = CCamera::EFormatFbsBitmapColor16MU;
-        TRAP(err, cameraSnapshot->PrepareSnapshotL(snapFormat,
-                                                   getSnapshotSize(),
-                                                   KMaintainAspectRatio));
-        CX_DEBUG(("PrepareSnapshotL done, err=%d", err));
-        // Start snapshot if no errors encountered.
-        if (err == KErrNone) {
-            CX_DEBUG(("Start video snapshot"));
-            cameraSnapshot->StartSnapshot();
-        }
-    } else {
-        // No snapshot interface available. Report error.
-        // Assert above takes care of this, but keeping this as an option.
-        err = KErrNotReady;
+    // Get quality index for primary camera. Only one quality for secondary camera.
+    if (mCameraDeviceControl.cameraIndex() == Cxe::PrimaryCameraIndex) {
+        CxeException::throwIfError(mSettings.get(CxeSettingIds::VIDEO_QUALITY, quality));
     }
 
-    CX_DEBUG_EXIT_FUNCTION();
-
-    return err;
-}
-
-
-
-/*!
-* Returns snapshot size. Snapshot size is calculated based on the
-* display resolution and current video aspect ratio.
-*/
-TSize CxeVideoCaptureControlSymbian::getSnapshotSize() const
-{
-    CX_DEBUG_ENTER_FUNCTION();
-
-    TSize snapshotSize;
-
-    QSize deviceResolution = mViewfinderControl.deviceDisplayResolution();
-    QSize size = QSize(mCurrentVideoDetails.mWidth, mCurrentVideoDetails.mHeight);
-
-    // scale according to aspect ratio.
-    size.scale(deviceResolution.width(),
-               deviceResolution.height(),
-               Qt::KeepAspectRatio);
-    CX_DEBUG(("Video Snapshot size, (%d,%d)", size.width(), size.height()));
-    snapshotSize.SetSize(size.width(), deviceResolution.height());
-
-    CX_DEBUG_EXIT_FUNCTION();
-
-    return snapshotSize;
-}
-
-
-
-/**!
-* Camera events coming from ecam.
-*/
-void CxeVideoCaptureControlSymbian::handleCameraEvent(int eventUid, int error)
-{
-    CX_DEBUG_ENTER_FUNCTION();
-    if (eventUid == KUidECamEventSnapshotUidValue) {
-        handleSnapshotEvent(CxeErrorHandlingSymbian::map(error));
-    }
-    CX_DEBUG_EXIT_FUNCTION();
-}
-
-
-/*!
-* Handle Snapshot event from ecam
-*/
-void CxeVideoCaptureControlSymbian::handleSnapshotEvent(CxeError::Id error)
-{
-    CX_DEBUG_ENTER_FUNCTION();
-
-    if (state() == Idle) {
-        // we ignore this event, when we are not in active state(s)
-        CX_DEBUG(( "wrong state, ignoring snapshot" ));
-        CX_DEBUG_EXIT_FUNCTION();
-        return;
+    if (quality < 0 || quality >= mIcmSupportedVideoResolutions.count()) {
+       throw new CxeException(CxeError::NotFound);
     }
 
-    if (error) {
-        mSnapshot = QPixmap();
-        emit snapshotReady(error, mSnapshot, filename());
-        return;
-    }
-
-    RArray<TInt> snapList;
-    MCameraBuffer* buffer(NULL);
-    // Note: Cleanup not required in this function
-    CFbsBitmap *snapshot = NULL;
-    TRAPD(snapErr,
-          buffer = &mCameraDevice.cameraSnapshot()->SnapshotDataL(snapList));
-    if (!snapErr) {
-        TInt firstImageIndex = snapList.Find(0);
-        snapList.Close();
-        TRAP(snapErr, snapshot = &(buffer->BitmapL(firstImageIndex)));
-    }
-    if (!snapErr) {
-        TSize size = snapshot->SizeInPixels();
-        TInt sizeInWords = size.iHeight * CFbsBitmap::ScanLineLength(size.iWidth, EColor16MU)
-                / sizeof(TUint32);
-
-        TUint32 *snapshotData = NULL;
-        snapshotData = new TUint32[sizeInWords];
-
-        if (snapshotData) {
-            // Convert to QImage
-            snapshot->LockHeap();
-            TUint32* dataPtr = snapshot->DataAddress();
-            memcpy(snapshotData, dataPtr, sizeof(TUint32) * sizeInWords);
-            snapshot->UnlockHeap();
-
-
-            QImage *img = new QImage((uchar*) snapshotData, size.iWidth, size.iHeight,
-                                   CFbsBitmap::ScanLineLength(size.iWidth, EColor16MU),
-                                   QImage::Format_RGB32);
-
-            mSnapshot = QPixmap::fromImage(*img);
-            delete [] snapshotData;
-            delete img;
-        }
-    }
-    if (buffer) {
-        buffer->Release();
-    }
-    // Snapshot ready
-    emit snapshotReady(CxeErrorHandlingSymbian::map(snapErr), mSnapshot, filename());
+    // get video quality details
+    videoInfo = mIcmSupportedVideoResolutions.at(quality);
 
     CX_DEBUG_EXIT_FUNCTION();
 }
 
-
 /*!
 * Resets the video snapshot and current video filename
 */
@@ -627,7 +380,6 @@
     CX_DEBUG_EXIT_FUNCTION();
 }
 
-
 /*!
 * Returns current video filename
 */
@@ -639,7 +391,6 @@
     return mCurrentFilename;
 }
 
-
 /*!
 * Returns current video snapshot
 */
@@ -648,7 +399,6 @@
     return mSnapshot;
 }
 
-
 /*!
 * Starts video recording if we are in appropriate state.
 */
@@ -666,30 +416,23 @@
     CX_DEBUG_EXIT_FUNCTION();
 }
 
-
 /*!
 * Pauses video recording.
 */
 void CxeVideoCaptureControlSymbian::pause()
 {
     CX_DEBUG_ENTER_FUNCTION();
-
-    setState(CxeVideoCaptureControl::Paused);
-    TRAPD(pauseErr, mVideoRecorder->PauseL());
-    // play the sound, but not changing the state
-    mVideoStopSoundPlayer->play();
-    if (pauseErr) {
-        CX_DEBUG(("[WARNING] Error %d pausing!", pauseErr));
-        //pause operation failed, report it
-        emit videoComposed(CxeErrorHandlingSymbian::map(pauseErr), filename());
-        // release resources.
-        deinit();
+    try {
+        mVideoRecorder->pause();
+        setState(CxeVideoCaptureControl::Paused);
+        // play the sound, but not changing the state
+        mVideoStopSoundPlayer->play();
+    } catch (const std::exception &e) {
+        handleComposeFailed(qt_symbian_exception2Error(e));
     }
-
     CX_DEBUG_EXIT_FUNCTION();
 }
 
-
 /*!
 * Stops video recording.
 */
@@ -701,35 +444,30 @@
         // first stop viewfinder
         mViewfinderControl.stop();
 
-        TInt asyncStopErr = mVideoRecorder->CustomCommandSync(
-            TMMFMessageDestination(KCamCControllerImplementationUid,
-                                   KMMFObjectHandleController),
-            ECamCControllerCCVideoStopAsync,
-            KNullDesC8,
-            KNullDesC8 );
-        CX_DEBUG(("ECamCControllerCCVideoStopAsync sent, err=%d", asyncStopErr));
-        if (asyncStopErr) { // fall back to synchronous stop
-            TInt syncStopErr = mVideoRecorder->Stop();
-            if (syncStopErr) {
-                // error during stop operation, release resources
-                emit videoComposed(CxeErrorHandlingSymbian::map(asyncStopErr), filename());
-                deinit();
-            } else {
-                // stop operation went fine, set back the state to Initialized.
+        try {
+            // Try asynchronous stopping first.
+            mVideoRecorder->stop(true);
+            // No error from asynchronous stop -> wait for stop event
+            setState(Stopping);
+        } catch (const std::exception &e) {
+            CX_DEBUG(("CxeVideoCaptureControlSymbian - async stop failed, try sync.."));
+            try {
+                mVideoRecorder->stop(false);
+                 // stop operation went fine, set back the state to Initialized.
                 setState(Initialized);
+                // must increment counter now since no callback is coming in sync stop
                 mFilenameGenerator.raiseCounterValue();
+            } catch (const std::exception &e) {
+                // Even synchronous stopping failed -> release resources.
+                CX_DEBUG(("CxeVideoCaptureControlSymbian - sync stop failed, too!"));
+                handleComposeFailed(qt_symbian_exception2Error(e));
             }
-        } else {
-            // No error from asynch stop custom command... wait for stop event
-            setState(Stopping);
-            mFilenameGenerator.raiseCounterValue();
         }
     }
 
     CX_DEBUG_EXIT_FUNCTION();
 }
 
-
 /*!
 * Callback when "Open" operation is complete.
 */
@@ -739,20 +477,16 @@
     CX_DEBUG(("CxeVideoCaptureControlSymbian::MvruoOpenComplete, err=%d", aError));
 
     if (state() == Preparing) {
-        if (aError != KErrNone) {
-            deinit();
-            CxeError::Id err = CxeErrorHandlingSymbian::map(KErrNotReady);
-            // report error to interested parties
-            emit videoPrepareComplete(CxeErrorHandlingSymbian::map(err));
+        if (!aError) {
+            prepare();
         } else {
-            prepare();
+            handlePrepareFailed();
         }
     }
 
     CX_DEBUG_EXIT_FUNCTION();
 }
 
-
 /*!
 * Callback when "Prepare" request is complete.
 */
@@ -767,17 +501,13 @@
             mViewfinderControl.start();
             OstTrace0( camerax_performance, CXEVIDEOCAPTURECONTROLSYMBIAN_GOTOVIDEO, "msg: e_CX_GO_TO_VIDEO_MODE 0" );
         } else {
-            deinit();
-            // report error to interested parties
-            CxeError::Id err = CxeErrorHandlingSymbian::map(KErrNotReady);
-            emit videoPrepareComplete(CxeErrorHandlingSymbian::map(err));
+            handlePrepareFailed();
         }
     }
 
     CX_DEBUG_EXIT_FUNCTION();
 }
 
-
 /*!
 * Callback when "Record" operation is complete.
 */
@@ -799,14 +529,12 @@
     }
     else {
         // error during recording, report to client
-        deinit();
-        emit videoComposed(CxeErrorHandlingSymbian::map(aError), filename());
+        handleComposeFailed(aError);
     }
 
     CX_DEBUG_EXIT_FUNCTION();
 }
 
-
 /*!
 * Callback from MVideoRecorderUtilityObserver
 */
@@ -824,11 +552,9 @@
             // stop operation went fine, set back the state to intialized.
             setState(Initialized);
         }
+        mFilenameGenerator.raiseCounterValue();
         // video file has composed, everything went well, inform the client
         emit videoComposed(CxeError::None, filename());
-        // revert back the new filename to empty string, since recording
-        // is complete and we need to generate a new file name
-        mNewFileName = QString("");
     } else {
         CX_DEBUG(("ignoring unknown MvruoEvent 0x%08x", aEvent.iEventType.iUid ));
     }
@@ -836,85 +562,6 @@
     CX_DEBUG_EXIT_FUNCTION();
 }
 
-
-/*!
-Get corresponding controller for video capture.
-@param aMimeType denotes videofile mimetype,
-@param aPreferredSupplier denotes supplier.
-Returns CxeError::Id if any.
-*/
-CxeError::Id
-CxeVideoCaptureControlSymbian::findVideoController(const TDesC8& aMimeType,
-                                                   const TDesC& aSupplier)
-{
-    CX_DEBUG_ENTER_FUNCTION();
-
-    CX_DEBUG(("video file mime type : %s", &aMimeType));
-    CX_DEBUG(("supplier name: %s", &aSupplier));
-
-    mVideoControllerUid.iUid = 0;
-    mVideoFormatUid.iUid = 0;
-
-    // Retrieve a list of possible controllers from ECOM.
-    // Controller must support recording the requested mime type.
-    // Controller must be provided by preferred supplier.
-
-    CMMFControllerPluginSelectionParameters* cSelect(NULL);
-    CMMFFormatSelectionParameters* fSelect(NULL);
-    RMMFControllerImplInfoArray controllers;
-
-    TRAPD(err, cSelect = CMMFControllerPluginSelectionParameters::NewL());
-    if (err) {
-        return CxeErrorHandlingSymbian::map(err);
-    }
-
-    TRAP(err, fSelect = CMMFFormatSelectionParameters::NewL());
-    if (err) {
-        if(cSelect) {
-            delete cSelect;
-        }
-        return CxeErrorHandlingSymbian::map(err);
-    }
-
-    TRAP( err, {
-        fSelect->SetMatchToMimeTypeL(aMimeType);
-        cSelect->SetRequiredRecordFormatSupportL(*fSelect);
-        cSelect->SetPreferredSupplierL(aSupplier,
-                                       CMMFPluginSelectionParameters::EOnlyPreferredSupplierPluginsReturned);
-        cSelect->ListImplementationsL(controllers);
-    } );
-
-    if (!err && controllers.Count() >= 1) {
-        // KErrNotFound is returned unless a controller is found
-        err = KErrNotFound;
-        // Get the controller UID.
-        mVideoControllerUid = controllers[0]->Uid();
-
-        // Inquires the controller about supported formats.
-        // We use the first controller found having index 0.
-        RMMFFormatImplInfoArray formats;
-        formats = controllers[0]->RecordFormats();
-
-        // Get the first format that supports our mime type.
-        int count = formats.Count();
-        for (int i=0; i<count; i++) {
-            if (formats[i]->SupportsMimeType(aMimeType)) {
-                mVideoFormatUid = formats[i]->Uid(); // set the UID
-                err = KErrNone;
-                break;
-            }
-        }
-    }
-    delete cSelect;
-    delete fSelect;
-    controllers.ResetAndDestroy();
-
-    CX_DEBUG_EXIT_FUNCTION();
-
-    return CxeErrorHandlingSymbian::map(err);
-}
-
-
 /*!
 * camera reference changing, release resources
 */
@@ -935,19 +582,24 @@
     CX_DEBUG_EXIT_FUNCTION();
 }
 
-
 /*!
-* new camera available,
+* new camera available
 */
 void CxeVideoCaptureControlSymbian::handleCameraAllocated(CxeError::Id error)
 {
     CX_DEBUG_ENTER_FUNCTION();
 
     if (!error) {
-        // initialize the video recorder utility
-        createVideoRecorder();
+        try {
+            // Create the video recorder utility
+            createVideoRecorder();
+        } catch (...) {
+            // We are just trying to create the recorder early.
+            // Retry later when preparing, and fail then if
+            // error still persists.
+        }
         // new camera available, read supported video qualities from icm
-        // load all still qualities supported by icm
+        // load all video qualities supported by icm
         mIcmSupportedVideoResolutions.clear();
         Cxe::CameraIndex cameraIndex = mCameraDeviceControl.cameraIndex();
         // get list of supported image qualities based on camera index
@@ -958,34 +610,21 @@
     CX_DEBUG_EXIT_FUNCTION();
 }
 
-
 /*!
 * Initializes video recorder.
+* May throw exception.
 */
 void CxeVideoCaptureControlSymbian::createVideoRecorder()
 {
     CX_DEBUG_ENTER_FUNCTION();
-
-    // init video recoder
-    if (state() == CxeVideoCaptureControl::Idle) {
-        if (mVideoRecorder == NULL) {
-            TRAPD(initErr, mVideoRecorder =
-                new CxeVideoRecorderUtilitySymbian( *this ,
-                            KAudioPriorityVideoRecording,
-                            TMdaPriorityPreference( KAudioPrefVideoRecording )));
-            if (initErr) {
-                CX_DEBUG(("WARNING - VideoRecorderUtility could not be reserved. Failed with err:%d", initErr));
-                mVideoRecorder = NULL;
-            }
-        }
+    if (mVideoRecorder == NULL) {
+        mVideoRecorder = new CxeVideoRecorderUtilitySymbian(*this);
     }
-
     CX_DEBUG_EXIT_FUNCTION();
 }
 
-
 /*!
-* releases resources used by videocapture
+* releases resources used by video capture control
 */
 void CxeVideoCaptureControlSymbian::releaseResources()
 {
@@ -1013,18 +652,16 @@
     CX_DEBUG_EXIT_FUNCTION();
 }
 
-
 /*!
-Returns current state of videocapture
+* Returns current state of video capture control
 */
 CxeVideoCaptureControl::State CxeVideoCaptureControlSymbian::state() const
 {
     return static_cast<CxeVideoCaptureControl::State> (stateId());
 }
 
-
 /*!
-* slot called when state is changed.
+* Called when state is changed.
 */
 void CxeVideoCaptureControlSymbian::handleStateChanged(int newStateId, CxeError::Id error)
 {
@@ -1047,7 +684,6 @@
     emit stateChanged(static_cast<State> (newStateId), error);
 }
 
-
 /*!
 * Initialize states for videocapturecontrol
 */
@@ -1066,7 +702,6 @@
     setInitialState(Idle);
 }
 
-
 /*!
 * Updates remaining video recordng time counter to all the video qualities supported by ICM
 * this should be done whenever storage location setting changes and when values are
@@ -1078,7 +713,7 @@
 
     for( int index = 0; index < mIcmSupportedVideoResolutions.count(); index++) {
         CxeVideoDetails &qualityDetails = mIcmSupportedVideoResolutions[index];
-        calculateRemainingTime(qualityDetails, qualityDetails.mRemainingTime);
+        qualityDetails.mRemainingTime = calculateRemainingTime(qualityDetails);
     }
 
     CX_DEBUG_EXIT_FUNCTION();
@@ -1093,14 +728,12 @@
 
     if (state() == CxeVideoCaptureControl::Recording ||
         state() == CxeVideoCaptureControl::Paused) {
-        TTimeIntervalMicroSeconds remaining = 0;
-        remaining = mVideoRecorder->RecordTimeAvailable();
-        time = remaining.Int64() * 1.0 / KOneSecond;
-        CX_DEBUG(( "timeRemaining2: %d", time ));
+        time = mVideoRecorder->availableRecordingTime();
+        CX_DEBUG(("CxeVideoCaptureControlSymbian - time remaining: %d", time));
     } else {
         // Check if we need to recalculate the remaining time.
         if (mCurrentVideoDetails.mRemainingTime == CxeVideoDetails::UNKNOWN) {
-            calculateRemainingTime(mCurrentVideoDetails, mCurrentVideoDetails.mRemainingTime);
+            mCurrentVideoDetails.mRemainingTime = calculateRemainingTime(mCurrentVideoDetails);
         }
         time = mCurrentVideoDetails.mRemainingTime;
     }
@@ -1108,99 +741,41 @@
     CX_DEBUG_EXIT_FUNCTION();
 }
 
-
-
 /*!
-* algorithm to calculate remaining recording time
-@ param videoDetails contains the current video resolution that is in use.
-@ time contains the remaining recording time
+* Get the remaining recording time
+* @param videoDetails Contains the current video resolution that is in use.
+* @return The remaining recording time
 */
-void CxeVideoCaptureControlSymbian::calculateRemainingTime(CxeVideoDetails videoDetails, int &time)
+int CxeVideoCaptureControlSymbian::calculateRemainingTime(const CxeVideoDetails& videoDetails)
 {
     CX_DEBUG_ENTER_FUNCTION();
-
-    TTimeIntervalMicroSeconds remaining = 0;
-
-    // get available space in the drive selected in the settings
-    // for storing videos
-    qint64 availableSpace = mDiskMonitor.free();
-
-    availableSpace = availableSpace - KMinRequiredSpaceVideo;
-
-    // Maximum clip size may be limited for mms quality.
-    // If mMaximumSizeInBytes == 0, no limit is specified.
-    if (videoDetails.mMaximumSizeInBytes > 0 && videoDetails.mMaximumSizeInBytes < availableSpace) {
-        availableSpace = videoDetails.mMaximumSizeInBytes;
-    }
-
-    // Use average audio/video bitrates to estimate remaining time
-    quint32  averageBitRate = 0;
-    quint32  averageByteRate = 0;
-    qreal    scaler = mQualityPresets.avgVideoBitRateScaler();
-
-    if (scaler == 0) {
-        // video bit rate scaler is 0, use the constant value
-        scaler = KCMRAvgVideoBitRateScaler;
-    }
-
-    int avgVideoBitRate = (videoDetails.mVideoBitRate * scaler);
-    int avgAudioBitRate =  videoDetails.mAudioBitRate;
-
-    int muteSetting = 0; // audio enabled
-    mSettings.get(CxeSettingIds::VIDEO_MUTE_SETTING, muteSetting);
-
-    if (muteSetting == 1) {
-        // audio disabled from setting. hence no audio
-        avgAudioBitRate = 0;
-    }
-
-    averageBitRate = (quint32)(
-                     (avgVideoBitRate + avgAudioBitRate) * KMetaDataCoeff);
-
-    averageByteRate = averageBitRate / 8;
-
-    if (availableSpace <= 0) {
-        remaining = 0;
-    } else {
-        // converting microseconds to seconds
-        remaining = availableSpace * KOneMillion / averageByteRate;
-        if ( (remaining.Int64()) > (quint64(KCamCMaxClipDurationInSecs) * KOneMillion) ) {
-            remaining = (quint64(KCamCMaxClipDurationInSecs) * KOneMillion);
-        }
-    }
-    if ( remaining <= quint64(0) ) {
-        remaining = 0;
-    }
-
-    time = remaining.Int64() * 1.0 / KOneSecond;
-
-    CX_DEBUG(( "remaining time from algorithm: %d", time ));
-
+    qint64 availableSpace = mDiskMonitor.free() - KMinRequiredSpaceVideo;
+    int time = mQualityPresets.recordingTimeAvailable(videoDetails, availableSpace);
     CX_DEBUG_EXIT_FUNCTION();
+    return time;
 }
 
-
 /*!
-* Calculates remaining recording time during video recording
+* Calculates elapsed recording time during video recording
+* @return Did fetching elapsed time succeed.
 */
 bool CxeVideoCaptureControlSymbian::elapsedTime(int &time)
 {
     CX_DEBUG_ENTER_FUNCTION();
 
-    TTimeIntervalMicroSeconds timeElapsed = 0;
     bool ok = false;
     if (state() == CxeVideoCaptureControl::Recording ||
         state() == CxeVideoCaptureControl::Paused) {
-        TRAPD( err, timeElapsed = mVideoRecorder->DurationL() );
-        if (!err) {
-            time = timeElapsed.Int64() * 1.0 / KOneSecond;
-            CX_DEBUG(("timeElapsed2: %d", time));
+        try {
+            time = mVideoRecorder->duration();
+            CX_DEBUG(("CxeVideoCaptureControlSymbian - elapsed: %d", time));
             ok = true;
+        } catch (const std::exception &e) {
+            // Returning false.
         }
     }
 
     CX_DEBUG_EXIT_FUNCTION();
-
     return ok;
 }
 
@@ -1214,8 +789,7 @@
     // start recording, if we were playing capture sound
     if (state() == CxeVideoCaptureControl::PlayingStartSound) {
         setState(CxeVideoCaptureControl::Recording);
-
-        mVideoRecorder->Record();
+        mVideoRecorder->record();
     }
 
     // in case of video capture stop sound playing, nothing needs to be done
@@ -1224,6 +798,23 @@
     CX_DEBUG_EXIT_FUNCTION();
 }
 
+/*!
+* Handle new snapshot.
+* @param status Status code for getting the snapshot.
+* @param snapshot Snapshot pixmap. Empty if error code reported.
+*/
+void CxeVideoCaptureControlSymbian::handleSnapshotReady(CxeError::Id status, const QPixmap& snapshot)
+{
+    CX_DEBUG_ENTER_FUNCTION();
+
+    if (mCameraDeviceControl.mode() == Cxe::VideoMode) {
+        // Need to store snapshot for ui to be able to get it also later.
+        mSnapshot = snapshot;
+        emit snapshotReady(status, snapshot, filename());
+    }
+
+    CX_DEBUG_EXIT_FUNCTION();
+}
 
 /*!
 * setting has changed, check if we are interested.
@@ -1247,7 +838,7 @@
             // mute setting changed, apply the new setting and re-prepare.
             setState(Preparing);
             prepare();
-        } else if (settingId == CxeSettingIds::FRAME_RATE){
+        } else if (settingId == CxeSettingIds::FRAME_RATE) {
             // Frame rate setting changed. Need to re-prepare if we are prepared already.
             // Otherwise can wait for next init call.
             if (state() == Ready) {
@@ -1268,6 +859,7 @@
  */
 void CxeVideoCaptureControlSymbian::handleSceneChanged(CxeScene& scene)
 {
+    Q_UNUSED(scene)
     CX_DEBUG_ENTER_FUNCTION();
 
     // make sure we are in video mode
@@ -1293,8 +885,7 @@
     // Ignore updates on preparing phase.
     if (state() == CxeVideoCaptureControl::Ready) {
 
-        int time(0);
-        calculateRemainingTime(mCurrentVideoDetails, time);
+        int time(calculateRemainingTime(mCurrentVideoDetails));
 
         if (time !=  mCurrentVideoDetails.mRemainingTime) {
             mCurrentVideoDetails.mRemainingTime = time;
@@ -1316,4 +907,32 @@
     return mIcmSupportedVideoResolutions;
 }
 
+/*!
+* Helper method to handle error during preparing phase.
+*/
+void CxeVideoCaptureControlSymbian::handlePrepareFailed()
+{
+    CX_DEBUG_ENTER_FUNCTION();
+    CX_DEBUG(("[ERROR] Preparing video failed!"));
+    // Cleanup
+    deinit();
+    // Inform client
+    emit videoPrepareComplete(CxeError::InitializationFailed);
+    CX_DEBUG_EXIT_FUNCTION();
+}
+
+/*!
+* Helper method to handle error from video composing.
+* @param error Symbian error code.
+*/
+void CxeVideoCaptureControlSymbian::handleComposeFailed(int error)
+{
+    CX_DEBUG_ENTER_FUNCTION();
+    CX_DEBUG(("[ERROR] Composing video failed!"));
+    // Inform client
+    emit videoComposed(CxeErrorHandlingSymbian::map(error), filename());
+    // Cleanup
+    deinit();
+    CX_DEBUG_EXIT_FUNCTION();
+}
 // End of file