6#include <QtMultimedia/private/qplatformaudiodevices_p.h>
7#include <QtMultimedia/private/qplatformaudioinput_p.h>
8#include <QtMultimedia/private/qplatformaudiooutput_p.h>
9#include <QtMultimedia/private/qplatformaudioresampler_p.h>
10#include <QtMultimedia/private/qplatformcapturablewindows_p.h>
11#include <QtMultimedia/private/qplatformmediaformatinfo_p.h>
12#include <QtMultimedia/private/qplatformmediaplugin_p.h>
13#include <QtMultimedia/private/qplatformvideodevices_p.h>
14#include <QtMultimedia/private/qtmultimediaglobal_p.h>
15#include <QtMultimedia/qcameradevice.h>
16#include <QtMultimedia/qmediadevices.h>
17#include <QtGui/qwindow.h>
18#include <QtCore/private/qcoreapplication_p.h>
19#include <QtCore/private/qfactoryloader_p.h>
20#include <QtCore/qapplicationstatic.h>
21#include <QtCore/qatomic.h>
22#include <QtCore/qcoreapplication.h>
23#include <QtCore/qloggingcategory.h>
24#include <QtCore/qmutex.h>
28class QFallbackIntegration :
public QPlatformMediaIntegration
31 QFallbackIntegration() : QPlatformMediaIntegration(QLatin1String(
"fallback"))
33 qWarning(
"No QtMultimedia backends found. Only QMediaDevices, QAudioDevice, QSoundEffect, QAudioSink, and QAudioSource are available.");
37Q_STATIC_LOGGING_CATEGORY(qLcMediaPlugin,
"qt.multimedia.plugin")
39Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
40 (QPlatformMediaPlugin_iid,
41 QLatin1String(
"/multimedia")))
43static const auto FFmpegBackend = QStringLiteral(
"ffmpeg");
45static QString defaultBackend(
const QStringList &backends)
47#ifdef QT_DEFAULT_MEDIA_BACKEND
48 auto backend = QString::fromUtf8(QT_DEFAULT_MEDIA_BACKEND);
49 if (backends.contains(backend))
53#if defined(Q_OS_DARWIN) || defined(Q_OS_LINUX) || defined(Q_OS_WINDOWS) || defined(Q_OS_ANDROID)
56 if (backends.contains(FFmpegBackend))
60 if (backends.size() > 1 && backends[0] == FFmpegBackend)
76 if (!QCoreApplication::instance())
77 qCCritical(qLcMediaPlugin()) <<
"Qt Multimedia requires a QCoreApplication instance";
79 QStringList backends = QPlatformMediaIntegration::availableBackends();
80 QString backend = QString::fromUtf8(qgetenv(
"QT_MEDIA_BACKEND")).toLower();
81 if (backend.isEmpty() && !backends.isEmpty())
82 backend = defaultBackend(backends);
84 qCDebug(qLcMediaPlugin) <<
"Loading media backend" << backend;
86 qLoadPlugin<QPlatformMediaIntegration, QPlatformMediaPlugin>(loader(), backend));
91 backends.removeAll(backend);
93 for (
const QString &backend : std::as_const(backends)) {
94 qCDebug(qLcMediaPlugin) <<
"Loading alternative backend" << backend;
95 instance.reset(qLoadPlugin<QPlatformMediaIntegration, QPlatformMediaPlugin>(loader(),
102 instance = std::make_unique<QFallbackIntegration>();
108 qCDebug(qLcMediaPlugin) <<
"Released media backend";
111 std::unique_ptr<QPlatformMediaIntegration> instance;
114Q_APPLICATION_STATIC(InstanceHolder, s_instanceHolder);
122 return s_instanceHolder->instance.get();
125void QPlatformMediaIntegration::resetInstance()
127 s_instanceHolder->init();
130q23::expected<std::unique_ptr<QPlatformAudioResampler>, QString>
131QPlatformMediaIntegration::createAudioResampler(
const QAudioFormat &,
const QAudioFormat &)
133 return q23::unexpected(notAvailable);
136q23::expected<QPlatformAudioInput *, QString> QPlatformMediaIntegration::createAudioInput(QAudioInput *q)
138 return new QPlatformAudioInput(q);
141q23::expected<QPlatformAudioOutput *, QString> QPlatformMediaIntegration::createAudioOutput(QAudioOutput *q)
143 return new QPlatformAudioOutput(q);
146QList<QCapturableWindow> QPlatformMediaIntegration::capturableWindowsList()
148 const auto capturableWindows =
this->capturableWindows();
149 return capturableWindows ? capturableWindows->windows() : QList<QCapturableWindow>{};
152bool QPlatformMediaIntegration::isCapturableWindowValid(
const QCapturableWindowPrivate &window)
154 const auto capturableWindows =
this->capturableWindows();
155 return capturableWindows && capturableWindows->isWindowValid(window);
158q23::expected<QCapturableWindow, QString> QPlatformMediaIntegration::capturableWindowFromQWindow(QWindow *window)
160 const auto capturableWindows =
this->capturableWindows();
161 if (!capturableWindows)
162 return q23::unexpected{ QStringLiteral(
"No windowcapture platform implementation") };
163 if (window ==
nullptr)
164 return q23::unexpected{ QStringLiteral(
"QWindow is nullptr") };
165 if (!window->isTopLevel())
166 return q23::unexpected{ QStringLiteral(
"QWindow is not top-level.") };
167 return capturableWindows->fromQWindow(window);
170const QPlatformMediaFormatInfo *QPlatformMediaIntegration::formatInfo()
172 std::call_once(m_formatInfoOnceFlg, [
this]() {
173 m_formatInfo.reset(createFormatInfo());
174 Q_ASSERT(m_formatInfo);
176 return m_formatInfo.get();
179QPlatformMediaFormatInfo *QPlatformMediaIntegration::createFormatInfo()
181 return new QPlatformMediaFormatInfo;
184std::unique_ptr<QPlatformAudioDevices> QPlatformMediaIntegration::createAudioDevices()
186 return QPlatformAudioDevices::create();
190QPlatformVideoDevices *QPlatformMediaIntegration::videoDevices()
192 std::call_once(m_videoDevicesOnceFlag,
194 m_videoDevices.reset(createVideoDevices());
196 return m_videoDevices.get();
199QPlatformCapturableWindows *QPlatformMediaIntegration::capturableWindows()
201 std::call_once(m_capturableWindowsOnceFlag,
203 m_capturableWindows.reset(createCapturableWindows());
205 return m_capturableWindows.get();
208QPlatformAudioDevices *QPlatformMediaIntegration::audioDevices()
210 std::call_once(m_audioDevicesOnceFlag, [
this] {
211 m_audioDevices = createAudioDevices();
213 return m_audioDevices.get();
218QStringList QPlatformMediaIntegration::availableBackends()
222 if (QFactoryLoader *fl = loader()) {
223 const auto keyMap = fl->keyMap();
224 for (
auto it = keyMap.constBegin(); it != keyMap.constEnd(); ++it)
225 if (!list.contains(it.value()))
229 qCDebug(qLcMediaPlugin) <<
"Available backends" << list;
233QLatin1String QPlatformMediaIntegration::name()
235 return m_backendName;
238QVideoFrame QPlatformMediaIntegration::convertVideoFrame(QVideoFrame &,
239 const QVideoFrameFormat &)
244QLatin1String QPlatformMediaIntegration::audioBackendName()
246 return QPlatformMediaIntegration::instance()->audioDevices()->backendName();
249QPlatformMediaIntegration::QPlatformMediaIntegration(QLatin1String name) : m_backendName(name) { }
251QPlatformMediaIntegration::~QPlatformMediaIntegration() =
default;
255#include "moc_qplatformmediaintegration_p.cpp"