camerauis/cameraxui/cxengine/src/cxevideocapturecontrolsymbian.cpp
branchRCL_3
changeset 23 61bc0f252b2b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/camerauis/cameraxui/cxengine/src/cxevideocapturecontrolsymbian.cpp	Tue Aug 31 15:03:46 2010 +0300
@@ -0,0 +1,1002 @@
+/*
+* 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"
+* 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:
+*
+*/
+
+#include <algorithm>
+#include <exception>
+#include <QTime>
+#include <QPixmap>
+#include <coemain.h>
+#include <QStringList>
+
+#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"
+#include "cxestate.h"
+#include "cxesettings.h"
+#include "cxenamespace.h"
+#include "cxesoundplayersymbian.h"
+#include "cxequalitypresetssymbian.h"
+#include "cxeviewfindercontrolsymbian.h"
+#include "cxediskmonitor.h"
+#include "cxesettingsmappersymbian.h"
+
+#include "OstTraceDefinitions.h"
+#ifdef OST_TRACE_COMPILER_IN_USE
+#include "cxevideocapturecontrolsymbianTraces.h"
+#endif
+
+
+// constants
+namespace
+{
+    // TMMFEvent UIDs for Async stop
+    const TUid KCamCControllerCCVideoRecordStopped = {0x2000E546};
+    const TUid KCamCControllerCCVideoFileComposed = {0x2000E547};
+
+    const TInt64  KMinRequiredSpaceVideo      = 4000000;
+}
+
+
+/*!
+* CxeVideoCaptureControlSymbian::CxeVideoCaptureControlSymbian
+*/
+CxeVideoCaptureControlSymbian::CxeVideoCaptureControlSymbian(
+    CxeCameraDevice &cameraDevice,
+    CxeViewfinderControl &viewfinderControl,
+    CxeSnapshotControl &snapshotControl,
+    CxeCameraDeviceControl &cameraDeviceControl,
+    CxeFilenameGenerator &nameGenerator,
+    CxeSettings &settings,
+    CxeQualityPresets &qualityPresets,
+    CxeDiskMonitor &diskMonitor)
+    : CxeStateMachine("CxeVideoCaptureControlSymbian"),
+      mVideoRecorder(NULL),
+      mCameraDevice(cameraDevice),
+      mCameraDeviceControl(cameraDeviceControl),
+      mViewfinderControl(viewfinderControl),
+      mSnapshotControl(snapshotControl),
+      mFilenameGenerator(nameGenerator),
+      mSettings(settings),
+      mQualityPresets(qualityPresets),
+      mDiskMonitor(diskMonitor),
+      mSnapshot(),
+      mVideoStartSoundPlayer(NULL),
+      mVideoStopSoundPlayer(NULL),
+      mCurrentFilename("")
+{
+    CX_DEBUG_ENTER_FUNCTION();
+    OstTrace0(camerax_performance, CXEVIDEOCAPTURECONTROLSYMBIAN_CREATE_IN, "msg: e_CX_VIDEOCAPTURECONTROL_NEW 1");
+
+    qRegisterMetaType<CxeVideoCaptureControl::State> ();
+    initializeStates();
+
+    mVideoStopSoundPlayer = new
+             CxeSoundPlayerSymbian(CxeSoundPlayerSymbian::VideoCaptureStop,
+                                   mSettings);
+    mVideoStartSoundPlayer = new
+             CxeSoundPlayerSymbian(CxeSoundPlayerSymbian::VideoCaptureStart,
+                                   mSettings);
+
+    // If camera is already allocated, call the slot ourselves.
+    if (mCameraDevice.camera()) {
+        handleCameraAllocated(CxeError::None);
+    }
+
+    OstTrace0(camerax_performance, CXEVIDEOCAPTURECONTROLSYMBIAN_CREATE_M1, "msg: e_CX_ENGINE_CONNECT_SIGNALS 1");
+    // connect signals from cameraDevice, so we recieve events when camera reference changes
+    connect(&cameraDevice, SIGNAL(prepareForCameraDelete()),
+            this, SLOT(prepareForCameraDelete()));
+    connect(&cameraDevice, SIGNAL(prepareForRelease()),
+            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 QImage&)),
+            this, SLOT(handleSnapshotReady(CxeError::Id, const QImage&)));
+
+    // enabling setting change callbacks to videocapturecontrol
+    connect(&mSettings, SIGNAL(settingValueChanged(const QString&,QVariant)),
+            this, SLOT(handleSettingValueChanged(const QString&,QVariant)));
+
+    mSettings.listenForSetting(CxeSettingIds::VIDEO_SCENE, this, SLOT(handleSceneChanged(const QVariant&)));
+
+    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()
+*/
+CxeVideoCaptureControlSymbian::~CxeVideoCaptureControlSymbian()
+{
+    CX_DEBUG_ENTER_FUNCTION();
+
+    releaseResources();
+    mIcmSupportedVideoResolutions.clear();
+    delete mVideoStartSoundPlayer;
+    delete mVideoStopSoundPlayer;
+
+    CX_DEBUG_EXIT_FUNCTION();
+}
+
+/*!
+* Initializes resources for video recording.
+*/
+void CxeVideoCaptureControlSymbian::init()
+{
+    CX_DEBUG_ENTER_FUNCTION();
+    OstTrace0( camerax_performance, CXEVIDEOCAPTURECONTROLSYMBIAN_INIT, "msg: e_CX_VIDEO_CAPCONT_INIT 1" );
+
+    if (state() == Idle) {
+        // start initializing resources for video capture
+        initVideoRecorder();
+    } else if (state() == Initialized) {
+        // video recorder already initalized. Continue to prepare video reocording.
+        open();
+    }
+
+    OstTrace0( camerax_performance, DUP1_CXEVIDEOCAPTURECONTROLSYMBIAN_INIT, "msg: e_CX_VIDEO_CAPCONT_INIT 0" );
+    CX_DEBUG_EXIT_FUNCTION();
+}
+
+/*!
+* Releases all resources
+*/
+void CxeVideoCaptureControlSymbian::deinit()
+{
+    CX_DEBUG_ENTER_FUNCTION();
+
+    // Nothing to do if already idle.
+    if(state() != Idle) {
+        OstTrace0( camerax_performance, CXEVIDEOCAPTURECONTROLSYMBIAN_DEINIT, "msg: e_CX_VIDEO_CAPCONT_DEINIT 1" );
+
+        // first stop viewfinder
+        mViewfinderControl.stop();
+
+        // stop video-recording in-case if its ongoing.
+        stop();
+
+        // Check if state is stopping, in which case we have to inform the
+        // file harvester that a file is to be completed. We would not
+        // call harvestFile otherwise in this case.
+        // Otherwise the video will not be found from videos app.
+        if (state() == Stopping) {
+            emit videoComposed(CxeError::None, mCurrentFilename);
+        }
+
+        mSnapshotControl.stop();
+
+        if (mVideoRecorder) {
+            mVideoRecorder->close();
+        }
+
+        setState(Idle);
+
+        OstTrace0( camerax_performance, DUP1_CXEVIDEOCAPTURECONTROLSYMBIAN_DEINIT, "msg: e_CX_VIDEO_CAPCONT_DEINIT 0" );
+    }
+    CX_DEBUG_EXIT_FUNCTION();
+}
+
+/*!
+* Intializes VideoRecorder for recording.
+*/
+void CxeVideoCaptureControlSymbian::initVideoRecorder()
+{
+    CX_DEBUG_ENTER_FUNCTION();
+
+    // Init needed only in Idle state
+    if (state() == Idle) {
+        try {
+            // If video recorder is not yet created, do it now.
+            createVideoRecorder();
+
+            // Update current video quality details from ICM.
+            // Throws an error if unable to get the quality.
+            updateVideoCaptureParameters();
+
+            // Video recorder is ready to open video file for recording.
+            setState(Initialized);
+            open();
+        } catch (const std::exception &e) {
+            // Handle error
+            handlePrepareFailed();
+        }
+    }
+
+    CX_DEBUG_EXIT_FUNCTION();
+}
+
+/*!
+* Opens file for video recording.
+*/
+void CxeVideoCaptureControlSymbian::open()
+{
+    CX_DEBUG_ENTER_FUNCTION();
+
+    // 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() ));
+
+            // Start preparing..
+            setState(CxeVideoCaptureControl::Preparing);
+
+            // 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();
+}
+
+/*!
+* Helper method for generating filename.
+* Throws exception, if file type mime is formatted wrong or
+* filename generation fails.
+*/
+void CxeVideoCaptureControlSymbian::generateFilename()
+{
+    CX_DEBUG_ENTER_FUNCTION();
+    mCurrentFilename = QString("");
+
+    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];
+
+    // Generate new filename and open the file for writing video data
+    CxeException::throwIfError(mFilenameGenerator.generateFilename(mCurrentFilename, fileExt));
+
+    CX_DEBUG_EXIT_FUNCTION();
+}
+
+/*!
+* Prepare Video Recorder with necessary settings for video capture.
+*/
+void CxeVideoCaptureControlSymbian::prepare()
+{
+    CX_DEBUG_ENTER_FUNCTION();
+
+    if (state() != Preparing) {
+        // not valid state to continue prepare.
+        return;
+    }
+
+    OstTrace0(camerax_performance, CXEVIDEOCAPTURECONTROL_PREPARE_1, "msg: e_CX_VIDCAPCONT_PREPARE 1");
+    QSize frameSize(mCurrentVideoDetails.mWidth, mCurrentVideoDetails.mHeight);
+
+    bool muteSetting = mSettings.get<bool>(CxeSettingIds::VIDEO_MUTE_SETTING, false);
+
+    // Check if scene defines frame rate.
+    // Use generic frame rate defined in video details, if no value is set in scene.
+    int frameRate = mSettings.get<int>(CxeSettingIds::FRAME_RATE, 0);
+    if (frameRate <= 0) {
+        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));
+
+    try {
+        mVideoRecorder->setVideoFrameSize(frameSize);
+        mVideoRecorder->setVideoFrameRate(frameRate);
+        mVideoRecorder->setVideoBitRate(mCurrentVideoDetails.mVideoBitRate);
+        mVideoRecorder->setAudioEnabled(!muteSetting);
+        // "No limit" value is handled in video recorder wrapper.
+        mVideoRecorder->setVideoMaxSize(mCurrentVideoDetails.mMaximumSizeInBytes);
+
+        // Settings have been applied successfully, start to prepare.
+        mVideoRecorder->prepare();
+
+        // Prepare zoom only when there are no errors during prepare.
+        emit prepareZoomForVideo();
+        emit videoPrepareComplete(CxeError::None);
+    } catch (const std::exception &e) {
+        // Handle error.
+        handlePrepareFailed();
+    }
+
+    OstTrace0(camerax_performance, CXEVIDEOCAPTURECONTROL_PREPARE_2, "msg: e_CX_VIDCAPCONT_PREPARE 0");
+    CX_DEBUG_EXIT_FUNCTION();
+}
+
+/*!
+* Prepare video snapshot.
+* Throws exception on error.
+*/
+void CxeVideoCaptureControlSymbian::prepareSnapshot()
+{
+    CX_DEBUG_ENTER_FUNCTION();
+    OstTrace0( camerax_performance, CXEVIDEOCAPTURECONTROL_PREPARESNAP_1, "msg: e_CX_PREPARE_SNAPSHOT 1" );
+
+    // Prepare snapshot. Snapshot control throws error if problems.
+    QSize snapshotSize = mSnapshotControl.calculateSnapshotSize(
+                            mViewfinderControl.deviceDisplayResolution(),
+                            mCurrentVideoDetails.mAspectRatio);
+    mSnapshotControl.start(snapshotSize);
+
+    OstTrace0( camerax_performance, CXEVIDEOCAPTURECONTROL_PREPARESNAP_2, "msg: e_CX_PREPARE_SNAPSHOT 0" );
+    CX_DEBUG_EXIT_FUNCTION();
+}
+
+/*!
+  Fetch video quality details based on current video quality setting.
+*/
+void CxeVideoCaptureControlSymbian::updateVideoCaptureParameters()
+{
+    CX_DEBUG_ENTER_FUNCTION();
+    OstTrace0(camerax_performance, CXEVIDEOCAPTURECONTROL_UPDATEVIDEOCAPTUREPARAMETERS_1, "msg: e_CX_UPDATE_VIDEO_CAPTURE_PARAMETERS 1");
+
+    int quality = 0;
+
+    // Get quality index for primary camera. Only one quality for secondary camera.
+    if (mCameraDeviceControl.cameraIndex() == Cxe::PrimaryCameraIndex) {
+        quality = mSettings.get<int>(CxeSettingIds::VIDEO_QUALITY);
+    }
+
+    if (quality < 0 || quality >= mIcmSupportedVideoResolutions.count()) {
+       throw new CxeException(CxeError::NotFound);
+    }
+
+    // Get video quality details
+    mCurrentVideoDetails = mIcmSupportedVideoResolutions.at(quality);
+
+    OstTrace0(camerax_performance, CXEVIDEOCAPTURECONTROL_UPDATEVIDEOCAPTUREPARAMETERS_2, "msg: e_CX_UPDATE_VIDEO_CAPTURE_PARAMETERS 0");
+    CX_DEBUG_EXIT_FUNCTION();
+}
+
+/*!
+* Resets the video snapshot and current video filename
+*/
+void CxeVideoCaptureControlSymbian::reset()
+{
+    CX_DEBUG_ENTER_FUNCTION();
+
+    // Snapshot will consume considerably memory.
+    // Replace it with null pixmap to have it freed.
+    mSnapshot = QPixmap();
+    // reset the current file name.
+    mCurrentFilename = QString("");
+
+    CX_DEBUG_EXIT_FUNCTION();
+}
+
+/*!
+* Returns current video filename
+*/
+QString CxeVideoCaptureControlSymbian::filename() const
+{
+    // Simply return the current contents of mCurrentFilename.
+    // If video recording was started then it returns proper filename
+    // otherwise an empty string is returned.
+    return mCurrentFilename;
+}
+
+/*!
+* Returns current video snapshot
+*/
+QPixmap CxeVideoCaptureControlSymbian::snapshot() const
+{
+    return mSnapshot;
+}
+
+/*!
+* Starts video recording if we are in appropriate state.
+*/
+void CxeVideoCaptureControlSymbian::record()
+{
+    CX_DEBUG_ENTER_FUNCTION();
+
+    if (state() == Ready || state() == Paused) {
+        // ask the player to play the sound
+        // recording will start once start sound is played
+        setState(CxeVideoCaptureControl::PlayingStartSound);
+        mVideoStartSoundPlayer->play();
+    }
+
+    CX_DEBUG_EXIT_FUNCTION();
+}
+
+/*!
+* Pauses video recording.
+*/
+void CxeVideoCaptureControlSymbian::pause()
+{
+    CX_DEBUG_ENTER_FUNCTION();
+    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.
+*/
+void CxeVideoCaptureControlSymbian::stop()
+{
+    CX_DEBUG_ENTER_FUNCTION();
+
+    if (state() == Recording || state() == Paused) {
+        // first stop viewfinder
+        mViewfinderControl.stop();
+
+        try {
+            // Try asynchronous stopping first.
+            mVideoRecorder->stop(true);
+            // No error from asynchronous stop -> wait for stop event
+            if (state() != Ready) {
+                setState(Stopping);
+            }
+        } catch (const std::exception &e) {
+            CX_DEBUG(("CxeVideoCaptureControlSymbian - async stop failed, try sync.."));
+            try {
+                mVideoRecorder->stop(false);
+                // stopping went ok
+                emulateNormalStopping();
+            } catch (const std::exception &e) {
+                // Even synchronous stopping failed -> release resources.
+                CX_DEBUG(("CxeVideoCaptureControlSymbian - sync stop failed, too!"));
+                handleComposeFailed(qt_symbian_exception2Error(e));
+            }
+        }
+    }
+
+    CX_DEBUG_EXIT_FUNCTION();
+}
+
+/*!
+* Callback when "Open" operation is complete.
+*/
+void CxeVideoCaptureControlSymbian::MvruoOpenComplete(TInt aError)
+{
+    CX_DEBUG_ENTER_FUNCTION();
+    CX_DEBUG(("CxeVideoCaptureControlSymbian::MvruoOpenComplete, err=%d", aError));
+
+    if (state() == Preparing) {
+        if (!aError) {
+            prepare();
+        } else {
+            handlePrepareFailed();
+        }
+    }
+
+    CX_DEBUG_EXIT_FUNCTION();
+}
+
+/*!
+* Callback when "Prepare" request is complete.
+*/
+void CxeVideoCaptureControlSymbian::MvruoPrepareComplete(TInt aError)
+{
+    CX_DEBUG_ENTER_FUNCTION();
+    CX_DEBUG(("CxeVideoCaptureControlSymbian::MvruoPrepareComplete, err=%d", aError));
+
+    if (state() == Preparing) {
+        try {
+            // Check that no error coming in.
+            CxeException::throwIfError(aError);
+            // Start viewfinder
+            mViewfinderControl.start();
+            // Prepare snapshot (throws exception if fails).
+            prepareSnapshot();
+            // Ready for recording now.
+            setState(CxeVideoCaptureControl::Ready);
+            OstTrace0( camerax_performance, CXEVIDEOCAPTURECONTROLSYMBIAN_GOTOVIDEO, "msg: e_CX_GO_TO_VIDEO_MODE 0" );
+        } catch (const std::exception &e) {
+            handlePrepareFailed();
+        }
+    }
+
+    CX_DEBUG_EXIT_FUNCTION();
+}
+
+/*!
+* Callback when "Record" operation is complete.
+*/
+void CxeVideoCaptureControlSymbian::MvruoRecordComplete(TInt aError)
+{
+    CX_DEBUG_ENTER_FUNCTION();
+    CX_DEBUG(("CxeVideoCaptureControlSymbian::MvruoRecordComplete, err=%d", aError));
+
+    //! async stop customcommand stuff
+    if (aError == KErrNone) {
+        setState(CxeVideoCaptureControl::Ready);
+    } else if (aError == KErrCompletion) {
+        // KErrCompletion is received when video recording stops
+        // because of maximum clip size is reached. Emulate
+        // normal stopping.
+        emulateNormalStopping();
+    }
+    else {
+        // error during recording, report to client
+        handleComposeFailed(aError);
+    }
+
+    CX_DEBUG_EXIT_FUNCTION();
+}
+
+/*!
+* Callback from MVideoRecorderUtilityObserver
+*/
+void CxeVideoCaptureControlSymbian::MvruoEvent(const TMMFEvent& aEvent)
+{
+    CX_DEBUG_ENTER_FUNCTION();
+
+    if (aEvent.iEventType.iUid == KCamCControllerCCVideoRecordStopped.iUid) {
+        CX_DEBUG(("KCamCControllerCCVideoRecordStopped"));
+        // play the sound, but not changing the state
+        mVideoStopSoundPlayer->play();
+    } else if (aEvent.iEventType.iUid == KCamCControllerCCVideoFileComposed.iUid) {
+        CX_DEBUG(("KCamCControllerCCVideoFileComposed"));
+        if (state() == Stopping) {
+            // 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());
+    } else {
+        CX_DEBUG(("ignoring unknown MvruoEvent 0x%08x", aEvent.iEventType.iUid ));
+    }
+
+    CX_DEBUG_EXIT_FUNCTION();
+}
+
+/*!
+* camera reference changing, release resources
+*/
+void CxeVideoCaptureControlSymbian::prepareForCameraDelete()
+{
+    CX_DEBUG_ENTER_FUNCTION();
+    releaseResources();
+    CX_DEBUG_EXIT_FUNCTION();
+}
+
+/*!
+* prepare for camera release.
+*/
+void CxeVideoCaptureControlSymbian::prepareForRelease()
+{
+    CX_DEBUG_ENTER_FUNCTION();
+    deinit();
+    CX_DEBUG_EXIT_FUNCTION();
+}
+
+/*!
+* new camera available
+*/
+void CxeVideoCaptureControlSymbian::handleCameraAllocated(CxeError::Id error)
+{
+    CX_DEBUG_ENTER_FUNCTION();
+
+    if (!error) {
+        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 video qualities supported by icm
+        mIcmSupportedVideoResolutions.clear();
+        Cxe::CameraIndex cameraIndex = mCameraDeviceControl.cameraIndex();
+        // get list of supported image qualities based on camera index
+        mIcmSupportedVideoResolutions =
+                mQualityPresets.videoQualityPresets(cameraIndex);
+    }
+
+    CX_DEBUG_EXIT_FUNCTION();
+}
+
+/*!
+* Initializes video recorder.
+* May throw exception.
+*/
+void CxeVideoCaptureControlSymbian::createVideoRecorder()
+{
+    CX_DEBUG_ENTER_FUNCTION();
+    if (mVideoRecorder == NULL) {
+        mVideoRecorder = new CxeVideoRecorderUtilitySymbian(*this);
+    }
+    CX_DEBUG_EXIT_FUNCTION();
+}
+
+/*!
+* releases resources used by video capture control
+*/
+void CxeVideoCaptureControlSymbian::releaseResources()
+{
+    CX_DEBUG_ENTER_FUNCTION();
+
+    // first de-init videocapture control
+    deinit();
+    reset();
+
+    delete mVideoRecorder;
+    mVideoRecorder = NULL;
+
+    CX_DEBUG_EXIT_FUNCTION();
+}
+
+/*!
+* Returns current state of video capture control
+*/
+CxeVideoCaptureControl::State CxeVideoCaptureControlSymbian::state() const
+{
+    return static_cast<CxeVideoCaptureControl::State> (stateId());
+}
+
+/*!
+* Called when state is changed.
+*/
+void CxeVideoCaptureControlSymbian::handleStateChanged(int newStateId, CxeError::Id error)
+{
+    switch (newStateId) {
+    case Ready:
+        if (error == CxeError::None && !mDiskMonitor.isMonitoring()) {
+            mDiskMonitor.start();
+            connect(&mDiskMonitor, SIGNAL(diskSpaceChanged()), this, SLOT(handleDiskSpaceChanged()));
+        }
+        break;
+    default:
+        // Stop monitoring when video mode is released.
+        // Same goes during recording, as video times come from recorder.
+        if (mDiskMonitor.isMonitoring()) {
+            mDiskMonitor.stop();
+            disconnect(&mDiskMonitor, SIGNAL(diskSpaceChanged()), this, SLOT(handleDiskSpaceChanged()));
+        }
+        break;
+    }
+    emit stateChanged(static_cast<State> (newStateId), error);
+}
+
+/*!
+* Initialize states for videocapturecontrol
+*/
+void CxeVideoCaptureControlSymbian::initializeStates()
+{
+    // addState( id, name, allowed next states )
+    addState(new CxeState(Idle, "Idle", Initialized));
+    addState(new CxeState(Initialized, "Initialized", Preparing | Idle));
+    addState(new CxeState(Preparing, "Preparing", Ready | Idle));
+    addState(new CxeState(Ready, "Ready", Recording | PlayingStartSound | Preparing | Idle));
+    addState(new CxeState(Recording, "Recording", Recording | Paused | Stopping | Idle | Ready));
+    addState(new CxeState(Paused, "Paused", Recording | Stopping | PlayingStartSound | Idle));
+    addState(new CxeState(Stopping, "Stopping", Initialized | Idle | Ready));
+    addState(new CxeState(PlayingStartSound, "PlayingStartSound", Recording | Idle));
+
+    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
+* read from ICM for the first time
+*/
+void CxeVideoCaptureControlSymbian::updateRemainingRecordingTimeCounter()
+{
+    CX_DEBUG_ENTER_FUNCTION();
+
+    for( int index = 0; index < mIcmSupportedVideoResolutions.count(); index++) {
+        CxeVideoDetails &qualityDetails = mIcmSupportedVideoResolutions[index];
+        qualityDetails.mRemainingTime = calculateRemainingTime(qualityDetails);
+    }
+
+    CX_DEBUG_EXIT_FUNCTION();
+}
+
+/*!
+* calculates remaining video recording time.
+*/
+void CxeVideoCaptureControlSymbian::remainingTime(int &time)
+{
+    CX_DEBUG_ENTER_FUNCTION();
+
+    if (state() == CxeVideoCaptureControl::Recording ||
+        state() == CxeVideoCaptureControl::Paused) {
+        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) {
+            mCurrentVideoDetails.mRemainingTime = calculateRemainingTime(mCurrentVideoDetails);
+        }
+        time = mCurrentVideoDetails.mRemainingTime;
+    }
+
+    CX_DEBUG_EXIT_FUNCTION();
+}
+
+/*!
+* Get the remaining recording time
+* @param videoDetails Contains the current video resolution that is in use.
+* @return The remaining recording time
+*/
+int CxeVideoCaptureControlSymbian::calculateRemainingTime(const CxeVideoDetails& videoDetails)
+{
+    CX_DEBUG_ENTER_FUNCTION();
+    qint64 availableSpace = mDiskMonitor.free() - KMinRequiredSpaceVideo;
+    int time = mQualityPresets.recordingTimeAvailable(videoDetails, availableSpace);
+    CX_DEBUG_EXIT_FUNCTION();
+    return time;
+}
+
+/*!
+* Calculates elapsed recording time during video recording
+* @return Did fetching elapsed time succeed.
+*/
+bool CxeVideoCaptureControlSymbian::elapsedTime(int &time)
+{
+    CX_DEBUG_ENTER_FUNCTION();
+
+    bool ok = false;
+    if (state() == CxeVideoCaptureControl::Recording ||
+        state() == CxeVideoCaptureControl::Paused) {
+        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;
+}
+
+/*!
+* slot called when playing a sound has finished.
+*/
+void CxeVideoCaptureControlSymbian::handleSoundPlayed()
+{
+    CX_DEBUG_ENTER_FUNCTION();
+
+    // start recording, if we were playing capture sound
+    if (state() == CxeVideoCaptureControl::PlayingStartSound) {
+        setState(CxeVideoCaptureControl::Recording);
+        mVideoRecorder->record();
+    }
+
+    // in case of video capture stop sound playing, nothing needs to be done
+    // meaning the state set elsewhere, and the video capture has been stopped already
+
+    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 QImage &snapshot)
+{
+    CX_DEBUG_ENTER_FUNCTION();
+
+    if (mCameraDeviceControl.mode() == Cxe::VideoMode) {
+        OstTrace0(camerax_performance, CXEVIDEOCAPTURECONTROL_HANDLESNAPSHOT_1, "msg: e_CX_HANDLE_SNAPSHOT 1");
+
+        // Need to store snapshot for ui to be able to get it also later.
+        mSnapshot = QPixmap::fromImage(snapshot);
+        emit snapshotReady(status, snapshot, filename());
+
+        OstTrace0(camerax_performance, CXEVIDEOCAPTURECONTROL_HANDLESNAPSHOT_2, "msg: e_CX_HANDLE_SNAPSHOT 0");
+    }
+
+    CX_DEBUG_EXIT_FUNCTION();
+}
+
+/*!
+* setting has changed, check if we are interested.
+*/
+void CxeVideoCaptureControlSymbian::handleSettingValueChanged(const QString& settingId,
+                                                              QVariant newValue)
+{
+    CX_DEBUG_ENTER_FUNCTION();
+    Q_UNUSED(newValue);
+
+    if (mCameraDeviceControl.mode() == Cxe::VideoMode) {
+        if (settingId == CxeSettingIds::VIDEO_QUALITY) {
+            // re-prepare for video
+            if (state() == Ready) {
+                // release resources
+                deinit();
+                // initialize video recording again
+                init();
+            }
+        } else if (settingId == CxeSettingIds::VIDEO_MUTE_SETTING) {
+            // mute setting changed, apply the new setting and re-prepare.
+            setState(Preparing);
+            prepare();
+        } 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) {
+                setState(Preparing);
+                prepare();
+            }
+        } else {
+            // Setting not relevant to video mode
+        }
+    }
+
+    CX_DEBUG_EXIT_FUNCTION();
+}
+
+/*!
+ * Scene mode changed. We need to know about it because frame rate
+ * might have changed.
+ */
+void CxeVideoCaptureControlSymbian::handleSceneChanged(const QVariant& scene)
+{
+    Q_UNUSED(scene)
+    CX_DEBUG_ENTER_FUNCTION();
+
+    // make sure we are in video mode
+    if (mCameraDeviceControl.mode() == Cxe::VideoMode) {
+        // Frame rate setting might have changed so re-prepare.
+        if (state() == Ready) {
+            setState(Preparing);
+            prepare();
+        }
+
+    }
+    CX_DEBUG_EXIT_FUNCTION();
+}
+
+/*!
+* Disk space changed.
+* Emit remaining time changed signal, if space change affects it.
+*/
+void CxeVideoCaptureControlSymbian::handleDiskSpaceChanged()
+{
+    CX_DEBUG_ENTER_FUNCTION();
+
+    // Ignore updates on preparing phase.
+    if (state() == CxeVideoCaptureControl::Ready) {
+
+        int time(calculateRemainingTime(mCurrentVideoDetails));
+
+        if (time !=  mCurrentVideoDetails.mRemainingTime) {
+            mCurrentVideoDetails.mRemainingTime = time;
+            emit remainingTimeChanged();
+        }
+    }
+
+    CX_DEBUG_EXIT_FUNCTION();
+}
+
+/*!
+    Use ECam Use Case Hint Custom API to inform ECam of our intended use case
+    before calling Reserve().
+*/
+void CxeVideoCaptureControlSymbian::hintUseCase()
+{
+    CX_DEBUG_ENTER_FUNCTION();
+
+    // Make sure ECam knows we're doing video recording so it can prepare
+    // for the correct use case.
+    if (mCameraDeviceControl.mode() == Cxe::VideoMode) {
+        MCameraUseCaseHint *useCaseHintApi = mCameraDevice.useCaseHintApi();
+        if (useCaseHintApi) {
+            MCameraUseCaseHint::TVideoCodec codec =
+                    MCameraUseCaseHint::ECodecUnknown;
+            MCameraUseCaseHint::TVideoProfile profile =
+                    MCameraUseCaseHint::EProfileUnknown;
+
+            updateVideoCaptureParameters();
+            CxeSettingsMapperSymbian::Map2UseCaseHintVideoParameters(
+                    mCurrentVideoDetails, codec, profile);
+
+            TSize resolution(mCurrentVideoDetails.mWidth,
+                             mCurrentVideoDetails.mHeight);
+            TRAP_IGNORE(useCaseHintApi->HintDirectVideoCaptureL(codec, profile,
+                                                                resolution));
+        }
+    }
+
+    CX_DEBUG_EXIT_FUNCTION();
+}
+
+/*!
+* Returns QList of all supported video quality details based on the camera index
+* (primary/secondary).
+*/
+QList<CxeVideoDetails> CxeVideoCaptureControlSymbian::supportedVideoQualities()
+{
+    // update the remaining time counters for each quality setting
+    updateRemainingRecordingTimeCounter();
+    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();
+}
+
+/*!
+ * Helper method to emulate video stopping events.
+ */
+void CxeVideoCaptureControlSymbian::emulateNormalStopping()
+{
+    CX_DEBUG_ENTER_FUNCTION();
+
+    setState(Stopping);
+    MvruoEvent(TMMFEvent(KCamCControllerCCVideoRecordStopped, KErrNone));
+    MvruoEvent(TMMFEvent(KCamCControllerCCVideoFileComposed, KErrNone));
+
+    CX_DEBUG_EXIT_FUNCTION();
+}
+// End of file