summaryrefslogtreecommitdiffstats
path: root/src/multimediawidgets
diff options
context:
space:
mode:
authorMichael Goddard <michael.goddard@nokia.com>2011-10-06 14:31:58 +1000
committerQt by Nokia <qt-info@nokia.com>2011-10-07 06:16:34 +0200
commit03f22bcdaf1f80083618856d6e4140d3062f175b (patch)
treefdfbf0895f4fbd91fb1f4a247cf09e28a1056096 /src/multimediawidgets
parent55bc4f2b46b0099d187db16e049d760cd55626e6 (diff)
Rename QtMultimediaKit to QtMultimedia.
There are a few legacy bits left in place so it passes CI, and then qt5.git etc can be updated. Change-Id: I6b082e50e6958c72fdabc2974992e16d90dafa3a Reviewed-on: http://codereview.qt-project.org/5368 Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: Jonas Rabbe <jonas.rabbe@nokia.com>
Diffstat (limited to 'src/multimediawidgets')
-rw-r--r--src/multimediawidgets/multimediawidgets.pro68
-rw-r--r--src/multimediawidgets/qcameraviewfinder.cpp113
-rw-r--r--src/multimediawidgets/qcameraviewfinder.h90
-rw-r--r--src/multimediawidgets/qeglimagetexturesurface.cpp554
-rw-r--r--src/multimediawidgets/qeglimagetexturesurface_p.h150
-rw-r--r--src/multimediawidgets/qgraphicsvideoitem.cpp432
-rw-r--r--src/multimediawidgets/qgraphicsvideoitem.h115
-rw-r--r--src/multimediawidgets/qgraphicsvideoitem_maemo6.cpp498
-rw-r--r--src/multimediawidgets/qpaintervideosurface.cpp1728
-rw-r--r--src/multimediawidgets/qpaintervideosurface_mac.mm285
-rw-r--r--src/multimediawidgets/qpaintervideosurface_mac_p.h103
-rw-r--r--src/multimediawidgets/qpaintervideosurface_p.h191
-rw-r--r--src/multimediawidgets/qtmultimediawidgetdefs.h89
-rw-r--r--src/multimediawidgets/qvideowidget.cpp1043
-rw-r--r--src/multimediawidgets/qvideowidget.h139
-rw-r--r--src/multimediawidgets/qvideowidget_p.h290
-rw-r--r--src/multimediawidgets/qvideowidgetcontrol.cpp245
-rw-r--r--src/multimediawidgets/qvideowidgetcontrol.h105
-rw-r--r--src/multimediawidgets/qvideowindowcontrol.cpp284
-rw-r--r--src/multimediawidgets/qvideowindowcontrol.h112
20 files changed, 6634 insertions, 0 deletions
diff --git a/src/multimediawidgets/multimediawidgets.pro b/src/multimediawidgets/multimediawidgets.pro
new file mode 100644
index 000000000..9251f2f71
--- /dev/null
+++ b/src/multimediawidgets/multimediawidgets.pro
@@ -0,0 +1,68 @@
+load(qt_module)
+
+# distinct from QtMultimedia
+TARGET = QtMultimediaWidgets
+QPRO_PWD = $$PWD
+QT = core gui multimedia-private widgets
+
+CONFIG += module no_private_qt_headers_warning
+MODULE_PRI += ../../modules/qt_multimediawidgets.pri
+
+contains(QT_CONFIG, opengl) | contains(QT_CONFIG, opengles2) {
+ QT += opengl
+} else {
+ DEFINES += QT_NO_OPENGL
+}
+
+!static:DEFINES += QT_MAKEDLL
+DEFINES += QT_BUILD_MULTIMEDIAWIDGETS_LIB
+
+load(qt_module_config)
+
+PRIVATE_HEADERS += \
+ qvideowidget_p.h \
+ qpaintervideosurface_p.h \
+
+PUBLIC_HEADERS += \
+ qtmultimediawidgetdefs.h \
+ qtmultimediawidgetsversion.h \
+ qcameraviewfinder.h \
+ qgraphicsvideoitem.h \
+ qvideowidgetcontrol.h \
+ qvideowidget.h \
+ qvideowindowcontrol.h
+
+SOURCES += \
+ qcameraviewfinder.cpp \
+ qpaintervideosurface.cpp \
+ qvideowidgetcontrol.cpp \
+ qvideowidget.cpp \
+ qvideowindowcontrol.cpp \
+
+mac:!qpa {
+!simulator {
+ PRIVATE_HEADERS += qpaintervideosurface_mac_p.h
+ OBJECTIVE_SOURCES += qpaintervideosurface_mac.mm
+}
+ LIBS += -framework AppKit -framework QuartzCore -framework QTKit
+}
+
+maemo6 {
+ isEqual(QT_ARCH,armv6) {
+ PRIVATE_HEADERS += qeglimagetexturesurface_p.h
+ SOURCES += qeglimagetexturesurface.cpp
+
+ SOURCES += qgraphicsvideoitem_maemo6.cpp
+
+ LIBS += -lX11
+ } else {
+ SOURCES += qgraphicsvideoitem.cpp
+ }
+}
+
+!maemo* {
+ SOURCES += qgraphicsvideoitem.cpp
+}
+
+HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS
+
diff --git a/src/multimediawidgets/qcameraviewfinder.cpp b/src/multimediawidgets/qcameraviewfinder.cpp
new file mode 100644
index 000000000..1d3f18549
--- /dev/null
+++ b/src/multimediawidgets/qcameraviewfinder.cpp
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QDebug>
+
+#include <private/qmediaobject_p.h>
+
+#include <qcamera.h>
+#include <qcameraviewfinder.h>
+#include <qvideowidget_p.h>
+#include <qvideodevicecontrol.h>
+
+QT_USE_NAMESPACE
+
+/*!
+ \class QCameraViewfinder
+
+
+ \brief The QCameraViewfinder class provides a camera viewfinder widget.
+
+ \inmodule QtMultimedia
+ \ingroup camera
+ \since 1.1
+
+ \snippet doc/src/snippets/multimedia-snippets/camera.cpp Camera
+
+*/
+
+class QCameraViewfinderPrivate : public QVideoWidgetPrivate
+{
+ Q_DECLARE_NON_CONST_PUBLIC(QCameraViewfinder)
+public:
+ QCameraViewfinderPrivate():
+ QVideoWidgetPrivate()
+ {
+ }
+};
+
+/*!
+ Constructs a new camera viewfinder widget.
+
+ The \a parent is passed to QVideoWidget.
+*/
+
+QCameraViewfinder::QCameraViewfinder(QWidget *parent)
+ :QVideoWidget(*new QCameraViewfinderPrivate, parent)
+{
+}
+
+/*!
+ Destroys a camera viewfinder widget.
+*/
+QCameraViewfinder::~QCameraViewfinder()
+{
+}
+
+/*!
+ \reimp
+ \since 1.1
+*/
+QMediaObject *QCameraViewfinder::mediaObject() const
+{
+ return QVideoWidget::mediaObject();
+}
+
+/*!
+ \reimp
+ \since 1.1
+*/
+bool QCameraViewfinder::setMediaObject(QMediaObject *object)
+{
+ return QVideoWidget::setMediaObject(object);
+}
+
+#include "moc_qcameraviewfinder.cpp"
diff --git a/src/multimediawidgets/qcameraviewfinder.h b/src/multimediawidgets/qcameraviewfinder.h
new file mode 100644
index 000000000..4ac39ebb9
--- /dev/null
+++ b/src/multimediawidgets/qcameraviewfinder.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCAMERAVIEWFINDER_H
+#define QCAMERAVIEWFINDER_H
+
+#include <QtCore/qstringlist.h>
+#include <QtCore/qpair.h>
+#include <QtCore/qsize.h>
+#include <QtCore/qpoint.h>
+#include <QtCore/qrect.h>
+
+#include <qmediacontrol.h>
+#include <qmediaobject.h>
+#include <qmediaservice.h>
+#include <qvideowidget.h>
+
+#include <qmediaserviceprovider.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Multimedia)
+
+
+class QCamera;
+
+class QCameraViewfinderPrivate;
+class Q_MULTIMEDIA_EXPORT QCameraViewfinder : public QVideoWidget
+{
+ Q_OBJECT
+public:
+ QCameraViewfinder(QWidget *parent = 0);
+ ~QCameraViewfinder();
+
+ QMediaObject *mediaObject() const;
+
+protected:
+ bool setMediaObject(QMediaObject *object);
+
+private:
+ Q_DISABLE_COPY(QCameraViewfinder)
+ Q_DECLARE_PRIVATE(QCameraViewfinder)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+
+#endif // QCAMERA_H
diff --git a/src/multimediawidgets/qeglimagetexturesurface.cpp b/src/multimediawidgets/qeglimagetexturesurface.cpp
new file mode 100644
index 000000000..dfab86c90
--- /dev/null
+++ b/src/multimediawidgets/qeglimagetexturesurface.cpp
@@ -0,0 +1,554 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qeglimagetexturesurface_p.h>
+#include <qpaintervideosurface_p.h>
+
+#include <QtCore/qmath.h>
+#include <QtCore/qvariant.h>
+#include <QtCore/qdebug.h>
+#include <QtGui/qpainter.h>
+#include <QtWidgets/qx11info_x11.h>
+#include <qvideosurfaceformat.h>
+
+
+QT_BEGIN_NAMESPACE
+
+//#define DEBUG_OMAPFB_SURFACE
+
+const QAbstractVideoBuffer::HandleType EGLImageTextureHandle =
+QAbstractVideoBuffer::HandleType(QAbstractVideoBuffer::UserHandle+3434);
+
+/*!
+ \class QOmapFbVideoSurface
+ \internal
+ \since 1.2
+*/
+
+/*!
+*/
+QEglImageTextureSurface::QEglImageTextureSurface(QObject *parent)
+ : QAbstractVideoSurface(parent)
+ , m_context(0)
+ , m_program(0)
+ , m_pixelFormat(QVideoFrame::Format_Invalid)
+ , m_ready(false)
+ , m_colorKey(49,0,49)
+ , m_fallbackSurface(0)
+ , m_fallbackSurfaceActive(false)
+{
+ m_fallbackSurface = new QPainterVideoSurface(this);
+}
+
+/*!
+*/
+QEglImageTextureSurface::~QEglImageTextureSurface()
+{
+ if (isActive())
+ stop();
+}
+
+/*!
+ \since 1.2
+*/
+QList<QVideoFrame::PixelFormat> QEglImageTextureSurface::supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType) const
+{
+#ifdef DEBUG_OMAPFB_SURFACE
+ qDebug() << Q_FUNC_INFO << handleType;
+#endif
+
+ if (handleType == EGLImageTextureHandle) {
+ return QList<QVideoFrame::PixelFormat>()
+ << QVideoFrame::Format_RGB32
+ << QVideoFrame::Format_ARGB32;
+ }
+
+ return m_fallbackSurface->supportedPixelFormats(handleType);
+}
+
+const char *qt_glsl_eglTextureVertexShaderProgram =
+ "attribute highp vec4 vertexCoordArray;\n"
+ "attribute mediump vec2 textureCoordArray;\n"
+ "uniform highp mat4 positionMatrix;\n"
+ "varying mediump vec2 textureCoord;\n"
+ "void main (void)\n"
+ "{\n"
+ " gl_Position = positionMatrix * vertexCoordArray;\n"
+ " textureCoord = textureCoordArray;\n"
+ "}";
+
+static const char* qt_glsl_eglTextureShaderProgram =
+ "#extension GL_OES_EGL_image_external: enable\n"
+ "\n"
+ "uniform samplerExternalOES texRgb;\n"
+ "varying mediump vec2 textureCoord;\n"
+ "\n"
+ "void main (void)\n"
+ "{\n"
+ " gl_FragColor = texture2D(texRgb, textureCoord);\n"
+ "}";
+
+
+/*!
+ \since 1.2
+*/
+bool QEglImageTextureSurface::start(const QVideoSurfaceFormat &format)
+{
+#ifdef DEBUG_OMAPFB_SURFACE
+ qDebug() << Q_FUNC_INFO << format;
+#endif
+
+ m_fallbackSurfaceActive = false;
+ if (format.handleType() != EGLImageTextureHandle) {
+ qWarning() << Q_FUNC_INFO << "Non EGLImageTextureHandle based format requested, fallback to QPainterVideoSurface";
+ connect(m_fallbackSurface, SIGNAL(activeChanged(bool)),
+ this, SIGNAL(activeChanged(bool)));
+ connect(m_fallbackSurface, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)),
+ this, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)));
+ connect(m_fallbackSurface, SIGNAL(supportedFormatsChanged()),
+ this, SIGNAL(supportedFormatsChanged()));
+ connect(m_fallbackSurface, SIGNAL(nativeResolutionChanged(QSize)),
+ this, SIGNAL(nativeResolutionChanged(QSize)));
+ connect(m_fallbackSurface, SIGNAL(frameChanged()),
+ this, SIGNAL(frameChanged()));
+
+ if (m_fallbackSurface->start(format)) {
+ m_fallbackSurfaceActive = true;
+ QAbstractVideoSurface::start(format);
+ } else {
+ qWarning() << Q_FUNC_INFO << "failed to start video surface:" << m_fallbackSurface->error();
+ setError(m_fallbackSurface->error());
+
+ disconnect(m_fallbackSurface, SIGNAL(activeChanged(bool)),
+ this, SIGNAL(activeChanged(bool)));
+ disconnect(m_fallbackSurface, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)),
+ this, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)));
+ disconnect(m_fallbackSurface, SIGNAL(supportedFormatsChanged()),
+ this, SIGNAL(supportedFormatsChanged()));
+ disconnect(m_fallbackSurface, SIGNAL(nativeResolutionChanged(QSize)),
+ this, SIGNAL(nativeResolutionChanged(QSize)));
+ disconnect(m_fallbackSurface, SIGNAL(frameChanged()),
+ this, SIGNAL(frameChanged()));
+ }
+
+ return m_fallbackSurfaceActive;
+ }
+
+ QAbstractVideoSurface::Error error = NoError;
+
+ if (isActive())
+ stop();
+
+ if (format.frameSize().isEmpty()) {
+ setError(UnsupportedFormatError);
+ } else if (m_context) {
+ m_context->makeCurrent();
+ m_program = new QGLShaderProgram(m_context, this);
+
+ if (!m_program->addShaderFromSourceCode(QGLShader::Vertex, qt_glsl_eglTextureVertexShaderProgram)) {
+ qWarning("QOmapFbVideoSurface: Vertex shader compile error %s",
+ qPrintable(m_program->log()));
+ error = ResourceError;
+ }
+
+ if (error == NoError
+ && !m_program->addShaderFromSourceCode(QGLShader::Fragment, qt_glsl_eglTextureShaderProgram)) {
+ qWarning("QOmapFbVideoSurface: Vertex shader compile error %s",
+ qPrintable(m_program->log()));
+ error = QAbstractVideoSurface::ResourceError;
+ }
+
+ if (error == NoError) {
+ m_program->bindAttributeLocation("textureCoordArray", 1);
+ if(!m_program->link()) {
+ qWarning("QOmapFbVideoSurface: Shader link error %s", qPrintable(m_program->log()));
+ m_program->removeAllShaders();
+ error = QAbstractVideoSurface::ResourceError;
+ }
+ }
+
+ if (error != QAbstractVideoSurface::NoError) {
+ delete m_program;
+ m_program = 0;
+ }
+ }
+
+ if (error == QAbstractVideoSurface::NoError) {
+ m_scanLineDirection = format.scanLineDirection();
+ m_frameSize = format.frameSize();
+ m_pixelFormat = format.pixelFormat();
+ m_frameSize = format.frameSize();
+ m_sourceRect = format.viewport();
+ m_ready = true;
+
+ return QAbstractVideoSurface::start(format);
+ }
+
+ QAbstractVideoSurface::stop();
+ return false;
+}
+
+/*!
+ \since 1.2
+*/
+void QEglImageTextureSurface::stop()
+{
+#ifdef DEBUG_OMAPFB_SURFACE
+ qDebug() << Q_FUNC_INFO;
+#endif
+
+ if (m_fallbackSurfaceActive) {
+ m_fallbackSurface->stop();
+ m_fallbackSurfaceActive = false;
+
+ disconnect(m_fallbackSurface, SIGNAL(activeChanged(bool)),
+ this, SIGNAL(activeChanged(bool)));
+ disconnect(m_fallbackSurface, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)),
+ this, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)));
+ disconnect(m_fallbackSurface, SIGNAL(supportedFormatsChanged()),
+ this, SIGNAL(supportedFormatsChanged()));
+ disconnect(m_fallbackSurface, SIGNAL(nativeResolutionChanged(QSize)),
+ this, SIGNAL(nativeResolutionChanged(QSize)));
+ disconnect(m_fallbackSurface, SIGNAL(frameChanged()),
+ this, SIGNAL(frameChanged()));
+
+ m_ready = false;
+ QAbstractVideoSurface::stop();
+ }
+
+ if (isActive()) {
+ if (m_context)
+ m_context->makeCurrent();
+ m_frame = QVideoFrame();
+
+ m_program->removeAllShaders();
+ delete m_program;
+ m_program = 0;
+ m_ready = false;
+
+ QAbstractVideoSurface::stop();
+ }
+}
+
+/*!
+ \since 1.2
+*/
+bool QEglImageTextureSurface::present(const QVideoFrame &frame)
+{
+ if (m_fallbackSurfaceActive) {
+ if (m_fallbackSurface->present(frame)) {
+ return true;
+ } else {
+ setError(m_fallbackSurface->error());
+ stop();
+ return false;
+ }
+ }
+
+ if (!m_ready) {
+ if (!isActive())
+ setError(StoppedError);
+ else
+ m_frame = frame;
+ } else if (frame.isValid()
+ && (frame.pixelFormat() != m_pixelFormat || frame.size() != m_frameSize)) {
+ setError(IncorrectFormatError);
+ qWarning() << "Received frame of incorrect format, stopping the surface";
+
+ stop();
+ } else {
+ if (m_context)
+ m_context->makeCurrent();
+ m_frame = frame;
+ m_ready = false;
+ emit frameChanged();
+ return true;
+ }
+ return false;
+}
+
+/*!
+ \since 1.2
+*/
+int QEglImageTextureSurface::brightness() const
+{
+ return m_fallbackSurface->brightness();
+}
+
+/*!
+ \since 1.2
+*/
+void QEglImageTextureSurface::setBrightness(int brightness)
+{
+ m_fallbackSurface->setBrightness(brightness);
+}
+
+/*!
+ \since 1.2
+*/
+int QEglImageTextureSurface::contrast() const
+{
+ return m_fallbackSurface->contrast();
+}
+
+/*!
+ \since 1.2
+*/
+void QEglImageTextureSurface::setContrast(int contrast)
+{
+ m_fallbackSurface->setContrast(contrast);
+}
+
+/*!
+ \since 1.2
+*/
+int QEglImageTextureSurface::hue() const
+{
+ return m_fallbackSurface->hue();
+}
+
+/*!
+ \since 1.2
+*/
+void QEglImageTextureSurface::setHue(int hue)
+{
+ m_fallbackSurface->setHue(hue);
+}
+
+/*!
+ \since 1.2
+*/
+int QEglImageTextureSurface::saturation() const
+{
+ return m_fallbackSurface->saturation();
+}
+
+/*!
+ \since 1.2
+*/
+void QEglImageTextureSurface::setSaturation(int saturation)
+{
+ m_fallbackSurface->setSaturation(saturation);
+}
+
+/*!
+ \since 1.2
+*/
+bool QEglImageTextureSurface::isReady() const
+{
+ return m_fallbackSurfaceActive ? m_fallbackSurface->isReady() : m_ready;
+}
+
+/*!
+ \since 1.2
+*/
+void QEglImageTextureSurface::setReady(bool ready)
+{
+ m_ready = ready;
+ if (m_fallbackSurfaceActive)
+ m_fallbackSurface->setReady(ready);
+}
+
+/*!
+ \since 1.2
+*/
+void QEglImageTextureSurface::paint(QPainter *painter, const QRectF &target, const QRectF &sourceRect)
+{
+ if (m_fallbackSurfaceActive) {
+ m_fallbackSurface->paint(painter, target, sourceRect);
+ return;
+ }
+
+ if (!isActive() || !m_frame.isValid()) {
+ painter->fillRect(target, QBrush(Qt::black));
+ } else {
+ const QRectF source(
+ m_sourceRect.x() + m_sourceRect.width() * sourceRect.x(),
+ m_sourceRect.y() + m_sourceRect.height() * sourceRect.y(),
+ m_sourceRect.width() * sourceRect.width(),
+ m_sourceRect.height() * sourceRect.height());
+
+ bool stencilTestEnabled = glIsEnabled(GL_STENCIL_TEST);
+ bool scissorTestEnabled = glIsEnabled(GL_SCISSOR_TEST);
+
+ painter->beginNativePainting();
+
+ if (stencilTestEnabled)
+ glEnable(GL_STENCIL_TEST);
+ if (scissorTestEnabled)
+ glEnable(GL_SCISSOR_TEST);
+
+ const int width = QGLContext::currentContext()->device()->width();
+ const int height = QGLContext::currentContext()->device()->height();
+
+ const QTransform transform = painter->deviceTransform();
+
+ const GLfloat wfactor = 2.0 / width;
+ const GLfloat hfactor = -2.0 / height;
+
+ const GLfloat positionMatrix[4][4] =
+ {
+ {
+ /*(0,0)*/ GLfloat(wfactor * transform.m11() - transform.m13()),
+ /*(0,1)*/ GLfloat(hfactor * transform.m12() + transform.m13()),
+ /*(0,2)*/ 0.0,
+ /*(0,3)*/ GLfloat(transform.m13())
+ }, {
+ /*(1,0)*/ GLfloat(wfactor * transform.m21() - transform.m23()),
+ /*(1,1)*/ GLfloat(hfactor * transform.m22() + transform.m23()),
+ /*(1,2)*/ 0.0,
+ /*(1,3)*/ GLfloat(transform.m23())
+ }, {
+ /*(2,0)*/ 0.0,
+ /*(2,1)*/ 0.0,
+ /*(2,2)*/ -1.0,
+ /*(2,3)*/ 0.0
+ }, {
+ /*(3,0)*/ GLfloat(wfactor * transform.dx() - transform.m33()),
+ /*(3,1)*/ GLfloat(hfactor * transform.dy() + transform.m33()),
+ /*(3,2)*/ 0.0,
+ /*(3,3)*/ GLfloat(transform.m33())
+ }
+ };
+
+ const GLfloat vTop = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
+ ? target.top()
+ : target.bottom() + 1;
+ const GLfloat vBottom = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
+ ? target.bottom() + 1
+ : target.top();
+
+
+ const GLfloat vertexCoordArray[] =
+ {
+ GLfloat(target.left()) , GLfloat(vBottom),
+ GLfloat(target.right() + 1), GLfloat(vBottom),
+ GLfloat(target.left()) , GLfloat(vTop),
+ GLfloat(target.right() + 1), GLfloat(vTop)
+ };
+
+ const GLfloat txLeft = source.left() / m_frameSize.width();
+ const GLfloat txRight = source.right() / m_frameSize.width();
+ const GLfloat txTop = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
+ ? source.top() / m_frameSize.height()
+ : source.bottom() / m_frameSize.height();
+ const GLfloat txBottom = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
+ ? source.bottom() / m_frameSize.height()
+ : source.top() / m_frameSize.height();
+
+ const GLfloat textureCoordArray[] =
+ {
+ txLeft , txBottom,
+ txRight, txBottom,
+ txLeft , txTop,
+ txRight, txTop
+ };
+
+ m_program->bind();
+
+ m_program->enableAttributeArray("vertexCoordArray");
+ m_program->enableAttributeArray("textureCoordArray");
+ m_program->setAttributeArray("vertexCoordArray", vertexCoordArray, 2);
+ m_program->setAttributeArray("textureCoordArray", textureCoordArray, 2);
+ m_program->setUniformValue("positionMatrix", positionMatrix);
+ m_program->setUniformValue("texRgb", 0);
+
+ //map() binds the external texture
+ m_frame.map(QAbstractVideoBuffer::ReadOnly);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ //it's necessary to unbind the external texture
+ m_frame.unmap();
+
+ m_program->release();
+
+ painter->endNativePainting();
+ }
+}
+
+/*!
+ \fn QOmapFbVideoSurface::frameChanged()
+ \since 1.2
+*/
+
+/*!
+ \since 1.2
+*/
+const QGLContext *QEglImageTextureSurface::glContext() const
+{
+ return m_context;
+}
+
+/*!
+ \since 1.2
+*/
+void QEglImageTextureSurface::setGLContext(QGLContext *context)
+{
+ if (m_context == context)
+ return;
+
+ stop();
+
+ m_context = context;
+
+ m_fallbackSurface->setGLContext(context);
+ if (m_fallbackSurface->supportedShaderTypes() & QPainterVideoSurface::GlslShader) {
+ m_fallbackSurface->setShaderType(QPainterVideoSurface::GlslShader);
+ } else {
+ m_fallbackSurface->setShaderType(QPainterVideoSurface::FragmentProgramShader);
+ }
+
+ emit supportedFormatsChanged();
+}
+
+void QEglImageTextureSurface::viewportDestroyed()
+{
+ m_context = 0;
+ m_fallbackSurface->viewportDestroyed();
+
+ setError(ResourceError);
+ stop();
+}
+
+#include "moc_qeglimagetexturesurface_p.cpp"
+QT_END_NAMESPACE
diff --git a/src/multimediawidgets/qeglimagetexturesurface_p.h b/src/multimediawidgets/qeglimagetexturesurface_p.h
new file mode 100644
index 000000000..f56c9da78
--- /dev/null
+++ b/src/multimediawidgets/qeglimagetexturesurface_p.h
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEGLIMAGETEXTURESURFACE_P_H
+#define QEGLIMAGETEXTURESURFACE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <qtmultimediawidgetdefs.h>
+#include <QtCore/qsize.h>
+#include <QtGui/qimage.h>
+#include <QtGui/qmatrix4x4.h>
+#include <QtGui/qpaintengine.h>
+
+#include <QtOpenGL/qglshaderprogram.h>
+
+#include <qabstractvideosurface.h>
+#include <qvideosurfaceformat.h>
+#include <qvideoframe.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Multimedia)
+
+class QGLContext;
+class QGLShaderProgram;
+class QPainterVideoSurface;
+
+class QEglImageTextureSurface : public QAbstractVideoSurface
+{
+ Q_OBJECT
+public:
+ explicit QEglImageTextureSurface(QObject *parent = 0);
+ ~QEglImageTextureSurface();
+
+ QList<QVideoFrame::PixelFormat> supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const;
+
+ bool start(const QVideoSurfaceFormat &format);
+ void stop();
+
+ bool present(const QVideoFrame &frame);
+
+ int brightness() const;
+ void setBrightness(int brightness);
+
+ int contrast() const;
+ void setContrast(int contrast);
+
+ int hue() const;
+ void setHue(int hue);
+
+ int saturation() const;
+ void setSaturation(int saturation);
+
+ bool isReady() const;
+ void setReady(bool ready);
+
+ void paint(QPainter *painter, const QRectF &target, const QRectF &source = QRectF(0, 0, 1, 1));
+
+ const QGLContext *glContext() const;
+ void setGLContext(QGLContext *context);
+
+ bool isOverlayEnabled() const;
+ void setOverlayEnabled(bool enabled);
+
+ QRect displayRect() const;
+ void setDisplayRect(const QRect &rect);
+
+public Q_SLOTS:
+ void viewportDestroyed();
+
+Q_SIGNALS:
+ void frameChanged();
+
+private:
+ QGLContext *m_context;
+ QGLShaderProgram *m_program;
+
+ QVideoFrame m_frame;
+
+ QVideoFrame::PixelFormat m_pixelFormat;
+ QVideoSurfaceFormat::Direction m_scanLineDirection;
+ QSize m_frameSize;
+ QRect m_sourceRect;
+ bool m_ready;
+
+ QRect m_viewport;
+ QRect m_displayRect;
+ QColor m_colorKey;
+
+ QPainterVideoSurface *m_fallbackSurface;
+ bool m_fallbackSurfaceActive;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+
+#endif
diff --git a/src/multimediawidgets/qgraphicsvideoitem.cpp b/src/multimediawidgets/qgraphicsvideoitem.cpp
new file mode 100644
index 000000000..120a24f26
--- /dev/null
+++ b/src/multimediawidgets/qgraphicsvideoitem.cpp
@@ -0,0 +1,432 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qgraphicsvideoitem.h"
+
+#include <qmediaobject.h>
+#include <qmediaservice.h>
+#include <qpaintervideosurface_p.h>
+#include <qvideorenderercontrol.h>
+
+#include <QtCore/qcoreevent.h>
+#include <QtCore/qpointer.h>
+
+#include <qvideosurfaceformat.h>
+
+#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
+#include <QtOpenGL/qgl.h>
+#endif
+
+Q_DECLARE_METATYPE(QVideoSurfaceFormat)
+
+QT_BEGIN_NAMESPACE
+
+class QGraphicsVideoItemPrivate
+{
+public:
+ QGraphicsVideoItemPrivate()
+ : q_ptr(0)
+ , surface(0)
+ , mediaObject(0)
+ , service(0)
+ , rendererControl(0)
+ , aspectRatioMode(Qt::KeepAspectRatio)
+ , updatePaintDevice(true)
+ , rect(0.0, 0.0, 320, 240)
+ {
+ }
+
+ QGraphicsVideoItem *q_ptr;
+
+ QPainterVideoSurface *surface;
+ QPointer<QMediaObject> mediaObject;
+ QMediaService *service;
+ QVideoRendererControl *rendererControl;
+ Qt::AspectRatioMode aspectRatioMode;
+ bool updatePaintDevice;
+ QRectF rect;
+ QRectF boundingRect;
+ QRectF sourceRect;
+ QSizeF nativeSize;
+
+ void clearService();
+ void updateRects();
+
+ void _q_present();
+ void _q_formatChanged(const QVideoSurfaceFormat &format);
+ void _q_updateNativeSize();
+ void _q_serviceDestroyed();
+};
+
+void QGraphicsVideoItemPrivate::clearService()
+{
+ if (rendererControl) {
+ surface->stop();
+ rendererControl->setSurface(0);
+ service->releaseControl(rendererControl);
+ rendererControl = 0;
+ }
+ if (service) {
+ QObject::disconnect(service, SIGNAL(destroyed()), q_ptr, SLOT(_q_serviceDestroyed()));
+ service = 0;
+ }
+}
+
+void QGraphicsVideoItemPrivate::updateRects()
+{
+ q_ptr->prepareGeometryChange();
+
+ if (nativeSize.isEmpty()) {
+ //this is necessary for item to receive the
+ //first paint event and configure video surface.
+ boundingRect = rect;
+ } else if (aspectRatioMode == Qt::IgnoreAspectRatio) {
+ boundingRect = rect;
+ sourceRect = QRectF(0, 0, 1, 1);
+ } else if (aspectRatioMode == Qt::KeepAspectRatio) {
+ QSizeF size = nativeSize;
+ size.scale(rect.size(), Qt::KeepAspectRatio);
+
+ boundingRect = QRectF(0, 0, size.width(), size.height());
+ boundingRect.moveCenter(rect.center());
+
+ sourceRect = QRectF(0, 0, 1, 1);
+ } else if (aspectRatioMode == Qt::KeepAspectRatioByExpanding) {
+ boundingRect = rect;
+
+ QSizeF size = rect.size();
+ size.scale(nativeSize, Qt::KeepAspectRatio);
+
+ sourceRect = QRectF(
+ 0, 0, size.width() / nativeSize.width(), size.height() / nativeSize.height());
+ sourceRect.moveCenter(QPointF(0.5, 0.5));
+ }
+}
+
+void QGraphicsVideoItemPrivate::_q_present()
+{
+ if (q_ptr->isObscured()) {
+ q_ptr->update(boundingRect);
+ surface->setReady(true);
+ } else {
+ q_ptr->update(boundingRect);
+ }
+}
+
+void QGraphicsVideoItemPrivate::_q_updateNativeSize()
+{
+ const QSize &size = surface->surfaceFormat().sizeHint();
+ if (nativeSize != size) {
+ nativeSize = size;
+
+ updateRects();
+ emit q_ptr->nativeSizeChanged(nativeSize);
+ }
+}
+
+void QGraphicsVideoItemPrivate::_q_serviceDestroyed()
+{
+ rendererControl = 0;
+ service = 0;
+
+ surface->stop();
+}
+
+
+/*!
+ \class QGraphicsVideoItem
+
+ \brief The QGraphicsVideoItem class provides a graphics item which display video produced by a QMediaObject.
+
+ \inmodule QtMultimedia
+ \ingroup multimedia
+ \since 1.0
+
+ Attaching a QGraphicsVideoItem to a QMediaObject allows it to display
+ the video or image output of that media object. A QGraphicsVideoItem
+ is attached to a media object by passing a pointer to the QMediaObject
+ to the setMediaObject() function.
+
+ \snippet doc/src/snippets/multimedia-snippets/video.cpp Video graphics item
+
+ \bold {Note}: Only a single display output can be attached to a media
+ object at one time.
+
+ \sa QMediaObject, QMediaPlayer, QVideoWidget
+*/
+
+/*!
+ Constructs a graphics item that displays video.
+
+ The \a parent is passed to QGraphicsItem.
+*/
+QGraphicsVideoItem::QGraphicsVideoItem(QGraphicsItem *parent)
+ : QGraphicsObject(parent)
+ , d_ptr(new QGraphicsVideoItemPrivate)
+{
+ d_ptr->q_ptr = this;
+ d_ptr->surface = new QPainterVideoSurface;
+
+ qRegisterMetaType<QVideoSurfaceFormat>();
+
+ connect(d_ptr->surface, SIGNAL(frameChanged()), this, SLOT(_q_present()));
+ connect(d_ptr->surface, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)),
+ this, SLOT(_q_updateNativeSize()), Qt::QueuedConnection);
+}
+
+/*!
+ Destroys a video graphics item.
+*/
+QGraphicsVideoItem::~QGraphicsVideoItem()
+{
+ if (d_ptr->rendererControl) {
+ d_ptr->rendererControl->setSurface(0);
+ d_ptr->service->releaseControl(d_ptr->rendererControl);
+ }
+
+ delete d_ptr->surface;
+ delete d_ptr;
+}
+
+/*!
+ \property QGraphicsVideoItem::mediaObject
+ \brief the media object which provides the video displayed by a graphics
+ item.
+ \since 1.0
+*/
+
+QMediaObject *QGraphicsVideoItem::mediaObject() const
+{
+ return d_func()->mediaObject;
+}
+
+/*!
+ \internal
+ \since 1.0
+*/
+bool QGraphicsVideoItem::setMediaObject(QMediaObject *object)
+{
+ Q_D(QGraphicsVideoItem);
+
+ if (object == d->mediaObject)
+ return true;
+
+ d->clearService();
+
+ d->mediaObject = object;
+
+ if (d->mediaObject) {
+ d->service = d->mediaObject->service();
+
+ if (d->service) {
+ QMediaControl *control = d->service->requestControl(QVideoRendererControl_iid);
+ if (control) {
+ d->rendererControl = qobject_cast<QVideoRendererControl *>(control);
+
+ if (d->rendererControl) {
+ //don't set the surface untill the item is painted
+ //at least once and the surface is configured
+ if (!d->updatePaintDevice)
+ d->rendererControl->setSurface(d->surface);
+ else
+ update(boundingRect());
+
+ connect(d->service, SIGNAL(destroyed()), this, SLOT(_q_serviceDestroyed()));
+
+ return true;
+ }
+ if (control)
+ d->service->releaseControl(control);
+ }
+ }
+ }
+
+ d->mediaObject = 0;
+ return false;
+}
+
+/*!
+ \property QGraphicsVideoItem::aspectRatioMode
+ \brief how a video is scaled to fit the graphics item's size.
+ \since 1.0
+*/
+
+Qt::AspectRatioMode QGraphicsVideoItem::aspectRatioMode() const
+{
+ return d_func()->aspectRatioMode;
+}
+
+void QGraphicsVideoItem::setAspectRatioMode(Qt::AspectRatioMode mode)
+{
+ Q_D(QGraphicsVideoItem);
+
+ d->aspectRatioMode = mode;
+ d->updateRects();
+}
+
+/*!
+ \property QGraphicsVideoItem::offset
+ \brief the video item's offset.
+
+ QGraphicsVideoItem will draw video using the offset for its top left
+ corner.
+ \since 1.0
+*/
+
+QPointF QGraphicsVideoItem::offset() const
+{
+ return d_func()->rect.topLeft();
+}
+
+void QGraphicsVideoItem::setOffset(const QPointF &offset)
+{
+ Q_D(QGraphicsVideoItem);
+
+ d->rect.moveTo(offset);
+ d->updateRects();
+}
+
+/*!
+ \property QGraphicsVideoItem::size
+ \brief the video item's size.
+
+ QGraphicsVideoItem will draw video scaled to fit size according to its
+ fillMode.
+ \since 1.0
+*/
+
+QSizeF QGraphicsVideoItem::size() const
+{
+ return d_func()->rect.size();
+}
+
+void QGraphicsVideoItem::setSize(const QSizeF &size)
+{
+ Q_D(QGraphicsVideoItem);
+
+ d->rect.setSize(size.isValid() ? size : QSizeF(0, 0));
+ d->updateRects();
+}
+
+/*!
+ \property QGraphicsVideoItem::nativeSize
+ \brief the native size of the video.
+ \since 1.0
+*/
+
+QSizeF QGraphicsVideoItem::nativeSize() const
+{
+ return d_func()->nativeSize;
+}
+
+/*!
+ \fn QGraphicsVideoItem::nativeSizeChanged(const QSizeF &size)
+
+ Signals that the native \a size of the video has changed.
+ \since 1.0
+*/
+
+/*!
+ \reimp
+ \since 1.0
+*/
+QRectF QGraphicsVideoItem::boundingRect() const
+{
+ return d_func()->boundingRect;
+}
+
+/*!
+ \reimp
+ \since 1.0
+*/
+void QGraphicsVideoItem::paint(
+ QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_D(QGraphicsVideoItem);
+
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+
+ if (d->surface && d->updatePaintDevice) {
+ d->updatePaintDevice = false;
+#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
+ if (widget)
+ connect(widget, SIGNAL(destroyed()), d->surface, SLOT(viewportDestroyed()));
+
+ d->surface->setGLContext(const_cast<QGLContext *>(QGLContext::currentContext()));
+ if (d->surface->supportedShaderTypes() & QPainterVideoSurface::GlslShader) {
+ d->surface->setShaderType(QPainterVideoSurface::GlslShader);
+ } else {
+ d->surface->setShaderType(QPainterVideoSurface::FragmentProgramShader);
+ }
+#endif
+ if (d->rendererControl && d->rendererControl->surface() != d->surface)
+ d->rendererControl->setSurface(d->surface);
+ }
+
+ if (d->surface && d->surface->isActive()) {
+ d->surface->paint(painter, d->boundingRect, d->sourceRect);
+ d->surface->setReady(true);
+ }
+}
+
+/*!
+ \reimp
+
+ \internal
+ \since 1.0
+*/
+QVariant QGraphicsVideoItem::itemChange(GraphicsItemChange change, const QVariant &value)
+{
+ return QGraphicsItem::itemChange(change, value);
+}
+
+/*!
+ \internal
+ \since 1.0
+*/
+void QGraphicsVideoItem::timerEvent(QTimerEvent *event)
+{
+ QGraphicsObject::timerEvent(event);
+}
+
+#include "moc_qgraphicsvideoitem.cpp"
+QT_END_NAMESPACE
diff --git a/src/multimediawidgets/qgraphicsvideoitem.h b/src/multimediawidgets/qgraphicsvideoitem.h
new file mode 100644
index 000000000..cf8913417
--- /dev/null
+++ b/src/multimediawidgets/qgraphicsvideoitem.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGRAPHICSVIDEOITEM_H
+#define QGRAPHICSVIDEOITEM_H
+
+#include <QtWidgets/qgraphicsitem.h>
+
+#include <qvideowidget.h>
+#include <qmediabindableinterface.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Multimedia)
+
+class QVideoSurfaceFormat;
+QT_END_NAMESPACE
+
+QT_BEGIN_NAMESPACE
+
+class QGraphicsVideoItemPrivate;
+class Q_MULTIMEDIA_EXPORT QGraphicsVideoItem : public QGraphicsObject, public QMediaBindableInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QMediaBindableInterface)
+ Q_PROPERTY(QMediaObject* mediaObject READ mediaObject WRITE setMediaObject)
+ Q_PROPERTY(Qt::AspectRatioMode aspectRatioMode READ aspectRatioMode WRITE setAspectRatioMode)
+ Q_PROPERTY(QPointF offset READ offset WRITE setOffset)
+ Q_PROPERTY(QSizeF size READ size WRITE setSize)
+ Q_PROPERTY(QSizeF nativeSize READ nativeSize NOTIFY nativeSizeChanged)
+public:
+ QGraphicsVideoItem(QGraphicsItem *parent = 0);
+ ~QGraphicsVideoItem();
+
+ QMediaObject *mediaObject() const;
+
+ Qt::AspectRatioMode aspectRatioMode() const;
+ void setAspectRatioMode(Qt::AspectRatioMode mode);
+
+ QPointF offset() const;
+ void setOffset(const QPointF &offset);
+
+ QSizeF size() const;
+ void setSize(const QSizeF &size);
+
+ QSizeF nativeSize() const;
+
+ QRectF boundingRect() const;
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+Q_SIGNALS:
+ void nativeSizeChanged(const QSizeF &size);
+
+protected:
+ void timerEvent(QTimerEvent *event);
+ QVariant itemChange(GraphicsItemChange change, const QVariant &value);
+
+ bool setMediaObject(QMediaObject *object);
+
+ QGraphicsVideoItemPrivate *d_ptr;
+
+private:
+ Q_DECLARE_PRIVATE(QGraphicsVideoItem)
+ Q_PRIVATE_SLOT(d_func(), void _q_present())
+ Q_PRIVATE_SLOT(d_func(), void _q_updateNativeSize())
+ Q_PRIVATE_SLOT(d_func(), void _q_serviceDestroyed())
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+
+#endif
diff --git a/src/multimediawidgets/qgraphicsvideoitem_maemo6.cpp b/src/multimediawidgets/qgraphicsvideoitem_maemo6.cpp
new file mode 100644
index 000000000..aa55f0420
--- /dev/null
+++ b/src/multimediawidgets/qgraphicsvideoitem_maemo6.cpp
@@ -0,0 +1,498 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qgraphicsvideoitem.h"
+
+#include <QtCore/qcoreevent.h>
+#include <QtCore/qpointer.h>
+#include <QtCore/qbasictimer.h>
+
+#include <QtWidgets/qgraphicsscene.h>
+
+#include <qmediaobject.h>
+#include <qmediaservice.h>
+#include <qpaintervideosurface_p.h>
+#include <qeglimagetexturesurface_p.h>
+#include <qvideorenderercontrol.h>
+
+#include <qvideosurfaceformat.h>
+
+#include <X11/Xlib.h>
+
+#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
+#include <QtOpenGL/qgl.h>
+#endif
+
+//#define ENABLE_OVERLAY
+
+namespace
+{
+//XInitThreads is necessary for gltexturesink element.
+//To ensure it's called before main() it's better to link to
+//libQtMultimedia.so directly, not when QML multimedia plugin is loaded.
+class InitThreads
+{
+public:
+ InitThreads()
+ {
+ XInitThreads();
+ }
+} _initThreads;
+}
+
+Q_DECLARE_METATYPE(QVideoSurfaceFormat)
+
+QT_BEGIN_NAMESPACE
+
+class QGraphicsVideoItemPrivate
+{
+public:
+ QGraphicsVideoItemPrivate()
+ : q_ptr(0)
+ , surface(0)
+ , mediaObject(0)
+ , service(0)
+ , rendererControl(0)
+ , aspectRatioMode(Qt::KeepAspectRatio)
+ , updatePaintDevice(true)
+ , rect(0.0, 0.0, 320, 240)
+ {
+ }
+
+ QGraphicsVideoItem *q_ptr;
+
+ QEglImageTextureSurface *surface;
+ QPointer<QMediaObject> mediaObject;
+ QMediaService *service;
+ QVideoRendererControl *rendererControl;
+ Qt::AspectRatioMode aspectRatioMode;
+ bool updatePaintDevice;
+ QRectF rect;
+ QRectF boundingRect;
+ QRectF sourceRect;
+ QSizeF nativeSize;
+
+ void clearService();
+ void updateRects();
+
+ void _q_present();
+ void _q_formatChanged(const QVideoSurfaceFormat &format);
+ void _q_updateNativeSize();
+ void _q_serviceDestroyed();
+};
+
+void QGraphicsVideoItemPrivate::clearService()
+{
+ if (rendererControl) {
+ surface->stop();
+ rendererControl->setSurface(0);
+ service->releaseControl(rendererControl);
+ rendererControl = 0;
+ }
+ if (service) {
+ QObject::disconnect(service, SIGNAL(destroyed()), q_ptr, SLOT(_q_serviceDestroyed()));
+ service = 0;
+ }
+}
+
+void QGraphicsVideoItemPrivate::updateRects()
+{
+ q_ptr->prepareGeometryChange();
+
+ if (nativeSize.isEmpty()) {
+ //this is necessary for item to receive the
+ //first paint event and configure video surface.
+ boundingRect = rect;
+ } else if (aspectRatioMode == Qt::IgnoreAspectRatio) {
+ boundingRect = rect;
+ sourceRect = QRectF(0, 0, 1, 1);
+ } else if (aspectRatioMode == Qt::KeepAspectRatio) {
+ QSizeF size = nativeSize;
+ size.scale(rect.size(), Qt::KeepAspectRatio);
+
+ boundingRect = QRectF(0, 0, size.width(), size.height());
+ boundingRect.moveCenter(rect.center());
+
+ sourceRect = QRectF(0, 0, 1, 1);
+ } else if (aspectRatioMode == Qt::KeepAspectRatioByExpanding) {
+ boundingRect = rect;
+
+ QSizeF size = rect.size();
+ size.scale(nativeSize, Qt::KeepAspectRatio);
+
+ sourceRect = QRectF(
+ 0, 0, size.width() / nativeSize.width(), size.height() / nativeSize.height());
+ sourceRect.moveCenter(QPointF(0.5, 0.5));
+ }
+}
+
+void QGraphicsVideoItemPrivate::_q_present()
+{
+ if (q_ptr->isObscured()) {
+ q_ptr->update(boundingRect);
+ surface->setReady(true);
+ } else {
+ q_ptr->update(boundingRect);
+ }
+}
+
+void QGraphicsVideoItemPrivate::_q_updateNativeSize()
+{
+ QSize size = surface->surfaceFormat().sizeHint();
+ if (size.isEmpty())
+ size = rendererControl->property("nativeSize").toSize();
+
+ if (nativeSize != size) {
+ nativeSize = size;
+
+ updateRects();
+ emit q_ptr->nativeSizeChanged(nativeSize);
+ }
+}
+
+void QGraphicsVideoItemPrivate::_q_serviceDestroyed()
+{
+ rendererControl = 0;
+ service = 0;
+
+ surface->stop();
+}
+
+
+/*!
+ \class QGraphicsVideoItem
+
+ \brief The QGraphicsVideoItem class provides a graphics item which display video produced by a QMediaObject.
+
+ \inmodule QtMultimedia
+ \ingroup multimedia
+
+ Attaching a QGraphicsVideoItem to a QMediaObject allows it to display
+ the video or image output of that media object. A QGraphicsVideoItem
+ is attached to a media object by passing a pointer to the QMediaObject
+ to the setMediaObject() function.
+
+ \code
+ player = new QMediaPlayer(this);
+
+ QGraphicsVideoItem *item = new QGraphicsVideoItem;
+ player->setVideoOutput(item);
+ graphicsView->scene()->addItem(item);
+ graphicsView->show();
+
+ player->setMedia(video);
+ player->play();
+ \endcode
+
+ \bold {Note}: Only a single display output can be attached to a media
+ object at one time.
+
+ \sa QMediaObject, QMediaPlayer, QVideoWidget
+*/
+
+/*!
+ Constructs a graphics item that displays video.
+
+ The \a parent is passed to QGraphicsItem.
+*/
+QGraphicsVideoItem::QGraphicsVideoItem(QGraphicsItem *parent)
+ : QGraphicsObject(parent)
+ , d_ptr(new QGraphicsVideoItemPrivate)
+{
+ d_ptr->q_ptr = this;
+ d_ptr->surface = new QEglImageTextureSurface(this);
+
+ qRegisterMetaType<QVideoSurfaceFormat>();
+
+ connect(d_ptr->surface, SIGNAL(frameChanged()), this, SLOT(_q_present()));
+ connect(d_ptr->surface, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)),
+ this, SLOT(_q_updateNativeSize()), Qt::QueuedConnection);
+}
+
+/*!
+ Destroys a video graphics item.
+*/
+QGraphicsVideoItem::~QGraphicsVideoItem()
+{
+ if (d_ptr->rendererControl) {
+ d_ptr->rendererControl->setSurface(0);
+ d_ptr->service->releaseControl(d_ptr->rendererControl);
+ }
+
+ delete d_ptr->surface;
+ delete d_ptr;
+}
+
+/*!
+ \property QGraphicsVideoItem::mediaObject
+ \brief the media object which provides the video displayed by a graphics
+ item.
+*/
+
+QMediaObject *QGraphicsVideoItem::mediaObject() const
+{
+ return d_func()->mediaObject;
+}
+
+/*!
+ \internal
+*/
+bool QGraphicsVideoItem::setMediaObject(QMediaObject *object)
+{
+ Q_D(QGraphicsVideoItem);
+
+ if (object == d->mediaObject)
+ return true;
+
+ d->clearService();
+
+ d->mediaObject = object;
+
+ if (d->mediaObject) {
+ d->service = d->mediaObject->service();
+
+ if (d->service) {
+ QMediaControl *control = d->service->requestControl(QVideoRendererControl_iid);
+ if (control) {
+ d->rendererControl = qobject_cast<QVideoRendererControl *>(control);
+
+ if (d->rendererControl) {
+ connect(d->rendererControl, SIGNAL(nativeSizeChanged()),
+ this, SLOT(_q_updateNativeSize()), Qt::QueuedConnection);
+ d->_q_updateNativeSize();
+ //don't set the surface untill the item is painted
+ //at least once and the surface is configured
+ if (!d->updatePaintDevice)
+ d->rendererControl->setSurface(d->surface);
+ else
+ update(boundingRect());
+
+ connect(d->service, SIGNAL(destroyed()), this, SLOT(_q_serviceDestroyed()));
+
+ return true;
+ }
+ if (control)
+ d->service->releaseControl(control);
+ }
+ }
+ }
+
+ d->mediaObject = 0;
+ return false;
+}
+
+/*!
+ \property QGraphicsVideoItem::aspectRatioMode
+ \brief how a video is scaled to fit the graphics item's size.
+*/
+
+Qt::AspectRatioMode QGraphicsVideoItem::aspectRatioMode() const
+{
+ return d_func()->aspectRatioMode;
+}
+
+void QGraphicsVideoItem::setAspectRatioMode(Qt::AspectRatioMode mode)
+{
+ Q_D(QGraphicsVideoItem);
+
+ d->aspectRatioMode = mode;
+ d->updateRects();
+}
+
+/*!
+ \property QGraphicsVideoItem::offset
+ \brief the video item's offset.
+
+ QGraphicsVideoItem will draw video using the offset for its top left
+ corner.
+*/
+
+QPointF QGraphicsVideoItem::offset() const
+{
+ return d_func()->rect.topLeft();
+}
+
+void QGraphicsVideoItem::setOffset(const QPointF &offset)
+{
+ Q_D(QGraphicsVideoItem);
+
+ d->rect.moveTo(offset);
+ d->updateRects();
+}
+
+/*!
+ \property QGraphicsVideoItem::size
+ \brief the video item's size.
+
+ QGraphicsVideoItem will draw video scaled to fit size according to its
+ fillMode.
+*/
+
+QSizeF QGraphicsVideoItem::size() const
+{
+ return d_func()->rect.size();
+}
+
+void QGraphicsVideoItem::setSize(const QSizeF &size)
+{
+ Q_D(QGraphicsVideoItem);
+
+ d->rect.setSize(size.isValid() ? size : QSizeF(0, 0));
+ d->updateRects();
+}
+
+/*!
+ \property QGraphicsVideoItem::nativeSize
+ \brief the native size of the video.
+*/
+
+QSizeF QGraphicsVideoItem::nativeSize() const
+{
+ return d_func()->nativeSize;
+}
+
+/*!
+ \fn QGraphicsVideoItem::nativeSizeChanged(const QSizeF &size)
+
+ Signals that the native \a size of the video has changed.
+*/
+
+/*!
+ \reimp
+*/
+QRectF QGraphicsVideoItem::boundingRect() const
+{
+ return d_func()->boundingRect;
+}
+
+/*!
+ \reimp
+*/
+void QGraphicsVideoItem::paint(
+ QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_D(QGraphicsVideoItem);
+
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+
+ if (d->surface && d->rendererControl && d->updatePaintDevice) {
+ d->updatePaintDevice = false;
+
+ if (widget)
+ d->rendererControl->setProperty("winId", qulonglong(widget->winId()));
+
+#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
+ if (widget)
+ connect(widget, SIGNAL(destroyed()), d->surface, SLOT(viewportDestroyed()));
+
+ d->surface->setGLContext(const_cast<QGLContext *>(QGLContext::currentContext()));
+#endif
+ if (d->rendererControl->surface() != d->surface)
+ d->rendererControl->setSurface(d->surface);
+ }
+
+
+ //overlay doesn't work reliably
+
+ //check if the item is obscured:
+#ifdef ENABLE_OVERLAY
+ if (!isObscured()) {
+ bool obscured = false;
+
+ if (scene()) {
+ foreach (QGraphicsItem *item,
+ scene()->items(mapToScene(boundingRect()), Qt::IntersectsItemBoundingRect) ) {
+ if (item->flags() & QGraphicsItem::ItemHasNoContents)
+ continue;
+
+ if (item == this)
+ break;
+
+ if (collidesWithItem(item)) {
+ obscured = true;
+ break;
+ }
+ }
+ }
+
+ d->rendererControl->setProperty("overlayEnabled", !obscured);
+ }
+
+ if (d->rendererControl->property("overlayEnabled").toBool()) {
+ QTransform transform = painter->combinedTransform();
+ QRect overlayRect = transform.mapRect(d->boundingRect).toRect();
+
+ d->rendererControl->setProperty("overlayGeometry", overlayRect);
+ QMetaObject::invokeMethod(d->rendererControl, "repaintOverlay");
+
+ painter->fillRect(d->boundingRect,
+ d->rendererControl->property("colorKey").value<QColor>());
+ } else
+#endif //ENABLE_OVERLAY
+ {
+ if (d->surface && d->surface->isActive()) {
+ d->surface->paint(painter, d->boundingRect, d->sourceRect);
+ d->surface->setReady(true);
+ }
+ }
+}
+
+/*!
+ \reimp
+
+ \internal
+*/
+QVariant QGraphicsVideoItem::itemChange(GraphicsItemChange change, const QVariant &value)
+{
+ return QGraphicsItem::itemChange(change, value);
+}
+
+/*!
+ \internal
+*/
+void QGraphicsVideoItem::timerEvent(QTimerEvent *event)
+{
+ QGraphicsObject::timerEvent(event);
+}
+
+#include "moc_qgraphicsvideoitem.cpp"
+QT_END_NAMESPACE
diff --git a/src/multimediawidgets/qpaintervideosurface.cpp b/src/multimediawidgets/qpaintervideosurface.cpp
new file mode 100644
index 000000000..bd82f7841
--- /dev/null
+++ b/src/multimediawidgets/qpaintervideosurface.cpp
@@ -0,0 +1,1728 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qpaintervideosurface_p.h>
+#include <qpaintervideosurface_mac_p.h>
+
+#include <qmath.h>
+
+#include <qpainter.h>
+#include <qvariant.h>
+#include <qvideosurfaceformat.h>
+
+#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
+#include <qglshaderprogram.h>
+#ifndef GL_CLAMP_TO_EDGE
+#define GL_CLAMP_TO_EDGE 0x812F
+#endif
+#endif
+
+#include <QtDebug>
+QT_BEGIN_NAMESPACE
+
+QVideoSurfacePainter::~QVideoSurfacePainter()
+{
+}
+
+class QVideoSurfaceGenericPainter : public QVideoSurfacePainter
+{
+public:
+ QVideoSurfaceGenericPainter();
+
+ QList<QVideoFrame::PixelFormat> supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType) const;
+
+ bool isFormatSupported(
+ const QVideoSurfaceFormat &format, QVideoSurfaceFormat *similar) const;
+
+ QAbstractVideoSurface::Error start(const QVideoSurfaceFormat &format);
+ void stop();
+
+ QAbstractVideoSurface::Error setCurrentFrame(const QVideoFrame &frame);
+
+ QAbstractVideoSurface::Error paint(
+ const QRectF &target, QPainter *painter, const QRectF &source);
+
+ void updateColors(int brightness, int contrast, int hue, int saturation);
+
+private:
+ QList<QVideoFrame::PixelFormat> m_imagePixelFormats;
+ QVideoFrame m_frame;
+ QSize m_imageSize;
+ QImage::Format m_imageFormat;
+ QVideoSurfaceFormat::Direction m_scanLineDirection;
+};
+
+QVideoSurfaceGenericPainter::QVideoSurfaceGenericPainter()
+ : m_imageFormat(QImage::Format_Invalid)
+ , m_scanLineDirection(QVideoSurfaceFormat::TopToBottom)
+{
+ m_imagePixelFormats
+ << QVideoFrame::Format_RGB32
+#ifndef QT_OPENGL_ES // The raster formats should be a subset of the GL formats.
+ << QVideoFrame::Format_RGB24
+#endif
+ << QVideoFrame::Format_ARGB32
+ << QVideoFrame::Format_RGB565;
+}
+
+QList<QVideoFrame::PixelFormat> QVideoSurfaceGenericPainter::supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType) const
+{
+ switch (handleType) {
+ case QAbstractVideoBuffer::QPixmapHandle:
+ case QAbstractVideoBuffer::NoHandle:
+ return m_imagePixelFormats;
+ default:
+ ;
+ }
+ return QList<QVideoFrame::PixelFormat>();
+}
+
+bool QVideoSurfaceGenericPainter::isFormatSupported(
+ const QVideoSurfaceFormat &format, QVideoSurfaceFormat *) const
+{
+ switch (format.handleType()) {
+ case QAbstractVideoBuffer::QPixmapHandle:
+ return true;
+ case QAbstractVideoBuffer::NoHandle:
+ return m_imagePixelFormats.contains(format.pixelFormat())
+ && !format.frameSize().isEmpty();
+ default:
+ ;
+ }
+ return false;
+}
+
+QAbstractVideoSurface::Error QVideoSurfaceGenericPainter::start(const QVideoSurfaceFormat &format)
+{
+ m_frame = QVideoFrame();
+ m_imageFormat = QVideoFrame::imageFormatFromPixelFormat(format.pixelFormat());
+ m_imageSize = format.frameSize();
+ m_scanLineDirection = format.scanLineDirection();
+
+ const QAbstractVideoBuffer::HandleType t = format.handleType();
+ if (t == QAbstractVideoBuffer::NoHandle) {
+ if (m_imageFormat != QImage::Format_Invalid
+#ifdef QT_OPENGL_ES
+ && format.pixelFormat() != QVideoFrame::Format_RGB24
+#endif
+ && !m_imageSize.isEmpty()) {
+ return QAbstractVideoSurface::NoError;
+ }
+ } else if (t == QAbstractVideoBuffer::QPixmapHandle) {
+ return QAbstractVideoSurface::NoError;
+ }
+ return QAbstractVideoSurface::UnsupportedFormatError;
+}
+
+void QVideoSurfaceGenericPainter::stop()
+{
+ m_frame = QVideoFrame();
+}
+
+QAbstractVideoSurface::Error QVideoSurfaceGenericPainter::setCurrentFrame(const QVideoFrame &frame)
+{
+ m_frame = frame;
+
+ return QAbstractVideoSurface::NoError;
+}
+
+QAbstractVideoSurface::Error QVideoSurfaceGenericPainter::paint(
+ const QRectF &target, QPainter *painter, const QRectF &source)
+{
+ if (!m_frame.isValid()) {
+ painter->fillRect(target, Qt::black);
+ return QAbstractVideoSurface::NoError;
+ }
+
+ if (m_frame.handleType() == QAbstractVideoBuffer::QPixmapHandle) {
+ painter->drawPixmap(target, m_frame.handle().value<QPixmap>(), source);
+ } else if (m_frame.map(QAbstractVideoBuffer::ReadOnly)) {
+ QImage image(
+ m_frame.bits(),
+ m_imageSize.width(),
+ m_imageSize.height(),
+ m_frame.bytesPerLine(),
+ m_imageFormat);
+
+ if (m_scanLineDirection == QVideoSurfaceFormat::BottomToTop) {
+ const QTransform oldTransform = painter->transform();
+
+ painter->scale(1, -1);
+ painter->translate(0, -target.bottom());
+ painter->drawImage(
+ QRectF(target.x(), 0, target.width(), target.height()), image, source);
+ painter->setTransform(oldTransform);
+ } else {
+ painter->drawImage(target, image, source);
+ }
+
+ m_frame.unmap();
+ } else if (m_frame.isValid()) {
+ return QAbstractVideoSurface::IncorrectFormatError;
+ } else {
+ painter->fillRect(target, Qt::black);
+ }
+ return QAbstractVideoSurface::NoError;
+}
+
+void QVideoSurfaceGenericPainter::updateColors(int, int, int, int)
+{
+}
+
+#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
+
+#ifndef Q_WS_MAC
+# ifndef APIENTRYP
+# ifdef APIENTRY
+# define APIENTRYP APIENTRY *
+# else
+# define APIENTRY
+# define APIENTRYP *
+# endif
+# endif
+#else
+# define APIENTRY
+# define APIENTRYP *
+#endif
+
+#ifndef GL_TEXTURE0
+# define GL_TEXTURE0 0x84C0
+# define GL_TEXTURE1 0x84C1
+# define GL_TEXTURE2 0x84C2
+#endif
+#ifndef GL_PROGRAM_ERROR_STRING_ARB
+# define GL_PROGRAM_ERROR_STRING_ARB 0x8874
+#endif
+
+#ifndef GL_UNSIGNED_SHORT_5_6_5
+# define GL_UNSIGNED_SHORT_5_6_5 33635
+#endif
+
+class QVideoSurfaceGLPainter : public QVideoSurfacePainter
+{
+public:
+ QVideoSurfaceGLPainter(QGLContext *context);
+ ~QVideoSurfaceGLPainter();
+ QList<QVideoFrame::PixelFormat> supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType) const;
+
+ bool isFormatSupported(
+ const QVideoSurfaceFormat &format, QVideoSurfaceFormat *similar) const;
+
+ QAbstractVideoSurface::Error setCurrentFrame(const QVideoFrame &frame);
+
+ QAbstractVideoSurface::Error paint(
+ const QRectF &target, QPainter *painter, const QRectF &source);
+
+ void updateColors(int brightness, int contrast, int hue, int saturation);
+ void viewportDestroyed();
+
+protected:
+ void initRgbTextureInfo(GLenum internalFormat, GLuint format, GLenum type, const QSize &size);
+ void initYuv420PTextureInfo(const QSize &size);
+ void initYv12TextureInfo(const QSize &size);
+
+#ifndef QT_OPENGL_ES
+ typedef void (APIENTRY *_glActiveTexture) (GLenum);
+ _glActiveTexture glActiveTexture;
+#endif
+
+ QList<QVideoFrame::PixelFormat> m_imagePixelFormats;
+ QList<QVideoFrame::PixelFormat> m_glPixelFormats;
+ QMatrix4x4 m_colorMatrix;
+ QVideoFrame m_frame;
+
+ QGLContext *m_context;
+ QAbstractVideoBuffer::HandleType m_handleType;
+ QVideoSurfaceFormat::Direction m_scanLineDirection;
+ QVideoSurfaceFormat::YCbCrColorSpace m_colorSpace;
+ GLenum m_textureFormat;
+ GLuint m_textureInternalFormat;
+ GLenum m_textureType;
+ int m_textureCount;
+ GLuint m_textureIds[3];
+ int m_textureWidths[3];
+ int m_textureHeights[3];
+ int m_textureOffsets[3];
+ bool m_yuv;
+};
+
+QVideoSurfaceGLPainter::QVideoSurfaceGLPainter(QGLContext *context)
+ : m_context(context)
+ , m_handleType(QAbstractVideoBuffer::NoHandle)
+ , m_scanLineDirection(QVideoSurfaceFormat::TopToBottom)
+ , m_colorSpace(QVideoSurfaceFormat::YCbCr_BT601)
+ , m_textureFormat(0)
+ , m_textureInternalFormat(0)
+ , m_textureType(0)
+ , m_textureCount(0)
+ , m_yuv(false)
+{
+#ifndef QT_OPENGL_ES
+ glActiveTexture = (_glActiveTexture)m_context->getProcAddress(QLatin1String("glActiveTexture"));
+#endif
+}
+
+QVideoSurfaceGLPainter::~QVideoSurfaceGLPainter()
+{
+}
+
+void QVideoSurfaceGLPainter::viewportDestroyed()
+{
+ m_context = 0;
+}
+
+QList<QVideoFrame::PixelFormat> QVideoSurfaceGLPainter::supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType) const
+{
+ switch (handleType) {
+ case QAbstractVideoBuffer::NoHandle:
+ return m_imagePixelFormats;
+ case QAbstractVideoBuffer::QPixmapHandle:
+ case QAbstractVideoBuffer::GLTextureHandle:
+ return m_glPixelFormats;
+ default:
+ ;
+ }
+ return QList<QVideoFrame::PixelFormat>();
+}
+
+bool QVideoSurfaceGLPainter::isFormatSupported(
+ const QVideoSurfaceFormat &format, QVideoSurfaceFormat *) const
+{
+ if (format.frameSize().isEmpty()) {
+ return false;
+ } else {
+ switch (format.handleType()) {
+ case QAbstractVideoBuffer::NoHandle:
+ return m_imagePixelFormats.contains(format.pixelFormat());
+ case QAbstractVideoBuffer::QPixmapHandle:
+ case QAbstractVideoBuffer::GLTextureHandle:
+ return m_glPixelFormats.contains(format.pixelFormat());
+ default:
+ ;
+ }
+ }
+ return false;
+}
+
+QAbstractVideoSurface::Error QVideoSurfaceGLPainter::setCurrentFrame(const QVideoFrame &frame)
+{
+ m_frame = frame;
+
+ if (m_handleType == QAbstractVideoBuffer::GLTextureHandle) {
+ m_textureIds[0] = frame.handle().toInt();
+ } else if (m_frame.map(QAbstractVideoBuffer::ReadOnly)) {
+ m_context->makeCurrent();
+
+ for (int i = 0; i < m_textureCount; ++i) {
+ glBindTexture(GL_TEXTURE_2D, m_textureIds[i]);
+ glTexImage2D(
+ GL_TEXTURE_2D,
+ 0,
+ m_textureInternalFormat,
+ m_textureWidths[i],
+ m_textureHeights[i],
+ 0,
+ m_textureFormat,
+ m_textureType,
+ m_frame.bits() + m_textureOffsets[i]);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ }
+ m_frame.unmap();
+ } else if (m_handleType != QAbstractVideoBuffer::QPixmapHandle && m_frame.isValid()) {
+ return QAbstractVideoSurface::IncorrectFormatError;
+ }
+
+ return QAbstractVideoSurface::NoError;
+}
+
+QAbstractVideoSurface::Error QVideoSurfaceGLPainter::paint(
+ const QRectF &target, QPainter *painter, const QRectF &source)
+{
+ if (!m_frame.isValid()) {
+ painter->fillRect(target, Qt::black);
+ return QAbstractVideoSurface::NoError;
+ }
+
+ if (m_frame.handleType() == QAbstractVideoBuffer::QPixmapHandle) {
+ painter->drawPixmap(target, m_frame.handle().value<QPixmap>(), source);
+ } else if (m_frame.isValid()) {
+ return QAbstractVideoSurface::IncorrectFormatError;
+ } else {
+ painter->fillRect(target, Qt::black);
+ }
+ return QAbstractVideoSurface::NoError;
+}
+
+void QVideoSurfaceGLPainter::updateColors(int brightness, int contrast, int hue, int saturation)
+{
+ const qreal b = brightness / 200.0;
+ const qreal c = contrast / 100.0 + 1.0;
+ const qreal h = hue / 100.0;
+ const qreal s = saturation / 100.0 + 1.0;
+
+ const qreal cosH = qCos(M_PI * h);
+ const qreal sinH = qSin(M_PI * h);
+
+ const qreal h11 = 0.787 * cosH - 0.213 * sinH + 0.213;
+ const qreal h21 = -0.213 * cosH + 0.143 * sinH + 0.213;
+ const qreal h31 = -0.213 * cosH - 0.787 * sinH + 0.213;
+
+ const qreal h12 = -0.715 * cosH - 0.715 * sinH + 0.715;
+ const qreal h22 = 0.285 * cosH + 0.140 * sinH + 0.715;
+ const qreal h32 = -0.715 * cosH + 0.715 * sinH + 0.715;
+
+ const qreal h13 = -0.072 * cosH + 0.928 * sinH + 0.072;
+ const qreal h23 = -0.072 * cosH - 0.283 * sinH + 0.072;
+ const qreal h33 = 0.928 * cosH + 0.072 * sinH + 0.072;
+
+ const qreal sr = (1.0 - s) * 0.3086;
+ const qreal sg = (1.0 - s) * 0.6094;
+ const qreal sb = (1.0 - s) * 0.0820;
+
+ const qreal sr_s = sr + s;
+ const qreal sg_s = sg + s;
+ const qreal sb_s = sr + s;
+
+ const float m4 = (s + sr + sg + sb) * (0.5 - 0.5 * c + b);
+
+ m_colorMatrix(0, 0) = c * (sr_s * h11 + sg * h21 + sb * h31);
+ m_colorMatrix(0, 1) = c * (sr_s * h12 + sg * h22 + sb * h32);
+ m_colorMatrix(0, 2) = c * (sr_s * h13 + sg * h23 + sb * h33);
+ m_colorMatrix(0, 3) = m4;
+
+ m_colorMatrix(1, 0) = c * (sr * h11 + sg_s * h21 + sb * h31);
+ m_colorMatrix(1, 1) = c * (sr * h12 + sg_s * h22 + sb * h32);
+ m_colorMatrix(1, 2) = c * (sr * h13 + sg_s * h23 + sb * h33);
+ m_colorMatrix(1, 3) = m4;
+
+ m_colorMatrix(2, 0) = c * (sr * h11 + sg * h21 + sb_s * h31);
+ m_colorMatrix(2, 1) = c * (sr * h12 + sg * h22 + sb_s * h32);
+ m_colorMatrix(2, 2) = c * (sr * h13 + sg * h23 + sb_s * h33);
+ m_colorMatrix(2, 3) = m4;
+
+ m_colorMatrix(3, 0) = 0.0;
+ m_colorMatrix(3, 1) = 0.0;
+ m_colorMatrix(3, 2) = 0.0;
+ m_colorMatrix(3, 3) = 1.0;
+
+ if (m_yuv) {
+ QMatrix4x4 colorSpaceMatrix;
+
+ switch (m_colorSpace) {
+ case QVideoSurfaceFormat::YCbCr_JPEG:
+ colorSpaceMatrix = QMatrix4x4(
+ 1.0, 0.000, 1.402, -0.701,
+ 1.0, -0.344, -0.714, 0.529,
+ 1.0, 1.772, 0.000, -0.886,
+ 0.0, 0.000, 0.000, 1.0000);
+ break;
+ case QVideoSurfaceFormat::YCbCr_BT709:
+ case QVideoSurfaceFormat::YCbCr_xvYCC709:
+ colorSpaceMatrix = QMatrix4x4(
+ 1.164, 0.000, 1.793, -0.5727,
+ 1.164, -0.534, -0.213, 0.3007,
+ 1.164, 2.115, 0.000, -1.1302,
+ 0.0, 0.000, 0.000, 1.0000);
+ break;
+ default: //BT 601:
+ colorSpaceMatrix = QMatrix4x4(
+ 1.164, 0.000, 1.596, -0.8708,
+ 1.164, -0.392, -0.813, 0.5296,
+ 1.164, 2.017, 0.000, -1.081,
+ 0.0, 0.000, 0.000, 1.0000);
+ }
+
+ m_colorMatrix = m_colorMatrix * colorSpaceMatrix;
+ }
+}
+
+void QVideoSurfaceGLPainter::initRgbTextureInfo(
+ GLenum internalFormat, GLuint format, GLenum type, const QSize &size)
+{
+ m_yuv = false;
+ m_textureInternalFormat = internalFormat;
+ m_textureFormat = format;
+ m_textureType = type;
+ m_textureCount = 1;
+ m_textureWidths[0] = size.width();
+ m_textureHeights[0] = size.height();
+ m_textureOffsets[0] = 0;
+}
+
+void QVideoSurfaceGLPainter::initYuv420PTextureInfo(const QSize &size)
+{
+ int bytesPerLine = (size.width() + 3) & ~3;
+ int bytesPerLine2 = (size.width() / 2 + 3) & ~3;
+
+ m_yuv = true;
+ m_textureInternalFormat = GL_LUMINANCE;
+ m_textureFormat = GL_LUMINANCE;
+ m_textureType = GL_UNSIGNED_BYTE;
+ m_textureCount = 3;
+ m_textureWidths[0] = bytesPerLine;
+ m_textureHeights[0] = size.height();
+ m_textureOffsets[0] = 0;
+ m_textureWidths[1] = bytesPerLine2;
+ m_textureHeights[1] = size.height() / 2;
+ m_textureOffsets[1] = bytesPerLine * size.height();
+ m_textureWidths[2] = bytesPerLine2;
+ m_textureHeights[2] = size.height() / 2;
+ m_textureOffsets[2] = bytesPerLine * size.height() + bytesPerLine2 * size.height()/2;
+}
+
+void QVideoSurfaceGLPainter::initYv12TextureInfo(const QSize &size)
+{
+ int bytesPerLine = (size.width() + 3) & ~3;
+ int bytesPerLine2 = (size.width() / 2 + 3) & ~3;
+
+ m_yuv = true;
+ m_textureInternalFormat = GL_LUMINANCE;
+ m_textureFormat = GL_LUMINANCE;
+ m_textureType = GL_UNSIGNED_BYTE;
+ m_textureCount = 3;
+ m_textureWidths[0] = bytesPerLine;
+ m_textureHeights[0] = size.height();
+ m_textureOffsets[0] = 0;
+ m_textureWidths[1] = bytesPerLine2;
+ m_textureHeights[1] = size.height() / 2;
+ m_textureOffsets[1] = bytesPerLine * size.height() + bytesPerLine2 * size.height()/2;
+ m_textureWidths[2] = bytesPerLine2;
+ m_textureHeights[2] = size.height() / 2;
+ m_textureOffsets[2] = bytesPerLine * size.height();
+}
+
+#ifndef QT_OPENGL_ES
+
+# ifndef GL_FRAGMENT_PROGRAM_ARB
+# define GL_FRAGMENT_PROGRAM_ARB 0x8804
+# define GL_PROGRAM_FORMAT_ASCII_ARB 0x8875
+# endif
+
+// Paints an RGB32 frame
+static const char *qt_arbfp_xrgbShaderProgram =
+ "!!ARBfp1.0\n"
+ "PARAM matrix[4] = { program.local[0..2],"
+ "{ 0.0, 0.0, 0.0, 1.0 } };\n"
+ "TEMP xrgb;\n"
+ "TEX xrgb.xyz, fragment.texcoord[0], texture[0], 2D;\n"
+ "MOV xrgb.w, matrix[3].w;\n"
+ "DP4 result.color.x, xrgb.zyxw, matrix[0];\n"
+ "DP4 result.color.y, xrgb.zyxw, matrix[1];\n"
+ "DP4 result.color.z, xrgb.zyxw, matrix[2];\n"
+ "END";
+
+// Paints an ARGB frame.
+static const char *qt_arbfp_argbShaderProgram =
+ "!!ARBfp1.0\n"
+ "PARAM matrix[4] = { program.local[0..2],"
+ "{ 0.0, 0.0, 0.0, 1.0 } };\n"
+ "TEMP argb;\n"
+ "TEX argb, fragment.texcoord[0], texture[0], 2D;\n"
+ "MOV argb.w, matrix[3].w;\n"
+ "DP4 result.color.x, argb.zyxw, matrix[0];\n"
+ "DP4 result.color.y, argb.zyxw, matrix[1];\n"
+ "DP4 result.color.z, argb.zyxw, matrix[2];\n"
+ "TEX result.color.w, fragment.texcoord[0], texture, 2D;\n"
+ "END";
+
+// Paints an RGB(A) frame.
+static const char *qt_arbfp_rgbShaderProgram =
+ "!!ARBfp1.0\n"
+ "PARAM matrix[4] = { program.local[0..2],"
+ "{ 0.0, 0.0, 0.0, 1.0 } };\n"
+ "TEMP rgb;\n"
+ "TEX rgb, fragment.texcoord[0], texture[0], 2D;\n"
+ "MOV rgb.w, matrix[3].w;\n"
+ "DP4 result.color.x, rgb, matrix[0];\n"
+ "DP4 result.color.y, rgb, matrix[1];\n"
+ "DP4 result.color.z, rgb, matrix[2];\n"
+ "TEX result.color.w, fragment.texcoord[0], texture, 2D;\n"
+ "END";
+
+// Paints a YUV420P or YV12 frame.
+static const char *qt_arbfp_yuvPlanarShaderProgram =
+ "!!ARBfp1.0\n"
+ "PARAM matrix[4] = { program.local[0..2],"
+ "{ 0.0, 0.0, 0.0, 1.0 } };\n"
+ "TEMP yuv;\n"
+ "TEX yuv.x, fragment.texcoord[0], texture[0], 2D;\n"
+ "TEX yuv.y, fragment.texcoord[0], texture[1], 2D;\n"
+ "TEX yuv.z, fragment.texcoord[0], texture[2], 2D;\n"
+ "MOV yuv.w, matrix[3].w;\n"
+ "DP4 result.color.x, yuv, matrix[0];\n"
+ "DP4 result.color.y, yuv, matrix[1];\n"
+ "DP4 result.color.z, yuv, matrix[2];\n"
+ "END";
+
+// Paints a YUV444 frame.
+static const char *qt_arbfp_xyuvShaderProgram =
+ "!!ARBfp1.0\n"
+ "PARAM matrix[4] = { program.local[0..2],"
+ "{ 0.0, 0.0, 0.0, 1.0 } };\n"
+ "TEMP ayuv;\n"
+ "TEX ayuv, fragment.texcoord[0], texture[0], 2D;\n"
+ "MOV ayuv.x, matrix[3].w;\n"
+ "DP4 result.color.x, ayuv.yzwx, matrix[0];\n"
+ "DP4 result.color.y, ayuv.yzwx, matrix[1];\n"
+ "DP4 result.color.z, ayuv.yzwx, matrix[2];\n"
+ "END";
+
+// Paints a AYUV444 frame.
+static const char *qt_arbfp_ayuvShaderProgram =
+ "!!ARBfp1.0\n"
+ "PARAM matrix[4] = { program.local[0..2],"
+ "{ 0.0, 0.0, 0.0, 1.0 } };\n"
+ "TEMP ayuv;\n"
+ "TEX ayuv, fragment.texcoord[0], texture[0], 2D;\n"
+ "MOV ayuv.x, matrix[3].w;\n"
+ "DP4 result.color.x, ayuv.yzwx, matrix[0];\n"
+ "DP4 result.color.y, ayuv.yzwx, matrix[1];\n"
+ "DP4 result.color.z, ayuv.yzwx, matrix[2];\n"
+ "TEX result.color.w, fragment.texcoord[0], texture, 2D;\n"
+ "END";
+
+class QVideoSurfaceArbFpPainter : public QVideoSurfaceGLPainter
+{
+public:
+ QVideoSurfaceArbFpPainter(QGLContext *context);
+
+ QAbstractVideoSurface::Error start(const QVideoSurfaceFormat &format);
+ void stop();
+
+ QAbstractVideoSurface::Error paint(
+ const QRectF &target, QPainter *painter, const QRectF &source);
+
+private:
+ typedef void (APIENTRY *_glProgramStringARB) (GLenum, GLenum, GLsizei, const GLvoid *);
+ typedef void (APIENTRY *_glBindProgramARB) (GLenum, GLuint);
+ typedef void (APIENTRY *_glDeleteProgramsARB) (GLsizei, const GLuint *);
+ typedef void (APIENTRY *_glGenProgramsARB) (GLsizei, GLuint *);
+ typedef void (APIENTRY *_glProgramLocalParameter4fARB) (
+ GLenum, GLuint, GLfloat, GLfloat, GLfloat, GLfloat);
+ typedef void (APIENTRY *_glActiveTexture) (GLenum);
+
+ _glProgramStringARB glProgramStringARB;
+ _glBindProgramARB glBindProgramARB;
+ _glDeleteProgramsARB glDeleteProgramsARB;
+ _glGenProgramsARB glGenProgramsARB;
+ _glProgramLocalParameter4fARB glProgramLocalParameter4fARB;
+
+ GLuint m_programId;
+ QSize m_frameSize;
+};
+
+QVideoSurfaceArbFpPainter::QVideoSurfaceArbFpPainter(QGLContext *context)
+ : QVideoSurfaceGLPainter(context)
+ , m_programId(0)
+{
+ glProgramStringARB = (_glProgramStringARB) m_context->getProcAddress(
+ QLatin1String("glProgramStringARB"));
+ glBindProgramARB = (_glBindProgramARB) m_context->getProcAddress(
+ QLatin1String("glBindProgramARB"));
+ glDeleteProgramsARB = (_glDeleteProgramsARB) m_context->getProcAddress(
+ QLatin1String("glDeleteProgramsARB"));
+ glGenProgramsARB = (_glGenProgramsARB) m_context->getProcAddress(
+ QLatin1String("glGenProgramsARB"));
+ glProgramLocalParameter4fARB = (_glProgramLocalParameter4fARB) m_context->getProcAddress(
+ QLatin1String("glProgramLocalParameter4fARB"));
+
+ m_imagePixelFormats
+ << QVideoFrame::Format_RGB32
+ << QVideoFrame::Format_BGR32
+ << QVideoFrame::Format_ARGB32
+ << QVideoFrame::Format_RGB24
+ << QVideoFrame::Format_BGR24
+ << QVideoFrame::Format_RGB565
+ << QVideoFrame::Format_AYUV444
+ << QVideoFrame::Format_YUV444
+ << QVideoFrame::Format_YV12
+ << QVideoFrame::Format_YUV420P;
+ m_glPixelFormats
+ << QVideoFrame::Format_RGB32
+ << QVideoFrame::Format_ARGB32;
+}
+
+QAbstractVideoSurface::Error QVideoSurfaceArbFpPainter::start(const QVideoSurfaceFormat &format)
+{
+ Q_ASSERT(m_textureCount == 0);
+
+ QAbstractVideoSurface::Error error = QAbstractVideoSurface::NoError;
+
+ m_context->makeCurrent();
+
+ const char *program = 0;
+
+ if (format.handleType() == QAbstractVideoBuffer::NoHandle) {
+ switch (format.pixelFormat()) {
+ case QVideoFrame::Format_RGB32:
+ initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
+ program = qt_arbfp_xrgbShaderProgram;
+ break;
+ case QVideoFrame::Format_BGR32:
+ initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
+ program = qt_arbfp_rgbShaderProgram;
+ break;
+ case QVideoFrame::Format_ARGB32:
+ initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
+ program = qt_arbfp_argbShaderProgram;
+ break;
+ case QVideoFrame::Format_RGB24:
+ initRgbTextureInfo(GL_RGB8, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
+ program = qt_arbfp_rgbShaderProgram;
+ break;
+ case QVideoFrame::Format_BGR24:
+ initRgbTextureInfo(GL_RGB8, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
+ program = qt_arbfp_xrgbShaderProgram;
+ break;
+ case QVideoFrame::Format_RGB565:
+ initRgbTextureInfo(GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, format.frameSize());
+ program = qt_arbfp_rgbShaderProgram;
+ break;
+ case QVideoFrame::Format_YUV444:
+ initRgbTextureInfo(GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, format.frameSize());
+ program = qt_arbfp_xyuvShaderProgram;
+ m_yuv = true;
+ break;
+ case QVideoFrame::Format_AYUV444:
+ initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
+ program = qt_arbfp_ayuvShaderProgram;
+ m_yuv = true;
+ break;
+ case QVideoFrame::Format_YV12:
+ initYv12TextureInfo(format.frameSize());
+ program = qt_arbfp_yuvPlanarShaderProgram;
+ break;
+ case QVideoFrame::Format_YUV420P:
+ initYuv420PTextureInfo(format.frameSize());
+ program = qt_arbfp_yuvPlanarShaderProgram;
+ break;
+ default:
+ break;
+ }
+ } else if (format.handleType() == QAbstractVideoBuffer::GLTextureHandle) {
+ switch (format.pixelFormat()) {
+ case QVideoFrame::Format_RGB32:
+ case QVideoFrame::Format_ARGB32:
+ m_yuv = false;
+ m_textureCount = 1;
+ program = qt_arbfp_rgbShaderProgram;
+ break;
+ default:
+ break;
+ }
+ } else if (format.handleType() == QAbstractVideoBuffer::QPixmapHandle) {
+ m_handleType = QAbstractVideoBuffer::QPixmapHandle;
+ return QAbstractVideoSurface::NoError;
+ }
+
+ if (!program) {
+ error = QAbstractVideoSurface::UnsupportedFormatError;
+ } else {
+ glGenProgramsARB(1, &m_programId);
+
+ GLenum glError = glGetError();
+ if (glError != GL_NO_ERROR) {
+ qWarning("QPainterVideoSurface: ARBfb Shader allocation error %x", int(glError));
+ m_textureCount = 0;
+ m_programId = 0;
+
+ error = QAbstractVideoSurface::ResourceError;
+ } else {
+ glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_programId);
+ glProgramStringARB(
+ GL_FRAGMENT_PROGRAM_ARB,
+ GL_PROGRAM_FORMAT_ASCII_ARB,
+ qstrlen(program),
+ reinterpret_cast<const GLvoid *>(program));
+
+ if ((glError = glGetError()) != GL_NO_ERROR) {
+ const GLubyte* errorString = glGetString(GL_PROGRAM_ERROR_STRING_ARB);
+
+ qWarning("QPainterVideoSurface: ARBfp Shader compile error %x, %s",
+ int(glError),
+ reinterpret_cast<const char *>(errorString));
+ glDeleteProgramsARB(1, &m_programId);
+
+ m_textureCount = 0;
+ m_programId = 0;
+
+ error = QAbstractVideoSurface::ResourceError;
+ } else {
+ m_handleType = format.handleType();
+ m_scanLineDirection = format.scanLineDirection();
+ m_frameSize = format.frameSize();
+ m_colorSpace = format.yCbCrColorSpace();
+
+ if (m_handleType == QAbstractVideoBuffer::NoHandle)
+ glGenTextures(m_textureCount, m_textureIds);
+ }
+ }
+ }
+
+ return error;
+}
+
+void QVideoSurfaceArbFpPainter::stop()
+{
+ if (m_context) {
+ m_context->makeCurrent();
+
+ if (m_handleType != QAbstractVideoBuffer::GLTextureHandle)
+ glDeleteTextures(m_textureCount, m_textureIds);
+ glDeleteProgramsARB(1, &m_programId);
+ }
+
+ m_textureCount = 0;
+ m_programId = 0;
+ m_handleType = QAbstractVideoBuffer::NoHandle;
+}
+
+QAbstractVideoSurface::Error QVideoSurfaceArbFpPainter::paint(
+ const QRectF &target, QPainter *painter, const QRectF &source)
+{
+ if (!m_frame.isValid()) {
+ painter->fillRect(target, Qt::black);
+ return QAbstractVideoSurface::NoError;
+ }
+
+ const QAbstractVideoBuffer::HandleType h = m_frame.handleType();
+ if (h == QAbstractVideoBuffer::NoHandle || h == QAbstractVideoBuffer::GLTextureHandle) {
+ bool stencilTestEnabled = glIsEnabled(GL_STENCIL_TEST);
+ bool scissorTestEnabled = glIsEnabled(GL_SCISSOR_TEST);
+
+ painter->beginNativePainting();
+
+ if (stencilTestEnabled)
+ glEnable(GL_STENCIL_TEST);
+ if (scissorTestEnabled)
+ glEnable(GL_SCISSOR_TEST);
+
+ const float txLeft = source.left() / m_frameSize.width();
+ const float txRight = source.right() / m_frameSize.width();
+ const float txTop = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
+ ? source.top() / m_frameSize.height()
+ : source.bottom() / m_frameSize.height();
+ const float txBottom = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
+ ? source.bottom() / m_frameSize.height()
+ : source.top() / m_frameSize.height();
+
+ const float tx_array[] =
+ {
+ txLeft , txBottom,
+ txRight, txBottom,
+ txLeft , txTop,
+ txRight, txTop
+ };
+
+ const GLfloat vTop = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
+ ? target.top()
+ : target.bottom() + 1;
+ const GLfloat vBottom = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
+ ? target.bottom() + 1
+ : target.top();
+
+ const GLfloat v_array[] =
+ {
+ GLfloat(target.left()) , GLfloat(vBottom),
+ GLfloat(target.right() + 1), GLfloat(vBottom),
+ GLfloat(target.left()) , GLfloat(vTop),
+ GLfloat(target.right() + 1), GLfloat(vTop)
+ };
+
+ glEnable(GL_FRAGMENT_PROGRAM_ARB);
+ glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_programId);
+
+ glProgramLocalParameter4fARB(
+ GL_FRAGMENT_PROGRAM_ARB,
+ 0,
+ m_colorMatrix(0, 0),
+ m_colorMatrix(0, 1),
+ m_colorMatrix(0, 2),
+ m_colorMatrix(0, 3));
+ glProgramLocalParameter4fARB(
+ GL_FRAGMENT_PROGRAM_ARB,
+ 1,
+ m_colorMatrix(1, 0),
+ m_colorMatrix(1, 1),
+ m_colorMatrix(1, 2),
+ m_colorMatrix(1, 3));
+ glProgramLocalParameter4fARB(
+ GL_FRAGMENT_PROGRAM_ARB,
+ 2,
+ m_colorMatrix(2, 0),
+ m_colorMatrix(2, 1),
+ m_colorMatrix(2, 2),
+ m_colorMatrix(2, 3));
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, m_textureIds[0]);
+
+ if (m_textureCount == 3) {
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, m_textureIds[1]);
+ glActiveTexture(GL_TEXTURE2);
+ glBindTexture(GL_TEXTURE_2D, m_textureIds[2]);
+ glActiveTexture(GL_TEXTURE0);
+ }
+
+ glVertexPointer(2, GL_FLOAT, 0, v_array);
+ glTexCoordPointer(2, GL_FLOAT, 0, tx_array);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisable(GL_FRAGMENT_PROGRAM_ARB);
+
+ painter->endNativePainting();
+
+ return QAbstractVideoSurface::NoError;
+ }
+
+ return QVideoSurfaceGLPainter::paint(target, painter, source);
+}
+
+#endif
+
+static const char *qt_glsl_vertexShaderProgram =
+ "attribute highp vec4 vertexCoordArray;\n"
+ "attribute highp vec2 textureCoordArray;\n"
+ "uniform highp mat4 positionMatrix;\n"
+ "varying highp vec2 textureCoord;\n"
+ "void main(void)\n"
+ "{\n"
+ " gl_Position = positionMatrix * vertexCoordArray;\n"
+ " textureCoord = textureCoordArray;\n"
+ "}\n";
+
+// Paints an RGB32 frame
+static const char *qt_glsl_xrgbShaderProgram =
+ "uniform sampler2D texRgb;\n"
+ "uniform mediump mat4 colorMatrix;\n"
+ "varying highp vec2 textureCoord;\n"
+ "void main(void)\n"
+ "{\n"
+ " highp vec4 color = vec4(texture2D(texRgb, textureCoord.st).bgr, 1.0);\n"
+ " gl_FragColor = colorMatrix * color;\n"
+ "}\n";
+
+// Paints an ARGB frame.
+static const char *qt_glsl_argbShaderProgram =
+ "uniform sampler2D texRgb;\n"
+ "uniform mediump mat4 colorMatrix;\n"
+ "varying highp vec2 textureCoord;\n"
+ "void main(void)\n"
+ "{\n"
+ " highp vec4 color = vec4(texture2D(texRgb, textureCoord.st).bgr, 1.0);\n"
+ " color = colorMatrix * color;\n"
+ " gl_FragColor = vec4(color.rgb, texture2D(texRgb, textureCoord.st).a);\n"
+ "}\n";
+
+// Paints an RGB(A) frame.
+static const char *qt_glsl_rgbShaderProgram =
+ "uniform sampler2D texRgb;\n"
+ "uniform mediump mat4 colorMatrix;\n"
+ "varying highp vec2 textureCoord;\n"
+ "void main(void)\n"
+ "{\n"
+ " highp vec4 color = vec4(texture2D(texRgb, textureCoord.st).rgb, 1.0);\n"
+ " color = colorMatrix * color;\n"
+ " gl_FragColor = vec4(color.rgb, texture2D(texRgb, textureCoord.st).a);\n"
+ "}\n";
+
+// Paints a YUV420P or YV12 frame.
+static const char *qt_glsl_yuvPlanarShaderProgram =
+ "uniform sampler2D texY;\n"
+ "uniform sampler2D texU;\n"
+ "uniform sampler2D texV;\n"
+ "uniform mediump mat4 colorMatrix;\n"
+ "varying highp vec2 textureCoord;\n"
+ "void main(void)\n"
+ "{\n"
+ " highp vec4 color = vec4(\n"
+ " texture2D(texY, textureCoord.st).r,\n"
+ " texture2D(texU, textureCoord.st).r,\n"
+ " texture2D(texV, textureCoord.st).r,\n"
+ " 1.0);\n"
+ " gl_FragColor = colorMatrix * color;\n"
+ "}\n";
+
+// Paints a YUV444 frame.
+static const char *qt_glsl_xyuvShaderProgram =
+ "uniform sampler2D texRgb;\n"
+ "uniform mediump mat4 colorMatrix;\n"
+ "varying highp vec2 textureCoord;\n"
+ "void main(void)\n"
+ "{\n"
+ " highp vec4 color = vec4(texture2D(texRgb, textureCoord.st).gba, 1.0);\n"
+ " gl_FragColor = colorMatrix * color;\n"
+ "}\n";
+
+// Paints a AYUV444 frame.
+static const char *qt_glsl_ayuvShaderProgram =
+ "uniform sampler2D texRgb;\n"
+ "uniform mediump mat4 colorMatrix;\n"
+ "varying highp vec2 textureCoord;\n"
+ "void main(void)\n"
+ "{\n"
+ " highp vec4 color = vec4(texture2D(texRgb, textureCoord.st).gba, 1.0);\n"
+ " color = colorMatrix * color;\n"
+ " gl_FragColor = vec4(color.rgb, texture2D(texRgb, textureCoord.st).r);\n"
+ "}\n";
+
+class QVideoSurfaceGlslPainter : public QVideoSurfaceGLPainter
+{
+public:
+ QVideoSurfaceGlslPainter(QGLContext *context);
+
+ QAbstractVideoSurface::Error start(const QVideoSurfaceFormat &format);
+ void stop();
+
+ QAbstractVideoSurface::Error paint(
+ const QRectF &target, QPainter *painter, const QRectF &source);
+
+private:
+ QGLShaderProgram m_program;
+ QSize m_frameSize;
+};
+
+QVideoSurfaceGlslPainter::QVideoSurfaceGlslPainter(QGLContext *context)
+ : QVideoSurfaceGLPainter(context)
+ , m_program(context)
+{
+ m_imagePixelFormats
+ << QVideoFrame::Format_RGB32
+ << QVideoFrame::Format_BGR32
+ << QVideoFrame::Format_ARGB32
+#ifndef QT_OPENGL_ES
+ << QVideoFrame::Format_RGB24
+ << QVideoFrame::Format_BGR24
+#endif
+ << QVideoFrame::Format_RGB565
+ << QVideoFrame::Format_YUV444
+ << QVideoFrame::Format_AYUV444
+ << QVideoFrame::Format_YV12
+ << QVideoFrame::Format_YUV420P;
+ m_glPixelFormats
+ << QVideoFrame::Format_RGB32
+ << QVideoFrame::Format_ARGB32;
+}
+
+QAbstractVideoSurface::Error QVideoSurfaceGlslPainter::start(const QVideoSurfaceFormat &format)
+{
+ Q_ASSERT(m_textureCount == 0);
+
+ QAbstractVideoSurface::Error error = QAbstractVideoSurface::NoError;
+
+ m_context->makeCurrent();
+
+ const char *fragmentProgram = 0;
+
+ if (format.handleType() == QAbstractVideoBuffer::NoHandle) {
+ switch (format.pixelFormat()) {
+ case QVideoFrame::Format_RGB32:
+ initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
+ fragmentProgram = qt_glsl_xrgbShaderProgram;
+ break;
+ case QVideoFrame::Format_BGR32:
+ initRgbTextureInfo(GL_RGB, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
+ fragmentProgram = qt_glsl_rgbShaderProgram;
+ break;
+ case QVideoFrame::Format_ARGB32:
+ initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
+ fragmentProgram = qt_glsl_argbShaderProgram;
+ break;
+#ifndef QT_OPENGL_ES
+ case QVideoFrame::Format_RGB24:
+ initRgbTextureInfo(GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, format.frameSize());
+ fragmentProgram = qt_glsl_rgbShaderProgram;
+ break;
+ case QVideoFrame::Format_BGR24:
+ initRgbTextureInfo(GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, format.frameSize());
+ fragmentProgram = qt_glsl_argbShaderProgram;
+ break;
+#endif
+ case QVideoFrame::Format_RGB565:
+ initRgbTextureInfo(GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, format.frameSize());
+ fragmentProgram = qt_glsl_rgbShaderProgram;
+ break;
+ case QVideoFrame::Format_YUV444:
+ initRgbTextureInfo(GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, format.frameSize());
+ fragmentProgram = qt_glsl_xyuvShaderProgram;
+ m_yuv = true;
+ break;
+ case QVideoFrame::Format_AYUV444:
+ initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
+ fragmentProgram = qt_glsl_ayuvShaderProgram;
+ m_yuv = true;
+ break;
+ case QVideoFrame::Format_YV12:
+ initYv12TextureInfo(format.frameSize());
+ fragmentProgram = qt_glsl_yuvPlanarShaderProgram;
+ break;
+ case QVideoFrame::Format_YUV420P:
+ initYuv420PTextureInfo(format.frameSize());
+ fragmentProgram = qt_glsl_yuvPlanarShaderProgram;
+ break;
+ default:
+ break;
+ }
+ } else if (format.handleType() == QAbstractVideoBuffer::GLTextureHandle) {
+ switch (format.pixelFormat()) {
+ case QVideoFrame::Format_RGB32:
+ case QVideoFrame::Format_ARGB32:
+ m_yuv = false;
+ m_textureCount = 1;
+ fragmentProgram = qt_glsl_rgbShaderProgram;
+ break;
+ default:
+ break;
+ }
+ } else if (format.handleType() == QAbstractVideoBuffer::QPixmapHandle) {
+ m_handleType = QAbstractVideoBuffer::QPixmapHandle;
+ return QAbstractVideoSurface::NoError;
+ }
+
+ if (!fragmentProgram) {
+ error = QAbstractVideoSurface::UnsupportedFormatError;
+ } else if (!m_program.addShaderFromSourceCode(QGLShader::Vertex, qt_glsl_vertexShaderProgram)) {
+ qWarning("QPainterVideoSurface: Vertex shader compile error %s",
+ qPrintable(m_program.log()));
+ error = QAbstractVideoSurface::ResourceError;
+ } else if (!m_program.addShaderFromSourceCode(QGLShader::Fragment, fragmentProgram)) {
+ qWarning("QPainterVideoSurface: Shader compile error %s", qPrintable(m_program.log()));
+ error = QAbstractVideoSurface::ResourceError;
+ m_program.removeAllShaders();
+ } else if(!m_program.link()) {
+ qWarning("QPainterVideoSurface: Shader link error %s", qPrintable(m_program.log()));
+ m_program.removeAllShaders();
+ error = QAbstractVideoSurface::ResourceError;
+ } else {
+ m_handleType = format.handleType();
+ m_scanLineDirection = format.scanLineDirection();
+ m_frameSize = format.frameSize();
+ m_colorSpace = format.yCbCrColorSpace();
+
+ if (m_handleType == QAbstractVideoBuffer::NoHandle)
+ glGenTextures(m_textureCount, m_textureIds);
+ }
+
+ return error;
+}
+
+void QVideoSurfaceGlslPainter::stop()
+{
+ if (m_context) {
+ m_context->makeCurrent();
+
+ if (m_handleType != QAbstractVideoBuffer::GLTextureHandle)
+ glDeleteTextures(m_textureCount, m_textureIds);
+ }
+
+ m_program.removeAllShaders();
+
+ m_textureCount = 0;
+ m_handleType = QAbstractVideoBuffer::NoHandle;
+}
+
+QAbstractVideoSurface::Error QVideoSurfaceGlslPainter::paint(
+ const QRectF &target, QPainter *painter, const QRectF &source)
+{
+ if (!m_frame.isValid()) {
+ painter->fillRect(target, Qt::black);
+ return QAbstractVideoSurface::NoError;
+ }
+
+ const QAbstractVideoBuffer::HandleType h = m_frame.handleType();
+ if (h == QAbstractVideoBuffer::NoHandle || h == QAbstractVideoBuffer::GLTextureHandle) {
+ bool stencilTestEnabled = glIsEnabled(GL_STENCIL_TEST);
+ bool scissorTestEnabled = glIsEnabled(GL_SCISSOR_TEST);
+
+ painter->beginNativePainting();
+
+ if (stencilTestEnabled)
+ glEnable(GL_STENCIL_TEST);
+ if (scissorTestEnabled)
+ glEnable(GL_SCISSOR_TEST);
+
+ const int width = QGLContext::currentContext()->device()->width();
+ const int height = QGLContext::currentContext()->device()->height();
+
+ const QTransform transform = painter->deviceTransform();
+
+ const GLfloat wfactor = 2.0 / width;
+ const GLfloat hfactor = -2.0 / height;
+
+ const GLfloat positionMatrix[4][4] =
+ {
+ {
+ /*(0,0)*/ GLfloat(wfactor * transform.m11() - transform.m13()),
+ /*(0,1)*/ GLfloat(hfactor * transform.m12() + transform.m13()),
+ /*(0,2)*/ 0.0,
+ /*(0,3)*/ GLfloat(transform.m13())
+ }, {
+ /*(1,0)*/ GLfloat(wfactor * transform.m21() - transform.m23()),
+ /*(1,1)*/ GLfloat(hfactor * transform.m22() + transform.m23()),
+ /*(1,2)*/ 0.0,
+ /*(1,3)*/ GLfloat(transform.m23())
+ }, {
+ /*(2,0)*/ 0.0,
+ /*(2,1)*/ 0.0,
+ /*(2,2)*/ -1.0,
+ /*(2,3)*/ 0.0
+ }, {
+ /*(3,0)*/ GLfloat(wfactor * transform.dx() - transform.m33()),
+ /*(3,1)*/ GLfloat(hfactor * transform.dy() + transform.m33()),
+ /*(3,2)*/ 0.0,
+ /*(3,3)*/ GLfloat(transform.m33())
+ }
+ };
+
+ const GLfloat vTop = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
+ ? target.top()
+ : target.bottom() + 1;
+ const GLfloat vBottom = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
+ ? target.bottom() + 1
+ : target.top();
+
+
+ const GLfloat vertexCoordArray[] =
+ {
+ GLfloat(target.left()) , GLfloat(vBottom),
+ GLfloat(target.right() + 1), GLfloat(vBottom),
+ GLfloat(target.left()) , GLfloat(vTop),
+ GLfloat(target.right() + 1), GLfloat(vTop)
+ };
+
+ const GLfloat txLeft = source.left() / m_frameSize.width();
+ const GLfloat txRight = source.right() / m_frameSize.width();
+ const GLfloat txTop = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
+ ? source.top() / m_frameSize.height()
+ : source.bottom() / m_frameSize.height();
+ const GLfloat txBottom = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
+ ? source.bottom() / m_frameSize.height()
+ : source.top() / m_frameSize.height();
+
+ const GLfloat textureCoordArray[] =
+ {
+ txLeft , txBottom,
+ txRight, txBottom,
+ txLeft , txTop,
+ txRight, txTop
+ };
+
+ m_program.bind();
+
+ m_program.enableAttributeArray("vertexCoordArray");
+ m_program.enableAttributeArray("textureCoordArray");
+ m_program.setAttributeArray("vertexCoordArray", vertexCoordArray, 2);
+ m_program.setAttributeArray("textureCoordArray", textureCoordArray, 2);
+ m_program.setUniformValue("positionMatrix", positionMatrix);
+
+ if (m_textureCount == 3) {
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, m_textureIds[0]);
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, m_textureIds[1]);
+ glActiveTexture(GL_TEXTURE2);
+ glBindTexture(GL_TEXTURE_2D, m_textureIds[2]);
+ glActiveTexture(GL_TEXTURE0);
+
+ m_program.setUniformValue("texY", 0);
+ m_program.setUniformValue("texU", 1);
+ m_program.setUniformValue("texV", 2);
+ } else {
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, m_textureIds[0]);
+
+ m_program.setUniformValue("texRgb", 0);
+ }
+ m_program.setUniformValue("colorMatrix", m_colorMatrix);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ m_program.release();
+
+ painter->endNativePainting();
+
+ return QAbstractVideoSurface::NoError;
+ }
+
+ return QVideoSurfaceGLPainter::paint(target, painter, source);
+}
+
+#endif
+
+/*!
+ \class QPainterVideoSurface
+ \since 1.0
+ \internal
+*/
+
+/*!
+*/
+QPainterVideoSurface::QPainterVideoSurface(QObject *parent)
+ : QAbstractVideoSurface(parent)
+ , m_painter(0)
+#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
+ , m_glContext(0)
+ , m_shaderTypes(NoShaders)
+ , m_shaderType(NoShaders)
+#endif
+ , m_brightness(0)
+ , m_contrast(0)
+ , m_hue(0)
+ , m_saturation(0)
+ , m_pixelFormat(QVideoFrame::Format_Invalid)
+ , m_colorsDirty(true)
+ , m_ready(false)
+{
+}
+
+/*!
+*/
+QPainterVideoSurface::~QPainterVideoSurface()
+{
+ if (isActive())
+ m_painter->stop();
+
+ delete m_painter;
+}
+
+/*!
+ \since 1.0
+*/
+QList<QVideoFrame::PixelFormat> QPainterVideoSurface::supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType) const
+{
+ if (!m_painter)
+ const_cast<QPainterVideoSurface *>(this)->createPainter();
+
+ return m_painter->supportedPixelFormats(handleType);
+}
+
+/*!
+ \since 1.0
+*/
+bool QPainterVideoSurface::isFormatSupported(
+ const QVideoSurfaceFormat &format, QVideoSurfaceFormat *similar) const
+{
+ if (!m_painter)
+ const_cast<QPainterVideoSurface *>(this)->createPainter();
+
+ return m_painter->isFormatSupported(format, similar);
+}
+
+/*!
+ \since 1.0
+*/
+bool QPainterVideoSurface::start(const QVideoSurfaceFormat &format)
+{
+ if (isActive())
+ m_painter->stop();
+
+ if (!m_painter)
+ createPainter();
+
+ if (format.frameSize().isEmpty()) {
+ setError(UnsupportedFormatError);
+ } else {
+ QAbstractVideoSurface::Error error = m_painter->start(format);
+
+ if (error != QAbstractVideoSurface::NoError) {
+ setError(error);
+ } else {
+ m_pixelFormat = format.pixelFormat();
+ m_frameSize = format.frameSize();
+ m_sourceRect = format.viewport();
+ m_colorsDirty = true;
+ m_ready = true;
+
+ return QAbstractVideoSurface::start(format);
+ }
+ }
+
+ QAbstractVideoSurface::stop();
+
+ return false;
+}
+
+/*!
+ \since 1.0
+*/
+void QPainterVideoSurface::stop()
+{
+ if (isActive()) {
+ m_painter->stop();
+ m_ready = false;
+
+ QAbstractVideoSurface::stop();
+ }
+}
+
+/*!
+ \since 1.0
+*/
+bool QPainterVideoSurface::present(const QVideoFrame &frame)
+{
+ if (!m_ready) {
+ if (!isActive())
+ setError(StoppedError);
+ } else if (frame.isValid()
+ && (frame.pixelFormat() != m_pixelFormat || frame.size() != m_frameSize)) {
+ setError(IncorrectFormatError);
+
+ stop();
+ } else {
+ QAbstractVideoSurface::Error error = m_painter->setCurrentFrame(frame);
+
+ if (error != QAbstractVideoSurface::NoError) {
+ setError(error);
+
+ stop();
+ } else {
+ m_ready = false;
+
+ emit frameChanged();
+
+ return true;
+ }
+ }
+ return false;
+}
+
+/*!
+ \since 1.0
+*/
+int QPainterVideoSurface::brightness() const
+{
+ return m_brightness;
+}
+
+/*!
+ \since 1.0
+*/
+void QPainterVideoSurface::setBrightness(int brightness)
+{
+ m_brightness = brightness;
+
+ m_colorsDirty = true;
+}
+
+/*!
+ \since 1.0
+*/
+int QPainterVideoSurface::contrast() const
+{
+ return m_contrast;
+}
+
+/*!
+ \since 1.0
+*/
+void QPainterVideoSurface::setContrast(int contrast)
+{
+ m_contrast = contrast;
+
+ m_colorsDirty = true;
+}
+
+/*!
+ \since 1.0
+*/
+int QPainterVideoSurface::hue() const
+{
+ return m_hue;
+}
+
+/*!
+ \since 1.0
+*/
+void QPainterVideoSurface::setHue(int hue)
+{
+ m_hue = hue;
+
+ m_colorsDirty = true;
+}
+
+/*!
+ \since 1.0
+*/
+int QPainterVideoSurface::saturation() const
+{
+ return m_saturation;
+}
+
+/*!
+ \since 1.0
+*/
+void QPainterVideoSurface::setSaturation(int saturation)
+{
+ m_saturation = saturation;
+
+ m_colorsDirty = true;
+}
+
+/*!
+ \since 1.0
+*/
+bool QPainterVideoSurface::isReady() const
+{
+ return m_ready;
+}
+
+/*!
+ \since 1.0
+*/
+void QPainterVideoSurface::setReady(bool ready)
+{
+ m_ready = ready;
+}
+
+/*!
+ \since 1.0
+*/
+void QPainterVideoSurface::paint(QPainter *painter, const QRectF &target, const QRectF &source)
+{
+ if (!isActive()) {
+ painter->fillRect(target, QBrush(Qt::black));
+ } else {
+ if (m_colorsDirty) {
+ m_painter->updateColors(m_brightness, m_contrast, m_hue, m_saturation);
+ m_colorsDirty = false;
+ }
+
+ const QRectF sourceRect(
+ m_sourceRect.x() + m_sourceRect.width() * source.x(),
+ m_sourceRect.y() + m_sourceRect.height() * source.y(),
+ m_sourceRect.width() * source.width(),
+ m_sourceRect.height() * source.height());
+
+ QAbstractVideoSurface::Error error = m_painter->paint(target, painter, sourceRect);
+
+ if (error != QAbstractVideoSurface::NoError) {
+ setError(error);
+
+ stop();
+ }
+ }
+}
+
+/*!
+ \fn QPainterVideoSurface::frameChanged()
+ \since 1.0
+*/
+
+#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
+
+/*!
+*/
+const QGLContext *QPainterVideoSurface::glContext() const
+{
+ return m_glContext;
+}
+
+/*!
+*/
+void QPainterVideoSurface::setGLContext(QGLContext *context)
+{
+ if (m_glContext == context)
+ return;
+
+ m_glContext = context;
+
+ m_shaderTypes = NoShaders;
+
+ if (m_glContext) {
+ m_glContext->makeCurrent();
+
+ const QByteArray extensions(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)));
+#ifndef QT_OPENGL_ES
+
+ if (extensions.contains("ARB_fragment_program"))
+ m_shaderTypes |= FragmentProgramShader;
+#endif
+ if (QGLShaderProgram::hasOpenGLShaderPrograms(m_glContext)
+#ifndef QT_OPENGL_ES_2
+ && extensions.contains("ARB_shader_objects")
+#endif
+ )
+ m_shaderTypes |= GlslShader;
+ }
+
+ ShaderType type = (m_shaderType & m_shaderTypes)
+ ? m_shaderType
+ : NoShaders;
+
+ if (type != m_shaderType || type != NoShaders) {
+ m_shaderType = type;
+
+ if (isActive()) {
+ m_painter->stop();
+ delete m_painter;
+ m_painter = 0;
+ m_ready = false;
+
+ setError(ResourceError);
+ QAbstractVideoSurface::stop();
+ }
+ emit supportedFormatsChanged();
+ }
+}
+
+/*!
+ \enum QPainterVideoSurface::ShaderType
+
+ \value NoShaders
+ \value FragmentProgramShader
+ \value HlslShader
+*/
+
+/*!
+ \typedef QPainterVideoSurface::ShaderTypes
+*/
+
+/*!
+ \since 1.0
+*/
+QPainterVideoSurface::ShaderTypes QPainterVideoSurface::supportedShaderTypes() const
+{
+ return m_shaderTypes;
+}
+
+/*!
+ \since 1.0
+*/
+QPainterVideoSurface::ShaderType QPainterVideoSurface::shaderType() const
+{
+ return m_shaderType;
+}
+
+/*!
+ \since 1.0
+*/
+void QPainterVideoSurface::setShaderType(ShaderType type)
+{
+ if (!(type & m_shaderTypes))
+ type = NoShaders;
+
+ if (type != m_shaderType) {
+ m_shaderType = type;
+
+ if (isActive()) {
+ m_painter->stop();
+ delete m_painter;
+ m_painter = 0;
+ m_ready = false;
+
+ setError(ResourceError);
+ QAbstractVideoSurface::stop();
+ } else {
+ delete m_painter;
+ m_painter = 0;
+ }
+ emit supportedFormatsChanged();
+ }
+}
+
+#endif
+
+void QPainterVideoSurface::viewportDestroyed()
+{
+ if (m_painter) {
+ m_painter->viewportDestroyed();
+
+ setError(ResourceError);
+ stop();
+ delete m_painter;
+ m_painter = 0;
+ }
+}
+
+void QPainterVideoSurface::createPainter()
+{
+ Q_ASSERT(!m_painter);
+
+#ifdef Q_WS_MAC
+ if (m_glContext)
+ m_glContext->makeCurrent();
+
+ m_painter = new QVideoSurfaceCoreGraphicsPainter(m_glContext != 0);
+ return;
+#endif
+
+#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
+ switch (m_shaderType) {
+#ifndef QT_OPENGL_ES
+ case FragmentProgramShader:
+ Q_ASSERT(m_glContext);
+ m_glContext->makeCurrent();
+ m_painter = new QVideoSurfaceArbFpPainter(m_glContext);
+ break;
+#endif
+ case GlslShader:
+ Q_ASSERT(m_glContext);
+ m_glContext->makeCurrent();
+ m_painter = new QVideoSurfaceGlslPainter(m_glContext);
+ break;
+ default:
+ m_painter = new QVideoSurfaceGenericPainter;
+ break;
+ }
+#else
+ m_painter = new QVideoSurfaceGenericPainter;
+#endif
+}
+
+#include "moc_qpaintervideosurface_p.cpp"
+QT_END_NAMESPACE
+
+
diff --git a/src/multimediawidgets/qpaintervideosurface_mac.mm b/src/multimediawidgets/qpaintervideosurface_mac.mm
new file mode 100644
index 000000000..02eabfe7d
--- /dev/null
+++ b/src/multimediawidgets/qpaintervideosurface_mac.mm
@@ -0,0 +1,285 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <AppKit/AppKit.h>
+#include <QuartzCore/CIContext.h>
+#include <CGLCurrent.h>
+#include <OpenGL/gl.h>
+
+#include "qpaintervideosurface_mac_p.h"
+
+#include <QtCore/qdatetime.h>
+
+#include <qmath.h>
+
+#include <qpainter.h>
+#include <qvariant.h>
+#include <qvideosurfaceformat.h>
+
+#include <QtDebug>
+
+QT_BEGIN_NAMESPACE
+
+extern CGContextRef qt_mac_cg_context(const QPaintDevice *pdev); //qpaintdevice_mac.cpp
+
+QVideoSurfaceCoreGraphicsPainter::QVideoSurfaceCoreGraphicsPainter(bool glSupported)
+ : ciContext(0)
+ , m_imageFormat(QImage::Format_Invalid)
+ , m_scanLineDirection(QVideoSurfaceFormat::TopToBottom)
+{
+ //qDebug() << "QVideoSurfaceCoreGraphicsPainter, GL supported:" << glSupported;
+ ciContext = 0;
+ m_imagePixelFormats
+ << QVideoFrame::Format_RGB32
+ << QVideoFrame::Format_ARGB32
+ << QVideoFrame::Format_ARGB32_Premultiplied
+ << QVideoFrame::Format_RGB24
+ << QVideoFrame::Format_RGB565
+ << QVideoFrame::Format_RGB555
+ << QVideoFrame::Format_ARGB8565_Premultiplied;
+
+ m_supportedHandles
+ << QAbstractVideoBuffer::NoHandle
+ << QAbstractVideoBuffer::CoreImageHandle;
+
+ if (glSupported)
+ m_supportedHandles << QAbstractVideoBuffer::GLTextureHandle;
+}
+
+QVideoSurfaceCoreGraphicsPainter::~QVideoSurfaceCoreGraphicsPainter()
+{
+ [(CIContext*)ciContext release];
+}
+
+QList<QVideoFrame::PixelFormat> QVideoSurfaceCoreGraphicsPainter::supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType) const
+{
+ return m_supportedHandles.contains(handleType)
+ ? m_imagePixelFormats
+ : QList<QVideoFrame::PixelFormat>();
+}
+
+bool QVideoSurfaceCoreGraphicsPainter::isFormatSupported(
+ const QVideoSurfaceFormat &format, QVideoSurfaceFormat *) const
+{
+ return m_supportedHandles.contains(format.handleType())
+ && m_imagePixelFormats.contains(format.pixelFormat())
+ && !format.frameSize().isEmpty();
+}
+
+QAbstractVideoSurface::Error QVideoSurfaceCoreGraphicsPainter::start(const QVideoSurfaceFormat &format)
+{
+ m_frame = QVideoFrame();
+ m_imageFormat = QVideoFrame::imageFormatFromPixelFormat(format.pixelFormat());
+ m_imageSize = format.frameSize();
+ m_scanLineDirection = format.scanLineDirection();
+
+ return m_supportedHandles.contains(format.handleType())
+ && m_imageFormat != QImage::Format_Invalid
+ && !m_imageSize.isEmpty()
+ ? QAbstractVideoSurface::NoError
+ : QAbstractVideoSurface::UnsupportedFormatError;
+}
+
+void QVideoSurfaceCoreGraphicsPainter::stop()
+{
+ m_frame = QVideoFrame();
+}
+
+QAbstractVideoSurface::Error QVideoSurfaceCoreGraphicsPainter::setCurrentFrame(const QVideoFrame &frame)
+{
+ m_frame = frame;
+
+ return QAbstractVideoSurface::NoError;
+}
+
+QAbstractVideoSurface::Error QVideoSurfaceCoreGraphicsPainter::paint(
+ const QRectF &target, QPainter *painter, const QRectF &source)
+{
+ if (m_frame.handleType() == QAbstractVideoBuffer::CoreImageHandle) {
+ if (painter->paintEngine()->type() == QPaintEngine::CoreGraphics ) {
+
+ CIImage *img = (CIImage*)(m_frame.handle().value<void*>());
+
+ if (img) {
+ CGContextRef cgContext = qt_mac_cg_context(painter->device());
+
+ if (cgContext) {
+ painter->beginNativePainting();
+
+ CGRect sRect = CGRectMake(source.x(), source.y(), source.width(), source.height());
+ CGRect dRect = CGRectMake(target.x(), target.y(), target.width(), target.height());
+
+ NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithCIImage:img];
+
+ if (m_scanLineDirection == QVideoSurfaceFormat::TopToBottom) {
+ CGContextSaveGState( cgContext );
+ CGContextTranslateCTM(cgContext, 0, dRect.origin.y + CGRectGetMaxY(dRect));
+ CGContextScaleCTM(cgContext, 1, -1);
+
+ CGContextDrawImage(cgContext, dRect, [bitmap CGImage]);
+
+ CGContextRestoreGState(cgContext);
+ } else {
+ CGContextDrawImage(cgContext, dRect, [bitmap CGImage]);
+ }
+
+ [bitmap release];
+
+ painter->endNativePainting();
+
+ return QAbstractVideoSurface::NoError;
+ }
+ }
+ } else if (painter->paintEngine()->type() == QPaintEngine::OpenGL2 ||
+ painter->paintEngine()->type() == QPaintEngine::OpenGL) {
+ CIImage *img = (CIImage*)(m_frame.handle().value<void*>());
+
+ if (img) {
+ CGLContextObj cglContext = CGLGetCurrentContext();
+
+ if (cglContext) {
+
+ if (!ciContext) {
+ CGLContextObj cglContext = CGLGetCurrentContext();
+ NSOpenGLPixelFormat *nsglPixelFormat = [NSOpenGLView defaultPixelFormat];
+ CGLPixelFormatObj cglPixelFormat = static_cast<CGLPixelFormatObj>([nsglPixelFormat CGLPixelFormatObj]);
+
+ ciContext = [CIContext contextWithCGLContext:cglContext
+ pixelFormat:cglPixelFormat
+ options:nil];
+
+ [(CIContext*)ciContext retain];
+ }
+
+ CGRect sRect = CGRectMake(source.x(), source.y(), source.width(), source.height());
+ CGRect dRect = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom ?
+ CGRectMake(target.x(), target.y()+target.height(), target.width(), -target.height()) :
+ CGRectMake(target.x(), target.y(), target.width(), target.height());
+
+
+ painter->beginNativePainting();
+
+ [(CIContext*)ciContext drawImage:img inRect:dRect fromRect:sRect];
+
+ painter->endNativePainting();
+
+ return QAbstractVideoSurface::NoError;
+ }
+ }
+ }
+ }
+
+ if (m_frame.handleType() == QAbstractVideoBuffer::GLTextureHandle &&
+ (painter->paintEngine()->type() == QPaintEngine::OpenGL2 ||
+ painter->paintEngine()->type() == QPaintEngine::OpenGL)) {
+
+ painter->beginNativePainting();
+ GLuint texture = m_frame.handle().toUInt();
+
+ glDisable(GL_CULL_FACE);
+ glEnable(GL_TEXTURE_2D);
+
+ glBindTexture(GL_TEXTURE_2D, texture);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ const float txLeft = source.left() / m_frame.width();
+ const float txRight = source.right() / m_frame.width();
+ const float txTop = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
+ ? source.top() / m_frame.height()
+ : source.bottom() / m_frame.height();
+ const float txBottom = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
+ ? source.bottom() / m_frame.height()
+ : source.top() / m_frame.height();
+
+ glBegin(GL_QUADS);
+ QRectF rect = target;
+ glTexCoord2f(txLeft, txBottom);
+ glVertex2f(rect.topLeft().x(), rect.topLeft().y());
+ glTexCoord2f(txRight, txBottom);
+ glVertex2f(rect.topRight().x() + 1, rect.topRight().y());
+ glTexCoord2f(txRight, txTop);
+ glVertex2f(rect.bottomRight().x() + 1, rect.bottomRight().y() + 1);
+ glTexCoord2f(txLeft, txTop);
+ glVertex2f(rect.bottomLeft().x(), rect.bottomLeft().y() + 1);
+ glEnd();
+ painter->endNativePainting();
+
+ return QAbstractVideoSurface::NoError;
+ }
+
+ //fallback case, software rendering
+ if (m_frame.map(QAbstractVideoBuffer::ReadOnly)) {
+ QImage image(
+ m_frame.bits(),
+ m_imageSize.width(),
+ m_imageSize.height(),
+ m_frame.bytesPerLine(),
+ m_imageFormat);
+
+ if (m_scanLineDirection == QVideoSurfaceFormat::BottomToTop) {
+ const QTransform oldTransform = painter->transform();
+
+ painter->scale(1, -1);
+ painter->translate(0, -target.bottom());
+ painter->drawImage(
+ QRectF(target.x(), 0, target.width(), target.height()), image, source);
+ painter->setTransform(oldTransform);
+ } else {
+ painter->drawImage(target, image, source);
+ }
+
+ m_frame.unmap();
+ } else if (m_frame.isValid()) {
+ return QAbstractVideoSurface::IncorrectFormatError;
+ } else {
+ painter->fillRect(target, Qt::black);
+ }
+
+ return QAbstractVideoSurface::NoError;
+}
+
+void QVideoSurfaceCoreGraphicsPainter::updateColors(int, int, int, int)
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/multimediawidgets/qpaintervideosurface_mac_p.h b/src/multimediawidgets/qpaintervideosurface_mac_p.h
new file mode 100644
index 000000000..d650d9ad7
--- /dev/null
+++ b/src/multimediawidgets/qpaintervideosurface_mac_p.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPAINTERVIDEOSURFACE_MAC_P_H
+#define QPAINTERVIDEOSURFACE_MAC_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qpaintervideosurface_p.h"
+#include <qvideosurfaceformat.h>
+#include <qvideoframe.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Multimedia)
+
+
+class QVideoSurfaceCoreGraphicsPainter : public QVideoSurfacePainter
+{
+public:
+ QVideoSurfaceCoreGraphicsPainter(bool glSupported);
+ ~QVideoSurfaceCoreGraphicsPainter();
+
+ QList<QVideoFrame::PixelFormat> supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType) const;
+
+ bool isFormatSupported(
+ const QVideoSurfaceFormat &format, QVideoSurfaceFormat *similar) const;
+
+ QAbstractVideoSurface::Error start(const QVideoSurfaceFormat &format);
+ void stop();
+
+ QAbstractVideoSurface::Error setCurrentFrame(const QVideoFrame &frame);
+
+ QAbstractVideoSurface::Error paint(
+ const QRectF &target, QPainter *painter, const QRectF &source);
+
+ void updateColors(int brightness, int contrast, int hue, int saturation);
+
+private:
+ void* ciContext;
+ QList<QVideoFrame::PixelFormat> m_imagePixelFormats;
+ QVideoFrame m_frame;
+ QSize m_imageSize;
+ QImage::Format m_imageFormat;
+ QVector<QAbstractVideoBuffer::HandleType> m_supportedHandles;
+ QVideoSurfaceFormat::Direction m_scanLineDirection;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/multimediawidgets/qpaintervideosurface_p.h b/src/multimediawidgets/qpaintervideosurface_p.h
new file mode 100644
index 000000000..a8b535b59
--- /dev/null
+++ b/src/multimediawidgets/qpaintervideosurface_p.h
@@ -0,0 +1,191 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPAINTERVIDEOSURFACE_P_H
+#define QPAINTERVIDEOSURFACE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <qtmultimediawidgetdefs.h>
+#include <QtCore/qsize.h>
+#include <QtGui/qimage.h>
+#include <QtGui/qmatrix4x4.h>
+#include <QtGui/qpaintengine.h>
+#include <qabstractvideosurface.h>
+#include <qvideoframe.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Multimedia)
+
+class QGLContext;
+QT_END_NAMESPACE
+
+QT_USE_NAMESPACE
+
+QT_BEGIN_NAMESPACE
+
+class QVideoSurfacePainter
+{
+public:
+ virtual ~QVideoSurfacePainter();
+
+ virtual QList<QVideoFrame::PixelFormat> supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType) const = 0;
+
+ virtual bool isFormatSupported(
+ const QVideoSurfaceFormat &format, QVideoSurfaceFormat *similar) const = 0;
+
+ virtual QAbstractVideoSurface::Error start(const QVideoSurfaceFormat &format) = 0;
+ virtual void stop() = 0;
+
+ virtual QAbstractVideoSurface::Error setCurrentFrame(const QVideoFrame &frame) = 0;
+
+ virtual QAbstractVideoSurface::Error paint(
+ const QRectF &target, QPainter *painter, const QRectF &source) = 0;
+
+ virtual void updateColors(int brightness, int contrast, int hue, int saturation) = 0;
+ virtual void viewportDestroyed() {}
+};
+
+
+class Q_AUTOTEST_EXPORT QPainterVideoSurface : public QAbstractVideoSurface
+{
+ Q_OBJECT
+public:
+ explicit QPainterVideoSurface(QObject *parent = 0);
+ ~QPainterVideoSurface();
+
+ QList<QVideoFrame::PixelFormat> supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const;
+
+ bool isFormatSupported(
+ const QVideoSurfaceFormat &format, QVideoSurfaceFormat *similar = 0) const;
+
+ bool start(const QVideoSurfaceFormat &format);
+ void stop();
+
+ bool present(const QVideoFrame &frame);
+
+ int brightness() const;
+ void setBrightness(int brightness);
+
+ int contrast() const;
+ void setContrast(int contrast);
+
+ int hue() const;
+ void setHue(int hue);
+
+ int saturation() const;
+ void setSaturation(int saturation);
+
+ bool isReady() const;
+ void setReady(bool ready);
+
+ void paint(QPainter *painter, const QRectF &target, const QRectF &source = QRectF(0, 0, 1, 1));
+
+#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
+ const QGLContext *glContext() const;
+ void setGLContext(QGLContext *context);
+
+ enum ShaderType
+ {
+ NoShaders = 0x00,
+ FragmentProgramShader = 0x01,
+ GlslShader = 0x02
+ };
+
+ Q_DECLARE_FLAGS(ShaderTypes, ShaderType)
+
+ ShaderTypes supportedShaderTypes() const;
+
+ ShaderType shaderType() const;
+ void setShaderType(ShaderType type);
+#endif
+
+public Q_SLOTS:
+ void viewportDestroyed();
+
+Q_SIGNALS:
+ void frameChanged();
+
+private:
+ void createPainter();
+
+ QVideoSurfacePainter *m_painter;
+#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
+ QGLContext *m_glContext;
+ ShaderTypes m_shaderTypes;
+ ShaderType m_shaderType;
+#endif
+ int m_brightness;
+ int m_contrast;
+ int m_hue;
+ int m_saturation;
+
+ QVideoFrame::PixelFormat m_pixelFormat;
+ QSize m_frameSize;
+ QRect m_sourceRect;
+ bool m_colorsDirty;
+ bool m_ready;
+};
+
+#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QPainterVideoSurface::ShaderTypes)
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+
+#endif
diff --git a/src/multimediawidgets/qtmultimediawidgetdefs.h b/src/multimediawidgets/qtmultimediawidgetdefs.h
new file mode 100644
index 000000000..57ce226a1
--- /dev/null
+++ b/src/multimediawidgets/qtmultimediawidgetdefs.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QTMULTIMEDIAWIDGETS_P_H
+#define QTMULTIMEDIAWIDGETS_P_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+
+#if defined(Q_OS_WIN)
+# if defined(QT_NODLL)
+# undef QT_MAKEDLL
+# undef QT_DLL
+# elif defined(QT_MAKEDLL)
+# if defined(QT_DLL)
+# undef QT_DLL
+# endif
+# if defined(QT_BUILD_MULTIMEDIA_LIB)
+# define Q_MULTIMEDIAWIDGETS_EXPORT Q_DECL_EXPORT
+# else
+# define Q_MULTIMEDIAWIDGETS_EXPORT Q_DECL_IMPORT
+# endif
+# elif defined(QT_DLL) /* use a Qt DLL library */
+# define Q_MULTIMEDIAWIDGETS_EXPORT Q_DECL_IMPORT
+# endif
+#endif
+
+#if !defined(Q_MULTIMEDIAWIDGETS_EXPORT)
+# if defined(QT_SHARED)
+# define Q_MULTIMEDIAWIDGETS_EXPORT Q_DECL_EXPORT
+# else
+# define Q_MULTIMEDIAWIDGETS_EXPORT
+# endif
+#endif
+
+QT_END_HEADER
+
+#endif // QMULTIMEDIAWIDGETS_P_H
+
diff --git a/src/multimediawidgets/qvideowidget.cpp b/src/multimediawidgets/qvideowidget.cpp
new file mode 100644
index 000000000..f31144cb0
--- /dev/null
+++ b/src/multimediawidgets/qvideowidget.cpp
@@ -0,0 +1,1043 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvideowidget_p.h"
+
+#include <qmediaobject.h>
+#include <qmediaservice.h>
+#include <qvideowindowcontrol.h>
+#include <qvideowidgetcontrol.h>
+
+#include <qpaintervideosurface_p.h>
+#include <qvideorenderercontrol.h>
+#include <qvideosurfaceformat.h>
+#include <qpainter.h>
+
+#include <qapplication.h>
+#include <qevent.h>
+#include <qdialog.h>
+#include <qboxlayout.h>
+#include <qnamespace.h>
+
+using namespace Qt;
+
+QT_BEGIN_NAMESPACE
+
+QVideoWidgetControlBackend::QVideoWidgetControlBackend(
+ QMediaService *service, QVideoWidgetControl *control, QWidget *widget)
+ : m_service(service)
+ , m_widgetControl(control)
+{
+ connect(control, SIGNAL(brightnessChanged(int)), widget, SLOT(_q_brightnessChanged(int)));
+ connect(control, SIGNAL(contrastChanged(int)), widget, SLOT(_q_contrastChanged(int)));
+ connect(control, SIGNAL(hueChanged(int)), widget, SLOT(_q_hueChanged(int)));
+ connect(control, SIGNAL(saturationChanged(int)), widget, SLOT(_q_saturationChanged(int)));
+ connect(control, SIGNAL(fullScreenChanged(bool)), widget, SLOT(_q_fullScreenChanged(bool)));
+
+ QBoxLayout *layout = new QVBoxLayout;
+ layout->setMargin(0);
+ layout->setSpacing(0);
+
+ layout->addWidget(control->videoWidget());
+
+ widget->setLayout(layout);
+}
+
+void QVideoWidgetControlBackend::releaseControl()
+{
+ m_service->releaseControl(m_widgetControl);
+}
+
+void QVideoWidgetControlBackend::setBrightness(int brightness)
+{
+ m_widgetControl->setBrightness(brightness);
+}
+
+void QVideoWidgetControlBackend::setContrast(int contrast)
+{
+ m_widgetControl->setContrast(contrast);
+}
+
+void QVideoWidgetControlBackend::setHue(int hue)
+{
+ m_widgetControl->setHue(hue);
+}
+
+void QVideoWidgetControlBackend::setSaturation(int saturation)
+{
+ m_widgetControl->setSaturation(saturation);
+}
+
+void QVideoWidgetControlBackend::setFullScreen(bool fullScreen)
+{
+ m_widgetControl->setFullScreen(fullScreen);
+}
+
+
+Qt::AspectRatioMode QVideoWidgetControlBackend::aspectRatioMode() const
+{
+ return m_widgetControl->aspectRatioMode();
+}
+
+void QVideoWidgetControlBackend::setAspectRatioMode(Qt::AspectRatioMode mode)
+{
+ m_widgetControl->setAspectRatioMode(mode);
+}
+
+QRendererVideoWidgetBackend::QRendererVideoWidgetBackend(
+ QMediaService *service, QVideoRendererControl *control, QWidget *widget)
+ : m_service(service)
+ , m_rendererControl(control)
+ , m_widget(widget)
+ , m_surface(new QPainterVideoSurface)
+ , m_aspectRatioMode(Qt::KeepAspectRatio)
+ , m_updatePaintDevice(true)
+{
+ connect(this, SIGNAL(brightnessChanged(int)), m_widget, SLOT(_q_brightnessChanged(int)));
+ connect(this, SIGNAL(contrastChanged(int)), m_widget, SLOT(_q_contrastChanged(int)));
+ connect(this, SIGNAL(hueChanged(int)), m_widget, SLOT(_q_hueChanged(int)));
+ connect(this, SIGNAL(saturationChanged(int)), m_widget, SLOT(_q_saturationChanged(int)));
+ connect(m_surface, SIGNAL(frameChanged()), this, SLOT(frameChanged()));
+ connect(m_surface, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)),
+ this, SLOT(formatChanged(QVideoSurfaceFormat)));
+
+ m_rendererControl->setSurface(m_surface);
+}
+
+QRendererVideoWidgetBackend::~QRendererVideoWidgetBackend()
+{
+ delete m_surface;
+}
+
+void QRendererVideoWidgetBackend::releaseControl()
+{
+ m_service->releaseControl(m_rendererControl);
+}
+
+void QRendererVideoWidgetBackend::clearSurface()
+{
+ m_rendererControl->setSurface(0);
+}
+
+void QRendererVideoWidgetBackend::setBrightness(int brightness)
+{
+ m_surface->setBrightness(brightness);
+
+ emit brightnessChanged(brightness);
+}
+
+void QRendererVideoWidgetBackend::setContrast(int contrast)
+{
+ m_surface->setContrast(contrast);
+
+ emit contrastChanged(contrast);
+}
+
+void QRendererVideoWidgetBackend::setHue(int hue)
+{
+ m_surface->setHue(hue);
+
+ emit hueChanged(hue);
+}
+
+void QRendererVideoWidgetBackend::setSaturation(int saturation)
+{
+ m_surface->setSaturation(saturation);
+
+ emit saturationChanged(saturation);
+}
+
+Qt::AspectRatioMode QRendererVideoWidgetBackend::aspectRatioMode() const
+{
+ return m_aspectRatioMode;
+}
+
+void QRendererVideoWidgetBackend::setAspectRatioMode(Qt::AspectRatioMode mode)
+{
+ m_aspectRatioMode = mode;
+
+ m_widget->updateGeometry();
+}
+
+void QRendererVideoWidgetBackend::setFullScreen(bool)
+{
+}
+
+QSize QRendererVideoWidgetBackend::sizeHint() const
+{
+ return m_surface->surfaceFormat().sizeHint();
+}
+
+void QRendererVideoWidgetBackend::showEvent()
+{
+}
+
+void QRendererVideoWidgetBackend::hideEvent(QHideEvent *)
+{
+#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
+ m_updatePaintDevice = true;
+ m_surface->setGLContext(0);
+#endif
+}
+
+void QRendererVideoWidgetBackend::resizeEvent(QResizeEvent *)
+{
+ updateRects();
+}
+
+void QRendererVideoWidgetBackend::moveEvent(QMoveEvent *)
+{
+}
+
+void QRendererVideoWidgetBackend::paintEvent(QPaintEvent *event)
+{
+ QPainter painter(m_widget);
+
+ if (m_widget->testAttribute(Qt::WA_OpaquePaintEvent)) {
+ QRegion borderRegion = event->region();
+ borderRegion = borderRegion.subtracted(m_boundingRect);
+
+ QBrush brush = m_widget->palette().window();
+
+ QVector<QRect> rects = borderRegion.rects();
+ for (QVector<QRect>::iterator it = rects.begin(), end = rects.end(); it != end; ++it) {
+ painter.fillRect(*it, brush);
+ }
+ }
+
+ if (m_surface->isActive() && m_boundingRect.intersects(event->rect())) {
+ m_surface->paint(&painter, m_boundingRect, m_sourceRect);
+
+ m_surface->setReady(true);
+ } else {
+ #if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
+ if (m_updatePaintDevice && (painter.paintEngine()->type() == QPaintEngine::OpenGL
+ || painter.paintEngine()->type() == QPaintEngine::OpenGL2)) {
+ m_updatePaintDevice = false;
+
+ m_surface->setGLContext(const_cast<QGLContext *>(QGLContext::currentContext()));
+ if (m_surface->supportedShaderTypes() & QPainterVideoSurface::GlslShader) {
+ m_surface->setShaderType(QPainterVideoSurface::GlslShader);
+ } else {
+ m_surface->setShaderType(QPainterVideoSurface::FragmentProgramShader);
+ }
+ }
+#endif
+ }
+
+}
+
+void QRendererVideoWidgetBackend::formatChanged(const QVideoSurfaceFormat &format)
+{
+ m_nativeSize = format.sizeHint();
+
+ updateRects();
+
+ m_widget->updateGeometry();
+ m_widget->update();
+}
+
+void QRendererVideoWidgetBackend::frameChanged()
+{
+ m_widget->update(m_boundingRect);
+}
+
+void QRendererVideoWidgetBackend::updateRects()
+{
+ QRect rect = m_widget->rect();
+
+ if (m_nativeSize.isEmpty()) {
+ m_boundingRect = QRect();
+ } else if (m_aspectRatioMode == Qt::IgnoreAspectRatio) {
+ m_boundingRect = rect;
+ m_sourceRect = QRectF(0, 0, 1, 1);
+ } else if (m_aspectRatioMode == Qt::KeepAspectRatio) {
+ QSize size = m_nativeSize;
+ size.scale(rect.size(), Qt::KeepAspectRatio);
+
+ m_boundingRect = QRect(0, 0, size.width(), size.height());
+ m_boundingRect.moveCenter(rect.center());
+
+ m_sourceRect = QRectF(0, 0, 1, 1);
+ } else if (m_aspectRatioMode == Qt::KeepAspectRatioByExpanding) {
+ m_boundingRect = rect;
+
+ QSizeF size = rect.size();
+ size.scale(m_nativeSize, Qt::KeepAspectRatio);
+
+ m_sourceRect = QRectF(
+ 0, 0, size.width() / m_nativeSize.width(), size.height() / m_nativeSize.height());
+ m_sourceRect.moveCenter(QPointF(0.5, 0.5));
+ }
+}
+
+QWindowVideoWidgetBackend::QWindowVideoWidgetBackend(
+ QMediaService *service, QVideoWindowControl *control, QWidget *widget)
+ : m_service(service)
+ , m_windowControl(control)
+ , m_widget(widget)
+ , m_aspectRatioMode(Qt::KeepAspectRatio)
+{
+ connect(control, SIGNAL(brightnessChanged(int)), m_widget, SLOT(_q_brightnessChanged(int)));
+ connect(control, SIGNAL(contrastChanged(int)), m_widget, SLOT(_q_contrastChanged(int)));
+ connect(control, SIGNAL(hueChanged(int)), m_widget, SLOT(_q_hueChanged(int)));
+ connect(control, SIGNAL(saturationChanged(int)), m_widget, SLOT(_q_saturationChanged(int)));
+ connect(control, SIGNAL(fullScreenChanged(bool)), m_widget, SLOT(_q_fullScreenChanged(bool)));
+ connect(control, SIGNAL(nativeSizeChanged()), m_widget, SLOT(_q_dimensionsChanged()));
+
+ control->setWinId(widget->winId());
+}
+
+QWindowVideoWidgetBackend::~QWindowVideoWidgetBackend()
+{
+}
+
+void QWindowVideoWidgetBackend::releaseControl()
+{
+ m_service->releaseControl(m_windowControl);
+}
+
+void QWindowVideoWidgetBackend::setBrightness(int brightness)
+{
+ m_windowControl->setBrightness(brightness);
+}
+
+void QWindowVideoWidgetBackend::setContrast(int contrast)
+{
+ m_windowControl->setContrast(contrast);
+}
+
+void QWindowVideoWidgetBackend::setHue(int hue)
+{
+ m_windowControl->setHue(hue);
+}
+
+void QWindowVideoWidgetBackend::setSaturation(int saturation)
+{
+ m_windowControl->setSaturation(saturation);
+}
+
+void QWindowVideoWidgetBackend::setFullScreen(bool fullScreen)
+{
+ m_windowControl->setFullScreen(fullScreen);
+}
+
+Qt::AspectRatioMode QWindowVideoWidgetBackend::aspectRatioMode() const
+{
+ return m_windowControl->aspectRatioMode();
+}
+
+void QWindowVideoWidgetBackend::setAspectRatioMode(Qt::AspectRatioMode mode)
+{
+ m_windowControl->setAspectRatioMode(mode);
+}
+
+QSize QWindowVideoWidgetBackend::sizeHint() const
+{
+ return m_windowControl->nativeSize();
+}
+
+void QWindowVideoWidgetBackend::showEvent()
+{
+ m_windowControl->setWinId(m_widget->winId());
+
+ m_windowControl->setDisplayRect(m_widget->rect());
+
+#if defined(Q_WS_WIN)
+ m_widget->setUpdatesEnabled(false);
+#endif
+}
+
+void QWindowVideoWidgetBackend::hideEvent(QHideEvent *)
+{
+#if defined(Q_WS_WIN)
+ m_widget->setUpdatesEnabled(true);
+#endif
+}
+
+void QWindowVideoWidgetBackend::moveEvent(QMoveEvent *)
+{
+ m_windowControl->setDisplayRect(m_widget->rect());
+}
+
+void QWindowVideoWidgetBackend::resizeEvent(QResizeEvent *)
+{
+ m_windowControl->setDisplayRect(m_widget->rect());
+}
+
+void QWindowVideoWidgetBackend::paintEvent(QPaintEvent *event)
+{
+ if (m_widget->testAttribute(Qt::WA_OpaquePaintEvent)) {
+ QPainter painter(m_widget);
+
+ painter.fillRect(event->rect(), m_widget->palette().window());
+ }
+
+ m_windowControl->repaint();
+
+ event->accept();
+}
+
+#if defined(Q_WS_WIN)
+bool QWindowVideoWidgetBackend::winEvent(MSG *message, long *)
+{
+ if (message->message == WM_PAINT)
+ m_windowControl->repaint();
+
+ return false;
+}
+#endif
+
+void QVideoWidgetPrivate::setCurrentControl(QVideoWidgetControlInterface *control)
+{
+ if (currentControl != control) {
+ currentControl = control;
+
+ currentControl->setBrightness(brightness);
+ currentControl->setContrast(contrast);
+ currentControl->setHue(hue);
+ currentControl->setSaturation(saturation);
+ currentControl->setAspectRatioMode(aspectRatioMode);
+ }
+}
+
+void QVideoWidgetPrivate::clearService()
+{
+ if (service) {
+ QObject::disconnect(service, SIGNAL(destroyed()), q_func(), SLOT(_q_serviceDestroyed()));
+
+ if (widgetBackend) {
+ QLayout *layout = q_func()->layout();
+
+ for (QLayoutItem *item = layout->takeAt(0); item; item = layout->takeAt(0)) {
+ item->widget()->setParent(0);
+ delete item;
+ }
+ delete layout;
+
+ widgetBackend->releaseControl();
+
+ delete widgetBackend;
+ widgetBackend = 0;
+ } else if (rendererBackend) {
+ rendererBackend->clearSurface();
+ rendererBackend->releaseControl();
+
+ delete rendererBackend;
+ rendererBackend = 0;
+ } else {
+ windowBackend->releaseControl();
+
+ delete windowBackend;
+ windowBackend = 0;
+ }
+
+ currentBackend = 0;
+ currentControl = 0;
+ service = 0;
+ }
+}
+
+bool QVideoWidgetPrivate::createWidgetBackend()
+{
+ if (QMediaControl *control = service->requestControl(QVideoWidgetControl_iid)) {
+ if (QVideoWidgetControl *widgetControl = qobject_cast<QVideoWidgetControl *>(control)) {
+ widgetBackend = new QVideoWidgetControlBackend(service, widgetControl, q_func());
+
+ setCurrentControl(widgetBackend);
+
+ return true;
+ }
+ service->releaseControl(control);
+ }
+ return false;
+}
+
+bool QVideoWidgetPrivate::createWindowBackend()
+{
+ if (QMediaControl *control = service->requestControl(QVideoWindowControl_iid)) {
+ if (QVideoWindowControl *windowControl = qobject_cast<QVideoWindowControl *>(control)) {
+ windowBackend = new QWindowVideoWidgetBackend(service, windowControl, q_func());
+ currentBackend = windowBackend;
+
+ setCurrentControl(windowBackend);
+
+ return true;
+ }
+ service->releaseControl(control);
+ }
+ return false;
+}
+
+bool QVideoWidgetPrivate::createRendererBackend()
+{
+ if (QMediaControl *control = service->requestControl(QVideoRendererControl_iid)) {
+ if (QVideoRendererControl *rendererControl = qobject_cast<QVideoRendererControl *>(control)) {
+ rendererBackend = new QRendererVideoWidgetBackend(service, rendererControl, q_func());
+ currentBackend = rendererBackend;
+
+ setCurrentControl(rendererBackend);
+
+ return true;
+ }
+ service->releaseControl(control);
+ }
+ return false;
+}
+
+void QVideoWidgetPrivate::_q_serviceDestroyed()
+{
+ if (widgetBackend)
+ delete q_func()->layout();
+
+ delete widgetBackend;
+ delete windowBackend;
+ delete rendererBackend;
+
+ widgetBackend = 0;
+ windowBackend = 0;
+ rendererBackend = 0;
+ currentControl = 0;
+ currentBackend = 0;
+ service = 0;
+}
+
+void QVideoWidgetPrivate::_q_brightnessChanged(int b)
+{
+ if (b != brightness)
+ emit q_func()->brightnessChanged(brightness = b);
+}
+
+void QVideoWidgetPrivate::_q_contrastChanged(int c)
+{
+ if (c != contrast)
+ emit q_func()->contrastChanged(contrast = c);
+}
+
+void QVideoWidgetPrivate::_q_hueChanged(int h)
+{
+ if (h != hue)
+ emit q_func()->hueChanged(hue = h);
+}
+
+void QVideoWidgetPrivate::_q_saturationChanged(int s)
+{
+ if (s != saturation)
+ emit q_func()->saturationChanged(saturation = s);
+}
+
+
+void QVideoWidgetPrivate::_q_fullScreenChanged(bool fullScreen)
+{
+ if (!fullScreen && q_func()->isFullScreen())
+ q_func()->showNormal();
+}
+
+void QVideoWidgetPrivate::_q_dimensionsChanged()
+{
+ q_func()->updateGeometry();
+ q_func()->update();
+}
+
+/*!
+ \class QVideoWidget
+
+
+ \brief The QVideoWidget class provides a widget which presents video
+ produced by a media object.
+ \ingroup multimedia
+ \inmodule QtMultimedia
+ \since 1.0
+
+ \inmodule QtMultimedia
+
+ Attaching a QVideoWidget to a QMediaObject allows it to display the
+ video or image output of that media object. A QVideoWidget is attached
+ to media object by passing a pointer to the QMediaObject in its
+ constructor, and detached by destroying the QVideoWidget.
+
+ \snippet doc/src/snippets/multimedia-snippets/video.cpp Video widget
+
+ \bold {Note}: Only a single display output can be attached to a media
+ object at one time.
+
+ \sa QMediaObject, QMediaPlayer, QGraphicsVideoItem
+*/
+
+/*!
+ Constructs a new video widget.
+
+ The \a parent is passed to QWidget.
+*/
+QVideoWidget::QVideoWidget(QWidget *parent)
+ : QWidget(parent, 0)
+ , d_ptr(new QVideoWidgetPrivate)
+{
+ d_ptr->q_ptr = this;
+}
+
+/*!
+ \internal
+*/
+QVideoWidget::QVideoWidget(QVideoWidgetPrivate &dd, QWidget *parent)
+ : QWidget(parent, 0)
+ , d_ptr(&dd)
+{
+ d_ptr->q_ptr = this;
+
+ QPalette palette = QWidget::palette();
+ palette.setColor(QPalette::Background, Qt::black);
+ setPalette(palette);
+}
+
+/*!
+ Destroys a video widget.
+*/
+QVideoWidget::~QVideoWidget()
+{
+ d_ptr->clearService();
+
+ delete d_ptr;
+}
+
+/*!
+ \property QVideoWidget::mediaObject
+ \brief the media object which provides the video displayed by a widget.
+ \since 1.0
+*/
+
+QMediaObject *QVideoWidget::mediaObject() const
+{
+ return d_func()->mediaObject;
+}
+
+/*!
+ \internal
+ \since 1.0
+*/
+bool QVideoWidget::setMediaObject(QMediaObject *object)
+{
+ Q_D(QVideoWidget);
+
+ if (object == d->mediaObject)
+ return true;
+
+ d->clearService();
+
+ d->mediaObject = object;
+
+ if (d->mediaObject)
+ d->service = d->mediaObject->service();
+
+ if (d->service) {
+ if (d->createWidgetBackend()) {
+ // Nothing to do here.
+ } else if ((!window() || !window()->testAttribute(Qt::WA_DontShowOnScreen))
+ && d->createWindowBackend()) {
+ if (isVisible())
+ d->windowBackend->showEvent();
+ } else if (d->createRendererBackend()) {
+ if (isVisible())
+ d->rendererBackend->showEvent();
+ } else {
+ d->service = 0;
+ d->mediaObject = 0;
+
+ return false;
+ }
+
+ connect(d->service, SIGNAL(destroyed()), SLOT(_q_serviceDestroyed()));
+ } else {
+ d->mediaObject = 0;
+
+ return false;
+ }
+
+ return true;
+}
+
+/*!
+ \property QVideoWidget::aspectRatioMode
+ \brief how video is scaled with respect to its aspect ratio.
+ \since 1.0
+*/
+
+Qt::AspectRatioMode QVideoWidget::aspectRatioMode() const
+{
+ return d_func()->aspectRatioMode;
+}
+
+void QVideoWidget::setAspectRatioMode(Qt::AspectRatioMode mode)
+{
+ Q_D(QVideoWidget);
+
+ if (d->currentControl) {
+ d->currentControl->setAspectRatioMode(mode);
+ d->aspectRatioMode = d->currentControl->aspectRatioMode();
+ } else {
+ d->aspectRatioMode = mode;
+ }
+}
+
+/*!
+ \property QVideoWidget::fullScreen
+ \brief whether video display is confined to a window or is fullScreen.
+ \since 1.0
+*/
+
+void QVideoWidget::setFullScreen(bool fullScreen)
+{
+ Q_D(QVideoWidget);
+
+ if (fullScreen) {
+ Qt::WindowFlags flags = windowFlags();
+
+ d->nonFullScreenFlags = flags & (Qt::Window | Qt::SubWindow);
+ flags |= Qt::Window;
+ flags &= ~Qt::SubWindow;
+ setWindowFlags(flags);
+
+ showFullScreen();
+ } else {
+ showNormal();
+ }
+}
+
+/*!
+ \fn QVideoWidget::fullScreenChanged(bool fullScreen)
+
+ Signals that the \a fullScreen mode of a video widget has changed.
+
+ \since 1.0
+ \sa fullScreen
+*/
+
+/*!
+ \property QVideoWidget::brightness
+ \brief an adjustment to the brightness of displayed video.
+
+ Valid brightness values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+int QVideoWidget::brightness() const
+{
+ return d_func()->brightness;
+}
+
+void QVideoWidget::setBrightness(int brightness)
+{
+ Q_D(QVideoWidget);
+
+ int boundedBrightness = qBound(-100, brightness, 100);
+
+ if (d->currentControl)
+ d->currentControl->setBrightness(boundedBrightness);
+ else if (d->brightness != boundedBrightness)
+ emit brightnessChanged(d->brightness = boundedBrightness);
+}
+
+/*!
+ \fn QVideoWidget::brightnessChanged(int brightness)
+
+ Signals that a video widgets's \a brightness adjustment has changed.
+
+ \since 1.0
+ \sa brightness
+*/
+
+/*!
+ \property QVideoWidget::contrast
+ \brief an adjustment to the contrast of displayed video.
+
+ Valid contrast values range between -100 and 100, the default is 0.
+
+ \since 1.0
+*/
+
+int QVideoWidget::contrast() const
+{
+ return d_func()->contrast;
+}
+
+void QVideoWidget::setContrast(int contrast)
+{
+ Q_D(QVideoWidget);
+
+ int boundedContrast = qBound(-100, contrast, 100);
+
+ if (d->currentControl)
+ d->currentControl->setContrast(boundedContrast);
+ else if (d->contrast != boundedContrast)
+ emit contrastChanged(d->contrast = boundedContrast);
+}
+
+/*!
+ \fn QVideoWidget::contrastChanged(int contrast)
+
+ Signals that a video widgets's \a contrast adjustment has changed.
+
+ \since 1.0
+ \sa contrast
+*/
+
+/*!
+ \property QVideoWidget::hue
+ \brief an adjustment to the hue of displayed video.
+
+ Valid hue values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+int QVideoWidget::hue() const
+{
+ return d_func()->hue;
+}
+
+void QVideoWidget::setHue(int hue)
+{
+ Q_D(QVideoWidget);
+
+ int boundedHue = qBound(-100, hue, 100);
+
+ if (d->currentControl)
+ d->currentControl->setHue(boundedHue);
+ else if (d->hue != boundedHue)
+ emit hueChanged(d->hue = boundedHue);
+}
+
+/*!
+ \fn QVideoWidget::hueChanged(int hue)
+
+ Signals that a video widgets's \a hue has changed.
+
+ \since 1.0
+ \sa hue
+*/
+
+/*!
+ \property QVideoWidget::saturation
+ \brief an adjustment to the saturation of displayed video.
+
+ Valid saturation values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+int QVideoWidget::saturation() const
+{
+ return d_func()->saturation;
+}
+
+void QVideoWidget::setSaturation(int saturation)
+{
+ Q_D(QVideoWidget);
+
+ int boundedSaturation = qBound(-100, saturation, 100);
+
+ if (d->currentControl)
+ d->currentControl->setSaturation(boundedSaturation);
+ else if (d->saturation != boundedSaturation)
+ emit saturationChanged(d->saturation = boundedSaturation);
+
+}
+
+/*!
+ \fn QVideoWidget::saturationChanged(int saturation)
+
+ Signals that a video widgets's \a saturation has changed.
+
+ \since 1.0
+ \sa saturation
+*/
+
+/*!
+ Returns the size hint for the current back end,
+ if there is one, or else the size hint from QWidget.
+ \since 1.0
+ */
+QSize QVideoWidget::sizeHint() const
+{
+ Q_D(const QVideoWidget);
+
+ if (d->currentBackend)
+ return d->currentBackend->sizeHint();
+ else
+ return QWidget::sizeHint();
+
+
+}
+
+/*!
+ Current event \a event.
+ Returns the value of the baseclass QWidget::event(QEvent *event) function.
+ \since 1.0
+*/
+bool QVideoWidget::event(QEvent *event)
+{
+ Q_D(QVideoWidget);
+
+ if (event->type() == QEvent::WindowStateChange) {
+ Qt::WindowFlags flags = windowFlags();
+
+ if (windowState() & Qt::WindowFullScreen) {
+ if (d->currentControl)
+ d->currentControl->setFullScreen(true);
+
+ if (!d->wasFullScreen)
+ emit fullScreenChanged(d->wasFullScreen = true);
+ } else {
+ if (d->currentControl)
+ d->currentControl->setFullScreen(false);
+
+ if (d->wasFullScreen) {
+ flags &= ~(Qt::Window | Qt::SubWindow); //clear the flags...
+ flags |= d->nonFullScreenFlags; //then we reset the flags (window and subwindow)
+ setWindowFlags(flags);
+
+ emit fullScreenChanged(d->wasFullScreen = false);
+ }
+ }
+ }
+ return QWidget::event(event);
+}
+
+/*!
+ Handles the show \a event.
+ \since 1.0
+ */
+void QVideoWidget::showEvent(QShowEvent *event)
+{
+ Q_D(QVideoWidget);
+
+ QWidget::showEvent(event);
+
+ // The window backend won't work for re-directed windows so use the renderer backend instead.
+ if (d->windowBackend && window()->testAttribute(Qt::WA_DontShowOnScreen)) {
+ d->windowBackend->releaseControl();
+
+ delete d->windowBackend;
+ d->windowBackend = 0;
+
+ d->createRendererBackend();
+ }
+
+ if (d->currentBackend)
+ d->currentBackend->showEvent();
+}
+
+/*!
+
+ Handles the hide \a event.
+ \since 1.0
+*/
+void QVideoWidget::hideEvent(QHideEvent *event)
+{
+ Q_D(QVideoWidget);
+
+ if (d->currentBackend)
+ d->currentBackend->hideEvent(event);
+
+ QWidget::hideEvent(event);
+}
+
+/*!
+ Handles the resize \a event.
+ \since 1.0
+ */
+void QVideoWidget::resizeEvent(QResizeEvent *event)
+{
+ Q_D(QVideoWidget);
+
+ QWidget::resizeEvent(event);
+
+ if (d->currentBackend)
+ d->currentBackend->resizeEvent(event);
+}
+
+/*!
+ Handles the move \a event.
+ \since 1.0
+ */
+void QVideoWidget::moveEvent(QMoveEvent *event)
+{
+ Q_D(QVideoWidget);
+
+ if (d->currentBackend)
+ d->currentBackend->moveEvent(event);
+}
+
+/*!
+ Handles the paint \a event.
+ \since 1.0
+ */
+void QVideoWidget::paintEvent(QPaintEvent *event)
+{
+ Q_D(QVideoWidget);
+
+ if (d->currentBackend) {
+ d->currentBackend->paintEvent(event);
+ } else if (testAttribute(Qt::WA_OpaquePaintEvent)) {
+ QPainter painter(this);
+
+ painter.fillRect(event->rect(), palette().window());
+ }
+}
+
+
+#if defined(Q_WS_WIN)
+/*!
+ \reimp
+ \internal
+ \since 1.1
+*/
+bool QVideoWidget::winEvent(MSG *message, long *result)
+{
+ return d_func()->windowBackend && d_func()->windowBackend->winEvent(message, result)
+ ? true
+ : QWidget::winEvent(message, result);
+}
+#endif
+
+
+#include "moc_qvideowidget.cpp"
+#include "moc_qvideowidget_p.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediawidgets/qvideowidget.h b/src/multimediawidgets/qvideowidget.h
new file mode 100644
index 000000000..c4c6f8d3f
--- /dev/null
+++ b/src/multimediawidgets/qvideowidget.h
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVIDEOWIDGET_H
+#define QVIDEOWIDGET_H
+
+#include <QtWidgets/qwidget.h>
+
+#include <qtmultimediawidgetdefs.h>
+#include <qmediabindableinterface.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Multimedia)
+
+
+class QMediaObject;
+
+class QVideoWidgetPrivate;
+class Q_MULTIMEDIA_EXPORT QVideoWidget : public QWidget, public QMediaBindableInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QMediaBindableInterface)
+ Q_PROPERTY(QMediaObject* mediaObject READ mediaObject WRITE setMediaObject)
+ Q_PROPERTY(bool fullScreen READ isFullScreen WRITE setFullScreen NOTIFY fullScreenChanged)
+ Q_PROPERTY(Qt::AspectRatioMode aspectRatioMode READ aspectRatioMode WRITE setAspectRatioMode)
+ Q_PROPERTY(int brightness READ brightness WRITE setBrightness NOTIFY brightnessChanged)
+ Q_PROPERTY(int contrast READ contrast WRITE setContrast NOTIFY contrastChanged)
+ Q_PROPERTY(int hue READ hue WRITE setHue NOTIFY hueChanged)
+ Q_PROPERTY(int saturation READ saturation WRITE setSaturation NOTIFY saturationChanged)
+
+public:
+ QVideoWidget(QWidget *parent = 0);
+ ~QVideoWidget();
+
+ QMediaObject *mediaObject() const;
+
+#ifdef Q_QDOC
+ bool isFullScreen() const;
+#endif
+
+ Qt::AspectRatioMode aspectRatioMode() const;
+
+ int brightness() const;
+ int contrast() const;
+ int hue() const;
+ int saturation() const;
+
+ QSize sizeHint() const;
+
+public Q_SLOTS:
+ void setFullScreen(bool fullScreen);
+ void setAspectRatioMode(Qt::AspectRatioMode mode);
+ void setBrightness(int brightness);
+ void setContrast(int contrast);
+ void setHue(int hue);
+ void setSaturation(int saturation);
+
+Q_SIGNALS:
+ void fullScreenChanged(bool fullScreen);
+ void brightnessChanged(int brightness);
+ void contrastChanged(int contrast);
+ void hueChanged(int hue);
+ void saturationChanged(int saturation);
+
+protected:
+ bool event(QEvent *event);
+ void showEvent(QShowEvent *event);
+ void hideEvent(QHideEvent *event);
+ void resizeEvent(QResizeEvent *event);
+ void moveEvent(QMoveEvent *event);
+ void paintEvent(QPaintEvent *event);
+
+ bool setMediaObject(QMediaObject *object);
+
+#if defined(Q_WS_WIN)
+ bool winEvent(MSG *message, long *result);
+#endif
+
+ QVideoWidget(QVideoWidgetPrivate &dd, QWidget *parent);
+ QVideoWidgetPrivate *d_ptr;
+
+private:
+ Q_DECLARE_PRIVATE(QVideoWidget)
+ Q_PRIVATE_SLOT(d_func(), void _q_serviceDestroyed())
+ Q_PRIVATE_SLOT(d_func(), void _q_brightnessChanged(int))
+ Q_PRIVATE_SLOT(d_func(), void _q_contrastChanged(int))
+ Q_PRIVATE_SLOT(d_func(), void _q_hueChanged(int))
+ Q_PRIVATE_SLOT(d_func(), void _q_saturationChanged(int))
+ Q_PRIVATE_SLOT(d_func(), void _q_fullScreenChanged(bool))
+ Q_PRIVATE_SLOT(d_func(), void _q_dimensionsChanged())
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+
+#endif
diff --git a/src/multimediawidgets/qvideowidget_p.h b/src/multimediawidgets/qvideowidget_p.h
new file mode 100644
index 000000000..df1d86df0
--- /dev/null
+++ b/src/multimediawidgets/qvideowidget_p.h
@@ -0,0 +1,290 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVIDEOWIDGET_P_H
+#define QVIDEOWIDGET_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <qtmultimediawidgetdefs.h>
+#include "qvideowidget.h"
+
+#ifndef QT_NO_OPENGL
+#include <QGLWidget>
+#endif
+
+#include "qpaintervideosurface_p.h"
+
+#include <QtCore/qpointer.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Multimedia)
+
+
+class QMediaService;
+
+class QVideoWidgetControlInterface
+{
+public:
+ virtual ~QVideoWidgetControlInterface() {}
+
+ virtual void setBrightness(int brightness) = 0;
+ virtual void setContrast(int contrast) = 0;
+ virtual void setHue(int hue) = 0;
+ virtual void setSaturation(int saturation) = 0;
+
+ virtual void setFullScreen(bool fullScreen) = 0;
+
+ virtual Qt::AspectRatioMode aspectRatioMode() const = 0;
+ virtual void setAspectRatioMode(Qt::AspectRatioMode mode) = 0;
+};
+
+class QVideoWidgetBackend : public QObject, public QVideoWidgetControlInterface
+{
+ Q_OBJECT
+public:
+ virtual QSize sizeHint() const = 0;
+
+ virtual void showEvent() = 0;
+ virtual void hideEvent(QHideEvent *event) = 0;
+ virtual void resizeEvent(QResizeEvent *event) = 0;
+ virtual void moveEvent(QMoveEvent *event) = 0;
+ virtual void paintEvent(QPaintEvent *event) = 0;
+};
+
+class QVideoWidgetControl;
+
+class QVideoWidgetControlBackend : public QObject, public QVideoWidgetControlInterface
+{
+ Q_OBJECT
+public:
+ QVideoWidgetControlBackend(QMediaService *service, QVideoWidgetControl *control, QWidget *widget);
+
+ void releaseControl();
+
+ void setBrightness(int brightness);
+ void setContrast(int contrast);
+ void setHue(int hue);
+ void setSaturation(int saturation);
+
+ void setFullScreen(bool fullScreen);
+
+ Qt::AspectRatioMode aspectRatioMode() const;
+ void setAspectRatioMode(Qt::AspectRatioMode mode);
+
+private:
+ QMediaService *m_service;
+ QVideoWidgetControl *m_widgetControl;
+};
+
+
+class QVideoRendererControl;
+
+class QRendererVideoWidgetBackend : public QVideoWidgetBackend
+{
+ Q_OBJECT
+public:
+ QRendererVideoWidgetBackend(QMediaService *service, QVideoRendererControl *control, QWidget *widget);
+ ~QRendererVideoWidgetBackend();
+
+ void releaseControl();
+ void clearSurface();
+
+ void setBrightness(int brightness);
+ void setContrast(int contrast);
+ void setHue(int hue);
+ void setSaturation(int saturation);
+
+ void setFullScreen(bool fullScreen);
+
+ Qt::AspectRatioMode aspectRatioMode() const;
+ void setAspectRatioMode(Qt::AspectRatioMode mode);
+
+ QSize sizeHint() const;
+
+ void showEvent();
+ void hideEvent(QHideEvent *event);
+ void resizeEvent(QResizeEvent *event);
+ void moveEvent(QMoveEvent *event);
+ void paintEvent(QPaintEvent *event);
+
+Q_SIGNALS:
+ void fullScreenChanged(bool fullScreen);
+ void brightnessChanged(int brightness);
+ void contrastChanged(int contrast);
+ void hueChanged(int hue);
+ void saturationChanged(int saturation);
+
+private Q_SLOTS:
+ void formatChanged(const QVideoSurfaceFormat &format);
+ void frameChanged();
+
+private:
+ void updateRects();
+
+ QMediaService *m_service;
+ QVideoRendererControl *m_rendererControl;
+ QWidget *m_widget;
+ QPainterVideoSurface *m_surface;
+ Qt::AspectRatioMode m_aspectRatioMode;
+ QRect m_boundingRect;
+ QRectF m_sourceRect;
+ QSize m_nativeSize;
+ bool m_updatePaintDevice;
+};
+
+class QVideoWindowControl;
+
+class QWindowVideoWidgetBackend : public QVideoWidgetBackend
+{
+ Q_OBJECT
+public:
+ QWindowVideoWidgetBackend(QMediaService *service, QVideoWindowControl *control, QWidget *widget);
+ ~QWindowVideoWidgetBackend();
+
+ void releaseControl();
+
+ void setBrightness(int brightness);
+ void setContrast(int contrast);
+ void setHue(int hue);
+ void setSaturation(int saturation);
+
+ void setFullScreen(bool fullScreen);
+
+ Qt::AspectRatioMode aspectRatioMode() const;
+ void setAspectRatioMode(Qt::AspectRatioMode mode);
+
+ QSize sizeHint() const;
+
+ void showEvent();
+ void hideEvent(QHideEvent *event);
+ void resizeEvent(QResizeEvent *event);
+ void moveEvent(QMoveEvent *event);
+ void paintEvent(QPaintEvent *event);
+
+#if defined(Q_WS_WIN)
+ bool winEvent(MSG *message, long *result);
+#endif
+
+private:
+ QMediaService *m_service;
+ QVideoWindowControl *m_windowControl;
+ QWidget *m_widget;
+ Qt::AspectRatioMode m_aspectRatioMode;
+ QSize m_pixelAspectRatio;
+};
+
+class QMediaService;
+class QVideoOutputControl;
+
+class QVideoWidgetPrivate
+{
+ Q_DECLARE_PUBLIC(QVideoWidget)
+public:
+ QVideoWidgetPrivate()
+ : q_ptr(0)
+ , mediaObject(0)
+ , service(0)
+ , widgetBackend(0)
+ , windowBackend(0)
+ , rendererBackend(0)
+ , currentControl(0)
+ , currentBackend(0)
+ , brightness(0)
+ , contrast(0)
+ , hue(0)
+ , saturation(0)
+ , aspectRatioMode(Qt::KeepAspectRatio)
+ , nonFullScreenFlags(0)
+ , wasFullScreen(false)
+ {
+ }
+
+ QVideoWidget *q_ptr;
+ QPointer<QMediaObject> mediaObject;
+ QMediaService *service;
+ QVideoWidgetControlBackend *widgetBackend;
+ QWindowVideoWidgetBackend *windowBackend;
+ QRendererVideoWidgetBackend *rendererBackend;
+ QVideoWidgetControlInterface *currentControl;
+ QVideoWidgetBackend *currentBackend;
+ int brightness;
+ int contrast;
+ int hue;
+ int saturation;
+ Qt::AspectRatioMode aspectRatioMode;
+ Qt::WindowFlags nonFullScreenFlags;
+ bool wasFullScreen;
+
+ bool createWidgetBackend();
+ bool createWindowBackend();
+ bool createRendererBackend();
+
+ void setCurrentControl(QVideoWidgetControlInterface *control);
+ void clearService();
+
+ void _q_serviceDestroyed();
+ void _q_brightnessChanged(int brightness);
+ void _q_contrastChanged(int contrast);
+ void _q_hueChanged(int hue);
+ void _q_saturationChanged(int saturation);
+ void _q_fullScreenChanged(bool fullScreen);
+ void _q_dimensionsChanged();
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+
+#endif
diff --git a/src/multimediawidgets/qvideowidgetcontrol.cpp b/src/multimediawidgets/qvideowidgetcontrol.cpp
new file mode 100644
index 000000000..e153030f2
--- /dev/null
+++ b/src/multimediawidgets/qvideowidgetcontrol.cpp
@@ -0,0 +1,245 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvideowidgetcontrol.h"
+#include "private/qmediacontrol_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QVideoWidgetControl
+
+
+ \brief The QVideoWidgetControl class provides a media control which
+ implements a video widget.
+
+ \inmodule QtMultimedia
+ \ingroup multimedia-serv
+ \since 1.0
+
+ The videoWidget() property of QVideoWidgetControl provides a pointer to a
+ video widget implemented by the control's media service. This widget is
+ owned by the media service and so care should be taken not to delete it.
+
+ \snippet doc/src/snippets/multimedia-snippets/video.cpp Video widget control
+
+ QVideoWidgetControl is one of number of possible video output controls.
+
+ The interface name of QVideoWidgetControl is \c com.nokia.Qt.QVideoWidgetControl/1.0 as
+ defined in QVideoWidgetControl_iid.
+
+ \sa QMediaService::requestControl(), QVideoWidget
+*/
+
+/*!
+ \macro QVideoWidgetControl_iid
+
+ \c com.nokia.Qt.QVideoWidgetControl/1.0
+
+ Defines the interface name of the QVideoWidgetControl class.
+
+ \relates QVideoWidgetControl
+*/
+
+/*!
+ Constructs a new video widget control with the given \a parent.
+*/
+QVideoWidgetControl::QVideoWidgetControl(QObject *parent)
+ :QMediaControl(parent)
+{
+}
+
+/*!
+ Destroys a video widget control.
+*/
+QVideoWidgetControl::~QVideoWidgetControl()
+{
+}
+
+/*!
+ \fn QVideoWidgetControl::isFullScreen() const
+
+ Returns true if the video is shown using the complete screen.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWidgetControl::setFullScreen(bool fullScreen)
+
+ Sets whether a video widget is in \a fullScreen mode.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWidgetControl::fullScreenChanged(bool fullScreen)
+
+ Signals that the \a fullScreen state of a video widget has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWidgetControl::aspectRatioMode() const
+
+ Returns how video is scaled to fit the widget with respect to its aspect ratio.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWidgetControl::setAspectRatioMode(Qt::AspectRatioMode mode)
+
+ Sets the aspect ratio \a mode which determines how video is scaled to the fit the widget with
+ respect to its aspect ratio.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWidgetControl::brightness() const
+
+ Returns the brightness adjustment applied to a video.
+
+ Valid brightness values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWidgetControl::setBrightness(int brightness)
+
+ Sets a \a brightness adjustment for a video.
+
+ Valid brightness values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWidgetControl::brightnessChanged(int brightness)
+
+ Signals that a video widget's \a brightness adjustment has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWidgetControl::contrast() const
+
+ Returns the contrast adjustment applied to a video.
+
+ Valid contrast values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWidgetControl::setContrast(int contrast)
+
+ Sets the contrast adjustment for a video widget to \a contrast.
+
+ Valid contrast values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+
+/*!
+ \fn QVideoWidgetControl::contrastChanged(int contrast)
+
+ Signals that a video widget's \a contrast adjustment has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWidgetControl::hue() const
+
+ Returns the hue adjustment applied to a video widget.
+
+ Value hue values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWidgetControl::setHue(int hue)
+
+ Sets a \a hue adjustment for a video widget.
+
+ Valid hue values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+
+/*!
+ \fn QVideoWidgetControl::hueChanged(int hue)
+
+ Signals that a video widget's \a hue adjustment has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWidgetControl::saturation() const
+
+ Returns the saturation adjustment applied to a video widget.
+
+ Value saturation values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+
+/*!
+ \fn QVideoWidgetControl::setSaturation(int saturation)
+
+ Sets a \a saturation adjustment for a video widget.
+
+ Valid saturation values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWidgetControl::saturationChanged(int saturation)
+
+ Signals that a video widget's \a saturation adjustment has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWidgetControl::videoWidget()
+
+ Returns the QWidget.
+ \since 1.0
+*/
+
+#include "moc_qvideowidgetcontrol.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediawidgets/qvideowidgetcontrol.h b/src/multimediawidgets/qvideowidgetcontrol.h
new file mode 100644
index 000000000..c5ac880fa
--- /dev/null
+++ b/src/multimediawidgets/qvideowidgetcontrol.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVIDEOWIDGETCONTROL_H
+#define QVIDEOWIDGETCONTROL_H
+
+#include "qvideowidget.h"
+#include "qmediacontrol.h"
+
+#include <QtWidgets/qwidget.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Multimedia)
+
+
+class QVideoWidgetControlPrivate;
+
+class Q_MULTIMEDIA_EXPORT QVideoWidgetControl : public QMediaControl
+{
+ Q_OBJECT
+
+public:
+ virtual ~QVideoWidgetControl();
+
+ virtual QWidget *videoWidget() = 0;
+
+ virtual Qt::AspectRatioMode aspectRatioMode() const = 0;
+ virtual void setAspectRatioMode(Qt::AspectRatioMode mode) = 0;
+
+ virtual bool isFullScreen() const = 0;
+ virtual void setFullScreen(bool fullScreen) = 0;
+
+ virtual int brightness() const = 0;
+ virtual void setBrightness(int brightness) = 0;
+
+ virtual int contrast() const = 0;
+ virtual void setContrast(int contrast) = 0;
+
+ virtual int hue() const = 0;
+ virtual void setHue(int hue) = 0;
+
+ virtual int saturation() const = 0;
+ virtual void setSaturation(int saturation) = 0;
+
+Q_SIGNALS:
+ void fullScreenChanged(bool fullScreen);
+ void brightnessChanged(int brightness);
+ void contrastChanged(int contrast);
+ void hueChanged(int hue);
+ void saturationChanged(int saturation);
+
+protected:
+ QVideoWidgetControl(QObject *parent = 0);
+};
+
+#define QVideoWidgetControl_iid "com.nokia.Qt.QVideoWidgetControl/1.0"
+Q_MEDIA_DECLARE_CONTROL(QVideoWidgetControl, QVideoWidgetControl_iid)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+
+#endif
diff --git a/src/multimediawidgets/qvideowindowcontrol.cpp b/src/multimediawidgets/qvideowindowcontrol.cpp
new file mode 100644
index 000000000..d96391947
--- /dev/null
+++ b/src/multimediawidgets/qvideowindowcontrol.cpp
@@ -0,0 +1,284 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvideowindowcontrol.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QVideoWindowControl
+
+ \inmodule QtMultimedia
+ \ingroup multimedia-serv
+ \brief The QVideoWindowControl class provides a media control for rendering video to a window.
+ \since 1.0
+
+
+ The winId() property QVideoWindowControl allows a platform specific window
+ ID to be set as the video render target of a QMediaService. The
+ displayRect() property is used to set the region of the window the video
+ should be rendered to, and the aspectRatioMode() property indicates how the
+ video should be scaled to fit the displayRect().
+
+ \snippet doc/src/snippets/multimedia-snippets/video.cpp Video window control
+
+ QVideoWindowControl is one of a number of possible video output controls.
+
+ The interface name of QVideoWindowControl is \c com.nokia.Qt.QVideoWindowControl/1.0 as
+ defined in QVideoWindowControl_iid.
+
+ \sa QMediaService::requestControl(), QVideoWidget
+*/
+
+/*!
+ \macro QVideoWindowControl_iid
+
+ \c com.nokia.Qt.QVideoWindowControl/1.0
+
+ Defines the interface name of the QVideoWindowControl class.
+
+ \relates QVideoWindowControl
+*/
+
+/*!
+ Constructs a new video window control with the given \a parent.
+*/
+QVideoWindowControl::QVideoWindowControl(QObject *parent)
+ : QMediaControl(parent)
+{
+}
+
+/*!
+ Destroys a video window control.
+*/
+QVideoWindowControl::~QVideoWindowControl()
+{
+}
+
+/*!
+ \fn QVideoWindowControl::winId() const
+
+ Returns the ID of the window a video overlay end point renders to.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::setWinId(WId id)
+
+ Sets the \a id of the window a video overlay end point renders to.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::displayRect() const
+ Returns the sub-rect of a window where video is displayed.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::setDisplayRect(const QRect &rect)
+ Sets the sub-\a rect of a window where video is displayed.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::isFullScreen() const
+
+ Identifies if a video overlay is a fullScreen overlay.
+
+ Returns true if the video overlay is fullScreen, and false otherwise.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::setFullScreen(bool fullScreen)
+
+ Sets whether a video overlay is a \a fullScreen overlay.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::fullScreenChanged(bool fullScreen)
+
+ Signals that the \a fullScreen state of a video overlay has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::repaint()
+
+ Repaints the last frame.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::nativeSize() const
+
+ Returns a suggested size for the video display based on the resolution and aspect ratio of the
+ video.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::nativeSizeChanged()
+
+ Signals that the native dimensions of the video have changed.
+ \since 1.0
+*/
+
+
+/*!
+ \fn QVideoWindowControl::aspectRatioMode() const
+
+ Returns how video is scaled to fit the display region with respect to its aspect ratio.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::setAspectRatioMode(Qt::AspectRatioMode mode)
+
+ Sets the aspect ratio \a mode which determines how video is scaled to the fit the display region
+ with respect to its aspect ratio.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::brightness() const
+
+ Returns the brightness adjustment applied to a video overlay.
+
+ Valid brightness values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::setBrightness(int brightness)
+
+ Sets a \a brightness adjustment for a video overlay.
+
+ Valid brightness values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::brightnessChanged(int brightness)
+
+ Signals that a video overlay's \a brightness adjustment has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::contrast() const
+
+ Returns the contrast adjustment applied to a video overlay.
+
+ Valid contrast values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::setContrast(int contrast)
+
+ Sets the \a contrast adjustment for a video overlay.
+
+ Valid contrast values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::contrastChanged(int contrast)
+
+ Signals that a video overlay's \a contrast adjustment has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::hue() const
+
+ Returns the hue adjustment applied to a video overlay.
+
+ Value hue values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::setHue(int hue)
+
+ Sets a \a hue adjustment for a video overlay.
+
+ Valid hue values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::hueChanged(int hue)
+
+ Signals that a video overlay's \a hue adjustment has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::saturation() const
+
+ Returns the saturation adjustment applied to a video overlay.
+
+ Value saturation values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::setSaturation(int saturation)
+ Sets a \a saturation adjustment for a video overlay.
+
+ Valid saturation values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::saturationChanged(int saturation)
+
+ Signals that a video overlay's \a saturation adjustment has changed.
+ \since 1.0
+*/
+
+#include "moc_qvideowindowcontrol.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediawidgets/qvideowindowcontrol.h b/src/multimediawidgets/qvideowindowcontrol.h
new file mode 100644
index 000000000..590ce64be
--- /dev/null
+++ b/src/multimediawidgets/qvideowindowcontrol.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVIDEOWINDOWCONTROL_H
+#define QVIDEOWINDOWCONTROL_H
+
+#include "qmediacontrol.h"
+#include "qvideowidget.h"
+
+#include <QtWidgets/qwidget.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Multimedia)
+
+
+class Q_MULTIMEDIA_EXPORT QVideoWindowControl : public QMediaControl
+{
+ Q_OBJECT
+
+public:
+ ~QVideoWindowControl();
+
+ virtual WId winId() const = 0;
+ virtual void setWinId(WId id) = 0;
+
+ virtual QRect displayRect() const = 0;
+ virtual void setDisplayRect(const QRect &rect) = 0;
+
+ virtual bool isFullScreen() const = 0;
+ virtual void setFullScreen(bool fullScreen) = 0;
+
+ virtual void repaint() = 0;
+
+ virtual QSize nativeSize() const = 0;
+
+ virtual Qt::AspectRatioMode aspectRatioMode() const = 0;
+ virtual void setAspectRatioMode(Qt::AspectRatioMode mode) = 0;
+
+ virtual int brightness() const = 0;
+ virtual void setBrightness(int brightness) = 0;
+
+ virtual int contrast() const = 0;
+ virtual void setContrast(int contrast) = 0;
+
+ virtual int hue() const = 0;
+ virtual void setHue(int hue) = 0;
+
+ virtual int saturation() const = 0;
+ virtual void setSaturation(int saturation) = 0;
+
+Q_SIGNALS:
+ void fullScreenChanged(bool fullScreen);
+ void brightnessChanged(int brightness);
+ void contrastChanged(int contrast);
+ void hueChanged(int hue);
+ void saturationChanged(int saturation);
+ void nativeSizeChanged();
+
+protected:
+ QVideoWindowControl(QObject *parent = 0);
+};
+
+#define QVideoWindowControl_iid "com.nokia.Qt.QVideoWindowControl/1.0"
+Q_MEDIA_DECLARE_CONTROL(QVideoWindowControl, QVideoWindowControl_iid)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+
+#endif