summaryrefslogtreecommitdiffstats
path: root/tests/auto/unit/mockbackend
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/unit/mockbackend')
-rw-r--r--tests/auto/unit/mockbackend/CMakeLists.txt33
-rw-r--r--tests/auto/unit/mockbackend/mock.json3
-rw-r--r--tests/auto/unit/mockbackend/qmockaudiodecoder.cpp139
-rw-r--r--tests/auto/unit/mockbackend/qmockaudiodecoder.h69
-rw-r--r--tests/auto/unit/mockbackend/qmockaudiooutput.h30
-rw-r--r--tests/auto/unit/mockbackend/qmockcamera.cpp158
-rw-r--r--tests/auto/unit/mockbackend/qmockcamera.h81
-rw-r--r--tests/auto/unit/mockbackend/qmockimagecapture.cpp59
-rw-r--r--tests/auto/unit/mockbackend/qmockimagecapture.h48
-rw-r--r--tests/auto/unit/mockbackend/qmockintegration.cpp198
-rw-r--r--tests/auto/unit/mockbackend/qmockintegration.h103
-rw-r--r--tests/auto/unit/mockbackend/qmockmediacapturesession.h86
-rw-r--r--tests/auto/unit/mockbackend/qmockmediadevices.cpp43
-rw-r--r--tests/auto/unit/mockbackend/qmockmediadevices.h45
-rw-r--r--tests/auto/unit/mockbackend/qmockmediaencoder.h95
-rw-r--r--tests/auto/unit/mockbackend/qmockmediaplayer.h175
-rw-r--r--tests/auto/unit/mockbackend/qmocksurfacecapture.h88
-rw-r--r--tests/auto/unit/mockbackend/qmockvideobuffer.h38
-rw-r--r--tests/auto/unit/mockbackend/qmockvideosink.h33
19 files changed, 1524 insertions, 0 deletions
diff --git a/tests/auto/unit/mockbackend/CMakeLists.txt b/tests/auto/unit/mockbackend/CMakeLists.txt
new file mode 100644
index 000000000..959341366
--- /dev/null
+++ b/tests/auto/unit/mockbackend/CMakeLists.txt
@@ -0,0 +1,33 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+# Generated from mockbackend.pro.
+
+#####################################################################
+## MockMultimediaPlugin Generic Library:
+#####################################################################
+
+qt_internal_add_plugin(MockMultimediaPlugin
+ STATIC
+ OUTPUT_NAME mockmultimediaplugin
+ PLUGIN_TYPE multimedia
+ OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../plugins"
+ DEFAULT_IF FALSE
+ SOURCES
+ qmockaudiodecoder.cpp qmockaudiodecoder.h
+ qmockaudiooutput.h
+ qmockcamera.cpp qmockcamera.h
+ qmockimagecapture.cpp qmockimagecapture.h
+ qmockmediaplayer.h
+ qmockmediaencoder.h
+ qmockmediacapturesession.h
+ qmockvideosink.h
+ qmockmediadevices.cpp qmockmediadevices.h
+ qmockintegration.cpp qmockintegration.h
+ LIBRARIES
+ Qt::MultimediaPrivate
+ Qt::CorePrivate
+)
+
+#### Keys ignored in scope 1:.:.:mockbackend.pro:<TRUE>:
+# TEMPLATE = "lib"
diff --git a/tests/auto/unit/mockbackend/mock.json b/tests/auto/unit/mockbackend/mock.json
new file mode 100644
index 000000000..499a3de8c
--- /dev/null
+++ b/tests/auto/unit/mockbackend/mock.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "mock" ]
+}
diff --git a/tests/auto/unit/mockbackend/qmockaudiodecoder.cpp b/tests/auto/unit/mockbackend/qmockaudiodecoder.cpp
new file mode 100644
index 000000000..3c6b940a9
--- /dev/null
+++ b/tests/auto/unit/mockbackend/qmockaudiodecoder.cpp
@@ -0,0 +1,139 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "qmockaudiodecoder.h"
+
+QT_BEGIN_NAMESPACE
+
+QMockAudioDecoder::QMockAudioDecoder(QAudioDecoder *parent)
+ : QPlatformAudioDecoder(parent), mDevice(0), mPosition(-1), mSerial(0)
+{
+ mFormat.setChannelCount(1);
+ mFormat.setSampleFormat(QAudioFormat::UInt8);
+ mFormat.setSampleRate(1000);
+}
+
+QUrl QMockAudioDecoder::source() const
+{
+ return mSource;
+}
+
+void QMockAudioDecoder::setSource(const QUrl &fileName)
+{
+ mSource = fileName;
+ mDevice = 0;
+ stop();
+}
+
+QIODevice *QMockAudioDecoder::sourceDevice() const
+{
+ return mDevice;
+}
+
+void QMockAudioDecoder::setSourceDevice(QIODevice *device)
+{
+ mDevice = device;
+ mSource.clear();
+ stop();
+}
+
+QAudioFormat QMockAudioDecoder::audioFormat() const
+{
+ return mFormat;
+}
+
+void QMockAudioDecoder::setAudioFormat(const QAudioFormat &format)
+{
+ if (mFormat != format) {
+ mFormat = format;
+ formatChanged(mFormat);
+ }
+}
+
+// When decoding we decode to first buffer, then second buffer
+// we then stop until the first is read again and so on, for
+// 5 buffers
+void QMockAudioDecoder::start()
+{
+ if (!isDecoding()) {
+ if (!mSource.isEmpty()) {
+ setIsDecoding(true);
+ durationChanged(duration());
+
+ QTimer::singleShot(50, this, &QMockAudioDecoder::pretendDecode);
+ } else {
+ error(QAudioDecoder::ResourceError, "No source set");
+ }
+ }
+}
+
+void QMockAudioDecoder::stop()
+{
+ if (isDecoding()) {
+ mSerial = 0;
+ mPosition = 0;
+ mBuffers.clear();
+ setIsDecoding(false);
+ bufferAvailableChanged(false);
+ }
+}
+
+QAudioBuffer QMockAudioDecoder::read()
+{
+ QAudioBuffer a;
+ if (mBuffers.size() > 0) {
+ a = mBuffers.takeFirst();
+ mPosition = a.startTime() / 1000;
+ positionChanged(mPosition);
+
+ if (mBuffers.isEmpty())
+ bufferAvailableChanged(false);
+
+ if (mBuffers.isEmpty() && mSerial >= MOCK_DECODER_MAX_BUFFERS) {
+ finished();
+ } else
+ QTimer::singleShot(50, this, &QMockAudioDecoder::pretendDecode);
+ }
+
+ return a;
+}
+
+bool QMockAudioDecoder::bufferAvailable() const
+{
+ return mBuffers.size() > 0;
+}
+
+qint64 QMockAudioDecoder::position() const
+{
+ return mPosition;
+}
+
+qint64 QMockAudioDecoder::duration() const
+{
+ return (sizeof(mSerial) * MOCK_DECODER_MAX_BUFFERS * qint64(1000))
+ / (mFormat.sampleRate() * mFormat.channelCount());
+}
+
+void QMockAudioDecoder::pretendDecode()
+{
+ // Check if we've reached end of stream
+ if (mSerial >= MOCK_DECODER_MAX_BUFFERS)
+ return;
+
+ // We just keep the length of mBuffers to 3 or less.
+ if (mBuffers.size() < 3) {
+ QByteArray b(sizeof(mSerial), 0);
+ memcpy(b.data(), &mSerial, sizeof(mSerial));
+ qint64 position = (sizeof(mSerial) * mSerial * qint64(1000000))
+ / (mFormat.sampleRate() * mFormat.channelCount());
+ mSerial++;
+ mBuffers.push_back(QAudioBuffer(b, mFormat, position));
+ bufferReady();
+ if (mBuffers.size() == 1)
+ bufferAvailableChanged(true);
+ }
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qmockaudiodecoder.cpp"
diff --git a/tests/auto/unit/mockbackend/qmockaudiodecoder.h b/tests/auto/unit/mockbackend/qmockaudiodecoder.h
new file mode 100644
index 000000000..89e21ef23
--- /dev/null
+++ b/tests/auto/unit/mockbackend/qmockaudiodecoder.h
@@ -0,0 +1,69 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef MOCKAUDIODECODERCONTROL_H
+#define MOCKAUDIODECODERCONTROL_H
+
+#include "private/qplatformaudiodecoder_p.h"
+
+#include <QtCore/qpair.h>
+#include <QtCore/qurl.h>
+
+#include "qaudiobuffer.h"
+#include <QTimer>
+#include <QIODevice>
+
+#define MOCK_DECODER_MAX_BUFFERS 10
+
+QT_BEGIN_NAMESPACE
+
+class QMockAudioDecoder : public QPlatformAudioDecoder
+{
+ Q_OBJECT
+
+public:
+ QMockAudioDecoder(QAudioDecoder *parent = nullptr);
+
+ QUrl source() const override;
+
+ void setSource(const QUrl &fileName) override;
+
+ QIODevice *sourceDevice() const override;
+
+ void setSourceDevice(QIODevice *device) override;
+
+ QAudioFormat audioFormat() const override;
+
+ void setAudioFormat(const QAudioFormat &format) override;
+
+ // When decoding we decode to first buffer, then second buffer
+ // we then stop until the first is read again and so on, for
+ // 5 buffers
+ void start() override;
+
+ void stop() override;
+
+ QAudioBuffer read() override;
+
+ bool bufferAvailable() const override;
+
+ qint64 position() const override;
+
+ qint64 duration() const override;
+
+private slots:
+ void pretendDecode();
+
+public:
+ QUrl mSource;
+ QIODevice *mDevice;
+ QAudioFormat mFormat;
+ qint64 mPosition;
+
+ int mSerial;
+ QList<QAudioBuffer> mBuffers;
+};
+
+QT_END_NAMESPACE
+
+#endif // QAUDIODECODERCONTROL_H
diff --git a/tests/auto/unit/mockbackend/qmockaudiooutput.h b/tests/auto/unit/mockbackend/qmockaudiooutput.h
new file mode 100644
index 000000000..a35fc8fe4
--- /dev/null
+++ b/tests/auto/unit/mockbackend/qmockaudiooutput.h
@@ -0,0 +1,30 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+#ifndef QMOCKAUDIOOUTPUT_H
+#define QMOCKAUDIOOUTPUT_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qplatformaudiooutput_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QMockAudioOutput : public QPlatformAudioOutput
+{
+public:
+ QMockAudioOutput(QAudioOutput *qq) : QPlatformAudioOutput(qq) {}
+};
+
+QT_END_NAMESPACE
+
+
+#endif // QMOCKAUDIOOUTPUT_H
diff --git a/tests/auto/unit/mockbackend/qmockcamera.cpp b/tests/auto/unit/mockbackend/qmockcamera.cpp
new file mode 100644
index 000000000..23ecc36ae
--- /dev/null
+++ b/tests/auto/unit/mockbackend/qmockcamera.cpp
@@ -0,0 +1,158 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "qmockcamera.h"
+
+QT_BEGIN_NAMESPACE
+
+QMockCamera::QMockCamera(QCamera *parent)
+ : QPlatformCamera(parent), m_propertyChangesSupported(false)
+{
+ if (!simpleCamera) {
+ minIsoChanged(100);
+ maxIsoChanged(800);
+ minExposureTimeChanged(.001f);
+ maxExposureTimeChanged(1.f);
+ exposureCompensationRangeChanged(-2, 2);
+ maximumZoomFactorChanged(4.);
+ setFlashMode(QCamera::FlashAuto);
+ }
+}
+
+QMockCamera::~QMockCamera() { }
+
+bool QMockCamera::isActive() const
+{
+ return m_active;
+}
+
+void QMockCamera::setActive(bool active)
+{
+ if (m_active == active)
+ return;
+ m_active = active;
+ emit activeChanged(active);
+}
+
+void QMockCamera::setCamera(const QCameraDevice &camera)
+{
+ m_camera = camera;
+}
+
+bool QMockCamera::setCameraFormat(const QCameraFormat &format)
+{
+ if (!format.isNull() && !m_camera.videoFormats().contains(format))
+ return false;
+ return true;
+}
+
+void QMockCamera::setFocusMode(QCamera::FocusMode mode)
+{
+ if (isFocusModeSupported(mode))
+ focusModeChanged(mode);
+}
+
+bool QMockCamera::isFocusModeSupported(QCamera::FocusMode mode) const
+{
+ return simpleCamera ? mode == QCamera::FocusModeAuto : mode != QCamera::FocusModeInfinity;
+}
+
+void QMockCamera::setCustomFocusPoint(const QPointF &point)
+{
+ if (!simpleCamera)
+ customFocusPointChanged(point);
+}
+
+void QMockCamera::setFocusDistance(float d)
+{
+ if (!simpleCamera)
+ focusDistanceChanged(d);
+}
+
+void QMockCamera::zoomTo(float newZoomFactor, float /*rate*/)
+{
+ zoomFactorChanged(newZoomFactor);
+}
+
+void QMockCamera::setFlashMode(QCamera::FlashMode mode)
+{
+ if (!simpleCamera)
+ flashModeChanged(mode);
+ flashReadyChanged(mode != QCamera::FlashOff);
+}
+bool QMockCamera::isFlashModeSupported(QCamera::FlashMode mode) const
+{
+ return simpleCamera ? mode == QCamera::FlashOff : true;
+}
+
+bool QMockCamera::isFlashReady() const
+{
+ return flashMode() != QCamera::FlashOff;
+}
+
+void QMockCamera::setExposureMode(QCamera::ExposureMode mode)
+{
+ if (!simpleCamera && isExposureModeSupported(mode))
+ exposureModeChanged(mode);
+}
+
+bool QMockCamera::isExposureModeSupported(QCamera::ExposureMode mode) const
+{
+ return simpleCamera ? mode == QCamera::ExposureAuto : mode <= QCamera::ExposureBeach;
+}
+
+void QMockCamera::setExposureCompensation(float c)
+{
+ if (!simpleCamera)
+ exposureCompensationChanged(qBound(-2., c, 2.));
+}
+
+int QMockCamera::isoSensitivity() const
+{
+ if (simpleCamera)
+ return -1;
+ return manualIsoSensitivity() > 0 ? manualIsoSensitivity() : 100;
+}
+
+void QMockCamera::setManualIsoSensitivity(int iso)
+{
+ if (!simpleCamera)
+ isoSensitivityChanged(qBound(100, iso, 800));
+}
+
+void QMockCamera::setManualExposureTime(float secs)
+{
+ if (!simpleCamera)
+ exposureTimeChanged(qBound(0.001, secs, 1.));
+}
+
+float QMockCamera::exposureTime() const
+{
+ if (simpleCamera)
+ return -1.;
+ return manualExposureTime() > 0 ? manualExposureTime() : .05;
+}
+
+bool QMockCamera::isWhiteBalanceModeSupported(QCamera::WhiteBalanceMode mode) const
+{
+ if (simpleCamera)
+ return mode == QCamera::WhiteBalanceAuto;
+ return mode == QCamera::WhiteBalanceAuto || mode == QCamera::WhiteBalanceManual
+ || mode == QCamera::WhiteBalanceSunlight;
+}
+
+void QMockCamera::setWhiteBalanceMode(QCamera::WhiteBalanceMode mode)
+{
+ if (isWhiteBalanceModeSupported(mode))
+ whiteBalanceModeChanged(mode);
+}
+
+void QMockCamera::setColorTemperature(int temperature)
+{
+ if (!simpleCamera)
+ colorTemperatureChanged(temperature);
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qmockcamera.cpp"
diff --git a/tests/auto/unit/mockbackend/qmockcamera.h b/tests/auto/unit/mockbackend/qmockcamera.h
new file mode 100644
index 000000000..3d8159e84
--- /dev/null
+++ b/tests/auto/unit/mockbackend/qmockcamera.h
@@ -0,0 +1,81 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef QMOCKCAMERA_H
+#define QMOCKCAMERA_H
+
+#include "private/qplatformcamera_p.h"
+#include "qcameradevice.h"
+#include <qtimer.h>
+
+QT_BEGIN_NAMESPACE
+
+class QMockCamera : public QPlatformCamera
+{
+ friend class MockCaptureControl;
+ Q_OBJECT
+
+ static bool simpleCamera;
+public:
+
+ struct Simple {
+ Simple() { simpleCamera = true; }
+ ~Simple() { simpleCamera = false; }
+ };
+
+ QMockCamera(QCamera *parent);
+
+ ~QMockCamera() override;
+
+ bool isActive() const override;
+
+ void setActive(bool active) override;
+
+ void setCamera(const QCameraDevice &camera) override;
+
+ bool setCameraFormat(const QCameraFormat &format) override;
+
+ void setFocusMode(QCamera::FocusMode mode) override;
+
+ bool isFocusModeSupported(QCamera::FocusMode mode) const override;
+
+ void setCustomFocusPoint(const QPointF &point) override;
+
+ void setFocusDistance(float d) override;
+
+ void zoomTo(float newZoomFactor, float /*rate*/) override;
+
+ void setFlashMode(QCamera::FlashMode mode) override;
+
+ bool isFlashModeSupported(QCamera::FlashMode mode) const override;
+
+ bool isFlashReady() const override;
+
+ void setExposureMode(QCamera::ExposureMode mode) override;
+
+ bool isExposureModeSupported(QCamera::ExposureMode mode) const override;
+
+ void setExposureCompensation(float c) override;
+
+ int isoSensitivity() const override;
+
+ void setManualIsoSensitivity(int iso) override;
+
+ void setManualExposureTime(float secs) override;
+
+ float exposureTime() const override;
+
+ bool isWhiteBalanceModeSupported(QCamera::WhiteBalanceMode mode) const override;
+
+ void setWhiteBalanceMode(QCamera::WhiteBalanceMode mode) override;
+
+ void setColorTemperature(int temperature) override;
+
+ bool m_active = false;
+ QCameraDevice m_camera;
+ bool m_propertyChangesSupported;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMOCKCAMERA_H
diff --git a/tests/auto/unit/mockbackend/qmockimagecapture.cpp b/tests/auto/unit/mockbackend/qmockimagecapture.cpp
new file mode 100644
index 000000000..96e53b2f4
--- /dev/null
+++ b/tests/auto/unit/mockbackend/qmockimagecapture.cpp
@@ -0,0 +1,59 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <qmockimagecapture.h>
+#include <qmockcamera.h>
+#include <qmockmediacapturesession.h>
+#include <qimagecapture.h>
+#include <qcamera.h>
+
+QT_BEGIN_NAMESPACE
+
+QMockImageCapture::QMockImageCapture(QImageCapture *parent)
+ : QPlatformImageCapture(parent)
+{
+}
+
+bool QMockImageCapture::isReadyForCapture() const
+{
+ return m_ready;
+}
+
+int QMockImageCapture::capture(const QString &fileName)
+{
+ if (isReadyForCapture()) {
+ m_fileName = fileName;
+ m_captureRequest++;
+ emit readyForCaptureChanged(m_ready = false);
+ QTimer::singleShot(5, this, &QMockImageCapture::captured);
+ return m_captureRequest;
+ } else {
+ emit error(-1, QImageCapture::NotReadyError,
+ QLatin1String("Could not capture in stopped state"));
+ }
+
+ return -1;
+}
+
+void QMockImageCapture::captured()
+{
+ emit imageCaptured(m_captureRequest, QImage());
+
+ QMediaMetaData metaData;
+ metaData.insert(QMediaMetaData::Author, QStringLiteral("Author"));
+ metaData.insert(QMediaMetaData::Date, QDateTime(QDate(2021, 1, 1), QTime()));
+
+ emit imageMetadataAvailable(m_captureRequest, metaData);
+
+ if (!m_ready)
+ {
+ emit readyForCaptureChanged(m_ready = true);
+ emit imageExposed(m_captureRequest);
+ }
+
+ emit imageSaved(m_captureRequest, m_fileName);
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qmockimagecapture.cpp"
diff --git a/tests/auto/unit/mockbackend/qmockimagecapture.h b/tests/auto/unit/mockbackend/qmockimagecapture.h
new file mode 100644
index 000000000..376f53cbc
--- /dev/null
+++ b/tests/auto/unit/mockbackend/qmockimagecapture.h
@@ -0,0 +1,48 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef QMOCKCAMERAIMAGECAPTURE_H
+#define QMOCKCAMERAIMAGECAPTURE_H
+
+#include <QDateTime>
+#include <QTimer>
+#include <QtMultimedia/qmediametadata.h>
+
+#include "private/qplatformimagecapture_p.h"
+#include "private/qplatformcamera_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QMockMediaCaptureSession;
+
+class QMockImageCapture : public QPlatformImageCapture
+{
+ Q_OBJECT
+public:
+ QMockImageCapture(QImageCapture *parent);
+
+ ~QMockImageCapture()
+ {
+ }
+
+ bool isReadyForCapture() const override;
+
+ int capture(const QString &fileName) override;
+ int captureToBuffer() override { return -1; }
+
+ QImageEncoderSettings imageSettings() const override { return m_settings; }
+ void setImageSettings(const QImageEncoderSettings &settings) override { m_settings = settings; }
+
+private Q_SLOTS:
+ void captured();
+
+private:
+ QString m_fileName;
+ int m_captureRequest = 0;
+ bool m_ready = true;
+ QImageEncoderSettings m_settings;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMOCKCAMERAIMAGECAPTURE_H
diff --git a/tests/auto/unit/mockbackend/qmockintegration.cpp b/tests/auto/unit/mockbackend/qmockintegration.cpp
new file mode 100644
index 000000000..b554b31e0
--- /dev/null
+++ b/tests/auto/unit/mockbackend/qmockintegration.cpp
@@ -0,0 +1,198 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QtMultimedia/private/qplatformmediaplugin_p.h>
+#include "qmockintegration.h"
+#include "qmockmediaplayer.h"
+#include "qmockaudiodecoder.h"
+#include "qmockcamera.h"
+#include "qmockmediacapturesession.h"
+#include "qmockvideosink.h"
+#include "qmockimagecapture.h"
+#include "qmockaudiooutput.h"
+#include "qmocksurfacecapture.h"
+#include <private/qcameradevice_p.h>
+#include <private/qplatformvideodevices_p.h>
+
+#include "qmockmediadevices.h"
+
+QT_BEGIN_NAMESPACE
+
+class MockMultimediaPlugin : public QPlatformMediaPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QPlatformMediaPlugin_iid FILE "mock.json")
+
+public:
+ MockMultimediaPlugin() : QPlatformMediaPlugin() { }
+
+ QPlatformMediaIntegration *create(const QString &name) override
+ {
+ if (name == QLatin1String("mock"))
+ return new QMockIntegration;
+ return nullptr;
+ }
+};
+
+class QMockVideoDevices : public QPlatformVideoDevices
+{
+public:
+ QMockVideoDevices(QPlatformMediaIntegration *pmi)
+ : QPlatformVideoDevices(pmi)
+ {
+ QCameraDevicePrivate *info = new QCameraDevicePrivate;
+ info->description = QStringLiteral("defaultCamera");
+ info->id = "default";
+ info->isDefault = true;
+ auto *f = new QCameraFormatPrivate{
+ QSharedData(),
+ QVideoFrameFormat::Format_ARGB8888,
+ QSize(640, 480),
+ 0,
+ 30
+ };
+ info->videoFormats << f->create();
+ m_cameraDevices.append(info->create());
+ info = new QCameraDevicePrivate;
+ info->description = QStringLiteral("frontCamera");
+ info->id = "front";
+ info->isDefault = false;
+ info->position = QCameraDevice::FrontFace;
+ f = new QCameraFormatPrivate{
+ QSharedData(),
+ QVideoFrameFormat::Format_XRGB8888,
+ QSize(1280, 720),
+ 0,
+ 30
+ };
+ info->videoFormats << f->create();
+ m_cameraDevices.append(info->create());
+ info = new QCameraDevicePrivate;
+ info->description = QStringLiteral("backCamera");
+ info->id = "back";
+ info->isDefault = false;
+ info->position = QCameraDevice::BackFace;
+ m_cameraDevices.append(info->create());
+ }
+
+ void addNewCamera()
+ {
+ auto info = new QCameraDevicePrivate;
+ info->description = QLatin1String("newCamera") + QString::number(m_cameraDevices.size());
+ info->id =
+ QString(QLatin1String("camera") + QString::number(m_cameraDevices.size())).toUtf8();
+ info->isDefault = false;
+ m_cameraDevices.append(info->create());
+
+ emit videoInputsChanged();
+ }
+
+ QList<QCameraDevice> videoDevices() const override
+ {
+ return m_cameraDevices;
+ }
+
+private:
+ QList<QCameraDevice> m_cameraDevices;
+};
+
+QMockIntegration::QMockIntegration() : QPlatformMediaIntegration(QLatin1String("mock")) { }
+QMockIntegration::~QMockIntegration() = default;
+
+QPlatformVideoDevices *QMockIntegration::createVideoDevices()
+{
+ return new QMockVideoDevices(this);
+}
+
+std::unique_ptr<QPlatformMediaDevices> QMockIntegration::createMediaDevices()
+{
+ return std::make_unique<QMockMediaDevices>();
+}
+
+QMaybe<QPlatformAudioDecoder *> QMockIntegration::createAudioDecoder(QAudioDecoder *decoder)
+{
+ if (m_flags & NoAudioDecoderInterface)
+ m_lastAudioDecoderControl = nullptr;
+ else
+ m_lastAudioDecoderControl = new QMockAudioDecoder(decoder);
+ return m_lastAudioDecoderControl;
+}
+
+QMaybe<QPlatformMediaPlayer *> QMockIntegration::createPlayer(QMediaPlayer *parent)
+{
+ if (m_flags & NoPlayerInterface)
+ m_lastPlayer = nullptr;
+ else
+ m_lastPlayer = new QMockMediaPlayer(parent);
+ return m_lastPlayer;
+}
+
+QMaybe<QPlatformCamera *> QMockIntegration::createCamera(QCamera *parent)
+{
+ if (m_flags & NoCaptureInterface)
+ m_lastCamera = nullptr;
+ else
+ m_lastCamera = new QMockCamera(parent);
+ return m_lastCamera;
+}
+
+QMaybe<QPlatformImageCapture *> QMockIntegration::createImageCapture(QImageCapture *capture)
+{
+ return new QMockImageCapture(capture);
+}
+
+QMaybe<QPlatformMediaRecorder *> QMockIntegration::createRecorder(QMediaRecorder *recorder)
+{
+ return new QMockMediaEncoder(recorder);
+}
+
+QPlatformSurfaceCapture *QMockIntegration::createScreenCapture(QScreenCapture * /*capture*/)
+{
+ if (m_flags & NoCaptureInterface)
+ m_lastScreenCapture = nullptr;
+ else
+ m_lastScreenCapture = new QMockSurfaceCapture(QPlatformSurfaceCapture::ScreenSource{});
+
+ return m_lastScreenCapture;
+}
+
+QPlatformSurfaceCapture *QMockIntegration::createWindowCapture(QWindowCapture *)
+{
+ if (m_flags & NoCaptureInterface)
+ m_lastWindowCapture = nullptr;
+ else
+ m_lastWindowCapture = new QMockSurfaceCapture(QPlatformSurfaceCapture::WindowSource{});
+
+ return m_lastWindowCapture;
+}
+
+QMaybe<QPlatformMediaCaptureSession *> QMockIntegration::createCaptureSession()
+{
+ if (m_flags & NoCaptureInterface)
+ m_lastCaptureService = nullptr;
+ else
+ m_lastCaptureService = new QMockMediaCaptureSession();
+ return m_lastCaptureService;
+}
+
+QMaybe<QPlatformVideoSink *> QMockIntegration::createVideoSink(QVideoSink *sink)
+{
+ m_lastVideoSink = new QMockVideoSink(sink);
+ return m_lastVideoSink;
+}
+
+QMaybe<QPlatformAudioOutput *> QMockIntegration::createAudioOutput(QAudioOutput *q)
+{
+ return new QMockAudioOutput(q);
+}
+
+void QMockIntegration::addNewCamera()
+{
+ static_cast<QMockVideoDevices *>(videoDevices())->addNewCamera();
+}
+
+bool QMockCamera::simpleCamera = false;
+
+QT_END_NAMESPACE
+
+#include "qmockintegration.moc"
diff --git a/tests/auto/unit/mockbackend/qmockintegration.h b/tests/auto/unit/mockbackend/qmockintegration.h
new file mode 100644
index 000000000..20b61721c
--- /dev/null
+++ b/tests/auto/unit/mockbackend/qmockintegration.h
@@ -0,0 +1,103 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef QMOCKINTEGRATION_H
+#define QMOCKINTEGRATION_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qplatformmediaintegration_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QMockMediaPlayer;
+class QMockAudioDecoder;
+class QMockCamera;
+class QMockMediaCaptureSession;
+class QMockVideoSink;
+class QMockSurfaceCapture;
+
+class QMockIntegration : public QPlatformMediaIntegration
+{
+public:
+ QMockIntegration();
+ ~QMockIntegration();
+
+ static QMockIntegration *instance()
+ {
+ return static_cast<QMockIntegration *>(QPlatformMediaIntegration::instance());
+ }
+
+ QMaybe<QPlatformAudioDecoder *> createAudioDecoder(QAudioDecoder *decoder) override;
+ QMaybe<QPlatformMediaPlayer *> createPlayer(QMediaPlayer *) override;
+ QMaybe<QPlatformCamera *> createCamera(QCamera *) override;
+ QMaybe<QPlatformMediaRecorder *> createRecorder(QMediaRecorder *) override;
+ QMaybe<QPlatformImageCapture *> createImageCapture(QImageCapture *) override;
+ QMaybe<QPlatformMediaCaptureSession *> createCaptureSession() override;
+ QMaybe<QPlatformVideoSink *> createVideoSink(QVideoSink *) override;
+
+ QMaybe<QPlatformAudioOutput *> createAudioOutput(QAudioOutput *) override;
+
+ QPlatformSurfaceCapture *createScreenCapture(QScreenCapture *) override;
+ QPlatformSurfaceCapture *createWindowCapture(QWindowCapture *) override;
+
+ void addNewCamera();
+
+ enum Flag { NoPlayerInterface = 0x1, NoAudioDecoderInterface = 0x2, NoCaptureInterface = 0x4 };
+ Q_DECLARE_FLAGS(Flags, Flag);
+
+ void setFlags(Flags f) { m_flags = f; }
+ Flags flags() const { return m_flags; }
+
+ QMockMediaPlayer *lastPlayer() const { return m_lastPlayer; }
+ QMockAudioDecoder *lastAudioDecoder() const { return m_lastAudioDecoderControl; }
+ QMockCamera *lastCamera() const { return m_lastCamera; }
+ // QMockMediaEncoder *lastEncoder const { return m_lastEncoder; }
+ QMockMediaCaptureSession *lastCaptureService() const { return m_lastCaptureService; }
+ QMockVideoSink *lastVideoSink() const { return m_lastVideoSink; }
+ QMockSurfaceCapture *lastScreenCapture() { return m_lastScreenCapture; }
+ QMockSurfaceCapture *lastWindowCapture() { return m_lastWindowCapture; }
+
+protected:
+ QPlatformVideoDevices *createVideoDevices() override;
+ std::unique_ptr<QPlatformMediaDevices> createMediaDevices() override;
+
+private:
+
+ Flags m_flags = {};
+ QMockMediaPlayer *m_lastPlayer = nullptr;
+ QMockAudioDecoder *m_lastAudioDecoderControl = nullptr;
+ QMockCamera *m_lastCamera = nullptr;
+ // QMockMediaEncoder *m_lastEncoder = nullptr;
+ QMockMediaCaptureSession *m_lastCaptureService = nullptr;
+ QMockVideoSink *m_lastVideoSink = nullptr;
+ QMockSurfaceCapture *m_lastScreenCapture = nullptr;
+ QMockSurfaceCapture *m_lastWindowCapture = nullptr;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QMockIntegration::Flags);
+
+#define Q_ENABLE_MOCK_MULTIMEDIA_PLUGIN \
+ Q_IMPORT_PLUGIN(MockMultimediaPlugin) \
+ struct EnableMockPlugin \
+ { \
+ EnableMockPlugin() \
+ { \
+ qputenv("QT_MEDIA_BACKEND", "mock"); \
+ } \
+ }; \
+ static EnableMockPlugin s_mockMultimediaPluginEnabler;
+
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tests/auto/unit/mockbackend/qmockmediacapturesession.h b/tests/auto/unit/mockbackend/qmockmediacapturesession.h
new file mode 100644
index 000000000..0a2d3fb60
--- /dev/null
+++ b/tests/auto/unit/mockbackend/qmockmediacapturesession.h
@@ -0,0 +1,86 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef QMOCKMEDIACAPTURESESSION_H
+#define QMOCKMEDIACAPTURESESSION_H
+
+#include "qmockmediaencoder.h"
+#include "qmockimagecapture.h"
+#include "qmockcamera.h"
+#include "qmockimagecapture.h"
+#include "qmocksurfacecapture.h"
+#include <private/qplatformmediacapture_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QMockMediaCaptureSession : public QPlatformMediaCaptureSession
+{
+public:
+ QMockMediaCaptureSession()
+ : hasControls(true)
+ {
+ }
+ ~QMockMediaCaptureSession()
+ {
+ }
+
+ QPlatformCamera *camera() override { return hasControls ? mockCameraControl : nullptr; }
+
+ void setCamera(QPlatformCamera *camera) override
+ {
+ QMockCamera *control = static_cast<QMockCamera *>(camera);
+ if (mockCameraControl == control)
+ return;
+
+ mockCameraControl = control;
+ }
+
+ void setImageCapture(QPlatformImageCapture *imageCapture) override
+ {
+ mockImageCapture = imageCapture;
+ }
+ QPlatformImageCapture *imageCapture() override { return hasControls ? mockImageCapture : nullptr; }
+
+ QPlatformMediaRecorder *mediaRecorder() override { return hasControls ? mockControl : nullptr; }
+ void setMediaRecorder(QPlatformMediaRecorder *recorder) override
+ {
+ if (!hasControls) {
+ mockControl = nullptr;
+ return;
+ }
+ QMockMediaEncoder *control = static_cast<QMockMediaEncoder *>(recorder);
+ if (mockControl == control)
+ return;
+
+ mockControl = control;
+ }
+
+ void setVideoPreview(QVideoSink *) override {}
+
+ void setAudioInput(QPlatformAudioInput *input) override
+ {
+ m_audioInput = input;
+ }
+
+ QPlatformSurfaceCapture *screenCapture() override { return m_screenCapture; }
+ void setScreenCapture(QPlatformSurfaceCapture *capture) override { m_screenCapture = capture; }
+
+ QPlatformSurfaceCapture *windowCapture() override { return m_windowCapture; }
+ void setWindowCapture(QPlatformSurfaceCapture *capture) override { m_windowCapture = capture; }
+
+ QPlatformVideoFrameInput *videoFrameInput() override { return m_videoFrameInput; }
+ void setVideoFrameInput(QPlatformVideoFrameInput *input) override { m_videoFrameInput = input; }
+
+ QMockCamera *mockCameraControl = nullptr;
+ QPlatformImageCapture *mockImageCapture = nullptr;
+ QMockMediaEncoder *mockControl = nullptr;
+ QPlatformAudioInput *m_audioInput = nullptr;
+ QPlatformSurfaceCapture *m_screenCapture = nullptr;
+ QPlatformSurfaceCapture *m_windowCapture = nullptr;
+ QPlatformVideoFrameInput *m_videoFrameInput = nullptr;
+ bool hasControls;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMOCKMEDIACAPTURESESSION_H
diff --git a/tests/auto/unit/mockbackend/qmockmediadevices.cpp b/tests/auto/unit/mockbackend/qmockmediadevices.cpp
new file mode 100644
index 000000000..7f2478741
--- /dev/null
+++ b/tests/auto/unit/mockbackend/qmockmediadevices.cpp
@@ -0,0 +1,43 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "qmockmediadevices.h"
+#include "private/qcameradevice_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QMockMediaDevices::QMockMediaDevices()
+ : QPlatformMediaDevices()
+{
+}
+
+QMockMediaDevices::~QMockMediaDevices() = default;
+
+QList<QAudioDevice> QMockMediaDevices::audioInputs() const
+{
+ return m_inputDevices;
+}
+
+QList<QAudioDevice> QMockMediaDevices::audioOutputs() const
+{
+ return m_outputDevices;
+}
+
+QPlatformAudioSource *QMockMediaDevices::createAudioSource(const QAudioDevice &info,
+ QObject *parent)
+{
+ Q_UNUSED(info);
+ Q_UNUSED(parent);
+ return nullptr;// ###
+}
+
+QPlatformAudioSink *QMockMediaDevices::createAudioSink(const QAudioDevice &info,
+ QObject *parent)
+{
+ Q_UNUSED(info);
+ Q_UNUSED(parent);
+ return nullptr; //###
+}
+
+
+QT_END_NAMESPACE
diff --git a/tests/auto/unit/mockbackend/qmockmediadevices.h b/tests/auto/unit/mockbackend/qmockmediadevices.h
new file mode 100644
index 000000000..e9e823194
--- /dev/null
+++ b/tests/auto/unit/mockbackend/qmockmediadevices.h
@@ -0,0 +1,45 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef QMOCKMEDIADEVICES_H
+#define QMOCKMEDIADEVICES_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qplatformmediadevices_p.h>
+#include <qelapsedtimer.h>
+#include <qaudiodevice.h>
+#include <qcameradevice.h>
+
+QT_BEGIN_NAMESPACE
+
+class QCameraDevice;
+
+class QMockMediaDevices : public QPlatformMediaDevices
+{
+public:
+ QMockMediaDevices();
+ ~QMockMediaDevices();
+
+ QList<QAudioDevice> audioInputs() const override;
+ QList<QAudioDevice> audioOutputs() const override;
+ QPlatformAudioSource *createAudioSource(const QAudioDevice &info, QObject *parent) override;
+ QPlatformAudioSink *createAudioSink(const QAudioDevice &info, QObject *parent) override;
+
+private:
+ QList<QAudioDevice> m_inputDevices;
+ QList<QAudioDevice> m_outputDevices;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tests/auto/unit/mockbackend/qmockmediaencoder.h b/tests/auto/unit/mockbackend/qmockmediaencoder.h
new file mode 100644
index 000000000..cf855488b
--- /dev/null
+++ b/tests/auto/unit/mockbackend/qmockmediaencoder.h
@@ -0,0 +1,95 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef MOCKRECORDERCONTROL_H
+#define MOCKRECORDERCONTROL_H
+
+#include <QUrl>
+#include <qaudiodevice.h>
+
+#include "private/qplatformmediarecorder_p.h"
+
+class QMockMediaEncoder : public QPlatformMediaRecorder
+{
+public:
+ QMockMediaEncoder(QMediaRecorder *parent):
+ QPlatformMediaRecorder(parent),
+ m_state(QMediaRecorder::StoppedState),
+ m_position(0)
+ {
+ }
+
+ bool isLocationWritable(const QUrl &) const override
+ {
+ return true;
+ }
+
+ QMediaRecorder::RecorderState state() const override
+ {
+ return m_state;
+ }
+
+ qint64 duration() const override
+ {
+ return m_position;
+ }
+
+ virtual void setMetaData(const QMediaMetaData &m) override
+ {
+ m_metaData = m;
+ metaDataChanged();
+ }
+ virtual QMediaMetaData metaData() const override { return m_metaData; }
+
+ using QPlatformMediaRecorder::updateError;
+
+public:
+ void record(QMediaEncoderSettings &settings) override
+ {
+ m_state = QMediaRecorder::RecordingState;
+ m_settings = settings;
+ m_position=1;
+ stateChanged(m_state);
+ durationChanged(m_position);
+
+ QUrl actualLocation = outputLocation().isEmpty() ? QUrl::fromLocalFile("default_name.mp4") : outputLocation();
+ actualLocationChanged(actualLocation);
+ }
+
+ void pause() override
+ {
+ m_state = QMediaRecorder::PausedState;
+ stateChanged(m_state);
+ }
+
+ void resume() override
+ {
+ m_state = QMediaRecorder::RecordingState;
+ stateChanged(m_state);
+ }
+
+ void stop() override
+ {
+ m_position=0;
+ m_state = QMediaRecorder::StoppedState;
+ stateChanged(m_state);
+ }
+
+ void reset()
+ {
+ m_state = QMediaRecorder::StoppedState;
+ m_settings = QMediaEncoderSettings();
+ m_position = 0;
+ stateChanged(m_state);
+ durationChanged(m_position);
+ clearActualLocation();
+ }
+
+public:
+ QMediaMetaData m_metaData;
+ QMediaRecorder::RecorderState m_state;
+ QMediaEncoderSettings m_settings;
+ qint64 m_position;
+};
+
+#endif // MOCKRECORDERCONTROL_H
diff --git a/tests/auto/unit/mockbackend/qmockmediaplayer.h b/tests/auto/unit/mockbackend/qmockmediaplayer.h
new file mode 100644
index 000000000..a3ba76beb
--- /dev/null
+++ b/tests/auto/unit/mockbackend/qmockmediaplayer.h
@@ -0,0 +1,175 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef QMOCKMEDIAPLAYER_H
+#define QMOCKMEDIAPLAYER_H
+
+#include "private/qplatformmediaplayer_p.h"
+#include <qurl.h>
+
+QT_BEGIN_NAMESPACE
+
+class QMockMediaPlayer : public QPlatformMediaPlayer
+{
+ friend class QMockMediaPlayerService;
+
+public:
+ QMockMediaPlayer(QMediaPlayer *parent)
+ : QPlatformMediaPlayer(parent)
+ , _state(QMediaPlayer::StoppedState)
+ , _error(QMediaPlayer::NoError)
+ , _duration(0)
+ , _position(0)
+ , _bufferProgress(0)
+ , _audioAvailable(false)
+ , _videoAvailable(false)
+ , _isSeekable(true)
+ , _playbackRate(qreal(1.0))
+ , _stream(0)
+ , _isValid(false)
+ {
+ }
+ ~QMockMediaPlayer()
+ {
+ }
+
+ QMediaPlayer::PlaybackState state() const override { return _state; }
+ void updateState(QMediaPlayer::PlaybackState state) { setState(state); }
+ void updateMediaStatus(QMediaPlayer::MediaStatus status, QMediaPlayer::PlaybackState state)
+ {
+ _state = state;
+
+ mediaStatusChanged(status);
+ stateChanged(_state);
+ }
+
+ qint64 duration() const override { return _duration; }
+ void setDuration(qint64 duration) { durationChanged(_duration = duration); }
+
+ qint64 position() const override { return _position; }
+
+ void setPosition(qint64 position) override
+ {
+ if (position != _position)
+ positionChanged(_position = position);
+ }
+
+ float bufferProgress() const override { return _bufferProgress; }
+ void setBufferStatus(float status)
+ {
+ if (_bufferProgress == status)
+ return;
+ _bufferProgress = status;
+ bufferProgressChanged(status);
+ }
+
+ bool isAudioAvailable() const override { return _audioAvailable; }
+ bool isVideoAvailable() const override { return _videoAvailable; }
+
+ bool isSeekable() const override { return _isSeekable; }
+ void setSeekable(bool seekable) { seekableChanged(_isSeekable = seekable); }
+
+ QMediaTimeRange availablePlaybackRanges() const override { return QMediaTimeRange(_seekRange.first, _seekRange.second); }
+ void setSeekRange(qint64 minimum, qint64 maximum) { _seekRange = qMakePair(minimum, maximum); }
+
+ qreal playbackRate() const override { return _playbackRate; }
+ void setPlaybackRate(qreal rate) override
+ {
+ if (rate != _playbackRate)
+ playbackRateChanged(_playbackRate = rate);
+ }
+
+ QUrl media() const override { return _media; }
+ void setMedia(const QUrl &content, QIODevice *stream) override
+ {
+ _stream = stream;
+ _media = content;
+ setState(QMediaPlayer::StoppedState);
+ mediaStatusChanged(_media.isEmpty() ? QMediaPlayer::NoMedia : QMediaPlayer::LoadingMedia);
+ }
+ QIODevice *mediaStream() const override { return _stream; }
+
+ bool streamPlaybackSupported() const override { return m_supportsStreamPlayback; }
+ void setStreamPlaybackSupported(bool b) { m_supportsStreamPlayback = b; }
+
+ void play() override { if (_isValid && !_media.isEmpty()) setState(QMediaPlayer::PlayingState); }
+ void pause() override { if (_isValid && !_media.isEmpty()) setState(QMediaPlayer::PausedState); }
+ void stop() override { if (_state != QMediaPlayer::StoppedState) setState(QMediaPlayer::StoppedState); }
+
+ void setVideoSink(QVideoSink *) override {}
+
+ void setAudioOutput(QPlatformAudioOutput *output) override { m_audioOutput = output; }
+
+ void emitError(QMediaPlayer::Error err, const QString &errorString) { error(err, errorString); }
+
+ void setState(QMediaPlayer::PlaybackState state)
+ {
+ if (_state == state)
+ return;
+ _state = state;
+ stateChanged(state);
+ }
+ void setState(QMediaPlayer::PlaybackState state, QMediaPlayer::MediaStatus status)
+ {
+ _state = state;
+ mediaStatusChanged(status);
+ stateChanged(state);
+ }
+ void setMediaStatus(QMediaPlayer::MediaStatus status)
+ {
+ if (status == QMediaPlayer::StalledMedia || status == QMediaPlayer::BufferingMedia)
+ bufferProgressChanged(_bufferProgress);
+ mediaStatusChanged(status);
+ }
+ void setIsValid(bool isValid) { _isValid = isValid; }
+ void setMedia(QUrl media) { _media = media; }
+ void setVideoAvailable(bool videoAvailable) { _videoAvailable = videoAvailable; }
+ void setError(QMediaPlayer::Error err)
+ {
+ _error = err;
+ error(_error, _errorString);
+ }
+ void setErrorString(QString errorString)
+ {
+ _errorString = errorString;
+ error(_error, _errorString);
+ }
+
+ void reset()
+ {
+ _state = QMediaPlayer::StoppedState;
+ _error = QMediaPlayer::NoError;
+ _duration = 0;
+ _position = 0;
+ _bufferProgress = 0;
+ _videoAvailable = false;
+ _isSeekable = false;
+ _playbackRate = 0.0;
+ _media = QUrl();
+ _stream = 0;
+ _isValid = false;
+ _errorString = QString();
+ }
+
+
+ QMediaPlayer::PlaybackState _state;
+ QMediaPlayer::Error _error;
+ qint64 _duration;
+ qint64 _position;
+ float _bufferProgress;
+ bool _audioAvailable;
+ bool _videoAvailable;
+ bool _isSeekable;
+ QPair<qint64, qint64> _seekRange;
+ qreal _playbackRate;
+ QUrl _media;
+ QIODevice *_stream;
+ bool _isValid;
+ QString _errorString;
+ bool m_supportsStreamPlayback = false;
+ QPlatformAudioOutput *m_audioOutput = nullptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMOCKMEDIAPLAYER_H
diff --git a/tests/auto/unit/mockbackend/qmocksurfacecapture.h b/tests/auto/unit/mockbackend/qmocksurfacecapture.h
new file mode 100644
index 000000000..00ce80ebb
--- /dev/null
+++ b/tests/auto/unit/mockbackend/qmocksurfacecapture.h
@@ -0,0 +1,88 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef QMOCKSURFACECAPTURE_H
+#define QMOCKSURFACECAPTURE_H
+
+#include "private/qplatformsurfacecapture_p.h"
+#include "private/qvideoframe_p.h"
+
+#include "qmockvideobuffer.h"
+#include "qthread.h"
+
+QT_BEGIN_NAMESPACE
+
+class QMockSurfaceCapture : public QPlatformSurfaceCapture
+{
+ class Grabber : public QThread
+ {
+ public:
+ Grabber(QMockSurfaceCapture &capture) : QThread(&capture), m_capture(capture) { }
+
+ void run() override
+ {
+ for (int i = 0; !isInterruptionRequested(); ++i) {
+ QImage image(m_capture.m_imageSize, QImage::Format_ARGB32);
+
+ image.fill(i % 2 ? Qt::red : Qt::blue);
+
+ QVideoFrame frame = QVideoFramePrivate::createFrame(
+ std::make_unique<QMockVideoBuffer>(image),
+ QVideoFrameFormat(m_capture.m_imageSize,
+ QVideoFrameFormat::pixelFormatFromImageFormat(
+ m_capture.m_imageFormat)));
+
+ emit m_capture.newVideoFrame(frame);
+ }
+ }
+
+ private:
+ QMockSurfaceCapture &m_capture;
+ };
+
+public:
+ using QPlatformSurfaceCapture::QPlatformSurfaceCapture;
+
+ ~QMockSurfaceCapture() { resetGrabber(); }
+
+ bool setActiveInternal(bool active) override
+ {
+ if (active) {
+ m_grabber = std::make_unique<Grabber>(*this);
+ m_grabber->start();
+ } else {
+ resetGrabber();
+ }
+
+ return true;
+ }
+
+ bool isActive() const override { return bool(m_grabber); }
+
+ QVideoFrameFormat frameFormat() const override
+ {
+ return m_grabber ? QVideoFrameFormat(
+ m_imageSize, QVideoFrameFormat::pixelFormatFromImageFormat(m_imageFormat))
+ : QVideoFrameFormat{};
+ }
+
+private:
+ void resetGrabber()
+ {
+ if (m_grabber) {
+ m_grabber->requestInterruption();
+ m_grabber->quit();
+ m_grabber->wait();
+ m_grabber.reset();
+ }
+ }
+
+private:
+ std::unique_ptr<Grabber> m_grabber;
+ const QImage::Format m_imageFormat = QImage::Format_ARGB32;
+ const QSize m_imageSize = QSize(2, 3);
+};
+
+QT_END_NAMESPACE
+
+#endif // QMOCKSURFACECAPTURE_H
diff --git a/tests/auto/unit/mockbackend/qmockvideobuffer.h b/tests/auto/unit/mockbackend/qmockvideobuffer.h
new file mode 100644
index 000000000..0ee32416c
--- /dev/null
+++ b/tests/auto/unit/mockbackend/qmockvideobuffer.h
@@ -0,0 +1,38 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef QMOCKVIDEOBUFFER_H
+#define QMOCKVIDEOBUFFER_H
+
+#include "qimage.h"
+#include "private/qhwvideobuffer_p.h"
+
+class QMockVideoBuffer : public QHwVideoBuffer
+{
+public:
+ QMockVideoBuffer(QImage image) : QHwVideoBuffer(QVideoFrame::NoHandle), m_image(image) { }
+
+ MapData map(QtVideo::MapMode mode) override
+ {
+ MapData mapData;
+ if (m_mapMode == QtVideo::MapMode::NotMapped && !m_image.isNull()
+ && mode != QtVideo::MapMode::NotMapped) {
+ m_mapMode = mode;
+
+ mapData.planeCount = 1;
+ mapData.bytesPerLine[0] = m_image.bytesPerLine();
+ mapData.data[0] = m_image.bits();
+ mapData.dataSize[0] = m_image.sizeInBytes();
+ }
+
+ return mapData;
+ }
+
+ void unmap() override { m_mapMode = QtVideo::MapMode::NotMapped; }
+
+private:
+ QtVideo::MapMode m_mapMode = QtVideo::MapMode::NotMapped;
+ QImage m_image;
+};
+
+#endif // QMOCKVIDEOBUFFER_H
diff --git a/tests/auto/unit/mockbackend/qmockvideosink.h b/tests/auto/unit/mockbackend/qmockvideosink.h
new file mode 100644
index 000000000..d93178668
--- /dev/null
+++ b/tests/auto/unit/mockbackend/qmockvideosink.h
@@ -0,0 +1,33 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef QMOCKVIDEOSINK_H
+#define QMOCKVIDEOSINK_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qplatformvideosink_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QMockVideoSink : public QPlatformVideoSink
+{
+public:
+ explicit QMockVideoSink(QVideoSink *parent)
+ : QPlatformVideoSink(parent)
+ {}
+ void setRhi(QRhi * /*rhi*/) override {}
+};
+
+QT_END_NAMESPACE
+
+#endif