Android: Don't expose java calls in the control classes.

Makes the abstraction more clear.

Change-Id: Ia9a7b0b157e1182158cd26b62775d13f6c5e1727
Reviewed-by: Yoann Lopes <yoann.lopes@digia.com>
This commit is contained in:
Christian Strømme
2014-05-12 14:38:09 +02:00
committed by The Qt Project
parent 1ef3ef6a30
commit b9b06defc7
15 changed files with 237 additions and 113 deletions

View File

@@ -44,17 +44,17 @@
#include <qglobal.h> #include <qglobal.h>
#include <qsize.h> #include <qsize.h>
#include <jni.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class AndroidSurfaceTexture;
class QAndroidVideoOutput class QAndroidVideoOutput
{ {
public: public:
virtual ~QAndroidVideoOutput() { } virtual ~QAndroidVideoOutput() { }
virtual jobject surfaceHolder() = 0; virtual AndroidSurfaceTexture *surfaceTexture() { return 0; }
virtual jobject surfaceTexture() { return 0; }
virtual bool isReady() { return true; } virtual bool isReady() { return true; }

View File

@@ -109,9 +109,7 @@ private:
QAndroidVideoRendererControl::QAndroidVideoRendererControl(QObject *parent) QAndroidVideoRendererControl::QAndroidVideoRendererControl(QObject *parent)
: QVideoRendererControl(parent) : QVideoRendererControl(parent)
, m_surface(0) , m_surface(0)
, m_androidSurface(0)
, m_surfaceTexture(0) , m_surfaceTexture(0)
, m_surfaceHolder(0)
, m_externalTex(0) , m_externalTex(0)
, m_fbo(0) , m_fbo(0)
, m_program(0) , m_program(0)
@@ -176,7 +174,7 @@ bool QAndroidVideoRendererControl::initSurfaceTexture()
m_surfaceTexture = new AndroidSurfaceTexture(m_externalTex); m_surfaceTexture = new AndroidSurfaceTexture(m_externalTex);
if (m_surfaceTexture->object()) { if (m_surfaceTexture->surfaceTexture() != 0) {
connect(m_surfaceTexture, SIGNAL(frameAvailable()), this, SLOT(onFrameAvailable())); connect(m_surfaceTexture, SIGNAL(frameAvailable()), this, SLOT(onFrameAvailable()));
} else { } else {
delete m_surfaceTexture; delete m_surfaceTexture;
@@ -195,42 +193,14 @@ void QAndroidVideoRendererControl::clearSurfaceTexture()
delete m_surfaceTexture; delete m_surfaceTexture;
m_surfaceTexture = 0; m_surfaceTexture = 0;
} }
if (m_androidSurface) {
if (QtAndroidPrivate::androidSdkVersion() > 13)
m_androidSurface->callMethod<void>("release");
delete m_androidSurface;
m_androidSurface = 0;
}
if (m_surfaceHolder) {
delete m_surfaceHolder;
m_surfaceHolder = 0;
}
} }
jobject QAndroidVideoRendererControl::surfaceHolder() AndroidSurfaceTexture *QAndroidVideoRendererControl::surfaceTexture()
{ {
if (!initSurfaceTexture()) if (!initSurfaceTexture())
return 0; return 0;
if (!m_surfaceHolder) { return m_surfaceTexture;
m_androidSurface = new QJNIObjectPrivate("android/view/Surface",
"(Landroid/graphics/SurfaceTexture;)V",
m_surfaceTexture->object());
m_surfaceHolder = new QJNIObjectPrivate("org/qtproject/qt5/android/multimedia/QtSurfaceTextureHolder",
"(Landroid/view/Surface;)V",
m_androidSurface->object());
}
return m_surfaceHolder->object();
}
jobject QAndroidVideoRendererControl::surfaceTexture()
{
if (!initSurfaceTexture())
return 0;
return m_surfaceTexture->object();
} }
void QAndroidVideoRendererControl::setVideoSize(const QSize &size) void QAndroidVideoRendererControl::setVideoSize(const QSize &size)

View File

@@ -86,8 +86,7 @@ public:
QAbstractVideoSurface *surface() const Q_DECL_OVERRIDE; QAbstractVideoSurface *surface() const Q_DECL_OVERRIDE;
void setSurface(QAbstractVideoSurface *surface) Q_DECL_OVERRIDE; void setSurface(QAbstractVideoSurface *surface) Q_DECL_OVERRIDE;
jobject surfaceHolder() Q_DECL_OVERRIDE; AndroidSurfaceTexture *surfaceTexture() Q_DECL_OVERRIDE;
jobject surfaceTexture() Q_DECL_OVERRIDE;
bool isReady() Q_DECL_OVERRIDE; bool isReady() Q_DECL_OVERRIDE;
void setVideoSize(const QSize &size) Q_DECL_OVERRIDE; void setVideoSize(const QSize &size) Q_DECL_OVERRIDE;
void stop() Q_DECL_OVERRIDE; void stop() Q_DECL_OVERRIDE;
@@ -112,9 +111,7 @@ private:
QAbstractVideoSurface *m_surface; QAbstractVideoSurface *m_surface;
QSize m_nativeSize; QSize m_nativeSize;
QJNIObjectPrivate *m_androidSurface;
AndroidSurfaceTexture *m_surfaceTexture; AndroidSurfaceTexture *m_surfaceTexture;
QJNIObjectPrivate *m_surfaceHolder;
quint32 m_externalTex; quint32 m_externalTex;
QOpenGLFramebufferObject *m_fbo; QOpenGLFramebufferObject *m_fbo;

View File

@@ -183,36 +183,10 @@ void QAndroidCameraSession::updateAvailableCameras()
{ {
g_availableCameras->clear(); g_availableCameras->clear();
const QJNIObjectPrivate cameraInfo("android/hardware/Camera$CameraInfo"); const int numCameras = AndroidCamera::getNumberOfCameras();
const int numCameras = QJNIObjectPrivate::callStaticMethod<jint>("android/hardware/Camera",
"getNumberOfCameras");
for (int i = 0; i < numCameras; ++i) { for (int i = 0; i < numCameras; ++i) {
AndroidCameraInfo info; AndroidCameraInfo info;
AndroidCamera::getCameraInfo(i, &info);
QJNIObjectPrivate::callStaticMethod<void>("android/hardware/Camera",
"getCameraInfo",
"(ILandroid/hardware/Camera$CameraInfo;)V",
i, cameraInfo.object());
AndroidCamera::CameraFacing facing = AndroidCamera::CameraFacing(cameraInfo.getField<jint>("facing"));
// The orientation provided by Android is counter-clockwise, we need it clockwise
info.orientation = (360 - cameraInfo.getField<jint>("orientation")) % 360;
switch (facing) {
case AndroidCamera::CameraFacingBack:
info.name = QByteArray("back");
info.description = QStringLiteral("Rear-facing camera");
info.position = QCamera::BackFace;
break;
case AndroidCamera::CameraFacingFront:
info.name = QByteArray("front");
info.description = QStringLiteral("Front-facing camera");
info.position = QCamera::FrontFace;
break;
default:
break;
}
if (!info.name.isNull()) if (!info.name.isNull())
g_availableCameras->append(info); g_availableCameras->append(info);

View File

@@ -48,21 +48,13 @@
#include <QSet> #include <QSet>
#include <QMutex> #include <QMutex>
#include <private/qmediastoragelocation_p.h> #include <private/qmediastoragelocation_p.h>
#include "androidcamera.h"
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class AndroidCamera;
class QAndroidVideoOutput; class QAndroidVideoOutput;
class QAndroidMediaVideoProbeControl; class QAndroidMediaVideoProbeControl;
struct AndroidCameraInfo
{
QByteArray name;
QString description;
QCamera::Position position;
int orientation;
};
class QAndroidCameraSession : public QObject class QAndroidCameraSession : public QObject
{ {
Q_OBJECT Q_OBJECT

View File

@@ -455,7 +455,7 @@ void QAndroidCaptureSession::onCameraOpened()
for (int i = 0; i < 8; ++i) { for (int i = 0; i < 8; ++i) {
CaptureProfile profile = getProfile(i); CaptureProfile profile = getProfile(i);
if (!profile.isNull) { if (!profile.isNull) {
if (i == 1) // QUALITY_HIGH if (i == AndroidCamcorderProfile::QUALITY_HIGH)
m_defaultSettings = profile; m_defaultSettings = profile;
if (!m_supportedResolutions.contains(profile.videoResolution)) if (!m_supportedResolutions.contains(profile.videoResolution))
@@ -474,30 +474,23 @@ void QAndroidCaptureSession::onCameraOpened()
QAndroidCaptureSession::CaptureProfile QAndroidCaptureSession::getProfile(int id) QAndroidCaptureSession::CaptureProfile QAndroidCaptureSession::getProfile(int id)
{ {
CaptureProfile profile; CaptureProfile profile;
bool hasProfile = QJNIObjectPrivate::callStaticMethod<jboolean>("android/media/CamcorderProfile", const bool hasProfile = AndroidCamcorderProfile::hasProfile(m_cameraSession->camera()->cameraId(),
"hasProfile", AndroidCamcorderProfile::Quality(id));
"(II)Z",
m_cameraSession->camera()->cameraId(),
id);
if (hasProfile) { if (hasProfile) {
QJNIObjectPrivate obj = QJNIObjectPrivate::callStaticObjectMethod("android/media/CamcorderProfile", AndroidCamcorderProfile camProfile = AndroidCamcorderProfile::get(m_cameraSession->camera()->cameraId(),
"get", AndroidCamcorderProfile::Quality(id));
"(II)Landroid/media/CamcorderProfile;",
m_cameraSession->camera()->cameraId(),
id);
profile.outputFormat = AndroidMediaRecorder::OutputFormat(camProfile.getValue(AndroidCamcorderProfile::fileFormat));
profile.outputFormat = AndroidMediaRecorder::OutputFormat(obj.getField<jint>("fileFormat")); profile.audioEncoder = AndroidMediaRecorder::AudioEncoder(camProfile.getValue(AndroidCamcorderProfile::audioCodec));
profile.audioEncoder = AndroidMediaRecorder::AudioEncoder(obj.getField<jint>("audioCodec")); profile.audioBitRate = camProfile.getValue(AndroidCamcorderProfile::audioBitRate);
profile.audioBitRate = obj.getField<jint>("audioBitRate"); profile.audioChannels = camProfile.getValue(AndroidCamcorderProfile::audioChannels);
profile.audioChannels = obj.getField<jint>("audioChannels"); profile.audioSampleRate = camProfile.getValue(AndroidCamcorderProfile::audioSampleRate);
profile.audioSampleRate = obj.getField<jint>("audioSampleRate"); profile.videoEncoder = AndroidMediaRecorder::VideoEncoder(camProfile.getValue(AndroidCamcorderProfile::videoCodec));
profile.videoEncoder = AndroidMediaRecorder::VideoEncoder(obj.getField<jint>("videoCodec")); profile.videoBitRate = camProfile.getValue(AndroidCamcorderProfile::videoBitRate);
profile.videoBitRate = obj.getField<jint>("videoBitRate"); profile.videoFrameRate = camProfile.getValue(AndroidCamcorderProfile::videoFrameRate);
profile.videoFrameRate = obj.getField<jint>("videoFrameRate"); profile.videoResolution = QSize(camProfile.getValue(AndroidCamcorderProfile::videoFrameWidth),
profile.videoResolution = QSize(obj.getField<jint>("videoFrameWidth"), camProfile.getValue(AndroidCamcorderProfile::videoFrameHeight));
obj.getField<jint>("videoFrameHeight"));
if (profile.outputFormat == AndroidMediaRecorder::MPEG_4) if (profile.outputFormat == AndroidMediaRecorder::MPEG_4)
profile.outputFileExtension = QStringLiteral("mp4"); profile.outputFileExtension = QStringLiteral("mp4");

View File

@@ -320,8 +320,8 @@ void QAndroidMediaPlayerControl::setMedia(const QMediaContent &mediaContent,
if (mVideoSize.isValid() && mVideoOutput) if (mVideoSize.isValid() && mVideoOutput)
mVideoOutput->setVideoSize(mVideoSize); mVideoOutput->setVideoSize(mVideoSize);
if (!mMediaPlayer->display() && mVideoOutput) if ((mMediaPlayer->display() == 0) && mVideoOutput)
mMediaPlayer->setDisplay(mVideoOutput->surfaceHolder()); mMediaPlayer->setDisplay(mVideoOutput->surfaceTexture());
mMediaPlayer->setDataSource(mediaPath); mMediaPlayer->setDataSource(mediaPath);
mMediaPlayer->prepareAsync(); mMediaPlayer->prepareAsync();
@@ -345,7 +345,7 @@ void QAndroidMediaPlayerControl::setVideoOutput(QObject *videoOutput)
return; return;
if (mVideoOutput->isReady()) if (mVideoOutput->isReady())
mMediaPlayer->setDisplay(mVideoOutput->surfaceHolder()); mMediaPlayer->setDisplay(mVideoOutput->surfaceTexture());
connect(videoOutput, SIGNAL(readyChanged(bool)), this, SLOT(onVideoOutputReady(bool))); connect(videoOutput, SIGNAL(readyChanged(bool)), this, SLOT(onVideoOutputReady(bool)));
} }
@@ -590,8 +590,8 @@ void QAndroidMediaPlayerControl::onStateChanged(qint32 state)
void QAndroidMediaPlayerControl::onVideoOutputReady(bool ready) void QAndroidMediaPlayerControl::onVideoOutputReady(bool ready)
{ {
if (!mMediaPlayer->display() && mVideoOutput && ready) if ((mMediaPlayer->display() == 0) && mVideoOutput && ready)
mMediaPlayer->setDisplay(mVideoOutput->surfaceHolder()); mMediaPlayer->setDisplay(mVideoOutput->surfaceTexture());
flushPendingStates(); flushPendingStates();
} }

View File

@@ -40,10 +40,11 @@
****************************************************************************/ ****************************************************************************/
#include "androidcamera.h" #include "androidcamera.h"
#include "androidsurfacetexture.h"
#include "qandroidmultimediautils.h"
#include <qstringlist.h> #include <qstringlist.h>
#include <qdebug.h> #include <qdebug.h>
#include "qandroidmultimediautils.h"
#include <qmutex.h> #include <qmutex.h>
#include <QtCore/private/qjnihelpers_p.h> #include <QtCore/private/qjnihelpers_p.h>
#include <QtCore/qthread.h> #include <QtCore/qthread.h>
@@ -367,10 +368,13 @@ void AndroidCamera::setPreviewSize(const QSize &size)
QMetaObject::invokeMethod(d, "updatePreviewSize"); QMetaObject::invokeMethod(d, "updatePreviewSize");
} }
void AndroidCamera::setPreviewTexture(jobject surfaceTexture) void AndroidCamera::setPreviewTexture(AndroidSurfaceTexture *surfaceTexture)
{ {
Q_D(AndroidCamera); Q_D(AndroidCamera);
QMetaObject::invokeMethod(d, "setPreviewTexture", Qt::BlockingQueuedConnection, Q_ARG(void *, surfaceTexture)); QMetaObject::invokeMethod(d,
"setPreviewTexture",
Qt::BlockingQueuedConnection,
Q_ARG(void *, surfaceTexture ? surfaceTexture->surfaceTexture() : 0));
} }
bool AndroidCamera::isZoomSupported() bool AndroidCamera::isZoomSupported()
@@ -633,6 +637,42 @@ QJNIObjectPrivate AndroidCamera::getCameraObject()
return d->m_camera; return d->m_camera;
} }
int AndroidCamera::getNumberOfCameras()
{
return QJNIObjectPrivate::callStaticMethod<jint>("android/hardware/Camera",
"getNumberOfCameras");
}
void AndroidCamera::getCameraInfo(int id, AndroidCameraInfo *info)
{
Q_ASSERT(info);
QJNIObjectPrivate cameraInfo("android/hardware/Camera$CameraInfo");
QJNIObjectPrivate::callStaticMethod<void>("android/hardware/Camera",
"getCameraInfo",
"(ILandroid/hardware/Camera$CameraInfo;)V",
id, cameraInfo.object());
AndroidCamera::CameraFacing facing = AndroidCamera::CameraFacing(cameraInfo.getField<jint>("facing"));
// The orientation provided by Android is counter-clockwise, we need it clockwise
info->orientation = (360 - cameraInfo.getField<jint>("orientation")) % 360;
switch (facing) {
case AndroidCamera::CameraFacingBack:
info->name = QByteArray("back");
info->description = QStringLiteral("Rear-facing camera");
info->position = QCamera::BackFace;
break;
case AndroidCamera::CameraFacingFront:
info->name = QByteArray("front");
info->description = QStringLiteral("Front-facing camera");
info->position = QCamera::FrontFace;
break;
default:
break;
}
}
void AndroidCamera::startPreview() void AndroidCamera::startPreview()
{ {
Q_D(AndroidCamera); Q_D(AndroidCamera);

View File

@@ -46,12 +46,22 @@
#include <QtCore/private/qjni_p.h> #include <QtCore/private/qjni_p.h>
#include <qsize.h> #include <qsize.h>
#include <qrect.h> #include <qrect.h>
#include <QtMultimedia/qcamera.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QThread; class QThread;
class AndroidCameraPrivate; class AndroidCameraPrivate;
class AndroidSurfaceTexture;
struct AndroidCameraInfo
{
QByteArray name;
QString description;
QCamera::Position position;
int orientation;
};
class AndroidCamera : public QObject class AndroidCamera : public QObject
{ {
@@ -96,7 +106,7 @@ public:
QSize previewSize() const; QSize previewSize() const;
void setPreviewSize(const QSize &size); void setPreviewSize(const QSize &size);
void setPreviewTexture(jobject surfaceTexture); void setPreviewTexture(AndroidSurfaceTexture *surfaceTexture);
bool isZoomSupported(); bool isZoomSupported();
int getMaxZoom(); int getMaxZoom();
@@ -157,6 +167,9 @@ public:
void fetchLastPreviewFrame(); void fetchLastPreviewFrame();
QJNIObjectPrivate getCameraObject(); QJNIObjectPrivate getCameraObject();
static int getNumberOfCameras();
static void getCameraInfo(int id, AndroidCameraInfo *info);
static bool initJNI(JNIEnv *env); static bool initJNI(JNIEnv *env);
Q_SIGNALS: Q_SIGNALS:

View File

@@ -44,6 +44,7 @@
#include <QString> #include <QString>
#include <QtCore/private/qjni_p.h> #include <QtCore/private/qjni_p.h>
#include <QtCore/private/qjnihelpers_p.h> #include <QtCore/private/qjnihelpers_p.h>
#include "androidsurfacetexture.h"
#include <QMap> #include <QMap>
static jclass mediaPlayerClass = Q_NULLPTR; static jclass mediaPlayerClass = Q_NULLPTR;
@@ -150,9 +151,11 @@ void AndroidMediaPlayer::setVolume(int volume)
mMediaPlayer.callMethod<void>("setVolume", "(I)V", jint(volume)); mMediaPlayer.callMethod<void>("setVolume", "(I)V", jint(volume));
} }
void AndroidMediaPlayer::setDisplay(jobject surfaceHolder) void AndroidMediaPlayer::setDisplay(AndroidSurfaceTexture *surfaceTexture)
{ {
mMediaPlayer.callMethod<void>("setDisplay", "(Landroid/view/SurfaceHolder;)V", surfaceHolder); mMediaPlayer.callMethod<void>("setDisplay",
"(Landroid/view/SurfaceHolder;)V",
surfaceTexture ? surfaceTexture->surfaceHolder() : 0);
} }
static void onErrorNative(JNIEnv *env, jobject thiz, jint what, jint extra, jlong id) static void onErrorNative(JNIEnv *env, jobject thiz, jint what, jint extra, jlong id)

View File

@@ -47,6 +47,8 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class AndroidSurfaceTexture;
class AndroidMediaPlayer : public QObject class AndroidMediaPlayer : public QObject
{ {
Q_OBJECT Q_OBJECT
@@ -113,7 +115,7 @@ public:
void setDataSource(const QString &path); void setDataSource(const QString &path);
void prepareAsync(); void prepareAsync();
void setVolume(int volume); void setVolume(int volume);
void setDisplay(jobject surfaceHolder); void setDisplay(AndroidSurfaceTexture *surfaceTexture);
static bool initJNI(JNIEnv *env); static bool initJNI(JNIEnv *env);

View File

@@ -47,6 +47,80 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
typedef QMap<QString, QJNIObjectPrivate> CamcorderProfiles;
Q_GLOBAL_STATIC(CamcorderProfiles, g_camcorderProfiles)
static QString profileKey()
{
return QStringLiteral("%1-%2");
}
bool AndroidCamcorderProfile::hasProfile(jint cameraId, Quality quality)
{
if (g_camcorderProfiles->contains(profileKey().arg(cameraId).arg(quality)))
return true;
return QJNIObjectPrivate::callStaticMethod<jboolean>("android/media/CamcorderProfile",
"hasProfile",
"(II)Z",
cameraId,
quality);
}
AndroidCamcorderProfile AndroidCamcorderProfile::get(jint cameraId, Quality quality)
{
const QString key = profileKey().arg(cameraId).arg(quality);
QMap<QString, QJNIObjectPrivate>::const_iterator it = g_camcorderProfiles->constFind(key);
if (it != g_camcorderProfiles->constEnd())
return AndroidCamcorderProfile(*it);
QJNIObjectPrivate camProfile = QJNIObjectPrivate::callStaticObjectMethod("android/media/CamcorderProfile",
"get",
"(II)Landroid/media/CamcorderProfile;",
cameraId,
quality);
return AndroidCamcorderProfile((*g_camcorderProfiles)[key] = camProfile);
}
int AndroidCamcorderProfile::getValue(AndroidCamcorderProfile::Field field) const
{
switch (field) {
case audioBitRate:
return m_camcorderProfile.getField<jint>("audioBitRate");
case audioChannels:
return m_camcorderProfile.getField<jint>("audioChannels");
case audioCodec:
return m_camcorderProfile.getField<jint>("audioCodec");
case audioSampleRate:
return m_camcorderProfile.getField<jint>("audioSampleRate");
case duration:
return m_camcorderProfile.getField<jint>("duration");
case fileFormat:
return m_camcorderProfile.getField<jint>("fileFormat");
case quality:
return m_camcorderProfile.getField<jint>("quality");
case videoBitRate:
return m_camcorderProfile.getField<jint>("videoBitRate");
case videoCodec:
return m_camcorderProfile.getField<jint>("videoCodec");
case videoFrameHeight:
return m_camcorderProfile.getField<jint>("videoFrameHeight");
case videoFrameRate:
return m_camcorderProfile.getField<jint>("videoFrameRate");
case videoFrameWidth:
return m_camcorderProfile.getField<jint>("videoFrameWidth");
}
return 0;
}
AndroidCamcorderProfile::AndroidCamcorderProfile(const QJNIObjectPrivate &camcorderProfile)
{
m_camcorderProfile = camcorderProfile;
}
static jclass g_qtMediaRecorderListenerClass = 0; static jclass g_qtMediaRecorderListenerClass = 0;
typedef QMap<jlong, AndroidMediaRecorder*> MediaRecorderMap; typedef QMap<jlong, AndroidMediaRecorder*> MediaRecorderMap;
Q_GLOBAL_STATIC(MediaRecorderMap, mediaRecorders) Q_GLOBAL_STATIC(MediaRecorderMap, mediaRecorders)

View File

@@ -50,6 +50,44 @@ QT_BEGIN_NAMESPACE
class AndroidCamera; class AndroidCamera;
class AndroidCamcorderProfile
{
public:
enum Quality { // Needs to match CamcorderProfile
QUALITY_LOW,
QUALITY_HIGH,
QUALITY_QCIF,
QUALITY_CIF,
QUALITY_480P,
QUALITY_720P,
QUALITY_1080P,
QUALITY_QVGA
};
enum Field {
audioBitRate,
audioChannels,
audioCodec,
audioSampleRate,
duration,
fileFormat,
quality,
videoBitRate,
videoCodec,
videoFrameHeight,
videoFrameRate,
videoFrameWidth
};
static bool hasProfile(jint cameraId, Quality quality);
static AndroidCamcorderProfile get(jint cameraId, Quality quality);
int getValue(Field field) const;
private:
AndroidCamcorderProfile(const QJNIObjectPrivate &camcorderProfile);
QJNIObjectPrivate m_camcorderProfile;
};
class AndroidMediaRecorder : public QObject class AndroidMediaRecorder : public QObject
{ {
Q_OBJECT Q_OBJECT

View File

@@ -86,6 +86,9 @@ AndroidSurfaceTexture::AndroidSurfaceTexture(unsigned int texName)
AndroidSurfaceTexture::~AndroidSurfaceTexture() AndroidSurfaceTexture::~AndroidSurfaceTexture()
{ {
if (QtAndroidPrivate::androidSdkVersion() > 13 && m_surfaceView.isValid())
m_surfaceView.callMethod<void>("release");
if (m_surfaceTexture.isValid()) { if (m_surfaceTexture.isValid()) {
release(); release();
g_objectMap.remove(m_texID); g_objectMap.remove(m_texID);
@@ -124,11 +127,31 @@ void AndroidSurfaceTexture::updateTexImage()
m_surfaceTexture.callMethod<void>("updateTexImage"); m_surfaceTexture.callMethod<void>("updateTexImage");
} }
jobject AndroidSurfaceTexture::object() jobject AndroidSurfaceTexture::surfaceTexture()
{ {
return m_surfaceTexture.object(); return m_surfaceTexture.object();
} }
jobject AndroidSurfaceTexture::surfaceView()
{
return m_surfaceView.object();
}
jobject AndroidSurfaceTexture::surfaceHolder()
{
if (!m_surfaceHolder.isValid()) {
m_surfaceView = QJNIObjectPrivate("android/view/Surface",
"(Landroid/graphics/SurfaceTexture;)V",
m_surfaceTexture.object());
m_surfaceHolder = QJNIObjectPrivate("org/qtproject/qt5/android/multimedia/QtSurfaceTextureHolder",
"(Landroid/view/Surface;)V",
m_surfaceView.object());
}
return m_surfaceHolder.object();
}
static JNINativeMethod methods[] = { static JNINativeMethod methods[] = {
{"notifyFrameAvailable", "(I)V", (void *)notifyFrameAvailable} {"notifyFrameAvailable", "(I)V", (void *)notifyFrameAvailable}
}; };

View File

@@ -57,7 +57,10 @@ public:
~AndroidSurfaceTexture(); ~AndroidSurfaceTexture();
int textureID() const { return m_texID; } int textureID() const { return m_texID; }
jobject object(); jobject surfaceTexture();
jobject surfaceView();
jobject surfaceHolder();
inline bool isValid() const { return m_surfaceTexture.isValid(); }
QMatrix4x4 getTransformMatrix(); QMatrix4x4 getTransformMatrix();
void release(); // API level 14 void release(); // API level 14
@@ -71,6 +74,8 @@ Q_SIGNALS:
private: private:
int m_texID; int m_texID;
QJNIObjectPrivate m_surfaceTexture; QJNIObjectPrivate m_surfaceTexture;
QJNIObjectPrivate m_surfaceView;
QJNIObjectPrivate m_surfaceHolder;
}; };
QT_END_NAMESPACE QT_END_NAMESPACE