From 443ed0be093b2d8e78d111a59eca97f2eba5b0fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Mon, 4 Jul 2016 17:32:24 +0200 Subject: Android: Fix attach- and detachFromGLContext() This fixes a regression caused by ba8127639857232d8a. The change assumed that the AndroidSurfaceTexture class could cope with changing textures, but since the callback from the SurfaceTextureListener was tied to the initial, invalid, texture handle, it would only work as long as there were only one texture; all textures would register the callback to the same invalid handle. This change maps the callback directly to the android texture object, instead of the texture handle. Task-number: QTBUG-54340 Change-Id: I39568d0f97fa6b9cb1182efaca568b16a26f0d09 Reviewed-by: Yoann Lopes --- .../src/wrappers/jni/androidsurfacetexture.cpp | 42 +++++++++++++++------- .../src/wrappers/jni/androidsurfacetexture.h | 4 +-- 2 files changed, 32 insertions(+), 14 deletions(-) (limited to 'src/plugins/android/src') diff --git a/src/plugins/android/src/wrappers/jni/androidsurfacetexture.cpp b/src/plugins/android/src/wrappers/jni/androidsurfacetexture.cpp index 2cea896e1..bc7187e9c 100644 --- a/src/plugins/android/src/wrappers/jni/androidsurfacetexture.cpp +++ b/src/plugins/android/src/wrappers/jni/androidsurfacetexture.cpp @@ -34,24 +34,32 @@ #include "androidsurfacetexture.h" #include #include +#include QT_BEGIN_NAMESPACE static const char QtSurfaceTextureListenerClassName[] = "org/qtproject/qt5/android/multimedia/QtSurfaceTextureListener"; -static QMap g_objectMap; +typedef QVector SurfaceTextures; +Q_GLOBAL_STATIC(SurfaceTextures, g_surfaceTextures); +Q_GLOBAL_STATIC(QMutex, g_textureMutex); // native method for QtSurfaceTexture.java -static void notifyFrameAvailable(JNIEnv* , jobject, int id) +static void notifyFrameAvailable(JNIEnv* , jobject, jlong id) { - AndroidSurfaceTexture *obj = g_objectMap.value(id, 0); + const QMutexLocker lock(g_textureMutex); + const int idx = g_surfaceTextures->indexOf(id); + if (idx == -1) + return; + + AndroidSurfaceTexture *obj = reinterpret_cast(g_surfaceTextures->at(idx)); if (obj) Q_EMIT obj->frameAvailable(); } AndroidSurfaceTexture::AndroidSurfaceTexture(unsigned int texName) : QObject() - , m_texID(int(texName)) { + Q_STATIC_ASSERT(sizeof (jlong) >= sizeof (void *)); // API level 11 or higher is required if (QtAndroidPrivate::androidSdkVersion() < 11) { qWarning("Camera preview and video playback require Android 3.0 (API level 11) or later."); @@ -67,13 +75,13 @@ AndroidSurfaceTexture::AndroidSurfaceTexture(unsigned int texName) env->ExceptionClear(); } - if (m_surfaceTexture.isValid()) - g_objectMap.insert(int(texName), this); + if (!m_surfaceTexture.isValid()) + return; - QJNIObjectPrivate listener(QtSurfaceTextureListenerClassName, "(I)V", jint(texName)); - m_surfaceTexture.callMethod("setOnFrameAvailableListener", - "(Landroid/graphics/SurfaceTexture$OnFrameAvailableListener;)V", - listener.object()); + const QMutexLocker lock(g_textureMutex); + g_surfaceTextures->append(jlong(this)); + QJNIObjectPrivate listener(QtSurfaceTextureListenerClassName, "(J)V", jlong(this)); + setOnFrameAvailableListener(listener); } AndroidSurfaceTexture::~AndroidSurfaceTexture() @@ -83,7 +91,10 @@ AndroidSurfaceTexture::~AndroidSurfaceTexture() if (m_surfaceTexture.isValid()) { release(); - g_objectMap.remove(m_texID); + const QMutexLocker lock(g_textureMutex); + const int idx = g_surfaceTextures->indexOf(jlong(this)); + if (idx != -1) + g_surfaceTextures->remove(idx); } } @@ -172,7 +183,7 @@ bool AndroidSurfaceTexture::initJNI(JNIEnv *env) env); static const JNINativeMethod methods[] = { - {"notifyFrameAvailable", "(I)V", (void *)notifyFrameAvailable} + {"notifyFrameAvailable", "(J)V", (void *)notifyFrameAvailable} }; if (clazz && env->RegisterNatives(clazz, @@ -184,4 +195,11 @@ bool AndroidSurfaceTexture::initJNI(JNIEnv *env) return true; } +void AndroidSurfaceTexture::setOnFrameAvailableListener(const QJNIObjectPrivate &listener) +{ + m_surfaceTexture.callMethod("setOnFrameAvailableListener", + "(Landroid/graphics/SurfaceTexture$OnFrameAvailableListener;)V", + listener.object()); +} + QT_END_NAMESPACE diff --git a/src/plugins/android/src/wrappers/jni/androidsurfacetexture.h b/src/plugins/android/src/wrappers/jni/androidsurfacetexture.h index a08483e5e..3c41bf51d 100644 --- a/src/plugins/android/src/wrappers/jni/androidsurfacetexture.h +++ b/src/plugins/android/src/wrappers/jni/androidsurfacetexture.h @@ -48,7 +48,6 @@ public: explicit AndroidSurfaceTexture(unsigned int texName); ~AndroidSurfaceTexture(); - int textureID() const { return m_texID; } jobject surfaceTexture(); jobject surface(); jobject surfaceHolder(); @@ -67,7 +66,8 @@ Q_SIGNALS: void frameAvailable(); private: - int m_texID; + void setOnFrameAvailableListener(const QJNIObjectPrivate &listener); + QJNIObjectPrivate m_surfaceTexture; QJNIObjectPrivate m_surface; QJNIObjectPrivate m_surfaceHolder; -- cgit v1.2.3 From 278fd530f0ad883f88e15d3403f1ab63fbdeb131 Mon Sep 17 00:00:00 2001 From: Pavel Golikov Date: Wed, 6 Jul 2016 15:22:31 +0300 Subject: Android: Fix OpenGL texture name leak This fixes texture name leak when changing media player's source. Texture name shold be deleted by OpenGLResourcesDeleter class, but when player's source is changed OpenGLResourcesDeleter's texture name is reassigned with new one without old name deletion. This change deletes OpenGLResourcesDeleter's current texture name when new name is assigned. Task-number: QTBUG-54340 Change-Id: I22bbd60b4462b0034fd115f0582ea43b9bcaee4b Reviewed-by: Yoann Lopes --- src/plugins/android/src/common/qandroidvideooutput.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/plugins/android/src') diff --git a/src/plugins/android/src/common/qandroidvideooutput.cpp b/src/plugins/android/src/common/qandroidvideooutput.cpp index f69be679a..f462a28d5 100644 --- a/src/plugins/android/src/common/qandroidvideooutput.cpp +++ b/src/plugins/android/src/common/qandroidvideooutput.cpp @@ -141,7 +141,13 @@ public: delete m_program; } - void setTexture(quint32 id) { m_textureID = id; } + void setTexture(quint32 id) { + if (m_textureID) + glDeleteTextures(1, &m_textureID); + + m_textureID = id; + } + void setFbo(QOpenGLFramebufferObject *fbo) { m_fbo = fbo; } void setShaderProgram(QOpenGLShaderProgram *prog) { m_program = prog; } -- cgit v1.2.3 From 6f28963c50261fffdabd48be0b0dfe20480277bb Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Wed, 20 Jul 2016 15:47:58 +0300 Subject: Make sure JNI_OnLoad is not called more than once Since Android 5.0 Google introduce a nasty bug[1] which calls JNI_OnLoad more than once. Basically every time when a library is loaded JNI_OnLoad is called if found, but it calls *again* JNI_OnLoad of its .so dependencies! [1] Workaround https://code.google.com/p/android/issues/detail?id=215069 Change-Id: I81b4a94beedaad299267ac6deab2f9c3a1693a62 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/plugins/android/src/qandroidmediaserviceplugin.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/plugins/android/src') diff --git a/src/plugins/android/src/qandroidmediaserviceplugin.cpp b/src/plugins/android/src/qandroidmediaserviceplugin.cpp index bf89badb3..91381b76d 100644 --- a/src/plugins/android/src/qandroidmediaserviceplugin.cpp +++ b/src/plugins/android/src/qandroidmediaserviceplugin.cpp @@ -145,6 +145,11 @@ QT_END_NAMESPACE #ifndef Q_OS_ANDROID_NO_SDK Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void * /*reserved*/) { + static bool initialized = false; + if (initialized) + return JNI_VERSION_1_6; + initialized = true; + QT_USE_NAMESPACE typedef union { JNIEnv *nativeEnvironment; -- cgit v1.2.3 From d7d31d63db5f0029a4a5e24d998601baee8bade0 Mon Sep 17 00:00:00 2001 From: Anatoly Stolbov Date: Wed, 27 Jul 2016 11:01:51 +0300 Subject: Android camera: use closest viewfinder resolution For some cameras difference between preview aspect rate and capture aspect rate is more than 0.01. Therefore it is better to use preview size with closest aspect rate. Task-number: QTBUG-50813 Change-Id: I1284c8ec2be1aa160a656e396a52960fa06aaa56 Reviewed-by: Yoann Lopes --- .../android/src/mediacapture/qandroidcamerasession.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'src/plugins/android/src') diff --git a/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp b/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp index 7b065c8c4..df9f0367b 100644 --- a/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp +++ b/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp @@ -261,17 +261,28 @@ void QAndroidCameraSession::adjustViewfinderSize(const QSize &captureSize, bool // search for viewfinder resolution with the same aspect ratio const qreal aspectRatio = qreal(captureSize.width()) / qreal(captureSize.height()); QList previewSizes = m_camera->getSupportedPreviewSizes(); + qreal minAspectDiff = 1; + QSize closestResolution; for (int i = previewSizes.count() - 1; i >= 0; --i) { const QSize &size = previewSizes.at(i); - if (qAbs(aspectRatio - (qreal(size.width()) / size.height())) < 0.01) { + const qreal sizeAspect = qreal(size.width()) / size.height(); + if (qFuzzyCompare(aspectRatio, sizeAspect)) { adjustedViewfinderResolution = size; break; + } else if (minAspectDiff > qAbs(sizeAspect - aspectRatio)) { + closestResolution = size; + minAspectDiff = qAbs(sizeAspect - aspectRatio); } } if (!adjustedViewfinderResolution.isValid()) { qWarning("Cannot find a viewfinder resolution matching the capture aspect ratio."); - return; + if (closestResolution.isValid()) { + adjustedViewfinderResolution = closestResolution; + qWarning("Using closest viewfinder resolution."); + } else { + return; + } } } -- cgit v1.2.3