summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorFrederik Gladhorn <frederik.gladhorn@digia.com>2013-07-11 23:26:39 +0200
committerFrederik Gladhorn <frederik.gladhorn@digia.com>2013-07-11 23:26:39 +0200
commit0a05ae544693c10a30e4cfd9c1460f193f252a3f (patch)
tree603ebe744fbb1bfe5e72f06c9aa4d4727b7012b7 /src
parent0a3f1aacd38cc447bc85032a4ae2509ae472af94 (diff)
parente15a2b92b6120a119cf218ab0f0630f23bc45ba5 (diff)
Merge remote-tracking branch 'origin/stable' into dev
Diffstat (limited to 'src')
-rw-r--r--src/multimedia/multimedia.pro4
-rw-r--r--src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java15
-rw-r--r--src/plugins/android/mediaplayer/qandroidmediaplayercontrol.cpp55
-rw-r--r--src/plugins/android/mediaplayer/qandroidmediaplayercontrol.h4
-rw-r--r--src/plugins/android/mediaplayer/qandroidvideooutput.h6
-rw-r--r--src/plugins/android/mediaplayer/qandroidvideorendercontrol.cpp84
-rw-r--r--src/plugins/android/mediaplayer/qandroidvideorendercontrol.h9
-rw-r--r--src/plugins/android/wrappers/jmediaplayer.cpp5
-rw-r--r--src/plugins/android/wrappers/jmediaplayer.h2
-rw-r--r--src/plugins/directshow/player/directshowplayerservice.cpp4
10 files changed, 158 insertions, 30 deletions
diff --git a/src/multimedia/multimedia.pro b/src/multimedia/multimedia.pro
index 726f00ab4..265728552 100644
--- a/src/multimedia/multimedia.pro
+++ b/src/multimedia/multimedia.pro
@@ -52,9 +52,9 @@ include(recording/recording.pri)
include(video/video.pri)
ANDROID_BUNDLED_JAR_DEPENDENCIES = \
- jar/QtMultimedia-bundled.jar:org.qtproject.qt5.android.multimedia.QtAndroidMediaPlayer
+ jar/QtMultimedia-bundled.jar
ANDROID_JAR_DEPENDENCIES = \
- jar/QtMultimedia.jar:org.qtproject.qt5.android.multimedia.QtAndroidMediaPlayer
+ jar/QtMultimedia.jar
ANDROID_LIB_DEPENDENCIES = \
plugins/mediaservice/libandroidmediaplayer.so \
lib/libQt5MultimediaQuick_p.so:Qt5Quick
diff --git a/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java b/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java
index e4dbae632..d1abf658e 100644
--- a/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java
+++ b/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java
@@ -50,6 +50,9 @@ import android.content.Context;
import android.media.MediaPlayer;
import android.net.Uri;
import android.util.Log;
+import java.io.FileDescriptor;
+import android.content.res.AssetFileDescriptor;
+import android.content.res.AssetManager;
public class QtAndroidMediaPlayer extends MediaPlayer
{
@@ -335,7 +338,17 @@ public class QtAndroidMediaPlayer extends MediaPlayer
mPreparing = true;
onMediaPlayerInfoNative(MEDIA_PLAYER_PREPARING, 0, mID);
mUri = Uri.parse(path);
- setDataSource(mApplicationContext, mUri);
+ if (mUri.getScheme().compareTo("assets") == 0) {
+ final String asset = mUri.getPath().substring(1 /* Remove first '/' */);
+ final AssetManager am = mApplicationContext.getAssets();
+ final AssetFileDescriptor afd = am.openFd(asset);
+ final long offset = afd.getStartOffset();
+ final long length = afd.getLength();
+ FileDescriptor fd = afd.getFileDescriptor();
+ setDataSource(fd, offset, length);
+ } else {
+ setDataSource(mApplicationContext, mUri);
+ }
mInitialized = true;
setOnPreparedListener(new MediaPlayerPreparedListener());
prepareAsync();
diff --git a/src/plugins/android/mediaplayer/qandroidmediaplayercontrol.cpp b/src/plugins/android/mediaplayer/qandroidmediaplayercontrol.cpp
index 5a9c8b84f..a70f4e130 100644
--- a/src/plugins/android/mediaplayer/qandroidmediaplayercontrol.cpp
+++ b/src/plugins/android/mediaplayer/qandroidmediaplayercontrol.cpp
@@ -45,6 +45,12 @@
QT_BEGIN_NAMESPACE
+static void textureReadyCallback(void *context)
+{
+ if (context)
+ reinterpret_cast<QAndroidMediaPlayerControl *>(context)->onSurfaceTextureReady();
+}
+
QAndroidMediaPlayerControl::QAndroidMediaPlayerControl(QObject *parent)
: QMediaPlayerControl(parent),
mMediaPlayer(new JMediaPlayer),
@@ -58,7 +64,8 @@ QAndroidMediaPlayerControl::QAndroidMediaPlayerControl(QObject *parent)
mVideoAvailable(false),
mBuffering(false),
mMediaPlayerReady(false),
- mPendingPosition(-1)
+ mPendingPosition(-1),
+ mPendingSetMedia(false)
{
connect(mMediaPlayer, SIGNAL(bufferingUpdate(qint32)),
this, SLOT(onBufferChanged(qint32)));
@@ -74,6 +81,7 @@ QAndroidMediaPlayerControl::QAndroidMediaPlayerControl(QObject *parent)
QAndroidMediaPlayerControl::~QAndroidMediaPlayerControl()
{
+ mMediaPlayer->release();
delete mMediaPlayer;
}
@@ -207,6 +215,13 @@ void QAndroidMediaPlayerControl::setMedia(const QMediaContent &mediaContent,
mMediaContent = mediaContent;
mMediaStream = stream;
+ if (mVideoOutput && !mMediaPlayer->display()) {
+ // if a video output is set but the video texture is not ready, delay loading the media
+ // since it can cause problems on some hardware
+ mPendingSetMedia = true;
+ return;
+ }
+
const QString uri = mediaContent.canonicalUrl().toString();
if (!uri.isEmpty())
@@ -230,6 +245,13 @@ void QAndroidMediaPlayerControl::setVideoOutput(QAndroidVideoOutput *videoOutput
mVideoOutput->stop();
mVideoOutput = videoOutput;
+
+ if (mVideoOutput && !mMediaPlayer->display()) {
+ if (mVideoOutput->isTextureReady())
+ mMediaPlayer->setDisplay(mVideoOutput->surfaceHolder());
+ else
+ mVideoOutput->setTextureReadyCallback(textureReadyCallback, this);
+ }
}
void QAndroidMediaPlayerControl::play()
@@ -238,7 +260,8 @@ void QAndroidMediaPlayerControl::play()
mPendingState = QMediaPlayer::PlayingState;
if (mCurrentState == QMediaPlayer::StoppedState
&& !mMediaContent.isNull()
- && mCurrentMediaStatus != QMediaPlayer::LoadingMedia) {
+ && mCurrentMediaStatus != QMediaPlayer::LoadingMedia
+ && !mPendingSetMedia) {
setMedia(mMediaContent, 0);
}
return;
@@ -391,16 +414,23 @@ void QAndroidMediaPlayerControl::onBufferChanged(qint32 percent)
void QAndroidMediaPlayerControl::onVideoSizeChanged(qint32 width, qint32 height)
{
- if (width == 0 || height == 0)
+ QSize newSize(width, height);
+
+ if (width == 0 || height == 0 || newSize == mVideoSize)
return;
setVideoAvailable(true);
+ mVideoSize = newSize;
- if (mVideoOutput) {
- if (!mMediaPlayer->display())
- mMediaPlayer->setDisplay(mVideoOutput->surfaceHolder());
- if (mMediaPlayer->display())
- mVideoOutput->setVideoSize(QSize(width, height));
+ if (mVideoOutput)
+ mVideoOutput->setVideoSize(mVideoSize);
+}
+
+void QAndroidMediaPlayerControl::onSurfaceTextureReady()
+{
+ if (!mMediaPlayer->display() && mVideoOutput) {
+ mMediaPlayer->setDisplay(mVideoOutput->surfaceHolder());
+ flushPendingStates();
}
}
@@ -464,6 +494,9 @@ void QAndroidMediaPlayerControl::setVideoAvailable(bool available)
if (mVideoAvailable == available)
return;
+ if (!available)
+ mVideoSize = QSize();
+
mVideoAvailable = available;
Q_EMIT videoAvailableChanged(mVideoAvailable);
}
@@ -478,6 +511,12 @@ void QAndroidMediaPlayerControl::resetBufferingProgress()
void QAndroidMediaPlayerControl::flushPendingStates()
{
+ if (mPendingSetMedia) {
+ setMedia(mMediaContent, 0);
+ mPendingSetMedia = false;
+ return;
+ }
+
switch (mPendingState) {
case QMediaPlayer::PlayingState:
if (mPendingPosition > -1)
diff --git a/src/plugins/android/mediaplayer/qandroidmediaplayercontrol.h b/src/plugins/android/mediaplayer/qandroidmediaplayercontrol.h
index 445e8de7a..93eced853 100644
--- a/src/plugins/android/mediaplayer/qandroidmediaplayercontrol.h
+++ b/src/plugins/android/mediaplayer/qandroidmediaplayercontrol.h
@@ -44,6 +44,7 @@
#include <qglobal.h>
#include <QMediaPlayerControl>
+#include <qsize.h>
QT_BEGIN_NAMESPACE
@@ -75,6 +76,7 @@ public:
void setMedia(const QMediaContent &mediaContent, QIODevice *stream) Q_DECL_OVERRIDE;
void setVideoOutput(QAndroidVideoOutput *videoOutput);
+ void onSurfaceTextureReady();
Q_SIGNALS:
void metaDataUpdated();
@@ -105,11 +107,13 @@ private:
int mBufferPercent;
bool mAudioAvailable;
bool mVideoAvailable;
+ QSize mVideoSize;
bool mBuffering;
QMediaTimeRange mAvailablePlaybackRange;
bool mMediaPlayerReady;
QMediaPlayer::State mPendingState;
qint64 mPendingPosition;
+ bool mPendingSetMedia;
void setState(QMediaPlayer::State state);
void setMediaStatus(QMediaPlayer::MediaStatus status);
diff --git a/src/plugins/android/mediaplayer/qandroidvideooutput.h b/src/plugins/android/mediaplayer/qandroidvideooutput.h
index 99db7c3e7..d59971f3b 100644
--- a/src/plugins/android/mediaplayer/qandroidvideooutput.h
+++ b/src/plugins/android/mediaplayer/qandroidvideooutput.h
@@ -48,6 +48,8 @@
QT_BEGIN_NAMESPACE
+typedef void (*TextureReadyCallback)(void*);
+
class QAndroidVideoOutput
{
public:
@@ -55,6 +57,10 @@ public:
virtual ~QAndroidVideoOutput() { }
virtual jobject surfaceHolder() = 0;
+
+ virtual bool isTextureReady() = 0;
+ virtual void setTextureReadyCallback(TextureReadyCallback cb, void *context = 0) = 0;
+
virtual void setVideoSize(const QSize &size) = 0;
virtual void stop() = 0;
};
diff --git a/src/plugins/android/mediaplayer/qandroidvideorendercontrol.cpp b/src/plugins/android/mediaplayer/qandroidvideorendercontrol.cpp
index c63e0e771..fe26b455a 100644
--- a/src/plugins/android/mediaplayer/qandroidvideorendercontrol.cpp
+++ b/src/plugins/android/mediaplayer/qandroidvideorendercontrol.cpp
@@ -50,6 +50,7 @@
#include <QVideoSurfaceFormat>
#include <QOpenGLFunctions>
#include <QOpenGLShaderProgram>
+#include <qevent.h>
QT_BEGIN_NAMESPACE
@@ -134,6 +135,8 @@ QAndroidVideoRendererControl::QAndroidVideoRendererControl(QObject *parent)
, m_surfaceTexture(0)
, m_surfaceHolder(0)
, m_externalTex(0)
+ , m_textureReadyCallback(0)
+ , m_textureReadyContext(0)
{
}
@@ -177,42 +180,66 @@ void QAndroidVideoRendererControl::setSurface(QAbstractVideoSurface *surface)
if (surface == m_surface)
return;
- if (m_surface && m_surface->isActive())
+ if (m_surface && m_surface->isActive()) {
m_surface->stop();
+ m_surface->removeEventFilter(this);
+ }
m_surface = surface;
- if (m_surface)
+ if (m_surface) {
m_useImage = !m_surface->supportedPixelFormats(QAbstractVideoBuffer::GLTextureHandle).contains(QVideoFrame::Format_BGR32);
+ m_surface->installEventFilter(this);
+ }
}
-jobject QAndroidVideoRendererControl::surfaceHolder()
+bool QAndroidVideoRendererControl::isTextureReady()
+{
+ return QOpenGLContext::currentContext() || (m_surface && m_surface->property("GLContext").isValid());
+}
+
+void QAndroidVideoRendererControl::setTextureReadyCallback(TextureReadyCallback cb, void *context)
+{
+ m_textureReadyCallback = cb;
+ m_textureReadyContext = context;
+}
+
+bool QAndroidVideoRendererControl::initSurfaceTexture()
{
- if (m_surfaceHolder)
- return m_surfaceHolder->object();
+ if (m_surfaceTexture)
+ return true;
+
+ if (!m_surface)
+ return false;
QOpenGLContext *currContext = QOpenGLContext::currentContext();
// If we don't have a GL context in the current thread, create one and share it
// with the render thread GL context
if (!currContext && !m_glContext) {
+ QOpenGLContext *shareContext = qobject_cast<QOpenGLContext*>(m_surface->property("GLContext").value<QObject*>());
+ if (!shareContext)
+ return false;
+
m_offscreenSurface = new QOffscreenSurface;
QSurfaceFormat format;
format.setSwapBehavior(QSurfaceFormat::SingleBuffer);
m_offscreenSurface->setFormat(format);
m_offscreenSurface->create();
- QOpenGLContext *shareContext = 0;
- if (m_surface)
- shareContext = qobject_cast<QOpenGLContext*>(m_surface->property("GLContext").value<QObject*>());
m_glContext = new QOpenGLContext;
m_glContext->setFormat(m_offscreenSurface->requestedFormat());
if (shareContext)
m_glContext->setShareContext(shareContext);
- if (!m_glContext->create())
- return 0;
+ if (!m_glContext->create()) {
+ delete m_glContext;
+ m_glContext = 0;
+ delete m_offscreenSurface;
+ m_offscreenSurface = 0;
+ return false;
+ }
// if sharing contexts is not supported, fallback to image rendering and send the bits
// to the video surface
@@ -228,7 +255,21 @@ jobject QAndroidVideoRendererControl::surfaceHolder()
if (m_surfaceTexture->isValid()) {
connect(m_surfaceTexture, SIGNAL(frameAvailable()), this, SLOT(onFrameAvailable()));
+ } else {
+ delete m_surfaceTexture;
+ m_surfaceTexture = 0;
+ glDeleteTextures(1, &m_externalTex);
+ }
+ return m_surfaceTexture != 0;
+}
+
+jobject QAndroidVideoRendererControl::surfaceHolder()
+{
+ if (!initSurfaceTexture())
+ return 0;
+
+ if (!m_surfaceHolder) {
QJNILocalRef<jobject> surfaceTex = m_surfaceTexture->surfaceTexture();
m_androidSurface = new QJNIObject("android/view/Surface",
@@ -236,16 +277,9 @@ jobject QAndroidVideoRendererControl::surfaceHolder()
surfaceTex.object());
m_surfaceHolder = new JSurfaceTextureHolder(m_androidSurface->object());
- } else {
- delete m_surfaceTexture;
- m_surfaceTexture = 0;
- glDeleteTextures(1, &m_externalTex);
}
- if (m_surfaceHolder)
- return m_surfaceHolder->object();
-
- return 0;
+ return m_surfaceHolder->object();
}
void QAndroidVideoRendererControl::setVideoSize(const QSize &size)
@@ -373,4 +407,18 @@ void QAndroidVideoRendererControl::createGLResources()
}
}
+bool QAndroidVideoRendererControl::eventFilter(QObject *, QEvent *e)
+{
+ if (e->type() == QEvent::DynamicPropertyChange) {
+ QDynamicPropertyChangeEvent *event = static_cast<QDynamicPropertyChangeEvent*>(e);
+ if (event->propertyName() == "GLContext" && m_textureReadyCallback) {
+ m_textureReadyCallback(m_textureReadyContext);
+ m_textureReadyCallback = 0;
+ m_textureReadyContext = 0;
+ }
+ }
+
+ return false;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/android/mediaplayer/qandroidvideorendercontrol.h b/src/plugins/android/mediaplayer/qandroidvideorendercontrol.h
index 525291e1f..cd935502c 100644
--- a/src/plugins/android/mediaplayer/qandroidvideorendercontrol.h
+++ b/src/plugins/android/mediaplayer/qandroidvideorendercontrol.h
@@ -65,14 +65,18 @@ public:
void setSurface(QAbstractVideoSurface *surface) Q_DECL_OVERRIDE;
jobject surfaceHolder() Q_DECL_OVERRIDE;
+ bool isTextureReady() Q_DECL_OVERRIDE;
+ void setTextureReadyCallback(TextureReadyCallback cb, void *context = 0) Q_DECL_OVERRIDE;
void setVideoSize(const QSize &size) Q_DECL_OVERRIDE;
void stop() Q_DECL_OVERRIDE;
+ bool eventFilter(QObject *obj, QEvent *event) Q_DECL_OVERRIDE;
+
private Q_SLOTS:
void onFrameAvailable();
private:
- void setupSurface();
+ bool initSurfaceTexture();
void renderFrameToFbo();
void createGLResources();
@@ -88,6 +92,9 @@ private:
JSurfaceTexture *m_surfaceTexture;
JSurfaceTextureHolder *m_surfaceHolder;
uint m_externalTex;
+
+ TextureReadyCallback m_textureReadyCallback;
+ void *m_textureReadyContext;
};
QT_END_NAMESPACE
diff --git a/src/plugins/android/wrappers/jmediaplayer.cpp b/src/plugins/android/wrappers/jmediaplayer.cpp
index 48e743b26..f6e03ee22 100644
--- a/src/plugins/android/wrappers/jmediaplayer.cpp
+++ b/src/plugins/android/wrappers/jmediaplayer.cpp
@@ -82,6 +82,11 @@ JMediaPlayer::~JMediaPlayer()
mplayers.remove(mId);
}
+void JMediaPlayer::release()
+{
+ callMethod<void>("release");
+}
+
void JMediaPlayer::onError(qint32 what, qint32 extra)
{
Q_EMIT error(what, extra);
diff --git a/src/plugins/android/wrappers/jmediaplayer.h b/src/plugins/android/wrappers/jmediaplayer.h
index f5cb11773..710246b9a 100644
--- a/src/plugins/android/wrappers/jmediaplayer.h
+++ b/src/plugins/android/wrappers/jmediaplayer.h
@@ -89,6 +89,8 @@ public:
MEDIA_PLAYER_FINISHED = 6
};
+ void release();
+
int getCurrentPosition();
int getDuration();
bool isPlaying();
diff --git a/src/plugins/directshow/player/directshowplayerservice.cpp b/src/plugins/directshow/player/directshowplayerservice.cpp
index d89ed7bdb..70049e245 100644
--- a/src/plugins/directshow/player/directshowplayerservice.cpp
+++ b/src/plugins/directshow/player/directshowplayerservice.cpp
@@ -578,6 +578,9 @@ void DirectShowPlayerService::doReleaseGraph(QMutexLocker *locker)
control->Release();
}
+ //release m_headerInfo -> decrease ref counter of m_source
+ m_metaDataControl->updateGraph(0, 0);
+
if (m_source) {
m_source->Release();
m_source = 0;
@@ -627,6 +630,7 @@ int DirectShowPlayerService::findStreamTypes(IBaseFilter *source) const
}
}
}
+ pins->Release();
}
filter->Release();
}