summaryrefslogtreecommitdiffstats
path: root/src/imports/multimedia
diff options
context:
space:
mode:
authorThomas McGuire <thomas.mcguire@kdab.com>2012-04-05 15:53:44 +0200
committerQt by Nokia <qt-info@nokia.com>2012-05-03 10:34:10 +0200
commit025f4d2ee1cdc4a68e880854584f9bef0980b630 (patch)
tree239ad793d3a2d0e7116e97a948bbc21ec96e8e13 /src/imports/multimedia
parent926049cb153b50afebad78d8da17ce964b4e0934 (diff)
Support QVideoWindowControl in the QtQuick Video element.
Change-Id: I953899a3ec92856955d36528057b0d45f9c26394 Reviewed-by: Sean Harmer <sean.harmer@kdab.com> Reviewed-by: Dmytro Poplavskiy <dmytro.poplavskiy@nokia.com>
Diffstat (limited to 'src/imports/multimedia')
-rw-r--r--src/imports/multimedia/multimedia.pro5
-rw-r--r--src/imports/multimedia/qdeclarativevideooutput.cpp306
-rw-r--r--src/imports/multimedia/qdeclarativevideooutput_backend_p.h108
-rw-r--r--src/imports/multimedia/qdeclarativevideooutput_p.h58
-rw-r--r--src/imports/multimedia/qdeclarativevideooutput_render.cpp268
-rw-r--r--src/imports/multimedia/qdeclarativevideooutput_render_p.h104
-rw-r--r--src/imports/multimedia/qdeclarativevideooutput_window.cpp135
-rw-r--r--src/imports/multimedia/qdeclarativevideooutput_window_p.h72
8 files changed, 804 insertions, 252 deletions
diff --git a/src/imports/multimedia/multimedia.pro b/src/imports/multimedia/multimedia.pro
index a70bb5671..6803f6fd6 100644
--- a/src/imports/multimedia/multimedia.pro
+++ b/src/imports/multimedia/multimedia.pro
@@ -14,6 +14,9 @@ HEADERS += \
qdeclarativeaudio_p.h \
qdeclarativemediametadata_p.h \
qdeclarativevideooutput_p.h \
+ qdeclarativevideooutput_backend_p.h \
+ qdeclarativevideooutput_render_p.h \
+ qdeclarativevideooutput_window_p.h \
qsgvideonode_i420.h \
qsgvideonode_rgb.h \
qdeclarativeradio_p.h \
@@ -35,6 +38,8 @@ SOURCES += \
multimedia.cpp \
qdeclarativeaudio.cpp \
qdeclarativevideooutput.cpp \
+ qdeclarativevideooutput_render.cpp \
+ qdeclarativevideooutput_window.cpp \
qsgvideonode_i420.cpp \
qsgvideonode_rgb.cpp \
qdeclarativeradio.cpp \
diff --git a/src/imports/multimedia/qdeclarativevideooutput.cpp b/src/imports/multimedia/qdeclarativevideooutput.cpp
index d38533363..3304ff47b 100644
--- a/src/imports/multimedia/qdeclarativevideooutput.cpp
+++ b/src/imports/multimedia/qdeclarativevideooutput.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Research In Motion
** Contact: http://www.qt-project.org/
**
** This file is part of the Qt Toolkit.
@@ -40,83 +41,15 @@
****************************************************************************/
#include "qdeclarativevideooutput_p.h"
-#include "qsgvideonode_i420.h"
-#include "qsgvideonode_rgb.h"
-
-#include <QtQuick/QQuickItem>
-
-#include <QtMultimedia/QAbstractVideoSurface>
+#include "qdeclarativevideooutput_render_p.h"
+#include "qdeclarativevideooutput_window_p.h"
+#include <QtMultimedia/qmediaobject.h>
#include <QtMultimedia/qmediaservice.h>
-#include <QtMultimedia/qvideorenderercontrol.h>
-#include <QtMultimedia/qvideosurfaceformat.h>
-#include <private/qmediapluginloader_p.h>
-
-#include <QtCore/qmetaobject.h>
//#define DEBUG_VIDEOITEM
-Q_DECLARE_METATYPE(QAbstractVideoSurface*)
QT_BEGIN_NAMESPACE
-Q_GLOBAL_STATIC_WITH_ARGS(QMediaPluginLoader, videoNodeFactoryLoader,
- (QSGVideoNodeFactoryInterface_iid, QLatin1String("video/videonode"), Qt::CaseInsensitive))
-
-class QSGVideoItemSurface : public QAbstractVideoSurface
-{
-public:
- QSGVideoItemSurface(QDeclarativeVideoOutput *item, QObject *parent = 0) :
- QAbstractVideoSurface(parent),
- m_item(item)
- {
- }
-
- ~QSGVideoItemSurface()
- {
- }
-
- QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const
- {
- QList<QVideoFrame::PixelFormat> formats;
-
- foreach (QSGVideoNodeFactoryInterface* factory, m_item->m_videoNodeFactories) {
- formats.append(factory->supportedPixelFormats(handleType));
- }
-
- return formats;
- }
-
- bool start(const QVideoSurfaceFormat &format)
- {
-#ifdef DEBUG_VIDEOITEM
- qDebug() << Q_FUNC_INFO << format;
-#endif
-
- if (!supportedPixelFormats(format.handleType()).contains(format.pixelFormat()))
- return false;
-
- return QAbstractVideoSurface::start(format);
- }
-
- void stop()
- {
- m_item->stop();
- QAbstractVideoSurface::stop();
- }
-
- virtual bool present(const QVideoFrame &frame)
- {
- if (!frame.isValid()) {
- qWarning() << Q_FUNC_INFO << "I'm getting bad frames here...";
- return false;
- }
- m_item->present(frame);
- return true;
- }
-
-private:
- QDeclarativeVideoOutput *m_item;
-};
-
/*!
\qmlclass VideoOutput QDeclarativeVideoOutput
\brief The VideoOutput element allows you to render video or camera viewfinder.
@@ -155,6 +88,17 @@ private:
For a description of stretched uniformly scaled presentation, see the \l fillMode property
description.
+ The VideoOutput item works with backends that support either QVideoRendererControl or
+ QVideoWindowControl. If the backend only supports QVideoWindowControl, the video is rendered
+ onto an overlay window that is layered on top of the QtQuick window. Due to the nature of the
+ video overlays, certain features are not available for these kind of backends:
+ \list
+ \li Some transformations like rotations
+ \li Having other QtQuick items on top of the VideoOutput item
+ \endlist
+ Most backends however do support QVideoRendererControl and therefore don't have the limitations
+ listed above.
+
\sa MediaPlayer, Camera
\section1 Screen Saver
@@ -185,32 +129,13 @@ QDeclarativeVideoOutput::QDeclarativeVideoOutput(QQuickItem *parent) :
m_orientation(0)
{
setFlag(ItemHasContents, true);
- m_surface = new QSGVideoItemSurface(this);
- connect(m_surface, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)),
- this, SLOT(_q_updateNativeSize(QVideoSurfaceFormat)), Qt::QueuedConnection);
-
- foreach (QObject *instance, videoNodeFactoryLoader()->instances(QSGVideoNodeFactoryPluginKey)) {
- QSGVideoNodeFactoryInterface* plugin = qobject_cast<QSGVideoNodeFactoryInterface*>(instance);
- if (plugin) {
- m_videoNodeFactories.append(plugin);
- }
- }
-
- // Append existing node factories as fallback if we have no plugins
- m_videoNodeFactories.append(&m_i420Factory);
- m_videoNodeFactories.append(&m_rgbFactory);
}
QDeclarativeVideoOutput::~QDeclarativeVideoOutput()
{
- if (m_source && m_sourceType == VideoSurfaceSource) {
- if (m_source.data()->property("videoSurface").value<QAbstractVideoSurface*>() == m_surface)
- m_source.data()->setProperty("videoSurface", QVariant::fromValue<QAbstractVideoSurface*>(0));
- }
-
+ m_backend.reset();
m_source.clear();
_q_updateMediaObject();
- delete m_surface;
}
/*!
@@ -238,12 +163,8 @@ void QDeclarativeVideoOutput::setSource(QObject *source)
if (m_source && m_sourceType == MediaObjectSource)
disconnect(m_source.data(), 0, this, SLOT(_q_updateMediaObject()));
- if (m_source && m_sourceType == VideoSurfaceSource) {
- if (m_source.data()->property("videoSurface").value<QAbstractVideoSurface*>() == m_surface)
- m_source.data()->setProperty("videoSurface", QVariant::fromValue<QAbstractVideoSurface*>(0));
- }
-
- m_surface->stop();
+ if (m_backend)
+ m_backend->releaseSource();
m_source = source;
@@ -263,7 +184,14 @@ void QDeclarativeVideoOutput::setSource(QObject *source)
}
m_sourceType = MediaObjectSource;
} else if (metaObject->indexOfProperty("videoSurface") != -1) {
- m_source.data()->setProperty("videoSurface", QVariant::fromValue<QAbstractVideoSurface*>(m_surface));
+ // Make sure our backend is a QDeclarativeVideoRendererBackend
+ m_backend.reset();
+ createBackend(0);
+ Q_ASSERT(m_backend && dynamic_cast<QDeclarativeVideoRendererBackend *>(m_backend.data()));
+ QAbstractVideoSurface * const surface = m_backend->videoSurface();
+ Q_ASSERT(surface);
+ m_source.data()->setProperty("videoSurface",
+ QVariant::fromValue<QAbstractVideoSurface*>(surface));
m_sourceType = VideoSurfaceSource;
} else {
m_sourceType = NoSource;
@@ -276,6 +204,29 @@ void QDeclarativeVideoOutput::setSource(QObject *source)
emit sourceChanged();
}
+bool QDeclarativeVideoOutput::createBackend(QMediaService *service)
+{
+ bool backendAvailable = false;
+ m_backend.reset(new QDeclarativeVideoRendererBackend(this));
+ if (m_backend->init(service))
+ backendAvailable = true;
+
+ // QDeclarativeVideoWindowBackend only works when there is a service with a QVideoWindowControl.
+ // Without service, the QDeclarativeVideoRendererBackend should always work.
+ if (!backendAvailable) {
+ Q_ASSERT(service);
+ m_backend.reset(new QDeclarativeVideoWindowBackend(this));
+ if (m_backend->init(service))
+ backendAvailable = true;
+ }
+
+ if (!backendAvailable) {
+ qWarning() << Q_FUNC_INFO << "Media service has neither renderer nor window control available.";
+ m_backend.reset();
+ }
+ return backendAvailable;
+}
+
void QDeclarativeVideoOutput::_q_updateMediaObject()
{
QMediaObject *mediaObject = 0;
@@ -290,66 +241,22 @@ void QDeclarativeVideoOutput::_q_updateMediaObject()
if (m_mediaObject.data() == mediaObject)
return;
- if (m_rendererControl) {
- m_rendererControl.data()->setSurface(0);
- m_service.data()->releaseControl(m_rendererControl.data());
- }
+ if (m_sourceType != VideoSurfaceSource)
+ m_backend.reset();
- m_mediaObject = mediaObject;
m_mediaObject.clear();
m_service.clear();
- m_rendererControl.clear();
if (mediaObject) {
if (QMediaService *service = mediaObject->service()) {
- if (QMediaControl *control = service->requestControl(QVideoRendererControl_iid)) {
- if ((m_rendererControl = qobject_cast<QVideoRendererControl *>(control))) {
- m_service = service;
- m_mediaObject = mediaObject;
- m_rendererControl.data()->setSurface(m_surface);
- } else {
- qWarning() << Q_FUNC_INFO << "Media service has no renderer control available";
- service->releaseControl(control);
- }
+ if (createBackend(service)) {
+ m_service = service;
+ m_mediaObject = mediaObject;
}
}
}
}
-void QDeclarativeVideoOutput::present(const QVideoFrame &frame)
-{
- m_frameMutex.lock();
- m_frame = frame;
- m_frameMutex.unlock();
-
- update();
-}
-
-void QDeclarativeVideoOutput::stop()
-{
- present(QVideoFrame());
-}
-
-/*
- * Helper - returns true if the given orientation has the same aspect as the default (e.g. 180*n)
- */
-static inline bool qIsDefaultAspect(int o)
-{
- return (o % 180) == 0;
-}
-
-/*
- * Return the orientation normailized to 0-359
- */
-static inline int qNormalizedOrientation(int o)
-{
- // Negative orientations give negative results
- int o2 = o % 360;
- if (o2 < 0)
- o2 += 360;
- return o2;
-}
-
/*!
\qmlproperty enumeration QtMultimedia5::VideoOutput::fillMode
@@ -381,9 +288,12 @@ void QDeclarativeVideoOutput::setFillMode(FillMode mode)
emit fillModeChanged(mode);
}
-void QDeclarativeVideoOutput::_q_updateNativeSize(const QVideoSurfaceFormat &format)
+void QDeclarativeVideoOutput::_q_updateNativeSize()
{
- QSize size = format.sizeHint();
+ if (!m_backend)
+ return;
+
+ QSize size = m_backend->nativeSize();
if (!qIsDefaultAspect(m_orientation)) {
size.transpose();
}
@@ -403,57 +313,35 @@ void QDeclarativeVideoOutput::_q_updateNativeSize(const QVideoSurfaceFormat &for
/* Based on fill mode and our size, figure out the source/dest rects */
void QDeclarativeVideoOutput::_q_updateGeometry()
{
- QRectF rect(0, 0, width(), height());
+ const QRectF rect(0, 0, width(), height());
+ const QRectF absoluteRect(x(), y(), width(), height());
- if (!m_geometryDirty && m_lastSize == rect)
+ if (!m_geometryDirty && m_lastRect == absoluteRect)
return;
QRectF oldContentRect(m_contentRect);
m_geometryDirty = false;
- m_lastSize = rect;
+ m_lastRect = absoluteRect;
if (m_nativeSize.isEmpty()) {
//this is necessary for item to receive the
//first paint event and configure video surface.
- m_renderedRect = rect;
m_contentRect = rect;
- m_sourceTextureRect = QRectF(0, 0, 1, 1);
} else if (m_fillMode == Stretch) {
- m_renderedRect = rect;
m_contentRect = rect;
- m_sourceTextureRect = QRectF(0, 0, 1, 1);
- } else if (m_fillMode == PreserveAspectFit) {
- QSizeF size = m_nativeSize;
- size.scale(rect.size(), Qt::KeepAspectRatio);
-
- m_renderedRect = QRectF(0, 0, size.width(), size.height());
- m_renderedRect.moveCenter(rect.center());
- m_contentRect = m_renderedRect;
-
- m_sourceTextureRect = QRectF(0, 0, 1, 1);
- } else if (m_fillMode == PreserveAspectCrop) {
- m_renderedRect = rect;
-
+ } else if (m_fillMode == PreserveAspectFit || m_fillMode == PreserveAspectCrop) {
QSizeF scaled = m_nativeSize;
- scaled.scale(rect.size(), Qt::KeepAspectRatioByExpanding);
+ scaled.scale(rect.size(), m_fillMode == PreserveAspectFit ?
+ Qt::KeepAspectRatio : Qt::KeepAspectRatioByExpanding);
m_contentRect = QRectF(QPointF(), scaled);
m_contentRect.moveCenter(rect.center());
-
- if (qIsDefaultAspect(m_orientation)) {
- m_sourceTextureRect = QRectF((-m_contentRect.left()) / m_contentRect.width(),
- (-m_contentRect.top()) / m_contentRect.height(),
- rect.width() / m_contentRect.width(),
- rect.height() / m_contentRect.height());
- } else {
- m_sourceTextureRect = QRectF((-m_contentRect.top()) / m_contentRect.height(),
- (-m_contentRect.left()) / m_contentRect.width(),
- rect.height() / m_contentRect.height(),
- rect.width() / m_contentRect.width());
- }
}
+ if (m_backend)
+ m_backend->updateGeometry();
+
if (m_contentRect != oldContentRect)
emit contentRectChanged();
}
@@ -707,6 +595,11 @@ QRectF QDeclarativeVideoOutput::mapRectToSourceNormalized(const QRectF &rectangl
mapPointToSourceNormalized(rectangle.bottomRight())).normalized();
}
+QDeclarativeVideoOutput::SourceType QDeclarativeVideoOutput::sourceType() const
+{
+ return m_sourceType;
+}
+
/*!
\qmlmethod QPointF QtMultimedia5::VideoOutput::mapPointToItem(const QPointF &point) const
@@ -747,44 +640,33 @@ QRectF QDeclarativeVideoOutput::mapRectToItem(const QRectF &rectangle) const
mapPointToItem(rectangle.bottomRight())).normalized();
}
-
-QSGNode *QDeclarativeVideoOutput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
+QSGNode *QDeclarativeVideoOutput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
{
- QSGVideoNode *videoNode = static_cast<QSGVideoNode *>(oldNode);
-
- QMutexLocker lock(&m_frameMutex);
-
- if (videoNode && videoNode->pixelFormat() != m_frame.pixelFormat()) {
-#ifdef DEBUG_VIDEOITEM
- qDebug() << "updatePaintNode: deleting old video node because frame format changed...";
-#endif
- delete videoNode;
- videoNode = 0;
- }
+ _q_updateGeometry();
- if (!m_frame.isValid()) {
-#ifdef DEBUG_VIDEOITEM
- qDebug() << "updatePaintNode: no frames yet... aborting...";
-#endif
+ if (!m_backend)
return 0;
- }
- if (videoNode == 0) {
- foreach (QSGVideoNodeFactoryInterface* factory, m_videoNodeFactories) {
- videoNode = factory->createNode(m_surface->surfaceFormat());
- if (videoNode)
- break;
- }
- }
+ return m_backend->updatePaintNode(oldNode, data);
+}
- if (videoNode == 0)
- return 0;
+void QDeclarativeVideoOutput::itemChange(QQuickItem::ItemChange change,
+ const QQuickItem::ItemChangeData &changeData)
+{
+ if (m_backend)
+ m_backend->itemChange(change, changeData);
+}
+
+void QDeclarativeVideoOutput::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ Q_UNUSED(newGeometry);
+ Q_UNUSED(oldGeometry);
+ // Explicitly listen to geometry changes here. This is needed since changing the position does
+ // not trigger a call to updatePaintNode().
+ // We need to react to position changes though, as the window backened's display rect gets
+ // changed in that situation.
_q_updateGeometry();
- // Negative rotations need lots of %360
- videoNode->setTexturedRectGeometry(m_renderedRect, m_sourceTextureRect, qNormalizedOrientation(m_orientation));
- videoNode->setCurrentFrame(m_frame);
- return videoNode;
}
QT_END_NAMESPACE
diff --git a/src/imports/multimedia/qdeclarativevideooutput_backend_p.h b/src/imports/multimedia/qdeclarativevideooutput_backend_p.h
new file mode 100644
index 000000000..f094635f7
--- /dev/null
+++ b/src/imports/multimedia/qdeclarativevideooutput_backend_p.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Research In Motion
+** Contact: http://www.qt-project.org/
+**
+** 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 QDECLARATIVEVIDEOOUTPUT_BACKEND_P_H
+#define QDECLARATIVEVIDEOOUTPUT_BACKEND_P_H
+
+#include <QtCore/qpointer.h>
+#include <QtCore/qsize.h>
+#include <QtQuick/qquickitem.h>
+#include <QtQuick/qsgnode.h>
+
+QT_BEGIN_NAMESPACE
+
+class QAbstractVideoSurface;
+class QDeclarativeVideoOutput;
+class QMediaService;
+
+class QDeclarativeVideoBackend
+{
+public:
+ explicit QDeclarativeVideoBackend(QDeclarativeVideoOutput *parent)
+ : q(parent)
+ {}
+
+ virtual ~QDeclarativeVideoBackend()
+ {}
+
+ virtual bool init(QMediaService *service) = 0;
+ virtual void releaseSource() = 0;
+ virtual void releaseControl() = 0;
+ virtual void itemChange(QQuickItem::ItemChange change,
+ const QQuickItem::ItemChangeData &changeData) = 0;
+ virtual QSize nativeSize() const = 0;
+ virtual void updateGeometry() = 0;
+ virtual QSGNode *updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *data) = 0;
+ virtual QAbstractVideoSurface *videoSurface() const = 0;
+
+protected:
+ QDeclarativeVideoOutput *q;
+ QPointer<QMediaService> m_service;
+};
+
+/*
+ * Helper - returns true if the given orientation has the same aspect as the default (e.g. 180*n)
+ */
+namespace {
+
+inline bool qIsDefaultAspect(int o)
+{
+ return (o % 180) == 0;
+}
+
+/*
+ * Return the orientation normalized to 0-359
+ */
+inline int qNormalizedOrientation(int o)
+{
+ // Negative orientations give negative results
+ int o2 = o % 360;
+ if (o2 < 0)
+ o2 += 360;
+ return o2;
+}
+
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/imports/multimedia/qdeclarativevideooutput_p.h b/src/imports/multimedia/qdeclarativevideooutput_p.h
index a0ee1460a..39cb549b7 100644
--- a/src/imports/multimedia/qdeclarativevideooutput_p.h
+++ b/src/imports/multimedia/qdeclarativevideooutput_p.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Research In Motion
** Contact: http://www.qt-project.org/
**
** This file is part of the Qt Toolkit.
@@ -42,29 +43,15 @@
#ifndef QDECLARATIVEVIDEOOUTPUT_P_H
#define QDECLARATIVEVIDEOOUTPUT_P_H
-#include <QtCore/QRectF>
-
-#include <QtQuick/QQuickItem>
-
-#include <QtMultimedia/qvideoframe.h>
-#include <QtMultimedia/qmediaobject.h>
-
+#include <QtCore/qrect.h>
#include <QtCore/qsharedpointer.h>
-#include <QtCore/qmutex.h>
-
-#include <private/qsgvideonode_p.h>
-
-
-#include "qsgvideonode_i420.h"
-#include "qsgvideonode_rgb.h"
-
+#include <QtQuick/qquickitem.h>
QT_BEGIN_NAMESPACE
-class QSGVideoItemSurface;
-class QVideoRendererControl;
+class QMediaObject;
class QMediaService;
-class QVideoSurfaceFormat;
+class QDeclarativeVideoBackend;
class QDeclarativeVideoOutput : public QQuickItem
{
@@ -109,6 +96,13 @@ public:
Q_INVOKABLE QPointF mapPointToSourceNormalized(const QPointF &point) const;
Q_INVOKABLE QRectF mapRectToSourceNormalized(const QRectF &rectangle) const;
+ enum SourceType {
+ NoSource,
+ MediaObjectSource,
+ VideoSurfaceSource
+ };
+ SourceType sourceType() const;
+
Q_SIGNALS:
void sourceChanged();
void fillModeChanged(QDeclarativeVideoOutput::FillMode);
@@ -118,48 +112,32 @@ Q_SIGNALS:
protected:
QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
+ void itemChange(ItemChange change, const ItemChangeData &changeData);
+ void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
private Q_SLOTS:
void _q_updateMediaObject();
- void _q_updateNativeSize(const QVideoSurfaceFormat&);
+ void _q_updateNativeSize();
void _q_updateGeometry();
private:
- enum SourceType {
- NoSource,
- MediaObjectSource,
- VideoSurfaceSource
- };
-
- void present(const QVideoFrame &frame);
- void stop();
-
- friend class QSGVideoItemSurface;
+ bool createBackend(QMediaService *service);
SourceType m_sourceType;
QWeakPointer<QObject> m_source;
QWeakPointer<QMediaObject> m_mediaObject;
QWeakPointer<QMediaService> m_service;
- QWeakPointer<QVideoRendererControl> m_rendererControl;
- QList<QSGVideoNodeFactoryInterface*> m_videoNodeFactories;
- QSGVideoItemSurface *m_surface;
- QVideoFrame m_frame;
FillMode m_fillMode;
QSize m_nativeSize;
- QSGVideoNodeFactory_I420 m_i420Factory;
- QSGVideoNodeFactory_RGB m_rgbFactory;
-
bool m_geometryDirty;
- QRectF m_lastSize; // Cache of last size to avoid recalculating geometry
- QRectF m_renderedRect; // Destination pixel coordinates, clipped
+ QRectF m_lastRect; // Cache of last rect to avoid recalculating geometry
QRectF m_contentRect; // Destination pixel coordinates, unclipped
- QRectF m_sourceTextureRect; // Source texture coordinates
int m_orientation;
- QMutex m_frameMutex;
+ QScopedPointer<QDeclarativeVideoBackend> m_backend;
};
QT_END_NAMESPACE
diff --git a/src/imports/multimedia/qdeclarativevideooutput_render.cpp b/src/imports/multimedia/qdeclarativevideooutput_render.cpp
new file mode 100644
index 000000000..8455794c2
--- /dev/null
+++ b/src/imports/multimedia/qdeclarativevideooutput_render.cpp
@@ -0,0 +1,268 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Research In Motion
+** Contact: http://www.qt-project.org/
+**
+** 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 "qdeclarativevideooutput_render_p.h"
+#include "qdeclarativevideooutput_p.h"
+#include <QtMultimedia/qvideorenderercontrol.h>
+#include <QtMultimedia/qmediaservice.h>
+#include <private/qmediapluginloader_p.h>
+#include <private/qsgvideonode_p.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_GLOBAL_STATIC_WITH_ARGS(QMediaPluginLoader, videoNodeFactoryLoader,
+ (QSGVideoNodeFactoryInterface_iid, QLatin1String("video/videonode"), Qt::CaseInsensitive))
+
+QDeclarativeVideoRendererBackend::QDeclarativeVideoRendererBackend(QDeclarativeVideoOutput *parent)
+ : QDeclarativeVideoBackend(parent)
+{
+ m_surface = new QSGVideoItemSurface(this);
+ QObject::connect(m_surface, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)),
+ q, SLOT(_q_updateNativeSize()), Qt::QueuedConnection);
+
+ foreach (QObject *instance, videoNodeFactoryLoader()->instances(QSGVideoNodeFactoryPluginKey)) {
+ QSGVideoNodeFactoryInterface* plugin = qobject_cast<QSGVideoNodeFactoryInterface*>(instance);
+ if (plugin)
+ m_videoNodeFactories.append(plugin);
+ }
+
+ // Append existing node factories as fallback if we have no plugins
+ m_videoNodeFactories.append(&m_i420Factory);
+ m_videoNodeFactories.append(&m_rgbFactory);
+}
+
+QDeclarativeVideoRendererBackend::~QDeclarativeVideoRendererBackend()
+{
+ releaseSource();
+ releaseControl();
+ delete m_surface;
+}
+
+bool QDeclarativeVideoRendererBackend::init(QMediaService *service)
+{
+ // When there is no service, the source is an object with a "videoSurface" property, which
+ // doesn't require a QVideoRendererControl and therefore always works
+ if (!service)
+ return true;
+
+ if (QMediaControl *control = service->requestControl(QVideoRendererControl_iid)) {
+ if ((m_rendererControl = qobject_cast<QVideoRendererControl *>(control))) {
+ m_rendererControl->setSurface(m_surface);
+ m_service = service;
+ return true;
+ }
+ }
+ return false;
+}
+
+void QDeclarativeVideoRendererBackend::itemChange(QQuickItem::ItemChange change,
+ const QQuickItem::ItemChangeData &changeData)
+{
+ Q_UNUSED(change);
+ Q_UNUSED(changeData);
+}
+
+void QDeclarativeVideoRendererBackend::releaseSource()
+{
+ if (q->source() && q->sourceType() == QDeclarativeVideoOutput::VideoSurfaceSource) {
+ if (q->source()->property("videoSurface").value<QAbstractVideoSurface*>() == m_surface)
+ q->source()->setProperty("videoSurface", QVariant::fromValue<QAbstractVideoSurface*>(0));
+ }
+
+ m_surface->stop();
+}
+
+void QDeclarativeVideoRendererBackend::releaseControl()
+{
+ if (m_rendererControl) {
+ m_rendererControl->setSurface(0);
+ if (m_service)
+ m_service->releaseControl(m_rendererControl);
+ m_rendererControl = 0;
+ }
+}
+
+QSize QDeclarativeVideoRendererBackend::nativeSize() const
+{
+ return m_surface->surfaceFormat().sizeHint();
+}
+
+void QDeclarativeVideoRendererBackend::updateGeometry()
+{
+ const QRectF rect(0, 0, q->width(), q->height());
+ if (nativeSize().isEmpty()) {
+ m_renderedRect = rect;
+ m_sourceTextureRect = QRectF(0, 0, 1, 1);
+ } else if (q->fillMode() == QDeclarativeVideoOutput::Stretch) {
+ m_renderedRect = rect;
+ m_sourceTextureRect = QRectF(0, 0, 1, 1);
+ } else if (q->fillMode() == QDeclarativeVideoOutput::PreserveAspectFit) {
+ m_sourceTextureRect = QRectF(0, 0, 1, 1);
+ m_renderedRect = q->contentRect();
+ } else if (q->fillMode() == QDeclarativeVideoOutput::PreserveAspectCrop) {
+ m_renderedRect = rect;
+ const qreal contentHeight = q->contentRect().height();
+ const qreal contentWidth = q->contentRect().width();
+ if (qIsDefaultAspect(q->orientation())) {
+ m_sourceTextureRect = QRectF(-q->contentRect().left() / contentWidth,
+ -q->contentRect().top() / contentHeight,
+ rect.width() / contentWidth,
+ rect.height() / contentHeight);
+ } else {
+ m_sourceTextureRect = QRectF(-q->contentRect().top() / contentHeight,
+ -q->contentRect().left() / contentWidth,
+ rect.height() / contentHeight,
+ rect.width() / contentWidth);
+ }
+ }
+}
+
+QSGNode *QDeclarativeVideoRendererBackend::updatePaintNode(QSGNode *oldNode,
+ QQuickItem::UpdatePaintNodeData *data)
+{
+ Q_UNUSED(data);
+ QSGVideoNode *videoNode = static_cast<QSGVideoNode *>(oldNode);
+
+ QMutexLocker lock(&m_frameMutex);
+
+ if (videoNode && videoNode->pixelFormat() != m_frame.pixelFormat()) {
+#ifdef DEBUG_VIDEOITEM
+ qDebug() << "updatePaintNode: deleting old video node because frame format changed...";
+#endif
+ delete videoNode;
+ videoNode = 0;
+ }
+
+ if (!m_frame.isValid()) {
+#ifdef DEBUG_VIDEOITEM
+ qDebug() << "updatePaintNode: no frames yet... aborting...";
+#endif
+ return 0;
+ }
+
+ if (!videoNode) {
+ foreach (QSGVideoNodeFactoryInterface* factory, m_videoNodeFactories) {
+ videoNode = factory->createNode(m_surface->surfaceFormat());
+ if (videoNode)
+ break;
+ }
+ }
+
+ if (!videoNode)
+ return 0;
+
+ // Negative rotations need lots of %360
+ videoNode->setTexturedRectGeometry(m_renderedRect, m_sourceTextureRect,
+ qNormalizedOrientation(q->orientation()));
+ videoNode->setCurrentFrame(m_frame);
+ return videoNode;
+}
+
+QAbstractVideoSurface *QDeclarativeVideoRendererBackend::videoSurface() const
+{
+ return m_surface;
+}
+
+void QDeclarativeVideoRendererBackend::present(const QVideoFrame &frame)
+{
+ m_frameMutex.lock();
+ m_frame = frame;
+ m_frameMutex.unlock();
+
+ q->update();
+}
+
+void QDeclarativeVideoRendererBackend::stop()
+{
+ present(QVideoFrame());
+}
+
+QSGVideoItemSurface::QSGVideoItemSurface(QDeclarativeVideoRendererBackend *backend, QObject *parent)
+ : QAbstractVideoSurface(parent),
+ m_backend(backend)
+{
+}
+
+QSGVideoItemSurface::~QSGVideoItemSurface()
+{
+}
+
+QList<QVideoFrame::PixelFormat> QSGVideoItemSurface::supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType) const
+{
+ QList<QVideoFrame::PixelFormat> formats;
+
+ foreach (QSGVideoNodeFactoryInterface* factory, m_backend->m_videoNodeFactories)
+ formats.append(factory->supportedPixelFormats(handleType));
+
+ return formats;
+}
+
+bool QSGVideoItemSurface::start(const QVideoSurfaceFormat &format)
+{
+#ifdef DEBUG_VIDEOITEM
+ qDebug() << Q_FUNC_INFO << format;
+#endif
+
+ if (!supportedPixelFormats(format.handleType()).contains(format.pixelFormat()))
+ return false;
+
+ return QAbstractVideoSurface::start(format);
+}
+
+void QSGVideoItemSurface::stop()
+{
+ m_backend->stop();
+ QAbstractVideoSurface::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;
+}
+
+QT_END_NAMESPACE
diff --git a/src/imports/multimedia/qdeclarativevideooutput_render_p.h b/src/imports/multimedia/qdeclarativevideooutput_render_p.h
new file mode 100644
index 000000000..e717ddb1d
--- /dev/null
+++ b/src/imports/multimedia/qdeclarativevideooutput_render_p.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Research In Motion
+** Contact: http://www.qt-project.org/
+**
+** 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 QDECLARATIVEVIDEOOUTPUT_RENDER_P_H
+#define QDECLARATIVEVIDEOOUTPUT_RENDER_P_H
+
+#include "qdeclarativevideooutput_backend_p.h"
+#include "qsgvideonode_i420.h"
+#include "qsgvideonode_rgb.h"
+#include <QtCore/qmutex.h>
+#include <QtMultimedia/qabstractvideosurface.h>
+
+QT_BEGIN_NAMESPACE
+
+class QSGVideoItemSurface;
+class QVideoRendererControl;
+
+class QDeclarativeVideoRendererBackend : public QDeclarativeVideoBackend
+{
+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;
+
+ friend class QSGVideoItemSurface;
+ void present(const QVideoFrame &frame);
+ void stop();
+
+private:
+ QPointer<QVideoRendererControl> m_rendererControl;
+ QList<QSGVideoNodeFactoryInterface*> m_videoNodeFactories;
+ QSGVideoItemSurface *m_surface;
+ QVideoFrame m_frame;
+ QSGVideoNodeFactory_I420 m_i420Factory;
+ QSGVideoNodeFactory_RGB m_rgbFactory;
+ QMutex m_frameMutex;
+ QRectF m_renderedRect; // Destination pixel coordinates, clipped
+ QRectF m_sourceTextureRect; // Source texture coordinates
+};
+
+class QSGVideoItemSurface : public QAbstractVideoSurface
+{
+public:
+ explicit QSGVideoItemSurface(QDeclarativeVideoRendererBackend *backend, QObject *parent = 0);
+ ~QSGVideoItemSurface();
+ QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const;
+ bool start(const QVideoSurfaceFormat &format);
+ void stop();
+ bool present(const QVideoFrame &frame);
+
+private:
+ QDeclarativeVideoRendererBackend *m_backend;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/imports/multimedia/qdeclarativevideooutput_window.cpp b/src/imports/multimedia/qdeclarativevideooutput_window.cpp
new file mode 100644
index 000000000..91512d734
--- /dev/null
+++ b/src/imports/multimedia/qdeclarativevideooutput_window.cpp
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Research In Motion
+** Contact: http://www.qt-project.org/
+**
+** 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 "qdeclarativevideooutput_window_p.h"
+#include "qdeclarativevideooutput_p.h"
+#include <QtQuick/qquickcanvas.h>
+#include <QtMultimedia/qmediaservice.h>
+#include <QtMultimedia/qvideowindowcontrol.h>
+
+QT_BEGIN_NAMESPACE
+
+QDeclarativeVideoWindowBackend::QDeclarativeVideoWindowBackend(QDeclarativeVideoOutput *parent)
+ : QDeclarativeVideoBackend(parent)
+{
+}
+
+QDeclarativeVideoWindowBackend::~QDeclarativeVideoWindowBackend()
+{
+ releaseSource();
+ releaseControl();
+}
+
+bool QDeclarativeVideoWindowBackend::init(QMediaService *service)
+{
+ if (QMediaControl *control = service->requestControl(QVideoWindowControl_iid)) {
+ if ((m_videoWindowControl = qobject_cast<QVideoWindowControl *>(control))) {
+ if (q->canvas())
+ m_videoWindowControl->setWinId(q->canvas()->winId());
+ m_service = service;
+ QObject::connect(m_videoWindowControl.data(), SIGNAL(nativeSizeChanged()),
+ q, SLOT(_q_updateNativeSize()));
+ return true;
+ }
+ }
+ return false;
+}
+
+void QDeclarativeVideoWindowBackend::itemChange(QQuickItem::ItemChange change,
+ const QQuickItem::ItemChangeData &changeData)
+{
+ if (change == QQuickItem::ItemSceneChange && m_videoWindowControl) {
+ if (changeData.canvas)
+ m_videoWindowControl->setWinId(changeData.canvas->winId());
+ else
+ m_videoWindowControl->setWinId(0);
+ }
+}
+
+void QDeclarativeVideoWindowBackend::releaseSource()
+{
+}
+
+void QDeclarativeVideoWindowBackend::releaseControl()
+{
+ if (m_videoWindowControl) {
+ m_videoWindowControl->setWinId(0);
+ if (m_service)
+ m_service->releaseControl(m_videoWindowControl);
+ m_videoWindowControl = 0;
+ }
+}
+
+QSize QDeclarativeVideoWindowBackend::nativeSize() const
+{
+ return m_videoWindowControl->nativeSize();
+}
+
+void QDeclarativeVideoWindowBackend::updateGeometry()
+{
+ switch (q->fillMode()) {
+ case QDeclarativeVideoOutput::PreserveAspectFit:
+ m_videoWindowControl->setAspectRatioMode(Qt::KeepAspectRatio); break;
+ case QDeclarativeVideoOutput::PreserveAspectCrop:
+ m_videoWindowControl->setAspectRatioMode(Qt::KeepAspectRatioByExpanding); break;
+ case QDeclarativeVideoOutput::Stretch:
+ m_videoWindowControl->setAspectRatioMode(Qt::IgnoreAspectRatio); break;
+ };
+
+ const QRectF canvasRect = q->mapRectToScene(QRectF(0, 0, q->width(), q->height()));
+ m_videoWindowControl->setDisplayRect(canvasRect.toAlignedRect());
+}
+
+QSGNode *QDeclarativeVideoWindowBackend::updatePaintNode(QSGNode *oldNode,
+ QQuickItem::UpdatePaintNodeData *data)
+{
+ Q_UNUSED(oldNode);
+ Q_UNUSED(data);
+ m_videoWindowControl->repaint();
+ return 0;
+}
+
+QAbstractVideoSurface *QDeclarativeVideoWindowBackend::videoSurface() const
+{
+ return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/src/imports/multimedia/qdeclarativevideooutput_window_p.h b/src/imports/multimedia/qdeclarativevideooutput_window_p.h
new file mode 100644
index 000000000..af2e686f1
--- /dev/null
+++ b/src/imports/multimedia/qdeclarativevideooutput_window_p.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Research In Motion
+** Contact: http://www.qt-project.org/
+**
+** 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 QDECLARATIVEVIDEOOUTPUT_WINDOW_P_H
+#define QDECLARATIVEVIDEOOUTPUT_WINDOW_P_H
+
+#include "qdeclarativevideooutput_backend_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QVideoWindowControl;
+
+class QDeclarativeVideoWindowBackend : public QDeclarativeVideoBackend
+{
+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;
+
+private:
+ QPointer<QVideoWindowControl> m_videoWindowControl;
+};
+
+QT_END_NAMESPACE
+
+#endif