summaryrefslogtreecommitdiffstats
path: root/src/plugins/android/src/wrappers/jcamera.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/android/src/wrappers/jcamera.cpp')
-rw-r--r--src/plugins/android/src/wrappers/jcamera.cpp712
1 files changed, 712 insertions, 0 deletions
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