diff options
author | George Kiagiadakis <george.kiagiadakis@collabora.com> | 2013-10-17 21:13:19 +0200 |
---|---|---|
committer | George Kiagiadakis <george.kiagiadakis@collabora.com> | 2013-10-18 18:08:20 +0200 |
commit | a70cefc572fb190d4d71d3dfbb7d75afa79f119a (patch) | |
tree | 9f750840ba1357b0d3507c32759090448c0bc2b8 | |
parent | 7d9a800163a92cdbfcc38aa24591c8ad20a6bb19 (diff) |
qtvideosink: Improve paint areas calculations based on the qtquick2 video sink patches from Benjamin Federau
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; |