diff options
author | Artem Dyomin <artem.dyomin@qt.io> | 2023-06-20 13:27:46 +0200 |
---|---|---|
committer | Artem Dyomin <artem.dyomin@qt.io> | 2023-06-27 00:08:51 +0200 |
commit | 3d23c26565f087c2be2bb13cb511536ab05ab4d6 (patch) | |
tree | bfd7570ab2812b41aca3f6a21233ce2ec68c7c60 /src/multimedia/platform | |
parent | 0e6a68fff78a487c809557fada08a87cec8d2ff0 (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.cpp | 16 | ||||
-rw-r--r-- | src/multimedia/platform/qplatformmediadevices_p.h | 6 | ||||
-rw-r--r-- | src/multimedia/platform/qplatformmediaintegration.cpp | 43 | ||||
-rw-r--r-- | src/multimedia/platform/qplatformmediaintegration_p.h | 12 | ||||
-rw-r--r-- | src/multimedia/platform/qplatformvideodevices.cpp | 13 | ||||
-rw-r--r-- | src/multimedia/platform/qplatformvideodevices_p.h | 11 |
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; }; |