Android: Fix attach- and detachFromGLContext()
This fixes a regression caused by ba81276398. 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 <yoann.lopes@qt.io>
This commit is contained in:
committed by
Christian Stromme
parent
7fb7f278ff
commit
443ed0be09
@@ -37,18 +37,18 @@ import android.graphics.SurfaceTexture;
|
||||
|
||||
public class QtSurfaceTextureListener implements SurfaceTexture.OnFrameAvailableListener
|
||||
{
|
||||
private final int texID;
|
||||
private final long m_id;
|
||||
|
||||
public QtSurfaceTextureListener(int texName)
|
||||
public QtSurfaceTextureListener(long id)
|
||||
{
|
||||
texID = texName;
|
||||
m_id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFrameAvailable(SurfaceTexture surfaceTexture)
|
||||
{
|
||||
notifyFrameAvailable(texID);
|
||||
notifyFrameAvailable(m_id);
|
||||
}
|
||||
|
||||
private static native void notifyFrameAvailable(int id);
|
||||
private static native void notifyFrameAvailable(long id);
|
||||
}
|
||||
|
||||
@@ -34,24 +34,32 @@
|
||||
#include "androidsurfacetexture.h"
|
||||
#include <QtCore/private/qjni_p.h>
|
||||
#include <QtCore/private/qjnihelpers_p.h>
|
||||
#include <QtCore/qmutex.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
static const char QtSurfaceTextureListenerClassName[] = "org/qtproject/qt5/android/multimedia/QtSurfaceTextureListener";
|
||||
static QMap<int, AndroidSurfaceTexture*> g_objectMap;
|
||||
typedef QVector<jlong> 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<AndroidSurfaceTexture *>(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<void>("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<void>("setOnFrameAvailableListener",
|
||||
"(Landroid/graphics/SurfaceTexture$OnFrameAvailableListener;)V",
|
||||
listener.object());
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user