summaryrefslogtreecommitdiffstats
path: root/src/plugins/android/src
diff options
context:
space:
mode:
authorYoann Lopes <yoann.lopes@digia.com>2013-03-25 18:11:27 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-12 12:56:57 +0200
commit0a7882f6b308296ff9d44d891d3bdfed91679ce2 (patch)
tree8a1e1575158d8213773fcf4e692a160bf4b301cd /src/plugins/android/src
parent99fff6941ba6b1929c1bd8d46dc8776a6cbf11c6 (diff)
Android: added camera support.
This patch includes all camera features: viewport, settings, image capture, and video recording. It also adds support for QAudioRecorder. Change-Id: Ib962177cc8de4bac03f42a2bc0f534e03464bbfc Reviewed-by: Christian Stromme <christian.stromme@digia.com>
Diffstat (limited to 'src/plugins/android/src')
-rw-r--r--src/plugins/android/src/android_mediaservice.json3
-rw-r--r--src/plugins/android/src/common/common.pri10
-rw-r--r--src/plugins/android/src/common/qandroidmultimediautils.cpp79
-rw-r--r--src/plugins/android/src/common/qandroidmultimediautils.h58
-rw-r--r--src/plugins/android/src/common/qandroidvideooutput.h73
-rw-r--r--src/plugins/android/src/common/qandroidvideorendercontrol.cpp438
-rw-r--r--src/plugins/android/src/common/qandroidvideorendercontrol.h104
-rw-r--r--src/plugins/android/src/mediacapture/mediacapture.pri47
-rw-r--r--src/plugins/android/src/mediacapture/qandroidaudioencodersettingscontrol.cpp98
-rw-r--r--src/plugins/android/src/mediacapture/qandroidaudioencodersettingscontrol.h69
-rw-r--r--src/plugins/android/src/mediacapture/qandroidaudioinputselectorcontrol.cpp113
-rw-r--r--src/plugins/android/src/mediacapture/qandroidaudioinputselectorcontrol.h73
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcameracapturebufferformatcontrol.cpp66
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcameracapturebufferformatcontrol.h62
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcameracapturedestinationcontrol.cpp71
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcameracapturedestinationcontrol.h67
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcameracontrol.cpp114
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcameracontrol.h76
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcameraexposurecontrol.cpp227
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcameraexposurecontrol.h85
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcameraflashcontrol.cpp120
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcameraflashcontrol.h73
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcamerafocuscontrol.cpp304
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcamerafocuscontrol.h95
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcameraimagecapturecontrol.cpp86
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcameraimagecapturecontrol.h71
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcameraimageprocessingcontrol.cpp135
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcameraimageprocessingcontrol.h73
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcameralockscontrol.cpp254
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcameralockscontrol.h87
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcamerasession.cpp553
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcamerasession.h158
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcamerazoomcontrol.cpp141
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcamerazoomcontrol.h80
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcaptureservice.cpp216
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcaptureservice.h109
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcapturesession.cpp547
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcapturesession.h184
-rw-r--r--src/plugins/android/src/mediacapture/qandroidimageencodercontrol.cpp95
-rw-r--r--src/plugins/android/src/mediacapture/qandroidimageencodercontrol.h72
-rw-r--r--src/plugins/android/src/mediacapture/qandroidmediacontainercontrol.cpp86
-rw-r--r--src/plugins/android/src/mediacapture/qandroidmediacontainercontrol.h68
-rw-r--r--src/plugins/android/src/mediacapture/qandroidmediarecordercontrol.cpp120
-rw-r--r--src/plugins/android/src/mediacapture/qandroidmediarecordercontrol.h77
-rw-r--r--src/plugins/android/src/mediacapture/qandroidmediastoragelocation.cpp130
-rw-r--r--src/plugins/android/src/mediacapture/qandroidmediastoragelocation.h75
-rw-r--r--src/plugins/android/src/mediacapture/qandroidvideodeviceselectorcontrol.cpp150
-rw-r--r--src/plugins/android/src/mediacapture/qandroidvideodeviceselectorcontrol.h84
-rw-r--r--src/plugins/android/src/mediacapture/qandroidvideoencodersettingscontrol.cpp99
-rw-r--r--src/plugins/android/src/mediacapture/qandroidvideoencodersettingscontrol.h70
-rw-r--r--src/plugins/android/src/mediaplayer/mediaplayer.pri11
-rw-r--r--src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp535
-rw-r--r--src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h131
-rw-r--r--src/plugins/android/src/mediaplayer/qandroidmediaservice.cpp97
-rw-r--r--src/plugins/android/src/mediaplayer/qandroidmediaservice.h71
-rw-r--r--src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.cpp222
-rw-r--r--src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.h80
-rw-r--r--src/plugins/android/src/qandroidmediaserviceplugin.cpp149
-rw-r--r--src/plugins/android/src/qandroidmediaserviceplugin.h75
-rw-r--r--src/plugins/android/src/src.pro19
-rw-r--r--src/plugins/android/src/wrappers/jcamera.cpp712
-rw-r--r--src/plugins/android/src/wrappers/jcamera.h166
-rw-r--r--src/plugins/android/src/wrappers/jmediametadataretriever.cpp126
-rw-r--r--src/plugins/android/src/wrappers/jmediametadataretriever.h91
-rw-r--r--src/plugins/android/src/wrappers/jmediaplayer.cpp270
-rw-r--r--src/plugins/android/src/wrappers/jmediaplayer.h135
-rw-r--r--src/plugins/android/src/wrappers/jmediarecorder.cpp242
-rw-r--r--src/plugins/android/src/wrappers/jmediarecorder.h134
-rw-r--r--src/plugins/android/src/wrappers/jmultimediautils.cpp95
-rw-r--r--src/plugins/android/src/wrappers/jmultimediautils.h73
-rw-r--r--src/plugins/android/src/wrappers/jsurfacetexture.cpp113
-rw-r--r--src/plugins/android/src/wrappers/jsurfacetexture.h73
-rw-r--r--src/plugins/android/src/wrappers/jsurfacetextureholder.cpp65
-rw-r--r--src/plugins/android/src/wrappers/jsurfacetextureholder.h59
-rw-r--r--src/plugins/android/src/wrappers/wrappers.pri21
75 files changed, 10110 insertions, 0 deletions
diff --git a/src/plugins/android/src/android_mediaservice.json b/src/plugins/android/src/android_mediaservice.json
new file mode 100644
index 000000000..a12be52bc
--- /dev/null
+++ b/src/plugins/android/src/android_mediaservice.json
@@ -0,0 +1,3 @@
+{
+ "Keys": ["org.qt-project.qt.camera", "org.qt-project.qt.mediaplayer", "org.qt-project.qt.audiosource"]
+}
diff --git a/src/plugins/android/src/common/common.pri b/src/plugins/android/src/common/common.pri
new file mode 100644
index 000000000..f99dad507
--- /dev/null
+++ b/src/plugins/android/src/common/common.pri
@@ -0,0 +1,10 @@
+INCLUDEPATH += $$PWD
+
+HEADERS += \
+ $$PWD/qandroidvideooutput.h \
+ $$PWD/qandroidvideorendercontrol.h \
+ $$PWD/qandroidmultimediautils.h
+
+SOURCES += \
+ $$PWD/qandroidvideorendercontrol.cpp \
+ $$PWD/qandroidmultimediautils.cpp
diff --git a/src/plugins/android/src/common/qandroidmultimediautils.cpp b/src/plugins/android/src/common/qandroidmultimediautils.cpp
new file mode 100644
index 000000000..7ae40358f
--- /dev/null
+++ b/src/plugins/android/src/common/qandroidmultimediautils.cpp
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qandroidmultimediautils.h"
+
+#include <qlist.h>
+
+QT_BEGIN_NAMESPACE
+
+int qt_findClosestValue(const QList<int> &list, int value)
+{
+ if (list.size() < 2)
+ return 0;
+
+ int begin = 0;
+ int end = list.size() - 1;
+ int pivot = begin + (end - begin) / 2;
+ int v = list.at(pivot);
+
+ while (end - begin > 1) {
+ if (value == v)
+ return pivot;
+
+ if (value > v)
+ begin = pivot;
+ else
+ end = pivot;
+
+ pivot = begin + (end - begin) / 2;
+ v = list.at(pivot);
+ }
+
+ return value - v >= list.at(pivot + 1) - value ? pivot + 1 : pivot;
+}
+
+bool qt_sizeLessThan(const QSize &s1, const QSize &s2)
+{
+ return s1.width() * s1.height() < s2.width() * s2.height();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/android/src/common/qandroidmultimediautils.h b/src/plugins/android/src/common/qandroidmultimediautils.h
new file mode 100644
index 000000000..1996209b0
--- /dev/null
+++ b/src/plugins/android/src/common/qandroidmultimediautils.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANDROIDMULTIMEDIAUTILS_H
+#define QANDROIDMULTIMEDIAUTILS_H
+
+#include <qglobal.h>
+#include <qsize.h>
+
+QT_BEGIN_NAMESPACE
+
+// return the index of the closest value to <value> in <list>
+// (binary search)
+int qt_findClosestValue(const QList<int> &list, int value);
+
+bool qt_sizeLessThan(const QSize &s1, const QSize &s2);
+
+QT_END_NAMESPACE
+
+#endif // QANDROIDMULTIMEDIAUTILS_H
diff --git a/src/plugins/android/src/common/qandroidvideooutput.h b/src/plugins/android/src/common/qandroidvideooutput.h
new file mode 100644
index 000000000..8110b67b0
--- /dev/null
+++ b/src/plugins/android/src/common/qandroidvideooutput.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANDROIDVIDEOOUTPUT_H
+#define QANDROIDVIDEOOUTPUT_H
+
+#include <qglobal.h>
+#include <qsize.h>
+#include <jni.h>
+
+QT_BEGIN_NAMESPACE
+
+typedef void (*TextureReadyCallback)(void*);
+
+class QAndroidVideoOutput
+{
+public:
+ QAndroidVideoOutput() { }
+ virtual ~QAndroidVideoOutput() { }
+
+ virtual jobject surfaceHolder() = 0;
+
+ virtual bool isTextureReady() = 0;
+ virtual void setTextureReadyCallback(TextureReadyCallback cb, void *context = 0) = 0;
+ virtual jobject surfaceTexture() = 0;
+
+ virtual void setVideoSize(const QSize &size) = 0;
+ virtual void stop() = 0;
+
+ virtual QImage toImage() = 0;
+};
+
+QT_END_NAMESPACE
+
+#endif // QANDROIDVIDEOOUTPUT_H
diff --git a/src/plugins/android/src/common/qandroidvideorendercontrol.cpp b/src/plugins/android/src/common/qandroidvideorendercontrol.cpp
new file mode 100644
index 000000000..c5d38aebe
--- /dev/null
+++ b/src/plugins/android/src/common/qandroidvideorendercontrol.cpp
@@ -0,0 +1,438 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qandroidvideorendercontrol.h"
+
+#include <QtPlatformSupport/private/qjnihelpers_p.h>
+#include "jsurfacetextureholder.h"
+#include <QAbstractVideoSurface>
+#include <QOpenGLContext>
+#include <QOffscreenSurface>
+#include <QOpenGLFramebufferObject>
+#include <QVideoSurfaceFormat>
+#include <QOpenGLFunctions>
+#include <QOpenGLShaderProgram>
+#include <qevent.h>
+
+QT_BEGIN_NAMESPACE
+
+static const GLfloat g_vertex_data[] = {
+ -1.f, 1.f,
+ 1.f, 1.f,
+ 1.f, -1.f,
+ -1.f, -1.f
+};
+
+static const GLfloat g_texture_data[] = {
+ 0.f, 0.f,
+ 1.f, 0.f,
+ 1.f, 1.f,
+ 0.f, 1.f
+};
+
+class TextureVideoBuffer : public QAbstractVideoBuffer
+{
+public:
+ TextureVideoBuffer(GLuint textureId)
+ : QAbstractVideoBuffer(GLTextureHandle)
+ , m_textureId(textureId)
+ {}
+
+ virtual ~TextureVideoBuffer() {}
+
+ MapMode mapMode() const { return NotMapped; }
+ uchar *map(MapMode, int*, int*) { return 0; }
+ void unmap() {}
+
+ QVariant handle() const
+ {
+ return QVariant::fromValue<unsigned int>(m_textureId);
+ }
+
+private:
+ GLuint m_textureId;
+};
+
+class ImageVideoBuffer : public QAbstractVideoBuffer
+{
+public:
+ ImageVideoBuffer(const QImage &image)
+ : QAbstractVideoBuffer(NoHandle)
+ , m_image(image)
+ , m_mode(NotMapped)
+ {
+
+ }
+
+ MapMode mapMode() const { return m_mode; }
+ uchar *map(MapMode mode, int *, int *)
+ {
+ if (mode != NotMapped && m_mode == NotMapped) {
+ m_mode = mode;
+ return m_image.bits();
+ }
+
+ return 0;
+ }
+
+ void unmap()
+ {
+ m_mode = NotMapped;
+ }
+
+private:
+ QImage m_image;
+ MapMode m_mode;
+};
+
+QAndroidVideoRendererControl::QAndroidVideoRendererControl(QObject *parent)
+ : QVideoRendererControl(parent)
+ , m_surface(0)
+ , m_offscreenSurface(0)
+ , m_glContext(0)
+ , m_fbo(0)
+ , m_program(0)
+ , m_useImage(false)
+ , m_androidSurface(0)
+ , m_surfaceTexture(0)
+ , m_surfaceHolder(0)
+ , m_externalTex(0)
+ , m_textureReadyCallback(0)
+ , m_textureReadyContext(0)
+{
+}
+
+QAndroidVideoRendererControl::~QAndroidVideoRendererControl()
+{
+ if (m_glContext)
+ m_glContext->makeCurrent(m_offscreenSurface);
+
+ if (m_surfaceTexture) {
+ m_surfaceTexture->callMethod<void>("release");
+ delete m_surfaceTexture;
+ m_surfaceTexture = 0;
+ }
+ if (m_androidSurface) {
+ m_androidSurface->callMethod<void>("release");
+ delete m_androidSurface;
+ m_androidSurface = 0;
+ }
+ if (m_surfaceHolder) {
+ delete m_surfaceHolder;
+ m_surfaceHolder = 0;
+ }
+ if (m_externalTex)
+ glDeleteTextures(1, &m_externalTex);
+
+ delete m_fbo;
+ delete m_program;
+ delete m_glContext;
+ delete m_offscreenSurface;
+}
+
+QAbstractVideoSurface *QAndroidVideoRendererControl::surface() const
+{
+ return m_surface;
+}
+
+void QAndroidVideoRendererControl::setSurface(QAbstractVideoSurface *surface)
+{
+ if (surface == m_surface)
+ return;
+
+ if (m_surface && m_surface->isActive()) {
+ m_surface->stop();
+ m_surface->removeEventFilter(this);
+ }
+
+ m_surface = surface;
+
+ if (m_surface) {
+ m_useImage = !m_surface->supportedPixelFormats(QAbstractVideoBuffer::GLTextureHandle).contains(QVideoFrame::Format_BGR32);
+ m_surface->installEventFilter(this);
+ }
+}
+
+bool QAndroidVideoRendererControl::isTextureReady()
+{
+ return QOpenGLContext::currentContext() || (m_surface && m_surface->property("GLContext").isValid());
+}
+
+void QAndroidVideoRendererControl::setTextureReadyCallback(TextureReadyCallback cb, void *context)
+{
+ m_textureReadyCallback = cb;
+ m_textureReadyContext = context;
+}
+
+bool QAndroidVideoRendererControl::initSurfaceTexture()
+{
+ if (m_surfaceTexture)
+ return true;
+
+ if (!m_surface)
+ return false;
+
+ QOpenGLContext *currContext = QOpenGLContext::currentContext();
+
+ // If we don't have a GL context in the current thread, create one and share it
+ // with the render thread GL context
+ if (!currContext && !m_glContext) {
+ QOpenGLContext *shareContext = qobject_cast<QOpenGLContext*>(m_surface->property("GLContext").value<QObject*>());
+ if (!shareContext)
+ return false;
+
+ m_offscreenSurface = new QOffscreenSurface;
+ QSurfaceFormat format;
+ format.setSwapBehavior(QSurfaceFormat::SingleBuffer);
+ m_offscreenSurface->setFormat(format);
+ m_offscreenSurface->create();
+
+ m_glContext = new QOpenGLContext;
+ m_glContext->setFormat(m_offscreenSurface->requestedFormat());
+
+ if (shareContext)
+ m_glContext->setShareContext(shareContext);
+
+ if (!m_glContext->create()) {
+ delete m_glContext;
+ m_glContext = 0;
+ delete m_offscreenSurface;
+ m_offscreenSurface = 0;
+ return false;
+ }
+
+ // if sharing contexts is not supported, fallback to image rendering and send the bits
+ // to the video surface
+ if (!m_glContext->shareContext())
+ m_useImage = true;
+ }
+
+ if (m_glContext)
+ m_glContext->makeCurrent(m_offscreenSurface);
+
+ glGenTextures(1, &m_externalTex);
+ m_surfaceTexture = new JSurfaceTexture(m_externalTex);
+
+ if (m_surfaceTexture->isValid()) {
+ connect(m_surfaceTexture, SIGNAL(frameAvailable()), this, SLOT(onFrameAvailable()));
+ } else {
+ delete m_surfaceTexture;
+ m_surfaceTexture = 0;
+ glDeleteTextures(1, &m_externalTex);
+ }
+
+ return m_surfaceTexture != 0;
+}
+
+jobject QAndroidVideoRendererControl::surfaceHolder()
+{
+ if (!initSurfaceTexture())
+ return 0;
+
+ if (!m_surfaceHolder) {
+ m_androidSurface = new QJNIObject("android/view/Surface",
+ "(Landroid/graphics/SurfaceTexture;)V",
+ m_surfaceTexture->object());
+
+ m_surfaceHolder = new JSurfaceTextureHolder(m_androidSurface->object());
+ }
+
+ return m_surfaceHolder->object();
+}
+
+jobject QAndroidVideoRendererControl::surfaceTexture()
+{
+ if (!initSurfaceTexture())
+ return 0;
+
+ return m_surfaceTexture->object();
+}
+
+void QAndroidVideoRendererControl::setVideoSize(const QSize &size)
+{
+ if (m_nativeSize == size)
+ return;
+
+ stop();
+
+ m_nativeSize = size;
+
+ delete m_fbo;
+ m_fbo = 0;
+}
+
+void QAndroidVideoRendererControl::stop()
+{
+ if (m_surface && m_surface->isActive())
+ m_surface->stop();
+ m_nativeSize = QSize();
+}
+
+QImage QAndroidVideoRendererControl::toImage()
+{
+ if (!m_fbo)
+ return QImage();
+
+ return m_fbo->toImage().mirrored();
+}
+
+void QAndroidVideoRendererControl::onFrameAvailable()
+{
+ if (m_glContext)
+ m_glContext->makeCurrent(m_offscreenSurface);
+
+ m_surfaceTexture->updateTexImage();
+
+ if (!m_nativeSize.isValid())
+ return;
+
+ renderFrameToFbo();
+
+ QAbstractVideoBuffer *buffer = 0;
+ QVideoFrame frame;
+
+ if (m_useImage) {
+ buffer = new ImageVideoBuffer(m_fbo->toImage().mirrored());
+ frame = QVideoFrame(buffer, m_nativeSize, QVideoFrame::Format_RGB32);
+ } else {
+ buffer = new TextureVideoBuffer(m_fbo->texture());
+ frame = QVideoFrame(buffer, m_nativeSize, QVideoFrame::Format_BGR32);
+ }
+
+ if (m_surface && frame.isValid()) {
+ if (m_surface->isActive() && (m_surface->surfaceFormat().pixelFormat() != frame.pixelFormat()
+ || m_surface->nativeResolution() != frame.size())) {
+ m_surface->stop();
+ }
+
+ if (!m_surface->isActive()) {
+ QVideoSurfaceFormat format(frame.size(), frame.pixelFormat(),
+ m_useImage ? QAbstractVideoBuffer::NoHandle
+ : QAbstractVideoBuffer::GLTextureHandle);
+
+ m_surface->start(format);
+ }
+
+ if (m_surface->isActive())
+ m_surface->present(frame);
+ }
+}
+
+void QAndroidVideoRendererControl::renderFrameToFbo()
+{
+ createGLResources();
+
+ m_fbo->bind();
+
+ glViewport(0, 0, m_nativeSize.width(), m_nativeSize.height());
+
+ m_program->bind();
+ m_program->enableAttributeArray(0);
+ m_program->enableAttributeArray(1);
+ m_program->setUniformValue("frameTexture", GLuint(0));
+ m_program->setUniformValue("texMatrix", m_surfaceTexture->getTransformMatrix());
+
+ glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, g_vertex_data);
+ glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, g_texture_data);
+
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ m_program->disableAttributeArray(0);
+ m_program->disableAttributeArray(1);
+ m_program->release();
+
+ glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
+ m_fbo->release();
+
+ glFinish();
+}
+
+void QAndroidVideoRendererControl::createGLResources()
+{
+ if (!m_fbo)
+ m_fbo = new QOpenGLFramebufferObject(m_nativeSize);
+
+ if (!m_program) {
+ m_program = new QOpenGLShaderProgram;
+
+ QOpenGLShader *vertexShader = new QOpenGLShader(QOpenGLShader::Vertex, m_program);
+ vertexShader->compileSourceCode("attribute highp vec4 vertexCoordsArray; \n" \
+ "attribute highp vec2 textureCoordArray; \n" \
+ "uniform highp mat4 texMatrix; \n" \
+ "varying highp vec2 textureCoords; \n" \
+ "void main(void) \n" \
+ "{ \n" \
+ " gl_Position = vertexCoordsArray; \n" \
+ " textureCoords = (texMatrix * vec4(textureCoordArray, 0.0, 1.0)).xy; \n" \
+ "}\n");
+ m_program->addShader(vertexShader);
+
+ QOpenGLShader *fragmentShader = new QOpenGLShader(QOpenGLShader::Fragment, m_program);
+ fragmentShader->compileSourceCode("#extension GL_OES_EGL_image_external : require \n" \
+ "varying highp vec2 textureCoords; \n" \
+ "uniform samplerExternalOES frameTexture; \n" \
+ "void main() \n" \
+ "{ \n" \
+ " gl_FragColor = texture2D(frameTexture, textureCoords); \n" \
+ "}\n");
+ m_program->addShader(fragmentShader);
+
+ m_program->bindAttributeLocation("vertexCoordsArray", 0);
+ m_program->bindAttributeLocation("textureCoordArray", 1);
+ m_program->link();
+ }
+}
+
+bool QAndroidVideoRendererControl::eventFilter(QObject *, QEvent *e)
+{
+ if (e->type() == QEvent::DynamicPropertyChange) {
+ QDynamicPropertyChangeEvent *event = static_cast<QDynamicPropertyChangeEvent*>(e);
+ if (event->propertyName() == "GLContext" && m_textureReadyCallback) {
+ m_textureReadyCallback(m_textureReadyContext);
+ m_textureReadyCallback = 0;
+ m_textureReadyContext = 0;
+ }
+ }
+
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/android/src/common/qandroidvideorendercontrol.h b/src/plugins/android/src/common/qandroidvideorendercontrol.h
new file mode 100644
index 000000000..d8078f075
--- /dev/null
+++ b/src/plugins/android/src/common/qandroidvideorendercontrol.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANDROIDVIDEORENDERCONTROL_H
+#define QANDROIDVIDEORENDERCONTROL_H
+
+#include <qvideorenderercontrol.h>
+#include "qandroidvideooutput.h"
+#include "jsurfacetexture.h"
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLContext;
+class QOffscreenSurface;
+class QOpenGLFramebufferObject;
+class QOpenGLShaderProgram;
+class JSurfaceTextureHolder;
+
+class QAndroidVideoRendererControl : public QVideoRendererControl, public QAndroidVideoOutput
+{
+ Q_OBJECT
+public:
+ explicit QAndroidVideoRendererControl(QObject *parent = 0);
+ ~QAndroidVideoRendererControl() Q_DECL_OVERRIDE;
+
+ QAbstractVideoSurface *surface() const Q_DECL_OVERRIDE;
+ void setSurface(QAbstractVideoSurface *surface) Q_DECL_OVERRIDE;
+
+ jobject surfaceHolder() Q_DECL_OVERRIDE;
+ bool isTextureReady() Q_DECL_OVERRIDE;
+ void setTextureReadyCallback(TextureReadyCallback cb, void *context = 0) Q_DECL_OVERRIDE;
+ jobject surfaceTexture() Q_DECL_OVERRIDE;
+ void setVideoSize(const QSize &size) Q_DECL_OVERRIDE;
+ void stop() Q_DECL_OVERRIDE;
+ QImage toImage() Q_DECL_OVERRIDE;
+
+ bool eventFilter(QObject *obj, QEvent *event) Q_DECL_OVERRIDE;
+
+private Q_SLOTS:
+ void onFrameAvailable();
+
+private:
+ bool initSurfaceTexture();
+ void renderFrameToFbo();
+ void createGLResources();
+
+ QAbstractVideoSurface *m_surface;
+ QOffscreenSurface *m_offscreenSurface;
+ QOpenGLContext *m_glContext;
+ QOpenGLFramebufferObject *m_fbo;
+ QOpenGLShaderProgram *m_program;
+ bool m_useImage;
+ QSize m_nativeSize;
+
+ QJNIObject *m_androidSurface;
+ JSurfaceTexture *m_surfaceTexture;
+ JSurfaceTextureHolder *m_surfaceHolder;
+ uint m_externalTex;
+
+ TextureReadyCallback m_textureReadyCallback;
+ void *m_textureReadyContext;
+};
+
+QT_END_NAMESPACE
+
+#endif // QANDROIDVIDEORENDERCONTROL_H
diff --git a/src/plugins/android/src/mediacapture/mediacapture.pri b/src/plugins/android/src/mediacapture/mediacapture.pri
new file mode 100644
index 000000000..d994bebfd
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/mediacapture.pri
@@ -0,0 +1,47 @@
+INCLUDEPATH += $$PWD
+
+SOURCES += \
+ $$PWD/qandroidcaptureservice.cpp \
+ $$PWD/qandroidcameracontrol.cpp \
+ $$PWD/qandroidvideodeviceselectorcontrol.cpp \
+ $$PWD/qandroidcamerasession.cpp \
+ $$PWD/qandroidcamerazoomcontrol.cpp \
+ $$PWD/qandroidcameraexposurecontrol.cpp \
+ $$PWD/qandroidcameraimageprocessingcontrol.cpp \
+ $$PWD/qandroidimageencodercontrol.cpp \
+ $$PWD/qandroidcameraimagecapturecontrol.cpp \
+ $$PWD/qandroidcameracapturedestinationcontrol.cpp \
+ $$PWD/qandroidcameracapturebufferformatcontrol.cpp \
+ $$PWD/qandroidmediastoragelocation.cpp \
+ $$PWD/qandroidcameraflashcontrol.cpp \
+ $$PWD/qandroidcamerafocuscontrol.cpp \
+ $$PWD/qandroidcameralockscontrol.cpp \
+ $$PWD/qandroidcapturesession.cpp \
+ $$PWD/qandroidmediarecordercontrol.cpp \
+ $$PWD/qandroidaudioencodersettingscontrol.cpp \
+ $$PWD/qandroidmediacontainercontrol.cpp \
+ $$PWD/qandroidvideoencodersettingscontrol.cpp \
+ $$PWD/qandroidaudioinputselectorcontrol.cpp
+
+HEADERS += \
+ $$PWD/qandroidcaptureservice.h \
+ $$PWD/qandroidcameracontrol.h \
+ $$PWD/qandroidvideodeviceselectorcontrol.h \
+ $$PWD/qandroidcamerasession.h \
+ $$PWD/qandroidcamerazoomcontrol.h \
+ $$PWD/qandroidcameraexposurecontrol.h \
+ $$PWD/qandroidcameraimageprocessingcontrol.h \
+ $$PWD/qandroidimageencodercontrol.h \
+ $$PWD/qandroidcameraimagecapturecontrol.h \
+ $$PWD/qandroidcameracapturedestinationcontrol.h \
+ $$PWD/qandroidcameracapturebufferformatcontrol.h \
+ $$PWD/qandroidmediastoragelocation.h \
+ $$PWD/qandroidcameraflashcontrol.h \
+ $$PWD/qandroidcamerafocuscontrol.h \
+ $$PWD/qandroidcameralockscontrol.h \
+ $$PWD/qandroidcapturesession.h \
+ $$PWD/qandroidmediarecordercontrol.h \
+ $$PWD/qandroidaudioencodersettingscontrol.h \
+ $$PWD/qandroidmediacontainercontrol.h \
+ $$PWD/qandroidvideoencodersettingscontrol.h \
+ $$PWD/qandroidaudioinputselectorcontrol.h
diff --git a/src/plugins/android/src/mediacapture/qandroidaudioencodersettingscontrol.cpp b/src/plugins/android/src/mediacapture/qandroidaudioencodersettingscontrol.cpp
new file mode 100644
index 000000000..8015ec38c
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidaudioencodersettingscontrol.cpp
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qandroidaudioencodersettingscontrol.h"
+
+#include "qandroidcapturesession.h"
+
+QT_BEGIN_NAMESPACE
+
+QAndroidAudioEncoderSettingsControl::QAndroidAudioEncoderSettingsControl(QAndroidCaptureSession *session)
+ : QAudioEncoderSettingsControl()
+ , m_session(session)
+{
+}
+
+QStringList QAndroidAudioEncoderSettingsControl::supportedAudioCodecs() const
+{
+ return QStringList() << QLatin1String("amr-nb") << QLatin1String("amr-wb") << QLatin1String("aac");
+}
+
+QString QAndroidAudioEncoderSettingsControl::codecDescription(const QString &codecName) const
+{
+ if (codecName == QLatin1String("amr-nb"))
+ return tr("Adaptive Multi-Rate Narrowband (AMR-NB) audio codec");
+ else if (codecName == QLatin1String("amr-wb"))
+ return tr("Adaptive Multi-Rate Wideband (AMR-WB) audio codec");
+ else if (codecName == QLatin1String("aac"))
+ return tr("AAC Low Complexity (AAC-LC) audio codec");
+
+ return QString();
+}
+
+QList<int> QAndroidAudioEncoderSettingsControl::supportedSampleRates(const QAudioEncoderSettings &settings, bool *continuous) const
+{
+ if (continuous)
+ *continuous = false;
+
+ if (settings.isNull() || settings.codec().isNull() || settings.codec() == QLatin1String("aac")) {
+ return QList<int>() << 8000 << 11025 << 12000 << 16000 << 22050
+ << 24000 << 32000 << 44100 << 48000 << 96000;
+ } else if (settings.codec() == QLatin1String("amr-nb")) {
+ return QList<int>() << 8000;
+ } else if (settings.codec() == QLatin1String("amr-wb")) {
+ return QList<int>() << 16000;
+ }
+
+ return QList<int>();
+}
+
+QAudioEncoderSettings QAndroidAudioEncoderSettingsControl::audioSettings() const
+{
+ return m_session->audioSettings();
+}
+
+void QAndroidAudioEncoderSettingsControl::setAudioSettings(const QAudioEncoderSettings &settings)
+{
+ m_session->setAudioSettings(settings);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/android/src/mediacapture/qandroidaudioencodersettingscontrol.h b/src/plugins/android/src/mediacapture/qandroidaudioencodersettingscontrol.h
new file mode 100644
index 000000000..11a35fe6a
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidaudioencodersettingscontrol.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANDROIDAUDIOENCODERSETTINGSCONTROL_H
+#define QANDROIDAUDIOENCODERSETTINGSCONTROL_H
+
+#include <qaudioencodersettingscontrol.h>
+
+QT_BEGIN_NAMESPACE
+
+class QAndroidCaptureSession;
+
+class QAndroidAudioEncoderSettingsControl : public QAudioEncoderSettingsControl
+{
+ Q_OBJECT
+public:
+ explicit QAndroidAudioEncoderSettingsControl(QAndroidCaptureSession *session);
+
+ QStringList supportedAudioCodecs() const Q_DECL_OVERRIDE;
+ QString codecDescription(const QString &codecName) const Q_DECL_OVERRIDE;
+ QList<int> supportedSampleRates(const QAudioEncoderSettings &settings, bool *continuous = 0) const Q_DECL_OVERRIDE;
+ QAudioEncoderSettings audioSettings() const Q_DECL_OVERRIDE;
+ void setAudioSettings(const QAudioEncoderSettings &settings) Q_DECL_OVERRIDE;
+
+private:
+ QAndroidCaptureSession *m_session;
+};
+
+QT_END_NAMESPACE
+
+#endif // QANDROIDAUDIOENCODERSETTINGSCONTROL_H
diff --git a/src/plugins/android/src/mediacapture/qandroidaudioinputselectorcontrol.cpp b/src/plugins/android/src/mediacapture/qandroidaudioinputselectorcontrol.cpp
new file mode 100644
index 000000000..4032b2d0b
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidaudioinputselectorcontrol.cpp
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qandroidaudioinputselectorcontrol.h"
+
+#include "qandroidcapturesession.h"
+
+QT_BEGIN_NAMESPACE
+
+QAndroidAudioInputSelectorControl::QAndroidAudioInputSelectorControl(QAndroidCaptureSession *session)
+ : QAudioInputSelectorControl()
+ , m_session(session)
+{
+ connect(m_session, SIGNAL(audioInputChanged(QString)), this, SIGNAL(activeInputChanged(QString)));
+}
+
+QList<QString> QAndroidAudioInputSelectorControl::availableInputs() const
+{
+ return QList<QString>() << QLatin1String("default")
+ << QLatin1String("mic")
+ << QLatin1String("voice_uplink")
+ << QLatin1String("voice_downlink")
+ << QLatin1String("voice_call")
+ << QLatin1String("voice_recognition");
+}
+
+QString QAndroidAudioInputSelectorControl::inputDescription(const QString& name) const
+{
+ return availableDeviceDescription(name.toLatin1());
+}
+
+QString QAndroidAudioInputSelectorControl::defaultInput() const
+{
+ return QLatin1String("default");
+}
+
+QString QAndroidAudioInputSelectorControl::activeInput() const
+{
+ return m_session->audioInput();
+}
+
+void QAndroidAudioInputSelectorControl::setActiveInput(const QString& name)
+{
+ m_session->setAudioInput(name);
+}
+
+QList<QByteArray> QAndroidAudioInputSelectorControl::availableDevices()
+{
+ return QList<QByteArray>() << "default"
+ << "mic"
+ << "voice_uplink"
+ << "voice_downlink"
+ << "voice_call"
+ << "voice_recognition";
+}
+
+QString QAndroidAudioInputSelectorControl::availableDeviceDescription(const QByteArray &device)
+{
+ if (device == "default")
+ return QLatin1String("Default audio source");
+ else if (device == "mic")
+ return QLatin1String("Microphone audio source");
+ else if (device == "voice_uplink")
+ return QLatin1String("Voice call uplink (Tx) audio source");
+ else if (device == "voice_downlink")
+ return QLatin1String("Voice call downlink (Rx) audio source");
+ else if (device == "voice_call")
+ return QLatin1String("Voice call uplink + downlink audio source");
+ else if (device == "voice_recognition")
+ return QLatin1String("Microphone audio source tuned for voice recognition");
+ else
+ return QString();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/android/src/mediacapture/qandroidaudioinputselectorcontrol.h b/src/plugins/android/src/mediacapture/qandroidaudioinputselectorcontrol.h
new file mode 100644
index 000000000..3dfa7c712
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidaudioinputselectorcontrol.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANDROIDAUDIOINPUTSELECTORCONTROL_H
+#define QANDROIDAUDIOINPUTSELECTORCONTROL_H
+
+#include <qaudioinputselectorcontrol.h>
+
+QT_BEGIN_NAMESPACE
+
+class QAndroidCaptureSession;
+
+class QAndroidAudioInputSelectorControl : public QAudioInputSelectorControl
+{
+ Q_OBJECT
+public:
+ explicit QAndroidAudioInputSelectorControl(QAndroidCaptureSession *session);
+
+ QList<QString> availableInputs() const;
+ QString inputDescription(const QString& name) const;
+ QString defaultInput() const;
+
+ QString activeInput() const;
+ void setActiveInput(const QString& name);
+
+ static QList<QByteArray> availableDevices();
+ static QString availableDeviceDescription(const QByteArray &device);
+
+private:
+ QAndroidCaptureSession *m_session;
+};
+
+QT_END_NAMESPACE
+
+#endif // QANDROIDAUDIOINPUTSELECTORCONTROL_H
diff --git a/src/plugins/android/src/mediacapture/qandroidcameracapturebufferformatcontrol.cpp b/src/plugins/android/src/mediacapture/qandroidcameracapturebufferformatcontrol.cpp
new file mode 100644
index 000000000..dc7f20ee7
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidcameracapturebufferformatcontrol.cpp
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qandroidcameracapturebufferformatcontrol.h"
+
+QT_BEGIN_NAMESPACE
+
+QAndroidCameraCaptureBufferFormatControl::QAndroidCameraCaptureBufferFormatControl()
+ : QCameraCaptureBufferFormatControl()
+{
+}
+
+QList<QVideoFrame::PixelFormat> QAndroidCameraCaptureBufferFormatControl::supportedBufferFormats() const
+{
+ return (QList<QVideoFrame::PixelFormat>() << QVideoFrame::Format_Jpeg);
+}
+
+QVideoFrame::PixelFormat QAndroidCameraCaptureBufferFormatControl::bufferFormat() const
+{
+ return QVideoFrame::Format_Jpeg;
+}
+
+void QAndroidCameraCaptureBufferFormatControl::setBufferFormat(QVideoFrame::PixelFormat format)
+{
+ Q_UNUSED(format)
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/android/src/mediacapture/qandroidcameracapturebufferformatcontrol.h b/src/plugins/android/src/mediacapture/qandroidcameracapturebufferformatcontrol.h
new file mode 100644
index 000000000..cf8bd4933
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidcameracapturebufferformatcontrol.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANDROIDCAMERACAPTUREBUFFERFORMATCONTROL_H
+#define QANDROIDCAMERACAPTUREBUFFERFORMATCONTROL_H
+
+#include <qcameracapturebufferformatcontrol.h>
+
+QT_BEGIN_NAMESPACE
+
+class QAndroidCameraCaptureBufferFormatControl : public QCameraCaptureBufferFormatControl
+{
+ Q_OBJECT
+public:
+ QAndroidCameraCaptureBufferFormatControl();
+
+ QList<QVideoFrame::PixelFormat> supportedBufferFormats() const Q_DECL_OVERRIDE;
+ QVideoFrame::PixelFormat bufferFormat() const Q_DECL_OVERRIDE;
+ void setBufferFormat(QVideoFrame::PixelFormat format) Q_DECL_OVERRIDE;
+};
+
+QT_END_NAMESPACE
+
+#endif // QANDROIDCAMERACAPTUREBUFFERFORMATCONTROL_H
diff --git a/src/plugins/android/src/mediacapture/qandroidcameracapturedestinationcontrol.cpp b/src/plugins/android/src/mediacapture/qandroidcameracapturedestinationcontrol.cpp
new file mode 100644
index 000000000..870a4240d
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidcameracapturedestinationcontrol.cpp
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qandroidcameracapturedestinationcontrol.h"
+
+#include "qandroidcamerasession.h"
+
+QT_BEGIN_NAMESPACE
+
+QAndroidCameraCaptureDestinationControl::QAndroidCameraCaptureDestinationControl(QAndroidCameraSession *session)
+ : QCameraCaptureDestinationControl()
+ , m_session(session)
+{
+ connect(m_session, SIGNAL(captureDestinationChanged(QCameraImageCapture::CaptureDestinations)),
+ this, SIGNAL(captureDestinationChanged(QCameraImageCapture::CaptureDestinations)));
+}
+
+bool QAndroidCameraCaptureDestinationControl::isCaptureDestinationSupported(QCameraImageCapture::CaptureDestinations destination) const
+{
+ return m_session->isCaptureDestinationSupported(destination);
+}
+
+QCameraImageCapture::CaptureDestinations QAndroidCameraCaptureDestinationControl::captureDestination() const
+{
+ return m_session->captureDestination();;
+}
+
+void QAndroidCameraCaptureDestinationControl::setCaptureDestination(QCameraImageCapture::CaptureDestinations destination)
+{
+ m_session->setCaptureDestination(destination);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/android/src/mediacapture/qandroidcameracapturedestinationcontrol.h b/src/plugins/android/src/mediacapture/qandroidcameracapturedestinationcontrol.h
new file mode 100644
index 000000000..46ff96bca
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidcameracapturedestinationcontrol.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANDROIDCAMERACAPTUREDESTINATIONCONTROL_H
+#define QANDROIDCAMERACAPTUREDESTINATIONCONTROL_H
+
+#include <qcameracapturedestinationcontrol.h>
+
+QT_BEGIN_NAMESPACE
+
+class QAndroidCameraSession;
+
+class QAndroidCameraCaptureDestinationControl : public QCameraCaptureDestinationControl
+{
+ Q_OBJECT
+public:
+ explicit QAndroidCameraCaptureDestinationControl(QAndroidCameraSession *session);
+
+ bool isCaptureDestinationSupported(QCameraImageCapture::CaptureDestinations destination) const Q_DECL_OVERRIDE;
+ QCameraImageCapture::CaptureDestinations captureDestination() const Q_DECL_OVERRIDE;
+ void setCaptureDestination(QCameraImageCapture::CaptureDestinations destination) Q_DECL_OVERRIDE;
+
+private:
+ QAndroidCameraSession *m_session;
+};
+
+QT_END_NAMESPACE
+
+#endif // QANDROIDCAMERACAPTUREDESTINATIONCONTROL_H
diff --git a/src/plugins/android/src/mediacapture/qandroidcameracontrol.cpp b/src/plugins/android/src/mediacapture/qandroidcameracontrol.cpp
new file mode 100644
index 000000000..f91ae1e89
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidcameracontrol.cpp
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qandroidcameracontrol.h"
+
+#include "qandroidcamerasession.h"
+
+QT_BEGIN_NAMESPACE
+
+QAndroidCameraControl::QAndroidCameraControl(QAndroidCameraSession *session)
+ : QCameraControl(0)
+ , m_cameraSession(session)
+
+{
+ connect(m_cameraSession, SIGNAL(statusChanged(QCamera::Status)),
+ this, SIGNAL(statusChanged(QCamera::Status)));
+
+ connect(m_cameraSession, SIGNAL(stateChanged(QCamera::State)),
+ this, SIGNAL(stateChanged(QCamera::State)));
+
+ connect(m_cameraSession, SIGNAL(error(int,QString)), this, SIGNAL(error(int,QString)));
+
+ connect(m_cameraSession, SIGNAL(captureModeChanged(QCamera::CaptureModes)),
+ this, SIGNAL(captureModeChanged(QCamera::CaptureModes)));
+}
+
+QAndroidCameraControl::~QAndroidCameraControl()
+{
+}
+
+QCamera::CaptureModes QAndroidCameraControl::captureMode() const
+{
+ return m_cameraSession->captureMode();
+}
+
+void QAndroidCameraControl::setCaptureMode(QCamera::CaptureModes mode)
+{
+ m_cameraSession->setCaptureMode(mode);
+}
+
+bool QAndroidCameraControl::isCaptureModeSupported(QCamera::CaptureModes mode) const
+{
+ return m_cameraSession->isCaptureModeSupported(mode);
+}
+
+void QAndroidCameraControl::setState(QCamera::State state)
+{
+ m_cameraSession->setState(state);
+}
+
+QCamera::State QAndroidCameraControl::state() const
+{
+ return m_cameraSession->state();
+}
+
+QCamera::Status QAndroidCameraControl::status() const
+{
+ return m_cameraSession->status();
+}
+
+bool QAndroidCameraControl::canChangeProperty(PropertyChangeType changeType, QCamera::Status status) const
+{
+ Q_UNUSED(status);
+
+ switch (changeType) {
+ case QCameraControl::CaptureMode:
+ case QCameraControl::ImageEncodingSettings:
+ case QCameraControl::VideoEncodingSettings:
+ case QCameraControl::Viewfinder:
+ return true;
+ default:
+ return false;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/android/src/mediacapture/qandroidcameracontrol.h b/src/plugins/android/src/mediacapture/qandroidcameracontrol.h
new file mode 100644
index 000000000..f5070c13e
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidcameracontrol.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QANDROIDCAMERACONTROL_H
+#define QANDROIDCAMERACONTROL_H
+
+#include <qcameracontrol.h>
+
+QT_BEGIN_NAMESPACE
+
+class QAndroidCameraSession;
+
+class QAndroidCameraControl : public QCameraControl
+{
+ Q_OBJECT
+public:
+ explicit QAndroidCameraControl(QAndroidCameraSession *session);
+ virtual ~QAndroidCameraControl();
+
+ QCamera::State state() const;
+ void setState(QCamera::State state);
+
+ QCamera::Status status() const;
+
+ QCamera::CaptureModes captureMode() const;
+ void setCaptureMode(QCamera::CaptureModes mode);
+ bool isCaptureModeSupported(QCamera::CaptureModes mode) const;
+
+ bool canChangeProperty(PropertyChangeType changeType, QCamera::Status status) const;
+
+private:
+ QAndroidCameraSession *m_cameraSession;
+};
+
+QT_END_NAMESPACE
+
+#endif // QANDROIDCAMERACONTROL_H
diff --git a/src/plugins/android/src/mediacapture/qandroidcameraexposurecontrol.cpp b/src/plugins/android/src/mediacapture/qandroidcameraexposurecontrol.cpp
new file mode 100644
index 000000000..03bbadb93
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidcameraexposurecontrol.cpp
@@ -0,0 +1,227 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qandroidcameraexposurecontrol.h"
+
+#include "qandroidcamerasession.h"
+#include "jcamera.h"
+
+QT_BEGIN_NAMESPACE
+
+QAndroidCameraExposureControl::QAndroidCameraExposureControl(QAndroidCameraSession *session)
+ : QCameraExposureControl()
+ , m_session(session)
+ , m_minExposureCompensationIndex(0)
+ , m_maxExposureCompensationIndex(0)
+ , m_exposureCompensationStep(0.0)
+ , m_requestedExposureCompensation(0.0)
+ , m_actualExposureCompensation(0.0)
+ , m_requestedExposureMode(QCameraExposure::ExposureAuto)
+ , m_actualExposureMode(QCameraExposure::ExposureAuto)
+{
+ connect(m_session, SIGNAL(opened()),
+ this, SLOT(onCameraOpened()));
+}
+
+bool QAndroidCameraExposureControl::isParameterSupported(ExposureParameter parameter) const
+{
+ switch (parameter) {
+ case QCameraExposureControl::ISO:
+ return false;
+ case QCameraExposureControl::Aperture:
+ return false;
+ case QCameraExposureControl::ShutterSpeed:
+ return false;
+ case QCameraExposureControl::ExposureCompensation:
+ return true;
+ case QCameraExposureControl::FlashPower:
+ return false;
+ case QCameraExposureControl::FlashCompensation:
+ return false;
+ case QCameraExposureControl::TorchPower:
+ return false;
+ case QCameraExposureControl::SpotMeteringPoint:
+ return false;
+ case QCameraExposureControl::ExposureMode:
+ return true;
+ case QCameraExposureControl::MeteringMode:
+ return false;
+ default:
+ return false;
+ }
+}
+
+QVariantList QAndroidCameraExposureControl::supportedParameterRange(ExposureParameter parameter, bool *continuous) const
+{
+ if (!m_session->camera())
+ return QVariantList();
+
+ if (continuous)
+ *continuous = false;
+
+ if (parameter == QCameraExposureControl::ExposureCompensation)
+ return m_supportedExposureCompensations;
+ else if (parameter == QCameraExposureControl::ExposureMode)
+ return m_supportedExposureModes;
+
+ return QVariantList();
+}
+
+QVariant QAndroidCameraExposureControl::requestedValue(ExposureParameter parameter) const
+{
+ if (parameter == QCameraExposureControl::ExposureCompensation)
+ return QVariant::fromValue(m_requestedExposureCompensation);
+ else if (parameter == QCameraExposureControl::ExposureMode)
+ return QVariant::fromValue(m_requestedExposureMode);
+
+ return QVariant();
+}
+
+QVariant QAndroidCameraExposureControl::actualValue(ExposureParameter parameter) const
+{
+ if (parameter == QCameraExposureControl::ExposureCompensation)
+ return QVariant::fromValue(m_actualExposureCompensation);
+ else if (parameter == QCameraExposureControl::ExposureMode)
+ return QVariant::fromValue(m_actualExposureMode);
+
+ return QVariant();
+}
+
+bool QAndroidCameraExposureControl::setValue(ExposureParameter parameter, const QVariant& value)
+{
+ if (!m_session->camera() || !value.isValid())
+ return false;
+
+ if (parameter == QCameraExposureControl::ExposureCompensation) {
+ m_requestedExposureCompensation = value.toReal();
+ emit requestedValueChanged(QCameraExposureControl::ExposureCompensation);
+
+ int expCompIndex = qRound(m_requestedExposureCompensation / m_exposureCompensationStep);
+ if (expCompIndex >= m_minExposureCompensationIndex
+ && expCompIndex <= m_maxExposureCompensationIndex) {
+ m_session->camera()->setExposureCompensation(expCompIndex);
+
+ m_actualExposureCompensation = expCompIndex * m_exposureCompensationStep;
+ emit actualValueChanged(QCameraExposureControl::ExposureCompensation);
+
+ return true;
+ }
+
+ } else if (parameter == QCameraExposureControl::ExposureMode) {
+ m_requestedExposureMode = value.value<QCameraExposure::ExposureMode>();
+ emit requestedValueChanged(QCameraExposureControl::ExposureMode);
+
+ if (!m_supportedExposureModes.isEmpty()) {
+ m_actualExposureMode = m_requestedExposureMode;
+
+ QString sceneMode;
+ switch (m_requestedExposureMode) {
+ case QCameraExposure::ExposureAuto:
+ sceneMode = QLatin1String("auto");
+ break;
+ case QCameraExposure::ExposureSports:
+ sceneMode = QLatin1String("sports");
+ break;
+ case QCameraExposure::ExposurePortrait:
+ sceneMode = QLatin1String("portrait");
+ break;
+ case QCameraExposure::ExposureBeach:
+ sceneMode = QLatin1String("beach");
+ break;
+ case QCameraExposure::ExposureSnow:
+ sceneMode = QLatin1String("snow");
+ break;
+ case QCameraExposure::ExposureNight:
+ sceneMode = QLatin1String("night");
+ break;
+ default:
+ sceneMode = QLatin1String("auto");
+ m_actualExposureMode = QCameraExposure::ExposureAuto;
+ break;
+ }
+
+ m_session->camera()->setSceneMode(sceneMode);
+ emit actualValueChanged(QCameraExposureControl::ExposureMode);
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void QAndroidCameraExposureControl::onCameraOpened()
+{
+ m_requestedExposureCompensation = m_actualExposureCompensation = 0.0;
+ m_requestedExposureMode = m_actualExposureMode = QCameraExposure::ExposureAuto;
+ emit requestedValueChanged(QCameraExposureControl::ExposureCompensation);
+ emit actualValueChanged(QCameraExposureControl::ExposureCompensation);
+ emit requestedValueChanged(QCameraExposureControl::ExposureMode);
+ emit actualValueChanged(QCameraExposureControl::ExposureMode);
+
+ m_minExposureCompensationIndex = m_session->camera()->getMinExposureCompensation();
+ m_maxExposureCompensationIndex = m_session->camera()->getMaxExposureCompensation();
+ m_exposureCompensationStep = m_session->camera()->getExposureCompensationStep();
+ for (int i = m_minExposureCompensationIndex; i <= m_maxExposureCompensationIndex; ++i)
+ m_supportedExposureCompensations.append(i * m_exposureCompensationStep);
+ emit parameterRangeChanged(QCameraExposureControl::ExposureCompensation);
+
+ m_supportedExposureModes.clear();
+ QStringList sceneModes = m_session->camera()->getSupportedSceneModes();
+ for (int i = 0; i < sceneModes.size(); ++i) {
+ const QString &sceneMode = sceneModes.at(i);
+ if (sceneMode == QLatin1String("auto"))
+ m_supportedExposureModes << QVariant::fromValue(QCameraExposure::ExposureAuto);
+ else if (sceneMode == QLatin1String("beach"))
+ m_supportedExposureModes << QVariant::fromValue(QCameraExposure::ExposureBeach);
+ else if (sceneMode == QLatin1String("night"))
+ m_supportedExposureModes << QVariant::fromValue(QCameraExposure::ExposureNight);
+ else if (sceneMode == QLatin1String("portrait"))
+ m_supportedExposureModes << QVariant::fromValue(QCameraExposure::ExposurePortrait);
+ else if (sceneMode == QLatin1String("snow"))
+ m_supportedExposureModes << QVariant::fromValue(QCameraExposure::ExposureSnow);
+ else if (sceneMode == QLatin1String("sports"))
+ m_supportedExposureModes << QVariant::fromValue(QCameraExposure::ExposureSports);
+ }
+ emit parameterRangeChanged(QCameraExposureControl::ExposureMode);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/android/src/mediacapture/qandroidcameraexposurecontrol.h b/src/plugins/android/src/mediacapture/qandroidcameraexposurecontrol.h
new file mode 100644
index 000000000..d07fea539
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidcameraexposurecontrol.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANDROIDCAMERAEXPOSURECONTROL_H
+#define QANDROIDCAMERAEXPOSURECONTROL_H
+
+#include <qcameraexposurecontrol.h>
+
+QT_BEGIN_NAMESPACE
+
+class QAndroidCameraSession;
+
+class QAndroidCameraExposureControl : public QCameraExposureControl
+{
+ Q_OBJECT
+public:
+ explicit QAndroidCameraExposureControl(QAndroidCameraSession *session);
+
+ bool isParameterSupported(ExposureParameter parameter) const Q_DECL_OVERRIDE;
+ QVariantList supportedParameterRange(ExposureParameter parameter, bool *continuous) const Q_DECL_OVERRIDE;
+
+ QVariant requestedValue(ExposureParameter parameter) const Q_DECL_OVERRIDE;
+ QVariant actualValue(ExposureParameter parameter) const Q_DECL_OVERRIDE;
+ bool setValue(ExposureParameter parameter, const QVariant& value) Q_DECL_OVERRIDE;
+
+private Q_SLOTS:
+ void onCameraOpened();
+
+private:
+ QAndroidCameraSession *m_session;
+
+ QVariantList m_supportedExposureCompensations;
+ QVariantList m_supportedExposureModes;
+
+ int m_minExposureCompensationIndex;
+ int m_maxExposureCompensationIndex;
+ qreal m_exposureCompensationStep;
+
+ qreal m_requestedExposureCompensation;
+ qreal m_actualExposureCompensation;
+ QCameraExposure::ExposureMode m_requestedExposureMode;
+ QCameraExposure::ExposureMode m_actualExposureMode;
+};
+
+QT_END_NAMESPACE
+
+#endif // QANDROIDCAMERAEXPOSURECONTROL_H
diff --git a/src/plugins/android/src/mediacapture/qandroidcameraflashcontrol.cpp b/src/plugins/android/src/mediacapture/qandroidcameraflashcontrol.cpp
new file mode 100644
index 000000000..253b1baa5
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidcameraflashcontrol.cpp
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qandroidcameraflashcontrol.h"
+
+#include "qandroidcamerasession.h"
+#include "jcamera.h"
+
+QT_BEGIN_NAMESPACE
+
+QAndroidCameraFlashControl::QAndroidCameraFlashControl(QAndroidCameraSession *session)
+ : QCameraFlashControl()
+ , m_session(session)
+ , m_flashMode(QCameraExposure::FlashOff)
+{
+ connect(m_session, SIGNAL(opened()),
+ this, SLOT(onCameraOpened()));
+}
+
+QCameraExposure::FlashModes QAndroidCameraFlashControl::flashMode() const
+{
+ return m_flashMode;
+}
+
+void QAndroidCameraFlashControl::setFlashMode(QCameraExposure::FlashModes mode)
+{
+ if (m_flashMode == mode || !m_session->camera() || !isFlashModeSupported(mode))
+ return;
+
+ // if torch was enabled, it first needs to be turned off before setting another mode
+ if (m_flashMode == QCameraExposure::FlashVideoLight)
+ m_session->camera()->setFlashMode(QLatin1String("off"));
+
+ m_flashMode = mode;
+
+ QString flashMode;
+ if (mode.testFlag(QCameraExposure::FlashAuto))
+ flashMode = QLatin1String("auto");
+ else if (mode.testFlag(QCameraExposure::FlashOn))
+ flashMode = QLatin1String("on");
+ else if (mode.testFlag(QCameraExposure::FlashRedEyeReduction))
+ flashMode = QLatin1String("red-eye");
+ else if (mode.testFlag(QCameraExposure::FlashVideoLight))
+ flashMode = QLatin1String("torch");
+ else // FlashOff
+ flashMode = QLatin1String("off");
+
+ m_session->camera()->setFlashMode(flashMode);
+}
+
+bool QAndroidCameraFlashControl::isFlashModeSupported(QCameraExposure::FlashModes mode) const
+{
+ return m_supportedFlashModes.contains(mode);
+}
+
+bool QAndroidCameraFlashControl::isFlashReady() const
+{
+ // Android doesn't have an API for that
+ return true;
+}
+
+void QAndroidCameraFlashControl::onCameraOpened()
+{
+ m_supportedFlashModes.clear();
+
+ QStringList flashModes = m_session->camera()->getSupportedFlashModes();
+ for (int i = 0; i < flashModes.size(); ++i) {
+ const QString &flashMode = flashModes.at(i);
+ if (flashMode == QLatin1String("off"))
+ m_supportedFlashModes << QCameraExposure::FlashOff;
+ else if (flashMode == QLatin1String("auto"))
+ m_supportedFlashModes << QCameraExposure::FlashAuto;
+ else if (flashMode == QLatin1String("on"))
+ m_supportedFlashModes << QCameraExposure::FlashOn;
+ else if (flashMode == QLatin1String("red-eye"))
+ m_supportedFlashModes << QCameraExposure::FlashRedEyeReduction;
+ else if (flashMode == QLatin1String("torch"))
+ m_supportedFlashModes << QCameraExposure::FlashVideoLight;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/android/src/mediacapture/qandroidcameraflashcontrol.h b/src/plugins/android/src/mediacapture/qandroidcameraflashcontrol.h
new file mode 100644
index 000000000..35ed71894
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidcameraflashcontrol.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANDROIDCAMERAFLASHCONTROL_H
+#define QANDROIDCAMERAFLASHCONTROL_H
+
+#include <qcameraflashcontrol.h>
+
+QT_BEGIN_NAMESPACE
+
+class QAndroidCameraSession;
+
+class QAndroidCameraFlashControl : public QCameraFlashControl
+{
+ Q_OBJECT
+public:
+ explicit QAndroidCameraFlashControl(QAndroidCameraSession *session);
+
+ QCameraExposure::FlashModes flashMode() const Q_DECL_OVERRIDE;
+ void setFlashMode(QCameraExposure::FlashModes mode) Q_DECL_OVERRIDE;
+ bool isFlashModeSupported(QCameraExposure::FlashModes mode) const Q_DECL_OVERRIDE;
+ bool isFlashReady() const Q_DECL_OVERRIDE;
+
+private Q_SLOTS:
+ void onCameraOpened();
+
+private:
+ QAndroidCameraSession *m_session;
+ QList<QCameraExposure::FlashModes> m_supportedFlashModes;
+ QCameraExposure::FlashModes m_flashMode;
+};
+
+QT_END_NAMESPACE
+
+#endif // QANDROIDCAMERAFLASHCONTROL_H
diff --git a/src/plugins/android/src/mediacapture/qandroidcamerafocuscontrol.cpp b/src/plugins/android/src/mediacapture/qandroidcamerafocuscontrol.cpp
new file mode 100644
index 000000000..cb785fe1e
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidcamerafocuscontrol.cpp
@@ -0,0 +1,304 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qandroidcamerafocuscontrol.h"
+
+#include "qandroidcamerasession.h"
+#include "jcamera.h"
+
+QT_BEGIN_NAMESPACE
+
+static QRect adjustedArea(const QRectF &area)
+{
+ // Qt maps focus points in the range (0.0, 0.0) -> (1.0, 1.0)
+ // Android maps focus points in the range (-1000, -1000) -> (1000, 1000)
+ // Converts an area in Qt coordinates to Android coordinates
+ return QRect(-1000 + qRound(area.x() * 2000),
+ -1000 + qRound(area.y() * 2000),
+ qRound(area.width() * 2000),
+ qRound(area.height() * 2000))
+ .intersected(QRect(-1000, -1000, 2000, 2000));
+}
+
+QAndroidCameraFocusControl::QAndroidCameraFocusControl(QAndroidCameraSession *session)
+ : QCameraFocusControl()
+ , m_session(session)
+ , m_focusMode(QCameraFocus::AutoFocus)
+ , m_focusPointMode(QCameraFocus::FocusPointAuto)
+ , m_actualFocusPoint(0.5, 0.5)
+ , m_continuousPictureFocusSupported(false)
+ , m_continuousVideoFocusSupported(false)
+{
+ connect(m_session, SIGNAL(opened()),
+ this, SLOT(onCameraOpened()));
+ connect(m_session, SIGNAL(captureModeChanged(QCamera::CaptureModes)),
+ this, SLOT(onCameraCaptureModeChanged()));
+}
+
+QCameraFocus::FocusModes QAndroidCameraFocusControl::focusMode() const
+{
+ return m_focusMode;
+}
+
+void QAndroidCameraFocusControl::setFocusMode(QCameraFocus::FocusModes mode)
+{
+ if (m_focusMode == mode || !m_session->camera() || !isFocusModeSupported(mode))
+ return;
+
+ QString focusMode = QLatin1String("fixed");
+
+ if (mode.testFlag(QCameraFocus::HyperfocalFocus)) {
+ focusMode = QLatin1String("edof");
+ } else if (mode.testFlag(QCameraFocus::ManualFocus)) {
+ focusMode = QLatin1String("fixed");
+ } else if (mode.testFlag(QCameraFocus::AutoFocus)) {
+ focusMode = QLatin1String("auto");
+ } else if (mode.testFlag(QCameraFocus::MacroFocus)) {
+ focusMode = QLatin1String("macro");
+ } else if (mode.testFlag(QCameraFocus::ContinuousFocus)) {
+ if ((m_session->captureMode().testFlag(QCamera::CaptureVideo) && m_continuousVideoFocusSupported)
+ || !m_continuousPictureFocusSupported) {
+ focusMode = QLatin1String("continuous-video");
+ } else {
+ focusMode = QLatin1String("continuous-picture");
+ }
+ } else if (mode.testFlag(QCameraFocus::InfinityFocus)) {
+ focusMode = QLatin1String("infinity");
+ }
+
+ m_session->camera()->setFocusMode(focusMode);
+
+ // reset focus position
+ m_session->camera()->cancelAutoFocus();
+
+ m_focusMode = mode;
+ emit focusModeChanged(m_focusMode);
+}
+
+bool QAndroidCameraFocusControl::isFocusModeSupported(QCameraFocus::FocusModes mode) const
+{
+ return m_supportedFocusModes.contains(mode);
+}
+
+QCameraFocus::FocusPointMode QAndroidCameraFocusControl::focusPointMode() const
+{
+ return m_focusPointMode;
+}
+
+void QAndroidCameraFocusControl::setFocusPointMode(QCameraFocus::FocusPointMode mode)
+{
+ if (!m_session->camera() || m_focusPointMode == mode || !isFocusPointModeSupported(mode))
+ return;
+
+ m_focusPointMode = mode;
+
+ if (mode == QCameraFocus::FocusPointCustom) {
+ m_actualFocusPoint = m_customFocusPoint;
+ } else {
+ // FocusPointAuto | FocusPointCenter
+ // note: there is no way to know the actual focus point in FocusPointAuto mode,
+ // so just report the focus point to be at the center of the frame
+ m_actualFocusPoint = QPointF(0.5, 0.5);
+ }
+
+ updateFocusZones();
+ setCameraFocusArea();
+
+ emit focusPointModeChanged(mode);
+}
+
+bool QAndroidCameraFocusControl::isFocusPointModeSupported(QCameraFocus::FocusPointMode mode) const
+{
+ return m_supportedFocusPointModes.contains(mode);
+}
+
+QPointF QAndroidCameraFocusControl::customFocusPoint() const
+{
+ return m_customFocusPoint;
+}
+
+void QAndroidCameraFocusControl::setCustomFocusPoint(const QPointF &point)
+{
+ if (m_customFocusPoint == point)
+ return;
+
+ m_customFocusPoint = point;
+ emit customFocusPointChanged(m_customFocusPoint);
+
+ if (m_focusPointMode == QCameraFocus::FocusPointCustom) {
+ m_actualFocusPoint = m_customFocusPoint;
+ updateFocusZones();
+ setCameraFocusArea();
+ }
+}
+
+QCameraFocusZoneList QAndroidCameraFocusControl::focusZones() const
+{
+ return m_focusZones;
+}
+
+void QAndroidCameraFocusControl::onCameraOpened()
+{
+ connect(m_session->camera(), SIGNAL(previewSizeChanged()),
+ this, SLOT(onViewportSizeChanged()));
+ connect(m_session->camera(), SIGNAL(autoFocusStarted()),
+ this, SLOT(onAutoFocusStarted()));
+ connect(m_session->camera(), SIGNAL(autoFocusComplete(bool)),
+ this, SLOT(onAutoFocusComplete(bool)));
+
+ m_supportedFocusModes.clear();
+ m_continuousPictureFocusSupported = false;
+ m_continuousVideoFocusSupported = false;
+
+ m_focusPointMode = QCameraFocus::FocusPointAuto;
+ m_actualFocusPoint = QPointF(0.5, 0.5);
+ m_customFocusPoint = QPointF();
+ m_supportedFocusPointModes.clear();
+ m_focusZones.clear();
+
+ QStringList focusModes = m_session->camera()->getSupportedFocusModes();
+ for (int i = 0; i < focusModes.size(); ++i) {
+ const QString &focusMode = focusModes.at(i);
+ if (focusMode == QLatin1String("auto")) {
+ m_supportedFocusModes << QCameraFocus::AutoFocus;
+ } else if (focusMode == QLatin1String("continuous-picture")) {
+ m_supportedFocusModes << QCameraFocus::ContinuousFocus;
+ m_continuousPictureFocusSupported = true;
+ } else if (focusMode == QLatin1String("continuous-video")) {
+ m_supportedFocusModes << QCameraFocus::ContinuousFocus;
+ m_continuousVideoFocusSupported = true;
+ } else if (focusMode == QLatin1String("edof")) {
+ m_supportedFocusModes << QCameraFocus::HyperfocalFocus;
+ } else if (focusMode == QLatin1String("fixed")) {
+ m_supportedFocusModes << QCameraFocus::ManualFocus;
+ } else if (focusMode == QLatin1String("infinity")) {
+ m_supportedFocusModes << QCameraFocus::InfinityFocus;
+ } else if (focusMode == QLatin1String("macro")) {
+ m_supportedFocusModes << QCameraFocus::MacroFocus;
+ }
+ }
+
+ m_supportedFocusPointModes << QCameraFocus::FocusPointAuto;
+ if (m_session->camera()->getMaxNumFocusAreas() > 0)
+ m_supportedFocusPointModes << QCameraFocus::FocusPointCenter << QCameraFocus::FocusPointCustom;
+
+ emit focusModeChanged(focusMode());
+ emit focusPointModeChanged(m_focusPointMode);
+ emit customFocusPointChanged(m_customFocusPoint);
+ emit focusZonesChanged();
+}
+
+void QAndroidCameraFocusControl::updateFocusZones(QCameraFocusZone::FocusZoneStatus status)
+{
+ if (!m_session->camera())
+ return;
+
+ // create a focus zone (50x50 pixel) around the focus point
+ m_focusZones.clear();
+
+ if (m_actualFocusPoint.isNull())
+ return;
+
+ QSize viewportSize = m_session->camera()->previewSize();
+ QSizeF focusSize(50.f / viewportSize.width(), 50.f / viewportSize.height());
+ float x = qBound(0.f,
+ m_actualFocusPoint.x() - (focusSize.width() / 2),
+ 1.f - focusSize.width());
+ float y = qBound(0.f,
+ m_actualFocusPoint.y() - (focusSize.height() / 2),
+ 1.f - focusSize.height());
+
+ QRectF area(QPointF(x, y), focusSize);
+
+ m_focusZones.append(QCameraFocusZone(area, status));
+
+ emit focusZonesChanged();
+}
+
+void QAndroidCameraFocusControl::setCameraFocusArea()
+{
+ QList<QRect> areas;
+ if (m_focusPointMode != QCameraFocus::FocusPointAuto) {
+ // in FocusPointAuto mode, leave the area list empty
+ // to let the driver choose the focus point.
+
+ for (int i = 0; i < m_focusZones.size(); ++i)
+ areas.append(adjustedArea(m_focusZones.at(i).area()));
+
+ }
+ m_session->camera()->setFocusAreas(areas);
+}
+
+void QAndroidCameraFocusControl::onViewportSizeChanged()
+{
+ QCameraFocusZone::FocusZoneStatus status = QCameraFocusZone::Selected;
+ if (!m_focusZones.isEmpty())
+ status = m_focusZones.at(0).status();
+ updateFocusZones(status);
+}
+
+void QAndroidCameraFocusControl::onCameraCaptureModeChanged()
+{
+ if (m_focusMode == QCameraFocus::ContinuousFocus) {
+ QString focusMode;
+ if ((m_session->captureMode().testFlag(QCamera::CaptureVideo) && m_continuousVideoFocusSupported)
+ || !m_continuousPictureFocusSupported) {
+ focusMode = QLatin1String("continuous-video");
+ } else {
+ focusMode = QLatin1String("continuous-picture");
+ }
+ m_session->camera()->setFocusMode(focusMode);
+ m_session->camera()->cancelAutoFocus();
+ }
+}
+
+void QAndroidCameraFocusControl::onAutoFocusStarted()
+{
+ updateFocusZones(QCameraFocusZone::Selected);
+}
+
+void QAndroidCameraFocusControl::onAutoFocusComplete(bool success)
+{
+ if (success)
+ updateFocusZones(QCameraFocusZone::Focused);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/android/src/mediacapture/qandroidcamerafocuscontrol.h b/src/plugins/android/src/mediacapture/qandroidcamerafocuscontrol.h
new file mode 100644
index 000000000..4311e78ba
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidcamerafocuscontrol.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANDROIDCAMERAFOCUSCONTROL_H
+#define QANDROIDCAMERAFOCUSCONTROL_H
+
+#include <qcamerafocuscontrol.h>
+
+QT_BEGIN_NAMESPACE
+
+class QAndroidCameraSession;
+
+class QAndroidCameraFocusControl : public QCameraFocusControl
+{
+ Q_OBJECT
+public:
+ explicit QAndroidCameraFocusControl(QAndroidCameraSession *session);
+
+ QCameraFocus::FocusModes focusMode() const Q_DECL_OVERRIDE;
+ void setFocusMode(QCameraFocus::FocusModes mode) Q_DECL_OVERRIDE;
+ bool isFocusModeSupported(QCameraFocus::FocusModes mode) const Q_DECL_OVERRIDE;
+ QCameraFocus::FocusPointMode focusPointMode() const Q_DECL_OVERRIDE;
+ void setFocusPointMode(QCameraFocus::FocusPointMode mode) Q_DECL_OVERRIDE;
+ bool isFocusPointModeSupported(QCameraFocus::FocusPointMode mode) const Q_DECL_OVERRIDE;
+ QPointF customFocusPoint() const Q_DECL_OVERRIDE;
+ void setCustomFocusPoint(const QPointF &point) Q_DECL_OVERRIDE;
+ QCameraFocusZoneList focusZones() const Q_DECL_OVERRIDE;
+
+private Q_SLOTS:
+ void onCameraOpened();
+ void onViewportSizeChanged();
+ void onCameraCaptureModeChanged();
+ void onAutoFocusStarted();
+ void onAutoFocusComplete(bool success);
+
+private:
+ void updateFocusZones(QCameraFocusZone::FocusZoneStatus status = QCameraFocusZone::Selected);
+ void setCameraFocusArea();
+
+ QAndroidCameraSession *m_session;
+
+ QCameraFocus::FocusModes m_focusMode;
+ QCameraFocus::FocusPointMode m_focusPointMode;
+ QPointF m_actualFocusPoint;
+ QPointF m_customFocusPoint;
+ QCameraFocusZoneList m_focusZones;
+
+ QList<QCameraFocus::FocusModes> m_supportedFocusModes;
+ bool m_continuousPictureFocusSupported;
+ bool m_continuousVideoFocusSupported;
+
+ QList<QCameraFocus::FocusPointMode> m_supportedFocusPointModes;
+};
+
+QT_END_NAMESPACE
+
+#endif // QANDROIDCAMERAFOCUSCONTROL_H
diff --git a/src/plugins/android/src/mediacapture/qandroidcameraimagecapturecontrol.cpp b/src/plugins/android/src/mediacapture/qandroidcameraimagecapturecontrol.cpp
new file mode 100644
index 000000000..3c04d292f
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidcameraimagecapturecontrol.cpp
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qandroidcameraimagecapturecontrol.h"
+
+#include "qandroidcamerasession.h"
+
+QT_BEGIN_NAMESPACE
+
+QAndroidCameraImageCaptureControl::QAndroidCameraImageCaptureControl(QAndroidCameraSession *session)
+ : QCameraImageCaptureControl()
+ , m_session(session)
+{
+ connect(m_session, SIGNAL(readyForCaptureChanged(bool)), this, SIGNAL(readyForCaptureChanged(bool)));
+ connect(m_session, SIGNAL(imageExposed(int)), this, SIGNAL(imageExposed(int)));
+ connect(m_session, SIGNAL(imageCaptured(int,QImage)), this, SIGNAL(imageCaptured(int,QImage)));
+ connect(m_session, SIGNAL(imageMetadataAvailable(int,QString,QVariant)), this, SIGNAL(imageMetadataAvailable(int,QString,QVariant)));
+ connect(m_session, SIGNAL(imageAvailable(int,QVideoFrame)), this, SIGNAL(imageAvailable(int,QVideoFrame)));
+ connect(m_session, SIGNAL(imageSaved(int,QString)), this, SIGNAL(imageSaved(int,QString)));
+ connect(m_session, SIGNAL(imageCaptureError(int,int,QString)), this, SIGNAL(error(int,int,QString)));
+}
+
+bool QAndroidCameraImageCaptureControl::isReadyForCapture() const
+{
+ return m_session->isReadyForCapture();
+}
+
+QCameraImageCapture::DriveMode QAndroidCameraImageCaptureControl::driveMode() const
+{
+ return m_session->driveMode();
+}
+
+void QAndroidCameraImageCaptureControl::setDriveMode(QCameraImageCapture::DriveMode mode)
+{
+ m_session->setDriveMode(mode);
+}
+
+int QAndroidCameraImageCaptureControl::capture(const QString &fileName)
+{
+ return m_session->capture(fileName);
+}
+
+void QAndroidCameraImageCaptureControl::cancelCapture()
+{
+ m_session->cancelCapture();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/android/src/mediacapture/qandroidcameraimagecapturecontrol.h b/src/plugins/android/src/mediacapture/qandroidcameraimagecapturecontrol.h
new file mode 100644
index 000000000..f69913b14
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidcameraimagecapturecontrol.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANDROIDCAMERAIMAGECAPTURECONTROL_H
+#define QANDROIDCAMERAIMAGECAPTURECONTROL_H
+
+#include <qcameraimagecapturecontrol.h>
+
+QT_BEGIN_NAMESPACE
+
+class QAndroidCameraSession;
+
+class QAndroidCameraImageCaptureControl : public QCameraImageCaptureControl
+{
+ Q_OBJECT
+public:
+ explicit QAndroidCameraImageCaptureControl(QAndroidCameraSession *session);
+
+ bool isReadyForCapture() const Q_DECL_OVERRIDE;
+
+ QCameraImageCapture::DriveMode driveMode() const Q_DECL_OVERRIDE;
+ void setDriveMode(QCameraImageCapture::DriveMode mode) Q_DECL_OVERRIDE;
+
+ int capture(const QString &fileName) Q_DECL_OVERRIDE;
+ void cancelCapture() Q_DECL_OVERRIDE;
+
+private:
+ QAndroidCameraSession *m_session;
+};
+
+QT_END_NAMESPACE
+
+#endif // QANDROIDCAMERAIMAGECAPTURECONTROL_H
diff --git a/src/plugins/android/src/mediacapture/qandroidcameraimageprocessingcontrol.cpp b/src/plugins/android/src/mediacapture/qandroidcameraimageprocessingcontrol.cpp
new file mode 100644
index 000000000..ec5a3bcbf
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidcameraimageprocessingcontrol.cpp
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qandroidcameraimageprocessingcontrol.h"
+
+#include "qandroidcamerasession.h"
+#include "jcamera.h"
+
+QT_BEGIN_NAMESPACE
+
+QAndroidCameraImageProcessingControl::QAndroidCameraImageProcessingControl(QAndroidCameraSession *session)
+ : QCameraImageProcessingControl()
+ , m_session(session)
+{
+ connect(m_session, SIGNAL(opened()),
+ this, SLOT(onCameraOpened()));
+}
+
+bool QAndroidCameraImageProcessingControl::isParameterSupported(ProcessingParameter parameter) const
+{
+ return (parameter == QCameraImageProcessingControl::WhiteBalancePreset);
+}
+
+bool QAndroidCameraImageProcessingControl::isParameterValueSupported(ProcessingParameter parameter,
+ const QVariant &value) const
+{
+ if (parameter != QCameraImageProcessingControl::WhiteBalancePreset)
+ return false;
+
+ if (!m_session->camera())
+ return false;
+
+ return m_supportedWhiteBalanceModes.contains(value.value<QCameraImageProcessing::WhiteBalanceMode>());
+}
+
+QVariant QAndroidCameraImageProcessingControl::parameter(ProcessingParameter parameter) const
+{
+ if (parameter != QCameraImageProcessingControl::WhiteBalancePreset)
+ return QVariant();
+
+ if (!m_session->camera())
+ return QVariant();
+
+ QString wb = m_session->camera()->getWhiteBalance();
+ QCameraImageProcessing::WhiteBalanceMode mode = m_supportedWhiteBalanceModes.key(wb, QCameraImageProcessing::WhiteBalanceAuto);
+
+ return QVariant::fromValue(mode);
+}
+
+void QAndroidCameraImageProcessingControl::setParameter(ProcessingParameter parameter, const QVariant &value)
+{
+ if (parameter != QCameraImageProcessingControl::WhiteBalancePreset)
+ return;
+
+ if (!m_session->camera())
+ return;
+
+ QString wb = m_supportedWhiteBalanceModes.value(value.value<QCameraImageProcessing::WhiteBalanceMode>(), QString());
+ if (!wb.isEmpty())
+ m_session->camera()->setWhiteBalance(wb);
+}
+
+void QAndroidCameraImageProcessingControl::onCameraOpened()
+{
+ m_supportedWhiteBalanceModes.clear();
+ QStringList whiteBalanceModes = m_session->camera()->getSupportedWhiteBalance();
+ for (int i = 0; i < whiteBalanceModes.size(); ++i) {
+ const QString &wb = whiteBalanceModes.at(i);
+ if (wb == QLatin1String("auto")) {
+ m_supportedWhiteBalanceModes.insert(QCameraImageProcessing::WhiteBalanceAuto,
+ QStringLiteral("auto"));
+ } else if (wb == QLatin1String("cloudy-daylight")) {
+ m_supportedWhiteBalanceModes.insert(QCameraImageProcessing::WhiteBalanceCloudy,
+ QStringLiteral("cloudy-daylight"));
+ } else if (wb == QLatin1String("daylight")) {
+ m_supportedWhiteBalanceModes.insert(QCameraImageProcessing::WhiteBalanceSunlight,
+ QStringLiteral("daylight"));
+ } else if (wb == QLatin1String("fluorescent")) {
+ m_supportedWhiteBalanceModes.insert(QCameraImageProcessing::WhiteBalanceFluorescent,
+ QStringLiteral("fluorescent"));
+ } else if (wb == QLatin1String("incandescent")) {
+ m_supportedWhiteBalanceModes.insert(QCameraImageProcessing::WhiteBalanceTungsten,
+ QStringLiteral("incandescent"));
+ } else if (wb == QLatin1String("shade")) {
+ m_supportedWhiteBalanceModes.insert(QCameraImageProcessing::WhiteBalanceShade,
+ QStringLiteral("shade"));
+ } else if (wb == QLatin1String("twilight")) {
+ m_supportedWhiteBalanceModes.insert(QCameraImageProcessing::WhiteBalanceSunset,
+ QStringLiteral("twilight"));
+ } else if (wb == QLatin1String("warm-fluorescent")) {
+ m_supportedWhiteBalanceModes.insert(QCameraImageProcessing::WhiteBalanceFlash,
+ QStringLiteral("warm-fluorescent"));
+ }
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/android/src/mediacapture/qandroidcameraimageprocessingcontrol.h b/src/plugins/android/src/mediacapture/qandroidcameraimageprocessingcontrol.h
new file mode 100644
index 000000000..3ef3c3144
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidcameraimageprocessingcontrol.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANDROIDCAMERAIMAGEPROCESSINGCONTROL_H
+#define QANDROIDCAMERAIMAGEPROCESSINGCONTROL_H
+
+#include <qcameraimageprocessingcontrol.h>
+
+QT_BEGIN_NAMESPACE
+
+class QAndroidCameraSession;
+
+class QAndroidCameraImageProcessingControl : public QCameraImageProcessingControl
+{
+ Q_OBJECT
+public:
+ explicit QAndroidCameraImageProcessingControl(QAndroidCameraSession *session);
+
+ bool isParameterSupported(ProcessingParameter) const Q_DECL_OVERRIDE;
+ bool isParameterValueSupported(ProcessingParameter parameter, const QVariant &value) const Q_DECL_OVERRIDE;
+ QVariant parameter(ProcessingParameter parameter) const Q_DECL_OVERRIDE;
+ void setParameter(ProcessingParameter parameter, const QVariant &value) Q_DECL_OVERRIDE;
+
+private Q_SLOTS:
+ void onCameraOpened();
+
+private:
+ QAndroidCameraSession *m_session;
+
+ QHash<QCameraImageProcessing::WhiteBalanceMode, QString> m_supportedWhiteBalanceModes;
+};
+
+QT_END_NAMESPACE
+
+#endif // QANDROIDCAMERAIMAGEPROCESSINGCONTROL_H
diff --git a/src/plugins/android/src/mediacapture/qandroidcameralockscontrol.cpp b/src/plugins/android/src/mediacapture/qandroidcameralockscontrol.cpp
new file mode 100644
index 000000000..d9f20ec04
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidcameralockscontrol.cpp
@@ -0,0 +1,254 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qandroidcameralockscontrol.h"
+
+#include "qandroidcamerasession.h"
+#include "jcamera.h"
+#include <qtimer.h>
+
+QT_BEGIN_NAMESPACE
+
+QAndroidCameraLocksControl::QAndroidCameraLocksControl(QAndroidCameraSession *session)
+ : QCameraLocksControl()
+ , m_session(session)
+ , m_supportedLocks(QCamera::NoLock)
+ , m_focusLockStatus(QCamera::Unlocked)
+ , m_exposureLockStatus(QCamera::Unlocked)
+ , m_whiteBalanceLockStatus(QCamera::Unlocked)
+{
+ connect(m_session, SIGNAL(opened()),
+ this, SLOT(onCameraOpened()));
+
+ m_recalculateTimer = new QTimer(this);
+ m_recalculateTimer->setInterval(1000);
+ m_recalculateTimer->setSingleShot(true);
+ connect(m_recalculateTimer, SIGNAL(timeout()), this, SLOT(onRecalculateTimeOut()));
+}
+
+QCamera::LockTypes QAndroidCameraLocksControl::supportedLocks() const
+{
+ return (QCamera::LockExposure | QCamera::LockWhiteBalance | QCamera::LockFocus);
+}
+
+QCamera::LockStatus QAndroidCameraLocksControl::lockStatus(QCamera::LockType lock) const
+{
+ if (!m_supportedLocks.testFlag(lock) || !m_session->camera())
+ return QCamera::Locked;
+
+ if (lock == QCamera::LockFocus)
+ return m_focusLockStatus;
+
+ if (lock == QCamera::LockExposure)
+ return m_exposureLockStatus;
+
+ if (lock == QCamera::LockWhiteBalance)
+ return m_whiteBalanceLockStatus;
+
+ return QCamera::Locked;
+}
+
+void QAndroidCameraLocksControl::searchAndLock(QCamera::LockTypes locks)
+{
+ if (!m_session->camera())
+ return;
+
+ // filter out unsupported locks
+ locks &= m_supportedLocks;
+
+ if (locks.testFlag(QCamera::LockFocus)) {
+ QString focusMode = m_session->camera()->getFocusMode();
+ if (focusMode == QLatin1String("auto")
+ || focusMode == QLatin1String("macro")
+ || focusMode == QLatin1String("continuous-picture")
+ || focusMode == QLatin1String("continuous-video")) {
+
+ if (m_focusLockStatus == QCamera::Searching)
+ m_session->camera()->cancelAutoFocus();
+ else
+ setFocusLockStatus(QCamera::Searching, QCamera::UserRequest);
+
+ m_session->camera()->autoFocus();
+
+ } else {
+ setFocusLockStatus(QCamera::Locked, QCamera::LockAcquired);
+ }
+ }
+
+ if (locks.testFlag(QCamera::LockExposure) && m_exposureLockStatus != QCamera::Searching) {
+ if (m_session->camera()->getAutoExposureLock()) {
+ // if already locked, unlock and give some time to recalculate exposure
+ m_session->camera()->setAutoExposureLock(false);
+ setExposureLockStatus(QCamera::Searching, QCamera::UserRequest);
+ } else {
+ m_session->camera()->setAutoExposureLock(true);
+ setExposureLockStatus(QCamera::Locked, QCamera::LockAcquired);
+ }
+ }
+
+ if (locks.testFlag(QCamera::LockWhiteBalance) && m_whiteBalanceLockStatus != QCamera::Searching) {
+ if (m_session->camera()->getAutoWhiteBalanceLock()) {
+ // if already locked, unlock and give some time to recalculate white balance
+ m_session->camera()->setAutoWhiteBalanceLock(false);
+ setWhiteBalanceLockStatus(QCamera::Searching, QCamera::UserRequest);
+ } else {
+ m_session->camera()->setAutoWhiteBalanceLock(true);
+ setWhiteBalanceLockStatus(QCamera::Locked, QCamera::LockAcquired);
+ }
+ }
+
+ if (m_exposureLockStatus == QCamera::Searching || m_whiteBalanceLockStatus == QCamera::Searching)
+ m_recalculateTimer->start();
+}
+
+void QAndroidCameraLocksControl::unlock(QCamera::LockTypes locks)
+{
+ if (!m_session->camera())
+ return;
+
+ if (m_recalculateTimer->isActive())
+ m_recalculateTimer->stop();
+
+ // filter out unsupported locks
+ locks &= m_supportedLocks;
+
+ if (locks.testFlag(QCamera::LockFocus)) {
+ m_session->camera()->cancelAutoFocus();
+ setFocusLockStatus(QCamera::Unlocked, QCamera::UserRequest);
+ }
+
+ if (locks.testFlag(QCamera::LockExposure)) {
+ m_session->camera()->setAutoExposureLock(false);
+ setExposureLockStatus(QCamera::Unlocked, QCamera::UserRequest);
+ }
+
+ if (locks.testFlag(QCamera::LockWhiteBalance)) {
+ m_session->camera()->setAutoWhiteBalanceLock(false);
+ setWhiteBalanceLockStatus(QCamera::Unlocked, QCamera::UserRequest);
+ }
+}
+
+void QAndroidCameraLocksControl::onCameraOpened()
+{
+ m_supportedLocks = QCamera::NoLock;
+ m_focusLockStatus = QCamera::Unlocked;
+ m_exposureLockStatus = QCamera::Unlocked;
+ m_whiteBalanceLockStatus = QCamera::Unlocked;
+
+ // check if focus lock is supported
+ QStringList focusModes = m_session->camera()->getSupportedFocusModes();
+ for (int i = 0; i < focusModes.size(); ++i) {
+ const QString &focusMode = focusModes.at(i);
+ if (focusMode == QLatin1String("auto")
+ || focusMode == QLatin1String("continuous-picture")
+ || focusMode == QLatin1String("continuous-video")
+ || focusMode == QLatin1String("macro")) {
+
+ m_supportedLocks |= QCamera::LockFocus;
+ setFocusLockStatus(QCamera::Unlocked, QCamera::UserRequest);
+
+ connect(m_session->camera(), SIGNAL(autoFocusComplete(bool)),
+ this, SLOT(onCameraAutoFocusComplete(bool)));
+
+ break;
+ }
+ }
+
+ if (m_session->camera()->isAutoExposureLockSupported()) {
+ m_supportedLocks |= QCamera::LockExposure;
+ setExposureLockStatus(QCamera::Unlocked, QCamera::UserRequest);
+ }
+
+ if (m_session->camera()->isAutoWhiteBalanceLockSupported()) {
+ m_supportedLocks |= QCamera::LockWhiteBalance;
+ setWhiteBalanceLockStatus(QCamera::Unlocked, QCamera::UserRequest);
+
+ connect(m_session->camera(), SIGNAL(whiteBalanceChanged()),
+ this, SLOT(onWhiteBalanceChanged()));
+ }
+}
+
+void QAndroidCameraLocksControl::onCameraAutoFocusComplete(bool success)
+{
+ m_focusLockStatus = success ? QCamera::Locked : QCamera::Unlocked;
+ QCamera::LockChangeReason reason = success ? QCamera::LockAcquired : QCamera::LockFailed;
+ emit lockStatusChanged(QCamera::LockFocus, m_focusLockStatus, reason);
+}
+
+void QAndroidCameraLocksControl::onRecalculateTimeOut()
+{
+ if (m_exposureLockStatus == QCamera::Searching) {
+ m_session->camera()->setAutoExposureLock(true);
+ setExposureLockStatus(QCamera::Locked, QCamera::LockAcquired);
+ }
+
+ if (m_whiteBalanceLockStatus == QCamera::Searching) {
+ m_session->camera()->setAutoWhiteBalanceLock(true);
+ setWhiteBalanceLockStatus(QCamera::Locked, QCamera::LockAcquired);
+ }
+}
+
+void QAndroidCameraLocksControl::onWhiteBalanceChanged()
+{
+ // changing the white balance mode releases the white balance lock
+ if (m_whiteBalanceLockStatus != QCamera::Unlocked)
+ setWhiteBalanceLockStatus(QCamera::Unlocked, QCamera::LockLost);
+}
+
+void QAndroidCameraLocksControl::setFocusLockStatus(QCamera::LockStatus status, QCamera::LockChangeReason reason)
+{
+ m_focusLockStatus = status;
+ emit lockStatusChanged(QCamera::LockFocus, m_focusLockStatus, reason);
+}
+
+void QAndroidCameraLocksControl::setWhiteBalanceLockStatus(QCamera::LockStatus status, QCamera::LockChangeReason reason)
+{
+ m_whiteBalanceLockStatus = status;
+ emit lockStatusChanged(QCamera::LockWhiteBalance, m_whiteBalanceLockStatus, reason);
+}
+
+void QAndroidCameraLocksControl::setExposureLockStatus(QCamera::LockStatus status, QCamera::LockChangeReason reason)
+{
+ m_exposureLockStatus = status;
+ emit lockStatusChanged(QCamera::LockExposure, m_exposureLockStatus, reason);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/android/src/mediacapture/qandroidcameralockscontrol.h b/src/plugins/android/src/mediacapture/qandroidcameralockscontrol.h
new file mode 100644
index 000000000..d49821bff
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidcameralockscontrol.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANDROIDCAMERALOCKSCONTROL_H
+#define QANDROIDCAMERALOCKSCONTROL_H
+
+#include <qcameralockscontrol.h>
+
+QT_BEGIN_NAMESPACE
+
+class QAndroidCameraSession;
+class QTimer;
+
+class QAndroidCameraLocksControl : public QCameraLocksControl
+{
+ Q_OBJECT
+public:
+ explicit QAndroidCameraLocksControl(QAndroidCameraSession *session);
+
+ QCamera::LockTypes supportedLocks() const Q_DECL_OVERRIDE;
+ QCamera::LockStatus lockStatus(QCamera::LockType lock) const Q_DECL_OVERRIDE;
+ void searchAndLock(QCamera::LockTypes locks) Q_DECL_OVERRIDE;
+ void unlock(QCamera::LockTypes locks) Q_DECL_OVERRIDE;
+
+private Q_SLOTS:
+ void onCameraOpened();
+ void onCameraAutoFocusComplete(bool success);
+ void onRecalculateTimeOut();
+ void onWhiteBalanceChanged();
+
+private:
+ void setFocusLockStatus(QCamera::LockStatus status, QCamera::LockChangeReason reason);
+ void setWhiteBalanceLockStatus(QCamera::LockStatus status, QCamera::LockChangeReason reason);
+ void setExposureLockStatus(QCamera::LockStatus status, QCamera::LockChangeReason reason);
+
+ QAndroidCameraSession *m_session;
+
+ QTimer *m_recalculateTimer;
+
+ QCamera::LockTypes m_supportedLocks;
+
+ QCamera::LockStatus m_focusLockStatus;
+ QCamera::LockStatus m_exposureLockStatus;
+ QCamera::LockStatus m_whiteBalanceLockStatus;
+};
+
+QT_END_NAMESPACE
+
+#endif // QANDROIDCAMERALOCKSCONTROL_H
diff --git a/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp b/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp
new file mode 100644
index 000000000..761b716d1
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp
@@ -0,0 +1,553 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qandroidcamerasession.h"
+
+#include "jcamera.h"
+#include "jmultimediautils.h"
+#include "qandroidvideooutput.h"
+#include "qandroidmultimediautils.h"
+#include <QtConcurrent/qtconcurrentrun.h>
+#include <qfile.h>
+#include <qguiapplication.h>
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+static void textureReadyCallback(void *context)
+{
+ if (context)
+ reinterpret_cast<QAndroidCameraSession *>(context)->onSurfaceTextureReady();
+}
+
+QAndroidCameraSession::QAndroidCameraSession(QObject *parent)
+ : QObject(parent)
+ , m_selectedCamera(0)
+ , m_camera(0)
+ , m_nativeOrientation(0)
+ , m_videoOutput(0)
+ , m_captureMode(QCamera::CaptureViewfinder)
+ , m_state(QCamera::UnloadedState)
+ , m_savedState(-1)
+ , m_status(QCamera::UnloadedStatus)
+ , m_previewStarted(false)
+ , m_imageSettingsDirty(true)
+ , m_captureDestination(QCameraImageCapture::CaptureToFile)
+ , m_captureImageDriveMode(QCameraImageCapture::SingleImageCapture)
+ , m_lastImageCaptureId(0)
+ , m_readyForCapture(false)
+ , m_captureCanceled(false)
+ , m_currentImageCaptureId(-1)
+{
+ if (qApp) {
+ connect(qApp, SIGNAL(applicationStateChanged(Qt::ApplicationState)),
+ this, SLOT(onApplicationStateChanged(Qt::ApplicationState)));
+ }
+}
+
+QAndroidCameraSession::~QAndroidCameraSession()
+{
+ close();
+}
+
+void QAndroidCameraSession::setCaptureMode(QCamera::CaptureModes mode)
+{
+ if (m_captureMode == mode || !isCaptureModeSupported(mode))
+ return;
+
+ m_captureMode = mode;
+ emit captureModeChanged(m_captureMode);
+
+ if (m_previewStarted && m_captureMode.testFlag(QCamera::CaptureStillImage))
+ adjustViewfinderSize(m_imageSettings.resolution());
+}
+
+bool QAndroidCameraSession::isCaptureModeSupported(QCamera::CaptureModes mode) const
+{
+ if (mode & (QCamera::CaptureStillImage & QCamera::CaptureVideo))
+ return false;
+
+ return true;
+}
+
+void QAndroidCameraSession::setState(QCamera::State state)
+{
+ // If the application is inactive, the camera shouldn't be started. Save the desired state
+ // instead and it will be set when the application becomes active.
+ if (qApp->applicationState() != Qt::ApplicationActive) {
+ m_savedState = state;
+ return;
+ }
+
+ if (m_state == state)
+ return;
+
+ switch (state) {
+ case QCamera::UnloadedState:
+ close();
+ break;
+ case QCamera::LoadedState:
+ case QCamera::ActiveState:
+ if (!m_camera && !open()) {
+ emit error(QCamera::CameraError, QStringLiteral("Failed to open camera"));
+ return;
+ }
+ if (state == QCamera::ActiveState)
+ startPreview();
+ else if (state == QCamera::LoadedState)
+ stopPreview();
+ break;
+ }
+
+ m_state = state;
+ emit stateChanged(m_state);
+}
+
+bool QAndroidCameraSession::open()
+{
+ close();
+
+ m_status = QCamera::LoadingStatus;
+ emit statusChanged(m_status);
+
+ m_camera = JCamera::open(m_selectedCamera);
+
+ if (m_camera) {
+ connect(m_camera, SIGNAL(pictureExposed()), this, SLOT(onCameraPictureExposed()));
+ connect(m_camera, SIGNAL(pictureCaptured(QByteArray)), this, SLOT(onCameraPictureCaptured(QByteArray)));
+ m_nativeOrientation = m_camera->getNativeOrientation();
+ m_status = QCamera::LoadedStatus;
+ emit opened();
+ } else {
+ m_status = QCamera::UnavailableStatus;
+ }
+
+ emit statusChanged(m_status);
+
+ return m_camera != 0;
+}
+
+void QAndroidCameraSession::close()
+{
+ if (!m_camera)
+ return;
+
+ stopPreview();
+
+ m_status = QCamera::UnloadingStatus;
+ emit statusChanged(m_status);
+
+ m_readyForCapture = false;
+ m_currentImageCaptureId = -1;
+ m_currentImageCaptureFileName.clear();
+ m_imageSettingsDirty = true;
+
+ m_camera->release();
+ delete m_camera;
+ m_camera = 0;
+
+ m_status = QCamera::UnloadedStatus;
+ emit statusChanged(m_status);
+}
+
+void QAndroidCameraSession::setVideoPreview(QAndroidVideoOutput *videoOutput)
+{
+ if (m_videoOutput)
+ m_videoOutput->stop();
+
+ m_videoOutput = videoOutput;
+}
+
+void QAndroidCameraSession::adjustViewfinderSize(const QSize &captureSize, bool restartPreview)
+{
+ if (!m_camera)
+ return;
+
+ QSize viewfinderResolution = m_camera->previewSize();
+ const qreal aspectRatio = qreal(captureSize.width()) / qreal(captureSize.height());
+ if (qFuzzyCompare(aspectRatio, qreal(viewfinderResolution.width()) / qreal(viewfinderResolution.height())))
+ return;
+
+ QList<QSize> previewSizes = m_camera->getSupportedPreviewSizes();
+ for (int i = previewSizes.count() - 1; i >= 0; --i) {
+ const QSize &size = previewSizes.at(i);
+ // search for viewfinder resolution with the same aspect ratio
+ if (qFuzzyCompare(aspectRatio, (static_cast<qreal>(size.width())/static_cast<qreal>(size.height())))) {
+ viewfinderResolution = size;
+ break;
+ }
+ }
+
+ if (m_camera->previewSize() != viewfinderResolution) {
+ if (m_videoOutput)
+ m_videoOutput->setVideoSize(viewfinderResolution);
+
+ // if preview is started, we have to stop it first before changing its size
+ if (m_previewStarted && restartPreview)
+ m_camera->stopPreview();
+
+ m_camera->setPreviewSize(viewfinderResolution);
+
+ // restart preview
+ if (m_previewStarted && restartPreview)
+ m_camera->startPreview();
+ }
+}
+
+void QAndroidCameraSession::startPreview()
+{
+ if (!m_camera || m_previewStarted)
+ return;
+
+ m_status = QCamera::StartingStatus;
+ emit statusChanged(m_status);
+
+ applyImageSettings();
+ adjustViewfinderSize(m_imageSettings.resolution());
+
+ if (m_videoOutput) {
+ if (m_videoOutput->isTextureReady())
+ m_camera->setPreviewTexture(m_videoOutput->surfaceTexture());
+ else
+ m_videoOutput->setTextureReadyCallback(textureReadyCallback, this);
+ }
+
+ JMultimediaUtils::enableOrientationListener(true);
+
+ m_camera->startPreview();
+ m_previewStarted = true;
+
+ m_status = QCamera::ActiveStatus;
+ emit statusChanged(m_status);
+
+ setReadyForCapture(true);
+}
+
+void QAndroidCameraSession::stopPreview()
+{
+ if (!m_camera || !m_previewStarted)
+ return;
+
+ m_status = QCamera::StoppingStatus;
+ emit statusChanged(m_status);
+
+ JMultimediaUtils::enableOrientationListener(false);
+
+ m_camera->stopPreview();
+ if (m_videoOutput)
+ m_videoOutput->stop();
+ m_previewStarted = false;
+
+ m_status = QCamera::LoadedStatus;
+ emit statusChanged(m_status);
+
+ setReadyForCapture(false);
+}
+
+void QAndroidCameraSession::setImageSettings(const QImageEncoderSettings &settings)
+{
+ if (m_imageSettings == settings)
+ return;
+
+ m_imageSettings = settings;
+ if (m_imageSettings.codec().isEmpty())
+ m_imageSettings.setCodec(QLatin1String("jpeg"));
+
+ m_imageSettingsDirty = true;
+
+ applyImageSettings();
+
+ if (m_readyForCapture && m_captureMode.testFlag(QCamera::CaptureStillImage))
+ adjustViewfinderSize(m_imageSettings.resolution());
+}
+
+int QAndroidCameraSession::currentCameraRotation() const
+{
+ if (!m_camera)
+ return 0;
+
+ // subtract natural camera orientation and physical device orientation
+ int rotation = 0;
+ int deviceOrientation = (JMultimediaUtils::getDeviceOrientation() + 45) / 90 * 90;
+ if (m_camera->getFacing() == JCamera::CameraFacingFront)
+ rotation = (m_nativeOrientation - deviceOrientation + 360) % 360;
+ else // back-facing camera
+ rotation = (m_nativeOrientation + deviceOrientation) % 360;
+
+ return rotation;
+}
+
+void QAndroidCameraSession::applyImageSettings()
+{
+ if (!m_camera || !m_imageSettingsDirty)
+ return;
+
+ const QSize requestedResolution = m_imageSettings.resolution();
+ const QList<QSize> supportedResolutions = m_camera->getSupportedPictureSizes();
+
+ if (!requestedResolution.isValid()) {
+ // if no resolution is set, use the highest supported one
+ m_imageSettings.setResolution(supportedResolutions.last());
+ } else if (!supportedResolutions.contains(requestedResolution)) {
+ // if the requested resolution is not supported, find the closest one
+ int reqPixelCount = requestedResolution.width() * requestedResolution.height();
+ QList<int> supportedPixelCounts;
+ for (int i = 0; i < supportedResolutions.size(); ++i) {
+ const QSize &s = supportedResolutions.at(i);
+ supportedPixelCounts.append(s.width() * s.height());
+ }
+ int closestIndex = qt_findClosestValue(supportedPixelCounts, reqPixelCount);
+ m_imageSettings.setResolution(supportedResolutions.at(closestIndex));
+ }
+
+ int jpegQuality = 100;
+ switch (m_imageSettings.quality()) {
+ case QMultimedia::VeryLowQuality:
+ jpegQuality = 20;
+ break;
+ case QMultimedia::LowQuality:
+ jpegQuality = 40;
+ break;
+ case QMultimedia::NormalQuality:
+ jpegQuality = 60;
+ break;
+ case QMultimedia::HighQuality:
+ jpegQuality = 80;
+ break;
+ case QMultimedia::VeryHighQuality:
+ jpegQuality = 100;
+ break;
+ }
+
+ m_camera->setPictureSize(m_imageSettings.resolution());
+ m_camera->setJpegQuality(jpegQuality);
+
+ m_imageSettingsDirty = false;
+}
+
+bool QAndroidCameraSession::isCaptureDestinationSupported(QCameraImageCapture::CaptureDestinations destination) const
+{
+ return destination & (QCameraImageCapture::CaptureToFile | QCameraImageCapture::CaptureToBuffer);
+}
+
+QCameraImageCapture::CaptureDestinations QAndroidCameraSession::captureDestination() const
+{
+ return m_captureDestination;
+}
+
+void QAndroidCameraSession::setCaptureDestination(QCameraImageCapture::CaptureDestinations destination)
+{
+ if (m_captureDestination != destination) {
+ m_captureDestination = destination;
+ emit captureDestinationChanged(m_captureDestination);
+ }
+}
+
+bool QAndroidCameraSession::isReadyForCapture() const
+{
+ return m_status == QCamera::ActiveStatus && m_readyForCapture;
+}
+
+void QAndroidCameraSession::setReadyForCapture(bool ready)
+{
+ if (m_readyForCapture == ready)
+ return;
+
+ m_readyForCapture = ready;
+ emit readyForCaptureChanged(ready);
+}
+
+QCameraImageCapture::DriveMode QAndroidCameraSession::driveMode() const
+{
+ return m_captureImageDriveMode;
+}
+
+void QAndroidCameraSession::setDriveMode(QCameraImageCapture::DriveMode mode)
+{
+ m_captureImageDriveMode = mode;
+}
+
+int QAndroidCameraSession::capture(const QString &fileName)
+{
+ ++m_lastImageCaptureId;
+
+ if (!isReadyForCapture()) {
+ emit imageCaptureError(m_lastImageCaptureId, QCameraImageCapture::NotReadyError,
+ tr("Camera not ready"));
+ return m_lastImageCaptureId;
+ }
+
+ if (m_captureImageDriveMode == QCameraImageCapture::SingleImageCapture) {
+ setReadyForCapture(false);
+
+ m_currentImageCaptureId = m_lastImageCaptureId;
+ m_currentImageCaptureFileName = fileName;
+
+ applyImageSettings();
+ adjustViewfinderSize(m_imageSettings.resolution());
+
+ // adjust picture rotation depending on the device orientation
+ m_camera->setRotation(currentCameraRotation());
+
+ m_camera->takePicture();
+ } else {
+ emit imageCaptureError(m_lastImageCaptureId, QCameraImageCapture::NotSupportedFeatureError,
+ tr("Drive mode not supported"));
+ }
+
+ return m_lastImageCaptureId;
+}
+
+void QAndroidCameraSession::cancelCapture()
+{
+ if (m_readyForCapture)
+ return;
+
+ m_captureCanceled = true;
+}
+
+void QAndroidCameraSession::onCameraPictureExposed()
+{
+ if (m_captureCanceled)
+ return;
+
+ emit imageExposed(m_currentImageCaptureId);
+}
+
+void QAndroidCameraSession::onCameraPictureCaptured(const QByteArray &data)
+{
+ if (!m_captureCanceled) {
+ // generate a preview from the viewport
+ if (m_videoOutput)
+ emit imageCaptured(m_currentImageCaptureId, m_videoOutput->toImage());
+
+ // Loading and saving the captured image can be slow, do it in a separate thread
+ QtConcurrent::run(this, &QAndroidCameraSession::processCapturedImage,
+ m_currentImageCaptureId,
+ data,
+ m_captureDestination,
+ m_currentImageCaptureFileName);
+ }
+
+ m_captureCanceled = false;
+
+ // Preview needs to be restarted after taking a picture
+ m_camera->startPreview();
+
+ setReadyForCapture(true);
+}
+
+void QAndroidCameraSession::processCapturedImage(int id,
+ const QByteArray &data,
+ QCameraImageCapture::CaptureDestinations dest,
+ const QString &fileName)
+{
+
+
+ if (dest & QCameraImageCapture::CaptureToFile) {
+ const QString actualFileName = m_mediaStorageLocation.generateFileName(fileName,
+ QAndroidMediaStorageLocation::Camera,
+ QLatin1String("IMG_"),
+ QLatin1String("jpg"));
+
+ QFile file(actualFileName);
+ if (file.open(QFile::WriteOnly)) {
+ if (file.write(data) == data.size()) {
+ // if the picture is saved into the standard picture location, register it
+ // with the Android media scanner so it appears immediately in apps
+ // such as the gallery.
+ QString standardLoc = JMultimediaUtils::getDefaultMediaDirectory(JMultimediaUtils::DCIM);
+ if (actualFileName.startsWith(standardLoc))
+ JMultimediaUtils::registerMediaFile(actualFileName);
+
+ emit imageSaved(id, actualFileName);
+ } else {
+ emit imageCaptureError(id, QCameraImageCapture::OutOfSpaceError, file.errorString());
+ }
+ } else {
+ const QString errorMessage = tr("Could not open destination file: %1").arg(actualFileName);
+ emit imageCaptureError(id, QCameraImageCapture::ResourceError, errorMessage);
+ }
+ }
+
+ if (dest & QCameraImageCapture::CaptureToBuffer) {
+ QImage image;
+ const bool ok = image.loadFromData(data, "JPG");
+
+ if (ok) {
+ QVideoFrame frame(image);
+ emit imageAvailable(id, frame);
+ } else {
+ emit imageCaptureError(id, QCameraImageCapture::FormatError,
+ tr("Could not load JPEG data from captured image"));
+ }
+ }
+}
+
+void QAndroidCameraSession::onSurfaceTextureReady()
+{
+ if (m_camera && m_videoOutput)
+ m_camera->setPreviewTexture(m_videoOutput->surfaceTexture());
+}
+
+void QAndroidCameraSession::onApplicationStateChanged(Qt::ApplicationState state)
+{
+ switch (state) {
+ case Qt::ApplicationInactive:
+ if (m_state != QCamera::UnloadedState) {
+ m_savedState = m_state;
+ close();
+ m_state = QCamera::UnloadedState;
+ emit stateChanged(m_state);
+ }
+ break;
+ case Qt::ApplicationActive:
+ if (m_savedState != -1) {
+ setState(QCamera::State(m_savedState));
+ m_savedState = -1;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/android/src/mediacapture/qandroidcamerasession.h b/src/plugins/android/src/mediacapture/qandroidcamerasession.h
new file mode 100644
index 000000000..f1cf44eec
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidcamerasession.h
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANDROIDCAMERASESSION_H
+#define QANDROIDCAMERASESSION_H
+
+#include <qcamera.h>
+#include <qmediaencodersettings.h>
+#include <QCameraImageCapture>
+#include "qandroidmediastoragelocation.h"
+
+QT_BEGIN_NAMESPACE
+
+class JCamera;
+class QAndroidVideoOutput;
+
+class QAndroidCameraSession : public QObject
+{
+ Q_OBJECT
+public:
+ explicit QAndroidCameraSession(QObject *parent = 0);
+ ~QAndroidCameraSession();
+
+ void setSelectedCamera(int cameraId) { m_selectedCamera = cameraId; }
+ JCamera *camera() const { return m_camera; }
+
+ QCamera::State state() const { return m_state; }
+ void setState(QCamera::State state);
+
+ QCamera::Status status() const { return m_status; }
+
+ QCamera::CaptureModes captureMode() const { return m_captureMode; }
+ void setCaptureMode(QCamera::CaptureModes mode);
+ bool isCaptureModeSupported(QCamera::CaptureModes mode) const;
+
+ void setVideoPreview(QAndroidVideoOutput *videoOutput);
+ void adjustViewfinderSize(const QSize &captureSize, bool restartPreview = true);
+
+ QImageEncoderSettings imageSettings() const { return m_imageSettings; }
+ void setImageSettings(const QImageEncoderSettings &settings);
+
+ bool isCaptureDestinationSupported(QCameraImageCapture::CaptureDestinations destination) const;
+ QCameraImageCapture::CaptureDestinations captureDestination() const;
+ void setCaptureDestination(QCameraImageCapture::CaptureDestinations destination);
+
+ bool isReadyForCapture() const;
+ void setReadyForCapture(bool ready);
+ QCameraImageCapture::DriveMode driveMode() const;
+ void setDriveMode(QCameraImageCapture::DriveMode mode);
+ int capture(const QString &fileName);
+ void cancelCapture();
+
+ void onSurfaceTextureReady();
+
+ int currentCameraRotation() const;
+
+Q_SIGNALS:
+ void statusChanged(QCamera::Status status);
+ void stateChanged(QCamera::State);
+ void error(int error, const QString &errorString);
+ void captureModeChanged(QCamera::CaptureModes);
+ void opened();
+
+ void captureDestinationChanged(QCameraImageCapture::CaptureDestinations destination);
+
+ void readyForCaptureChanged(bool);
+ void imageExposed(int id);
+ void imageCaptured(int id, const QImage &preview);
+ void imageMetadataAvailable(int id, const QString &key, const QVariant &value);
+ void imageAvailable(int id, const QVideoFrame &buffer);
+ void imageSaved(int id, const QString &fileName);
+ void imageCaptureError(int id, int error, const QString &errorString);
+
+private Q_SLOTS:
+ void onApplicationStateChanged(Qt::ApplicationState state);
+
+ void onCameraPictureExposed();
+ void onCameraPictureCaptured(const QByteArray &data);
+
+private:
+ bool open();
+ void close();
+
+ void startPreview();
+ void stopPreview();
+
+ void applyImageSettings();
+ void processPreviewImage(int id);
+ void processCapturedImage(int id,
+ const QByteArray &data,
+ QCameraImageCapture::CaptureDestinations dest,
+ const QString &fileName);
+
+ int m_selectedCamera;
+ JCamera *m_camera;
+ int m_nativeOrientation;
+ QAndroidVideoOutput *m_videoOutput;
+
+ QCamera::CaptureModes m_captureMode;
+ QCamera::State m_state;
+ int m_savedState;
+ QCamera::Status m_status;
+ bool m_previewStarted;
+
+ QImageEncoderSettings m_imageSettings;
+ bool m_imageSettingsDirty;
+ QCameraImageCapture::CaptureDestinations m_captureDestination;
+ QCameraImageCapture::DriveMode m_captureImageDriveMode;
+ int m_lastImageCaptureId;
+ bool m_readyForCapture;
+ bool m_captureCanceled;
+ int m_currentImageCaptureId;
+ QString m_currentImageCaptureFileName;
+
+ QAndroidMediaStorageLocation m_mediaStorageLocation;
+};
+
+QT_END_NAMESPACE
+
+#endif // QANDROIDCAMERASESSION_H
diff --git a/src/plugins/android/src/mediacapture/qandroidcamerazoomcontrol.cpp b/src/plugins/android/src/mediacapture/qandroidcamerazoomcontrol.cpp
new file mode 100644
index 000000000..b7030e56b
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidcamerazoomcontrol.cpp
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qandroidcamerazoomcontrol.h"
+
+#include "qandroidcamerasession.h"
+#include "jcamera.h"
+#include "qandroidmultimediautils.h"
+#include <qmath.h>
+
+QT_BEGIN_NAMESPACE
+
+QAndroidCameraZoomControl::QAndroidCameraZoomControl(QAndroidCameraSession *session)
+ : QCameraZoomControl()
+ , m_cameraSession(session)
+ , m_maximumZoom(1.0)
+ , m_requestedZoom(1.0)
+ , m_currentZoom(1.0)
+{
+ connect(m_cameraSession, SIGNAL(opened()),
+ this, SLOT(onCameraOpened()));
+}
+
+qreal QAndroidCameraZoomControl::maximumOpticalZoom() const
+{
+ // Optical zoom not supported
+ return 1.0;
+}
+
+qreal QAndroidCameraZoomControl::maximumDigitalZoom() const
+{
+ return m_maximumZoom;
+}
+
+qreal QAndroidCameraZoomControl::requestedOpticalZoom() const
+{
+ // Optical zoom not supported
+ return 1.0;
+}
+
+qreal QAndroidCameraZoomControl::requestedDigitalZoom() const
+{
+ return m_requestedZoom;
+}
+
+qreal QAndroidCameraZoomControl::currentOpticalZoom() const
+{
+ // Optical zoom not supported
+ return 1.0;
+}
+
+qreal QAndroidCameraZoomControl::currentDigitalZoom() const
+{
+ return m_currentZoom;
+}
+
+void QAndroidCameraZoomControl::zoomTo(qreal optical, qreal digital)
+{
+ Q_UNUSED(optical);
+
+ if (!m_cameraSession->camera() ||
+ qFuzzyCompare(m_requestedZoom, digital) ||
+ qFuzzyCompare(m_maximumZoom, qreal(1))) {
+ return;
+ }
+
+ m_requestedZoom = digital;
+ emit requestedDigitalZoomChanged(m_requestedZoom);
+
+ digital = qBound(qreal(1), digital, m_maximumZoom);
+ int validZoomIndex = qt_findClosestValue(m_zoomRatios, qRound(digital * 100));
+ qreal newZoom = m_zoomRatios.at(validZoomIndex) / qreal(100);
+ if (!qFuzzyCompare(m_currentZoom, newZoom)) {
+ m_cameraSession->camera()->setZoom(validZoomIndex);
+ m_currentZoom = newZoom;
+ emit currentDigitalZoomChanged(m_currentZoom);
+ }
+}
+
+void QAndroidCameraZoomControl::onCameraOpened()
+{
+ m_requestedZoom = 1.0;
+ m_currentZoom = 1.0;
+ emit requestedDigitalZoomChanged(m_requestedZoom);
+ emit currentDigitalZoomChanged(m_currentZoom);
+
+ if (m_cameraSession->camera()->isZoomSupported()) {
+ m_zoomRatios = m_cameraSession->camera()->getZoomRatios();
+ qreal maxZoom = m_zoomRatios.last() / qreal(100);
+ if (m_maximumZoom != maxZoom) {
+ m_maximumZoom = maxZoom;
+ emit maximumDigitalZoomChanged(m_maximumZoom);
+ }
+ } else {
+ m_zoomRatios.clear();
+ if (!qFuzzyCompare(m_maximumZoom, qreal(1))) {
+ m_maximumZoom = 1.0;
+ emit maximumDigitalZoomChanged(m_maximumZoom);
+ }
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/android/src/mediacapture/qandroidcamerazoomcontrol.h b/src/plugins/android/src/mediacapture/qandroidcamerazoomcontrol.h
new file mode 100644
index 000000000..b102c5dda
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidcamerazoomcontrol.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANDROIDCAMERAZOOMCONTROL_H
+#define QANDROIDCAMERAZOOMCONTROL_H
+
+#include <qcamerazoomcontrol.h>
+#include <qcamera.h>
+
+QT_BEGIN_NAMESPACE
+
+class QAndroidCameraSession;
+
+class QAndroidCameraZoomControl : public QCameraZoomControl
+{
+ Q_OBJECT
+public:
+ explicit QAndroidCameraZoomControl(QAndroidCameraSession *session);
+
+ qreal maximumOpticalZoom() const Q_DECL_OVERRIDE;
+ qreal maximumDigitalZoom() const Q_DECL_OVERRIDE;
+ qreal requestedOpticalZoom() const Q_DECL_OVERRIDE;
+ qreal requestedDigitalZoom() const Q_DECL_OVERRIDE;
+ qreal currentOpticalZoom() const Q_DECL_OVERRIDE;
+ qreal currentDigitalZoom() const Q_DECL_OVERRIDE;
+ void zoomTo(qreal optical, qreal digital) Q_DECL_OVERRIDE;
+
+private Q_SLOTS:
+ void onCameraOpened();
+
+private:
+ QAndroidCameraSession *m_cameraSession;
+
+ qreal m_maximumZoom;
+ QList<int> m_zoomRatios;
+ qreal m_requestedZoom;
+ qreal m_currentZoom;
+};
+
+QT_END_NAMESPACE
+
+#endif // QANDROIDCAMERAZOOMCONTROL_H
diff --git a/src/plugins/android/src/mediacapture/qandroidcaptureservice.cpp b/src/plugins/android/src/mediacapture/qandroidcaptureservice.cpp
new file mode 100644
index 000000000..3468c64e5
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidcaptureservice.cpp
@@ -0,0 +1,216 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qandroidcaptureservice.h"
+
+#include "qandroidmediarecordercontrol.h"
+#include "qandroidcapturesession.h"
+#include "qandroidcameracontrol.h"
+#include "qandroidvideodeviceselectorcontrol.h"
+#include "qandroidaudioinputselectorcontrol.h"
+#include "qandroidcamerasession.h"
+#include "qandroidvideorendercontrol.h"
+#include "qandroidcamerazoomcontrol.h"
+#include "qandroidcameraexposurecontrol.h"
+#include "qandroidcameraflashcontrol.h"
+#include "qandroidcamerafocuscontrol.h"
+#include "qandroidcameralockscontrol.h"
+#include "qandroidcameraimageprocessingcontrol.h"
+#include "qandroidimageencodercontrol.h"
+#include "qandroidcameraimagecapturecontrol.h"
+#include "qandroidcameracapturedestinationcontrol.h"
+#include "qandroidcameracapturebufferformatcontrol.h"
+#include "qandroidaudioencodersettingscontrol.h"
+#include "qandroidvideoencodersettingscontrol.h"
+#include "qandroidmediacontainercontrol.h"
+
+#include <qmediaserviceproviderplugin.h>
+
+QT_BEGIN_NAMESPACE
+
+QAndroidCaptureService::QAndroidCaptureService(const QString &service, QObject *parent)
+ : QMediaService(parent)
+ , m_service(service)
+ , m_videoRendererControl(0)
+{
+ if (m_service == QLatin1String(Q_MEDIASERVICE_CAMERA)) {
+ m_cameraSession = new QAndroidCameraSession;
+ m_cameraControl = new QAndroidCameraControl(m_cameraSession);
+ m_videoInputControl = new QAndroidVideoDeviceSelectorControl(m_cameraSession);
+ m_cameraZoomControl = new QAndroidCameraZoomControl(m_cameraSession);
+ m_cameraExposureControl = new QAndroidCameraExposureControl(m_cameraSession);
+ m_cameraFlashControl = new QAndroidCameraFlashControl(m_cameraSession);
+ m_cameraFocusControl = new QAndroidCameraFocusControl(m_cameraSession);
+ m_cameraLocksControl = new QAndroidCameraLocksControl(m_cameraSession);
+ m_cameraImageProcessingControl = new QAndroidCameraImageProcessingControl(m_cameraSession);
+ m_imageEncoderControl = new QAndroidImageEncoderControl(m_cameraSession);
+ m_imageCaptureControl = new QAndroidCameraImageCaptureControl(m_cameraSession);
+ m_captureDestinationControl = new QAndroidCameraCaptureDestinationControl(m_cameraSession);
+ m_captureBufferFormatControl = new QAndroidCameraCaptureBufferFormatControl;
+ m_audioInputControl = 0;
+ } else {
+ m_cameraSession = 0;
+ m_cameraControl = 0;
+ m_videoInputControl = 0;
+ m_cameraZoomControl = 0;
+ m_cameraExposureControl = 0;
+ m_cameraFlashControl = 0;
+ m_cameraFocusControl = 0;
+ m_cameraLocksControl = 0;
+ m_cameraImageProcessingControl = 0;
+ m_imageEncoderControl = 0;
+ m_imageCaptureControl = 0;
+ m_captureDestinationControl = 0;
+ m_captureBufferFormatControl = 0;
+ m_videoEncoderSettingsControl = 0;
+ }
+
+ m_captureSession = new QAndroidCaptureSession(m_cameraSession);
+ m_recorderControl = new QAndroidMediaRecorderControl(m_captureSession);
+ m_audioEncoderSettingsControl = new QAndroidAudioEncoderSettingsControl(m_captureSession);
+ m_mediaContainerControl = new QAndroidMediaContainerControl(m_captureSession);
+
+ if (m_service == QLatin1String(Q_MEDIASERVICE_CAMERA)) {
+ m_videoEncoderSettingsControl = new QAndroidVideoEncoderSettingsControl(m_captureSession);
+ } else {
+ m_audioInputControl = new QAndroidAudioInputSelectorControl(m_captureSession);
+ m_captureSession->setAudioInput(m_audioInputControl->defaultInput());
+ }
+}
+
+QAndroidCaptureService::~QAndroidCaptureService()
+{
+ delete m_audioEncoderSettingsControl;
+ delete m_videoEncoderSettingsControl;
+ delete m_mediaContainerControl;
+ delete m_recorderControl;
+ delete m_captureSession;
+ delete m_cameraControl;
+ delete m_audioInputControl;
+ delete m_videoInputControl;
+ delete m_videoRendererControl;
+ delete m_cameraZoomControl;
+ delete m_cameraExposureControl;
+ delete m_cameraFlashControl;
+ delete m_cameraFocusControl;
+ delete m_cameraLocksControl;
+ delete m_cameraImageProcessingControl;
+ delete m_imageEncoderControl;
+ delete m_imageCaptureControl;
+ delete m_captureDestinationControl;
+ delete m_captureBufferFormatControl;
+ delete m_cameraSession;
+}
+
+QMediaControl *QAndroidCaptureService::requestControl(const char *name)
+{
+ if (qstrcmp(name, QMediaRecorderControl_iid) == 0)
+ return m_recorderControl;
+
+ if (qstrcmp(name, QMediaContainerControl_iid) == 0)
+ return m_mediaContainerControl;
+
+ if (qstrcmp(name, QAudioEncoderSettingsControl_iid) == 0)
+ return m_audioEncoderSettingsControl;
+
+ if (qstrcmp(name, QVideoEncoderSettingsControl_iid) == 0)
+ return m_videoEncoderSettingsControl;
+
+ if (qstrcmp(name, QCameraControl_iid) == 0)
+ return m_cameraControl;
+
+ if (qstrcmp(name, QAudioInputSelectorControl_iid) == 0)
+ return m_audioInputControl;
+
+ if (qstrcmp(name, QVideoDeviceSelectorControl_iid) == 0)
+ return m_videoInputControl;
+
+ if (qstrcmp(name, QCameraZoomControl_iid) == 0)
+ return m_cameraZoomControl;
+
+ if (qstrcmp(name, QCameraExposureControl_iid) == 0)
+ return m_cameraExposureControl;
+
+ if (qstrcmp(name, QCameraFlashControl_iid) == 0)
+ return m_cameraFlashControl;
+
+ if (qstrcmp(name, QCameraFocusControl_iid) == 0)
+ return m_cameraFocusControl;
+
+ if (qstrcmp(name, QCameraLocksControl_iid) == 0)
+ return m_cameraLocksControl;
+
+ if (qstrcmp(name, QCameraImageProcessingControl_iid) == 0)
+ return m_cameraImageProcessingControl;
+
+ if (qstrcmp(name, QImageEncoderControl_iid) == 0)
+ return m_imageEncoderControl;
+
+ if (qstrcmp(name, QCameraImageCaptureControl_iid) == 0)
+ return m_imageCaptureControl;
+
+ if (qstrcmp(name, QCameraCaptureDestinationControl_iid) == 0)
+ return m_captureDestinationControl;
+
+ if (qstrcmp(name, QCameraCaptureBufferFormatControl_iid) == 0)
+ return m_captureBufferFormatControl;
+
+ if (qstrcmp(name, QVideoRendererControl_iid) == 0
+ && m_service == QLatin1String(Q_MEDIASERVICE_CAMERA)
+ && !m_videoRendererControl) {
+ m_videoRendererControl = new QAndroidVideoRendererControl;
+ m_cameraSession->setVideoPreview(m_videoRendererControl);
+ return m_videoRendererControl;
+ }
+
+ return 0;
+}
+
+void QAndroidCaptureService::releaseControl(QMediaControl *control)
+{
+ if (control && control == m_videoRendererControl) {
+ m_cameraSession->setVideoPreview(0);
+ delete m_videoRendererControl;
+ m_videoRendererControl = 0;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/android/src/mediacapture/qandroidcaptureservice.h b/src/plugins/android/src/mediacapture/qandroidcaptureservice.h
new file mode 100644
index 000000000..71aaf2d64
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidcaptureservice.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANDROIDCAPTURESERVICE_H
+#define QANDROIDCAPTURESERVICE_H
+
+#include <qmediaservice.h>
+#include <qmediacontrol.h>
+
+QT_BEGIN_NAMESPACE
+
+class QAndroidMediaRecorderControl;
+class QAndroidCaptureSession;
+class QAndroidCameraControl;
+class QAndroidVideoDeviceSelectorControl;
+class QAndroidAudioInputSelectorControl;
+class QAndroidCameraSession;
+class QAndroidVideoRendererControl;
+class QAndroidCameraZoomControl;
+class QAndroidCameraExposureControl;
+class QAndroidCameraFlashControl;
+class QAndroidCameraFocusControl;
+class QAndroidCameraLocksControl;
+class QAndroidCameraImageProcessingControl;
+class QAndroidImageEncoderControl;
+class QAndroidCameraImageCaptureControl;
+class QAndroidCameraCaptureDestinationControl;
+class QAndroidCameraCaptureBufferFormatControl;
+class QAndroidAudioEncoderSettingsControl;
+class QAndroidVideoEncoderSettingsControl;
+class QAndroidMediaContainerControl;
+
+class QAndroidCaptureService : public QMediaService
+{
+ Q_OBJECT
+
+public:
+ explicit QAndroidCaptureService(const QString &service, QObject *parent = 0);
+ virtual ~QAndroidCaptureService();
+
+ QMediaControl *requestControl(const char *name);
+ void releaseControl(QMediaControl *);
+
+private:
+ QString m_service;
+
+ QAndroidMediaRecorderControl *m_recorderControl;
+ QAndroidCaptureSession *m_captureSession;
+ QAndroidCameraControl *m_cameraControl;
+ QAndroidVideoDeviceSelectorControl *m_videoInputControl;
+ QAndroidAudioInputSelectorControl *m_audioInputControl;
+ QAndroidCameraSession *m_cameraSession;
+ QAndroidVideoRendererControl *m_videoRendererControl;
+ QAndroidCameraZoomControl *m_cameraZoomControl;
+ QAndroidCameraExposureControl *m_cameraExposureControl;
+ QAndroidCameraFlashControl *m_cameraFlashControl;
+ QAndroidCameraFocusControl *m_cameraFocusControl;
+ QAndroidCameraLocksControl *m_cameraLocksControl;
+ QAndroidCameraImageProcessingControl *m_cameraImageProcessingControl;
+ QAndroidImageEncoderControl *m_imageEncoderControl;
+ QAndroidCameraImageCaptureControl *m_imageCaptureControl;
+ QAndroidCameraCaptureDestinationControl *m_captureDestinationControl;
+ QAndroidCameraCaptureBufferFormatControl *m_captureBufferFormatControl;
+ QAndroidAudioEncoderSettingsControl *m_audioEncoderSettingsControl;
+ QAndroidVideoEncoderSettingsControl *m_videoEncoderSettingsControl;
+ QAndroidMediaContainerControl *m_mediaContainerControl;
+};
+
+QT_END_NAMESPACE
+
+#endif // QANDROIDCAPTURESERVICE_H
diff --git a/src/plugins/android/src/mediacapture/qandroidcapturesession.cpp b/src/plugins/android/src/mediacapture/qandroidcapturesession.cpp
new file mode 100644
index 000000000..1927aeb8e
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidcapturesession.cpp
@@ -0,0 +1,547 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qandroidcapturesession.h"
+
+#include "jcamera.h"
+#include "qandroidcamerasession.h"
+#include "jmultimediautils.h"
+#include "qandroidmultimediautils.h"
+#include <QtPlatformSupport/private/qjnihelpers_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QAndroidCaptureSession::QAndroidCaptureSession(QAndroidCameraSession *cameraSession)
+ : QObject()
+ , m_mediaRecorder(0)
+ , m_cameraSession(cameraSession)
+ , m_audioSource(JMediaRecorder::DefaultAudioSource)
+ , m_duration(0)
+ , m_state(QMediaRecorder::StoppedState)
+ , m_status(QMediaRecorder::UnloadedStatus)
+ , m_resolutionDirty(false)
+ , m_containerFormatDirty(true)
+ , m_videoSettingsDirty(true)
+ , m_audioSettingsDirty(true)
+ , m_outputFormat(JMediaRecorder::DefaultOutputFormat)
+ , m_audioEncoder(JMediaRecorder::DefaultAudioEncoder)
+ , m_videoEncoder(JMediaRecorder::DefaultVideoEncoder)
+{
+ if (cameraSession) {
+ connect(cameraSession, SIGNAL(opened()), this, SLOT(onCameraOpened()));
+ connect(cameraSession, SIGNAL(statusChanged(QCamera::Status)),
+ this, SLOT(onCameraStatusChanged(QCamera::Status)));
+ connect(cameraSession, SIGNAL(captureModeChanged(QCamera::CaptureModes)),
+ this, SLOT(onCameraCaptureModeChanged(QCamera::CaptureModes)));
+ }
+
+ m_notifyTimer.setInterval(1000);
+ connect(&m_notifyTimer, SIGNAL(timeout()), this, SLOT(updateDuration()));
+}
+
+QAndroidCaptureSession::~QAndroidCaptureSession()
+{
+ stop();
+ delete m_mediaRecorder;
+}
+
+void QAndroidCaptureSession::setAudioInput(const QString &input)
+{
+ if (m_audioInput == input)
+ return;
+
+ m_audioInput = input;
+
+ if (m_audioInput == QLatin1String("default"))
+ m_audioSource = JMediaRecorder::DefaultAudioSource;
+ else if (m_audioInput == QLatin1String("mic"))
+ m_audioSource = JMediaRecorder::Mic;
+ else if (m_audioInput == QLatin1String("voice_uplink"))
+ m_audioSource = JMediaRecorder::VoiceUplink;
+ else if (m_audioInput == QLatin1String("voice_downlink"))
+ m_audioSource = JMediaRecorder::VoiceDownlink;
+ else if (m_audioInput == QLatin1String("voice_call"))
+ m_audioSource = JMediaRecorder::VoiceCall;
+ else if (m_audioInput == QLatin1String("voice_recognition"))
+ m_audioSource = JMediaRecorder::VoiceRecognition;
+ else
+ m_audioSource = JMediaRecorder::DefaultAudioSource;
+
+ emit audioInputChanged(m_audioInput);
+}
+
+QUrl QAndroidCaptureSession::outputLocation() const
+{
+ return m_outputLocation;
+}
+
+bool QAndroidCaptureSession::setOutputLocation(const QUrl &location)
+{
+ if (m_outputLocation == location)
+ return false;
+
+ m_outputLocation = location;
+
+ if (m_outputLocation.isEmpty())
+ return true;
+
+ if (m_outputLocation.isValid() && (m_outputLocation.isLocalFile() || m_outputLocation.isRelative())) {
+ emit actualLocationChanged(m_outputLocation);
+ return true;
+ }
+
+ m_outputLocation = QUrl();
+ return false;
+}
+
+QMediaRecorder::State QAndroidCaptureSession::state() const
+{
+ return m_state;
+}
+
+void QAndroidCaptureSession::setState(QMediaRecorder::State state)
+{
+ if (m_state == state)
+ return;
+
+ switch (state) {
+ case QMediaRecorder::StoppedState:
+ stop();
+ break;
+ case QMediaRecorder::RecordingState:
+ if (!start())
+ return;
+ break;
+ case QMediaRecorder::PausedState:
+ // Not supported by Android API
+ qWarning("QMediaRecorder::PausedState is not supported on Android");
+ return;
+ }
+
+ m_state = state;
+ emit stateChanged(m_state);
+}
+
+bool QAndroidCaptureSession::start()
+{
+ if (m_state == QMediaRecorder::RecordingState)
+ return false;
+
+ setStatus(QMediaRecorder::LoadingStatus);
+
+ if (m_mediaRecorder) {
+ m_mediaRecorder->release();
+ delete m_mediaRecorder;
+ }
+ m_mediaRecorder = new JMediaRecorder;
+ connect(m_mediaRecorder, SIGNAL(error(int,int)), this, SLOT(onError(int,int)));
+ connect(m_mediaRecorder, SIGNAL(info(int,int)), this, SLOT(onInfo(int,int)));
+
+ // Set audio/video sources
+ if (m_cameraSession) {
+ if (m_cameraSession->status() != QCamera::ActiveStatus) {
+ emit error(QMediaRecorder::ResourceError, QLatin1String("Camera must be active to record it."));
+ setStatus(QMediaRecorder::UnloadedStatus);
+ return false;
+ } else {
+ updateViewfinder();
+ m_cameraSession->camera()->unlock();
+ m_mediaRecorder->setCamera(m_cameraSession->camera());
+ m_mediaRecorder->setAudioSource(JMediaRecorder::Camcorder);
+ m_mediaRecorder->setVideoSource(JMediaRecorder::Camera);
+ }
+ } else {
+ m_mediaRecorder->setAudioSource(m_audioSource);
+ }
+
+ // Set output format
+ m_mediaRecorder->setOutputFormat(m_outputFormat);
+
+ // Set audio encoder settings
+ m_mediaRecorder->setAudioChannels(m_audioSettings.channelCount());
+ m_mediaRecorder->setAudioEncodingBitRate(m_audioSettings.bitRate());
+ m_mediaRecorder->setAudioSamplingRate(m_audioSettings.sampleRate());
+ m_mediaRecorder->setAudioEncoder(m_audioEncoder);
+
+ // Set video encoder settings
+ if (m_cameraSession) {
+ m_mediaRecorder->setVideoSize(m_videoSettings.resolution());
+ m_mediaRecorder->setVideoFrameRate(qRound(m_videoSettings.frameRate()));
+ m_mediaRecorder->setVideoEncodingBitRate(m_videoSettings.bitRate());
+ m_mediaRecorder->setVideoEncoder(m_videoEncoder);
+
+ m_mediaRecorder->setOrientationHint(m_cameraSession->currentCameraRotation());
+ }
+
+
+ // Set output file
+ QString filePath = m_mediaStorageLocation.generateFileName(m_outputLocation.isLocalFile() ? m_outputLocation.toLocalFile()
+ : m_outputLocation.toString(),
+ m_cameraSession ? QAndroidMediaStorageLocation::Camera
+ : QAndroidMediaStorageLocation::Audio,
+ m_cameraSession ? QLatin1String("VID_")
+ : QLatin1String("REC_"),
+ m_containerFormat);
+ m_outputLocation = QUrl::fromLocalFile(filePath);
+ emit actualLocationChanged(m_outputLocation);
+
+ m_mediaRecorder->setOutputFile(filePath);
+
+ if (!m_mediaRecorder->prepare()) {
+ emit error(QMediaRecorder::FormatError, QLatin1String("Unable to prepare the media recorder."));
+ setStatus(QMediaRecorder::UnloadedStatus);
+ return false;
+ }
+
+ setStatus(QMediaRecorder::LoadedStatus);
+ setStatus(QMediaRecorder::StartingStatus);
+
+ if (!m_mediaRecorder->start()) {
+ emit error(QMediaRecorder::FormatError, QLatin1String("Unable to start the media recorder."));
+ setStatus(QMediaRecorder::UnloadedStatus);
+ return false;
+ }
+
+ setStatus(QMediaRecorder::RecordingStatus);
+
+ m_elapsedTime.start();
+ m_notifyTimer.start();
+ updateDuration();
+
+ if (m_cameraSession)
+ m_cameraSession->setReadyForCapture(false);
+
+ return true;
+}
+
+void QAndroidCaptureSession::stop(bool error)
+{
+ if (m_state == QMediaRecorder::StoppedState)
+ return;
+
+ setStatus(QMediaRecorder::FinalizingStatus);
+
+ m_mediaRecorder->stop();
+
+ m_notifyTimer.stop();
+ updateDuration();
+ m_elapsedTime.invalidate();
+
+ if (m_cameraSession) {
+ m_cameraSession->camera()->reconnect();
+ // Viewport needs to be restarted
+ m_cameraSession->camera()->startPreview();
+ m_cameraSession->setReadyForCapture(true);
+ }
+
+ m_mediaRecorder->release();
+ delete m_mediaRecorder;
+ m_mediaRecorder = 0;
+
+ if (!error) {
+ // if the media is saved into the standard media location, register it
+ // with the Android media scanner so it appears immediately in apps
+ // such as the gallery.
+ QString mediaPath = m_outputLocation.toLocalFile();
+ QString standardLoc = m_cameraSession ? JMultimediaUtils::getDefaultMediaDirectory(JMultimediaUtils::DCIM)
+ : JMultimediaUtils::getDefaultMediaDirectory(JMultimediaUtils::Sounds);
+ if (mediaPath.startsWith(standardLoc))
+ JMultimediaUtils::registerMediaFile(mediaPath);
+ }
+
+ setStatus(QMediaRecorder::UnloadedStatus);
+}
+
+void QAndroidCaptureSession::setStatus(QMediaRecorder::Status status)
+{
+ if (m_status == status)
+ return;
+
+ m_status = status;
+ emit statusChanged(m_status);
+}
+
+QMediaRecorder::Status QAndroidCaptureSession::status() const
+{
+ return m_status;
+}
+
+qint64 QAndroidCaptureSession::duration() const
+{
+ return m_duration;
+}
+
+void QAndroidCaptureSession::setContainerFormat(const QString &format)
+{
+ if (m_containerFormat == format)
+ return;
+
+ m_containerFormat = format;
+ m_containerFormatDirty = true;
+}
+
+void QAndroidCaptureSession::setAudioSettings(const QAudioEncoderSettings &settings)
+{
+ if (m_audioSettings == settings)
+ return;
+
+ m_audioSettings = settings;
+ m_audioSettingsDirty = true;
+}
+
+void QAndroidCaptureSession::setVideoSettings(const QVideoEncoderSettings &settings)
+{
+ if (!m_cameraSession || m_videoSettings == settings)
+ return;
+
+ if (m_videoSettings.resolution() != settings.resolution())
+ m_resolutionDirty = true;
+
+ m_videoSettings = settings;
+ m_videoSettingsDirty = true;
+}
+
+void QAndroidCaptureSession::applySettings()
+{
+ // container settings
+ if (m_containerFormatDirty) {
+ if (m_containerFormat.isEmpty()) {
+ m_containerFormat = m_defaultSettings.outputFileExtension;
+ m_outputFormat = m_defaultSettings.outputFormat;
+ } else if (m_containerFormat == QLatin1String("3gp")) {
+ m_outputFormat = JMediaRecorder::THREE_GPP;
+ } else if (!m_cameraSession && m_containerFormat == QLatin1String("amr")) {
+ m_outputFormat = JMediaRecorder::AMR_NB_Format;
+ } else if (!m_cameraSession && m_containerFormat == QLatin1String("awb")) {
+ m_outputFormat = JMediaRecorder::AMR_WB_Format;
+ } else {
+ m_containerFormat = QStringLiteral("mp4");
+ m_outputFormat = JMediaRecorder::MPEG_4;
+ }
+
+ m_containerFormatDirty = false;
+ }
+
+ // audio settings
+ if (m_audioSettingsDirty) {
+ if (m_audioSettings.channelCount() <= 0)
+ m_audioSettings.setChannelCount(m_defaultSettings.audioChannels);
+ if (m_audioSettings.bitRate() <= 0)
+ m_audioSettings.setBitRate(m_defaultSettings.audioBitRate);
+ if (m_audioSettings.sampleRate() <= 0)
+ m_audioSettings.setSampleRate(m_defaultSettings.audioSampleRate);
+
+ if (m_audioSettings.codec().isEmpty())
+ m_audioEncoder = m_defaultSettings.audioEncoder;
+ else if (m_audioSettings.codec() == QLatin1String("aac"))
+ m_audioEncoder = JMediaRecorder::AAC;
+ else if (m_audioSettings.codec() == QLatin1String("amr-nb"))
+ m_audioEncoder = JMediaRecorder::AMR_NB_Encoder;
+ else if (m_audioSettings.codec() == QLatin1String("amr-wb"))
+ m_audioEncoder = JMediaRecorder::AMR_WB_Encoder;
+ else
+ m_audioEncoder = m_defaultSettings.audioEncoder;
+
+ m_audioSettingsDirty = false;
+ }
+
+ // video settings
+ if (m_cameraSession && m_videoSettingsDirty) {
+ if (m_videoSettings.resolution().isEmpty()) {
+ m_videoSettings.setResolution(m_defaultSettings.videoResolution);
+ m_resolutionDirty = true;
+ } else if (!m_supportedResolutions.contains(m_videoSettings.resolution())) {
+ // if the requested resolution is not supported, find the closest one
+ QSize reqSize = m_videoSettings.resolution();
+ int reqPixelCount = reqSize.width() * reqSize.height();
+ QList<int> supportedPixelCounts;
+ for (int i = 0; i < m_supportedResolutions.size(); ++i) {
+ const QSize &s = m_supportedResolutions.at(i);
+ supportedPixelCounts.append(s.width() * s.height());
+ }
+ int closestIndex = qt_findClosestValue(supportedPixelCounts, reqPixelCount);
+ m_videoSettings.setResolution(m_supportedResolutions.at(closestIndex));
+ m_resolutionDirty = true;
+ }
+
+ if (m_videoSettings.frameRate() <= 0)
+ m_videoSettings.setFrameRate(m_defaultSettings.videoFrameRate);
+ if (m_videoSettings.bitRate() <= 0)
+ m_videoSettings.setBitRate(m_defaultSettings.videoBitRate);
+
+ if (m_videoSettings.codec().isEmpty())
+ m_videoEncoder = m_defaultSettings.videoEncoder;
+ else if (m_videoSettings.codec() == QLatin1String("h263"))
+ m_videoEncoder = JMediaRecorder::H263;
+ else if (m_videoSettings.codec() == QLatin1String("h264"))
+ m_videoEncoder = JMediaRecorder::H264;
+ else if (m_videoSettings.codec() == QLatin1String("mpeg4_sp"))
+ m_videoEncoder = JMediaRecorder::MPEG_4_SP;
+ else
+ m_videoEncoder = m_defaultSettings.videoEncoder;
+
+ m_videoSettingsDirty = false;
+ }
+}
+
+void QAndroidCaptureSession::updateViewfinder()
+{
+ if (!m_resolutionDirty)
+ return;
+
+ m_cameraSession->camera()->stopPreview();
+ m_cameraSession->adjustViewfinderSize(m_videoSettings.resolution(), false);
+ m_resolutionDirty = false;
+}
+
+void QAndroidCaptureSession::updateDuration()
+{
+ if (m_elapsedTime.isValid())
+ m_duration = m_elapsedTime.elapsed();
+
+ emit durationChanged(m_duration);
+}
+
+void QAndroidCaptureSession::onCameraOpened()
+{
+ m_supportedResolutions.clear();
+ m_supportedFramerates.clear();
+
+ // get supported resolutions from predefined profiles
+ for (int i = 0; i < 8; ++i) {
+ CaptureProfile profile = getProfile(i);
+ if (!profile.isNull) {
+ if (i == 1) // QUALITY_HIGH
+ m_defaultSettings = profile;
+
+ if (!m_supportedResolutions.contains(profile.videoResolution))
+ m_supportedResolutions.append(profile.videoResolution);
+ if (!m_supportedFramerates.contains(profile.videoFrameRate))
+ m_supportedFramerates.append(profile.videoFrameRate);
+ }
+ }
+
+ qSort(m_supportedResolutions.begin(), m_supportedResolutions.end(), qt_sizeLessThan);
+ qSort(m_supportedFramerates.begin(), m_supportedFramerates.end());
+}
+
+QAndroidCaptureSession::CaptureProfile QAndroidCaptureSession::getProfile(int id)
+{
+ CaptureProfile profile;
+ bool hasProfile = QJNIObject::callStaticMethod<jboolean>("android/media/CamcorderProfile",
+ "hasProfile",
+ "(II)Z",
+ m_cameraSession->camera()->cameraId(),
+ id);
+
+ if (hasProfile) {
+ QJNILocalRef<jobject> ref = QJNIObject::callStaticObjectMethod<jobject>("android/media/CamcorderProfile",
+ "get",
+ "(II)Landroid/media/CamcorderProfile;",
+ m_cameraSession->camera()->cameraId(),
+ id);
+
+
+ QJNIObject obj(ref.object());
+
+ profile.outputFormat = JMediaRecorder::OutputFormat(obj.getField<jint>("fileFormat"));
+ profile.audioEncoder = JMediaRecorder::AudioEncoder(obj.getField<jint>("audioCodec"));
+ profile.audioBitRate = obj.getField<jint>("audioBitRate");
+ profile.audioChannels = obj.getField<jint>("audioChannels");
+ profile.audioSampleRate = obj.getField<jint>("audioSampleRate");
+ profile.videoEncoder = JMediaRecorder::VideoEncoder(obj.getField<jint>("videoCodec"));
+ profile.videoBitRate = obj.getField<jint>("videoBitRate");
+ profile.videoFrameRate = obj.getField<jint>("videoFrameRate");
+ profile.videoResolution = QSize(obj.getField<jint>("videoFrameWidth"),
+ obj.getField<jint>("videoFrameHeight"));
+
+ if (profile.outputFormat == JMediaRecorder::MPEG_4)
+ profile.outputFileExtension = QStringLiteral("mp4");
+ else if (profile.outputFormat == JMediaRecorder::THREE_GPP)
+ profile.outputFileExtension = QStringLiteral("3gp");
+ else if (profile.outputFormat == JMediaRecorder::AMR_NB_Format)
+ profile.outputFileExtension = QStringLiteral("amr");
+ else if (profile.outputFormat == JMediaRecorder::AMR_WB_Format)
+ profile.outputFileExtension = QStringLiteral("awb");
+
+ profile.isNull = false;
+ }
+
+ return profile;
+}
+
+void QAndroidCaptureSession::onCameraStatusChanged(QCamera::Status status)
+{
+ if (status == QCamera::StoppingStatus)
+ setState(QMediaRecorder::StoppedState);
+}
+
+void QAndroidCaptureSession::onCameraCaptureModeChanged(QCamera::CaptureModes mode)
+{
+ if (!mode.testFlag(QCamera::CaptureVideo))
+ setState(QMediaRecorder::StoppedState);
+}
+
+void QAndroidCaptureSession::onError(int what, int extra)
+{
+ Q_UNUSED(what)
+ Q_UNUSED(extra)
+ stop(true);
+ m_state = QMediaRecorder::StoppedState;
+ emit stateChanged(m_state);
+ emit error(QMediaRecorder::ResourceError, QLatin1String("Unknown error."));
+}
+
+void QAndroidCaptureSession::onInfo(int what, int extra)
+{
+ Q_UNUSED(extra)
+ if (what == 800) {
+ // MEDIA_RECORDER_INFO_MAX_DURATION_REACHED
+ setState(QMediaRecorder::StoppedState);
+ emit error(QMediaRecorder::OutOfSpaceError, QLatin1String("Maximum duration reached."));
+ } else if (what == 801) {
+ // MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED
+ setState(QMediaRecorder::StoppedState);
+ emit error(QMediaRecorder::OutOfSpaceError, QLatin1String("Maximum file size reached."));
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/android/src/mediacapture/qandroidcapturesession.h b/src/plugins/android/src/mediacapture/qandroidcapturesession.h
new file mode 100644
index 000000000..6d3645c13
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidcapturesession.h
@@ -0,0 +1,184 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANDROIDCAPTURESESSION_H
+#define QANDROIDCAPTURESESSION_H
+
+#include <qobject.h>
+#include <qmediarecorder.h>
+#include <qurl.h>
+#include <qelapsedtimer.h>
+#include <qtimer.h>
+#include "qandroidmediastoragelocation.h"
+#include "jmediarecorder.h"
+
+QT_BEGIN_NAMESPACE
+
+class QAndroidCameraSession;
+
+class QAndroidCaptureSession : public QObject
+{
+ Q_OBJECT
+public:
+ explicit QAndroidCaptureSession(QAndroidCameraSession *cameraSession = 0);
+ ~QAndroidCaptureSession();
+
+ QList<QSize> supportedResolutions() const { return m_supportedResolutions; }
+ QList<qreal> supportedFrameRates() const { return m_supportedFramerates; }
+
+ QString audioInput() const { return m_audioInput; }
+ void setAudioInput(const QString &input);
+
+ QUrl outputLocation() const;
+ bool setOutputLocation(const QUrl &location);
+
+ QMediaRecorder::State state() const;
+ void setState(QMediaRecorder::State state);
+
+ QMediaRecorder::Status status() const;
+
+ qint64 duration() const;
+
+ QString containerFormat() const { return m_containerFormat; }
+ void setContainerFormat(const QString &format);
+
+ QAudioEncoderSettings audioSettings() const { return m_audioSettings; }
+ void setAudioSettings(const QAudioEncoderSettings &settings);
+
+ QVideoEncoderSettings videoSettings() const { return m_videoSettings; }
+ void setVideoSettings(const QVideoEncoderSettings &settings);
+
+ void applySettings();
+
+Q_SIGNALS:
+ void audioInputChanged(const QString& name);
+ void stateChanged(QMediaRecorder::State state);
+ void statusChanged(QMediaRecorder::Status status);
+ void durationChanged(qint64 position);
+ void actualLocationChanged(const QUrl &location);
+ void error(int error, const QString &errorString);
+
+private Q_SLOTS:
+ void updateDuration();
+ void onCameraOpened();
+ void onCameraStatusChanged(QCamera::Status);
+ void onCameraCaptureModeChanged(QCamera::CaptureModes mode);
+
+ void onError(int what, int extra);
+ void onInfo(int what, int extra);
+
+private:
+ struct CaptureProfile {
+ JMediaRecorder::OutputFormat outputFormat;
+ QString outputFileExtension;
+
+ JMediaRecorder::AudioEncoder audioEncoder;
+ int audioBitRate;
+ int audioChannels;
+ int audioSampleRate;
+
+ JMediaRecorder::VideoEncoder videoEncoder;
+ int videoBitRate;
+ int videoFrameRate;
+ QSize videoResolution;
+
+ bool isNull;
+
+ CaptureProfile()
+ : outputFormat(JMediaRecorder::MPEG_4)
+ , outputFileExtension(QLatin1String("mp4"))
+ , audioEncoder(JMediaRecorder::DefaultAudioEncoder)
+ , audioBitRate(128000)
+ , audioChannels(2)
+ , audioSampleRate(44100)
+ , videoEncoder(JMediaRecorder::DefaultVideoEncoder)
+ , videoBitRate(1)
+ , videoFrameRate(-1)
+ , videoResolution(320, 240)
+ , isNull(true)
+ { }
+ };
+
+ CaptureProfile getProfile(int id);
+
+ bool start();
+ void stop(bool error = false);
+
+ void setStatus(QMediaRecorder::Status status);
+
+ void updateViewfinder();
+
+ JMediaRecorder *m_mediaRecorder;
+ QAndroidCameraSession *m_cameraSession;
+
+ QString m_audioInput;
+ JMediaRecorder::AudioSource m_audioSource;
+
+ QAndroidMediaStorageLocation m_mediaStorageLocation;
+
+ QElapsedTimer m_elapsedTime;
+ QTimer m_notifyTimer;
+ qint64 m_duration;
+
+ QMediaRecorder::State m_state;
+ QMediaRecorder::Status m_status;
+ QUrl m_outputLocation;
+
+ CaptureProfile m_defaultSettings;
+
+ QString m_containerFormat;
+ QAudioEncoderSettings m_audioSettings;
+ QVideoEncoderSettings m_videoSettings;
+ bool m_resolutionDirty;
+ bool m_containerFormatDirty;
+ bool m_videoSettingsDirty;
+ bool m_audioSettingsDirty;
+ JMediaRecorder::OutputFormat m_outputFormat;
+ JMediaRecorder::AudioEncoder m_audioEncoder;
+ JMediaRecorder::VideoEncoder m_videoEncoder;
+
+ QList<QSize> m_supportedResolutions;
+ QList<qreal> m_supportedFramerates;
+};
+
+QT_END_NAMESPACE
+
+#endif // QANDROIDCAPTURESESSION_H
diff --git a/src/plugins/android/src/mediacapture/qandroidimageencodercontrol.cpp b/src/plugins/android/src/mediacapture/qandroidimageencodercontrol.cpp
new file mode 100644
index 000000000..79e0651a3
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidimageencodercontrol.cpp
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qandroidimageencodercontrol.h"
+
+#include "qandroidcamerasession.h"
+#include "jcamera.h"
+
+QT_BEGIN_NAMESPACE
+
+QAndroidImageEncoderControl::QAndroidImageEncoderControl(QAndroidCameraSession *session)
+ : QImageEncoderControl()
+ , m_session(session)
+{
+ connect(m_session, SIGNAL(opened()),
+ this, SLOT(onCameraOpened()));
+}
+
+QStringList QAndroidImageEncoderControl::supportedImageCodecs() const
+{
+ return QStringList() << QLatin1String("jpeg");
+}
+
+QString QAndroidImageEncoderControl::imageCodecDescription(const QString &codecName) const
+{
+ if (codecName == QLatin1String("jpeg"))
+ return tr("JPEG image");
+
+ return QString();
+}
+
+QList<QSize> QAndroidImageEncoderControl::supportedResolutions(const QImageEncoderSettings &settings, bool *continuous) const
+{
+ Q_UNUSED(settings);
+
+ if (continuous)
+ *continuous = false;
+
+ return m_supportedResolutions;
+}
+
+QImageEncoderSettings QAndroidImageEncoderControl::imageSettings() const
+{
+ return m_session->imageSettings();
+}
+
+void QAndroidImageEncoderControl::setImageSettings(const QImageEncoderSettings &settings)
+{
+ m_session->setImageSettings(settings);
+}
+
+void QAndroidImageEncoderControl::onCameraOpened()
+{
+ m_supportedResolutions = m_session->camera()->getSupportedPictureSizes();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/android/src/mediacapture/qandroidimageencodercontrol.h b/src/plugins/android/src/mediacapture/qandroidimageencodercontrol.h
new file mode 100644
index 000000000..23e397d4d
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidimageencodercontrol.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANDROIDIMAGEENCODERCONTROL_H
+#define QANDROIDIMAGEENCODERCONTROL_H
+
+#include <qimageencodercontrol.h>
+
+QT_BEGIN_NAMESPACE
+
+class QAndroidCameraSession;
+
+class QAndroidImageEncoderControl : public QImageEncoderControl
+{
+ Q_OBJECT
+public:
+ explicit QAndroidImageEncoderControl(QAndroidCameraSession *session);
+
+ QStringList supportedImageCodecs() const Q_DECL_OVERRIDE;
+ QString imageCodecDescription(const QString &codecName) const Q_DECL_OVERRIDE;
+ QList<QSize> supportedResolutions(const QImageEncoderSettings &settings, bool *continuous = 0) const Q_DECL_OVERRIDE;
+ QImageEncoderSettings imageSettings() const Q_DECL_OVERRIDE;
+ void setImageSettings(const QImageEncoderSettings &settings) Q_DECL_OVERRIDE;
+
+private Q_SLOTS:
+ void onCameraOpened();
+
+private:
+ QAndroidCameraSession *m_session;
+
+ QList<QSize> m_supportedResolutions;
+};
+
+#endif // QANDROIDIMAGEENCODERCONTROL_H
diff --git a/src/plugins/android/src/mediacapture/qandroidmediacontainercontrol.cpp b/src/plugins/android/src/mediacapture/qandroidmediacontainercontrol.cpp
new file mode 100644
index 000000000..33f7f2351
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidmediacontainercontrol.cpp
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qandroidmediacontainercontrol.h"
+
+#include "qandroidcapturesession.h"
+
+QT_BEGIN_NAMESPACE
+
+QAndroidMediaContainerControl::QAndroidMediaContainerControl(QAndroidCaptureSession *session)
+ : QMediaContainerControl()
+ , m_session(session)
+{
+}
+
+QStringList QAndroidMediaContainerControl::supportedContainers() const
+{
+ return QStringList() << QLatin1String("mp4")
+ << QLatin1String("3gp")
+ << QLatin1String("amr")
+ << QLatin1String("awb");
+}
+
+QString QAndroidMediaContainerControl::containerFormat() const
+{
+ return m_session->containerFormat();
+}
+
+void QAndroidMediaContainerControl::setContainerFormat(const QString &format)
+{
+ m_session->setContainerFormat(format);
+}
+
+QString QAndroidMediaContainerControl::containerDescription(const QString &formatMimeType) const
+{
+ if (formatMimeType == QLatin1String("mp4"))
+ return tr("MPEG4 media file format");
+ else if (formatMimeType == QLatin1String("3gp"))
+ return tr("3GPP media file format");
+ else if (formatMimeType == QLatin1String("amr"))
+ return tr("AMR NB file format");
+ else if (formatMimeType == QLatin1String("awb"))
+ return tr("AMR WB file format");
+
+ return QString();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/android/src/mediacapture/qandroidmediacontainercontrol.h b/src/plugins/android/src/mediacapture/qandroidmediacontainercontrol.h
new file mode 100644
index 000000000..d52e8365f
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidmediacontainercontrol.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANDROIDMEDIACONTAINERCONTROL_H
+#define QANDROIDMEDIACONTAINERCONTROL_H
+
+#include <qmediacontainercontrol.h>
+
+QT_BEGIN_NAMESPACE
+
+class QAndroidCaptureSession;
+
+class QAndroidMediaContainerControl : public QMediaContainerControl
+{
+ Q_OBJECT
+public:
+ QAndroidMediaContainerControl(QAndroidCaptureSession *session);
+
+ QStringList supportedContainers() const Q_DECL_OVERRIDE;
+ QString containerFormat() const Q_DECL_OVERRIDE;
+ void setContainerFormat(const QString &format) Q_DECL_OVERRIDE;
+ QString containerDescription(const QString &formatMimeType) const Q_DECL_OVERRIDE;
+
+private:
+ QAndroidCaptureSession *m_session;
+};
+
+QT_END_NAMESPACE
+
+#endif // QANDROIDMEDIACONTAINERCONTROL_H
diff --git a/src/plugins/android/src/mediacapture/qandroidmediarecordercontrol.cpp b/src/plugins/android/src/mediacapture/qandroidmediarecordercontrol.cpp
new file mode 100644
index 000000000..dab9f3e30
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidmediarecordercontrol.cpp
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qandroidmediarecordercontrol.h"
+
+#include "qandroidcapturesession.h"
+
+QT_BEGIN_NAMESPACE
+
+QAndroidMediaRecorderControl::QAndroidMediaRecorderControl(QAndroidCaptureSession *session)
+ : QMediaRecorderControl()
+ , m_session(session)
+{
+ connect(m_session, SIGNAL(stateChanged(QMediaRecorder::State)), this, SIGNAL(stateChanged(QMediaRecorder::State)));
+ connect(m_session, SIGNAL(statusChanged(QMediaRecorder::Status)), this, SIGNAL(statusChanged(QMediaRecorder::Status)));
+ connect(m_session, SIGNAL(durationChanged(qint64)), this, SIGNAL(durationChanged(qint64)));
+ connect(m_session, SIGNAL(actualLocationChanged(QUrl)), this, SIGNAL(actualLocationChanged(QUrl)));
+ connect(m_session, SIGNAL(error(int,QString)), this, SIGNAL(error(int,QString)));
+}
+
+QUrl QAndroidMediaRecorderControl::outputLocation() const
+{
+ return m_session->outputLocation();
+}
+
+bool QAndroidMediaRecorderControl::setOutputLocation(const QUrl &location)
+{
+ return m_session->setOutputLocation(location);
+}
+
+QMediaRecorder::State QAndroidMediaRecorderControl::state() const
+{
+ return m_session->state();
+}
+
+QMediaRecorder::Status QAndroidMediaRecorderControl::status() const
+{
+ return m_session->status();
+}
+
+qint64 QAndroidMediaRecorderControl::duration() const
+{
+ return m_session->duration();
+}
+
+bool QAndroidMediaRecorderControl::isMuted() const
+{
+ // No API for this in Android
+ return false;
+}
+
+qreal QAndroidMediaRecorderControl::volume() const
+{
+ // No API for this in Android
+ return 1.0;
+}
+
+void QAndroidMediaRecorderControl::applySettings()
+{
+ m_session->applySettings();
+}
+
+void QAndroidMediaRecorderControl::setState(QMediaRecorder::State state)
+{
+ m_session->setState(state);
+}
+
+void QAndroidMediaRecorderControl::setMuted(bool muted)
+{
+ // No API for this in Android
+ Q_UNUSED(muted)
+ qWarning("QMediaRecorder::setMuted() is not supported on Android.");
+}
+
+void QAndroidMediaRecorderControl::setVolume(qreal volume)
+{
+ // No API for this in Android
+ Q_UNUSED(volume)
+ qWarning("QMediaRecorder::setVolume() is not supported on Android.");
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/android/src/mediacapture/qandroidmediarecordercontrol.h b/src/plugins/android/src/mediacapture/qandroidmediarecordercontrol.h
new file mode 100644
index 000000000..c518f7f70
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidmediarecordercontrol.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANDROIDMEDIARECORDERCONTROL_H
+#define QANDROIDMEDIARECORDERCONTROL_H
+
+#include <qmediarecordercontrol.h>
+
+QT_BEGIN_NAMESPACE
+
+class QAndroidCaptureSession;
+
+class QAndroidMediaRecorderControl : public QMediaRecorderControl
+{
+ Q_OBJECT
+public:
+ explicit QAndroidMediaRecorderControl(QAndroidCaptureSession *session);
+
+ QUrl outputLocation() const Q_DECL_OVERRIDE;
+ bool setOutputLocation(const QUrl &location) Q_DECL_OVERRIDE;
+ QMediaRecorder::State state() const Q_DECL_OVERRIDE;
+ QMediaRecorder::Status status() const Q_DECL_OVERRIDE;
+ qint64 duration() const Q_DECL_OVERRIDE;
+ bool isMuted() const Q_DECL_OVERRIDE;
+ qreal volume() const Q_DECL_OVERRIDE;
+ void applySettings() Q_DECL_OVERRIDE;
+
+public Q_SLOTS:
+ void setState(QMediaRecorder::State state) Q_DECL_OVERRIDE;
+ void setMuted(bool muted) Q_DECL_OVERRIDE;
+ void setVolume(qreal volume) Q_DECL_OVERRIDE;
+
+private:
+ QAndroidCaptureSession *m_session;
+};
+
+QT_END_NAMESPACE
+
+#endif // QANDROIDMEDIARECORDERCONTROL_H
diff --git a/src/plugins/android/src/mediacapture/qandroidmediastoragelocation.cpp b/src/plugins/android/src/mediacapture/qandroidmediastoragelocation.cpp
new file mode 100644
index 000000000..ee6734158
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidmediastoragelocation.cpp
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qandroidmediastoragelocation.h"
+
+#include "jmultimediautils.h"
+
+QT_BEGIN_NAMESPACE
+
+QAndroidMediaStorageLocation::QAndroidMediaStorageLocation()
+{
+}
+
+QDir QAndroidMediaStorageLocation::defaultDir(CaptureSource source) const
+{
+ QStringList dirCandidates;
+
+ if (source == Camera)
+ dirCandidates << JMultimediaUtils::getDefaultMediaDirectory(JMultimediaUtils::DCIM);
+ else
+ dirCandidates << JMultimediaUtils::getDefaultMediaDirectory(JMultimediaUtils::Sounds);
+ dirCandidates << QDir::homePath();
+ dirCandidates << QDir::currentPath();
+ dirCandidates << QDir::tempPath();
+
+ Q_FOREACH (const QString &path, dirCandidates) {
+ if (QFileInfo(path).isWritable())
+ return QDir(path);
+ }
+
+ return QDir();
+}
+
+QString QAndroidMediaStorageLocation::generateFileName(const QString &requestedName,
+ CaptureSource source,
+ const QString &prefix,
+ const QString &extension) const
+{
+ if (requestedName.isEmpty())
+ return generateFileName(prefix, defaultDir(source), extension);
+
+ QString path = requestedName;
+
+ if (QFileInfo(path).isRelative())
+ path = defaultDir(source).absoluteFilePath(path);
+
+ if (QFileInfo(path).isDir())
+ return generateFileName(prefix, QDir(path), extension);
+
+ if (!path.endsWith(extension))
+ path.append(QString(".%1").arg(extension));
+
+ return path;
+}
+
+QString QAndroidMediaStorageLocation::generateFileName(const QString &prefix,
+ const QDir &dir,
+ const QString &extension) const
+{
+ QMutexLocker lock(&m_mutex);
+
+ const QString lastMediaKey = dir.absolutePath() + QLatin1Char(' ') + prefix + QLatin1Char(' ') + extension;
+ qint64 lastMediaIndex = m_lastUsedIndex.value(lastMediaKey, 0);
+
+ if (lastMediaIndex == 0) {
+ // first run, find the maximum media number during the fist capture
+ Q_FOREACH (const QString &fileName, dir.entryList(QStringList() << QString("%1*.%2").arg(prefix).arg(extension))) {
+ const qint64 mediaIndex = fileName.mid(prefix.length(), fileName.size() - prefix.length() - extension.length() - 1).toInt();
+ lastMediaIndex = qMax(lastMediaIndex, mediaIndex);
+ }
+ }
+
+ // don't just rely on cached lastMediaIndex value,
+ // someone else may create a file after camera started
+ while (true) {
+ const QString name = QString("%1%2.%3").arg(prefix)
+ .arg(lastMediaIndex + 1, 8, 10, QLatin1Char('0'))
+ .arg(extension);
+
+ const QString path = dir.absoluteFilePath(name);
+ if (!QFileInfo(path).exists()) {
+ m_lastUsedIndex[lastMediaKey] = lastMediaIndex + 1;
+ return path;
+ }
+
+ lastMediaIndex++;
+ }
+
+ return QString();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/android/src/mediacapture/qandroidmediastoragelocation.h b/src/plugins/android/src/mediacapture/qandroidmediastoragelocation.h
new file mode 100644
index 000000000..2e63f3df5
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidmediastoragelocation.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANDROIDMEDIASTORAGELOCATION_H
+#define QANDROIDMEDIASTORAGELOCATION_H
+
+#include <QCamera>
+#include <QDir>
+#include <QHash>
+#include <QMutex>
+
+QT_BEGIN_NAMESPACE
+
+class QAndroidMediaStorageLocation
+{
+public:
+ enum CaptureSource {
+ Camera,
+ Audio
+ };
+
+ QAndroidMediaStorageLocation();
+
+ QDir defaultDir(CaptureSource source) const;
+
+ QString generateFileName(const QString &requestedName, CaptureSource source, const QString &prefix, const QString &extension) const;
+ QString generateFileName(const QString &prefix, const QDir &dir, const QString &extension) const;
+
+private:
+ mutable QHash<QString, qint64> m_lastUsedIndex;
+
+ mutable QMutex m_mutex;
+};
+
+QT_END_NAMESPACE
+
+#endif // QANDROIDMEDIASTORAGELOCATION_H
diff --git a/src/plugins/android/src/mediacapture/qandroidvideodeviceselectorcontrol.cpp b/src/plugins/android/src/mediacapture/qandroidvideodeviceselectorcontrol.cpp
new file mode 100644
index 000000000..26dce565e
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidvideodeviceselectorcontrol.cpp
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qandroidvideodeviceselectorcontrol.h"
+
+#include "qandroidcamerasession.h"
+#include "jcamera.h"
+#include <QtPlatformSupport/private/qjnihelpers_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QList<QByteArray> QAndroidVideoDeviceSelectorControl::m_names;
+QStringList QAndroidVideoDeviceSelectorControl::m_descriptions;
+
+QAndroidVideoDeviceSelectorControl::QAndroidVideoDeviceSelectorControl(QAndroidCameraSession *session)
+ : QVideoDeviceSelectorControl(0)
+ , m_selectedDevice(0)
+ , m_cameraSession(session)
+{
+ if (m_names.isEmpty())
+ update();
+}
+
+QAndroidVideoDeviceSelectorControl::~QAndroidVideoDeviceSelectorControl()
+{
+}
+
+int QAndroidVideoDeviceSelectorControl::deviceCount() const
+{
+ return m_names.size();
+}
+
+QString QAndroidVideoDeviceSelectorControl::deviceName(int index) const
+{
+ return m_names.at(index);
+}
+
+QString QAndroidVideoDeviceSelectorControl::deviceDescription(int index) const
+{
+ return m_descriptions.at(index);
+}
+
+int QAndroidVideoDeviceSelectorControl::defaultDevice() const
+{
+ return 0;
+}
+
+int QAndroidVideoDeviceSelectorControl::selectedDevice() const
+{
+ return m_selectedDevice;
+}
+
+void QAndroidVideoDeviceSelectorControl::setSelectedDevice(int index)
+{
+ if (index != m_selectedDevice) {
+ m_selectedDevice = index;
+ m_cameraSession->setSelectedCamera(m_selectedDevice);
+ emit selectedDeviceChanged(index);
+ emit selectedDeviceChanged(deviceName(index));
+ }
+}
+
+void QAndroidVideoDeviceSelectorControl::update()
+{
+ m_names.clear();
+ m_descriptions.clear();
+
+ QJNIObject cameraInfo("android/hardware/Camera$CameraInfo");
+ int numCameras = QJNIObject::callStaticMethod<jint>("android/hardware/Camera",
+ "getNumberOfCameras");
+
+ for (int i = 0; i < numCameras; ++i) {
+ QJNIObject::callStaticMethod<void>("android/hardware/Camera",
+ "getCameraInfo",
+ "(ILandroid/hardware/Camera$CameraInfo;)V",
+ i, cameraInfo.object());
+
+ JCamera::CameraFacing facing = JCamera::CameraFacing(cameraInfo.getField<jint>("facing"));
+
+ switch (facing) {
+ case JCamera::CameraFacingBack:
+ m_names.append("back");
+ m_descriptions.append(QStringLiteral("Rear-facing camera"));
+ break;
+ case JCamera::CameraFacingFront:
+ m_names.append("front");
+ m_descriptions.append(QStringLiteral("Front-facing camera"));
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+QList<QByteArray> QAndroidVideoDeviceSelectorControl::availableDevices()
+{
+ if (m_names.isEmpty())
+ update();
+
+ return m_names;
+}
+
+QString QAndroidVideoDeviceSelectorControl::availableDeviceDescription(const QByteArray &device)
+{
+ int i = m_names.indexOf(device);
+ if (i != -1)
+ return m_descriptions.at(i);
+
+ return QString();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/android/src/mediacapture/qandroidvideodeviceselectorcontrol.h b/src/plugins/android/src/mediacapture/qandroidvideodeviceselectorcontrol.h
new file mode 100644
index 000000000..3ebf83ab2
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidvideodeviceselectorcontrol.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANDROIDVIDEODEVICESELECTORCONTROL_H
+#define QANDROIDVIDEODEVICESELECTORCONTROL_H
+
+#include <qvideodeviceselectorcontrol.h>
+#include <QtCore/qstringlist.h>
+
+QT_BEGIN_NAMESPACE
+
+class QAndroidCameraSession;
+
+class QAndroidVideoDeviceSelectorControl : public QVideoDeviceSelectorControl
+{
+ Q_OBJECT
+public:
+ explicit QAndroidVideoDeviceSelectorControl(QAndroidCameraSession *session);
+ ~QAndroidVideoDeviceSelectorControl();
+
+ int deviceCount() const;
+
+ QString deviceName(int index) const;
+ QString deviceDescription(int index) const;
+
+ int defaultDevice() const;
+ int selectedDevice() const;
+
+ void setSelectedDevice(int index);
+
+ static QList<QByteArray> availableDevices();
+ static QString availableDeviceDescription(const QByteArray &device);
+
+private:
+ static void update();
+
+ int m_selectedDevice;
+ static QList<QByteArray> m_names;
+ static QStringList m_descriptions;
+
+ QAndroidCameraSession *m_cameraSession;
+};
+
+QT_END_NAMESPACE
+
+#endif // QANDROIDVIDEODEVICESELECTORCONTROL_H
diff --git a/src/plugins/android/src/mediacapture/qandroidvideoencodersettingscontrol.cpp b/src/plugins/android/src/mediacapture/qandroidvideoencodersettingscontrol.cpp
new file mode 100644
index 000000000..20318c8bb
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidvideoencodersettingscontrol.cpp
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qandroidvideoencodersettingscontrol.h"
+
+#include "qandroidcapturesession.h"
+
+QT_BEGIN_NAMESPACE
+
+QAndroidVideoEncoderSettingsControl::QAndroidVideoEncoderSettingsControl(QAndroidCaptureSession *session)
+ : QVideoEncoderSettingsControl()
+ , m_session(session)
+{
+}
+
+QList<QSize> QAndroidVideoEncoderSettingsControl::supportedResolutions(const QVideoEncoderSettings &, bool *continuous) const
+{
+ if (continuous)
+ *continuous = false;
+
+ return m_session->supportedResolutions();
+}
+
+QList<qreal> QAndroidVideoEncoderSettingsControl::supportedFrameRates(const QVideoEncoderSettings &, bool *continuous) const
+{
+ if (continuous)
+ *continuous = false;
+
+ return m_session->supportedFrameRates();
+}
+
+QStringList QAndroidVideoEncoderSettingsControl::supportedVideoCodecs() const
+{
+ return QStringList() << QLatin1String("h263")
+ << QLatin1String("h264")
+ << QLatin1String("mpeg4_sp");
+}
+
+QString QAndroidVideoEncoderSettingsControl::videoCodecDescription(const QString &codecName) const
+{
+ if (codecName == QLatin1String("h263"))
+ return tr("H.263 compression");
+ else if (codecName == QLatin1String("h264"))
+ return tr("H.264 compression");
+ else if (codecName == QLatin1String("mpeg4_sp"))
+ return tr("MPEG-4 SP compression");
+
+ return QString();
+}
+
+QVideoEncoderSettings QAndroidVideoEncoderSettingsControl::videoSettings() const
+{
+ return m_session->videoSettings();
+}
+
+void QAndroidVideoEncoderSettingsControl::setVideoSettings(const QVideoEncoderSettings &settings)
+{
+ m_session->setVideoSettings(settings);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/android/src/mediacapture/qandroidvideoencodersettingscontrol.h b/src/plugins/android/src/mediacapture/qandroidvideoencodersettingscontrol.h
new file mode 100644
index 000000000..1427924c0
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidvideoencodersettingscontrol.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANDROIDVIDEOENCODERSETTINGSCONTROL_H
+#define QANDROIDVIDEOENCODERSETTINGSCONTROL_H
+
+#include <qvideoencodersettingscontrol.h>
+
+QT_BEGIN_NAMESPACE
+
+class QAndroidCaptureSession;
+
+class QAndroidVideoEncoderSettingsControl : public QVideoEncoderSettingsControl
+{
+ Q_OBJECT
+public:
+ explicit QAndroidVideoEncoderSettingsControl(QAndroidCaptureSession *session);
+
+ QList<QSize> supportedResolutions(const QVideoEncoderSettings &settings, bool *continuous = 0) const Q_DECL_OVERRIDE;
+ QList<qreal> supportedFrameRates(const QVideoEncoderSettings &settings, bool *continuous = 0) const Q_DECL_OVERRIDE;
+ QStringList supportedVideoCodecs() const Q_DECL_OVERRIDE;
+ QString videoCodecDescription(const QString &codecName) const Q_DECL_OVERRIDE;
+ QVideoEncoderSettings videoSettings() const Q_DECL_OVERRIDE;
+ void setVideoSettings(const QVideoEncoderSettings &settings) Q_DECL_OVERRIDE;
+
+private:
+ QAndroidCaptureSession *m_session;
+};
+
+QT_END_NAMESPACE
+
+#endif // QANDROIDVIDEOENCODERSETTINGSCONTROL_H
diff --git a/src/plugins/android/src/mediaplayer/mediaplayer.pri b/src/plugins/android/src/mediaplayer/mediaplayer.pri
new file mode 100644
index 000000000..c386d996b
--- /dev/null
+++ b/src/plugins/android/src/mediaplayer/mediaplayer.pri
@@ -0,0 +1,11 @@
+INCLUDEPATH += $$PWD
+
+HEADERS += \
+ $$PWD/qandroidmediaplayercontrol.h \
+ $$PWD/qandroidmediaservice.h \
+ $$PWD/qandroidmetadatareadercontrol.h
+
+SOURCES += \
+ $$PWD/qandroidmediaplayercontrol.cpp \
+ $$PWD/qandroidmediaservice.cpp \
+ $$PWD/qandroidmetadatareadercontrol.cpp
diff --git a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp
new file mode 100644
index 000000000..753c60662
--- /dev/null
+++ b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp
@@ -0,0 +1,535 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qandroidmediaplayercontrol.h"
+#include "jmediaplayer.h"
+#include "qandroidvideooutput.h"
+
+QT_BEGIN_NAMESPACE
+
+static void textureReadyCallback(void *context)
+{
+ if (context)
+ reinterpret_cast<QAndroidMediaPlayerControl *>(context)->onSurfaceTextureReady();
+}
+
+QAndroidMediaPlayerControl::QAndroidMediaPlayerControl(QObject *parent)
+ : QMediaPlayerControl(parent),
+ mMediaPlayer(new JMediaPlayer),
+ mCurrentState(QMediaPlayer::StoppedState),
+ mCurrentMediaStatus(QMediaPlayer::NoMedia),
+ mMediaStream(0),
+ mVideoOutput(0),
+ mSeekable(true),
+ mBufferPercent(-1),
+ mAudioAvailable(false),
+ mVideoAvailable(false),
+ mBuffering(false),
+ mMediaPlayerReady(false),
+ mPendingPosition(-1),
+ mPendingSetMedia(false)
+{
+ connect(mMediaPlayer, SIGNAL(bufferingUpdate(qint32)),
+ this, SLOT(onBufferChanged(qint32)));
+ connect(mMediaPlayer, SIGNAL(info(qint32, qint32)),
+ this, SLOT(onInfo(qint32, qint32)));
+ connect(mMediaPlayer, SIGNAL(error(qint32, qint32)),
+ this, SLOT(onError(qint32, qint32)));
+ connect(mMediaPlayer, SIGNAL(mediaPlayerInfo(qint32, qint32)),
+ this, SLOT(onMediaPlayerInfo(qint32, qint32)));
+ connect(mMediaPlayer, SIGNAL(videoSizeChanged(qint32,qint32)),
+ this, SLOT(onVideoSizeChanged(qint32,qint32)));
+}
+
+QAndroidMediaPlayerControl::~QAndroidMediaPlayerControl()
+{
+ mMediaPlayer->stop();
+ mMediaPlayer->release();
+ delete mMediaPlayer;
+}
+
+QMediaPlayer::State QAndroidMediaPlayerControl::state() const
+{
+ return mCurrentState;
+}
+
+QMediaPlayer::MediaStatus QAndroidMediaPlayerControl::mediaStatus() const
+{
+ return mCurrentMediaStatus;
+}
+
+qint64 QAndroidMediaPlayerControl::duration() const
+{
+ return (mCurrentMediaStatus == QMediaPlayer::InvalidMedia
+ || mCurrentMediaStatus == QMediaPlayer::NoMedia
+ || !mMediaPlayerReady) ? 0
+ : mMediaPlayer->getDuration();
+}
+
+qint64 QAndroidMediaPlayerControl::position() const
+{
+ if (!mMediaPlayerReady)
+ return mPendingPosition < 0 ? 0 : mPendingPosition;
+
+ return mMediaPlayer->getCurrentPosition();
+}
+
+void QAndroidMediaPlayerControl::setPosition(qint64 position)
+{
+ if (!mSeekable)
+ return;
+
+ const int seekPosition = (position > INT_MAX) ? INT_MAX : position;
+
+ if (!mMediaPlayerReady) {
+ mPendingPosition = seekPosition;
+ Q_EMIT positionChanged(seekPosition);
+ return;
+ }
+
+ mMediaPlayer->seekTo(seekPosition);
+ mPendingPosition = -1;
+}
+
+int QAndroidMediaPlayerControl::volume() const
+{
+ return mMediaPlayer->volume();
+}
+
+void QAndroidMediaPlayerControl::setVolume(int volume)
+{
+ mMediaPlayer->setVolume(volume);
+ Q_EMIT volumeChanged(volume);
+}
+
+bool QAndroidMediaPlayerControl::isMuted() const
+{
+ return mMediaPlayer->isMuted();
+}
+
+void QAndroidMediaPlayerControl::setMuted(bool muted)
+{
+ mMediaPlayer->setMuted(muted);
+ Q_EMIT mutedChanged(muted);
+}
+
+int QAndroidMediaPlayerControl::bufferStatus() const
+{
+ return mBufferPercent;
+}
+
+bool QAndroidMediaPlayerControl::isAudioAvailable() const
+{
+ return mAudioAvailable;
+}
+
+bool QAndroidMediaPlayerControl::isVideoAvailable() const
+{
+ return mVideoAvailable;
+}
+
+bool QAndroidMediaPlayerControl::isSeekable() const
+{
+ return mSeekable;
+}
+
+QMediaTimeRange QAndroidMediaPlayerControl::availablePlaybackRanges() const
+{
+ return mAvailablePlaybackRange;
+}
+
+void QAndroidMediaPlayerControl::updateAvailablePlaybackRanges()
+{
+ if (mBuffering) {
+ const qint64 pos = position();
+ const qint64 end = (duration() / 100) * mBufferPercent;
+ mAvailablePlaybackRange.addInterval(pos, end);
+ } else if (mSeekable) {
+ mAvailablePlaybackRange = QMediaTimeRange(0, duration());
+ } else {
+ mAvailablePlaybackRange = QMediaTimeRange();
+ }
+
+ Q_EMIT availablePlaybackRangesChanged(mAvailablePlaybackRange);
+}
+
+qreal QAndroidMediaPlayerControl::playbackRate() const
+{
+ return 1.0f;
+}
+
+void QAndroidMediaPlayerControl::setPlaybackRate(qreal rate)
+{
+ Q_UNUSED(rate);
+}
+
+QMediaContent QAndroidMediaPlayerControl::media() const
+{
+ return mMediaContent;
+}
+
+const QIODevice *QAndroidMediaPlayerControl::mediaStream() const
+{
+ return mMediaStream;
+}
+
+void QAndroidMediaPlayerControl::setMedia(const QMediaContent &mediaContent,
+ QIODevice *stream)
+{
+ mMediaContent = mediaContent;
+ mMediaStream = stream;
+
+ if (mVideoOutput && !mMediaPlayer->display()) {
+ // if a video output is set but the video texture is not ready, delay loading the media
+ // since it can cause problems on some hardware
+ mPendingSetMedia = true;
+ return;
+ }
+
+ const QString uri = mediaContent.canonicalUrl().toString();
+
+ if (!uri.isEmpty())
+ mMediaPlayer->setDataSource(uri);
+ else
+ setMediaStatus(QMediaPlayer::NoMedia);
+
+ Q_EMIT mediaChanged(mMediaContent);
+
+ resetBufferingProgress();
+
+ // reset some properties
+ setAudioAvailable(false);
+ setVideoAvailable(false);
+ setSeekable(true);
+}
+
+void QAndroidMediaPlayerControl::setVideoOutput(QAndroidVideoOutput *videoOutput)
+{
+ if (mVideoOutput)
+ mVideoOutput->stop();
+
+ mVideoOutput = videoOutput;
+
+ if (mVideoOutput && !mMediaPlayer->display()) {
+ if (mVideoOutput->isTextureReady())
+ mMediaPlayer->setDisplay(mVideoOutput->surfaceHolder());
+ else
+ mVideoOutput->setTextureReadyCallback(textureReadyCallback, this);
+ }
+}
+
+void QAndroidMediaPlayerControl::play()
+{
+ if (!mMediaPlayerReady) {
+ mPendingState = QMediaPlayer::PlayingState;
+ if (mCurrentState == QMediaPlayer::StoppedState
+ && !mMediaContent.isNull()
+ && mCurrentMediaStatus != QMediaPlayer::LoadingMedia
+ && !mPendingSetMedia) {
+ setMedia(mMediaContent, 0);
+ }
+ return;
+ }
+
+ mMediaPlayer->play();
+ setState(QMediaPlayer::PlayingState);
+}
+
+void QAndroidMediaPlayerControl::pause()
+{
+ if (!mMediaPlayerReady) {
+ mPendingState = QMediaPlayer::PausedState;
+ return;
+ }
+
+ mMediaPlayer->pause();
+ setState(QMediaPlayer::PausedState);
+}
+
+void QAndroidMediaPlayerControl::stop()
+{
+ mMediaPlayer->stop();
+ setState(QMediaPlayer::StoppedState);
+}
+
+void QAndroidMediaPlayerControl::onInfo(qint32 what, qint32 extra)
+{
+ Q_UNUSED(extra);
+ switch (what) {
+ case JMediaPlayer::MEDIA_INFO_UNKNOWN:
+ break;
+ case JMediaPlayer::MEDIA_INFO_VIDEO_TRACK_LAGGING:
+ // IGNORE
+ break;
+ case JMediaPlayer::MEDIA_INFO_VIDEO_RENDERING_START:
+ break;
+ case JMediaPlayer::MEDIA_INFO_BUFFERING_START:
+ mPendingState = mCurrentState;
+ setState(QMediaPlayer::PausedState);
+ setMediaStatus(QMediaPlayer::StalledMedia);
+ break;
+ case JMediaPlayer::MEDIA_INFO_BUFFERING_END:
+ setMediaStatus(mBufferPercent == 100 ? QMediaPlayer::BufferedMedia : QMediaPlayer::BufferingMedia);
+ flushPendingStates();
+ break;
+ case JMediaPlayer::MEDIA_INFO_BAD_INTERLEAVING:
+ break;
+ case JMediaPlayer::MEDIA_INFO_NOT_SEEKABLE:
+ setSeekable(false);
+ break;
+ case JMediaPlayer::MEDIA_INFO_METADATA_UPDATE:
+ Q_EMIT metaDataUpdated();
+ break;
+ }
+}
+
+void QAndroidMediaPlayerControl::onMediaPlayerInfo(qint32 what, qint32 extra)
+{
+ switch (what) {
+ case JMediaPlayer::MEDIA_PLAYER_INVALID_STATE:
+ setError(what, QStringLiteral("Error: Invalid state"));
+ break;
+ case JMediaPlayer::MEDIA_PLAYER_PREPARING:
+ setMediaStatus(QMediaPlayer::LoadingMedia);
+ setState(QMediaPlayer::StoppedState);
+ break;
+ case JMediaPlayer::MEDIA_PLAYER_READY:
+ setMediaStatus(QMediaPlayer::LoadedMedia);
+ if (mBuffering) {
+ setMediaStatus(mBufferPercent == 100 ? QMediaPlayer::BufferedMedia
+ : QMediaPlayer::BufferingMedia);
+ } else {
+ onBufferChanged(100);
+ }
+ setAudioAvailable(true);
+ mMediaPlayerReady = true;
+ flushPendingStates();
+ break;
+ case JMediaPlayer::MEDIA_PLAYER_DURATION:
+ Q_EMIT durationChanged(extra);
+ break;
+ case JMediaPlayer::MEDIA_PLAYER_PROGRESS:
+ Q_EMIT positionChanged(extra);
+ break;
+ case JMediaPlayer::MEDIA_PLAYER_FINISHED:
+ setState(QMediaPlayer::StoppedState);
+ setMediaStatus(QMediaPlayer::EndOfMedia);
+ break;
+ }
+}
+
+void QAndroidMediaPlayerControl::onError(qint32 what, qint32 extra)
+{
+ QString errorString;
+ QMediaPlayer::Error error = QMediaPlayer::ResourceError;
+
+ switch (what) {
+ case JMediaPlayer::MEDIA_ERROR_UNKNOWN:
+ errorString = QLatin1String("Error:");
+ break;
+ case JMediaPlayer::MEDIA_ERROR_SERVER_DIED:
+ errorString = QLatin1String("Error: Server died");
+ error = QMediaPlayer::ServiceMissingError;
+ break;
+ }
+
+ switch (extra) {
+ case JMediaPlayer::MEDIA_ERROR_IO: // Network OR file error
+ errorString += QLatin1String(" (I/O operation failed)");
+ error = QMediaPlayer::NetworkError;
+ setMediaStatus(QMediaPlayer::InvalidMedia);
+ break;
+ case JMediaPlayer::MEDIA_ERROR_MALFORMED:
+ errorString += QLatin1String(" (Malformed bitstream)");
+ error = QMediaPlayer::FormatError;
+ setMediaStatus(QMediaPlayer::InvalidMedia);
+ break;
+ case JMediaPlayer::MEDIA_ERROR_UNSUPPORTED:
+ errorString += QLatin1String(" (Unsupported media)");
+ error = QMediaPlayer::FormatError;
+ setMediaStatus(QMediaPlayer::InvalidMedia);
+ break;
+ case JMediaPlayer::MEDIA_ERROR_TIMED_OUT:
+ errorString += QLatin1String(" (Timed out)");
+ break;
+ case JMediaPlayer::MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK:
+ errorString += QLatin1String(" (Unable to start progressive playback')");
+ error = QMediaPlayer::FormatError;
+ setMediaStatus(QMediaPlayer::InvalidMedia);
+ break;
+ }
+
+ setError(error, errorString);
+}
+
+void QAndroidMediaPlayerControl::onBufferChanged(qint32 percent)
+{
+ mBuffering = percent != 100;
+ mBufferPercent = percent;
+ Q_EMIT bufferStatusChanged(mBufferPercent);
+
+ updateAvailablePlaybackRanges();
+
+ if (mBufferPercent == 100)
+ setMediaStatus(QMediaPlayer::BufferedMedia);
+}
+
+void QAndroidMediaPlayerControl::onVideoSizeChanged(qint32 width, qint32 height)
+{
+ QSize newSize(width, height);
+
+ if (width == 0 || height == 0 || newSize == mVideoSize)
+ return;
+
+ setVideoAvailable(true);
+ mVideoSize = newSize;
+
+ if (mVideoOutput)
+ mVideoOutput->setVideoSize(mVideoSize);
+}
+
+void QAndroidMediaPlayerControl::onSurfaceTextureReady()
+{
+ if (!mMediaPlayer->display() && mVideoOutput) {
+ mMediaPlayer->setDisplay(mVideoOutput->surfaceHolder());
+ flushPendingStates();
+ }
+}
+
+void QAndroidMediaPlayerControl::setState(QMediaPlayer::State state)
+{
+ if (mCurrentState == state)
+ return;
+
+ if (state == QMediaPlayer::StoppedState) {
+ if (mVideoOutput)
+ mVideoOutput->stop();
+ resetBufferingProgress();
+ mMediaPlayerReady = false;
+ mPendingPosition = -1;
+ Q_EMIT positionChanged(0);
+ }
+
+ mCurrentState = state;
+ Q_EMIT stateChanged(mCurrentState);
+}
+
+void QAndroidMediaPlayerControl::setMediaStatus(QMediaPlayer::MediaStatus status)
+{
+ if (mCurrentMediaStatus == status)
+ return;
+
+ if (status == QMediaPlayer::NoMedia || status == QMediaPlayer::InvalidMedia)
+ Q_EMIT durationChanged(0);
+
+ mCurrentMediaStatus = status;
+ Q_EMIT mediaStatusChanged(mCurrentMediaStatus);
+}
+
+void QAndroidMediaPlayerControl::setError(int error,
+ const QString &errorString)
+{
+ setState(QMediaPlayer::StoppedState);
+ Q_EMIT QMediaPlayerControl::error(error, errorString);
+}
+
+void QAndroidMediaPlayerControl::setSeekable(bool seekable)
+{
+ if (mSeekable == seekable)
+ return;
+
+ mSeekable = seekable;
+ Q_EMIT seekableChanged(mSeekable);
+}
+
+void QAndroidMediaPlayerControl::setAudioAvailable(bool available)
+{
+ if (mAudioAvailable == available)
+ return;
+
+ mAudioAvailable = available;
+ Q_EMIT audioAvailableChanged(mAudioAvailable);
+}
+
+void QAndroidMediaPlayerControl::setVideoAvailable(bool available)
+{
+ if (mVideoAvailable == available)
+ return;
+
+ if (!available)
+ mVideoSize = QSize();
+
+ mVideoAvailable = available;
+ Q_EMIT videoAvailableChanged(mVideoAvailable);
+}
+
+void QAndroidMediaPlayerControl::resetBufferingProgress()
+{
+ mBuffering = false;
+ mBufferPercent = 0;
+ mAvailablePlaybackRange = QMediaTimeRange();
+ Q_EMIT bufferStatusChanged(mBufferPercent);
+}
+
+void QAndroidMediaPlayerControl::flushPendingStates()
+{
+ if (mPendingSetMedia) {
+ setMedia(mMediaContent, 0);
+ mPendingSetMedia = false;
+ return;
+ }
+
+ switch (mPendingState) {
+ case QMediaPlayer::PlayingState:
+ if (mPendingPosition > -1)
+ setPosition(mPendingPosition);
+ play();
+ break;
+ case QMediaPlayer::PausedState:
+ pause();
+ break;
+ case QMediaPlayer::StoppedState:
+ stop();
+ break;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h
new file mode 100644
index 000000000..93eced853
--- /dev/null
+++ b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANDROIDMEDIAPLAYERCONTROL_H
+#define QANDROIDMEDIAPLAYERCONTROL_H
+
+#include <qglobal.h>
+#include <QMediaPlayerControl>
+#include <qsize.h>
+
+QT_BEGIN_NAMESPACE
+
+class JMediaPlayer;
+class QAndroidVideoOutput;
+
+class QAndroidMediaPlayerControl : public QMediaPlayerControl
+{
+ Q_OBJECT
+public:
+ explicit QAndroidMediaPlayerControl(QObject *parent = 0);
+ ~QAndroidMediaPlayerControl() Q_DECL_OVERRIDE;
+
+ QMediaPlayer::State state() const Q_DECL_OVERRIDE;
+ QMediaPlayer::MediaStatus mediaStatus() const Q_DECL_OVERRIDE;
+ qint64 duration() const Q_DECL_OVERRIDE;
+ qint64 position() const Q_DECL_OVERRIDE;
+ int volume() const Q_DECL_OVERRIDE;
+ bool isMuted() const Q_DECL_OVERRIDE;
+ int bufferStatus() const Q_DECL_OVERRIDE;
+ bool isAudioAvailable() const Q_DECL_OVERRIDE;
+ bool isVideoAvailable() const Q_DECL_OVERRIDE;
+ bool isSeekable() const Q_DECL_OVERRIDE;
+ QMediaTimeRange availablePlaybackRanges() const Q_DECL_OVERRIDE;
+ qreal playbackRate() const Q_DECL_OVERRIDE;
+ void setPlaybackRate(qreal rate) Q_DECL_OVERRIDE;
+ QMediaContent media() const Q_DECL_OVERRIDE;
+ const QIODevice *mediaStream() const Q_DECL_OVERRIDE;
+ void setMedia(const QMediaContent &mediaContent, QIODevice *stream) Q_DECL_OVERRIDE;
+
+ void setVideoOutput(QAndroidVideoOutput *videoOutput);
+ void onSurfaceTextureReady();
+
+Q_SIGNALS:
+ void metaDataUpdated();
+
+public Q_SLOTS:
+ void setPosition(qint64 position) Q_DECL_OVERRIDE;
+ void play() Q_DECL_OVERRIDE;
+ void pause() Q_DECL_OVERRIDE;
+ void stop() Q_DECL_OVERRIDE;
+ void setVolume(int volume) Q_DECL_OVERRIDE;
+ void setMuted(bool muted) Q_DECL_OVERRIDE;
+
+private Q_SLOTS:
+ void onError(qint32 what, qint32 extra);
+ void onInfo(qint32 what, qint32 extra);
+ void onMediaPlayerInfo(qint32 what, qint32 extra);
+ void onBufferChanged(qint32 percent);
+ void onVideoSizeChanged(qint32 width, qint32 height);
+
+private:
+ JMediaPlayer *mMediaPlayer;
+ QMediaPlayer::State mCurrentState;
+ QMediaPlayer::MediaStatus mCurrentMediaStatus;
+ QMediaContent mMediaContent;
+ QIODevice *mMediaStream;
+ QAndroidVideoOutput *mVideoOutput;
+ bool mSeekable;
+ int mBufferPercent;
+ bool mAudioAvailable;
+ bool mVideoAvailable;
+ QSize mVideoSize;
+ bool mBuffering;
+ QMediaTimeRange mAvailablePlaybackRange;
+ bool mMediaPlayerReady;
+ QMediaPlayer::State mPendingState;
+ qint64 mPendingPosition;
+ bool mPendingSetMedia;
+
+ void setState(QMediaPlayer::State state);
+ void setMediaStatus(QMediaPlayer::MediaStatus status);
+ void setError(int error, const QString &errorString);
+ void setSeekable(bool seekable);
+ void setAudioAvailable(bool available);
+ void setVideoAvailable(bool available);
+ void updateAvailablePlaybackRanges();
+ void resetBufferingProgress();
+ void flushPendingStates();
+};
+
+QT_END_NAMESPACE
+
+#endif // QANDROIDMEDIAPLAYERCONTROL_H
diff --git a/src/plugins/android/src/mediaplayer/qandroidmediaservice.cpp b/src/plugins/android/src/mediaplayer/qandroidmediaservice.cpp
new file mode 100644
index 000000000..175958676
--- /dev/null
+++ b/src/plugins/android/src/mediaplayer/qandroidmediaservice.cpp
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qandroidmediaservice.h"
+
+#include "qandroidmediaplayercontrol.h"
+#include "qandroidmetadatareadercontrol.h"
+#include "qandroidvideorendercontrol.h"
+
+QT_BEGIN_NAMESPACE
+
+QAndroidMediaService::QAndroidMediaService(QObject *parent)
+ : QMediaService(parent)
+ , mVideoRendererControl(0)
+{
+ mMediaControl = new QAndroidMediaPlayerControl;
+ mMetadataControl = new QAndroidMetaDataReaderControl;
+ connect(mMediaControl, SIGNAL(mediaChanged(QMediaContent)),
+ mMetadataControl, SLOT(onMediaChanged(QMediaContent)));
+ connect(mMediaControl, SIGNAL(metaDataUpdated()),
+ mMetadataControl, SLOT(onUpdateMetaData()));
+}
+
+QAndroidMediaService::~QAndroidMediaService()
+{
+ delete mMediaControl;
+ delete mMetadataControl;
+ delete mVideoRendererControl;
+}
+
+QMediaControl *QAndroidMediaService::requestControl(const char *name)
+{
+ if (qstrcmp(name, QMediaPlayerControl_iid) == 0)
+ return mMediaControl;
+
+ if (qstrcmp(name, QMetaDataReaderControl_iid) == 0)
+ return mMetadataControl;
+
+ if (qstrcmp(name, QVideoRendererControl_iid) == 0) {
+ if (!mVideoRendererControl) {
+ mVideoRendererControl = new QAndroidVideoRendererControl;
+ mMediaControl->setVideoOutput(mVideoRendererControl);
+ return mVideoRendererControl;
+ }
+ }
+
+ return 0;
+}
+
+void QAndroidMediaService::releaseControl(QMediaControl *control)
+{
+ if (control == mVideoRendererControl) {
+ mMediaControl->setVideoOutput(0);
+ delete mVideoRendererControl;
+ mVideoRendererControl = 0;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/android/src/mediaplayer/qandroidmediaservice.h b/src/plugins/android/src/mediaplayer/qandroidmediaservice.h
new file mode 100644
index 000000000..4d310e8e0
--- /dev/null
+++ b/src/plugins/android/src/mediaplayer/qandroidmediaservice.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANDROIDMEDIASERVICE_H
+#define QANDROIDMEDIASERVICE_H
+
+#include <QMediaService>
+
+QT_BEGIN_NAMESPACE
+
+class QAndroidMediaPlayerControl;
+class QAndroidMetaDataReaderControl;
+class QAndroidVideoRendererControl;
+
+class QAndroidMediaService : public QMediaService
+{
+ Q_OBJECT
+public:
+ explicit QAndroidMediaService(QObject *parent = 0);
+ ~QAndroidMediaService() Q_DECL_OVERRIDE;
+
+ QMediaControl* requestControl(const char *name) Q_DECL_OVERRIDE;
+ void releaseControl(QMediaControl *control) Q_DECL_OVERRIDE;
+
+private:
+ QAndroidMediaPlayerControl *mMediaControl;
+ QAndroidMetaDataReaderControl *mMetadataControl;
+ QAndroidVideoRendererControl *mVideoRendererControl;
+};
+
+QT_END_NAMESPACE
+
+#endif // QANDROIDMEDIASERVICE_H
diff --git a/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.cpp b/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.cpp
new file mode 100644
index 000000000..e52c46387
--- /dev/null
+++ b/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.cpp
@@ -0,0 +1,222 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qandroidmetadatareadercontrol.h"
+
+#include "jmediametadataretriever.h"
+#include <QtMultimedia/qmediametadata.h>
+#include <qsize.h>
+#include <QDate>
+
+QT_BEGIN_NAMESPACE
+
+// Genre name ordered by ID
+// see: http://id3.org/id3v2.3.0#Appendix_A_-_Genre_List_from_ID3v1
+static const char* qt_ID3GenreNames[] =
+{
+ "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge", "Hip-Hop", "Jazz",
+ "Metal", "New Age", "Oldies", "Other", "Pop", "R&B", "Rap", "Reggae", "Rock", "Techno",
+ "Industrial", "Alternative", "Ska", "Death Metal", "Pranks", "Soundtrack", "Euro-Techno",
+ "Ambient", "Trip-Hop", "Vocal", "Jazz+Funk", "Fusion", "Trance", "Classical", "Instrumental",
+ "Acid", "House", "Game", "Sound Clip", "Gospel", "Noise", "AlternRock", "Bass", "Soul", "Punk",
+ "Space", "Meditative", "Instrumental Pop", "Instrumental Rock", "Ethnic", "Gothic", "Darkwave",
+ "Techno-Industrial", "Electronic", "Pop-Folk", "Eurodance", "Dream", "Southern Rock", "Comedy",
+ "Cult", "Gangsta", "Top 40", "Christian Rap", "Pop/Funk", "Jungle", "Native American",
+ "Cabaret", "New Wave", "Psychadelic", "Rave", "Showtunes", "Trailer", "Lo-Fi", "Tribal",
+ "Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical", "Rock & Roll", "Hard Rock", "Folk",
+ "Folk-Rock", "National Folk", "Swing", "Fast Fusion", "Bebob", "Latin", "Revival", "Celtic",
+ "Bluegrass", "Avantgarde", "Gothic Rock", "Progressive Rock", "Psychedelic Rock",
+ "Symphonic Rock", "Slow Rock", "Big Band", "Chorus", "Easy Listening", "Acoustic", "Humour",
+ "Speech", "Chanson", "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass", "Primus",
+ "Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba", "Folklore", "Ballad",
+ "Power Ballad", "Rhythmic Soul", "Freestyle", "Duet", "Punk Rock", "Drum Solo", "A capella",
+ "Euro-House", "Dance Hall"
+};
+
+QAndroidMetaDataReaderControl::QAndroidMetaDataReaderControl(QObject *parent)
+ : QMetaDataReaderControl(parent)
+ , m_available(false)
+ , m_retriever(0)
+{
+ m_retriever = new JMediaMetadataRetriever;
+ if (!m_retriever->isValid()) {
+ delete m_retriever;
+ m_retriever = 0;
+ }
+}
+
+QAndroidMetaDataReaderControl::~QAndroidMetaDataReaderControl()
+{
+ if (m_retriever) {
+ m_retriever->release();
+ delete m_retriever;
+ }
+}
+
+bool QAndroidMetaDataReaderControl::isMetaDataAvailable() const
+{
+ return m_available;
+}
+
+QVariant QAndroidMetaDataReaderControl::metaData(const QString &key) const
+{
+ return m_metadata.value(key);
+}
+
+QStringList QAndroidMetaDataReaderControl::availableMetaData() const
+{
+ return m_metadata.keys();
+}
+
+void QAndroidMetaDataReaderControl::onMediaChanged(const QMediaContent &media)
+{
+ if (!m_retriever)
+ return;
+
+ m_mediaContent = media;
+ updateData();
+}
+
+void QAndroidMetaDataReaderControl::onUpdateMetaData()
+{
+ if (!m_retriever || m_mediaContent.isNull())
+ return;
+
+ updateData();
+}
+
+void QAndroidMetaDataReaderControl::updateData()
+{
+ m_metadata.clear();
+
+ if (!m_mediaContent.isNull()) {
+ if (m_retriever->setDataSource(m_mediaContent.canonicalUrl())) {
+ QString mimeType = m_retriever->extractMetadata(JMediaMetadataRetriever::MimeType);
+ if (!mimeType.isNull())
+ m_metadata.insert(QMediaMetaData::MediaType, mimeType);
+
+ bool isVideo = !m_retriever->extractMetadata(JMediaMetadataRetriever::HasVideo).isNull()
+ || mimeType.startsWith(QStringLiteral("video"));
+
+ QString string = m_retriever->extractMetadata(JMediaMetadataRetriever::Album);
+ if (!string.isNull())
+ m_metadata.insert(QMediaMetaData::AlbumTitle, string);
+
+ string = m_retriever->extractMetadata(JMediaMetadataRetriever::AlbumArtist);
+ if (!string.isNull())
+ m_metadata.insert(QMediaMetaData::AlbumArtist, string);
+
+ string = m_retriever->extractMetadata(JMediaMetadataRetriever::Artist);
+ if (!string.isNull()) {
+ m_metadata.insert(isVideo ? QMediaMetaData::LeadPerformer
+ : QMediaMetaData::ContributingArtist,
+ string.split('/', QString::SkipEmptyParts));
+ }
+
+ string = m_retriever->extractMetadata(JMediaMetadataRetriever::Author);
+ if (!string.isNull())
+ m_metadata.insert(QMediaMetaData::Author, string.split('/', QString::SkipEmptyParts));
+
+ string = m_retriever->extractMetadata(JMediaMetadataRetriever::Bitrate);
+ if (!string.isNull()) {
+ m_metadata.insert(isVideo ? QMediaMetaData::VideoBitRate
+ : QMediaMetaData::AudioBitRate,
+ string.toInt());
+ }
+
+ string = m_retriever->extractMetadata(JMediaMetadataRetriever::CDTrackNumber);
+ if (!string.isNull())
+ m_metadata.insert(QMediaMetaData::TrackNumber, string.toInt());
+
+ string = m_retriever->extractMetadata(JMediaMetadataRetriever::Composer);
+ if (!string.isNull())
+ m_metadata.insert(QMediaMetaData::Composer, string.split('/', QString::SkipEmptyParts));
+
+ string = m_retriever->extractMetadata(JMediaMetadataRetriever::Date);
+ if (!string.isNull())
+ m_metadata.insert(QMediaMetaData::Date, QDateTime::fromString(string, QStringLiteral("yyyyMMddTHHmmss.zzzZ")).date());
+
+ string = m_retriever->extractMetadata(JMediaMetadataRetriever::Duration);
+ if (!string.isNull())
+ m_metadata.insert(QMediaMetaData::Duration, string.toLongLong());
+
+ string = m_retriever->extractMetadata(JMediaMetadataRetriever::Genre);
+ if (!string.isNull()) {
+ // The genre can be returned as an ID3v2 id, get the name for it in that case
+ if (string.startsWith('(') && string.endsWith(')')) {
+ bool ok = false;
+ int genreId = string.mid(1, string.length() - 2).toInt(&ok);
+ if (ok && genreId >= 0 && genreId <= 125)
+ string = QLatin1String(qt_ID3GenreNames[genreId]);
+ }
+ m_metadata.insert(QMediaMetaData::Genre, string);
+ }
+
+ string = m_retriever->extractMetadata(JMediaMetadataRetriever::Title);
+ if (!string.isNull())
+ m_metadata.insert(QMediaMetaData::Title, string);
+
+ string = m_retriever->extractMetadata(JMediaMetadataRetriever::VideoHeight);
+ if (!string.isNull()) {
+ int height = string.toInt();
+ int width = m_retriever->extractMetadata(JMediaMetadataRetriever::VideoWidth).toInt();
+ m_metadata.insert(QMediaMetaData::Resolution, QSize(width, height));
+ }
+
+ string = m_retriever->extractMetadata(JMediaMetadataRetriever::Writer);
+ if (!string.isNull())
+ m_metadata.insert(QMediaMetaData::Writer, string.split('/', QString::SkipEmptyParts));
+
+ string = m_retriever->extractMetadata(JMediaMetadataRetriever::Year);
+ if (!string.isNull())
+ m_metadata.insert(QMediaMetaData::Year, string.toInt());
+ }
+ }
+
+ bool oldAvailable = m_available;
+ m_available = !m_metadata.isEmpty();
+ if (m_available != oldAvailable)
+ Q_EMIT metaDataAvailableChanged(m_available);
+
+ Q_EMIT metaDataChanged();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.h b/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.h
new file mode 100644
index 000000000..7ea736ffd
--- /dev/null
+++ b/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANDROIDMETADATAREADERCONTROL_H
+#define QANDROIDMETADATAREADERCONTROL_H
+
+#include <QMetaDataReaderControl>
+#include <qmediacontent.h>
+
+QT_BEGIN_NAMESPACE
+
+class JMediaMetadataRetriever;
+
+class QAndroidMetaDataReaderControl : public QMetaDataReaderControl
+{
+ Q_OBJECT
+public:
+ explicit QAndroidMetaDataReaderControl(QObject *parent = 0);
+ ~QAndroidMetaDataReaderControl() Q_DECL_OVERRIDE;
+
+ bool isMetaDataAvailable() const Q_DECL_OVERRIDE;
+
+ QVariant metaData(const QString &key) const Q_DECL_OVERRIDE;
+ QStringList availableMetaData() const Q_DECL_OVERRIDE;
+
+public Q_SLOTS:
+ void onMediaChanged(const QMediaContent &media);
+ void onUpdateMetaData();
+
+private:
+ void updateData();
+
+ QMediaContent m_mediaContent;
+ bool m_available;
+ QVariantMap m_metadata;
+
+ JMediaMetadataRetriever *m_retriever;
+};
+
+QT_END_NAMESPACE
+
+#endif // QANDROIDMETADATAREADERCONTROL_H
diff --git a/src/plugins/android/src/qandroidmediaserviceplugin.cpp b/src/plugins/android/src/qandroidmediaserviceplugin.cpp
new file mode 100644
index 000000000..d7a2cd29f
--- /dev/null
+++ b/src/plugins/android/src/qandroidmediaserviceplugin.cpp
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qandroidmediaserviceplugin.h"
+
+#include "qandroidmediaservice.h"
+#include "qandroidcaptureservice.h"
+#include "qandroidvideodeviceselectorcontrol.h"
+#include "qandroidaudioinputselectorcontrol.h"
+#include "jmediaplayer.h"
+#include "jsurfacetexture.h"
+#include "jsurfacetextureholder.h"
+#include "jcamera.h"
+#include "jmultimediautils.h"
+#include "jmediarecorder.h"
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+QAndroidMediaServicePlugin::QAndroidMediaServicePlugin()
+{
+}
+
+QAndroidMediaServicePlugin::~QAndroidMediaServicePlugin()
+{
+}
+
+QMediaService *QAndroidMediaServicePlugin::create(const QString &key)
+{
+ if (key == QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER))
+ return new QAndroidMediaService;
+
+ if (key == QLatin1String(Q_MEDIASERVICE_CAMERA)
+ || key == QLatin1String(Q_MEDIASERVICE_AUDIOSOURCE)) {
+ return new QAndroidCaptureService(key);
+ }
+
+ qWarning() << "Android service plugin: unsupported key:" << key;
+ return 0;
+}
+
+void QAndroidMediaServicePlugin::release(QMediaService *service)
+{
+ delete service;
+}
+
+QMediaServiceProviderHint::Features QAndroidMediaServicePlugin::supportedFeatures(const QByteArray &service) const
+{
+ if (service == Q_MEDIASERVICE_MEDIAPLAYER)
+ return QMediaServiceProviderHint::VideoSurface;
+
+ if (service == Q_MEDIASERVICE_CAMERA)
+ return QMediaServiceProviderHint::VideoSurface | QMediaServiceProviderHint::RecordingSupport;
+
+ if (service == Q_MEDIASERVICE_AUDIOSOURCE)
+ return QMediaServiceProviderHint::RecordingSupport;
+
+ return QMediaServiceProviderHint::Features();
+}
+
+QList<QByteArray> QAndroidMediaServicePlugin::devices(const QByteArray &service) const
+{
+ if (service == Q_MEDIASERVICE_CAMERA)
+ return QAndroidVideoDeviceSelectorControl::availableDevices();
+
+ if (service == Q_MEDIASERVICE_AUDIOSOURCE)
+ return QAndroidAudioInputSelectorControl::availableDevices();
+
+ return QList<QByteArray>();
+}
+
+QString QAndroidMediaServicePlugin::deviceDescription(const QByteArray &service, const QByteArray &device)
+{
+ if (service == Q_MEDIASERVICE_CAMERA)
+ return QAndroidVideoDeviceSelectorControl::availableDeviceDescription(device);
+
+ if (service == Q_MEDIASERVICE_AUDIOSOURCE)
+ return QAndroidAudioInputSelectorControl::availableDeviceDescription(device);
+
+ return QString();
+}
+
+
+Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void * /*reserved*/)
+{
+ typedef union {
+ JNIEnv *nativeEnvironment;
+ void *venv;
+ } UnionJNIEnvToVoid;
+
+ UnionJNIEnvToVoid uenv;
+ uenv.venv = NULL;
+
+ if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK)
+ return JNI_ERR;
+
+ JNIEnv *jniEnv = uenv.nativeEnvironment;
+
+ if (!JMediaPlayer::initJNI(jniEnv) ||
+ !JSurfaceTexture::initJNI(jniEnv) ||
+ !JSurfaceTextureHolder::initJNI(jniEnv) ||
+ !JCamera::initJNI(jniEnv) ||
+ !JMultimediaUtils::initJNI(jniEnv) ||
+ !JMediaRecorder::initJNI(jniEnv)) {
+ return JNI_ERR;
+ }
+
+ return JNI_VERSION_1_4;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/android/src/qandroidmediaserviceplugin.h b/src/plugins/android/src/qandroidmediaserviceplugin.h
new file mode 100644
index 000000000..18b1def21
--- /dev/null
+++ b/src/plugins/android/src/qandroidmediaserviceplugin.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANDROIDMEDIASERVICEPLUGIN_H
+#define QANDROIDMEDIASERVICEPLUGIN_H
+
+#include <QMediaServiceProviderPlugin>
+
+QT_BEGIN_NAMESPACE
+
+class QAndroidMediaServicePlugin
+ : public QMediaServiceProviderPlugin
+ , public QMediaServiceSupportedDevicesInterface
+ , public QMediaServiceFeaturesInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QMediaServiceSupportedDevicesInterface)
+ Q_INTERFACES(QMediaServiceFeaturesInterface)
+ Q_PLUGIN_METADATA(IID "org.qt-project.qt.mediaserviceproviderfactory/5.0"
+ FILE "android_mediaservice.json")
+
+public:
+ QAndroidMediaServicePlugin();
+ ~QAndroidMediaServicePlugin();
+
+ QMediaService* create(QString const& key) Q_DECL_OVERRIDE;
+ void release(QMediaService *service) Q_DECL_OVERRIDE;
+
+ QMediaServiceProviderHint::Features supportedFeatures(const QByteArray &service) const Q_DECL_OVERRIDE;
+
+ QList<QByteArray> devices(const QByteArray &service) const;
+ QString deviceDescription(const QByteArray &service, const QByteArray &device);
+};
+
+QT_END_NAMESPACE
+
+#endif // QANDROIDMEDIASERVICEPLUGIN_H
diff --git a/src/plugins/android/src/src.pro b/src/plugins/android/src/src.pro
new file mode 100644
index 000000000..e99fd30f5
--- /dev/null
+++ b/src/plugins/android/src/src.pro
@@ -0,0 +1,19 @@
+TARGET = qtmedia_android
+QT += multimedia-private gui-private platformsupport-private network
+
+PLUGIN_TYPE = mediaservice
+PLUGIN_CLASS_NAME = QAndroidMediaServicePlugin
+load(qt_plugin)
+
+HEADERS += \
+ qandroidmediaserviceplugin.h
+
+SOURCES += \
+ qandroidmediaserviceplugin.cpp
+
+include (wrappers/wrappers.pri)
+include (common/common.pri)
+include (mediaplayer/mediaplayer.pri)
+include (mediacapture/mediacapture.pri)
+
+OTHER_FILES += android_mediaservice.json
diff --git a/src/plugins/android/src/wrappers/jcamera.cpp b/src/plugins/android/src/wrappers/jcamera.cpp
new file mode 100644
index 000000000..9005ac6e0
--- /dev/null
+++ b/src/plugins/android/src/wrappers/jcamera.cpp
@@ -0,0 +1,712 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "jcamera.h"
+
+#include <QtPlatformSupport/private/qjnihelpers_p.h>
+#include <qstringlist.h>
+#include <qdebug.h>
+#include "qandroidmultimediautils.h"
+
+QT_BEGIN_NAMESPACE
+
+static jclass g_qtCameraClass = 0;
+static QMap<int, JCamera*> g_objectMap;
+
+static QRect areaToRect(jobject areaObj)
+{
+ QJNIObject area(areaObj);
+ QJNILocalRef<jobject> rectRef = area.getObjectField<jobject>("rect", "android/graphics/Rect");
+ QJNIObject rect(rectRef.object());
+
+ return QRect(rect.getField<jint>("left"),
+ rect.getField<jint>("top"),
+ rect.callMethod<jint>("width"),
+ rect.callMethod<jint>("height"));
+}
+
+static QJNILocalRef<jobject> rectToArea(const QRect &rect)
+{
+ QJNIObject jrect("android/graphics/Rect",
+ "(IIII)V",
+ rect.left(), rect.top(), rect.right(), rect.bottom());
+
+ QJNIObject area("android/hardware/Camera$Area",
+ "(Landroid/graphics/Rect;I)V",
+ jrect.object(), 500);
+
+ return QJNILocalRef<jobject>(QAttachedJNIEnv()->NewLocalRef(area.object()));
+}
+
+// native method for QtCamera.java
+static void notifyAutoFocusComplete(JNIEnv* , jobject, int id, jboolean success)
+{
+ JCamera *obj = g_objectMap.value(id, 0);
+ if (obj)
+ Q_EMIT obj->autoFocusComplete(success);
+}
+
+static void notifyPictureExposed(JNIEnv* , jobject, int id)
+{
+ JCamera *obj = g_objectMap.value(id, 0);
+ if (obj)
+ Q_EMIT obj->pictureExposed();
+}
+
+static void notifyPictureCaptured(JNIEnv *env, jobject, int id, jbyteArray data)
+{
+ JCamera *obj = g_objectMap.value(id, 0);
+ if (obj) {
+ QByteArray bytes;
+ int arrayLength = env->GetArrayLength(data);
+ bytes.resize(arrayLength);
+ env->GetByteArrayRegion(data, 0, arrayLength, (jbyte*)bytes.data());
+ Q_EMIT obj->pictureCaptured(bytes);
+ }
+}
+
+JCamera::JCamera(int cameraId, jobject cam)
+ : QObject()
+ , QJNIObject(cam)
+ , m_cameraId(cameraId)
+ , m_info(0)
+ , m_parameters(0)
+ , m_hasAPI14(false)
+{
+ if (isValid()) {
+ g_objectMap.insert(cameraId, this);
+
+ m_info = new QJNIObject("android/hardware/Camera$CameraInfo");
+ callStaticMethod<void>("android/hardware/Camera",
+ "getCameraInfo",
+ "(ILandroid/hardware/Camera$CameraInfo;)V",
+ cameraId, m_info->object());
+
+ QJNILocalRef<jobject> params = callObjectMethod<jobject>("getParameters",
+ "()Landroid/hardware/Camera$Parameters;");
+ m_parameters = new QJNIObject(params.object());
+
+ // Check if API 14 is available
+ QAttachedJNIEnv env;
+ jclass clazz = env->FindClass("android/hardware/Camera");
+ if (env->ExceptionCheck()) {
+ clazz = 0;
+ env->ExceptionClear();
+ }
+ if (clazz) {
+ // startFaceDetection() was added in API 14
+ jmethodID id = env->GetMethodID(clazz, "startFaceDetection", "()V");
+ if (env->ExceptionCheck()) {
+ id = 0;
+ env->ExceptionClear();
+ }
+ m_hasAPI14 = bool(id);
+ }
+ }
+}
+
+JCamera::~JCamera()
+{
+ if (isValid())
+ g_objectMap.remove(m_cameraId);
+ delete m_parameters;
+ delete m_info;
+}
+
+JCamera *JCamera::open(int cameraId)
+{
+ QAttachedJNIEnv env;
+
+ QJNILocalRef<jobject> camera = callStaticObjectMethod<jobject>(g_qtCameraClass,
+ "open",
+ "(I)Lorg/qtproject/qt5/android/multimedia/QtCamera;",
+ cameraId);
+
+ if (camera.isNull())
+ return 0;
+ else
+ return new JCamera(cameraId, camera.object());
+}
+
+void JCamera::lock()
+{
+ callMethod<void>("lock");
+}
+
+void JCamera::unlock()
+{
+ callMethod<void>("unlock");
+}
+
+void JCamera::reconnect()
+{
+ callMethod<void>("reconnect");
+}
+
+void JCamera::release()
+{
+ m_previewSize = QSize();
+ delete m_parameters;
+ m_parameters = 0;
+ callMethod<void>("release");
+}
+
+JCamera::CameraFacing JCamera::getFacing()
+{
+ return CameraFacing(m_info->getField<jint>("facing"));
+}
+
+int JCamera::getNativeOrientation()
+{
+ return m_info->getField<jint>("orientation");
+}
+
+QSize JCamera::getPreferredPreviewSizeForVideo()
+{
+ if (!m_parameters || !m_parameters->isValid())
+ return QSize();
+
+ QJNILocalRef<jobject> sizeRef = m_parameters->callObjectMethod<jobject>("getPreferredPreviewSizeForVideo",
+ "()Landroid/hardware/Camera$Size;");
+
+ QJNIObject size(sizeRef.object());
+ return QSize(size.getField<jint>("width"), size.getField<jint>("height"));
+}
+
+QList<QSize> JCamera::getSupportedPreviewSizes()
+{
+ QList<QSize> list;
+
+ if (m_parameters && m_parameters->isValid()) {
+ QJNILocalRef<jobject> sizeListRef = m_parameters->callObjectMethod<jobject>("getSupportedPreviewSizes",
+ "()Ljava/util/List;");
+ QJNIObject sizeList(sizeListRef.object());
+ int count = sizeList.callMethod<jint>("size");
+ for (int i = 0; i < count; ++i) {
+ QJNILocalRef<jobject> sizeRef = sizeList.callObjectMethod<jobject>("get",
+ "(I)Ljava/lang/Object;",
+ i);
+ QJNIObject size(sizeRef.object());
+ list.append(QSize(size.getField<jint>("width"), size.getField<jint>("height")));
+ }
+
+ qSort(list.begin(), list.end(), qt_sizeLessThan);
+ }
+
+ return list;
+}
+
+void JCamera::setPreviewSize(const QSize &size)
+{
+ if (!m_parameters || !m_parameters->isValid())
+ return;
+
+ m_previewSize = size;
+
+ m_parameters->callMethod<void>("setPreviewSize", "(II)V", size.width(), size.height());
+ applyParameters();
+
+ emit previewSizeChanged();
+}
+
+void JCamera::setPreviewTexture(jobject surfaceTexture)
+{
+ callMethod<void>("setPreviewTexture", "(Landroid/graphics/SurfaceTexture;)V", surfaceTexture);
+}
+
+bool JCamera::isZoomSupported()
+{
+ if (!m_parameters || !m_parameters->isValid())
+ return false;
+
+ return m_parameters->callMethod<jboolean>("isZoomSupported");
+}
+
+int JCamera::getMaxZoom()
+{
+ if (!m_parameters || !m_parameters->isValid())
+ return 0;
+
+ return m_parameters->callMethod<jint>("getMaxZoom");
+}
+
+QList<int> JCamera::getZoomRatios()
+{
+ QList<int> ratios;
+
+ if (m_parameters && m_parameters->isValid()) {
+ QJNILocalRef<jobject> ratioListRef = m_parameters->callObjectMethod<jobject>("getZoomRatios",
+ "()Ljava/util/List;");
+ QJNIObject ratioList(ratioListRef.object());
+ int count = ratioList.callMethod<jint>("size");
+ for (int i = 0; i < count; ++i) {
+ QJNILocalRef<jobject> zoomRatioRef = ratioList.callObjectMethod<jobject>("get",
+ "(I)Ljava/lang/Object;",
+ i);
+
+ QJNIObject zoomRatio(zoomRatioRef.object());
+ ratios.append(zoomRatio.callMethod<jint>("intValue"));
+ }
+ }
+
+ return ratios;
+}
+
+int JCamera::getZoom()
+{
+ if (!m_parameters || !m_parameters->isValid())
+ return 0;
+
+ return m_parameters->callMethod<jint>("getZoom");
+}
+
+void JCamera::setZoom(int value)
+{
+ if (!m_parameters || !m_parameters->isValid())
+ return;
+
+ m_parameters->callMethod<void>("setZoom", "(I)V", value);
+ applyParameters();
+}
+
+QStringList JCamera::getSupportedFlashModes()
+{
+ return callStringListMethod("getSupportedFlashModes");
+}
+
+QString JCamera::getFlashMode()
+{
+ QString value;
+
+ if (m_parameters && m_parameters->isValid()) {
+ QJNILocalRef<jstring> flashMode = m_parameters->callObjectMethod<jstring>("getFlashMode",
+ "()Ljava/lang/String;");
+ if (!flashMode.isNull())
+ value = qt_convertJString(flashMode.object());
+ }
+
+ return value;
+}
+
+void JCamera::setFlashMode(const QString &value)
+{
+ if (!m_parameters || !m_parameters->isValid())
+ return;
+
+ m_parameters->callMethod<void>("setFlashMode",
+ "(Ljava/lang/String;)V",
+ qt_toJString(value).object());
+ applyParameters();
+}
+
+QStringList JCamera::getSupportedFocusModes()
+{
+ return callStringListMethod("getSupportedFocusModes");
+}
+
+QString JCamera::getFocusMode()
+{
+ QString value;
+
+ if (m_parameters && m_parameters->isValid()) {
+ QJNILocalRef<jstring> focusMode = m_parameters->callObjectMethod<jstring>("getFocusMode",
+ "()Ljava/lang/String;");
+ if (!focusMode.isNull())
+ value = qt_convertJString(focusMode.object());
+ }
+
+ return value;
+}
+
+void JCamera::setFocusMode(const QString &value)
+{
+ if (!m_parameters || !m_parameters->isValid())
+ return;
+
+ m_parameters->callMethod<void>("setFocusMode",
+ "(Ljava/lang/String;)V",
+ qt_toJString(value).object());
+ applyParameters();
+}
+
+int JCamera::getMaxNumFocusAreas()
+{
+ if (!m_hasAPI14 || !m_parameters || !m_parameters->isValid())
+ return 0;
+
+ return m_parameters->callMethod<jint>("getMaxNumFocusAreas");
+}
+
+QList<QRect> JCamera::getFocusAreas()
+{
+ QList<QRect> areas;
+
+ if (m_hasAPI14 && m_parameters && m_parameters->isValid()) {
+ QJNILocalRef<jobject> listRef = m_parameters->callObjectMethod<jobject>("getFocusAreas",
+ "()Ljava/util/List;");
+
+ if (!listRef.isNull()) {
+ QJNIObject list(listRef.object());
+ int count = list.callMethod<jint>("size");
+ for (int i = 0; i < count; ++i) {
+ QJNILocalRef<jobject> areaRef = list.callObjectMethod<jobject>("get",
+ "(I)Ljava/lang/Object;",
+ i);
+
+ areas.append(areaToRect(areaRef.object()));
+ }
+ }
+ }
+
+ return areas;
+}
+
+void JCamera::setFocusAreas(const QList<QRect> &areas)
+{
+ if (!m_hasAPI14 || !m_parameters || !m_parameters->isValid())
+ return;
+
+ QJNILocalRef<jobject> list(0);
+
+ if (!areas.isEmpty()) {
+ QAttachedJNIEnv env;
+ QJNIObject arrayList("java/util/ArrayList", "(I)V", areas.size());
+ for (int i = 0; i < areas.size(); ++i) {
+ arrayList.callMethod<jboolean>("add",
+ "(Ljava/lang/Object;)Z",
+ rectToArea(areas.at(i)).object());
+ if (env->ExceptionCheck())
+ env->ExceptionClear();
+ }
+ list = env->NewLocalRef(arrayList.object());
+ }
+
+ m_parameters->callMethod<void>("setFocusAreas", "(Ljava/util/List;)V", list.object());
+
+ applyParameters();
+}
+
+void JCamera::autoFocus()
+{
+ callMethod<void>("autoFocus");
+ emit autoFocusStarted();
+}
+
+void JCamera::cancelAutoFocus()
+{
+ callMethod<void>("cancelAutoFocus");
+}
+
+bool JCamera::isAutoExposureLockSupported()
+{
+ if (!m_hasAPI14 || !m_parameters || !m_parameters->isValid())
+ return false;
+
+ return m_parameters->callMethod<jboolean>("isAutoExposureLockSupported");
+}
+
+bool JCamera::getAutoExposureLock()
+{
+ if (!m_hasAPI14 || !m_parameters || !m_parameters->isValid())
+ return false;
+
+ return m_parameters->callMethod<jboolean>("getAutoExposureLock");
+}
+
+void JCamera::setAutoExposureLock(bool toggle)
+{
+ if (!m_hasAPI14 || !m_parameters || !m_parameters->isValid())
+ return;
+
+ m_parameters->callMethod<void>("setAutoExposureLock", "(Z)V", toggle);
+ applyParameters();
+}
+
+bool JCamera::isAutoWhiteBalanceLockSupported()
+{
+ if (!m_hasAPI14 || !m_parameters || !m_parameters->isValid())
+ return false;
+
+ return m_parameters->callMethod<jboolean>("isAutoWhiteBalanceLockSupported");
+}
+
+bool JCamera::getAutoWhiteBalanceLock()
+{
+ if (!m_hasAPI14 || !m_parameters || !m_parameters->isValid())
+ return false;
+
+ return m_parameters->callMethod<jboolean>("getAutoWhiteBalanceLock");
+}
+
+void JCamera::setAutoWhiteBalanceLock(bool toggle)
+{
+ if (!m_hasAPI14 || !m_parameters || !m_parameters->isValid())
+ return;
+
+ m_parameters->callMethod<void>("setAutoWhiteBalanceLock", "(Z)V", toggle);
+ applyParameters();
+}
+
+int JCamera::getExposureCompensation()
+{
+ if (!m_parameters || !m_parameters->isValid())
+ return 0;
+
+ return m_parameters->callMethod<jint>("getExposureCompensation");
+}
+
+void JCamera::setExposureCompensation(int value)
+{
+ if (!m_parameters || !m_parameters->isValid())
+ return;
+
+ m_parameters->callMethod<void>("setExposureCompensation", "(I)V", value);
+ applyParameters();
+}
+
+float JCamera::getExposureCompensationStep()
+{
+ if (!m_parameters || !m_parameters->isValid())
+ return 0;
+
+ return m_parameters->callMethod<jfloat>("getExposureCompensationStep");
+}
+
+int JCamera::getMinExposureCompensation()
+{
+ if (!m_parameters || !m_parameters->isValid())
+ return 0;
+
+ return m_parameters->callMethod<jint>("getMinExposureCompensation");
+}
+
+int JCamera::getMaxExposureCompensation()
+{
+ if (!m_parameters || !m_parameters->isValid())
+ return 0;
+
+ return m_parameters->callMethod<jint>("getMaxExposureCompensation");
+}
+
+QStringList JCamera::getSupportedSceneModes()
+{
+ return callStringListMethod("getSupportedSceneModes");
+}
+
+QString JCamera::getSceneMode()
+{
+ QString value;
+
+ if (m_parameters && m_parameters->isValid()) {
+ QJNILocalRef<jstring> sceneMode = m_parameters->callObjectMethod<jstring>("getSceneMode",
+ "()Ljava/lang/String;");
+ if (!sceneMode.isNull())
+ value = qt_convertJString(sceneMode.object());
+ }
+
+ return value;
+}
+
+void JCamera::setSceneMode(const QString &value)
+{
+ if (!m_parameters || !m_parameters->isValid())
+ return;
+
+ m_parameters->callMethod<void>("setSceneMode",
+ "(Ljava/lang/String;)V",
+ qt_toJString(value).object());
+ applyParameters();
+}
+
+QStringList JCamera::getSupportedWhiteBalance()
+{
+ return callStringListMethod("getSupportedWhiteBalance");
+}
+
+QString JCamera::getWhiteBalance()
+{
+ QString value;
+
+ if (m_parameters && m_parameters->isValid()) {
+ QJNILocalRef<jstring> wb = m_parameters->callObjectMethod<jstring>("getWhiteBalance",
+ "()Ljava/lang/String;");
+ if (!wb.isNull())
+ value = qt_convertJString(wb.object());
+ }
+
+ return value;
+}
+
+void JCamera::setWhiteBalance(const QString &value)
+{
+ if (!m_parameters || !m_parameters->isValid())
+ return;
+
+ m_parameters->callMethod<void>("setWhiteBalance",
+ "(Ljava/lang/String;)V",
+ qt_toJString(value).object());
+ applyParameters();
+
+ emit whiteBalanceChanged();
+}
+
+void JCamera::setRotation(int rotation)
+{
+ if (!m_parameters || !m_parameters->isValid())
+ return;
+
+ m_parameters->callMethod<void>("setRotation", "(I)V", rotation);
+ applyParameters();
+}
+
+QList<QSize> JCamera::getSupportedPictureSizes()
+{
+ QList<QSize> list;
+
+ if (m_parameters && m_parameters->isValid()) {
+ QJNILocalRef<jobject> sizeListRef = m_parameters->callObjectMethod<jobject>("getSupportedPictureSizes",
+ "()Ljava/util/List;");
+ QJNIObject sizeList(sizeListRef.object());
+ int count = sizeList.callMethod<jint>("size");
+ for (int i = 0; i < count; ++i) {
+ QJNILocalRef<jobject> sizeRef = sizeList.callObjectMethod<jobject>("get",
+ "(I)Ljava/lang/Object;",
+ i);
+ QJNIObject size(sizeRef.object());
+ list.append(QSize(size.getField<jint>("width"), size.getField<jint>("height")));
+ }
+
+ qSort(list.begin(), list.end(), qt_sizeLessThan);
+ }
+
+ return list;
+}
+
+void JCamera::setPictureSize(const QSize &size)
+{
+ if (!m_parameters || !m_parameters->isValid())
+ return;
+
+ m_parameters->callMethod<void>("setPictureSize", "(II)V", size.width(), size.height());
+ applyParameters();
+}
+
+void JCamera::setJpegQuality(int quality)
+{
+ if (!m_parameters || !m_parameters->isValid())
+ return;
+
+ m_parameters->callMethod<void>("setJpegQuality", "(I)V", quality);
+ applyParameters();
+}
+
+void JCamera::takePicture()
+{
+ callMethod<void>("takePicture");
+}
+
+void JCamera::startPreview()
+{
+ callMethod<void>("startPreview");
+}
+
+void JCamera::stopPreview()
+{
+ callMethod<void>("stopPreview");
+}
+
+void JCamera::applyParameters()
+{
+ callMethod<void>("setParameters",
+ "(Landroid/hardware/Camera$Parameters;)V",
+ m_parameters->object());
+}
+
+QStringList JCamera::callStringListMethod(const char *methodName)
+{
+ QStringList stringList;
+
+ if (m_parameters && m_parameters->isValid()) {
+ QJNILocalRef<jobject> listRef = m_parameters->callObjectMethod<jobject>(methodName,
+ "()Ljava/util/List;");
+
+ if (!listRef.isNull()) {
+ QJNIObject list(listRef.object());
+ int count = list.callMethod<jint>("size");
+ for (int i = 0; i < count; ++i) {
+ QJNILocalRef<jobject> stringRef = list.callObjectMethod<jobject>("get",
+ "(I)Ljava/lang/Object;",
+ i);
+
+ QJNIObject string(stringRef.object());
+ stringList.append(qt_convertJString(string.callObjectMethod<jstring>("toString").object()));
+ }
+ }
+ }
+
+ return stringList;
+}
+
+static JNINativeMethod methods[] = {
+ {"notifyAutoFocusComplete", "(IZ)V", (void *)notifyAutoFocusComplete},
+ {"notifyPictureExposed", "(I)V", (void *)notifyPictureExposed},
+ {"notifyPictureCaptured", "(I[B)V", (void *)notifyPictureCaptured}
+};
+
+bool JCamera::initJNI(JNIEnv *env)
+{
+ jclass clazz = env->FindClass("org/qtproject/qt5/android/multimedia/QtCamera");
+ if (env->ExceptionCheck())
+ env->ExceptionClear();
+
+ if (clazz) {
+ g_qtCameraClass = static_cast<jclass>(env->NewGlobalRef(clazz));
+ if (env->RegisterNatives(g_qtCameraClass,
+ methods,
+ sizeof(methods) / sizeof(methods[0])) < 0) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/android/src/wrappers/jcamera.h b/src/plugins/android/src/wrappers/jcamera.h
new file mode 100644
index 000000000..100628721
--- /dev/null
+++ b/src/plugins/android/src/wrappers/jcamera.h
@@ -0,0 +1,166 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef JCAMERA_H
+#define JCAMERA_H
+
+#include <qobject.h>
+#include <QtPlatformSupport/private/qjniobject_p.h>
+#include <qsize.h>
+#include <qrect.h>
+
+QT_BEGIN_NAMESPACE
+
+class JCamera : public QObject, public QJNIObject
+{
+ Q_OBJECT
+public:
+ enum CameraFacing {
+ CameraFacingBack = 0,
+ CameraFacingFront = 1
+ };
+
+ ~JCamera();
+
+ static JCamera *open(int cameraId);
+
+ int cameraId() const { return m_cameraId; }
+
+ void lock();
+ void unlock();
+ void reconnect();
+ void release();
+
+ CameraFacing getFacing();
+ int getNativeOrientation();
+
+ QSize getPreferredPreviewSizeForVideo();
+ QList<QSize> getSupportedPreviewSizes();
+
+ QSize previewSize() const { return m_previewSize; }
+ void setPreviewSize(const QSize &size);
+ void setPreviewTexture(jobject surfaceTexture);
+
+ bool isZoomSupported();
+ int getMaxZoom();
+ QList<int> getZoomRatios();
+ int getZoom();
+ void setZoom(int value);
+
+ QStringList getSupportedFlashModes();
+ QString getFlashMode();
+ void setFlashMode(const QString &value);
+
+ QStringList getSupportedFocusModes();
+ QString getFocusMode();
+ void setFocusMode(const QString &value);
+
+ int getMaxNumFocusAreas();
+ QList<QRect> getFocusAreas();
+ void setFocusAreas(const QList<QRect> &areas);
+
+ void autoFocus();
+ void cancelAutoFocus();
+
+ bool isAutoExposureLockSupported();
+ bool getAutoExposureLock();
+ void setAutoExposureLock(bool toggle);
+
+ bool isAutoWhiteBalanceLockSupported();
+ bool getAutoWhiteBalanceLock();
+ void setAutoWhiteBalanceLock(bool toggle);
+
+ int getExposureCompensation();
+ void setExposureCompensation(int value);
+ float getExposureCompensationStep();
+ int getMinExposureCompensation();
+ int getMaxExposureCompensation();
+
+ QStringList getSupportedSceneModes();
+ QString getSceneMode();
+ void setSceneMode(const QString &value);
+
+ QStringList getSupportedWhiteBalance();
+ QString getWhiteBalance();
+ void setWhiteBalance(const QString &value);
+
+ void setRotation(int rotation);
+
+ QList<QSize> getSupportedPictureSizes();
+ void setPictureSize(const QSize &size);
+ void setJpegQuality(int quality);
+
+ void startPreview();
+ void stopPreview();
+
+ void takePicture();
+
+ static bool initJNI(JNIEnv *env);
+
+Q_SIGNALS:
+ void previewSizeChanged();
+
+ void autoFocusStarted();
+ void autoFocusComplete(bool success);
+
+ void whiteBalanceChanged();
+
+ void pictureExposed();
+ void pictureCaptured(const QByteArray &data);
+
+private:
+ JCamera(int cameraId, jobject cam);
+ void applyParameters();
+
+ QStringList callStringListMethod(const char *methodName);
+
+ int m_cameraId;
+ QJNIObject *m_info;
+ QJNIObject *m_parameters;
+
+ QSize m_previewSize;
+
+ bool m_hasAPI14;
+};
+
+QT_END_NAMESPACE
+
+#endif // JCAMERA_H
diff --git a/src/plugins/android/src/wrappers/jmediametadataretriever.cpp b/src/plugins/android/src/wrappers/jmediametadataretriever.cpp
new file mode 100644
index 000000000..ae5abcf43
--- /dev/null
+++ b/src/plugins/android/src/wrappers/jmediametadataretriever.cpp
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "jmediametadataretriever.h"
+
+#include <QtPlatformSupport/private/qjnihelpers_p.h>
+#include <qpa/qplatformnativeinterface.h>
+#include <qguiapplication.h>
+
+QT_BEGIN_NAMESPACE
+
+static jobject g_activity = 0;
+
+JMediaMetadataRetriever::JMediaMetadataRetriever()
+ : QJNIObject("android/media/MediaMetadataRetriever")
+{
+ if (!g_activity) {
+ QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
+ g_activity = static_cast<jobject>(nativeInterface->nativeResourceForIntegration("QtActivity"));
+ }
+}
+
+JMediaMetadataRetriever::~JMediaMetadataRetriever()
+{
+}
+
+QString JMediaMetadataRetriever::extractMetadata(MetadataKey key)
+{
+ QString value;
+
+ QJNILocalRef<jstring> metadata = callObjectMethod<jstring>("extractMetadata",
+ "(I)Ljava/lang/String;",
+ jint(key));
+ if (!metadata.isNull())
+ value = qt_convertJString(metadata.object());
+
+ return value;
+}
+
+void JMediaMetadataRetriever::release()
+{
+ callMethod<void>("release");
+}
+
+bool JMediaMetadataRetriever::setDataSource(const QUrl &url)
+{
+ QAttachedJNIEnv env;
+
+ bool loaded = false;
+
+ QJNILocalRef<jstring> string = qt_toJString(url.toString());
+
+ QJNILocalRef<jobject> uri = callStaticObjectMethod<jobject>("android/net/Uri",
+ "parse",
+ "(Ljava/lang/String;)Landroid/net/Uri;",
+ string.object());
+ if (env->ExceptionCheck()) {
+ env->ExceptionClear();
+ } else {
+ callMethod<void>("setDataSource",
+ "(Landroid/content/Context;Landroid/net/Uri;)V",
+ g_activity,
+ uri.object());
+ if (env->ExceptionCheck())
+ env->ExceptionClear();
+ else
+ loaded = true;
+ }
+
+ return loaded;
+}
+
+bool JMediaMetadataRetriever::setDataSource(const QString &path)
+{
+ QAttachedJNIEnv env;
+
+ bool loaded = false;
+
+ callMethod<void>("setDataSource", "(Ljava/lang/String;)V", qt_toJString(path).object());
+ if (env->ExceptionCheck())
+ env->ExceptionClear();
+ else
+ loaded = true;
+
+ return loaded;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/android/src/wrappers/jmediametadataretriever.h b/src/plugins/android/src/wrappers/jmediametadataretriever.h
new file mode 100644
index 000000000..dd63e0d87
--- /dev/null
+++ b/src/plugins/android/src/wrappers/jmediametadataretriever.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef JMEDIAMETADATARETRIEVER_H
+#define JMEDIAMETADATARETRIEVER_H
+
+#include <QtPlatformSupport/private/qjniobject_p.h>
+#include <qurl.h>
+
+QT_BEGIN_NAMESPACE
+
+class JMediaMetadataRetriever : public QJNIObject
+{
+public:
+ enum MetadataKey {
+ Album = 1,
+ AlbumArtist = 13,
+ Artist = 2,
+ Author = 3,
+ Bitrate = 20,
+ CDTrackNumber = 0,
+ Compilation = 15,
+ Composer = 4,
+ Date = 5,
+ DiscNumber = 14,
+ Duration = 9,
+ Genre = 6,
+ HasAudio = 16,
+ HasVideo = 17,
+ Location = 23,
+ MimeType = 12,
+ NumTracks = 10,
+ Title = 7,
+ VideoHeight = 19,
+ VideoWidth = 18,
+ VideoRotation = 24,
+ Writer = 11,
+ Year = 8
+ };
+
+ JMediaMetadataRetriever();
+ ~JMediaMetadataRetriever();
+
+ QString extractMetadata(MetadataKey key);
+ void release();
+ bool setDataSource(const QUrl &url);
+ bool setDataSource(const QString &path);
+
+};
+
+QT_END_NAMESPACE
+
+#endif // JMEDIAMETADATARETRIEVER_H
diff --git a/src/plugins/android/src/wrappers/jmediaplayer.cpp b/src/plugins/android/src/wrappers/jmediaplayer.cpp
new file mode 100644
index 000000000..f6e03ee22
--- /dev/null
+++ b/src/plugins/android/src/wrappers/jmediaplayer.cpp
@@ -0,0 +1,270 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "jmediaplayer.h"
+
+#include <QString>
+#include <qpa/qplatformnativeinterface.h>
+#include <qguiapplication.h>
+#include <QtPlatformSupport/private/qjnihelpers_p.h>
+
+namespace {
+
+jclass mediaPlayerClass = 0;
+
+QMap<jlong, JMediaPlayer *> mplayers;
+
+}
+
+QT_BEGIN_NAMESPACE
+
+bool JMediaPlayer::mActivitySet = false;
+
+JMediaPlayer::JMediaPlayer()
+ : QObject()
+ , QJNIObject(mediaPlayerClass, "(J)V", reinterpret_cast<jlong>(this))
+ , mId(reinterpret_cast<jlong>(this))
+ , mDisplay(0)
+{
+ mplayers.insert(mId, this);
+
+ if (!mActivitySet) {
+ QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
+ jobject activity = static_cast<jobject>(nativeInterface->nativeResourceForIntegration("QtActivity"));
+ QJNIObject::callStaticMethod<void>(mediaPlayerClass,
+ "setActivity",
+ "(Landroid/app/Activity;)V",
+ activity);
+ mActivitySet = true;
+ }
+}
+
+JMediaPlayer::~JMediaPlayer()
+{
+ mplayers.remove(mId);
+}
+
+void JMediaPlayer::release()
+{
+ callMethod<void>("release");
+}
+
+void JMediaPlayer::onError(qint32 what, qint32 extra)
+{
+ Q_EMIT error(what, extra);
+}
+
+void JMediaPlayer::onBufferingUpdate(qint32 percent)
+{
+ Q_EMIT bufferingUpdate(percent);
+}
+
+void JMediaPlayer::onInfo(qint32 what, qint32 extra)
+{
+ Q_EMIT info(what, extra);
+}
+
+void JMediaPlayer::onMediaPlayerInfo(qint32 what, qint32 extra)
+{
+ Q_EMIT mediaPlayerInfo(what, extra);
+}
+
+void JMediaPlayer::onVideoSizeChanged(qint32 width, qint32 height)
+{
+ Q_EMIT videoSizeChanged(width, height);
+}
+
+int JMediaPlayer::getCurrentPosition()
+{
+ return callMethod<jint>("getCurrentPosition");
+}
+
+int JMediaPlayer::getDuration()
+{
+ return callMethod<jint>("getDuration");
+}
+
+bool JMediaPlayer::isPlaying()
+{
+ return callMethod<jboolean>("isPlaying");
+}
+
+int JMediaPlayer::volume()
+{
+ return callMethod<jint>("getVolume");
+}
+
+bool JMediaPlayer::isMuted()
+{
+ return callMethod<jboolean>("isMuted");
+}
+
+void JMediaPlayer::play()
+{
+ callMethod<void>("start");
+}
+
+void JMediaPlayer::pause()
+{
+ callMethod<void>("pause");
+}
+
+void JMediaPlayer::stop()
+{
+ callMethod<void>("stop");
+}
+
+void JMediaPlayer::seekTo(qint32 msec)
+{
+ callMethod<void>("seekTo", "(I)V", jint(msec));
+}
+
+void JMediaPlayer::setMuted(bool mute)
+{
+ callMethod<void>("mute", "(Z)V", jboolean(mute));
+}
+
+void JMediaPlayer::setDataSource(const QString &path)
+{
+ QJNILocalRef<jstring> string = qt_toJString(path);
+ callMethod<void>("setMediaPath", "(Ljava/lang/String;)V", string.object());
+}
+
+void JMediaPlayer::setVolume(int volume)
+{
+ callMethod<void>("setVolume", "(I)V", jint(volume));
+}
+
+void JMediaPlayer::setDisplay(jobject surfaceHolder)
+{
+ mDisplay = surfaceHolder;
+ callMethod<void>("setDisplay", "(Landroid/view/SurfaceHolder;)V", mDisplay);
+}
+
+QT_END_NAMESPACE
+
+static void onErrorNative(JNIEnv *env, jobject thiz, jint what, jint extra, jlong id)
+{
+ Q_UNUSED(env);
+ Q_UNUSED(thiz);
+ JMediaPlayer *const mp = mplayers[id];
+ if (!mp)
+ return;
+
+ mp->onError(what, extra);
+}
+
+static void onBufferingUpdateNative(JNIEnv *env, jobject thiz, jint percent, jlong id)
+{
+ Q_UNUSED(env);
+ Q_UNUSED(thiz);
+ JMediaPlayer *const mp = mplayers[id];
+ if (!mp)
+ return;
+
+ mp->onBufferingUpdate(percent);
+}
+
+static void onInfoNative(JNIEnv *env, jobject thiz, jint what, jint extra, jlong id)
+{
+ Q_UNUSED(env);
+ Q_UNUSED(thiz);
+ JMediaPlayer *const mp = mplayers[id];
+ if (!mp)
+ return;
+
+ mp->onInfo(what, extra);
+}
+
+static void onMediaPlayerInfoNative(JNIEnv *env, jobject thiz, jint what, jint extra, jlong id)
+{
+ Q_UNUSED(env);
+ Q_UNUSED(thiz);
+ JMediaPlayer *const mp = mplayers[id];
+ if (!mp)
+ return;
+
+ mp->onMediaPlayerInfo(what, extra);
+}
+
+static void onVideoSizeChangedNative(JNIEnv *env,
+ jobject thiz,
+ jint width,
+ jint height,
+ jlong id)
+{
+ Q_UNUSED(env);
+ Q_UNUSED(thiz);
+ JMediaPlayer *const mp = mplayers[id];
+ if (!mp)
+ return;
+
+ mp->onVideoSizeChanged(width, height);
+}
+
+QT_BEGIN_NAMESPACE
+
+bool JMediaPlayer::initJNI(JNIEnv *env)
+{
+ jclass jClass = env->FindClass("org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer");
+
+ if (jClass) {
+ mediaPlayerClass = static_cast<jclass>(env->NewGlobalRef(jClass));
+
+ JNINativeMethod methods[] = {
+ {"onErrorNative", "(IIJ)V", reinterpret_cast<void *>(onErrorNative)},
+ {"onBufferingUpdateNative", "(IJ)V", reinterpret_cast<void *>(onBufferingUpdateNative)},
+ {"onInfoNative", "(IIJ)V", reinterpret_cast<void *>(onInfoNative)},
+ {"onMediaPlayerInfoNative", "(IIJ)V", reinterpret_cast<void *>(onMediaPlayerInfoNative)},
+ {"onVideoSizeChangedNative", "(IIJ)V", reinterpret_cast<void *>(onVideoSizeChangedNative)}
+ };
+
+ if (env->RegisterNatives(mediaPlayerClass,
+ methods,
+ sizeof(methods) / sizeof(methods[0])) < 0) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/android/src/wrappers/jmediaplayer.h b/src/plugins/android/src/wrappers/jmediaplayer.h
new file mode 100644
index 000000000..710246b9a
--- /dev/null
+++ b/src/plugins/android/src/wrappers/jmediaplayer.h
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANDROIDMEDIAPLAYER_H
+#define QANDROIDMEDIAPLAYER_H
+
+#include <QObject>
+#include <QtPlatformSupport/private/qjniobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class JMediaPlayer : public QObject, public QJNIObject
+{
+ Q_OBJECT
+public:
+ JMediaPlayer();
+ ~JMediaPlayer();
+
+ enum MediaError
+ {
+ // What
+ MEDIA_ERROR_UNKNOWN = 1,
+ MEDIA_ERROR_SERVER_DIED = 100,
+ // Extra
+ MEDIA_ERROR_IO = -1004,
+ MEDIA_ERROR_MALFORMED = -1007,
+ MEDIA_ERROR_UNSUPPORTED = -1010,
+ MEDIA_ERROR_TIMED_OUT = -110,
+ MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 200
+ };
+
+ enum MediaInfo
+ {
+ MEDIA_INFO_UNKNOWN = 1,
+ MEDIA_INFO_VIDEO_TRACK_LAGGING = 700,
+ MEDIA_INFO_VIDEO_RENDERING_START = 3,
+ MEDIA_INFO_BUFFERING_START = 701,
+ MEDIA_INFO_BUFFERING_END = 702,
+ MEDIA_INFO_BAD_INTERLEAVING = 800,
+ MEDIA_INFO_NOT_SEEKABLE = 801,
+ MEDIA_INFO_METADATA_UPDATE = 802
+ };
+
+ enum MediaPlayerInfo
+ {
+ MEDIA_PLAYER_INVALID_STATE = 1,
+ MEDIA_PLAYER_PREPARING = 2,
+ MEDIA_PLAYER_READY = 3,
+ MEDIA_PLAYER_DURATION = 4,
+ MEDIA_PLAYER_PROGRESS = 5,
+ MEDIA_PLAYER_FINISHED = 6
+ };
+
+ void release();
+
+ int getCurrentPosition();
+ int getDuration();
+ bool isPlaying();
+ int volume();
+ bool isMuted();
+ jobject display() { return mDisplay; }
+
+ void play();
+ void pause();
+ void stop();
+ void seekTo(qint32 msec);
+ void setMuted(bool mute);
+ void setDataSource(const QString &path);
+ void setVolume(int volume);
+ void setDisplay(jobject surfaceHolder);
+
+ void onError(qint32 what, qint32 extra);
+ void onBufferingUpdate(qint32 percent);
+ void onInfo(qint32 what, qint32 extra);
+ void onMediaPlayerInfo(qint32 what, qint32 extra);
+ void onVideoSizeChanged(qint32 width, qint32 height);
+
+ static bool initJNI(JNIEnv *env);
+
+Q_SIGNALS:
+ void error(qint32 what, qint32 extra);
+ void bufferingUpdate(qint32 percent);
+ void completion();
+ void info(qint32 what, qint32 extra);
+ void mediaPlayerInfo(qint32 what, qint32 extra);
+ void videoSizeChanged(qint32 width, qint32 height);
+
+private:
+ jlong mId;
+ jobject mDisplay;
+
+ static bool mActivitySet;
+};
+
+QT_END_NAMESPACE
+
+#endif // QANDROIDMEDIAPLAYER_H
diff --git a/src/plugins/android/src/wrappers/jmediarecorder.cpp b/src/plugins/android/src/wrappers/jmediarecorder.cpp
new file mode 100644
index 000000000..b7cbe5724
--- /dev/null
+++ b/src/plugins/android/src/wrappers/jmediarecorder.cpp
@@ -0,0 +1,242 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "jmediarecorder.h"
+
+#include "jcamera.h"
+#include <QtPlatformSupport/private/qjnihelpers_p.h>
+#include <qmap.h>
+
+QT_BEGIN_NAMESPACE
+
+static jclass g_qtMediaRecorderClass = 0;
+static QMap<jlong, JMediaRecorder*> g_objectMap;
+
+static void notifyError(JNIEnv* , jobject, jlong id, jint what, jint extra)
+{
+ JMediaRecorder *obj = g_objectMap.value(id, 0);
+ if (obj)
+ emit obj->error(what, extra);
+}
+
+static void notifyInfo(JNIEnv* , jobject, jlong id, jint what, jint extra)
+{
+ JMediaRecorder *obj = g_objectMap.value(id, 0);
+ if (obj)
+ emit obj->info(what, extra);
+}
+
+JMediaRecorder::JMediaRecorder()
+ : QObject()
+ , QJNIObject(g_qtMediaRecorderClass, "(J)V", reinterpret_cast<jlong>(this))
+ , m_id(reinterpret_cast<jlong>(this))
+{
+ if (isValid())
+ g_objectMap.insert(m_id, this);
+}
+
+JMediaRecorder::~JMediaRecorder()
+{
+ g_objectMap.remove(m_id);
+}
+
+void JMediaRecorder::release()
+{
+ callMethod<void>("release");
+}
+
+bool JMediaRecorder::prepare()
+{
+ QAttachedJNIEnv env;
+ callMethod<void>("prepare");
+ if (env->ExceptionCheck()) {
+ env->ExceptionClear();
+ return false;
+ }
+ return true;
+}
+
+void JMediaRecorder::reset()
+{
+ callMethod<void>("reset");
+}
+
+bool JMediaRecorder::start()
+{
+ QAttachedJNIEnv env;
+ callMethod<void>("start");
+ if (env->ExceptionCheck()) {
+ env->ExceptionClear();
+ return false;
+ }
+ return true;
+}
+
+void JMediaRecorder::stop()
+{
+ QAttachedJNIEnv env;
+ callMethod<void>("stop");
+ if (env->ExceptionCheck())
+ env->ExceptionClear();
+}
+
+void JMediaRecorder::setAudioChannels(int numChannels)
+{
+ callMethod<void>("setAudioChannels", "(I)V", numChannels);
+}
+
+void JMediaRecorder::setAudioEncoder(AudioEncoder encoder)
+{
+ QAttachedJNIEnv env;
+ callMethod<void>("setAudioEncoder", "(I)V", int(encoder));
+ if (env->ExceptionCheck())
+ env->ExceptionClear();
+}
+
+void JMediaRecorder::setAudioEncodingBitRate(int bitRate)
+{
+ callMethod<void>("setAudioEncodingBitRate", "(I)V", bitRate);
+}
+
+void JMediaRecorder::setAudioSamplingRate(int samplingRate)
+{
+ callMethod<void>("setAudioSamplingRate", "(I)V", samplingRate);
+}
+
+void JMediaRecorder::setAudioSource(AudioSource source)
+{
+ QAttachedJNIEnv env;
+ callMethod<void>("setAudioSource", "(I)V", int(source));
+ if (env->ExceptionCheck())
+ env->ExceptionClear();
+}
+
+void JMediaRecorder::setCamera(JCamera *camera)
+{
+ QJNILocalRef<jobject> cam = camera->getObjectField<jobject>("m_camera", "Landroid/hardware/Camera;");
+ callMethod<void>("setCamera", "(Landroid/hardware/Camera;)V", cam.object());
+}
+
+void JMediaRecorder::setVideoEncoder(VideoEncoder encoder)
+{
+ QAttachedJNIEnv env;
+ callMethod<void>("setVideoEncoder", "(I)V", int(encoder));
+ if (env->ExceptionCheck())
+ env->ExceptionClear();
+}
+
+void JMediaRecorder::setVideoEncodingBitRate(int bitRate)
+{
+ callMethod<void>("setVideoEncodingBitRate", "(I)V", bitRate);
+}
+
+void JMediaRecorder::setVideoFrameRate(int rate)
+{
+ QAttachedJNIEnv env;
+ callMethod<void>("setVideoFrameRate", "(I)V", rate);
+ if (env->ExceptionCheck())
+ env->ExceptionClear();
+}
+
+void JMediaRecorder::setVideoSize(const QSize &size)
+{
+ QAttachedJNIEnv env;
+ callMethod<void>("setVideoSize", "(II)V", size.width(), size.height());
+ if (env->ExceptionCheck())
+ env->ExceptionClear();
+}
+
+void JMediaRecorder::setVideoSource(VideoSource source)
+{
+ QAttachedJNIEnv env;
+ callMethod<void>("setVideoSource", "(I)V", int(source));
+ if (env->ExceptionCheck())
+ env->ExceptionClear();
+}
+
+void JMediaRecorder::setOrientationHint(int degrees)
+{
+ QAttachedJNIEnv env;
+ callMethod<void>("setOrientationHint", "(I)V", degrees);
+ if (env->ExceptionCheck())
+ env->ExceptionClear();
+}
+
+void JMediaRecorder::setOutputFormat(OutputFormat format)
+{
+ QAttachedJNIEnv env;
+ callMethod<void>("setOutputFormat", "(I)V", int(format));
+ if (env->ExceptionCheck())
+ env->ExceptionClear();
+}
+
+void JMediaRecorder::setOutputFile(const QString &path)
+{
+ QAttachedJNIEnv env;
+ callMethod<void>("setOutputFile", "(Ljava/lang/String;)V", qt_toJString(path).object());
+ if (env->ExceptionCheck())
+ env->ExceptionClear();
+}
+
+static JNINativeMethod methods[] = {
+ {"notifyError", "(JII)V", (void *)notifyError},
+ {"notifyInfo", "(JII)V", (void *)notifyInfo}
+};
+
+bool JMediaRecorder::initJNI(JNIEnv *env)
+{
+ jclass clazz = env->FindClass("org/qtproject/qt5/android/multimedia/QtMediaRecorder");
+ if (env->ExceptionCheck())
+ env->ExceptionClear();
+
+ if (clazz) {
+ g_qtMediaRecorderClass = static_cast<jclass>(env->NewGlobalRef(clazz));
+ if (env->RegisterNatives(g_qtMediaRecorderClass,
+ methods,
+ sizeof(methods) / sizeof(methods[0])) < 0) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/android/src/wrappers/jmediarecorder.h b/src/plugins/android/src/wrappers/jmediarecorder.h
new file mode 100644
index 000000000..ef26b8a72
--- /dev/null
+++ b/src/plugins/android/src/wrappers/jmediarecorder.h
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef JMEDIARECORDER_H
+#define JMEDIARECORDER_H
+
+#include <qobject.h>
+#include <QtPlatformSupport/private/qjniobject_p.h>
+#include <qsize.h>
+
+QT_BEGIN_NAMESPACE
+
+class JCamera;
+
+class JMediaRecorder : public QObject, public QJNIObject
+{
+ Q_OBJECT
+public:
+ enum AudioEncoder {
+ DefaultAudioEncoder = 0,
+ AMR_NB_Encoder = 1,
+ AMR_WB_Encoder = 2,
+ AAC = 3
+ };
+
+ enum AudioSource {
+ DefaultAudioSource = 0,
+ Mic = 1,
+ VoiceUplink = 2,
+ VoiceDownlink = 3,
+ VoiceCall = 4,
+ Camcorder = 5,
+ VoiceRecognition = 6
+ };
+
+ enum VideoEncoder {
+ DefaultVideoEncoder = 0,
+ H263 = 1,
+ H264 = 2,
+ MPEG_4_SP = 3
+ };
+
+ enum VideoSource {
+ DefaultVideoSource = 0,
+ Camera = 1
+ };
+
+ enum OutputFormat {
+ DefaultOutputFormat = 0,
+ THREE_GPP = 1,
+ MPEG_4 = 2,
+ AMR_NB_Format = 3,
+ AMR_WB_Format = 4
+ };
+
+ JMediaRecorder();
+ ~JMediaRecorder();
+
+ void release();
+ bool prepare();
+ void reset();
+
+ bool start();
+ void stop();
+
+ void setAudioChannels(int numChannels);
+ void setAudioEncoder(AudioEncoder encoder);
+ void setAudioEncodingBitRate(int bitRate);
+ void setAudioSamplingRate(int samplingRate);
+ void setAudioSource(AudioSource source);
+
+ void setCamera(JCamera *camera);
+ void setVideoEncoder(VideoEncoder encoder);
+ void setVideoEncodingBitRate(int bitRate);
+ void setVideoFrameRate(int rate);
+ void setVideoSize(const QSize &size);
+ void setVideoSource(VideoSource source);
+
+ void setOrientationHint(int degrees);
+
+ void setOutputFormat(OutputFormat format);
+ void setOutputFile(const QString &path);
+
+ static bool initJNI(JNIEnv *env);
+
+Q_SIGNALS:
+ void error(int what, int extra);
+ void info(int what, int extra);
+
+private:
+ jlong m_id;
+};
+
+QT_END_NAMESPACE
+
+#endif // JMEDIARECORDER_H
diff --git a/src/plugins/android/src/wrappers/jmultimediautils.cpp b/src/plugins/android/src/wrappers/jmultimediautils.cpp
new file mode 100644
index 000000000..6832e6b6e
--- /dev/null
+++ b/src/plugins/android/src/wrappers/jmultimediautils.cpp
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "jmultimediautils.h"
+
+#include <QtPlatformSupport/private/qjnihelpers_p.h>
+
+QT_BEGIN_NAMESPACE
+
+static jclass g_qtMultimediaUtilsClass = 0;
+
+JMultimediaUtils::JMultimediaUtils()
+ : QObject()
+ , QJNIObject(g_qtMultimediaUtilsClass)
+{
+}
+
+void JMultimediaUtils::enableOrientationListener(bool enable)
+{
+ callStaticMethod<void>(g_qtMultimediaUtilsClass, "enableOrientationListener", "(Z)V", enable);
+}
+
+int JMultimediaUtils::getDeviceOrientation()
+{
+ return callStaticMethod<jint>(g_qtMultimediaUtilsClass, "getDeviceOrientation");
+}
+
+QString JMultimediaUtils::getDefaultMediaDirectory(MediaType type)
+{
+ QJNILocalRef<jstring> path = callStaticObjectMethod<jstring>(g_qtMultimediaUtilsClass,
+ "getDefaultMediaDirectory",
+ "(I)Ljava/lang/String;",
+ jint(type));
+ return qt_convertJString(path.object());
+}
+
+void JMultimediaUtils::registerMediaFile(const QString &file)
+{
+ callStaticMethod<void>(g_qtMultimediaUtilsClass,
+ "registerMediaFile",
+ "(Ljava/lang/String;)V",
+ qt_toJString(file).object());
+}
+
+bool JMultimediaUtils::initJNI(JNIEnv *env)
+{
+ jclass clazz = env->FindClass("org/qtproject/qt5/android/multimedia/QtMultimediaUtils");
+ if (env->ExceptionCheck())
+ env->ExceptionClear();
+
+ if (clazz)
+ g_qtMultimediaUtilsClass = static_cast<jclass>(env->NewGlobalRef(clazz));
+
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/android/src/wrappers/jmultimediautils.h b/src/plugins/android/src/wrappers/jmultimediautils.h
new file mode 100644
index 000000000..909f5c155
--- /dev/null
+++ b/src/plugins/android/src/wrappers/jmultimediautils.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef JMULTIMEDIAUTILS_H
+#define JMULTIMEDIAUTILS_H
+
+#include <qobject.h>
+#include <QtPlatformSupport/private/qjniobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class JMultimediaUtils : public QObject, public QJNIObject
+{
+ Q_OBJECT
+public:
+ enum MediaType {
+ Music = 0,
+ Movies = 1,
+ DCIM = 2,
+ Sounds = 3
+ };
+
+ JMultimediaUtils();
+
+ static void enableOrientationListener(bool enable);
+ static int getDeviceOrientation();
+ static QString getDefaultMediaDirectory(MediaType type);
+ static void registerMediaFile(const QString &file);
+
+ static bool initJNI(JNIEnv *env);
+};
+
+QT_END_NAMESPACE
+
+#endif // JMULTIMEDIAUTILS_H
diff --git a/src/plugins/android/src/wrappers/jsurfacetexture.cpp b/src/plugins/android/src/wrappers/jsurfacetexture.cpp
new file mode 100644
index 000000000..60c85cdf0
--- /dev/null
+++ b/src/plugins/android/src/wrappers/jsurfacetexture.cpp
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "jsurfacetexture.h"
+#include <QtPlatformSupport/private/qjnihelpers_p.h>
+
+QT_BEGIN_NAMESPACE
+
+static jclass g_qtSurfaceTextureClass = 0;
+static QMap<int, JSurfaceTexture*> g_objectMap;
+
+// native method for QtSurfaceTexture.java
+static void notifyFrameAvailable(JNIEnv* , jobject, int id)
+{
+ JSurfaceTexture *obj = g_objectMap.value(id, 0);
+ if (obj)
+ Q_EMIT obj->frameAvailable();
+}
+
+JSurfaceTexture::JSurfaceTexture(unsigned int texName)
+ : QObject()
+ , QJNIObject(g_qtSurfaceTextureClass, "(I)V", jint(texName))
+ , m_texID(int(texName))
+{
+ if (isValid())
+ g_objectMap.insert(int(texName), this);
+}
+
+JSurfaceTexture::~JSurfaceTexture()
+{
+ if (isValid())
+ g_objectMap.remove(m_texID);
+}
+
+QMatrix4x4 JSurfaceTexture::getTransformMatrix()
+{
+ QAttachedJNIEnv env;
+
+ QMatrix4x4 matrix;
+ jfloatArray array = env->NewFloatArray(16);
+ callMethod<void>("getTransformMatrix", "([F)V", array);
+ env->GetFloatArrayRegion(array, 0, 16, matrix.data());
+ env->DeleteLocalRef(array);
+
+ return matrix;
+}
+
+void JSurfaceTexture::updateTexImage()
+{
+ callMethod<void>("updateTexImage");
+}
+
+static JNINativeMethod methods[] = {
+ {"notifyFrameAvailable", "(I)V", (void *)notifyFrameAvailable}
+};
+
+bool JSurfaceTexture::initJNI(JNIEnv *env)
+{
+ jclass clazz = env->FindClass("org/qtproject/qt5/android/multimedia/QtSurfaceTexture");
+ if (env->ExceptionCheck())
+ env->ExceptionClear();
+
+ if (clazz) {
+ g_qtSurfaceTextureClass = static_cast<jclass>(env->NewGlobalRef(clazz));
+ if (env->RegisterNatives(g_qtSurfaceTextureClass,
+ methods,
+ sizeof(methods) / sizeof(methods[0])) < 0) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/android/src/wrappers/jsurfacetexture.h b/src/plugins/android/src/wrappers/jsurfacetexture.h
new file mode 100644
index 000000000..2a2f27ae3
--- /dev/null
+++ b/src/plugins/android/src/wrappers/jsurfacetexture.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef JSURFACETEXTURE_H
+#define JSURFACETEXTURE_H
+
+#include <qobject.h>
+#include <QtPlatformSupport/private/qjniobject_p.h>
+
+#include <QMatrix4x4>
+
+QT_BEGIN_NAMESPACE
+
+class JSurfaceTexture : public QObject, public QJNIObject
+{
+ Q_OBJECT
+public:
+ explicit JSurfaceTexture(unsigned int texName);
+ ~JSurfaceTexture();
+
+ QMatrix4x4 getTransformMatrix();
+ void updateTexImage();
+
+ static bool initJNI(JNIEnv *env);
+
+Q_SIGNALS:
+ void frameAvailable();
+
+private:
+ int m_texID;
+};
+
+QT_END_NAMESPACE
+
+#endif // JSURFACETEXTURE_H
diff --git a/src/plugins/android/src/wrappers/jsurfacetextureholder.cpp b/src/plugins/android/src/wrappers/jsurfacetextureholder.cpp
new file mode 100644
index 000000000..4ec8935c2
--- /dev/null
+++ b/src/plugins/android/src/wrappers/jsurfacetextureholder.cpp
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "jsurfacetextureholder.h"
+
+QT_BEGIN_NAMESPACE
+
+static jclass g_qtSurfaceTextureHolderClass = 0;
+
+JSurfaceTextureHolder::JSurfaceTextureHolder(jobject surface)
+ : QJNIObject(g_qtSurfaceTextureHolderClass, "(Landroid/view/Surface;)V", surface)
+{
+}
+
+bool JSurfaceTextureHolder::initJNI(JNIEnv *env)
+{
+ jclass clazz = env->FindClass("org/qtproject/qt5/android/multimedia/QtSurfaceTextureHolder");
+ if (env->ExceptionCheck())
+ env->ExceptionClear();
+
+ if (clazz)
+ g_qtSurfaceTextureHolderClass = static_cast<jclass>(env->NewGlobalRef(clazz));
+
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/android/src/wrappers/jsurfacetextureholder.h b/src/plugins/android/src/wrappers/jsurfacetextureholder.h
new file mode 100644
index 000000000..5b567de3a
--- /dev/null
+++ b/src/plugins/android/src/wrappers/jsurfacetextureholder.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef JSURFACETEXTUREHOLDER_H
+#define JSURFACETEXTUREHOLDER_H
+
+#include <QtPlatformSupport/private/qjniobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class JSurfaceTextureHolder : public QJNIObject
+{
+public:
+ JSurfaceTextureHolder(jobject surface);
+
+ static bool initJNI(JNIEnv *env);
+};
+
+QT_END_NAMESPACE
+
+#endif // JSURFACETEXTUREHOLDER_H
diff --git a/src/plugins/android/src/wrappers/wrappers.pri b/src/plugins/android/src/wrappers/wrappers.pri
new file mode 100644
index 000000000..b2faa5b79
--- /dev/null
+++ b/src/plugins/android/src/wrappers/wrappers.pri
@@ -0,0 +1,21 @@
+QT += platformsupport-private
+
+INCLUDEPATH += $$PWD
+
+HEADERS += \
+ $$PWD/jmediaplayer.h \
+ $$PWD/jsurfacetexture.h \
+ $$PWD/jsurfacetextureholder.h \
+ $$PWD/jmediametadataretriever.h \
+ $$PWD/jcamera.h \
+ $$PWD/jmultimediautils.h \
+ $$PWD/jmediarecorder.h
+
+SOURCES += \
+ $$PWD/jmediaplayer.cpp \
+ $$PWD/jsurfacetexture.cpp \
+ $$PWD/jsurfacetextureholder.cpp \
+ $$PWD/jmediametadataretriever.cpp \
+ $$PWD/jcamera.cpp \
+ $$PWD/jmultimediautils.cpp \
+ $$PWD/jmediarecorder.cpp