summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Dubsky <pavel.dubsky@qt.io>2024-04-11 13:55:32 +0200
committerPavel Dubsky <pavel.dubsky@qt.io>2024-04-17 12:56:53 +0200
commit38c85f0fb274f9dd989bd7601791209589fab94a (patch)
treed2c2765878790c5f3c6cdad13350cae304bbee66
parentf1e64525961e56424651b44c34355518e80af537 (diff)
Enable HDR based on video frame format for QtWidgets
Currently swap chain is configured for SDR or HDR only on creation and there is no support for dynamic change when video is played using QVideoWindow. This change adds check that determines whether video frame contains SDR or HDR content and reconfigures swap chain (and subsequently shaders) if needed. Fixes: QTBUG-120963 Pick-to: 6.7 6.6 6.5 Change-Id: I8eef9b46b3999e00427cc50f82486cea7cd80e09 Reviewed-by: Artem Dyomin <artem.dyomin@qt.io>
-rw-r--r--src/multimedia/qmultimediautils.cpp27
-rw-r--r--src/multimedia/qmultimediautils_p.h12
-rw-r--r--src/multimedia/video/qvideowindow.cpp11
-rw-r--r--tests/auto/unit/multimedia/qmultimediautils/tst_qmultimediautils.cpp71
4 files changed, 119 insertions, 2 deletions
diff --git a/src/multimedia/qmultimediautils.cpp b/src/multimedia/qmultimediautils.cpp
index b08875592..9740b6d60 100644
--- a/src/multimedia/qmultimediautils.cpp
+++ b/src/multimedia/qmultimediautils.cpp
@@ -3,6 +3,7 @@
#include "qmultimediautils_p.h"
#include "qvideoframe.h"
+#include "qvideoframeformat.h"
#include <QtCore/qdir.h>
@@ -70,4 +71,30 @@ QUrl qMediaFromUserInput(QUrl url)
return url;
}
+bool qIsAutoHdrEnabled()
+{
+ static const bool autoHdrEnabled = qEnvironmentVariableIntValue("QT_MEDIA_AUTO_HDR");
+
+ return autoHdrEnabled;
+}
+
+QRhiSwapChain::Format qGetRequiredSwapChainFormat(const QVideoFrameFormat &format)
+{
+ constexpr auto sdrMaxLuminance = 100.0f;
+ const auto formatMaxLuminance = format.maxLuminance();
+
+ return formatMaxLuminance > sdrMaxLuminance ? QRhiSwapChain::HDRExtendedSrgbLinear
+ : QRhiSwapChain::SDR;
+}
+
+bool qShouldUpdateSwapChainFormat(QRhiSwapChain *swapChain,
+ QRhiSwapChain::Format requiredSwapChainFormat)
+{
+ if (!swapChain)
+ return false;
+
+ return qIsAutoHdrEnabled() && swapChain->format() != requiredSwapChainFormat
+ && swapChain->isFormatSupported(requiredSwapChainFormat);
+}
+
QT_END_NAMESPACE
diff --git a/src/multimedia/qmultimediautils_p.h b/src/multimedia/qmultimediautils_p.h
index d95bb9e4b..a5d60e066 100644
--- a/src/multimedia/qmultimediautils_p.h
+++ b/src/multimedia/qmultimediautils_p.h
@@ -20,10 +20,13 @@
#include <QtMultimedia/private/qmaybe_p.h>
#include <QtCore/qsize.h>
#include <QtCore/qurl.h>
+#include <QtGui/rhi/qrhi.h>
QT_BEGIN_NAMESPACE
+class QRhiSwapChain;
class QVideoFrame;
+class QVideoFrameFormat;
struct Fraction {
int numerator;
@@ -47,6 +50,15 @@ Q_MULTIMEDIA_EXPORT QSize qRotatedFrameSize(const QVideoFrame &frame);
Q_MULTIMEDIA_EXPORT QUrl qMediaFromUserInput(QUrl fileName);
+Q_MULTIMEDIA_EXPORT bool qIsAutoHdrEnabled();
+
+Q_MULTIMEDIA_EXPORT QRhiSwapChain::Format
+qGetRequiredSwapChainFormat(const QVideoFrameFormat &format);
+
+Q_MULTIMEDIA_EXPORT bool
+qShouldUpdateSwapChainFormat(QRhiSwapChain *swapChain,
+ QRhiSwapChain::Format requiredSwapChainFormat);
+
QT_END_NAMESPACE
#endif // QMULTIMEDIAUTILS_P_H
diff --git a/src/multimedia/video/qvideowindow.cpp b/src/multimedia/video/qvideowindow.cpp
index c5afdaa7d..9cab23f5f 100644
--- a/src/multimedia/video/qvideowindow.cpp
+++ b/src/multimedia/video/qvideowindow.cpp
@@ -7,6 +7,7 @@
#include <qpainter.h>
#include <private/qguiapplication_p.h>
#include <private/qmemoryvideobuffer_p.h>
+#include <private/qmultimediautils_p.h>
#include <qpa/qplatformintegration.h>
QT_BEGIN_NAMESPACE
@@ -153,8 +154,6 @@ void QVideoWindowPrivate::initRhi()
m_swapChain.reset(m_rhi->newSwapChain());
m_swapChain->setWindow(q);
- if (m_swapChain->isFormatSupported(QRhiSwapChain::HDRExtendedSrgbLinear))
- m_swapChain->setFormat(QRhiSwapChain::HDRExtendedSrgbLinear);
m_renderPass.reset(m_swapChain->newCompatibleRenderPassDescriptor());
m_swapChain->setRenderPassDescriptor(m_renderPass.get());
@@ -344,6 +343,14 @@ void QVideoWindowPrivate::render()
if (!m_hasSwapChain || (m_swapChain->currentPixelSize() != m_swapChain->surfacePixelSize()))
resizeSwapChain();
+ const auto requiredSwapChainFormat =
+ qGetRequiredSwapChainFormat(m_currentFrame.surfaceFormat());
+ if (qShouldUpdateSwapChainFormat(m_swapChain.get(), requiredSwapChainFormat)) {
+ releaseSwapChain();
+ m_swapChain->setFormat(requiredSwapChainFormat);
+ resizeSwapChain();
+ }
+
if (!m_hasSwapChain)
return;
diff --git a/tests/auto/unit/multimedia/qmultimediautils/tst_qmultimediautils.cpp b/tests/auto/unit/multimedia/qmultimediautils/tst_qmultimediautils.cpp
index 0acd41696..8ed54ac64 100644
--- a/tests/auto/unit/multimedia/qmultimediautils/tst_qmultimediautils.cpp
+++ b/tests/auto/unit/multimedia/qmultimediautils/tst_qmultimediautils.cpp
@@ -4,6 +4,7 @@
#include <QtTest/QtTest>
#include <QDebug>
#include <private/qmultimediautils_p.h>
+#include <qvideoframeformat.h>
class tst_QMultimediaUtils : public QObject
{
@@ -21,6 +22,13 @@ private slots:
void qRotatedFrameSize_returnsSizeAccordinglyToRotation();
void qMediaFromUserInput_addsFilePrefix_whenCalledWithLocalFile();
+
+ void qGetRequiredSwapChainFormat_returnsSdr_whenMaxLuminanceIsBelowSdrThreshold_data();
+ void qGetRequiredSwapChainFormat_returnsSdr_whenMaxLuminanceIsBelowSdrThreshold();
+ void qGetRequiredSwapChainFormat_returnsHdr_whenMaxLuminanceIsBelowHdrThreshold_data();
+ void qGetRequiredSwapChainFormat_returnsHdr_whenMaxLuminanceIsBelowHdrThreshold();
+
+ void qShouldUpdateSwapChainFormat_returnsFalse_whenSwapChainIsNullPointer();
};
void tst_QMultimediaUtils::fraction_of_0()
@@ -109,5 +117,68 @@ void tst_QMultimediaUtils::qMediaFromUserInput_addsFilePrefix_whenCalledWithLoca
QUrl::fromLocalFile(QDir::currentPath() + u"/foo/bar/baz"_s));
}
+void tst_QMultimediaUtils::
+ qGetRequiredSwapChainFormat_returnsSdr_whenMaxLuminanceIsBelowSdrThreshold_data()
+{
+ QTest::addColumn<float>("maxLuminance");
+
+ QTest::newRow("0") << 0.0f;
+ QTest::newRow("80") << 80.0f;
+ QTest::newRow("100") << 100.0f;
+}
+
+void tst_QMultimediaUtils::
+ qGetRequiredSwapChainFormat_returnsSdr_whenMaxLuminanceIsBelowSdrThreshold()
+{
+ // Arrange
+ QFETCH(float, maxLuminance);
+
+ QVideoFrameFormat format;
+ format.setMaxLuminance(maxLuminance);
+
+ // Act
+ QRhiSwapChain::Format requiredSwapChainFormat = qGetRequiredSwapChainFormat(format);
+
+ // Assert
+ QCOMPARE(requiredSwapChainFormat, QRhiSwapChain::Format::SDR);
+}
+
+void tst_QMultimediaUtils::
+ qGetRequiredSwapChainFormat_returnsHdr_whenMaxLuminanceIsBelowHdrThreshold_data()
+{
+ QTest::addColumn<float>("maxLuminance");
+
+ QTest::newRow("101") << 101.0f;
+ QTest::newRow("300") << 300.0f;
+ QTest::newRow("1600") << 1600.0f;
+}
+
+void tst_QMultimediaUtils::
+ qGetRequiredSwapChainFormat_returnsHdr_whenMaxLuminanceIsBelowHdrThreshold()
+{
+ // Arrange
+ QVideoFrameFormat format;
+ format.setMaxLuminance(300.0f);
+
+ // Act
+ QRhiSwapChain::Format requiredSwapChainFormat = qGetRequiredSwapChainFormat(format);
+
+ // Assert
+ QCOMPARE(requiredSwapChainFormat, QRhiSwapChain::Format::HDRExtendedSrgbLinear);
+}
+
+void tst_QMultimediaUtils::qShouldUpdateSwapChainFormat_returnsFalse_whenSwapChainIsNullPointer()
+{
+ // Arrange
+ QRhiSwapChain *swapChain = nullptr;
+ QRhiSwapChain::Format requiredSwapChainFormat = QRhiSwapChain::Format::SDR;
+
+ // Act
+ bool shouldUpdate = qShouldUpdateSwapChainFormat(swapChain, requiredSwapChainFormat);
+
+ // Assert
+ QCOMPARE(shouldUpdate, false);
+}
+
QTEST_MAIN(tst_QMultimediaUtils)
#include "tst_qmultimediautils.moc"