6#include <QtCore/qapplicationstatic.h>
7#include <QtCore/qatomic.h>
8#include <QtCore/qcoreapplication.h>
9#include <QtCore/qloggingcategory.h>
10#include <QtCore/qmutex.h>
11#include <QtCore/private/qcoreapplication_p.h>
12#include <QtCore/private/qfactoryloader_p.h>
14#include <QtGui/qwindow.h>
16#include <QtMultimedia/qcameradevice.h>
17#include <QtMultimedia/qmediadevices.h>
18#include <QtMultimedia/private/qplatformaudiodevices_p.h>
19#include <QtMultimedia/private/qplatformaudioinput_p.h>
20#include <QtMultimedia/private/qplatformaudiooutput_p.h>
21#include <QtMultimedia/private/qplatformaudioresampler_p.h>
22#include <QtMultimedia/private/qplatformcapturablewindows_p.h>
23#include <QtMultimedia/private/qplatformmediaformatinfo_p.h>
24#include <QtMultimedia/private/qplatformmediaplugin_p.h>
25#include <QtMultimedia/private/qplatformvideodevices_p.h>
26#include <QtMultimedia/private/qtmultimediaglobal_p.h>
30class QFallbackIntegration :
public QPlatformMediaIntegration
33 QFallbackIntegration() : QPlatformMediaIntegration(QLatin1String(
"fallback"))
35 qWarning(
"No QtMultimedia backends found. Only QMediaDevices, QAudioDevice, QSoundEffect, QAudioSink, and QAudioSource are available.");
39Q_STATIC_LOGGING_CATEGORY(qLcMediaPlugin,
"qt.multimedia.plugin")
41Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
42 (QPlatformMediaPlugin_iid,
43 QLatin1String(
"/multimedia")))
45static const auto FFmpegBackend = QStringLiteral(
"ffmpeg");
47static QString defaultBackend(
const QStringList &backends)
49#ifdef QT_DEFAULT_MEDIA_BACKEND
50 auto backend = QString::fromUtf8(QT_DEFAULT_MEDIA_BACKEND);
51 if (backends.contains(backend))
55#if defined(Q_OS_DARWIN) || defined(Q_OS_LINUX) || defined(Q_OS_WINDOWS) || defined(Q_OS_ANDROID)
58 if (backends.contains(FFmpegBackend))
62 if (backends.size() > 1 && backends[0] == FFmpegBackend)
78 if (!QCoreApplication::instance())
79 qCCritical(qLcMediaPlugin()) <<
"Qt Multimedia requires a QCoreApplication instance";
81 QStringList backends = QPlatformMediaIntegration::availableBackends();
82 QString backend = QString::fromUtf8(qgetenv(
"QT_MEDIA_BACKEND")).toLower();
83 if (backend.isEmpty() && !backends.isEmpty())
84 backend = defaultBackend(backends);
86 qCDebug(qLcMediaPlugin) <<
"Loading media backend" << backend;
88 qLoadPlugin<QPlatformMediaIntegration, QPlatformMediaPlugin>(loader(), backend));
93 backends.removeAll(backend);
95 for (
const QString &backend : std::as_const(backends)) {
96 qCDebug(qLcMediaPlugin) <<
"Loading alternative backend" << backend;
97 instance.reset(qLoadPlugin<QPlatformMediaIntegration, QPlatformMediaPlugin>(loader(),
104 instance = std::make_unique<QFallbackIntegration>();
110 qCDebug(qLcMediaPlugin) <<
"Released media backend";
113 std::unique_ptr<QPlatformMediaIntegration> instance;
116Q_APPLICATION_STATIC(InstanceHolder, s_instanceHolder);
124 return s_instanceHolder->instance.get();
127void QPlatformMediaIntegration::resetInstance()
129 s_instanceHolder->init();
132q23::expected<std::unique_ptr<QPlatformAudioResampler>, QString>
133QPlatformMediaIntegration::createAudioResampler(
const QAudioFormat &,
const QAudioFormat &)
135 return q23::unexpected(notAvailable);
138q23::expected<QPlatformAudioInput *, QString> QPlatformMediaIntegration::createAudioInput(QAudioInput *q)
140 return new QPlatformAudioInput(q);
143q23::expected<QPlatformAudioOutput *, QString> QPlatformMediaIntegration::createAudioOutput(QAudioOutput *q)
145 return new QPlatformAudioOutput(q);
148QList<QCapturableWindow> QPlatformMediaIntegration::capturableWindowsList()
150 const auto capturableWindows =
this->capturableWindows();
151 return capturableWindows ? capturableWindows->windows() : QList<QCapturableWindow>{};
154bool QPlatformMediaIntegration::isCapturableWindowValid(
const QCapturableWindowPrivate &window)
156 const auto capturableWindows =
this->capturableWindows();
157 return capturableWindows && capturableWindows->isWindowValid(window);
160q23::expected<QCapturableWindow, QString> QPlatformMediaIntegration::capturableWindowFromQWindow(QWindow *window)
162 const auto capturableWindows =
this->capturableWindows();
163 if (!capturableWindows)
164 return q23::unexpected{ QStringLiteral(
"No windowcapture platform implementation") };
165 if (window ==
nullptr)
166 return q23::unexpected{ QStringLiteral(
"QWindow is nullptr") };
167 if (!window->isTopLevel())
168 return q23::unexpected{ QStringLiteral(
"QWindow is not top-level.") };
169 return capturableWindows->fromQWindow(window);
172const QPlatformMediaFormatInfo *QPlatformMediaIntegration::formatInfo()
174 std::call_once(m_formatInfoOnceFlg, [
this]() {
175 m_formatInfo.reset(createFormatInfo());
176 Q_ASSERT(m_formatInfo);
178 return m_formatInfo.get();
181QPlatformMediaFormatInfo *QPlatformMediaIntegration::createFormatInfo()
183 return new QPlatformMediaFormatInfo;
186std::unique_ptr<QPlatformAudioDevices> QPlatformMediaIntegration::createAudioDevices()
188 return QPlatformAudioDevices::create();
192QPlatformVideoDevices *QPlatformMediaIntegration::videoDevices()
194 std::call_once(m_videoDevicesOnceFlag,
196 m_videoDevices.reset(createVideoDevices());
198 return m_videoDevices.get();
201QPlatformCapturableWindows *QPlatformMediaIntegration::capturableWindows()
203 std::call_once(m_capturableWindowsOnceFlag,
205 m_capturableWindows.reset(createCapturableWindows());
207 return m_capturableWindows.get();
210QPlatformAudioDevices *QPlatformMediaIntegration::audioDevices()
212 std::call_once(m_audioDevicesOnceFlag, [
this] {
213 m_audioDevices = createAudioDevices();
215 return m_audioDevices.get();
220QStringList QPlatformMediaIntegration::availableBackends()
224 if (QFactoryLoader *fl = loader()) {
225 const auto keyMap = fl->keyMap();
226 for (
auto it = keyMap.constBegin(); it != keyMap.constEnd(); ++it)
227 if (!list.contains(it.value()))
231 qCDebug(qLcMediaPlugin) <<
"Available backends" << list;
235QLatin1String QPlatformMediaIntegration::name()
237 return m_backendName;
240QVideoFrame QPlatformMediaIntegration::convertVideoFrame(QVideoFrame &,
241 const QVideoFrameFormat &)
246QLatin1String QPlatformMediaIntegration::audioBackendName()
248 return QPlatformMediaIntegration::instance()->audioDevices()->backendName();
251QPlatformMediaIntegration::QPlatformMediaIntegration(QLatin1String name) : m_backendName(name) { }
253QPlatformMediaIntegration::~QPlatformMediaIntegration() =
default;
257#include "moc_qplatformmediaintegration_p.cpp"