diff options
author | Christian Strømme <christian.stromme@digia.com> | 2014-04-03 18:09:48 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-04-15 16:46:57 +0200 |
commit | b088962950dbc4c6f0219de30b0d9a8cf47a3376 (patch) | |
tree | d7d027187dd2715bf68d39ea04e9995dcf64f38e /src/plugins/android/src/wrappers | |
parent | 60a911096f04b5159b99ad444bc9ad9aedf42eb8 (diff) | |
download | qtmultimedia-b088962950dbc4c6f0219de30b0d9a8cf47a3376.tar.gz |
Android: Camera code clean-up
Change-Id: Ib400afde12067764c3dcc0f44e40ddc1abb3012f
Reviewed-by: Yoann Lopes <yoann.lopes@digia.com>
Diffstat (limited to 'src/plugins/android/src/wrappers')
-rw-r--r-- | src/plugins/android/src/wrappers/jcamera.cpp | 470 | ||||
-rw-r--r-- | src/plugins/android/src/wrappers/jcamera.h | 8 |
2 files changed, 283 insertions, 195 deletions
diff --git a/src/plugins/android/src/wrappers/jcamera.cpp b/src/plugins/android/src/wrappers/jcamera.cpp index f43e2308c..5401e6d1f 100644 --- a/src/plugins/android/src/wrappers/jcamera.cpp +++ b/src/plugins/android/src/wrappers/jcamera.cpp @@ -41,19 +41,19 @@ #include "jcamera.h" -#include <QtCore/private/qjni_p.h> #include <qstringlist.h> #include <qdebug.h> #include "qandroidmultimediautils.h" -#include <qthread.h> #include <qmutex.h> #include <QtCore/private/qjnihelpers_p.h> +#include <QtCore/qthread.h> QT_BEGIN_NAMESPACE -static jclass g_qtCameraClass = 0; -static QMap<int, JCamera*> g_objectMap; -static QMutex g_objectMapMutex; +static jclass g_qtCameraListenerClass = 0; +static QMutex g_cameraMapMutex; +typedef QMap<int, JCamera *> CameraMap; +Q_GLOBAL_STATIC(CameraMap, g_cameraMap) static QRect areaToRect(jobject areaObj) { @@ -79,31 +79,30 @@ static QJNIObjectPrivate rectToArea(const QRect &rect) return area; } -// native method for QtCamera.java +// native method for QtCameraLisener.java static void notifyAutoFocusComplete(JNIEnv* , jobject, int id, jboolean success) { - QMutexLocker locker(&g_objectMapMutex); - JCamera *obj = g_objectMap.value(id, 0); + QMutexLocker locker(&g_cameraMapMutex); + JCamera *obj = g_cameraMap->value(id, 0); if (obj) Q_EMIT obj->autoFocusComplete(success); } static void notifyPictureExposed(JNIEnv* , jobject, int id) { - QMutexLocker locker(&g_objectMapMutex); - JCamera *obj = g_objectMap.value(id, 0); + QMutexLocker locker(&g_cameraMapMutex); + JCamera *obj = g_cameraMap->value(id, 0); if (obj) Q_EMIT obj->pictureExposed(); } static void notifyPictureCaptured(JNIEnv *env, jobject, int id, jbyteArray data) { - QMutexLocker locker(&g_objectMapMutex); - JCamera *obj = g_objectMap.value(id, 0); + QMutexLocker locker(&g_cameraMapMutex); + JCamera *obj = g_cameraMap->value(id, 0); if (obj) { - QByteArray bytes; - int arrayLength = env->GetArrayLength(data); - bytes.resize(arrayLength); + const int arrayLength = env->GetArrayLength(data); + QByteArray bytes(arrayLength, Qt::Uninitialized); env->GetByteArrayRegion(data, 0, arrayLength, (jbyte*)bytes.data()); Q_EMIT obj->pictureCaptured(bytes); } @@ -111,46 +110,30 @@ static void notifyPictureCaptured(JNIEnv *env, jobject, int id, jbyteArray data) static void notifyFrameFetched(JNIEnv *env, jobject, int id, jbyteArray data) { - QMutexLocker locker(&g_objectMapMutex); - JCamera *obj = g_objectMap.value(id, 0); + QMutexLocker locker(&g_cameraMapMutex); + JCamera *obj = g_cameraMap->value(id, 0); if (obj) { - QByteArray bytes; - int arrayLength = env->GetArrayLength(data); - bytes.resize(arrayLength); + const int arrayLength = env->GetArrayLength(data); + QByteArray bytes(arrayLength, Qt::Uninitialized); env->GetByteArrayRegion(data, 0, arrayLength, (jbyte*)bytes.data()); Q_EMIT obj->frameFetched(bytes); } } -class JCameraInstantiator : public QObject +class JCameraPrivate : public QObject { Q_OBJECT public: - JCameraInstantiator() : QObject(0) {} - QJNIObjectPrivate result() {return lastCamera;} -public slots: - void openCamera(int cameraId) - { - QJNIEnvironmentPrivate env; - lastCamera = QJNIObjectPrivate::callStaticObjectMethod(g_qtCameraClass, - "open", - "(I)Lorg/qtproject/qt5/android/multimedia/QtCamera;", - cameraId); - } -private: - QJNIObjectPrivate lastCamera; -}; + JCameraPrivate(); + ~JCameraPrivate(); -class JCameraWorker : public QObject -{ - Q_OBJECT - friend class JCamera; - - JCameraWorker(JCamera *camera, int cameraId, jobject cam, QThread *workerThread); - ~JCameraWorker(); + Q_INVOKABLE bool init(int cameraId); Q_INVOKABLE void release(); + Q_INVOKABLE void lock(); + Q_INVOKABLE void unlock(); + Q_INVOKABLE void reconnect(); Q_INVOKABLE JCamera::CameraFacing getFacing(); Q_INVOKABLE int getNativeOrientation(); @@ -182,6 +165,7 @@ class JCameraWorker : public QObject Q_INVOKABLE void setFocusAreas(const QList<QRect> &areas); Q_INVOKABLE void autoFocus(); + Q_INVOKABLE void cancelAutoFocus(); Q_INVOKABLE bool isAutoExposureLockSupported(); Q_INVOKABLE bool getAutoExposureLock(); @@ -212,26 +196,23 @@ class JCameraWorker : public QObject Q_INVOKABLE void startPreview(); Q_INVOKABLE void stopPreview(); + Q_INVOKABLE void takePicture(); + Q_INVOKABLE void fetchEachFrame(bool fetch); Q_INVOKABLE void fetchLastPreviewFrame(); Q_INVOKABLE void applyParameters(); Q_INVOKABLE QStringList callParametersStringListMethod(const QByteArray &methodName); - Q_INVOKABLE void callVoidMethod(const QByteArray &methodName); int m_cameraId; - QJNIObjectPrivate m_info; - QJNIObjectPrivate m_parameters; - + QMutex m_parametersMutex; QSize m_previewSize; int m_rotation; - - JCamera *q; - - QThread *m_workerThread; - QMutex m_parametersMutex; + QJNIObjectPrivate m_info; + QJNIObjectPrivate m_parameters; QJNIObjectPrivate m_camera; + QJNIObjectPrivate m_cameraListener; Q_SIGNALS: void previewSizeChanged(); @@ -245,122 +226,137 @@ Q_SIGNALS: void previewFetched(const QByteArray &preview); }; +JCamera::JCamera(JCameraPrivate *d, QThread *worker) + : QObject(), + d_ptr(d), + m_worker(worker) - -JCamera::JCamera(int cameraId, jobject cam, QThread *workerThread) - : QObject() { qRegisterMetaType<QList<int> >(); qRegisterMetaType<QList<QSize> >(); qRegisterMetaType<QList<QRect> >(); - d = new JCameraWorker(this, cameraId, cam, workerThread); - connect(d, &JCameraWorker::previewSizeChanged, this, &JCamera::previewSizeChanged); - connect(d, &JCameraWorker::previewStarted, this, &JCamera::previewStarted); - connect(d, &JCameraWorker::previewStopped, this, &JCamera::previewStopped); - connect(d, &JCameraWorker::autoFocusStarted, this, &JCamera::autoFocusStarted); - connect(d, &JCameraWorker::whiteBalanceChanged, this, &JCamera::whiteBalanceChanged); - connect(d, &JCameraWorker::previewFetched, this, &JCamera::previewFetched); + connect(d, &JCameraPrivate::previewSizeChanged, this, &JCamera::previewSizeChanged); + connect(d, &JCameraPrivate::previewStarted, this, &JCamera::previewStarted); + connect(d, &JCameraPrivate::previewStopped, this, &JCamera::previewStopped); + connect(d, &JCameraPrivate::autoFocusStarted, this, &JCamera::autoFocusStarted); + connect(d, &JCameraPrivate::whiteBalanceChanged, this, &JCamera::whiteBalanceChanged); + connect(d, &JCameraPrivate::previewFetched, this, &JCamera::previewFetched); } JCamera::~JCamera() { + Q_D(JCamera); if (d->m_camera.isValid()) { - g_objectMapMutex.lock(); - g_objectMap.remove(d->m_cameraId); - g_objectMapMutex.unlock(); + g_cameraMapMutex.lock(); + g_cameraMap->remove(d->m_cameraId); + g_cameraMapMutex.unlock(); } - d->deleteLater(); + + release(); + m_worker->exit(); + m_worker->wait(5000); } JCamera *JCamera::open(int cameraId) { - QThread *cameraThread = new QThread; - connect(cameraThread, &QThread::finished, cameraThread, &QThread::deleteLater); - cameraThread->start(); - JCameraInstantiator *instantiator = new JCameraInstantiator; - instantiator->moveToThread(cameraThread); - QMetaObject::invokeMethod(instantiator, "openCamera", - Qt::BlockingQueuedConnection, - Q_ARG(int, cameraId)); - QJNIObjectPrivate camera = instantiator->result(); - delete instantiator; - - if (!camera.isValid()) { - cameraThread->terminate(); - delete cameraThread; + JCameraPrivate *d = new JCameraPrivate(); + QThread *worker = new QThread; + worker->start(); + d->moveToThread(worker); + connect(worker, &QThread::finished, d, &JCameraPrivate::deleteLater); + bool ok = false; + QMetaObject::invokeMethod(d, "init", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, ok), Q_ARG(int, cameraId)); + if (!ok) { + worker->quit(); + worker->wait(5000); + delete d; + delete worker; return 0; - } else { - return new JCamera(cameraId, camera.object(), cameraThread); } + + JCamera *q = new JCamera(d, worker); + g_cameraMapMutex.lock(); + g_cameraMap->insert(cameraId, q); + g_cameraMapMutex.unlock(); + return q; } int JCamera::cameraId() const { + Q_D(const JCamera); return d->m_cameraId; } void JCamera::lock() { - QMetaObject::invokeMethod(d, "callVoidMethod", - Qt::BlockingQueuedConnection, - Q_ARG(QByteArray, "lock")); + Q_D(JCamera); + QMetaObject::invokeMethod(d, "lock", Qt::BlockingQueuedConnection); } void JCamera::unlock() { - QMetaObject::invokeMethod(d, "callVoidMethod", - Qt::BlockingQueuedConnection, - Q_ARG(QByteArray, "unlock")); + Q_D(JCamera); + QMetaObject::invokeMethod(d, "unlock", Qt::BlockingQueuedConnection); } void JCamera::reconnect() { - QMetaObject::invokeMethod(d, "callVoidMethod", Q_ARG(QByteArray, "reconnect")); + Q_D(JCamera); + QMetaObject::invokeMethod(d, "reconnect"); } void JCamera::release() { - QMetaObject::invokeMethod(d, "release"); + Q_D(JCamera); + QMetaObject::invokeMethod(d, "release", Qt::BlockingQueuedConnection); } JCamera::CameraFacing JCamera::getFacing() { + Q_D(JCamera); return d->getFacing(); } int JCamera::getNativeOrientation() { + Q_D(JCamera); return d->getNativeOrientation(); } QSize JCamera::getPreferredPreviewSizeForVideo() { + Q_D(JCamera); return d->getPreferredPreviewSizeForVideo(); } QList<QSize> JCamera::getSupportedPreviewSizes() { + Q_D(JCamera); return d->getSupportedPreviewSizes(); } JCamera::ImageFormat JCamera::getPreviewFormat() { + Q_D(JCamera); return d->getPreviewFormat(); } void JCamera::setPreviewFormat(ImageFormat fmt) { + Q_D(JCamera); QMetaObject::invokeMethod(d, "setPreviewFormat", Q_ARG(JCamera::ImageFormat, fmt)); } QSize JCamera::previewSize() const { + Q_D(const JCamera); return d->m_previewSize; } void JCamera::setPreviewSize(const QSize &size) { + Q_D(JCamera); d->m_parametersMutex.lock(); bool areParametersValid = d->m_parameters.isValid(); d->m_parametersMutex.unlock(); @@ -373,176 +369,211 @@ void JCamera::setPreviewSize(const QSize &size) void JCamera::setPreviewTexture(jobject surfaceTexture) { - QMetaObject::invokeMethod(d, "setPreviewTexture", Q_ARG(void *, surfaceTexture)); + Q_D(JCamera); + QMetaObject::invokeMethod(d, "setPreviewTexture", Qt::BlockingQueuedConnection, Q_ARG(void *, surfaceTexture)); } bool JCamera::isZoomSupported() { + Q_D(JCamera); return d->isZoomSupported(); } int JCamera::getMaxZoom() { + Q_D(JCamera); return d->getMaxZoom(); } QList<int> JCamera::getZoomRatios() { + Q_D(JCamera); return d->getZoomRatios(); } int JCamera::getZoom() { + Q_D(JCamera); return d->getZoom(); } void JCamera::setZoom(int value) { + Q_D(JCamera); QMetaObject::invokeMethod(d, "setZoom", Q_ARG(int, value)); } QStringList JCamera::getSupportedFlashModes() { + Q_D(JCamera); return d->callParametersStringListMethod("getSupportedFlashModes"); } QString JCamera::getFlashMode() { + Q_D(JCamera); return d->getFlashMode(); } void JCamera::setFlashMode(const QString &value) { + Q_D(JCamera); QMetaObject::invokeMethod(d, "setFlashMode", Q_ARG(QString, value)); } QStringList JCamera::getSupportedFocusModes() { + Q_D(JCamera); return d->callParametersStringListMethod("getSupportedFocusModes"); } QString JCamera::getFocusMode() { + Q_D(JCamera); return d->getFocusMode(); } void JCamera::setFocusMode(const QString &value) { + Q_D(JCamera); QMetaObject::invokeMethod(d, "setFocusMode", Q_ARG(QString, value)); } int JCamera::getMaxNumFocusAreas() { + Q_D(JCamera); return d->getMaxNumFocusAreas(); } QList<QRect> JCamera::getFocusAreas() { + Q_D(JCamera); return d->getFocusAreas(); } void JCamera::setFocusAreas(const QList<QRect> &areas) { + Q_D(JCamera); QMetaObject::invokeMethod(d, "setFocusAreas", Q_ARG(QList<QRect>, areas)); } void JCamera::autoFocus() { + Q_D(JCamera); QMetaObject::invokeMethod(d, "autoFocus"); } void JCamera::cancelAutoFocus() { - QMetaObject::invokeMethod(d, "callVoidMethod", Q_ARG(QByteArray, "cancelAutoFocus")); + Q_D(JCamera); + QMetaObject::invokeMethod(d, "cancelAutoFocus", Qt::QueuedConnection); } bool JCamera::isAutoExposureLockSupported() { + Q_D(JCamera); return d->isAutoExposureLockSupported(); } bool JCamera::getAutoExposureLock() { + Q_D(JCamera); return d->getAutoExposureLock(); } void JCamera::setAutoExposureLock(bool toggle) { + Q_D(JCamera); QMetaObject::invokeMethod(d, "setAutoExposureLock", Q_ARG(bool, toggle)); } bool JCamera::isAutoWhiteBalanceLockSupported() { + Q_D(JCamera); return d->isAutoWhiteBalanceLockSupported(); } bool JCamera::getAutoWhiteBalanceLock() { + Q_D(JCamera); return d->getAutoWhiteBalanceLock(); } void JCamera::setAutoWhiteBalanceLock(bool toggle) { + Q_D(JCamera); QMetaObject::invokeMethod(d, "setAutoWhiteBalanceLock", Q_ARG(bool, toggle)); } int JCamera::getExposureCompensation() { + Q_D(JCamera); return d->getExposureCompensation(); } void JCamera::setExposureCompensation(int value) { + Q_D(JCamera); QMetaObject::invokeMethod(d, "setExposureCompensation", Q_ARG(int, value)); } float JCamera::getExposureCompensationStep() { + Q_D(JCamera); return d->getExposureCompensationStep(); } int JCamera::getMinExposureCompensation() { + Q_D(JCamera); return d->getMinExposureCompensation(); } int JCamera::getMaxExposureCompensation() { + Q_D(JCamera); return d->getMaxExposureCompensation(); } QStringList JCamera::getSupportedSceneModes() { + Q_D(JCamera); return d->callParametersStringListMethod("getSupportedSceneModes"); } QString JCamera::getSceneMode() { + Q_D(JCamera); return d->getSceneMode(); } void JCamera::setSceneMode(const QString &value) { + Q_D(JCamera); QMetaObject::invokeMethod(d, "setSceneMode", Q_ARG(QString, value)); } QStringList JCamera::getSupportedWhiteBalance() { + Q_D(JCamera); return d->callParametersStringListMethod("getSupportedWhiteBalance"); } QString JCamera::getWhiteBalance() { + Q_D(JCamera); return d->getWhiteBalance(); } void JCamera::setWhiteBalance(const QString &value) { + Q_D(JCamera); QMetaObject::invokeMethod(d, "setWhiteBalance", Q_ARG(QString, value)); } void JCamera::setRotation(int rotation) { + Q_D(JCamera); //We need to do it here and not in worker class because we cache rotation d->m_parametersMutex.lock(); bool areParametersValid = d->m_parameters.isValid(); @@ -556,110 +587,143 @@ void JCamera::setRotation(int rotation) int JCamera::getRotation() const { + Q_D(const JCamera); return d->m_rotation; } QList<QSize> JCamera::getSupportedPictureSizes() { + Q_D(JCamera); return d->getSupportedPictureSizes(); } void JCamera::setPictureSize(const QSize &size) { + Q_D(JCamera); QMetaObject::invokeMethod(d, "setPictureSize", Q_ARG(QSize, size)); } void JCamera::setJpegQuality(int quality) { + Q_D(JCamera); QMetaObject::invokeMethod(d, "setJpegQuality", Q_ARG(int, quality)); } void JCamera::takePicture() { - QMetaObject::invokeMethod(d, "callVoidMethod", Q_ARG(QByteArray, "takePicture")); + Q_D(JCamera); + QMetaObject::invokeMethod(d, "takePicture", Qt::BlockingQueuedConnection); } void JCamera::fetchEachFrame(bool fetch) { + Q_D(JCamera); QMetaObject::invokeMethod(d, "fetchEachFrame", Q_ARG(bool, fetch)); } void JCamera::fetchLastPreviewFrame() { + Q_D(JCamera); QMetaObject::invokeMethod(d, "fetchLastPreviewFrame"); } QJNIObjectPrivate JCamera::getCameraObject() { - return d->m_camera.getObjectField("m_camera", "Landroid/hardware/Camera;"); + Q_D(JCamera); + return d->m_camera; } void JCamera::startPreview() { + Q_D(JCamera); QMetaObject::invokeMethod(d, "startPreview"); } void JCamera::stopPreview() { + Q_D(JCamera); QMetaObject::invokeMethod(d, "stopPreview"); } +JCameraPrivate::JCameraPrivate() + : QObject(), + m_parametersMutex(QMutex::Recursive) +{ +} -//JCameraWorker +JCameraPrivate::~JCameraPrivate() +{ +} -JCameraWorker::JCameraWorker(JCamera *camera, int cameraId, jobject cam, QThread *workerThread) - : QObject(0) - , m_cameraId(cameraId) - , m_rotation(0) - , m_parametersMutex(QMutex::Recursive) - , m_camera(cam) +bool JCameraPrivate::init(int cameraId) { - q = camera; - m_workerThread = workerThread; - moveToThread(m_workerThread); + m_cameraId = cameraId; + m_camera = QJNIObjectPrivate::callStaticObjectMethod("android/hardware/Camera", + "open", + "(I)Landroid/hardware/Camera;", + cameraId); - if (m_camera.isValid()) { - g_objectMapMutex.lock(); - g_objectMap.insert(cameraId, q); - g_objectMapMutex.unlock(); + if (!m_camera.isValid()) + return false; - m_info = QJNIObjectPrivate("android/hardware/Camera$CameraInfo"); - m_camera.callStaticMethod<void>("android/hardware/Camera", - "getCameraInfo", - "(ILandroid/hardware/Camera$CameraInfo;)V", - cameraId, m_info.object()); + m_cameraListener = QJNIObjectPrivate(g_qtCameraListenerClass, "(I)V", m_cameraId); + m_info = QJNIObjectPrivate("android/hardware/Camera$CameraInfo"); + m_camera.callStaticMethod<void>("android/hardware/Camera", + "getCameraInfo", + "(ILandroid/hardware/Camera$CameraInfo;)V", + cameraId, + m_info.object()); - QJNIObjectPrivate params = m_camera.callObjectMethod("getParameters", - "()Landroid/hardware/Camera$Parameters;"); - m_parameters = QJNIObjectPrivate(params); - } -} + QJNIObjectPrivate params = m_camera.callObjectMethod("getParameters", + "()Landroid/hardware/Camera$Parameters;"); + m_parameters = QJNIObjectPrivate(params); -JCameraWorker::~JCameraWorker() -{ - m_workerThread->quit(); + return true; } -void JCameraWorker::release() +void JCameraPrivate::release() { m_previewSize = QSize(); m_parametersMutex.lock(); m_parameters = QJNIObjectPrivate(); m_parametersMutex.unlock(); - m_camera.callMethod<void>("release"); + if (m_camera.isValid()) + m_camera.callMethod<void>("release"); +} + +void JCameraPrivate::lock() +{ + m_camera.callMethod<void>("lock"); +} + +void JCameraPrivate::unlock() +{ + m_camera.callMethod<void>("unlock"); +} + +void JCameraPrivate::reconnect() +{ + QJNIEnvironmentPrivate env; + m_camera.callMethod<void>("reconnect"); + if (env->ExceptionCheck()) { +#ifdef QT_DEBUG + env->ExceptionDescribe(); +#endif // QT_DEBUG + env->ExceptionDescribe(); + } } -JCamera::CameraFacing JCameraWorker::getFacing() +JCamera::CameraFacing JCameraPrivate::getFacing() { return JCamera::CameraFacing(m_info.getField<jint>("facing")); } -int JCameraWorker::getNativeOrientation() +int JCameraPrivate::getNativeOrientation() { return m_info.getField<jint>("orientation"); } -QSize JCameraWorker::getPreferredPreviewSizeForVideo() +QSize JCameraPrivate::getPreferredPreviewSizeForVideo() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -672,7 +736,7 @@ QSize JCameraWorker::getPreferredPreviewSizeForVideo() return QSize(size.getField<jint>("width"), size.getField<jint>("height")); } -QList<QSize> JCameraWorker::getSupportedPreviewSizes() +QList<QSize> JCameraPrivate::getSupportedPreviewSizes() { QList<QSize> list; @@ -695,7 +759,7 @@ QList<QSize> JCameraWorker::getSupportedPreviewSizes() return list; } -JCamera::ImageFormat JCameraWorker::getPreviewFormat() +JCamera::ImageFormat JCameraPrivate::getPreviewFormat() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -705,7 +769,7 @@ JCamera::ImageFormat JCameraWorker::getPreviewFormat() return JCamera::ImageFormat(m_parameters.callMethod<jint>("getPreviewFormat")); } -void JCameraWorker::setPreviewFormat(JCamera::ImageFormat fmt) +void JCameraPrivate::setPreviewFormat(JCamera::ImageFormat fmt) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -716,7 +780,7 @@ void JCameraWorker::setPreviewFormat(JCamera::ImageFormat fmt) applyParameters(); } -void JCameraWorker::updatePreviewSize() +void JCameraPrivate::updatePreviewSize() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -728,14 +792,14 @@ void JCameraWorker::updatePreviewSize() emit previewSizeChanged(); } -void JCameraWorker::setPreviewTexture(void *surfaceTexture) +void JCameraPrivate::setPreviewTexture(void *surfaceTexture) { m_camera.callMethod<void>("setPreviewTexture", "(Landroid/graphics/SurfaceTexture;)V", static_cast<jobject>(surfaceTexture)); } -bool JCameraWorker::isZoomSupported() +bool JCameraPrivate::isZoomSupported() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -745,7 +809,7 @@ bool JCameraWorker::isZoomSupported() return m_parameters.callMethod<jboolean>("isZoomSupported"); } -int JCameraWorker::getMaxZoom() +int JCameraPrivate::getMaxZoom() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -755,7 +819,7 @@ int JCameraWorker::getMaxZoom() return m_parameters.callMethod<jint>("getMaxZoom"); } -QList<int> JCameraWorker::getZoomRatios() +QList<int> JCameraPrivate::getZoomRatios() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -777,7 +841,7 @@ QList<int> JCameraWorker::getZoomRatios() return ratios; } -int JCameraWorker::getZoom() +int JCameraPrivate::getZoom() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -787,7 +851,7 @@ int JCameraWorker::getZoom() return m_parameters.callMethod<jint>("getZoom"); } -void JCameraWorker::setZoom(int value) +void JCameraPrivate::setZoom(int value) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -798,7 +862,7 @@ void JCameraWorker::setZoom(int value) applyParameters(); } -QString JCameraWorker::getFlashMode() +QString JCameraPrivate::getFlashMode() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -814,7 +878,7 @@ QString JCameraWorker::getFlashMode() return value; } -void JCameraWorker::setFlashMode(const QString &value) +void JCameraPrivate::setFlashMode(const QString &value) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -827,7 +891,7 @@ void JCameraWorker::setFlashMode(const QString &value) applyParameters(); } -QString JCameraWorker::getFocusMode() +QString JCameraPrivate::getFocusMode() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -843,7 +907,7 @@ QString JCameraWorker::getFocusMode() return value; } -void JCameraWorker::setFocusMode(const QString &value) +void JCameraPrivate::setFocusMode(const QString &value) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -856,7 +920,7 @@ void JCameraWorker::setFocusMode(const QString &value) applyParameters(); } -int JCameraWorker::getMaxNumFocusAreas() +int JCameraPrivate::getMaxNumFocusAreas() { if (QtAndroidPrivate::androidSdkVersion() < 14) return 0; @@ -869,7 +933,7 @@ int JCameraWorker::getMaxNumFocusAreas() return m_parameters.callMethod<jint>("getMaxNumFocusAreas"); } -QList<QRect> JCameraWorker::getFocusAreas() +QList<QRect> JCameraPrivate::getFocusAreas() { QList<QRect> areas; @@ -897,7 +961,7 @@ QList<QRect> JCameraWorker::getFocusAreas() return areas; } -void JCameraWorker::setFocusAreas(const QList<QRect> &areas) +void JCameraPrivate::setFocusAreas(const QList<QRect> &areas) { if (QtAndroidPrivate::androidSdkVersion() < 14) return; @@ -927,13 +991,20 @@ void JCameraWorker::setFocusAreas(const QList<QRect> &areas) applyParameters(); } -void JCameraWorker::autoFocus() +void JCameraPrivate::autoFocus() { - m_camera.callMethod<void>("autoFocus"); + m_camera.callMethod<void>("autoFocus", + "(Landroid/hardware/Camera$AutoFocusCallback;)V", + m_cameraListener.object()); emit autoFocusStarted(); } -bool JCameraWorker::isAutoExposureLockSupported() +void JCameraPrivate::cancelAutoFocus() +{ + m_camera.callMethod<void>("cancelAutoFocus"); +} + +bool JCameraPrivate::isAutoExposureLockSupported() { if (QtAndroidPrivate::androidSdkVersion() < 14) return false; @@ -946,7 +1017,7 @@ bool JCameraWorker::isAutoExposureLockSupported() return m_parameters.callMethod<jboolean>("isAutoExposureLockSupported"); } -bool JCameraWorker::getAutoExposureLock() +bool JCameraPrivate::getAutoExposureLock() { if (QtAndroidPrivate::androidSdkVersion() < 14) return false; @@ -959,7 +1030,7 @@ bool JCameraWorker::getAutoExposureLock() return m_parameters.callMethod<jboolean>("getAutoExposureLock"); } -void JCameraWorker::setAutoExposureLock(bool toggle) +void JCameraPrivate::setAutoExposureLock(bool toggle) { if (QtAndroidPrivate::androidSdkVersion() < 14) return; @@ -973,7 +1044,7 @@ void JCameraWorker::setAutoExposureLock(bool toggle) applyParameters(); } -bool JCameraWorker::isAutoWhiteBalanceLockSupported() +bool JCameraPrivate::isAutoWhiteBalanceLockSupported() { if (QtAndroidPrivate::androidSdkVersion() < 14) return false; @@ -986,7 +1057,7 @@ bool JCameraWorker::isAutoWhiteBalanceLockSupported() return m_parameters.callMethod<jboolean>("isAutoWhiteBalanceLockSupported"); } -bool JCameraWorker::getAutoWhiteBalanceLock() +bool JCameraPrivate::getAutoWhiteBalanceLock() { if (QtAndroidPrivate::androidSdkVersion() < 14) return false; @@ -999,7 +1070,7 @@ bool JCameraWorker::getAutoWhiteBalanceLock() return m_parameters.callMethod<jboolean>("getAutoWhiteBalanceLock"); } -void JCameraWorker::setAutoWhiteBalanceLock(bool toggle) +void JCameraPrivate::setAutoWhiteBalanceLock(bool toggle) { if (QtAndroidPrivate::androidSdkVersion() < 14) return; @@ -1013,7 +1084,7 @@ void JCameraWorker::setAutoWhiteBalanceLock(bool toggle) applyParameters(); } -int JCameraWorker::getExposureCompensation() +int JCameraPrivate::getExposureCompensation() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1023,7 +1094,7 @@ int JCameraWorker::getExposureCompensation() return m_parameters.callMethod<jint>("getExposureCompensation"); } -void JCameraWorker::setExposureCompensation(int value) +void JCameraPrivate::setExposureCompensation(int value) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1034,7 +1105,7 @@ void JCameraWorker::setExposureCompensation(int value) applyParameters(); } -float JCameraWorker::getExposureCompensationStep() +float JCameraPrivate::getExposureCompensationStep() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1044,7 +1115,7 @@ float JCameraWorker::getExposureCompensationStep() return m_parameters.callMethod<jfloat>("getExposureCompensationStep"); } -int JCameraWorker::getMinExposureCompensation() +int JCameraPrivate::getMinExposureCompensation() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1054,7 +1125,7 @@ int JCameraWorker::getMinExposureCompensation() return m_parameters.callMethod<jint>("getMinExposureCompensation"); } -int JCameraWorker::getMaxExposureCompensation() +int JCameraPrivate::getMaxExposureCompensation() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1064,7 +1135,7 @@ int JCameraWorker::getMaxExposureCompensation() return m_parameters.callMethod<jint>("getMaxExposureCompensation"); } -QString JCameraWorker::getSceneMode() +QString JCameraPrivate::getSceneMode() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1080,7 +1151,7 @@ QString JCameraWorker::getSceneMode() return value; } -void JCameraWorker::setSceneMode(const QString &value) +void JCameraPrivate::setSceneMode(const QString &value) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1093,7 +1164,7 @@ void JCameraWorker::setSceneMode(const QString &value) applyParameters(); } -QString JCameraWorker::getWhiteBalance() +QString JCameraPrivate::getWhiteBalance() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1109,7 +1180,7 @@ QString JCameraWorker::getWhiteBalance() return value; } -void JCameraWorker::setWhiteBalance(const QString &value) +void JCameraPrivate::setWhiteBalance(const QString &value) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1124,7 +1195,7 @@ void JCameraWorker::setWhiteBalance(const QString &value) emit whiteBalanceChanged(); } -void JCameraWorker::updateRotation() +void JCameraPrivate::updateRotation() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1132,7 +1203,7 @@ void JCameraWorker::updateRotation() applyParameters(); } -QList<QSize> JCameraWorker::getSupportedPictureSizes() +QList<QSize> JCameraPrivate::getSupportedPictureSizes() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1155,7 +1226,7 @@ QList<QSize> JCameraWorker::getSupportedPictureSizes() return list; } -void JCameraWorker::setPictureSize(const QSize &size) +void JCameraPrivate::setPictureSize(const QSize &size) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1166,7 +1237,7 @@ void JCameraWorker::setPictureSize(const QSize &size) applyParameters(); } -void JCameraWorker::setJpegQuality(int quality) +void JCameraPrivate::setJpegQuality(int quality) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1177,49 +1248,71 @@ void JCameraWorker::setJpegQuality(int quality) applyParameters(); } -void JCameraWorker::startPreview() -{ - callVoidMethod("startPreview"); +void JCameraPrivate::startPreview() +{ + //We need to clear preview buffers queue here, but there is no method to do it + //Though just resetting preview callback do the trick + m_camera.callMethod<void>("setPreviewCallbackWithBuffer", + "(Landroid/hardware/Camera$PreviewCallback;)V", + jobject(0)); + m_cameraListener.callMethod<void>("preparePreviewBuffer", "(Landroid/hardware/Camera;)V", m_camera.object()); + QJNIObjectPrivate buffer = m_cameraListener.callObjectMethod<jbyteArray>("callbackBuffer"); + m_camera.callMethod<void>("addCallbackBuffer", "([B)V", buffer.object()); + m_camera.callMethod<void>("setPreviewCallbackWithBuffer", + "(Landroid/hardware/Camera$PreviewCallback;)V", + m_cameraListener.object()); + m_camera.callMethod<void>("startPreview"); emit previewStarted(); } -void JCameraWorker::stopPreview() +void JCameraPrivate::stopPreview() { - callVoidMethod("stopPreview"); + m_camera.callMethod<void>("stopPreview"); emit previewStopped(); } -void JCameraWorker::fetchEachFrame(bool fetch) +void JCameraPrivate::takePicture() +{ + m_camera.callMethod<void>("takePicture", "(Landroid/hardware/Camera$ShutterCallback;" + "Landroid/hardware/Camera$PictureCallback;" + "Landroid/hardware/Camera$PictureCallback;)V", + m_cameraListener.object(), + jobject(0), + m_cameraListener.object()); +} + +void JCameraPrivate::fetchEachFrame(bool fetch) { - m_camera.callMethod<void>("fetchEachFrame", "(Z)V", fetch); + m_cameraListener.callMethod<void>("fetchEachFrame", "(Z)V", fetch); } -void JCameraWorker::fetchLastPreviewFrame() +void JCameraPrivate::fetchLastPreviewFrame() { QJNIEnvironmentPrivate env; - QJNIObjectPrivate dataObj = m_camera.callObjectMethod("lockAndFetchPreviewBuffer", "()[B"); - if (!dataObj.object()) { - m_camera.callMethod<void>("unlockPreviewBuffer"); + QJNIObjectPrivate data = m_cameraListener.callObjectMethod("lockAndFetchPreviewBuffer", "()[B"); + if (!data.isValid()) { + m_cameraListener.callMethod<void>("unlockPreviewBuffer"); return; } - jbyteArray data = static_cast<jbyteArray>(dataObj.object()); - QByteArray bytes; - int arrayLength = env->GetArrayLength(data); - bytes.resize(arrayLength); - env->GetByteArrayRegion(data, 0, arrayLength, (jbyte*)bytes.data()); - m_camera.callMethod<void>("unlockPreviewBuffer"); + const int arrayLength = env->GetArrayLength(static_cast<jbyteArray>(data.object())); + QByteArray bytes(arrayLength, Qt::Uninitialized); + env->GetByteArrayRegion(static_cast<jbyteArray>(data.object()), + 0, + arrayLength, + reinterpret_cast<jbyte *>(bytes.data())); + m_cameraListener.callMethod<void>("unlockPreviewBuffer"); emit previewFetched(bytes); } -void JCameraWorker::applyParameters() +void JCameraPrivate::applyParameters() { m_camera.callMethod<void>("setParameters", "(Landroid/hardware/Camera$Parameters;)V", m_parameters.object()); } -QStringList JCameraWorker::callParametersStringListMethod(const QByteArray &methodName) +QStringList JCameraPrivate::callParametersStringListMethod(const QByteArray &methodName) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1235,7 +1328,6 @@ QStringList JCameraWorker::callParametersStringListMethod(const QByteArray &meth QJNIObjectPrivate string = list.callObjectMethod("get", "(I)Ljava/lang/Object;", i); - stringList.append(string.toString()); } } @@ -1244,12 +1336,6 @@ QStringList JCameraWorker::callParametersStringListMethod(const QByteArray &meth return stringList; } -void JCameraWorker::callVoidMethod(const QByteArray &methodName) -{ - m_camera.callMethod<void>(methodName.constData()); -} - - static JNINativeMethod methods[] = { {"notifyAutoFocusComplete", "(IZ)V", (void *)notifyAutoFocusComplete}, {"notifyPictureExposed", "(I)V", (void *)notifyPictureExposed}, @@ -1259,13 +1345,13 @@ static JNINativeMethod methods[] = { bool JCamera::initJNI(JNIEnv *env) { - jclass clazz = env->FindClass("org/qtproject/qt5/android/multimedia/QtCamera"); + jclass clazz = env->FindClass("org/qtproject/qt5/android/multimedia/QtCameraListener"); if (env->ExceptionCheck()) env->ExceptionClear(); if (clazz) { - g_qtCameraClass = static_cast<jclass>(env->NewGlobalRef(clazz)); - if (env->RegisterNatives(g_qtCameraClass, + g_qtCameraListenerClass = static_cast<jclass>(env->NewGlobalRef(clazz)); + if (env->RegisterNatives(g_qtCameraListenerClass, methods, sizeof(methods) / sizeof(methods[0])) < 0) { return false; diff --git a/src/plugins/android/src/wrappers/jcamera.h b/src/plugins/android/src/wrappers/jcamera.h index 81c334eb4..ec5bcc3c7 100644 --- a/src/plugins/android/src/wrappers/jcamera.h +++ b/src/plugins/android/src/wrappers/jcamera.h @@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE class QThread; -class JCameraWorker; +class JCameraPrivate; class JCamera : public QObject { @@ -175,9 +175,11 @@ Q_SIGNALS: void frameFetched(const QByteArray &frame); private: - JCamera(int cameraId, jobject cam, QThread *workerThread); + JCamera(JCameraPrivate *d, QThread *worker); - JCameraWorker *d; + Q_DECLARE_PRIVATE(JCamera) + JCameraPrivate *d_ptr; + QScopedPointer<QThread> m_worker; }; QT_END_NAMESPACE |