summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew den Exter <andrew.den.exter@jollamobile.com>2014-04-17 22:50:13 +1000
committerYoann Lopes <yoann.lopes@digia.com>2014-07-18 16:03:52 +0200
commit39c269441421e1e61fbfc698b65f769db82cad56 (patch)
treef257195b0bf1a86430d04f12ac522c8c6185c2e7
parent888759e334e81117843afb6d0f8991db8aec5ca8 (diff)
Add an EGLImageKHR video node.
[ChangeLog] Added a VideoNode plugin which allows direct rendering of EGLImageKHR backed video frames. Change-Id: I36fb6fd27680dbe9c71a446bbd54df95488725f8 Reviewed-by: Yoann Lopes <yoann.lopes@digia.com>
-rw-r--r--src/multimedia/video/qabstractvideobuffer.cpp1
-rw-r--r--src/multimedia/video/qabstractvideobuffer.h1
-rw-r--r--src/plugins/videonode/egl/egl.json3
-rw-r--r--src/plugins/videonode/egl/egl.pro17
-rw-r--r--src/plugins/videonode/egl/qsgvideonode_egl.cpp243
-rw-r--r--src/plugins/videonode/egl/qsgvideonode_egl.h102
-rw-r--r--src/plugins/videonode/videonode.pro2
-rw-r--r--src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp2
8 files changed, 370 insertions, 1 deletions
diff --git a/src/multimedia/video/qabstractvideobuffer.cpp b/src/multimedia/video/qabstractvideobuffer.cpp
index 5f29a01a1..3e0643479 100644
--- a/src/multimedia/video/qabstractvideobuffer.cpp
+++ b/src/multimedia/video/qabstractvideobuffer.cpp
@@ -102,6 +102,7 @@ int QAbstractVideoBufferPrivate::map(
\value XvShmImageHandle The handle contains pointer to shared memory XVideo image.
\value CoreImageHandle The handle contains pointer to Mac OS X CIImage.
\value QPixmapHandle The handle of the buffer is a QPixmap.
+ \value EGLImageHandle The handle of the buffer is an EGLImageKHR.
\value UserHandle Start value for user defined handle types.
\sa handleType()
diff --git a/src/multimedia/video/qabstractvideobuffer.h b/src/multimedia/video/qabstractvideobuffer.h
index 7f3edf569..25d70e4ba 100644
--- a/src/multimedia/video/qabstractvideobuffer.h
+++ b/src/multimedia/video/qabstractvideobuffer.h
@@ -65,6 +65,7 @@ public:
XvShmImageHandle,
CoreImageHandle,
QPixmapHandle,
+ EGLImageHandle,
UserHandle = 1000
};
diff --git a/src/plugins/videonode/egl/egl.json b/src/plugins/videonode/egl/egl.json
new file mode 100644
index 000000000..08bb12c3f
--- /dev/null
+++ b/src/plugins/videonode/egl/egl.json
@@ -0,0 +1,3 @@
+{
+ "Keys": ["sgvideonodes"]
+}
diff --git a/src/plugins/videonode/egl/egl.pro b/src/plugins/videonode/egl/egl.pro
new file mode 100644
index 000000000..a6256cea1
--- /dev/null
+++ b/src/plugins/videonode/egl/egl.pro
@@ -0,0 +1,17 @@
+TARGET = eglvideonode
+QT += multimedia-private qtmultimediaquicktools-private
+CONFIG += egl
+
+PLUGIN_TYPE=video/videonode
+PLUGIN_EXTENDS = quick
+PLUGIN_CLASS_NAME = QSGVideoNodeFactory_EGL
+load(qt_plugin)
+
+HEADERS += \
+ qsgvideonode_egl.h
+
+SOURCES += \
+ qsgvideonode_egl.cpp
+
+OTHER_FILES += \
+ egl.json
diff --git a/src/plugins/videonode/egl/qsgvideonode_egl.cpp b/src/plugins/videonode/egl/qsgvideonode_egl.cpp
new file mode 100644
index 000000000..33e92a963
--- /dev/null
+++ b/src/plugins/videonode/egl/qsgvideonode_egl.cpp
@@ -0,0 +1,243 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Jolla Ltd.
+** 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 "qsgvideonode_egl.h"
+
+#include <QtMultimedia/qvideosurfaceformat.h>
+
+#include <GLES2/gl2ext.h>
+
+QT_BEGIN_NAMESPACE
+
+class QSGVideoMaterial_EGLShader : public QSGMaterialShader
+{
+public:
+ void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
+ char const *const *attributeNames() const;
+
+ static QSGMaterialType type;
+
+protected:
+ void initialize();
+
+ const char *vertexShader() const;
+ const char *fragmentShader() const;
+
+private:
+ int id_matrix;
+ int id_opacity;
+ int id_texture;
+};
+
+void QSGVideoMaterial_EGLShader::updateState(
+ const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
+{
+ QSGVideoMaterial_EGL *material = static_cast<QSGVideoMaterial_EGL *>(newEffect);
+ if (!oldEffect) {
+ program()->setUniformValue(id_texture, 0);
+ }
+
+ if (state.isMatrixDirty()) {
+ program()->setUniformValue(id_matrix, state.combinedMatrix());
+ }
+
+ if (state.isOpacityDirty()) {
+ program()->setUniformValue(id_opacity, state.opacity());
+ }
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_EXTERNAL_OES, material->m_textureId);
+}
+
+char const *const *QSGVideoMaterial_EGLShader::attributeNames() const
+{
+ static char const *const attr[] = { "position", "texcoord", 0 };
+ return attr;
+}
+
+QSGMaterialType QSGVideoMaterial_EGLShader::type;
+
+void QSGVideoMaterial_EGLShader::initialize()
+{
+ id_matrix = program()->uniformLocation("matrix");
+ id_opacity = program()->uniformLocation("opacity");
+ id_texture = program()->uniformLocation("texture");
+}
+
+const char *QSGVideoMaterial_EGLShader::vertexShader() const
+{
+ return "\n uniform highp mat4 matrix;"
+ "\n attribute highp vec4 position;"
+ "\n attribute highp vec2 texcoord;"
+ "\n varying highp vec2 frag_tx;"
+ "\n void main(void)"
+ "\n {"
+ "\n gl_Position = matrix * position;"
+ "\n frag_tx = texcoord;"
+ "\n }";
+}
+
+const char *QSGVideoMaterial_EGLShader::fragmentShader() const
+{
+ return "\n #extension GL_OES_EGL_image_external : require"
+ "\n uniform samplerExternalOES texture;"
+ "\n varying highp vec2 frag_tx;"
+ "\n void main(void)"
+ "\n {"
+ "\n gl_FragColor = texture2D(texture, frag_tx.st);"
+ "\n }";
+}
+
+QSGVideoMaterial_EGL::QSGVideoMaterial_EGL()
+ : m_image(0)
+ , m_textureId(0)
+{
+}
+
+QSGVideoMaterial_EGL::~QSGVideoMaterial_EGL()
+{
+ if (m_textureId) {
+ glDeleteTextures(1, &m_textureId);
+ m_textureId = 0;
+ }
+}
+
+QSGMaterialShader *QSGVideoMaterial_EGL::createShader() const
+{
+ return new QSGVideoMaterial_EGLShader;
+}
+
+QSGMaterialType *QSGVideoMaterial_EGL::type() const
+{
+ return &QSGVideoMaterial_EGLShader::type;
+}
+
+int QSGVideoMaterial_EGL::compare(const QSGMaterial *other) const
+{
+ return m_textureId - static_cast<const QSGVideoMaterial_EGL *>(other)->m_textureId;
+}
+
+void QSGVideoMaterial_EGL::setImage(EGLImageKHR image)
+{
+ static const PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES
+ = reinterpret_cast<PFNGLEGLIMAGETARGETTEXTURE2DOESPROC>(eglGetProcAddress("glEGLImageTargetTexture2DOES"));
+
+ if (m_image == image || !glEGLImageTargetTexture2DOES)
+ return;
+
+ m_image = image;
+
+ if (!m_image) {
+ if (m_textureId) {
+ glDeleteTextures(1, &m_textureId);
+ m_textureId = 0;
+ }
+ } else {
+ if (!m_textureId) {
+ glGenTextures(1, &m_textureId);
+ glBindTexture(GL_TEXTURE_EXTERNAL_OES, m_textureId);
+ glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ } else {
+ glBindTexture(GL_TEXTURE_EXTERNAL_OES, m_textureId);
+ }
+ glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, m_image);
+ }
+}
+
+QSGVideoNode_EGL::QSGVideoNode_EGL(const QVideoSurfaceFormat &format)
+ : m_pixelFormat(format.pixelFormat())
+{
+ setMaterial(&m_material);
+}
+
+QSGVideoNode_EGL::~QSGVideoNode_EGL()
+{
+}
+
+void QSGVideoNode_EGL::setCurrentFrame(const QVideoFrame &frame)
+{
+ EGLImageKHR image = frame.handle().value<void *>();
+ m_material.setImage(image);
+ markDirty(DirtyMaterial);
+}
+
+QVideoFrame::PixelFormat QSGVideoNode_EGL::pixelFormat() const
+{
+ return m_pixelFormat;
+}
+
+static bool isExtensionSupported()
+{
+ static const bool supported = eglGetProcAddress("glEGLImageTargetTexture2DOES");
+ return supported;
+}
+
+QList<QVideoFrame::PixelFormat> QSGVideoNodeFactory_EGL::supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType) const
+{
+ if (handleType != QAbstractVideoBuffer::EGLImageHandle || !isExtensionSupported())
+ return QList<QVideoFrame::PixelFormat>();
+
+ return QList<QVideoFrame::PixelFormat>()
+ << QVideoFrame::Format_Invalid
+ << QVideoFrame::Format_YV12
+ << QVideoFrame::Format_UYVY
+ << QVideoFrame::Format_NV21
+ << QVideoFrame::Format_YUYV
+ << QVideoFrame::Format_RGB32
+ << QVideoFrame::Format_BGR32
+ << QVideoFrame::Format_RGB24
+ << QVideoFrame::Format_BGR24
+ << QVideoFrame::Format_RGB565
+ << QVideoFrame::Format_BGR565;
+}
+
+QSGVideoNode *QSGVideoNodeFactory_EGL::createNode(const QVideoSurfaceFormat &format)
+{
+ return format.handleType() == QAbstractVideoBuffer::EGLImageHandle && isExtensionSupported()
+ ? new QSGVideoNode_EGL(format)
+ : 0;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/videonode/egl/qsgvideonode_egl.h b/src/plugins/videonode/egl/qsgvideonode_egl.h
new file mode 100644
index 000000000..23294a123
--- /dev/null
+++ b/src/plugins/videonode/egl/qsgvideonode_egl.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Jolla Ltd.
+** 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 EGLVIDEONODE_H
+#define EGLVIDEONODE_H
+
+#include <private/qsgvideonode_p.h>
+
+#include <QSGOpaqueTextureMaterial>
+#include <QSGTexture>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+QT_BEGIN_NAMESPACE
+
+class QSGVideoMaterial_EGL : public QSGMaterial
+{
+public:
+ QSGVideoMaterial_EGL();
+ ~QSGVideoMaterial_EGL();
+
+ QSGMaterialShader *createShader() const;
+ QSGMaterialType *type() const;
+ int compare(const QSGMaterial *other) const;
+
+ void setImage(EGLImageKHR image);
+
+private:
+ friend class QSGVideoMaterial_EGLShader;
+
+ QRectF m_subrect;
+ EGLImageKHR m_image;
+ GLuint m_textureId;
+};
+
+class QSGVideoNode_EGL : public QSGVideoNode
+{
+public:
+ QSGVideoNode_EGL(const QVideoSurfaceFormat &format);
+ ~QSGVideoNode_EGL();
+
+ void setCurrentFrame(const QVideoFrame &frame);
+ QVideoFrame::PixelFormat pixelFormat() const;
+
+private:
+ QSGVideoMaterial_EGL m_material;
+ QVideoFrame::PixelFormat m_pixelFormat;
+};
+
+class QSGVideoNodeFactory_EGL : public QSGVideoNodeFactoryPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.qt.sgvideonodefactory/5.2" FILE "egl.json")
+public:
+ QList<QVideoFrame::PixelFormat> supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType) const;
+ QSGVideoNode *createNode(const QVideoSurfaceFormat &format);
+};
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/plugins/videonode/videonode.pro b/src/plugins/videonode/videonode.pro
index c311200d3..e38b0a6a0 100644
--- a/src/plugins/videonode/videonode.pro
+++ b/src/plugins/videonode/videonode.pro
@@ -3,3 +3,5 @@ TEMPLATE = subdirs
config_gpu_vivante {
SUBDIRS += imx6
}
+
+contains(QT_CONFIG, egl):contains(QT_CONFIG, opengles2):!android: SUBDIRS += egl
diff --git a/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp b/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp
index 647732485..46dfc9468 100644
--- a/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp
+++ b/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp
@@ -321,7 +321,7 @@ QList<QVideoFrame::PixelFormat> QSGVideoItemSurface::supportedPixelFormats(
bool QSGVideoItemSurface::start(const QVideoSurfaceFormat &format)
{
#ifdef DEBUG_VIDEOITEM
- qDebug() << Q_FUNC_INFO << format;
+ qDebug() << Q_FUNC_INFO << format << supportedPixelFormats(format.handleType());
#endif
if (!supportedPixelFormats(format.handleType()).contains(format.pixelFormat()))