Allow plugins to override the QML VideoOutput type.
Move QDeclarativeVideoOutput to the private QtMultimediaQuickTools library to make the QDeclarativeVideoOutputBackend interface implementable by a plugin. Change-Id: I763c483a1fc9ec56dc7b8be0bc71523f029a36ee Reviewed-by: Yoann Lopes <yoann.lopes@digia.com>
This commit is contained in:
committed by
The Qt Project
parent
a52f552d42
commit
60fb11d9a2
760
src/qtmultimediaquicktools/qdeclarativevideooutput.cpp
Normal file
760
src/qtmultimediaquicktools/qdeclarativevideooutput.cpp
Normal file
@@ -0,0 +1,760 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** 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>
|
||||
#include <private/qmediapluginloader_p.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();
|
||||
}
|
||||
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(QMediaPluginLoader, videoBackendFactoryLoader,
|
||||
(QDeclarativeVideoBackendFactoryInterface_iid, QLatin1String("video/declarativevideobackend"), Qt::CaseInsensitive))
|
||||
|
||||
bool QDeclarativeVideoOutput::createBackend(QMediaService *service)
|
||||
{
|
||||
bool backendAvailable = false;
|
||||
|
||||
foreach (QObject *instance, videoBackendFactoryLoader()->instances(QLatin1String("declarativevideobackend"))) {
|
||||
if (QDeclarativeVideoBackendFactoryInterface *plugin = qobject_cast<QDeclarativeVideoBackendFactoryInterface*>(instance)) {
|
||||
m_backend.reset(plugin->create(this));
|
||||
if (m_backend && m_backend->init(service)) {
|
||||
backendAvailable = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!backendAvailable) {
|
||||
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
|
||||
Reference in New Issue
Block a user