diff options
author | Artem Dyomin <artem.dyomin@qt.io> | 2024-01-02 15:14:32 +0100 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2024-01-06 14:36:49 +0000 |
commit | 1d9aab3c80603d24df5cc692e958834b50e4f8fb (patch) | |
tree | ac4f4afaad9ed42228f41865c403ecdc2f326116 | |
parent | c75c91b5abed08d08ca26af75e00019896bd79f1 (diff) |
Add unit tests for basic video buffers
The patch adds unit tests for QImageVideoBuffer and QMemoryVideoBuffer.
As those behave the same in most cases, the added test suite contains
parametric test cases for both.
Pick-to: 6.5
Change-Id: I51cbbf9bcc5f3ad06cfee7777c439791579bcf34
Reviewed-by: Jøger Hansegård <joger.hansegard@qt.io>
Reviewed-by: Lars Knoll <lars@knoll.priv.no>
(cherry picked from commit 716c094fb40641b23bc0c006f639e68019551fd8)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
(cherry picked from commit 6b6ea0d42704db8f5fd5910dbe0e5959ec0c09e4)
-rw-r--r-- | tests/auto/unit/multimedia/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/auto/unit/multimedia/qvideobuffers/CMakeLists.txt | 10 | ||||
-rw-r--r-- | tests/auto/unit/multimedia/qvideobuffers/tst_qvideobuffers.cpp | 223 |
3 files changed, 234 insertions, 0 deletions
diff --git a/tests/auto/unit/multimedia/CMakeLists.txt b/tests/auto/unit/multimedia/CMakeLists.txt index 467934920..c8fa299ab 100644 --- a/tests/auto/unit/multimedia/CMakeLists.txt +++ b/tests/auto/unit/multimedia/CMakeLists.txt @@ -27,3 +27,4 @@ add_subdirectory(qscreencapture) add_subdirectory(qvideotexturehelper) add_subdirectory(qmediadevices) add_subdirectory(qerrorinfo) +add_subdirectory(qvideobuffers) diff --git a/tests/auto/unit/multimedia/qvideobuffers/CMakeLists.txt b/tests/auto/unit/multimedia/qvideobuffers/CMakeLists.txt new file mode 100644 index 000000000..765d02c96 --- /dev/null +++ b/tests/auto/unit/multimedia/qvideobuffers/CMakeLists.txt @@ -0,0 +1,10 @@ +# Copyright (C) 2024 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +qt_internal_add_test(tst_qvideobuffers + SOURCES + tst_qvideobuffers.cpp + LIBRARIES + Qt::Multimedia + Qt::MultimediaPrivate +) diff --git a/tests/auto/unit/multimedia/qvideobuffers/tst_qvideobuffers.cpp b/tests/auto/unit/multimedia/qvideobuffers/tst_qvideobuffers.cpp new file mode 100644 index 000000000..cbbfea91e --- /dev/null +++ b/tests/auto/unit/multimedia/qvideobuffers/tst_qvideobuffers.cpp @@ -0,0 +1,223 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include <QtTest/QtTest> + +#include <private/qmemoryvideobuffer_p.h> +#include <private/qimagevideobuffer_p.h> + +using BufferPtr = std::shared_ptr<QAbstractVideoBuffer>; +using MapModes = std::vector<QVideoFrame::MapMode>; + +static const MapModes validMapModes = { QVideoFrame::ReadOnly, QVideoFrame::WriteOnly, QVideoFrame::ReadWrite }; + +class tst_QVideoBuffers : public QObject +{ + Q_OBJECT + +public: + tst_QVideoBuffers() {} +public slots: + void initTestCase(); + +private slots: + void map_changesMappedStateAndReturnsProperMappings_whenBufferIsNotMapped_data(); + void map_changesMappedStateAndReturnsProperMappings_whenBufferIsNotMapped(); + + void mapWithNotMappedMode_doesNothing_data(); + void mapWithNotMappedMode_doesNothing(); + + void map_doesNothing_whenBufferIsMapped_data(); + void map_doesNothing_whenBufferIsMapped(); + + void mapMemoryBufferWithReadOnly_doesntDetachArray(); + + void mapMemoryBufferWithWriteModes_detachsArray_data(); + void mapMemoryBufferWithWriteModes_detachsArray(); + + void underlyingByteArray_returnsCorrectValueForPlanes(); + + void unmap_resetsMappedState_whenBufferIsMapped_data(); + void unmap_resetsMappedState_whenBufferIsMapped(); + +private: + QString mapModeToString(QVideoFrame::MapMode mapMode) const + { + switch (mapMode) { + case QVideoFrame::NotMapped: + return QLatin1String("NotMapped"); + case QVideoFrame::ReadOnly: + return QLatin1String("ReadOnly"); + case QVideoFrame::WriteOnly: + return QLatin1String("WriteOnly"); + case QVideoFrame::ReadWrite: + return QLatin1String("ReadWrite"); + default: + return QLatin1String("Unknown"); + } + } + + void generateImageAndMemoryBuffersWithAllModes(const MapModes& modes = validMapModes) const + { + QTest::addColumn<BufferPtr>("buffer"); + QTest::addColumn<QVideoFrame::MapMode>("mapMode"); + + for (auto mode : modes) { + QTest::newRow(QString("ImageBuffer, %1").arg(mapModeToString(mode)).toUtf8().constData()) + << createImageBuffer() << mode; + QTest::newRow(QString("MemoryBuffer, %1").arg(mapModeToString(mode)).toUtf8().constData()) + << createMemoryBuffer() << mode; + } + } + + BufferPtr createImageBuffer() const + { + return std::make_shared<QImageVideoBuffer>(m_image); + } + + BufferPtr createMemoryBuffer() const + { + return std::make_shared<QMemoryVideoBuffer>(m_byteArray, m_byteArray.size() / m_image.height()); + } + + QImage m_image = { QSize(5, 4), QImage::Format_RGBA8888 }; + QByteArray m_byteArray; +}; + + +void tst_QVideoBuffers::initTestCase() +{ + m_image.fill(Qt::gray); + m_image.setPixelColor(0, 0, Qt::green); + m_image.setPixelColor(m_image.width() - 1, 0, Qt::blue); + m_image.setPixelColor(0, m_image.height() - 1, Qt::red); + + m_byteArray.assign(m_image.constBits(), m_image.constBits() + m_image.sizeInBytes()); +} + +void tst_QVideoBuffers::map_changesMappedStateAndReturnsProperMappings_whenBufferIsNotMapped_data() +{ + generateImageAndMemoryBuffersWithAllModes(); +} + +void tst_QVideoBuffers::map_changesMappedStateAndReturnsProperMappings_whenBufferIsNotMapped() +{ + QFETCH(BufferPtr, buffer); + QFETCH(QVideoFrame::MapMode, mapMode); + + auto mappedData = buffer->map(mapMode); + + QCOMPARE(buffer->mapMode(), mapMode); + + QCOMPARE(mappedData.nPlanes, 1); + QVERIFY(mappedData.data[0]); + QCOMPARE(mappedData.size[0], 80); + QCOMPARE(mappedData.bytesPerLine[0], 20); + + const auto data = reinterpret_cast<const char*>(mappedData.data[0]); + QCOMPARE(QByteArray(data, mappedData.size[0]), m_byteArray); +} + +void tst_QVideoBuffers::mapWithNotMappedMode_doesNothing_data() +{ + generateImageAndMemoryBuffersWithAllModes(); +} + +void tst_QVideoBuffers::mapWithNotMappedMode_doesNothing() +{ + QFETCH(BufferPtr, buffer); + QFETCH(QVideoFrame::MapMode, mapMode); + + buffer->map(mapMode); + + buffer->map(QVideoFrame::NotMapped); + + QCOMPARE(buffer->mapMode(), mapMode); +} + +void tst_QVideoBuffers::map_doesNothing_whenBufferIsMapped_data() +{ + generateImageAndMemoryBuffersWithAllModes(); +} + +void tst_QVideoBuffers::map_doesNothing_whenBufferIsMapped() +{ + QFETCH(BufferPtr, buffer); + QFETCH(QVideoFrame::MapMode, mapMode); + + buffer->map(mapMode); + auto mappedData = buffer->map(QVideoFrame::ReadOnly); + QCOMPARE(mappedData.nPlanes, 0); + QCOMPARE(buffer->mapMode(), mapMode); +} + +void tst_QVideoBuffers::mapMemoryBufferWithReadOnly_doesntDetachArray() +{ + auto buffer = createMemoryBuffer(); + auto underlyingArray = buffer->underlyingByteArray(0); + + auto mappedData = buffer->map(QVideoFrame::ReadOnly); + QCOMPARE(mappedData.nPlanes, 1); + QCOMPARE(mappedData.data[0], reinterpret_cast<const uchar *>(underlyingArray.constData())); + QCOMPARE(mappedData.data[0], reinterpret_cast<const uchar *>(m_byteArray.constData())); +} + +void tst_QVideoBuffers::mapMemoryBufferWithWriteModes_detachsArray_data() +{ + QTest::addColumn<QVideoFrame::MapMode>("mapMode"); + + QTest::newRow(mapModeToString(QVideoFrame::WriteOnly).toUtf8().constData()) << QVideoFrame::WriteOnly; + QTest::newRow(mapModeToString(QVideoFrame::WriteOnly).toUtf8().constData()) << QVideoFrame::WriteOnly; +} + +void tst_QVideoBuffers::mapMemoryBufferWithWriteModes_detachsArray() +{ + QFETCH(QVideoFrame::MapMode, mapMode); + + auto buffer = createMemoryBuffer(); + auto underlyingArray = buffer->underlyingByteArray(0); + + auto mappedData = buffer->map(mapMode); + QCOMPARE(mappedData.nPlanes, 1); + QCOMPARE_NE(mappedData.data[0], reinterpret_cast<const uchar *>(underlyingArray.constData())); +} + +void tst_QVideoBuffers::underlyingByteArray_returnsCorrectValueForPlanes() +{ + auto buffer = createMemoryBuffer(); + + QCOMPARE(buffer->underlyingByteArray(0).constData(), m_byteArray.constData()); + + QVERIFY(buffer->underlyingByteArray(-1).isNull()); + QVERIFY(buffer->underlyingByteArray(1).isNull()); + QVERIFY(buffer->underlyingByteArray(2).isNull()); +} + +void tst_QVideoBuffers::unmap_resetsMappedState_whenBufferIsMapped_data() +{ + generateImageAndMemoryBuffersWithAllModes(); +} + +void tst_QVideoBuffers::unmap_resetsMappedState_whenBufferIsMapped() +{ + QFETCH(BufferPtr, buffer); + QFETCH(QVideoFrame::MapMode, mapMode); + + buffer->map(mapMode); + + buffer->unmap(); + + QCOMPARE(buffer->mapMode(), QVideoFrame::NotMapped); + + // Check buffer is valid and it's possible to map again + auto mappedData = buffer->map(QVideoFrame::ReadOnly); + QCOMPARE(mappedData.nPlanes, 1); + QCOMPARE(buffer->mapMode(), QVideoFrame::ReadOnly); + + const auto data = reinterpret_cast<const char*>(mappedData.data[0]); + QCOMPARE(QByteArray(data, mappedData.size[0]), m_byteArray); +} + +QTEST_APPLESS_MAIN(tst_QVideoBuffers); + +#include "tst_qvideobuffers.moc" |