summaryrefslogtreecommitdiffstats
path: root/src/multimedia/platform
diff options
context:
space:
mode:
authorArtem Dyomin <artem.dyomin@qt.io>2023-06-20 13:27:46 +0200
committerArtem Dyomin <artem.dyomin@qt.io>2023-06-27 00:08:51 +0200
commit3d23c26565f087c2be2bb13cb511536ab05ab4d6 (patch)
treebfd7570ab2812b41aca3f6a21233ce2ec68c7c60 /src/multimedia/platform
parent0e6a68fff78a487c809557fada08a87cec8d2ff0 (diff)
Implement initialization of video devices on the first connection
The problem is that VideoDevices are created and managed by QPlatformMediaIntegration, but signals are connected to QPlatformMediaDevices. A possible redesign is here codereview.qt-project.org/c/qt/qtmultimedia/+/484647, but the concern is that it's a bit of controversy with the initial idea. Current patchs solves the poblem directly and covers with UTs. Idea of the patch: let's handle connection to QMediaDevices::videoInputsChanged and initialize QPlatformMediaIntegration and video devices connection. I propose postpone initialization because users don't expect us doing any serious magic just on the signal connection. The UTs were slightly refactored in order to test the case. Pick-to: 6.6 6.5 Change-Id: I0ca3dfb2126daf69746380fa65096d9d05327f5e Reviewed-by: Artem Dyomin <artem.dyomin@qt.io>
Diffstat (limited to 'src/multimedia/platform')
-rw-r--r--src/multimedia/platform/qplatformmediadevices.cpp16
-rw-r--r--src/multimedia/platform/qplatformmediadevices_p.h6
-rw-r--r--src/multimedia/platform/qplatformmediaintegration.cpp43
-rw-r--r--src/multimedia/platform/qplatformmediaintegration_p.h12
-rw-r--r--src/multimedia/platform/qplatformvideodevices.cpp13
-rw-r--r--src/multimedia/platform/qplatformvideodevices_p.h11
6 files changed, 60 insertions, 41 deletions
diff --git a/src/multimedia/platform/qplatformmediadevices.cpp b/src/multimedia/platform/qplatformmediadevices.cpp
index 09c26a670..f971fb4c3 100644
--- a/src/multimedia/platform/qplatformmediadevices.cpp
+++ b/src/multimedia/platform/qplatformmediadevices.cpp
@@ -2,11 +2,13 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformmediadevices_p.h"
+#include "qplatformmediaintegration_p.h"
#include "qmediadevices.h"
#include "qaudiodevice.h"
#include "qcameradevice.h"
#include "qaudiosystem_p.h"
#include "qaudiodevice.h"
+#include "qplatformvideodevices_p.h"
#include <qmutex.h>
#include <qloggingcategory.h>
@@ -75,8 +77,18 @@ QPlatformMediaDevices *QPlatformMediaDevices::instance()
}
-QPlatformMediaDevices::QPlatformMediaDevices()
-{}
+QPlatformMediaDevices::QPlatformMediaDevices() = default;
+
+void QPlatformMediaDevices::initVideoDevicesConnection() {
+ std::call_once(m_videoDevicesConnectionFlag, [this]() {
+ QMetaObject::invokeMethod(this, [this]() {
+ auto videoDevices = QPlatformMediaIntegration::instance()->videoDevices();
+ if (videoDevices)
+ connect(videoDevices, &QPlatformVideoDevices::videoInputsChanged, this,
+ &QPlatformMediaDevices::videoInputsChanged);
+ }, Qt::QueuedConnection);
+ });
+}
void QPlatformMediaDevices::setDevices(QPlatformMediaDevices *devices)
{
diff --git a/src/multimedia/platform/qplatformmediadevices_p.h b/src/multimedia/platform/qplatformmediadevices_p.h
index d475495d1..0d7ba9306 100644
--- a/src/multimedia/platform/qplatformmediadevices_p.h
+++ b/src/multimedia/platform/qplatformmediadevices_p.h
@@ -18,6 +18,7 @@
#include <private/qtmultimediaglobal_p.h>
#include <qlist.h>
#include <qobject.h>
+#include <mutex>
QT_BEGIN_NAMESPACE
@@ -52,10 +53,15 @@ public:
virtual void prepareAudio();
+ void initVideoDevicesConnection();
+
Q_SIGNALS:
void audioInputsChanged();
void audioOutputsChanged();
void videoInputsChanged();
+
+private:
+ std::once_flag m_videoDevicesConnectionFlag;
};
QT_END_NAMESPACE
diff --git a/src/multimedia/platform/qplatformmediaintegration.cpp b/src/multimedia/platform/qplatformmediaintegration.cpp
index 7adfbcf54..b094d549c 100644
--- a/src/multimedia/platform/qplatformmediaintegration.cpp
+++ b/src/multimedia/platform/qplatformmediaintegration.cpp
@@ -73,25 +73,24 @@ static QString defaultBackend(const QStringList &backends)
QT_BEGIN_NAMESPACE
-namespace {
-struct InstanceHolder {
- ~InstanceHolder()
- {
- QMutexLocker locker(&mutex);
- instance = nullptr;
- }
+struct QPlatformMediaIntegration::InstanceHolder
+{
+ // TODO: replace the mutex with std::once
QBasicMutex mutex;
- QPlatformMediaIntegration *instance = nullptr;
- QPlatformMediaIntegration *nativeInstance = nullptr;
+ std::unique_ptr<QPlatformMediaIntegration> instance;
+ Factory factory;
} instanceHolder;
-}
-
QPlatformMediaIntegration *QPlatformMediaIntegration::instance()
{
QMutexLocker locker(&instanceHolder.mutex);
if (instanceHolder.instance)
- return instanceHolder.instance;
+ return instanceHolder.instance.get();
+
+ if (instanceHolder.factory) {
+ instanceHolder.instance = instanceHolder.factory();
+ return instanceHolder.instance.get();
+ }
const auto backends = availableBackends();
QString backend = QString::fromUtf8(qgetenv("QT_MEDIA_BACKEND"));
@@ -99,27 +98,25 @@ QPlatformMediaIntegration *QPlatformMediaIntegration::instance()
backend = defaultBackend(backends);
qCDebug(qLcMediaPlugin) << "loading backend" << backend;
- instanceHolder.nativeInstance =
- qLoadPlugin<QPlatformMediaIntegration, QPlatformMediaPlugin>(loader(), backend);
+ instanceHolder.instance.reset(
+ qLoadPlugin<QPlatformMediaIntegration, QPlatformMediaPlugin>(loader(), backend));
- if (!instanceHolder.nativeInstance) {
+ if (!instanceHolder.instance) {
qWarning() << "could not load multimedia backend" << backend;
- instanceHolder.nativeInstance = new QDummyIntegration;
+ instanceHolder.instance = std::make_unique<QDummyIntegration>();
}
- instanceHolder.instance = instanceHolder.nativeInstance;
- return instanceHolder.instance;
+ return instanceHolder.instance.get();
}
/*
This API is there to be able to test with a mock backend.
*/
-void QPlatformMediaIntegration::setIntegration(QPlatformMediaIntegration *integration)
+void QPlatformMediaIntegration::setPlatformFactory(Factory factory)
{
- if (integration)
- instanceHolder.instance = integration;
- else
- instanceHolder.instance = instanceHolder.nativeInstance;
+ Q_ASSERT((factory == nullptr) ^ (instanceHolder.factory == nullptr));
+ instanceHolder.instance.reset();
+ instanceHolder.factory = std::move(factory);
}
QList<QCameraDevice> QPlatformMediaIntegration::videoInputs()
diff --git a/src/multimedia/platform/qplatformmediaintegration_p.h b/src/multimedia/platform/qplatformmediaintegration_p.h
index debd68485..728425355 100644
--- a/src/multimedia/platform/qplatformmediaintegration_p.h
+++ b/src/multimedia/platform/qplatformmediaintegration_p.h
@@ -58,9 +58,6 @@ class Q_MULTIMEDIA_EXPORT QPlatformMediaIntegration
public:
static QPlatformMediaIntegration *instance();
- // API to be able to test with a mock backend
- static void setIntegration(QPlatformMediaIntegration *);
-
QPlatformMediaIntegration();
virtual ~QPlatformMediaIntegration();
virtual QPlatformMediaFormatInfo *formatInfo() = 0;
@@ -84,6 +81,15 @@ public:
QList<QCapturableWindow> capturableWindows();
bool isCapturableWindowValid(const QCapturableWindowPrivate &);
+ QPlatformVideoDevices *videoDevices() { return m_videoDevices.get(); }
+
+private:
+ friend class QMockIntegrationFactory;
+ // API to be able to test with a mock backend
+ using Factory = std::function<std::unique_ptr<QPlatformMediaIntegration>()>;
+ struct InstanceHolder;
+ static void setPlatformFactory(Factory factory);
+
protected:
std::unique_ptr<QPlatformVideoDevices> m_videoDevices;
std::unique_ptr<QPlatformCapturableWindows> m_capturableWindows;
diff --git a/src/multimedia/platform/qplatformvideodevices.cpp b/src/multimedia/platform/qplatformvideodevices.cpp
index e556bb899..bcf664cd2 100644
--- a/src/multimedia/platform/qplatformvideodevices.cpp
+++ b/src/multimedia/platform/qplatformvideodevices.cpp
@@ -2,18 +2,11 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformvideodevices_p.h"
-#include "qplatformmediadevices_p.h"
QT_BEGIN_NAMESPACE
-QPlatformVideoDevices::~QPlatformVideoDevices()
-{
-
-}
-
-void QPlatformVideoDevices::videoInputsChanged()
-{
- emit QPlatformMediaDevices::instance()->videoInputsChanged();
-}
+QPlatformVideoDevices::~QPlatformVideoDevices() = default;
QT_END_NAMESPACE
+
+#include "moc_qplatformvideodevices_p.cpp"
diff --git a/src/multimedia/platform/qplatformvideodevices_p.h b/src/multimedia/platform/qplatformvideodevices_p.h
index 0ec049c3c..008322be2 100644
--- a/src/multimedia/platform/qplatformvideodevices_p.h
+++ b/src/multimedia/platform/qplatformvideodevices_p.h
@@ -16,23 +16,28 @@
#include <private/qtmultimediaglobal_p.h>
#include <qmediarecorder.h>
+#include <qobject.h>
QT_BEGIN_NAMESPACE
class QPlatformMediaIntegration;
-class Q_MULTIMEDIA_EXPORT QPlatformVideoDevices
+class Q_MULTIMEDIA_EXPORT QPlatformVideoDevices : public QObject
{
+ Q_OBJECT
public:
QPlatformVideoDevices(QPlatformMediaIntegration *integration)
: m_integration(integration)
{}
- virtual ~QPlatformVideoDevices();
+
+ ~QPlatformVideoDevices() override;
virtual QList<QCameraDevice> videoDevices() const = 0;
-protected:
+Q_SIGNALS:
void videoInputsChanged();
+
+protected:
QPlatformMediaIntegration *m_integration = nullptr;
};