summaryrefslogtreecommitdiffstats
path: root/src/qtmultimediaquicktools
diff options
context:
space:
mode:
Diffstat (limited to 'src/qtmultimediaquicktools')
-rw-r--r--src/qtmultimediaquicktools/qdeclarativevideooutput.cpp76
-rw-r--r--src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp132
-rw-r--r--src/qtmultimediaquicktools/qdeclarativevideooutput_render_p.h51
-rw-r--r--src/qtmultimediaquicktools/qdeclarativevideooutput_window.cpp12
-rw-r--r--src/qtmultimediaquicktools/qdeclarativevideooutput_window_p.h28
-rw-r--r--src/qtmultimediaquicktools/qsgvideonode_p.cpp14
-rw-r--r--src/qtmultimediaquicktools/qsgvideonode_rgb.cpp16
-rw-r--r--src/qtmultimediaquicktools/qsgvideonode_rgb.h19
-rw-r--r--src/qtmultimediaquicktools/qsgvideonode_texture.cpp16
-rw-r--r--src/qtmultimediaquicktools/qsgvideonode_texture.h19
-rw-r--r--src/qtmultimediaquicktools/qsgvideonode_yuv.cpp (renamed from src/qtmultimediaquicktools/qsgvideonode_i420.cpp)227
-rw-r--r--src/qtmultimediaquicktools/qsgvideonode_yuv.h (renamed from src/qtmultimediaquicktools/qsgvideonode_i420.h)37
-rw-r--r--src/qtmultimediaquicktools/qtmultimediaquicktools.pro4
13 files changed, 477 insertions, 174 deletions
diff --git a/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp b/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp
index 9a9256868..c638b3065 100644
--- a/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp
+++ b/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp
@@ -1,8 +1,8 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2015 The Qt Company Ltd.
** Copyright (C) 2012 Research In Motion
-** Contact: http://www.qt-project.org/legal
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt Toolkit.
**
@@ -11,9 +11,9 @@
** 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.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -24,8 +24,8 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
@@ -262,6 +262,12 @@ bool QDeclarativeVideoOutput::createBackend(QMediaService *service)
m_backend->updateGeometry();
}
+ if (m_backend) {
+ m_backend->clearFilters();
+ for (int i = 0; i < m_filters.count(); ++i)
+ m_backend->appendFilter(m_filters[i]);
+ }
+
return backendAvailable;
}
@@ -795,6 +801,12 @@ void QDeclarativeVideoOutput::itemChange(QQuickItem::ItemChange change,
m_backend->itemChange(change, changeData);
}
+void QDeclarativeVideoOutput::releaseResources()
+{
+ if (m_backend)
+ m_backend->releaseResources();
+}
+
void QDeclarativeVideoOutput::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
{
Q_UNUSED(newGeometry);
@@ -809,4 +821,54 @@ void QDeclarativeVideoOutput::geometryChanged(const QRectF &newGeometry, const Q
_q_updateGeometry();
}
+/*!
+ \qmlproperty list<object> QtMultimedia::VideoOutput::filters
+
+ This property holds the list of video filters that are run on the video
+ frames. The order of the filters in the list matches the order in which
+ they will be invoked on the video frames. The objects in the list must be
+ instances of a subclass of QAbstractVideoFilter.
+
+ \sa QAbstractVideoFilter
+*/
+
+QQmlListProperty<QAbstractVideoFilter> QDeclarativeVideoOutput::filters()
+{
+ return QQmlListProperty<QAbstractVideoFilter>(this, 0, filter_append, filter_count, filter_at, filter_clear);
+}
+
+void QDeclarativeVideoOutput::filter_append(QQmlListProperty<QAbstractVideoFilter> *property, QAbstractVideoFilter *value)
+{
+ QDeclarativeVideoOutput *self = static_cast<QDeclarativeVideoOutput *>(property->object);
+ self->m_filters.append(value);
+ if (self->m_backend)
+ self->m_backend->appendFilter(value);
+}
+
+int QDeclarativeVideoOutput::filter_count(QQmlListProperty<QAbstractVideoFilter> *property)
+{
+ QDeclarativeVideoOutput *self = static_cast<QDeclarativeVideoOutput *>(property->object);
+ return self->m_filters.count();
+}
+
+QAbstractVideoFilter *QDeclarativeVideoOutput::filter_at(QQmlListProperty<QAbstractVideoFilter> *property, int index)
+{
+ QDeclarativeVideoOutput *self = static_cast<QDeclarativeVideoOutput *>(property->object);
+ return self->m_filters.at(index);
+}
+
+void QDeclarativeVideoOutput::filter_clear(QQmlListProperty<QAbstractVideoFilter> *property)
+{
+ QDeclarativeVideoOutput *self = static_cast<QDeclarativeVideoOutput *>(property->object);
+ self->m_filters.clear();
+ if (self->m_backend)
+ self->m_backend->clearFilters();
+}
+
+void QDeclarativeVideoOutput::_q_invalidateSceneGraph()
+{
+ if (m_backend)
+ m_backend->invalidateSceneGraph();
+}
+
QT_END_NAMESPACE
diff --git a/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp b/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp
index 657ef1767..f4efe47e7 100644
--- a/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp
+++ b/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp
@@ -1,8 +1,8 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2015 The Qt Company Ltd.
** Copyright (C) 2012 Research In Motion
-** Contact: http://www.qt-project.org/legal
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt Toolkit.
**
@@ -11,9 +11,9 @@
** 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.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -24,8 +24,8 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
@@ -34,6 +34,7 @@
#include "qdeclarativevideooutput_render_p.h"
#include "qdeclarativevideooutput_p.h"
+#include <QtMultimedia/qabstractvideofilter.h>
#include <QtMultimedia/qvideorenderercontrol.h>
#include <QtMultimedia/qmediaservice.h>
#include <QtCore/qloggingcategory.h>
@@ -41,6 +42,8 @@
#include <private/qsgvideonode_p.h>
#include <QtGui/QOpenGLContext>
+#include <QtQuick/QQuickWindow>
+#include <QtCore/QRunnable>
QT_BEGIN_NAMESPACE
@@ -103,11 +106,79 @@ bool QDeclarativeVideoRendererBackend::init(QMediaService *service)
return false;
}
+void QDeclarativeVideoRendererBackend::appendFilter(QAbstractVideoFilter *filter)
+{
+ QMutexLocker lock(&m_frameMutex);
+ m_filters.append(Filter(filter));
+}
+
+void QDeclarativeVideoRendererBackend::clearFilters()
+{
+ QMutexLocker lock(&m_frameMutex);
+ scheduleDeleteFilterResources();
+ m_filters.clear();
+}
+
+class FilterRunnableDeleter : public QRunnable
+{
+public:
+ FilterRunnableDeleter(const QList<QVideoFilterRunnable *> &runnables) : m_runnables(runnables) { }
+ void run() Q_DECL_OVERRIDE {
+ foreach (QVideoFilterRunnable *runnable, m_runnables)
+ delete runnable;
+ }
+private:
+ QList<QVideoFilterRunnable *> m_runnables;
+};
+
+void QDeclarativeVideoRendererBackend::scheduleDeleteFilterResources()
+{
+ if (!q->window())
+ return;
+
+ QList<QVideoFilterRunnable *> runnables;
+ for (int i = 0; i < m_filters.count(); ++i) {
+ if (m_filters[i].runnable) {
+ runnables.append(m_filters[i].runnable);
+ m_filters[i].runnable = 0;
+ }
+ }
+
+ if (!runnables.isEmpty()) {
+ // Request the scenegraph to run our cleanup job on the render thread.
+ // The execution of our QRunnable may happen after the QML tree including the QAbstractVideoFilter instance is
+ // destroyed on the main thread so no references to it must be used during cleanup.
+ q->window()->scheduleRenderJob(new FilterRunnableDeleter(runnables), QQuickWindow::BeforeSynchronizingStage);
+ }
+}
+
+void QDeclarativeVideoRendererBackend::releaseResources()
+{
+ // Called on the gui thread when the window is closed or changed.
+ QMutexLocker lock(&m_frameMutex);
+ scheduleDeleteFilterResources();
+}
+
+void QDeclarativeVideoRendererBackend::invalidateSceneGraph()
+{
+ // Called on the render thread, e.g. when the context is lost.
+ QMutexLocker lock(&m_frameMutex);
+ for (int i = 0; i < m_filters.count(); ++i) {
+ if (m_filters[i].runnable) {
+ delete m_filters[i].runnable;
+ m_filters[i].runnable = 0;
+ }
+ }
+}
+
void QDeclarativeVideoRendererBackend::itemChange(QQuickItem::ItemChange change,
const QQuickItem::ItemChangeData &changeData)
{
- Q_UNUSED(change);
- Q_UNUSED(changeData);
+ if (change == QQuickItem::ItemSceneChange) {
+ if (changeData.window)
+ QObject::connect(changeData.window, SIGNAL(sceneGraphInvalidated()),
+ q, SLOT(_q_invalidateSceneGraph()), Qt::DirectConnection);
+ }
}
void QDeclarativeVideoRendererBackend::releaseSource()
@@ -216,8 +287,36 @@ QSGNode *QDeclarativeVideoRendererBackend::updatePaintNode(QSGNode *oldNode,
}
#endif
+ bool isFrameModified = false;
if (m_frameChanged) {
- if (videoNode && videoNode->pixelFormat() != m_frame.pixelFormat()) {
+ // Run the VideoFilter if there is one. This must be done before potentially changing the videonode below.
+ if (m_frame.isValid() && !m_filters.isEmpty()) {
+ const QVideoSurfaceFormat surfaceFormat = videoSurface()->surfaceFormat();
+ for (int i = 0; i < m_filters.count(); ++i) {
+ QAbstractVideoFilter *filter = m_filters[i].filter;
+ QVideoFilterRunnable *&runnable = m_filters[i].runnable;
+ if (filter && filter->isActive()) {
+ // Create the filter runnable if not yet done. Ownership is taken and is tied to this thread, on which rendering happens.
+ if (!runnable)
+ runnable = filter->createFilterRunnable();
+ if (!runnable)
+ continue;
+
+ QVideoFilterRunnable::RunFlags flags = 0;
+ if (i == m_filters.count() - 1)
+ flags |= QVideoFilterRunnable::LastInChain;
+
+ QVideoFrame newFrame = runnable->run(&m_frame, surfaceFormat, flags);
+
+ if (newFrame.isValid() && newFrame != m_frame) {
+ isFrameModified = true;
+ m_frame = newFrame;
+ }
+ }
+ }
+ }
+
+ if (videoNode && (videoNode->pixelFormat() != m_frame.pixelFormat() || videoNode->handleType() != m_frame.handleType())) {
qCDebug(qLcVideo) << "updatePaintNode: deleting old video node because frame format changed";
delete videoNode;
videoNode = 0;
@@ -231,7 +330,9 @@ QSGNode *QDeclarativeVideoRendererBackend::updatePaintNode(QSGNode *oldNode,
if (!videoNode) {
foreach (QSGVideoNodeFactoryInterface* factory, m_videoNodeFactories) {
- videoNode = factory->createNode(m_surface->surfaceFormat());
+ // Get a node that supports our frame. The surface is irrelevant, our
+ // QSGVideoItemSurface supports (logically) anything.
+ videoNode = factory->createNode(QVideoSurfaceFormat(m_frame.size(), m_frame.pixelFormat(), m_frame.handleType()));
if (videoNode) {
qCDebug(qLcVideo) << "updatePaintNode: Video node created. Handle type:" << m_frame.handleType()
<< " Supported formats for the handle by this node:"
@@ -252,7 +353,10 @@ QSGNode *QDeclarativeVideoRendererBackend::updatePaintNode(QSGNode *oldNode,
videoNode->setTexturedRectGeometry(m_renderedRect, m_sourceTextureRect,
qNormalizedOrientation(q->orientation()));
if (m_frameChanged) {
- videoNode->setCurrentFrame(m_frame);
+ QSGVideoNode::FrameFlags flags = 0;
+ if (isFrameModified)
+ flags |= QSGVideoNode::FrameFiltered;
+ videoNode->setCurrentFrame(m_frame, flags);
//don't keep the frame for more than really necessary
m_frameChanged = false;
m_frame = QVideoFrame();
@@ -340,10 +444,6 @@ void QSGVideoItemSurface::stop()
bool QSGVideoItemSurface::present(const QVideoFrame &frame)
{
- if (!frame.isValid()) {
- qWarning() << Q_FUNC_INFO << "I'm getting bad frames here...";
- return false;
- }
m_backend->present(frame);
return true;
}
diff --git a/src/qtmultimediaquicktools/qdeclarativevideooutput_render_p.h b/src/qtmultimediaquicktools/qdeclarativevideooutput_render_p.h
index dd8449fa8..cb1168ee9 100644
--- a/src/qtmultimediaquicktools/qdeclarativevideooutput_render_p.h
+++ b/src/qtmultimediaquicktools/qdeclarativevideooutput_render_p.h
@@ -1,8 +1,8 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2015 The Qt Company Ltd.
** Copyright (C) 2012 Research In Motion
-** Contact: http://www.qt-project.org/legal
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt Toolkit.
**
@@ -11,9 +11,9 @@
** 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.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -24,8 +24,8 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
@@ -36,7 +36,7 @@
#define QDECLARATIVEVIDEOOUTPUT_RENDER_P_H
#include "qdeclarativevideooutput_backend_p.h"
-#include "qsgvideonode_i420.h"
+#include "qsgvideonode_yuv.h"
#include "qsgvideonode_rgb.h"
#include "qsgvideonode_texture.h"
@@ -48,6 +48,8 @@ QT_BEGIN_NAMESPACE
class QSGVideoItemSurface;
class QVideoRendererControl;
class QOpenGLContext;
+class QAbstractVideoFilter;
+class QVideoFilterRunnable;
class QDeclarativeVideoRendererBackend : public QDeclarativeVideoBackend
{
@@ -55,14 +57,14 @@ public:
QDeclarativeVideoRendererBackend(QDeclarativeVideoOutput *parent);
~QDeclarativeVideoRendererBackend();
- bool init(QMediaService *service);
- void itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &changeData);
- void releaseSource();
- void releaseControl();
- QSize nativeSize() const;
- void updateGeometry();
- QSGNode *updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *data);
- QAbstractVideoSurface *videoSurface() const;
+ bool init(QMediaService *service) Q_DECL_OVERRIDE;
+ void itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &changeData) Q_DECL_OVERRIDE;
+ void releaseSource() Q_DECL_OVERRIDE;
+ void releaseControl() Q_DECL_OVERRIDE;
+ QSize nativeSize() const Q_DECL_OVERRIDE;
+ void updateGeometry() Q_DECL_OVERRIDE;
+ QSGNode *updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *data) Q_DECL_OVERRIDE;
+ QAbstractVideoSurface *videoSurface() const Q_DECL_OVERRIDE;
QRectF adjustedViewport() const Q_DECL_OVERRIDE;
QOpenGLContext *glContext() const;
@@ -70,19 +72,34 @@ public:
void present(const QVideoFrame &frame);
void stop();
+ void appendFilter(QAbstractVideoFilter *filter) Q_DECL_OVERRIDE;
+ void clearFilters() Q_DECL_OVERRIDE;
+ void releaseResources() Q_DECL_OVERRIDE;
+ void invalidateSceneGraph() Q_DECL_OVERRIDE;
+
private:
+ void scheduleDeleteFilterResources();
+
QPointer<QVideoRendererControl> m_rendererControl;
QList<QSGVideoNodeFactoryInterface*> m_videoNodeFactories;
QSGVideoItemSurface *m_surface;
QOpenGLContext *m_glContext;
QVideoFrame m_frame;
bool m_frameChanged;
- QSGVideoNodeFactory_I420 m_i420Factory;
+ QSGVideoNodeFactory_YUV m_i420Factory;
QSGVideoNodeFactory_RGB m_rgbFactory;
QSGVideoNodeFactory_Texture m_textureFactory;
QMutex m_frameMutex;
QRectF m_renderedRect; // Destination pixel coordinates, clipped
QRectF m_sourceTextureRect; // Source texture coordinates
+
+ struct Filter {
+ Filter() : filter(0), runnable(0) { }
+ Filter(QAbstractVideoFilter *filter) : filter(filter), runnable(0) { }
+ QAbstractVideoFilter *filter;
+ QVideoFilterRunnable *runnable;
+ };
+ QList<Filter> m_filters;
};
class QSGVideoItemSurface : public QAbstractVideoSurface
diff --git a/src/qtmultimediaquicktools/qdeclarativevideooutput_window.cpp b/src/qtmultimediaquicktools/qdeclarativevideooutput_window.cpp
index d02adc5f5..390c16d0d 100644
--- a/src/qtmultimediaquicktools/qdeclarativevideooutput_window.cpp
+++ b/src/qtmultimediaquicktools/qdeclarativevideooutput_window.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2012 Research In Motion
-** Contact: http://www.qt-project.org/legal
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt Toolkit.
**
@@ -10,9 +10,9 @@
** 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.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -23,8 +23,8 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
diff --git a/src/qtmultimediaquicktools/qdeclarativevideooutput_window_p.h b/src/qtmultimediaquicktools/qdeclarativevideooutput_window_p.h
index e31a12985..446ce52cd 100644
--- a/src/qtmultimediaquicktools/qdeclarativevideooutput_window_p.h
+++ b/src/qtmultimediaquicktools/qdeclarativevideooutput_window_p.h
@@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2012 Research In Motion
-** Contact: http://www.qt-project.org/legal
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt Toolkit.
**
@@ -10,9 +10,9 @@
** 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.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -23,8 +23,8 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
@@ -46,14 +46,14 @@ public:
QDeclarativeVideoWindowBackend(QDeclarativeVideoOutput *parent);
~QDeclarativeVideoWindowBackend();
- bool init(QMediaService *service);
- void itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &changeData);
- void releaseSource();
- void releaseControl();
- QSize nativeSize() const;
- void updateGeometry();
- QSGNode *updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *data);
- QAbstractVideoSurface *videoSurface() const;
+ bool init(QMediaService *service) Q_DECL_OVERRIDE;
+ void itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &changeData) Q_DECL_OVERRIDE;
+ void releaseSource() Q_DECL_OVERRIDE;
+ void releaseControl() Q_DECL_OVERRIDE;
+ QSize nativeSize() const Q_DECL_OVERRIDE;
+ void updateGeometry() Q_DECL_OVERRIDE;
+ QSGNode *updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *data) Q_DECL_OVERRIDE;
+ QAbstractVideoSurface *videoSurface() const Q_DECL_OVERRIDE;
QRectF adjustedViewport() const Q_DECL_OVERRIDE;
private:
diff --git a/src/qtmultimediaquicktools/qsgvideonode_p.cpp b/src/qtmultimediaquicktools/qsgvideonode_p.cpp
index c2ca9f294..0fb4239d6 100644
--- a/src/qtmultimediaquicktools/qsgvideonode_p.cpp
+++ b/src/qtmultimediaquicktools/qsgvideonode_p.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt Toolkit.
**
@@ -10,9 +10,9 @@
** 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.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -23,8 +23,8 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
diff --git a/src/qtmultimediaquicktools/qsgvideonode_rgb.cpp b/src/qtmultimediaquicktools/qsgvideonode_rgb.cpp
index 56257dab5..659dc8bdd 100644
--- a/src/qtmultimediaquicktools/qsgvideonode_rgb.cpp
+++ b/src/qtmultimediaquicktools/qsgvideonode_rgb.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt Toolkit.
**
@@ -10,9 +10,9 @@
** 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.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -23,8 +23,8 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
@@ -278,7 +278,7 @@ QSGVideoNode_RGB::~QSGVideoNode_RGB()
{
}
-void QSGVideoNode_RGB::setCurrentFrame(const QVideoFrame &frame)
+void QSGVideoNode_RGB::setCurrentFrame(const QVideoFrame &frame, FrameFlags)
{
m_material->setVideoFrame(frame);
markDirty(DirtyMaterial);
diff --git a/src/qtmultimediaquicktools/qsgvideonode_rgb.h b/src/qtmultimediaquicktools/qsgvideonode_rgb.h
index e6800ce9d..77d11b6d8 100644
--- a/src/qtmultimediaquicktools/qsgvideonode_rgb.h
+++ b/src/qtmultimediaquicktools/qsgvideonode_rgb.h
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt Toolkit.
**
@@ -10,9 +10,9 @@
** 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.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -23,8 +23,8 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
@@ -50,7 +50,10 @@ public:
virtual QVideoFrame::PixelFormat pixelFormat() const {
return m_format.pixelFormat();
}
- void setCurrentFrame(const QVideoFrame &frame);
+ QAbstractVideoBuffer::HandleType handleType() const {
+ return QAbstractVideoBuffer::NoHandle;
+ }
+ void setCurrentFrame(const QVideoFrame &frame, FrameFlags flags);
private:
QVideoSurfaceFormat m_format;
diff --git a/src/qtmultimediaquicktools/qsgvideonode_texture.cpp b/src/qtmultimediaquicktools/qsgvideonode_texture.cpp
index 3af14c0b8..3dc845c88 100644
--- a/src/qtmultimediaquicktools/qsgvideonode_texture.cpp
+++ b/src/qtmultimediaquicktools/qsgvideonode_texture.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt Toolkit.
**
@@ -10,9 +10,9 @@
** 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.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -23,8 +23,8 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
@@ -235,7 +235,7 @@ QSGVideoNode_Texture::~QSGVideoNode_Texture()
{
}
-void QSGVideoNode_Texture::setCurrentFrame(const QVideoFrame &frame)
+void QSGVideoNode_Texture::setCurrentFrame(const QVideoFrame &frame, FrameFlags)
{
m_material->setVideoFrame(frame);
markDirty(DirtyMaterial);
diff --git a/src/qtmultimediaquicktools/qsgvideonode_texture.h b/src/qtmultimediaquicktools/qsgvideonode_texture.h
index c5b84c53d..0849c574f 100644
--- a/src/qtmultimediaquicktools/qsgvideonode_texture.h
+++ b/src/qtmultimediaquicktools/qsgvideonode_texture.h
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt Toolkit.
**
@@ -10,9 +10,9 @@
** 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.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -23,8 +23,8 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
@@ -50,7 +50,10 @@ public:
virtual QVideoFrame::PixelFormat pixelFormat() const {
return m_format.pixelFormat();
}
- void setCurrentFrame(const QVideoFrame &frame);
+ QAbstractVideoBuffer::HandleType handleType() const {
+ return QAbstractVideoBuffer::GLTextureHandle;
+ }
+ void setCurrentFrame(const QVideoFrame &frame, FrameFlags flags);
private:
QVideoSurfaceFormat m_format;
diff --git a/src/qtmultimediaquicktools/qsgvideonode_i420.cpp b/src/qtmultimediaquicktools/qsgvideonode_yuv.cpp
index 17b4924d0..fc40d659a 100644
--- a/src/qtmultimediaquicktools/qsgvideonode_i420.cpp
+++ b/src/qtmultimediaquicktools/qsgvideonode_yuv.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt Toolkit.
**
@@ -10,9 +10,9 @@
** 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.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -23,14 +23,14 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
-#include "qsgvideonode_i420.h"
+#include "qsgvideonode_yuv.h"
#include <QtCore/qmutex.h>
#include <QtQuick/qsgtexturematerial.h>
#include <QtQuick/qsgmaterial.h>
@@ -40,21 +40,23 @@
QT_BEGIN_NAMESPACE
-QList<QVideoFrame::PixelFormat> QSGVideoNodeFactory_I420::supportedPixelFormats(
+QList<QVideoFrame::PixelFormat> QSGVideoNodeFactory_YUV::supportedPixelFormats(
QAbstractVideoBuffer::HandleType handleType) const
{
QList<QVideoFrame::PixelFormat> formats;
- if (handleType == QAbstractVideoBuffer::NoHandle)
- formats << QVideoFrame::Format_YUV420P << QVideoFrame::Format_YV12;
+ if (handleType == QAbstractVideoBuffer::NoHandle) {
+ formats << QVideoFrame::Format_YUV420P << QVideoFrame::Format_YV12
+ << QVideoFrame::Format_NV12 << QVideoFrame::Format_NV21;
+ }
return formats;
}
-QSGVideoNode *QSGVideoNodeFactory_I420::createNode(const QVideoSurfaceFormat &format)
+QSGVideoNode *QSGVideoNodeFactory_YUV::createNode(const QVideoSurfaceFormat &format)
{
if (supportedPixelFormats(format.handleType()).contains(format.pixelFormat()))
- return new QSGVideoNode_I420(format);
+ return new QSGVideoNode_YUV(format);
return 0;
}
@@ -136,12 +138,85 @@ protected:
int m_id_opacity;
};
+class QSGVideoMaterialShader_NV_12_21 : public QSGVideoMaterialShader_YUV420
+{
+public:
+ QSGVideoMaterialShader_NV_12_21(bool isNV21) : m_isNV21(isNV21) {
+ }
+
+ virtual void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial);
+
+protected:
+
+ virtual const char *vertexShader() const {
+ const char *shader =
+ "uniform highp mat4 qt_Matrix; \n"
+ "uniform highp float yWidth; \n"
+ "attribute highp vec4 qt_VertexPosition; \n"
+ "attribute highp vec2 qt_VertexTexCoord; \n"
+ "varying highp vec2 yTexCoord; \n"
+ "void main() { \n"
+ " yTexCoord = qt_VertexTexCoord * vec2(yWidth, 1);\n"
+ " gl_Position = qt_Matrix * qt_VertexPosition; \n"
+ "}";
+ return shader;
+ }
-class QSGVideoMaterial_YUV420 : public QSGMaterial
+ virtual const char *fragmentShader() const {
+ static const char *shaderNV12 =
+ "uniform sampler2D yTexture; \n"
+ "uniform sampler2D uvTexture; \n"
+ "uniform mediump mat4 colorMatrix; \n"
+ "uniform lowp float opacity; \n"
+ "varying highp vec2 yTexCoord; \n"
+ "void main() \n"
+ "{ \n"
+ " mediump float Y = texture2D(yTexture, yTexCoord).r; \n"
+ " mediump vec2 UV = texture2D(uvTexture, yTexCoord).ra; \n"
+ " mediump vec4 color = vec4(Y, UV.x, UV.y, 1.); \n"
+ " gl_FragColor = colorMatrix * color * opacity; \n"
+ "}";
+
+ static const char *shaderNV21 =
+ "uniform sampler2D yTexture; \n"
+ "uniform sampler2D uvTexture; \n"
+ "uniform mediump mat4 colorMatrix; \n"
+ "uniform lowp float opacity; \n"
+ "varying highp vec2 yTexCoord; \n"
+ "void main() \n"
+ "{ \n"
+ " mediump float Y = texture2D(yTexture, yTexCoord).r; \n"
+ " mediump vec2 UV = texture2D(uvTexture, yTexCoord).ar; \n"
+ " mediump vec4 color = vec4(Y, UV.x, UV.y, 1.); \n"
+ " gl_FragColor = colorMatrix * color * opacity; \n"
+ "}";
+ return m_isNV21 ? shaderNV21 : shaderNV12;
+ }
+
+ virtual void initialize() {
+ m_id_yTexture = program()->uniformLocation("yTexture");
+ m_id_uTexture = program()->uniformLocation("uvTexture");
+ m_id_matrix = program()->uniformLocation("qt_Matrix");
+ m_id_yWidth = program()->uniformLocation("yWidth");
+ m_id_colorMatrix = program()->uniformLocation("colorMatrix");
+ m_id_opacity = program()->uniformLocation("opacity");
+ }
+
+private:
+ bool m_isNV21;
+};
+
+
+class QSGVideoMaterial_YUV : public QSGMaterial
{
public:
- QSGVideoMaterial_YUV420(const QVideoSurfaceFormat &format);
- ~QSGVideoMaterial_YUV420();
+ QSGVideoMaterial_YUV(const QVideoSurfaceFormat &format);
+ ~QSGVideoMaterial_YUV();
+
+ bool isNV12_21() const {
+ const QVideoFrame::PixelFormat pf = m_format.pixelFormat();
+ return pf == QVideoFrame::Format_NV12 || pf == QVideoFrame::Format_NV21;
+ }
virtual QSGMaterialType *type() const {
static QSGMaterialType theType;
@@ -149,18 +224,25 @@ public:
}
virtual QSGMaterialShader *createShader() const {
+ const QVideoFrame::PixelFormat pf = m_format.pixelFormat();
+ if (isNV12_21())
+ return new QSGVideoMaterialShader_NV_12_21(pf == QVideoFrame::Format_NV21);
+
return new QSGVideoMaterialShader_YUV420;
}
virtual int compare(const QSGMaterial *other) const {
- const QSGVideoMaterial_YUV420 *m = static_cast<const QSGVideoMaterial_YUV420 *>(other);
+ const QSGVideoMaterial_YUV *m = static_cast<const QSGVideoMaterial_YUV *>(other);
int d = m_textureIds[0] - m->m_textureIds[0];
if (d)
return d;
- else if ((d = m_textureIds[1] - m->m_textureIds[1]) != 0)
+
+ d = m_textureIds[1] - m->m_textureIds[1];
+
+ if (m_textureIds.size() == 2 || d != 0)
return d;
- else
- return m_textureIds[2] - m->m_textureIds[2];
+
+ return m_textureIds[2] - m->m_textureIds[2];
}
void updateBlending() {
@@ -173,13 +255,12 @@ public:
}
void bind();
- void bindTexture(int id, int w, int h, const uchar *bits);
+ void bindTexture(int id, int w, int h, const uchar *bits, GLenum format);
QVideoSurfaceFormat m_format;
QSize m_textureSize;
- static const uint Num_Texture_IDs = 3;
- GLuint m_textureIds[Num_Texture_IDs];
+ QVector<GLuint> m_textureIds;
qreal m_opacity;
GLfloat m_yWidth;
@@ -190,13 +271,13 @@ public:
QMutex m_frameMutex;
};
-QSGVideoMaterial_YUV420::QSGVideoMaterial_YUV420(const QVideoSurfaceFormat &format) :
+QSGVideoMaterial_YUV::QSGVideoMaterial_YUV(const QVideoSurfaceFormat &format) :
m_format(format),
m_opacity(1.0),
m_yWidth(1.0),
m_uvWidth(1.0)
{
- memset(m_textureIds, 0, sizeof(m_textureIds));
+ m_textureIds.resize(isNV12_21() ? 2 : 3);
switch (format.yCbCrColorSpace()) {
case QVideoSurfaceFormat::YCbCr_JPEG:
@@ -225,20 +306,19 @@ QSGVideoMaterial_YUV420::QSGVideoMaterial_YUV420(const QVideoSurfaceFormat &form
setFlag(Blending, false);
}
-QSGVideoMaterial_YUV420::~QSGVideoMaterial_YUV420()
+QSGVideoMaterial_YUV::~QSGVideoMaterial_YUV()
{
if (!m_textureSize.isEmpty()) {
if (QOpenGLContext *current = QOpenGLContext::currentContext())
- current->functions()->glDeleteTextures(Num_Texture_IDs, m_textureIds);
+ current->functions()->glDeleteTextures(m_textureIds.size(), &m_textureIds[0]);
else
- qWarning() << "QSGVideoMaterial_YUV420: Cannot obtain GL context, unable to delete textures";
+ qWarning() << "QSGVideoMaterial_YUV: Cannot obtain GL context, unable to delete textures";
}
}
-void QSGVideoMaterial_YUV420::bind()
+void QSGVideoMaterial_YUV::bind()
{
QOpenGLFunctions *functions = QOpenGLContext::currentContext()->functions();
-
QMutexLocker lock(&m_frameMutex);
if (m_frame.isValid()) {
if (m_frame.map(QAbstractVideoBuffer::ReadOnly)) {
@@ -248,31 +328,43 @@ void QSGVideoMaterial_YUV420::bind()
// Frame has changed size, recreate textures...
if (m_textureSize != m_frame.size()) {
if (!m_textureSize.isEmpty())
- functions->glDeleteTextures(Num_Texture_IDs, m_textureIds);
- functions->glGenTextures(Num_Texture_IDs, m_textureIds);
+ functions->glDeleteTextures(m_textureIds.size(), &m_textureIds[0]);
+ functions->glGenTextures(m_textureIds.size(), &m_textureIds[0]);
m_textureSize = m_frame.size();
}
- const int y = 0;
- const int u = m_frame.pixelFormat() == QVideoFrame::Format_YUV420P ? 1 : 2;
- const int v = m_frame.pixelFormat() == QVideoFrame::Format_YUV420P ? 2 : 1;
-
- m_yWidth = qreal(fw) / m_frame.bytesPerLine(y);
- m_uvWidth = qreal(fw) / (2 * m_frame.bytesPerLine(u));
-
GLint previousAlignment;
functions->glGetIntegerv(GL_UNPACK_ALIGNMENT, &previousAlignment);
functions->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- functions->glActiveTexture(GL_TEXTURE1);
- bindTexture(m_textureIds[1], m_frame.bytesPerLine(u), fh / 2, m_frame.bits(u));
- functions->glActiveTexture(GL_TEXTURE2);
- bindTexture(m_textureIds[2], m_frame.bytesPerLine(v), fh / 2, m_frame.bits(v));
- functions->glActiveTexture(GL_TEXTURE0); // Finish with 0 as default texture unit
- bindTexture(m_textureIds[0], m_frame.bytesPerLine(y), fh, m_frame.bits(y));
+ if (isNV12_21()) {
+ const int y = 0;
+ const int uv = 1;
+
+ m_yWidth = qreal(fw) / m_frame.bytesPerLine(y);
+ m_uvWidth = m_yWidth;
+
+ functions->glActiveTexture(GL_TEXTURE1);
+ bindTexture(m_textureIds[1], m_frame.bytesPerLine(uv) / 2, fh / 2, m_frame.bits(uv), GL_LUMINANCE_ALPHA);
+ functions->glActiveTexture(GL_TEXTURE0); // Finish with 0 as default texture unit
+ bindTexture(m_textureIds[0], m_frame.bytesPerLine(y), fh, m_frame.bits(y), GL_LUMINANCE);
+ } else {
+ const int y = 0;
+ const int u = m_frame.pixelFormat() == QVideoFrame::Format_YUV420P ? 1 : 2;
+ const int v = m_frame.pixelFormat() == QVideoFrame::Format_YUV420P ? 2 : 1;
+
+ m_yWidth = qreal(fw) / m_frame.bytesPerLine(y);
+ m_uvWidth = qreal(fw) / (2 * m_frame.bytesPerLine(u));
+
+ functions->glActiveTexture(GL_TEXTURE1);
+ bindTexture(m_textureIds[1], m_frame.bytesPerLine(u), fh / 2, m_frame.bits(u), GL_LUMINANCE);
+ functions->glActiveTexture(GL_TEXTURE2);
+ bindTexture(m_textureIds[2], m_frame.bytesPerLine(v), fh / 2, m_frame.bits(v), GL_LUMINANCE);
+ functions->glActiveTexture(GL_TEXTURE0); // Finish with 0 as default texture unit
+ bindTexture(m_textureIds[0], m_frame.bytesPerLine(y), fh, m_frame.bits(y), GL_LUMINANCE);
+ }
functions->glPixelStorei(GL_UNPACK_ALIGNMENT, previousAlignment);
-
m_frame.unmap();
}
@@ -280,51 +372,52 @@ void QSGVideoMaterial_YUV420::bind()
} else {
functions->glActiveTexture(GL_TEXTURE1);
functions->glBindTexture(GL_TEXTURE_2D, m_textureIds[1]);
- functions->glActiveTexture(GL_TEXTURE2);
- functions->glBindTexture(GL_TEXTURE_2D, m_textureIds[2]);
+ if (!isNV12_21()) {
+ functions->glActiveTexture(GL_TEXTURE2);
+ functions->glBindTexture(GL_TEXTURE_2D, m_textureIds[2]);
+ }
functions->glActiveTexture(GL_TEXTURE0); // Finish with 0 as default texture unit
functions->glBindTexture(GL_TEXTURE_2D, m_textureIds[0]);
}
}
-void QSGVideoMaterial_YUV420::bindTexture(int id, int w, int h, const uchar *bits)
+void QSGVideoMaterial_YUV::bindTexture(int id, int w, int h, const uchar *bits, GLenum format)
{
QOpenGLFunctions *functions = QOpenGLContext::currentContext()->functions();
functions->glBindTexture(GL_TEXTURE_2D, id);
- functions->glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, bits);
+ functions->glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, GL_UNSIGNED_BYTE, bits);
functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
-QSGVideoNode_I420::QSGVideoNode_I420(const QVideoSurfaceFormat &format) :
+QSGVideoNode_YUV::QSGVideoNode_YUV(const QVideoSurfaceFormat &format) :
m_format(format)
{
setFlag(QSGNode::OwnsMaterial);
- m_material = new QSGVideoMaterial_YUV420(format);
+ m_material = new QSGVideoMaterial_YUV(format);
setMaterial(m_material);
}
-QSGVideoNode_I420::~QSGVideoNode_I420()
+QSGVideoNode_YUV::~QSGVideoNode_YUV()
{
}
-void QSGVideoNode_I420::setCurrentFrame(const QVideoFrame &frame)
+void QSGVideoNode_YUV::setCurrentFrame(const QVideoFrame &frame, FrameFlags)
{
m_material->setCurrentFrame(frame);
markDirty(DirtyMaterial);
}
-
void QSGVideoMaterialShader_YUV420::updateState(const RenderState &state,
QSGMaterial *newMaterial,
QSGMaterial *oldMaterial)
{
Q_UNUSED(oldMaterial);
- QSGVideoMaterial_YUV420 *mat = static_cast<QSGVideoMaterial_YUV420 *>(newMaterial);
+ QSGVideoMaterial_YUV *mat = static_cast<QSGVideoMaterial_YUV *>(newMaterial);
program()->setUniformValue(m_id_yTexture, 0);
program()->setUniformValue(m_id_uTexture, 1);
program()->setUniformValue(m_id_vTexture, 2);
@@ -342,4 +435,26 @@ void QSGVideoMaterialShader_YUV420::updateState(const RenderState &state,
program()->setUniformValue(m_id_matrix, state.combinedMatrix());
}
+void QSGVideoMaterialShader_NV_12_21::updateState(const RenderState &state,
+ QSGMaterial *newMaterial,
+ QSGMaterial *oldMaterial)
+{
+ Q_UNUSED(oldMaterial);
+
+ QSGVideoMaterial_YUV *mat = static_cast<QSGVideoMaterial_YUV *>(newMaterial);
+ program()->setUniformValue(m_id_yTexture, 0);
+ program()->setUniformValue(m_id_uTexture, 1);
+
+ mat->bind();
+
+ program()->setUniformValue(m_id_colorMatrix, mat->m_colorMatrix);
+ program()->setUniformValue(m_id_yWidth, mat->m_yWidth);
+ if (state.isOpacityDirty()) {
+ mat->m_opacity = state.opacity();
+ program()->setUniformValue(m_id_opacity, GLfloat(mat->m_opacity));
+ }
+ if (state.isMatrixDirty())
+ program()->setUniformValue(m_id_matrix, state.combinedMatrix());
+}
+
QT_END_NAMESPACE
diff --git a/src/qtmultimediaquicktools/qsgvideonode_i420.h b/src/qtmultimediaquicktools/qsgvideonode_yuv.h
index 06d302d80..776f0a5a2 100644
--- a/src/qtmultimediaquicktools/qsgvideonode_i420.h
+++ b/src/qtmultimediaquicktools/qsgvideonode_yuv.h
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt Toolkit.
**
@@ -10,9 +10,9 @@
** 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.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -23,42 +23,45 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
-#ifndef QSGVIDEONODE_I420_H
-#define QSGVIDEONODE_I420_H
+#ifndef QSGVIDEONODE_YUV_H
+#define QSGVIDEONODE_YUV_H
#include <private/qsgvideonode_p.h>
#include <QtMultimedia/qvideosurfaceformat.h>
QT_BEGIN_NAMESPACE
-class QSGVideoMaterial_YUV420;
-class QSGVideoNode_I420 : public QSGVideoNode
+class QSGVideoMaterial_YUV;
+class QSGVideoNode_YUV : public QSGVideoNode
{
public:
- QSGVideoNode_I420(const QVideoSurfaceFormat &format);
- ~QSGVideoNode_I420();
+ QSGVideoNode_YUV(const QVideoSurfaceFormat &format);
+ ~QSGVideoNode_YUV();
virtual QVideoFrame::PixelFormat pixelFormat() const {
return m_format.pixelFormat();
}
- void setCurrentFrame(const QVideoFrame &frame);
+ QAbstractVideoBuffer::HandleType handleType() const {
+ return QAbstractVideoBuffer::NoHandle;
+ }
+ void setCurrentFrame(const QVideoFrame &frame, FrameFlags flags);
private:
void bindTexture(int id, int unit, int w, int h, const uchar *bits);
QVideoSurfaceFormat m_format;
- QSGVideoMaterial_YUV420 *m_material;
+ QSGVideoMaterial_YUV *m_material;
};
-class QSGVideoNodeFactory_I420 : public QSGVideoNodeFactoryInterface {
+class QSGVideoNodeFactory_YUV : public QSGVideoNodeFactoryInterface {
public:
QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const;
QSGVideoNode *createNode(const QVideoSurfaceFormat &format);
@@ -66,4 +69,4 @@ public:
QT_END_NAMESPACE
-#endif // QSGVIDEONODE_I420_H
+#endif // QSGVIDEONODE_YUV_H
diff --git a/src/qtmultimediaquicktools/qtmultimediaquicktools.pro b/src/qtmultimediaquicktools/qtmultimediaquicktools.pro
index 6fd38be86..917a5ac27 100644
--- a/src/qtmultimediaquicktools/qtmultimediaquicktools.pro
+++ b/src/qtmultimediaquicktools/qtmultimediaquicktools.pro
@@ -21,7 +21,7 @@ SOURCES += \
qdeclarativevideooutput.cpp \
qdeclarativevideooutput_render.cpp \
qdeclarativevideooutput_window.cpp \
- qsgvideonode_i420.cpp \
+ qsgvideonode_yuv.cpp \
qsgvideonode_rgb.cpp \
qsgvideonode_texture.cpp
@@ -29,6 +29,6 @@ HEADERS += \
$$PRIVATE_HEADERS \
qdeclarativevideooutput_render_p.h \
qdeclarativevideooutput_window_p.h \
- qsgvideonode_i420.h \
+ qsgvideonode_yuv.h \
qsgvideonode_rgb.h \
qsgvideonode_texture.h