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 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()
|
||||
|
||||
@@ -65,6 +65,7 @@ public:
|
||||
XvShmImageHandle,
|
||||
CoreImageHandle,
|
||||
QPixmapHandle,
|
||||
EGLImageHandle,
|
||||
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 {
|
||||
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)
|
||||
{
|
||||
#ifdef DEBUG_VIDEOITEM
|
||||
qDebug() << Q_FUNC_INFO << format;
|
||||
qDebug() << Q_FUNC_INFO << format << supportedPixelFormats(format.handleType());
|
||||
#endif
|
||||
|
||||
if (!supportedPixelFormats(format.handleType()).contains(format.pixelFormat()))
|
||||
|
||||
Reference in New Issue
Block a user