mapPointToSource() and mapPointToSourceNormalized() were documented with the wrong name. Change-Id: Ia128f698a02f1c865bc27443ef2c6cef8fc7a720 Reviewed-by: Christian Stromme <christian.stromme@digia.com>
744 lines
24 KiB
C++
744 lines
24 KiB
C++
/****************************************************************************
|
|
**
|
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
|
** Copyright (C) 2012 Research In Motion
|
|
** Contact: http://www.qt-project.org/legal
|
|
**
|
|
** This file is part of the Qt Toolkit.
|
|
**
|
|
** $QT_BEGIN_LICENSE:LGPL$
|
|
** Commercial License Usage
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
** accordance with the commercial license agreement provided with the
|
|
** Software or, alternatively, in accordance with the terms contained in
|
|
** a written agreement between you and Digia. For licensing terms and
|
|
** conditions see http://qt.digia.com/licensing. For further information
|
|
** use the contact form at http://qt.digia.com/contact-us.
|
|
**
|
|
** GNU Lesser General Public License Usage
|
|
** Alternatively, 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, Digia gives you certain additional
|
|
** rights. These rights are described in the Digia 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.
|
|
**
|
|
**
|
|
** $QT_END_LICENSE$
|
|
**
|
|
****************************************************************************/
|
|
#include "qdeclarativevideooutput_p.h"
|
|
|
|
#include "qdeclarativevideooutput_render_p.h"
|
|
#include "qdeclarativevideooutput_window_p.h"
|
|
#include <private/qvideooutputorientationhandler_p.h>
|
|
#include <QtMultimedia/qmediaobject.h>
|
|
#include <QtMultimedia/qmediaservice.h>
|
|
|
|
//#define DEBUG_VIDEOITEM
|
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
/*!
|
|
\qmltype VideoOutput
|
|
\instantiates QDeclarativeVideoOutput
|
|
\brief Render video or camera viewfinder.
|
|
|
|
\ingroup multimedia_qml
|
|
\ingroup multimedia_video_qml
|
|
\inqmlmodule QtMultimedia
|
|
|
|
\c VideoOutput is part of the \b{QtMultimedia 5.0} module.
|
|
|
|
\qml
|
|
import QtQuick 2.0
|
|
import QtMultimedia 5.0
|
|
|
|
Rectangle {
|
|
width: 800
|
|
height: 600
|
|
color: "black"
|
|
|
|
MediaPlayer {
|
|
id: player
|
|
source: "file://video.webm"
|
|
autoPlay: true
|
|
}
|
|
|
|
VideoOutput {
|
|
id: videoOutput
|
|
source: player
|
|
anchors.fill: parent
|
|
}
|
|
}
|
|
|
|
\endqml
|
|
|
|
The VideoOutput item supports untransformed, stretched, and uniformly scaled video presentation.
|
|
For a description of stretched uniformly scaled presentation, see the \l fillMode property
|
|
description.
|
|
|
|
The VideoOutput item works with backends that support either QVideoRendererControl or
|
|
QVideoWindowControl. If the backend only supports QVideoWindowControl, the video is rendered
|
|
onto an overlay window that is layered on top of the QtQuick window. Due to the nature of the
|
|
video overlays, certain features are not available for these kind of backends:
|
|
\list
|
|
\li Some transformations like rotations
|
|
\li Having other QtQuick items on top of the VideoOutput item
|
|
\endlist
|
|
Most backends however do support QVideoRendererControl and therefore don't have the limitations
|
|
listed above.
|
|
|
|
\sa MediaPlayer, Camera
|
|
|
|
\section1 Screen Saver
|
|
|
|
If it is likely that an application will be playing video for an extended
|
|
period of time without user interaction it may be necessary to disable
|
|
the platform's screen saver. The \l ScreenSaver (from \l QtSystemInfo)
|
|
may be used to disable the screensaver in this fashion:
|
|
|
|
\qml
|
|
import QtSystemInfo 5.0
|
|
|
|
ScreenSaver { screenSaverEnabled: false }
|
|
\endqml
|
|
*/
|
|
|
|
/*!
|
|
\internal
|
|
\class QDeclarativeVideoOutput
|
|
\brief The QDeclarativeVideoOutput class provides a video output item.
|
|
*/
|
|
|
|
QDeclarativeVideoOutput::QDeclarativeVideoOutput(QQuickItem *parent) :
|
|
QQuickItem(parent),
|
|
m_sourceType(NoSource),
|
|
m_fillMode(PreserveAspectFit),
|
|
m_geometryDirty(true),
|
|
m_orientation(0),
|
|
m_autoOrientation(false),
|
|
m_screenOrientationHandler(0)
|
|
{
|
|
setFlag(ItemHasContents, true);
|
|
}
|
|
|
|
QDeclarativeVideoOutput::~QDeclarativeVideoOutput()
|
|
{
|
|
m_backend.reset();
|
|
m_source.clear();
|
|
_q_updateMediaObject();
|
|
}
|
|
|
|
/*!
|
|
\qmlproperty variant QtMultimedia::VideoOutput::source
|
|
|
|
This property holds the source item providing the video frames like MediaPlayer or Camera.
|
|
|
|
If you are extending your own C++ classes to interoperate with VideoOutput, you can
|
|
either provide a QObject based class with a \c mediaObject property that exposes a
|
|
QMediaObject derived class that has a QVideoRendererControl available, or you can
|
|
provide a QObject based class with a writable \c videoSurface property that can
|
|
accept a QAbstractVideoSurface based class and can follow the correct protocol to
|
|
deliver QVideoFrames to it.
|
|
*/
|
|
|
|
void QDeclarativeVideoOutput::setSource(QObject *source)
|
|
{
|
|
#ifdef DEBUG_VIDEOITEM
|
|
qDebug() << Q_FUNC_INFO << source;
|
|
#endif
|
|
|
|
if (source == m_source.data())
|
|
return;
|
|
|
|
if (m_source && m_sourceType == MediaObjectSource)
|
|
disconnect(m_source.data(), 0, this, SLOT(_q_updateMediaObject()));
|
|
|
|
if (m_backend)
|
|
m_backend->releaseSource();
|
|
|
|
m_source = source;
|
|
|
|
if (m_source) {
|
|
const QMetaObject *metaObject = m_source.data()->metaObject();
|
|
|
|
int mediaObjectPropertyIndex = metaObject->indexOfProperty("mediaObject");
|
|
if (mediaObjectPropertyIndex != -1) {
|
|
const QMetaProperty mediaObjectProperty = metaObject->property(mediaObjectPropertyIndex);
|
|
|
|
if (mediaObjectProperty.hasNotifySignal()) {
|
|
QMetaMethod method = mediaObjectProperty.notifySignal();
|
|
QMetaObject::connect(m_source.data(), method.methodIndex(),
|
|
this, this->metaObject()->indexOfSlot("_q_updateMediaObject()"),
|
|
Qt::DirectConnection, 0);
|
|
|
|
}
|
|
m_sourceType = MediaObjectSource;
|
|
} else if (metaObject->indexOfProperty("videoSurface") != -1) {
|
|
// Make sure our backend is a QDeclarativeVideoRendererBackend
|
|
m_backend.reset();
|
|
createBackend(0);
|
|
Q_ASSERT(m_backend);
|
|
#ifndef QT_NO_DYNAMIC_CAST
|
|
Q_ASSERT(dynamic_cast<QDeclarativeVideoRendererBackend *>(m_backend.data()));
|
|
#endif
|
|
QAbstractVideoSurface * const surface = m_backend->videoSurface();
|
|
Q_ASSERT(surface);
|
|
m_source.data()->setProperty("videoSurface",
|
|
QVariant::fromValue<QAbstractVideoSurface*>(surface));
|
|
m_sourceType = VideoSurfaceSource;
|
|
} else {
|
|
m_sourceType = NoSource;
|
|
}
|
|
} else {
|
|
m_sourceType = NoSource;
|
|
}
|
|
|
|
_q_updateMediaObject();
|
|
emit sourceChanged();
|
|
}
|
|
|
|
bool QDeclarativeVideoOutput::createBackend(QMediaService *service)
|
|
{
|
|
bool backendAvailable = false;
|
|
m_backend.reset(new QDeclarativeVideoRendererBackend(this));
|
|
if (m_backend->init(service))
|
|
backendAvailable = true;
|
|
|
|
// QDeclarativeVideoWindowBackend only works when there is a service with a QVideoWindowControl.
|
|
// Without service, the QDeclarativeVideoRendererBackend should always work.
|
|
if (!backendAvailable) {
|
|
Q_ASSERT(service);
|
|
m_backend.reset(new QDeclarativeVideoWindowBackend(this));
|
|
if (m_backend->init(service))
|
|
backendAvailable = true;
|
|
}
|
|
|
|
if (!backendAvailable) {
|
|
qWarning() << Q_FUNC_INFO << "Media service has neither renderer nor window control available.";
|
|
m_backend.reset();
|
|
}
|
|
return backendAvailable;
|
|
}
|
|
|
|
void QDeclarativeVideoOutput::_q_updateMediaObject()
|
|
{
|
|
QMediaObject *mediaObject = 0;
|
|
|
|
if (m_source)
|
|
mediaObject = qobject_cast<QMediaObject*>(m_source.data()->property("mediaObject").value<QObject*>());
|
|
|
|
#ifdef DEBUG_VIDEOITEM
|
|
qDebug() << Q_FUNC_INFO << mediaObject;
|
|
#endif
|
|
|
|
if (m_mediaObject.data() == mediaObject)
|
|
return;
|
|
|
|
if (m_sourceType != VideoSurfaceSource)
|
|
m_backend.reset();
|
|
|
|
m_mediaObject.clear();
|
|
m_service.clear();
|
|
|
|
if (mediaObject) {
|
|
if (QMediaService *service = mediaObject->service()) {
|
|
if (createBackend(service)) {
|
|
m_service = service;
|
|
m_mediaObject = mediaObject;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\qmlproperty enumeration QtMultimedia::VideoOutput::fillMode
|
|
|
|
Set this property to define how the video is scaled to fit the target area.
|
|
|
|
\list
|
|
\li Stretch - the video is scaled to fit.
|
|
\li PreserveAspectFit - the video is scaled uniformly to fit without cropping
|
|
\li PreserveAspectCrop - the video is scaled uniformly to fill, cropping if necessary
|
|
\endlist
|
|
|
|
The default fill mode is PreserveAspectFit.
|
|
*/
|
|
|
|
QDeclarativeVideoOutput::FillMode QDeclarativeVideoOutput::fillMode() const
|
|
{
|
|
return m_fillMode;
|
|
}
|
|
|
|
void QDeclarativeVideoOutput::setFillMode(FillMode mode)
|
|
{
|
|
if (mode == m_fillMode)
|
|
return;
|
|
|
|
m_fillMode = mode;
|
|
m_geometryDirty = true;
|
|
update();
|
|
|
|
emit fillModeChanged(mode);
|
|
}
|
|
|
|
void QDeclarativeVideoOutput::_q_updateNativeSize()
|
|
{
|
|
if (!m_backend)
|
|
return;
|
|
|
|
QSize size = m_backend->nativeSize();
|
|
if (!qIsDefaultAspect(m_orientation)) {
|
|
size.transpose();
|
|
}
|
|
|
|
if (m_nativeSize != size) {
|
|
m_nativeSize = size;
|
|
|
|
m_geometryDirty = true;
|
|
|
|
setImplicitWidth(size.width());
|
|
setImplicitHeight(size.height());
|
|
|
|
emit sourceRectChanged();
|
|
}
|
|
}
|
|
|
|
/* Based on fill mode and our size, figure out the source/dest rects */
|
|
void QDeclarativeVideoOutput::_q_updateGeometry()
|
|
{
|
|
const QRectF rect(0, 0, width(), height());
|
|
const QRectF absoluteRect(x(), y(), width(), height());
|
|
|
|
if (!m_geometryDirty && m_lastRect == absoluteRect)
|
|
return;
|
|
|
|
QRectF oldContentRect(m_contentRect);
|
|
|
|
m_geometryDirty = false;
|
|
m_lastRect = absoluteRect;
|
|
|
|
if (m_nativeSize.isEmpty()) {
|
|
//this is necessary for item to receive the
|
|
//first paint event and configure video surface.
|
|
m_contentRect = rect;
|
|
} else if (m_fillMode == Stretch) {
|
|
m_contentRect = rect;
|
|
} else if (m_fillMode == PreserveAspectFit || m_fillMode == PreserveAspectCrop) {
|
|
QSizeF scaled = m_nativeSize;
|
|
scaled.scale(rect.size(), m_fillMode == PreserveAspectFit ?
|
|
Qt::KeepAspectRatio : Qt::KeepAspectRatioByExpanding);
|
|
|
|
m_contentRect = QRectF(QPointF(), scaled);
|
|
m_contentRect.moveCenter(rect.center());
|
|
}
|
|
|
|
if (m_backend)
|
|
m_backend->updateGeometry();
|
|
|
|
if (m_contentRect != oldContentRect)
|
|
emit contentRectChanged();
|
|
}
|
|
|
|
void QDeclarativeVideoOutput::_q_screenOrientationChanged(int orientation)
|
|
{
|
|
setOrientation(orientation);
|
|
}
|
|
|
|
/*!
|
|
\qmlproperty int QtMultimedia::VideoOutput::orientation
|
|
|
|
In some cases the source video stream requires a certain
|
|
orientation to be correct. This includes
|
|
sources like a camera viewfinder, where the displayed
|
|
viewfinder should match reality, no matter what rotation
|
|
the rest of the user interface has.
|
|
|
|
This property allows you to apply a rotation (in steps
|
|
of 90 degrees) to compensate for any user interface
|
|
rotation, with positive values in the anti-clockwise direction.
|
|
|
|
The orientation change will also affect the mapping
|
|
of coordinates from source to viewport.
|
|
*/
|
|
int QDeclarativeVideoOutput::orientation() const
|
|
{
|
|
return m_orientation;
|
|
}
|
|
|
|
void QDeclarativeVideoOutput::setOrientation(int orientation)
|
|
{
|
|
// Make sure it's a multiple of 90.
|
|
if (orientation % 90)
|
|
return;
|
|
|
|
// If there's no actual change, return
|
|
if (m_orientation == orientation)
|
|
return;
|
|
|
|
// If the new orientation is the same effect
|
|
// as the old one, don't update the video node stuff
|
|
if ((m_orientation % 360) == (orientation % 360)) {
|
|
m_orientation = orientation;
|
|
emit orientationChanged();
|
|
return;
|
|
}
|
|
|
|
m_geometryDirty = true;
|
|
|
|
// Otherwise, a new orientation
|
|
// See if we need to change aspect ratio orientation too
|
|
bool oldAspect = qIsDefaultAspect(m_orientation);
|
|
bool newAspect = qIsDefaultAspect(orientation);
|
|
|
|
m_orientation = orientation;
|
|
|
|
if (oldAspect != newAspect) {
|
|
m_nativeSize.transpose();
|
|
|
|
setImplicitWidth(m_nativeSize.width());
|
|
setImplicitHeight(m_nativeSize.height());
|
|
|
|
// Source rectangle does not change for orientation
|
|
}
|
|
|
|
update();
|
|
emit orientationChanged();
|
|
}
|
|
|
|
/*!
|
|
\qmlproperty int QtMultimedia::VideoOutput::autoOrientation
|
|
|
|
This property allows you to enable and disable auto orientation
|
|
of the video stream, so that its orientation always matches
|
|
the orientation of the screen. If \c autoOrientation is enabled,
|
|
the \c orientation property is overwritten.
|
|
|
|
By default \c autoOrientation is disabled.
|
|
|
|
\since QtMultimedia 5.2
|
|
*/
|
|
bool QDeclarativeVideoOutput::autoOrientation() const
|
|
{
|
|
return m_autoOrientation;
|
|
}
|
|
|
|
void QDeclarativeVideoOutput::setAutoOrientation(bool autoOrientation)
|
|
{
|
|
if (autoOrientation == m_autoOrientation)
|
|
return;
|
|
|
|
m_autoOrientation = autoOrientation;
|
|
if (m_autoOrientation) {
|
|
m_screenOrientationHandler = new QVideoOutputOrientationHandler(this);
|
|
connect(m_screenOrientationHandler, SIGNAL(orientationChanged(int)),
|
|
this, SLOT(_q_screenOrientationChanged(int)));
|
|
|
|
_q_screenOrientationChanged(m_screenOrientationHandler->currentOrientation());
|
|
} else {
|
|
disconnect(m_screenOrientationHandler, SIGNAL(orientationChanged(int)),
|
|
this, SLOT(_q_screenOrientationChanged(int)));
|
|
m_screenOrientationHandler->deleteLater();
|
|
m_screenOrientationHandler = 0;
|
|
}
|
|
|
|
emit autoOrientationChanged();
|
|
}
|
|
|
|
/*!
|
|
\qmlproperty rectangle QtMultimedia::VideoOutput::contentRect
|
|
|
|
This property holds the item coordinates of the area that
|
|
would contain video to render. With certain fill modes,
|
|
this rectangle will be larger than the visible area of the
|
|
\c VideoOutput.
|
|
|
|
This property is useful when other coordinates are specified
|
|
in terms of the source dimensions - this applied for relative
|
|
(normalized) frame coordinates in the range of 0 to 1.0.
|
|
|
|
\sa mapRectToItem(), mapPointToItem()
|
|
|
|
Areas outside this will be transparent.
|
|
*/
|
|
QRectF QDeclarativeVideoOutput::contentRect() const
|
|
{
|
|
return m_contentRect;
|
|
}
|
|
|
|
/*!
|
|
\qmlproperty rectangle QtMultimedia::VideoOutput::sourceRect
|
|
|
|
This property holds the area of the source video
|
|
content that is considered for rendering. The
|
|
values are in source pixel coordinates, adjusted for
|
|
the source's pixel aspect ratio.
|
|
|
|
Note that typically the top left corner of this rectangle
|
|
will be \c {0,0} while the width and height will be the
|
|
width and height of the input content. Only when the video
|
|
source has a viewport set, these values will differ.
|
|
|
|
The orientation setting does not affect this rectangle.
|
|
|
|
\sa QVideoSurfaceFormat::pixelAspectRatio()
|
|
\sa QVideoSurfaceFormat::viewport()
|
|
*/
|
|
QRectF QDeclarativeVideoOutput::sourceRect() const
|
|
{
|
|
// We might have to transpose back
|
|
QSizeF size = m_nativeSize;
|
|
if (!qIsDefaultAspect(m_orientation)) {
|
|
size.transpose();
|
|
}
|
|
|
|
// No backend? Just assume no viewport.
|
|
if (!m_nativeSize.isValid() || !m_backend) {
|
|
return QRectF(QPointF(), size);
|
|
}
|
|
|
|
// Take the viewport into account for the top left position.
|
|
// m_nativeSize is already adjusted to the viewport, as it originats
|
|
// from QVideoSurfaceFormat::sizeHint(), which includes pixel aspect
|
|
// ratio and viewport.
|
|
const QRectF viewport = m_backend->adjustedViewport();
|
|
Q_ASSERT(viewport.size() == size);
|
|
return QRectF(viewport.topLeft(), size);
|
|
}
|
|
|
|
/*!
|
|
\qmlmethod QPointF QtMultimedia::VideoOutput::mapNormalizedPointToItem (const QPointF &point) const
|
|
|
|
Given normalized coordinates \a point (that is, each
|
|
component in the range of 0 to 1.0), return the mapped point
|
|
that it corresponds to (in item coordinates).
|
|
This mapping is affected by the orientation.
|
|
|
|
Depending on the fill mode, this point may lie outside the rendered
|
|
rectangle.
|
|
*/
|
|
QPointF QDeclarativeVideoOutput::mapNormalizedPointToItem(const QPointF &point) const
|
|
{
|
|
qreal dx = point.x();
|
|
qreal dy = point.y();
|
|
|
|
if (qIsDefaultAspect(m_orientation)) {
|
|
dx *= m_contentRect.width();
|
|
dy *= m_contentRect.height();
|
|
} else {
|
|
dx *= m_contentRect.height();
|
|
dy *= m_contentRect.width();
|
|
}
|
|
|
|
switch (qNormalizedOrientation(m_orientation)) {
|
|
case 0:
|
|
default:
|
|
return m_contentRect.topLeft() + QPointF(dx, dy);
|
|
case 90:
|
|
return m_contentRect.bottomLeft() + QPointF(dy, -dx);
|
|
case 180:
|
|
return m_contentRect.bottomRight() + QPointF(-dx, -dy);
|
|
case 270:
|
|
return m_contentRect.topRight() + QPointF(-dy, dx);
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\qmlmethod QRectF QtMultimedia::VideoOutput::mapNormalizedRectToItem(const QRectF &rectangle) const
|
|
|
|
Given a rectangle \a rectangle in normalized
|
|
coordinates (that is, each component in the range of 0 to 1.0),
|
|
return the mapped rectangle that it corresponds to (in item coordinates).
|
|
This mapping is affected by the orientation.
|
|
|
|
Depending on the fill mode, this rectangle may extend outside the rendered
|
|
rectangle.
|
|
*/
|
|
QRectF QDeclarativeVideoOutput::mapNormalizedRectToItem(const QRectF &rectangle) const
|
|
{
|
|
return QRectF(mapNormalizedPointToItem(rectangle.topLeft()),
|
|
mapNormalizedPointToItem(rectangle.bottomRight())).normalized();
|
|
}
|
|
|
|
/*!
|
|
\qmlmethod QPointF QtMultimedia::VideoOutput::mapPointToSource(const QPointF &point) const
|
|
|
|
Given a point \a point in item coordinates, return the
|
|
corresponding point in source coordinates. This mapping is
|
|
affected by the orientation.
|
|
|
|
If the supplied point lies outside the rendered area, the returned
|
|
point will be outside the source rectangle.
|
|
*/
|
|
QPointF QDeclarativeVideoOutput::mapPointToSource(const QPointF &point) const
|
|
{
|
|
QPointF norm = mapPointToSourceNormalized(point);
|
|
|
|
if (qIsDefaultAspect(m_orientation))
|
|
return QPointF(norm.x() * m_nativeSize.width(), norm.y() * m_nativeSize.height());
|
|
else
|
|
return QPointF(norm.x() * m_nativeSize.height(), norm.y() * m_nativeSize.width());
|
|
}
|
|
|
|
/*!
|
|
\qmlmethod QRectF QtMultimedia::VideoOutput::mapRectToSource(const QRectF &rectangle) const
|
|
|
|
Given a rectangle \a rectangle in item coordinates, return the
|
|
corresponding rectangle in source coordinates. This mapping is
|
|
affected by the orientation.
|
|
|
|
This mapping is affected by the orientation.
|
|
|
|
If the supplied point lies outside the rendered area, the returned
|
|
point will be outside the source rectangle.
|
|
*/
|
|
QRectF QDeclarativeVideoOutput::mapRectToSource(const QRectF &rectangle) const
|
|
{
|
|
return QRectF(mapPointToSource(rectangle.topLeft()),
|
|
mapPointToSource(rectangle.bottomRight())).normalized();
|
|
}
|
|
|
|
/*!
|
|
\qmlmethod QPointF QtMultimedia::VideoOutput::mapPointToSourceNormalized(const QPointF &point) const
|
|
|
|
Given a point \a point in item coordinates, return the
|
|
corresponding point in normalized source coordinates. This mapping is
|
|
affected by the orientation.
|
|
|
|
If the supplied point lies outside the rendered area, the returned
|
|
point will be outside the source rectangle. No clamping is performed.
|
|
*/
|
|
QPointF QDeclarativeVideoOutput::mapPointToSourceNormalized(const QPointF &point) const
|
|
{
|
|
if (m_contentRect.isEmpty())
|
|
return QPointF();
|
|
|
|
// Normalize the item source point
|
|
qreal nx = (point.x() - m_contentRect.left()) / m_contentRect.width();
|
|
qreal ny = (point.y() - m_contentRect.top()) / m_contentRect.height();
|
|
|
|
const qreal one(1.0f);
|
|
|
|
// For now, the origin of the source rectangle is 0,0
|
|
switch (qNormalizedOrientation(m_orientation)) {
|
|
case 0:
|
|
default:
|
|
return QPointF(nx, ny);
|
|
case 90:
|
|
return QPointF(one - ny, nx);
|
|
case 180:
|
|
return QPointF(one - nx, one - ny);
|
|
case 270:
|
|
return QPointF(ny, one - nx);
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\qmlmethod QRectF QtMultimedia::VideoOutput::mapRectToSourceNormalized(const QRectF &rectangle) const
|
|
|
|
Given a rectangle \a rectangle in item coordinates, return the
|
|
corresponding rectangle in normalized source coordinates. This mapping is
|
|
affected by the orientation.
|
|
|
|
This mapping is affected by the orientation.
|
|
|
|
If the supplied point lies outside the rendered area, the returned
|
|
point will be outside the source rectangle. No clamping is performed.
|
|
*/
|
|
QRectF QDeclarativeVideoOutput::mapRectToSourceNormalized(const QRectF &rectangle) const
|
|
{
|
|
return QRectF(mapPointToSourceNormalized(rectangle.topLeft()),
|
|
mapPointToSourceNormalized(rectangle.bottomRight())).normalized();
|
|
}
|
|
|
|
QDeclarativeVideoOutput::SourceType QDeclarativeVideoOutput::sourceType() const
|
|
{
|
|
return m_sourceType;
|
|
}
|
|
|
|
/*!
|
|
\qmlmethod QPointF QtMultimedia::VideoOutput::mapPointToItem(const QPointF &point) const
|
|
|
|
Given a point \a point in source coordinates, return the
|
|
corresponding point in item coordinates. This mapping is
|
|
affected by the orientation.
|
|
|
|
Depending on the fill mode, this point may lie outside the rendered
|
|
rectangle.
|
|
*/
|
|
QPointF QDeclarativeVideoOutput::mapPointToItem(const QPointF &point) const
|
|
{
|
|
if (m_nativeSize.isEmpty())
|
|
return QPointF();
|
|
|
|
// Just normalize and use that function
|
|
// m_nativeSize is transposed in some orientations
|
|
if (qIsDefaultAspect(m_orientation))
|
|
return mapNormalizedPointToItem(QPointF(point.x() / m_nativeSize.width(), point.y() / m_nativeSize.height()));
|
|
else
|
|
return mapNormalizedPointToItem(QPointF(point.x() / m_nativeSize.height(), point.y() / m_nativeSize.width()));
|
|
}
|
|
|
|
/*!
|
|
\qmlmethod QRectF QtMultimedia::VideoOutput::mapRectToItem(const QRectF &rectangle) const
|
|
|
|
Given a rectangle \a rectangle in source coordinates, return the
|
|
corresponding rectangle in item coordinates. This mapping is
|
|
affected by the orientation.
|
|
|
|
Depending on the fill mode, this rectangle may extend outside the rendered
|
|
rectangle.
|
|
|
|
*/
|
|
QRectF QDeclarativeVideoOutput::mapRectToItem(const QRectF &rectangle) const
|
|
{
|
|
return QRectF(mapPointToItem(rectangle.topLeft()),
|
|
mapPointToItem(rectangle.bottomRight())).normalized();
|
|
}
|
|
|
|
QSGNode *QDeclarativeVideoOutput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
|
|
{
|
|
_q_updateGeometry();
|
|
|
|
if (!m_backend)
|
|
return 0;
|
|
|
|
return m_backend->updatePaintNode(oldNode, data);
|
|
}
|
|
|
|
void QDeclarativeVideoOutput::itemChange(QQuickItem::ItemChange change,
|
|
const QQuickItem::ItemChangeData &changeData)
|
|
{
|
|
if (m_backend)
|
|
m_backend->itemChange(change, changeData);
|
|
}
|
|
|
|
void QDeclarativeVideoOutput::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
|
|
{
|
|
Q_UNUSED(newGeometry);
|
|
Q_UNUSED(oldGeometry);
|
|
|
|
QQuickItem::geometryChanged(newGeometry, oldGeometry);
|
|
|
|
// Explicitly listen to geometry changes here. This is needed since changing the position does
|
|
// not trigger a call to updatePaintNode().
|
|
// We need to react to position changes though, as the window backened's display rect gets
|
|
// changed in that situation.
|
|
_q_updateGeometry();
|
|
}
|
|
|
|
QT_END_NAMESPACE
|