summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmytro Poplavskiy <dmytro.poplavskiy@nokia.com>2011-10-14 12:36:18 +1000
committerQt by Nokia <qt-info@nokia.com>2011-10-14 08:37:46 +0200
commit21fbb1d02509df805234f30d94e200a1f76fab4e (patch)
treebf129c6d1e0a24b0249ee3ae11a5f27fa7315642
parent6b25a189ca4a9d547e15ed8225025f2c1f9de352 (diff)
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 <michael.goddard@nokia.com> Reviewed-by: Jonas Rabbe <jonas.rabbe@nokia.com>
-rw-r--r--src/imports/multimedia/multimedia.pro4
-rw-r--r--src/imports/multimedia/qdeclarativevideooutput.cpp6
-rw-r--r--src/imports/multimedia/qsgvideonode_rgb.cpp275
-rw-r--r--src/imports/multimedia/qsgvideonode_rgb.h (renamed from src/imports/multimedia/qsgvideonode_rgb32.h)27
-rw-r--r--src/imports/multimedia/qsgvideonode_rgb32.cpp145
5 files changed, 294 insertions, 163 deletions
diff --git a/src/imports/multimedia/multimedia.pro b/src/imports/multimedia/multimedia.pro
index f6aa364..2043130 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 ceefc7e..9bd5eb3 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 <QtDeclarative/qsgitem.h>
@@ -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 0000000..41d778e
--- /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 <QtDeclarative/qsgtexturematerial.h>
+#include <QtDeclarative/qsgmaterial.h>
+#include <QtGui/QOpenGLContext>
+#include <QtGui/QOpenGLFunctions>
+#include <QtOpenGL/qglshaderprogram.h>
+
+QList<QVideoFrame::PixelFormat> QSGVideoNodeFactory_RGB::supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType) const
+{
+ QList<QVideoFrame::PixelFormat> 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<const QSGVideoMaterial_RGB *>(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<QSGVideoMaterial_RGB *>(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_rgb32.h b/src/imports/multimedia/qsgvideonode_rgb.h
index b53f38a..cd82adc 100644
--- a/src/imports/multimedia/qsgvideonode_rgb32.h
+++ b/src/imports/multimedia/qsgvideonode_rgb.h
@@ -39,33 +39,36 @@
**
****************************************************************************/
-#ifndef QSGVIDEONODE_RGB32_H
-#define QSGVIDEONODE_RGB32_H
+#ifndef QSGVIDEONODE_RGB_H
+#define QSGVIDEONODE_RGB_H
#include "qsgvideonode_p.h"
-#include <QtDeclarative/qsgtexturematerial.h>
+#include <QtMultimedia/qvideosurfaceformat.h>
-class QSGVideoTexture_RGB32;
+class QSGVideoMaterial_RGB;
-class QSGVideoNode_RGB32 : public QSGVideoNode
+class QSGVideoNode_RGB : public QSGVideoNode
{
public:
- QSGVideoNode_RGB32();
+ QSGVideoNode_RGB(const QVideoSurfaceFormat &format);
+ ~QSGVideoNode_RGB();
+ virtual QVideoFrame::PixelFormat pixelFormat() const {
+ return m_format.pixelFormat();
+ }
void setCurrentFrame(const QVideoFrame &frame);
- QVideoFrame::PixelFormat pixelFormat() const { return QVideoFrame::Format_RGB32; }
-
private:
- QSGTextureMaterial m_material;
- QSGVideoTexture_RGB32 *m_texture;
+ QVideoSurfaceFormat m_format;
+ QSGVideoMaterial_RGB *m_material;
+ QVideoFrame m_frame;
};
-class QSGVideoNodeFactory_RGB32 : public QSGVideoNodeFactory {
+class QSGVideoNodeFactory_RGB : public QSGVideoNodeFactory {
public:
QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const;
QSGVideoNode *createNode(const QVideoSurfaceFormat &format);
};
-#endif // QSGVIDEONODE_RGB32_H
+#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 dbb2e8b..0000000
--- 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 <QtDeclarative/qsgtexture.h>
-
-#include <QtGui/QOpenGLContext>
-#include <QtGui/QOpenGLFunctions>
-
-QList<QVideoFrame::PixelFormat> QSGVideoNodeFactory_RGB32::supportedPixelFormats(
- QAbstractVideoBuffer::HandleType handleType) const
-{
- QList<QVideoFrame::PixelFormat> 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);
-}