Add new property to QVideoSurfaceFormat.
The 'mirrored' property indicates the QVideoFrames need to be mirrored along their vertical axis. This is typically needed for video frames coming from a front camera on a mobile device. This is implemented as a string-based property. In Qt 5.6, this should be replaced by a new public function. Change-Id: Ideb7de81e83f66826f4efb5f2951c4beec13546b Reviewed-by: Christian Stromme <christian.stromme@theqtcompany.com>
This commit is contained in:
@@ -61,6 +61,7 @@ public:
|
|||||||
, pixelAspectRatio(1, 1)
|
, pixelAspectRatio(1, 1)
|
||||||
, ycbcrColorSpace(QVideoSurfaceFormat::YCbCr_Undefined)
|
, ycbcrColorSpace(QVideoSurfaceFormat::YCbCr_Undefined)
|
||||||
, frameRate(0.0)
|
, frameRate(0.0)
|
||||||
|
, mirrored(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,6 +77,7 @@ public:
|
|||||||
, ycbcrColorSpace(QVideoSurfaceFormat::YCbCr_Undefined)
|
, ycbcrColorSpace(QVideoSurfaceFormat::YCbCr_Undefined)
|
||||||
, viewport(QPoint(0, 0), size)
|
, viewport(QPoint(0, 0), size)
|
||||||
, frameRate(0.0)
|
, frameRate(0.0)
|
||||||
|
, mirrored(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,6 +91,7 @@ public:
|
|||||||
, ycbcrColorSpace(other.ycbcrColorSpace)
|
, ycbcrColorSpace(other.ycbcrColorSpace)
|
||||||
, viewport(other.viewport)
|
, viewport(other.viewport)
|
||||||
, frameRate(other.frameRate)
|
, frameRate(other.frameRate)
|
||||||
|
, mirrored(other.mirrored)
|
||||||
, propertyNames(other.propertyNames)
|
, propertyNames(other.propertyNames)
|
||||||
, propertyValues(other.propertyValues)
|
, propertyValues(other.propertyValues)
|
||||||
{
|
{
|
||||||
@@ -104,6 +107,7 @@ public:
|
|||||||
&& viewport == other.viewport
|
&& viewport == other.viewport
|
||||||
&& frameRatesEqual(frameRate, other.frameRate)
|
&& frameRatesEqual(frameRate, other.frameRate)
|
||||||
&& ycbcrColorSpace == other.ycbcrColorSpace
|
&& ycbcrColorSpace == other.ycbcrColorSpace
|
||||||
|
&& mirrored == other.mirrored
|
||||||
&& propertyNames.count() == other.propertyNames.count()) {
|
&& propertyNames.count() == other.propertyNames.count()) {
|
||||||
for (int i = 0; i < propertyNames.count(); ++i) {
|
for (int i = 0; i < propertyNames.count(); ++i) {
|
||||||
int j = other.propertyNames.indexOf(propertyNames.at(i));
|
int j = other.propertyNames.indexOf(propertyNames.at(i));
|
||||||
@@ -130,6 +134,7 @@ public:
|
|||||||
QVideoSurfaceFormat::YCbCrColorSpace ycbcrColorSpace;
|
QVideoSurfaceFormat::YCbCrColorSpace ycbcrColorSpace;
|
||||||
QRect viewport;
|
QRect viewport;
|
||||||
qreal frameRate;
|
qreal frameRate;
|
||||||
|
bool mirrored;
|
||||||
QList<QByteArray> propertyNames;
|
QList<QByteArray> propertyNames;
|
||||||
QList<QVariant> propertyValues;
|
QList<QVariant> propertyValues;
|
||||||
};
|
};
|
||||||
@@ -468,7 +473,8 @@ QList<QByteArray> QVideoSurfaceFormat::propertyNames() const
|
|||||||
<< "frameRate"
|
<< "frameRate"
|
||||||
<< "pixelAspectRatio"
|
<< "pixelAspectRatio"
|
||||||
<< "sizeHint"
|
<< "sizeHint"
|
||||||
<< "yCbCrColorSpace")
|
<< "yCbCrColorSpace"
|
||||||
|
<< "mirrored")
|
||||||
+ d->propertyNames;
|
+ d->propertyNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -499,6 +505,8 @@ QVariant QVideoSurfaceFormat::property(const char *name) const
|
|||||||
return sizeHint();
|
return sizeHint();
|
||||||
} else if (qstrcmp(name, "yCbCrColorSpace") == 0) {
|
} else if (qstrcmp(name, "yCbCrColorSpace") == 0) {
|
||||||
return qVariantFromValue(d->ycbcrColorSpace);
|
return qVariantFromValue(d->ycbcrColorSpace);
|
||||||
|
} else if (qstrcmp(name, "mirrored") == 0) {
|
||||||
|
return d->mirrored;
|
||||||
} else {
|
} else {
|
||||||
int id = 0;
|
int id = 0;
|
||||||
for (; id < d->propertyNames.count() && d->propertyNames.at(id) != name; ++id) {}
|
for (; id < d->propertyNames.count() && d->propertyNames.at(id) != name; ++id) {}
|
||||||
@@ -547,6 +555,9 @@ void QVideoSurfaceFormat::setProperty(const char *name, const QVariant &value)
|
|||||||
} else if (qstrcmp(name, "yCbCrColorSpace") == 0) {
|
} else if (qstrcmp(name, "yCbCrColorSpace") == 0) {
|
||||||
if (value.canConvert<YCbCrColorSpace>())
|
if (value.canConvert<YCbCrColorSpace>())
|
||||||
d->ycbcrColorSpace = qvariant_cast<YCbCrColorSpace>(value);
|
d->ycbcrColorSpace = qvariant_cast<YCbCrColorSpace>(value);
|
||||||
|
} else if (qstrcmp(name, "mirrored") == 0) {
|
||||||
|
if (value.canConvert<bool>())
|
||||||
|
d->mirrored = qvariant_cast<bool>(value);
|
||||||
} else {
|
} else {
|
||||||
int id = 0;
|
int id = 0;
|
||||||
for (; id < d->propertyNames.count() && d->propertyNames.at(id) != name; ++id) {}
|
for (; id < d->propertyNames.count() && d->propertyNames.at(id) != name; ++id) {}
|
||||||
|
|||||||
@@ -86,11 +86,13 @@ private:
|
|||||||
QSize m_imageSize;
|
QSize m_imageSize;
|
||||||
QImage::Format m_imageFormat;
|
QImage::Format m_imageFormat;
|
||||||
QVideoSurfaceFormat::Direction m_scanLineDirection;
|
QVideoSurfaceFormat::Direction m_scanLineDirection;
|
||||||
|
bool m_mirrored;
|
||||||
};
|
};
|
||||||
|
|
||||||
QVideoSurfaceGenericPainter::QVideoSurfaceGenericPainter()
|
QVideoSurfaceGenericPainter::QVideoSurfaceGenericPainter()
|
||||||
: m_imageFormat(QImage::Format_Invalid)
|
: m_imageFormat(QImage::Format_Invalid)
|
||||||
, m_scanLineDirection(QVideoSurfaceFormat::TopToBottom)
|
, m_scanLineDirection(QVideoSurfaceFormat::TopToBottom)
|
||||||
|
, m_mirrored(false)
|
||||||
{
|
{
|
||||||
m_imagePixelFormats << QVideoFrame::Format_RGB32;
|
m_imagePixelFormats << QVideoFrame::Format_RGB32;
|
||||||
|
|
||||||
@@ -137,6 +139,7 @@ QAbstractVideoSurface::Error QVideoSurfaceGenericPainter::start(const QVideoSurf
|
|||||||
m_imageFormat = QVideoFrame::imageFormatFromPixelFormat(format.pixelFormat());
|
m_imageFormat = QVideoFrame::imageFormatFromPixelFormat(format.pixelFormat());
|
||||||
m_imageSize = format.frameSize();
|
m_imageSize = format.frameSize();
|
||||||
m_scanLineDirection = format.scanLineDirection();
|
m_scanLineDirection = format.scanLineDirection();
|
||||||
|
m_mirrored = format.property("mirrored").toBool();
|
||||||
|
|
||||||
const QAbstractVideoBuffer::HandleType t = format.handleType();
|
const QAbstractVideoBuffer::HandleType t = format.handleType();
|
||||||
if (t == QAbstractVideoBuffer::NoHandle) {
|
if (t == QAbstractVideoBuffer::NoHandle) {
|
||||||
@@ -183,17 +186,22 @@ QAbstractVideoSurface::Error QVideoSurfaceGenericPainter::paint(
|
|||||||
m_frame.bytesPerLine(),
|
m_frame.bytesPerLine(),
|
||||||
m_imageFormat);
|
m_imageFormat);
|
||||||
|
|
||||||
if (m_scanLineDirection == QVideoSurfaceFormat::BottomToTop) {
|
|
||||||
const QTransform oldTransform = painter->transform();
|
const QTransform oldTransform = painter->transform();
|
||||||
|
QTransform transform = oldTransform;
|
||||||
painter->scale(1, -1);
|
QRectF targetRect = target;
|
||||||
painter->translate(0, -target.bottom());
|
if (m_scanLineDirection == QVideoSurfaceFormat::BottomToTop) {
|
||||||
painter->drawImage(
|
transform.scale(1, -1);
|
||||||
QRectF(target.x(), 0, target.width(), target.height()), image, source);
|
transform.translate(0, -target.bottom());
|
||||||
painter->setTransform(oldTransform);
|
targetRect.setY(0);
|
||||||
} else {
|
|
||||||
painter->drawImage(target, image, source);
|
|
||||||
}
|
}
|
||||||
|
if (m_mirrored) {
|
||||||
|
transform.scale(-1, 1);
|
||||||
|
transform.translate(-target.right(), 0);
|
||||||
|
targetRect.setX(0);
|
||||||
|
}
|
||||||
|
painter->setTransform(transform);
|
||||||
|
painter->drawImage(targetRect, image, source);
|
||||||
|
painter->setTransform(oldTransform);
|
||||||
|
|
||||||
m_frame.unmap();
|
m_frame.unmap();
|
||||||
} else if (m_frame.isValid()) {
|
} else if (m_frame.isValid()) {
|
||||||
@@ -281,6 +289,7 @@ protected:
|
|||||||
QGLContext *m_context;
|
QGLContext *m_context;
|
||||||
QAbstractVideoBuffer::HandleType m_handleType;
|
QAbstractVideoBuffer::HandleType m_handleType;
|
||||||
QVideoSurfaceFormat::Direction m_scanLineDirection;
|
QVideoSurfaceFormat::Direction m_scanLineDirection;
|
||||||
|
bool m_mirrored;
|
||||||
QVideoSurfaceFormat::YCbCrColorSpace m_colorSpace;
|
QVideoSurfaceFormat::YCbCrColorSpace m_colorSpace;
|
||||||
GLenum m_textureFormat;
|
GLenum m_textureFormat;
|
||||||
GLuint m_textureInternalFormat;
|
GLuint m_textureInternalFormat;
|
||||||
@@ -299,6 +308,7 @@ QVideoSurfaceGLPainter::QVideoSurfaceGLPainter(QGLContext *context)
|
|||||||
: m_context(context)
|
: m_context(context)
|
||||||
, m_handleType(QAbstractVideoBuffer::NoHandle)
|
, m_handleType(QAbstractVideoBuffer::NoHandle)
|
||||||
, m_scanLineDirection(QVideoSurfaceFormat::TopToBottom)
|
, m_scanLineDirection(QVideoSurfaceFormat::TopToBottom)
|
||||||
|
, m_mirrored(false)
|
||||||
, m_colorSpace(QVideoSurfaceFormat::YCbCr_BT601)
|
, m_colorSpace(QVideoSurfaceFormat::YCbCr_BT601)
|
||||||
, m_textureFormat(0)
|
, m_textureFormat(0)
|
||||||
, m_textureInternalFormat(0)
|
, m_textureInternalFormat(0)
|
||||||
@@ -829,6 +839,7 @@ QAbstractVideoSurface::Error QVideoSurfaceArbFpPainter::start(const QVideoSurfac
|
|||||||
} else {
|
} else {
|
||||||
m_handleType = format.handleType();
|
m_handleType = format.handleType();
|
||||||
m_scanLineDirection = format.scanLineDirection();
|
m_scanLineDirection = format.scanLineDirection();
|
||||||
|
m_mirrored = format.property("mirrored").toBool();
|
||||||
m_frameSize = format.frameSize();
|
m_frameSize = format.frameSize();
|
||||||
m_colorSpace = format.yCbCrColorSpace();
|
m_colorSpace = format.yCbCrColorSpace();
|
||||||
|
|
||||||
@@ -878,8 +889,10 @@ QAbstractVideoSurface::Error QVideoSurfaceArbFpPainter::paint(
|
|||||||
if (scissorTestEnabled)
|
if (scissorTestEnabled)
|
||||||
glEnable(GL_SCISSOR_TEST);
|
glEnable(GL_SCISSOR_TEST);
|
||||||
|
|
||||||
const float txLeft = source.left() / m_frameSize.width();
|
const float txLeft = m_mirrored ? source.right() / m_frameSize.width()
|
||||||
const float txRight = source.right() / m_frameSize.width();
|
: source.left() / m_frameSize.width();
|
||||||
|
const float txRight = m_mirrored ? source.left() / m_frameSize.width()
|
||||||
|
: source.right() / m_frameSize.width();
|
||||||
const float txTop = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
|
const float txTop = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
|
||||||
? source.top() / m_frameSize.height()
|
? source.top() / m_frameSize.height()
|
||||||
: source.bottom() / m_frameSize.height();
|
: source.bottom() / m_frameSize.height();
|
||||||
@@ -1188,6 +1201,7 @@ QAbstractVideoSurface::Error QVideoSurfaceGlslPainter::start(const QVideoSurface
|
|||||||
} else {
|
} else {
|
||||||
m_handleType = format.handleType();
|
m_handleType = format.handleType();
|
||||||
m_scanLineDirection = format.scanLineDirection();
|
m_scanLineDirection = format.scanLineDirection();
|
||||||
|
m_mirrored = format.property("mirrored").toBool();
|
||||||
m_frameSize = format.frameSize();
|
m_frameSize = format.frameSize();
|
||||||
m_colorSpace = format.yCbCrColorSpace();
|
m_colorSpace = format.yCbCrColorSpace();
|
||||||
|
|
||||||
@@ -1276,8 +1290,10 @@ QAbstractVideoSurface::Error QVideoSurfaceGlslPainter::paint(
|
|||||||
GLfloat(target.right() + 1), GLfloat(target.top())
|
GLfloat(target.right() + 1), GLfloat(target.top())
|
||||||
};
|
};
|
||||||
|
|
||||||
const GLfloat txLeft = source.left() / m_frameSize.width();
|
const GLfloat txLeft = m_mirrored ? source.right() / m_frameSize.width()
|
||||||
const GLfloat txRight = source.right() / m_frameSize.width();
|
: source.left() / m_frameSize.width();
|
||||||
|
const GLfloat txRight = m_mirrored ? source.left() / m_frameSize.width()
|
||||||
|
: source.right() / m_frameSize.width();
|
||||||
const GLfloat txTop = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
|
const GLfloat txTop = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
|
||||||
? source.top() / m_frameSize.height()
|
? source.top() / m_frameSize.height()
|
||||||
: source.bottom() / m_frameSize.height();
|
: source.bottom() / m_frameSize.height();
|
||||||
|
|||||||
@@ -255,6 +255,12 @@ void QDeclarativeVideoRendererBackend::updateGeometry()
|
|||||||
m_sourceTextureRect.setTop(m_sourceTextureRect.bottom());
|
m_sourceTextureRect.setTop(m_sourceTextureRect.bottom());
|
||||||
m_sourceTextureRect.setBottom(top);
|
m_sourceTextureRect.setBottom(top);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (videoSurface()->surfaceFormat().property("mirrored").toBool()) {
|
||||||
|
qreal left = m_sourceTextureRect.left();
|
||||||
|
m_sourceTextureRect.setLeft(m_sourceTextureRect.right());
|
||||||
|
m_sourceTextureRect.setRight(left);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QSGNode *QDeclarativeVideoRendererBackend::updatePaintNode(QSGNode *oldNode,
|
QSGNode *QDeclarativeVideoRendererBackend::updatePaintNode(QSGNode *oldNode,
|
||||||
|
|||||||
@@ -521,7 +521,8 @@ void tst_QVideoSurfaceFormat::staticPropertyNames()
|
|||||||
QVERIFY(propertyNames.contains("pixelAspectRatio"));
|
QVERIFY(propertyNames.contains("pixelAspectRatio"));
|
||||||
QVERIFY(propertyNames.contains("yCbCrColorSpace"));
|
QVERIFY(propertyNames.contains("yCbCrColorSpace"));
|
||||||
QVERIFY(propertyNames.contains("sizeHint"));
|
QVERIFY(propertyNames.contains("sizeHint"));
|
||||||
QCOMPARE(propertyNames.count(), 10);
|
QVERIFY(propertyNames.contains("mirrored"));
|
||||||
|
QCOMPARE(propertyNames.count(), 11);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QVideoSurfaceFormat::dynamicProperty()
|
void tst_QVideoSurfaceFormat::dynamicProperty()
|
||||||
|
|||||||
Reference in New Issue
Block a user