Android: Media player improvments.
Add locks around the global media player pool to avoid races. And since we don't need any of the features a map provides us, there's no reason to use one. In the most extreme case it's unlikely that there will be more then a couple media players active at one time, so iterating over continuously storage containing only pointers should be at least as fast, if not faster, then a map or a hash (and use less space). Change-Id: Id8d7810b43a9217da402a4b825d7beec891cdf74 Reviewed-by: Yoann Lopes <yoann.lopes@theqtcompany.com>
This commit is contained in:
committed by
Christian Stromme
parent
3bd9da9aba
commit
62268c2d4b
@@ -37,29 +37,34 @@
|
|||||||
#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 "androidsurfacetexture.h"
|
||||||
#include <QMap>
|
#include <QVector>
|
||||||
|
#include <QReadWriteLock>
|
||||||
|
|
||||||
static const char QtAndroidMediaPlayerClassName[] = "org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer";
|
static const char QtAndroidMediaPlayerClassName[] = "org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer";
|
||||||
typedef QMap<jlong, AndroidMediaPlayer *> MediaPlayerMap;
|
typedef QVector<AndroidMediaPlayer *> MediaPlayerList;
|
||||||
Q_GLOBAL_STATIC(MediaPlayerMap, mediaPlayers)
|
Q_GLOBAL_STATIC(MediaPlayerList, mediaPlayers)
|
||||||
|
Q_GLOBAL_STATIC(QReadWriteLock, rwLock)
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
AndroidMediaPlayer::AndroidMediaPlayer()
|
AndroidMediaPlayer::AndroidMediaPlayer()
|
||||||
: QObject()
|
: QObject()
|
||||||
{
|
{
|
||||||
|
QWriteLocker locker(rwLock);
|
||||||
const jlong id = reinterpret_cast<jlong>(this);
|
const jlong id = reinterpret_cast<jlong>(this);
|
||||||
mMediaPlayer = QJNIObjectPrivate(QtAndroidMediaPlayerClassName,
|
mMediaPlayer = QJNIObjectPrivate(QtAndroidMediaPlayerClassName,
|
||||||
"(Landroid/app/Activity;J)V",
|
"(Landroid/app/Activity;J)V",
|
||||||
QtAndroidPrivate::activity(),
|
QtAndroidPrivate::activity(),
|
||||||
id);
|
id);
|
||||||
(*mediaPlayers)[id] = this;
|
mediaPlayers->append(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
AndroidMediaPlayer::~AndroidMediaPlayer()
|
AndroidMediaPlayer::~AndroidMediaPlayer()
|
||||||
{
|
{
|
||||||
mediaPlayers->remove(reinterpret_cast<jlong>(this));
|
QWriteLocker locker(rwLock);
|
||||||
|
const int i = mediaPlayers->indexOf(this);
|
||||||
|
Q_ASSERT(i != -1);
|
||||||
|
mediaPlayers->remove(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidMediaPlayer::release()
|
void AndroidMediaPlayer::release()
|
||||||
@@ -154,66 +159,72 @@ static void onErrorNative(JNIEnv *env, jobject thiz, jint what, jint extra, jlon
|
|||||||
{
|
{
|
||||||
Q_UNUSED(env);
|
Q_UNUSED(env);
|
||||||
Q_UNUSED(thiz);
|
Q_UNUSED(thiz);
|
||||||
AndroidMediaPlayer *const mp = (*mediaPlayers)[id];
|
QReadLocker locker(rwLock);
|
||||||
if (!mp)
|
const int i = mediaPlayers->indexOf(reinterpret_cast<AndroidMediaPlayer *>(id));
|
||||||
|
if (Q_UNLIKELY(i == -1))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Q_EMIT mp->error(what, extra);
|
Q_EMIT (*mediaPlayers)[i]->error(what, extra);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void onBufferingUpdateNative(JNIEnv *env, jobject thiz, jint percent, jlong id)
|
static void onBufferingUpdateNative(JNIEnv *env, jobject thiz, jint percent, jlong id)
|
||||||
{
|
{
|
||||||
Q_UNUSED(env);
|
Q_UNUSED(env);
|
||||||
Q_UNUSED(thiz);
|
Q_UNUSED(thiz);
|
||||||
AndroidMediaPlayer *const mp = (*mediaPlayers)[id];
|
QReadLocker locker(rwLock);
|
||||||
if (!mp)
|
const int i = mediaPlayers->indexOf(reinterpret_cast<AndroidMediaPlayer *>(id));
|
||||||
|
if (Q_UNLIKELY(i == -1))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Q_EMIT mp->bufferingChanged(percent);
|
Q_EMIT (*mediaPlayers)[i]->bufferingChanged(percent);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void onProgressUpdateNative(JNIEnv *env, jobject thiz, jint progress, jlong id)
|
static void onProgressUpdateNative(JNIEnv *env, jobject thiz, jint progress, jlong id)
|
||||||
{
|
{
|
||||||
Q_UNUSED(env);
|
Q_UNUSED(env);
|
||||||
Q_UNUSED(thiz);
|
Q_UNUSED(thiz);
|
||||||
AndroidMediaPlayer *const mp = (*mediaPlayers)[id];
|
QReadLocker locker(rwLock);
|
||||||
if (!mp)
|
const int i = mediaPlayers->indexOf(reinterpret_cast<AndroidMediaPlayer *>(id));
|
||||||
|
if (Q_UNLIKELY(i == -1))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Q_EMIT mp->progressChanged(progress);
|
Q_EMIT (*mediaPlayers)[i]->progressChanged(progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void onDurationChangedNative(JNIEnv *env, jobject thiz, jint duration, jlong id)
|
static void onDurationChangedNative(JNIEnv *env, jobject thiz, jint duration, jlong id)
|
||||||
{
|
{
|
||||||
Q_UNUSED(env);
|
Q_UNUSED(env);
|
||||||
Q_UNUSED(thiz);
|
Q_UNUSED(thiz);
|
||||||
AndroidMediaPlayer *const mp = (*mediaPlayers)[id];
|
QReadLocker locker(rwLock);
|
||||||
if (!mp)
|
const int i = mediaPlayers->indexOf(reinterpret_cast<AndroidMediaPlayer *>(id));
|
||||||
|
if (Q_UNLIKELY(i == -1))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Q_EMIT mp->durationChanged(duration);
|
Q_EMIT (*mediaPlayers)[i]->durationChanged(duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void onInfoNative(JNIEnv *env, jobject thiz, jint what, jint extra, jlong id)
|
static void onInfoNative(JNIEnv *env, jobject thiz, jint what, jint extra, jlong id)
|
||||||
{
|
{
|
||||||
Q_UNUSED(env);
|
Q_UNUSED(env);
|
||||||
Q_UNUSED(thiz);
|
Q_UNUSED(thiz);
|
||||||
AndroidMediaPlayer *const mp = (*mediaPlayers)[id];
|
QReadLocker locker(rwLock);
|
||||||
if (!mp)
|
const int i = mediaPlayers->indexOf(reinterpret_cast<AndroidMediaPlayer *>(id));
|
||||||
|
if (Q_UNLIKELY(i == -1))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Q_EMIT mp->info(what, extra);
|
Q_EMIT (*mediaPlayers)[i]->info(what, extra);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void onStateChangedNative(JNIEnv *env, jobject thiz, jint state, jlong id)
|
static void onStateChangedNative(JNIEnv *env, jobject thiz, jint state, jlong id)
|
||||||
{
|
{
|
||||||
Q_UNUSED(env);
|
Q_UNUSED(env);
|
||||||
Q_UNUSED(thiz);
|
Q_UNUSED(thiz);
|
||||||
AndroidMediaPlayer *const mp = (*mediaPlayers)[id];
|
QReadLocker locker(rwLock);
|
||||||
if (!mp)
|
const int i = mediaPlayers->indexOf(reinterpret_cast<AndroidMediaPlayer *>(id));
|
||||||
|
if (Q_UNLIKELY(i == -1))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Q_EMIT mp->stateChanged(state);
|
Q_EMIT (*mediaPlayers)[i]->stateChanged(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void onVideoSizeChangedNative(JNIEnv *env,
|
static void onVideoSizeChangedNative(JNIEnv *env,
|
||||||
@@ -224,11 +235,12 @@ static void onVideoSizeChangedNative(JNIEnv *env,
|
|||||||
{
|
{
|
||||||
Q_UNUSED(env);
|
Q_UNUSED(env);
|
||||||
Q_UNUSED(thiz);
|
Q_UNUSED(thiz);
|
||||||
AndroidMediaPlayer *const mp = (*mediaPlayers)[id];
|
QReadLocker locker(rwLock);
|
||||||
if (!mp)
|
const int i = mediaPlayers->indexOf(reinterpret_cast<AndroidMediaPlayer *>(id));
|
||||||
|
if (Q_UNLIKELY(i == -1))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Q_EMIT mp->videoSizeChanged(width, height);
|
Q_EMIT (*mediaPlayers)[i]->videoSizeChanged(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AndroidMediaPlayer::initJNI(JNIEnv *env)
|
bool AndroidMediaPlayer::initJNI(JNIEnv *env)
|
||||||
|
|||||||
Reference in New Issue
Block a user