diff options
author | Yoann Lopes <yoann.lopes@digia.com> | 2013-09-27 11:24:10 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-10-01 17:26:21 +0200 |
commit | be7a6241e77f67e4a19c63ac5683dd7fa566e9d2 (patch) | |
tree | ab8b66b5124d4a982d7690cf7893a40650bccc8d /src/plugins/android/src | |
parent | 329d9d4563445d785284a02983e237ff1a07f5dd (diff) |
Android: refactor video renderer.
Removed the overhead of having to create a shared OpenGL context in the GUI
thread and pre-render the frame into a FBO.
We now directly render the GL_TEXTURE_EXTERNAL_OES in the QtQuick render
thread, using an Android-specific QSGVideoNode.
We also use a callback from the render thread to create the texture from
there and not have to create a separate shared OpenGL context.
Change-Id: I6c8eb94b47d0a03329c912701b8af3fb5ebd1876
Reviewed-by: Christian Stromme <christian.stromme@digia.com>
Diffstat (limited to 'src/plugins/android/src')
10 files changed, 118 insertions, 295 deletions
diff --git a/src/plugins/android/src/common/qandroidvideooutput.h b/src/plugins/android/src/common/qandroidvideooutput.h index 8110b67b0..1ad64a4b4 100644 --- a/src/plugins/android/src/common/qandroidvideooutput.h +++ b/src/plugins/android/src/common/qandroidvideooutput.h @@ -48,26 +48,28 @@ QT_BEGIN_NAMESPACE -typedef void (*TextureReadyCallback)(void*); - class QAndroidVideoOutput { public: - QAndroidVideoOutput() { } virtual ~QAndroidVideoOutput() { } virtual jobject surfaceHolder() = 0; + virtual jobject surfaceTexture() { return 0; } - virtual bool isTextureReady() = 0; - virtual void setTextureReadyCallback(TextureReadyCallback cb, void *context = 0) = 0; - virtual jobject surfaceTexture() = 0; + virtual bool isReady() { return true; } - virtual void setVideoSize(const QSize &size) = 0; - virtual void stop() = 0; + virtual void setVideoSize(const QSize &) { } + virtual void stop() { } virtual QImage toImage() = 0; + + // signals: + // void readyChanged(bool); }; +#define QAndroidVideoOutput_iid "org.qt-project.qt.qandroidvideooutput/5.0" +Q_DECLARE_INTERFACE(QAndroidVideoOutput, QAndroidVideoOutput_iid) + QT_END_NAMESPACE #endif // QANDROIDVIDEOOUTPUT_H diff --git a/src/plugins/android/src/common/qandroidvideorendercontrol.cpp b/src/plugins/android/src/common/qandroidvideorendercontrol.cpp index 0eb8d172f..b9aac6434 100644 --- a/src/plugins/android/src/common/qandroidvideorendercontrol.cpp +++ b/src/plugins/android/src/common/qandroidvideorendercontrol.cpp @@ -44,39 +44,31 @@ #include <QtCore/private/qjni_p.h> #include "jsurfacetextureholder.h" #include <QAbstractVideoSurface> -#include <QOpenGLContext> -#include <QOffscreenSurface> -#include <QOpenGLFramebufferObject> #include <QVideoSurfaceFormat> -#include <QOpenGLFunctions> -#include <QOpenGLShaderProgram> #include <qevent.h> +#include <qcoreapplication.h> +#include <qopenglcontext.h> +#include <qopenglfunctions.h> QT_BEGIN_NAMESPACE -static const GLfloat g_vertex_data[] = { - -1.f, 1.f, - 1.f, 1.f, - 1.f, -1.f, - -1.f, -1.f -}; +#define ExternalGLTextureHandle QAbstractVideoBuffer::HandleType(QAbstractVideoBuffer::UserHandle + 1) -static const GLfloat g_texture_data[] = { - 0.f, 0.f, - 1.f, 0.f, - 1.f, 1.f, - 0.f, 1.f -}; +TextureDeleter::~TextureDeleter() +{ + glDeleteTextures(1, &m_id); +} -class TextureVideoBuffer : public QAbstractVideoBuffer +class AndroidTextureVideoBuffer : public QAbstractVideoBuffer { public: - TextureVideoBuffer(GLuint textureId) - : QAbstractVideoBuffer(GLTextureHandle) - , m_textureId(textureId) - {} + AndroidTextureVideoBuffer(JSurfaceTexture *surface) + : QAbstractVideoBuffer(ExternalGLTextureHandle) + , m_surfaceTexture(surface) + { + } - virtual ~TextureVideoBuffer() {} + virtual ~AndroidTextureVideoBuffer() {} MapMode mapMode() const { return NotMapped; } uchar *map(MapMode, int*, int*) { return 0; } @@ -84,67 +76,33 @@ public: QVariant handle() const { - return QVariant::fromValue<unsigned int>(m_textureId); - } - -private: - GLuint m_textureId; -}; - -class ImageVideoBuffer : public QAbstractVideoBuffer -{ -public: - ImageVideoBuffer(const QImage &image) - : QAbstractVideoBuffer(NoHandle) - , m_image(image) - , m_mode(NotMapped) - { - - } - - MapMode mapMode() const { return m_mode; } - uchar *map(MapMode mode, int *, int *) - { - if (mode != NotMapped && m_mode == NotMapped) { - m_mode = mode; - return m_image.bits(); + if (m_data.isEmpty()) { + // update the video texture (called from the render thread) + m_surfaceTexture->updateTexImage(); + m_data << (uint)m_surfaceTexture->textureID() << m_surfaceTexture->getTransformMatrix(); } - return 0; - } - - void unmap() - { - m_mode = NotMapped; + return m_data; } private: - QImage m_image; - MapMode m_mode; + mutable JSurfaceTexture *m_surfaceTexture; + mutable QVariantList m_data; }; QAndroidVideoRendererControl::QAndroidVideoRendererControl(QObject *parent) : QVideoRendererControl(parent) , m_surface(0) - , m_offscreenSurface(0) - , m_glContext(0) - , m_fbo(0) - , m_program(0) - , m_useImage(false) , m_androidSurface(0) , m_surfaceTexture(0) , m_surfaceHolder(0) , m_externalTex(0) - , m_textureReadyCallback(0) - , m_textureReadyContext(0) + , m_textureDeleter(0) { } QAndroidVideoRendererControl::~QAndroidVideoRendererControl() { - if (m_glContext) - m_glContext->makeCurrent(m_offscreenSurface); - if (m_surfaceTexture) { m_surfaceTexture->callMethod<void>("release"); delete m_surfaceTexture; @@ -159,13 +117,8 @@ QAndroidVideoRendererControl::~QAndroidVideoRendererControl() delete m_surfaceHolder; m_surfaceHolder = 0; } - if (m_externalTex) - glDeleteTextures(1, &m_externalTex); - - delete m_fbo; - delete m_program; - delete m_glContext; - delete m_offscreenSurface; + if (m_textureDeleter) + m_textureDeleter->deleteLater(); } QAbstractVideoSurface *QAndroidVideoRendererControl::surface() const @@ -178,28 +131,23 @@ void QAndroidVideoRendererControl::setSurface(QAbstractVideoSurface *surface) if (surface == m_surface) return; - if (m_surface && m_surface->isActive()) { - m_surface->stop(); - m_surface->removeEventFilter(this); + if (m_surface) { + if (m_surface->isActive()) + m_surface->stop(); + m_surface->setProperty("_q_GLThreadCallback", QVariant()); } m_surface = surface; if (m_surface) { - m_useImage = !m_surface->supportedPixelFormats(QAbstractVideoBuffer::GLTextureHandle).contains(QVideoFrame::Format_BGR32); - m_surface->installEventFilter(this); + m_surface->setProperty("_q_GLThreadCallback", + QVariant::fromValue<QObject*>(this)); } } -bool QAndroidVideoRendererControl::isTextureReady() +bool QAndroidVideoRendererControl::isReady() { - return QOpenGLContext::currentContext() || (m_surface && m_surface->property("GLContext").isValid()); -} - -void QAndroidVideoRendererControl::setTextureReadyCallback(TextureReadyCallback cb, void *context) -{ - m_textureReadyCallback = cb; - m_textureReadyContext = context; + return QOpenGLContext::currentContext() || m_externalTex; } bool QAndroidVideoRendererControl::initSurfaceTexture() @@ -210,45 +158,15 @@ bool QAndroidVideoRendererControl::initSurfaceTexture() 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(); - - m_glContext = new QOpenGLContext; - m_glContext->setFormat(m_offscreenSurface->requestedFormat()); - - if (shareContext) - m_glContext->setShareContext(shareContext); - - 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 - if (!m_glContext->shareContext()) - m_useImage = true; + // if we have an OpenGL context in the current thread, create a texture. Otherwise, wait + // for the GL render thread to call us back to do it. + if (QOpenGLContext::currentContext()) { + glGenTextures(1, &m_externalTex); + m_textureDeleter = new TextureDeleter(m_externalTex); + } else if (!m_externalTex) { + return false; } - if (m_glContext) - m_glContext->makeCurrent(m_offscreenSurface); - - glGenTextures(1, &m_externalTex); m_surfaceTexture = new JSurfaceTexture(m_externalTex); if (m_surfaceTexture->isValid()) { @@ -256,7 +174,9 @@ bool QAndroidVideoRendererControl::initSurfaceTexture() } else { delete m_surfaceTexture; m_surfaceTexture = 0; - glDeleteTextures(1, &m_externalTex); + m_textureDeleter->deleteLater(); + m_externalTex = 0; + m_textureDeleter = 0; } return m_surfaceTexture != 0; @@ -294,9 +214,6 @@ void QAndroidVideoRendererControl::setVideoSize(const QSize &size) stop(); m_nativeSize = size; - - delete m_fbo; - m_fbo = 0; } void QAndroidVideoRendererControl::stop() @@ -308,131 +225,45 @@ void QAndroidVideoRendererControl::stop() QImage QAndroidVideoRendererControl::toImage() { - if (!m_fbo) - return QImage(); - - return m_fbo->toImage().mirrored(); + // FIXME!!! Since we are not using a FBO anymore, we can't grab the pixels. And glGetTexImage + // doesn't work on GL_TEXTURE_EXTERNAL_OES + return QImage(); } void QAndroidVideoRendererControl::onFrameAvailable() { - if (m_glContext) - m_glContext->makeCurrent(m_offscreenSurface); - - m_surfaceTexture->updateTexImage(); - - if (!m_nativeSize.isValid()) + if (!m_nativeSize.isValid() || !m_surface) return; - renderFrameToFbo(); - - QAbstractVideoBuffer *buffer = 0; - QVideoFrame frame; + QAbstractVideoBuffer *buffer = new AndroidTextureVideoBuffer(m_surfaceTexture); + QVideoFrame frame(buffer, m_nativeSize, QVideoFrame::Format_BGR32); - if (m_useImage) { - buffer = new ImageVideoBuffer(m_fbo->toImage().mirrored()); - frame = QVideoFrame(buffer, m_nativeSize, QVideoFrame::Format_RGB32); - } else { - buffer = new TextureVideoBuffer(m_fbo->texture()); - frame = QVideoFrame(buffer, m_nativeSize, QVideoFrame::Format_BGR32); + if (m_surface->isActive() && (m_surface->surfaceFormat().pixelFormat() != frame.pixelFormat() + || m_surface->nativeResolution() != frame.size())) { + m_surface->stop(); } - if (m_surface && frame.isValid()) { - if (m_surface->isActive() && (m_surface->surfaceFormat().pixelFormat() != frame.pixelFormat() - || m_surface->nativeResolution() != frame.size())) { - m_surface->stop(); - } - - if (!m_surface->isActive()) { - QVideoSurfaceFormat format(frame.size(), frame.pixelFormat(), - m_useImage ? QAbstractVideoBuffer::NoHandle - : QAbstractVideoBuffer::GLTextureHandle); - - m_surface->start(format); - } + if (!m_surface->isActive()) { + QVideoSurfaceFormat format(frame.size(), frame.pixelFormat(), ExternalGLTextureHandle); + format.setScanLineDirection(QVideoSurfaceFormat::BottomToTop); - if (m_surface->isActive()) - m_surface->present(frame); + m_surface->start(format); } -} - -void QAndroidVideoRendererControl::renderFrameToFbo() -{ - createGLResources(); - - m_fbo->bind(); - - glViewport(0, 0, m_nativeSize.width(), m_nativeSize.height()); - - m_program->bind(); - m_program->enableAttributeArray(0); - m_program->enableAttributeArray(1); - m_program->setUniformValue("frameTexture", GLuint(0)); - m_program->setUniformValue("texMatrix", m_surfaceTexture->getTransformMatrix()); - - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, g_vertex_data); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, g_texture_data); - - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - m_program->disableAttributeArray(0); - m_program->disableAttributeArray(1); - m_program->release(); - - glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0); - m_fbo->release(); - - glFinish(); + if (m_surface->isActive()) + m_surface->present(frame); } -void QAndroidVideoRendererControl::createGLResources() +void QAndroidVideoRendererControl::customEvent(QEvent *e) { - if (!m_fbo) - m_fbo = new QOpenGLFramebufferObject(m_nativeSize); - - if (!m_program) { - m_program = new QOpenGLShaderProgram; - - QOpenGLShader *vertexShader = new QOpenGLShader(QOpenGLShader::Vertex, m_program); - vertexShader->compileSourceCode("attribute highp vec4 vertexCoordsArray; \n" \ - "attribute highp vec2 textureCoordArray; \n" \ - "uniform highp mat4 texMatrix; \n" \ - "varying highp vec2 textureCoords; \n" \ - "void main(void) \n" \ - "{ \n" \ - " gl_Position = vertexCoordsArray; \n" \ - " textureCoords = (texMatrix * vec4(textureCoordArray, 0.0, 1.0)).xy; \n" \ - "}\n"); - m_program->addShader(vertexShader); - - QOpenGLShader *fragmentShader = new QOpenGLShader(QOpenGLShader::Fragment, m_program); - fragmentShader->compileSourceCode("#extension GL_OES_EGL_image_external : require \n" \ - "varying highp vec2 textureCoords; \n" \ - "uniform samplerExternalOES frameTexture; \n" \ - "void main() \n" \ - "{ \n" \ - " gl_FragColor = texture2D(frameTexture, textureCoords); \n" \ - "}\n"); - m_program->addShader(fragmentShader); - - m_program->bindAttributeLocation("vertexCoordsArray", 0); - m_program->bindAttributeLocation("textureCoordArray", 1); - m_program->link(); - } -} - -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; + if (e->type() == QEvent::User) { + // This is running in the render thread (OpenGL enabled) + if (!m_externalTex) { + glGenTextures(1, &m_externalTex); + m_textureDeleter = new TextureDeleter(m_externalTex); // will be deleted in the correct thread + emit readyChanged(true); } } - - return false; } QT_END_NAMESPACE diff --git a/src/plugins/android/src/common/qandroidvideorendercontrol.h b/src/plugins/android/src/common/qandroidvideorendercontrol.h index 25220310e..e98495ede 100644 --- a/src/plugins/android/src/common/qandroidvideorendercontrol.h +++ b/src/plugins/android/src/common/qandroidvideorendercontrol.h @@ -48,15 +48,23 @@ QT_BEGIN_NAMESPACE -class QOpenGLContext; -class QOffscreenSurface; -class QOpenGLFramebufferObject; -class QOpenGLShaderProgram; class JSurfaceTextureHolder; +class TextureDeleter : public QObject +{ + Q_OBJECT +public: + TextureDeleter(uint id) : m_id(id) { } + ~TextureDeleter(); + +private: + uint m_id; +}; + class QAndroidVideoRendererControl : public QVideoRendererControl, public QAndroidVideoOutput { Q_OBJECT + Q_INTERFACES(QAndroidVideoOutput) public: explicit QAndroidVideoRendererControl(QObject *parent = 0); ~QAndroidVideoRendererControl() Q_DECL_OVERRIDE; @@ -65,38 +73,31 @@ 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; jobject surfaceTexture() Q_DECL_OVERRIDE; + bool isReady() Q_DECL_OVERRIDE; void setVideoSize(const QSize &size) Q_DECL_OVERRIDE; void stop() Q_DECL_OVERRIDE; QImage toImage() Q_DECL_OVERRIDE; - bool eventFilter(QObject *obj, QEvent *event) Q_DECL_OVERRIDE; + void customEvent(QEvent *) Q_DECL_OVERRIDE; + +Q_SIGNALS: + void readyChanged(bool); private Q_SLOTS: void onFrameAvailable(); private: bool initSurfaceTexture(); - void renderFrameToFbo(); - void createGLResources(); QAbstractVideoSurface *m_surface; - QOffscreenSurface *m_offscreenSurface; - QOpenGLContext *m_glContext; - QOpenGLFramebufferObject *m_fbo; - QOpenGLShaderProgram *m_program; - bool m_useImage; QSize m_nativeSize; QJNIObjectPrivate *m_androidSurface; JSurfaceTexture *m_surfaceTexture; JSurfaceTextureHolder *m_surfaceHolder; uint m_externalTex; - - TextureReadyCallback m_textureReadyCallback; - void *m_textureReadyContext; + TextureDeleter *m_textureDeleter; }; QT_END_NAMESPACE diff --git a/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp b/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp index 761b716d1..ec86322a4 100644 --- a/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp +++ b/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp @@ -52,12 +52,6 @@ QT_BEGIN_NAMESPACE -static void textureReadyCallback(void *context) -{ - if (context) - reinterpret_cast<QAndroidCameraSession *>(context)->onSurfaceTextureReady(); -} - QAndroidCameraSession::QAndroidCameraSession(QObject *parent) : QObject(parent) , m_selectedCamera(0) @@ -188,12 +182,17 @@ void QAndroidCameraSession::close() emit statusChanged(m_status); } -void QAndroidCameraSession::setVideoPreview(QAndroidVideoOutput *videoOutput) +void QAndroidCameraSession::setVideoPreview(QObject *videoOutput) { if (m_videoOutput) m_videoOutput->stop(); - m_videoOutput = videoOutput; + if (videoOutput) { + connect(videoOutput, SIGNAL(readyChanged(bool)), this, SLOT(onVideoOutputReady(bool))); + m_videoOutput = qobject_cast<QAndroidVideoOutput *>(videoOutput); + } else { + m_videoOutput = 0; + } } void QAndroidCameraSession::adjustViewfinderSize(const QSize &captureSize, bool restartPreview) @@ -243,12 +242,8 @@ void QAndroidCameraSession::startPreview() applyImageSettings(); adjustViewfinderSize(m_imageSettings.resolution()); - if (m_videoOutput) { - if (m_videoOutput->isTextureReady()) - m_camera->setPreviewTexture(m_videoOutput->surfaceTexture()); - else - m_videoOutput->setTextureReadyCallback(textureReadyCallback, this); - } + if (m_videoOutput && m_videoOutput->isReady()) + onVideoOutputReady(true); JMultimediaUtils::enableOrientationListener(true); @@ -522,9 +517,9 @@ void QAndroidCameraSession::processCapturedImage(int id, } } -void QAndroidCameraSession::onSurfaceTextureReady() +void QAndroidCameraSession::onVideoOutputReady(bool ready) { - if (m_camera && m_videoOutput) + if (m_camera && m_videoOutput && ready) m_camera->setPreviewTexture(m_videoOutput->surfaceTexture()); } diff --git a/src/plugins/android/src/mediacapture/qandroidcamerasession.h b/src/plugins/android/src/mediacapture/qandroidcamerasession.h index f1cf44eec..8d5b01c64 100644 --- a/src/plugins/android/src/mediacapture/qandroidcamerasession.h +++ b/src/plugins/android/src/mediacapture/qandroidcamerasession.h @@ -71,7 +71,7 @@ public: void setCaptureMode(QCamera::CaptureModes mode); bool isCaptureModeSupported(QCamera::CaptureModes mode) const; - void setVideoPreview(QAndroidVideoOutput *videoOutput); + void setVideoPreview(QObject *videoOutput); void adjustViewfinderSize(const QSize &captureSize, bool restartPreview = true); QImageEncoderSettings imageSettings() const { return m_imageSettings; } @@ -88,8 +88,6 @@ public: int capture(const QString &fileName); void cancelCapture(); - void onSurfaceTextureReady(); - int currentCameraRotation() const; Q_SIGNALS: @@ -110,6 +108,8 @@ Q_SIGNALS: void imageCaptureError(int id, int error, const QString &errorString); private Q_SLOTS: + void onVideoOutputReady(bool ready); + void onApplicationStateChanged(Qt::ApplicationState state); void onCameraPictureExposed(); diff --git a/src/plugins/android/src/mediacapture/qandroidcaptureservice.h b/src/plugins/android/src/mediacapture/qandroidcaptureservice.h index 71aaf2d64..4050622f2 100644 --- a/src/plugins/android/src/mediacapture/qandroidcaptureservice.h +++ b/src/plugins/android/src/mediacapture/qandroidcaptureservice.h @@ -88,7 +88,7 @@ private: QAndroidVideoDeviceSelectorControl *m_videoInputControl; QAndroidAudioInputSelectorControl *m_audioInputControl; QAndroidCameraSession *m_cameraSession; - QAndroidVideoRendererControl *m_videoRendererControl; + QMediaControl *m_videoRendererControl; QAndroidCameraZoomControl *m_cameraZoomControl; QAndroidCameraExposureControl *m_cameraExposureControl; QAndroidCameraFlashControl *m_cameraFlashControl; diff --git a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp index 753c60662..3f3b599ac 100644 --- a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp +++ b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp @@ -45,12 +45,6 @@ QT_BEGIN_NAMESPACE -static void textureReadyCallback(void *context) -{ - if (context) - reinterpret_cast<QAndroidMediaPlayerControl *>(context)->onSurfaceTextureReady(); -} - QAndroidMediaPlayerControl::QAndroidMediaPlayerControl(QObject *parent) : QMediaPlayerControl(parent), mMediaPlayer(new JMediaPlayer), @@ -241,18 +235,18 @@ void QAndroidMediaPlayerControl::setMedia(const QMediaContent &mediaContent, setSeekable(true); } -void QAndroidMediaPlayerControl::setVideoOutput(QAndroidVideoOutput *videoOutput) +void QAndroidMediaPlayerControl::setVideoOutput(QObject *videoOutput) { if (mVideoOutput) mVideoOutput->stop(); - mVideoOutput = videoOutput; + mVideoOutput = qobject_cast<QAndroidVideoOutput *>(videoOutput); if (mVideoOutput && !mMediaPlayer->display()) { - if (mVideoOutput->isTextureReady()) + if (mVideoOutput->isReady()) mMediaPlayer->setDisplay(mVideoOutput->surfaceHolder()); else - mVideoOutput->setTextureReadyCallback(textureReadyCallback, this); + connect(videoOutput, SIGNAL(readyChanged(bool)), this, SLOT(onVideoOutputReady(bool))); } } @@ -426,9 +420,9 @@ void QAndroidMediaPlayerControl::onVideoSizeChanged(qint32 width, qint32 height) mVideoOutput->setVideoSize(mVideoSize); } -void QAndroidMediaPlayerControl::onSurfaceTextureReady() +void QAndroidMediaPlayerControl::onVideoOutputReady(bool ready) { - if (!mMediaPlayer->display() && mVideoOutput) { + if (!mMediaPlayer->display() && mVideoOutput && ready) { mMediaPlayer->setDisplay(mVideoOutput->surfaceHolder()); flushPendingStates(); } diff --git a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h index 93eced853..ef1d325e5 100644 --- a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h +++ b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h @@ -75,8 +75,7 @@ public: const QIODevice *mediaStream() const Q_DECL_OVERRIDE; void setMedia(const QMediaContent &mediaContent, QIODevice *stream) Q_DECL_OVERRIDE; - void setVideoOutput(QAndroidVideoOutput *videoOutput); - void onSurfaceTextureReady(); + void setVideoOutput(QObject *videoOutput); Q_SIGNALS: void metaDataUpdated(); @@ -90,6 +89,7 @@ public Q_SLOTS: void setMuted(bool muted) Q_DECL_OVERRIDE; private Q_SLOTS: + void onVideoOutputReady(bool ready); void onError(qint32 what, qint32 extra); void onInfo(qint32 what, qint32 extra); void onMediaPlayerInfo(qint32 what, qint32 extra); diff --git a/src/plugins/android/src/mediaplayer/qandroidmediaservice.h b/src/plugins/android/src/mediaplayer/qandroidmediaservice.h index 4d310e8e0..ba4b4ccd2 100644 --- a/src/plugins/android/src/mediaplayer/qandroidmediaservice.h +++ b/src/plugins/android/src/mediaplayer/qandroidmediaservice.h @@ -48,7 +48,6 @@ QT_BEGIN_NAMESPACE class QAndroidMediaPlayerControl; class QAndroidMetaDataReaderControl; -class QAndroidVideoRendererControl; class QAndroidMediaService : public QMediaService { @@ -63,7 +62,7 @@ public: private: QAndroidMediaPlayerControl *mMediaControl; QAndroidMetaDataReaderControl *mMetadataControl; - QAndroidVideoRendererControl *mVideoRendererControl; + QMediaControl *mVideoRendererControl; }; QT_END_NAMESPACE diff --git a/src/plugins/android/src/wrappers/jsurfacetexture.h b/src/plugins/android/src/wrappers/jsurfacetexture.h index d65fc01e9..ea53b68ba 100644 --- a/src/plugins/android/src/wrappers/jsurfacetexture.h +++ b/src/plugins/android/src/wrappers/jsurfacetexture.h @@ -56,6 +56,7 @@ public: explicit JSurfaceTexture(unsigned int texName); ~JSurfaceTexture(); + int textureID() const { return m_texID; } QMatrix4x4 getTransformMatrix(); void updateTexImage(); |