summaryrefslogtreecommitdiffstats
path: root/src/plugins/symbian/ecam
diff options
context:
space:
mode:
authorMichael Goddard <michael.goddard@nokia.com>2011-06-29 13:38:46 +1000
committerMichael Goddard <michael.goddard@nokia.com>2011-06-29 13:38:46 +1000
commit2a34e88c1e1ced28e75c487cd13402e1c9cf9fa3 (patch)
treee6c1b770c5c47212792a1f9344fa034ea3e54c44 /src/plugins/symbian/ecam
Initial copy of QtMultimediaKit.
Comes from original repo, with SHA1: 2c82d5611655e5967f5c5095af50c0991c4378b2
Diffstat (limited to 'src/plugins/symbian/ecam')
-rw-r--r--src/plugins/symbian/ecam/camera_s60.pri157
-rw-r--r--src/plugins/symbian/ecam/ecam.pro40
-rw-r--r--src/plugins/symbian/ecam/s60audioencodercontrol.cpp159
-rw-r--r--src/plugins/symbian/ecam/s60audioencodercontrol.h90
-rw-r--r--src/plugins/symbian/ecam/s60cameraconstants.h257
-rw-r--r--src/plugins/symbian/ecam/s60cameracontrol.cpp983
-rw-r--r--src/plugins/symbian/ecam/s60cameracontrol.h178
-rw-r--r--src/plugins/symbian/ecam/s60cameraengine.cpp824
-rw-r--r--src/plugins/symbian/ecam/s60cameraengine.h407
-rw-r--r--src/plugins/symbian/ecam/s60cameraengineobserver.h178
-rw-r--r--src/plugins/symbian/ecam/s60cameraexposurecontrol.cpp584
-rw-r--r--src/plugins/symbian/ecam/s60cameraexposurecontrol.h138
-rw-r--r--src/plugins/symbian/ecam/s60cameraflashcontrol.cpp109
-rw-r--r--src/plugins/symbian/ecam/s60cameraflashcontrol.h93
-rw-r--r--src/plugins/symbian/ecam/s60camerafocuscontrol.cpp193
-rw-r--r--src/plugins/symbian/ecam/s60camerafocuscontrol.h112
-rw-r--r--src/plugins/symbian/ecam/s60cameraimagecapturecontrol.cpp124
-rw-r--r--src/plugins/symbian/ecam/s60cameraimagecapturecontrol.h99
-rw-r--r--src/plugins/symbian/ecam/s60cameraimageprocessingcontrol.cpp254
-rw-r--r--src/plugins/symbian/ecam/s60cameraimageprocessingcontrol.h118
-rw-r--r--src/plugins/symbian/ecam/s60cameralockscontrol.cpp263
-rw-r--r--src/plugins/symbian/ecam/s60cameralockscontrol.h115
-rw-r--r--src/plugins/symbian/ecam/s60cameraservice.cpp259
-rw-r--r--src/plugins/symbian/ecam/s60cameraservice.h111
-rw-r--r--src/plugins/symbian/ecam/s60cameraserviceplugin.cpp115
-rw-r--r--src/plugins/symbian/ecam/s60cameraserviceplugin.h81
-rw-r--r--src/plugins/symbian/ecam/s60camerasettings.cpp986
-rw-r--r--src/plugins/symbian/ecam/s60camerasettings.h177
-rw-r--r--src/plugins/symbian/ecam/s60cameraviewfinderengine.cpp789
-rw-r--r--src/plugins/symbian/ecam/s60cameraviewfinderengine.h182
-rw-r--r--src/plugins/symbian/ecam/s60imagecapturesession.cpp1884
-rw-r--r--src/plugins/symbian/ecam/s60imagecapturesession.h359
-rw-r--r--src/plugins/symbian/ecam/s60imageencodercontrol.cpp128
-rw-r--r--src/plugins/symbian/ecam/s60imageencodercontrol.h84
-rw-r--r--src/plugins/symbian/ecam/s60mediacontainercontrol.cpp97
-rw-r--r--src/plugins/symbian/ecam/s60mediacontainercontrol.h82
-rw-r--r--src/plugins/symbian/ecam/s60mediarecordercontrol.cpp187
-rw-r--r--src/plugins/symbian/ecam/s60mediarecordercontrol.h118
-rw-r--r--src/plugins/symbian/ecam/s60videocapturesession.cpp2995
-rw-r--r--src/plugins/symbian/ecam/s60videocapturesession.h414
-rw-r--r--src/plugins/symbian/ecam/s60videodevicecontrol.cpp108
-rw-r--r--src/plugins/symbian/ecam/s60videodevicecontrol.h95
-rw-r--r--src/plugins/symbian/ecam/s60videoencodercontrol.cpp204
-rw-r--r--src/plugins/symbian/ecam/s60videoencodercontrol.h94
-rw-r--r--src/plugins/symbian/ecam/s60videorenderercontrol.cpp78
-rw-r--r--src/plugins/symbian/ecam/s60videorenderercontrol.h76
46 files changed, 15178 insertions, 0 deletions
diff --git a/src/plugins/symbian/ecam/camera_s60.pri b/src/plugins/symbian/ecam/camera_s60.pri
new file mode 100644
index 000000000..beb44db8d
--- /dev/null
+++ b/src/plugins/symbian/ecam/camera_s60.pri
@@ -0,0 +1,157 @@
+INCLUDEPATH += $$PWD
+
+include (../videooutput/videooutput.pri)
+
+# Camera Service
+DEFINES += QMEDIA_SYMBIAN_CAMERA
+
+# S60 3.1 platform
+contains(S60_VERSION, 3.1) {
+ DEFINES += S60_31_PLATFORM
+ DEFINES *= S60_3X_PLATFORM
+}
+
+# S60 3.2 platform
+contains(S60_VERSION, 3.2) {
+ DEFINES += S60_32_PLATFORM
+ DEFINES *= S60_3X_PLATFORM
+}
+
+# S60 5.0 platform
+!contains(DEFINES, S60_31_PLATFORM) {
+ !contains(DEFINES, S60_32_PLATFORM) {
+ !contains(DEFINES, SYMBIAN_3_PLATFORM) {
+ DEFINES += S60_50_PLATFORM
+ }
+ }
+}
+
+# Symbian 3 platform
+contains(DEFINES, VIDEOOUTPUT_GRAPHICS_SURFACES) {
+ DEFINES += SYMBIAN_3_PLATFORM
+}
+
+# AutoFocusing (CamAutoFocus) from ForumNokia example
+contains(symbian_camera_camautofocus_enabled, yes) {
+ exists($${EPOCROOT}epoc32\\include\\CCamAutoFocus.h) {
+ message ("CameraBE: Using S60 3.1 autofocusing")
+ MMP_RULES += \
+ "$${LITERAL_HASH}ifdef WINSCW" \
+ "LIBRARY camautofocus.lib" \
+ "$${LITERAL_HASH}else" \
+ "STATICLIBRARY camautofocus_s.lib" \
+ "$${LITERAL_HASH}endif // WINS" \
+ "MACRO S60_CAM_AUTOFOCUS_SUPPORT"
+ }
+}
+
+# ECam AdvancedSettings
+contains(symbian_camera_ecamadvsettings_enabled, yes) {
+ exists($${EPOCROOT}epoc32\\include\\ecamadvancedsettings.h) {
+ MMP_RULES += \
+ "$${LITERAL_HASH}ifndef WINSCW" \
+ "LIBRARY ecamadvsettings.lib" \
+ "MACRO USE_S60_32_ECAM_ADVANCED_SETTINGS_HEADER" \
+ "$${LITERAL_HASH}endif"
+ message("CameraBE: Using from S60 3.2 CCameraAdvancedSettings header")
+ }
+ exists($${EPOCROOT}epoc32\\include\\ecamadvsettings.h) {
+ symbian:LIBS += -lecamadvsettings
+ DEFINES += USE_S60_50_ECAM_ADVANCED_SETTINGS_HEADER
+ message("CameraBE: Using CCameraAdvancedSettings header from S60 5.0 or later")
+ }
+}
+
+# DevVideo API Check (Requires both, DevVideoPlay and DevVideoRecord plugins):
+# DevVideoConstants has been problematic since not being included in SDK plugins
+# For S60 5.0 this has changed with plugin extension 1.1
+# But for S60 3.2 this is still a problem
+contains(symbian_camera_devvideorecord_enabled, yes) {
+ exists($${EPOCROOT}epoc32\\include\\mmf\\devvideo\\devvideorecord.h) {
+ exists($${EPOCROOT}epoc32\\include\\mmf\\devvideo\\devvideobase.h) {
+ exists($${EPOCROOT}epoc32\\include\\mmf\\devvideo\\devvideoconstants.h) {
+ symbian:LIBS += -ldevvideo
+ DEFINES += S60_DEVVIDEO_RECORDING_SUPPORTED
+ message("CameraBE: Devvideo API supported")
+ }
+ }
+ }
+}
+
+# ECam Snapshot API:
+contains(symbian_camera_snapshot_enabled, yes) {
+ exists($${EPOCROOT}epoc32\\include\\platform\\ecam\\camerasnapshot.h) {
+ DEFINES += ECAM_PREVIEW_API
+ message("CameraBE: Using CCameraSnapshot API")
+ symbian:LIBS += -lecamsnapshot
+ } else {
+ message("CameraBE: Using custom snapshot proving methods")
+ }
+} else {
+ message("CameraBE: Using custom snapshot proving methods")
+}
+
+# Libraries:
+symbian:LIBS += -lfbscli \
+ -lmediaclientvideo \
+ -lecam \
+ -lbafl \
+ -lPlatformEnv \
+ -lcharconv \
+ -lconvnames \
+ -lgb2312_shared \
+ -ljisx0201 \
+ -ljisx0208 \
+ -lmmfcontrollerframework \
+ -lfbscli \
+ -lefsrv \
+ -lcone \
+ -lws32 \
+ -limageconversion
+
+# Source:
+HEADERS += $$PWD/s60cameraconstants.h \
+ $$PWD/s60cameralockscontrol.h \
+ $$PWD/s60camerafocuscontrol.h \
+ $$PWD/s60cameraexposurecontrol.h \
+ $$PWD/s60cameraflashcontrol.h \
+ $$PWD/s60cameracontrol.h \
+ $$PWD/s60mediarecordercontrol.h \
+ $$PWD/s60videocapturesession.h \
+ $$PWD/s60imagecapturesession.h \
+ $$PWD/s60mediacontainercontrol.h \
+ $$PWD/s60videoencodercontrol.h \
+ $$PWD/s60audioencodercontrol.h \
+ $$PWD/s60cameraservice.h \
+ $$PWD/s60cameraimageprocessingcontrol.h \
+ $$PWD/s60cameraimagecapturecontrol.h \
+ $$PWD/s60videodevicecontrol.h \
+ $$PWD/s60imageencodercontrol.h \
+ $$PWD/s60camerasettings.h \
+ $$PWD/s60cameraengine.h \
+ $$PWD/s60cameraviewfinderengine.h \
+ $$PWD/s60cameraengineobserver.h \
+ $$PWD/s60videorenderercontrol.h
+
+SOURCES += $$PWD/s60cameralockscontrol.cpp \
+ $$PWD/s60camerafocuscontrol.cpp \
+ $$PWD/s60cameraexposurecontrol.cpp \
+ $$PWD/s60cameraflashcontrol.cpp \
+ $$PWD/s60cameracontrol.cpp \
+ $$PWD/s60mediarecordercontrol.cpp \
+ $$PWD/s60videocapturesession.cpp \
+ $$PWD/s60imagecapturesession.cpp \
+ $$PWD/s60mediacontainercontrol.cpp \
+ $$PWD/s60videoencodercontrol.cpp \
+ $$PWD/s60audioencodercontrol.cpp \
+ $$PWD/s60cameraservice.cpp \
+ $$PWD/s60cameraimageprocessingcontrol.cpp \
+ $$PWD/s60cameraimagecapturecontrol.cpp \
+ $$PWD/s60videodevicecontrol.cpp \
+ $$PWD/s60imageencodercontrol.cpp \
+ $$PWD/s60camerasettings.cpp \
+ $$PWD/s60cameraengine.cpp \
+ $$PWD/s60cameraviewfinderengine.cpp \
+ $$PWD/s60videorenderercontrol.cpp
+
+# End of file
diff --git a/src/plugins/symbian/ecam/ecam.pro b/src/plugins/symbian/ecam/ecam.pro
new file mode 100644
index 000000000..31f30b61c
--- /dev/null
+++ b/src/plugins/symbian/ecam/ecam.pro
@@ -0,0 +1,40 @@
+######################################################################
+#
+# Mobility API project - Symbian Camera backend
+#
+######################################################################
+
+TEMPLATE = lib
+CONFIG += plugin
+
+TARGET = $$qtLibraryTarget(qtmultimediakit_ecamengine)
+PLUGIN_TYPE = mediaservice
+include (../../../../common.pri)
+
+CONFIG += mobility
+MOBILITY += multimedia
+
+# Include here so that all defines are added here also
+include(camera_s60.pri)
+
+DEPENDPATH += .
+
+INCLUDEPATH += . \
+ $${SOURCE_DIR}/include \
+ $${SOURCE_DIR}/src/multimedia \
+ $${SOURCE_DIR}/src/multimedia/audio \
+ $${SOURCE_DIR}/src/multimedia/video \
+ $${SOURCE_DIR}
+
+HEADERS += s60cameraserviceplugin.h
+SOURCES += s60cameraserviceplugin.cpp
+
+load(data_caging_paths)
+TARGET.EPOCALLOWDLLDATA = 1
+TARGET.UID3 = 0x2002BFC2
+TARGET.CAPABILITY = ALL -TCB
+
+# Make a sis package from plugin + api + stub (plugin)
+pluginDep.sources = $${TARGET}.dll
+pluginDep.path = $${QT_PLUGINS_BASE_DIR}/$${PLUGIN_TYPE}
+DEPLOYMENT += pluginDep
diff --git a/src/plugins/symbian/ecam/s60audioencodercontrol.cpp b/src/plugins/symbian/ecam/s60audioencodercontrol.cpp
new file mode 100644
index 000000000..bd8f0147d
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60audioencodercontrol.cpp
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "s60audioencodercontrol.h"
+#include "s60videocapturesession.h"
+
+S60AudioEncoderControl::S60AudioEncoderControl(QObject *parent) :
+ QAudioEncoderControl(parent)
+{
+}
+
+S60AudioEncoderControl::S60AudioEncoderControl(S60VideoCaptureSession *session, QObject *parent) :
+ QAudioEncoderControl(parent)
+{
+ m_session = session;
+}
+
+S60AudioEncoderControl::~S60AudioEncoderControl()
+{
+}
+
+QStringList S60AudioEncoderControl::supportedAudioCodecs() const
+{
+ return m_session->supportedAudioCaptureCodecs();
+}
+
+QString S60AudioEncoderControl::codecDescription(const QString &codecName) const
+{
+ // According to ForumNokia MMF camcorder plugin supports AAC, AMR and QCELP
+ // QCELP is speech codec and can be discarded
+ if (qstrcmp(codecName.toLocal8Bit().constData(), "audio/aac") == 0)
+ return QLatin1String("Advanced Audio Coding");
+ else if (qstrcmp(codecName.toLocal8Bit().constData(), "audio/amr") == 0)
+ return QLatin1String("Adaptive Multi-Rate Audio Codec");
+
+ return QString();
+}
+
+QStringList S60AudioEncoderControl::supportedEncodingOptions(const QString &codec) const
+{
+ // Possible settings: EncodingMode, Codec, BitRate, ChannelCount, SampleRate, Quality
+ // Possible (codec specific) Options: None
+ Q_UNUSED(codec);
+ return QStringList();
+}
+
+QVariant S60AudioEncoderControl::encodingOption(const QString &codec, const QString &name) const
+{
+ // Possible settings: EncodingMode, Codec, BitRate, ChannelCount, SampleRate, Quality
+ // Possible (codec specific) Options: None
+ Q_UNUSED(codec);
+ Q_UNUSED(name);
+ return QVariant();
+}
+
+void S60AudioEncoderControl::setEncodingOption(
+ const QString &codec, const QString &name, const QVariant &value)
+{
+ m_session->setError(KErrNotSupported, tr("Audio encoding option is not supported"));
+
+ // The audio settings can currently be set only using setAudioSettings() function
+ Q_UNUSED(value)
+ Q_UNUSED(codec)
+ Q_UNUSED(name)
+}
+
+QList<int> S60AudioEncoderControl::supportedSampleRates(
+ const QAudioEncoderSettings &settings, bool *continuous) const
+{
+ return m_session->supportedSampleRates(settings, continuous);
+}
+
+QAudioEncoderSettings S60AudioEncoderControl::audioSettings() const
+{
+ QAudioEncoderSettings settings;
+ m_session->audioEncoderSettings(settings);
+
+ return settings;
+}
+
+void S60AudioEncoderControl::setAudioSettings(const QAudioEncoderSettings &settings)
+{
+ // Notify that settings have been implicitly set and there's no need to
+ // initialize them in case camera is changed
+ m_session->notifySettingsSet();
+
+ // Quality defines SampleRate/BitRate combination if either or both are missing
+ if (settings.codec().isEmpty()) { // Empty settings
+ m_session->setAudioCaptureQuality(settings.quality(), S60VideoCaptureSession::EOnlyAudioQuality);
+
+ } else if (settings.bitRate() == -1 && settings.sampleRate() != -1) { // Only SampleRate set
+ m_session->setAudioCaptureCodec(settings.codec());
+ m_session->setAudioChannelCount(settings.channelCount());
+ m_session->setAudioSampleRate(settings.sampleRate());
+ m_session->setAudioEncodingMode(settings.encodingMode());
+ m_session->setAudioCaptureQuality(settings.quality(), S60VideoCaptureSession::EAudioQualityAndSampleRate);
+
+ } else if (settings.bitRate() != -1 && settings.sampleRate() == -1) { // Only BitRate set
+ m_session->setAudioCaptureCodec(settings.codec());
+ m_session->setAudioChannelCount(settings.channelCount());
+ m_session->setAudioBitRate(settings.bitRate());
+ m_session->setAudioEncodingMode(settings.encodingMode());
+ m_session->setAudioCaptureQuality(settings.quality(), S60VideoCaptureSession::EAudioQualityAndBitRate);
+
+ } else if (settings.bitRate() == -1 && settings.sampleRate() == -1) { // No BitRate or SampleRate set
+ m_session->setAudioCaptureCodec(settings.codec());
+ m_session->setAudioChannelCount(settings.channelCount());
+ m_session->setAudioEncodingMode(settings.encodingMode());
+ m_session->setAudioCaptureQuality(settings.quality(), S60VideoCaptureSession::EOnlyAudioQuality);
+
+ } else { // Both SampleRate and BitRate set
+ m_session->setAudioCaptureCodec(settings.codec());
+ m_session->setAudioChannelCount(settings.channelCount());
+ m_session->setAudioSampleRate(settings.sampleRate());
+ m_session->setAudioBitRate(settings.bitRate());
+ m_session->setAudioEncodingMode(settings.encodingMode());
+ m_session->setAudioCaptureQuality(settings.quality(), S60VideoCaptureSession::ENoAudioQuality);
+ }
+}
+
+// End of file
diff --git a/src/plugins/symbian/ecam/s60audioencodercontrol.h b/src/plugins/symbian/ecam/s60audioencodercontrol.h
new file mode 100644
index 000000000..db6ada5d1
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60audioencodercontrol.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef S60AUDIOENCODERCONTROL_H
+#define S60AUDIOENCODERCONTROL_H
+
+#include <QtCore/qstringlist.h>
+#include <QtCore/qmap.h>
+
+#include <qaudioencodercontrol.h>
+
+QT_USE_NAMESPACE
+
+class S60VideoCaptureSession;
+
+/*
+ * Control for audio settings when recording video using QMediaRecorder.
+ */
+class S60AudioEncoderControl : public QAudioEncoderControl
+{
+ Q_OBJECT
+
+public: // Constructor & Destructor
+
+ S60AudioEncoderControl(QObject *parent = 0);
+ S60AudioEncoderControl(S60VideoCaptureSession *session, QObject *parent = 0);
+ virtual ~S60AudioEncoderControl();
+
+public: // QAudioEncoderControl
+
+ // Audio Codec
+ QStringList supportedAudioCodecs() const;
+ QString codecDescription(const QString &codecName) const;
+
+ // Sample Rate
+ QList<int> supportedSampleRates(const QAudioEncoderSettings &settings, bool *continuous = 0) const;
+
+ // Audio Settings
+ QAudioEncoderSettings audioSettings() const;
+ void setAudioSettings(const QAudioEncoderSettings &settings);
+
+ // Encoding Option
+ QStringList supportedEncodingOptions(const QString &codec) const;
+ QVariant encodingOption(const QString &codec, const QString &name) const;
+ void setEncodingOption(const QString &codec, const QString &name, const QVariant &value);
+
+private: // Data
+
+ S60VideoCaptureSession* m_session;
+};
+
+#endif // S60AUDIOENCODERCONTROL_H
diff --git a/src/plugins/symbian/ecam/s60cameraconstants.h b/src/plugins/symbian/ecam/s60cameraconstants.h
new file mode 100644
index 000000000..4b415c3e8
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameraconstants.h
@@ -0,0 +1,257 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef S60CAMERACONSTANTS_H
+#define S60CAMERACONSTANTS_H
+
+//=============================================================================
+
+// GENERAL SETTINGS
+
+#define KDefaultCameraDevice 0
+#define KECamCameraPriority 0
+#define KInactivityTimerTimeout 30000 // msec
+#define KSymbianFineResolutionFactor 100.0
+#define KDefaultOpticalZoom 1.0
+#define KDefaultDigitalZoom 1.0
+#define KSmoothZoomStep 1
+#define KDefaultFocusMode QCameraFocus::AutoFocus
+
+#define KDefaultViewfinderSize QSize(320,240)
+#define KDefaultSizePreview_Normal TSize(640,480)
+#define KDefaultSizePreview_Wide TSize(640,360)
+#define KDefaultSizePreview_CIF TSize(352,288)
+#define KDefaultSizePreview_PAL TSize(640,512)
+#define KDefaultSizePreview_NTSC TSize(640,426)
+#define KDefaultFormatPreview CCamera::EFormatFbsBitmapColor16MU
+#define KViewfinderFrameRate 30
+#define KMaxVFErrorsSignalled 3
+
+//=============================================================================
+
+// IMAGE SETTINGS
+
+#define KDefaultImagePath QLatin1String("c:\\Data\\Images")
+#define KDefaultImageFileName QLatin1String("image.jpg")
+#define KDefaultImageCodec QLatin1String("image/jpeg")
+#define KDefaultImageFormatPrimaryCam CCamera::EFormatExif
+#ifdef SYMBIAN_3_PLATFORM
+#define KDefaultImageFormatSecondaryCam CCamera::EFormatExif
+#define KDefaultImageResolution QSize(3264, 2448)
+#else // Pre-Symbian3 Platforms
+#define KDefaultImageFormatSecondaryCam CCamera::EFormatFbsBitmapColor64K
+#define KDefaultImageResolution QSize(2048, 1536)
+#endif // SYMBIAN_3_PLATFORM
+#define KSymbianImageQualityCoefficient 25
+// This must be divisible by 4 and creater or equal to 8
+#define KSnapshotDownScaleFactor 8
+#define KSnapshotMinWidth 640
+#define KSnapshotMinHeight 360
+#define KJpegQualityVeryLow 40
+#define KJpegQualityLow 50
+#define KJpegQualityNormal 75
+#define KJpegQualityHigh 85
+#define KJpegQualityVeryHigh 95
+#define KDefaultImageQuality KJpegQualityHigh
+
+//=============================================================================
+
+// VIDEO SETTINGS
+
+// ================
+// General settings
+// ================
+
+// Dummy file name to execute CVideoRecorderUtility::OpenFileL() without
+// knowing the actual outputLocation. This is needed to be able to query/set
+// supported video settings.
+_LIT(KDummyVideoFile, "c:\\data\\temp");
+
+// Default container MIME type
+#define KMimeTypeDefaultContainer QLatin1String("video/mp4")
+#define KDefaultVideoPath QLatin1String("c:\\Data\\Videos")
+#define KDefaultVideoFileName QLatin1String("video.mp4")
+#define KDurationChangedInterval 1000 // 1 second
+
+// ==============
+// Audio Settings
+// ==============
+
+// Default audio codec MIME type
+#define KMimeTypeDefaultAudioCodec QLatin1String("audio/aac")
+
+// Default audio settings for video recording
+#define KDefaultChannelCount -1 // Not Supported on Symbian
+#define KDefaultBitRate 32000 // 32kbps
+#define KDefaultSampleRate -1 // Not Supported on Symbian
+
+// ==============
+// Video Settings
+// ==============
+
+// Default video codec MIME type
+#ifdef SYMBIAN_3_PLATFORM
+ // H.264: BaselineProfile Level 3.1, Max resolution: 1280x720
+ #define KMimeTypeDefaultVideoCodec QLatin1String("video/H264; profile-level-id=42801F")
+#else
+ // MPEG-4: Simple Profile, Level 4, Max resolution: 640x480
+ #define KMimeTypeDefaultVideoCodec QLatin1String("video/mp4v-es; profile-level-id=4")
+#endif
+
+// Maximum resolutions for encoder MIME Types
+// H.263
+#define KResH263 QSize(176,144);
+#define KResH263_Profile0 QSize(176,144);
+#define KResH263_Profile0_Level10 QSize(176,144);
+#define KResH263_Profile0_Level20 QSize(352,288);
+#define KResH263_Profile0_Level30 QSize(352,288);
+#define KResH263_Profile0_Level40 QSize(352,288);
+#define KResH263_Profile0_Level45 QSize(176,144);
+#define KResH263_Profile0_Level50 QSize(352,288);
+#define KResH263_Profile3 QSize(176,144);
+// MPEG-4
+#define KResMPEG4 QSize(176,144);
+#define KResMPEG4_PLID_1 QSize(176,144);
+#define KResMPEG4_PLID_2 QSize(352,288);
+#define KResMPEG4_PLID_3 QSize(352,288);
+#define KResMPEG4_PLID_4 QSize(640,480);
+#define KResMPEG4_PLID_5 QSize(720,576);
+#define KResMPEG4_PLID_6 QSize(1280,720);
+#define KResMPEG4_PLID_8 QSize(176,144);
+#define KResMPEG4_PLID_9 QSize(176,144);
+// H.264 (Baseline Profile, same resolutions apply to Main and High Profile)
+#define KResH264 QSize(176,144);
+#define KResH264_PLID_42800A QSize(176,144);
+#define KResH264_PLID_42900B QSize(176,144);
+#define KResH264_PLID_42800B QSize(352,288);
+#define KResH264_PLID_42800C QSize(352,288);
+#define KResH264_PLID_42800D QSize(352,288);
+#define KResH264_PLID_428014 QSize(352,288);
+#define KResH264_PLID_428015 QSize(352,288);
+#define KResH264_PLID_428016 QSize(640,480);
+#define KResH264_PLID_42801E QSize(640,480);
+#define KResH264_PLID_42801F QSize(1280,720);
+#define KResH264_PLID_428020 QSize(1280,720);
+#define KResH264_PLID_428028 QSize(1920,1080);
+
+// Maximum framerates for encoder MIME Types
+// H.263
+#define KFrR_H263 qreal(15);
+#define KFrR_H263_Profile0 qreal(15);
+#define KFrR_H263_Profile0_Level10 qreal(15);
+#define KFrR_H263_Profile0_Level20 qreal(15);
+#define KFrR_H263_Profile0_Level30 qreal(30);
+#define KFrR_H263_Profile0_Level40 qreal(30);
+#define KFrR_H263_Profile0_Level45 qreal(15);
+#define KFrR_H263_Profile0_Level50 qreal(15);
+#define KFrR_H263_Profile3 qreal(15);
+// MPEG-4
+#define KFrR_MPEG4 qreal(15);
+#define KFrR_MPEG4_PLID_1 qreal(15);
+#define KFrR_MPEG4_PLID_2 qreal(15);
+#define KFrR_MPEG4_PLID_3 qreal(30);
+// This is a workaround for a known platform bug
+#if (defined(S60_31_PLATFORM) | defined(S60_32_PLATFORM))
+#define KFrR_MPEG4_PLID_4 qreal(15);
+#else // All other platforms
+#define KFrR_MPEG4_PLID_4 qreal(30);
+#endif // S60 3.1 or 3.2
+#define KFrR_MPEG4_PLID_5 qreal(30);
+#define KFrR_MPEG4_PLID_6 qreal(30);
+#define KFrR_MPEG4_PLID_8 qreal(15);
+#define KFrR_MPEG4_PLID_9 qreal(15);
+// H.264 (Baseline Profile, same framerates apply to Main and High Profile)
+#define KFrR_H264 qreal(15);
+#define KFrR_H264_PLID_42800A qreal(15);
+#define KFrR_H264_PLID_42900B qreal(15);
+#define KFrR_H264_PLID_42800B qreal(7.5);
+#define KFrR_H264_PLID_42800C qreal(15);
+#define KFrR_H264_PLID_42800D qreal(30);
+#define KFrR_H264_PLID_428014 qreal(30);
+#define KFrR_H264_PLID_428015 qreal(50);
+#define KFrR_H264_PLID_428016 qreal(16.9);
+#define KFrR_H264_PLID_42801E qreal(33.8);
+#define KFrR_H264_PLID_42801F qreal(30);
+#define KFrR_H264_PLID_428020 qreal(60);
+#define KFrR_H264_PLID_428028 qreal(30);
+
+// Maximum bitrates for encoder MIME Types
+// H.263
+#define KBiR_H263 int(64000);
+#define KBiR_H263_Profile0 int(64000);
+#define KBiR_H263_Profile0_Level10 int(64000);
+#define KBiR_H263_Profile0_Level20 int(128000);
+#define KBiR_H263_Profile0_Level30 int(384000);
+#define KBiR_H263_Profile0_Level40 int(2048000);
+#define KBiR_H263_Profile0_Level45 int(128000);
+#define KBiR_H263_Profile0_Level50 int(4096000);
+#define KBiR_H263_Profile3 int(64000);
+// MPEG-4
+#define KBiR_MPEG4 int(64000);
+#define KBiR_MPEG4_PLID_1 int(64000);
+#define KBiR_MPEG4_PLID_2 int(128000);
+#define KBiR_MPEG4_PLID_3 int(384000);
+// This is a workaround for a known platform bug
+#if (defined(S60_31_PLATFORM) | defined(S60_32_PLATFORM))
+#define KBiR_MPEG4_PLID_4 int(2000000);
+#else // All other platforms
+#define KBiR_MPEG4_PLID_4 int(4000000);
+#endif // S60 3.1 or 3.2
+#define KBiR_MPEG4_PLID_5 int(8000000);
+#define KBiR_MPEG4_PLID_6 int(12000000);
+#define KBiR_MPEG4_PLID_8 int(64000);
+#define KBiR_MPEG4_PLID_9 int(128000);
+// H.264 (Baseline Profile, same bitrates apply to Main and High Profile)
+#define KBiR_H264 int(64000);
+#define KBiR_H264_PLID_42800A int(64000);
+#define KBiR_H264_PLID_42900B int(128000);
+#define KBiR_H264_PLID_42800B int(192000);
+#define KBiR_H264_PLID_42800C int(384000);
+#define KBiR_H264_PLID_42800D int(768000);
+#define KBiR_H264_PLID_428014 int(2000000);
+#define KBiR_H264_PLID_428015 int(4000000);
+#define KBiR_H264_PLID_428016 int(4000000);
+#define KBiR_H264_PLID_42801E int(10000000);
+#define KBiR_H264_PLID_42801F int(14000000);
+#define KBiR_H264_PLID_428020 int(20000000);
+#define KBiR_H264_PLID_428028 int(20000000);
+
+#endif // S60CAMERACONSTANTS_H
diff --git a/src/plugins/symbian/ecam/s60cameracontrol.cpp b/src/plugins/symbian/ecam/s60cameracontrol.cpp
new file mode 100644
index 000000000..64a3ff37e
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameracontrol.cpp
@@ -0,0 +1,983 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qstring.h>
+#include <QTimer>
+
+#include "s60cameraservice.h"
+#include "s60cameraengine.h"
+#include "s60cameracontrol.h"
+#include "s60imagecapturesession.h"
+#include "s60videowidgetcontrol.h"
+#include "s60cameraviewfinderengine.h"
+#include "s60cameraconstants.h"
+
+S60CameraControl::S60CameraControl(QObject *parent) :
+ QCameraControl(parent)
+{
+}
+
+S60CameraControl::S60CameraControl(S60VideoCaptureSession *videosession,
+ S60ImageCaptureSession *imagesession,
+ QObject *parent):
+ QCameraControl(parent),
+ m_cameraEngine(0),
+ m_viewfinderEngine(0),
+ m_imageSession(0),
+ m_videoSession(0),
+ m_advancedSettings(0),
+ m_videoOutput(0),
+ m_inactivityTimer(0),
+ m_captureMode(QCamera::CaptureStillImage), // Default CaptureMode
+ m_requestedCaptureMode(QCamera::CaptureStillImage),
+ m_settingCaptureModeInternally(false),
+ m_internalState(QCamera::UnloadedStatus), // Default Status
+ m_requestedState(QCamera::UnloadedState), // Default State
+ m_deviceIndex(KDefaultCameraDevice),
+ m_error(KErrNone),
+ m_changeCaptureModeWhenReady(false),
+ m_rotateCameraWhenReady(false),
+ m_videoCaptureState(S60VideoCaptureSession::ENotInitialized)
+{
+ m_videoSession = videosession;
+ m_imageSession = imagesession;
+
+ m_inactivityTimer = new QTimer;
+ if (m_inactivityTimer)
+ m_inactivityTimer->setSingleShot(true);
+
+ TRAPD(err, m_cameraEngine = CCameraEngine::NewL(m_deviceIndex, KECamCameraPriority, this));
+ if (err) {
+ m_error = err;
+ if (err == KErrPermissionDenied)
+ qWarning("Failed to create camera. Possibly missing capabilities.");
+ else
+ qWarning("Failed to create camera.");
+ return;
+ }
+
+ m_viewfinderEngine = new S60CameraViewfinderEngine(this, m_cameraEngine, this);
+ if (m_viewfinderEngine == 0) {
+ m_error = KErrNoMemory;
+ qWarning("Failed to create viewfinder engine.");
+ return;
+ }
+
+ // Connect signals
+ connect(m_inactivityTimer, SIGNAL(timeout()), this, SLOT(toStandByStatus()));
+ connect(this, SIGNAL(statusChanged(QCamera::Status)),
+ m_imageSession, SLOT(cameraStatusChanged(QCamera::Status)));
+ connect(this, SIGNAL(statusChanged(QCamera::Status)),
+ m_videoSession, SLOT(cameraStatusChanged(QCamera::Status)));
+ connect(m_videoSession, SIGNAL(stateChanged(S60VideoCaptureSession::TVideoCaptureState)),
+ this, SLOT(videoStateChanged(S60VideoCaptureSession::TVideoCaptureState)));
+ connect(m_imageSession, SIGNAL(advancedSettingChanged()), this, SLOT(advancedSettingsCreated()));
+ connect(this, SIGNAL(cameraReadyChanged(bool)), m_imageSession, SIGNAL(readyForCaptureChanged(bool)));
+ connect(m_viewfinderEngine, SIGNAL(error(int, const QString&)), this, SIGNAL(error(int,const QString&)));
+ connect(m_imageSession, SIGNAL(cameraError(int, const QString&)), this, SIGNAL(error(int, const QString&)));
+ connect(m_imageSession, SIGNAL(captureSizeChanged(const QSize&)),
+ m_viewfinderEngine, SLOT(handleContentAspectRatioChange(const QSize&)));
+ connect(m_videoSession, SIGNAL(captureSizeChanged(const QSize&)),
+ m_viewfinderEngine, SLOT(handleContentAspectRatioChange(const QSize&)));
+
+ setCameraHandles();
+}
+
+S60CameraControl::~S60CameraControl()
+{
+ unloadCamera();
+
+ if (m_viewfinderEngine) {
+ delete m_viewfinderEngine;
+ m_viewfinderEngine = 0;
+ }
+
+ // Make sure AdvancedSettings are destructed
+ m_imageSession->deleteAdvancedSettings();
+
+ if (m_cameraEngine) {
+ delete m_cameraEngine;
+ m_cameraEngine = 0;
+ }
+
+ if (m_inactivityTimer) {
+ delete m_inactivityTimer;
+ m_inactivityTimer = 0;
+ }
+}
+
+void S60CameraControl::setState(QCamera::State state)
+{
+ if (m_error) { // Most probably failure in contructor
+ setError(m_error, tr("Unexpected camera error."));
+ return;
+ }
+
+ if (m_requestedState == state)
+ return;
+
+ if (m_inactivityTimer->isActive())
+ m_inactivityTimer->stop();
+
+ // Save the target state
+ m_requestedState = state;
+ emit stateChanged(m_requestedState);
+
+ switch (state) {
+ case QCamera::UnloadedState: // To UnloadedState - Release resources
+ switch (m_internalState) {
+ case QCamera::UnloadedStatus:
+ // Do nothing
+ break;
+ case QCamera::LoadingStatus:
+ case QCamera::StartingStatus:
+ // Release resources when ready (setting state handles this)
+ return;
+ case QCamera::LoadedStatus:
+ case QCamera::StandbyStatus:
+ // Unload
+ unloadCamera();
+ break;
+ case QCamera::ActiveStatus:
+ // Stop and Unload
+ stopCamera();
+ unloadCamera();
+ break;
+
+ default:
+ // Unrecognized internal state (Status)
+ setError(KErrGeneral, tr("Unexpected camera error."));
+ return;
+ }
+ break;
+
+ case QCamera::LoadedState: // To LoadedState - Reserve resources OR Stop ViewFinder and Cancel Capture
+ switch (m_internalState) {
+ case QCamera::UnloadedStatus:
+ case QCamera::StandbyStatus:
+ // Load
+ loadCamera();
+ break;
+ case QCamera::LoadingStatus:
+ // Discard, already moving to LoadedStatus
+ return;
+ case QCamera::StartingStatus:
+ // Stop when ready (setting state handles this)
+ return;
+ case QCamera::LoadedStatus:
+ m_inactivityTimer->start(KInactivityTimerTimeout);
+ break;
+ case QCamera::ActiveStatus:
+ // Stop
+ stopCamera();
+ break;
+
+ default:
+ // Unregocnized internal state (Status)
+ setError(KErrGeneral, tr("Unexpected camera error."));
+ return;
+ }
+ break;
+
+ case QCamera::ActiveState: // To ActiveState - (Reserve Resources and) Start ViewFinder
+ switch (m_internalState) {
+ case QCamera::UnloadedStatus:
+ case QCamera::StandbyStatus:
+ // Load and Start (setting state handles starting)
+ loadCamera();
+ break;
+ case QCamera::LoadingStatus:
+ // Start when loaded (setting state handles this)
+ break;
+ case QCamera::StartingStatus:
+ // Discard, already moving to ActiveStatus
+ return;
+ case QCamera::LoadedStatus:
+ // Start
+ startCamera();
+ break;
+ case QCamera::ActiveStatus:
+ // Do nothing
+ break;
+
+ default:
+ // Unregocnized internal state (Status)
+ setError(KErrGeneral, tr("Unexpected camera error."));
+ return;
+ }
+ break;
+
+ default:
+ setError(KErrNotSupported, tr("Requested state is not supported."));
+ return;
+ }
+}
+
+QCamera::State S60CameraControl::state() const
+{
+ return m_requestedState;
+}
+
+QCamera::Status S60CameraControl::status() const
+{
+ return m_internalState;
+}
+
+QCamera::CaptureMode S60CameraControl::captureMode() const
+{
+ return m_captureMode;
+}
+
+void S60CameraControl::setCaptureMode(QCamera::CaptureMode mode)
+{
+ if (m_error) { // Most probably failure in contructor
+ setError(m_error, tr("Unexpected camera error."));
+ return;
+ }
+
+ if (m_captureMode == mode)
+ return;
+
+ // Setting CaptureMode Internally or Externally (Client)
+ if (!m_settingCaptureModeInternally) {
+ // Save the requested mode
+ m_requestedCaptureMode = mode;
+
+ // CaptureMode change pending (backend busy), wait
+ if (m_changeCaptureModeWhenReady)
+ return;
+ } else {
+ m_changeCaptureModeWhenReady = false; // Reset
+ }
+ m_settingCaptureModeInternally = false; // Reset
+
+ if (!isCaptureModeSupported(mode)) {
+ setError(KErrNotSupported, tr("Requested capture mode is not supported."));
+ return;
+ }
+
+ if (m_inactivityTimer->isActive())
+ m_inactivityTimer->stop();
+
+ switch (m_internalState) {
+ case QCamera::UnloadedStatus:
+ case QCamera::LoadedStatus:
+ case QCamera::StandbyStatus:
+ switch (mode) {
+ case QCamera::CaptureStillImage:
+ m_videoSession->releaseVideoRecording();
+ m_captureMode = QCamera::CaptureStillImage;
+ if (m_internalState == QCamera::LoadedStatus)
+ m_inactivityTimer->start(KInactivityTimerTimeout);
+ else if (m_internalState == QCamera::StandbyStatus)
+ loadCamera();
+ break;
+ case QCamera::CaptureVideo:
+ m_imageSession->releaseImageCapture();
+ m_captureMode = QCamera::CaptureVideo;
+ if (m_internalState == QCamera::LoadedStatus) {
+ // Revet InternalState as we need to wait for the video
+ // side initialization to complete
+ m_internalState = QCamera::LoadingStatus;
+ emit statusChanged(m_internalState);
+ int prepareSuccess = m_videoSession->initializeVideoRecording();
+ setError(prepareSuccess, tr("Loading video capture failed."));
+ } else if (m_internalState == QCamera::StandbyStatus)
+ loadCamera();
+ break;
+ }
+ break;
+ case QCamera::LoadingStatus:
+ case QCamera::StartingStatus:
+ m_changeCaptureModeWhenReady = true;
+ return;
+ case QCamera::ActiveStatus:
+ // Stop, Change Mode and Start again
+ stopCamera();
+ switch (mode) {
+ case QCamera::CaptureStillImage:
+ m_videoSession->releaseVideoRecording();
+ m_captureMode = QCamera::CaptureStillImage;
+ startCamera();
+ break;
+ case QCamera::CaptureVideo:
+ m_imageSession->releaseImageCapture();
+ m_captureMode = QCamera::CaptureVideo;
+ // Revet InternalState as we need to wait for the video
+ // side initialization to complete
+ m_internalState = QCamera::LoadingStatus;
+ emit statusChanged(m_internalState);
+ int prepareSuccess = m_videoSession->initializeVideoRecording();
+ setError(prepareSuccess, tr("Loading video recorder failed."));
+ break;
+ }
+ break;
+
+ default:
+ // Unregocnized internal state (Status)
+ setError(KErrNotSupported, tr("Requested capture mode is not supported."));
+ break;
+ }
+
+ emit captureModeChanged(mode);
+}
+
+bool S60CameraControl::isCaptureModeSupported(QCamera::CaptureMode mode) const
+{
+ switch (mode) {
+ case QCamera::CaptureStillImage:
+ return true;
+ case QCamera::CaptureVideo:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool S60CameraControl::canChangeProperty(QCameraControl::PropertyChangeType changeType, QCamera::Status status) const
+{
+ Q_UNUSED(status);
+
+ bool returnValue = false;
+
+ switch (changeType) {
+ case QCameraControl::CaptureMode:
+ case QCameraControl::VideoEncodingSettings:
+ case QCameraControl::ImageEncodingSettings:
+ returnValue = true;
+ break;
+
+ case QCameraControl::Viewfinder:
+ returnValue = false;
+ break;
+
+ default:
+ // Safer to revert state before the unknown operation
+ returnValue = false;
+ break;
+ }
+
+ return returnValue;
+}
+
+void S60CameraControl::setVideoOutput(QObject *output,
+ S60CameraViewfinderEngine::ViewfinderOutputType type)
+{
+ if (!m_viewfinderEngine) {
+ setError(KErrGeneral, tr("Failed to set viewfinder"));
+ return;
+ }
+
+ switch (type) {
+ case S60CameraViewfinderEngine::OutputTypeVideoWidget:
+ m_viewfinderEngine->setVideoWidgetControl(output);
+ break;
+ case S60CameraViewfinderEngine::OutputTypeRenderer:
+ m_viewfinderEngine->setVideoRendererControl(output);
+ break;
+ case S60CameraViewfinderEngine::OutputTypeVideoWindow:
+ m_viewfinderEngine->setVideoWindowControl(output);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void S60CameraControl::releaseVideoOutput(const S60CameraViewfinderEngine::ViewfinderOutputType type)
+{
+ m_viewfinderEngine->releaseControl(type);
+}
+
+void S60CameraControl::loadCamera()
+{
+ if (m_internalState < QCamera::LoadingStatus) {
+ m_internalState = QCamera::LoadingStatus;
+ emit statusChanged(m_internalState);
+ } else if (m_internalState == QCamera::LoadedStatus
+ || m_internalState >= QCamera::StartingStatus) {
+ // Nothing to load (already loaded)
+ return;
+ }
+ // Status = Loading or Standby
+
+ m_cameraEngine->ReserveAndPowerOn();
+
+ // Completion notified in MceoCameraReady()
+}
+
+void S60CameraControl::unloadCamera()
+{
+ if (m_internalState > QCamera::LoadingStatus) {
+ m_internalState = QCamera::LoadingStatus;
+ emit statusChanged(m_internalState);
+ } else if (m_internalState < QCamera::LoadingStatus) {
+ // Nothing to unload
+ return;
+ }
+ // Status = Loading
+
+ if (m_inactivityTimer->isActive())
+ m_inactivityTimer->stop();
+
+ m_cameraEngine->ReleaseAndPowerOff();
+
+ m_internalState = QCamera::UnloadedStatus;
+ emit statusChanged(m_internalState);
+}
+
+void S60CameraControl::startCamera()
+{
+ if (m_internalState < QCamera::StartingStatus) {
+ m_internalState = QCamera::StartingStatus;
+ emit statusChanged(m_internalState);
+ } else if (m_internalState > QCamera::StartingStatus) {
+ // Nothing to start (already started)
+ return;
+ }
+ // Status = Starting
+
+ if (m_inactivityTimer->isActive())
+ m_inactivityTimer->stop();
+
+ if (m_viewfinderEngine)
+ m_viewfinderEngine->startViewfinder();
+ else
+ setError(KErrGeneral, tr("Failed to start viewfinder."));
+
+ m_internalState = QCamera::ActiveStatus;
+ emit statusChanged(m_internalState);
+
+ emit cameraReadyChanged(true);
+
+#ifdef Q_CC_NOKIAX86 // Emulator
+ MceoCameraReady(); // Signal that we are ready
+#endif
+}
+
+void S60CameraControl::stopCamera()
+{
+ if (m_internalState > QCamera::StartingStatus) {
+ m_internalState = QCamera::StartingStatus;
+ emit statusChanged(m_internalState);
+ } else if (m_internalState < QCamera::StartingStatus) {
+ // Nothing to stop
+ return;
+ }
+ // Status = Starting
+
+ // Cancel ongoing operations if any
+ m_imageSession->cancelCapture();
+ m_videoSession->stopRecording();
+
+ emit cameraReadyChanged(false);
+ if (m_viewfinderEngine)
+ m_viewfinderEngine->stopViewfinder();
+ else
+ setError(KErrGeneral, tr("Failed to stop viewfinder."));
+
+ m_internalState = QCamera::LoadedStatus;
+ emit statusChanged(m_internalState);
+
+ m_inactivityTimer->start(KInactivityTimerTimeout);
+}
+
+void S60CameraControl::videoStateChanged(const S60VideoCaptureSession::TVideoCaptureState state)
+{
+ // Save video state
+ m_videoCaptureState = state;
+
+ if (m_rotateCameraWhenReady) {
+ if (m_videoCaptureState != S60VideoCaptureSession::ERecording &&
+ m_videoCaptureState != S60VideoCaptureSession::EPaused)
+ resetCameraOrientation();
+ }
+
+ // If video recording was stopped, video state reverts back to
+ // Initializing. In that case revert also Camera status to notify that
+ // video initialization needs to be completed.
+ if (state == S60VideoCaptureSession::EInitializing) {
+ if (m_internalState > QCamera::LoadingStatus) {
+ m_internalState = QCamera::LoadingStatus;
+ emit statusChanged(m_internalState);
+ }
+
+ // Handle video initialization completion
+ } else if (state == S60VideoCaptureSession::EInitialized) {
+
+ // Make sure state is not downgraded
+ if (m_internalState == QCamera::LoadedStatus
+ || m_internalState == QCamera::ActiveStatus) {
+ // Do nothing (already in target state)
+ } else if (m_internalState == QCamera::StartingStatus) {
+ m_internalState = QCamera::ActiveStatus;
+ emit statusChanged(m_internalState);
+ } else {
+ m_internalState = QCamera::LoadedStatus;
+ emit statusChanged(m_internalState);
+ }
+
+ switch (m_requestedState) {
+ case QCamera::UnloadedState:
+ stopCamera();
+ unloadCamera();
+ if (m_changeCaptureModeWhenReady) {
+ m_settingCaptureModeInternally = true;
+ setCaptureMode(m_requestedCaptureMode);
+ }
+ break;
+ case QCamera::LoadedState:
+ stopCamera();
+ if (m_changeCaptureModeWhenReady) {
+ m_settingCaptureModeInternally = true;
+ setCaptureMode(m_requestedCaptureMode);
+ }
+ m_inactivityTimer->start(KInactivityTimerTimeout);
+ break;
+ case QCamera::ActiveState:
+ if (m_changeCaptureModeWhenReady) {
+ m_settingCaptureModeInternally = true;
+ setCaptureMode(m_requestedCaptureMode);
+ }
+ startCamera();
+ break;
+
+ default:
+ setError(KErrGeneral, tr("Unexpected camera error."));
+ return;
+ }
+ }
+}
+
+void S60CameraControl::imageCaptured(const int imageId, const QImage& preview)
+{
+ Q_UNUSED(imageId);
+ Q_UNUSED(preview);
+
+ // Unsubscribe the readyForCaptureChanged notification
+ disconnect(m_imageSession, SIGNAL(imageCaptured(const int, const QImage&)),
+ this, SLOT(imageCaptured(const int, const QImage&)));
+
+ if (m_rotateCameraWhenReady)
+ resetCameraOrientation();
+}
+
+void S60CameraControl::advancedSettingsCreated()
+{
+ m_advancedSettings = m_imageSession->advancedSettings();
+
+ if (m_advancedSettings)
+ connect(m_advancedSettings, SIGNAL(error(int, const QString&)), this, SIGNAL(error(int, const QString&)));
+}
+
+void S60CameraControl::MceoCameraReady()
+{
+ // Rotate camera if requested
+ if (m_rotateCameraWhenReady) {
+ resetCameraOrientation();
+ return;
+ }
+
+ if (m_internalState != QCamera::LoadedStatus) {
+
+ switch (m_requestedState) {
+ case QCamera::UnloadedState:
+ m_internalState = QCamera::LoadedStatus;
+ emit statusChanged(QCamera::LoadedStatus);
+
+ stopCamera();
+ unloadCamera();
+
+ if (m_changeCaptureModeWhenReady) {
+ m_settingCaptureModeInternally = true;
+ setCaptureMode(m_requestedCaptureMode);
+ }
+ break;
+
+ case QCamera::LoadedState:
+ if (m_captureMode == QCamera::CaptureVideo) {
+ int prepareSuccess = m_videoSession->initializeVideoRecording();
+ setError(prepareSuccess, tr("Loading video capture failed."));
+
+ // State change signalled when reservation is complete (in videoStateChanged())
+ return;
+ }
+ m_internalState = QCamera::LoadedStatus;
+ emit statusChanged(QCamera::LoadedStatus);
+
+ if (m_changeCaptureModeWhenReady) {
+ setCaptureMode(m_requestedCaptureMode);
+ m_changeCaptureModeWhenReady = false; // Reset
+ }
+
+ if (m_requestedState == QCamera::LoadedStatus &&
+ m_internalState == QCamera::LoadedStatus)
+ m_inactivityTimer->start(KInactivityTimerTimeout);
+ break;
+
+ case QCamera::ActiveState:
+ if (m_captureMode == QCamera::CaptureVideo) {
+ int prepareSuccess = m_videoSession->initializeVideoRecording();
+ setError(prepareSuccess, tr("Loading video capture failed."));
+
+ // State change signalled when reservation is complete (in videoStateChanged())
+ return;
+ }
+
+ m_internalState = QCamera::LoadedStatus;
+ emit statusChanged(QCamera::LoadedStatus);
+
+ if (m_changeCaptureModeWhenReady) {
+ setCaptureMode(m_requestedCaptureMode);
+ m_changeCaptureModeWhenReady = false; // Reset
+ }
+ startCamera();
+ break;
+
+ default:
+ setError(KErrGeneral, tr("Unexpected camera error."));
+ return;
+ }
+ }
+}
+
+void S60CameraControl::MceoHandleError(TCameraEngineError aErrorType, TInt aError)
+{
+ Q_UNUSED(aErrorType);
+
+ if (aError == KErrAccessDenied) {
+ setError(KErrGeneral, tr("Access to camera device was rejected."));
+ } else if (aError == KErrHardwareNotAvailable) {
+ setError(aError, tr("Camera resources were lost."));
+ toStandByStatus();
+ }
+ else
+ setError(aError, tr("Unexpected camera error."));
+}
+
+void S60CameraControl::setError(const TInt error, const QString &description)
+{
+ if (error == KErrNone)
+ return;
+
+ m_error = error;
+ QCamera::Error cameraError = fromSymbianErrorToQtMultimediaError(m_error);
+
+ emit this->error(int(cameraError), description);
+
+ // Reset everything, if other than not supported error or resource loss
+ if (error != KErrNotSupported && error != KErrHardwareNotAvailable)
+ resetCamera(true); // Try to recover from error
+ else
+ m_error = KErrNone; // Reset error
+}
+
+QCamera::Error S60CameraControl::fromSymbianErrorToQtMultimediaError(int aError)
+{
+ switch(aError) {
+ case KErrNone:
+ return QCamera::NoError; // No errors have occurred
+
+ case KErrNotSupported:
+ return QCamera::NotSupportedFeatureError; // The feature is not supported
+ case KErrNotFound:
+ case KErrBadHandle:
+ return QCamera::ServiceMissingError; // No camera service available
+ case KErrArgument:
+ case KErrNotReady:
+ return QCamera::InvalidRequestError; // Invalid parameter or state
+
+ default:
+ return QCamera::CameraError; // An error has occurred (i.e. General Error)
+ }
+}
+
+// For S60CameraVideoDeviceControl
+int S60CameraControl::deviceCount()
+{
+#ifdef Q_CC_NOKIAX86 // Emulator
+ return 1;
+#endif
+
+ return CCameraEngine::CamerasAvailable();
+}
+
+int S60CameraControl::defaultDevice() const
+{
+ return KDefaultCameraDevice;
+}
+
+int S60CameraControl::selectedDevice() const
+{
+ return m_deviceIndex;
+}
+
+void S60CameraControl::setSelectedDevice(const int index)
+{
+ if (m_deviceIndex != index) {
+ if (index >= 0 && index < deviceCount()) {
+ m_deviceIndex = index;
+ resetCamera();
+ } else {
+ setError(KErrNotSupported, tr("Requested camera is not available."));
+ }
+ }
+}
+
+QString S60CameraControl::name(const int index)
+{
+ QString cameraName;
+ switch (index) {
+ case 0:
+ cameraName = tr("Primary camera");
+ break;
+ case 1:
+ cameraName = tr("Secondary camera");
+ break;
+ case 2:
+ cameraName = tr("Tertiary camera");
+ break;
+
+ default:
+ cameraName = tr("Unidentified Camera");
+ break;
+ }
+
+ return cameraName;
+}
+
+QString S60CameraControl::description(const int index)
+{
+ QString cameraDesc;
+ switch (index) {
+ case 0:
+ cameraDesc = tr("Device primary camera");
+ break;
+ case 1:
+ cameraDesc = tr("Device secondary camera");
+ break;
+ case 2:
+ cameraDesc = tr("Device tertiary camera");
+ break;
+
+ default:
+ cameraDesc = tr("Unidentified Camera");
+ break;
+ }
+
+ return cameraDesc;
+}
+
+void S60CameraControl::resetCamera(bool errorHandling)
+{
+ if (m_inactivityTimer->isActive())
+ m_inactivityTimer->stop();
+
+ // Cancel ongoing activity
+ m_imageSession->cancelCapture();
+ m_videoSession->stopRecording(false); // Don't re-initialize video
+
+ // Advanced settings must be destructed before the camera
+ m_imageSession->deleteAdvancedSettings();
+
+ // Release resources
+ stopCamera();
+ unloadCamera();
+
+ disconnect(m_viewfinderEngine, SIGNAL(error(int, const QString&)), this, SIGNAL(error(int,const QString&)));
+ if (m_viewfinderEngine) {
+ delete m_viewfinderEngine;
+ m_viewfinderEngine = 0;
+ }
+
+ if (m_cameraEngine) {
+ delete m_cameraEngine;
+ m_cameraEngine = 0;
+ }
+
+ TRAPD(err, m_cameraEngine = CCameraEngine::NewL(m_deviceIndex, 0, this));
+ if (err) {
+ m_cameraEngine = 0;
+ if (errorHandling) {
+ qWarning("Failed to recover from error.");
+ if (err == KErrPermissionDenied)
+ emit error(int(QCamera::ServiceMissingError), tr("Recovering from error failed. Possibly missing capabilities."));
+ else
+ emit error(int(QCamera::CameraError), tr("Recovering from error failed."));
+ } else {
+ if (err == KErrPermissionDenied)
+ setError(err, tr("Camera device creation failed. Possibly missing capabilities."));
+ else
+ setError(err, tr("Camera device creation failed."));
+ }
+ return;
+ }
+
+ // Notify list of available camera devices has been updated
+ emit devicesChanged();
+
+ m_viewfinderEngine = new S60CameraViewfinderEngine(this, m_cameraEngine, this);
+ if (m_viewfinderEngine == 0)
+ setError(KErrNoMemory, tr("Viewfinder device creation failed."));
+ connect(m_viewfinderEngine, SIGNAL(error(int, const QString&)), this, SIGNAL(error(int,const QString&)));
+
+ setCameraHandles();
+
+ // Reset state
+ //setState(QCamera::UnloadedState);
+ if (m_internalState != QCamera::UnloadedStatus) {
+ m_internalState = QCamera::UnloadedStatus;
+ emit statusChanged(m_internalState);
+ }
+ if (m_requestedState != QCamera::UnloadedState) {
+ m_requestedState = QCamera::UnloadedState;
+ emit stateChanged(m_requestedState);
+ }
+
+ // Reset error
+ m_error = KErrNone;
+}
+
+/*
+ * Reset everything else than viewfinder engine and errors.
+ */
+void S60CameraControl::resetCameraOrientation()
+{
+ // If camera has not been created, it will be created automatically to correct orientation
+ if (!m_cameraEngine)
+ return;
+
+ // Check Image/VideoCapture allow rotation
+ if ((!m_cameraEngine->IsCameraReady() && m_internalState != QCamera::UnloadedStatus) ||
+ m_videoCaptureState == S60VideoCaptureSession::ERecording ||
+ m_videoCaptureState == S60VideoCaptureSession::EPaused) {
+
+ // If image capture is ongoing, request notification about the
+ // completion (imageCaptured() is used because that comes asynchronously
+ // after the image is captured)
+ // Obs! If preview creation is changed to be synchnonously done during
+ // the image capture this implementation needs to be changed)
+ if (m_videoCaptureState != S60VideoCaptureSession::ERecording &&
+ m_videoCaptureState != S60VideoCaptureSession::EPaused &&
+ m_internalState == QCamera::ActiveStatus)
+ connect(m_imageSession, SIGNAL(imageCaptured(const int, const QImage&)),
+ this, SLOT(imageCaptured(const int, const QImage&)));
+
+ m_rotateCameraWhenReady = true;
+ return;
+ }
+
+ m_rotateCameraWhenReady = false; // Reset
+
+ QCamera::State originalState = m_requestedState;
+
+ // Cancel ongoing activity
+ m_imageSession->cancelCapture();
+ m_videoSession->stopRecording(false); // Don't re-initialize video
+
+ // Advanced settings must be destructed before the camera
+ m_imageSession->deleteAdvancedSettings();
+
+ // Release resources
+ stopCamera();
+ unloadCamera();
+
+ // Unset CameraEngine to ViewfinderEngine
+ m_viewfinderEngine->setNewCameraEngine(0);
+ if (m_cameraEngine) {
+ delete m_cameraEngine;
+ m_cameraEngine = 0;
+ }
+
+ TRAPD(err, m_cameraEngine = CCameraEngine::NewL(m_deviceIndex, 0, this));
+ if (err) {
+ setError(err, tr("Camera device creation failed."));
+ return;
+ }
+ // Reset CameraEngine to ViewfinderEngine
+ m_viewfinderEngine->setNewCameraEngine(m_cameraEngine);
+
+ // Notify list of available camera devices has been updated
+ emit devicesChanged();
+
+ setCameraHandles();
+
+ // Reset state
+ if (m_internalState != QCamera::UnloadedStatus) {
+ m_internalState = QCamera::UnloadedStatus;
+ emit statusChanged(m_internalState);
+ }
+ if (m_requestedState != QCamera::UnloadedState) {
+ m_requestedState = QCamera::UnloadedState;
+ emit stateChanged(m_requestedState);
+ }
+
+ setState(originalState);
+}
+
+void S60CameraControl::setCameraHandles()
+{
+ m_imageSession->setCurrentDevice(m_deviceIndex);
+ m_imageSession->setCameraHandle(m_cameraEngine);
+ m_cameraEngine->SetImageCaptureObserver(m_imageSession);
+ m_videoSession->setCameraHandle(m_cameraEngine);
+}
+
+void S60CameraControl::toStandByStatus()
+{
+ // Cancel ongoing operations if any
+ m_imageSession->cancelCapture();
+ m_videoSession->stopRecording(false); // Don't re-initialize video
+
+ emit cameraReadyChanged(false);
+ if (m_viewfinderEngine)
+ m_viewfinderEngine->stopViewfinder();
+ else
+ setError(KErrGeneral, tr("Failed to stop viewfinder."));
+
+ m_cameraEngine->ReleaseAndPowerOff();
+
+ m_internalState = QCamera::StandbyStatus;
+ emit statusChanged(m_internalState);
+}
+
+// End of file
diff --git a/src/plugins/symbian/ecam/s60cameracontrol.h b/src/plugins/symbian/ecam/s60cameracontrol.h
new file mode 100644
index 000000000..95c31fb34
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameracontrol.h
@@ -0,0 +1,178 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef S60CAMERACONTROL_H
+#define S60CAMERACONTROL_H
+
+#include <qcameracontrol.h>
+
+#include "s60cameraengineobserver.h" // MCameraEngineObserver
+#include "s60videocapturesession.h" // TVideoCaptureState
+#include "s60cameraviewfinderengine.h" // ViewfinderOutputType
+
+#include <e32base.h>
+#include <fbs.h>
+
+QT_USE_NAMESPACE
+
+class S60CameraService;
+class S60ImageCaptureSession;
+class S60VideoCaptureSession;
+class S60CameraSettings;
+class CCameraEngine;
+class S60CameraViewfinderEngine;
+class QTimer;
+
+/*
+ * Control for controlling camera base operations (e.g. start/stop and capture
+ * mode).
+ */
+class S60CameraControl : public QCameraControl, public MCameraEngineObserver
+{
+ Q_OBJECT
+
+public: // Constructors & Destructor
+
+ S60CameraControl(QObject *parent = 0);
+ S60CameraControl(S60VideoCaptureSession *videosession,
+ S60ImageCaptureSession *imagesession,
+ QObject *parent = 0);
+ ~S60CameraControl();
+
+public: // QCameraControl
+
+ // State
+ QCamera::State state() const;
+ void setState(QCamera::State state);
+
+ // Status
+ QCamera::Status status() const;
+
+ // Capture Mode
+ QCamera::CaptureMode captureMode() const;
+ void setCaptureMode(QCamera::CaptureMode);
+ bool isCaptureModeSupported(QCamera::CaptureMode mode) const;
+
+ // Property Setting
+ bool canChangeProperty(QCameraControl::PropertyChangeType changeType, QCamera::Status status) const;
+
+/*
+Q_SIGNALS:
+ void stateChanged(QCamera::State);
+ void statusChanged(QCamera::Status);
+ void error(int error, const QString &errorString);
+ void captureModeChanged(QCamera::CaptureMode);
+*/
+
+public: // Internal
+
+ void setError(const TInt error, const QString &description);
+ void resetCameraOrientation();
+
+ // To provide QVideoDeviceControl info
+ static int deviceCount();
+ static QString name(const int index);
+ static QString description(const int index);
+ int defaultDevice() const;
+ int selectedDevice() const;
+ void setSelectedDevice(const int index);
+
+ void setVideoOutput(QObject *output,
+ const S60CameraViewfinderEngine::ViewfinderOutputType type);
+ void releaseVideoOutput(const S60CameraViewfinderEngine::ViewfinderOutputType type);
+
+private slots: // Internal Slots
+
+ void videoStateChanged(const S60VideoCaptureSession::TVideoCaptureState state);
+ // Needed to detect image capture completion when trying to rotate the camera
+ void imageCaptured(const int imageId, const QImage& preview);
+ /*
+ * This method moves the camera to the StandBy status:
+ * - If camera access was lost
+ * - If camera has been inactive in LoadedStatus for a long time
+ */
+ void toStandByStatus();
+ void advancedSettingsCreated();
+
+protected: // MCameraEngineObserver
+
+ void MceoCameraReady();
+ void MceoHandleError(TCameraEngineError aErrorType, TInt aError);
+
+private: // Internal
+
+ QCamera::Error fromSymbianErrorToQtMultimediaError(int aError);
+
+ void loadCamera();
+ void unloadCamera();
+ void startCamera();
+ void stopCamera();
+
+ void resetCamera(bool errorHandling = false);
+ void setCameraHandles();
+
+signals: // Internal Signals
+
+ void cameraReadyChanged(bool);
+ void devicesChanged();
+
+private: // Data
+
+ CCameraEngine *m_cameraEngine;
+ S60CameraViewfinderEngine *m_viewfinderEngine;
+ S60ImageCaptureSession *m_imageSession;
+ S60VideoCaptureSession *m_videoSession;
+ S60CameraSettings *m_advancedSettings;
+ QObject *m_videoOutput;
+ QTimer *m_inactivityTimer;
+ QCamera::CaptureMode m_captureMode;
+ QCamera::CaptureMode m_requestedCaptureMode;
+ bool m_settingCaptureModeInternally;
+ QCamera::Status m_internalState;
+ QCamera::State m_requestedState;
+ int m_deviceIndex;
+ mutable int m_error;
+ bool m_changeCaptureModeWhenReady;
+ bool m_rotateCameraWhenReady;
+ S60VideoCaptureSession::TVideoCaptureState m_videoCaptureState;
+};
+
+#endif // S60CAMERACONTROL_H
diff --git a/src/plugins/symbian/ecam/s60cameraengine.cpp b/src/plugins/symbian/ecam/s60cameraengine.cpp
new file mode 100644
index 000000000..dbd5fb33e
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameraengine.cpp
@@ -0,0 +1,824 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ ** All rights reserved.
+ ** Contact: Nokia Corporation (qt-info@nokia.com)
+ **
+ ** This file is part of the Qt Mobility Components.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** No Commercial Usage
+ ** This file contains pre-release code and may not be distributed.
+ ** You may use this file in accordance with the terms and conditions
+ ** contained in the Technology Preview License Agreement accompanying
+ ** this package.
+ **
+ ** GNU Lesser General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU Lesser
+ ** General Public License version 2.1 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.LGPL included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU Lesser General Public License version 2.1 requirements
+ ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** If you have questions regarding the use of this file, please contact
+ ** Nokia at qt-info@nokia.com.
+ **
+ **
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#include "s60cameraengine.h"
+#include "s60cameraengineobserver.h"
+#include "s60cameraconstants.h"
+#include <QtCore/qglobal.h>
+#include <fbs.h> // CFbsBitmap
+#ifdef ECAM_PREVIEW_API
+ #include <platform/ecam/camerasnapshot.h>
+#endif // ECAM_PREVIEW_API
+
+CCameraEngine::CCameraEngine()
+{
+}
+
+CCameraEngine::CCameraEngine(TInt aCameraHandle,
+ TInt aPriority,
+ MCameraEngineObserver* aObserver) :
+ // CBase initializes member variables to NULL
+ iObserver(aObserver),
+ iCameraIndex(aCameraHandle),
+ iPriority(aPriority),
+ iEngineState(EEngineNotReady),
+ iCaptureResolution(TSize(0,0)),
+ iNew2LImplementation(false),
+ iLatestImageBufferIndex(1) // Thus we start from index 0
+{
+ // Observer is mandatory
+ ASSERT(aObserver != NULL);
+}
+
+CCameraEngine::~CCameraEngine()
+{
+ StopViewFinder();
+ ReleaseViewFinderBuffer(); // Releases iViewFinderBuffer
+ ReleaseImageBuffer(); // Releases iImageBuffer + iImageBitmap
+
+ iAdvancedSettingsObserver = NULL;
+ iImageCaptureObserver = NULL;
+ iViewfinderObserver = NULL;
+
+#ifdef S60_CAM_AUTOFOCUS_SUPPORT
+ delete iAutoFocus;
+#endif // S60_CAM_AUTOFOCUS_SUPPORT
+
+ if (iCamera) {
+ iCamera->Release();
+ delete iCamera;
+ iCamera = NULL;
+ }
+}
+
+TInt CCameraEngine::CamerasAvailable()
+{
+ return CCamera::CamerasAvailable();
+}
+
+CCameraEngine* CCameraEngine::NewL(TInt aCameraHandle,
+ TInt aPriority,
+ MCameraEngineObserver* aObserver)
+{
+ CCameraEngine* self = new (ELeave) CCameraEngine(aCameraHandle, aPriority, aObserver);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+}
+
+void CCameraEngine::ConstructL()
+{
+ if (!CCamera::CamerasAvailable())
+ User::Leave(KErrHardwareNotAvailable);
+
+#ifndef Q_CC_NOKIAX86 // Not Emulator
+ TInt err(KErrNone);
+#else // Emulator
+ TInt err(KErrNotFound);
+#endif // !(Q_CC_NOKIAX86)
+
+#ifdef S60_31_PLATFORM
+ // Construct CCamera object for S60 3.1 (NewL)
+ iNew2LImplementation = false;
+ TRAP(err, iCamera = CCamera::NewL(*this, iCameraIndex));
+ if (err)
+ User::Leave(err);
+#else // For S60 3.2 onwards - use this constructor (New2L)
+ iNew2LImplementation = true;
+ TRAP(err, iCamera = CCamera::New2L(*this, iCameraIndex, iPriority));
+ if (err)
+ User::Leave(err);
+#endif // S60_31_PLATFORM
+
+#ifdef S60_CAM_AUTOFOCUS_SUPPORT
+ // Might not be supported for secondary camera, discard errors
+ TRAP(err, iAutoFocus = CCamAutoFocus::NewL(iCamera));
+#endif // S60_CAM_AUTOFOCUS_SUPPORT
+
+ if (iCamera == NULL)
+ User::Leave(KErrNoMemory);
+
+ iCamera->CameraInfo(iCameraInfo);
+}
+
+void CCameraEngine::SetAdvancedObserver(MAdvancedSettingsObserver* aAdvancedSettingsObserver)
+{
+ iAdvancedSettingsObserver = aAdvancedSettingsObserver;
+}
+
+void CCameraEngine::SetImageCaptureObserver(MCameraEngineImageCaptureObserver* aImageCaptureObserver)
+{
+ iImageCaptureObserver = aImageCaptureObserver;
+}
+
+void CCameraEngine::SetViewfinderObserver(MCameraViewfinderObserver* aViewfinderObserver)
+{
+ iViewfinderObserver = aViewfinderObserver;
+}
+
+void CCameraEngine::ReserveAndPowerOn()
+{
+ if (!iCamera || iEngineState > EEngineNotReady) {
+ iObserver->MceoHandleError(EErrReserve, KErrNotReady);
+ return;
+ }
+
+ iCamera->Reserve();
+}
+
+void CCameraEngine::ReleaseAndPowerOff()
+{
+ if (iEngineState >= EEngineIdle) {
+ CancelCapture();
+ StopViewFinder();
+ FocusCancel();
+ iCamera->PowerOff();
+ iCamera->Release();
+ }
+ iEngineState = EEngineNotReady;
+}
+
+void CCameraEngine::StartViewFinderL(TSize& aSize)
+{
+ if (iEngineState < EEngineIdle)
+ User::Leave(KErrNotReady);
+
+ if (0 == (iCameraInfo.iOptionsSupported & TCameraInfo::EViewFinderBitmapsSupported))
+ User::Leave(KErrNotSupported);
+
+ if (!iCamera->ViewFinderActive()) {
+ if (iCameraIndex != 0)
+ iCamera->SetViewFinderMirrorL(true);
+ iCamera->StartViewFinderBitmapsL(aSize);
+ }
+}
+
+void CCameraEngine::StopViewFinder()
+{
+ if (iCamera && iCamera->ViewFinderActive())
+ iCamera->StopViewFinder();
+}
+
+void CCameraEngine::StartDirectViewFinderL(RWsSession& aSession,
+ CWsScreenDevice& aScreenDevice,
+ RWindowBase& aWindow,
+ TRect& aScreenRect,
+ TRect& aClipRect)
+{
+ if (iEngineState < EEngineIdle)
+ User::Leave(KErrNotReady);
+
+ if (0 == (iCameraInfo.iOptionsSupported & TCameraInfo::EViewFinderDirectSupported))
+ User::Leave(KErrNotSupported);
+
+ if (!iCamera->ViewFinderActive()) {
+ // Viewfinder extent needs to be clipped according to the clip rect.
+ // This is because the native camera framework does not support
+ // clipping and starting viewfinder with bigger than the display(S60
+ // 5.0 and older)/window(Symbian^3 and later) would cause viewfinder
+ // starting to fail entirely. This causes shrinking effect in some
+ // cases, but is better than not having the viewfinder at all.
+ if (aScreenRect.Intersects(aClipRect))
+ aScreenRect.Intersection(aClipRect);
+
+ if (iCameraIndex != 0)
+ iCamera->SetViewFinderMirrorL(true);
+ if (aScreenRect.Width() > 0 && aScreenRect.Height() > 0) {
+ iCamera->StartViewFinderDirectL(aSession, aScreenDevice, aWindow, aScreenRect);
+ } else {
+ if (iObserver)
+ iObserver->MceoHandleError(EErrViewFinderReady, KErrArgument);
+ }
+ }
+}
+
+void CCameraEngine::PrepareL(TSize& aCaptureSize, CCamera::TFormat aFormat)
+{
+ iImageCaptureFormat = aFormat;
+
+ TInt closestVar = KMaxTInt, selected = 0;
+ TSize size;
+
+ // Scan through supported capture sizes and select the closest match
+ for (TInt index = 0; index < iCameraInfo.iNumImageSizesSupported; index++) {
+
+ iCamera->EnumerateCaptureSizes(size, index, aFormat);
+ if (size == aCaptureSize) {
+ selected = index;
+ break;
+ }
+
+ TSize varSz = size - aCaptureSize;
+ TInt variation = varSz.iWidth * varSz.iHeight;
+ if (variation < closestVar) {
+ closestVar = variation;
+ selected = index;
+ }
+ }
+
+ iCamera->EnumerateCaptureSizes(aCaptureSize, selected, aFormat);
+ iCaptureResolution = aCaptureSize;
+ iCamera->PrepareImageCaptureL(aFormat, selected);
+}
+
+void CCameraEngine::CaptureL()
+{
+ if (iEngineState < EEngineIdle)
+ User::Leave(KErrNotReady);
+
+ iCamera->CaptureImage();
+ iEngineState = EEngineCapturing;
+}
+
+void CCameraEngine::CancelCapture()
+{
+ if (iEngineState == EEngineCapturing) {
+ iCamera->CancelCaptureImage();
+ iEngineState = EEngineIdle;
+ }
+}
+
+void CCameraEngine::HandleEvent(const TECAMEvent &aEvent)
+{
+ if (aEvent.iEventType == KUidECamEventReserveComplete) {
+ ReserveComplete(aEvent.iErrorCode);
+ return;
+ }
+
+ if (aEvent.iEventType == KUidECamEventPowerOnComplete) {
+ PowerOnComplete(aEvent.iErrorCode);
+ return;
+ }
+
+ if (aEvent.iEventType == KUidECamEventCameraNoLongerReserved) {
+ // All camera related operations need to be stopped
+ iObserver->MceoHandleError(EErrReserve, KErrHardwareNotAvailable);
+ return;
+ }
+
+#ifdef ECAM_PREVIEW_API
+ if (aEvent.iEventType == KUidECamEventCameraSnapshot) {
+ HandlePreview();
+ return;
+ }
+#endif // ECAM_PREVIEW_API
+
+#if !defined(Q_CC_NOKIAX86) // Not Emulator
+ // Other events; Exposure, Zoom, etc. (See ecamadvancedsettings.h)
+ if (iAdvancedSettingsObserver)
+ iAdvancedSettingsObserver->HandleAdvancedEvent(aEvent);
+
+ if (iImageCaptureObserver)
+ iImageCaptureObserver->MceoHandleOtherEvent(aEvent);
+#endif // !Q_CC_NOKIAX86
+}
+
+void CCameraEngine::ReserveComplete(TInt aError)
+{
+ if (aError == KErrNone) {
+ iCamera->PowerOn();
+#ifdef S60_31_PLATFORM
+ } else if (aError == KErrAlreadyExists) { // Known Issue on some S60 3.1 devices
+ User::After(500000); // Wait for 0,5 second and try again
+ iCamera->Reserve();
+#endif // S60_31_PLATFORM
+ } else {
+ iObserver->MceoHandleError(EErrReserve, aError);
+ }
+}
+
+void CCameraEngine::PowerOnComplete(TInt aError)
+{
+ if (aError) {
+ iObserver->MceoHandleError(EErrPowerOn, aError);
+ iEngineState = EEngineNotReady;
+ return;
+ }
+
+ // Init AutoFocus
+#ifndef Q_CC_NOKIAX86 // Not Emulator
+#ifdef S60_CAM_AUTOFOCUS_SUPPORT // S60 3.1
+ if( iAutoFocus ) {
+ TRAPD(afErr, iAutoFocus->InitL( *this ));
+ if (afErr) {
+ delete iAutoFocus;
+ iAutoFocus = 0;
+ }
+ }
+#endif // S60_CAM_AUTOFOCUS_SUPPORT
+#endif // !Q_CC_NOKIAX86
+
+ iEngineState = EEngineIdle;
+ iObserver->MceoCameraReady();
+}
+
+#ifdef ECAM_PREVIEW_API
+/**
+ * This method creates the CCameraPreview object and requests the previews to
+ * be provided during the image or video capture
+ */
+void CCameraEngine::EnablePreviewProvider(MCameraPreviewObserver *aPreviewObserver)
+{
+ // Delete old one if exists
+ if (iCameraSnapshot)
+ delete iCameraSnapshot;
+
+ iPreviewObserver = aPreviewObserver;
+
+ TInt error = KErrNone;
+
+ if (iCamera) {
+ TRAP(error, iCameraSnapshot = CCamera::CCameraSnapshot::NewL(*iCamera));
+ if (error) {
+ if (iObserver)
+ iObserver->MceoHandleError(EErrPreview, error);
+ return;
+ }
+
+ TRAP(error, iCameraSnapshot->PrepareSnapshotL(KDefaultFormatPreview, SelectPreviewResolution(), EFalse));
+ if (error) {
+ if (iObserver)
+ iObserver->MceoHandleError(EErrPreview, error);
+ return;
+ }
+
+ iCameraSnapshot->StartSnapshot();
+ } else {
+ if (iObserver)
+ iObserver->MceoHandleError(EErrPreview, KErrNotReady);
+ }
+}
+
+/**
+ * This method disables and destroys the CCameraPreview object. Thus previews
+ * will not be provided during the image or video capture.
+ */
+void CCameraEngine::DisablePreviewProvider()
+{
+ if (!iCameraSnapshot)
+ return;
+
+ iCameraSnapshot->StopSnapshot();
+
+ delete iCameraSnapshot;
+ iCameraSnapshot = 0;
+
+ iPreviewObserver = 0;
+}
+#endif // ECAM_PREVIEW_API
+
+/*
+ * MCameraObserver2:
+ * New viewfinder frame available
+ */
+void CCameraEngine::ViewFinderReady(MCameraBuffer &aCameraBuffer, TInt aError)
+{
+ iViewFinderBuffer = &aCameraBuffer;
+
+ if (aError == KErrNone) {
+ if (iViewfinderObserver) {
+ TRAPD(err, iViewfinderObserver->MceoViewFinderFrameReady(aCameraBuffer.BitmapL(0)));
+ if (err)
+ iObserver->MceoHandleError(EErrViewFinderReady, err);
+ } else {
+ iObserver->MceoHandleError(EErrViewFinderReady, KErrNotReady);
+ }
+ }
+ else {
+ iObserver->MceoHandleError(EErrViewFinderReady, aError);
+ }
+}
+
+/*
+ * MCameraObserver:
+ * New viewfinder frame available
+ */
+void CCameraEngine::ViewFinderFrameReady(CFbsBitmap& aFrame)
+{
+ if (iViewfinderObserver)
+ iViewfinderObserver->MceoViewFinderFrameReady(aFrame);
+ else
+ iObserver->MceoHandleError(EErrViewFinderReady, KErrNotReady);
+}
+
+void CCameraEngine::ReleaseViewFinderBuffer()
+{
+ if (iNew2LImplementation) { // NewL Implementation does not use MCameraBuffer
+ if (iViewFinderBuffer) {
+ iViewFinderBuffer->Release();
+ iViewFinderBuffer = NULL;
+ }
+ }
+}
+
+void CCameraEngine::ReleaseImageBuffer()
+{
+ // Reset Bitmap
+ if (iLatestImageBufferIndex == 1 || iImageBitmap2 == NULL) {
+ if (iImageBitmap1) {
+ if (!iNew2LImplementation) { // NewL - Ownership transferred
+ iImageBitmap1->Reset(); // Reset/Delete Bitmap
+ delete iImageBitmap1;
+ }
+ iImageBitmap1 = NULL;
+ }
+ } else {
+ if (iImageBitmap2) {
+ if (!iNew2LImplementation) { // NewL - Ownership transferred
+ iImageBitmap2->Reset(); // Reset/Delete Bitmap
+ delete iImageBitmap2;
+ }
+ iImageBitmap2 = NULL;
+ }
+ }
+
+ // Reset Data pointers
+ if (iLatestImageBufferIndex == 1 || iImageData2 == NULL) {
+ if (!iNew2LImplementation) // NewL - Ownership transfers with buffer
+ delete iImageData1;
+ iImageData1 = NULL;
+ } else {
+ if (!iNew2LImplementation) // NewL - Ownership transfers with buffer
+ delete iImageData2;
+ iImageData2 = NULL;
+ }
+
+ // Reset ImageBuffer - New2L Implementation only
+ if (iLatestImageBufferIndex == 1 || iImageBuffer2 == NULL) {
+ if (iImageBuffer1) {
+ iImageBuffer1->Release();
+ iImageBuffer1 = NULL;
+ }
+ } else {
+ if (iImageBuffer2) {
+ iImageBuffer2->Release();
+ iImageBuffer2 = NULL;
+ }
+ }
+}
+
+/*
+ * MCameraObserver2
+ * Captured image is ready (New2L version)
+ */
+void CCameraEngine::ImageBufferReady(MCameraBuffer &aCameraBuffer, TInt aError)
+{
+ // Use the buffer that is available
+ if (!iImageBuffer1) {
+ iLatestImageBufferIndex = 0;
+ iImageBuffer1 = &aCameraBuffer;
+ } else {
+ iLatestImageBufferIndex = 1;
+ iImageBuffer2 = &aCameraBuffer;
+ }
+
+ bool isBitmap = true;
+ TInt err = KErrNone;
+
+ switch (iImageCaptureFormat) {
+ case CCamera::EFormatFbsBitmapColor4K:
+ case CCamera::EFormatFbsBitmapColor64K:
+ case CCamera::EFormatFbsBitmapColor16M:
+ case CCamera::EFormatFbsBitmapColor16MU:
+ if (iLatestImageBufferIndex == 0) {
+ TRAP(err, iImageBitmap1 = &iImageBuffer1->BitmapL(0));
+ if (err) {
+ if (iImageCaptureObserver)
+ iImageCaptureObserver->MceoHandleError(EErrImageReady, err);
+ }
+ } else {
+ TRAP(err, iImageBitmap2 = &iImageBuffer2->BitmapL(0));
+ if (err) {
+ if (iImageCaptureObserver)
+ iImageCaptureObserver->MceoHandleError(EErrImageReady, err);
+ }
+ }
+ isBitmap = true;
+ break;
+ case CCamera::EFormatExif:
+ if (iLatestImageBufferIndex == 0) {
+ TRAP(err, iImageData1 = iImageBuffer1->DataL(0));
+ if (err) {
+ if (iImageCaptureObserver)
+ iImageCaptureObserver->MceoHandleError(EErrImageReady, err);
+ }
+ } else {
+ TRAP(err, iImageData2 = iImageBuffer2->DataL(0));
+ if (err) {
+ if (iImageCaptureObserver)
+ iImageCaptureObserver->MceoHandleError(EErrImageReady, err);
+ }
+ }
+ isBitmap = false;
+ break;
+
+ default:
+ if (iImageCaptureObserver)
+ iImageCaptureObserver->MceoHandleError(EErrImageReady, KErrNotSupported);
+ return;
+ }
+
+ // Handle captured image
+ HandleImageReady(aError, isBitmap);
+}
+
+/*
+ * MCameraObserver
+ * Captured image is ready (NewL version)
+ */
+void CCameraEngine::ImageReady(CFbsBitmap* aBitmap, HBufC8* aData, TInt aError)
+{
+ bool isBitmap = true;
+
+ // Toggle between the 2 buffers
+ if (iLatestImageBufferIndex == 1) {
+ iLatestImageBufferIndex = 0;
+ } else {
+ iLatestImageBufferIndex = 1;
+ }
+
+ switch (iImageCaptureFormat) {
+ case CCamera::EFormatFbsBitmapColor4K:
+ case CCamera::EFormatFbsBitmapColor64K:
+ case CCamera::EFormatFbsBitmapColor16M:
+ case CCamera::EFormatFbsBitmapColor16MU:
+ if (iLatestImageBufferIndex == 0)
+ iImageBitmap1 = aBitmap;
+ else
+ iImageBitmap2 = aBitmap;
+ isBitmap = true;
+ break;
+ case CCamera::EFormatExif:
+ if (iLatestImageBufferIndex == 0)
+ iImageData1 = aData;
+ else
+ iImageData2 = aData;
+ isBitmap = false;
+ break;
+
+ default:
+ if (iImageCaptureObserver)
+ iImageCaptureObserver->MceoHandleError(EErrImageReady, KErrNotSupported);
+ return;
+ }
+
+ // Handle captured image
+ HandleImageReady(aError, isBitmap);
+}
+
+void CCameraEngine::HandleImageReady(const TInt aError, const bool isBitmap)
+{
+ iEngineState = EEngineIdle;
+
+ if (aError == KErrNone) {
+ if (isBitmap)
+ if (iImageCaptureObserver) {
+ if (iLatestImageBufferIndex == 0)
+ iImageCaptureObserver->MceoCapturedBitmapReady(iImageBitmap1);
+ else
+ iImageCaptureObserver->MceoCapturedBitmapReady(iImageBitmap2);
+ }
+ else
+ ReleaseImageBuffer();
+ else {
+ if (iImageCaptureObserver) {
+ if (iLatestImageBufferIndex == 0)
+ iImageCaptureObserver->MceoCapturedDataReady(iImageData1);
+ else
+ iImageCaptureObserver->MceoCapturedDataReady(iImageData2);
+ }
+ else
+ ReleaseImageBuffer();
+ }
+ } else {
+ if (iImageCaptureObserver)
+ iImageCaptureObserver->MceoHandleError(EErrImageReady, aError);
+ }
+}
+
+#ifdef ECAM_PREVIEW_API
+void CCameraEngine::HandlePreview()
+{
+ if (!iCameraSnapshot) {
+ if (iObserver)
+ iObserver->MceoHandleError(EErrPreview, KErrGeneral);
+ return;
+ }
+
+ RArray<TInt> previewIndices;
+ CleanupClosePushL(previewIndices);
+
+ MCameraBuffer &newPreview = iCameraSnapshot->SnapshotDataL(previewIndices);
+
+ for (TInt i = 0; i < previewIndices.Count(); ++i)
+ iPreviewObserver->MceoPreviewReady(newPreview.BitmapL(0));
+
+ CleanupStack::PopAndDestroy(); // RArray<TInt> previewIndices
+}
+
+TSize CCameraEngine::SelectPreviewResolution()
+{
+ TSize currentResolution(iCaptureResolution);
+
+ TSize previewResolution(0, 0);
+ if (currentResolution == TSize(4000,2248) ||
+ currentResolution == TSize(3264,1832) ||
+ currentResolution == TSize(2592,1456) ||
+ currentResolution == TSize(1920,1080) ||
+ currentResolution == TSize(1280,720)) {
+ previewResolution = KDefaultSizePreview_Wide;
+ } else if (currentResolution == TSize(352,288) ||
+ currentResolution == TSize(176,144)) {
+ previewResolution = KDefaultSizePreview_CIF;
+ } else if (currentResolution == TSize(720,576)) {
+ previewResolution = KDefaultSizePreview_PAL;
+ } else if (currentResolution == TSize(720,480)) {
+ previewResolution = KDefaultSizePreview_NTSC;
+ } else {
+ previewResolution = KDefaultSizePreview_Normal;
+ }
+
+ return previewResolution;
+}
+#endif // ECAM_PREVIEW_API
+
+//=============================================================================
+// S60 3.1 - AutoFocus support (Other platforms, see S60CameraSettings class)
+//=============================================================================
+
+void CCameraEngine::InitComplete(TInt aError)
+{
+ if (aError) {
+ if (iImageCaptureObserver)
+ iImageCaptureObserver->MceoHandleError(EErrAutoFocusInit, aError);
+ }
+}
+
+void CCameraEngine::OptimisedFocusComplete(TInt aError)
+{
+ iEngineState = EEngineIdle;
+
+ if (aError == KErrNone)
+ if (iImageCaptureObserver)
+ iImageCaptureObserver->MceoFocusComplete();
+ else {
+ if (iImageCaptureObserver)
+ iImageCaptureObserver->MceoHandleError(EErrOptimisedFocusComplete, aError);
+ }
+}
+
+TBool CCameraEngine::IsCameraReady() const
+{
+ // If reserved and powered on, but not focusing or capturing
+ if (iEngineState == EEngineIdle)
+ return ETrue;
+
+ return EFalse;
+}
+
+TBool CCameraEngine::IsDirectViewFinderSupported() const
+{
+ if (iCameraInfo.iOptionsSupported & TCameraInfo::EViewFinderDirectSupported)
+ return true;
+ else
+ return false;
+}
+
+TCameraInfo *CCameraEngine::CameraInfo()
+{
+ return &iCameraInfo;
+}
+
+TBool CCameraEngine::IsAutoFocusSupported() const
+{
+#ifndef Q_CC_NOKIAX86 // Not Emulator
+
+#ifdef S60_CAM_AUTOFOCUS_SUPPORT // S60 3.1
+ return (iAutoFocus) ? ETrue : EFalse;
+#else // !S60_CAM_AUTOFOCUS_SUPPORT
+ return EFalse;
+#endif // S60_CAM_AUTOFOCUS_SUPPORT
+
+#else // Q_CC_NOKIAX86 - Emulator
+ return EFalse;
+#endif // !Q_CC_NOKIAX86
+}
+
+/*
+ * This function is used for focusing in S60 3.1 platform. Platforms from S60
+ * 3.2 onwards should use the focusing provided by the S60CameraSettings class.
+ */
+void CCameraEngine::StartFocusL()
+{
+ if (iEngineState != EEngineIdle)
+ return;
+
+#ifndef Q_CC_NOKIAX86 // Not Emulator
+#ifdef S60_CAM_AUTOFOCUS_SUPPORT // S60 3.1
+ if (iAutoFocus) {
+ if (!iAFRange) {
+ iAFRange = CCamAutoFocus::ERangeNormal;
+ iAutoFocus->SetFocusRangeL(iAFRange);
+ }
+
+ iAutoFocus->AttemptOptimisedFocusL();
+ iEngineState = EEngineFocusing;
+ }
+#endif // S60_CAM_AUTOFOCUS_SUPPORT
+#endif // !Q_CC_NOKIAX86
+}
+
+/*
+ * This function is used for cancelling focusing in S60 3.1 platform. Platforms
+ * from S60 3.2 onwards should use the focusing provided by the
+ * S60CameraSettings class.
+ */
+void CCameraEngine::FocusCancel()
+{
+#ifndef Q_CC_NOKIAX86 // Not Emulator
+#ifdef S60_CAM_AUTOFOCUS_SUPPORT
+ if (iAutoFocus) {
+ iAutoFocus->Cancel();
+ iEngineState = EEngineIdle;
+ }
+#endif // S60_CAM_AUTOFOCUS_SUPPORT
+#endif // !Q_CC_NOKIAX86
+}
+
+void CCameraEngine::SupportedFocusRanges(TInt& aSupportedRanges) const
+{
+ aSupportedRanges = 0;
+
+#ifndef Q_CC_NOKIAX86 // Not Emulator
+#ifdef S60_CAM_AUTOFOCUS_SUPPORT
+ if (iAutoFocus) {
+ // CCamAutoFocus doesn't provide a method for getting supported ranges!
+ // Assume everything is supported (rather optimistic)
+ aSupportedRanges = CCamAutoFocus::ERangeMacro |
+ CCamAutoFocus::ERangePortrait |
+ CCamAutoFocus::ERangeNormal |
+ CCamAutoFocus::ERangeInfinite;
+ }
+#endif // S60_CAM_AUTOFOCUS_SUPPORT
+#endif // !Q_CC_NOKIAX86
+}
+
+void CCameraEngine::SetFocusRange(TInt aFocusRange)
+{
+#if !defined(Q_CC_NOKIAX86) // Not Emulator
+
+#ifdef S60_CAM_AUTOFOCUS_SUPPORT
+ if (iAutoFocus) {
+ TRAPD(focusErr, iAutoFocus->SetFocusRangeL((CCamAutoFocus::TAutoFocusRange)aFocusRange));
+ if (focusErr)
+ iObserver->MceoHandleError(EErrAutoFocusRange, focusErr);
+ }
+#endif // S60_CAM_AUTOFOCUS_SUPPORT
+
+#else // Q_CC_NOKIAX86 // Emulator
+ Q_UNUSED(aFocusRange);
+ if (iImageCaptureObserver)
+ iImageCaptureObserver->MceoHandleError(EErrAutoFocusRange, KErrNotSupported);
+#endif // !Q_CC_NOKIAX86
+}
+
+// End of file
diff --git a/src/plugins/symbian/ecam/s60cameraengine.h b/src/plugins/symbian/ecam/s60cameraengine.h
new file mode 100644
index 000000000..7a925c0ba
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameraengine.h
@@ -0,0 +1,407 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ ** All rights reserved.
+ ** Contact: Nokia Corporation (qt-info@nokia.com)
+ **
+ ** This file is part of the Qt Mobility Components.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** No Commercial Usage
+ ** This file contains pre-release code and may not be distributed.
+ ** You may use this file in accordance with the terms and conditions
+ ** contained in the Technology Preview License Agreement accompanying
+ ** this package.
+ **
+ ** GNU Lesser General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU Lesser
+ ** General Public License version 2.1 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.LGPL included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU Lesser General Public License version 2.1 requirements
+ ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** If you have questions regarding the use of this file, please contact
+ ** Nokia at qt-info@nokia.com.
+ **
+ **
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+#ifndef S60CCAMERAENGINE_H
+#define S60CCAMERAENGINE_H
+
+// INCLUDES
+#include <e32base.h>
+#include <ecam.h> // for MCameraObserver(2)
+#ifdef S60_CAM_AUTOFOCUS_SUPPORT
+#include <ccamautofocus.h> // for CCamAutoFocus, MCamAutoFocusObserver
+#endif
+
+// FORWARD DECLARATIONS
+class MCameraEngineObserver;
+class MCameraEngineImageCaptureObserver;
+class MAdvancedSettingsObserver;
+class MCameraViewfinderObserver;
+class MCameraPreviewObserver;
+
+/*
+ * CameraEngine handling ECam operations needed.
+ */
+NONSHARABLE_CLASS( CCameraEngine ) : public CBase,
+ public MCameraObserver,
+ public MCameraObserver2
+#ifdef S60_CAM_AUTOFOCUS_SUPPORT
+ ,public MCamAutoFocusObserver
+#endif
+
+{
+public: // Enums
+
+ enum TCameraEngineState
+ {
+ EEngineNotReady = 0, // 0 - No resources reserved
+ EEngineInitializing, // 1 - Reserving and Powering On
+ EEngineIdle, // 2 - Reseved and Powered On
+ EEngineCapturing, // 3 - Capturing Still Image
+ EEngineFocusing // 4 - Focusing
+ };
+
+public: // Constructor & Destructor
+
+ static CCameraEngine* NewL( TInt aCameraHandle,
+ TInt aPriority,
+ MCameraEngineObserver* aObserver );
+ ~CCameraEngine();
+
+public:
+
+ /**
+ * External Advanced Settings callback observer.
+ */
+ void SetAdvancedObserver(MAdvancedSettingsObserver *aAdvancedSettingsObserver);
+
+ /**
+ * External Image Capture callback observer.
+ */
+ void SetImageCaptureObserver(MCameraEngineImageCaptureObserver *aImageCaptureObserver);
+
+ /**
+ * External Viewfinder callback observer.
+ */
+ void SetViewfinderObserver(MCameraViewfinderObserver *aViewfinderObserver);
+
+ /**
+ * Static function that returns the number of cameras on the device.
+ */
+ static TInt CamerasAvailable();
+
+ /**
+ * Returns the index of the currently active camera device
+ */
+ TInt CurrentCameraIndex() const { return iCameraIndex; }
+
+ /**
+ * Returns the current state (TCameraEngineState)
+ * of the camera engine.
+ */
+ TCameraEngineState State() const { return iEngineState; }
+
+ /**
+ * Returns true if the camera has been reserved and
+ * powered on, and not recording or capturing image
+ */
+ TBool IsCameraReady() const;
+
+ /**
+ * Returns whether DirectScreen ViewFinder is supported by the platform
+ */
+ TBool IsDirectViewFinderSupported() const;
+
+ /**
+ * Returns true if the camera supports AutoFocus.
+ */
+ TBool IsAutoFocusSupported() const;
+
+ /**
+ * Returns camera info
+ */
+ TCameraInfo *CameraInfo();
+
+ /**
+ * Captures an image. When complete, observer will receive
+ * MceoCapturedDataReady() or MceoCapturedBitmapReady() callback,
+ * depending on which image format was used in PrepareL().
+ * @leave May leave with KErrNotReady if camera is not
+ * reserved or prepared for capture.
+ */
+ void CaptureL();
+
+ /**
+ * Cancels ongoing image capture
+ */
+ void CancelCapture();
+
+ /**
+ * Reserves and powers on the camera. When complete,
+ * observer will receive MceoCameraReady() callback
+ *
+ */
+ void ReserveAndPowerOn();
+
+ /**
+ * Releases and powers off the camera
+ *
+ */
+ void ReleaseAndPowerOff();
+
+ /**
+ * Prepares for image capture.
+ * @param aCaptureSize requested capture size. On return,
+ * contains the selected size (closest match)
+ * @param aFormat Image format to use. Default is JPEG with
+ * EXIF information as provided by the camera module
+ * @leave KErrNotSupported, KErrNoMemory, KErrNotReady
+ */
+ void PrepareL( TSize& aCaptureSize,
+ CCamera::TFormat aFormat = CCamera::EFormatExif );
+
+ /**
+ * Starts the viewfinder. Observer will receive
+ * MceoViewFinderFrameReady() callbacks periodically.
+ * @param aSize requested viewfinder size. On return,
+ * contains the selected size.
+ *
+ * @leave KErrNotSupported is viewfinding with bitmaps is not
+ * supported, KErrNotReady
+ */
+ void StartViewFinderL( TSize& aSize );
+
+ /**
+ * Stops the viewfinder if active.
+ */
+ void StopViewFinder();
+
+ void StartDirectViewFinderL(RWsSession& aSession,
+ CWsScreenDevice& aScreenDevice,
+ RWindowBase& aWindow,
+ TRect& aScreenRect,
+ TRect& aClipRect);
+
+ /**
+ * Releases memory for the last received viewfinder frame.
+ * Client must call this in response to MceoViewFinderFrameReady()
+ * callback, after drawing the viewfinder frame is complete.
+ */
+ void ReleaseViewFinderBuffer();
+
+ /**
+ * Releases memory for the last captured image.
+ * Client must call this in response to MceoCapturedDataReady()
+ * or MceoCapturedBitmapReady()callback, after processing the
+ * data/bitmap is complete.
+ */
+ void ReleaseImageBuffer();
+
+ /**
+ * Starts focusing. Does nothing if AutoFocus is not supported.
+ * When complete, observer will receive MceoFocusComplete()
+ * callback.
+ * @leave KErrInUse, KErrNotReady
+ */
+ void StartFocusL();
+
+ /**
+ * Cancels the ongoing focusing operation.
+ */
+ void FocusCancel();
+
+ /**
+ * Gets a bitfield of supported focus ranges.
+ * @param aSupportedRanges a bitfield of either TAutoFocusRange
+ * (S60 3.0/3.1 devices) or TFocusRange (S60 3.2 and onwards) values
+ */
+ void SupportedFocusRanges( TInt& aSupportedRanges ) const;
+
+ /**
+ * Sets the focus range
+ * @param aFocusRange one of the values returned by
+ * SupportedFocusRanges().
+ */
+ void SetFocusRange( TInt aFocusRange );
+
+ /**
+ * Returns a pointer to CCamera object used by the engine.
+ * Allows getting access to additional functionality
+ * from CCamera - do not use for functionality already provided
+ * by CCameraEngine methods.
+ */
+ CCamera* Camera() { return iCamera; }
+
+#ifdef ECAM_PREVIEW_API
+ /**
+ * This enables the preview creation during the capture (image or video).
+ */
+ void EnablePreviewProvider(MCameraPreviewObserver *aPreviewObserver);
+
+ /**
+ * This disabled the preview creation during the capture (image or video)
+ */
+ void DisablePreviewProvider();
+#endif // ECAM_PREVIEW_API
+
+protected: // Protected constructors
+
+ CCameraEngine();
+ CCameraEngine( TInt aCameraHandle,
+ TInt aPriority,
+ MCameraEngineObserver* aObserver );
+ void ConstructL();
+
+protected: // MCameraObserver
+
+ /**
+ * From MCameraObserver
+ * Gets called when CCamera::Reserve() is completed.
+ * (V2: Called internally from HandleEvent)
+ */
+ virtual void ReserveComplete(TInt aError);
+
+ /**
+ * From MCameraObserver.
+ * Gets called when CCamera::PowerOn() is completed.
+ * (V2: Called internally from HandleEvent)
+ */
+ virtual void PowerOnComplete(TInt aError);
+
+ /**
+ * From MCameraObserver.
+ * Gets called when CCamera::StartViewFinderBitmapsL() is completed.
+ * (V2: Called internally from ViewFinderReady)
+ */
+ virtual void ViewFinderFrameReady( CFbsBitmap& aFrame );
+
+ /**
+ * From MCameraObserver.
+ * Gets called when CCamera::CaptureImage() is completed.
+ */
+ virtual void ImageReady( CFbsBitmap* aBitmap, HBufC8* aData, TInt aError );
+
+ /**
+ * From MCameraObserver.
+ * Video capture not implemented.
+ */
+ virtual void FrameBufferReady( MFrameBuffer* /*aFrameBuffer*/, TInt /*aError*/ ) {}
+
+protected: // MCameraObserver2
+
+ /**
+ * From MCameraObserver2
+ * Camera event handler
+ */
+ virtual void HandleEvent(const TECAMEvent &aEvent);
+
+ /**
+ * From MCameraObserver2
+ * Notifies the client of new viewfinder data
+ */
+ virtual void ViewFinderReady(MCameraBuffer &aCameraBuffer, TInt aError);
+
+ /**
+ * From MCameraObserver2
+ * Notifies the client of a new captured image
+ */
+ virtual void ImageBufferReady(MCameraBuffer &aCameraBuffer, TInt aError);
+
+ /**
+ * From MCameraObserver2
+ * Video capture not implemented.
+ */
+ virtual void VideoBufferReady(MCameraBuffer& /*aCameraBuffer*/, TInt /*aError*/) {}
+
+protected: // MCamAutoFocusObserver
+
+ /**
+ * From MCamAutoFocusObserver.
+ * Delivers notification of completion of auto focus initialisation to
+ * an interested party.
+ * @param aError Reason for completion of focus request.
+ */
+ virtual void InitComplete( TInt aError );
+
+ /**
+ * From MCamAutoFocusObserver.
+ * Gets called when CCamAutoFocus::AttemptOptimisedFocusL() is
+ * completed.
+ * (V2: Called internally from HandleEvent)
+ */
+ virtual void OptimisedFocusComplete( TInt aError );
+
+private: // Internal functions
+
+ /**
+ * Internal function to handle ImageReady callbacks from
+ * both observer (V1 & V2) interfaces
+ */
+ void HandleImageReady(const TInt aError, const bool isBitmap);
+
+#ifdef ECAM_PREVIEW_API
+ /**
+ * Handle preview. Retrieve preview data and notify observer about the
+ * preview availability.
+ */
+ void HandlePreview();
+
+ /**
+ * Calculate proper resolution for the SnapShot (Preview) image.
+ */
+ TSize SelectPreviewResolution();
+#endif // ECAM_PREVIEW_API
+
+private: // Data
+
+ CCamera *iCamera;
+ MCameraEngineObserver *iObserver;
+ MCameraEngineImageCaptureObserver *iImageCaptureObserver;
+ MAdvancedSettingsObserver *iAdvancedSettingsObserver;
+ MCameraViewfinderObserver *iViewfinderObserver;
+ MCameraPreviewObserver *iPreviewObserver;
+ MCameraBuffer *iViewFinderBuffer;
+ /*
+ * Following pointers are for the image buffers:
+ * * Makes buffering of 2 concurrent image buffers possible
+ */
+ MCameraBuffer *iImageBuffer1;
+ MCameraBuffer *iImageBuffer2;
+ TDesC8 *iImageData1;
+ TDesC8 *iImageData2;
+ CFbsBitmap *iImageBitmap1;
+ CFbsBitmap *iImageBitmap2;
+ TInt iCameraIndex;
+ TInt iPriority;
+ TCameraEngineState iEngineState;
+ TCameraInfo iCameraInfo;
+ CCamera::TFormat iImageCaptureFormat;
+ TSize iCaptureResolution;
+ bool iNew2LImplementation;
+ int iLatestImageBufferIndex; // 0 = Buffer1, 1 = Buffer2
+#ifdef ECAM_PREVIEW_API
+ CCamera::CCameraSnapshot *iCameraSnapshot;
+#endif // ECAM_PREVIEW_API
+#ifdef S60_CAM_AUTOFOCUS_SUPPORT
+ CCamAutoFocus* iAutoFocus;
+ CCamAutoFocus::TAutoFocusRange iAFRange;
+#endif // S60_CAM_AUTOFOCUS_SUPPORT
+};
+
+#endif // S60CCAMERAENGINE_H
diff --git a/src/plugins/symbian/ecam/s60cameraengineobserver.h b/src/plugins/symbian/ecam/s60cameraengineobserver.h
new file mode 100644
index 000000000..b1e669d70
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameraengineobserver.h
@@ -0,0 +1,178 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ ** All rights reserved.
+ ** Contact: Nokia Corporation (qt-info@nokia.com)
+ **
+ ** This file is part of the Qt Mobility Components.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** No Commercial Usage
+ ** This file contains pre-release code and may not be distributed.
+ ** You may use this file in accordance with the terms and conditions
+ ** contained in the Technology Preview License Agreement accompanying
+ ** this package.
+ **
+ ** GNU Lesser General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU Lesser
+ ** General Public License version 2.1 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.LGPL included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU Lesser General Public License version 2.1 requirements
+ ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** If you have questions regarding the use of this file, please contact
+ ** Nokia at qt-info@nokia.com.
+ **
+ **
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+#ifndef S60CCAMERAENGINEOBSERVER_H
+#define S60CCAMERAENGINEOBSERVER_H
+
+// FORWARD DECLARATIONS
+class CFbsBitmap;
+class TECAMEvent;
+
+enum TCameraEngineError
+{
+ EErrReserve,
+ EErrPowerOn,
+ EErrViewFinderReady,
+ EErrImageReady,
+ EErrPreview,
+ EErrAutoFocusInit,
+ EErrAutoFocusMode,
+ EErrAutoFocusArea,
+ EErrAutoFocusRange,
+ EErrAutoFocusType,
+ EErrOptimisedFocusComplete,
+};
+
+/*
+ * CameraEngine Observer class towards Camera AdvancedSettings
+ */
+class MAdvancedSettingsObserver
+{
+public:
+
+ virtual void HandleAdvancedEvent( const TECAMEvent &aEvent ) = 0;
+
+};
+
+//=============================================================================
+
+/*
+ * CameraEngine Observer class towards Camera Control
+ */
+class MCameraEngineObserver
+{
+public:
+
+ /**
+ * Camera is ready to use for capturing images.
+ */
+ virtual void MceoCameraReady() = 0;
+
+ /**
+ * Notifies clients about errors in camera engine
+ * @param aErrorType type of error (see TCameraEngineError)
+ * @param aError Symbian system-wide error code
+ */
+ virtual void MceoHandleError( TCameraEngineError aErrorType, TInt aError ) = 0;
+
+};
+
+//=============================================================================
+
+/*
+ * CameraEngine Observer class towards Camera ImageCaptureSession
+ */
+class MCameraEngineImageCaptureObserver
+{
+public:
+
+ /**
+ * Camera AF lens has attained optimal focus
+ */
+ virtual void MceoFocusComplete() = 0;
+
+ /**
+ * Captured data is ready - call CCameraEngine::ReleaseImageBuffer()
+ * after processing/saving the data (typically, JPG-encoded image)
+ * @param aData Pointer to a descriptor containing a frame of camera data.
+ */
+ virtual void MceoCapturedDataReady( TDesC8* aData ) = 0;
+
+ /**
+ * Captured bitmap is ready.
+ * after processing/saving the image, call
+ * CCameraEngine::ReleaseImageBuffer() to free the bitmap.
+ * @param aBitmap Pointer to an FBS bitmap containing a captured image.
+ */
+ virtual void MceoCapturedBitmapReady( CFbsBitmap* aBitmap ) = 0;
+
+ /**
+ * Notifies clients about errors in camera engine
+ * @param aErrorType type of error (see TCameraEngineError)
+ * @param aError Symbian system-wide error code
+ */
+ virtual void MceoHandleError( TCameraEngineError aErrorType, TInt aError ) = 0;
+
+ /**
+ * Notifies client about other events not recognized by camera engine.
+ * The default implementation is empty.
+ * @param aEvent camera event (see MCameraObserver2::HandleEvent())
+ */
+ virtual void MceoHandleOtherEvent( const TECAMEvent& /*aEvent*/ ) {}
+};
+
+//=============================================================================
+
+/*
+ * CameraEngine Observer class towards Camera ViewFinderEngine
+ */
+class MCameraViewfinderObserver
+{
+public:
+ /**
+ * A new viewfinder frame is ready.
+ * after displaying the frame, call
+ * CCameraEngine::ReleaseViewFinderBuffer()
+ * to free the bitmap.
+ * @param aFrame Pointer to an FBS bitmap containing a viewfinder frame.
+ */
+ virtual void MceoViewFinderFrameReady( CFbsBitmap& aFrame ) = 0;
+};
+
+//=============================================================================
+
+#ifdef ECAM_PREVIEW_API
+/*
+ * CameraEngine Observer class towards Camera ViewFinderEngine
+ */
+class MCameraPreviewObserver
+{
+public:
+ /**
+ * A new preview is available.
+ * @param aPreview Pointer to an FBS bitmap containing a preview.
+ */
+ virtual void MceoPreviewReady( CFbsBitmap& aPreview ) = 0;
+};
+#endif // ECAM_PREVIEW_API
+
+#endif // CCAMERAENGINEOBSERVER_H
+
+// End of file
diff --git a/src/plugins/symbian/ecam/s60cameraexposurecontrol.cpp b/src/plugins/symbian/ecam/s60cameraexposurecontrol.cpp
new file mode 100644
index 000000000..9ebdd2c6e
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameraexposurecontrol.cpp
@@ -0,0 +1,584 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qstring.h>
+
+#include "s60cameraexposurecontrol.h"
+#include "s60cameraservice.h"
+#include "s60imagecapturesession.h"
+
+S60CameraExposureControl::S60CameraExposureControl(QObject *parent) :
+ QCameraExposureControl(parent)
+{
+}
+
+S60CameraExposureControl::S60CameraExposureControl(S60ImageCaptureSession *session, QObject *parent) :
+ QCameraExposureControl(parent),
+ m_session(0),
+ m_service(0),
+ m_advancedSettings(0),
+ m_exposureMode(QCameraExposure::ExposureAuto),
+ m_meteringMode(QCameraExposure::MeteringMatrix)
+{
+ m_session = session;
+
+ connect(m_session, SIGNAL(advancedSettingChanged()), this, SLOT(resetAdvancedSetting()));
+ m_advancedSettings = m_session->advancedSettings();
+
+ if (m_advancedSettings) {
+ connect(m_advancedSettings, SIGNAL(apertureChanged()), this, SLOT(apertureChanged()));
+ connect(m_advancedSettings, SIGNAL(apertureRangeChanged()), this, SLOT(apertureRangeChanged()));
+ connect(m_advancedSettings, SIGNAL(shutterSpeedChanged()), this, SLOT(shutterSpeedChanged()));
+ connect(m_advancedSettings, SIGNAL(isoSensitivityChanged()), this, SLOT(isoSensitivityChanged()));
+ connect(m_advancedSettings, SIGNAL(evChanged()), this, SLOT(evChanged()));
+ }
+}
+
+S60CameraExposureControl::~S60CameraExposureControl()
+{
+ m_advancedSettings = 0;
+}
+
+void S60CameraExposureControl::resetAdvancedSetting()
+{
+ m_advancedSettings = m_session->advancedSettings();
+ if (m_advancedSettings) {
+ connect(m_advancedSettings, SIGNAL(apertureChanged()), this, SLOT(apertureChanged()));
+ connect(m_advancedSettings, SIGNAL(apertureRangeChanged()), this, SLOT(apertureRangeChanged()));
+ connect(m_advancedSettings, SIGNAL(shutterSpeedChanged()), this, SLOT(shutterSpeedChanged()));
+ connect(m_advancedSettings, SIGNAL(isoSensitivityChanged()), this, SLOT(isoSensitivityChanged()));
+ connect(m_advancedSettings, SIGNAL(evChanged()), this, SLOT(evChanged()));
+ }
+}
+
+void S60CameraExposureControl::apertureChanged()
+{
+ emit exposureParameterChanged(QCameraExposureControl::Aperture);
+}
+
+void S60CameraExposureControl::apertureRangeChanged()
+{
+ emit exposureParameterRangeChanged(QCameraExposureControl::Aperture);
+}
+
+void S60CameraExposureControl::shutterSpeedChanged()
+{
+ emit exposureParameterChanged(QCameraExposureControl::ShutterSpeed);
+}
+
+void S60CameraExposureControl::isoSensitivityChanged()
+{
+ emit exposureParameterChanged(QCameraExposureControl::ISO);
+}
+
+void S60CameraExposureControl::evChanged()
+{
+ emit exposureParameterChanged(QCameraExposureControl::ExposureCompensation);
+}
+
+QCameraExposure::ExposureMode S60CameraExposureControl::exposureMode() const
+{
+ return m_session->exposureMode();
+}
+
+void S60CameraExposureControl::setExposureMode(QCameraExposure::ExposureMode mode)
+{
+ if (isExposureModeSupported(mode)) {
+ m_exposureMode = mode;
+ m_session->setExposureMode(m_exposureMode);
+ return;
+ }
+
+ m_session->setError(KErrNotSupported, tr("Requested exposure mode is not supported."));
+}
+
+bool S60CameraExposureControl::isExposureModeSupported(QCameraExposure::ExposureMode mode) const
+{
+ if (m_session->isExposureModeSupported(mode))
+ return true;
+
+ return false;
+}
+
+QCameraExposure::MeteringMode S60CameraExposureControl::meteringMode() const
+{
+ if (m_advancedSettings)
+ return m_advancedSettings->meteringMode();
+
+ return QCameraExposure::MeteringMode();
+}
+
+void S60CameraExposureControl::setMeteringMode(QCameraExposure::MeteringMode mode)
+{
+ if (m_advancedSettings) {
+ if (isMeteringModeSupported(mode)) {
+ m_meteringMode = mode;
+ m_advancedSettings->setMeteringMode(mode);
+ return;
+ }
+ }
+
+ m_session->setError(KErrNotSupported, tr("Requested metering mode is not supported."));
+}
+
+bool S60CameraExposureControl::isMeteringModeSupported(QCameraExposure::MeteringMode mode) const
+{
+ if (m_advancedSettings)
+ return m_advancedSettings->isMeteringModeSupported(mode);
+
+ return false;
+}
+
+bool S60CameraExposureControl::isParameterSupported(ExposureParameter parameter) const
+{
+ // Settings supported only if advanced settings available
+ if (m_advancedSettings) {
+ switch (parameter) {
+ case QCameraExposureControl::ISO:
+ if (m_advancedSettings->supportedIsoSensitivities().count() > 0)
+ return true;
+ else
+ return false;
+ case QCameraExposureControl::Aperture:
+ if (m_advancedSettings->supportedApertures().count() > 0)
+ return true;
+ else
+ return false;
+ case QCameraExposureControl::ShutterSpeed:
+ if (m_advancedSettings->supportedShutterSpeeds().count() > 0)
+ return true;
+ else
+ return false;
+ case QCameraExposureControl::ExposureCompensation:
+ if (m_advancedSettings->supportedExposureCompensationValues().count() > 0)
+ return true;
+ else
+ return false;
+ case QCameraExposureControl::FlashPower:
+ case QCameraExposureControl::FlashCompensation:
+ return false;
+
+ default:
+ return false;
+ }
+ }
+
+ return false;
+}
+
+QVariant S60CameraExposureControl::exposureParameter(ExposureParameter parameter) const
+{
+ switch (parameter) {
+ case QCameraExposureControl::ISO:
+ return QVariant(isoSensitivity());
+ case QCameraExposureControl::Aperture:
+ return QVariant(aperture());
+ case QCameraExposureControl::ShutterSpeed:
+ return QVariant(shutterSpeed());
+ case QCameraExposureControl::ExposureCompensation:
+ return QVariant(exposureCompensation());
+ case QCameraExposureControl::FlashPower:
+ case QCameraExposureControl::FlashCompensation:
+ // Not supported in Symbian
+ return QVariant();
+
+ default:
+ // Not supported in Symbian
+ return QVariant();
+ }
+}
+
+QCameraExposureControl::ParameterFlags S60CameraExposureControl::exposureParameterFlags(ExposureParameter parameter) const
+{
+ QCameraExposureControl::ParameterFlags flags;
+
+ /*
+ * ISO, ExposureCompensation:
+ * - Automatic/Manual
+ * - Read/Write
+ * - Discrete range
+ *
+ * Aperture, ShutterSpeed, FlashPower, FlashCompensation:
+ * - Not supported
+ */
+ switch (parameter) {
+ case QCameraExposureControl::ISO:
+ case QCameraExposureControl::ExposureCompensation:
+ flags |= QCameraExposureControl::AutomaticValue;
+ break;
+ case QCameraExposureControl::Aperture:
+ case QCameraExposureControl::ShutterSpeed:
+ case QCameraExposureControl::FlashPower:
+ case QCameraExposureControl::FlashCompensation:
+ // Do nothing - no flags
+ break;
+
+ default:
+ // Do nothing - no flags
+ break;
+ }
+
+ return flags;
+}
+
+QVariantList S60CameraExposureControl::supportedParameterRange(ExposureParameter parameter) const
+{
+ QVariantList valueList;
+
+ if (m_advancedSettings) {
+ switch (parameter) {
+ case QCameraExposureControl::ISO: {
+ foreach (int iso, m_advancedSettings->supportedIsoSensitivities())
+ valueList << QVariant(iso);
+ break;
+ }
+ case QCameraExposureControl::Aperture: {
+ foreach (qreal aperture, m_advancedSettings->supportedApertures())
+ valueList << QVariant(aperture);
+ break;
+ }
+ case QCameraExposureControl::ShutterSpeed: {
+ foreach (qreal shutterSpeed, m_advancedSettings->supportedShutterSpeeds())
+ valueList << QVariant(shutterSpeed);
+ break;
+ }
+ case QCameraExposureControl::ExposureCompensation: {
+ foreach (qreal ev, m_advancedSettings->supportedExposureCompensationValues())
+ valueList << QVariant(ev);
+ break;
+ }
+ case QCameraExposureControl::FlashPower:
+ case QCameraExposureControl::FlashCompensation:
+ // Not supported in Symbian
+ break;
+
+ default:
+ // Not supported in Symbian
+ break;
+ }
+ }
+
+ return valueList;
+}
+
+bool S60CameraExposureControl::setExposureParameter(ExposureParameter parameter, const QVariant& value)
+{
+ bool useDefaultValue = false;
+
+ if (value.isNull())
+ useDefaultValue = true;
+
+ switch (parameter) {
+ case QCameraExposureControl::ISO:
+ if (useDefaultValue) {
+ setAutoIsoSensitivity();
+ return false;
+ }
+ else
+ return setManualIsoSensitivity(value.toInt());
+
+ case QCameraExposureControl::Aperture:
+ if (useDefaultValue) {
+ setAutoAperture();
+ return false;
+ }
+ else
+ return setManualAperture(value.toFloat());
+
+ case QCameraExposureControl::ShutterSpeed:
+ if (useDefaultValue) {
+ setAutoShutterSpeed();
+ return false;
+ }
+ else
+ return setManualShutterSpeed(value.toFloat());
+
+ case QCameraExposureControl::ExposureCompensation:
+ if (useDefaultValue) {
+ setAutoExposureCompensation();
+ return false;
+ }
+ else
+ return setManualExposureCompensation(value.toFloat());
+
+ case QCameraExposureControl::FlashPower:
+ return false;
+ case QCameraExposureControl::FlashCompensation:
+ return false;
+
+ default:
+ // Not supported in Symbian
+ return false;
+ }
+}
+
+QString S60CameraExposureControl::extendedParameterName(ExposureParameter parameter)
+{
+ switch (parameter) {
+ case QCameraExposureControl::ISO:
+ return QLatin1String("ISO Sensitivity");
+ case QCameraExposureControl::Aperture:
+ return QLatin1String("Aperture");
+ case QCameraExposureControl::ShutterSpeed:
+ return QLatin1String("Shutter Speed");
+ case QCameraExposureControl::ExposureCompensation:
+ return QLatin1String("Exposure Compensation");
+ case QCameraExposureControl::FlashPower:
+ return QLatin1String("Flash Power");
+ case QCameraExposureControl::FlashCompensation:
+ return QLatin1String("Flash Compensation");
+
+ default:
+ return QString();
+ }
+}
+
+int S60CameraExposureControl::isoSensitivity() const
+{
+ if (m_advancedSettings)
+ return m_advancedSettings->isoSensitivity();
+ return 0;
+}
+
+bool S60CameraExposureControl::isIsoSensitivitySupported(const int iso) const
+{
+ if (m_advancedSettings &&
+ m_advancedSettings->supportedIsoSensitivities().contains(iso))
+ return true;
+ else
+ return false;
+}
+
+bool S60CameraExposureControl::setManualIsoSensitivity(int iso)
+{
+ if (m_advancedSettings) {
+ if (isIsoSensitivitySupported(iso)) {
+ m_advancedSettings->setManualIsoSensitivity(iso);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void S60CameraExposureControl::setAutoIsoSensitivity()
+{
+ if (m_advancedSettings)
+ m_advancedSettings->setAutoIsoSensitivity();
+}
+
+qreal S60CameraExposureControl::aperture() const
+{
+ if (m_advancedSettings)
+ return m_advancedSettings->aperture();
+ return 0.0;
+}
+
+bool S60CameraExposureControl::isApertureSupported(const qreal aperture) const
+{
+ if (m_advancedSettings) {
+ QList<qreal> supportedValues = m_advancedSettings->supportedApertures();
+ if(supportedValues.indexOf(aperture) != -1)
+ return true;
+ }
+
+ return false;
+}
+
+bool S60CameraExposureControl::setManualAperture(qreal aperture)
+{
+ if (m_advancedSettings) {
+ if (isApertureSupported(aperture)) {
+ m_advancedSettings->setManualAperture(aperture);
+ return true;
+ } else {
+ QList<qreal> supportedApertureValues = m_advancedSettings->supportedApertures();
+ int minAperture = supportedApertureValues.first();
+ int maxAperture = supportedApertureValues.last();
+
+ if (aperture < minAperture) { // Smaller than minimum
+ aperture = minAperture;
+ } else if (aperture > maxAperture) { // Bigger than maximum
+ aperture = maxAperture;
+ } else { // Find closest
+ int indexOfClosest = 0;
+ int smallestDiff = 100000000; // Sensible max diff
+ for(int i = 0; i < supportedApertureValues.count(); ++i) {
+ if((abs((aperture*100) - (supportedApertureValues[i]*100))) < smallestDiff) {
+ smallestDiff = abs((aperture*100) - (supportedApertureValues[i]*100));
+ indexOfClosest = i;
+ }
+ }
+ aperture = supportedApertureValues[indexOfClosest];
+ }
+ m_advancedSettings->setManualAperture(aperture);
+ }
+ }
+
+ return false;
+}
+
+void S60CameraExposureControl::setAutoAperture()
+{
+ // Not supported in Symbian
+}
+
+qreal S60CameraExposureControl::shutterSpeed() const
+{
+ if (m_advancedSettings)
+ return m_advancedSettings->shutterSpeed();
+ return 0.0;
+}
+
+bool S60CameraExposureControl::isShutterSpeedSupported(const qreal seconds) const
+{
+ if (m_advancedSettings) {
+ QList<qreal> supportedValues = m_advancedSettings->supportedShutterSpeeds();
+ if(supportedValues.indexOf(seconds) != -1)
+ return true;
+ }
+
+ return false;
+}
+
+bool S60CameraExposureControl::setManualShutterSpeed(qreal seconds)
+{
+ if (m_advancedSettings) {
+ if (isShutterSpeedSupported(seconds)) {
+ m_advancedSettings->setManualShutterSpeed(seconds);
+ return true;
+ } else {
+ QList<qreal> supportedShutterSpeeds = m_advancedSettings->supportedShutterSpeeds();
+
+ if (supportedShutterSpeeds.count() == 0)
+ return false;
+
+ int minShutterSpeed = supportedShutterSpeeds.first();
+ int maxShutterSpeed = supportedShutterSpeeds.last();
+
+ if (seconds < minShutterSpeed) { // Smaller than minimum
+ seconds = minShutterSpeed;
+ } else if (seconds > maxShutterSpeed) { // Bigger than maximum
+ seconds = maxShutterSpeed;
+ } else { // Find closest
+ int indexOfClosest = 0;
+ int smallestDiff = 100000000; // Sensible max diff
+ for(int i = 0; i < supportedShutterSpeeds.count(); ++i) {
+ if((abs((seconds*100) - (supportedShutterSpeeds[i]*100))) < smallestDiff) {
+ smallestDiff = abs((seconds*100) - (supportedShutterSpeeds[i]*100));
+ indexOfClosest = i;
+ }
+ }
+ seconds = supportedShutterSpeeds[indexOfClosest];
+ }
+ m_advancedSettings->setManualShutterSpeed(seconds);
+ }
+ }
+
+ return false;
+}
+
+void S60CameraExposureControl::setAutoShutterSpeed()
+{
+ // Not supported in Symbian
+}
+
+qreal S60CameraExposureControl::exposureCompensation() const
+{
+ if (m_advancedSettings)
+ return m_advancedSettings->exposureCompensation();
+ return 0.0;
+}
+
+bool S60CameraExposureControl::isExposureCompensationSupported(const qreal ev) const
+{
+ if (m_advancedSettings) {
+ QList<qreal> supportedValues = m_advancedSettings->supportedExposureCompensationValues();
+ if(supportedValues.indexOf(ev) != -1)
+ return true;
+ }
+
+ return false;
+}
+
+bool S60CameraExposureControl::setManualExposureCompensation(qreal ev)
+{
+ if (m_advancedSettings) {
+ if (isExposureCompensationSupported(ev)) {
+ m_advancedSettings->setExposureCompensation(ev);
+ return true;
+ } else {
+ QList<qreal> supportedEVs = m_advancedSettings->supportedExposureCompensationValues();
+
+ if (supportedEVs.count() == 0)
+ return false;
+
+ int minEV = supportedEVs.first();
+ int maxEV = supportedEVs.last();
+
+ if (ev < minEV) { // Smaller than minimum
+ ev = minEV;
+ } else if (ev > maxEV) { // Bigger than maximum
+ ev = maxEV;
+ } else { // Find closest
+ int indexOfClosest = 0;
+ int smallestDiff = 100000000; // Sensible max diff
+ for(int i = 0; i < supportedEVs.count(); ++i) {
+ if((abs((ev*100) - (supportedEVs[i]*100))) < smallestDiff) {
+ smallestDiff = abs((ev*100) - (supportedEVs[i]*100));
+ indexOfClosest = i;
+ }
+ }
+ ev = supportedEVs[indexOfClosest];
+ }
+ m_advancedSettings->setExposureCompensation(ev);
+ }
+ }
+
+ return false;
+}
+
+void S60CameraExposureControl::setAutoExposureCompensation()
+{
+ // Not supported in Symbian
+}
+
+// End of file
diff --git a/src/plugins/symbian/ecam/s60cameraexposurecontrol.h b/src/plugins/symbian/ecam/s60cameraexposurecontrol.h
new file mode 100644
index 000000000..1c623c774
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameraexposurecontrol.h
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef S60CAMERAEXPOSURECONTROL_H
+#define S60CAMERAEXPOSURECONTROL_H
+
+#include <qcameraexposurecontrol.h>
+
+#include "s60camerasettings.h"
+
+QT_USE_NAMESPACE
+
+class S60CameraService;
+class S60ImageCaptureSession;
+
+/*
+ * Control for exposure related camera operation.
+ */
+class S60CameraExposureControl : public QCameraExposureControl
+{
+ Q_OBJECT
+
+public: // Constructors & Destructor
+
+ S60CameraExposureControl(QObject *parent = 0);
+ S60CameraExposureControl(S60ImageCaptureSession *session, QObject *parent = 0);
+ ~S60CameraExposureControl();
+
+public: // QCameraExposureControl
+
+ // Exposure Mode
+ QCameraExposure::ExposureMode exposureMode() const;
+ void setExposureMode(QCameraExposure::ExposureMode mode);
+ bool isExposureModeSupported(QCameraExposure::ExposureMode mode) const;
+
+ // Metering Mode
+ QCameraExposure::MeteringMode meteringMode() const;
+ void setMeteringMode(QCameraExposure::MeteringMode mode);
+ bool isMeteringModeSupported(QCameraExposure::MeteringMode mode) const;
+
+ // Exposure Parameter
+ bool isParameterSupported(ExposureParameter parameter) const;
+ QVariant exposureParameter(ExposureParameter parameter) const;
+ QCameraExposureControl::ParameterFlags exposureParameterFlags(ExposureParameter parameter) const;
+ QVariantList supportedParameterRange(ExposureParameter parameter) const;
+ bool setExposureParameter(ExposureParameter parameter, const QVariant& value);
+
+ QString extendedParameterName(ExposureParameter parameter);
+
+/*
+Q_SIGNALS: // QCameraExposureControl
+ void exposureParameterChanged(int parameter);
+ void exposureParameterRangeChanged(int parameter);
+*/
+
+private slots: // Internal Slots
+
+ void resetAdvancedSetting();
+ void apertureChanged();
+ void apertureRangeChanged();
+ void shutterSpeedChanged();
+ void isoSensitivityChanged();
+ void evChanged();
+
+private: // Internal - Implementing ExposureParameter
+
+ // ISO Sensitivity
+ int isoSensitivity() const;
+ bool setManualIsoSensitivity(int iso);
+ void setAutoIsoSensitivity();
+ bool isIsoSensitivitySupported(const int iso) const;
+
+ // Aperture
+ qreal aperture() const;
+ bool setManualAperture(qreal aperture);
+ void setAutoAperture();
+ bool isApertureSupported(const qreal aperture) const;
+
+ // Shutter Speed
+ qreal shutterSpeed() const;
+ bool setManualShutterSpeed(qreal seconds);
+ void setAutoShutterSpeed();
+ bool isShutterSpeedSupported(const qreal seconds) const;
+
+ // Exposure Compensation
+ qreal exposureCompensation() const;
+ bool setManualExposureCompensation(qreal ev);
+ void setAutoExposureCompensation();
+ bool isExposureCompensationSupported(const qreal ev) const;
+
+private: // Data
+
+ S60ImageCaptureSession *m_session;
+ S60CameraService *m_service;
+ S60CameraSettings *m_advancedSettings;
+ QCameraExposure::ExposureMode m_exposureMode;
+ QCameraExposure::MeteringMode m_meteringMode;
+};
+
+#endif // S60CAMERAEXPOSURECONTROL_H
diff --git a/src/plugins/symbian/ecam/s60cameraflashcontrol.cpp b/src/plugins/symbian/ecam/s60cameraflashcontrol.cpp
new file mode 100644
index 000000000..a18c57a03
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameraflashcontrol.cpp
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qstring.h>
+
+#include "s60cameraflashcontrol.h"
+#include "s60cameraservice.h"
+#include "s60imagecapturesession.h"
+
+S60CameraFlashControl::S60CameraFlashControl(QObject *parent) :
+ QCameraFlashControl(parent)
+{
+}
+
+S60CameraFlashControl::S60CameraFlashControl(S60ImageCaptureSession *session, QObject *parent) :
+ QCameraFlashControl(parent),
+ m_session(0),
+ m_service(0),
+ m_advancedSettings(0),
+ m_flashMode(QCameraExposure::FlashOff)
+{
+ m_session = session;
+
+ connect(m_session, SIGNAL(advancedSettingChanged()), this, SLOT(resetAdvancedSetting()));
+ m_advancedSettings = m_session->advancedSettings();
+
+ if (m_advancedSettings)
+ connect(m_advancedSettings, SIGNAL(flashReady(bool)), this, SIGNAL(flashReady(bool)));
+}
+
+S60CameraFlashControl::~S60CameraFlashControl()
+{
+ m_advancedSettings = 0;
+}
+
+void S60CameraFlashControl::resetAdvancedSetting()
+{
+ m_advancedSettings = m_session->advancedSettings();
+ if (m_advancedSettings)
+ connect(m_advancedSettings, SIGNAL(flashReady(bool)), this, SIGNAL(flashReady(bool)));
+}
+
+QCameraExposure::FlashModes S60CameraFlashControl::flashMode() const
+{
+ return m_session->flashMode();
+}
+
+void S60CameraFlashControl::setFlashMode(QCameraExposure::FlashModes mode)
+{
+ if (isFlashModeSupported(mode)) {
+ m_flashMode = mode;
+ m_session->setFlashMode(m_flashMode);
+ }
+ else
+ m_session->setError(KErrNotSupported, tr("Requested flash mode is not supported."));
+}
+
+bool S60CameraFlashControl::isFlashModeSupported(QCameraExposure::FlashModes mode) const
+{
+ return m_session->supportedFlashModes() & mode;
+}
+
+bool S60CameraFlashControl::isFlashReady() const
+{
+ if (m_advancedSettings)
+ return m_advancedSettings->isFlashReady();
+
+ return false;
+}
+
+// End of file
diff --git a/src/plugins/symbian/ecam/s60cameraflashcontrol.h b/src/plugins/symbian/ecam/s60cameraflashcontrol.h
new file mode 100644
index 000000000..50dbc41dc
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameraflashcontrol.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef S60CAMERAFLASHCONTROL_H
+#define S60CAMERAFLASHCONTROL_H
+
+#include <qcameraflashcontrol.h>
+
+#include "s60camerasettings.h"
+
+QT_USE_NAMESPACE
+
+class S60CameraService;
+class S60ImageCaptureSession;
+
+/*
+ * Control to setup Flash related camera settings.
+ */
+class S60CameraFlashControl : public QCameraFlashControl
+{
+ Q_OBJECT
+
+public: // Constructors & Destructor
+
+ S60CameraFlashControl(QObject *parent = 0);
+ S60CameraFlashControl(S60ImageCaptureSession *session, QObject *parent = 0);
+ ~S60CameraFlashControl();
+
+public: // QCameraExposureControl
+
+ // Flash Mode
+ QCameraExposure::FlashModes flashMode() const;
+ void setFlashMode(QCameraExposure::FlashModes mode);
+ bool isFlashModeSupported(QCameraExposure::FlashModes mode) const;
+
+ bool isFlashReady() const;
+
+/*
+Q_SIGNALS: // QCameraExposureControl
+ void flashReady(bool);
+*/
+
+private slots: // Internal Slots
+
+ void resetAdvancedSetting();
+
+private: // Data
+
+ S60ImageCaptureSession *m_session;
+ S60CameraService *m_service;
+ S60CameraSettings *m_advancedSettings;
+ QCameraExposure::FlashModes m_flashMode;
+};
+
+#endif // S60CAMERAFLASHCONTROL_H
diff --git a/src/plugins/symbian/ecam/s60camerafocuscontrol.cpp b/src/plugins/symbian/ecam/s60camerafocuscontrol.cpp
new file mode 100644
index 000000000..a7941ce20
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60camerafocuscontrol.cpp
@@ -0,0 +1,193 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qstring.h>
+
+#include "s60camerafocuscontrol.h"
+#include "s60cameraservice.h"
+#include "s60imagecapturesession.h"
+#include "s60cameraconstants.h"
+
+S60CameraFocusControl::S60CameraFocusControl(QObject *parent) :
+ QCameraFocusControl(parent)
+{
+}
+
+S60CameraFocusControl::S60CameraFocusControl(S60ImageCaptureSession *session, QObject *parent) :
+ QCameraFocusControl(parent),
+ m_session(0),
+ m_service(0),
+ m_advancedSettings(0),
+ m_isFocusLocked(false),
+ m_opticalZoomValue(KDefaultOpticalZoom),
+ m_digitalZoomValue(KDefaultDigitalZoom),
+ m_focusMode(KDefaultFocusMode)
+{
+ m_session = session;
+
+ connect(m_session, SIGNAL(advancedSettingChanged()), this, SLOT(resetAdvancedSetting()));
+ m_advancedSettings = m_session->advancedSettings();
+
+ TRAPD(err, m_session->doSetZoomFactorL(m_opticalZoomValue, m_digitalZoomValue));
+ if (err)
+ m_session->setError(KErrNotSupported, tr("Setting default zoom factors failed."));
+}
+
+S60CameraFocusControl::~S60CameraFocusControl()
+{
+}
+
+QCameraFocus::FocusMode S60CameraFocusControl::focusMode() const
+{
+ return m_focusMode;
+}
+
+void S60CameraFocusControl::setFocusMode(QCameraFocus::FocusMode mode)
+{
+ if (isFocusModeSupported(mode)) {
+ // FocusMode and FocusRange are set. Focusing is triggered by setting
+ // the corresponding FocusType active by calling searchAndLock in LocksControl.
+ m_focusMode = mode;
+ if (m_advancedSettings)
+ m_advancedSettings->setFocusMode(m_focusMode);
+ else
+ m_session->setError(KErrGeneral, tr("Unable to set focus mode before camera is started."));
+ } else {
+ m_session->setError(KErrNotSupported, tr("Requested focus mode is not supported."));
+ }
+}
+
+bool S60CameraFocusControl::isFocusModeSupported(QCameraFocus::FocusMode mode) const
+{
+ if (m_advancedSettings) {
+ return m_advancedSettings->supportedFocusModes() & mode;
+ } else {
+ if (mode == QCameraFocus::AutoFocus)
+ return m_session->isFocusSupported();
+ }
+
+ return false;
+}
+
+qreal S60CameraFocusControl::maximumOpticalZoom() const
+{
+ return m_session->maximumZoom();
+}
+
+qreal S60CameraFocusControl::maximumDigitalZoom() const
+{
+ return m_session->maxDigitalZoom();
+}
+
+qreal S60CameraFocusControl::opticalZoom() const
+{
+ return m_session->opticalZoomFactor();
+}
+
+qreal S60CameraFocusControl::digitalZoom() const
+{
+ return m_session->digitalZoomFactor();
+}
+
+void S60CameraFocusControl::zoomTo(qreal optical, qreal digital)
+{
+ TRAPD(err, m_session->doSetZoomFactorL(optical, digital));
+ if (err)
+ m_session->setError(KErrNotSupported, tr("Requested zoom factor is not supported."));
+
+ // Query new values
+ if (m_opticalZoomValue != m_session->opticalZoomFactor()) {
+ m_opticalZoomValue = m_session->opticalZoomFactor();
+ emit opticalZoomChanged(m_opticalZoomValue);
+ }
+ if (m_digitalZoomValue != m_session->digitalZoomFactor()) {
+ m_digitalZoomValue = m_session->digitalZoomFactor();
+ emit digitalZoomChanged(m_digitalZoomValue);
+ }
+}
+
+void S60CameraFocusControl::resetAdvancedSetting()
+{
+ m_advancedSettings = m_session->advancedSettings();
+}
+
+QCameraFocus::FocusPointMode S60CameraFocusControl::focusPointMode() const
+{
+ // Not supported in Symbian
+ return QCameraFocus::FocusPointAuto;
+}
+
+void S60CameraFocusControl::setFocusPointMode(QCameraFocus::FocusPointMode mode)
+{
+ if (mode != QCameraFocus::FocusPointAuto)
+ m_session->setError(KErrNotSupported, tr("Requested focus point mode is not supported."));
+}
+
+bool S60CameraFocusControl::isFocusPointModeSupported(QCameraFocus::FocusPointMode mode) const
+{
+ // Not supported in Symbian
+ if (mode == QCameraFocus::FocusPointAuto)
+ return true;
+ else
+ return false;
+}
+
+QPointF S60CameraFocusControl::customFocusPoint() const
+{
+ // Not supported in Symbian, return image center
+ return QPointF(0.5, 0.5);
+}
+
+void S60CameraFocusControl::setCustomFocusPoint(const QPointF &point)
+{
+ // Not supported in Symbian
+ Q_UNUSED(point);
+ m_session->setError(KErrNotSupported, tr("Setting custom focus point is not supported."));
+}
+
+QCameraFocusZoneList S60CameraFocusControl::focusZones() const
+{
+ // Not supported in Symbian
+ return QCameraFocusZoneList(); // Return empty list
+}
+
+// End of file
+
diff --git a/src/plugins/symbian/ecam/s60camerafocuscontrol.h b/src/plugins/symbian/ecam/s60camerafocuscontrol.h
new file mode 100644
index 000000000..28c83ed70
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60camerafocuscontrol.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef S60CAMERAFOCUSCONTROL_H
+#define S60CAMERAFOCUSCONTROL_H
+
+#include <qcamerafocuscontrol.h>
+
+#include "s60camerasettings.h"
+
+QT_USE_NAMESPACE
+
+class S60CameraService;
+class S60ImageCaptureSession;
+
+/*
+ * Control for focusing related operations (inc. zooming)
+ */
+class S60CameraFocusControl : public QCameraFocusControl
+{
+ Q_OBJECT
+
+public: // Constructors & Destructor
+
+ S60CameraFocusControl(QObject *parent = 0);
+ S60CameraFocusControl(S60ImageCaptureSession *session, QObject *parent = 0);
+ ~S60CameraFocusControl();
+
+public: // QCameraFocusControl
+
+ // Focus Mode
+ QCameraFocus::FocusMode focusMode() const;
+ void setFocusMode(QCameraFocus::FocusMode mode);
+ bool isFocusModeSupported(QCameraFocus::FocusMode) const;
+
+ // Zoom
+ qreal maximumOpticalZoom() const;
+ qreal maximumDigitalZoom() const;
+ qreal opticalZoom() const;
+ qreal digitalZoom() const;
+
+ void zoomTo(qreal optical, qreal digital);
+
+ // Focus Point
+ QCameraFocus::FocusPointMode focusPointMode() const;
+ void setFocusPointMode(QCameraFocus::FocusPointMode mode);
+ bool isFocusPointModeSupported(QCameraFocus::FocusPointMode mode) const;
+ QPointF customFocusPoint() const;
+ void setCustomFocusPoint(const QPointF &point);
+
+ QCameraFocusZoneList focusZones() const;
+
+/*
+Q_SIGNALS: // QCameraFocusControl
+ void opticalZoomChanged(qreal opticalZoom);
+ void digitalZoomChanged(qreal digitalZoom);
+ void focusZonesChanged();
+*/
+
+private slots: // Internal Slots
+
+ void resetAdvancedSetting();
+
+private: // Data
+ S60ImageCaptureSession *m_session;
+ S60CameraService *m_service;
+ S60CameraSettings *m_advancedSettings;
+ bool m_isFocusLocked;
+ qreal m_opticalZoomValue;
+ qreal m_digitalZoomValue;
+ QCameraFocus::FocusMode m_focusMode;
+};
+
+#endif // S60CAMERAFOCUSCONTROL_H
diff --git a/src/plugins/symbian/ecam/s60cameraimagecapturecontrol.cpp b/src/plugins/symbian/ecam/s60cameraimagecapturecontrol.cpp
new file mode 100644
index 000000000..427a3bd97
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameraimagecapturecontrol.cpp
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qstring.h>
+
+#include "s60cameraimagecapturecontrol.h"
+#include "s60cameraservice.h"
+#include "s60imagecapturesession.h"
+#include "s60cameracontrol.h"
+
+S60CameraImageCaptureControl::S60CameraImageCaptureControl(QObject *parent) :
+ QCameraImageCaptureControl(parent)
+{
+}
+
+S60CameraImageCaptureControl::S60CameraImageCaptureControl(S60CameraService *service,
+ S60ImageCaptureSession *session,
+ QObject *parent) :
+ QCameraImageCaptureControl(parent),
+ m_driveMode(QCameraImageCapture::SingleImageCapture) // Default DriveMode
+{
+ m_session = session;
+ m_service = service;
+ m_cameraControl = qobject_cast<S60CameraControl *>(m_service->requestControl(QCameraControl_iid));
+
+ if (!m_cameraControl)
+ m_session->setError(KErrGeneral, tr("Unexpected camera error."));
+
+ // Chain these signals from session class
+ connect(m_session, SIGNAL(imageCaptured(const int, QImage)),
+ this, SIGNAL(imageCaptured(const int, QImage)));
+ connect(m_session, SIGNAL(readyForCaptureChanged(bool)),
+ this, SIGNAL(readyForCaptureChanged(bool)), Qt::QueuedConnection);
+ connect(m_session, SIGNAL(imageSaved(const int, const QString&)),
+ this, SIGNAL(imageSaved(const int, const QString&)));
+ connect(m_session, SIGNAL(imageExposed(int)),
+ this, SIGNAL(imageExposed(int)));
+ connect(m_session, SIGNAL(captureError(int, int, const QString&)),
+ this, SIGNAL(error(int, int, const QString&)));
+}
+
+S60CameraImageCaptureControl::~S60CameraImageCaptureControl()
+{
+}
+
+bool S60CameraImageCaptureControl::isReadyForCapture() const
+{
+ if (m_cameraControl && m_cameraControl->captureMode() != QCamera::CaptureStillImage)
+ return false;
+
+ return m_session->isDeviceReady();
+}
+
+QCameraImageCapture::DriveMode S60CameraImageCaptureControl::driveMode() const
+{
+ return m_driveMode;
+}
+
+void S60CameraImageCaptureControl::setDriveMode(QCameraImageCapture::DriveMode mode)
+{
+ if (mode != QCameraImageCapture::SingleImageCapture) {
+ emit error((m_session->currentImageId() + 1), QCamera::NotSupportedFeatureError, tr("DriveMode not supported."));
+ return;
+ }
+
+ m_driveMode = mode;
+}
+
+int S60CameraImageCaptureControl::capture(const QString &fileName)
+{
+ if (m_cameraControl && m_cameraControl->captureMode() != QCamera::CaptureStillImage) {
+ emit error((m_session->currentImageId() + 1), QCameraImageCapture::NotReadyError, tr("Incorrect CaptureMode."));
+ return 0;
+ }
+
+ int imageId = m_session->capture(fileName);
+
+ return imageId;
+}
+
+void S60CameraImageCaptureControl::cancelCapture()
+{
+ m_session->cancelCapture();
+}
+
+// End of file
diff --git a/src/plugins/symbian/ecam/s60cameraimagecapturecontrol.h b/src/plugins/symbian/ecam/s60cameraimagecapturecontrol.h
new file mode 100644
index 000000000..4c369e807
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameraimagecapturecontrol.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef S60CAMERAIMAGECAPTURECONTROL_H
+#define S60CAMERAIMAGECAPTURECONTROL_H
+
+#include "qcameraimagecapturecontrol.h"
+
+QT_USE_NAMESPACE
+
+class S60CameraService;
+class S60ImageCaptureSession;
+class S60CameraControl;
+
+/*
+ * Control for image capture operations.
+ */
+class S60CameraImageCaptureControl : public QCameraImageCaptureControl
+{
+ Q_OBJECT
+
+public: // Contructors & Destrcutor
+
+ S60CameraImageCaptureControl(QObject *parent = 0);
+ S60CameraImageCaptureControl(S60CameraService *service,
+ S60ImageCaptureSession *session,
+ QObject *parent = 0);
+ ~S60CameraImageCaptureControl();
+
+public: // QCameraImageCaptureControl
+
+ bool isReadyForCapture() const;
+
+ // Drive Mode
+ QCameraImageCapture::DriveMode driveMode() const;
+ void setDriveMode(QCameraImageCapture::DriveMode mode);
+
+ // Capture
+ int capture(const QString &fileName);
+ void cancelCapture();
+
+/*
+Q_SIGNALS: // QCameraImageCaptureControl
+ void readyForCaptureChanged(bool);
+
+ void imageExposed(int id);
+ void imageCaptured(int id, const QImage &preview);
+ void imageSaved(int id, const QString &fileName);
+
+ void error(int id, int error, const QString &errorString);
+*/
+
+private: // Data
+
+ S60ImageCaptureSession *m_session;
+ S60CameraService *m_service;
+ S60CameraControl *m_cameraControl;
+ QCameraImageCapture::DriveMode m_driveMode;
+};
+
+#endif // S60CAMERAIMAGECAPTURECONTROL_H
diff --git a/src/plugins/symbian/ecam/s60cameraimageprocessingcontrol.cpp b/src/plugins/symbian/ecam/s60cameraimageprocessingcontrol.cpp
new file mode 100644
index 000000000..ae2c4535a
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameraimageprocessingcontrol.cpp
@@ -0,0 +1,254 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qstring.h>
+
+#include "s60cameraimageprocessingcontrol.h"
+#include "s60cameraservice.h"
+#include "s60imagecapturesession.h"
+
+S60CameraImageProcessingControl::S60CameraImageProcessingControl(QObject *parent) :
+ QCameraImageProcessingControl(parent)
+{
+}
+
+S60CameraImageProcessingControl::S60CameraImageProcessingControl(S60ImageCaptureSession *session, QObject *parent) :
+ QCameraImageProcessingControl(parent),
+ m_session(0),
+ m_advancedSettings(0)
+{
+ m_session = session;
+ m_advancedSettings = m_session->advancedSettings();
+}
+
+S60CameraImageProcessingControl::~S60CameraImageProcessingControl()
+{
+ m_advancedSettings = 0;
+}
+
+void S60CameraImageProcessingControl::resetAdvancedSetting()
+{
+ m_advancedSettings = m_session->advancedSettings();
+}
+
+QCameraImageProcessing::WhiteBalanceMode S60CameraImageProcessingControl::whiteBalanceMode() const
+{
+ return m_session->whiteBalanceMode();
+}
+
+void S60CameraImageProcessingControl::setWhiteBalanceMode(QCameraImageProcessing::WhiteBalanceMode mode)
+{
+ if (isWhiteBalanceModeSupported(mode))
+ m_session->setWhiteBalanceMode(mode);
+ else
+ m_session->setError(KErrNotSupported, tr("Requested white balance mode is not supported."));
+}
+
+bool S60CameraImageProcessingControl::isWhiteBalanceModeSupported(
+ QCameraImageProcessing::WhiteBalanceMode mode) const
+{
+ return m_session->isWhiteBalanceModeSupported(mode);
+}
+
+int S60CameraImageProcessingControl::manualWhiteBalance() const
+{
+ return 0;
+}
+
+void S60CameraImageProcessingControl::setManualWhiteBalance(int colorTemperature)
+{
+ m_session->setError(KErrNotSupported, tr("Setting manual white balance is not supported."));
+ Q_UNUSED(colorTemperature)
+}
+
+bool S60CameraImageProcessingControl::isProcessingParameterSupported(ProcessingParameter parameter) const
+{
+ // First check settings requiring Adv. Settings
+ if (m_advancedSettings) {
+ switch (parameter) {
+ case QCameraImageProcessingControl::Saturation:
+ return true;
+ case QCameraImageProcessingControl::Sharpening:
+ return isSharpeningSupported();
+ case QCameraImageProcessingControl::Denoising:
+ return isDenoisingSupported();
+ case QCameraImageProcessingControl::ColorTemperature:
+ return false;
+ }
+ }
+
+ // Then the rest
+ switch (parameter) {
+ case QCameraImageProcessingControl::Contrast:
+ case QCameraImageProcessingControl::Brightness:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+QVariant S60CameraImageProcessingControl::processingParameter(
+ QCameraImageProcessingControl::ProcessingParameter parameter) const
+{
+ switch (parameter) {
+ case QCameraImageProcessingControl::Contrast:
+ return QVariant(contrast());
+ case QCameraImageProcessingControl::Saturation:
+ return QVariant(saturation());
+ case QCameraImageProcessingControl::Brightness:
+ return QVariant(brightness());
+ case QCameraImageProcessingControl::Sharpening:
+ return QVariant(sharpeningLevel());
+ case QCameraImageProcessingControl::Denoising:
+ return QVariant(denoisingLevel());
+ case QCameraImageProcessingControl::ColorTemperature:
+ return QVariant(manualWhiteBalance());
+
+ default:
+ return QVariant();
+ }
+}
+
+void S60CameraImageProcessingControl::setProcessingParameter(
+ QCameraImageProcessingControl::ProcessingParameter parameter, QVariant value)
+{
+ switch (parameter) {
+ case QCameraImageProcessingControl::Contrast:
+ setContrast(value.toInt());
+ break;
+ case QCameraImageProcessingControl::Saturation:
+ setSaturation(value.toInt());
+ break;
+ case QCameraImageProcessingControl::Brightness:
+ setBrightness(value.toInt());
+ break;
+ case QCameraImageProcessingControl::Sharpening:
+ if (isSharpeningSupported())
+ setSharpeningLevel(value.toInt());
+ break;
+ case QCameraImageProcessingControl::Denoising:
+ if (isDenoisingSupported())
+ setDenoisingLevel(value.toInt());
+ break;
+ case QCameraImageProcessingControl::ColorTemperature:
+ setManualWhiteBalance(value.toInt());
+ break;
+
+ default:
+ break;
+ }
+}
+
+void S60CameraImageProcessingControl::setContrast(int value)
+{
+ m_session->setContrast(value);
+}
+
+int S60CameraImageProcessingControl::contrast() const
+{
+ return m_session->contrast();
+}
+
+void S60CameraImageProcessingControl::setBrightness(int value)
+{
+ m_session->setBrightness(value);
+}
+
+int S60CameraImageProcessingControl::brightness() const
+{
+ return m_session->brightness();
+}
+
+void S60CameraImageProcessingControl::setSaturation(int value)
+{
+ if (m_advancedSettings)
+ m_advancedSettings->setSaturation(value);
+ else
+ m_session->setError(KErrNotSupported, tr("Setting saturation is not supported."));
+}
+
+int S60CameraImageProcessingControl::saturation() const
+{
+ if (m_advancedSettings)
+ return m_advancedSettings->saturation();
+ return 0;
+}
+
+void S60CameraImageProcessingControl::setDenoisingLevel(int value)
+{
+ m_session->setError(KErrNotSupported, tr("Setting denoising level is not supported."));
+ Q_UNUSED(value); // Not supported for Symbian
+}
+
+bool S60CameraImageProcessingControl::isDenoisingSupported() const
+{
+ return false; // Not supported for Symbian
+}
+
+int S60CameraImageProcessingControl::denoisingLevel() const
+{
+ return 0; // Not supported for Symbian
+}
+
+void S60CameraImageProcessingControl::setSharpeningLevel(int value)
+{
+ if (m_advancedSettings)
+ m_advancedSettings->setSharpeningLevel(value);
+ else
+ m_session->setError(KErrNotSupported, tr("Setting sharpening level is not supported."));
+}
+
+bool S60CameraImageProcessingControl::isSharpeningSupported() const
+{
+ if (m_advancedSettings)
+ return m_advancedSettings->isSharpeningSupported();
+ return false;
+}
+
+int S60CameraImageProcessingControl::sharpeningLevel() const
+{
+ if (m_advancedSettings)
+ return m_advancedSettings->sharpeningLevel();
+ return 0;
+}
+
+// End of file
diff --git a/src/plugins/symbian/ecam/s60cameraimageprocessingcontrol.h b/src/plugins/symbian/ecam/s60cameraimageprocessingcontrol.h
new file mode 100644
index 000000000..7fc6b8900
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameraimageprocessingcontrol.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef S60CAMERAIMAGEPROCESSINGCONTROL_H
+#define S60CAMERAIMAGEPROCESSINGCONTROL_H
+
+#include <qcameraimageprocessing.h>
+#include <qcameraimageprocessingcontrol.h>
+
+#include "s60camerasettings.h"
+
+QT_USE_NAMESPACE
+
+class S60CameraService;
+class S60ImageCaptureSession;
+
+/*
+ * Control for image processing related camera operations (inc. white balance).
+ */
+class S60CameraImageProcessingControl : public QCameraImageProcessingControl
+{
+ Q_OBJECT
+
+public: // Constructors & Destructor
+
+ S60CameraImageProcessingControl(QObject *parent = 0);
+ S60CameraImageProcessingControl(S60ImageCaptureSession *session, QObject *parent = 0);
+ ~S60CameraImageProcessingControl();
+
+public: // QCameraImageProcessingControl
+
+ // White Balance
+ QCameraImageProcessing::WhiteBalanceMode whiteBalanceMode() const;
+ void setWhiteBalanceMode(QCameraImageProcessing::WhiteBalanceMode mode);
+ bool isWhiteBalanceModeSupported(QCameraImageProcessing::WhiteBalanceMode mode) const;
+
+ // Processing Parameter
+ bool isProcessingParameterSupported(ProcessingParameter parameter) const;
+ QVariant processingParameter(QCameraImageProcessingControl::ProcessingParameter parameter) const;
+ void setProcessingParameter(QCameraImageProcessingControl::ProcessingParameter parameter, QVariant value);
+
+private slots: // Internal Slots
+
+ void resetAdvancedSetting();
+
+private: // Internal operations - Implementing ProcessingParameter
+
+ // Manual White Balance (Color Temperature)
+ int manualWhiteBalance() const;
+ void setManualWhiteBalance(int colorTemperature);
+
+ // Contrast
+ int contrast() const;
+ void setContrast(int value);
+
+ // Brightness
+ int brightness() const;
+ void setBrightness(int value);
+
+ // Saturation
+ int saturation() const;
+ void setSaturation(int value);
+
+ // Sharpening
+ bool isSharpeningSupported() const;
+ int sharpeningLevel() const;
+ void setSharpeningLevel(int value);
+
+ // Denoising
+ bool isDenoisingSupported() const;
+ int denoisingLevel() const;
+ void setDenoisingLevel(int value);
+
+private: // Data
+
+ S60ImageCaptureSession *m_session;
+ S60CameraSettings *m_advancedSettings;
+};
+
+#endif // S60CAMERAIMAGEPROCESSINGCONTROL_H
diff --git a/src/plugins/symbian/ecam/s60cameralockscontrol.cpp b/src/plugins/symbian/ecam/s60cameralockscontrol.cpp
new file mode 100644
index 000000000..cce030f22
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameralockscontrol.cpp
@@ -0,0 +1,263 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qstring.h>
+#include <qcamerafocus.h> // FocusMode
+
+#include "s60cameralockscontrol.h"
+#include "s60cameraservice.h"
+#include "s60imagecapturesession.h"
+#include "s60camerasettings.h"
+#include "s60camerafocuscontrol.h"
+
+S60CameraLocksControl::S60CameraLocksControl(QObject *parent) :
+ QCameraLocksControl(parent)
+{
+}
+
+S60CameraLocksControl::S60CameraLocksControl(S60CameraService *service,
+ S60ImageCaptureSession *session,
+ QObject *parent) :
+ QCameraLocksControl(parent),
+ m_session(0),
+ m_service(0),
+ m_advancedSettings(0),
+ m_focusControl(0),
+ m_focusStatus(QCamera::Unlocked),
+ m_exposureStatus(QCamera::Unlocked),
+ m_whiteBalanceStatus(QCamera::Unlocked)
+{
+ m_session = session;
+ m_service = service;
+ m_focusControl = qobject_cast<S60CameraFocusControl *>(m_service->requestControl(QCameraFocusControl_iid));
+
+ connect(m_session, SIGNAL(advancedSettingChanged()), this, SLOT(resetAdvancedSetting()));
+ m_advancedSettings = m_session->advancedSettings();
+
+ // Exposure Lock Signals
+ if (m_advancedSettings)
+ connect(m_advancedSettings, SIGNAL(exposureStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason)),
+ this, SLOT(exposureStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason)));
+
+ // Focus Lock Signal
+ // * S60 3.2 and later (through Adv. Settings)
+ if (m_advancedSettings)
+ connect(m_advancedSettings, SIGNAL(focusStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason)),
+ this, SLOT(focusStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason)));
+ // * S60 3.1 (through ImageSession)
+ connect(m_session, SIGNAL(focusStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason)),
+ this, SLOT(focusStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason)));
+}
+
+S60CameraLocksControl::~S60CameraLocksControl()
+{
+ m_advancedSettings = 0;
+}
+
+QCamera::LockTypes S60CameraLocksControl::supportedLocks() const
+{
+ QCamera::LockTypes supportedLocks = 0;
+
+#ifdef S60_CAM_AUTOFOCUS_SUPPORT // S60 3.1
+ if (m_session)
+ if (m_session->isFocusSupported())
+ supportedLocks |= QCamera::LockFocus;
+#else // S60 3.2 and later
+ if (m_advancedSettings) {
+ QCameraFocus::FocusModes supportedFocusModes = m_advancedSettings->supportedFocusModes();
+ if (supportedFocusModes & QCameraFocus::AutoFocus)
+ supportedLocks |= QCamera::LockFocus;
+
+ // Exposure/WhiteBalance Locking not implemented in Symbian
+ // supportedLocks |= QCamera::LockExposure;
+ // supportedLocks |= QCamera::LockWhiteBalance;
+ }
+#endif // S60_CAM_AUTOFOCUS_SUPPORT
+
+ return supportedLocks;
+}
+
+QCamera::LockStatus S60CameraLocksControl::lockStatus(QCamera::LockType lock) const
+{
+ switch (lock) {
+ case QCamera::LockExposure:
+ return m_exposureStatus;
+ case QCamera::LockWhiteBalance:
+ return m_whiteBalanceStatus;
+ case QCamera::LockFocus:
+ return m_focusStatus;
+
+ default:
+ // Unsupported lock
+ return QCamera::Unlocked;
+ }
+}
+
+void S60CameraLocksControl::searchAndLock(QCamera::LockTypes locks)
+{
+ if (locks & QCamera::LockExposure) {
+ // Not implemented in Symbian
+ //startExposureLocking();
+ }
+ if (locks & QCamera::LockWhiteBalance) {
+ // Not implemented in Symbian
+ }
+ if (locks & QCamera::LockFocus)
+ startFocusing();
+}
+
+void S60CameraLocksControl::unlock(QCamera::LockTypes locks)
+{
+ if (locks & QCamera::LockExposure) {
+ // Not implemented in Symbian
+ //cancelExposureLocking();
+ }
+
+ if (locks & QCamera::LockFocus)
+ cancelFocusing();
+}
+
+void S60CameraLocksControl::resetAdvancedSetting()
+{
+ m_advancedSettings = m_session->advancedSettings();
+
+ // Reconnect Lock Signals
+ if (m_advancedSettings) {
+ connect(m_advancedSettings, SIGNAL(exposureStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason)),
+ this, SLOT(exposureStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason)));
+ connect(m_advancedSettings, SIGNAL(focusStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason)),
+ this, SLOT(focusStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason)));
+ }
+}
+
+void S60CameraLocksControl::exposureStatusChanged(QCamera::LockStatus status,
+ QCamera::LockChangeReason reason)
+{
+ if(status != m_exposureStatus) {
+ m_exposureStatus = status;
+ emit lockStatusChanged(QCamera::LockExposure, status, reason);
+ }
+}
+
+void S60CameraLocksControl::focusStatusChanged(QCamera::LockStatus status,
+ QCamera::LockChangeReason reason)
+{
+ if(status != m_focusStatus) {
+ m_focusStatus = status;
+ emit lockStatusChanged(QCamera::LockFocus, status, reason);
+ }
+}
+
+void S60CameraLocksControl::startFocusing()
+{
+#ifndef S60_CAM_AUTOFOCUS_SUPPORT // S60 3.2 or later
+ // Focusing is triggered on Symbian by setting the FocusType corresponding
+ // to the FocusMode set to FocusControl
+ if (m_focusControl) {
+ if (m_advancedSettings) {
+ m_advancedSettings->startFocusing();
+ m_focusStatus = QCamera::Searching;
+ emit lockStatusChanged(QCamera::LockFocus, QCamera::Searching, QCamera::UserRequest);
+ }
+ else
+ emit lockStatusChanged(QCamera::LockFocus, QCamera::Unlocked, QCamera::LockFailed);
+ }
+ else
+ emit lockStatusChanged(QCamera::LockFocus, QCamera::Unlocked, QCamera::LockFailed);
+
+#else // S60 3.1
+ if (m_focusControl && m_focusControl->focusMode() == QCameraFocus::AutoFocus) {
+ m_session->startFocus();
+ m_focusStatus = QCamera::Searching;
+ emit lockStatusChanged(QCamera::LockFocus, QCamera::Searching, QCamera::UserRequest);
+ }
+ else
+ emit lockStatusChanged(QCamera::LockFocus, QCamera::Unlocked, QCamera::LockFailed);
+#endif // S60_CAM_AUTOFOCUS_SUPPORT
+}
+
+void S60CameraLocksControl::cancelFocusing()
+{
+ if (m_focusStatus == QCamera::Unlocked)
+ return;
+
+#ifndef S60_CAM_AUTOFOCUS_SUPPORT // S60 3.2 or later
+ if (m_advancedSettings) {
+ m_advancedSettings->cancelFocusing();
+ m_focusStatus = QCamera::Unlocked;
+ emit lockStatusChanged(QCamera::LockFocus, QCamera::Unlocked, QCamera::UserRequest);
+ }
+ else
+ emit lockStatusChanged(QCamera::LockFocus, QCamera::Unlocked, QCamera::LockFailed);
+
+#else // S60 3.1
+ m_session->cancelFocus();
+ m_focusStatus = QCamera::Unlocked;
+ emit lockStatusChanged(QCamera::LockFocus, QCamera::Unlocked, QCamera::UserRequest);
+#endif // S60_CAM_AUTOFOCUS_SUPPORT
+}
+
+void S60CameraLocksControl::startExposureLocking()
+{
+ if (m_advancedSettings) {
+ m_advancedSettings->lockExposure(true);
+ m_exposureStatus = QCamera::Searching;
+ emit lockStatusChanged(QCamera::LockExposure, QCamera::Searching, QCamera::UserRequest);
+ }
+ else
+ emit lockStatusChanged(QCamera::LockExposure, QCamera::Unlocked, QCamera::LockFailed);
+}
+
+void S60CameraLocksControl::cancelExposureLocking()
+{
+ if (m_exposureStatus == QCamera::Unlocked)
+ return;
+
+ if (m_advancedSettings) {
+ m_advancedSettings->lockExposure(false);
+ m_exposureStatus = QCamera::Unlocked;
+ emit lockStatusChanged(QCamera::LockExposure, QCamera::Unlocked, QCamera::UserRequest);
+ }
+ else
+ emit lockStatusChanged(QCamera::LockExposure, QCamera::Unlocked, QCamera::LockFailed);
+}
+
+// End of file
diff --git a/src/plugins/symbian/ecam/s60cameralockscontrol.h b/src/plugins/symbian/ecam/s60cameralockscontrol.h
new file mode 100644
index 000000000..3b49cbaba
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameralockscontrol.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef S60CAMERALOCKSCONTROL_H
+#define S60CAMERALOCKSCONTROL_H
+
+#include <QtCore/qobject.h>
+#include "qcameralockscontrol.h"
+
+QT_USE_NAMESPACE
+
+class S60CameraService;
+class S60ImageCaptureSession;
+class S60CameraSettings;
+class S60CameraFocusControl;
+
+/*
+ * Control for searching and locking 3A algorithms (AutoFocus, AutoExposure
+ * and AutoWhitebalance).
+ */
+class S60CameraLocksControl : public QCameraLocksControl
+{
+ Q_OBJECT
+
+public: // Contructors & Destrcutor
+
+ S60CameraLocksControl(QObject *parent = 0);
+ S60CameraLocksControl(S60CameraService *service,
+ S60ImageCaptureSession *session,
+ QObject *parent = 0);
+ ~S60CameraLocksControl();
+
+public: // QCameraLocksControl
+
+ QCamera::LockTypes supportedLocks() const;
+
+ QCamera::LockStatus lockStatus(QCamera::LockType lock) const;
+
+ void searchAndLock(QCamera::LockTypes locks);
+ void unlock(QCamera::LockTypes locks);
+
+/*
+Q_SIGNALS: // QCameraLocksControl
+
+ void lockStatusChanged(QCamera::LockType type,
+ QCamera::LockStatus status,
+ QCamera::LockChangeReason reason);
+*/
+
+private slots: // Internal Slots
+
+ void exposureStatusChanged(QCamera::LockStatus status, QCamera::LockChangeReason reason);
+ void focusStatusChanged(QCamera::LockStatus status, QCamera::LockChangeReason reason);
+ void resetAdvancedSetting();
+
+private: // Internal
+
+ // Focus
+ void startFocusing();
+ void cancelFocusing();
+
+ // Exposure
+ void startExposureLocking();
+ void cancelExposureLocking();
+
+private: // Data
+
+ S60ImageCaptureSession *m_session;
+ S60CameraService *m_service;
+ S60CameraSettings *m_advancedSettings;
+ S60CameraFocusControl *m_focusControl;
+ QCamera::LockStatus m_focusStatus;
+ QCamera::LockStatus m_exposureStatus;
+ QCamera::LockStatus m_whiteBalanceStatus;
+};
+
+#endif // S60CAMERALOCKSCONTROL_H
diff --git a/src/plugins/symbian/ecam/s60cameraservice.cpp b/src/plugins/symbian/ecam/s60cameraservice.cpp
new file mode 100644
index 000000000..5cc4485c1
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameraservice.cpp
@@ -0,0 +1,259 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qvariant.h>
+#include <QtGui/qwidget.h>
+#include <QtCore/qlist.h>
+
+#include "s60cameraservice.h"
+#include "s60cameracontrol.h"
+#include "s60videodevicecontrol.h"
+#include "s60camerafocuscontrol.h"
+#include "s60cameraexposurecontrol.h"
+#include "s60cameraflashcontrol.h"
+#include "s60cameraimageprocessingcontrol.h"
+#include "s60cameraimagecapturecontrol.h"
+#include "s60mediarecordercontrol.h"
+#include "s60videocapturesession.h"
+#include "s60imagecapturesession.h"
+#include "s60videowidgetcontrol.h"
+#include "s60mediacontainercontrol.h"
+#include "s60videoencodercontrol.h"
+#include "s60audioencodercontrol.h"
+#include "s60imageencodercontrol.h"
+#include "s60cameralockscontrol.h"
+#include "s60videorenderercontrol.h"
+#include "s60videowindowcontrol.h"
+
+#include "s60cameraviewfinderengine.h" // ViewfinderOutputType
+
+S60CameraService::S60CameraService(QObject *parent) :
+ QMediaService(parent)
+{
+ // Session classes for video and image capturing
+ m_imagesession = new S60ImageCaptureSession(this);
+ m_videosession = new S60VideoCaptureSession(this);
+
+ if (m_imagesession && m_videosession) {
+ // Different control classes implementing the Camera API
+ m_control = new S60CameraControl(m_videosession, m_imagesession, this);
+ m_videoDeviceControl = new S60VideoDeviceControl(m_control, this);
+ m_focusControl = new S60CameraFocusControl(m_imagesession, this);
+ m_exposureControl = new S60CameraExposureControl(m_imagesession, this);
+ m_flashControl = new S60CameraFlashControl(m_imagesession, this);
+ m_imageProcessingControl = new S60CameraImageProcessingControl(m_imagesession, this);
+ m_imageCaptureControl = new S60CameraImageCaptureControl(this, m_imagesession, this);
+ m_media = new S60MediaRecorderControl(this, m_videosession, this);
+ m_mediaFormat = new S60MediaContainerControl(m_videosession, this);
+ m_videoEncoder = new S60VideoEncoderControl(m_videosession, this);
+ m_audioEncoder = new S60AudioEncoderControl(m_videosession, this);
+ m_viewFinderWidget = new S60VideoWidgetControl(this);
+ m_imageEncoderControl = new S60ImageEncoderControl(m_imagesession, this);
+ m_locksControl = new S60CameraLocksControl(this, m_imagesession, this);
+ m_rendererControl = new S60VideoRendererControl(this);
+ m_windowControl = new S60VideoWindowControl(this);
+ }
+}
+
+S60CameraService::~S60CameraService()
+{
+ // Delete controls
+ if (m_videoDeviceControl)
+ delete m_videoDeviceControl;
+ if (m_focusControl)
+ delete m_focusControl;
+ if (m_exposureControl)
+ delete m_exposureControl;
+ if (m_flashControl)
+ delete m_flashControl;
+ if (m_imageProcessingControl)
+ delete m_imageProcessingControl;
+ if (m_imageCaptureControl)
+ delete m_imageCaptureControl;
+ if (m_media)
+ delete m_media;
+ if (m_mediaFormat)
+ delete m_mediaFormat;
+ if (m_videoEncoder)
+ delete m_videoEncoder;
+ if (m_audioEncoder)
+ delete m_audioEncoder;
+ if (m_imageEncoderControl)
+ delete m_imageEncoderControl;
+ if (m_locksControl)
+ delete m_locksControl;
+
+ // CameraControl destroys:
+ // * ViewfinderEngine
+ // * CameraEngine
+ if (m_control)
+ delete m_control;
+
+ // Delete viewfinder controls after CameraControl to be sure that
+ // ViewFinder gets stopped before widget (and window) is destroyed
+ if (m_viewFinderWidget)
+ delete m_viewFinderWidget;
+ if (m_rendererControl)
+ delete m_rendererControl;
+ if (m_windowControl)
+ delete m_windowControl;
+
+ // Delete sessions
+ if (m_videosession)
+ delete m_videosession;
+ if (m_imagesession)
+ delete m_imagesession;
+}
+
+QMediaControl *S60CameraService::requestControl(const char *name)
+{
+ if (qstrcmp(name, QMediaRecorderControl_iid) == 0)
+ return m_media;
+
+ if (qstrcmp(name, QCameraControl_iid) == 0)
+ return m_control;
+
+ if (qstrcmp(name, QVideoEncoderControl_iid) == 0)
+ return m_videoEncoder;
+
+ if (qstrcmp(name, QAudioEncoderControl_iid) == 0)
+ return m_audioEncoder;
+
+ if (qstrcmp(name, QMediaContainerControl_iid) == 0)
+ return m_mediaFormat;
+
+ if (qstrcmp(name, QCameraExposureControl_iid) == 0)
+ return m_exposureControl;
+
+ if (qstrcmp(name, QCameraFlashControl_iid) == 0)
+ return m_flashControl;
+
+ if (qstrcmp(name, QVideoWidgetControl_iid) == 0) {
+ if (m_viewFinderWidget) {
+ m_control->setVideoOutput(m_viewFinderWidget,
+ S60CameraViewfinderEngine::OutputTypeVideoWidget);
+ return m_viewFinderWidget;
+ }
+ else
+ return 0;
+ }
+
+ if (qstrcmp(name, QVideoRendererControl_iid) == 0) {
+ if (m_rendererControl) {
+ m_control->setVideoOutput(m_rendererControl,
+ S60CameraViewfinderEngine::OutputTypeRenderer);
+ return m_rendererControl;
+ }
+ else
+ return 0;
+ }
+
+ if (qstrcmp(name, QVideoWindowControl_iid) == 0) {
+ if (m_windowControl) {
+ m_control->setVideoOutput(m_windowControl,
+ S60CameraViewfinderEngine::OutputTypeVideoWindow);
+ return m_windowControl;
+ }
+ else
+ return 0;
+ }
+
+
+ if (qstrcmp(name, QCameraFocusControl_iid) == 0)
+ return m_focusControl;
+
+ if (qstrcmp(name, QCameraImageProcessingControl_iid) == 0)
+ return m_imageProcessingControl;
+
+ if (qstrcmp(name, QCameraImageCaptureControl_iid) == 0)
+ return m_imageCaptureControl;
+
+ if (qstrcmp(name, QVideoDeviceControl_iid) == 0)
+ return m_videoDeviceControl;
+
+ if (qstrcmp(name, QImageEncoderControl_iid) == 0)
+ return m_imageEncoderControl;
+
+ if (qstrcmp(name, QCameraLocksControl_iid) == 0)
+ return m_locksControl;
+
+ return 0;
+}
+
+void S60CameraService::releaseControl(QMediaControl *control)
+{
+ if (control == 0)
+ return;
+
+ // Release viewfinder output
+ if (control == m_viewFinderWidget) {
+ if (m_viewFinderWidget)
+ m_control->releaseVideoOutput(S60CameraViewfinderEngine::OutputTypeVideoWidget);
+ }
+
+ if (control == m_rendererControl) {
+ if (m_rendererControl)
+ m_control->releaseVideoOutput(S60CameraViewfinderEngine::OutputTypeRenderer);
+ }
+
+ if (control == m_windowControl) {
+ if (m_windowControl)
+ m_control->releaseVideoOutput(S60CameraViewfinderEngine::OutputTypeVideoWindow);
+ }
+}
+
+int S60CameraService::deviceCount()
+{
+ return S60CameraControl::deviceCount();
+}
+
+QString S60CameraService::deviceDescription(const int index)
+{
+ return S60CameraControl::description(index);
+}
+
+QString S60CameraService::deviceName(const int index)
+{
+ return S60CameraControl::name(index);
+}
+
+// End of file
+
diff --git a/src/plugins/symbian/ecam/s60cameraservice.h b/src/plugins/symbian/ecam/s60cameraservice.h
new file mode 100644
index 000000000..a2744c1fa
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameraservice.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef S60CAMERASERVICE_H
+#define S60CAMERASERVICE_H
+
+#include <QtCore/qobject.h>
+#include <qmediaservice.h>
+
+QT_USE_NAMESPACE
+
+class S60MediaContainerControl;
+class S60VideoEncoderControl;
+class S60AudioEncoderControl;
+class S60CameraControl;
+class S60VideoDeviceControl;
+class S60MediaRecorderControl;
+class S60ImageCaptureSession;
+class S60VideoCaptureSession;
+class S60CameraFocusControl;
+class S60CameraExposureControl;
+class S60CameraFlashControl;
+class S60CameraImageProcessingControl;
+class S60CameraImageCaptureControl;
+class S60VideoWidgetControl;
+class S60ImageEncoderControl;
+class S60CameraLocksControl;
+class S60VideoRendererControl;
+class S60VideoWindowControl;
+
+class S60CameraService : public QMediaService
+{
+ Q_OBJECT
+
+public: // Contructor & Destructor
+
+ S60CameraService(QObject *parent = 0);
+ ~S60CameraService();
+
+public: // QMediaService
+
+ QMediaControl *requestControl(const char *name);
+ void releaseControl(QMediaControl *control);
+
+public: // Static Device Info
+
+ static int deviceCount();
+ static QString deviceName(const int index);
+ static QString deviceDescription(const int index);
+
+private: // Data
+
+ S60ImageCaptureSession *m_imagesession;
+ S60VideoCaptureSession *m_videosession;
+ S60MediaContainerControl *m_mediaFormat;
+ S60VideoEncoderControl *m_videoEncoder;
+ S60AudioEncoderControl *m_audioEncoder;
+ S60CameraControl *m_control;
+ S60VideoDeviceControl *m_videoDeviceControl;
+ S60CameraFocusControl *m_focusControl;
+ S60CameraExposureControl *m_exposureControl;
+ S60CameraFlashControl *m_flashControl;
+ S60CameraImageProcessingControl *m_imageProcessingControl;
+ S60CameraImageCaptureControl *m_imageCaptureControl;
+ S60MediaRecorderControl *m_media;
+ S60VideoWidgetControl *m_viewFinderWidget;
+ S60ImageEncoderControl *m_imageEncoderControl;
+ S60CameraLocksControl *m_locksControl;
+ S60VideoRendererControl *m_rendererControl;
+ S60VideoWindowControl *m_windowControl;
+};
+
+#endif // S60CAMERASERVICE_H
diff --git a/src/plugins/symbian/ecam/s60cameraserviceplugin.cpp b/src/plugins/symbian/ecam/s60cameraserviceplugin.cpp
new file mode 100644
index 000000000..8f22fd205
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameraserviceplugin.cpp
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qstring.h>
+
+#include "s60cameraserviceplugin.h"
+#ifdef QMEDIA_SYMBIAN_CAMERA
+#include "s60cameraservice.h"
+#endif
+
+QStringList S60CameraServicePlugin::keys() const
+{
+ QStringList list;
+#ifdef QMEDIA_SYMBIAN_CAMERA
+ list << QLatin1String(Q_MEDIASERVICE_CAMERA);
+#endif
+ return list;
+}
+
+QMediaService* S60CameraServicePlugin::create(QString const& key)
+{
+#ifdef QMEDIA_SYMBIAN_CAMERA
+ if (key == QLatin1String(Q_MEDIASERVICE_CAMERA))
+ return new S60CameraService;
+#endif
+ return 0;
+}
+
+void S60CameraServicePlugin::release(QMediaService *service)
+{
+ delete service;
+}
+
+QList<QByteArray> S60CameraServicePlugin::devices(const QByteArray &service) const
+{
+#ifdef QMEDIA_SYMBIAN_CAMERA
+ if (service == Q_MEDIASERVICE_CAMERA) {
+ if (m_cameraDevices.isEmpty())
+ updateDevices();
+
+ return m_cameraDevices;
+ }
+#endif
+ return QList<QByteArray>();
+}
+
+QString S60CameraServicePlugin::deviceDescription(const QByteArray &service, const QByteArray &device)
+{
+#ifdef QMEDIA_SYMBIAN_CAMERA
+ if (service == Q_MEDIASERVICE_CAMERA) {
+ if (m_cameraDevices.isEmpty())
+ updateDevices();
+
+ for (int i=0; i<m_cameraDevices.count(); i++)
+ if (m_cameraDevices[i] == device)
+ return m_cameraDescriptions[i];
+ }
+#endif
+ return QString();
+}
+
+void S60CameraServicePlugin::updateDevices() const
+{
+#ifdef QMEDIA_SYMBIAN_CAMERA
+ m_cameraDevices.clear();
+ m_cameraDescriptions.clear();
+ for (int i=0; i < S60CameraService::deviceCount(); i ++) {
+ m_cameraDevices.append(S60CameraService::deviceName(i).toUtf8());
+ m_cameraDescriptions.append(S60CameraService::deviceDescription(i));
+ }
+#endif
+}
+
+Q_EXPORT_PLUGIN2(qtmultimedia_ecamngine, S60CameraServicePlugin);
+
+// End of file
+
diff --git a/src/plugins/symbian/ecam/s60cameraserviceplugin.h b/src/plugins/symbian/ecam/s60cameraserviceplugin.h
new file mode 100644
index 000000000..c56b054c6
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameraserviceplugin.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef S60CAMERASERVICEPLUGIN_H
+#define S60CAMERASERVICEPLUGIN_H
+
+#include <qmediaservice.h>
+#include <qmediaserviceproviderplugin.h>
+
+QT_USE_NAMESPACE
+
+/*
+ * Plugin implementation for the Camera Service
+ */
+class S60CameraServicePlugin : public QMediaServiceProviderPlugin,
+ public QMediaServiceSupportedDevicesInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QMediaServiceSupportedDevicesInterface)
+
+public: // QMediaServiceProviderPlugin
+
+ QStringList keys() const;
+ QMediaService* create(QString const& key);
+ void release(QMediaService *service);
+
+public: // QMediaServiceSupportedDevicesInterface
+
+ QList<QByteArray> devices(const QByteArray &service) const;
+ QString deviceDescription(const QByteArray &service, const QByteArray &device);
+
+private: // Internal
+
+ void updateDevices() const;
+
+private: // Data
+
+ mutable QList<QByteArray> m_cameraDevices;
+ mutable QStringList m_cameraDescriptions;
+};
+
+#endif // S60CAMERASERVICEPLUGIN_H
diff --git a/src/plugins/symbian/ecam/s60camerasettings.cpp b/src/plugins/symbian/ecam/s60camerasettings.cpp
new file mode 100644
index 000000000..a5918078f
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60camerasettings.cpp
@@ -0,0 +1,986 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "s60camerasettings.h"
+#include "s60cameraconstants.h"
+
+// S60 3.2 Platform
+#ifdef USE_S60_32_ECAM_ADVANCED_SETTINGS_HEADER
+#define POST_31_PLATFORM
+#include <ecamadvancedsettings.h> // CCameraAdvancedSettings (inc. TValueInfo)
+#endif // S60 3.2
+
+// S60 5.0 or later
+#ifdef USE_S60_50_ECAM_ADVANCED_SETTINGS_HEADER
+#define POST_31_PLATFORM
+#include <ecamadvsettings.h> // CCameraAdvancedSettings
+#include <ecam/ecamconstants.h> // TValueInfo
+#endif // S60 5.0 or later
+
+S60CameraSettings::S60CameraSettings(QObject *parent, CCameraEngine *engine) :
+ QObject(parent),
+#ifndef S60_31_PLATFORM // Post S60 3.1 Platforms
+ m_advancedSettings(0),
+ m_imageProcessingSettings(0),
+#endif // S60_31_PLATFORM
+ m_cameraEngine(engine),
+ m_continuousFocusing(false)
+{
+}
+
+S60CameraSettings::~S60CameraSettings()
+{
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ delete m_advancedSettings;
+ m_advancedSettings = 0;
+ }
+
+ if (m_imageProcessingSettings) {
+ delete m_imageProcessingSettings;
+ m_imageProcessingSettings = 0;
+ }
+#endif // POST_31_PLATFORM
+}
+
+/*
+ * This is Symbian NewL kind of consructor, but unlike Symbian version this
+ * constructor will not leave, but instead it will return possible errors in
+ * the error variable. This is to be able to write the class without deriving
+ * it form CBase. Also CleanupStack is cleaned here if the ConstructL leaves.
+ */
+S60CameraSettings* S60CameraSettings::New(int &error, QObject *parent, CCameraEngine *engine)
+{
+ S60CameraSettings* self = new S60CameraSettings(parent, engine);
+ if (!self) {
+ error = KErrNoMemory;
+ return 0;
+ }
+
+ TRAPD(err, self->ConstructL());
+ if (err) {
+ // Clean created object
+ delete self;
+ self = 0;
+ error = err;
+ return 0;
+ }
+
+ error = KErrNone;
+ return self;
+}
+
+void S60CameraSettings::ConstructL()
+{
+#ifdef POST_31_PLATFORM
+ if (!m_cameraEngine)
+ User::Leave(KErrGeneral);
+ // From now on it is safe to assume engine exists
+
+ // If no AdvancedSettings is available, there's no benefit of S60CameraSettings
+ // Leave if creation fails
+ m_advancedSettings = CCamera::CCameraAdvancedSettings::NewL(*m_cameraEngine->Camera());
+ CleanupStack::PushL(m_advancedSettings);
+
+ // ImageProcessing module may not be supported, don't Leave
+ TRAPD(err, m_imageProcessingSettings = CCamera::CCameraImageProcessing::NewL(*m_cameraEngine->Camera()));
+ if (err == KErrNone && m_imageProcessingSettings) {
+ CleanupStack::PushL(m_imageProcessingSettings);
+ } else {
+ if (err == KErrNotSupported)
+ m_imageProcessingSettings = 0;
+ else {
+ // Leave with error
+ if (!m_imageProcessingSettings)
+ User::Leave(KErrNoMemory);
+ else
+ User::Leave(err);
+ }
+ }
+
+ if (m_advancedSettings) {
+ RArray<TInt> digitalZoomFactors;
+ CleanupClosePushL(digitalZoomFactors);
+
+ TValueInfo info = ENotActive;
+ m_advancedSettings->GetDigitalZoomStepsL(digitalZoomFactors, info);
+
+ for (int i = 0; i < digitalZoomFactors.Count(); ++i)
+ m_supportedSymbianDigitalZoomFactors << digitalZoomFactors[i];
+
+ CleanupStack::PopAndDestroy(); // RArray<TInt> digitalZoomFactors
+ }
+
+ // Pop objects from CleanupStack
+ if (m_imageProcessingSettings)
+ CleanupStack::Pop(m_imageProcessingSettings);
+ CleanupStack::Pop(m_advancedSettings);
+
+#else // S60 3.1
+ // AdvancedSettings are not suppoted on S60 3.1 (There's no use for S60CameraSettings)
+ User::Leave(KErrNotSupported);
+#endif // POST_31_PLATFORM
+}
+
+void S60CameraSettings::setFocusMode(QCameraFocus::FocusMode mode)
+{
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ switch (mode) {
+ case QCameraFocus::ManualFocus: // Manual focus mode
+ m_advancedSettings->SetFocusMode(CCamera::CCameraAdvancedSettings::EFocusModeManual);
+ m_continuousFocusing = false;
+ break;
+ case QCameraFocus::AutoFocus: // Single-shot AutoFocus mode
+ m_advancedSettings->SetFocusMode(CCamera::CCameraAdvancedSettings::EFocusModeAuto);
+ m_advancedSettings->SetFocusRange(CCamera::CCameraAdvancedSettings::EFocusRangeAuto);
+ m_continuousFocusing = false;
+ break;
+ case QCameraFocus::HyperfocalFocus:
+ m_advancedSettings->SetFocusMode(CCamera::CCameraAdvancedSettings::EFocusModeAuto);
+ m_advancedSettings->SetFocusRange(CCamera::CCameraAdvancedSettings::EFocusRangeHyperfocal);
+ m_continuousFocusing = false;
+ break;
+ case QCameraFocus::InfinityFocus:
+ m_advancedSettings->SetFocusMode(CCamera::CCameraAdvancedSettings::EFocusModeAuto);
+ m_advancedSettings->SetFocusRange(CCamera::CCameraAdvancedSettings::EFocusRangeInfinite);
+ m_continuousFocusing = false;
+ break;
+ case QCameraFocus::ContinuousFocus:
+ m_advancedSettings->SetFocusMode(CCamera::CCameraAdvancedSettings::EFocusModeAuto);
+ m_advancedSettings->SetFocusRange(CCamera::CCameraAdvancedSettings::EFocusRangeAuto);
+ m_continuousFocusing = true;
+ break;
+ case QCameraFocus::MacroFocus:
+ m_advancedSettings->SetFocusMode(CCamera::CCameraAdvancedSettings::EFocusModeAuto);
+ m_advancedSettings->SetFocusRange(CCamera::CCameraAdvancedSettings::EFocusRangeMacro);
+ m_continuousFocusing = false;
+ break;
+
+ default:
+ emit error(QCamera::NotSupportedFeatureError, tr("Requested focus mode is not supported."));
+ break;
+ }
+ } else {
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+ }
+#else // S60 3.1
+ Q_UNUSED(mode);
+ emit error(QCamera::NotSupportedFeatureError, tr("Settings focus mode is not supported."));
+#endif // POST_31_PLATFORM
+}
+
+void S60CameraSettings::startFocusing()
+{
+#ifdef POST_31_PLATFORM
+ // Setting AutoFocusType triggers the focusing on Symbian
+ if (m_advancedSettings) {
+ if (m_continuousFocusing)
+ m_advancedSettings->SetAutoFocusType(CCamera::CCameraAdvancedSettings::EAutoFocusTypeContinuous);
+ else
+ m_advancedSettings->SetAutoFocusType(CCamera::CCameraAdvancedSettings::EAutoFocusTypeSingle);
+ } else {
+ emit error(QCamera::CameraError, tr("Unable to focus."));
+ }
+#endif // POST_31_PLATFORM
+}
+
+void S60CameraSettings::cancelFocusing()
+{
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings)
+ m_advancedSettings->SetAutoFocusType(CCamera::CCameraAdvancedSettings::EAutoFocusTypeOff);
+ else
+ emit error(QCamera::CameraError, tr("Unable to cancel focusing."));
+#endif // POST_31_PLATFORM
+}
+
+QCameraFocus::FocusMode S60CameraSettings::focusMode()
+{
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ // First request needed info
+ CCamera::CCameraAdvancedSettings::TFocusMode mode = m_advancedSettings->FocusMode();
+ CCamera::CCameraAdvancedSettings::TFocusRange range = m_advancedSettings->FocusRange();
+ CCamera::CCameraAdvancedSettings::TAutoFocusType autoType = m_advancedSettings->AutoFocusType();
+
+ switch (mode) {
+ case CCamera::CCameraAdvancedSettings::EFocusModeManual:
+ case CCamera::CCameraAdvancedSettings::EFocusModeFixed:
+ return QCameraFocus::ManualFocus;
+
+ case CCamera::CCameraAdvancedSettings::EFocusModeAuto:
+ if (autoType == CCamera::CCameraAdvancedSettings::EAutoFocusTypeContinuous) {
+ return QCameraFocus::ContinuousFocus;
+ } else {
+ // Single-shot focusing
+ switch (range) {
+ case CCamera::CCameraAdvancedSettings::EFocusRangeMacro:
+ case CCamera::CCameraAdvancedSettings::EFocusRangeSuperMacro:
+ return QCameraFocus::MacroFocus;
+ case CCamera::CCameraAdvancedSettings::EFocusRangeHyperfocal:
+ return QCameraFocus::HyperfocalFocus;
+ case CCamera::CCameraAdvancedSettings::EFocusRangeInfinite:
+ return QCameraFocus::InfinityFocus;
+ case CCamera::CCameraAdvancedSettings::EFocusRangeAuto:
+ case CCamera::CCameraAdvancedSettings::EFocusRangeNormal:
+ return QCameraFocus::AutoFocus;
+
+ default:
+ return QCameraFocus::AutoFocus;
+ }
+ }
+ default:
+ return QCameraFocus::AutoFocus; // Return automatic focusing
+ }
+ } else {
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+ }
+#endif // POST_31_PLATFORM
+ return QCameraFocus::AutoFocus; // Return automatic focusing
+}
+
+QCameraFocus::FocusModes S60CameraSettings::supportedFocusModes()
+{
+ QCameraFocus::FocusModes modes = 0;
+
+#ifdef POST_31_PLATFORM
+ TInt supportedModes = 0;
+ TInt autoFocusTypes = 0;
+ TInt supportedRanges = 0;
+
+ if (m_advancedSettings) {
+ supportedModes = m_advancedSettings->SupportedFocusModes();
+ autoFocusTypes = m_advancedSettings->SupportedAutoFocusTypes();
+ supportedRanges = m_advancedSettings->SupportedFocusRanges();
+
+ if (supportedModes == 0 || autoFocusTypes == 0 || supportedRanges == 0)
+ return modes;
+
+ // EFocusModeAuto is the only supported on Symbian
+ if (supportedModes & CCamera::CCameraAdvancedSettings::EFocusModeAuto) {
+ // Check supported types (Single-shot Auto vs. Continuous)
+ if (autoFocusTypes & CCamera::CCameraAdvancedSettings::EAutoFocusTypeSingle)
+ modes |= QCameraFocus::AutoFocus;
+ if (autoFocusTypes & CCamera::CCameraAdvancedSettings::EAutoFocusTypeContinuous)
+ modes |= QCameraFocus::ContinuousFocus;
+
+ // Check supported ranges (Note! Some are actually fixed focuses
+ // even though the mode is Auto on Symbian)
+ if (supportedRanges & CCamera::CCameraAdvancedSettings::EFocusRangeMacro)
+ modes |= QCameraFocus::MacroFocus;
+ if (supportedRanges & CCamera::CCameraAdvancedSettings::EFocusRangeHyperfocal)
+ modes |= QCameraFocus::HyperfocalFocus;
+ if (supportedRanges & CCamera::CCameraAdvancedSettings::EFocusRangeInfinite)
+ modes |= QCameraFocus::InfinityFocus;
+ }
+ } else {
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+ }
+#endif // POST_31_PLATFORM
+
+ return modes;
+}
+
+qreal S60CameraSettings::opticalZoomFactorL() const
+{
+ // Not supported on Symbian
+ return 1.0;
+}
+
+void S60CameraSettings::setOpticalZoomFactorL(const qreal zoomFactor)
+{
+ // Not supported on Symbian
+ Q_UNUSED(zoomFactor);
+}
+
+QList<qreal> S60CameraSettings::supportedDigitalZoomFactors() const
+{
+ QList<qreal> zoomFactors;
+ foreach (int factor, m_supportedSymbianDigitalZoomFactors)
+ zoomFactors << qreal(factor) / KSymbianFineResolutionFactor;
+
+ return zoomFactors;
+}
+
+qreal S60CameraSettings::digitalZoomFactorL() const
+{
+ qreal factor = 1.0;
+
+#ifdef POST_31_PLATFORM
+ int symbianFactor = 0;
+ if (m_advancedSettings)
+ symbianFactor = m_advancedSettings->DigitalZoom();
+ else
+ User::Leave(KErrNotSupported);
+
+ if (symbianFactor != 0)
+ factor = qreal(symbianFactor) / KSymbianFineResolutionFactor;
+#endif // POST_31_PLATFORM
+
+ return factor;
+}
+
+void S60CameraSettings::setDigitalZoomFactorL(const qreal zoomFactor)
+{
+#ifdef POST_31_PLATFORM
+ int symbianFactor = zoomFactor * KSymbianFineResolutionFactor;
+
+ // Find closest supported Symbian ZoomFactor if needed
+ if (!m_supportedSymbianDigitalZoomFactors.contains(symbianFactor)) {
+ int closestIndex = -1;
+ int closestDiff = 1000000; // Sensible maximum
+ for (int i = 0; i < m_supportedSymbianDigitalZoomFactors.count(); ++i) {
+ int diff = abs(m_supportedSymbianDigitalZoomFactors.at(i) - symbianFactor);
+ if (diff < closestDiff) {
+ closestDiff = diff;
+ closestIndex = i;
+ }
+ }
+ if (closestIndex != -1)
+ symbianFactor = m_supportedSymbianDigitalZoomFactors.at(closestIndex);
+ else
+ User::Leave(KErrGeneral);
+ }
+ if (m_advancedSettings)
+ m_advancedSettings->SetDigitalZoom(symbianFactor);
+ else
+ User::Leave(KErrNotSupported);
+#else // S60 3.1 Platform
+ Q_UNUSED(zoomFactor);
+ emit error(QCamera::NotSupportedFeatureError, tr("Settings digital zoom factor is not supported."));
+#endif // POST_31_PLATFORM
+}
+
+// MCameraObserver2
+void S60CameraSettings::HandleAdvancedEvent(const TECAMEvent& aEvent)
+{
+#ifdef POST_31_PLATFORM
+
+ if (aEvent.iErrorCode != KErrNone) {
+ switch (aEvent.iErrorCode) {
+ case KErrECamCameraDisabled:
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+ return;
+ case KErrECamSettingDisabled:
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+ return;
+ case KErrECamParameterNotInRange:
+ emit error(QCamera::NotSupportedFeatureError, tr("Requested value is not in supported range."));
+ return;
+ case KErrECamSettingNotSupported:
+ emit error(QCamera::NotSupportedFeatureError, tr("Requested setting is not supported."));
+ return;
+ case KErrECamNotOptimalFocus:
+ if (m_continuousFocusing)
+ emit focusStatusChanged(QCamera::Searching, QCamera::LockTemporaryLost);
+ else
+ emit focusStatusChanged(QCamera::Unlocked, QCamera::LockFailed);
+ return;
+ }
+
+ if (aEvent.iEventType == KUidECamEventCameraSettingFocusRange ||
+ aEvent.iEventType == KUidECamEventCameraSettingAutoFocusType2) {
+ emit focusStatusChanged(QCamera::Unlocked, QCamera::LockFailed);
+ return;
+ } else if (aEvent.iEventType == KUidECamEventCameraSettingIsoRate) {
+ if (aEvent.iErrorCode == KErrNotSupported)
+ emit error(QCamera::NotSupportedFeatureError, tr("Requested ISO value is not supported."));
+ else
+ emit error(QCamera::CameraError, tr("Setting ISO value failed."));
+ return;
+ } else if (aEvent.iEventType == KUidECamEventCameraSettingAperture) {
+ if (aEvent.iErrorCode == KErrNotSupported)
+ emit error(QCamera::NotSupportedFeatureError, tr("Requested aperture value is not supported."));
+ else
+ emit error(QCamera::CameraError, tr("Setting aperture value failed."));
+ return;
+ } else if (aEvent.iEventType == KUidECamEventCameraSettingExposureCompensation) {
+ if (aEvent.iErrorCode == KErrNotSupported)
+ emit error(QCamera::NotSupportedFeatureError, tr("Requested exposure compensation is not supported."));
+ else
+ emit error(QCamera::CameraError, tr("Setting exposure compensation failed."));
+ return;
+ } else if (aEvent.iEventType == KUidECamEventCameraSettingOpticalZoom ||
+ aEvent.iEventType == KUidECamEventCameraSettingDigitalZoom) {
+ if (aEvent.iErrorCode == KErrNotSupported)
+ return; // Discard
+ else {
+ emit error(QCamera::CameraError, tr("Setting zoom factor failed."));
+ return;
+ }
+ } else if (aEvent.iEventType == KUidECamEventCameraSettingFocusMode) {
+ if (aEvent.iErrorCode == KErrNotSupported)
+ if (m_cameraEngine && m_cameraEngine->CurrentCameraIndex() != 0)
+ emit error(QCamera::NotSupportedFeatureError, tr("Focusing is not supported with this camera."));
+ else
+ emit error(QCamera::NotSupportedFeatureError, tr("Requested focus mode is not supported."));
+ else
+ emit error(QCamera::CameraError, tr("Setting focus mode failed."));
+ return;
+ } else {
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+ return;
+ }
+ }
+
+ if (aEvent.iEventType == KUidECamEventCameraSettingExposureLock) {
+ if (m_advancedSettings) {
+ if (m_advancedSettings->ExposureLockOn())
+ emit exposureStatusChanged(QCamera::Locked, QCamera::LockAcquired);
+ else
+ emit exposureStatusChanged(QCamera::Unlocked, QCamera::LockLost);
+ }
+ else
+ emit exposureStatusChanged(QCamera::Unlocked, QCamera::LockLost);
+ }
+ else if (aEvent.iEventType == KUidECamEventCameraSettingAperture)
+ emit apertureChanged();
+
+ else if (aEvent.iEventType == KUidECamEventCameraSettingApertureRange)
+ emit apertureRangeChanged();
+
+ else if (aEvent.iEventType == KUidECamEventCameraSettingIsoRateType)
+ emit isoSensitivityChanged();
+
+ else if (aEvent.iEventType == KUidECamEventCameraSettingShutterSpeed)
+ emit shutterSpeedChanged();
+
+ else if (aEvent.iEventType == KUidECamEventCameraSettingExposureCompensationStep)
+ emit evChanged();
+
+ else if (aEvent.iEventType == KUidECamEventFlashReady)
+ emit flashReady(true);
+
+ else if (aEvent.iEventType == KUidECamEventFlashNotReady)
+ emit flashReady(false);
+
+ else if (aEvent.iEventType.iUid == KUidECamEventCameraSettingsOptimalFocusUidValue)
+ emit focusStatusChanged(QCamera::Locked, QCamera::LockAcquired);
+
+#else // S60 3.1 Platform
+ Q_UNUSED(aEvent);
+#endif // POST_31_PLATFORM
+}
+
+bool S60CameraSettings::isFlashReady()
+{
+ TBool isReady = false;
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ int flashErr = m_advancedSettings->IsFlashReady(isReady);
+ if(flashErr != KErrNone) {
+ if (flashErr != KErrNotSupported)
+ emit error(QCamera::CameraError, tr("Unexpected error with flash."));
+ return false;
+ }
+ }
+ else
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+#endif
+ return isReady;
+}
+
+QCameraExposure::MeteringMode S60CameraSettings::meteringMode()
+{
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ CCamera::CCameraAdvancedSettings::TMeteringMode mode = m_advancedSettings->MeteringMode();
+ switch (mode) {
+ case CCamera::CCameraAdvancedSettings::EMeteringModeCenterWeighted:
+ return QCameraExposure::MeteringAverage;
+ case CCamera::CCameraAdvancedSettings::EMeteringModeEvaluative:
+ return QCameraExposure::MeteringMatrix;
+ case CCamera::CCameraAdvancedSettings::EMeteringModeSpot:
+ return QCameraExposure::MeteringSpot;
+
+ default:
+ return QCameraExposure::MeteringAverage;
+ }
+ }else {
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+ return QCameraExposure::MeteringAverage;
+ }
+#else // S60 3.1 Platform
+ return QCameraExposure::MeteringAverage;
+#endif // POST_31_PLATFORM
+}
+
+void S60CameraSettings::setMeteringMode(QCameraExposure::MeteringMode mode)
+{
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ switch(mode) {
+ case QCameraExposure::MeteringAverage:
+ m_advancedSettings->SetMeteringMode(CCamera::CCameraAdvancedSettings::EMeteringModeCenterWeighted);
+ break;
+ case QCameraExposure::MeteringMatrix:
+ m_advancedSettings->SetMeteringMode(CCamera::CCameraAdvancedSettings::EMeteringModeEvaluative);
+ break;
+ case QCameraExposure::MeteringSpot:
+ m_advancedSettings->SetMeteringMode(CCamera::CCameraAdvancedSettings::EMeteringModeSpot);
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+#else // S60 3.1
+ Q_UNUSED(mode);
+ emit error(QCamera::NotSupportedFeatureError, tr("Setting metering mode is not supported."));
+#endif // POST_31_PLATFORM
+}
+
+bool S60CameraSettings::isMeteringModeSupported(QCameraExposure::MeteringMode mode)
+{
+#ifdef POST_31_PLATFORM
+ TInt supportedModes = 0;
+
+ if (m_advancedSettings) {
+ supportedModes = m_advancedSettings->SupportedMeteringModes();
+ if (supportedModes == 0)
+ return false;
+
+ switch (mode) {
+ case QCameraExposure::MeteringMatrix:
+ if (supportedModes & CCamera::CCameraAdvancedSettings::EMeteringModeEvaluative)
+ return true;
+ else
+ return false;
+ case QCameraExposure::MeteringAverage:
+ if (supportedModes & CCamera::CCameraAdvancedSettings::EMeteringModeCenterWeighted)
+ return true;
+ else
+ return false;
+ case QCameraExposure::MeteringSpot:
+ if (supportedModes & CCamera::CCameraAdvancedSettings::EMeteringModeSpot)
+ return true;
+ else
+ return false;
+
+ default:
+ return false;
+ }
+ }
+ else
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+#else // S60 3.1
+ Q_UNUSED(mode);
+#endif // POST_31_PLATFORM
+
+ return false;
+}
+
+int S60CameraSettings::isoSensitivity()
+{
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ CCamera::CCameraAdvancedSettings::TISORateType isoRateType;
+ TInt param = 0;
+ TInt isoRate = 0;
+ TRAPD(err, m_advancedSettings->GetISORateL(isoRateType, param, isoRate));
+ if (err)
+ return 0;
+ if (isoRate != KErrNotFound)
+ return isoRate;
+ } else {
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+ }
+#endif // POST_31_PLATFORM
+ return 0;
+}
+
+QList<int> S60CameraSettings::supportedIsoSensitivities()
+{
+ QList<int> isoSentitivities;
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ RArray<TInt> supportedIsoRates;
+ CleanupClosePushL(supportedIsoRates);
+
+ TRAPD(err, m_advancedSettings->GetSupportedIsoRatesL(supportedIsoRates));
+ if (err != KErrNone) {
+ if (err != KErrNotSupported) // Don's emit error if ISO is not supported
+ emit error(QCamera::CameraError, tr("Failure while querying supported iso sensitivities."));
+ } else {
+ for (int i = 0; i < supportedIsoRates.Count(); ++i)
+ isoSentitivities << supportedIsoRates[i];
+ }
+ CleanupStack::PopAndDestroy(); // RArray<TInt> supportedIsoRates
+ } else {
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+ }
+
+ return isoSentitivities;
+#else // S60 3.1 Platform
+ return isoSentitivities;
+#endif // POST_31_PLATFORM
+}
+
+void S60CameraSettings::setManualIsoSensitivity(int iso)
+{
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ TRAPD(err, m_advancedSettings->SetISORateL(CCamera::CCameraAdvancedSettings::EISOManual, iso));
+ if (err)
+ emit error(QCamera::CameraError, tr("Setting manual iso sensitivity failed."));
+ return;
+ } else {
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+ }
+#else // S60 3.1 Platform
+ Q_UNUSED(iso);
+ emit error(QCamera::NotSupportedFeatureError, tr("Setting manual iso sensitivity is not supported."));
+#endif // POST_31_PLATFORM
+}
+
+void S60CameraSettings::setAutoIsoSensitivity()
+{
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ TRAPD(err, m_advancedSettings->SetISORateL(CCamera::CCameraAdvancedSettings::EISOAutoUnPrioritised, 0));
+ if (err)
+ emit error(QCamera::CameraError, tr("Setting auto iso sensitivity failed."));
+ return;
+ }
+ else
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+#else // S60 3.1 Platform
+ emit error(QCamera::NotSupportedFeatureError, tr("Setting auto iso sensitivity is not supported."));
+#endif // POST_31_PLATFORM
+}
+
+qreal S60CameraSettings::aperture()
+{
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings)
+ return qreal(m_advancedSettings->Aperture()) / KSymbianFineResolutionFactor;
+ else
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+ return 0;
+#else // S60 3.1 Platform
+ return 0;
+#endif // POST_31_PLATFORM
+}
+
+QList<qreal> S60CameraSettings::supportedApertures()
+{
+ QList<qreal> apertures;
+
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ RArray<TInt> supportedApertures;
+ TValueInfo info = ENotActive;
+
+ TRAPD(err, m_advancedSettings->GetAperturesL(supportedApertures, info));
+ if (err != KErrNone)
+ if (err != KErrNotSupported)
+ emit error(QCamera::CameraError, tr("Failure while querying supported apertures."));
+ else {
+ for (int i = 0; i < supportedApertures.Count(); i++) {
+ qreal q = qreal(supportedApertures[i]) / KSymbianFineResolutionFactor;
+ apertures.append(q);
+ }
+ }
+ supportedApertures.Close();
+ }
+ else
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+ return apertures;
+#else // S60 3.1 Platform
+ return apertures;
+#endif // POST_31_PLATFORM
+}
+
+void S60CameraSettings::setManualAperture(qreal aperture)
+{
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ int symbianAperture = (aperture * KSymbianFineResolutionFactor); // KSymbianFineResolutionFactor = 100
+ m_advancedSettings->SetAperture(symbianAperture);
+ }
+ else
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+#else // S60 3.1
+ Q_UNUSED(aperture);
+ emit error(QCamera::NotSupportedFeatureError, tr("Setting manual aperture is not supported."));
+#endif // POST_31_PLATFORM
+}
+
+void S60CameraSettings::lockExposure(bool lock)
+{
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ m_advancedSettings->SetExposureLockOn(lock);
+ return;
+ }
+ else
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+#else // S60 3.1
+ Q_UNUSED(lock);
+ emit error(QCamera::NotSupportedFeatureError, tr("Locking exposure is not supported."));
+#endif // POST_31_PLATFORM
+}
+
+bool S60CameraSettings::isExposureLocked()
+{
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings)
+ return m_advancedSettings->ExposureLockOn();
+ else
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+#endif // POST_31_PLATFORM
+ return false;
+}
+
+qreal S60CameraSettings::shutterSpeed()
+{
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ qreal shutterSpeed = qreal(m_advancedSettings->ShutterSpeed()) / 1000000.0;
+ return shutterSpeed; // In seconds
+ } else {
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+ }
+ return 0;
+#else // S60 3.1 Platform
+ return 0;
+#endif // POST_31_PLATFORM
+}
+
+QList<qreal> S60CameraSettings::supportedShutterSpeeds()
+{
+ QList<qreal> speeds;
+
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ RArray<TInt> supportedSpeeds;
+ TValueInfo info = ENotActive;
+
+ TRAPD(err, m_advancedSettings->GetShutterSpeedsL(supportedSpeeds, info));
+ if (err != KErrNone)
+ if (err != KErrNotSupported)
+ emit error(QCamera::CameraError, tr("Failure while querying supported shutter speeds."));
+ else {
+ for (int i = 0; i < supportedSpeeds.Count(); i++) {
+ qreal q = qreal(supportedSpeeds[i]) / 1000000.0;
+ speeds.append(q); // In seconds
+ }
+ }
+ supportedSpeeds.Close();
+ }
+ else
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+ return speeds;
+#else // S60 3.1 Platform
+ return speeds;
+#endif // POST_31_PLATFORM
+}
+
+void S60CameraSettings::setManualShutterSpeed(qreal speed)
+{
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ TInt shutterSpeed = speed * 1000000; // From seconds to microseconds
+ m_advancedSettings->SetShutterSpeed(shutterSpeed);
+ } else {
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+ }
+#else // S60 3.1
+ emit error(QCamera::NotSupportedFeatureError, tr("Setting manual shutter speed is not supported."));
+ Q_UNUSED(speed);
+#endif // POST_31_PLATFORM
+}
+
+void S60CameraSettings::setExposureCompensation(qreal ev)
+{
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ TInt evStep = ev * KSymbianFineResolutionFactor;
+ m_advancedSettings->SetExposureCompensationStep(evStep);
+ } else {
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+ }
+#else // S60 3.1 Platform
+ Q_UNUSED(ev);
+ emit error(QCamera::NotSupportedFeatureError, tr("Setting exposure compensation is not supported."));
+#endif // POST_31_PLATFORM
+}
+
+qreal S60CameraSettings::exposureCompensation()
+{
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ TInt evStepSymbian = 0;
+ m_advancedSettings->GetExposureCompensationStep(evStepSymbian);
+ qreal evStep = evStepSymbian;
+ evStep /= KSymbianFineResolutionFactor;
+ return evStep;
+ } else {
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+ }
+ return 0;
+#else // S60 3.1 Platform
+ return 0;
+#endif // POST_31_PLATFORM
+}
+
+QList<qreal> S60CameraSettings::supportedExposureCompensationValues()
+{
+ QList<qreal> valueList;
+
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ RArray<TInt> evSteps;
+ TValueInfo info;
+ TRAPD(err, m_advancedSettings->GetExposureCompensationStepsL(evSteps, info));
+ if (err) {
+ if (err != KErrNotSupported)
+ emit error(QCamera::CameraError, tr("Failure while querying supported exposure compensation values."));
+ return valueList;
+ }
+
+ if (info == ENotActive || evSteps.Count() == 0) {
+ // EV not supported, return empty list
+ return valueList;
+ }
+
+ for (int i = 0; i < evSteps.Count(); ++i) {
+ qreal appendValue = evSteps[i];
+ appendValue /= KSymbianFineResolutionFactor;
+ valueList.append(appendValue);
+ }
+ }
+ else
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+ return valueList;
+#else // S60 3.1 Platform
+ return valueList;
+#endif // POST_31_PLATFORM
+}
+
+void S60CameraSettings::setSharpeningLevel(int value)
+{
+#ifdef POST_31_PLATFORM
+ if (m_imageProcessingSettings && isSharpeningSupported())
+ m_imageProcessingSettings->SetTransformationValue(KUidECamEventImageProcessingAdjustSharpness, value);
+ else
+ emit error(QCamera::NotSupportedFeatureError, tr("Setting sharpening level is not supported."));
+#else // S60 3.1
+ Q_UNUSED(value);
+ emit error(QCamera::NotSupportedFeatureError, tr("Setting sharpening level is not supported."));
+#endif // POST_31_PLATFORM
+}
+
+bool S60CameraSettings::isSharpeningSupported() const
+{
+#ifdef POST_31_PLATFORM
+ if (m_imageProcessingSettings) {
+ RArray<TUid> suppTransforms;
+ TRAPD(err, m_imageProcessingSettings->GetSupportedTransformationsL(suppTransforms));
+ if (err)
+ return false;
+
+ if (suppTransforms.Find(KUidECamEventImageProcessingAdjustSharpness))
+ return true;
+ }
+ return false;
+#else // S60 3.1 Platform
+ return false;
+#endif // POST_31_PLATFORM
+}
+
+int S60CameraSettings::sharpeningLevel() const
+{
+#ifdef POST_31_PLATFORM
+ if (m_imageProcessingSettings && isSharpeningSupported())
+ return m_imageProcessingSettings->TransformationValue(KUidECamEventImageProcessingAdjustSharpness);
+ else
+ return 0;
+#else // S60 3.1 Platform
+ return 0;
+#endif // POST_31_PLATFORM
+}
+
+void S60CameraSettings::setSaturation(int value)
+{
+#ifdef POST_31_PLATFORM
+ if (m_imageProcessingSettings) {
+ RArray<TUid> suppTransforms;
+ TRAPD(err, m_imageProcessingSettings->GetSupportedTransformationsL(suppTransforms));
+ if (err)
+ if (err != KErrNotSupported)
+ emit error(QCamera::CameraError, tr("Failure while querying supported transformations."));
+
+ if (suppTransforms.Find(KUidECamEventtImageProcessingAdjustSaturation))
+ m_imageProcessingSettings->SetTransformationValue(KUidECamEventtImageProcessingAdjustSaturation, value == -1 ? 0 : value*2-100);
+ else
+ emit error(QCamera::NotSupportedFeatureError, tr("Setting saturation is not supported."));
+ }
+ else
+ emit error(QCamera::NotSupportedFeatureError, tr("Setting saturation is not supported."));
+#else // S60 3.1
+ Q_UNUSED(value);
+ emit error(QCamera::NotSupportedFeatureError, tr("Setting saturation is not supported."));
+#endif // POST_31_PLATFORM
+}
+
+int S60CameraSettings::saturation()
+{
+#ifdef POST_31_PLATFORM
+ if (m_imageProcessingSettings) {
+ RArray<TUid> suppTransforms;
+ TRAPD(err, m_imageProcessingSettings->GetSupportedTransformationsL(suppTransforms));
+ if (err)
+ if (err != KErrNotSupported)
+ emit error(QCamera::CameraError, tr("Failure while querying supported transformations."));
+
+ if (suppTransforms.Find(KUidECamEventtImageProcessingAdjustSaturation))
+ return m_imageProcessingSettings->TransformationValue(KUidECamEventtImageProcessingAdjustSaturation);
+ }
+ return 0;
+#else // S60 3.1 Platform
+ return 0;
+#endif // POST_31_PLATFORM
+}
+
+// End of file
diff --git a/src/plugins/symbian/ecam/s60camerasettings.h b/src/plugins/symbian/ecam/s60camerasettings.h
new file mode 100644
index 000000000..4ecb131b2
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60camerasettings.h
@@ -0,0 +1,177 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef S60CAMERASETTINGS_H
+#define S60CAMERASETTINGS_H
+
+#include "qcamera.h"
+
+#include "s60cameraengine.h"
+#include "s60cameraengineobserver.h"
+
+#include <e32base.h>
+
+QT_USE_NAMESPACE
+
+/*
+ * Class handling CCamera AdvancedSettings and ImageProcessing operations.
+ */
+class S60CameraSettings : public QObject,
+ public MAdvancedSettingsObserver
+{
+ Q_OBJECT
+
+public: // Static Contructor & Destructor
+
+ static S60CameraSettings* New(int &error, QObject *parent = 0, CCameraEngine *engine = 0);
+ ~S60CameraSettings();
+
+public: // Methods
+
+ // Focus
+ QCameraFocus::FocusMode focusMode();
+ void setFocusMode(QCameraFocus::FocusMode mode);
+ QCameraFocus::FocusModes supportedFocusModes();
+ void startFocusing();
+ void cancelFocusing();
+
+ // Zoom
+ qreal opticalZoomFactorL() const;
+ void setOpticalZoomFactorL(const qreal zoomFactor);
+ QList<qreal> supportedDigitalZoomFactors() const;
+ qreal digitalZoomFactorL() const;
+ void setDigitalZoomFactorL(const qreal zoomFactor);
+
+ // Flash
+ bool isFlashReady();
+
+ // Exposure
+ void setExposureMode(QCameraExposure::ExposureMode mode);
+ void lockExposure(bool lock);
+ bool isExposureLocked();
+
+ // Metering Mode
+ QCameraExposure::MeteringMode meteringMode();
+ void setMeteringMode(QCameraExposure::MeteringMode mode);
+ bool isMeteringModeSupported(QCameraExposure::MeteringMode mode);
+
+ // ISO Sensitivity
+ int isoSensitivity();
+ void setManualIsoSensitivity(int iso);
+ void setAutoIsoSensitivity();
+ QList<int> supportedIsoSensitivities();
+
+ // Aperture
+ qreal aperture();
+ void setManualAperture(qreal aperture);
+ QList<qreal> supportedApertures();
+
+ // Shutter Speed
+ qreal shutterSpeed();
+ void setManualShutterSpeed(qreal speed);
+ QList<qreal> supportedShutterSpeeds();
+
+ // ExposureCompensation
+ qreal exposureCompensation();
+ void setExposureCompensation(qreal ev);
+ QList<qreal> supportedExposureCompensationValues();
+
+ // Sharpening Level
+ int sharpeningLevel() const;
+ void setSharpeningLevel(int value);
+ bool isSharpeningSupported() const;
+
+ // Saturation
+ int saturation();
+ void setSaturation(int value);
+
+signals: // Notifications
+
+ // For QCameraExposureControl
+ void flashReady(bool ready);
+ void apertureChanged();
+ void apertureRangeChanged();
+ void shutterSpeedChanged();
+ void isoSensitivityChanged();
+ void evChanged();
+
+ // For QCameraLocksControl
+ void exposureStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason);
+ void focusStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason);
+
+ // Errors
+ void error(int, const QString&);
+
+protected: // Protected constructors
+
+ S60CameraSettings(QObject *parent, CCameraEngine *engine);
+ void ConstructL();
+
+protected: // MAdvancedSettingsObserver
+
+ void HandleAdvancedEvent(const TECAMEvent& aEvent);
+
+private: // Internal
+
+ bool queryAdvancedSettingsInfo();
+
+private: // Enums
+
+ enum EcamErrors {
+ KErrECamCameraDisabled = -12100, // The camera has been disabled, hence calls do not succeed
+ KErrECamSettingDisabled = -12101, // This parameter or operation is supported, but presently is disabled.
+ KErrECamParameterNotInRange = -12102, // This value is out of range.
+ KErrECamSettingNotSupported = -12103, // This parameter or operation is not supported.
+ KErrECamNotOptimalFocus = -12104 // The optimum focus is lost
+ };
+
+private: // Data
+
+#ifndef S60_31_PLATFORM // Post S60 3.1 Platforms
+ CCamera::CCameraAdvancedSettings *m_advancedSettings;
+ CCamera::CCameraImageProcessing *m_imageProcessingSettings;
+#endif // S60_31_PLATFORM
+ CCameraEngine *m_cameraEngine;
+ QList<int> m_supportedSymbianDigitalZoomFactors;
+ bool m_continuousFocusing;
+};
+
+#endif // S60CAMERASETTINGS_H
diff --git a/src/plugins/symbian/ecam/s60cameraviewfinderengine.cpp b/src/plugins/symbian/ecam/s60cameraviewfinderengine.cpp
new file mode 100644
index 000000000..55d7cbc67
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameraviewfinderengine.cpp
@@ -0,0 +1,789 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QApplication>
+#include <QDesktopWidget>
+#include <qcamera.h>
+#include <qabstractvideosurface.h>
+#include <qvideoframe.h>
+
+#include "s60cameraviewfinderengine.h"
+#include "s60cameraengine.h"
+#include "s60cameracontrol.h"
+#include "s60videowidgetcontrol.h"
+#include "s60videowidgetdisplay.h"
+#include "s60videorenderercontrol.h"
+#include "s60videowindowcontrol.h"
+#include "s60videowindowdisplay.h"
+#include "s60cameraconstants.h"
+
+#include <coemain.h> // CCoeEnv
+#include <coecntrl.h> // CCoeControl
+#include <w32std.h>
+
+// Helper function
+TRect qRect2TRect(const QRect &qr)
+{
+ return TRect(TPoint(qr.left(), qr.top()), TSize(qr.width(), qr.height()));
+}
+
+
+S60CameraViewfinderEngine::S60CameraViewfinderEngine(S60CameraControl *control,
+ CCameraEngine *engine,
+ QObject *parent):
+ QObject(parent),
+ m_cameraEngine(engine),
+ m_cameraControl(0),
+ m_viewfinderOutput(0),
+ m_viewfinderDisplay(0),
+ m_viewfinderSurface(0),
+ m_wsSession(CCoeEnv::Static()->WsSession()),
+ m_screenDevice(*CCoeEnv::Static()->ScreenDevice()),
+ m_window(0),
+ m_desktopWidget(0),
+ m_vfState(EVFNotConnectedNotStarted),
+ m_viewfinderSize(KDefaultViewfinderSize),
+ m_actualViewFinderSize(KDefaultViewfinderSize),
+ m_viewfinderAspectRatio(0.0),
+ m_viewfinderType(OutputTypeNotSet),
+ m_viewfinderNativeType(EBitmapViewFinder), // Default type
+ m_isViewFinderVisible(true), // True by default (only QVideoWidgetControl supports being hidden)
+ m_uiLandscape(true),
+ m_vfErrorsSignalled(0)
+{
+ m_cameraControl = control;
+
+ // Check whether platform supports DirectScreen ViewFinder
+ if (m_cameraEngine) {
+ if (m_cameraEngine->IsDirectViewFinderSupported())
+ m_viewfinderNativeType = EDirectScreenViewFinder;
+ else
+ m_viewfinderNativeType = EBitmapViewFinder;
+
+ MCameraViewfinderObserver *vfObserver = this;
+ m_cameraEngine->SetViewfinderObserver(vfObserver);
+ }
+ else
+ m_cameraControl->setError(KErrGeneral, tr("Unexpected camera error."));
+ // From now on it is safe to assume engine exists
+
+ // Check the UI orientation
+ QDesktopWidget* desktopWidget = QApplication::desktop();
+ QRect screenRect = desktopWidget->screenGeometry();
+ if (screenRect.width() > screenRect.height())
+ m_uiLandscape = true;
+ else
+ m_uiLandscape = false;
+
+ // Detect UI Rotations
+ m_desktopWidget = QApplication::desktop();
+ if (m_desktopWidget)
+ connect(m_desktopWidget, SIGNAL(resized(int)), this, SLOT(handleDesktopResize(int)));
+}
+
+S60CameraViewfinderEngine::~S60CameraViewfinderEngine()
+{
+ // No need to stop viewfinder:
+ // Engine has stopped it already
+ // Surface will be stopped by VideoRendererControl
+
+ m_viewfinderOutput = 0;
+ m_viewfinderSurface = 0;
+}
+
+void S60CameraViewfinderEngine::setNewCameraEngine(CCameraEngine *engine)
+{
+ m_cameraEngine = engine;
+
+ if (m_cameraEngine) {
+ // And set observer to the new CameraEngine
+ MCameraViewfinderObserver *vfObserver = this;
+ m_cameraEngine->SetViewfinderObserver(vfObserver);
+ }
+}
+
+void S60CameraViewfinderEngine::handleDesktopResize(int screen)
+{
+ Q_UNUSED(screen);
+ // UI Rotation is handled by the QVideoWidgetControl, thus this is needed
+ // only for the QVideoRendererControl
+ if (m_viewfinderType == OutputTypeRenderer) {
+ QSize newResolution(-1,-1);
+ if (m_viewfinderSurface)
+ newResolution = m_viewfinderSurface->nativeResolution();
+
+ if (newResolution.width() == -1 || newResolution.height() == -1) {
+ QDesktopWidget* desktopWidget = QApplication::desktop();
+ QRect screenRect = desktopWidget->screenGeometry();
+ newResolution = QSize(screenRect.width(), screenRect.height());
+ }
+
+ resetViewfinderSize(newResolution);
+ }
+
+ // Rotate Camera if UI has rotated
+ checkAndRotateCamera();
+}
+
+void S60CameraViewfinderEngine::setVideoWidgetControl(QObject *viewfinderOutput)
+{
+ // Release old control if it has not already been done
+ if (m_viewfinderOutput)
+ releaseControl(m_viewfinderType);
+
+ // Rotate Camera if UI has rotated
+ checkAndRotateCamera();
+
+ S60VideoWidgetControl* viewFinderWidgetControl =
+ qobject_cast<S60VideoWidgetControl*>(viewfinderOutput);
+
+ if (viewFinderWidgetControl) {
+ // Check whether platform supports DirectScreen ViewFinder
+ if (m_cameraEngine) {
+ if (m_cameraEngine->IsDirectViewFinderSupported())
+ m_viewfinderNativeType = EDirectScreenViewFinder;
+ else
+ m_viewfinderNativeType = EBitmapViewFinder;
+ }
+ else
+ return;
+
+ m_viewfinderDisplay = viewFinderWidgetControl->display();
+
+ if (m_viewfinderNativeType == EDirectScreenViewFinder) {
+ m_viewfinderDisplay->setPaintingEnabled(false); // No Qt Painter painting - Direct rendering
+ connect(m_viewfinderDisplay, SIGNAL(windowHandleChanged(RWindow *)), this, SLOT(resetViewfinderDisplay()));
+ } else {
+ m_viewfinderDisplay->setPaintingEnabled(true); // Qt Painter painting - Bitmap rendering
+ connect(this, SIGNAL(viewFinderFrameReady(const CFbsBitmap &)), m_viewfinderDisplay, SLOT(setFrame(const CFbsBitmap &)));
+ }
+
+ connect(m_viewfinderDisplay, SIGNAL(visibilityChanged(bool)), this, SLOT(handleVisibilityChange(bool)));
+ connect(m_viewfinderDisplay, SIGNAL(displayRectChanged(QRect, QRect)), this, SLOT(resetVideoWindowSize()));
+ connect(m_viewfinderDisplay, SIGNAL(windowHandleChanged(RWindow*)), this, SLOT(handleWindowChange(RWindow*)));
+
+ m_viewfinderSize = m_viewfinderDisplay->extentRect().size();
+ m_viewfinderOutput = viewfinderOutput;
+ m_viewfinderType = OutputTypeVideoWidget;
+ m_isViewFinderVisible = m_viewfinderDisplay->isVisible();
+
+ switch (m_vfState) {
+ case EVFNotConnectedNotStarted:
+ m_vfState = EVFIsConnectedNotStarted;
+ break;
+ case EVFNotConnectedIsStarted:
+ if (m_isViewFinderVisible)
+ m_vfState = EVFIsConnectedIsStartedIsVisible;
+ else
+ m_vfState = EVFIsConnectedIsStartedNotVisible;
+ break;
+ case EVFIsConnectedNotStarted:
+ case EVFIsConnectedIsStartedNotVisible:
+ case EVFIsConnectedIsStartedIsVisible:
+ // Already connected, state does not change
+ break;
+ default:
+ emit error(QCamera::CameraError, tr("General viewfinder error."));
+ break;
+ }
+
+ if (m_vfState == EVFIsConnectedIsStartedIsVisible)
+ startViewfinder(true); // Internal start (i.e. start if started externally)
+ }
+}
+
+void S60CameraViewfinderEngine::setVideoRendererControl(QObject *viewfinderOutput)
+{
+ // Release old control if it has not already been done
+ if (m_viewfinderOutput)
+ releaseControl(m_viewfinderType);
+
+ // Rotate Camera if UI has rotated
+ checkAndRotateCamera();
+
+ S60VideoRendererControl* viewFinderRenderControl =
+ qobject_cast<S60VideoRendererControl*>(viewfinderOutput);
+
+ if (viewFinderRenderControl) {
+ m_viewfinderNativeType = EBitmapViewFinder; // Always Bitmap
+
+ connect(viewFinderRenderControl, SIGNAL(viewFinderSurfaceSet()),
+ this, SLOT(rendererSurfaceSet()));
+
+ Q_ASSERT(!viewFinderRenderControl->surface());
+ m_viewfinderOutput = viewfinderOutput;
+ m_viewfinderType = OutputTypeRenderer;
+ // RendererControl viewfinder is "visible" when surface is set
+ m_isViewFinderVisible = false;
+ if (EVFIsConnectedIsStartedIsVisible)
+ m_vfState = EVFIsConnectedIsStartedNotVisible;
+
+ // Use display resolution as default viewfinder resolution
+ m_viewfinderSize = QApplication::desktop()->screenGeometry().size();
+
+ switch (m_vfState) {
+ case EVFNotConnectedNotStarted:
+ m_vfState = EVFIsConnectedNotStarted;
+ break;
+ case EVFNotConnectedIsStarted:
+ m_vfState = EVFIsConnectedIsStartedIsVisible; // GraphicsItem "always visible" (FrameWork decides to draw/not draw)
+ break;
+ case EVFIsConnectedNotStarted:
+ case EVFIsConnectedIsStartedNotVisible:
+ case EVFIsConnectedIsStartedIsVisible:
+ // Already connected, state does not change
+ break;
+ default:
+ emit error(QCamera::CameraError, tr("General viewfinder error."));
+ break;
+ }
+
+ if (m_vfState == EVFIsConnectedIsStartedIsVisible)
+ startViewfinder(true);
+ }
+}
+
+void S60CameraViewfinderEngine::setVideoWindowControl(QObject *viewfinderOutput)
+{
+ // Release old control if it has not already been done
+ if (m_viewfinderOutput)
+ releaseControl(m_viewfinderType);
+
+ // Rotate Camera if UI has rotated
+ checkAndRotateCamera();
+
+ S60VideoWindowControl* viewFinderWindowControl =
+ qobject_cast<S60VideoWindowControl*>(viewfinderOutput);
+
+ if (viewFinderWindowControl) {
+ // Check whether platform supports DirectScreen ViewFinder
+ if (m_cameraEngine) {
+ if (m_cameraEngine->IsDirectViewFinderSupported())
+ m_viewfinderNativeType = EDirectScreenViewFinder;
+ else
+ m_viewfinderNativeType = EBitmapViewFinder;
+ } else {
+ return;
+ }
+
+ m_viewfinderDisplay = viewFinderWindowControl->display();
+
+ if (m_viewfinderNativeType == EDirectScreenViewFinder) {
+ m_viewfinderDisplay->setPaintingEnabled(false); // No Qt Painter painting - Direct rendering
+ connect(m_viewfinderDisplay, SIGNAL(windowHandleChanged(RWindow *)), this, SLOT(resetViewfinderDisplay()));
+ } else {
+ m_viewfinderDisplay->setPaintingEnabled(true); // Qt Painter painting - Bitmap rendering
+ connect(this, SIGNAL(viewFinderFrameReady(const CFbsBitmap &)), m_viewfinderDisplay, SLOT(setFrame(const CFbsBitmap &)));
+ }
+
+ connect(m_viewfinderDisplay, SIGNAL(displayRectChanged(QRect, QRect)), this, SLOT(resetVideoWindowSize()));
+ connect(m_viewfinderDisplay, SIGNAL(visibilityChanged(bool)), this, SLOT(handleVisibilityChange(bool)));
+ connect(m_viewfinderDisplay, SIGNAL(windowHandleChanged(RWindow*)), this, SLOT(handleWindowChange(RWindow*)));
+
+ m_viewfinderSize = m_viewfinderDisplay->extentRect().size();
+ m_viewfinderOutput = viewfinderOutput;
+ m_viewfinderType = OutputTypeVideoWindow;
+ m_isViewFinderVisible = m_viewfinderDisplay->isVisible();
+
+ switch (m_vfState) {
+ case EVFNotConnectedNotStarted:
+ m_vfState = EVFIsConnectedNotStarted;
+ break;
+ case EVFNotConnectedIsStarted:
+ if (m_isViewFinderVisible)
+ m_vfState = EVFIsConnectedIsStartedIsVisible;
+ else
+ m_vfState = EVFIsConnectedIsStartedNotVisible;
+ break;
+ case EVFIsConnectedNotStarted:
+ case EVFIsConnectedIsStartedNotVisible:
+ case EVFIsConnectedIsStartedIsVisible:
+ // Already connected, state does not change
+ break;
+ default:
+ emit error(QCamera::CameraError, tr("General viewfinder error."));
+ break;
+ }
+
+ if (m_vfState == EVFIsConnectedIsStartedIsVisible)
+ startViewfinder(true); // Internal start (i.e. start if started externally)
+ }
+}
+
+void S60CameraViewfinderEngine::releaseControl(ViewfinderOutputType type)
+{
+ if (m_vfState == EVFIsConnectedIsStartedIsVisible)
+ stopViewfinder(true);
+
+ if (m_viewfinderOutput) {
+ switch (type) {
+ case OutputTypeNotSet:
+ return;
+ case OutputTypeVideoWidget:
+ if (m_viewfinderType != OutputTypeVideoWidget)
+ return;
+ disconnect(m_viewfinderOutput);
+ m_viewfinderOutput->disconnect(this);
+ Q_ASSERT(m_viewfinderDisplay);
+ disconnect(m_viewfinderDisplay);
+ m_viewfinderDisplay->disconnect(this);
+ m_viewfinderDisplay = 0;
+ // Invalidate the extent rect
+ qobject_cast<S60VideoWidgetControl*>(m_viewfinderOutput)->setExtentRect(QRect());
+ break;
+ case OutputTypeVideoWindow:
+ if (m_viewfinderType != OutputTypeVideoWindow)
+ return;
+ disconnect(m_viewfinderOutput);
+ m_viewfinderOutput->disconnect(this);
+ Q_ASSERT(m_viewfinderDisplay);
+ disconnect(m_viewfinderDisplay);
+ m_viewfinderDisplay->disconnect(this);
+ m_viewfinderDisplay = 0;
+ break;
+ case OutputTypeRenderer:
+ if (m_viewfinderType != OutputTypeRenderer)
+ return;
+ disconnect(m_viewfinderOutput);
+ m_viewfinderOutput->disconnect(this);
+ if (m_viewfinderSurface)
+ m_viewfinderSurface->disconnect(this);
+ disconnect(this, SIGNAL(viewFinderFrameReady(const CFbsBitmap &)),
+ this, SLOT(viewFinderBitmapReady(const CFbsBitmap &)));
+ break;
+ default:
+ emit error(QCamera::CameraError, tr("Unexpected viewfinder error."));
+ return;
+ }
+ }
+
+ Q_ASSERT(!m_viewfinderDisplay);
+ m_viewfinderOutput = 0;
+ m_viewfinderType = OutputTypeNotSet;
+
+ // Update state
+ switch (m_vfState) {
+ case EVFNotConnectedNotStarted:
+ case EVFNotConnectedIsStarted:
+ // Do nothing
+ break;
+ case EVFIsConnectedNotStarted:
+ m_vfState = EVFNotConnectedNotStarted;
+ break;
+ case EVFIsConnectedIsStartedNotVisible:
+ case EVFIsConnectedIsStartedIsVisible:
+ m_vfState = EVFNotConnectedIsStarted;
+ break;
+ default:
+ emit error(QCamera::CameraError, tr("General viewfinder error."));
+ break;
+ }
+}
+
+void S60CameraViewfinderEngine::startViewfinder(const bool internalStart)
+{
+ if (!internalStart) {
+ switch (m_vfState) {
+ case EVFNotConnectedNotStarted:
+ m_vfState = EVFNotConnectedIsStarted;
+ break;
+ case EVFIsConnectedNotStarted:
+ if (m_isViewFinderVisible)
+ m_vfState = EVFIsConnectedIsStartedIsVisible;
+ else
+ m_vfState = EVFIsConnectedIsStartedNotVisible;
+ break;
+ case EVFNotConnectedIsStarted:
+ case EVFIsConnectedIsStartedNotVisible:
+ case EVFIsConnectedIsStartedIsVisible:
+ // Already started, state does not change
+ break;
+ default:
+ emit error(QCamera::CameraError, tr("General viewfinder error."));
+ break;
+ }
+ }
+
+ // Start viewfinder
+ if (m_vfState == EVFIsConnectedIsStartedIsVisible) {
+
+ if (!m_cameraEngine)
+ return;
+
+ if (m_viewfinderNativeType == EDirectScreenViewFinder) {
+
+ if (RWindow *window = m_viewfinderDisplay ? m_viewfinderDisplay->windowHandle() : 0) {
+ m_window = window;
+ } else {
+ emit error(QCamera::CameraError, tr("Requesting window for viewfinder failed."));
+ return;
+ }
+
+ const QRect extentRect = m_viewfinderDisplay ? m_viewfinderDisplay->extentRect() : QRect();
+ const QRect clipRect = m_viewfinderDisplay ? m_viewfinderDisplay->clipRect() : QRect();
+
+ TRect extentRectSymbian = qRect2TRect(extentRect);
+ TRect clipRectSymbian = qRect2TRect(clipRect);
+ TRAPD(err, m_cameraEngine->StartDirectViewFinderL(m_wsSession, m_screenDevice, *m_window, extentRectSymbian, clipRectSymbian));
+ if (err) {
+ if (err == KErrNotSupported) {
+ emit error(QCamera::NotSupportedFeatureError, tr("Requested viewfinder size is not supported."));
+ } else {
+ emit error(QCamera::CameraError, tr("Starting viewfinder failed."));
+ }
+ return;
+ }
+
+ m_actualViewFinderSize = QSize(extentRectSymbian.Size().iWidth, extentRectSymbian.Size().iHeight);
+ m_viewfinderAspectRatio = qreal(m_actualViewFinderSize.width()) / qreal(m_actualViewFinderSize.height());
+
+ } else { // Bitmap ViewFinder
+ TSize size = TSize(m_viewfinderSize.width(), m_viewfinderSize.height());
+
+ if( m_viewfinderType == OutputTypeRenderer && m_viewfinderSurface) {
+ if (!m_surfaceFormat.isValid()) {
+ emit error(QCamera::NotSupportedFeatureError, tr("Invalid surface format."));
+ return;
+ }
+
+ // Start rendering to surface with correct size and format
+ if (!m_viewfinderSurface->isFormatSupported(m_surfaceFormat) ||
+ !m_viewfinderSurface->start(m_surfaceFormat)) {
+ emit error(QCamera::NotSupportedFeatureError, tr("Failed to start surface."));
+ return;
+ }
+
+ if (!m_viewfinderSurface->isActive())
+ return;
+ }
+
+ TRAPD(vfErr, m_cameraEngine->StartViewFinderL(size));
+ if (vfErr) {
+ if (vfErr == KErrNotSupported) {
+ emit error(QCamera::NotSupportedFeatureError, tr("Requested viewfinder size is not supported."));
+ } else {
+ emit error(QCamera::CameraError, tr("Starting viewfinder failed."));
+ }
+ return;
+ }
+
+ m_actualViewFinderSize = QSize(size.iWidth, size.iHeight);
+ m_viewfinderAspectRatio = qreal(m_actualViewFinderSize.width()) / qreal(m_actualViewFinderSize.height());
+
+ // Notify control about the frame size (triggers frame position calculation)
+ if (m_viewfinderDisplay) {
+ m_viewfinderDisplay->setNativeSize(m_actualViewFinderSize);
+ } else {
+ if (m_viewfinderType == OutputTypeRenderer && m_viewfinderSurface) {
+ m_viewfinderSurface->stop();
+ QVideoSurfaceFormat format = m_viewfinderSurface->surfaceFormat();
+ format.setFrameSize(QSize(m_actualViewFinderSize));
+ format.setViewport(QRect(0, 0, m_actualViewFinderSize.width(), m_actualViewFinderSize.height()));
+ m_viewfinderSurface->start(format);
+ }
+ }
+ }
+ }
+}
+
+void S60CameraViewfinderEngine::stopViewfinder(const bool internalStop)
+{
+ // Stop if viewfinder is started
+ if (m_vfState == EVFIsConnectedIsStartedIsVisible) {
+ if (m_viewfinderOutput && m_viewfinderType == OutputTypeRenderer && m_viewfinderSurface) {
+ // Stop surface if one still exists
+ m_viewfinderSurface->stop();
+ }
+
+ if (m_cameraEngine)
+ m_cameraEngine->StopViewFinder();
+ }
+
+ // Update state
+ if (!internalStop) {
+ switch (m_vfState) {
+ case EVFNotConnectedNotStarted:
+ case EVFIsConnectedNotStarted:
+ // Discard
+ break;
+ case EVFNotConnectedIsStarted:
+ m_vfState = EVFNotConnectedNotStarted;
+ break;
+ case EVFIsConnectedIsStartedNotVisible:
+ case EVFIsConnectedIsStartedIsVisible:
+ m_vfState = EVFIsConnectedNotStarted;
+ break;
+ default:
+ emit error(QCamera::CameraError, tr("General viewfinder error."));
+ break;
+ }
+ }
+}
+
+void S60CameraViewfinderEngine::MceoViewFinderFrameReady(CFbsBitmap& aFrame)
+{
+ emit viewFinderFrameReady(aFrame);
+ if (m_cameraEngine)
+ m_cameraEngine->ReleaseViewFinderBuffer();
+}
+
+void S60CameraViewfinderEngine::resetViewfinderSize(const QSize size)
+{
+ m_viewfinderSize = size;
+
+ if(m_vfState != EVFIsConnectedIsStartedIsVisible) {
+ // Set native size to Window/Renderer Control
+ if (m_viewfinderDisplay)
+ m_viewfinderDisplay->setNativeSize(m_actualViewFinderSize);
+ return;
+ }
+
+ stopViewfinder(true);
+
+ startViewfinder(true);
+}
+
+void S60CameraViewfinderEngine::resetVideoWindowSize()
+{
+ if (m_viewfinderDisplay)
+ resetViewfinderSize(m_viewfinderDisplay->extentRect().size());
+}
+
+void S60CameraViewfinderEngine::resetViewfinderDisplay()
+{
+ if (m_viewfinderNativeType == EDirectScreenViewFinder) {
+
+ switch (m_viewfinderType) {
+ case OutputTypeVideoWidget: {
+ if (!m_viewfinderOutput)
+ return;
+
+ // First stop viewfinder
+ stopViewfinder(true);
+
+ RWindow *window = m_viewfinderDisplay->windowHandle();
+ if (!window) {
+ return;
+ }
+
+ // Then start it with the new WindowID
+ startViewfinder(true);
+ break;
+ }
+ case OutputTypeRenderer:
+ case OutputTypeVideoWindow:
+ // Do nothing
+ break;
+
+ default:
+ // Not ViewFinder Output has been set, Discard
+ break;
+ }
+ }
+}
+
+void S60CameraViewfinderEngine::rendererSurfaceSet()
+{
+ S60VideoRendererControl* viewFinderRenderControl =
+ qobject_cast<S60VideoRendererControl*>(m_viewfinderOutput);
+
+ // Reset old surface if needed
+ if (m_viewfinderSurface) {
+ handleVisibilityChange(false);
+ disconnect(m_viewfinderSurface);
+ if (viewFinderRenderControl->surface())
+ stopViewfinder(true); // Temporary stop
+ else
+ stopViewfinder(); // Stop for good
+ m_viewfinderSize = QApplication::desktop()->screenGeometry().size();
+ m_viewfinderSurface = 0;
+ }
+
+ // Set new surface
+ m_viewfinderSurface = viewFinderRenderControl->surface();
+ if (!m_viewfinderSurface)
+ return;
+ if (!m_viewfinderSurface->nativeResolution().isEmpty()) {
+ if (m_viewfinderSurface->nativeResolution() != m_viewfinderSize)
+ resetViewfinderSize(m_viewfinderSurface->nativeResolution());
+ }
+
+ connect(m_viewfinderSurface, SIGNAL(nativeResolutionChanged(const QSize&)),
+ this, SLOT(resetViewfinderSize(QSize)));
+
+ // Set Surface Properties
+ if (m_viewfinderSurface->supportedPixelFormats().contains(QVideoFrame::Format_RGB32))
+ m_surfaceFormat = QVideoSurfaceFormat(m_actualViewFinderSize, QVideoFrame::Format_RGB32);
+ else if (m_viewfinderSurface->supportedPixelFormats().contains(QVideoFrame::Format_ARGB32))
+ m_surfaceFormat = QVideoSurfaceFormat(m_actualViewFinderSize, QVideoFrame::Format_ARGB32);
+ else {
+ return;
+ }
+ m_surfaceFormat.setFrameRate(KViewfinderFrameRate);
+ m_surfaceFormat.setYCbCrColorSpace(QVideoSurfaceFormat::YCbCr_Undefined); // EColor16MU (compatible with EColor16MA)
+ m_surfaceFormat.setPixelAspectRatio(1,1); // PAR 1:1
+
+
+ connect(this, SIGNAL(viewFinderFrameReady(const CFbsBitmap &)),
+ this, SLOT(viewFinderBitmapReady(const CFbsBitmap &)));
+
+ // Surface set, viewfinder is "visible"
+ handleVisibilityChange(true);
+}
+
+void S60CameraViewfinderEngine::viewFinderBitmapReady(const CFbsBitmap &bitmap)
+{
+ CFbsBitmap *bitmapPtr = const_cast<CFbsBitmap*>(&bitmap);
+ QPixmap pixmap = QPixmap::fromSymbianCFbsBitmap(bitmapPtr);
+
+ QImage newImage = pixmap.toImage();
+ if (newImage.format() != QImage::Format_ARGB32 &&
+ newImage.format() != QImage::Format_RGB32) {
+ newImage = newImage.convertToFormat(QImage::Format_RGB32);
+ }
+
+ if (!newImage.isNull()) {
+ QVideoFrame newFrame(newImage);
+ if (newFrame.isValid()) {
+ if (!m_viewfinderSurface->present(newFrame)) {
+ // Presenting may fail even if there are no errors (e.g. busy)
+ if (m_viewfinderSurface->error()) {
+ if (m_vfErrorsSignalled < KMaxVFErrorsSignalled) {
+ emit error(QCamera::CameraError, tr("Presenting viewfinder frame failed."));
+ ++m_vfErrorsSignalled;
+ }
+ }
+ }
+ } else {
+ if (m_vfErrorsSignalled < KMaxVFErrorsSignalled) {
+ emit error(QCamera::CameraError, tr("Invalid viewfinder frame was received."));
+ ++m_vfErrorsSignalled;
+ }
+ }
+
+ } else {
+ if (m_vfErrorsSignalled < KMaxVFErrorsSignalled) {
+ emit error(QCamera::CameraError, tr("Failed to convert viewfinder frame to presentable image."));
+ ++m_vfErrorsSignalled;
+ }
+ }
+}
+
+void S60CameraViewfinderEngine::handleVisibilityChange(const bool isVisible)
+{
+ if (m_isViewFinderVisible == isVisible)
+ return;
+
+ m_isViewFinderVisible = isVisible;
+
+ if (m_isViewFinderVisible) {
+ switch (m_vfState) {
+ case EVFNotConnectedNotStarted:
+ case EVFIsConnectedNotStarted:
+ case EVFNotConnectedIsStarted:
+ case EVFIsConnectedIsStartedIsVisible:
+ // Discard
+ break;
+ case EVFIsConnectedIsStartedNotVisible:
+ m_vfState = EVFIsConnectedIsStartedIsVisible;
+ break;
+ default:
+ emit error(QCamera::CameraError, tr("General viewfinder error."));
+ break;
+ }
+ startViewfinder(true);
+ } else {
+ // Stopping takes care of the state change
+ stopViewfinder(true);
+ }
+}
+
+void S60CameraViewfinderEngine::handleWindowChange(RWindow *handle)
+{
+ stopViewfinder(true);
+
+ if (handle) // New handle available, start viewfinder
+ startViewfinder(true);
+}
+
+void S60CameraViewfinderEngine::checkAndRotateCamera()
+{
+ bool isUiNowLandscape = false;
+ QDesktopWidget* desktopWidget = QApplication::desktop();
+ QRect screenRect = desktopWidget->screenGeometry();
+
+ if (screenRect.width() > screenRect.height())
+ isUiNowLandscape = true;
+ else
+ isUiNowLandscape = false;
+
+ // Rotate camera if possible
+ if (isUiNowLandscape != m_uiLandscape) {
+ stopViewfinder(true);
+
+ // Request orientation reset
+ m_cameraControl->resetCameraOrientation();
+ }
+ m_uiLandscape = isUiNowLandscape;
+}
+
+void S60CameraViewfinderEngine::handleContentAspectRatioChange(const QSize& newSize)
+{
+ qreal newAspectRatio = qreal(newSize.width()) / qreal(newSize.height());
+ // Check if aspect ratio changed
+ if (qFuzzyCompare(newAspectRatio, m_viewfinderAspectRatio))
+ return;
+
+ // Resize viewfinder by reducing either width or height to comply with the new aspect ratio
+ QSize newNativeResolution;
+ if (newAspectRatio > m_viewfinderAspectRatio) { // New AspectRatio is wider => Reduce height
+ newNativeResolution = QSize(m_actualViewFinderSize.width(), (m_actualViewFinderSize.width() / newAspectRatio));
+ } else { // New AspectRatio is higher => Reduce width
+ newNativeResolution = QSize((m_actualViewFinderSize.height() * newAspectRatio), m_actualViewFinderSize.height());
+ }
+
+ // Notify aspect ratio change (use actual content size to notify that)
+ // This triggers item size/position re-calculation
+ if (m_viewfinderDisplay)
+ m_viewfinderDisplay->setNativeSize(newNativeResolution);
+}
+
+// End of file
diff --git a/src/plugins/symbian/ecam/s60cameraviewfinderengine.h b/src/plugins/symbian/ecam/s60cameraviewfinderengine.h
new file mode 100644
index 000000000..c5df760d9
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameraviewfinderengine.h
@@ -0,0 +1,182 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef S60CAMERAVIEWFINDERENGINE_H
+#define S60CAMERAVIEWFINDERENGINE_H
+
+#include <QtCore/qsize.h>
+#include <QtGui/qpixmap.h>
+
+#include <qvideosurfaceformat.h>
+
+#include "s60cameraengineobserver.h"
+
+class CCameraEngine;
+class S60CameraControl;
+class QAbstractVideoSurface;
+
+// For DirectScreen ViewFinder
+class RWsSession;
+class CWsScreenDevice;
+class RWindowBase;
+class RWindow;
+class QDesktopWidget;
+
+class S60VideoDisplay;
+
+/*
+ * Class implementing video output selection for the viewfinder and the handler of
+ * all common viewfinder operations.
+ */
+class S60CameraViewfinderEngine : public QObject, public MCameraViewfinderObserver
+{
+ Q_OBJECT
+
+public: // Enums
+
+ /*
+ * Defines whether viewfinder output backend control is of type
+ * QVideoWidgetControl, QVideoRendererControl or QVideoWindowControl
+ */
+ enum ViewfinderOutputType {
+ OutputTypeNotSet = 0, // No viewfinder output connected
+ OutputTypeVideoWidget, // Using QVideoWidget
+ OutputTypeRenderer, // (Using QGraphicsVideoItem with) QVideoRendererControl
+ OutputTypeVideoWindow // Using QGraphicsVideoItem with QVideoWindow
+ };
+
+public: // Constructor & Destructor
+
+ S60CameraViewfinderEngine(S60CameraControl *control,
+ CCameraEngine *engine,
+ QObject *parent = 0);
+ ~S60CameraViewfinderEngine();
+
+public: // Methods
+
+ // Setting Viewfinder Output
+ void setVideoWidgetControl(QObject *viewfinderOutput);
+ void setVideoRendererControl(QObject *viewfinderOutput);
+ void setVideoWindowControl(QObject *viewfinderOutput);
+ void releaseControl(ViewfinderOutputType type);
+
+ // Controls
+ void startViewfinder(const bool internalStart = false);
+ void stopViewfinder(const bool internalStop = false);
+
+ // Start using new CameraEngine
+ void setNewCameraEngine(CCameraEngine *engine);
+
+protected: // MCameraViewfinderObserver
+
+ void MceoViewFinderFrameReady(CFbsBitmap& aFrame);
+
+private: // Internal operation
+
+ void checkAndRotateCamera();
+
+signals:
+
+ void error(int error, const QString &errorString);
+ void viewFinderFrameReady(const CFbsBitmap &bitmap);
+
+private slots:
+
+ void resetViewfinderSize(const QSize size);
+ void resetVideoWindowSize();
+ void resetViewfinderDisplay();
+ void viewFinderBitmapReady(const CFbsBitmap &bitmap);
+ void handleVisibilityChange(const bool isVisible);
+ void handleWindowChange(RWindow *handle);
+ void handleDesktopResize(int screen);
+ void handleContentAspectRatioChange(const QSize& newSize);
+ void rendererSurfaceSet();
+
+private: // Enums
+
+ /*
+ * Defines the internal state of the viewfinder. ViewFinder will only be
+ * started if output is connected to Camera and Camera is started (and
+ * ViewFinder widget is visible in case of QVideoWidget).
+ */
+ enum ViewFinderState {
+ EVFNotConnectedNotStarted = 0, // 0 - No output connected, viewfinder is not started
+ EVFNotConnectedIsStarted, // 1 - No output connected, viewfinder is started
+ EVFIsConnectedNotStarted, // 2 - Output is connected, viewfinder is not started
+ EVFIsConnectedIsStartedNotVisible, // 3 - Output is connected, viewfinder is started but is not visible
+ EVFIsConnectedIsStartedIsVisible // 4 - Output is connected, viewfinder is started and is visible
+ };
+
+ /*
+ * The native type of ViewFinder. DirectScreen ViewFinder is used with
+ * QVideoWidget if support for it is available in the platform. For
+ * QGraphicsVideoItem Bitmap ViewFinder is always used.
+ */
+ enum NativeViewFinderType {
+ EBitmapViewFinder = 0,
+ EDirectScreenViewFinder
+ };
+
+private: // Data
+
+ CCameraEngine *m_cameraEngine;
+ S60CameraControl *m_cameraControl;
+ QObject *m_viewfinderOutput;
+ S60VideoDisplay *m_viewfinderDisplay;
+ QAbstractVideoSurface *m_viewfinderSurface; // Used only by QVideoRendererControl
+ RWsSession &m_wsSession;
+ CWsScreenDevice &m_screenDevice;
+ RWindowBase *m_window;
+ QDesktopWidget *m_desktopWidget;
+ ViewFinderState m_vfState;
+ QSize m_viewfinderSize;
+ // Actual viewfinder size, which may differ from requested
+ // (m_viewfinderSize), if the size/aspect ratio was not supported.
+ QSize m_actualViewFinderSize;
+ qreal m_viewfinderAspectRatio;
+ ViewfinderOutputType m_viewfinderType;
+ NativeViewFinderType m_viewfinderNativeType;
+ QVideoSurfaceFormat m_surfaceFormat; // Used only by QVideoRendererControl
+ bool m_isViewFinderVisible;
+ bool m_uiLandscape; // For detecting UI rotation
+ int m_vfErrorsSignalled;
+};
+
+#endif // S60CAMERAVIEWFINDERENGINE_H
diff --git a/src/plugins/symbian/ecam/s60imagecapturesession.cpp b/src/plugins/symbian/ecam/s60imagecapturesession.cpp
new file mode 100644
index 000000000..16d240c7b
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60imagecapturesession.cpp
@@ -0,0 +1,1884 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qstring.h>
+#include <QtCore/qdir.h>
+
+#include "s60imagecapturesession.h"
+#include "s60videowidgetcontrol.h"
+#include "s60cameraservice.h"
+#include "s60cameraconstants.h"
+
+#include <fbs.h> // CFbsBitmap
+#include <pathinfo.h>
+#include <imageconversion.h> // ICL Decoder (for SnapShot) & Encoder (for Bitmap Images)
+
+S60ImageCaptureDecoder::S60ImageCaptureDecoder(S60ImageCaptureSession *imageSession,
+ RFs *fileSystemAccess,
+ const TDesC8 *data,
+ const TDesC16 *fileName) :
+ CActive(CActive::EPriorityStandard),
+ m_imageSession(imageSession),
+ m_fs(fileSystemAccess),
+ m_jpegImageData(data),
+ m_jpegImageFile(fileName),
+ m_fileInput(false)
+{
+ CActiveScheduler::Add(this);
+}
+
+S60ImageCaptureDecoder::~S60ImageCaptureDecoder()
+{
+ if (m_imageDecoder) {
+ delete m_imageDecoder;
+ m_imageDecoder = 0;
+ }
+}
+
+S60ImageCaptureDecoder *S60ImageCaptureDecoder::FileNewL(S60ImageCaptureSession *imageSession,
+ RFs *fileSystemAccess,
+ const TDesC16 *fileName)
+{
+ S60ImageCaptureDecoder* self = new (ELeave) S60ImageCaptureDecoder(imageSession,
+ fileSystemAccess,
+ 0,
+ fileName);
+ CleanupStack::PushL(self);
+ self->ConstructL(true);
+ CleanupStack::Pop(self);
+ return self;
+}
+
+S60ImageCaptureDecoder *S60ImageCaptureDecoder::DataNewL(S60ImageCaptureSession *imageSession,
+ RFs *fileSystemAccess,
+ const TDesC8 *data)
+{
+ S60ImageCaptureDecoder* self = new (ELeave) S60ImageCaptureDecoder(imageSession,
+ fileSystemAccess,
+ data,
+ 0);
+ CleanupStack::PushL(self);
+ self->ConstructL(false);
+ CleanupStack::Pop(self);
+ return self;
+}
+
+void S60ImageCaptureDecoder::ConstructL(const bool fileInput)
+{
+ if (fileInput) {
+ if (!m_imageSession || !m_fs || !m_jpegImageFile)
+ User::Leave(KErrGeneral);
+ m_imageDecoder = CImageDecoder::FileNewL(*m_fs, *m_jpegImageFile);
+ } else {
+ if (!m_imageSession || !m_fs || !m_jpegImageData)
+ User::Leave(KErrGeneral);
+ m_imageDecoder = CImageDecoder::DataNewL(*m_fs, *m_jpegImageData);
+ }
+}
+
+void S60ImageCaptureDecoder::decode(CFbsBitmap *destBitmap)
+{
+ if (m_imageDecoder) {
+ m_imageDecoder->Convert(&iStatus, *destBitmap, 0);
+ SetActive();
+ }
+ else
+ m_imageSession->setError(KErrGeneral, QLatin1String("Preview image creation failed."));
+}
+
+TFrameInfo *S60ImageCaptureDecoder::frameInfo()
+{
+ if (m_imageDecoder) {
+ m_frameInfo = m_imageDecoder->FrameInfo();
+ return &m_frameInfo;
+ }
+ else
+ return 0;
+}
+
+void S60ImageCaptureDecoder::RunL()
+{
+ m_imageSession->handleImageDecoded(iStatus.Int());
+}
+
+void S60ImageCaptureDecoder::DoCancel()
+{
+ if (m_imageDecoder)
+ m_imageDecoder->Cancel();
+}
+
+TInt S60ImageCaptureDecoder::RunError(TInt aError)
+{
+ m_imageSession->setError(aError, QLatin1String("Preview image creation failed."));
+ return KErrNone;
+}
+
+//=============================================================================
+
+S60ImageCaptureEncoder::S60ImageCaptureEncoder(S60ImageCaptureSession *imageSession,
+ RFs *fileSystemAccess,
+ const TDesC16 *fileName,
+ TInt jpegQuality) :
+ CActive(CActive::EPriorityStandard),
+ m_imageSession(imageSession),
+ m_fileSystemAccess(fileSystemAccess),
+ m_fileName(fileName),
+ m_jpegQuality(jpegQuality)
+{
+ CActiveScheduler::Add(this);
+}
+
+S60ImageCaptureEncoder::~S60ImageCaptureEncoder()
+{
+ if (m_frameImageData) {
+ delete m_frameImageData;
+ m_frameImageData = 0;
+ }
+ if (m_imageEncoder) {
+ delete m_imageEncoder;
+ m_imageEncoder = 0;
+ }
+}
+
+S60ImageCaptureEncoder *S60ImageCaptureEncoder::NewL(S60ImageCaptureSession *imageSession,
+ RFs *fileSystemAccess,
+ const TDesC16 *fileName,
+ TInt jpegQuality)
+{
+ S60ImageCaptureEncoder* self = new (ELeave) S60ImageCaptureEncoder(imageSession,
+ fileSystemAccess,
+ fileName,
+ jpegQuality);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+}
+
+void S60ImageCaptureEncoder::ConstructL()
+{
+ if (!m_imageSession || !m_fileSystemAccess || !m_fileName)
+ User::Leave(KErrGeneral);
+
+ m_imageEncoder = CImageEncoder::FileNewL(*m_fileSystemAccess,
+ *m_fileName,
+ CImageEncoder::EOptionNone,
+ KImageTypeJPGUid);
+ CleanupStack::PushL(m_imageEncoder);
+
+ // Set Jpeg Quality
+ m_frameImageData = CFrameImageData::NewL();
+ CleanupStack::PushL(m_frameImageData);
+
+ TJpegImageData* jpegFormat = new( ELeave ) TJpegImageData;
+ CleanupStack::PushL(jpegFormat);
+
+ jpegFormat->iQualityFactor = m_jpegQuality;
+
+ // jpegFormat (TJpegImageData) ownership transferred to m_frameImageData (CFrameImageData)
+ User::LeaveIfError( m_frameImageData->AppendImageData(jpegFormat));
+
+ CleanupStack::Pop(jpegFormat);
+ CleanupStack::Pop(m_frameImageData);
+ CleanupStack::Pop(m_imageEncoder);
+}
+
+void S60ImageCaptureEncoder::encode(CFbsBitmap *sourceBitmap)
+{
+ if (m_imageEncoder) {
+ m_imageEncoder->Convert(&iStatus, *sourceBitmap, m_frameImageData);
+ SetActive();
+ }
+ else
+ m_imageSession->setError(KErrGeneral, QLatin1String("Saving image to file failed."));
+}
+
+void S60ImageCaptureEncoder::RunL()
+{
+ m_imageSession->handleImageEncoded(iStatus.Int());
+}
+
+void S60ImageCaptureEncoder::DoCancel()
+{
+ if (m_imageEncoder)
+ m_imageEncoder->Cancel();
+}
+
+TInt S60ImageCaptureEncoder::RunError(TInt aError)
+{
+ m_imageSession->setError(aError, QLatin1String("Saving image to file failed."));
+ return KErrNone;
+}
+
+//=============================================================================
+
+S60ImageCaptureSession::S60ImageCaptureSession(QObject *parent) :
+ QObject(parent),
+ m_cameraEngine(0),
+ m_advancedSettings(0),
+ m_cameraInfo(0),
+ m_previewBitmap(0),
+ m_activeScheduler(0),
+ m_fileSystemAccess(0),
+ m_imageDecoder(0),
+ m_imageEncoder(0),
+ m_error(KErrNone),
+ m_activeDeviceIndex(KDefaultCameraDevice),
+ m_cameraStarted(false),
+ m_icState(EImageCaptureNotPrepared),
+ m_currentCodec(QString()),
+ m_captureSize(QSize()),
+ m_symbianImageQuality(QtMultimediaKit::HighQuality * KSymbianImageQualityCoefficient),
+ m_captureSettingsSet(false),
+ m_stillCaptureFileName(QString()),
+ m_requestedStillCaptureFileName(QString()),
+ m_currentImageId(0),
+ m_captureWhenReady(false),
+ m_previewDecodingOngoing(false),
+ m_previewInWaitLoop(false)
+{
+ // Define supported image codecs
+ m_supportedImageCodecs << "image/jpeg";
+
+ initializeImageCaptureSettings();
+
+ // Install ActiveScheduler if needed
+ if (!CActiveScheduler::Current()) {
+ m_activeScheduler = new CActiveScheduler;
+ CActiveScheduler::Install(m_activeScheduler);
+ }
+}
+
+S60ImageCaptureSession::~S60ImageCaptureSession()
+{
+ // Delete AdvancedSettings (Should already be destroyed by CameraControl)
+ deleteAdvancedSettings();
+
+ m_formats.clear();
+ m_supportedImageCodecs.clear();
+
+ if (m_imageDecoder) {
+ m_imageDecoder->Cancel();
+ delete m_imageDecoder;
+ m_imageDecoder = 0;
+ }
+ if (m_imageEncoder) {
+ m_imageEncoder->Cancel();
+ delete m_imageEncoder;
+ m_imageEncoder = 0;
+ }
+
+ if (m_previewBitmap) {
+ delete m_previewBitmap;
+ m_previewBitmap = 0;
+ }
+
+ // Uninstall ActiveScheduler if needed
+ if (m_activeScheduler) {
+ CActiveScheduler::Install(0);
+ delete m_activeScheduler;
+ m_activeScheduler = 0;
+ }
+}
+
+CCamera::TFormat S60ImageCaptureSession::defaultImageFormat()
+{
+ // Primary Camera
+ if (m_activeDeviceIndex == 0)
+ return KDefaultImageFormatPrimaryCam;
+
+ // Secondary Camera or other
+ else
+ return KDefaultImageFormatSecondaryCam;
+}
+
+bool S60ImageCaptureSession::isDeviceReady()
+{
+#ifdef Q_CC_NOKIAX86 // Emulator
+ return true;
+#endif
+
+ if (m_cameraEngine)
+ return m_cameraEngine->IsCameraReady();
+
+ return false;
+}
+
+void S60ImageCaptureSession::deleteAdvancedSettings()
+{
+ if (m_advancedSettings) {
+ delete m_advancedSettings;
+ m_advancedSettings = 0;
+ emit advancedSettingChanged();
+ }
+}
+
+void S60ImageCaptureSession::setCameraHandle(CCameraEngine* camerahandle)
+{
+ if (camerahandle) {
+ m_cameraEngine = camerahandle;
+ resetSession();
+
+ // Set default settings
+ initializeImageCaptureSettings();
+ }
+}
+
+void S60ImageCaptureSession::setCurrentDevice(TInt deviceindex)
+{
+ m_activeDeviceIndex = deviceindex;
+}
+
+void S60ImageCaptureSession::notifySettingsSet()
+{
+ m_captureSettingsSet = true;
+}
+
+void S60ImageCaptureSession::resetSession(bool errorHandling)
+{
+ // Delete old AdvancedSettings
+ deleteAdvancedSettings();
+
+ m_captureWhenReady = false;
+ m_previewDecodingOngoing = false;
+ m_previewInWaitLoop = false;
+ m_stillCaptureFileName = QString();
+ m_requestedStillCaptureFileName = QString();
+ m_icState = EImageCaptureNotPrepared;
+
+ m_error = KErrNone;
+ m_currentFormat = defaultImageFormat();
+
+ int err = KErrNone;
+ m_advancedSettings = S60CameraSettings::New(err, this, m_cameraEngine);
+ if (err == KErrNotSupported) {
+ m_advancedSettings = 0;
+#ifndef S60_31_PLATFORM // Post S60 3.1 Platform
+ // Adv. settings may not be supported for other than the Primary Camera
+ if (m_cameraEngine->CurrentCameraIndex() == 0)
+ setError(err, tr("Unexpected camera error."));
+#endif // !S60_31_PLATFORM
+ } else if (err != KErrNone) { // Other errors
+ m_advancedSettings = 0;
+ qWarning("Failed to create camera settings handler.");
+ if (errorHandling)
+ emit cameraError(QCamera::ServiceMissingError, tr("Failed to recover from error."));
+ else
+ setError(err, tr("Unexpected camera error."));
+ return;
+ }
+
+ if (m_advancedSettings) {
+ if (m_cameraEngine)
+ m_cameraEngine->SetAdvancedObserver(m_advancedSettings);
+ else
+ setError(KErrNotReady, tr("Unexpected camera error."));
+ }
+
+ updateImageCaptureFormats();
+
+ emit advancedSettingChanged();
+}
+
+S60CameraSettings* S60ImageCaptureSession::advancedSettings()
+{
+ return m_advancedSettings;
+}
+
+/*
+ * This function can be used both internally and from Control classes using
+ * this session. The error notification will go to the client application
+ * either through QCameraImageCapture (if captureError is true) or QCamera (if
+ * captureError is false, default) error signal.
+ */
+void S60ImageCaptureSession::setError(const TInt error,
+ const QString &description,
+ const bool captureError)
+{
+ if (error == KErrNone)
+ return;
+
+ m_error = error;
+ QCameraImageCapture::Error cameraError = fromSymbianErrorToQtMultimediaError(error);
+
+ if (captureError) {
+ emit this->captureError(m_currentImageId, cameraError, description);
+ if (cameraError != QCameraImageCapture::NotSupportedFeatureError)
+ resetSession(true);
+ } else {
+ emit this->cameraError(cameraError, description);
+ if (cameraError != QCamera::NotSupportedFeatureError)
+ resetSession(true);
+ }
+}
+
+QCameraImageCapture::Error S60ImageCaptureSession::fromSymbianErrorToQtMultimediaError(int aError)
+{
+ switch(aError) {
+ case KErrNone:
+ return QCameraImageCapture::NoError; // No errors have occurred
+ case KErrNotReady:
+ return QCameraImageCapture::NotReadyError; // Not ready for operation
+ case KErrNotSupported:
+ return QCameraImageCapture::NotSupportedFeatureError; // The feature is not supported
+ case KErrNoMemory:
+ return QCameraImageCapture::OutOfSpaceError; // Out of disk space
+ case KErrNotFound:
+ case KErrBadHandle:
+ return QCameraImageCapture::ResourceError; // No resources available
+
+ default:
+ return QCameraImageCapture::ResourceError; // Other error has occurred
+ }
+}
+
+int S60ImageCaptureSession::currentImageId() const
+{
+ return m_currentImageId;
+}
+
+void S60ImageCaptureSession::initializeImageCaptureSettings()
+{
+ if (m_captureSettingsSet)
+ return;
+
+ m_currentCodec = KDefaultImageCodec;
+ m_captureSize = QSize(-1, -1);
+ m_currentFormat = defaultImageFormat();
+
+ // Resolution
+ if (m_cameraEngine) {
+ QList<QSize> resolutions = supportedCaptureSizesForCodec(imageCaptureCodec());
+ foreach (QSize reso, resolutions) {
+ if ((reso.width() * reso.height()) > (m_captureSize.width() * m_captureSize.height()))
+ m_captureSize = reso;
+ }
+ } else {
+ m_captureSize = KDefaultImageResolution;
+ }
+
+ m_symbianImageQuality = KDefaultImageQuality;
+}
+
+/*
+ * This function selects proper format to be used for the captured image based
+ * on the requested image codec.
+ */
+CCamera::TFormat S60ImageCaptureSession::selectFormatForCodec(const QString &codec)
+{
+ CCamera::TFormat format = CCamera::EFormatMonochrome;
+
+ if (codec == "image/jpg" || codec == "image/jpeg") {
+ // Primary Camera
+ if (m_activeDeviceIndex == 0)
+ format = KDefaultImageFormatPrimaryCam;
+
+ // Secondary Camera or other
+ else
+ format = KDefaultImageFormatSecondaryCam;
+
+ return format;
+ }
+
+ setError(KErrNotSupported, tr("Failed to select color format to be used with image codec."));
+ return format;
+}
+
+int S60ImageCaptureSession::prepareImageCapture()
+{
+ if (m_cameraEngine) {
+ if (!m_cameraEngine->IsCameraReady()) {
+ // Reset state to make sure camera is prepared before capturing image
+ m_icState = EImageCaptureNotPrepared;
+ return KErrNotReady;
+ }
+
+ // First set the quality
+ CCamera *camera = m_cameraEngine->Camera();
+ if (camera)
+ camera->SetJpegQuality(m_symbianImageQuality);
+ else
+ setError(KErrNotReady, tr("Setting image quality failed."), true);
+
+ // Then prepare with correct resolution and format
+ TSize captureSize = TSize(m_captureSize.width(), m_captureSize.height());
+ TRAPD(symbianError, m_cameraEngine->PrepareL(captureSize, m_currentFormat));
+ if (!symbianError)
+ m_icState = EImageCapturePrepared;
+
+ // Check if CaptureSize was modified
+ if (captureSize.iWidth != m_captureSize.width() || captureSize.iHeight != m_captureSize.height())
+ m_captureSize = QSize(captureSize.iWidth, captureSize.iHeight);
+ emit captureSizeChanged(m_captureSize);
+
+#ifdef ECAM_PREVIEW_API
+ // Subscribe previews
+ MCameraPreviewObserver *observer = this;
+ m_cameraEngine->EnablePreviewProvider(observer);
+#endif // ECAM_PREVIEW_API
+
+ return symbianError;
+ }
+
+ return KErrGeneral;
+}
+
+void S60ImageCaptureSession::releaseImageCapture()
+{
+ // Make sure ImageCapture is prepared the next time it is being activated
+ m_icState = EImageCaptureNotPrepared;
+
+#ifdef ECAM_PREVIEW_API
+ // Cancel preview subscription
+ m_cameraEngine->DisablePreviewProvider();
+#endif // ECAM_PREVIEW_API
+}
+
+int S60ImageCaptureSession::capture(const QString &fileName)
+{
+ if (!m_cameraStarted) {
+ m_captureWhenReady = true;
+ m_requestedStillCaptureFileName = fileName; // Save name, it will be processed during actual capture
+ return 0;
+ }
+
+ if (m_icState < EImageCapturePrepared) {
+ int prepareSuccess = prepareImageCapture();
+ if (prepareSuccess) {
+ setError(prepareSuccess, tr("Failure during image capture preparation."), true);
+ return 0;
+ }
+ } else if (m_icState > EImageCapturePrepared) {
+ setError(KErrNotReady, tr("Previous operation is still ongoing."), true);
+ return 0;
+ }
+
+ m_icState = EImageCaptureCapturing;
+
+ // Give new ID for the new image
+ m_currentImageId += 1;
+
+ emit readyForCaptureChanged(false);
+
+ processFileName(fileName);
+
+ if (m_cameraEngine) {
+ TRAPD(err, m_cameraEngine->CaptureL());
+ setError(err, tr("Image capture failed."), true);
+ } else {
+ setError(KErrNotReady, tr("Unexpected camera error."), true);
+ }
+
+#ifdef Q_CC_NOKIAX86 // Emulator
+ QImage *snapImage = new QImage(QLatin1String("C:/Data/testimage.jpg"));
+ emit imageExposed(m_currentImageId);
+ emit imageCaptured(m_currentImageId, *snapImage);
+ emit imageSaved(m_currentImageId, m_stillCaptureFileName);
+#endif // Q_CC_NOKIAX86
+
+ return m_currentImageId;
+}
+
+void S60ImageCaptureSession::cancelCapture()
+{
+ if (m_icState != EImageCaptureCapturing)
+ return;
+
+ if (m_cameraEngine)
+ m_cameraEngine->CancelCapture();
+
+ m_icState = EImageCapturePrepared;
+}
+
+void S60ImageCaptureSession::processFileName(const QString &fileName)
+{
+ // Empty FileName - Use default file name and path (C:\Data\Images\image.jpg)
+ if (fileName.isEmpty()) {
+ // Make sure default directory exists
+ QDir videoDir(QDir::rootPath());
+ if (!videoDir.exists(KDefaultImagePath))
+ videoDir.mkpath(KDefaultImagePath);
+ QString defaultFile = KDefaultImagePath;
+ defaultFile.append("\\");
+ defaultFile.append(KDefaultImageFileName);
+ m_stillCaptureFileName = defaultFile;
+
+ } else { // Not empty
+
+ QString fullFileName;
+
+ // Relative FileName
+ if (!fileName.contains(":")) {
+ // Extract file name and path from the URL
+ fullFileName = KDefaultImagePath;
+ if (fileName.at(0) != '\\')
+ fullFileName.append("\\");
+ fullFileName.append(QDir::toNativeSeparators(QDir::cleanPath(fileName)));
+
+ // Absolute FileName
+ } else {
+ // Extract file name and path from the given location
+ fullFileName = QDir::toNativeSeparators(QDir::cleanPath(fileName));
+ }
+
+ QString fileNameOnly = fullFileName.right(fullFileName.length() - fullFileName.lastIndexOf("\\") - 1);
+ QString directory = fullFileName.left(fullFileName.lastIndexOf("\\"));
+ if (directory.lastIndexOf("\\") == (directory.length() - 1))
+ directory = directory.left(directory.length() - 1);
+
+ // URL is Absolute path, not including file name
+ if (!fileNameOnly.contains(".")) {
+ if (fileNameOnly != "") {
+ directory.append("\\");
+ directory.append(fileNameOnly);
+ }
+ fileNameOnly = KDefaultImageFileName;
+ }
+
+ // Make sure absolute directory exists
+ QDir imageDir(QDir::rootPath());
+ if (!imageDir.exists(directory))
+ imageDir.mkpath(directory);
+
+ QString resolvedFileName = directory;
+ resolvedFileName.append("\\");
+ resolvedFileName.append(fileNameOnly);
+ m_stillCaptureFileName = resolvedFileName;
+ }
+}
+
+void S60ImageCaptureSession::MceoFocusComplete()
+{
+ emit focusStatusChanged(QCamera::Locked, QCamera::LockAcquired);
+}
+
+void S60ImageCaptureSession::MceoCapturedDataReady(TDesC8* aData)
+{
+ emit imageExposed(m_currentImageId);
+
+ m_icState = EImageCaptureWritingImage;
+
+ TFileName path = convertImagePath();
+
+ // Try to save image and inform if it was succcesful
+ TRAPD(err, saveImageL(aData, path));
+ if (err) {
+ if (m_previewDecodingOngoing)
+ m_previewDecodingOngoing = false; // Reset
+
+ setError(err, tr("Writing captured image to a file failed."), true);
+ m_icState = EImageCapturePrepared;
+ return;
+ }
+
+ m_icState = EImageCapturePrepared;
+
+}
+
+void S60ImageCaptureSession::MceoCapturedBitmapReady(CFbsBitmap* aBitmap)
+{
+ emit imageExposed(m_currentImageId);
+
+ m_icState = EImageCaptureWritingImage;
+
+ if(aBitmap)
+ {
+#ifndef ECAM_PREVIEW_API
+ if (m_previewDecodingOngoing) {
+ m_previewInWaitLoop = true;
+ CActiveScheduler::Start(); // Wait for the completion of the previous Preview generation
+ }
+
+ // Delete old instances if needed
+ if (m_imageDecoder) {
+ delete m_imageDecoder;
+ m_imageDecoder = 0;
+ }
+ if (m_previewBitmap) {
+ delete m_previewBitmap;
+ m_previewBitmap = 0;
+ }
+#endif // ECAM_CAMERA_API
+ if (m_imageEncoder) {
+ delete m_imageEncoder;
+ m_imageEncoder = 0;
+ }
+ if (m_fileSystemAccess) {
+ m_fileSystemAccess->Close();
+ delete m_fileSystemAccess;
+ m_fileSystemAccess = 0;
+ }
+
+ TInt saveError = KErrNone;
+ TFileName path = convertImagePath();
+
+ // Create FileSystem access
+ m_fileSystemAccess = new RFs;
+ if (!m_fileSystemAccess) {
+ setError(KErrNoMemory, tr("Failed to write captured image to a file."));
+ return;
+ }
+ saveError = m_fileSystemAccess->Connect();
+ if (saveError) {
+ setError(saveError, tr("Failed to write captured image to a file."));
+ return;
+ }
+
+ TRAP(saveError, m_imageEncoder = S60ImageCaptureEncoder::NewL(this,
+ m_fileSystemAccess,
+ &path,
+ m_symbianImageQuality));
+ if (saveError)
+ setError(saveError, tr("Saving captured image failed."), true);
+ m_previewDecodingOngoing = true;
+ m_imageEncoder->encode(aBitmap);
+
+ } else {
+ setError(KErrBadHandle, tr("Unexpected camera error."), true);
+ }
+
+ m_icState = EImageCapturePrepared;
+}
+
+void S60ImageCaptureSession::MceoHandleError(TCameraEngineError aErrorType, TInt aError)
+{
+ Q_UNUSED(aErrorType);
+ setError(aError, tr("General camera error."));
+}
+
+TFileName S60ImageCaptureSession::convertImagePath()
+{
+ TFileName path = KNullDesC();
+
+ // Convert to Symbian path
+ TPtrC16 attachmentPath(KNullDesC);
+
+ // Path is already included in filename
+ attachmentPath.Set(reinterpret_cast<const TUint16*>(QDir::toNativeSeparators(m_stillCaptureFileName).utf16()));
+ path.Append(attachmentPath);
+
+ return path;
+}
+
+/*
+ * Creates (asynchronously) Preview Image from Jpeg ImageBuffer and also
+ * writes Jpeg (synchronously) to a file.
+ */
+void S60ImageCaptureSession::saveImageL(TDesC8 *aData, TFileName &aPath)
+{
+ if (aData == 0)
+ setError(KErrGeneral, tr("Captured image data is not available."), true);
+
+ if (aPath.Size() > 0) {
+#ifndef ECAM_PREVIEW_API
+ if (m_previewDecodingOngoing) {
+ m_previewInWaitLoop = true;
+ CActiveScheduler::Start(); // Wait for the completion of the previous Preview generation
+ }
+
+ // Delete old instances if needed
+ if (m_imageDecoder) {
+ delete m_imageDecoder;
+ m_imageDecoder = 0;
+ }
+ if (m_previewBitmap) {
+ delete m_previewBitmap;
+ m_previewBitmap = 0;
+ }
+#endif // ECAM_PREVIEW_API
+ if (m_fileSystemAccess) {
+ m_fileSystemAccess->Close();
+ delete m_fileSystemAccess;
+ m_fileSystemAccess = 0;
+ }
+
+ RFs *fileSystemAccess = new (ELeave) RFs;
+ User::LeaveIfError(fileSystemAccess->Connect());
+ CleanupClosePushL(*fileSystemAccess);
+
+#ifndef ECAM_PREVIEW_API
+ // Generate Thumbnail to be used as Preview
+ S60ImageCaptureDecoder *imageDecoder = S60ImageCaptureDecoder::DataNewL(this, fileSystemAccess, aData);
+ CleanupStack::PushL(imageDecoder);
+
+ // Set proper Preview Size
+ TSize scaledSize((m_captureSize.width() / KSnapshotDownScaleFactor), (m_captureSize.height() / KSnapshotDownScaleFactor));
+ if (scaledSize.iWidth < KSnapshotMinWidth || scaledSize.iHeight < KSnapshotMinHeight)
+ scaledSize.SetSize((m_captureSize.width() / (KSnapshotDownScaleFactor/2)), (m_captureSize.height() / (KSnapshotDownScaleFactor/2)));
+ if (scaledSize.iWidth < KSnapshotMinWidth || scaledSize.iHeight < KSnapshotMinHeight)
+ scaledSize.SetSize((m_captureSize.width() / (KSnapshotDownScaleFactor/4)), (m_captureSize.height() / (KSnapshotDownScaleFactor/4)));
+ if (scaledSize.iWidth < KSnapshotMinWidth || scaledSize.iHeight < KSnapshotMinHeight)
+ scaledSize.SetSize(m_captureSize.width(), m_captureSize.height());
+
+ TFrameInfo *info = imageDecoder->frameInfo();
+ if (!info) {
+ setError(KErrGeneral, tr("Preview image creation failed."));
+ return;
+ }
+
+ CFbsBitmap *previewBitmap = new (ELeave) CFbsBitmap;
+ CleanupStack::PushL(previewBitmap);
+ TInt bitmapCreationErr = previewBitmap->Create(scaledSize, info->iFrameDisplayMode);
+ if (bitmapCreationErr) {
+ setError(bitmapCreationErr, tr("Preview creation failed."));
+ return;
+ }
+
+ // Jpeg conversion completes in RunL
+ m_previewDecodingOngoing = true;
+ imageDecoder->decode(previewBitmap);
+#endif // ECAM_PREVIEW_API
+
+ RFile file;
+ TInt fileWriteErr = KErrNone;
+ fileWriteErr = file.Replace(*fileSystemAccess, aPath, EFileWrite);
+ if (fileWriteErr)
+ User::Leave(fileWriteErr);
+ CleanupClosePushL(file); // Close if Leaves
+
+ fileWriteErr = file.Write(*aData);
+ if (fileWriteErr)
+ User::Leave(fileWriteErr);
+
+ CleanupStack::PopAndDestroy(&file);
+#ifdef ECAM_PREVIEW_API
+ CleanupStack::PopAndDestroy(fileSystemAccess);
+#else // !ECAM_PREVIEW_API
+ // Delete when Image is decoded
+ CleanupStack::Pop(previewBitmap);
+ CleanupStack::Pop(imageDecoder);
+ CleanupStack::Pop(fileSystemAccess);
+
+ // Set member variables (Cannot leave any more)
+ m_previewBitmap = previewBitmap;
+ m_imageDecoder = imageDecoder;
+ m_fileSystemAccess = fileSystemAccess;
+#endif // ECAM_PREVIEW_API
+
+ emit imageSaved(m_currentImageId, m_stillCaptureFileName);
+
+ // Inform that we can continue taking more pictures
+ emit readyForCaptureChanged(true);
+
+ // For custom preview generation, image buffer gets released in RunL()
+#ifdef ECAM_PREVIEW_API
+ releaseImageBuffer();
+#endif // ECAM_PREVIEW_API
+
+ } else {
+ setError(KErrPathNotFound, tr("Invalid path given."), true);
+ }
+}
+
+void S60ImageCaptureSession::releaseImageBuffer()
+{
+ if (m_cameraEngine)
+ m_cameraEngine->ReleaseImageBuffer();
+ else
+ setError(KErrNotReady, tr("Unexpected camera error."), true);
+}
+
+/*
+ * Queries camera properties
+ * Results are returned to member variable m_info
+ *
+ * @return boolean indicating if querying the info was a success
+ */
+bool S60ImageCaptureSession::queryCurrentCameraInfo()
+{
+ if (m_cameraEngine) {
+ m_cameraInfo = m_cameraEngine->CameraInfo();
+ return true;
+ }
+
+ return false;
+}
+
+/*
+ * This function handles different camera status changes
+ */
+void S60ImageCaptureSession::cameraStatusChanged(QCamera::Status status)
+{
+ if (status == QCamera::ActiveStatus) {
+ m_cameraStarted = true;
+ if (m_captureWhenReady)
+ capture(m_requestedStillCaptureFileName);
+ }else if (status == QCamera::UnloadedStatus) {
+ m_cameraStarted = false;
+ m_icState = EImageCaptureNotPrepared;
+ }
+ else
+ m_cameraStarted = false;
+}
+
+QSize S60ImageCaptureSession::captureSize() const
+{
+ return m_captureSize;
+}
+
+QSize S60ImageCaptureSession::minimumCaptureSize()
+{
+ return supportedCaptureSizesForCodec(formatMap().key(m_currentFormat)).first();
+}
+QSize S60ImageCaptureSession::maximumCaptureSize()
+{
+ return supportedCaptureSizesForCodec(formatMap().key(m_currentFormat)).last();
+}
+
+void S60ImageCaptureSession::setCaptureSize(const QSize &size)
+{
+ if (size.isNull() ||
+ size.isEmpty() ||
+ size == QSize(-1,-1)) {
+ // An empty QSize indicates the encoder should make an optimal choice based on what is
+ // available from the image source and the limitations of the codec.
+ m_captureSize = supportedCaptureSizesForCodec(formatMap().key(m_currentFormat)).last();
+ }
+ else
+ m_captureSize = size;
+}
+
+QList<QSize> S60ImageCaptureSession::supportedCaptureSizesForCodec(const QString &codecName)
+{
+ QList<QSize> list;
+
+ // If we have CameraEngine loaded and we can update CameraInfo
+ if (m_cameraEngine && queryCurrentCameraInfo()) {
+ CCamera::TFormat format;
+ if (codecName == "")
+ format = defaultImageFormat();
+ else
+ format = selectFormatForCodec(codecName);
+
+ CCamera *camera = m_cameraEngine->Camera();
+ TSize imageSize;
+ if (camera) {
+ for (int i = 0; i < m_cameraInfo->iNumImageSizesSupported; i++) {
+ camera->EnumerateCaptureSizes(imageSize, i, format);
+ list << QSize(imageSize.iWidth, imageSize.iHeight); // Add resolution to the list
+ }
+ }
+ }
+
+#ifdef Q_CC_NOKIAX86 // Emulator
+ // Add some for testing purposes
+ list << QSize(50, 50);
+ list << QSize(100, 100);
+ list << QSize(800,600);
+#endif
+
+ return list;
+}
+
+QMap<QString, int> S60ImageCaptureSession::formatMap()
+{
+ QMap<QString, int> formats;
+
+ // Format list copied from CCamera::TFormat (in ecam.h)
+ formats.insert("Monochrome", 0x0001);
+ formats.insert("16bitRGB444", 0x0002);
+ formats.insert("16BitRGB565", 0x0004);
+ formats.insert("32BitRGB888", 0x0008);
+ formats.insert("Jpeg", 0x0010);
+ formats.insert("Exif", 0x0020);
+ formats.insert("FbsBitmapColor4K", 0x0040);
+ formats.insert("FbsBitmapColor64K", 0x0080);
+ formats.insert("FbsBitmapColor16M", 0x0100);
+ formats.insert("UserDefined", 0x0200);
+ formats.insert("YUV420Interleaved", 0x0400);
+ formats.insert("YUV420Planar", 0x0800);
+ formats.insert("YUV422", 0x1000);
+ formats.insert("YUV422Reversed", 0x2000);
+ formats.insert("YUV444", 0x4000);
+ formats.insert("YUV420SemiPlanar", 0x8000);
+ formats.insert("FbsBitmapColor16MU", 0x00010000);
+ formats.insert("MJPEG", 0x00020000);
+ formats.insert("EncodedH264", 0x00040000);
+
+ return formats;
+}
+
+QMap<QString, QString> S60ImageCaptureSession::codecDescriptionMap()
+{
+ QMap<QString, QString> formats;
+
+ formats.insert("image/jpg", "JPEG image codec");
+
+ return formats;
+}
+
+QStringList S60ImageCaptureSession::supportedImageCaptureCodecs()
+{
+#ifdef Q_CC_NOKIAX86 // Emulator
+ return formatMap().keys();
+#endif
+
+ return m_supportedImageCodecs;
+}
+
+void S60ImageCaptureSession::updateImageCaptureFormats()
+{
+ m_formats.clear();
+ if (m_cameraEngine && queryCurrentCameraInfo()) {
+ TUint32 supportedFormats = m_cameraInfo->iImageFormatsSupported;
+
+#ifdef S60_3X_PLATFORM // S60 3.1 & 3.2
+ int maskEnd = CCamera::EFormatFbsBitmapColor16MU;
+#else // S60 5.0 or later
+ int maskEnd = CCamera::EFormatEncodedH264;
+#endif // S60_3X_PLATFORM
+
+ for (int mask = CCamera::EFormatMonochrome; mask <= maskEnd; mask <<= 1) {
+ if (supportedFormats & mask)
+ m_formats << mask; // Store mask of supported format
+ }
+ }
+}
+
+QString S60ImageCaptureSession::imageCaptureCodec()
+{
+ return m_currentCodec;
+}
+void S60ImageCaptureSession::setImageCaptureCodec(const QString &codecName)
+{
+ if (!codecName.isEmpty()) {
+ if (supportedImageCaptureCodecs().contains(codecName, Qt::CaseInsensitive) ||
+ codecName == "image/jpg") {
+ m_currentCodec = codecName;
+ m_currentFormat = selectFormatForCodec(m_currentCodec);
+ } else {
+ setError(KErrNotSupported, tr("Requested image codec is not supported"));
+ }
+ } else {
+ m_currentCodec = KDefaultImageCodec;
+ m_currentFormat = selectFormatForCodec(m_currentCodec);
+ }
+}
+
+QString S60ImageCaptureSession::imageCaptureCodecDescription(const QString &codecName)
+{
+ QString description = codecDescriptionMap().value(codecName);
+ return description;
+}
+
+QtMultimediaKit::EncodingQuality S60ImageCaptureSession::captureQuality() const
+{
+ switch (m_symbianImageQuality) {
+ case KJpegQualityVeryLow:
+ return QtMultimediaKit::VeryLowQuality;
+ case KJpegQualityLow:
+ return QtMultimediaKit::LowQuality;
+ case KJpegQualityNormal:
+ return QtMultimediaKit::NormalQuality;
+ case KJpegQualityHigh:
+ return QtMultimediaKit::HighQuality;
+ case KJpegQualityVeryHigh:
+ return QtMultimediaKit::VeryHighQuality;
+
+ default:
+ // Return normal as default
+ return QtMultimediaKit::NormalQuality;
+ }
+}
+
+void S60ImageCaptureSession::setCaptureQuality(const QtMultimediaKit::EncodingQuality &quality)
+{
+ // Use sensible presets
+ switch (quality) {
+ case QtMultimediaKit::VeryLowQuality:
+ m_symbianImageQuality = KJpegQualityVeryLow;
+ break;
+ case QtMultimediaKit::LowQuality:
+ m_symbianImageQuality = KJpegQualityLow;
+ break;
+ case QtMultimediaKit::NormalQuality:
+ m_symbianImageQuality = KJpegQualityNormal;
+ break;
+ case QtMultimediaKit::HighQuality:
+ m_symbianImageQuality = KJpegQualityHigh;
+ break;
+ case QtMultimediaKit::VeryHighQuality:
+ m_symbianImageQuality = KJpegQualityVeryHigh;
+ break;
+
+ default:
+ m_symbianImageQuality = quality * KSymbianImageQualityCoefficient;
+ break;
+ }
+}
+
+qreal S60ImageCaptureSession::maximumZoom()
+{
+ qreal maxZoomFactor = 1.0;
+
+ if (queryCurrentCameraInfo()) {
+ maxZoomFactor = m_cameraInfo->iMaxZoomFactor;
+
+ if (maxZoomFactor == 0.0 || maxZoomFactor == 1.0) {
+ return 1.0; // Not supported
+ } else {
+ return maxZoomFactor;
+ }
+ } else {
+ return 1.0;
+ }
+}
+
+qreal S60ImageCaptureSession::minZoom()
+{
+ qreal minZoomValue = 1.0;
+
+ if (queryCurrentCameraInfo()) {
+ minZoomValue = m_cameraInfo->iMinZoomFactor;
+ if (minZoomValue == 0.0 || minZoomValue == 1.0)
+ return 1.0; // Macro Zoom is not supported
+ else {
+ return minZoomValue;
+ }
+
+ } else {
+ return 1.0;
+ }
+}
+
+qreal S60ImageCaptureSession::maxDigitalZoom()
+{
+ qreal maxDigitalZoomFactor = 1.0;
+
+ if (queryCurrentCameraInfo()) {
+ maxDigitalZoomFactor = m_cameraInfo->iMaxDigitalZoomFactor;
+ return maxDigitalZoomFactor;
+ } else {
+ return 1.0;
+ }
+}
+
+void S60ImageCaptureSession::doSetZoomFactorL(qreal optical, qreal digital)
+{
+#if !defined(USE_S60_32_ECAM_ADVANCED_SETTINGS_HEADER) & !defined(USE_S60_50_ECAM_ADVANCED_SETTINGS_HEADER)
+ // Convert Zoom Factor to Zoom Value if AdvSettings are not available
+ int digitalSymbian = (digital * m_cameraInfo->iMaxDigitalZoom) / maxDigitalZoom();
+ if (m_cameraInfo->iMaxDigitalZoom != 0 && digital == 1.0)
+ digitalSymbian = 1; // Make sure zooming out to initial value if requested
+#endif // !USE_S60_32_ECAM_ADVANCED_SETTINGS_HEADER & !USE_S60_50_ECAM_ADVANCED_SETTINGS_HEADER
+
+ if (m_cameraEngine && !m_cameraEngine->IsCameraReady())
+ return;
+
+ if (m_cameraEngine && queryCurrentCameraInfo()) {
+ CCamera *camera = m_cameraEngine->Camera();
+ if (camera) {
+
+ // Optical Zoom
+ if (!qFuzzyCompare(optical, qreal(1.0)) && !qFuzzyCompare(optical, qreal(0.0))) {
+ setError(KErrNotSupported, tr("Requested optical zoom factor is not supported."));
+ return;
+ }
+
+ // Digital Zoom (Smooth Zoom - Zoom value set in steps)
+ if (digital != digitalZoomFactor()) {
+ if ((digital > 1.0 || qFuzzyCompare(digital, qreal(1.0))) &&
+ digital <= m_cameraInfo->iMaxDigitalZoomFactor) {
+#if defined(USE_S60_32_ECAM_ADVANCED_SETTINGS_HEADER) | defined(USE_S60_50_ECAM_ADVANCED_SETTINGS_HEADER)
+ if (m_advancedSettings) {
+ qreal currentZoomFactor = m_advancedSettings->digitalZoomFactorL();
+
+ QList<qreal> smoothZoomSetValues;
+ QList<qreal> factors = m_advancedSettings->supportedDigitalZoomFactors();
+ if (currentZoomFactor < digital) {
+ for (int i = 0; i < factors.count(); ++i) {
+ if (factors.at(i) > currentZoomFactor && factors.at(i) < digital)
+ smoothZoomSetValues << factors.at(i);
+ }
+
+ for (int i = 0; i < smoothZoomSetValues.count(); i = i + KSmoothZoomStep) {
+ m_advancedSettings->setDigitalZoomFactorL(smoothZoomSetValues[i]); // Using Zoom Factor
+ }
+
+ } else {
+ for (int i = 0; i < factors.count(); ++i) {
+ if (factors.at(i) < currentZoomFactor && factors.at(i) > digital)
+ smoothZoomSetValues << factors.at(i);
+ }
+
+ for (int i = (smoothZoomSetValues.count() - 1); i >= 0; i = i - KSmoothZoomStep) {
+ m_advancedSettings->setDigitalZoomFactorL(smoothZoomSetValues[i]); // Using Zoom Factor
+ }
+ }
+
+ // Set final value
+ m_advancedSettings->setDigitalZoomFactorL(digital);
+ }
+ else
+ setError(KErrNotReady, tr("Zooming failed."));
+#else // No advanced settigns
+ // Define zoom steps
+ int currentZoomFactor = camera->DigitalZoomFactor();
+ int difference = abs(currentZoomFactor - digitalSymbian);
+ int midZoomValue = currentZoomFactor;
+
+ if (currentZoomFactor < digitalSymbian) {
+ while (midZoomValue < (digitalSymbian - KSmoothZoomStep)) {
+ midZoomValue = midZoomValue + KSmoothZoomStep;
+ camera->SetDigitalZoomFactorL(midZoomValue);
+ }
+ } else {
+ while (midZoomValue > (digitalSymbian + KSmoothZoomStep)) {
+ midZoomValue = midZoomValue - KSmoothZoomStep;
+ camera->SetDigitalZoomFactorL(midZoomValue);
+ }
+ }
+
+ // Set final and emit signal
+ camera->SetDigitalZoomFactorL(digitalSymbian);
+#endif // USE_S60_32_ECAM_ADVANCED_SETTINGS_HEADER | USE_S60_50_ECAM_ADVANCED_SETTINGS_HEADER
+ } else {
+ setError(KErrNotSupported, tr("Requested digital zoom factor is not supported."));
+ return;
+ }
+ }
+ }
+ } else {
+ setError(KErrGeneral, tr("Unexpected camera error."));
+ }
+}
+
+qreal S60ImageCaptureSession::opticalZoomFactor()
+{
+ qreal factor = 1.0;
+
+#if defined(USE_S60_32_ECAM_ADVANCED_SETTINGS_HEADER) | defined(USE_S60_50_ECAM_ADVANCED_SETTINGS_HEADER)
+ if (m_advancedSettings) {
+ TRAPD(err, factor = m_advancedSettings->opticalZoomFactorL());
+ if (err)
+ return 1.0;
+ }
+#else // No advanced settigns
+ if (m_cameraEngine && m_cameraInfo) {
+ if (m_cameraEngine->Camera()) {
+ if (m_cameraInfo->iMaxZoom != 0)
+ factor = (m_cameraEngine->Camera()->ZoomFactor()* maximumZoom()) / m_cameraInfo->iMaxZoom;
+ else
+ factor = 1.0;
+ }
+ }
+#endif // USE_S60_32_ECAM_ADVANCED_SETTINGS_HEADER | USE_S60_50_ECAM_ADVANCED_SETTINGS_HEADER
+
+ if (factor == 0.0) // If not supported
+ factor = 1.0;
+
+ return factor;
+}
+
+qreal S60ImageCaptureSession::digitalZoomFactor()
+{
+ qreal factor = 1.0;
+
+#if defined(USE_S60_32_ECAM_ADVANCED_SETTINGS_HEADER) | defined(USE_S60_50_ECAM_ADVANCED_SETTINGS_HEADER)
+ if (m_advancedSettings) {
+ TRAPD(err, factor = m_advancedSettings->digitalZoomFactorL());
+ if (err)
+ return 1.0;
+ }
+#else // No advanced settigns
+ if (m_cameraEngine && m_cameraInfo) {
+ if (m_cameraEngine->Camera()) {
+ if (m_cameraInfo->iMaxDigitalZoom != 0)
+ factor = (m_cameraEngine->Camera()->DigitalZoomFactor()* maxDigitalZoom()) / m_cameraInfo->iMaxDigitalZoom;
+ else
+ factor = 1.0;
+ }
+ }
+#endif // USE_S60_32_ECAM_ADVANCED_SETTINGS_HEADER | USE_S60_50_ECAM_ADVANCED_SETTINGS_HEADER
+
+ if (factor == 0.0)
+ factor = 1.0;
+
+ return factor;
+}
+
+void S60ImageCaptureSession::setFlashMode(QCameraExposure::FlashModes mode)
+{
+ TRAPD(err, doSetFlashModeL(mode));
+ setError(err, tr("Failed to set flash mode."));
+}
+
+void S60ImageCaptureSession::doSetFlashModeL(QCameraExposure::FlashModes mode)
+{
+ if (m_cameraEngine && m_cameraEngine->Camera()) {
+ CCamera *camera = m_cameraEngine->Camera();
+ switch(mode) {
+ case QCameraExposure::FlashOff:
+ camera->SetFlashL(CCamera::EFlashNone);
+ break;
+ case QCameraExposure::FlashAuto:
+ camera->SetFlashL(CCamera::EFlashAuto);
+ break;
+ case QCameraExposure::FlashOn:
+ camera->SetFlashL(CCamera::EFlashForced);
+ break;
+ case QCameraExposure::FlashRedEyeReduction:
+ camera->SetFlashL(CCamera::EFlashRedEyeReduce);
+ break;
+ case QCameraExposure::FlashFill:
+ camera->SetFlashL(CCamera::EFlashFillIn);
+ break;
+
+ default:
+ setError(KErrNotSupported, tr("Requested flash mode is not suported"));
+ break;
+ }
+ } else {
+ setError(KErrNotReady, tr("Unexpected camera error."));
+ }
+}
+
+QCameraExposure::FlashMode S60ImageCaptureSession::flashMode()
+{
+ if (m_cameraEngine && m_cameraEngine->Camera()) {
+ CCamera *camera = m_cameraEngine->Camera();
+ switch(camera->Flash()) {
+ case CCamera::EFlashAuto:
+ return QCameraExposure::FlashAuto;
+ case CCamera::EFlashForced:
+ return QCameraExposure::FlashOn;
+ case CCamera::EFlashRedEyeReduce:
+ return QCameraExposure::FlashRedEyeReduction;
+ case CCamera::EFlashFillIn:
+ return QCameraExposure::FlashFill;
+ case CCamera::EFlashNone:
+ return QCameraExposure::FlashOff;
+
+ default:
+ return QCameraExposure::FlashAuto; // Most probable default
+ }
+ } else {
+ setError(KErrNotReady, tr("Unexpected camera error."));
+ }
+
+ return QCameraExposure::FlashOff;
+}
+
+QCameraExposure::FlashModes S60ImageCaptureSession::supportedFlashModes()
+{
+ QCameraExposure::FlashModes modes = QCameraExposure::FlashOff;
+
+ if (queryCurrentCameraInfo()) {
+ TInt supportedModes = m_cameraInfo->iFlashModesSupported;
+
+ if (supportedModes == 0)
+ return modes;
+
+ if (supportedModes & CCamera::EFlashManual)
+ modes |= QCameraExposure::FlashOff;
+ if (supportedModes & CCamera::EFlashForced)
+ modes |= QCameraExposure::FlashOn;
+ if (supportedModes & CCamera::EFlashAuto)
+ modes |= QCameraExposure::FlashAuto;
+ if (supportedModes & CCamera::EFlashFillIn)
+ modes |= QCameraExposure::FlashFill;
+ if (supportedModes & CCamera::EFlashRedEyeReduce)
+ modes |= QCameraExposure::FlashRedEyeReduction;
+ }
+
+ return modes;
+}
+
+QCameraExposure::ExposureMode S60ImageCaptureSession::exposureMode()
+{
+ if (m_cameraEngine && m_cameraEngine->Camera()) {
+ CCamera* camera = m_cameraEngine->Camera();
+ switch(camera->Exposure()) {
+ case CCamera::EExposureManual:
+ return QCameraExposure::ExposureManual;
+ case CCamera::EExposureAuto:
+ return QCameraExposure::ExposureAuto;
+ case CCamera::EExposureNight:
+ return QCameraExposure::ExposureNight;
+ case CCamera::EExposureBacklight:
+ return QCameraExposure::ExposureBacklight;
+ case CCamera::EExposureSport:
+ return QCameraExposure::ExposureSports;
+ case CCamera::EExposureSnow:
+ return QCameraExposure::ExposureSnow;
+ case CCamera::EExposureBeach:
+ return QCameraExposure::ExposureBeach;
+
+ default:
+ return QCameraExposure::ExposureAuto;
+ }
+ }
+
+ return QCameraExposure::ExposureAuto;
+}
+
+bool S60ImageCaptureSession::isExposureModeSupported(QCameraExposure::ExposureMode mode) const
+{
+ TInt supportedModes = m_cameraInfo->iExposureModesSupported;
+
+ if (supportedModes == 0)
+ return false;
+
+ switch (mode) {
+ case QCameraExposure::ExposureManual:
+ if(supportedModes & CCamera::EExposureManual)
+ return true;
+ else
+ return false;
+ case QCameraExposure::ExposureAuto:
+ return true; // Always supported
+ case QCameraExposure::ExposureNight:
+ if(supportedModes & CCamera::EExposureNight)
+ return true;
+ else
+ return false;
+ case QCameraExposure::ExposureBacklight:
+ if(supportedModes & CCamera::EExposureBacklight)
+ return true;
+ else
+ return false;
+ case QCameraExposure::ExposureSports:
+ if(supportedModes & CCamera::EExposureSport)
+ return true;
+ else
+ return false;
+ case QCameraExposure::ExposureSnow:
+ if(supportedModes & CCamera::EExposureSnow)
+ return true;
+ else
+ return false;
+ case QCameraExposure::ExposureBeach:
+ if(supportedModes & CCamera::EExposureBeach)
+ return true;
+ else
+ return false;
+
+ default:
+ return false;
+ }
+}
+
+void S60ImageCaptureSession::setExposureMode(QCameraExposure::ExposureMode mode)
+{
+ TRAPD(err, doSetExposureModeL(mode));
+ setError(err, tr("Failed to set exposure mode."));
+}
+
+void S60ImageCaptureSession::doSetExposureModeL( QCameraExposure::ExposureMode mode)
+{
+ if (m_cameraEngine && m_cameraEngine->Camera()) {
+ CCamera *camera = m_cameraEngine->Camera();
+ switch(mode) {
+ case QCameraExposure::ExposureManual:
+ camera->SetExposureL(CCamera::EExposureManual);
+ break;
+ case QCameraExposure::ExposureAuto:
+ camera->SetExposureL(CCamera::EExposureAuto);
+ break;
+ case QCameraExposure::ExposureNight:
+ camera->SetExposureL(CCamera::EExposureNight);
+ break;
+ case QCameraExposure::ExposureBacklight:
+ camera->SetExposureL(CCamera::EExposureBacklight);
+ break;
+ case QCameraExposure::ExposureSports:
+ camera->SetExposureL(CCamera::EExposureSport);
+ break;
+ case QCameraExposure::ExposureSnow:
+ camera->SetExposureL(CCamera::EExposureSnow);
+ break;
+ case QCameraExposure::ExposureBeach:
+ camera->SetExposureL(CCamera::EExposureBeach);
+ break;
+ case QCameraExposure::ExposureLargeAperture:
+ case QCameraExposure::ExposureSmallAperture:
+ break;
+ case QCameraExposure::ExposurePortrait:
+ case QCameraExposure::ExposureSpotlight:
+ default:
+ setError(KErrNotSupported, tr("Requested exposure mode is not suported"));
+ break;
+ }
+ } else {
+ setError(KErrNotReady, tr("Unexpected camera error."));
+ }
+}
+
+int S60ImageCaptureSession::contrast() const
+{
+ if (m_cameraEngine && m_cameraEngine->Camera()) {
+ return m_cameraEngine->Camera()->Contrast();
+ } else {
+ return 0;
+ }
+}
+
+void S60ImageCaptureSession::setContrast(int value)
+{
+ if (m_cameraEngine && m_cameraEngine->Camera()) {
+ TRAPD(err, m_cameraEngine->Camera()->SetContrastL(value));
+ setError(err, tr("Failed to set contrast."));
+ } else {
+ setError(KErrNotReady, tr("Unexpected camera error."));
+ }
+}
+
+int S60ImageCaptureSession::brightness() const
+{
+ if (m_cameraEngine && m_cameraEngine->Camera()) {
+ return m_cameraEngine->Camera()->Brightness();
+ } else {
+ return 0;
+ }
+}
+
+void S60ImageCaptureSession::setBrightness(int value)
+{
+ if (m_cameraEngine && m_cameraEngine->Camera()) {
+ TRAPD(err, m_cameraEngine->Camera()->SetBrightnessL(value));
+ setError(err, tr("Failed to set brightness."));
+ } else {
+ setError(KErrNotReady, tr("Unexpected camera error."));
+ }
+}
+
+ QCameraImageProcessing::WhiteBalanceMode S60ImageCaptureSession::whiteBalanceMode()
+{
+ if (m_cameraEngine && m_cameraEngine->Camera()) {
+ CCamera::TWhiteBalance mode = m_cameraEngine->Camera()->WhiteBalance();
+ switch(mode) {
+ case CCamera::EWBAuto:
+ return QCameraImageProcessing::WhiteBalanceAuto;
+ case CCamera::EWBDaylight:
+ return QCameraImageProcessing::WhiteBalanceSunlight;
+ case CCamera::EWBCloudy:
+ return QCameraImageProcessing::WhiteBalanceCloudy;
+ case CCamera::EWBTungsten:
+ return QCameraImageProcessing::WhiteBalanceTungsten;
+ case CCamera::EWBFluorescent:
+ return QCameraImageProcessing::WhiteBalanceFluorescent;
+ case CCamera::EWBFlash:
+ return QCameraImageProcessing::WhiteBalanceFlash;
+ case CCamera::EWBBeach:
+ return QCameraImageProcessing::WhiteBalanceSunset;
+ case CCamera::EWBManual:
+ return QCameraImageProcessing::WhiteBalanceManual;
+ case CCamera::EWBShade:
+ return QCameraImageProcessing::WhiteBalanceShade;
+
+ default:
+ return QCameraImageProcessing::WhiteBalanceAuto;
+ }
+ }
+
+ return QCameraImageProcessing::WhiteBalanceAuto;
+}
+
+void S60ImageCaptureSession::setWhiteBalanceMode( QCameraImageProcessing::WhiteBalanceMode mode)
+{
+ TRAPD(err, doSetWhiteBalanceModeL(mode));
+ setError(err, tr("Failed to set white balance mode."));
+}
+
+void S60ImageCaptureSession::doSetWhiteBalanceModeL( QCameraImageProcessing::WhiteBalanceMode mode)
+{
+ if (m_cameraEngine && m_cameraEngine->Camera()) {
+ CCamera* camera = m_cameraEngine->Camera();
+ switch(mode) {
+ case QCameraImageProcessing::WhiteBalanceAuto:
+ camera->SetWhiteBalanceL(CCamera::EWBAuto);
+ break;
+ case QCameraImageProcessing::WhiteBalanceSunlight:
+ camera->SetWhiteBalanceL(CCamera::EWBDaylight);
+ break;
+ case QCameraImageProcessing::WhiteBalanceCloudy:
+ camera->SetWhiteBalanceL(CCamera::EWBCloudy);
+ break;
+ case QCameraImageProcessing::WhiteBalanceTungsten:
+ camera->SetWhiteBalanceL(CCamera::EWBTungsten);
+ break;
+ case QCameraImageProcessing::WhiteBalanceFluorescent:
+ camera->SetWhiteBalanceL(CCamera::EWBFluorescent);
+ break;
+ case QCameraImageProcessing::WhiteBalanceFlash:
+ camera->SetWhiteBalanceL(CCamera::EWBFlash);
+ break;
+ case QCameraImageProcessing::WhiteBalanceSunset:
+ camera->SetWhiteBalanceL(CCamera::EWBBeach);
+ break;
+ case QCameraImageProcessing::WhiteBalanceManual:
+ camera->SetWhiteBalanceL(CCamera::EWBManual);
+ break;
+ case QCameraImageProcessing::WhiteBalanceShade:
+ camera->SetWhiteBalanceL(CCamera::EWBShade);
+ break;
+
+ default:
+ setError(KErrNotSupported, tr("Requested white balance mode is not suported"));
+ break;
+ }
+ } else {
+ setError(KErrNotReady, tr("Unexpected camera error."));
+ }
+}
+
+bool S60ImageCaptureSession::isWhiteBalanceModeSupported(QCameraImageProcessing::WhiteBalanceMode mode) const
+{
+ if (m_cameraEngine) {
+ TInt supportedModes = m_cameraInfo->iWhiteBalanceModesSupported;
+ switch (mode) {
+ case QCameraImageProcessing::WhiteBalanceManual:
+ if (supportedModes & CCamera::EWBManual)
+ return true;
+ else
+ return false;
+ case QCameraImageProcessing::WhiteBalanceAuto:
+ if (supportedModes & CCamera::EWBAuto)
+ return true;
+ else
+ return false;
+ case QCameraImageProcessing::WhiteBalanceSunlight:
+ if (supportedModes & CCamera::EWBDaylight)
+ return true;
+ else
+ return false;
+ case QCameraImageProcessing::WhiteBalanceCloudy:
+ if (supportedModes & CCamera::EWBCloudy)
+ return true;
+ else
+ return false;
+ case QCameraImageProcessing::WhiteBalanceShade:
+ if (supportedModes & CCamera::EWBShade)
+ return true;
+ else
+ return false;
+ case QCameraImageProcessing::WhiteBalanceTungsten:
+ if (supportedModes & CCamera::EWBTungsten)
+ return true;
+ else
+ return false;
+ case QCameraImageProcessing::WhiteBalanceFluorescent:
+ if (supportedModes & CCamera::EWBFluorescent)
+ return true;
+ else
+ return false;
+ case QCameraImageProcessing::WhiteBalanceIncandescent: // Not available in Symbian
+ return false;
+ case QCameraImageProcessing::WhiteBalanceFlash:
+ if (supportedModes & CCamera::EWBFlash)
+ return true;
+ else
+ return false;
+ case QCameraImageProcessing::WhiteBalanceSunset:
+ if (supportedModes & CCamera::EWBBeach)
+ return true;
+ else
+ return false;
+
+ default:
+ return false;
+ }
+ }
+
+ return false;
+}
+
+/*
+ * ====================
+ * S60 3.1 AutoFocosing
+ * ====================
+ */
+bool S60ImageCaptureSession::isFocusSupported() const
+{
+ return m_cameraEngine->IsAutoFocusSupported();
+}
+
+void S60ImageCaptureSession::startFocus()
+{
+ if (m_cameraEngine) {
+ TRAPD(err, m_cameraEngine->StartFocusL());
+ setError(err, tr("Failed to start focusing."));
+ }
+ else
+ setError(KErrNotReady, tr("Unexpected camera error."));
+}
+
+void S60ImageCaptureSession::cancelFocus()
+{
+ if (m_cameraEngine) {
+ TRAPD(err, m_cameraEngine->FocusCancel());
+ setError(err, tr("Failed to cancel focusing."));
+ }
+ else
+ setError(KErrNotReady, tr("Unexpected camera error."));
+}
+
+void S60ImageCaptureSession::handleImageDecoded(int error)
+{
+ // Delete unneeded objects
+ if (m_imageDecoder) {
+ delete m_imageDecoder;
+ m_imageDecoder = 0;
+ }
+ if (m_fileSystemAccess) {
+ m_fileSystemAccess->Close();
+ delete m_fileSystemAccess;
+ m_fileSystemAccess = 0;
+ }
+
+ // Check status of decoding
+ if (error != KErrNone) {
+ if (m_previewBitmap) {
+ m_previewBitmap->Reset();
+ delete m_previewBitmap;
+ m_previewBitmap = 0;
+ }
+ releaseImageBuffer();
+ if (m_previewInWaitLoop) {
+ CActiveScheduler::Stop(); // Notify to continue execution of next Preview Image generation
+ m_previewInWaitLoop = false; // Reset
+ }
+ setError(error, tr("Preview creation failed."));
+ return;
+ }
+
+ m_previewDecodingOngoing = false;
+
+ QPixmap prevPixmap = QPixmap::fromSymbianCFbsBitmap(m_previewBitmap);
+ QImage preview = prevPixmap.toImage();
+
+ if (m_previewBitmap) {
+ m_previewBitmap->Reset();
+ delete m_previewBitmap;
+ m_previewBitmap = 0;
+ }
+
+ QT_TRYCATCH_LEAVING( emit imageCaptured(m_currentImageId, preview) );
+
+ // Release image resources (if not already done)
+ releaseImageBuffer();
+
+ if (m_previewInWaitLoop) {
+ CActiveScheduler::Stop(); // Notify to continue execution of next Preview Image generation
+ m_previewInWaitLoop = false; // Reset
+ }
+}
+
+void S60ImageCaptureSession::handleImageEncoded(int error)
+{
+ // Check status of encoding
+ if (error != KErrNone) {
+ releaseImageBuffer();
+ if (m_previewInWaitLoop) {
+ CActiveScheduler::Stop(); // Notify to continue execution of next Preview Image generation
+ m_previewInWaitLoop = false; // Reset
+ }
+ setError(error, tr("Saving captured image to file failed."));
+ return;
+ } else {
+ QT_TRYCATCH_LEAVING( emit imageSaved(m_currentImageId, m_stillCaptureFileName) );
+ }
+
+ if (m_imageEncoder) {
+ delete m_imageEncoder;
+ m_imageEncoder = 0;
+ }
+
+#ifndef ECAM_PREVIEW_API
+ // Start preview generation
+ TInt previewError = KErrNone;
+ TFileName fileName = convertImagePath();
+ TRAP(previewError, m_imageDecoder = S60ImageCaptureDecoder::FileNewL(this, m_fileSystemAccess, &fileName));
+ if (previewError) {
+ setError(previewError, tr("Failed to create preview image."));
+ return;
+ }
+
+ // Set proper Preview Size
+ TSize scaledSize((m_captureSize.width() / KSnapshotDownScaleFactor), (m_captureSize.height() / KSnapshotDownScaleFactor));
+ if (scaledSize.iWidth < KSnapshotMinWidth || scaledSize.iHeight < KSnapshotMinHeight)
+ scaledSize.SetSize((m_captureSize.width() / (KSnapshotDownScaleFactor/2)), (m_captureSize.height() / (KSnapshotDownScaleFactor/2)));
+ if (scaledSize.iWidth < KSnapshotMinWidth || scaledSize.iHeight < KSnapshotMinHeight)
+ scaledSize.SetSize((m_captureSize.width() / (KSnapshotDownScaleFactor/4)), (m_captureSize.height() / (KSnapshotDownScaleFactor/4)));
+ if (scaledSize.iWidth < KSnapshotMinWidth || scaledSize.iHeight < KSnapshotMinHeight)
+ scaledSize.SetSize(m_captureSize.width(), m_captureSize.height());
+
+ TFrameInfo *info = m_imageDecoder->frameInfo();
+ if (!info) {
+ setError(KErrGeneral, tr("Preview image creation failed."));
+ return;
+ }
+
+ m_previewBitmap = new CFbsBitmap;
+ if (!m_previewBitmap) {
+ setError(KErrNoMemory, tr("Failed to create preview image."));
+ return;
+ }
+ previewError = m_previewBitmap->Create(scaledSize, info->iFrameDisplayMode);
+ if (previewError) {
+ setError(previewError, tr("Preview creation failed."));
+ return;
+ }
+
+ // Jpeg decoding completes in handleImageDecoded()
+ m_imageDecoder->decode(m_previewBitmap);
+#endif // ECAM_PREVIEW_API
+
+ // Buffer can be released since Preview is created from file
+ releaseImageBuffer();
+
+ // Inform that we can continue taking more pictures
+ QT_TRYCATCH_LEAVING( emit readyForCaptureChanged(true) );
+}
+
+#ifdef ECAM_PREVIEW_API
+void S60ImageCaptureSession::MceoPreviewReady(CFbsBitmap& aPreview)
+{
+ QPixmap previewPixmap = QPixmap::fromSymbianCFbsBitmap(&aPreview);
+ QImage preview = previewPixmap.toImage();
+
+ // Notify preview availability
+ emit imageCaptured(m_currentImageId, preview);
+}
+#endif // ECAM_PREVIEW_API
+
+// End of file
+
diff --git a/src/plugins/symbian/ecam/s60imagecapturesession.h b/src/plugins/symbian/ecam/s60imagecapturesession.h
new file mode 100644
index 000000000..9cae05fc9
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60imagecapturesession.h
@@ -0,0 +1,359 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef S60IMAGECAPTURESESSION_H
+#define S60IMAGECAPTURESESSION_H
+
+#include <QtCore/qurl.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qmap.h>
+#include <QtGui/qicon.h>
+
+#include <qcamera.h>
+#include <qcamerafocus.h>
+#include <qcameraimagecapture.h>
+#include <qvideoframe.h>
+
+#include "s60camerasettings.h"
+#include "s60cameraengine.h"
+#include "s60cameraengineobserver.h"
+#include "s60cameraconstants.h" // Default Jpeg Quality
+
+#include <icl/imagedata.h> // TFrameInfo
+
+QT_USE_NAMESPACE
+
+class S60CameraService;
+class CImageDecoder;
+class CImageEncoder;
+class CFrameImageData;
+class RFs;
+class S60ImageCaptureSession;
+
+/*
+ * This class implements asynchronous image decoding service for the
+ * S60ImageCaptureSession.
+ */
+class S60ImageCaptureDecoder : public CActive
+{
+public: // Static Contructor & Destructor
+
+ static S60ImageCaptureDecoder* FileNewL(S60ImageCaptureSession *imageSession = 0,
+ RFs *fileSystemAccess = 0,
+ const TDesC16 *fileName = 0);
+ static S60ImageCaptureDecoder* DataNewL(S60ImageCaptureSession *imageSession = 0,
+ RFs *fileSystemAccess = 0,
+ const TDesC8 *data = 0);
+ ~S60ImageCaptureDecoder();
+
+public: // Operations
+
+ void decode(CFbsBitmap *destBitmap);
+ TFrameInfo *frameInfo();
+
+protected: // CActive
+
+ void RunL();
+ void DoCancel();
+ TInt RunError(TInt aError);
+
+protected: // Protected constructors
+
+ S60ImageCaptureDecoder(S60ImageCaptureSession *imageSession,
+ RFs *fileSystemAccess,
+ const TDesC8 *data,
+ const TDesC16 *fileName);
+ void ConstructL(const bool fileInput = false);
+
+private: // Data
+
+ S60ImageCaptureSession *m_imageSession;
+ CImageDecoder *m_imageDecoder;
+ RFs *m_fs;
+ const TDesC8 *m_jpegImageData;
+ const TDesC16 *m_jpegImageFile;
+ bool m_fileInput;
+ TFrameInfo m_frameInfo;
+
+};
+
+//=============================================================================
+
+/*
+ * This class implements asynchronous image encoding service for the
+ * S60ImageCaptureSession.
+ */
+class S60ImageCaptureEncoder : public CActive
+{
+public: // Static Contructor & Destructor
+
+ static S60ImageCaptureEncoder* NewL(S60ImageCaptureSession *imageSession = 0,
+ RFs *fileSystemAccess = 0,
+ const TDesC16 *fileName = 0,
+ TInt jpegQuality = KDefaultImageQuality);
+ ~S60ImageCaptureEncoder();
+
+public: // Operations
+
+ void encode(CFbsBitmap *sourceBitmap);
+
+protected: // CActive
+
+ void RunL();
+ void DoCancel();
+ TInt RunError(TInt aError);
+
+protected: // Protected constructors
+
+ S60ImageCaptureEncoder(S60ImageCaptureSession *imageSession,
+ RFs *fileSystemAccess,
+ const TDesC16 *fileName,
+ TInt jpegQuality);
+ void ConstructL();
+
+private: // Data
+
+ S60ImageCaptureSession *m_imageSession;
+ CImageEncoder *m_imageEncoder;
+ RFs *m_fileSystemAccess;
+ const TDesC16 *m_fileName;
+ CFrameImageData *m_frameImageData;
+ TInt m_jpegQuality;
+
+};
+
+//=============================================================================
+
+/*
+ * Session handling all image capture activities.
+ */
+class S60ImageCaptureSession : public QObject,
+#ifdef ECAM_PREVIEW_API
+ public MCameraPreviewObserver,
+#endif // ECAM_PREVIEW_API
+ public MCameraEngineImageCaptureObserver
+{
+ Q_OBJECT
+
+public: // Enums
+
+ enum ImageCaptureState {
+ EImageCaptureNotPrepared = 0, // 0 - ImageCapture has not been prepared
+ EImageCapturePrepared, // 1 - ImageCapture has been prepared
+ EImageCaptureCapturing, // 2 - Image capture ongoing
+ EImageCaptureWritingImage // 3 - Image captured and image writing to file ongoing
+ };
+
+public: // Constructor & Destructor
+
+ S60ImageCaptureSession(QObject *parent = 0);
+ ~S60ImageCaptureSession();
+
+public: // Methods
+
+ void setError(const TInt error, const QString &description, const bool captureError = false);
+ int currentImageId() const;
+
+ bool isDeviceReady();
+ void setCameraHandle(CCameraEngine* camerahandle);
+ void setCurrentDevice(TInt deviceindex);
+ void notifySettingsSet();
+
+ // Ecam Advanced Settings
+ S60CameraSettings* advancedSettings();
+ void deleteAdvancedSettings();
+
+ // Controls
+ int prepareImageCapture();
+ void releaseImageCapture();
+ int capture(const QString &fileName);
+ void cancelCapture();
+ void releaseImageBuffer();
+
+ // Image Resolution
+ QSize captureSize() const;
+ QSize minimumCaptureSize();
+ QSize maximumCaptureSize();
+ QList<QSize> supportedCaptureSizesForCodec(const QString &codecName);
+ void setCaptureSize(const QSize &size);
+
+ // Image Codec
+ QStringList supportedImageCaptureCodecs();
+ QString imageCaptureCodec();
+ void setImageCaptureCodec(const QString &codecName);
+ QString imageCaptureCodecDescription(const QString &codecName);
+
+ // Image Quality
+ QtMultimediaKit::EncodingQuality captureQuality() const;
+ void setCaptureQuality(const QtMultimediaKit::EncodingQuality &quality);
+
+ // S60 3.1 Focus Control (S60 3.2 and later via S60CameraSettings class)
+ bool isFocusSupported() const;
+ void startFocus();
+ void cancelFocus();
+
+ // Zoom Control
+ qreal maximumZoom();
+ qreal minZoom();
+ qreal maxDigitalZoom();
+ void doSetZoomFactorL(qreal optical, qreal digital);
+ qreal opticalZoomFactor();
+ qreal digitalZoomFactor();
+
+ // Exposure Mode Control
+ QCameraExposure::ExposureMode exposureMode();
+ void setExposureMode(QCameraExposure::ExposureMode mode);
+ bool isExposureModeSupported(QCameraExposure::ExposureMode mode) const;
+
+ // Flash Mode Control
+ QCameraExposure::FlashMode flashMode();
+ void setFlashMode(QCameraExposure::FlashModes mode);
+ QCameraExposure::FlashModes supportedFlashModes();
+
+ // Contrast Control
+ int contrast() const;
+ void setContrast(int value);
+
+ // Brightness Control
+ int brightness() const;
+ void setBrightness(int value);
+
+ // White Balance Mode Control
+ QCameraImageProcessing::WhiteBalanceMode whiteBalanceMode();
+ void setWhiteBalanceMode(QCameraImageProcessing::WhiteBalanceMode mode);
+ bool isWhiteBalanceModeSupported(QCameraImageProcessing::WhiteBalanceMode mode) const;
+
+public: // Image Decoding & Encoding Notifications
+
+ void handleImageDecoded(int error);
+ void handleImageEncoded(int error);
+
+protected: // MCameraEngineObserver
+
+ void MceoFocusComplete();
+ void MceoCapturedDataReady(TDesC8* aData);
+ void MceoCapturedBitmapReady(CFbsBitmap* aBitmap);
+ void MceoHandleError(TCameraEngineError aErrorType, TInt aError);
+
+#ifdef ECAM_PREVIEW_API
+protected: // MCameraPreviewObserver
+
+ void MceoPreviewReady(CFbsBitmap& aPreview);
+#endif // ECAM_PREVIEW_API
+
+private: // Internal
+
+ QCameraImageCapture::Error fromSymbianErrorToQtMultimediaError(int aError);
+
+ void initializeImageCaptureSettings();
+ void resetSession(bool errorHandling = false);
+
+ CCamera::TFormat selectFormatForCodec(const QString &codec);
+ CCamera::TFormat defaultImageFormat();
+ bool queryCurrentCameraInfo();
+ QMap<QString, int> formatMap();
+ QMap<QString, QString> codecDescriptionMap();
+ void updateImageCaptureFormats();
+
+ void doSetWhiteBalanceModeL(QCameraImageProcessing::WhiteBalanceMode mode);
+
+ void doSetFlashModeL(QCameraExposure::FlashModes mode);
+ void doSetExposureModeL(QCameraExposure::ExposureMode mode);
+
+ void saveImageL(TDesC8 *aData, TFileName &aPath);
+ void processFileName(const QString &fileName);
+ TFileName convertImagePath();
+
+signals: // Notifications
+
+ void stateChanged(QCamera::State);
+ void advancedSettingChanged();
+ void captureSizeChanged(const QSize&);
+
+ // Error signals
+ void cameraError(int, const QString&); // For QCamera::error
+ void captureError(int, int, const QString&); // For QCameraImageCapture::error
+
+ // Capture notifications
+ void readyForCaptureChanged(bool);
+ void imageExposed(int);
+ void imageCaptured(const int, const QImage&);
+ void imageSaved(const int, const QString&);
+
+ // Focus notifications
+ void focusStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason);
+
+private slots: // Internal Slots
+
+ void cameraStatusChanged(QCamera::Status);
+
+private: // Data
+
+ CCameraEngine *m_cameraEngine;
+ S60CameraSettings *m_advancedSettings;
+ mutable TCameraInfo *m_cameraInfo;
+ CFbsBitmap *m_previewBitmap;
+ CActiveScheduler *m_activeScheduler;
+ RFs *m_fileSystemAccess;
+ S60ImageCaptureDecoder *m_imageDecoder;
+ S60ImageCaptureEncoder *m_imageEncoder;
+ mutable int m_error; // Symbian ErrorCode
+ TInt m_activeDeviceIndex;
+ bool m_cameraStarted;
+ ImageCaptureState m_icState;
+ QStringList m_supportedImageCodecs;
+ QString m_currentCodec;
+ CCamera::TFormat m_currentFormat;
+ QSize m_captureSize;
+ int m_symbianImageQuality;
+ bool m_captureSettingsSet;
+ QString m_stillCaptureFileName;
+ QString m_requestedStillCaptureFileName;
+ mutable int m_currentImageId;
+ QList<uint> m_formats;
+ // This indicates that image capture should be triggered right after
+ // camera and image setting initialization has completed
+ bool m_captureWhenReady;
+ bool m_previewDecodingOngoing;
+ bool m_previewInWaitLoop;
+};
+
+#endif // S60IMAGECAPTURESESSION_H
diff --git a/src/plugins/symbian/ecam/s60imageencodercontrol.cpp b/src/plugins/symbian/ecam/s60imageencodercontrol.cpp
new file mode 100644
index 000000000..bfbf8d36b
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60imageencodercontrol.cpp
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qstring.h>
+
+#include "s60imageencodercontrol.h"
+#include "s60imagecapturesession.h"
+
+S60ImageEncoderControl::S60ImageEncoderControl(QObject *parent) :
+ QImageEncoderControl(parent)
+{
+}
+
+S60ImageEncoderControl::S60ImageEncoderControl(S60ImageCaptureSession *session, QObject *parent) :
+ QImageEncoderControl(parent)
+{
+ m_session = session;
+}
+
+S60ImageEncoderControl::~S60ImageEncoderControl()
+{
+}
+
+QList<QSize> S60ImageEncoderControl::supportedResolutions(
+ const QImageEncoderSettings &settings, bool *continuous) const
+{
+ QList<QSize> resolutions = m_session->supportedCaptureSizesForCodec(settings.codec());
+
+ // Discrete resolutions are returned
+ if (continuous)
+ *continuous = false;
+
+ return resolutions;
+}
+QStringList S60ImageEncoderControl::supportedImageCodecs() const
+{
+ return m_session->supportedImageCaptureCodecs();
+}
+
+QString S60ImageEncoderControl::imageCodecDescription(const QString &codec) const
+{
+ return m_session->imageCaptureCodecDescription(codec);
+}
+
+QImageEncoderSettings S60ImageEncoderControl::imageSettings() const
+{
+ // Update setting values from session
+ QImageEncoderSettings settings;
+ settings.setCodec(m_session->imageCaptureCodec());
+ settings.setResolution(m_session->captureSize());
+ settings.setQuality(m_session->captureQuality());
+
+ return settings;
+}
+void S60ImageEncoderControl::setImageSettings(const QImageEncoderSettings &settings)
+{
+ // Notify that settings have been implicitly set and there's no need to
+ // initialize them in case camera is changed
+ m_session->notifySettingsSet();
+
+ if (!settings.isNull()) {
+ if (!settings.codec().isEmpty()) {
+ if (settings.resolution() != QSize(-1,-1)) { // Codec, Resolution & Quality
+ m_session->setImageCaptureCodec(settings.codec());
+ m_session->setCaptureSize(settings.resolution());
+ m_session->setCaptureQuality(settings.quality());
+ } else { // Codec and Quality
+ m_session->setImageCaptureCodec(settings.codec());
+ m_session->setCaptureQuality(settings.quality());
+ }
+ } else {
+ if (settings.resolution() != QSize(-1,-1)) { // Resolution & Quality
+ m_session->setCaptureSize(settings.resolution());
+ m_session->setCaptureQuality(settings.quality());
+ }
+ else // Only Quality
+ m_session->setCaptureQuality(settings.quality());
+ }
+
+ // Prepare ImageCapture with the settings and set error if needed
+ int prepareSuccess = m_session->prepareImageCapture();
+
+ // Preparation fails with KErrNotReady if camera has not been started.
+ // That can be ignored since settings are set internally in that case.
+ if (prepareSuccess != KErrNotReady && prepareSuccess != KErrNone)
+ m_session->setError(prepareSuccess, tr("Failure in preparation of image capture."));
+ }
+}
+
+// End of file
diff --git a/src/plugins/symbian/ecam/s60imageencodercontrol.h b/src/plugins/symbian/ecam/s60imageencodercontrol.h
new file mode 100644
index 000000000..99a308286
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60imageencodercontrol.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef S60IMAGEENCODERCONTROL_H
+#define S60IMAGEENCODERCONTROL_H
+
+#include <QtCore/qobject.h>
+#include "qimageencodercontrol.h"
+
+QT_USE_NAMESPACE
+
+class S60ImageCaptureSession;
+
+/*
+ * Control for setting encoding settings for the captured image.
+ */
+class S60ImageEncoderControl : public QImageEncoderControl
+{
+ Q_OBJECT
+
+public: // Contructors & Destructor
+
+ S60ImageEncoderControl(QObject *parent = 0);
+ S60ImageEncoderControl(S60ImageCaptureSession *session, QObject *parent = 0);
+ ~S60ImageEncoderControl();
+
+public: // QImageEncoderControl
+
+ // Codec
+ QStringList supportedImageCodecs() const;
+ QString imageCodecDescription(const QString &codec) const;
+
+ // Resolution
+ QList<QSize> supportedResolutions(const QImageEncoderSettings &settings,
+ bool *continuous = 0) const;
+
+ // Settings
+ QImageEncoderSettings imageSettings() const;
+ void setImageSettings(const QImageEncoderSettings &settings);
+
+private: // Data
+
+ S60ImageCaptureSession *m_session;
+};
+
+#endif // S60IMAGEENCODERCONTROL_H
diff --git a/src/plugins/symbian/ecam/s60mediacontainercontrol.cpp b/src/plugins/symbian/ecam/s60mediacontainercontrol.cpp
new file mode 100644
index 000000000..f0d20f4e3
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60mediacontainercontrol.cpp
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "s60mediacontainercontrol.h"
+#include "s60videocapturesession.h"
+#include "s60cameraconstants.h"
+
+S60MediaContainerControl::S60MediaContainerControl(QObject *parent):
+ QMediaContainerControl(parent)
+{
+}
+
+S60MediaContainerControl::S60MediaContainerControl(S60VideoCaptureSession *session, QObject *parent):
+ QMediaContainerControl(parent)
+{
+ m_session = session;
+
+ // Set default video container
+ m_supportedContainers = m_session->supportedVideoContainers();
+
+ if (!m_supportedContainers.isEmpty()) {
+ // Check if default container is supported
+ if (m_supportedContainers.indexOf(KMimeTypeDefaultContainer) != -1)
+ setContainerMimeType(KMimeTypeDefaultContainer);
+ // Otherwise use first in the list
+ else
+ setContainerMimeType(m_supportedContainers[0]); // First as default
+ } else {
+ m_session->setError(KErrGeneral, tr("No supported video containers found."));
+ }
+}
+
+S60MediaContainerControl::~S60MediaContainerControl()
+{
+ m_supportedContainers.clear();
+ m_containerDescriptions.clear();
+}
+
+QStringList S60MediaContainerControl::supportedContainers() const
+{
+ return m_session->supportedVideoContainers();
+}
+
+QString S60MediaContainerControl::containerMimeType() const
+{
+ return m_session->videoContainer();
+}
+
+void S60MediaContainerControl::setContainerMimeType(const QString &containerMimeType)
+{
+ m_session->setVideoContainer(containerMimeType);
+}
+
+QString S60MediaContainerControl::containerDescription(const QString &containerMimeType) const
+{
+ return m_session->videoContainerDescription(containerMimeType);
+}
+
+// End of file
diff --git a/src/plugins/symbian/ecam/s60mediacontainercontrol.h b/src/plugins/symbian/ecam/s60mediacontainercontrol.h
new file mode 100644
index 000000000..057b4bc43
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60mediacontainercontrol.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef S60MEDIACONTAINERCONTROL_H
+#define S60MEDIACONTAINERCONTROL_H
+
+#include <QtCore/qstringlist.h>
+#include <QtCore/qmap.h>
+#include <qmediacontainercontrol.h>
+
+QT_USE_NAMESPACE
+
+class S60VideoCaptureSession;
+
+/*
+ * Control for setting container (file format) for video recorded using
+ * QMediaRecorder.
+ */
+class S60MediaContainerControl : public QMediaContainerControl
+{
+ Q_OBJECT
+
+public: // Contructors & Destructor
+
+ S60MediaContainerControl(QObject *parent = 0);
+ S60MediaContainerControl(S60VideoCaptureSession *session, QObject *parent = 0);
+ virtual ~S60MediaContainerControl();
+
+public: // QMediaContainerControl
+
+ QStringList supportedContainers() const;
+ QString containerMimeType() const;
+ void setContainerMimeType(const QString &containerMimeType);
+
+ QString containerDescription(const QString &containerMimeType) const;
+
+private: // Data
+
+ S60VideoCaptureSession *m_session;
+ QStringList m_supportedContainers;
+ QMap<QString, QString> m_containerDescriptions;
+};
+
+#endif // S60MEDIACONTAINERCONTROL_H
diff --git a/src/plugins/symbian/ecam/s60mediarecordercontrol.cpp b/src/plugins/symbian/ecam/s60mediarecordercontrol.cpp
new file mode 100644
index 000000000..2a1394fa5
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60mediarecordercontrol.cpp
@@ -0,0 +1,187 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "s60cameraservice.h"
+#include "s60mediarecordercontrol.h"
+#include "s60cameracontrol.h"
+#include "s60videocapturesession.h"
+
+S60MediaRecorderControl::S60MediaRecorderControl(QObject *parent) :
+ QMediaRecorderControl(parent)
+{
+}
+
+S60MediaRecorderControl::S60MediaRecorderControl(S60CameraService *service,
+ S60VideoCaptureSession *session,
+ QObject *parent):
+ QMediaRecorderControl(parent),
+ m_state(QMediaRecorder::StoppedState) // Default RecorderState
+{
+ m_session = session;
+ m_service = service;
+ m_cameraControl = qobject_cast<S60CameraControl *>(m_service->requestControl(QCameraControl_iid));
+
+ // Connect signals
+ connect(m_session, SIGNAL(stateChanged(S60VideoCaptureSession::TVideoCaptureState)),
+ this, SLOT(updateState(S60VideoCaptureSession::TVideoCaptureState)));
+ connect(m_session, SIGNAL(positionChanged(qint64)), this, SIGNAL(durationChanged(qint64)));
+ connect(m_session, SIGNAL(mutedChanged(bool)), this, SIGNAL(mutedChanged(bool)));
+ connect(m_session, SIGNAL(error(int,const QString &)), this, SIGNAL(error(int,const QString &)));
+}
+
+S60MediaRecorderControl::~S60MediaRecorderControl()
+{
+ // Release requested control
+ if (m_cameraControl)
+ m_service->releaseControl(m_cameraControl);
+}
+
+QUrl S60MediaRecorderControl::outputLocation() const
+{
+ return m_session->outputLocation();
+}
+
+bool S60MediaRecorderControl::setOutputLocation(const QUrl& sink)
+{
+ // Output location can only be set in StoppedState
+ if (m_state == QMediaRecorder::StoppedState)
+ return m_session->setOutputLocation(sink);
+
+ // Do not signal error, but notify that setting was not effective
+ return false;
+}
+
+QMediaRecorder::State S60MediaRecorderControl::convertInternalStateToQtState(S60VideoCaptureSession::TVideoCaptureState aState) const
+{
+ QMediaRecorder::State state;
+
+ switch (aState) {
+ case S60VideoCaptureSession::ERecording:
+ state = QMediaRecorder::RecordingState;
+ break;
+ case S60VideoCaptureSession::EPaused:
+ state = QMediaRecorder::PausedState;
+ break;
+
+ default:
+ // All others
+ state = QMediaRecorder::StoppedState;
+ break;
+ }
+
+ return state;
+}
+
+void S60MediaRecorderControl::updateState(S60VideoCaptureSession::TVideoCaptureState state)
+{
+ QMediaRecorder::State newState = convertInternalStateToQtState(state);
+
+ if (m_state != newState) {
+ m_state = newState;
+ emit stateChanged(m_state);
+ }
+}
+
+QMediaRecorder::State S60MediaRecorderControl::state() const
+{
+ return m_state;
+}
+
+qint64 S60MediaRecorderControl::duration() const
+{
+ return m_session->position();
+}
+
+/*
+This method is called after encoder configuration is done.
+Encoder can load necessary resources at this point,
+to reduce delay before recording is started. Calling this method reduces the
+latency when calling record() to start video recording.
+*/
+void S60MediaRecorderControl::applySettings()
+{
+ m_session->applyAllSettings();
+}
+
+void S60MediaRecorderControl::record()
+{
+ if (m_state == QMediaRecorder::RecordingState)
+ return;
+
+ if (m_cameraControl && m_cameraControl->captureMode() != QCamera::CaptureVideo) {
+ emit error(QCamera::CameraError, tr("Video capture mode is not selected."));
+ return;
+ }
+
+ m_session->startRecording();
+}
+
+void S60MediaRecorderControl::pause()
+{
+ if (m_state != QMediaRecorder::RecordingState) {
+ // Discard
+ return;
+ }
+
+ m_session->pauseRecording();
+}
+
+void S60MediaRecorderControl::stop()
+{
+ if (m_state == QMediaRecorder::StoppedState) {
+ // Ignore
+ return;
+ }
+
+ m_session->stopRecording();
+}
+
+bool S60MediaRecorderControl::isMuted() const
+{
+ return m_session->isMuted();
+}
+
+void S60MediaRecorderControl::setMuted(bool muted)
+{
+ m_session->setMuted(muted);
+}
+
+// End of file
diff --git a/src/plugins/symbian/ecam/s60mediarecordercontrol.h b/src/plugins/symbian/ecam/s60mediarecordercontrol.h
new file mode 100644
index 000000000..5db7477bd
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60mediarecordercontrol.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef S60MEDIARECORDERCONTROL_H
+#define S60MEDIARECORDERCONTROL_H
+
+#include <QtCore/qurl.h>
+#include <qmediarecorder.h>
+#include <qmediarecordercontrol.h>
+
+#include "s60videocapturesession.h"
+
+QT_USE_NAMESPACE
+
+class S60VideoCaptureSession;
+class S60CameraService;
+class S60CameraControl;
+
+/*
+ * Control for video recording operations.
+ */
+class S60MediaRecorderControl : public QMediaRecorderControl
+{
+ Q_OBJECT
+
+public: // Contructors & Destructor
+
+ S60MediaRecorderControl(QObject *parent = 0);
+ S60MediaRecorderControl(S60CameraService *service,
+ S60VideoCaptureSession *session,
+ QObject *parent = 0);
+ ~S60MediaRecorderControl();
+
+public: // QMediaRecorderControl
+
+ QUrl outputLocation() const;
+ bool setOutputLocation(const QUrl &sink);
+
+ QMediaRecorder::State state() const;
+
+ qint64 duration() const;
+
+ bool isMuted() const;
+
+ void applySettings();
+
+/*
+Q_SIGNALS: // QMediaRecorderControl
+ void stateChanged(QMediaRecorder::State state);
+ void durationChanged(qint64 position);
+ void mutedChanged(bool muted);
+ void error(int error, const QString &errorString);
+*/
+
+public slots: // QMediaRecorderControl
+
+ void record();
+ void pause();
+ void stop();
+ void setMuted(bool);
+
+private:
+
+ QMediaRecorder::State convertInternalStateToQtState(
+ S60VideoCaptureSession::TVideoCaptureState aState) const;
+
+private slots:
+
+ void updateState(S60VideoCaptureSession::TVideoCaptureState state);
+
+private: // Data
+
+ S60VideoCaptureSession *m_session;
+ S60CameraService *m_service;
+ S60CameraControl *m_cameraControl;
+ QMediaRecorder::State m_state;
+
+};
+
+#endif // S60MEDIARECORDERCONTROL_H
diff --git a/src/plugins/symbian/ecam/s60videocapturesession.cpp b/src/plugins/symbian/ecam/s60videocapturesession.cpp
new file mode 100644
index 000000000..7158f8696
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60videocapturesession.cpp
@@ -0,0 +1,2995 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qstring.h>
+#include <QtCore/qdir.h>
+#include <QtCore/qtimer.h>
+
+#include "s60videocapturesession.h"
+#include "s60cameraconstants.h"
+
+#include <utf.h>
+#include <bautils.h>
+
+#ifdef S60_DEVVIDEO_RECORDING_SUPPORTED
+#include <mmf/devvideo/devvideorecord.h>
+#endif
+
+S60VideoCaptureSession::S60VideoCaptureSession(QObject *parent) :
+ QObject(parent),
+ m_cameraEngine(0),
+ m_videoRecorder(0),
+ m_position(0),
+ m_error(KErrNone),
+ m_cameraStarted(false),
+ m_captureState(ENotInitialized), // Default state
+ m_sink(QUrl()),
+ m_requestedSink(QUrl()),
+ m_captureSettingsSet(false),
+ m_container(QString()),
+ m_requestedContainer(QString()),
+ m_muted(false),
+ m_maxClipSize(-1),
+ m_videoControllerMap(QHash<int, QHash<int,VideoFormatData> >()),
+ m_videoParametersForEncoder(QList<MaxResolutionRatesAndTypes>()),
+ m_openWhenReady(false),
+ m_prepareAfterOpenComplete(false),
+ m_startAfterPrepareComplete(false),
+ m_uncommittedSettings(false),
+ m_commitSettingsWhenReady(false)
+{
+#ifdef S60_DEVVIDEO_RECORDING_SUPPORTED
+ // Populate info of supported codecs, and their resolution, etc.
+ TRAPD(err, doPopulateVideoCodecsDataL());
+ setError(err, tr("Failed to gather video codec information."));
+#endif // S60_DEVVIDEO_RECORDING_SUPPORTED
+
+ initializeVideoCaptureSettings();
+
+ m_durationTimer = new QTimer;
+ m_durationTimer->setInterval(KDurationChangedInterval);
+ connect(m_durationTimer, SIGNAL(timeout()), this, SLOT(durationTimerTriggered()));
+}
+
+S60VideoCaptureSession::~S60VideoCaptureSession()
+{
+ if (m_captureState >= ERecording)
+ m_videoRecorder->Stop();
+
+ if (m_captureState >= EInitialized)
+ m_videoRecorder->Close();
+
+ if (m_videoRecorder) {
+ delete m_videoRecorder;
+ m_videoRecorder = 0;
+ }
+
+ if (m_durationTimer) {
+ delete m_durationTimer;
+ m_durationTimer = 0;
+ }
+
+ // Clear all data structures
+ foreach (MaxResolutionRatesAndTypes structure, m_videoParametersForEncoder) {
+ structure.frameRatePictureSizePair.clear();
+ structure.mimeTypes.clear();
+ }
+ m_videoParametersForEncoder.clear();
+
+ m_videoCodecList.clear();
+ m_audioCodecList.clear();
+
+ QList<TInt> controllers = m_videoControllerMap.keys();
+ for (int i = 0; i < controllers.size(); ++i) {
+ foreach(VideoFormatData data, m_videoControllerMap[controllers[i]]){
+ data.supportedMimeTypes.clear();
+ }
+ m_videoControllerMap[controllers[i]].clear();
+ }
+ m_videoControllerMap.clear();
+}
+
+/*
+ * This function can be used both internally and from Control classes using this session.
+ * The error notification will go to client application through QMediaRecorder error signal.
+ */
+void S60VideoCaptureSession::setError(const TInt error, const QString &description)
+{
+ if (error == KErrNone)
+ return;
+
+ m_error = error;
+ QMediaRecorder::Error recError = fromSymbianErrorToQtMultimediaError(m_error);
+
+ // Stop/Close/Reset only of other than "not supported" error
+ if (m_error != KErrNotSupported) {
+ if (m_captureState >= ERecording)
+ m_videoRecorder->Stop();
+
+ if (m_captureState >= EInitialized)
+ m_videoRecorder->Close();
+
+ // Reset state
+ if (m_captureState != ENotInitialized) {
+ if (m_durationTimer->isActive())
+ m_durationTimer->stop();
+ m_captureState = ENotInitialized;
+ emit stateChanged(m_captureState);
+ }
+ }
+
+ emit this->error(recError, description);
+
+ // Reset only of other than "not supported" error
+ if (m_error != KErrNotSupported)
+ resetSession(true);
+ else
+ m_error = KErrNone; // Reset error
+}
+
+QMediaRecorder::Error S60VideoCaptureSession::fromSymbianErrorToQtMultimediaError(int aError)
+{
+ switch(aError) {
+ case KErrNone:
+ return QMediaRecorder::NoError; // No errors have occurred
+ case KErrArgument:
+ case KErrNotSupported:
+ return QMediaRecorder::FormatError; // The feature/format is not supported
+ case KErrNoMemory:
+ case KErrNotFound:
+ case KErrBadHandle:
+ return QMediaRecorder::ResourceError; // Not able to use camera/recorder resources
+
+ default:
+ return QMediaRecorder::ResourceError; // Other error has occurred
+ }
+}
+
+/*
+ * This function applies all recording settings to make latency during the
+ * start of the recording as short as possible. After this it is not possible to
+ * set settings (inc. output location) before stopping the recording.
+ */
+void S60VideoCaptureSession::applyAllSettings()
+{
+ switch (m_captureState) {
+ case ENotInitialized:
+ case EInitializing:
+ m_commitSettingsWhenReady = true;
+ return;
+ case EInitialized:
+ setOutputLocation(QUrl());
+ m_prepareAfterOpenComplete = true;
+ return;
+ case EOpening:
+ m_prepareAfterOpenComplete = true;
+ return;
+ case EOpenComplete:
+ // Do nothing, ready to commit
+ break;
+ case EPreparing:
+ m_commitSettingsWhenReady = true;
+ return;
+ case EPrepared:
+ // Revert state internally, since logically applying settings means going
+ // from OpenComplete ==> Preparing ==> Prepared.
+ m_captureState = EOpenComplete;
+ break;
+ case ERecording:
+ case EPaused:
+ setError(KErrNotReady, tr("Cannot apply settings while recording."));
+ return;
+
+ default:
+ setError(KErrGeneral, tr("Unexpected camera error."));
+ return;
+ }
+
+ // Commit settings - State is now OpenComplete (possibly reverted from Prepared)
+ commitVideoEncoderSettings();
+
+ // If capture state has been changed to:
+ // * Opening: A different media container has been requested
+ // * Other: Failure during the setting committing
+ // ==> Return
+ if (m_captureState != EOpenComplete)
+ return;
+
+ // Start preparing
+ m_captureState = EPreparing;
+ emit stateChanged(m_captureState);
+
+ if (m_cameraEngine->IsCameraReady())
+ m_videoRecorder->Prepare();
+}
+
+void S60VideoCaptureSession::setCameraHandle(CCameraEngine* cameraHandle)
+{
+ m_cameraEngine = cameraHandle;
+
+ // Initialize settings for the new camera
+ initializeVideoCaptureSettings();
+
+ resetSession();
+}
+
+void S60VideoCaptureSession::notifySettingsSet()
+{
+ m_captureSettingsSet = true;
+}
+
+void S60VideoCaptureSession::doInitializeVideoRecorderL()
+{
+ if (m_captureState > ENotInitialized)
+ resetSession();
+
+ m_captureState = EInitializing;
+ emit stateChanged(m_captureState);
+
+ // Open Dummy file to be able to query supported settings
+ int cameraHandle = m_cameraEngine->Camera() ? m_cameraEngine->Camera()->Handle() : 0;
+
+ TUid controllerUid;
+ TUid formatUid;
+ selectController(m_requestedContainer, controllerUid, formatUid);
+
+ if (m_videoRecorder) {
+ // File open completes in MvruoOpenComplete
+ TRAPD(err, m_videoRecorder->OpenFileL(KDummyVideoFile, cameraHandle, controllerUid, formatUid));
+ setError(err, tr("Failed to initialize video recorder."));
+ m_container = m_requestedContainer;
+ } else {
+ setError(KErrNotReady, tr("Unexpected camera error."));
+ }
+}
+
+void S60VideoCaptureSession::resetSession(bool errorHandling)
+{
+ if (m_videoRecorder) {
+ delete m_videoRecorder;
+ m_videoRecorder = 0;
+ }
+
+ if (m_captureState != ENotInitialized) {
+ if (m_durationTimer->isActive())
+ m_durationTimer->stop();
+ m_captureState = ENotInitialized;
+ emit stateChanged(m_captureState);
+ }
+
+ // Reset error to be able to recover
+ m_error = KErrNone;
+
+ // Reset flags
+ m_openWhenReady = false;
+ m_prepareAfterOpenComplete = false;
+ m_startAfterPrepareComplete = false;
+ m_uncommittedSettings = false;
+ m_commitSettingsWhenReady = false;
+
+ TRAPD(err, m_videoRecorder = CVideoRecorderUtility::NewL(*this));
+ if (err) {
+ qWarning("Failed to create video recorder.");
+ if (errorHandling)
+ emit error(QMediaRecorder::ResourceError, tr("Failed to recover from video error."));
+ else
+ setError(err, tr("Failure in creation of video recorder device."));
+ return;
+ }
+
+ updateVideoCaptureContainers();
+}
+
+QList<QSize> S60VideoCaptureSession::supportedVideoResolutions(bool *continuous)
+{
+ QList<QSize> resolutions;
+
+ // Secondary Camera
+ if (m_cameraEngine->CurrentCameraIndex() != 0) {
+ TCameraInfo *info = m_cameraEngine->CameraInfo();
+ if (info) {
+ TInt videoResolutionCount = info->iNumVideoFrameSizesSupported;
+ CCamera *camera = m_cameraEngine->Camera();
+ if (camera) {
+ for (TInt i = 0; i < videoResolutionCount; ++i) {
+ TSize checkedResolution;
+ camera->EnumerateVideoFrameSizes(checkedResolution, i, CCamera::EFormatYUV420Planar);
+ QSize qtResolution(checkedResolution.iWidth, checkedResolution.iHeight);
+ if (!resolutions.contains(qtResolution))
+ resolutions.append(qtResolution);
+ }
+ } else {
+ setError(KErrGeneral, tr("Could not query supported video resolutions."));
+ }
+ } else {
+ setError(KErrGeneral, tr("Could not query supported video resolutions."));
+ }
+
+ // Primary Camera
+ } else {
+
+ if (m_videoParametersForEncoder.count() > 0) {
+
+ // Also arbitrary resolutions are supported
+ if (continuous)
+ *continuous = true;
+
+ // Append all supported resolutions to the list
+ foreach (MaxResolutionRatesAndTypes parameters, m_videoParametersForEncoder)
+ for (int i = 0; i < parameters.frameRatePictureSizePair.count(); ++i)
+ if (!resolutions.contains(parameters.frameRatePictureSizePair[i].frameSize))
+ resolutions.append(parameters.frameRatePictureSizePair[i].frameSize);
+ }
+ }
+
+#ifdef Q_CC_NOKIAX86 // Emulator
+ resolutions << QSize(160, 120);
+ resolutions << QSize(352, 288);
+ resolutions << QSize(640,480);
+#endif // Q_CC_NOKIAX86
+
+ return resolutions;
+}
+
+QList<QSize> S60VideoCaptureSession::supportedVideoResolutions(const QVideoEncoderSettings &settings, bool *continuous)
+{
+ QList<QSize> supportedFrameSizes;
+
+ // Secondary Camera
+ if (m_cameraEngine->CurrentCameraIndex() != 0) {
+ TCameraInfo *info = m_cameraEngine->CameraInfo();
+ if (info) {
+ TInt videoResolutionCount = info->iNumVideoFrameSizesSupported;
+ CCamera *camera = m_cameraEngine->Camera();
+ if (camera) {
+ for (TInt i = 0; i < videoResolutionCount; ++i) {
+ TSize checkedResolution;
+ camera->EnumerateVideoFrameSizes(checkedResolution, i, CCamera::EFormatYUV420Planar);
+ QSize qtResolution(checkedResolution.iWidth, checkedResolution.iHeight);
+ if (!supportedFrameSizes.contains(qtResolution))
+ supportedFrameSizes.append(qtResolution);
+ }
+ } else {
+ setError(KErrGeneral, tr("Could not query supported video resolutions."));
+ }
+ } else {
+ setError(KErrGeneral, tr("Could not query supported video resolutions."));
+ }
+
+ // Primary Camera
+ } else {
+
+ if (settings.codec().isEmpty())
+ return supportedFrameSizes;
+
+ if (!m_videoCodecList.contains(settings.codec(), Qt::CaseInsensitive))
+ return supportedFrameSizes;
+
+ // Also arbitrary resolutions are supported
+ if (continuous)
+ *continuous = true;
+
+ // Find maximum resolution (using defined framerate if set)
+ for (int i = 0; i < m_videoParametersForEncoder.count(); ++i) {
+ // Check if encoder supports the requested codec
+ if (!m_videoParametersForEncoder[i].mimeTypes.contains(settings.codec(), Qt::CaseInsensitive))
+ continue;
+
+ foreach (SupportedFrameRatePictureSize pair, m_videoParametersForEncoder[i].frameRatePictureSizePair) {
+ if (!supportedFrameSizes.contains(pair.frameSize)) {
+ QSize maxForMime = maximumResolutionForMimeType(settings.codec());
+ if (settings.frameRate() != 0) {
+ if (settings.frameRate() <= pair.frameRate) {
+ if ((pair.frameSize.width() * pair.frameSize.height()) <= (maxForMime.width() * maxForMime.height()))
+ supportedFrameSizes.append(pair.frameSize);
+ }
+ } else {
+ if ((pair.frameSize.width() * pair.frameSize.height()) <= (maxForMime.width() * maxForMime.height()))
+ supportedFrameSizes.append(pair.frameSize);
+ }
+ }
+ }
+ }
+ }
+
+#ifdef Q_CC_NOKIAX86 // Emulator
+ supportedFrameSizes << QSize(160, 120);
+ supportedFrameSizes << QSize(352, 288);
+ supportedFrameSizes << QSize(640,480);
+#endif
+
+ return supportedFrameSizes;
+}
+
+QList<qreal> S60VideoCaptureSession::supportedVideoFrameRates(bool *continuous)
+{
+ QList<qreal> supportedRatesList;
+
+ if (m_videoParametersForEncoder.count() > 0) {
+ // Insert min and max to the list
+ supportedRatesList.append(1.0); // Use 1fps as sensible minimum
+ qreal foundMaxFrameRate(0.0);
+
+ // Also arbitrary framerates are supported
+ if (continuous)
+ *continuous = true;
+
+ // Find max framerate
+ foreach (MaxResolutionRatesAndTypes parameters, m_videoParametersForEncoder) {
+ for (int i = 0; i < parameters.frameRatePictureSizePair.count(); ++i) {
+ qreal maxFrameRate = parameters.frameRatePictureSizePair[i].frameRate;
+ if (maxFrameRate > foundMaxFrameRate)
+ foundMaxFrameRate = maxFrameRate;
+ }
+ }
+
+ supportedRatesList.append(foundMaxFrameRate);
+ }
+
+ // Add also other standard framerates to the list
+ if (!supportedRatesList.isEmpty()) {
+ if (supportedRatesList.last() > 30.0) {
+ if (!supportedRatesList.contains(30.0))
+ supportedRatesList.insert(1, 30.0);
+ }
+ if (supportedRatesList.last() > 25.0) {
+ if (!supportedRatesList.contains(25.0))
+ supportedRatesList.insert(1, 25.0);
+ }
+ if (supportedRatesList.last() > 15.0) {
+ if (!supportedRatesList.contains(15.0))
+ supportedRatesList.insert(1, 15.0);
+ }
+ if (supportedRatesList.last() > 10.0) {
+ if (!supportedRatesList.contains(10))
+ supportedRatesList.insert(1, 10.0);
+ }
+ }
+
+#ifdef Q_CC_NOKIAX86 // Emulator
+ supportedRatesList << 30.0 << 25.0 << 15.0 << 10.0 << 5.0;
+#endif
+
+ return supportedRatesList;
+}
+
+QList<qreal> S60VideoCaptureSession::supportedVideoFrameRates(const QVideoEncoderSettings &settings, bool *continuous)
+{
+ QList<qreal> supportedFrameRates;
+
+ if (settings.codec().isEmpty())
+ return supportedFrameRates;
+ if (!m_videoCodecList.contains(settings.codec(), Qt::CaseInsensitive))
+ return supportedFrameRates;
+
+ // Also arbitrary framerates are supported
+ if (continuous)
+ *continuous = true;
+
+ // Find maximum framerate (using defined resolution if set)
+ for (int i = 0; i < m_videoParametersForEncoder.count(); ++i) {
+ // Check if encoder supports the requested codec
+ if (!m_videoParametersForEncoder[i].mimeTypes.contains(settings.codec(), Qt::CaseInsensitive))
+ continue;
+
+ foreach (SupportedFrameRatePictureSize pair, m_videoParametersForEncoder[i].frameRatePictureSizePair) {
+ if (!supportedFrameRates.contains(pair.frameRate)) {
+ qreal maxRateForMime = maximumFrameRateForMimeType(settings.codec());
+ if (settings.resolution().width() != 0 && settings.resolution().height() != 0) {
+ if((settings.resolution().width() * settings.resolution().height()) <= (pair.frameSize.width() * pair.frameSize.height())) {
+ if (pair.frameRate <= maxRateForMime)
+ supportedFrameRates.append(pair.frameRate);
+ }
+ } else {
+ if (pair.frameRate <= maxRateForMime)
+ supportedFrameRates.append(pair.frameRate);
+ }
+ }
+ }
+ }
+
+ // Add also other standard framerates to the list
+ if (!supportedFrameRates.isEmpty()) {
+ if (supportedFrameRates.last() > 30.0) {
+ if (!supportedFrameRates.contains(30.0))
+ supportedFrameRates.insert(1, 30.0);
+ }
+ if (supportedFrameRates.last() > 25.0) {
+ if (!supportedFrameRates.contains(25.0))
+ supportedFrameRates.insert(1, 25.0);
+ }
+ if (supportedFrameRates.last() > 15.0) {
+ if (!supportedFrameRates.contains(15.0))
+ supportedFrameRates.insert(1, 15.0);
+ }
+ if (supportedFrameRates.last() > 10.0) {
+ if (!supportedFrameRates.contains(10))
+ supportedFrameRates.insert(1, 10.0);
+ }
+ }
+
+#ifdef Q_CC_NOKIAX86 // Emulator
+ supportedFrameRates << 30.0 << 25.0 << 15.0 << 10.0 << 5.0;
+#endif
+
+ return supportedFrameRates;
+}
+
+bool S60VideoCaptureSession::setOutputLocation(const QUrl &sink)
+{
+ m_requestedSink = sink;
+
+ if (m_error)
+ return false;
+
+ switch (m_captureState) {
+ case ENotInitialized:
+ case EInitializing:
+ case EOpening:
+ case EPreparing:
+ m_openWhenReady = true;
+ return true;
+
+ case EInitialized:
+ case EOpenComplete:
+ case EPrepared:
+ // Continue
+ break;
+
+ case ERecording:
+ case EPaused:
+ setError(KErrNotReady, tr("Cannot set file name while recording."));
+ return false;
+
+ default:
+ setError(KErrGeneral, tr("Unexpected camera error."));
+ return false;
+ }
+
+ // Empty URL - Use default file name and path (C:\Data\Videos\video.mp4)
+ if (sink.isEmpty()) {
+
+ // Make sure default directory exists
+ QDir videoDir(QDir::rootPath());
+ if (!videoDir.exists(KDefaultVideoPath))
+ videoDir.mkpath(KDefaultVideoPath);
+ QString defaultFile = KDefaultVideoPath;
+ defaultFile.append("\\");
+ defaultFile.append(KDefaultVideoFileName);
+ m_sink.setUrl(defaultFile);
+
+ } else { // Non-empty URL
+
+ QString fullUrl = sink.scheme();
+
+ // Relative URL
+ if (sink.isRelative()) {
+
+ // Extract file name and path from the URL
+ fullUrl = KDefaultVideoPath;
+ fullUrl.append("\\");
+ fullUrl.append(QDir::toNativeSeparators(sink.path()));
+
+ // Absolute URL
+ } else {
+
+ // Extract file name and path from the URL
+ if (fullUrl == "file") {
+ fullUrl = QDir::toNativeSeparators(sink.path().right(sink.path().length() - 1));
+ } else {
+ fullUrl.append(":");
+ fullUrl.append(QDir::toNativeSeparators(sink.path()));
+ }
+ }
+
+ QString fileName = fullUrl.right(fullUrl.length() - fullUrl.lastIndexOf("\\") - 1);
+ QString directory = fullUrl.left(fullUrl.lastIndexOf("\\"));
+ if (directory.lastIndexOf("\\") == (directory.length() - 1))
+ directory = directory.left(directory.length() - 1);
+
+ // URL is Absolute path, not including file name
+ if (!fileName.contains(".")) {
+ if (fileName != "") {
+ directory.append("\\");
+ directory.append(fileName);
+ }
+ fileName = KDefaultVideoFileName;
+ }
+
+ // Make sure absolute directory exists
+ QDir videoDir(QDir::rootPath());
+ if (!videoDir.exists(directory))
+ videoDir.mkpath(directory);
+
+ QString resolvedURL = directory;
+ resolvedURL.append("\\");
+ resolvedURL.append(fileName);
+ m_sink = QUrl(resolvedURL);
+ }
+
+ // State is either Initialized, OpenComplete or Prepared, Close previously opened file
+ if (m_videoRecorder)
+ m_videoRecorder->Close();
+ else
+ setError(KErrNotReady, tr("Unexpected camera error."));
+
+ // Open file
+
+ QString fileName = QDir::toNativeSeparators(m_sink.toString());
+ TPtrC16 fileSink(reinterpret_cast<const TUint16*>(fileName.utf16()));
+
+ int cameraHandle = m_cameraEngine->Camera() ? m_cameraEngine->Camera()->Handle() : 0;
+
+ TUid controllerUid;
+ TUid formatUid;
+ selectController(m_requestedContainer, controllerUid, formatUid);
+
+ if (m_videoRecorder) {
+ // File open completes in MvruoOpenComplete
+ TRAPD(err, m_videoRecorder->OpenFileL(fileSink, cameraHandle, controllerUid, formatUid));
+ setError(err, tr("Failed to initialize video recorder."));
+ m_container = m_requestedContainer;
+ m_captureState = EOpening;
+ emit stateChanged(m_captureState);
+ }
+ else
+ setError(KErrNotReady, tr("Unexpected camera error."));
+
+ m_uncommittedSettings = true;
+ return true;
+}
+
+QUrl S60VideoCaptureSession::outputLocation() const
+{
+ return m_sink;
+}
+
+qint64 S60VideoCaptureSession::position()
+{
+ // Update position only if recording is ongoing
+ if ((m_captureState == ERecording) && m_videoRecorder) {
+ // Signal will be automatically emitted of position changes
+ TRAPD(err, m_position = m_videoRecorder->DurationL().Int64() / 1000);
+ setError(err, tr("Cannot retrieve video position."));
+ }
+
+ return m_position;
+}
+
+S60VideoCaptureSession::TVideoCaptureState S60VideoCaptureSession::state() const
+{
+ return m_captureState;
+}
+
+bool S60VideoCaptureSession::isMuted() const
+{
+ return m_muted;
+}
+
+void S60VideoCaptureSession::setMuted(const bool muted)
+{
+ // CVideoRecorderUtility can mute/unmute only if not recording
+ if (m_captureState > EPrepared) {
+ if (muted)
+ setError(KErrNotSupported, tr("Muting audio is not supported during recording."));
+ else
+ setError(KErrNotSupported, tr("Unmuting audio is not supported during recording."));
+ return;
+ }
+
+ // Check if request is already active
+ if (muted == isMuted())
+ return;
+
+ m_muted = muted;
+
+ m_uncommittedSettings = true;
+}
+
+void S60VideoCaptureSession::commitVideoEncoderSettings()
+{
+ if (m_captureState == EOpenComplete) {
+
+ if (m_container != m_requestedContainer) {
+ setOutputLocation(m_requestedSink);
+ return;
+ }
+
+ TRAPD(err, doSetCodecsL());
+ if (err) {
+ setError(err, tr("Failed to set audio or video codec."));
+ m_audioSettings.setCodec(KMimeTypeDefaultAudioCodec);
+ m_videoSettings.setCodec(KMimeTypeDefaultVideoCodec);
+ }
+
+ doSetVideoResolution(m_videoSettings.resolution());
+ doSetFrameRate(m_videoSettings.frameRate());
+ doSetBitrate(m_videoSettings.bitRate());
+
+ // Audio/Video EncodingMode are not supported in Symbian
+
+#ifndef S60_31_PLATFORM
+ if (m_audioSettings.sampleRate() != -1 && m_audioSettings.sampleRate() != 0) {
+ TRAP(err, m_videoRecorder->SetAudioSampleRateL((TInt)m_audioSettings.sampleRate()));
+ if (err != KErrNotSupported) {
+ setError(err, tr("Setting audio sample rate failed."));
+ } else {
+ setError(err, tr("Setting audio sample rate is not supported."));
+ m_audioSettings.setSampleRate(KDefaultSampleRate); // Reset
+ }
+ }
+#endif // S60_31_PLATFORM
+
+ TRAP(err, m_videoRecorder->SetAudioBitRateL((TInt)m_audioSettings.bitRate()));
+ if (err != KErrNotSupported) {
+ if (err == KErrArgument) {
+ setError(KErrNotSupported, tr("Requested audio bitrate is not supported or previously set codec is not supported with requested bitrate."));
+ int fallback = 16000;
+ TRAP(err, m_videoRecorder->SetAudioBitRateL(TInt(fallback)));
+ if (err == KErrNone)
+ m_audioSettings.setBitRate(fallback);
+ } else {
+ setError(err, tr("Setting audio bitrate failed."));
+ }
+ }
+
+#ifndef S60_31_PLATFORM
+ if (m_audioSettings.channelCount() != -1) {
+ TRAP(err, m_videoRecorder->SetAudioChannelsL(TUint(m_audioSettings.channelCount())));
+ if (err != KErrNotSupported) {
+ setError(err, tr("Setting audio channel count failed."));
+ } else {
+ setError(err, tr("Setting audio channel count is not supported."));
+ m_audioSettings.setChannelCount(KDefaultChannelCount); // Reset
+ }
+ }
+#endif // S60_31_PLATFORM
+
+ TBool isAudioMuted = EFalse;
+ TRAP(err, isAudioMuted = !m_videoRecorder->AudioEnabledL());
+ if (err != KErrNotSupported && err != KErrNone)
+ setError(err, tr("Failure when checking if audio is enabled."));
+
+ if (m_muted != (bool)isAudioMuted) {
+ TRAP(err, m_videoRecorder->SetAudioEnabledL(TBool(!m_muted)));
+ if (err) {
+ if (err != KErrNotSupported) {
+ setError(err, tr("Failed to mute/unmute audio."));
+ } else {
+ setError(err, tr("Muting/unmuting audio is not supported."));
+ }
+ }
+ else
+ emit mutedChanged(m_muted);
+ }
+
+ m_uncommittedSettings = false; // Reset
+ }
+}
+
+void S60VideoCaptureSession::queryAudioEncoderSettings()
+{
+ if (!m_videoRecorder)
+ return;
+
+ switch (m_captureState) {
+ case ENotInitialized:
+ case EInitializing:
+ case EOpening:
+ case EPreparing:
+ return;
+
+ // Possible to query settings from CVideoRecorderUtility
+ case EInitialized:
+ case EOpenComplete:
+ case EPrepared:
+ case ERecording:
+ case EPaused:
+ break;
+
+ default:
+ return;
+ }
+
+ TInt err = KErrNone;
+
+ // Codec
+ TFourCC audioCodec;
+ TRAP(err, audioCodec = m_videoRecorder->AudioTypeL());
+ if (err) {
+ if (err != KErrNotSupported)
+ setError(err, tr("Querying audio codec failed."));
+ }
+ QString codec = "";
+ foreach (TFourCC aCodec, m_audioCodecList) {
+ if (audioCodec == aCodec)
+ codec = m_audioCodecList.key(aCodec);
+ }
+ m_audioSettings.setCodec(codec);
+
+#ifndef S60_31_PLATFORM
+ // Samplerate
+ TInt sampleRate = -1;
+ TRAP(err, sampleRate = m_videoRecorder->AudioSampleRateL());
+ if (err) {
+ if (err != KErrNotSupported)
+ setError(err, tr("Querying audio sample rate failed."));
+ }
+ m_audioSettings.setSampleRate(int(sampleRate));
+#endif // S60_31_PLATFORM
+
+ // BitRate
+ TInt bitRate = -1;
+ TRAP(err, bitRate = m_videoRecorder->AudioBitRateL());
+ if (err) {
+ if (err != KErrNotSupported)
+ setError(err, tr("Querying audio bitrate failed."));
+ }
+ m_audioSettings.setBitRate(int(bitRate));
+
+#ifndef S60_31_PLATFORM
+ // ChannelCount
+ TUint channelCount = 0;
+ TRAP(err, channelCount = m_videoRecorder->AudioChannelsL());
+ if (err) {
+ if (err != KErrNotSupported)
+ setError(err, tr("Querying audio channel count failed."));
+ }
+ if (channelCount != 0)
+ m_audioSettings.setChannelCount(int(channelCount));
+ else
+ m_audioSettings.setChannelCount(-1);
+#endif // S60_31_PLATFORM
+
+ // EncodingMode
+ m_audioSettings.setEncodingMode(QtMultimediaKit::ConstantQualityEncoding);
+
+ // IsMuted
+ TBool isEnabled = ETrue;
+ TRAP(err, isEnabled = m_videoRecorder->AudioEnabledL());
+ if (err) {
+ if (err != KErrNotSupported)
+ setError(err, tr("Querying whether audio is muted failed."));
+ }
+ m_muted = bool(!isEnabled);
+}
+
+void S60VideoCaptureSession::queryVideoEncoderSettings()
+{
+ if (!m_videoRecorder)
+ return;
+
+ switch (m_captureState) {
+ case ENotInitialized:
+ case EInitializing:
+ case EOpening:
+ case EPreparing:
+ return;
+
+ // Possible to query settings from CVideoRecorderUtility
+ case EInitialized:
+ case EOpenComplete:
+ case EPrepared:
+ case ERecording:
+ case EPaused:
+ break;
+
+ default:
+ return;
+ }
+
+ TInt err = KErrNone;
+
+ // Codec
+ const TDesC8 &videoMimeType = m_videoRecorder->VideoFormatMimeType();
+ QString videoMimeTypeString = "";
+ if (videoMimeType.Length() > 0) {
+ // First convert the 8-bit descriptor to Unicode
+ HBufC16* videoCodec;
+ videoCodec = CnvUtfConverter::ConvertToUnicodeFromUtf8L(videoMimeType);
+ CleanupStack::PushL(videoCodec);
+
+ // Then deep copy QString from that
+ videoMimeTypeString = QString::fromUtf16(videoCodec->Ptr(), videoCodec->Length());
+ m_videoSettings.setCodec(videoMimeTypeString);
+
+ CleanupStack::PopAndDestroy(videoCodec);
+ }
+
+ // Resolution
+ TSize symbianResolution;
+ TRAP(err, m_videoRecorder->GetVideoFrameSizeL(symbianResolution));
+ if (err) {
+ if (err != KErrNotSupported)
+ setError(err, tr("Querying video resolution failed."));
+ }
+ QSize resolution = QSize(symbianResolution.iWidth, symbianResolution.iHeight);
+ m_videoSettings.setResolution(resolution);
+
+ // FrameRate
+ TReal32 frameRate = 0;
+ TRAP(err, frameRate = m_videoRecorder->VideoFrameRateL());
+ if (err) {
+ if (err != KErrNotSupported)
+ setError(err, tr("Querying video framerate failed."));
+ }
+ m_videoSettings.setFrameRate(qreal(frameRate));
+
+ // BitRate
+ TInt bitRate = -1;
+ TRAP(err, bitRate = m_videoRecorder->VideoBitRateL());
+ if (err) {
+ if (err != KErrNotSupported)
+ setError(err, tr("Querying video bitrate failed."));
+ }
+ m_videoSettings.setBitRate(int(bitRate));
+
+ // EncodingMode
+ m_audioSettings.setEncodingMode(QtMultimediaKit::ConstantQualityEncoding);
+}
+
+void S60VideoCaptureSession::videoEncoderSettings(QVideoEncoderSettings &videoSettings)
+{
+ switch (m_captureState) {
+ // CVideoRecorderUtility, return requested settings
+ case ENotInitialized:
+ case EInitializing:
+ case EInitialized:
+ case EOpening:
+ case EOpenComplete:
+ case EPreparing:
+ break;
+
+ // Possible to query settings from CVideoRecorderUtility
+ case EPrepared:
+ case ERecording:
+ case EPaused:
+ queryVideoEncoderSettings();
+ break;
+
+ default:
+ videoSettings = QVideoEncoderSettings();
+ setError(KErrGeneral, tr("Unexpected video error."));
+ return;
+ }
+
+ videoSettings = m_videoSettings;
+}
+
+void S60VideoCaptureSession::audioEncoderSettings(QAudioEncoderSettings &audioSettings)
+{
+ switch (m_captureState) {
+ // CVideoRecorderUtility, return requested settings
+ case ENotInitialized:
+ case EInitializing:
+ case EInitialized:
+ case EOpening:
+ case EOpenComplete:
+ case EPreparing:
+ break;
+
+ // Possible to query settings from CVideoRecorderUtility
+ case EPrepared:
+ case ERecording:
+ case EPaused:
+ queryAudioEncoderSettings();
+ break;
+
+ default:
+ audioSettings = QAudioEncoderSettings();
+ setError(KErrGeneral, tr("Unexpected video error."));
+ return;
+ }
+
+ audioSettings = m_audioSettings;
+}
+
+void S60VideoCaptureSession::validateRequestedCodecs()
+{
+ if (!m_audioCodecList.contains(m_audioSettings.codec())) {
+ m_audioSettings.setCodec(KMimeTypeDefaultAudioCodec);
+ setError(KErrNotSupported, tr("Currently selected audio codec is not supported by the platform."));
+ }
+ if (!m_videoCodecList.contains(m_videoSettings.codec())) {
+ m_videoSettings.setCodec(KMimeTypeDefaultVideoCodec);
+ setError(KErrNotSupported, tr("Currently selected video codec is not supported by the platform."));
+ }
+}
+
+void S60VideoCaptureSession::setVideoCaptureQuality(const QtMultimediaKit::EncodingQuality quality,
+ const VideoQualityDefinition mode)
+{
+ // Sensible presets
+ switch (mode) {
+ case ENoVideoQuality:
+ // Do nothing
+ break;
+ case EOnlyVideoQuality:
+ if (quality == QtMultimediaKit::VeryLowQuality) {
+ m_videoSettings.setResolution(QSize(128,96));
+ m_videoSettings.setFrameRate(10);
+ m_videoSettings.setBitRate(64000);
+ } else if (quality == QtMultimediaKit::LowQuality) {
+ m_videoSettings.setResolution(QSize(176,144));
+ m_videoSettings.setFrameRate(15);
+ m_videoSettings.setBitRate(64000);
+ } else if (quality == QtMultimediaKit::NormalQuality) {
+ m_videoSettings.setResolution(QSize(176,144));
+ m_videoSettings.setFrameRate(15);
+ m_videoSettings.setBitRate(128000);
+ } else if (quality == QtMultimediaKit::HighQuality) {
+ m_videoSettings.setResolution(QSize(352,288));
+ m_videoSettings.setFrameRate(15);
+ m_videoSettings.setBitRate(384000);
+ } else if (quality == QtMultimediaKit::VeryHighQuality) {
+ if (m_cameraEngine && m_cameraEngine->CurrentCameraIndex() == 0)
+ m_videoSettings.setResolution(QSize(640,480)); // Primary camera
+ else
+ m_videoSettings.setResolution(QSize(352,288)); // Other cameras
+ m_videoSettings.setFrameRate(15);
+ m_videoSettings.setBitRate(2000000);
+ } else {
+ m_videoSettings.setQuality(QtMultimediaKit::NormalQuality);
+ setError(KErrNotSupported, tr("Unsupported video quality."));
+ return;
+ }
+ break;
+ case EVideoQualityAndResolution:
+ if (quality == QtMultimediaKit::VeryLowQuality) {
+ m_videoSettings.setFrameRate(10);
+ m_videoSettings.setBitRate(64000);
+ } else if (quality == QtMultimediaKit::LowQuality) {
+ m_videoSettings.setFrameRate(15);
+ m_videoSettings.setBitRate(64000);
+ } else if (quality == QtMultimediaKit::NormalQuality) {
+ m_videoSettings.setFrameRate(15);
+ m_videoSettings.setBitRate(128000);
+ } else if (quality == QtMultimediaKit::HighQuality) {
+ m_videoSettings.setFrameRate(15);
+ m_videoSettings.setBitRate(384000);
+ } else if (quality == QtMultimediaKit::VeryHighQuality) {
+ m_videoSettings.setFrameRate(15);
+ m_videoSettings.setBitRate(2000000);
+ } else {
+ m_videoSettings.setQuality(QtMultimediaKit::NormalQuality);
+ setError(KErrNotSupported, tr("Unsupported video quality."));
+ return;
+ }
+ break;
+ case EVideoQualityAndFrameRate:
+ if (quality == QtMultimediaKit::VeryLowQuality) {
+ m_videoSettings.setResolution(QSize(128,96));
+ m_videoSettings.setBitRate(64000);
+ } else if (quality == QtMultimediaKit::LowQuality) {
+ m_videoSettings.setResolution(QSize(176,144));
+ m_videoSettings.setBitRate(64000);
+ } else if (quality == QtMultimediaKit::NormalQuality) {
+ m_videoSettings.setResolution(QSize(176,144));
+ m_videoSettings.setBitRate(128000);
+ } else if (quality == QtMultimediaKit::HighQuality) {
+ m_videoSettings.setResolution(QSize(352,288));
+ m_videoSettings.setBitRate(384000);
+ } else if (quality == QtMultimediaKit::VeryHighQuality) {
+ if (m_cameraEngine && m_cameraEngine->CurrentCameraIndex() == 0)
+ m_videoSettings.setResolution(QSize(640,480)); // Primary camera
+ else
+ m_videoSettings.setResolution(QSize(352,288)); // Other cameras
+ m_videoSettings.setBitRate(2000000);
+ } else {
+ m_videoSettings.setQuality(QtMultimediaKit::NormalQuality);
+ setError(KErrNotSupported, tr("Unsupported video quality."));
+ return;
+ }
+ break;
+ case EVideoQualityAndBitRate:
+ if (quality == QtMultimediaKit::VeryLowQuality) {
+ m_videoSettings.setResolution(QSize(128,96));
+ m_videoSettings.setFrameRate(10);
+ } else if (quality == QtMultimediaKit::LowQuality) {
+ m_videoSettings.setResolution(QSize(176,144));
+ m_videoSettings.setFrameRate(15);
+ } else if (quality == QtMultimediaKit::NormalQuality) {
+ m_videoSettings.setResolution(QSize(176,144));
+ m_videoSettings.setFrameRate(15);
+ } else if (quality == QtMultimediaKit::HighQuality) {
+ m_videoSettings.setResolution(QSize(352,288));
+ m_videoSettings.setFrameRate(15);
+ } else if (quality == QtMultimediaKit::VeryHighQuality) {
+ if (m_cameraEngine && m_cameraEngine->CurrentCameraIndex() == 0)
+ m_videoSettings.setResolution(QSize(640,480)); // Primary camera
+ else
+ m_videoSettings.setResolution(QSize(352,288)); // Other cameras
+ m_videoSettings.setFrameRate(15);
+ } else {
+ m_videoSettings.setQuality(QtMultimediaKit::NormalQuality);
+ setError(KErrNotSupported, tr("Unsupported video quality."));
+ return;
+ }
+ break;
+ case EVideoQualityAndResolutionAndBitRate:
+ if (quality == QtMultimediaKit::VeryLowQuality) {
+ m_videoSettings.setFrameRate(10);
+ } else if (quality == QtMultimediaKit::LowQuality) {
+ m_videoSettings.setFrameRate(15);
+ } else if (quality == QtMultimediaKit::NormalQuality) {
+ m_videoSettings.setFrameRate(15);
+ } else if (quality == QtMultimediaKit::HighQuality) {
+ m_videoSettings.setFrameRate(15);
+ } else if (quality == QtMultimediaKit::VeryHighQuality) {
+ m_videoSettings.setFrameRate(15);
+ } else {
+ m_videoSettings.setQuality(QtMultimediaKit::NormalQuality);
+ setError(KErrNotSupported, tr("Unsupported video quality."));
+ return;
+ }
+ break;
+ case EVideoQualityAndResolutionAndFrameRate:
+ if (quality == QtMultimediaKit::VeryLowQuality) {
+ m_videoSettings.setBitRate(64000);
+ } else if (quality == QtMultimediaKit::LowQuality) {
+ m_videoSettings.setBitRate(64000);
+ } else if (quality == QtMultimediaKit::NormalQuality) {
+ m_videoSettings.setBitRate(128000);
+ } else if (quality == QtMultimediaKit::HighQuality) {
+ m_videoSettings.setBitRate(384000);
+ } else if (quality == QtMultimediaKit::VeryHighQuality) {
+ m_videoSettings.setBitRate(2000000);
+ } else {
+ m_videoSettings.setQuality(QtMultimediaKit::NormalQuality);
+ setError(KErrNotSupported, tr("Unsupported video quality."));
+ return;
+ }
+ break;
+ case EVideoQualityAndFrameRateAndBitRate:
+ if (quality == QtMultimediaKit::VeryLowQuality) {
+ m_videoSettings.setResolution(QSize(128,96));
+ } else if (quality == QtMultimediaKit::LowQuality) {
+ m_videoSettings.setResolution(QSize(176,144));
+ } else if (quality == QtMultimediaKit::NormalQuality) {
+ m_videoSettings.setResolution(QSize(176,144));
+ } else if (quality == QtMultimediaKit::HighQuality) {
+ m_videoSettings.setResolution(QSize(352,288));
+ } else if (quality == QtMultimediaKit::VeryHighQuality) {
+ if (m_cameraEngine && m_cameraEngine->CurrentCameraIndex() == 0)
+ m_videoSettings.setResolution(QSize(640,480)); // Primary camera
+ else
+ m_videoSettings.setResolution(QSize(352,288)); // Other cameras
+ } else {
+ m_videoSettings.setQuality(QtMultimediaKit::NormalQuality);
+ setError(KErrNotSupported, tr("Unsupported video quality."));
+ return;
+ }
+ break;
+ }
+
+ m_videoSettings.setQuality(quality);
+ m_uncommittedSettings = true;
+}
+
+void S60VideoCaptureSession::setAudioCaptureQuality(const QtMultimediaKit::EncodingQuality quality,
+ const AudioQualityDefinition mode)
+{
+ // Based on audio quality definition mode, select proper SampleRate and BitRate
+ switch (mode) {
+ case EOnlyAudioQuality:
+ switch (quality) {
+ case QtMultimediaKit::VeryLowQuality:
+ m_audioSettings.setBitRate(16000);
+ m_audioSettings.setSampleRate(-1);
+ break;
+ case QtMultimediaKit::LowQuality:
+ m_audioSettings.setBitRate(16000);
+ m_audioSettings.setSampleRate(-1);
+ break;
+ case QtMultimediaKit::NormalQuality:
+ m_audioSettings.setBitRate(32000);
+ m_audioSettings.setSampleRate(-1);
+ break;
+ case QtMultimediaKit::HighQuality:
+ m_audioSettings.setBitRate(64000);
+ m_audioSettings.setSampleRate(-1);
+ break;
+ case QtMultimediaKit::VeryHighQuality:
+ m_audioSettings.setBitRate(64000);
+ m_audioSettings.setSampleRate(-1);
+ break;
+ default:
+ m_audioSettings.setQuality(QtMultimediaKit::NormalQuality);
+ setError(KErrNotSupported, tr("Unsupported audio quality."));
+ return;
+ }
+ break;
+ case EAudioQualityAndBitRate:
+ switch (quality) {
+ case QtMultimediaKit::VeryLowQuality:
+ m_audioSettings.setSampleRate(-1);
+ break;
+ case QtMultimediaKit::LowQuality:
+ m_audioSettings.setSampleRate(-1);
+ break;
+ case QtMultimediaKit::NormalQuality:
+ m_audioSettings.setSampleRate(-1);
+ break;
+ case QtMultimediaKit::HighQuality:
+ m_audioSettings.setSampleRate(-1);
+ break;
+ case QtMultimediaKit::VeryHighQuality:
+ m_audioSettings.setSampleRate(-1);
+ break;
+ default:
+ m_audioSettings.setQuality(QtMultimediaKit::NormalQuality);
+ setError(KErrNotSupported, tr("Unsupported audio quality."));
+ return;
+ }
+ break;
+ case EAudioQualityAndSampleRate:
+ switch (quality) {
+ case QtMultimediaKit::VeryLowQuality:
+ m_audioSettings.setBitRate(16000);
+ break;
+ case QtMultimediaKit::LowQuality:
+ m_audioSettings.setBitRate(16000);
+ break;
+ case QtMultimediaKit::NormalQuality:
+ m_audioSettings.setBitRate(32000);
+ break;
+ case QtMultimediaKit::HighQuality:
+ m_audioSettings.setBitRate(64000);
+ break;
+ case QtMultimediaKit::VeryHighQuality:
+ m_audioSettings.setBitRate(64000);
+ break;
+ default:
+ m_audioSettings.setQuality(QtMultimediaKit::NormalQuality);
+ setError(KErrNotSupported, tr("Unsupported audio quality."));
+ return;
+ }
+ break;
+ case ENoAudioQuality:
+ // No actions required, just set quality parameter
+ break;
+
+ default:
+ setError(KErrGeneral, tr("Unexpected camera error."));
+ return;
+ }
+
+ m_audioSettings.setQuality(quality);
+ m_uncommittedSettings = true;
+}
+
+int S60VideoCaptureSession::initializeVideoRecording()
+{
+ if (m_error)
+ return m_error;
+
+ TRAPD(symbianError, doInitializeVideoRecorderL());
+ setError(symbianError, tr("Failed to initialize video recorder."));
+
+ return symbianError;
+}
+
+void S60VideoCaptureSession::releaseVideoRecording()
+{
+ if (m_captureState >= ERecording) {
+ m_videoRecorder->Stop();
+ if (m_durationTimer->isActive())
+ m_durationTimer->stop();
+ }
+
+ if (m_captureState >= EInitialized)
+ m_videoRecorder->Close();
+
+ // Reset state
+ m_captureState = ENotInitialized;
+
+ // Reset error to be able to recover from error
+ m_error = KErrNone;
+
+ // Reset flags
+ m_openWhenReady = false;
+ m_prepareAfterOpenComplete = false;
+ m_startAfterPrepareComplete = false;
+ m_uncommittedSettings = false;
+ m_commitSettingsWhenReady = false;
+}
+
+void S60VideoCaptureSession::startRecording()
+{
+ if (m_error) {
+ setError(m_error, tr("Unexpected recording error."));
+ return;
+ }
+
+ switch (m_captureState) {
+ case ENotInitialized:
+ case EInitializing:
+ case EInitialized:
+ if (m_captureState == EInitialized)
+ setOutputLocation(m_requestedSink);
+ m_startAfterPrepareComplete = true;
+ return;
+
+ case EOpening:
+ case EPreparing:
+ // Execute FileOpenL() and Prepare() asap and then start recording
+ m_startAfterPrepareComplete = true;
+ return;
+ case EOpenComplete:
+ case EPrepared:
+ if (m_captureState == EPrepared && !m_uncommittedSettings)
+ break;
+
+ // Revert state internally, since logically applying settings means going
+ // from OpenComplete ==> Preparing ==> Prepared.
+ m_captureState = EOpenComplete;
+ m_startAfterPrepareComplete = true;
+
+ // Commit settings and prepare with them
+ applyAllSettings();
+ return;
+ case ERecording:
+ // Discard
+ return;
+ case EPaused:
+ // Continue
+ break;
+
+ default:
+ setError(KErrGeneral, tr("Unexpected camera error."));
+ return;
+ }
+
+ // State should now be either Prepared with no Uncommitted Settings or Paused
+
+ if (!m_cameraStarted) {
+ m_startAfterPrepareComplete = true;
+ return;
+ }
+
+ if (m_cameraEngine && !m_cameraEngine->IsCameraReady()) {
+ setError(KErrNotReady, tr("Camera not ready to start video recording."));
+ return;
+ }
+
+ if (m_videoRecorder) {
+ m_videoRecorder->Record();
+ m_captureState = ERecording;
+ emit stateChanged(m_captureState);
+ m_durationTimer->start();
+
+ // Reset all flags
+ m_openWhenReady = false;
+ m_prepareAfterOpenComplete = false;
+ m_startAfterPrepareComplete = false;
+ } else {
+ setError(KErrNotReady, tr("Unexpected camera error."));
+ }
+}
+
+void S60VideoCaptureSession::pauseRecording()
+{
+ if (m_captureState == ERecording) {
+ if (m_videoRecorder) {
+ TRAPD(err, m_videoRecorder->PauseL());
+ setError(err, tr("Pausing video recording failed."));
+ m_captureState = EPaused;
+ emit stateChanged(m_captureState);
+ if (m_durationTimer->isActive())
+ m_durationTimer->stop();
+
+ // Notify last duration
+ TRAP(err, m_position = m_videoRecorder->DurationL().Int64() / 1000);
+ setError(err, tr("Cannot retrieve video position."));
+ emit positionChanged(m_position);
+ }
+ else
+ setError(KErrNotReady, tr("Unexpected camera error."));
+ }
+}
+
+void S60VideoCaptureSession::stopRecording(const bool reInitialize)
+{
+ if (m_captureState != ERecording && m_captureState != EPaused)
+ return; // Ignore
+
+ if (m_videoRecorder) {
+ m_videoRecorder->Stop();
+ m_videoRecorder->Close();
+
+ // Notify muting is disabled if needed
+ if (m_muted)
+ emit mutedChanged(false);
+
+ m_captureState = ENotInitialized;
+ emit stateChanged(m_captureState);
+
+ if (m_durationTimer->isActive())
+ m_durationTimer->stop();
+
+ // VideoRecording will be re-initialized unless explicitly requested not to do so
+ if (reInitialize) {
+ if (m_cameraEngine->IsCameraReady())
+ initializeVideoRecording();
+ }
+ }
+ else
+ setError(KErrNotReady, tr("Unexpected camera error."));
+}
+
+void S60VideoCaptureSession::updateVideoCaptureContainers()
+{
+ TRAPD(err, doUpdateVideoCaptureContainersL());
+ setError(err, tr("Failed to gather video container information."));
+}
+
+void S60VideoCaptureSession::doUpdateVideoCaptureContainersL()
+{
+ // Clear container data structure
+ QList<TInt> mapControllers = m_videoControllerMap.keys();
+ for (int i = 0; i < mapControllers.size(); ++i) {
+ foreach(VideoFormatData data, m_videoControllerMap[mapControllers[i]]){
+ data.supportedMimeTypes.clear();
+ }
+ m_videoControllerMap[mapControllers[i]].clear();
+ }
+ m_videoControllerMap.clear();
+
+ // Resolve the supported video format and retrieve a list of controllers
+ CMMFControllerPluginSelectionParameters* pluginParameters =
+ CMMFControllerPluginSelectionParameters::NewLC();
+ CMMFFormatSelectionParameters* format =
+ CMMFFormatSelectionParameters::NewLC();
+
+ // Set the play and record format selection parameters to be blank.
+ // Format support is only retrieved if requested.
+ pluginParameters->SetRequiredPlayFormatSupportL(*format);
+ pluginParameters->SetRequiredRecordFormatSupportL(*format);
+
+ // Set the media IDs
+ RArray<TUid> mediaIds;
+ CleanupClosePushL(mediaIds);
+
+ User::LeaveIfError(mediaIds.Append(KUidMediaTypeVideo));
+
+ // Get plugins that support at least video
+ pluginParameters->SetMediaIdsL(mediaIds,
+ CMMFPluginSelectionParameters::EAllowOtherMediaIds);
+ pluginParameters->SetPreferredSupplierL(KNullDesC,
+ CMMFPluginSelectionParameters::EPreferredSupplierPluginsFirstInList);
+
+ // Array to hold all the controllers support the match data
+ RMMFControllerImplInfoArray controllers;
+ CleanupResetAndDestroyPushL(controllers);
+ pluginParameters->ListImplementationsL(controllers);
+
+ // Find the first controller with at least one record format available
+ for (TInt index = 0; index < controllers.Count(); ++index) {
+
+ m_videoControllerMap.insert(controllers[index]->Uid().iUid, QHash<TInt,VideoFormatData>());
+
+ const RMMFFormatImplInfoArray& recordFormats = controllers[index]->RecordFormats();
+ for (TInt j = 0; j < recordFormats.Count(); ++j) {
+ VideoFormatData formatData;
+ formatData.description = QString::fromUtf16(
+ recordFormats[j]->DisplayName().Ptr(),
+ recordFormats[j]->DisplayName().Length());
+
+ const CDesC8Array& mimeTypes = recordFormats[j]->SupportedMimeTypes();
+ for (int k = 0; k < mimeTypes.Count(); ++k) {
+ TPtrC8 mimeType = mimeTypes[k];
+ QString type = QString::fromUtf8((char *)mimeType.Ptr(),
+ mimeType.Length());
+ formatData.supportedMimeTypes.append(type);
+ }
+
+ m_videoControllerMap[controllers[index]->Uid().iUid].insert(recordFormats[j]->Uid().iUid, formatData);
+ }
+ }
+
+ CleanupStack::PopAndDestroy(&controllers);
+ CleanupStack::PopAndDestroy(&mediaIds);
+ CleanupStack::PopAndDestroy(format);
+ CleanupStack::PopAndDestroy(pluginParameters);
+}
+
+/*
+ * This goes through the available controllers and selects proper one based
+ * on the format. Function sets proper UIDs to be used for controller and format.
+ */
+void S60VideoCaptureSession::selectController(const QString &format,
+ TUid &controllerUid,
+ TUid &formatUid)
+{
+ QList<TInt> controllers = m_videoControllerMap.keys();
+ QList<TInt> formats;
+
+ for (int i = 0; i < controllers.count(); ++i) {
+ formats = m_videoControllerMap[controllers[i]].keys();
+ for (int j = 0; j < formats.count(); ++j) {
+ VideoFormatData formatData = m_videoControllerMap[controllers[i]][formats[j]];
+ if (formatData.supportedMimeTypes.contains(format, Qt::CaseInsensitive)) {
+ controllerUid = TUid::Uid(controllers[i]);
+ formatUid = TUid::Uid(formats[j]);
+ }
+ }
+ }
+}
+
+QStringList S60VideoCaptureSession::supportedVideoCaptureCodecs()
+{
+ return m_videoCodecList;
+}
+
+QStringList S60VideoCaptureSession::supportedAudioCaptureCodecs()
+{
+ QStringList keys = m_audioCodecList.keys();
+ keys.sort();
+ return keys;
+}
+
+QList<int> S60VideoCaptureSession::supportedSampleRates(const QAudioEncoderSettings &settings, bool *continuous)
+{
+ QList<int> rates;
+
+ TRAPD(err, rates = doGetSupportedSampleRatesL(settings, continuous));
+ if (err != KErrNotSupported)
+ setError(err, tr("Failed to query information of supported sample rates."));
+
+ return rates;
+}
+
+QList<int> S60VideoCaptureSession::doGetSupportedSampleRatesL(const QAudioEncoderSettings &settings, bool *continuous)
+{
+ QList<int> sampleRates;
+
+ if (m_captureState < EOpenComplete)
+ return sampleRates;
+
+#ifndef S60_31_PLATFORM
+ RArray<TUint> supportedSampleRates;
+ CleanupClosePushL(supportedSampleRates);
+
+ if (!settings.codec().isEmpty()) {
+
+ TFourCC currentAudioCodec;
+ currentAudioCodec = m_videoRecorder->AudioTypeL();
+
+ TFourCC requestedAudioCodec;
+ if (qstrcmp(settings.codec().toLocal8Bit().constData(), "audio/aac") == 0)
+ requestedAudioCodec.Set(KMMFFourCCCodeAAC);
+ else if (qstrcmp(settings.codec().toLocal8Bit().constData(), "audio/amr") == 0)
+ requestedAudioCodec.Set(KMMFFourCCCodeAMR);
+ m_videoRecorder->SetAudioTypeL(requestedAudioCodec);
+
+ m_videoRecorder->GetSupportedAudioSampleRatesL(supportedSampleRates);
+
+ m_videoRecorder->SetAudioTypeL(currentAudioCodec);
+ }
+ else
+ m_videoRecorder->GetSupportedAudioSampleRatesL(supportedSampleRates);
+
+ for (int i = 0; i < supportedSampleRates.Count(); ++i)
+ sampleRates.append(int(supportedSampleRates[i]));
+
+ CleanupStack::PopAndDestroy(); // RArray<TUint> supportedSampleRates
+#else // S60 3.1 Platform
+ Q_UNUSED(settings);
+#endif // S60_31_PLATFORM
+
+ if (continuous)
+ *continuous = false;
+
+ return sampleRates;
+}
+
+void S60VideoCaptureSession::setAudioSampleRate(const int sampleRate)
+{
+ if (sampleRate != -1)
+ m_audioSettings.setSampleRate(sampleRate);
+
+ m_uncommittedSettings = true;
+}
+
+void S60VideoCaptureSession::setAudioBitRate(const int bitRate)
+{
+ if (bitRate != -1)
+ m_audioSettings.setBitRate(bitRate);
+
+ m_uncommittedSettings = true;
+}
+
+void S60VideoCaptureSession::setAudioChannelCount(const int channelCount)
+{
+ if (channelCount != -1)
+ m_audioSettings.setChannelCount(channelCount);
+
+ m_uncommittedSettings = true;
+}
+
+void S60VideoCaptureSession::setVideoCaptureCodec(const QString &codecName)
+{
+ if (codecName == m_videoSettings.codec())
+ return;
+
+ if (codecName.isEmpty())
+ m_videoSettings.setCodec(KMimeTypeDefaultVideoCodec); // Use default
+ else
+ m_videoSettings.setCodec(codecName);
+
+ m_uncommittedSettings = true;
+}
+
+void S60VideoCaptureSession::setAudioCaptureCodec(const QString &codecName)
+{
+ if (codecName == m_audioSettings.codec())
+ return;
+
+ if (codecName.isEmpty()) {
+ m_audioSettings.setCodec(KMimeTypeDefaultAudioCodec); // Use default
+ } else {
+ // If information of supported codecs is already available check that
+ // given codec is supported
+ if (m_captureState >= EOpenComplete) {
+ if (m_audioCodecList.contains(codecName)) {
+ m_audioSettings.setCodec(codecName);
+ m_uncommittedSettings = true;
+ } else {
+ setError(KErrNotSupported, tr("Requested audio codec is not supported"));
+ }
+ } else {
+ m_audioSettings.setCodec(codecName);
+ m_uncommittedSettings = true;
+ }
+ }
+}
+
+QString S60VideoCaptureSession::videoCaptureCodecDescription(const QString &codecName)
+{
+ QString codecDescription;
+ if (codecName.contains("video/H263-2000", Qt::CaseInsensitive))
+ codecDescription.append("H.263 Video Codec");
+ else if (codecName.contains("video/mp4v-es", Qt::CaseInsensitive))
+ codecDescription.append("MPEG-4 Part 2 Video Codec");
+ else if (codecName.contains("video/H264", Qt::CaseInsensitive))
+ codecDescription.append("H.264 AVC (MPEG-4 Part 10) Video Codec");
+ else
+ codecDescription.append("Video Codec");
+
+ return codecDescription;
+}
+
+void S60VideoCaptureSession::doSetCodecsL()
+{
+ // Determine Profile and Level for the video codec if needed
+ // (MimeType/Profile-level-id contains "profile" if profile/level info is available)
+ if (!m_videoSettings.codec().contains(QString("profile"), Qt::CaseInsensitive))
+ m_videoSettings.setCodec(determineProfileAndLevel());
+
+ if (m_videoRecorder) {
+ TPtrC16 str(reinterpret_cast<const TUint16*>(m_videoSettings.codec().utf16()));
+ HBufC8* videoCodec(0);
+ videoCodec = CnvUtfConverter::ConvertFromUnicodeToUtf8L(str);
+ CleanupStack::PushL(videoCodec);
+
+ TFourCC audioCodec = m_audioCodecList[m_audioSettings.codec()];
+
+ TInt vErr = KErrNone;
+ TInt aErr = KErrNone;
+ TRAP(vErr, m_videoRecorder->SetVideoTypeL(*videoCodec));
+ TRAP(aErr, m_videoRecorder->SetAudioTypeL(audioCodec));
+
+ User::LeaveIfError(vErr);
+ User::LeaveIfError(aErr);
+
+ CleanupStack::PopAndDestroy(videoCodec);
+ }
+ else
+ setError(KErrNotReady, tr("Unexpected camera error."));
+}
+
+QString S60VideoCaptureSession::determineProfileAndLevel()
+{
+ QString determinedMimeType = m_videoSettings.codec();
+
+ // H.263
+ if (determinedMimeType.contains(QString("video/H263-2000"), Qt::CaseInsensitive)) {
+ if ((m_videoSettings.resolution().width() * m_videoSettings.resolution().height()) > (176*144)) {
+ if (m_videoSettings.frameRate() > 15.0)
+ determinedMimeType.append("; profile=0; level=20");
+ else
+ determinedMimeType.append("; profile=0; level=40");
+ } else {
+ if (m_videoSettings.bitRate() > 64000)
+ determinedMimeType.append("; profile=0; level=45");
+ else
+ determinedMimeType.append("; profile=0; level=10");
+ }
+
+ // MPEG-4
+ } else if (determinedMimeType.contains(QString("video/mp4v-es"), Qt::CaseInsensitive)) {
+ if ((m_videoSettings.resolution().width() * m_videoSettings.resolution().height()) > (720*480)) {
+ determinedMimeType.append("; profile-level-id=6");
+ } else if ((m_videoSettings.resolution().width() * m_videoSettings.resolution().height()) > (640*480)) {
+ determinedMimeType.append("; profile-level-id=5");
+ } else if ((m_videoSettings.resolution().width() * m_videoSettings.resolution().height()) > (352*288)) {
+ determinedMimeType.append("; profile-level-id=4");
+ } else if ((m_videoSettings.resolution().width() * m_videoSettings.resolution().height()) > (176*144)) {
+ if (m_videoSettings.frameRate() > 15.0)
+ determinedMimeType.append("; profile-level-id=3");
+ else
+ determinedMimeType.append("; profile-level-id=2");
+ } else {
+ if (m_videoSettings.bitRate() > 64000)
+ determinedMimeType.append("; profile-level-id=9");
+ else
+ determinedMimeType.append("; profile-level-id=1");
+ }
+
+ // H.264
+ } else if (determinedMimeType.contains(QString("video/H264"), Qt::CaseInsensitive)) {
+ if ((m_videoSettings.resolution().width() * m_videoSettings.resolution().height()) > (640*480)) {
+ determinedMimeType.append("; profile-level-id=42801F");
+ } else if ((m_videoSettings.resolution().width() * m_videoSettings.resolution().height()) > (352*288)) {
+ determinedMimeType.append("; profile-level-id=42801E");
+ } else if ((m_videoSettings.resolution().width() * m_videoSettings.resolution().height()) > (176*144)) {
+ if (m_videoSettings.frameRate() > 15.0)
+ determinedMimeType.append("; profile-level-id=428015");
+ else
+ determinedMimeType.append("; profile-level-id=42800C");
+ } else {
+ determinedMimeType.append("; profile-level-id=42900B");
+ }
+ }
+
+ return determinedMimeType;
+}
+
+void S60VideoCaptureSession::setBitrate(const int bitrate)
+{
+ m_videoSettings.setBitRate(bitrate);
+
+ m_uncommittedSettings = true;
+}
+
+void S60VideoCaptureSession::doSetBitrate(const int &bitrate)
+{
+ if (bitrate != -1) {
+ if (m_videoRecorder) {
+ TRAPD(err, m_videoRecorder->SetVideoBitRateL(bitrate));
+ if (err) {
+ if (err == KErrNotSupported || err == KErrArgument) {
+ setError(KErrNotSupported, tr("Requested video bitrate is not supported."));
+ m_videoSettings.setBitRate(64000); // Reset
+ } else {
+ setError(err, tr("Failed to set video bitrate."));
+ }
+ }
+ } else {
+ setError(KErrNotReady, tr("Unexpected camera error."));
+ }
+ }
+}
+
+void S60VideoCaptureSession::setVideoResolution(const QSize &resolution)
+{
+ m_videoSettings.setResolution(resolution);
+
+ m_uncommittedSettings = true;
+}
+
+void S60VideoCaptureSession::doSetVideoResolution(const QSize &resolution)
+{
+ TSize size((TInt)resolution.width(), (TInt)resolution.height());
+
+ // Make sure resolution is not too big if main camera is not used
+ if (m_cameraEngine->CurrentCameraIndex() != 0) {
+ TCameraInfo *info = m_cameraEngine->CameraInfo();
+ if (info) {
+ TInt videoResolutionCount = info->iNumVideoFrameSizesSupported;
+ TSize maxCameraVideoResolution = TSize(0,0);
+ CCamera *camera = m_cameraEngine->Camera();
+ if (camera) {
+ for (TInt i = 0; i < videoResolutionCount; ++i) {
+ TSize checkedResolution;
+ // Use YUV video max frame size in the check (Through
+ // CVideoRecorderUtility/DevVideoRecord it is possible to
+ // query only encoder maximums)
+ camera->EnumerateVideoFrameSizes(checkedResolution, i, CCamera::EFormatYUV420Planar);
+ if ((checkedResolution.iWidth * checkedResolution.iHeight) >
+ (maxCameraVideoResolution.iWidth * maxCameraVideoResolution.iHeight))
+ maxCameraVideoResolution = checkedResolution;
+ }
+ if ((maxCameraVideoResolution.iWidth * maxCameraVideoResolution.iHeight) <
+ (size.iWidth * size.iHeight)) {
+ size = maxCameraVideoResolution;
+ setError(KErrNotSupported, tr("Requested resolution is not supported for this camera."));
+ }
+ }
+ else
+ setError(KErrGeneral, tr("Could not query supported video resolutions."));
+ }else
+ setError(KErrGeneral, tr("Could not query supported video resolutions."));
+ }
+
+ if (resolution.width() != -1 && resolution.height() != -1) {
+ if (m_videoRecorder) {
+ TRAPD(err, m_videoRecorder->SetVideoFrameSizeL((TSize)size));
+ if (err == KErrNotSupported || err == KErrArgument) {
+ setError(KErrNotSupported, tr("Requested video resolution is not supported."));
+ TSize fallBack(640,480);
+ TRAPD(err, m_videoRecorder->SetVideoFrameSizeL(fallBack));
+ if (err == KErrNone) {
+ m_videoSettings.setResolution(QSize(fallBack.iWidth,fallBack.iHeight));
+ } else {
+ fallBack = TSize(176,144);
+ TRAPD(err, m_videoRecorder->SetVideoFrameSizeL(fallBack));
+ if (err == KErrNone)
+ m_videoSettings.setResolution(QSize(fallBack.iWidth,fallBack.iHeight));
+ }
+ } else {
+ setError(err, tr("Failed to set video resolution."));
+ }
+ } else {
+ setError(KErrNotReady, tr("Unexpected camera error."));
+ }
+ }
+}
+
+void S60VideoCaptureSession::setFrameRate(qreal rate)
+{
+ m_videoSettings.setFrameRate(rate);
+
+ m_uncommittedSettings = true;
+}
+
+void S60VideoCaptureSession::doSetFrameRate(qreal rate)
+{
+ if (rate != 0) {
+ if (m_videoRecorder) {
+ bool continuous = false;
+ QList<qreal> list = supportedVideoFrameRates(&continuous);
+ qreal maxRate = 0.0;
+ foreach (qreal fRate, list)
+ if (fRate > maxRate)
+ maxRate = fRate;
+ if (maxRate >= rate && rate > 0) {
+ TRAPD(err, m_videoRecorder->SetVideoFrameRateL((TReal32)rate));
+ if (err == KErrNotSupported) {
+ setError(KErrNotSupported, tr("Requested framerate is not supported."));
+ TReal32 fallBack = 15.0;
+ TRAPD(err, m_videoRecorder->SetVideoFrameRateL(fallBack));
+ if (err == KErrNone)
+ m_videoSettings.setFrameRate((qreal)fallBack);
+ } else {
+ if (err == KErrArgument) {
+ setError(KErrNotSupported, tr("Requested framerate is not supported."));
+ m_videoSettings.setFrameRate(15.0); // Reset
+ } else {
+ setError(err, tr("Failed to set video framerate."));
+ }
+ }
+ } else {
+ setError(KErrNotSupported, tr("Requested framerate is not supported."));
+ m_videoSettings.setFrameRate(15.0); // Reset
+ }
+ } else {
+ setError(KErrNotReady, tr("Unexpected camera error."));
+ }
+ }
+}
+
+void S60VideoCaptureSession::setVideoEncodingMode(const QtMultimediaKit::EncodingMode mode)
+{
+ // This has no effect as it has no support in Symbian
+
+ if (mode == QtMultimediaKit::ConstantQualityEncoding) {
+ m_videoSettings.setEncodingMode(mode);
+ return;
+ }
+
+ setError(KErrNotSupported, tr("Requested video encoding mode is not supported"));
+
+ // m_uncommittedSettings = true;
+}
+
+void S60VideoCaptureSession::setAudioEncodingMode(const QtMultimediaKit::EncodingMode mode)
+{
+ // This has no effect as it has no support in Symbian
+
+ if (mode == QtMultimediaKit::ConstantQualityEncoding) {
+ m_audioSettings.setEncodingMode(mode);
+ return;
+ }
+
+ setError(KErrNotSupported, tr("Requested audio encoding mode is not supported"));
+
+ // m_uncommittedSettings = true;
+}
+
+void S60VideoCaptureSession::initializeVideoCaptureSettings()
+{
+ // Check if user has already requested some settings
+ if (m_captureSettingsSet)
+ return;
+
+ QSize resolution(-1, -1);
+ qreal frameRate(0);
+ int bitRate(-1);
+
+ if (m_cameraEngine) {
+
+ if (m_videoRecorder && m_captureState >= EInitialized) {
+
+ // Resolution
+ QList<QSize> resos = supportedVideoResolutions(0);
+ foreach (QSize reso, resos) {
+ if ((reso.width() * reso.height()) > (resolution.width() * resolution.height()))
+ resolution = reso;
+ }
+
+ // Needed to query supported framerates for this codec/resolution pair
+ m_videoSettings.setCodec(KMimeTypeDefaultVideoCodec);
+ m_videoSettings.setResolution(resolution);
+
+ // FrameRate
+ QList<qreal> fRates = supportedVideoFrameRates(m_videoSettings, 0);
+ foreach (qreal rate, fRates) {
+ if (rate > frameRate)
+ frameRate = rate;
+ }
+
+ // BitRate
+#ifdef SYMBIAN_3_PLATFORM
+ if (m_cameraEngine->CurrentCameraIndex() == 0)
+ bitRate = KBiR_H264_PLID_42801F // 14Mbps
+ else
+ bitRate = KBiR_H264_PLID_428016 // 4Mbps
+#else // Other platforms
+ if (m_cameraEngine->CurrentCameraIndex() == 0)
+ bitRate = KBiR_MPEG4_PLID_4 // 2/4Mbps
+ else
+ bitRate = KBiR_MPEG4_PLID_3 // 384kbps
+#endif // SYMBIAN_3_PLATFORM
+
+ } else {
+#ifdef SYMBIAN_3_PLATFORM
+ if (m_cameraEngine->CurrentCameraIndex() == 0) {
+ // Primary camera
+ resolution = KResH264_PLID_42801F; // 1280x720
+ frameRate = KFrR_H264_PLID_42801F; // 30fps
+ bitRate = KBiR_H264_PLID_42801F; // 14Mbps
+ } else {
+ // Other cameras
+ resolution = KResH264_PLID_42801E; // 640x480
+ frameRate = KFrR_H264_PLID_428014; // 30fps
+ bitRate = KBiR_H264_PLID_428016; // 4Mbps
+ }
+#else // Other platforms
+ if (m_cameraEngine->CurrentCameraIndex() == 0) {
+ // Primary camera
+ resolution = KResMPEG4_PLID_4; // 640x480
+ frameRate = KFrR_MPEG4_PLID_4; // 15/30fps
+ bitRate = KBiR_MPEG4_PLID_4; // 2/4Mbps
+ } else {
+ // Other cameras
+ resolution = KResMPEG4_PLID_3; // 352x288
+ frameRate = KFrR_MPEG4; // 15fps
+ bitRate = KBiR_MPEG4_PLID_3; // 384kbps
+ }
+#endif // SYMBIAN_3_PLATFORM
+ }
+ } else {
+#ifdef SYMBIAN_3_PLATFORM
+ resolution = KResH264_PLID_42801F;
+ frameRate = KFrR_H264_PLID_42801F;
+ bitRate = KBiR_H264_PLID_42801F;
+#else // Pre-Symbian3 Platforms
+ resolution = KResMPEG4_PLID_4;
+ frameRate = KFrR_MPEG4_PLID_4;
+ bitRate = KBiR_MPEG4_PLID_4;
+#endif // SYMBIAN_3_PLATFORM
+ }
+
+ // Set specified settings (Resolution, FrameRate and BitRate)
+ m_videoSettings.setResolution(resolution);
+ m_videoSettings.setFrameRate(frameRate);
+ m_videoSettings.setBitRate(bitRate);
+
+ // Video Settings: Codec, EncodingMode and Quality
+ m_videoSettings.setCodec(KMimeTypeDefaultVideoCodec);
+ m_videoSettings.setEncodingMode(QtMultimediaKit::ConstantQualityEncoding);
+ m_videoSettings.setQuality(QtMultimediaKit::VeryHighQuality);
+
+ // Audio Settings
+ m_audioSettings.setCodec(KMimeTypeDefaultAudioCodec);
+ m_audioSettings.setBitRate(KDefaultBitRate);
+ m_audioSettings.setSampleRate(KDefaultSampleRate);
+ m_audioSettings.setChannelCount(KDefaultChannelCount);
+ m_audioSettings.setEncodingMode(QtMultimediaKit::ConstantQualityEncoding);
+ m_audioSettings.setQuality(QtMultimediaKit::VeryHighQuality);
+}
+
+QSize S60VideoCaptureSession::pixelAspectRatio()
+{
+#ifndef S60_31_PLATFORM
+ TVideoAspectRatio par;
+ TRAPD(err, m_videoRecorder->GetPixelAspectRatioL(par));
+ if (err)
+ setError(err, tr("Failed to query current pixel aspect ratio."));
+ return QSize(par.iNumerator, par.iDenominator);
+#else // S60_31_PLATFORM
+ return QSize();
+#endif // !S60_31_PLATFORM
+}
+
+void S60VideoCaptureSession::setPixelAspectRatio(const QSize par)
+{
+#ifndef S60_31_PLATFORM
+
+ const TVideoAspectRatio videoPar(par.width(), par.height());
+ TRAPD(err, m_videoRecorder->SetPixelAspectRatioL(videoPar));
+ if (err)
+ setError(err, tr("Failed to set pixel aspect ratio."));
+#else // S60_31_PLATFORM
+ Q_UNUSED(par);
+#endif // !S60_31_PLATFORM
+
+ m_uncommittedSettings = true;
+}
+
+int S60VideoCaptureSession::gain()
+{
+ TInt gain = 0;
+ TRAPD(err, gain = m_videoRecorder->GainL());
+ if (err)
+ setError(err, tr("Failed to query video gain."));
+ return (int)gain;
+}
+
+void S60VideoCaptureSession::setGain(const int gain)
+{
+ TRAPD(err, m_videoRecorder->SetGainL(gain));
+ if (err)
+ setError(err, tr("Failed to set video gain."));
+
+ m_uncommittedSettings = true;
+}
+
+int S60VideoCaptureSession::maxClipSizeInBytes() const
+{
+ return m_maxClipSize;
+}
+
+void S60VideoCaptureSession::setMaxClipSizeInBytes(const int size)
+{
+ TRAPD(err, m_videoRecorder->SetMaxClipSizeL(size));
+ if (err) {
+ setError(err, tr("Failed to set maximum video size."));
+ } else
+ m_maxClipSize = size;
+
+ m_uncommittedSettings = true;
+}
+
+void S60VideoCaptureSession::MvruoOpenComplete(TInt aError)
+{
+ if (m_error)
+ return;
+
+ if (aError == KErrNone && m_videoRecorder) {
+ if (m_captureState == EInitializing) {
+ // Dummy file open completed, initialize settings
+ TRAPD(err, doPopulateAudioCodecsL());
+ setError(err, tr("Failed to gather information of supported audio codecs."));
+
+ // For DevVideoRecord codecs are populated during
+ // doPopulateVideoCodecsDataL()
+ TRAP(err, doPopulateVideoCodecsL());
+ setError(err, tr("Failed to gather information of supported video codecs."));
+#ifndef S60_DEVVIDEO_RECORDING_SUPPORTED
+ // Max parameters needed to be populated, if not using DevVideoRecord
+ // Otherwise done already in constructor
+ doPopulateMaxVideoParameters();
+#endif // S60_DEVVIDEO_RECORDING_SUPPORTED
+
+ m_captureState = EInitialized;
+ emit stateChanged(m_captureState);
+
+ // Initialize settings if not already done
+ initializeVideoCaptureSettings();
+
+ // Validate codecs to be used
+ validateRequestedCodecs();
+
+ if (m_openWhenReady || m_prepareAfterOpenComplete || m_startAfterPrepareComplete) {
+ setOutputLocation(m_requestedSink);
+ m_openWhenReady = false; // Reset
+ }
+ if (m_commitSettingsWhenReady) {
+ applyAllSettings();
+ m_commitSettingsWhenReady = false; // Reset
+ }
+ return;
+
+ } else if (m_captureState == EOpening) {
+ // Actual file open completed
+ m_captureState = EOpenComplete;
+ emit stateChanged(m_captureState);
+
+ // Prepare right away
+ if (m_startAfterPrepareComplete || m_prepareAfterOpenComplete) {
+ m_prepareAfterOpenComplete = false; // Reset
+
+ // Commit settings and prepare with them
+ applyAllSettings();
+ }
+ return;
+
+ } else if (m_captureState == ENotInitialized) {
+ // Resources released while waiting OpenFileL to complete
+ m_videoRecorder->Close();
+ return;
+
+ } else {
+ setError(KErrGeneral, tr("Unexpected camera error."));
+ return;
+ }
+ }
+
+ m_videoRecorder->Close();
+ if (aError == KErrNotFound || aError == KErrNotSupported || aError == KErrArgument)
+ setError(KErrGeneral, tr("Requested video container or controller is not supported."));
+ else
+ setError(KErrGeneral, tr("Failure during video recorder initialization."));
+}
+
+void S60VideoCaptureSession::MvruoPrepareComplete(TInt aError)
+{
+ if (m_error)
+ return;
+
+ if(aError == KErrNone) {
+ if (m_captureState == ENotInitialized) {
+ // Resources released while waiting for Prepare to complete
+ m_videoRecorder->Close();
+ return;
+ }
+
+ emit captureSizeChanged(m_videoSettings.resolution());
+
+ m_captureState = EPrepared;
+ emit stateChanged(EPrepared);
+
+ // Check the actual active settings
+ queryAudioEncoderSettings();
+ queryVideoEncoderSettings();
+
+ if (m_openWhenReady == true) {
+ setOutputLocation(m_requestedSink);
+ m_openWhenReady = false; // Reset
+ }
+
+ if (m_commitSettingsWhenReady) {
+ applyAllSettings();
+ m_commitSettingsWhenReady = false; // Reset
+ }
+
+ if (m_startAfterPrepareComplete) {
+ m_startAfterPrepareComplete = false; // Reset
+ startRecording();
+ }
+ } else {
+ m_videoRecorder->Close();
+ if (aError == KErrNotSupported)
+ setError(aError, tr("Camera preparation for video recording failed because of unsupported setting."));
+ else
+ setError(aError, tr("Failed to prepare camera for video recording."));
+ }
+}
+
+void S60VideoCaptureSession::MvruoRecordComplete(TInt aError)
+{
+ if (!m_videoRecorder) {
+ setError(KErrNotReady, tr("Unexpected camera error."));
+ return;
+ }
+
+ if((aError == KErrNone || aError == KErrCompletion)) {
+ m_videoRecorder->Stop();
+
+ // Reset state
+ if (m_captureState != ENotInitialized) {
+ m_captureState = ENotInitialized;
+ emit stateChanged(m_captureState);
+ if (m_durationTimer->isActive())
+ m_durationTimer->stop();
+ }
+
+ if (m_cameraEngine->IsCameraReady())
+ initializeVideoRecording();
+ }
+ m_videoRecorder->Close();
+
+ // Notify muting is disabled if needed
+ if (m_muted)
+ emit mutedChanged(false);
+
+ if (aError == KErrDiskFull)
+ setError(aError, tr("Not enough space for video, recording stopped."));
+ else
+ setError(aError, tr("Recording stopped due to unexpected error."));
+}
+
+void S60VideoCaptureSession::MvruoEvent(const TMMFEvent& aEvent)
+{
+ Q_UNUSED(aEvent);
+}
+
+#ifdef S60_DEVVIDEO_RECORDING_SUPPORTED
+void S60VideoCaptureSession::MdvroReturnPicture(TVideoPicture *aPicture)
+{
+ // Not used
+ Q_UNUSED(aPicture);
+}
+
+void S60VideoCaptureSession::MdvroSupplementalInfoSent()
+{
+ // Not used
+}
+
+void S60VideoCaptureSession::MdvroNewBuffers()
+{
+ // Not used
+}
+
+void S60VideoCaptureSession::MdvroFatalError(TInt aError)
+{
+ setError(aError, tr("Unexpected camera error."));
+}
+
+void S60VideoCaptureSession::MdvroInitializeComplete(TInt aError)
+{
+ // Not used
+ Q_UNUSED(aError);
+}
+
+void S60VideoCaptureSession::MdvroStreamEnd()
+{
+ // Not used
+}
+
+/*
+ * This populates video codec information (supported codecs, resolutions,
+ * framerates, etc.) using DevVideoRecord API.
+ */
+void S60VideoCaptureSession::doPopulateVideoCodecsDataL()
+{
+ RArray<TUid> encoders;
+ CleanupClosePushL(encoders);
+
+ CMMFDevVideoRecord *mDevVideoRecord = CMMFDevVideoRecord::NewL(*this);
+ CleanupStack::PushL(mDevVideoRecord);
+
+ // Retrieve list of all encoders provided by the platform
+ mDevVideoRecord->GetEncoderListL(encoders);
+
+ for (int i = 0; i < encoders.Count(); ++i ) {
+
+ CVideoEncoderInfo *encoderInfo = mDevVideoRecord->VideoEncoderInfoLC(encoders[i]);
+
+ // Discard encoders that are not HW accelerated and do not support direct capture
+ if (encoderInfo->Accelerated() == false || encoderInfo->SupportsDirectCapture() == false) {
+ CleanupStack::Check(encoderInfo);
+ CleanupStack::PopAndDestroy(encoderInfo);
+ continue;
+ }
+
+ m_videoParametersForEncoder.append(MaxResolutionRatesAndTypes());
+ int newIndex = m_videoParametersForEncoder.count() - 1;
+
+ m_videoParametersForEncoder[newIndex].bitRate = (int)encoderInfo->MaxBitrate();
+
+ // Get supported MIME Types
+ const RPointerArray<CCompressedVideoFormat> &videoFormats = encoderInfo->SupportedOutputFormats();
+ for(int x = 0; x < videoFormats.Count(); ++x) {
+ QString codecMimeType = QString::fromUtf8((char *)videoFormats[x]->MimeType().Ptr(),videoFormats[x]->MimeType().Length());
+
+ m_videoParametersForEncoder[newIndex].mimeTypes.append(codecMimeType);
+ }
+
+ // Get supported maximum Resolution/Framerate pairs
+ const RArray<TPictureRateAndSize> &ratesAndSizes = encoderInfo->MaxPictureRates();
+ SupportedFrameRatePictureSize data;
+ for(int j = 0; j < ratesAndSizes.Count(); ++j) {
+ data.frameRate = ratesAndSizes[j].iPictureRate;
+ data.frameSize = QSize(ratesAndSizes[j].iPictureSize.iWidth, ratesAndSizes[j].iPictureSize.iHeight);
+
+ // Save data to the hash
+ m_videoParametersForEncoder[newIndex].frameRatePictureSizePair.append(data);
+ }
+
+ CleanupStack::Check(encoderInfo);
+ CleanupStack::PopAndDestroy(encoderInfo);
+ }
+
+ CleanupStack::Check(mDevVideoRecord);
+ CleanupStack::PopAndDestroy(mDevVideoRecord);
+ CleanupStack::PopAndDestroy(); // RArray<TUid> encoders
+}
+#endif // S60_DEVVIDEO_RECORDING_SUPPORTED
+
+QStringList S60VideoCaptureSession::supportedVideoContainers()
+{
+ QStringList containers;
+
+ QList<TInt> controllers = m_videoControllerMap.keys();
+ for (int i = 0; i < controllers.count(); ++i) {
+ foreach (VideoFormatData formatData, m_videoControllerMap[controllers[i]]) {
+ for (int j = 0; j < formatData.supportedMimeTypes.count(); ++j) {
+ if (containers.contains(formatData.supportedMimeTypes[j], Qt::CaseInsensitive) == false)
+ containers.append(formatData.supportedMimeTypes[j]);
+ }
+ }
+ }
+
+ return containers;
+}
+
+bool S60VideoCaptureSession::isSupportedVideoContainer(const QString &containerName)
+{
+ return supportedVideoContainers().contains(containerName, Qt::CaseInsensitive);
+}
+
+QString S60VideoCaptureSession::videoContainer() const
+{
+ return m_container;
+}
+
+void S60VideoCaptureSession::setVideoContainer(const QString &containerName)
+{
+ if (containerName == m_requestedContainer)
+ return;
+
+ if (containerName.isEmpty()) {
+ m_requestedContainer = KMimeTypeDefaultContainer; // Use default
+ } else {
+ if (supportedVideoContainers().contains(containerName)) {
+ m_requestedContainer = containerName;
+ } else {
+ setError(KErrNotSupported, tr("Requested video container is not supported."));
+ m_requestedContainer = KMimeTypeDefaultContainer; // Reset to default
+ }
+ }
+
+ m_uncommittedSettings = true;
+}
+
+QString S60VideoCaptureSession::videoContainerDescription(const QString &containerName)
+{
+ QList<TInt> formats;
+ QList<TInt> encoders = m_videoControllerMap.keys();
+ for (int i = 0; i < encoders.count(); ++i) {
+ formats = m_videoControllerMap[encoders[i]].keys();
+ for (int j = 0; j < formats.count(); ++j) {
+ if (m_videoControllerMap[encoders[i]][formats[j]].supportedMimeTypes.contains(containerName, Qt::CaseInsensitive))
+ return m_videoControllerMap[encoders[i]][formats[j]].description;
+ }
+ }
+
+ return QString();
+}
+
+void S60VideoCaptureSession::cameraStatusChanged(QCamera::Status status)
+{
+ if (status == QCamera::ActiveStatus) {
+ m_cameraStarted = true;
+
+ // Continue preparation or start recording if previously requested
+ if (m_captureState == EInitialized
+ && (m_openWhenReady || m_prepareAfterOpenComplete || m_startAfterPrepareComplete)) {
+ setOutputLocation(m_requestedSink);
+ m_openWhenReady = false; // Reset
+ } else if ((m_captureState == EOpenComplete || m_captureState == EPrepared)
+ && (m_prepareAfterOpenComplete || m_startAfterPrepareComplete)) {
+ startRecording();
+ m_prepareAfterOpenComplete = false; // Reset
+ }
+
+ } else if (status == QCamera::UnloadedStatus) {
+ m_cameraStarted = false;
+ releaseVideoRecording();
+ } else {
+ m_cameraStarted = false;
+ }
+}
+
+void S60VideoCaptureSession::durationTimerTriggered()
+{
+ // Update position only if recording is ongoing
+ if ((m_captureState == ERecording) && m_videoRecorder) {
+ // Signal will be automatically emitted of position changes
+ TRAPD(err, m_position = m_videoRecorder->DurationL().Int64() / 1000);
+ setError(err, tr("Cannot retrieve video position."));
+
+ emit positionChanged(m_position);
+ }
+}
+
+void S60VideoCaptureSession::doPopulateAudioCodecsL()
+{
+ if (m_captureState == EInitializing) {
+ m_audioCodecList.clear();
+
+ RArray<TFourCC> audioTypes;
+ CleanupClosePushL(audioTypes);
+
+ if (m_videoRecorder)
+ m_videoRecorder->GetSupportedAudioTypesL(audioTypes);
+ else
+ setError(KErrNotReady, tr("Unexpected camera error."));
+
+ for (TInt i = 0; i < audioTypes.Count(); i++) {
+ TUint32 codec = audioTypes[i].FourCC();
+
+ if (codec == KMMFFourCCCodeAMR)
+ m_audioCodecList.insert(QString("audio/amr"), KMMFFourCCCodeAMR);
+ if (codec == KMMFFourCCCodeAAC)
+ m_audioCodecList.insert(QString("audio/aac"), KMMFFourCCCodeAAC);
+ }
+ CleanupStack::PopAndDestroy(&audioTypes);
+ }
+}
+
+void S60VideoCaptureSession::doPopulateVideoCodecsL()
+{
+ if (m_captureState == EInitializing) {
+ m_videoCodecList.clear();
+
+ CDesC8ArrayFlat* videoTypes = new (ELeave) CDesC8ArrayFlat(10);
+ CleanupStack::PushL(videoTypes);
+
+ if (m_videoRecorder)
+ m_videoRecorder->GetSupportedVideoTypesL(*videoTypes);
+ else
+ setError(KErrNotReady, tr("Unexpected camera error."));
+
+ for (TInt i = 0; i < videoTypes->Count(); i++) {
+ TPtrC8 videoType = videoTypes->MdcaPoint(i);
+ QString codecMimeType = QString::fromUtf8((char *)videoType.Ptr(), videoType.Length());
+#ifdef S60_DEVVIDEO_RECORDING_SUPPORTED
+ for (int j = 0; j < m_videoParametersForEncoder.size(); ++j) {
+ if (m_videoParametersForEncoder[j].mimeTypes.contains(codecMimeType, Qt::CaseInsensitive)) {
+ m_videoCodecList << codecMimeType;
+ break;
+ }
+ }
+#else // CVideoRecorderUtility
+ m_videoCodecList << codecMimeType;
+#endif // S60_DEVVIDEO_RECORDING_SUPPORTED
+ }
+ CleanupStack::PopAndDestroy(videoTypes);
+ }
+}
+
+#ifndef S60_DEVVIDEO_RECORDING_SUPPORTED
+/*
+ * Maximum resolution, framerate and bitrate can not be queried via MMF or
+ * ECam, but needs to be set according to the definitions of the video
+ * standard in question. In video standards, the values often depend on each
+ * other, but the below function defines constant maximums.
+ */
+void S60VideoCaptureSession::doPopulateMaxVideoParameters()
+{
+ m_videoParametersForEncoder.append(MaxResolutionRatesAndTypes()); // For H.263
+ m_videoParametersForEncoder.append(MaxResolutionRatesAndTypes()); // For MPEG-4
+ m_videoParametersForEncoder.append(MaxResolutionRatesAndTypes()); // For H.264
+
+ for (int i = 0; i < m_videoCodecList.count(); ++i) {
+
+ // Use all lower case for comparisons
+ QString codec = m_videoCodecList[i].toLower();
+
+ if (codec.contains("video/h263-2000", Qt::CaseInsensitive)) {
+ // H.263
+ if (codec == "video/h263-2000" ||
+ codec == "video/h263-2000; profile=0" ||
+ codec == "video/h263-2000; profile=0; level=10" ||
+ codec == "video/h263-2000; profile=3") {
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(15.0, QSize(176,144)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 64000)
+ m_videoParametersForEncoder[0].bitRate = 64000;
+ continue;
+ } else if (codec == "video/h263-2000; profile=0; level=20") {
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(15.0, QSize(352,288)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 128000)
+ m_videoParametersForEncoder[0].bitRate = 128000;
+ continue;
+ } else if (codec == "video/h263-2000; profile=0; level=30") {
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(30.0, QSize(352,288)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 384000)
+ m_videoParametersForEncoder[0].bitRate = 384000;
+ continue;
+ } else if (codec == "video/h263-2000; profile=0; level=40") {
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(30.0, QSize(352,288)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 2048000)
+ m_videoParametersForEncoder[0].bitRate = 2048000;
+ continue;
+ } else if (codec == "video/h263-2000; profile=0; level=45") {
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(15.0, QSize(176,144)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 128000)
+ m_videoParametersForEncoder[0].bitRate = 128000;
+ continue;
+ } else if (codec == "video/h263-2000; profile=0; level=50") {
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(15.0, QSize(352,288)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 4096000)
+ m_videoParametersForEncoder[0].bitRate = 4096000;
+ continue;
+ }
+
+ } else if (codec.contains("video/mp4v-es", Qt::CaseInsensitive)) {
+ // Mpeg-4
+ if (codec == "video/mp4v-es" ||
+ codec == "video/mp4v-es; profile-level-id=1" ||
+ codec == "video/mp4v-es; profile-level-id=8") {
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(15.0, QSize(176,144)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 64000)
+ m_videoParametersForEncoder[0].bitRate = 64000;
+ continue;
+ } else if (codec == "video/mp4v-es; profile-level-id=2" ||
+ codec == "video/mp4v-es; profile-level-id=9") {
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(15.0, QSize(352,288)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 128000)
+ m_videoParametersForEncoder[0].bitRate = 128000;
+ continue;
+ } else if (codec == "video/mp4v-es; profile-level-id=3") {
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(30.0, QSize(352,288)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 384000)
+ m_videoParametersForEncoder[0].bitRate = 384000;
+ continue;
+ } else if (codec == "video/mp4v-es; profile-level-id=4") {
+#if (defined(S60_31_PLATFORM) | defined(S60_32_PLATFORM))
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(15.0, QSize(640,480)));
+#else // S60 5.0 and later platforms
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(30.0, QSize(640,480)));
+#endif
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 4000000)
+ m_videoParametersForEncoder[0].bitRate = 4000000;
+ continue;
+ } else if (codec == "video/mp4v-es; profile-level-id=5") {
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(25.0, QSize(720,576)));
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(30.0, QSize(720,480)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 8000000)
+ m_videoParametersForEncoder[0].bitRate = 8000000;
+ continue;
+ } else if (codec == "video/mp4v-es; profile-level-id=6") {
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(30.0, QSize(1280,720)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 12000000)
+ m_videoParametersForEncoder[0].bitRate = 12000000;
+ continue;
+ }
+
+ } else if (codec.contains("video/h264", Qt::CaseInsensitive)) {
+ // H.264
+ if (codec == "video/h264" ||
+ codec == "video/h264; profile-level-id=42800a") {
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(15.0, QSize(176,144)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 64000)
+ m_videoParametersForEncoder[0].bitRate = 64000;
+ continue;
+ } else if (codec == "video/h264; profile-level-id=42900b") { // BP, L1b
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(15.0, QSize(176,144)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 128000)
+ m_videoParametersForEncoder[0].bitRate = 128000;
+ continue;
+ } else if (codec == "video/h264; profile-level-id=42800b") { // BP, L1.1
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(7.5, QSize(352,288)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 192000)
+ m_videoParametersForEncoder[0].bitRate = 192000;
+ continue;
+ } else if (codec == "video/h264; profile-level-id=42800c") { // BP, L1.2
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(15.0, QSize(352,288)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 384000)
+ m_videoParametersForEncoder[0].bitRate = 384000;
+ continue;
+ } else if (codec == "video/h264; profile-level-id=42800d") { // BP, L1.3
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(30.0, QSize(352,288)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 768000)
+ m_videoParametersForEncoder[0].bitRate = 768000;
+ continue;
+ } else if (codec == "video/h264; profile-level-id=428014") { // BP, L2
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(30.0, QSize(352,288)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 2000000)
+ m_videoParametersForEncoder[0].bitRate = 2000000;
+ continue;
+ } else if (codec == "video/h264; profile-level-id=428015") { // BP, L2.1
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(50.0, QSize(352,288)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 4000000)
+ m_videoParametersForEncoder[0].bitRate = 4000000;
+ continue;
+ } else if (codec == "video/h264; profile-level-id=428016") { // BP, L2.2
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(16.9, QSize(640,480)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 4000000)
+ m_videoParametersForEncoder[0].bitRate = 4000000;
+ continue;
+ } else if (codec == "video/h264; profile-level-id=42801e") { // BP, L3
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(33.8, QSize(640,480)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 10000000)
+ m_videoParametersForEncoder[0].bitRate = 10000000;
+ continue;
+ } else if (codec == "video/h264; profile-level-id=42801f") { // BP, L3.1
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(30.0, QSize(1280,720)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 14000000)
+ m_videoParametersForEncoder[0].bitRate = 14000000;
+ continue;
+ }
+ }
+ }
+}
+#endif // S60_DEVVIDEO_RECORDING_SUPPORTED
+
+/*
+ * This function returns the maximum resolution defined by the video standards
+ * for different MIME Types.
+ */
+QSize S60VideoCaptureSession::maximumResolutionForMimeType(const QString &mimeType) const
+{
+ QSize maxSize(-1,-1);
+ // Use all lower case for comparisons
+ QString lowerMimeType = mimeType.toLower();
+
+ if (lowerMimeType == "video/h263-2000") {
+ maxSize = KResH263;
+ } else if (lowerMimeType == "video/h263-2000; profile=0") {
+ maxSize = KResH263_Profile0;
+ } else if (lowerMimeType == "video/h263-2000; profile=0; level=10") {
+ maxSize = KResH263_Profile0_Level10;
+ } else if (lowerMimeType == "video/h263-2000; profile=0; level=20") {
+ maxSize = KResH263_Profile0_Level20;
+ } else if (lowerMimeType == "video/h263-2000; profile=0; level=30") {
+ maxSize = KResH263_Profile0_Level30;
+ } else if (lowerMimeType == "video/h263-2000; profile=0; level=40") {
+ maxSize = KResH263_Profile0_Level40;
+ } else if (lowerMimeType == "video/h263-2000; profile=0; level=45") {
+ maxSize = KResH263_Profile0_Level45;
+ } else if (lowerMimeType == "video/h263-2000; profile=0; level=50") {
+ maxSize = KResH263_Profile0_Level50;
+ } else if (lowerMimeType == "video/h263-2000; profile=3") {
+ maxSize = KResH263_Profile3;
+ } else if (lowerMimeType == "video/mp4v-es") {
+ maxSize = KResMPEG4;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=1") {
+ maxSize = KResMPEG4_PLID_1;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=2") {
+ maxSize = KResMPEG4_PLID_2;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=3") {
+ maxSize = KResMPEG4_PLID_3;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=4") {
+ maxSize = KResMPEG4_PLID_4;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=5") {
+ maxSize = KResMPEG4_PLID_5;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=6") {
+ maxSize = KResMPEG4_PLID_6;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=8") {
+ maxSize = KResMPEG4_PLID_8;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=9") {
+ maxSize = KResMPEG4_PLID_9;
+ } else if (lowerMimeType == "video/h264") {
+ maxSize = KResH264;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42800a" ||
+ lowerMimeType == "video/h264; profile-level-id=4d400a" ||
+ lowerMimeType == "video/h264; profile-level-id=64400a") { // L1
+ maxSize = KResH264_PLID_42800A;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42900b" ||
+ lowerMimeType == "video/h264; profile-level-id=4d500b" ||
+ lowerMimeType == "video/h264; profile-level-id=644009") { // L1.b
+ maxSize = KResH264_PLID_42900B;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42800b" ||
+ lowerMimeType == "video/h264; profile-level-id=4d400b" ||
+ lowerMimeType == "video/h264; profile-level-id=64400b") { // L1.1
+ maxSize = KResH264_PLID_42800B;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42800c" ||
+ lowerMimeType == "video/h264; profile-level-id=4d400c" ||
+ lowerMimeType == "video/h264; profile-level-id=64400c") { // L1.2
+ maxSize = KResH264_PLID_42800C;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42800d" ||
+ lowerMimeType == "video/h264; profile-level-id=4d400d" ||
+ lowerMimeType == "video/h264; profile-level-id=64400d") { // L1.3
+ maxSize = KResH264_PLID_42800D;
+ } else if (lowerMimeType == "video/h264; profile-level-id=428014" ||
+ lowerMimeType == "video/h264; profile-level-id=4d4014" ||
+ lowerMimeType == "video/h264; profile-level-id=644014") { // L2
+ maxSize = KResH264_PLID_428014;
+ } else if (lowerMimeType == "video/h264; profile-level-id=428015" ||
+ lowerMimeType == "video/h264; profile-level-id=4d4015" ||
+ lowerMimeType == "video/h264; profile-level-id=644015") { // L2.1
+ maxSize = KResH264_PLID_428015;
+ } else if (lowerMimeType == "video/h264; profile-level-id=428016" ||
+ lowerMimeType == "video/h264; profile-level-id=4d4016" ||
+ lowerMimeType == "video/h264; profile-level-id=644016") { // L2.2
+ maxSize = KResH264_PLID_428016;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42801e" ||
+ lowerMimeType == "video/h264; profile-level-id=4d401e" ||
+ lowerMimeType == "video/h264; profile-level-id=64401e") { // L3
+ maxSize = KResH264_PLID_42801E;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42801f" ||
+ lowerMimeType == "video/h264; profile-level-id=4d401f" ||
+ lowerMimeType == "video/h264; profile-level-id=64401f") { // L3.1
+ maxSize = KResH264_PLID_42801F;
+ } else if (lowerMimeType == "video/h264; profile-level-id=428020" ||
+ lowerMimeType == "video/h264; profile-level-id=4d4020" ||
+ lowerMimeType == "video/h264; profile-level-id=644020") { // L3.2
+ maxSize = KResH264_PLID_428020;
+ } else if (lowerMimeType == "video/h264; profile-level-id=428028" ||
+ lowerMimeType == "video/h264; profile-level-id=4d4028" ||
+ lowerMimeType == "video/h264; profile-level-id=644028") { // L4
+ maxSize = KResH264_PLID_428028;
+ }
+
+ return maxSize;
+}
+
+/*
+ * This function returns the maximum framerate defined by the video standards
+ * for different MIME Types.
+ */
+
+qreal S60VideoCaptureSession::maximumFrameRateForMimeType(const QString &mimeType) const
+{
+ qreal maxRate(-1.0);
+ // Use all lower case for comparisons
+ QString lowerMimeType = mimeType.toLower();
+
+ if (lowerMimeType == "video/h263-2000") {
+ maxRate = KFrR_H263;
+ } else if (lowerMimeType == "video/h263-2000; profile=0") {
+ maxRate = KFrR_H263_Profile0;
+ } else if (lowerMimeType == "video/h263-2000; profile=0; level=10") {
+ maxRate = KFrR_H263_Profile0_Level10;
+ } else if (lowerMimeType == "video/h263-2000; profile=0; level=20") {
+ maxRate = KFrR_H263_Profile0_Level20;
+ } else if (lowerMimeType == "video/h263-2000; profile=0; level=30") {
+ maxRate = KFrR_H263_Profile0_Level30;
+ } else if (lowerMimeType == "video/h263-2000; profile=0; level=40") {
+ maxRate = KFrR_H263_Profile0_Level40;
+ } else if (lowerMimeType == "video/h263-2000; profile=0; level=45") {
+ maxRate = KFrR_H263_Profile0_Level45;
+ } else if (lowerMimeType == "video/h263-2000; profile=0; level=50") {
+ maxRate = KFrR_H263_Profile0_Level50;
+ } else if (lowerMimeType == "video/h263-2000; profile=3") {
+ maxRate = KFrR_H263_Profile3;
+ } else if (lowerMimeType == "video/mp4v-es") {
+ maxRate = KFrR_MPEG4;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=1") {
+ maxRate = KFrR_MPEG4_PLID_1;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=2") {
+ maxRate = KFrR_MPEG4_PLID_2;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=3") {
+ maxRate = KFrR_MPEG4_PLID_3;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=4") {
+ maxRate = KFrR_MPEG4_PLID_4;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=5") {
+ maxRate = KFrR_MPEG4_PLID_5;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=6") {
+ maxRate = KFrR_MPEG4_PLID_6;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=8") {
+ maxRate = KFrR_MPEG4_PLID_8;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=9") {
+ maxRate = KFrR_MPEG4_PLID_9;
+ } else if (lowerMimeType == "video/h264") {
+ maxRate = KFrR_H264;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42800a" ||
+ lowerMimeType == "video/h264; profile-level-id=4d400a" ||
+ lowerMimeType == "video/h264; profile-level-id=64400a") { // L1
+ maxRate = KFrR_H264_PLID_42800A;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42900b" ||
+ lowerMimeType == "video/h264; profile-level-id=4d500b" ||
+ lowerMimeType == "video/h264; profile-level-id=644009") { // L1.b
+ maxRate = KFrR_H264_PLID_42900B;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42800b" ||
+ lowerMimeType == "video/h264; profile-level-id=4d400b" ||
+ lowerMimeType == "video/h264; profile-level-id=64400b") { // L1.1
+ maxRate = KFrR_H264_PLID_42800B;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42800c" ||
+ lowerMimeType == "video/h264; profile-level-id=4d400c" ||
+ lowerMimeType == "video/h264; profile-level-id=64400c") { // L1.2
+ maxRate = KFrR_H264_PLID_42800C;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42800d" ||
+ lowerMimeType == "video/h264; profile-level-id=4d400d" ||
+ lowerMimeType == "video/h264; profile-level-id=64400d") { // L1.3
+ maxRate = KFrR_H264_PLID_42800D;
+ } else if (lowerMimeType == "video/h264; profile-level-id=428014" ||
+ lowerMimeType == "video/h264; profile-level-id=4d4014" ||
+ lowerMimeType == "video/h264; profile-level-id=644014") { // L2
+ maxRate = KFrR_H264_PLID_428014;
+ } else if (lowerMimeType == "video/h264; profile-level-id=428015" ||
+ lowerMimeType == "video/h264; profile-level-id=4d4015" ||
+ lowerMimeType == "video/h264; profile-level-id=644015") { // L2.1
+ maxRate = KFrR_H264_PLID_428015;
+ } else if (lowerMimeType == "video/h264; profile-level-id=428016" ||
+ lowerMimeType == "video/h264; profile-level-id=4d4016" ||
+ lowerMimeType == "video/h264; profile-level-id=644016") { // L2.2
+ maxRate = KFrR_H264_PLID_428016;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42801e" ||
+ lowerMimeType == "video/h264; profile-level-id=4d401e" ||
+ lowerMimeType == "video/h264; profile-level-id=64401e") { // L3
+ maxRate = KFrR_H264_PLID_42801E;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42801f" ||
+ lowerMimeType == "video/h264; profile-level-id=4d401f" ||
+ lowerMimeType == "video/h264; profile-level-id=64401f") { // L3.1
+ maxRate = KFrR_H264_PLID_42801F;
+ } else if (lowerMimeType == "video/h264; profile-level-id=428020" ||
+ lowerMimeType == "video/h264; profile-level-id=4d4020" ||
+ lowerMimeType == "video/h264; profile-level-id=644020") { // L3.2
+ maxRate = KFrR_H264_PLID_428020;
+ } else if (lowerMimeType == "video/h264; profile-level-id=428028" ||
+ lowerMimeType == "video/h264; profile-level-id=4d4028" ||
+ lowerMimeType == "video/h264; profile-level-id=644028") { // L4
+ maxRate = KFrR_H264_PLID_428028;
+ }
+
+ return maxRate;
+}
+
+/*
+ * This function returns the maximum bitrate defined by the video standards
+ * for different MIME Types.
+ */
+int S60VideoCaptureSession::maximumBitRateForMimeType(const QString &mimeType) const
+{
+ int maxRate(-1.0);
+ // Use all lower case for comparisons
+ QString lowerMimeType = mimeType.toLower();
+
+ if (lowerMimeType == "video/h263-2000") {
+ maxRate = KBiR_H263;
+ } else if (lowerMimeType == "video/h263-2000; profile=0") {
+ maxRate = KBiR_H263_Profile0;
+ } else if (lowerMimeType == "video/h263-2000; profile=0; level=10") {
+ maxRate = KBiR_H263_Profile0_Level10;
+ } else if (lowerMimeType == "video/h263-2000; profile=0; level=20") {
+ maxRate = KBiR_H263_Profile0_Level20;
+ } else if (lowerMimeType == "video/h263-2000; profile=0; level=30") {
+ maxRate = KBiR_H263_Profile0_Level30;
+ } else if (lowerMimeType == "video/h263-2000; profile=0; level=40") {
+ maxRate = KBiR_H263_Profile0_Level40;
+ } else if (lowerMimeType == "video/h263-2000; profile=0; level=45") {
+ maxRate = KBiR_H263_Profile0_Level45;
+ } else if (lowerMimeType == "video/h263-2000; profile=0; level=50") {
+ maxRate = KBiR_H263_Profile0_Level50;
+ } else if (lowerMimeType == "video/h263-2000; profile=3") {
+ maxRate = KBiR_H263_Profile3;
+ } else if (lowerMimeType == "video/mp4v-es") {
+ maxRate = KBiR_MPEG4;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=1") {
+ maxRate = KBiR_MPEG4_PLID_1;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=2") {
+ maxRate = KBiR_MPEG4_PLID_2;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=3") {
+ maxRate = KBiR_MPEG4_PLID_3;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=4") {
+ maxRate = KBiR_MPEG4_PLID_4;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=5") {
+ maxRate = KBiR_MPEG4_PLID_5;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=6") {
+ maxRate = KBiR_MPEG4_PLID_6;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=8") {
+ maxRate = KBiR_MPEG4_PLID_8;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=9") {
+ maxRate = KBiR_MPEG4_PLID_9;
+ } else if (lowerMimeType == "video/h264") {
+ maxRate = KBiR_H264;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42800a" ||
+ lowerMimeType == "video/h264; profile-level-id=4d400a" ||
+ lowerMimeType == "video/h264; profile-level-id=64400a") { // L1
+ maxRate = KBiR_H264_PLID_42800A;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42900b" ||
+ lowerMimeType == "video/h264; profile-level-id=4d500b" ||
+ lowerMimeType == "video/h264; profile-level-id=644009") { // L1.b
+ maxRate = KBiR_H264_PLID_42900B;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42800b" ||
+ lowerMimeType == "video/h264; profile-level-id=4d400b" ||
+ lowerMimeType == "video/h264; profile-level-id=64400b") { // L1.1
+ maxRate = KBiR_H264_PLID_42800B;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42800c" ||
+ lowerMimeType == "video/h264; profile-level-id=4d400c" ||
+ lowerMimeType == "video/h264; profile-level-id=64400c") { // L1.2
+ maxRate = KBiR_H264_PLID_42800C;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42800d" ||
+ lowerMimeType == "video/h264; profile-level-id=4d400d" ||
+ lowerMimeType == "video/h264; profile-level-id=64400d") { // L1.3
+ maxRate = KBiR_H264_PLID_42800D;
+ } else if (lowerMimeType == "video/h264; profile-level-id=428014" ||
+ lowerMimeType == "video/h264; profile-level-id=4d4014" ||
+ lowerMimeType == "video/h264; profile-level-id=644014") { // L2
+ maxRate = KBiR_H264_PLID_428014;
+ } else if (lowerMimeType == "video/h264; profile-level-id=428015" ||
+ lowerMimeType == "video/h264; profile-level-id=4d4015" ||
+ lowerMimeType == "video/h264; profile-level-id=644015") { // L2.1
+ maxRate = KBiR_H264_PLID_428015;
+ } else if (lowerMimeType == "video/h264; profile-level-id=428016" ||
+ lowerMimeType == "video/h264; profile-level-id=4d4016" ||
+ lowerMimeType == "video/h264; profile-level-id=644016") { // L2.2
+ maxRate = KBiR_H264_PLID_428016;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42801e" ||
+ lowerMimeType == "video/h264; profile-level-id=4d401e" ||
+ lowerMimeType == "video/h264; profile-level-id=64401e") { // L3
+ maxRate = KBiR_H264_PLID_42801E;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42801f" ||
+ lowerMimeType == "video/h264; profile-level-id=4d401f" ||
+ lowerMimeType == "video/h264; profile-level-id=64401f") { // L3.1
+ maxRate = KBiR_H264_PLID_42801F;
+ } else if (lowerMimeType == "video/h264; profile-level-id=428020" ||
+ lowerMimeType == "video/h264; profile-level-id=4d4020" ||
+ lowerMimeType == "video/h264; profile-level-id=644020") { // L3.2
+ maxRate = KBiR_H264_PLID_428020;
+ } else if (lowerMimeType == "video/h264; profile-level-id=428028" ||
+ lowerMimeType == "video/h264; profile-level-id=4d4028" ||
+ lowerMimeType == "video/h264; profile-level-id=644028") { // L4
+ maxRate = KBiR_H264_PLID_428028;
+ }
+
+ return maxRate;
+}
+
+// End of file
diff --git a/src/plugins/symbian/ecam/s60videocapturesession.h b/src/plugins/symbian/ecam/s60videocapturesession.h
new file mode 100644
index 000000000..cfa101f57
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60videocapturesession.h
@@ -0,0 +1,414 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef S60VIDEOCAPTURESESSION_H
+#define S60VIDEOCAPTURESESSION_H
+
+#include <QtCore/qurl.h>
+#include <QtCore/qhash.h>
+
+#include <qmediaencodersettings.h>
+#include <qcamera.h>
+#include <qmediarecorder.h>
+
+#include "s60cameraengine.h"
+
+#include <e32base.h>
+#include <videorecorder.h> // CVideoRecorderUtility
+#ifdef S60_DEVVIDEO_RECORDING_SUPPORTED
+#include <mmf/devvideo/devvideorecord.h>
+#endif // S60_DEVVIDEO_RECORDING_SUPPORTED
+
+QT_USE_NAMESPACE
+
+class QTimer;
+
+/*
+ * VideoSession is the main class handling all video recording related
+ * operations. It uses mainly CVideoRecorderUtility to do it's tasks, but if
+ * DevVideoRecord is available it is used to provide more detailed
+ * information of the supported video settings.
+ */
+class S60VideoCaptureSession : public QObject,
+ public MVideoRecorderUtilityObserver
+#ifdef S60_DEVVIDEO_RECORDING_SUPPORTED
+ ,public MMMFDevVideoRecordObserver
+#endif // S60_DEVVIDEO_RECORDING_SUPPORTED
+{
+ Q_OBJECT
+ Q_ENUMS(Error)
+ Q_ENUMS(EcamErrors)
+ Q_ENUMS(TVideoCaptureState)
+
+public: // Enums
+
+ enum TVideoCaptureState
+ {
+ ENotInitialized = 0, // 0 - VideoRecording is not initialized, instance may or may not be created
+ EInitializing, // 1 - Initialization is ongoing
+ EInitialized, // 2 - VideoRecording is initialized, OpenFile is called with dummy file
+ EOpening, // 3 - OpenFile called with actual output location, waiting completion
+ EOpenComplete, // 4 - OpenFile completed with the actual output location
+ EPreparing, // 5 - Preparing VideoRecording to use set video settings
+ EPrepared, // 6 - VideoRecording is prepared with the set settings, ready to record
+ ERecording, // 7 - Video recording is ongoing
+ EPaused // 8 - Video recording has been started and paused
+ };
+
+ enum AudioQualityDefinition
+ {
+ ENoAudioQuality = 0, // 0 - Both BitRate and SampleRate settings available
+ EOnlyAudioQuality, // 1 - No BitRate or SampleRate settings available, use Quality to set them
+ EAudioQualityAndBitRate, // 2 - BitRate setting available, use Quality to set SampleRate
+ EAudioQualityAndSampleRate, // 3 - SampleRate setting available, use Quality to set BitRate
+ };
+
+ enum VideoQualityDefinition
+ {
+ ENoVideoQuality = 0, // 0 - All, Resolution, FrameRate and BitRate available
+ EOnlyVideoQuality, // 1 - None available, use Quality to set Resolution, FrameRate and BitRate
+ EVideoQualityAndResolution, // 2 - Only Resolution available, use Quality to set FrameRate and BitRate
+ EVideoQualityAndFrameRate, // 3 - Only FrameRate available, use Quality to set Resolution and BitRate
+ EVideoQualityAndBitRate, // 4 - Only BitRate available, use Quality to set Resolution and FrameRate
+ EVideoQualityAndResolutionAndBitRate, // 5 - No FrameRate available, use Quality to set it
+ EVideoQualityAndResolutionAndFrameRate, // 6 - No BitRate available, use Quality to set it
+ EVideoQualityAndFrameRateAndBitRate // 7 - No Resolution available, use Quality to set it
+ };
+
+public: // Constructor & Destructor
+
+ S60VideoCaptureSession(QObject *parent = 0);
+ ~S60VideoCaptureSession();
+
+public: // MVideoRecorderUtilityObserver
+
+ void MvruoOpenComplete(TInt aError);
+ void MvruoPrepareComplete(TInt aError);
+ void MvruoRecordComplete(TInt aError);
+ void MvruoEvent(const TMMFEvent& aEvent);
+
+#ifdef S60_DEVVIDEO_RECORDING_SUPPORTED
+public: // MMMFDevVideoRecordObserver
+ void MdvroReturnPicture(TVideoPicture *aPicture);
+ void MdvroSupplementalInfoSent();
+ void MdvroNewBuffers();
+ void MdvroFatalError(TInt aError);
+ void MdvroInitializeComplete(TInt aError);
+ void MdvroStreamEnd();
+#endif // S60_DEVVIDEO_RECORDING_SUPPORTED
+
+public: // Methods
+
+ void setError(const TInt error, const QString &description);
+ void setCameraHandle(CCameraEngine* cameraHandle);
+ void notifySettingsSet();
+
+ qint64 position();
+ TVideoCaptureState state() const;
+ bool isMuted() const;
+
+ // Controls
+ int initializeVideoRecording();
+ void releaseVideoRecording();
+ void applyAllSettings();
+
+ void startRecording();
+ void pauseRecording();
+ void stopRecording(const bool reInitialize = true);
+ void setMuted(const bool muted);
+
+ // Output Location
+ bool setOutputLocation(const QUrl &sink);
+ QUrl outputLocation() const;
+
+ // Resolution
+ void setVideoResolution(const QSize &resolution);
+ QList<QSize> supportedVideoResolutions(bool *continuous);
+ QList<QSize> supportedVideoResolutions(const QVideoEncoderSettings &settings, bool *continuous);
+
+ // Framerate
+ void setFrameRate(const qreal rate);
+ QList<qreal> supportedVideoFrameRates(bool *continuous);
+ QList<qreal> supportedVideoFrameRates(const QVideoEncoderSettings &settings, bool *continuous);
+
+ // Other Video Settings
+ void setBitrate(const int bitrate);
+ void setVideoEncodingMode(const QtMultimediaKit::EncodingMode mode);
+
+ // Video Codecs
+ void setVideoCaptureCodec(const QString &codecName);
+ QStringList supportedVideoCaptureCodecs();
+ QString videoCaptureCodecDescription(const QString &codecName);
+
+ // Audio Codecs
+ void setAudioCaptureCodec(const QString &codecName);
+ QStringList supportedAudioCaptureCodecs();
+
+ // Encoder Settings
+ void videoEncoderSettings(QVideoEncoderSettings &videoSettings);
+ void audioEncoderSettings(QAudioEncoderSettings &audioSettings);
+
+ // Quality
+ void setVideoCaptureQuality(const QtMultimediaKit::EncodingQuality quality,
+ const VideoQualityDefinition mode);
+ void setAudioCaptureQuality(const QtMultimediaKit::EncodingQuality quality,
+ const AudioQualityDefinition mode);
+
+ // Video Containers
+ QString videoContainer() const;
+ void setVideoContainer(const QString &containerName);
+ QStringList supportedVideoContainers();
+ bool isSupportedVideoContainer(const QString &containerName);
+ QString videoContainerDescription(const QString &containerName);
+
+ // Audio Settings
+ QList<int> supportedSampleRates(const QAudioEncoderSettings &settings, bool *continuous);
+ void setAudioSampleRate(const int sampleRate);
+ void setAudioBitRate(const int bitRate);
+ void setAudioChannelCount(const int channelCount);
+ void setAudioEncodingMode(const QtMultimediaKit::EncodingMode mode);
+
+ // Video Options
+ QSize pixelAspectRatio();
+ void setPixelAspectRatio(const QSize par);
+ int gain();
+ void setGain(const int gain);
+ int maxClipSizeInBytes() const;
+ void setMaxClipSizeInBytes(const int size);
+
+private: // Internal
+
+ QMediaRecorder::Error fromSymbianErrorToQtMultimediaError(int aError);
+
+ void initializeVideoCaptureSettings();
+ void doInitializeVideoRecorderL();
+ void commitVideoEncoderSettings();
+ void queryAudioEncoderSettings();
+ void queryVideoEncoderSettings();
+ void validateRequestedCodecs();
+ void resetSession(bool errorHandling = false);
+
+ void doSetCodecsL();
+ QString determineProfileAndLevel();
+ void doSetVideoResolution(const QSize &resolution);
+ void doSetFrameRate(qreal rate);
+ void doSetBitrate(const int &bitrate);
+
+ void updateVideoCaptureContainers();
+ void doUpdateVideoCaptureContainersL();
+ void selectController(const QString &format,
+ TUid &controllerUid,
+ TUid &formatUid);
+
+ void doPopulateVideoCodecsDataL();
+ void doPopulateVideoCodecsL();
+#ifndef S60_DEVVIDEO_RECORDING_SUPPORTED
+ void doPopulateMaxVideoParameters();
+#endif // S60_DEVVIDEO_RECORDING_SUPPORTED
+ void doPopulateAudioCodecsL();
+
+ QList<int> doGetSupportedSampleRatesL(const QAudioEncoderSettings &settings,
+ bool *continuous);
+ QSize maximumResolutionForMimeType(const QString &mimeType) const;
+ qreal maximumFrameRateForMimeType(const QString &mimeType) const;
+ int maximumBitRateForMimeType(const QString &mimeType) const;
+
+signals: // Notification Signals
+
+ void stateChanged(S60VideoCaptureSession::TVideoCaptureState);
+ void positionChanged(qint64);
+ void mutedChanged(bool);
+ void captureSizeChanged(const QSize&);
+ void error(int, const QString&);
+
+private slots: // Internal Slots
+
+ void cameraStatusChanged(QCamera::Status);
+ void durationTimerTriggered();
+
+private: // Structs
+
+ /*
+ * This structure holds the information of supported video mime types for
+ * the format and also description for it.
+ */
+ struct VideoFormatData {
+ QString description;
+ QStringList supportedMimeTypes;
+ };
+
+ /*
+ * This structure is used to define supported resolutions and framerate
+ * (depending on each other) for each supported encoder mime type (defining
+ * encoder, profile and level)
+ */
+ struct SupportedFrameRatePictureSize {
+ SupportedFrameRatePictureSize() {}
+ SupportedFrameRatePictureSize(qreal rate, QSize size):
+ frameRate(rate),
+ frameSize(size) {}
+ qreal frameRate;
+ QSize frameSize;
+ };
+
+ /*
+ * This structure defines supported resolution/framerate pairs and maximum
+ * bitrate for a single encodec device. It also the supported mime types
+ * (codec, profile and level) of the encoder device.
+ *
+ * Structure defines 2 contructors:
+ * - First with no attributes
+ * - Second, which will construct the sructure appending one
+ * resolution/framerate pair to the list of
+ * SupportedFrameRatePictureSizes and setting the given bitrate as
+ * maximum. This second constructor is for convenience.
+ *
+ * This struct is used in m_videoParametersForEncoder (QList).
+ *
+ * Here's a visualization of an example strcuture:
+ * STRUCT:
+ * |-- Resolution/FrameRate Pairs:
+ * | |- VGA / 30fps
+ * | |- 720p / 25fps
+ * | |- Etc.
+ * |
+ * |-- MimeTypes:
+ * | |- video/mp4v-es; profile-level-id=1
+ * | |- video/mp4v-es; profile-level-id=2
+ * | |- Etc.
+ * |
+ * |-- Max BitRate: 1Mbps
+ */
+ struct MaxResolutionRatesAndTypes {
+ MaxResolutionRatesAndTypes() {}
+ MaxResolutionRatesAndTypes(QSize size, qreal fRate, int bRate):
+ bitRate(bRate)
+ {
+ frameRatePictureSizePair.append(SupportedFrameRatePictureSize(fRate,size));
+ }
+ QList<SupportedFrameRatePictureSize> frameRatePictureSizePair;
+ QStringList mimeTypes;
+ int bitRate;
+ };
+
+private: // Data
+
+ CCameraEngine *m_cameraEngine;
+ CVideoRecorderUtility *m_videoRecorder;
+ QTimer *m_durationTimer;
+ qint64 m_position;
+ // Symbian ErrorCode
+ mutable int m_error;
+ // This defines whether Camera is in ActiveStatus or not
+ bool m_cameraStarted;
+ // Internal state of the video recorder
+ TVideoCaptureState m_captureState;
+ // Actual output file name/path
+ QUrl m_sink;
+ // Requested output file name/path, this may be different from m_sink if
+ // asynchronous operation was ongoing in the CVideoRecorderUtility when new
+ // outputLocation was set.
+ QUrl m_requestedSink;
+ // Requested videoSettings. The may not be active settings before those are
+ // committed (with commitVideoEncoderSettings())
+ QVideoEncoderSettings m_videoSettings;
+ // Requested audioSettings. The may not be active settings before those are
+ // committed (with commitVideoEncoderSettings())
+ QAudioEncoderSettings m_audioSettings;
+ // Tells whether settings should be initialized when changing the camera
+ bool m_captureSettingsSet;
+ // Active container
+ QString m_container;
+ // Requested container, this may be different from m_container if
+ // asynchronous operation was ongoing in the CVideoRecorderUtility when new
+ // container was set.
+ QString m_requestedContainer;
+ // Requested muted value. This may not be active value before settings are
+ // committed (with commitVideoEncoderSettings())
+ bool m_muted;
+ // Maximum ClipSize in Bytes
+ int m_maxClipSize;
+ // List of supported video codec mime types
+ QStringList m_videoCodecList;
+ // Hash of supported video codec mime types and corresponding FourCC codes
+ QHash<QString, TFourCC> m_audioCodecList;
+ // Map of video capture controllers information. It is populated during
+ // doUpdateVideoCaptureContainersL().
+ //
+ // Here's a visualization of an example strcuture:
+ // m_videoControllerMap(HASH):
+ // |
+ // |-- Controller 1 : HASH
+ // | |- Container 1 (UID) : FormatData
+ // | | |- Description
+ // | | |- List of supported MimeTypes
+ // | |- Container 2 (UID) : FormatData
+ // | | |- Description
+ // | | |- List of supported MimeTypes
+ // | |- Etc.
+ // |
+ // |-- Controller 2: HASH
+ // | |- Container 1 (UID) : FormatData
+ // | | |- Description
+ // | | |- List of supported MimeTypes
+ // | |- Etc.
+ //
+ QHash<TInt, QHash<TInt,VideoFormatData> > m_videoControllerMap;
+ // List of Encoder information. If DevVideoRecord is available info is
+ // gathered during doPopulateVideoCodecsDataL() for each encoder (hw
+ // accelerated and supporting camera input) found. If DevVideoRecord is not
+ // available, the info is set in doPopulateMaxVideoParameters() based on
+ // supported codec list received from CVideoRecorderUtility.
+ QList<MaxResolutionRatesAndTypes> m_videoParametersForEncoder;
+ // Set if OpenFileL should be executed when currently ongoing operation
+ // is completed.
+ bool m_openWhenReady;
+ // Set if video capture should be prepared after OpenFileL has completed
+ bool m_prepareAfterOpenComplete;
+ // Set if video capture should be started when Prepare has completed
+ bool m_startAfterPrepareComplete;
+ // Tells if settings have been set after last Prepare()
+ bool m_uncommittedSettings;
+ // Tells if settings need to be applied after ongoing operation has finished
+ bool m_commitSettingsWhenReady;
+};
+
+#endif // S60VIDEOCAPTURESESSION_H
diff --git a/src/plugins/symbian/ecam/s60videodevicecontrol.cpp b/src/plugins/symbian/ecam/s60videodevicecontrol.cpp
new file mode 100644
index 000000000..3d55d3110
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60videodevicecontrol.cpp
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qstring.h>
+#include <QtGui/qicon.h>
+
+#include "s60videodevicecontrol.h"
+#include "s60cameracontrol.h"
+#include "s60cameraconstants.h"
+
+S60VideoDeviceControl::S60VideoDeviceControl(QObject *parent) :
+ QVideoDeviceControl(parent)
+{
+}
+
+S60VideoDeviceControl::S60VideoDeviceControl(S60CameraControl *control, QObject *parent) :
+ QVideoDeviceControl(parent),
+ m_selectedDevice(KDefaultCameraDevice)
+{
+ m_control = control;
+ connect(m_control, SIGNAL(devicesChanged()), this, SIGNAL(devicesChanged()));
+}
+
+S60VideoDeviceControl::~S60VideoDeviceControl()
+{
+}
+
+int S60VideoDeviceControl::deviceCount() const
+{
+ return S60CameraControl::deviceCount();
+}
+
+QString S60VideoDeviceControl::deviceName(int index) const
+{
+ return S60CameraControl::name(index);
+}
+
+QString S60VideoDeviceControl::deviceDescription(int index) const
+{
+ return S60CameraControl::description(index);
+}
+
+QIcon S60VideoDeviceControl::deviceIcon(int index) const
+{
+ Q_UNUSED(index);
+ return QIcon();
+}
+
+int S60VideoDeviceControl::defaultDevice() const
+{
+ return KDefaultCameraDevice;
+}
+
+int S60VideoDeviceControl::selectedDevice() const
+{
+ return m_selectedDevice;
+}
+
+void S60VideoDeviceControl::setSelectedDevice(int index)
+{
+ // Inform that we selected new device
+ if (m_selectedDevice != index) {
+ m_control->setSelectedDevice(index);
+ m_selectedDevice = index;
+ emit selectedDeviceChanged(m_selectedDevice);
+ emit selectedDeviceChanged(deviceName(m_selectedDevice));
+ }
+}
+
+// End of file
diff --git a/src/plugins/symbian/ecam/s60videodevicecontrol.h b/src/plugins/symbian/ecam/s60videodevicecontrol.h
new file mode 100644
index 000000000..03249441a
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60videodevicecontrol.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef S60VIDEODEVICECONTROL_H
+#define S60VIDEODEVICECONTROL_H
+
+#include "qvideodevicecontrol.h"
+
+QT_USE_NAMESPACE
+
+class S60CameraControl;
+class QString;
+class QIcon;
+
+/*
+ * Control for providing information of the video device (r. camera) and to
+ * enable other camera device (e.g. secondary camera if one exists).
+ */
+class S60VideoDeviceControl : public QVideoDeviceControl
+{
+ Q_OBJECT
+
+public: // Constructors & Destructor
+
+ S60VideoDeviceControl(QObject *parent);
+ S60VideoDeviceControl(S60CameraControl *control, QObject *parent = 0);
+ virtual ~S60VideoDeviceControl();
+
+public: // QVideoDeviceControl
+
+ int deviceCount() const;
+
+ QString deviceName(int index) const;
+ QString deviceDescription(int index) const;
+ QIcon deviceIcon(int index) const;
+
+ int defaultDevice() const;
+ int selectedDevice() const;
+
+public slots: // QVideoDeviceControl
+
+ void setSelectedDevice(int index);
+
+/*
+Q_SIGNALS:
+void selectedDeviceChanged(int index);
+void selectedDeviceChanged(const QString &deviceName);
+void devicesChanged();
+*/
+
+private: // Data
+
+ S60CameraControl *m_control;
+ int m_selectedDevice;
+};
+
+#endif // S60VIDEODEVICECONTROL_H
diff --git a/src/plugins/symbian/ecam/s60videoencodercontrol.cpp b/src/plugins/symbian/ecam/s60videoencodercontrol.cpp
new file mode 100644
index 000000000..34b28e28e
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60videoencodercontrol.cpp
@@ -0,0 +1,204 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "s60videoencodercontrol.h"
+#include "s60videocapturesession.h"
+
+S60VideoEncoderControl::S60VideoEncoderControl(QObject *parent) :
+ QVideoEncoderControl(parent)
+{
+}
+
+S60VideoEncoderControl::S60VideoEncoderControl(S60VideoCaptureSession *session, QObject *parent) :
+ QVideoEncoderControl(parent)
+{
+ m_session = session;
+}
+
+S60VideoEncoderControl::~S60VideoEncoderControl()
+{
+}
+
+QStringList S60VideoEncoderControl::supportedVideoCodecs() const
+{
+ return m_session->supportedVideoCaptureCodecs();
+}
+
+QString S60VideoEncoderControl::videoCodecDescription(const QString &codecName) const
+{
+ return m_session->videoCaptureCodecDescription(codecName);
+}
+
+QList<qreal> S60VideoEncoderControl::supportedFrameRates(const QVideoEncoderSettings &settings, bool *continuous) const
+{
+ if (!settings.isNull())
+ return m_session->supportedVideoFrameRates(settings, continuous);
+ return m_session->supportedVideoFrameRates(continuous);
+}
+
+QList<QSize> S60VideoEncoderControl::supportedResolutions(const QVideoEncoderSettings &settings, bool *continuous) const
+{
+ if (!settings.isNull())
+ return m_session->supportedVideoResolutions(settings, continuous);
+ return m_session->supportedVideoResolutions(continuous);
+}
+
+QStringList S60VideoEncoderControl::supportedEncodingOptions(const QString &codec) const
+{
+ // Possible settings: EncodingMode, Codec, Resolution, FrameRate, BitRate, Quality
+ // Possible (codec specific) options: PixelAspectRatio, Gain, MaxClipSizeInBytes
+
+ // Following options are valid for all codecs
+ Q_UNUSED(codec);
+
+ QStringList options;
+ options.append("pixelAspectRatio");
+ options.append("gain");
+ options.append("maxClipSizeInBytes");
+
+ return options;
+}
+
+QVariant S60VideoEncoderControl::encodingOption(const QString &codec, const QString &name) const
+{
+ Q_UNUSED(codec);
+
+ // Possible settings: EncodingMode, Codec, Resolution, FrameRate, BitRate, Quality
+ // Possible (codec specific) options: PixelAspectRatio, Gain, MaxClipSizeInBytes
+
+ QVariant returnValue;
+
+ if (qstrcmp(name.toLocal8Bit().constData(), "pixelAspectRatio") == 0)
+ returnValue.setValue(m_session->pixelAspectRatio());
+ else if (qstrcmp(name.toLocal8Bit().constData(), "gain") == 0)
+ returnValue.setValue((int)m_session->gain());
+ else if (qstrcmp(name.toLocal8Bit().constData(), "maxClipSizeInBytes") == 0)
+ returnValue.setValue(m_session->maxClipSizeInBytes());
+
+ return returnValue;
+}
+
+void S60VideoEncoderControl::setEncodingOption(
+ const QString &codec, const QString &name, const QVariant &value)
+{
+ // Set the codec first if not already set
+ m_session->setVideoCaptureCodec(codec);
+
+ if (qstrcmp(name.toLocal8Bit().constData(), "pixelAspectRatio") == 0)
+ m_session->setPixelAspectRatio(value.toSize());
+ else if (qstrcmp(name.toLocal8Bit().constData(), "gain") == 0)
+ m_session->setGain(value.toInt());
+ else if (qstrcmp(name.toLocal8Bit().constData(), "maxClipSizeInBytes") == 0)
+ m_session->setMaxClipSizeInBytes(value.toInt());
+ else
+ m_session->setError(KErrNotSupported, tr("Requested encoding option is not supported"));
+}
+
+QVideoEncoderSettings S60VideoEncoderControl::videoSettings() const
+{
+ QVideoEncoderSettings settings;
+ m_session->videoEncoderSettings(settings);
+
+ return settings;
+}
+
+void S60VideoEncoderControl::setVideoSettings(const QVideoEncoderSettings &settings)
+{
+ // Notify that settings have been implicitly set and there's no need to
+ // initialize them in case camera is changed
+ m_session->notifySettingsSet();
+
+ if (settings.codec().isEmpty()
+ || (settings.resolution() == QSize(-1,-1) && settings.frameRate() == 0 && settings.bitRate() == -1)) {
+ if (!settings.codec().isEmpty())
+ m_session->setVideoCaptureCodec(settings.codec());
+ m_session->setVideoEncodingMode(settings.encodingMode());
+ m_session->setVideoCaptureQuality(settings.quality(), S60VideoCaptureSession::EOnlyVideoQuality);
+ } else if (settings.resolution() != QSize(-1,-1) && settings.frameRate() == 0 && settings.bitRate() == -1) { // Only Resolution
+ m_session->setVideoCaptureCodec(settings.codec());
+ m_session->setVideoEncodingMode(settings.encodingMode());
+ m_session->setVideoResolution(settings.resolution());
+ m_session->setVideoCaptureQuality(settings.quality(), S60VideoCaptureSession::EVideoQualityAndResolution);
+
+ } else if (settings.resolution() == QSize(-1,-1) && settings.frameRate() != 0 && settings.bitRate() == -1) { // Only Framerate
+ m_session->setVideoCaptureCodec(settings.codec());
+ m_session->setVideoEncodingMode(settings.encodingMode());
+ m_session->setFrameRate(settings.frameRate());
+ m_session->setVideoCaptureQuality(settings.quality(), S60VideoCaptureSession::EVideoQualityAndFrameRate);
+
+ } else if (settings.resolution() == QSize(-1,-1) && settings.frameRate() == 0 && settings.bitRate() != -1) { // Only BitRate
+ m_session->setVideoCaptureCodec(settings.codec());
+ m_session->setVideoEncodingMode(settings.encodingMode());
+ m_session->setBitrate(settings.bitRate());
+ m_session->setVideoCaptureQuality(settings.quality(), S60VideoCaptureSession::EVideoQualityAndBitRate);
+
+ } else if (settings.resolution() != QSize(-1,-1) && settings.frameRate() != 0 && settings.bitRate() == -1) { // Resolution and FrameRate
+ m_session->setVideoCaptureCodec(settings.codec());
+ m_session->setVideoEncodingMode(settings.encodingMode());
+ m_session->setVideoResolution(settings.resolution());
+ m_session->setFrameRate(settings.frameRate());
+ m_session->setVideoCaptureQuality(settings.quality(), S60VideoCaptureSession::EVideoQualityAndResolutionAndFrameRate);
+
+ } else if (settings.resolution() != QSize(-1,-1) && settings.frameRate() == 0 && settings.bitRate() != -1) { // Resolution and BitRate
+ m_session->setVideoCaptureCodec(settings.codec());
+ m_session->setVideoEncodingMode(settings.encodingMode());
+ m_session->setVideoResolution(settings.resolution());
+ m_session->setBitrate(settings.bitRate());
+ m_session->setVideoCaptureQuality(settings.quality(), S60VideoCaptureSession::EVideoQualityAndResolutionAndBitRate);
+
+ } else if (settings.resolution() == QSize(-1,-1) && settings.frameRate() != 0 && settings.bitRate() != -1) { // FrameRate and BitRate
+ m_session->setVideoCaptureCodec(settings.codec());
+ m_session->setVideoEncodingMode(settings.encodingMode());
+ m_session->setFrameRate(settings.frameRate());
+ m_session->setBitrate(settings.bitRate());
+ m_session->setVideoCaptureQuality(settings.quality(), S60VideoCaptureSession::EVideoQualityAndFrameRateAndBitRate);
+
+ } else { // All: Resolution, BitRate and FrameRate
+ m_session->setVideoCaptureCodec(settings.codec());
+ m_session->setVideoEncodingMode(settings.encodingMode());
+ m_session->setVideoResolution(settings.resolution());
+ m_session->setFrameRate(settings.frameRate());
+ m_session->setBitrate(settings.bitRate());
+ m_session->setVideoCaptureQuality(settings.quality(), S60VideoCaptureSession::ENoVideoQuality);
+ }
+}
+
+// End of file
diff --git a/src/plugins/symbian/ecam/s60videoencodercontrol.h b/src/plugins/symbian/ecam/s60videoencodercontrol.h
new file mode 100644
index 000000000..4554d9291
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60videoencodercontrol.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef S60VIDEOENCODERCONTROL_H
+#define S60VIDEOENCODERCONTROL_H
+
+#include <QtCore/qstringlist.h>
+#include <QtCore/qmap.h>
+
+#include "qvideoencodercontrol.h"
+
+QT_USE_NAMESPACE
+
+class S60VideoCaptureSession;
+
+/*
+ * Control for video settings when recording video using QMediaRecorder.
+ */
+class S60VideoEncoderControl : public QVideoEncoderControl
+{
+ Q_OBJECT
+
+public: // Contructors & Destructor
+
+ S60VideoEncoderControl(QObject *parent = 0);
+ S60VideoEncoderControl(S60VideoCaptureSession *session, QObject *parent = 0);
+ virtual ~S60VideoEncoderControl();
+
+public: // QVideoEncoderControl
+
+ // Resolution
+ QList<QSize> supportedResolutions(const QVideoEncoderSettings &settings, bool *continuous = 0) const;
+
+ // Framerate
+ QList<qreal> supportedFrameRates(const QVideoEncoderSettings &settings, bool *continuous = 0) const;
+
+ // Video Codec
+ QStringList supportedVideoCodecs() const;
+ QString videoCodecDescription(const QString &codecName) const;
+
+ // Video Settings
+ QVideoEncoderSettings videoSettings() const;
+ void setVideoSettings(const QVideoEncoderSettings &settings);
+
+ // Encoding Options
+ QStringList supportedEncodingOptions(const QString &codec) const;
+ QVariant encodingOption(const QString &codec, const QString &name) const;
+ void setEncodingOption(const QString &codec, const QString &name, const QVariant &value);
+
+private: // Data
+
+ S60VideoCaptureSession* m_session;
+
+};
+
+#endif // S60VIDEOENCODERCONTROL_H
diff --git a/src/plugins/symbian/ecam/s60videorenderercontrol.cpp b/src/plugins/symbian/ecam/s60videorenderercontrol.cpp
new file mode 100644
index 000000000..8cc3546b5
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60videorenderercontrol.cpp
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qabstractvideosurface.h>
+
+#include "s60videorenderercontrol.h"
+
+S60VideoRendererControl::S60VideoRendererControl(QObject *parent) :
+ QVideoRendererControl(parent),
+ m_surface(0)
+{
+}
+
+S60VideoRendererControl::~S60VideoRendererControl()
+{
+ // Stop surface if still active
+ if (m_surface)
+ if (m_surface->isActive())
+ m_surface->stop();
+}
+
+QAbstractVideoSurface *S60VideoRendererControl::surface() const
+{
+ return m_surface;
+}
+
+void S60VideoRendererControl::setSurface(QAbstractVideoSurface *surface)
+{
+ if (surface == 0) {
+ // Stop current surface if needed
+ if (m_surface)
+ if (m_surface->isActive())
+ m_surface->stop();
+ }
+
+ m_surface = surface;
+ emit viewFinderSurfaceSet();
+}
+
+// End of file
diff --git a/src/plugins/symbian/ecam/s60videorenderercontrol.h b/src/plugins/symbian/ecam/s60videorenderercontrol.h
new file mode 100644
index 000000000..b35433f86
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60videorenderercontrol.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef S60VIDEORENDERERCONTROL_H
+#define S60VIDEORENDERERCONTROL_H
+
+#include <qvideorenderercontrol.h>
+
+/*
+ * Control for QGraphicsVideoItem. Viewfinder frames are streamed to a surface
+ * which is drawn to the display by the Qt Graphics Vide Framework.
+ * VideoRendererControl uses only Bitmap Viewfinder.
+ */
+class S60VideoRendererControl : public QVideoRendererControl
+{
+ Q_OBJECT
+
+public: // Constructor & Destructor
+
+ S60VideoRendererControl(QObject *parent = 0);
+ virtual ~S60VideoRendererControl();
+
+public: // S60VideoRendererControl
+
+ QAbstractVideoSurface *surface() const;
+ void setSurface(QAbstractVideoSurface *surface);
+
+signals: // Internal Signals
+
+ void viewFinderSurfaceSet();
+
+private: // Data
+
+ QAbstractVideoSurface *m_surface;
+
+};
+
+#endif // S60VIDEORENDERERCONTROL_H