summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Kiagiadakis <george.kiagiadakis@collabora.com>2013-10-17 21:13:19 +0200
committerGeorge Kiagiadakis <george.kiagiadakis@collabora.com>2013-10-18 18:08:20 +0200
commita70cefc572fb190d4d71d3dfbb7d75afa79f119a (patch)
tree9f750840ba1357b0d3507c32759090448c0bc2b8
parent7d9a800163a92cdbfcc38aa24591c8ad20a6bb19 (diff)
qtvideosink: Improve paint areas calculations based on the qtquick2 video sink patches from Benjamin Federau
-rw-r--r--elements/gstqtvideosink/autotest.cpp41
-rw-r--r--elements/gstqtvideosink/delegates/qtvideosinkdelegate.cpp24
-rw-r--r--elements/gstqtvideosink/delegates/qtvideosinkdelegate.h1
-rw-r--r--elements/gstqtvideosink/painters/abstractsurfacepainter.h2
-rw-r--r--elements/gstqtvideosink/painters/genericsurfacepainter.cpp9
-rw-r--r--elements/gstqtvideosink/painters/genericsurfacepainter.h2
-rw-r--r--elements/gstqtvideosink/painters/openglsurfacepainter.cpp9
-rw-r--r--elements/gstqtvideosink/painters/openglsurfacepainter.h2
-rw-r--r--elements/gstqtvideosink/utils/utils.cpp71
-rw-r--r--elements/gstqtvideosink/utils/utils.h15
10 files changed, 97 insertions, 79 deletions
diff --git a/elements/gstqtvideosink/autotest.cpp b/elements/gstqtvideosink/autotest.cpp
index 7aa2e40..9c760a5 100644
--- a/elements/gstqtvideosink/autotest.cpp
+++ b/elements/gstqtvideosink/autotest.cpp
@@ -43,6 +43,7 @@
#include "painters/genericsurfacepainter.h"
+Q_DECLARE_METATYPE(Qt::AspectRatioMode)
struct PipelineDeleter
{
@@ -247,27 +248,31 @@ void QtVideoSinkTest::paintAreasTest_data()
QTest::addColumn<QRectF>("blackArea1");
QTest::addColumn<QRectF>("videoArea");
QTest::addColumn<QRectF>("blackArea2");
+ QTest::addColumn<Qt::AspectRatioMode>("mode");
QTest::newRow("targetArea == videoArea")
<< QRectF(0.0, 0.0, 320.0, 240.0)
<< QSize(320, 240) << Fraction(1, 1) << Fraction(1, 1)
<< QRectF(0.0, 0.0, 0.0, 0.0)
<< QRectF(0.0, 0.0, 320.0, 240.0)
- << QRectF(0.0, 0.0, 0.0, 0.0);
+ << QRectF(0.0, 0.0, 0.0, 0.0)
+ << Qt::KeepAspectRatio;
QTest::newRow("targetArea wide")
<< QRectF(0.0, 0.0, 400.0, 240.0)
<< QSize(320, 240) << Fraction(1, 1) << Fraction(1, 1)
<< QRectF(0.0, 0.0, 40.0, 240.0)
<< QRectF(40.0, 0.0, 320.0, 240.0)
- << QRectF(360.0, 0.0, 40.0, 240.0);
+ << QRectF(360.0, 0.0, 40.0, 240.0)
+ << Qt::KeepAspectRatio;
QTest::newRow("targetArea tall")
<< QRectF(0.0, 0.0, 320.0, 300.0)
<< QSize(320, 240) << Fraction(1, 1) << Fraction(1, 1)
<< QRectF(0.0, 0.0, 320.0, 30.0)
<< QRectF(0.0, 30.0, 320.0, 240.0)
- << QRectF(0.0, 270.0, 320.0, 30.0);
+ << QRectF(0.0, 270.0, 320.0, 30.0)
+ << Qt::KeepAspectRatio;
QTest::newRow("targetArea == videoArea @ (2, 3)")
@@ -275,21 +280,24 @@ void QtVideoSinkTest::paintAreasTest_data()
<< QSize(320, 240) << Fraction(1, 1) << Fraction(1, 1)
<< QRectF(0.0, 0.0, 0.0, 0.0)
<< QRectF(2.0, 3.0, 320.0, 240.0)
- << QRectF(0.0, 0.0, 0.0, 0.0);
+ << QRectF(0.0, 0.0, 0.0, 0.0)
+ << Qt::KeepAspectRatio;
QTest::newRow("targetArea wide @ (2, 3)")
<< QRectF(2.0, 3.0, 400.0, 240.0)
<< QSize(320, 240) << Fraction(1, 1) << Fraction(1, 1)
<< QRectF(2.0, 3.0, 40.0, 240.0)
<< QRectF(42.0, 3.0, 320.0, 240.0)
- << QRectF(362.0, 3.0, 40.0, 240.0);
+ << QRectF(362.0, 3.0, 40.0, 240.0)
+ << Qt::KeepAspectRatio;
QTest::newRow("targetArea tall @ (2, 3)")
<< QRectF(2.0, 3.0, 320.0, 300.0)
<< QSize(320, 240) << Fraction(1, 1) << Fraction(1, 1)
<< QRectF(2.0, 3.0, 320.0, 30.0)
<< QRectF(2.0, 33.0, 320.0, 240.0)
- << QRectF(2.0, 273.0, 320.0, 30.0);
+ << QRectF(2.0, 273.0, 320.0, 30.0)
+ << Qt::KeepAspectRatio;
QTest::newRow("targetArea.size() == videoSize w/ par 2/1")
@@ -297,14 +305,16 @@ void QtVideoSinkTest::paintAreasTest_data()
<< QSize(160, 240) << Fraction(2, 1) << Fraction(1, 1)
<< QRectF(0.0, 0.0, 160.0, 60.0)
<< QRectF(0.0, 60.0, 160.0, 120.0)
- << QRectF(0.0, 180.0, 160.0, 60.0);
+ << QRectF(0.0, 180.0, 160.0, 60.0)
+ << Qt::KeepAspectRatio;
QTest::newRow("dar 2/1")
<< QRectF(0.0, 0.0, 160.0, 240.0)
<< QSize(320, 240) << Fraction(1, 1) << Fraction(2, 1)
<< QRectF(0.0, 0.0, 0.0, 0.0)
<< QRectF(0.0, 0.0, 160.0, 240.0)
- << QRectF(0.0, 0.0, 0.0, 0.0);
+ << QRectF(0.0, 0.0, 0.0, 0.0)
+ << Qt::KeepAspectRatio;
}
void QtVideoSinkTest::paintAreasTest()
@@ -316,9 +326,10 @@ void QtVideoSinkTest::paintAreasTest()
QFETCH(QRectF, blackArea1);
QFETCH(QRectF, videoArea);
QFETCH(QRectF, blackArea2);
+ QFETCH(Qt::AspectRatioMode, mode);
PaintAreas areas;
- areas.calculate(targetArea, frameSize, pixelAspectRatio, displayAspectRatio);
+ areas.calculate(targetArea, frameSize, pixelAspectRatio, displayAspectRatio, mode);
QCOMPARE(areas.targetArea, targetArea);
QCOMPARE(areas.videoArea, videoArea);
QCOMPARE(areas.blackArea1, blackArea1);
@@ -354,6 +365,7 @@ void QtVideoSinkTest::genericSurfacePainterFormatsTest()
PaintAreas areas;
areas.targetArea = QRectF(QPointF(0,0), bufferFormat.frameSize());
areas.videoArea = areas.targetArea;
+ areas.sourceRect = QRectF(0, 0, 1, 1);
GenericSurfacePainter genericSurfacePainter;
QVERIFY(genericSurfacePainter.supportsFormat(format));
@@ -372,7 +384,6 @@ void QtVideoSinkTest::genericSurfacePainterFormatsTest()
genericSurfacePainter.paint(
GST_BUFFER_DATA(buffer.data()),
bufferFormat,
- areas.targetArea,
&painter,
areas);
QCOMPARE(targetImage.pixel(50, 50), qRgb(255, 0, 0));
@@ -382,7 +393,6 @@ void QtVideoSinkTest::genericSurfacePainterFormatsTest()
genericSurfacePainter.paint(
GST_BUFFER_DATA(buffer.data()),
bufferFormat,
- areas.targetArea,
&painter,
areas);
QCOMPARE(targetImage.pixel(50, 50), qRgb(0, 255, 0));
@@ -392,7 +402,6 @@ void QtVideoSinkTest::genericSurfacePainterFormatsTest()
genericSurfacePainter.paint(
GST_BUFFER_DATA(buffer.data()),
bufferFormat,
- areas.targetArea,
&painter,
areas);
QCOMPARE(targetImage.pixel(50, 50), qRgb(0, 0, 255));
@@ -402,7 +411,6 @@ void QtVideoSinkTest::genericSurfacePainterFormatsTest()
genericSurfacePainter.paint(
GST_BUFFER_DATA(buffer.data()),
bufferFormat,
- areas.targetArea,
&painter,
areas);
}
@@ -451,6 +459,7 @@ void QtVideoSinkTest::glSurfacePainterFormatsTest()
PaintAreas areas;
areas.targetArea = QRectF(QPointF(0,0), bufferFormat.frameSize());
areas.videoArea = areas.targetArea;
+ areas.sourceRect = QRectF(0, 0, 1, 1);
QGLPixelBuffer pixelBuffer(100, 100);
pixelBuffer.makeCurrent();
@@ -480,7 +489,6 @@ void QtVideoSinkTest::glSurfacePainterFormatsTest()
glSurfacePainter->paint(
GST_BUFFER_DATA(buffer.data()),
bufferFormat,
- areas.targetArea,
&painter,
areas);
QRgb pixel1 = pixelBuffer.toImage().pixel(50, 50);
@@ -497,7 +505,6 @@ void QtVideoSinkTest::glSurfacePainterFormatsTest()
glSurfacePainter->paint(
GST_BUFFER_DATA(buffer.data()),
bufferFormat,
- areas.targetArea,
&painter,
areas);
pixel1 = pixelBuffer.toImage().pixel(50, 50);
@@ -513,7 +520,6 @@ void QtVideoSinkTest::glSurfacePainterFormatsTest()
glSurfacePainter->paint(
GST_BUFFER_DATA(buffer.data()),
bufferFormat,
- areas.targetArea,
&painter,
areas);
pixel1 = pixelBuffer.toImage().pixel(50, 50);
@@ -529,7 +535,6 @@ void QtVideoSinkTest::glSurfacePainterFormatsTest()
glSurfacePainter->paint(
GST_BUFFER_DATA(buffer.data()),
bufferFormat,
- areas.targetArea,
&painter,
areas);
}
@@ -948,7 +953,7 @@ void QtVideoSinkTest::imageCompare(const QImage & image1, const QImage & image2,
QRect barsArea;
if (sourceSize.isValid() && sourceSize != image1.size()) {
PaintAreas areas;
- areas.calculate(image1.rect(), sourceSize, Fraction(1,1), Fraction(1,1));
+ areas.calculate(image1.rect(), sourceSize, Fraction(1,1), Fraction(1,1), Qt::KeepAspectRatio);
barsArea = areas.videoArea.toRect();
} else {
barsArea = image1.rect();
diff --git a/elements/gstqtvideosink/delegates/qtvideosinkdelegate.cpp b/elements/gstqtvideosink/delegates/qtvideosinkdelegate.cpp
index 228f3f0..a200334 100644
--- a/elements/gstqtvideosink/delegates/qtvideosinkdelegate.cpp
+++ b/elements/gstqtvideosink/delegates/qtvideosinkdelegate.cpp
@@ -196,15 +196,14 @@ void QtVideoSinkDelegate::paint(QPainter *painter, const QRectF & targetArea)
{
m_forceAspectRatioDirty = false;
- if (m_forceAspectRatio) {
- QReadLocker pixelAspectRatioLocker(&m_pixelAspectRatioLock);
- m_areas.calculate(targetArea, format.frameSize(),
- format.pixelAspectRatio(), m_pixelAspectRatio);
- } else {
- m_areas.targetArea = targetArea;
- m_areas.videoArea = targetArea;
- m_areas.blackArea1 = m_areas.blackArea2 = QRectF();
- }
+
+ QReadLocker pixelAspectRatioLocker(&m_pixelAspectRatioLock);
+ Qt::AspectRatioMode aspectRatioMode = m_forceAspectRatio ?
+ Qt::KeepAspectRatio : Qt::IgnoreAspectRatio;
+ m_areas.calculate(targetArea, format.frameSize(),
+ format.pixelAspectRatio(), m_pixelAspectRatio,
+ aspectRatioMode);
+ pixelAspectRatioLocker.unlock();
GST_LOG_OBJECT(m_sink,
"Recalculated paint areas: "
@@ -222,11 +221,6 @@ void QtVideoSinkDelegate::paint(QPainter *painter, const QRectF & targetArea)
}
forceAspectRatioLocker.unlock();
- if (m_formatDirty /* || m_clipRectDirty */) {
- //TODO add properties for modifying clipRect
- m_clipRect = QRectF(QPointF(0,0), format.frameSize());
- }
-
//if either pixelFormat or frameSize have changed, we need to reset the painter
//and/or change painter, in case the current one does not handle the requested format
if ((m_formatDirty && (format.videoFormat() != m_bufferFormat.videoFormat()
@@ -251,7 +245,7 @@ void QtVideoSinkDelegate::paint(QPainter *painter, const QRectF & targetArea)
}
colorsLocker.unlock();
- m_painter->paint(m_buffer->data, m_bufferFormat, m_clipRect, painter, m_areas);
+ m_painter->paint(m_buffer->data, m_bufferFormat, painter, m_areas);
}
}
}
diff --git a/elements/gstqtvideosink/delegates/qtvideosinkdelegate.h b/elements/gstqtvideosink/delegates/qtvideosinkdelegate.h
index 31c1e78..b2f2726 100644
--- a/elements/gstqtvideosink/delegates/qtvideosinkdelegate.h
+++ b/elements/gstqtvideosink/delegates/qtvideosinkdelegate.h
@@ -156,7 +156,6 @@ private:
bool m_formatDirty;
BufferFormat m_bufferFormat;
PaintAreas m_areas;
- QRectF m_clipRect;
// whether the sink is active (PAUSED or PLAYING)
mutable QReadWriteLock m_isActiveLock;
diff --git a/elements/gstqtvideosink/painters/abstractsurfacepainter.h b/elements/gstqtvideosink/painters/abstractsurfacepainter.h
index 3e90a77..edc4177 100644
--- a/elements/gstqtvideosink/painters/abstractsurfacepainter.h
+++ b/elements/gstqtvideosink/painters/abstractsurfacepainter.h
@@ -33,7 +33,7 @@ public:
virtual void init(const BufferFormat & format) = 0;
virtual void cleanup() = 0;
- virtual void paint(quint8 *data, const BufferFormat & frameFormat, const QRectF & clipRect,
+ virtual void paint(quint8 *data, const BufferFormat & frameFormat,
QPainter *painter, const PaintAreas & areas) = 0;
virtual void updateColors(int brightness, int contrast, int hue, int saturation) = 0;
diff --git a/elements/gstqtvideosink/painters/genericsurfacepainter.cpp b/elements/gstqtvideosink/painters/genericsurfacepainter.cpp
index 864ea18..fcdeadd 100644
--- a/elements/gstqtvideosink/painters/genericsurfacepainter.cpp
+++ b/elements/gstqtvideosink/painters/genericsurfacepainter.cpp
@@ -78,7 +78,6 @@ void GenericSurfacePainter::cleanup()
void GenericSurfacePainter::paint(quint8 *data,
const BufferFormat & frameFormat,
- const QRectF & clipRect,
QPainter *painter,
const PaintAreas & areas)
{
@@ -91,8 +90,14 @@ void GenericSurfacePainter::paint(quint8 *data,
frameFormat.bytesPerLine(),
m_imageFormat);
+ QRectF sourceRect = areas.sourceRect;
+ sourceRect.setX(sourceRect.x() * frameFormat.frameSize().width());
+ sourceRect.setY(sourceRect.y() * frameFormat.frameSize().height());
+ sourceRect.setWidth(sourceRect.width() * frameFormat.frameSize().width());
+ sourceRect.setHeight(sourceRect.height() * frameFormat.frameSize().height());
+
painter->fillRect(areas.blackArea1, Qt::black);
- painter->drawImage(areas.videoArea, image, clipRect);
+ painter->drawImage(areas.videoArea, image, sourceRect);
painter->fillRect(areas.blackArea2, Qt::black);
}
diff --git a/elements/gstqtvideosink/painters/genericsurfacepainter.h b/elements/gstqtvideosink/painters/genericsurfacepainter.h
index 66325df..e481a75 100644
--- a/elements/gstqtvideosink/painters/genericsurfacepainter.h
+++ b/elements/gstqtvideosink/painters/genericsurfacepainter.h
@@ -39,7 +39,7 @@ public:
virtual void init(const BufferFormat &format);
virtual void cleanup();
- virtual void paint(quint8 *data, const BufferFormat & frameFormat, const QRectF & clipRect,
+ virtual void paint(quint8 *data, const BufferFormat & frameFormat,
QPainter *painter, const PaintAreas & areas);
virtual void updateColors(int brightness, int contrast, int hue, int saturation);
diff --git a/elements/gstqtvideosink/painters/openglsurfacepainter.cpp b/elements/gstqtvideosink/painters/openglsurfacepainter.cpp
index b3598ec..6cae138 100644
--- a/elements/gstqtvideosink/painters/openglsurfacepainter.cpp
+++ b/elements/gstqtvideosink/painters/openglsurfacepainter.cpp
@@ -165,7 +165,6 @@ void OpenGLSurfacePainter::updateColors(int brightness, int contrast, int hue, i
void OpenGLSurfacePainter::paint(quint8 *data,
const BufferFormat & frameFormat,
- const QRectF & clipRect,
QPainter *painter,
const PaintAreas & areas)
{
@@ -183,10 +182,10 @@ void OpenGLSurfacePainter::paint(quint8 *data,
const GLfloat vertexCoordArray[] = QRECT_TO_GLMATRIX(areas.videoArea);
- const GLfloat txLeft = clipRect.left() / frameFormat.frameSize().width();
- const GLfloat txRight = (clipRect.right() + 1) / frameFormat.frameSize().width();
- const GLfloat txTop = clipRect.top() / frameFormat.frameSize().height();
- const GLfloat txBottom = (clipRect.bottom() + 1) / frameFormat.frameSize().height();
+ const GLfloat txLeft = areas.sourceRect.left();
+ const GLfloat txRight = areas.sourceRect.right();
+ const GLfloat txTop = areas.sourceRect.top();
+ const GLfloat txBottom = areas.sourceRect.bottom();
const GLfloat textureCoordArray[] =
{
diff --git a/elements/gstqtvideosink/painters/openglsurfacepainter.h b/elements/gstqtvideosink/painters/openglsurfacepainter.h
index c1e2dd0..05762dc 100644
--- a/elements/gstqtvideosink/painters/openglsurfacepainter.h
+++ b/elements/gstqtvideosink/painters/openglsurfacepainter.h
@@ -48,7 +48,7 @@ public:
}
virtual void updateColors(int brightness, int contrast, int hue, int saturation);
- virtual void paint(quint8 *data, const BufferFormat & frameFormat, const QRectF & clipRect,
+ virtual void paint(quint8 *data, const BufferFormat & frameFormat,
QPainter *painter, const PaintAreas & areas);
protected:
diff --git a/elements/gstqtvideosink/utils/utils.cpp b/elements/gstqtvideosink/utils/utils.cpp
index c62100b..0c83f04 100644
--- a/elements/gstqtvideosink/utils/utils.cpp
+++ b/elements/gstqtvideosink/utils/utils.cpp
@@ -1,5 +1,7 @@
/*
- Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
+ Copyright (C) 2011-2013 Collabora Ltd. <info@collabora.com>
+ Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+ Copyright (C) 2013 basysKom GmbH <info@basyskom.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
@@ -15,42 +17,49 @@
*/
#include "utils.h"
-/*
- * Modified version of gst_video_sink_center_rect
- * Copyright (C) Julien Moutte <julien@moutte.net>
- */
-static QRectF centerRect(const QRectF & src, const QRectF & dst)
+void PaintAreas::calculate(const QRectF & targetArea,
+ const QSize & videoSize,
+ const Fraction & pixelAspectRatio,
+ const Fraction & displayAspectRatio,
+ Qt::AspectRatioMode aspectRatioMode)
{
- QRectF result = dst;
- qreal srcRatio = src.width() / src.height();
- qreal dstRatio = dst.width() / dst.height();
+ this->targetArea = targetArea;
- if (srcRatio > dstRatio) {
- result.setWidth(dst.width());
- result.setHeight(dst.width() / srcRatio);
- result.moveTop(result.top() + ((dst.height() - result.height()) / 2));
- } else if (srcRatio < dstRatio) {
- result.setWidth(dst.height() * srcRatio);
- result.setHeight(dst.height());
- result.moveLeft(result.left() + ((dst.width() - result.width()) / 2));
- }
-
- return result;
-}
+ switch (aspectRatioMode) {
+ case Qt::IgnoreAspectRatio:
+ videoArea = targetArea;
+ sourceRect = QRectF(0, 0, 1, 1);
+ blackArea1 = blackArea2 = QRectF();
+ break;
+ default:
+ {
+ qreal aspectRatio = pixelAspectRatio.ratio() * displayAspectRatio.invRatio();
-void PaintAreas::calculate(const QRectF & _targetArea,
- const QSize & frameSize,
- const Fraction & pixelAspectRatio,
- const Fraction & displayAspectRatio)
-{
- targetArea = _targetArea;
+ QSizeF videoSizeAdjusted = QSizeF(videoSize.width() * aspectRatio, videoSize.height());
+ videoSizeAdjusted.scale(targetArea.size(), aspectRatioMode);
- qreal aspectRatio = pixelAspectRatio.ratio() * displayAspectRatio.invRatio();
- QRectF srcRect(QPointF(0,0), QSizeF(frameSize.width() * aspectRatio, frameSize.height()));
+ // the area that the original video occupies, scaled
+ QRectF videoRect = QRectF(QPointF(), videoSizeAdjusted);
+ videoRect.moveCenter(targetArea.center());
- videoArea = centerRect(srcRect, targetArea);
+ if (aspectRatioMode == Qt::KeepAspectRatio) {
+ videoArea = videoRect;
+ sourceRect = QRectF(0, 0, 1, 1);
+ } else { // Qt::KeepAspectRatioByExpanding
+ videoArea = targetArea;
+ sourceRect = QRectF(
+ (videoArea.left() - videoRect.left()) / videoRect.width(),
+ (videoArea.top() - videoRect.top()) / videoRect.height(),
+ videoArea.width() / videoRect.width(),
+ videoArea.height() / videoRect.height());
+ }
+ break;
+ }
+ }
- if (videoArea == targetArea) {
+ if (aspectRatioMode == Qt::IgnoreAspectRatio
+ || aspectRatioMode == Qt::KeepAspectRatioByExpanding
+ || videoArea == targetArea) {
blackArea1 = blackArea2 = QRectF();
} else {
blackArea1 = QRectF(
diff --git a/elements/gstqtvideosink/utils/utils.h b/elements/gstqtvideosink/utils/utils.h
index a2924a9..6e16c45 100644
--- a/elements/gstqtvideosink/utils/utils.h
+++ b/elements/gstqtvideosink/utils/utils.h
@@ -42,15 +42,22 @@ struct Fraction
struct PaintAreas
{
- void calculate(const QRectF & targetArea, const QSize & frameSize,
- const Fraction & pixelAspectRatio, const Fraction & displayAspectRatio);
+ void calculate(const QRectF & targetArea,
+ const QSize & videoSize,
+ const Fraction & pixelAspectRatio,
+ const Fraction & displayAspectRatio,
+ Qt::AspectRatioMode aspectRatioMode);
// the area that we paint on
QRectF targetArea;
-
- // the area where the video should be painted on (subrect of or equal to targetArea)
+ // the area where the video should be painted on
+ // (subrect of or equal to targetArea)
QRectF videoArea;
+ // the part of the video rectangle that we are going to blit on the videoArea
+ // in the normalized (0,1] range (texture coordinates)
+ QRectF sourceRect;
+
// these are small subrects of targetArea that are not
// covered by videoArea to keep the video's aspect ratio
QRectF blackArea1;