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>
This commit is contained in:
committed by
Yoann Lopes
parent
888759e334
commit
39c2694414
@@ -102,6 +102,7 @@ int QAbstractVideoBufferPrivate::map(
|
|||||||
\value XvShmImageHandle The handle contains pointer to shared memory XVideo image.
|
\value XvShmImageHandle The handle contains pointer to shared memory XVideo image.
|
||||||
\value CoreImageHandle The handle contains pointer to Mac OS X CIImage.
|
\value CoreImageHandle The handle contains pointer to Mac OS X CIImage.
|
||||||
\value QPixmapHandle The handle of the buffer is a QPixmap.
|
\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.
|
\value UserHandle Start value for user defined handle types.
|
||||||
|
|
||||||
\sa handleType()
|
\sa handleType()
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ public:
|
|||||||
XvShmImageHandle,
|
XvShmImageHandle,
|
||||||
CoreImageHandle,
|
CoreImageHandle,
|
||||||
QPixmapHandle,
|
QPixmapHandle,
|
||||||
|
EGLImageHandle,
|
||||||
UserHandle = 1000
|
UserHandle = 1000
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
3
src/plugins/videonode/egl/egl.json
Normal file
3
src/plugins/videonode/egl/egl.json
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"Keys": ["sgvideonodes"]
|
||||||
|
}
|
||||||
17
src/plugins/videonode/egl/egl.pro
Normal file
17
src/plugins/videonode/egl/egl.pro
Normal file
@@ -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
|
||||||
243
src/plugins/videonode/egl/qsgvideonode_egl.cpp
Normal file
243
src/plugins/videonode/egl/qsgvideonode_egl.cpp
Normal file
@@ -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
|
||||||
102
src/plugins/videonode/egl/qsgvideonode_egl.h
Normal file
102
src/plugins/videonode/egl/qsgvideonode_egl.h
Normal file
@@ -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
|
||||||
|
|
||||||
@@ -3,3 +3,5 @@ TEMPLATE = subdirs
|
|||||||
config_gpu_vivante {
|
config_gpu_vivante {
|
||||||
SUBDIRS += imx6
|
SUBDIRS += imx6
|
||||||
}
|
}
|
||||||
|
|
||||||
|
contains(QT_CONFIG, egl):contains(QT_CONFIG, opengles2):!android: SUBDIRS += egl
|
||||||
|
|||||||
@@ -321,7 +321,7 @@ QList<QVideoFrame::PixelFormat> QSGVideoItemSurface::supportedPixelFormats(
|
|||||||
bool QSGVideoItemSurface::start(const QVideoSurfaceFormat &format)
|
bool QSGVideoItemSurface::start(const QVideoSurfaceFormat &format)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_VIDEOITEM
|
#ifdef DEBUG_VIDEOITEM
|
||||||
qDebug() << Q_FUNC_INFO << format;
|
qDebug() << Q_FUNC_INFO << format << supportedPixelFormats(format.handleType());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!supportedPixelFormats(format.handleType()).contains(format.pixelFormat()))
|
if (!supportedPixelFormats(format.handleType()).contains(format.pixelFormat()))
|
||||||
|
|||||||
Reference in New Issue
Block a user