From: Dmytro Poplavskiy Date: Fri, 14 Oct 2011 02:36:18 +0000 (+1000) Subject: Declarative VideoOutput: added support for more rgb formats. X-Git-Tag: submit/tizen/20140129.151714~776 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=21fbb1d02509df805234f30d94e200a1f76fab4e;p=platform%2Fupstream%2Fqtmultimedia.git Declarative VideoOutput: added support for more rgb formats. RGB 565, RGB 32 and BGR 32 formats added, all of them supported with OpenGL ES. Change-Id: I026628611c59575af5934bac0a5f95dfbc6770cb Reviewed-on: http://codereview.qt-project.org/6644 Reviewed-by: Michael Goddard Reviewed-by: Jonas Rabbe --- diff --git a/src/imports/multimedia/multimedia.pro b/src/imports/multimedia/multimedia.pro index f6aa3648..2043130d 100644 --- a/src/imports/multimedia/multimedia.pro +++ b/src/imports/multimedia/multimedia.pro @@ -15,7 +15,7 @@ HEADERS += \ qdeclarativevideooutput_p.h \ qsgvideonode_p.h \ qsgvideonode_i420.h \ - qsgvideonode_rgb32.h \ + qsgvideonode_rgb.h \ qdeclarativeradio_p.h \ qdeclarativebackgroundaudio_p.h \ qdeclarativecamera_p.h \ @@ -34,7 +34,7 @@ SOURCES += \ qdeclarativevideooutput.cpp \ qsgvideonode.cpp \ qsgvideonode_i420.cpp \ - qsgvideonode_rgb32.cpp \ + qsgvideonode_rgb.cpp \ qdeclarativeradio.cpp \ qdeclarativebackgroundaudio.cpp \ qdeclarativecamera.cpp \ diff --git a/src/imports/multimedia/qdeclarativevideooutput.cpp b/src/imports/multimedia/qdeclarativevideooutput.cpp index ceefc7eb..9bd5eb35 100644 --- a/src/imports/multimedia/qdeclarativevideooutput.cpp +++ b/src/imports/multimedia/qdeclarativevideooutput.cpp @@ -42,7 +42,7 @@ #include "qsgvideonode_p.h" #include "qsgvideonode_i420.h" -#include "qsgvideonode_rgb32.h" +#include "qsgvideonode_rgb.h" #include @@ -161,9 +161,7 @@ QDeclarativeVideoOutput::QDeclarativeVideoOutput(QSGItem *parent) : this, SLOT(_q_updateNativeSize(QVideoSurfaceFormat)), Qt::QueuedConnection); m_videoNodeFactories.append(new QSGVideoNodeFactory_I420); -#ifndef QT_OPENGL_ES - m_videoNodeFactories.append(new QSGVideoNodeFactory_RGB32); -#endif + m_videoNodeFactories.append(new QSGVideoNodeFactory_RGB); } QDeclarativeVideoOutput::~QDeclarativeVideoOutput() diff --git a/src/imports/multimedia/qsgvideonode_rgb.cpp b/src/imports/multimedia/qsgvideonode_rgb.cpp new file mode 100644 index 00000000..41d778ed --- /dev/null +++ b/src/imports/multimedia/qsgvideonode_rgb.cpp @@ -0,0 +1,275 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "qsgvideonode_rgb.h" +#include +#include +#include +#include +#include + +QList QSGVideoNodeFactory_RGB::supportedPixelFormats( + QAbstractVideoBuffer::HandleType handleType) const +{ + QList pixelFormats; + + if (handleType == QAbstractVideoBuffer::NoHandle) { + pixelFormats.append(QVideoFrame::Format_RGB565); + pixelFormats.append(QVideoFrame::Format_RGB32); + pixelFormats.append(QVideoFrame::Format_ARGB32); + pixelFormats.append(QVideoFrame::Format_BGR32); + pixelFormats.append(QVideoFrame::Format_BGRA32); + } + + return pixelFormats; +} + +QSGVideoNode *QSGVideoNodeFactory_RGB::createNode(const QVideoSurfaceFormat &format) +{ + if (supportedPixelFormats(format.handleType()).contains(format.pixelFormat())) + return new QSGVideoNode_RGB(format); + + return 0; +} + + +class QSGVideoMaterialShader_RGB : public QSGMaterialShader +{ +public: + QSGVideoMaterialShader_RGB(QVideoFrame::PixelFormat pixelFormat) + : QSGMaterialShader(), + m_pixelFormat(pixelFormat) + { + } + + void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial); + + virtual char const *const *attributeNames() const { + static const char *names[] = { + "qt_VertexPosition", + "qt_VertexTexCoord", + 0 + }; + return names; + } + +protected: + + virtual const char *vertexShader() const { + const char *shader = + "uniform highp mat4 qt_Matrix; \n" + "attribute highp vec4 qt_VertexPosition; \n" + "attribute highp vec2 qt_VertexTexCoord; \n" + "varying highp vec2 qt_TexCoord; \n" + "void main() { \n" + " qt_TexCoord = qt_VertexTexCoord; \n" + " gl_Position = qt_Matrix * qt_VertexPosition; \n" + "}"; + return shader; + } + + virtual const char *fragmentShader() const { + static const char *shader = + "uniform sampler2D rgbTexture;" + "uniform lowp float opacity;" + "" + "varying highp vec2 qt_TexCoord;" + "" + "void main()" + "{" + " gl_FragColor = texture2D(rgbTexture, qt_TexCoord) * opacity;" + "}"; + + static const char *colorsSwapShader = + "uniform sampler2D rgbTexture;" + "uniform lowp float opacity;" + "" + "varying highp vec2 qt_TexCoord;" + "" + "void main()" + "{" + " gl_FragColor = vec4(texture2D(rgbTexture, qt_TexCoord).bgr, 1.0) * opacity;" + "}"; + + + switch (m_pixelFormat) { + case QVideoFrame::Format_RGB32: + case QVideoFrame::Format_ARGB32: + return colorsSwapShader; + default: + return shader; + } + } + + virtual void initialize() { + m_id_matrix = program()->uniformLocation("qt_Matrix"); + m_id_rgbTexture = program()->uniformLocation("rgbTexture"); + m_id_opacity = program()->uniformLocation("opacity"); + } + + int m_id_matrix; + int m_id_rgbTexture; + int m_id_opacity; + QVideoFrame::PixelFormat m_pixelFormat; +}; + + +class QSGVideoMaterial_RGB : public QSGMaterial +{ +public: + QSGVideoMaterial_RGB(const QVideoSurfaceFormat &format) : + m_format(format), + m_textureId(0), + m_opacity(1.0) + { + setFlag(Blending, false); + } + + ~QSGVideoMaterial_RGB() + { + if (m_textureId) + glDeleteTextures(1, &m_textureId); + } + + virtual QSGMaterialType *type() const { + static QSGMaterialType theType; + return &theType; + } + + virtual QSGMaterialShader *createShader() const { + return new QSGVideoMaterialShader_RGB(m_format.pixelFormat()); + } + + virtual int compare(const QSGMaterial *other) const { + const QSGVideoMaterial_RGB *m = static_cast(other); + return m_textureId - m->m_textureId; + } + + void updateBlending() { + setFlag(Blending, qFuzzyCompare(m_opacity, qreal(1.0)) ? false : true); + } + + void setVideoFrame(const QVideoFrame &frame) { + m_frame = frame; + } + + void bind() + { + QOpenGLFunctions *functions = QOpenGLContext::currentContext()->functions(); + + if (m_frame.isValid() && m_frame.map(QAbstractVideoBuffer::ReadOnly)) { + if (m_textureSize != m_frame.size()) { + if (!m_textureSize.isEmpty()) + glDeleteTextures(1, &m_textureId); + glGenTextures(1, &m_textureId); + m_textureSize = m_frame.size(); + } + + GLint dataType = GL_UNSIGNED_BYTE; + GLint dataFormat = GL_RGBA; + + if (m_frame.pixelFormat() == QVideoFrame::Format_RGB565) { + dataType = GL_UNSIGNED_SHORT_5_6_5; + dataFormat = GL_RGB; + } + + functions->glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, m_textureId); + glTexImage2D(GL_TEXTURE_2D, 0, dataFormat, + m_textureSize.width(), m_textureSize.height(), + 0, dataFormat, dataType, m_frame.bits()); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + m_frame.unmap(); + m_frame = QVideoFrame(); + } else { + functions->glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, m_textureId); + } + } + + QVideoFrame m_frame; + QSize m_textureSize; + QVideoSurfaceFormat m_format; + GLuint m_textureId; + qreal m_opacity; +}; + + +QSGVideoNode_RGB::QSGVideoNode_RGB(const QVideoSurfaceFormat &format) : + m_format(format) +{ + m_material = new QSGVideoMaterial_RGB(format); + setMaterial(m_material); +} + +QSGVideoNode_RGB::~QSGVideoNode_RGB() +{ +} + +void QSGVideoNode_RGB::setCurrentFrame(const QVideoFrame &frame) +{ + m_material->setVideoFrame(frame); + markDirty(DirtyMaterial); +} + +void QSGVideoMaterialShader_RGB::updateState(const RenderState &state, + QSGMaterial *newMaterial, + QSGMaterial *oldMaterial) +{ + Q_UNUSED(oldMaterial); + QSGVideoMaterial_RGB *mat = static_cast(newMaterial); + program()->setUniformValue(m_id_rgbTexture, 0); + + mat->bind(); + + if (state.isOpacityDirty()) { + mat->m_opacity = state.opacity(); + mat->updateBlending(); + program()->setUniformValue(m_id_opacity, GLfloat(mat->m_opacity)); + } + + if (state.isMatrixDirty()) + program()->setUniformValue(m_id_matrix, state.combinedMatrix()); +} diff --git a/src/imports/multimedia/qsgvideonode_rgb.h b/src/imports/multimedia/qsgvideonode_rgb.h new file mode 100644 index 00000000..cd82adc8 --- /dev/null +++ b/src/imports/multimedia/qsgvideonode_rgb.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSGVIDEONODE_RGB_H +#define QSGVIDEONODE_RGB_H + +#include "qsgvideonode_p.h" +#include + +class QSGVideoMaterial_RGB; + +class QSGVideoNode_RGB : public QSGVideoNode +{ +public: + QSGVideoNode_RGB(const QVideoSurfaceFormat &format); + ~QSGVideoNode_RGB(); + + virtual QVideoFrame::PixelFormat pixelFormat() const { + return m_format.pixelFormat(); + } + void setCurrentFrame(const QVideoFrame &frame); + +private: + QVideoSurfaceFormat m_format; + QSGVideoMaterial_RGB *m_material; + QVideoFrame m_frame; +}; + +class QSGVideoNodeFactory_RGB : public QSGVideoNodeFactory { +public: + QList supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const; + QSGVideoNode *createNode(const QVideoSurfaceFormat &format); +}; + + +#endif // QSGVIDEONODE_RGB_H diff --git a/src/imports/multimedia/qsgvideonode_rgb32.cpp b/src/imports/multimedia/qsgvideonode_rgb32.cpp deleted file mode 100644 index dbb2e8b5..00000000 --- a/src/imports/multimedia/qsgvideonode_rgb32.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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, Nokia gives you certain additional -** rights. These rights are described in the Nokia 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include "qsgvideonode_rgb32.h" - -#include - -#include -#include - -QList QSGVideoNodeFactory_RGB32::supportedPixelFormats( - QAbstractVideoBuffer::HandleType handleType) const -{ - QList formats; - - if (handleType == QAbstractVideoBuffer::NoHandle) - formats.append(QVideoFrame::Format_RGB32); - - return formats; -} - -QSGVideoNode *QSGVideoNodeFactory_RGB32::createNode(const QVideoSurfaceFormat &format) -{ - if (supportedPixelFormats(format.handleType()).contains(format.pixelFormat())) - return new QSGVideoNode_RGB32(); - - return 0; -} - - -class QSGVideoTexture_RGB32 : public QSGTexture -{ -public: - QSGVideoTexture_RGB32(); - - int textureId() const { return m_textureId; } - QSize textureSize() const { return m_size; } - bool hasAlphaChannel() const { return false; } - bool hasMipmaps() const { return false; } - - void setCurrentFrame(const QVideoFrame &frame) { m_frame = frame; } - - //QRectF textureSubRect() const; - - void bind(); - -private: - QVideoFrame m_frame; - GLuint m_textureId; - QSize m_size; -}; - -QSGVideoTexture_RGB32::QSGVideoTexture_RGB32() - : QSGTexture() - , m_textureId(0) -{ -} - -void QSGVideoTexture_RGB32::bind() -{ - if (m_frame.isValid()) { - if (m_size != m_frame.size()) { - if (m_textureId) - glDeleteTextures(1, &m_textureId); - glGenTextures(1, &m_textureId); - m_size = m_frame.size(); - } - - if (m_frame.map(QAbstractVideoBuffer::ReadOnly)) { - QOpenGLFunctions *functions = QOpenGLContext::currentContext()->functions(); - const uchar *bits = m_frame.bits(); - functions->glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, m_textureId); -#ifdef QT_OPENGL_ES - qWarning() << "RGB video doesn't work on GL ES\n"; -#else - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, - m_size.width(), m_size.height(), - 0, GL_BGRA, GL_UNSIGNED_BYTE, bits); -#endif - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - m_frame.unmap(); - } - m_frame = QVideoFrame(); - updateBindOptions(true); - } else { - glBindTexture(GL_TEXTURE_2D, m_textureId); - updateBindOptions(false); - } -} - -QSGVideoNode_RGB32::QSGVideoNode_RGB32() -{ - setMaterial(&m_material); - m_texture = new QSGVideoTexture_RGB32(); - - m_material.setTexture(m_texture); - m_material.setFiltering(QSGTexture::Linear); -} - - -void QSGVideoNode_RGB32::setCurrentFrame(const QVideoFrame &frame) -{ - m_texture->setCurrentFrame(frame); - markDirty(DirtyMaterial); -} diff --git a/src/imports/multimedia/qsgvideonode_rgb32.h b/src/imports/multimedia/qsgvideonode_rgb32.h deleted file mode 100644 index b53f38a3..00000000 --- a/src/imports/multimedia/qsgvideonode_rgb32.h +++ /dev/null @@ -1,71 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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, Nokia gives you certain additional -** rights. These rights are described in the Nokia 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSGVIDEONODE_RGB32_H -#define QSGVIDEONODE_RGB32_H - -#include "qsgvideonode_p.h" -#include - -class QSGVideoTexture_RGB32; - -class QSGVideoNode_RGB32 : public QSGVideoNode -{ -public: - QSGVideoNode_RGB32(); - - void setCurrentFrame(const QVideoFrame &frame); - - QVideoFrame::PixelFormat pixelFormat() const { return QVideoFrame::Format_RGB32; } - -private: - QSGTextureMaterial m_material; - QSGVideoTexture_RGB32 *m_texture; -}; - -class QSGVideoNodeFactory_RGB32 : public QSGVideoNodeFactory { -public: - QList supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const; - QSGVideoNode *createNode(const QVideoSurfaceFormat &format); -}; - - -#endif // QSGVIDEONODE_RGB32_H