Add orientation support to VideoOutput.
Just uses an integer to represent the degrees rotation from standard. Only supports multiples of 90 - other rotation can be done with standard QML. Change-Id: Id4013169c5d9da473b6e5be94ba341da21c2f2a3 Reviewed-by: Dmytro Poplavskiy <dmytro.poplavskiy@nokia.com>
This commit is contained in:
committed by
Qt by Nokia
parent
581564c990
commit
be7cc17cbf
@@ -163,7 +163,8 @@ private:
|
|||||||
QDeclarativeVideoOutput::QDeclarativeVideoOutput(QQuickItem *parent) :
|
QDeclarativeVideoOutput::QDeclarativeVideoOutput(QQuickItem *parent) :
|
||||||
QQuickItem(parent),
|
QQuickItem(parent),
|
||||||
m_sourceType(NoSource),
|
m_sourceType(NoSource),
|
||||||
m_fillMode(PreserveAspectFit)
|
m_fillMode(PreserveAspectFit),
|
||||||
|
m_orientation(0)
|
||||||
{
|
{
|
||||||
setFlag(ItemHasContents, true);
|
setFlag(ItemHasContents, true);
|
||||||
m_surface = new QSGVideoItemSurface(this);
|
m_surface = new QSGVideoItemSurface(this);
|
||||||
@@ -290,6 +291,14 @@ void QDeclarativeVideoOutput::stop()
|
|||||||
present(QVideoFrame());
|
present(QVideoFrame());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper - returns true if the given orientation has the same aspect as the default (e.g. 180*n)
|
||||||
|
*/
|
||||||
|
static inline bool qIsDefaultAspect(int o)
|
||||||
|
{
|
||||||
|
return (o % 180) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\qmlproperty enumeration VideoOutput::fillMode
|
\qmlproperty enumeration VideoOutput::fillMode
|
||||||
|
|
||||||
@@ -322,7 +331,11 @@ void QDeclarativeVideoOutput::setFillMode(FillMode mode)
|
|||||||
|
|
||||||
void QDeclarativeVideoOutput::_q_updateNativeSize(const QVideoSurfaceFormat &format)
|
void QDeclarativeVideoOutput::_q_updateNativeSize(const QVideoSurfaceFormat &format)
|
||||||
{
|
{
|
||||||
const QSize &size = format.sizeHint();
|
QSize size = format.sizeHint();
|
||||||
|
if (!qIsDefaultAspect(m_orientation)) {
|
||||||
|
size.transpose();
|
||||||
|
}
|
||||||
|
|
||||||
if (m_nativeSize != size) {
|
if (m_nativeSize != size) {
|
||||||
m_nativeSize = size;
|
m_nativeSize = size;
|
||||||
|
|
||||||
@@ -363,6 +376,43 @@ void QDeclarativeVideoOutput::_q_updateGeometry()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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());
|
||||||
|
}
|
||||||
|
|
||||||
|
update();
|
||||||
|
emit orientationChanged();
|
||||||
|
}
|
||||||
|
|
||||||
QSGNode *QDeclarativeVideoOutput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
|
QSGNode *QDeclarativeVideoOutput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
|
||||||
{
|
{
|
||||||
QSGVideoNode *videoNode = static_cast<QSGVideoNode *>(oldNode);
|
QSGVideoNode *videoNode = static_cast<QSGVideoNode *>(oldNode);
|
||||||
@@ -396,7 +446,8 @@ QSGNode *QDeclarativeVideoOutput::updatePaintNode(QSGNode *oldNode, UpdatePaintN
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
_q_updateGeometry();
|
_q_updateGeometry();
|
||||||
videoNode->setTexturedRectGeometry(m_boundingRect, m_sourceRect);
|
// Negative rotations need lots of %360
|
||||||
|
videoNode->setTexturedRectGeometry(m_boundingRect, m_sourceRect, (360 + (m_orientation % 360)) % 360);
|
||||||
videoNode->setCurrentFrame(m_frame);
|
videoNode->setCurrentFrame(m_frame);
|
||||||
return videoNode;
|
return videoNode;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ class QDeclarativeVideoOutput : public QQuickItem
|
|||||||
Q_DISABLE_COPY(QDeclarativeVideoOutput)
|
Q_DISABLE_COPY(QDeclarativeVideoOutput)
|
||||||
Q_PROPERTY(QObject* source READ source WRITE setSource NOTIFY sourceChanged)
|
Q_PROPERTY(QObject* source READ source WRITE setSource NOTIFY sourceChanged)
|
||||||
Q_PROPERTY(FillMode fillMode READ fillMode WRITE setFillMode NOTIFY fillModeChanged)
|
Q_PROPERTY(FillMode fillMode READ fillMode WRITE setFillMode NOTIFY fillModeChanged)
|
||||||
|
Q_PROPERTY(int orientation READ orientation WRITE setOrientation NOTIFY orientationChanged)
|
||||||
Q_ENUMS(FillMode)
|
Q_ENUMS(FillMode)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -84,9 +85,13 @@ public:
|
|||||||
FillMode fillMode() const;
|
FillMode fillMode() const;
|
||||||
void setFillMode(FillMode mode);
|
void setFillMode(FillMode mode);
|
||||||
|
|
||||||
|
int orientation() const;
|
||||||
|
void setOrientation(int);
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void sourceChanged();
|
void sourceChanged();
|
||||||
void fillModeChanged(QDeclarativeVideoOutput::FillMode);
|
void fillModeChanged(QDeclarativeVideoOutput::FillMode);
|
||||||
|
void orientationChanged();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
|
QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
|
||||||
@@ -122,6 +127,7 @@ private:
|
|||||||
QSize m_nativeSize;
|
QSize m_nativeSize;
|
||||||
QRectF m_boundingRect;
|
QRectF m_boundingRect;
|
||||||
QRectF m_sourceRect;
|
QRectF m_sourceRect;
|
||||||
|
int m_orientation;
|
||||||
|
|
||||||
QMutex m_frameMutex;
|
QMutex m_frameMutex;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -42,26 +42,83 @@
|
|||||||
#include "qsgvideonode_p.h"
|
#include "qsgvideonode_p.h"
|
||||||
|
|
||||||
QSGVideoNode::QSGVideoNode()
|
QSGVideoNode::QSGVideoNode()
|
||||||
|
: m_orientation(-1)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void QSGVideoNode::setTexturedRectGeometry(const QRectF &rect, const QRectF &textureRect)
|
/* Helpers */
|
||||||
|
static inline void qSetGeom(QSGGeometry::TexturedPoint2D *v, const QPointF &p)
|
||||||
{
|
{
|
||||||
if (rect == m_rect && textureRect == m_textureRect)
|
v->x = p.x();
|
||||||
|
v->y = p.y();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void qSetTex(QSGGeometry::TexturedPoint2D *v, const QPointF &p)
|
||||||
|
{
|
||||||
|
v->tx = p.x();
|
||||||
|
v->ty = p.y();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update the vertices and texture coordinates. Orientation must be in {0,90,180,270} */
|
||||||
|
void QSGVideoNode::setTexturedRectGeometry(const QRectF &rect, const QRectF &textureRect, int orientation)
|
||||||
|
{
|
||||||
|
if (rect == m_rect && textureRect == m_textureRect && orientation == m_orientation)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_rect = rect;
|
m_rect = rect;
|
||||||
m_textureRect = textureRect;
|
m_textureRect = textureRect;
|
||||||
|
m_orientation = orientation;
|
||||||
|
|
||||||
QSGGeometry *g = geometry();
|
QSGGeometry *g = geometry();
|
||||||
|
|
||||||
if (g == 0) {
|
if (g == 0)
|
||||||
g = new QSGGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4);
|
g = new QSGGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4);
|
||||||
QSGGeometry::updateTexturedRectGeometry(g, rect, textureRect);
|
|
||||||
setGeometry(g);
|
QSGGeometry::TexturedPoint2D *v = g->vertexDataAsTexturedPoint2D();
|
||||||
} else {
|
|
||||||
QSGGeometry::updateTexturedRectGeometry(g, rect, textureRect);
|
// Set geometry first
|
||||||
|
qSetGeom(v + 0, rect.topLeft());
|
||||||
|
qSetGeom(v + 1, rect.bottomLeft());
|
||||||
|
qSetGeom(v + 2, rect.topRight());
|
||||||
|
qSetGeom(v + 3, rect.bottomRight());
|
||||||
|
|
||||||
|
// and then texture coordinates
|
||||||
|
switch (orientation) {
|
||||||
|
default:
|
||||||
|
// tl, bl, tr, br
|
||||||
|
qSetTex(v + 0, textureRect.topLeft());
|
||||||
|
qSetTex(v + 1, textureRect.bottomLeft());
|
||||||
|
qSetTex(v + 2, textureRect.topRight());
|
||||||
|
qSetTex(v + 3, textureRect.bottomRight());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 90:
|
||||||
|
// tr, tl, br, bl
|
||||||
|
qSetTex(v + 0, textureRect.topRight());
|
||||||
|
qSetTex(v + 1, textureRect.topLeft());
|
||||||
|
qSetTex(v + 2, textureRect.bottomRight());
|
||||||
|
qSetTex(v + 3, textureRect.bottomLeft());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 180:
|
||||||
|
// br, tr, bl, tl
|
||||||
|
qSetTex(v + 0, textureRect.bottomRight());
|
||||||
|
qSetTex(v + 1, textureRect.topRight());
|
||||||
|
qSetTex(v + 2, textureRect.bottomLeft());
|
||||||
|
qSetTex(v + 3, textureRect.topLeft());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 270:
|
||||||
|
// bl, br, tl, tr
|
||||||
|
qSetTex(v + 0, textureRect.bottomLeft());
|
||||||
|
qSetTex(v + 1, textureRect.bottomRight());
|
||||||
|
qSetTex(v + 2, textureRect.topLeft());
|
||||||
|
qSetTex(v + 3, textureRect.topRight());
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!geometry())
|
||||||
|
setGeometry(g);
|
||||||
|
|
||||||
markDirty(DirtyGeometry);
|
markDirty(DirtyGeometry);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,11 +56,12 @@ public:
|
|||||||
virtual void setCurrentFrame(const QVideoFrame &frame) = 0;
|
virtual void setCurrentFrame(const QVideoFrame &frame) = 0;
|
||||||
virtual QVideoFrame::PixelFormat pixelFormat() const = 0;
|
virtual QVideoFrame::PixelFormat pixelFormat() const = 0;
|
||||||
|
|
||||||
void setTexturedRectGeometry(const QRectF &boundingRect, const QRectF &textureRect);
|
void setTexturedRectGeometry(const QRectF &boundingRect, const QRectF &textureRect, int orientation);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QRectF m_rect;
|
QRectF m_rect;
|
||||||
QRectF m_textureRect;
|
QRectF m_textureRect;
|
||||||
|
int m_orientation;
|
||||||
};
|
};
|
||||||
|
|
||||||
class QSGVideoNodeFactory {
|
class QSGVideoNodeFactory {
|
||||||
|
|||||||
Reference in New Issue
Block a user