summaryrefslogtreecommitdiffstats
path: root/src/plugins/android/src/common
diff options
context:
space:
mode:
authorYoann Lopes <yoann.lopes@digia.com>2013-03-25 18:11:27 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-12 12:56:57 +0200
commit0a7882f6b308296ff9d44d891d3bdfed91679ce2 (patch)
tree8a1e1575158d8213773fcf4e692a160bf4b301cd /src/plugins/android/src/common
parent99fff6941ba6b1929c1bd8d46dc8776a6cbf11c6 (diff)
Android: added camera support.
This patch includes all camera features: viewport, settings, image capture, and video recording. It also adds support for QAudioRecorder. Change-Id: Ib962177cc8de4bac03f42a2bc0f534e03464bbfc Reviewed-by: Christian Stromme <christian.stromme@digia.com>
Diffstat (limited to 'src/plugins/android/src/common')
-rw-r--r--src/plugins/android/src/common/common.pri10
-rw-r--r--src/plugins/android/src/common/qandroidmultimediautils.cpp79
-rw-r--r--src/plugins/android/src/common/qandroidmultimediautils.h58
-rw-r--r--src/plugins/android/src/common/qandroidvideooutput.h73
-rw-r--r--src/plugins/android/src/common/qandroidvideorendercontrol.cpp438
-rw-r--r--src/plugins/android/src/common/qandroidvideorendercontrol.h104
6 files changed, 762 insertions, 0 deletions
diff --git a/src/plugins/android/src/common/common.pri b/src/plugins/android/src/common/common.pri
new file mode 100644
index 000000000..f99dad507
--- /dev/null
+++ b/src/plugins/android/src/common/common.pri
@@ -0,0 +1,10 @@
+INCLUDEPATH += $$PWD
+
+HEADERS += \
+ $$PWD/qandroidvideooutput.h \
+ $$PWD/qandroidvideorendercontrol.h \
+ $$PWD/qandroidmultimediautils.h
+
+SOURCES += \
+ $$PWD/qandroidvideorendercontrol.cpp \
+ $$PWD/qandroidmultimediautils.cpp
diff --git a/src/plugins/android/src/common/qandroidmultimediautils.cpp b/src/plugins/android/src/common/qandroidmultimediautils.cpp
new file mode 100644
index 000000000..7ae40358f
--- /dev/null
+++ b/src/plugins/android/src/common/qandroidmultimediautils.cpp
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qandroidmultimediautils.h"
+
+#include <qlist.h>
+
+QT_BEGIN_NAMESPACE
+
+int qt_findClosestValue(const QList<int> &list, int value)
+{
+ if (list.size() < 2)
+ return 0;
+
+ int begin = 0;
+ int end = list.size() - 1;
+ int pivot = begin + (end - begin) / 2;
+ int v = list.at(pivot);
+
+ while (end - begin > 1) {
+ if (value == v)
+ return pivot;
+
+ if (value > v)
+ begin = pivot;
+ else
+ end = pivot;
+
+ pivot = begin + (end - begin) / 2;
+ v = list.at(pivot);
+ }
+
+ return value - v >= list.at(pivot + 1) - value ? pivot + 1 : pivot;
+}
+
+bool qt_sizeLessThan(const QSize &s1, const QSize &s2)
+{
+ return s1.width() * s1.height() < s2.width() * s2.height();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/android/src/common/qandroidmultimediautils.h b/src/plugins/android/src/common/qandroidmultimediautils.h
new file mode 100644
index 000000000..1996209b0
--- /dev/null
+++ b/src/plugins/android/src/common/qandroidmultimediautils.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANDROIDMULTIMEDIAUTILS_H
+#define QANDROIDMULTIMEDIAUTILS_H
+
+#include <qglobal.h>
+#include <qsize.h>
+
+QT_BEGIN_NAMESPACE
+
+// return the index of the closest value to <value> in <list>
+// (binary search)
+int qt_findClosestValue(const QList<int> &list, int value);
+
+bool qt_sizeLessThan(const QSize &s1, const QSize &s2);
+
+QT_END_NAMESPACE
+
+#endif // QANDROIDMULTIMEDIAUTILS_H
diff --git a/src/plugins/android/src/common/qandroidvideooutput.h b/src/plugins/android/src/common/qandroidvideooutput.h
new file mode 100644
index 000000000..8110b67b0
--- /dev/null
+++ b/src/plugins/android/src/common/qandroidvideooutput.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANDROIDVIDEOOUTPUT_H
+#define QANDROIDVIDEOOUTPUT_H
+
+#include <qglobal.h>
+#include <qsize.h>
+#include <jni.h>
+
+QT_BEGIN_NAMESPACE
+
+typedef void (*TextureReadyCallback)(void*);
+
+class QAndroidVideoOutput
+{
+public:
+ QAndroidVideoOutput() { }
+ virtual ~QAndroidVideoOutput() { }
+
+ virtual jobject surfaceHolder() = 0;
+
+ virtual bool isTextureReady() = 0;
+ virtual void setTextureReadyCallback(TextureReadyCallback cb, void *context = 0) = 0;
+ virtual jobject surfaceTexture() = 0;
+
+ virtual void setVideoSize(const QSize &size) = 0;
+ virtual void stop() = 0;
+
+ virtual QImage toImage() = 0;
+};
+
+QT_END_NAMESPACE
+
+#endif // QANDROIDVIDEOOUTPUT_H
diff --git a/src/plugins/android/src/common/qandroidvideorendercontrol.cpp b/src/plugins/android/src/common/qandroidvideorendercontrol.cpp
new file mode 100644
index 000000000..c5d38aebe
--- /dev/null
+++ b/src/plugins/android/src/common/qandroidvideorendercontrol.cpp
@@ -0,0 +1,438 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qandroidvideorendercontrol.h"
+
+#include <QtPlatformSupport/private/qjnihelpers_p.h>
+#include "jsurfacetextureholder.h"
+#include <QAbstractVideoSurface>
+#include <QOpenGLContext>
+#include <QOffscreenSurface>
+#include <QOpenGLFramebufferObject>
+#include <QVideoSurfaceFormat>
+#include <QOpenGLFunctions>
+#include <QOpenGLShaderProgram>
+#include <qevent.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
+};
+
+static const GLfloat g_texture_data[] = {
+ 0.f, 0.f,
+ 1.f, 0.f,
+ 1.f, 1.f,
+ 0.f, 1.f
+};
+
+class TextureVideoBuffer : public QAbstractVideoBuffer
+{
+public:
+ TextureVideoBuffer(GLuint textureId)
+ : QAbstractVideoBuffer(GLTextureHandle)
+ , m_textureId(textureId)
+ {}
+
+ virtual ~TextureVideoBuffer() {}
+
+ MapMode mapMode() const { return NotMapped; }
+ uchar *map(MapMode, int*, int*) { return 0; }
+ void unmap() {}
+
+ 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();
+ }
+
+ return 0;
+ }
+
+ void unmap()
+ {
+ m_mode = NotMapped;
+ }
+
+private:
+ QImage m_image;
+ MapMode m_mode;
+};
+
+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)
+{
+}
+
+QAndroidVideoRendererControl::~QAndroidVideoRendererControl()
+{
+ if (m_glContext)
+ m_glContext->makeCurrent(m_offscreenSurface);
+
+ if (m_surfaceTexture) {
+ m_surfaceTexture->callMethod<void>("release");
+ delete m_surfaceTexture;
+ m_surfaceTexture = 0;
+ }
+ if (m_androidSurface) {
+ m_androidSurface->callMethod<void>("release");
+ delete m_androidSurface;
+ m_androidSurface = 0;
+ }
+ if (m_surfaceHolder) {
+ 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;
+}
+
+QAbstractVideoSurface *QAndroidVideoRendererControl::surface() const
+{
+ return m_surface;
+}
+
+void QAndroidVideoRendererControl::setSurface(QAbstractVideoSurface *surface)
+{
+ if (surface == m_surface)
+ return;
+
+ if (m_surface && m_surface->isActive()) {
+ m_surface->stop();
+ m_surface->removeEventFilter(this);
+ }
+
+ m_surface = surface;
+
+ if (m_surface) {
+ m_useImage = !m_surface->supportedPixelFormats(QAbstractVideoBuffer::GLTextureHandle).contains(QVideoFrame::Format_BGR32);
+ m_surface->installEventFilter(this);
+ }
+}
+
+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_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();
+
+ 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 (m_glContext)
+ m_glContext->makeCurrent(m_offscreenSurface);
+
+ glGenTextures(1, &m_externalTex);
+ m_surfaceTexture = new JSurfaceTexture(m_externalTex);
+
+ 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) {
+ m_androidSurface = new QJNIObject("android/view/Surface",
+ "(Landroid/graphics/SurfaceTexture;)V",
+ m_surfaceTexture->object());
+
+ m_surfaceHolder = new JSurfaceTextureHolder(m_androidSurface->object());
+ }
+
+ return m_surfaceHolder->object();
+}
+
+jobject QAndroidVideoRendererControl::surfaceTexture()
+{
+ if (!initSurfaceTexture())
+ return 0;
+
+ return m_surfaceTexture->object();
+}
+
+void QAndroidVideoRendererControl::setVideoSize(const QSize &size)
+{
+ if (m_nativeSize == size)
+ return;
+
+ stop();
+
+ m_nativeSize = size;
+
+ delete m_fbo;
+ m_fbo = 0;
+}
+
+void QAndroidVideoRendererControl::stop()
+{
+ if (m_surface && m_surface->isActive())
+ m_surface->stop();
+ m_nativeSize = QSize();
+}
+
+QImage QAndroidVideoRendererControl::toImage()
+{
+ if (!m_fbo)
+ return QImage();
+
+ return m_fbo->toImage().mirrored();
+}
+
+void QAndroidVideoRendererControl::onFrameAvailable()
+{
+ if (m_glContext)
+ m_glContext->makeCurrent(m_offscreenSurface);
+
+ m_surfaceTexture->updateTexImage();
+
+ if (!m_nativeSize.isValid())
+ return;
+
+ renderFrameToFbo();
+
+ QAbstractVideoBuffer *buffer = 0;
+ QVideoFrame frame;
+
+ 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 && 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())
+ m_surface->present(frame);
+ }
+}
+
+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();
+}
+
+void QAndroidVideoRendererControl::createGLResources()
+{
+ 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;
+ }
+ }
+
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/android/src/common/qandroidvideorendercontrol.h b/src/plugins/android/src/common/qandroidvideorendercontrol.h
new file mode 100644
index 000000000..d8078f075
--- /dev/null
+++ b/src/plugins/android/src/common/qandroidvideorendercontrol.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANDROIDVIDEORENDERCONTROL_H
+#define QANDROIDVIDEORENDERCONTROL_H
+
+#include <qvideorenderercontrol.h>
+#include "qandroidvideooutput.h"
+#include "jsurfacetexture.h"
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLContext;
+class QOffscreenSurface;
+class QOpenGLFramebufferObject;
+class QOpenGLShaderProgram;
+class JSurfaceTextureHolder;
+
+class QAndroidVideoRendererControl : public QVideoRendererControl, public QAndroidVideoOutput
+{
+ Q_OBJECT
+public:
+ explicit QAndroidVideoRendererControl(QObject *parent = 0);
+ ~QAndroidVideoRendererControl() Q_DECL_OVERRIDE;
+
+ QAbstractVideoSurface *surface() const Q_DECL_OVERRIDE;
+ 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;
+ 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;
+
+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;
+
+ QJNIObject *m_androidSurface;
+ JSurfaceTexture *m_surfaceTexture;
+ JSurfaceTextureHolder *m_surfaceHolder;
+ uint m_externalTex;
+
+ TextureReadyCallback m_textureReadyCallback;
+ void *m_textureReadyContext;
+};
+
+QT_END_NAMESPACE
+
+#endif // QANDROIDVIDEORENDERCONTROL_H