diff options
18 files changed, 89 insertions, 96 deletions
diff --git a/src/multimedia/android/qandroidmediadevices.cpp b/src/multimedia/android/qandroidmediadevices.cpp index cd6548ac3..55533621c 100644 --- a/src/multimedia/android/qandroidmediadevices.cpp +++ b/src/multimedia/android/qandroidmediadevices.cpp @@ -72,12 +72,12 @@ void QAndroidMediaDevices::forwardAudioInputsChanged() static void onAudioInputDevicesUpdated(JNIEnv */*env*/, jobject /*thiz*/) { - static_cast<QAndroidMediaDevices*>(QPlatformMediaDevices::instance())->forwardAudioInputsChanged(); + static_cast<QAndroidMediaDevices*>(QPlatformMediaIntegration::instance()->mediaDevices())->forwardAudioInputsChanged(); } static void onAudioOutputDevicesUpdated(JNIEnv */*env*/, jobject /*thiz*/) { - static_cast<QAndroidMediaDevices*>(QPlatformMediaDevices::instance())->forwardAudioOutputsChanged(); + static_cast<QAndroidMediaDevices*>(QPlatformMediaIntegration::instance()->mediaDevices())->forwardAudioOutputsChanged(); } Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void * /*reserved*/) diff --git a/src/multimedia/audio/qaudiosink.cpp b/src/multimedia/audio/qaudiosink.cpp index cb99f384e..aac96c342 100644 --- a/src/multimedia/audio/qaudiosink.cpp +++ b/src/multimedia/audio/qaudiosink.cpp @@ -87,7 +87,7 @@ QAudioSink::QAudioSink(const QAudioFormat &format, QObject *parent) QAudioSink::QAudioSink(const QAudioDevice &audioDevice, const QAudioFormat &format, QObject *parent): QObject(parent) { - d = QPlatformMediaDevices::instance()->audioOutputDevice(format, audioDevice, parent); + d = QPlatformMediaIntegration::instance()->mediaDevices()->audioOutputDevice(format, audioDevice, parent); if (d) connect(d, &QPlatformAudioSink::stateChanged, this, [this](QAudio::State state) { // if the signal has been emitted from another thread, diff --git a/src/multimedia/audio/qaudiosource.cpp b/src/multimedia/audio/qaudiosource.cpp index c92205c22..5e59a4798 100644 --- a/src/multimedia/audio/qaudiosource.cpp +++ b/src/multimedia/audio/qaudiosource.cpp @@ -96,7 +96,7 @@ QAudioSource::QAudioSource(const QAudioFormat &format, QObject *parent) QAudioSource::QAudioSource(const QAudioDevice &audioDevice, const QAudioFormat &format, QObject *parent): QObject(parent) { - d = QPlatformMediaDevices::instance()->audioInputDevice(format, audioDevice, parent); + d = QPlatformMediaIntegration::instance()->mediaDevices()->audioInputDevice(format, audioDevice, parent); if (d) { connect(d, &QPlatformAudioSource::stateChanged, this, [this](QAudio::State state) { // if the signal has been emitted from another thread, diff --git a/src/multimedia/audio/qsoundeffect.cpp b/src/multimedia/audio/qsoundeffect.cpp index 1ffe4b800..c793cf36b 100644 --- a/src/multimedia/audio/qsoundeffect.cpp +++ b/src/multimedia/audio/qsoundeffect.cpp @@ -99,7 +99,7 @@ QSoundEffectPrivate::QSoundEffectPrivate(QSoundEffect *q, const QAudioDevice &au { open(QIODevice::ReadOnly); - QPlatformMediaDevices::instance()->prepareAudio(); + QPlatformMediaIntegration::instance()->mediaDevices()->prepareAudio(); } void QSoundEffectPrivate::sampleReady() diff --git a/src/multimedia/platform/qplatformmediadevices.cpp b/src/multimedia/platform/qplatformmediadevices.cpp index 069b3012b..484886f44 100644 --- a/src/multimedia/platform/qplatformmediadevices.cpp +++ b/src/multimedia/platform/qplatformmediadevices.cpp @@ -3,17 +3,11 @@ #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> -#include <QtCore/qcoreapplication.h> - #if defined(Q_OS_ANDROID) #include <qandroidmediadevices_p.h> #elif defined(Q_OS_DARWIN) @@ -33,69 +27,27 @@ QT_BEGIN_NAMESPACE -namespace { - -struct DevicesHolder +std::unique_ptr<QPlatformMediaDevices> QPlatformMediaDevices::create() { - ~DevicesHolder() { reset(); } - - void reset() - { - QMutexLocker locker(&mutex); - - delete nativeInstance; - nativeInstance = nullptr; - instance = nullptr; - } - - QBasicMutex mutex; - QPlatformMediaDevices *instance = nullptr; - QPlatformMediaDevices *nativeInstance = nullptr; -}; - -Q_GLOBAL_STATIC(DevicesHolder, devicesHolder); - -} - -QPlatformMediaDevices *QPlatformMediaDevices::instance() -{ - QMutexLocker locker(&devicesHolder->mutex); - if (devicesHolder->instance) - return devicesHolder->instance; - #ifdef Q_OS_DARWIN - devicesHolder->nativeInstance = new QDarwinMediaDevices; + return std::make_unique<QDarwinMediaDevices>(); #elif defined(Q_OS_WINDOWS) - devicesHolder->nativeInstance = new QWindowsMediaDevices; + return std::make_unique<QWindowsMediaDevices>(); #elif defined(Q_OS_ANDROID) - devicesHolder->nativeInstance = new QAndroidMediaDevices; + return std::make_unique<QAndroidMediaDevices>(); #elif QT_CONFIG(alsa) - devicesHolder->nativeInstance = new QAlsaMediaDevices; + return std::make_unique<QAlsaMediaDevices>(); #elif QT_CONFIG(pulseaudio) - devicesHolder->nativeInstance = new QPulseAudioMediaDevices; + return std::make_unique<QPulseAudioMediaDevices>(); #elif defined(Q_OS_QNX) - devicesHolder->nativeInstance = new QQnxMediaDevices; + return std::make_unique<QQnxMediaDevices>(); #elif defined(Q_OS_WASM) - devicesHolder->nativeInstance = new QWasmMediaDevices; + return std::make_unique<QWasmMediaDevices>(); #else - devicesHolder->nativeInstance = new QPlatformMediaDevices; + return std::make_unique<QPlatformMediaDevices>(); #endif - - if (!QCoreApplication::instance()) { - // QTBUG-120198: Destructors are not called when shutting down - // application with Windows backend. - qWarning("Accessing QMediaDevices without a QCoreApplication"); - } else { - connect(qApp, &QObject::destroyed, devicesHolder->nativeInstance, []() { - devicesHolder->reset(); - }); - } - - devicesHolder->instance = devicesHolder->nativeInstance; - return devicesHolder->instance; } - QPlatformMediaDevices::QPlatformMediaDevices() = default; void QPlatformMediaDevices::initVideoDevicesConnection() @@ -106,11 +58,6 @@ void QPlatformMediaDevices::initVideoDevicesConnection() &QPlatformMediaDevices::videoInputsChanged, Qt::UniqueConnection); } -void QPlatformMediaDevices::setDevices(QPlatformMediaDevices *devices) -{ - devicesHolder->instance = devices; -} - QPlatformMediaDevices::~QPlatformMediaDevices() = default; QList<QAudioDevice> QPlatformMediaDevices::audioInputs() const diff --git a/src/multimedia/platform/qplatformmediadevices_p.h b/src/multimedia/platform/qplatformmediadevices_p.h index 555e269c8..b7aa68f1d 100644 --- a/src/multimedia/platform/qplatformmediadevices_p.h +++ b/src/multimedia/platform/qplatformmediadevices_p.h @@ -19,6 +19,7 @@ #include <qlist.h> #include <qobject.h> #include <mutex> +#include <memory> QT_BEGIN_NAMESPACE @@ -37,8 +38,7 @@ public: QPlatformMediaDevices(); ~QPlatformMediaDevices() override; - static void setDevices(QPlatformMediaDevices *); - static QPlatformMediaDevices *instance(); + static std::unique_ptr<QPlatformMediaDevices> create(); virtual QList<QAudioDevice> audioInputs() const; virtual QList<QAudioDevice> audioOutputs() const; diff --git a/src/multimedia/platform/qplatformmediaintegration.cpp b/src/multimedia/platform/qplatformmediaintegration.cpp index 3df477e45..dcb412acf 100644 --- a/src/multimedia/platform/qplatformmediaintegration.cpp +++ b/src/multimedia/platform/qplatformmediaintegration.cpp @@ -14,16 +14,20 @@ #include <QtCore/qcoreapplication.h> #include "qplatformcapturablewindows_p.h" -#include "QtCore/private/qfactoryloader_p.h" -#include "private/qplatformmediaformatinfo_p.h" +#include "qplatformmediadevices_p.h" +#include <QtCore/private/qfactoryloader_p.h> +#include <QtCore/private/qcoreapplication_p.h> +#include <private/qplatformmediaformatinfo_p.h> #include "qplatformmediaplugin_p.h" -class QDummyIntegration : public QPlatformMediaIntegration +namespace { + +class QFallbackIntegration : public QPlatformMediaIntegration { public: - QDummyIntegration() + QFallbackIntegration() { - qCritical("QtMultimedia is not currently supported on this platform or compiler."); + qWarning("No QtMultimedia backends found. Only QMediaDevices, QAudioDevice, QSoundEffect, QAudioSink, and QAudioSource are available."); } }; @@ -72,8 +76,6 @@ static QString defaultBackend(const QStringList &backends) return backends[0]; } -namespace { - struct InstanceHolder { InstanceHolder() @@ -91,8 +93,8 @@ struct InstanceHolder qLoadPlugin<QPlatformMediaIntegration, QPlatformMediaPlugin>(loader(), backend)); if (!instance) { - qWarning() << "could not load multimedia backend" << backend; - instance = std::make_unique<QDummyIntegration>(); + // No backends found. Use fallback to support basic functionality + instance = std::make_unique<QFallbackIntegration>(); } } @@ -152,22 +154,51 @@ QPlatformMediaFormatInfo *QPlatformMediaIntegration::createFormatInfo() return new QPlatformMediaFormatInfo; } +// clang-format off +std::unique_ptr<QPlatformMediaDevices> QPlatformMediaIntegration::createMediaDevices() +{ + // Avoid releasing WMF resources and uninitializing WMF during static + // destruction, QTBUG-120198 + if (QCoreApplication::instance()) + connect(qApp, &QObject::destroyed, this, [this] { + m_mediaDevices = nullptr; + }); + + return QPlatformMediaDevices::create(); +} + QPlatformVideoDevices *QPlatformMediaIntegration::videoDevices() { std::call_once(m_videoDevicesOnceFlag, - [this]() { m_videoDevices.reset(createVideoDevices()); }); + [this]() { + m_videoDevices.reset(createVideoDevices()); + }); return m_videoDevices.get(); } QPlatformCapturableWindows *QPlatformMediaIntegration::capturableWindows() { std::call_once(m_capturableWindowsOnceFlag, - [this]() { m_capturableWindows.reset(createCapturableWindows()); }); + [this]() { + m_capturableWindows.reset(createCapturableWindows()); + }); return m_capturableWindows.get(); } +QPlatformMediaDevices *QPlatformMediaIntegration::mediaDevices() +{ + std::call_once(m_mediaDevicesOnceFlag, [this] { + m_mediaDevices = createMediaDevices(); + }); + return m_mediaDevices.get(); +} + +// clang-format on + QPlatformMediaIntegration::QPlatformMediaIntegration() = default; QPlatformMediaIntegration::~QPlatformMediaIntegration() = default; QT_END_NAMESPACE + +#include "moc_qplatformmediaintegration_p.cpp" diff --git a/src/multimedia/platform/qplatformmediaintegration_p.h b/src/multimedia/platform/qplatformmediaintegration_p.h index 3f72c618b..4673c47b3 100644 --- a/src/multimedia/platform/qplatformmediaintegration_p.h +++ b/src/multimedia/platform/qplatformmediaintegration_p.h @@ -54,8 +54,9 @@ class QPlatformVideoDevices; class QCapturableWindow; class QPlatformCapturableWindows; -class Q_MULTIMEDIA_EXPORT QPlatformMediaIntegration +class Q_MULTIMEDIA_EXPORT QPlatformMediaIntegration : public QObject { + Q_OBJECT inline static const QString notAvailable = QStringLiteral("Not available"); public: static QPlatformMediaIntegration *instance(); @@ -93,6 +94,8 @@ public: QPlatformCapturableWindows *capturableWindows(); + QPlatformMediaDevices *mediaDevices(); + protected: virtual QPlatformMediaFormatInfo *createFormatInfo(); @@ -100,6 +103,8 @@ protected: virtual QPlatformCapturableWindows *createCapturableWindows() { return nullptr; } + virtual std::unique_ptr<QPlatformMediaDevices> createMediaDevices(); + private: std::unique_ptr<QPlatformVideoDevices> m_videoDevices; std::once_flag m_videoDevicesOnceFlag; @@ -109,6 +114,9 @@ private: mutable std::unique_ptr<QPlatformMediaFormatInfo> m_formatInfo; mutable std::once_flag m_formatInfoOnceFlg; + + std::unique_ptr<QPlatformMediaDevices> m_mediaDevices; + std::once_flag m_mediaDevicesOnceFlag; }; QT_END_NAMESPACE diff --git a/src/multimedia/platform/qplatformmediaplayer.cpp b/src/multimedia/platform/qplatformmediaplayer.cpp index 34c929b5a..ea22f94df 100644 --- a/src/multimedia/platform/qplatformmediaplayer.cpp +++ b/src/multimedia/platform/qplatformmediaplayer.cpp @@ -5,12 +5,13 @@ #include <private/qmediaplayer_p.h> #include "qmediaplayer.h" #include "qplatformmediadevices_p.h" +#include "qplatformmediaintegration_p.h" QT_BEGIN_NAMESPACE QPlatformMediaPlayer::QPlatformMediaPlayer(QMediaPlayer *parent) : player(parent) { - QPlatformMediaDevices::instance()->prepareAudio(); + QPlatformMediaIntegration::instance()->mediaDevices()->prepareAudio(); } QPlatformMediaPlayer::~QPlatformMediaPlayer() diff --git a/src/multimedia/qmediadevices.cpp b/src/multimedia/qmediadevices.cpp index fa6f8630e..1d77f4de8 100644 --- a/src/multimedia/qmediadevices.cpp +++ b/src/multimedia/qmediadevices.cpp @@ -126,7 +126,7 @@ QT_BEGIN_NAMESPACE */ QList<QAudioDevice> QMediaDevices::audioInputs() { - return QPlatformMediaDevices::instance()->audioInputs(); + return QPlatformMediaIntegration::instance()->mediaDevices()->audioInputs(); } /*! @@ -147,7 +147,7 @@ QList<QAudioDevice> QMediaDevices::audioInputs() */ QList<QAudioDevice> QMediaDevices::audioOutputs() { - return QPlatformMediaDevices::instance()->audioOutputs(); + return QPlatformMediaIntegration::instance()->mediaDevices()->audioOutputs(); } /*! @@ -162,7 +162,7 @@ QList<QAudioDevice> QMediaDevices::audioOutputs() */ QList<QCameraDevice> QMediaDevices::videoInputs() { - QPlatformMediaDevices::instance()->initVideoDevicesConnection(); + QPlatformMediaIntegration::instance()->mediaDevices()->initVideoDevicesConnection(); return QPlatformMediaIntegration::instance()->videoInputs(); } @@ -261,7 +261,7 @@ QCameraDevice QMediaDevices::defaultVideoInput() QMediaDevices::QMediaDevices(QObject *parent) : QObject(parent) { - auto platformDevices = QPlatformMediaDevices::instance(); + auto platformDevices = QPlatformMediaIntegration::instance()->mediaDevices(); connect(platformDevices, &QPlatformMediaDevices::videoInputsChanged, this, &QMediaDevices::videoInputsChanged); connect(platformDevices, &QPlatformMediaDevices::audioInputsChanged, this, @@ -278,7 +278,7 @@ QMediaDevices::~QMediaDevices() = default; void QMediaDevices::connectNotify(const QMetaMethod &signal) { if (signal == QMetaMethod::fromSignal(&QMediaDevices::videoInputsChanged)) - QPlatformMediaDevices::instance()->initVideoDevicesConnection(); + QPlatformMediaIntegration::instance()->mediaDevices()->initVideoDevicesConnection(); QObject::connectNotify(signal); } diff --git a/src/multimedia/wasm/qwasmmediadevices.cpp b/src/multimedia/wasm/qwasmmediadevices.cpp index e985654ac..4e59fd161 100644 --- a/src/multimedia/wasm/qwasmmediadevices.cpp +++ b/src/multimedia/wasm/qwasmmediadevices.cpp @@ -3,7 +3,7 @@ #include "qwasmmediadevices_p.h" #include "private/qcameradevice_p.h" - +#include "private/qplatformmediaintegration_p.h" #include "qwasmaudiosource_p.h" #include "qwasmaudiosink_p.h" #include "qwasmaudiodevice_p.h" @@ -20,7 +20,7 @@ Q_LOGGING_CATEGORY(qWasmMediaDevices, "qt.multimedia.wasm.mediadevices") QWasmCameraDevices::QWasmCameraDevices(QPlatformMediaIntegration *integration) : QPlatformVideoDevices(integration) { - m_mediaDevices = QPlatformMediaDevices::instance(); + m_mediaDevices = QPlatformMediaIntegration::instance()->mediaDevices(); } QList<QCameraDevice> QWasmCameraDevices::videoDevices() const diff --git a/src/plugins/multimedia/wasm/mediacapture/qwasmmediacapturesession.cpp b/src/plugins/multimedia/wasm/mediacapture/qwasmmediacapturesession.cpp index 975c0182d..826650570 100644 --- a/src/plugins/multimedia/wasm/mediacapture/qwasmmediacapturesession.cpp +++ b/src/plugins/multimedia/wasm/mediacapture/qwasmmediacapturesession.cpp @@ -6,13 +6,14 @@ #include "qwasmcamera_p.h" #include <private/qplatformmediadevices_p.h> +#include <private/qplatformmediaintegration_p.h> #include <private/qwasmmediadevices_p.h> Q_LOGGING_CATEGORY(qWasmMediaCaptureSession, "qt.multimedia.wasm.capturesession") QWasmMediaCaptureSession::QWasmMediaCaptureSession() { - QWasmMediaDevices *wasmMediaDevices = static_cast<QWasmMediaDevices *>(QPlatformMediaDevices::instance()); + QWasmMediaDevices *wasmMediaDevices = static_cast<QWasmMediaDevices *>(QPlatformMediaIntegration::instance()->mediaDevices()); wasmMediaDevices->initDevices(); } diff --git a/src/plugins/multimedia/wasm/mediacapture/qwasmmediarecorder.cpp b/src/plugins/multimedia/wasm/mediacapture/qwasmmediarecorder.cpp index 8bfd7bfae..98d0d860b 100644 --- a/src/plugins/multimedia/wasm/mediacapture/qwasmmediarecorder.cpp +++ b/src/plugins/multimedia/wasm/mediacapture/qwasmmediarecorder.cpp @@ -4,6 +4,7 @@ #include "qwasmmediarecorder_p.h" #include "qwasmmediacapturesession_p.h" #include <private/qplatformmediadevices_p.h> +#include <private/qplatformmediaintegration_p.h> #include "qwasmcamera_p.h" #include "qwasmaudioinput_p.h" @@ -21,7 +22,7 @@ QWasmMediaRecorder::QWasmMediaRecorder(QMediaRecorder *parent) : QPlatformMediaRecorder(parent) { m_durationTimer.reset(new QElapsedTimer()); - QPlatformMediaDevices::instance(); // initialize getUserMedia + QPlatformMediaIntegration::instance()->mediaDevices(); // initialize getUserMedia } QWasmMediaRecorder::~QWasmMediaRecorder() diff --git a/src/plugins/multimedia/windows/qwindowsintegration_p.h b/src/plugins/multimedia/windows/qwindowsintegration_p.h index 5b355eb1d..29498fa42 100644 --- a/src/plugins/multimedia/windows/qwindowsintegration_p.h +++ b/src/plugins/multimedia/windows/qwindowsintegration_p.h @@ -25,6 +25,7 @@ class QWindowsFormatInfo; class QWindowsMediaIntegration : public QPlatformMediaIntegration { + Q_OBJECT public: QWindowsMediaIntegration(); ~QWindowsMediaIntegration(); diff --git a/tests/auto/unit/mockbackend/qmockintegration.cpp b/tests/auto/unit/mockbackend/qmockintegration.cpp index 68f44ce2b..f79cd5b9e 100644 --- a/tests/auto/unit/mockbackend/qmockintegration.cpp +++ b/tests/auto/unit/mockbackend/qmockintegration.cpp @@ -14,6 +14,8 @@ #include <private/qcameradevice_p.h> #include <private/qplatformvideodevices_p.h> +#include "qmockmediadevices.h" + QT_BEGIN_NAMESPACE class MockMultimediaPlugin : public QPlatformMediaPlugin @@ -102,6 +104,11 @@ 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) diff --git a/tests/auto/unit/mockbackend/qmockintegration.h b/tests/auto/unit/mockbackend/qmockintegration.h index af9d0577e..fc9f661c0 100644 --- a/tests/auto/unit/mockbackend/qmockintegration.h +++ b/tests/auto/unit/mockbackend/qmockintegration.h @@ -69,6 +69,7 @@ public: protected: QPlatformVideoDevices *createVideoDevices() override; + std::unique_ptr<QPlatformMediaDevices> createMediaDevices() override; private: diff --git a/tests/auto/unit/mockbackend/qmockmediadevices.cpp b/tests/auto/unit/mockbackend/qmockmediadevices.cpp index 5ce18d8b7..4d1c23854 100644 --- a/tests/auto/unit/mockbackend/qmockmediadevices.cpp +++ b/tests/auto/unit/mockbackend/qmockmediadevices.cpp @@ -9,7 +9,6 @@ QT_BEGIN_NAMESPACE QMockMediaDevices::QMockMediaDevices() : QPlatformMediaDevices() { - setDevices(this); } QMockMediaDevices::~QMockMediaDevices() = default; diff --git a/tests/auto/unit/multimedia/qmediadevices/tst_qmediadevices.cpp b/tests/auto/unit/multimedia/qmediadevices/tst_qmediadevices.cpp index 54788fe51..85f52482c 100644 --- a/tests/auto/unit/multimedia/qmediadevices/tst_qmediadevices.cpp +++ b/tests/auto/unit/multimedia/qmediadevices/tst_qmediadevices.cpp @@ -7,7 +7,6 @@ #include <qmediadevices.h> #include "qmockintegration.h" -#include "qmockmediadevices.h" QT_USE_NAMESPACE @@ -23,9 +22,6 @@ public slots: private slots: void videoInputsChangedEmitted_whenCamerasChanged(); void onlyVideoInputsChangedEmitted_when2MediaDevicesCreated_andCamerasChanged(); - -private: - QMockMediaDevices devices; }; void tst_QMediaDevices::initTestCase() { } |