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) :
|
||||
QQuickItem(parent),
|
||||
m_sourceType(NoSource),
|
||||
m_fillMode(PreserveAspectFit)
|
||||
m_fillMode(PreserveAspectFit),
|
||||
m_orientation(0)
|
||||
{
|
||||
setFlag(ItemHasContents, true);
|
||||
m_surface = new QSGVideoItemSurface(this);
|
||||
@@ -290,6 +291,14 @@ void QDeclarativeVideoOutput::stop()
|
||||
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
|
||||
|
||||
@@ -322,7 +331,11 @@ void QDeclarativeVideoOutput::setFillMode(FillMode mode)
|
||||
|
||||
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) {
|
||||
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 *)
|
||||
{
|
||||
QSGVideoNode *videoNode = static_cast<QSGVideoNode *>(oldNode);
|
||||
@@ -396,7 +446,8 @@ QSGNode *QDeclarativeVideoOutput::updatePaintNode(QSGNode *oldNode, UpdatePaintN
|
||||
return 0;
|
||||
|
||||
_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);
|
||||
return videoNode;
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@ class QDeclarativeVideoOutput : public QQuickItem
|
||||
Q_DISABLE_COPY(QDeclarativeVideoOutput)
|
||||
Q_PROPERTY(QObject* source READ source WRITE setSource NOTIFY sourceChanged)
|
||||
Q_PROPERTY(FillMode fillMode READ fillMode WRITE setFillMode NOTIFY fillModeChanged)
|
||||
Q_PROPERTY(int orientation READ orientation WRITE setOrientation NOTIFY orientationChanged)
|
||||
Q_ENUMS(FillMode)
|
||||
|
||||
public:
|
||||
@@ -84,9 +85,13 @@ public:
|
||||
FillMode fillMode() const;
|
||||
void setFillMode(FillMode mode);
|
||||
|
||||
int orientation() const;
|
||||
void setOrientation(int);
|
||||
|
||||
Q_SIGNALS:
|
||||
void sourceChanged();
|
||||
void fillModeChanged(QDeclarativeVideoOutput::FillMode);
|
||||
void orientationChanged();
|
||||
|
||||
protected:
|
||||
QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
|
||||
@@ -122,6 +127,7 @@ private:
|
||||
QSize m_nativeSize;
|
||||
QRectF m_boundingRect;
|
||||
QRectF m_sourceRect;
|
||||
int m_orientation;
|
||||
|
||||
QMutex m_frameMutex;
|
||||
};
|
||||
|
||||
@@ -42,26 +42,83 @@
|
||||
#include "qsgvideonode_p.h"
|
||||
|
||||
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;
|
||||
|
||||
m_rect = rect;
|
||||
m_textureRect = textureRect;
|
||||
m_orientation = orientation;
|
||||
|
||||
QSGGeometry *g = geometry();
|
||||
|
||||
if (g == 0) {
|
||||
if (g == 0)
|
||||
g = new QSGGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4);
|
||||
QSGGeometry::updateTexturedRectGeometry(g, rect, textureRect);
|
||||
setGeometry(g);
|
||||
} else {
|
||||
QSGGeometry::updateTexturedRectGeometry(g, rect, textureRect);
|
||||
|
||||
QSGGeometry::TexturedPoint2D *v = g->vertexDataAsTexturedPoint2D();
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
@@ -56,11 +56,12 @@ public:
|
||||
virtual void setCurrentFrame(const QVideoFrame &frame) = 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:
|
||||
QRectF m_rect;
|
||||
QRectF m_textureRect;
|
||||
int m_orientation;
|
||||
};
|
||||
|
||||
class QSGVideoNodeFactory {
|
||||
|
||||
Reference in New Issue
Block a user