Commit 0d9526b5 authored by Thomas McGuire's avatar Thomas McGuire Committed by The Qt Project
Browse files

VideoOutput: Take the surface's viewport into account


Task-Number: QTBUG-30410

Change-Id: I480ce0bcd7ec136e54b5bfc5fec0e901141b72d8
Reviewed-by: default avatarJosh Faust <jfaust@suitabletech.com>
Reviewed-by: default avatarYoann Lopes <yoann.lopes@digia.com>
parent 2eac9327
Branches
Tags
No related merge requests found
Showing with 74 additions and 14 deletions
...@@ -436,13 +436,18 @@ QRectF QDeclarativeVideoOutput::contentRect() const ...@@ -436,13 +436,18 @@ QRectF QDeclarativeVideoOutput::contentRect() const
This property holds the area of the source video This property holds the area of the source video
content that is considered for rendering. The content that is considered for rendering. The
values are in source pixel coordinates. values are in source pixel coordinates, adjusted for
the source's pixel aspect ratio.
Note that typically the top left corner of this rectangle Note that typically the top left corner of this rectangle
will be \c {0,0} while the width and height will be the will be \c {0,0} while the width and height will be the
width and height of the input content. 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. The orientation setting does not affect this rectangle.
\sa QVideoSurfaceFormat::pixelAspectRatio()
\sa QVideoSurfaceFormat::viewport()
*/ */
QRectF QDeclarativeVideoOutput::sourceRect() const QRectF QDeclarativeVideoOutput::sourceRect() const
{ {
...@@ -451,7 +456,19 @@ QRectF QDeclarativeVideoOutput::sourceRect() const ...@@ -451,7 +456,19 @@ QRectF QDeclarativeVideoOutput::sourceRect() const
if (!qIsDefaultAspect(m_orientation)) { if (!qIsDefaultAspect(m_orientation)) {
size.transpose(); size.transpose();
} }
return QRectF(QPointF(), size); // XXX ignores viewport
// 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);
} }
/*! /*!
......
...@@ -74,6 +74,9 @@ public: ...@@ -74,6 +74,9 @@ public:
virtual QSGNode *updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *data) = 0; virtual QSGNode *updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *data) = 0;
virtual QAbstractVideoSurface *videoSurface() const = 0; virtual QAbstractVideoSurface *videoSurface() const = 0;
// The viewport, adjusted for the pixel aspect ratio
virtual QRectF adjustedViewport() const = 0;
protected: protected:
QDeclarativeVideoOutput *q; QDeclarativeVideoOutput *q;
QPointer<QMediaService> m_service; QPointer<QMediaService> m_service;
......
...@@ -133,30 +133,45 @@ QSize QDeclarativeVideoRendererBackend::nativeSize() const ...@@ -133,30 +133,45 @@ QSize QDeclarativeVideoRendererBackend::nativeSize() const
void QDeclarativeVideoRendererBackend::updateGeometry() void QDeclarativeVideoRendererBackend::updateGeometry()
{ {
const QRectF viewport = videoSurface()->surfaceFormat().viewport();
const QSizeF frameSize = videoSurface()->surfaceFormat().frameSize();
const QRectF normalizedViewport(viewport.x() / frameSize.width(),
viewport.y() / frameSize.height(),
viewport.width() / frameSize.width(),
viewport.height() / frameSize.height());
const QRectF rect(0, 0, q->width(), q->height()); const QRectF rect(0, 0, q->width(), q->height());
if (nativeSize().isEmpty()) { if (nativeSize().isEmpty()) {
m_renderedRect = rect; m_renderedRect = rect;
m_sourceTextureRect = QRectF(0, 0, 1, 1); m_sourceTextureRect = normalizedViewport;
} else if (q->fillMode() == QDeclarativeVideoOutput::Stretch) { } else if (q->fillMode() == QDeclarativeVideoOutput::Stretch) {
m_renderedRect = rect; m_renderedRect = rect;
m_sourceTextureRect = QRectF(0, 0, 1, 1); m_sourceTextureRect = normalizedViewport;
} else if (q->fillMode() == QDeclarativeVideoOutput::PreserveAspectFit) { } else if (q->fillMode() == QDeclarativeVideoOutput::PreserveAspectFit) {
m_sourceTextureRect = QRectF(0, 0, 1, 1); m_sourceTextureRect = normalizedViewport;
m_renderedRect = q->contentRect(); m_renderedRect = q->contentRect();
} else if (q->fillMode() == QDeclarativeVideoOutput::PreserveAspectCrop) { } else if (q->fillMode() == QDeclarativeVideoOutput::PreserveAspectCrop) {
m_renderedRect = rect; m_renderedRect = rect;
const qreal contentHeight = q->contentRect().height(); const qreal contentHeight = q->contentRect().height();
const qreal contentWidth = q->contentRect().width(); const qreal contentWidth = q->contentRect().width();
// Calculate the size of the source rectangle without taking the viewport into account
const qreal relativeOffsetLeft = -q->contentRect().left() / contentWidth;
const qreal relativeOffsetTop = -q->contentRect().top() / contentHeight;
const qreal relativeWidth = rect.width() / contentWidth;
const qreal relativeHeight = rect.height() / contentHeight;
// Now take the viewport size into account
const qreal totalOffsetLeft = normalizedViewport.x() + relativeOffsetLeft * normalizedViewport.width();
const qreal totalOffsetTop = normalizedViewport.y() + relativeOffsetTop * normalizedViewport.height();
const qreal totalWidth = normalizedViewport.width() * relativeWidth;
const qreal totalHeight = normalizedViewport.height() * relativeHeight;
if (qIsDefaultAspect(q->orientation())) { if (qIsDefaultAspect(q->orientation())) {
m_sourceTextureRect = QRectF(-q->contentRect().left() / contentWidth, m_sourceTextureRect = QRectF(totalOffsetLeft, totalOffsetTop,
-q->contentRect().top() / contentHeight, totalWidth, totalHeight);
rect.width() / contentWidth,
rect.height() / contentHeight);
} else { } else {
m_sourceTextureRect = QRectF(-q->contentRect().top() / contentHeight, m_sourceTextureRect = QRectF(totalOffsetTop, totalOffsetLeft,
-q->contentRect().left() / contentWidth, totalHeight, totalWidth);
rect.height() / contentHeight,
rect.width() / contentWidth);
} }
} }
} }
...@@ -223,6 +238,22 @@ QAbstractVideoSurface *QDeclarativeVideoRendererBackend::videoSurface() const ...@@ -223,6 +238,22 @@ QAbstractVideoSurface *QDeclarativeVideoRendererBackend::videoSurface() const
return m_surface; return m_surface;
} }
QRectF QDeclarativeVideoRendererBackend::adjustedViewport() const
{
const QRectF viewport = m_surface->surfaceFormat().viewport();
const QSize pixelAspectRatio = m_surface->surfaceFormat().pixelAspectRatio();
if (pixelAspectRatio.height() != 0) {
const qreal ratio = pixelAspectRatio.width() / pixelAspectRatio.height();
QRectF result = viewport;
result.setX(result.x() * ratio);
result.setWidth(result.width() * ratio);
return result;
}
return viewport;
}
QOpenGLContext *QDeclarativeVideoRendererBackend::glContext() const QOpenGLContext *QDeclarativeVideoRendererBackend::glContext() const
{ {
return m_glContext; return m_glContext;
......
...@@ -71,6 +71,7 @@ public: ...@@ -71,6 +71,7 @@ public:
void updateGeometry(); void updateGeometry();
QSGNode *updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *data); QSGNode *updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *data);
QAbstractVideoSurface *videoSurface() const; QAbstractVideoSurface *videoSurface() const;
QRectF adjustedViewport() const Q_DECL_OVERRIDE;
QOpenGLContext *glContext() const; QOpenGLContext *glContext() const;
friend class QSGVideoItemSurface; friend class QSGVideoItemSurface;
......
...@@ -143,4 +143,11 @@ QAbstractVideoSurface *QDeclarativeVideoWindowBackend::videoSurface() const ...@@ -143,4 +143,11 @@ QAbstractVideoSurface *QDeclarativeVideoWindowBackend::videoSurface() const
return 0; return 0;
} }
QRectF QDeclarativeVideoWindowBackend::adjustedViewport() const
{
// No viewport supported by QVideoWindowControl, so make the viewport the same size
// as the source
return QRectF(QPointF(0, 0), nativeSize());
}
QT_END_NAMESPACE QT_END_NAMESPACE
...@@ -62,6 +62,7 @@ public: ...@@ -62,6 +62,7 @@ public:
void updateGeometry(); void updateGeometry();
QSGNode *updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *data); QSGNode *updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *data);
QAbstractVideoSurface *videoSurface() const; QAbstractVideoSurface *videoSurface() const;
QRectF adjustedViewport() const Q_DECL_OVERRIDE;
private: private:
QPointer<QVideoWindowControl> m_videoWindowControl; QPointer<QVideoWindowControl> m_videoWindowControl;
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment