summaryrefslogtreecommitdiffstats
path: root/src/multimedia/platform/qplatformmediaintegration.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/multimedia/platform/qplatformmediaintegration.cpp')
-rw-r--r--src/multimedia/platform/qplatformmediaintegration.cpp276
1 files changed, 181 insertions, 95 deletions
diff --git a/src/multimedia/platform/qplatformmediaintegration.cpp b/src/multimedia/platform/qplatformmediaintegration.cpp
index c3b4f1444..dda00de61 100644
--- a/src/multimedia/platform/qplatformmediaintegration.cpp
+++ b/src/multimedia/platform/qplatformmediaintegration.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qtmultimediaglobal_p.h>
#include "qplatformmediaintegration_p.h"
@@ -43,88 +7,210 @@
#include <qmutex.h>
#include <qplatformaudioinput_p.h>
#include <qplatformaudiooutput_p.h>
+#include <qplatformaudioresampler_p.h>
+#include <qplatformvideodevices_p.h>
+#include <qmediadevices.h>
+#include <qcameradevice.h>
+#include <qloggingcategory.h>
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qapplicationstatic.h>
-#if QT_CONFIG(gstreamer)
-#include <private/qgstreamerintegration_p.h>
-using PlatformIntegration = QGstreamerIntegration;
-#elif QT_CONFIG(pulseaudio)
-#include <private/qpulseaudiointegration_p.h>
-using PlatformIntegration = QPulseAudioIntegration;
-#elif QT_CONFIG(alsa)
-#include <private/qalsaintegration_p.h>
-using PlatformIntegration = QAlsaIntegration;
-#elif QT_CONFIG(avfoundation)
-#include <private/qdarwinintegration_p.h>
-using PlatformIntegration = QDarwinIntegration;
-#elif QT_CONFIG(wmf)
-#include <private/qwindowsintegration_p.h>
-using PlatformIntegration = QWindowsMediaIntegration;
-#elif defined(Q_OS_ANDROID)
-#include <private/qandroidintegration_p.h>
-using PlatformIntegration = QAndroidIntegration;
-#elif defined(Q_OS_WASM)
-#include <private/qwasmmediaintegration_p.h>
-using PlatformIntegration = QWasmMediaIntegration;
-#else
-class QDummyIntegration : public QPlatformMediaIntegration
+#include "qplatformcapturablewindows_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"
+
+namespace {
+
+class QFallbackIntegration : public QPlatformMediaIntegration
{
public:
- QDummyIntegration() { qFatal("QtMultimedia is not currently supported on this platform or compiler."); }
- QPlatformMediaDevices *devices() override { return nullptr; }
- QPlatformMediaFormatInfo *formatInfo() override { return nullptr; }
+ QFallbackIntegration() : QPlatformMediaIntegration(QLatin1String("fallback"))
+ {
+ qWarning("No QtMultimedia backends found. Only QMediaDevices, QAudioDevice, QSoundEffect, QAudioSink, and QAudioSource are available.");
+ }
};
-using PlatformIntegration = QDummyIntegration;
+
+static Q_LOGGING_CATEGORY(qLcMediaPlugin, "qt.multimedia.plugin")
+
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
+ (QPlatformMediaPlugin_iid,
+ QLatin1String("/multimedia")))
+
+static const auto FFmpegBackend = QStringLiteral("ffmpeg");
+
+static QString defaultBackend(const QStringList &backends)
+{
+#ifdef QT_DEFAULT_MEDIA_BACKEND
+ auto backend = QString::fromUtf8(QT_DEFAULT_MEDIA_BACKEND);
+ if (backends.contains(backend))
+ return backend;
#endif
-QT_BEGIN_NAMESPACE
+#if defined(Q_OS_DARWIN) || defined(Q_OS_LINUX) || defined(Q_OS_WINDOWS) || defined(Q_OS_ANDROID)
+ // Return ffmpeg backend by default.
+ // Platform backends for the OS list are optionally available but have limited support.
+ if (backends.contains(FFmpegBackend))
+ return FFmpegBackend;
+#else
+ // Return platform backend (non-ffmpeg) by default.
+ if (backends.size() > 1 && backends[0] == FFmpegBackend)
+ return backends[1];
+#endif
-namespace {
-struct Holder {
- ~Holder()
+ return backends[0];
+}
+
+struct InstanceHolder
+{
+ InstanceHolder()
{
- QMutexLocker locker(&mutex);
- delete nativeInstance;
- nativeInstance = nullptr;
- instance = nullptr;
+ if (!QCoreApplication::instance())
+ qCCritical(qLcMediaPlugin()) << "Qt Multimedia requires a QCoreApplication instance";
+
+ const QStringList backends = QPlatformMediaIntegration::availableBackends();
+ QString backend = QString::fromUtf8(qgetenv("QT_MEDIA_BACKEND"));
+ if (backend.isEmpty() && !backends.isEmpty())
+ backend = defaultBackend(backends);
+
+ qCDebug(qLcMediaPlugin) << "Loading media backend" << backend;
+ instance.reset(
+ qLoadPlugin<QPlatformMediaIntegration, QPlatformMediaPlugin>(loader(), backend));
+
+ if (!instance) {
+ // No backends found. Use fallback to support basic functionality
+ instance = std::make_unique<QFallbackIntegration>();
+ }
}
- QBasicMutex mutex;
- QPlatformMediaIntegration *instance = nullptr;
- QAtomicPointer<QPlatformMediaIntegration> nativeInstance = nullptr;
-} holder;
-}
+ ~InstanceHolder()
+ {
+ instance.reset();
+ qCDebug(qLcMediaPlugin) << "Released media backend";
+ }
+
+ std::unique_ptr<QPlatformMediaIntegration> instance;
+};
+
+Q_APPLICATION_STATIC(InstanceHolder, s_instanceHolder);
+
+} // namespace
+
+QT_BEGIN_NAMESPACE
QPlatformMediaIntegration *QPlatformMediaIntegration::instance()
{
- if (!holder.nativeInstance.loadRelaxed()) {
- QMutexLocker locker(&holder.mutex);
- if (!holder.nativeInstance.loadAcquire())
- holder.nativeInstance.storeRelease(new PlatformIntegration);
- }
- if (!holder.instance)
- holder.instance = holder.nativeInstance.loadRelaxed();
- return holder.instance;
+ return s_instanceHolder->instance.get();
}
-/*
- This API is there to be able to test with a mock backend.
-*/
-void QPlatformMediaIntegration::setIntegration(QPlatformMediaIntegration *integration)
+QList<QCameraDevice> QPlatformMediaIntegration::videoInputs()
{
- holder.instance = integration;
+ auto devices = videoDevices();
+ return devices ? devices->videoDevices() : QList<QCameraDevice>{};
}
-QPlatformAudioInput *QPlatformMediaIntegration::createAudioInput(QAudioInput *q)
+QMaybe<std::unique_ptr<QPlatformAudioResampler>>
+QPlatformMediaIntegration::createAudioResampler(const QAudioFormat &, const QAudioFormat &)
+{
+ return notAvailable;
+}
+
+QMaybe<QPlatformAudioInput *> QPlatformMediaIntegration::createAudioInput(QAudioInput *q)
{
return new QPlatformAudioInput(q);
}
-QPlatformAudioOutput *QPlatformMediaIntegration::createAudioOutput(QAudioOutput *q)
+QMaybe<QPlatformAudioOutput *> QPlatformMediaIntegration::createAudioOutput(QAudioOutput *q)
{
return new QPlatformAudioOutput(q);
}
-QPlatformMediaIntegration::~QPlatformMediaIntegration()
-= default;
+QList<QCapturableWindow> QPlatformMediaIntegration::capturableWindowsList()
+{
+ const auto capturableWindows = this->capturableWindows();
+ return capturableWindows ? capturableWindows->windows() : QList<QCapturableWindow>{};
+}
+
+bool QPlatformMediaIntegration::isCapturableWindowValid(const QCapturableWindowPrivate &window)
+{
+ const auto capturableWindows = this->capturableWindows();
+ return capturableWindows && capturableWindows->isWindowValid(window);
+}
+
+const QPlatformMediaFormatInfo *QPlatformMediaIntegration::formatInfo()
+{
+ std::call_once(m_formatInfoOnceFlg, [this]() {
+ m_formatInfo.reset(createFormatInfo());
+ Q_ASSERT(m_formatInfo);
+ });
+ return m_formatInfo.get();
+}
+
+QPlatformMediaFormatInfo *QPlatformMediaIntegration::createFormatInfo()
+{
+ return new QPlatformMediaFormatInfo;
+}
+
+std::unique_ptr<QPlatformMediaDevices> QPlatformMediaIntegration::createMediaDevices()
+{
+ return QPlatformMediaDevices::create();
+}
+
+// clang-format off
+QPlatformVideoDevices *QPlatformMediaIntegration::videoDevices()
+{
+ std::call_once(m_videoDevicesOnceFlag,
+ [this]() {
+ m_videoDevices.reset(createVideoDevices());
+ });
+ return m_videoDevices.get();
+}
+
+QPlatformCapturableWindows *QPlatformMediaIntegration::capturableWindows()
+{
+ std::call_once(m_capturableWindowsOnceFlag,
+ [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
+
+QStringList QPlatformMediaIntegration::availableBackends()
+{
+ QStringList list;
+
+ if (QFactoryLoader *fl = loader()) {
+ const auto keyMap = fl->keyMap();
+ for (auto it = keyMap.constBegin(); it != keyMap.constEnd(); ++it)
+ if (!list.contains(it.value()))
+ list << it.value();
+ }
+
+ qCDebug(qLcMediaPlugin) << "Available backends" << list;
+ return list;
+}
+
+QLatin1String QPlatformMediaIntegration::name()
+{
+ return m_backendName;
+}
+
+QPlatformMediaIntegration::QPlatformMediaIntegration(QLatin1String name) : m_backendName(name) { }
+
+QPlatformMediaIntegration::~QPlatformMediaIntegration() = default;
QT_END_NAMESPACE
+
+#include "moc_qplatformmediaintegration_p.cpp"