4#include <QtFFmpegMediaPluginImpl/private/qffmpegmediaintegration_p.h>
6#include <QtFFmpegMediaPluginImpl/private/qffmpegaudiodecoder_p.h>
7#include <QtFFmpegMediaPluginImpl/private/qffmpegaudioinput_p.h>
8#include <QtFFmpegMediaPluginImpl/private/qffmpegconverter_p.h>
9#include <QtFFmpegMediaPluginImpl/private/qffmpegimagecapture_p.h>
10#include <QtFFmpegMediaPluginImpl/private/qffmpegmediacapturesession_p.h>
11#include <QtFFmpegMediaPluginImpl/private/qffmpegmediaformatinfo_p.h>
12#include <QtFFmpegMediaPluginImpl/private/qffmpegmediaplayer_p.h>
13#include <QtFFmpegMediaPluginImpl/private/qffmpegmediarecorder_p.h>
14#include <QtFFmpegMediaPluginImpl/private/qffmpegresampler_p.h>
15#include <QtFFmpegMediaPluginImpl/private/qffmpegvideosink_p.h>
16#include <QtFFmpegMediaPluginImpl/private/qgrabwindowsurfacecapture_p.h>
18#include <QtMultimedia/private/qplatformmediaplugin_p.h>
19#include <QtMultimedia/qcameradevice.h>
22#include <QtFFmpegMediaPluginImpl/private/qffmpegdarwinintegrationfactory_p.h>
23#include <QtMultimedia/private/qdarwinintegrationfactory_p.h>
27# include <QtMultimedia/private/qwindowsresampler_p.h>
28# include <QtMultimedia/private/qwindowsvideodevices_p.h>
29# include "qwindowscamera_p.h"
30# include "qffmpegscreencapture_dxgi_p.h"
31# include "qwincapturablewindows_p.h"
32# include "qgdiwindowcapture_p.h"
36#include <QtFFmpegMediaPluginImpl/private/qandroidcamera_p.h>
37#include <QtFFmpegMediaPluginImpl/private/qandroidimagecapture_p.h>
38#include <QtFFmpegMediaPluginImpl/private/qandroidscreencapture_p.h>
39#include <QtFFmpegMediaPluginImpl/private/qandroidvideodevices_p.h>
42# include <libavutil/log.h>
43# include <libavcodec/jni.h>
47#if QT_CONFIG(linux_v4l)
48#include "qv4l2camera_p.h"
49#include "qv4l2cameradevices_p.h"
52#if QT_CONFIG(cpp_winrt)
53#include "qffmpegwindowcapture_uwp_p.h"
57#include "qx11surfacecapture_p.h"
58#include "qx11capturablewindows_p.h"
61#if QT_CONFIG(pipewire_screencapture)
62# include <QtMultimedia/private/qpipewire_screencapture_p.h>
66#include "qeglfsscreencapture_p.h"
69#include <QtCore/qloggingcategory.h>
84 return av_log_default_callback(ptr, level, fmt, vl);
87 if (level < 0 || level > av_log_get_level())
90 QString message = QStringLiteral(
"FFmpeg log: %1").arg(QString::vasprintf(fmt, vl));
91 if (message.endsWith(u"\n"))
94 if (level == AV_LOG_DEBUG || level == AV_LOG_TRACE)
96 else if (level == AV_LOG_VERBOSE || level == AV_LOG_INFO)
98 else if (level == AV_LOG_WARNING)
99 qWarning() << message;
100 else if (level == AV_LOG_ERROR || level == AV_LOG_FATAL || level == AV_LOG_PANIC)
101 qCritical() << message;
106 if (qEnvironmentVariableIsSet(
"QT_FFMPEG_DEBUG")) {
107 av_log_set_level(AV_LOG_DEBUG);
111 av_log_set_callback(&qffmpegLogCallback);
116 if (backend == u"grabwindow")
117 return new QGrabWindowSurfaceCapture(QPlatformSurfaceCapture::ScreenSource{});
120 if (backend == u"eglfs")
121 return new QEglfsScreenCapture;
124#if QT_CONFIG(pipewire_screencapture)
125 if (backend == u"pipewire") {
126 if (
auto capture = QtPipeWire::QPipeWireCapture::create())
127 return capture.release();
132 if (backend == u"x11")
133 return new QX11SurfaceCapture(QPlatformSurfaceCapture::ScreenSource{});
134#elif defined(Q_OS_WINDOWS)
135 if (backend == u"dxgi")
136 return new QFFmpegScreenCaptureDxgi;
137#elif defined(Q_OS_MACOS)
138 if (backend == u"avf")
139 return QFFmpeg::makeQSckScreenCapture().release();
146 if (backend == u"grabwindow")
147 return new QGrabWindowSurfaceCapture(QPlatformSurfaceCapture::WindowSource{});
150 if (backend == u"x11")
151 return new QX11SurfaceCapture(QPlatformSurfaceCapture::WindowSource{});
152#elif defined(Q_OS_WINDOWS)
153 if (backend == u"gdi")
154 return new QGdiWindowCapture;
155#if QT_CONFIG(cpp_winrt)
156 if (backend == u"uwp")
157 return new QFFmpegWindowCaptureUwp;
159#elif defined(Q_OS_MACOS)
160 if (backend == u"cg")
161 return QFFmpeg::makeQSckWindowCapture().release();
166QFFmpegMediaIntegration::QFFmpegMediaIntegration()
167 : QPlatformMediaIntegration(QLatin1String(
"ffmpeg"))
171 qCInfo(qLcFFmpeg) <<
"Using Qt multimedia with FFmpeg version" << av_version_info()
174 qCDebug(qLcFFmpeg) <<
"Available HW decoding frameworks:";
175 for (
auto type : QFFmpeg::HWAccel::decodingDeviceTypes())
176 qCDebug(qLcFFmpeg) <<
" " << type;
178 qCDebug(qLcFFmpeg) <<
"Available HW encoding frameworks:";
179 for (
auto type : QFFmpeg::HWAccel::encodingDeviceTypes())
180 qCDebug(qLcFFmpeg) <<
" " << type;
183q23::expected<QPlatformAudioDecoder *, QString>
184QFFmpegMediaIntegration::createAudioDecoder(QAudioDecoder *decoder)
186 return new QFFmpegAudioDecoder(decoder);
189q23::expected<std::unique_ptr<QPlatformAudioResampler>, QString>
190QFFmpegMediaIntegration::createAudioResampler(
const QAudioFormat &inputFormat,
191 const QAudioFormat &outputFormat)
193 auto ffmpegResampler = QFFmpegResampler::createFromInputFormat(inputFormat, outputFormat);
195 return ffmpegResampler;
198 auto windowsResampler = std::make_unique<QWindowsResampler>();
199 if (windowsResampler->setup(inputFormat, outputFormat))
200 return windowsResampler;
203 return q23::unexpected{ notAvailable };
206q23::expected<QPlatformMediaCaptureSession *, QString>
207QFFmpegMediaIntegration::createCaptureSession()
209 return new QFFmpegMediaCaptureSession();
212q23::expected<QPlatformMediaPlayer *, QString>
213QFFmpegMediaIntegration::createPlayer(QMediaPlayer *player)
215 return new QFFmpegMediaPlayer(player);
218q23::expected<QPlatformCamera *, QString> QFFmpegMediaIntegration::createCamera(QCamera *camera)
222 return QFFmpeg::makeQAvfCamera(*camera).release();
223#elif defined(Q_OS_ANDROID)
224 return new QFFmpeg::QAndroidCamera(camera);
225#elif QT_CONFIG(linux_v4l)
226 return new QV4L2Camera(camera);
227#elif defined(Q_OS_WINDOWS)
228 return new QFFmpeg::QWindowsCamera(camera);
231 return q23::unexpected{ notAvailable };
235QPlatformSurfaceCapture *QFFmpegMediaIntegration::createScreenCapture(QScreenCapture *)
237 static const QString screenCaptureBackend =
238 QString::fromLocal8Bit(qgetenv(
"QT_SCREEN_CAPTURE_BACKEND")).toLower();
240 if (!screenCaptureBackend.isEmpty()) {
241 if (
auto screenCapture = createScreenCaptureByBackend(screenCaptureBackend))
242 return screenCapture;
244 qWarning() <<
"Not supported QT_SCREEN_CAPTURE_BACKEND:" << screenCaptureBackend;
248 if (QX11SurfaceCapture::isSupported())
249 return new QX11SurfaceCapture(QPlatformSurfaceCapture::ScreenSource{});
252#if QT_CONFIG(pipewire_screencapture)
253 if (
auto capture = QtPipeWire::QPipeWireCapture::create())
254 return capture.release();
258 if (QEglfsScreenCapture::isSupported())
259 return new QEglfsScreenCapture;
262#if defined(Q_OS_WINDOWS)
263 return new QFFmpegScreenCaptureDxgi;
264#elif defined(Q_OS_MACOS)
265 return QFFmpeg::makeQSckScreenCapture().release();
266#elif defined(Q_OS_ANDROID)
267 return new QAndroidScreenCapture;
269 return new QGrabWindowSurfaceCapture(QPlatformSurfaceCapture::ScreenSource{});
273QPlatformSurfaceCapture *QFFmpegMediaIntegration::createWindowCapture(QWindowCapture *)
275 static const QString windowCaptureBackend =
276 QString::fromLocal8Bit(qgetenv(
"QT_WINDOW_CAPTURE_BACKEND")).toLower();
278 if (!windowCaptureBackend.isEmpty()) {
279 if (
auto windowCapture = createWindowCaptureByBackend(windowCaptureBackend))
280 return windowCapture;
282 qWarning() <<
"Not supported QT_WINDOW_CAPTURE_BACKEND:" << windowCaptureBackend;
286 if (QX11SurfaceCapture::isSupported())
287 return new QX11SurfaceCapture(QPlatformSurfaceCapture::WindowSource{});
290#if defined(Q_OS_WINDOWS)
291# if QT_CONFIG(cpp_winrt)
292 if (QFFmpegWindowCaptureUwp::isSupported())
293 return new QFFmpegWindowCaptureUwp;
296 return new QGdiWindowCapture;
297#elif defined(Q_OS_MACOS)
298 return QFFmpeg::makeQSckWindowCapture().release();
300 return new QGrabWindowSurfaceCapture(QPlatformSurfaceCapture::WindowSource{});
304q23::expected<QPlatformMediaRecorder *, QString>
305QFFmpegMediaIntegration::createRecorder(QMediaRecorder *recorder)
307 return new QFFmpegMediaRecorder(recorder);
310q23::expected<QPlatformImageCapture *, QString>
311QFFmpegMediaIntegration::createImageCapture(QImageCapture *imageCapture)
313 Q_ASSERT(imageCapture);
314#if defined(Q_OS_ANDROID)
315 return new QFFmpeg::QAndroidImageCapture(imageCapture);
316#elif defined(Q_OS_DARWIN)
317 return QFFmpeg::makeQAvfImageCapture(*imageCapture).release();
319 return new QFFmpegImageCapture(imageCapture);
323q23::expected<QPlatformVideoSink *, QString>
324QFFmpegMediaIntegration::createVideoSink(QVideoSink *sink)
326 return new QFFmpegVideoSink(sink);
329q23::expected<QPlatformAudioInput *, QString>
330QFFmpegMediaIntegration::createAudioInput(QAudioInput *input)
332 return new QFFmpegAudioInput(input);
335QVideoFrame QFFmpegMediaIntegration::convertVideoFrame(QVideoFrame &srcFrame,
336 const QVideoFrameFormat &destFormat)
338 return convertFrame(srcFrame, destFormat);
341QPlatformMediaFormatInfo *QFFmpegMediaIntegration::createFormatInfo()
343 return new QFFmpegMediaFormatInfo;
346QPlatformVideoDevices *QFFmpegMediaIntegration::createVideoDevices()
348#if defined(Q_OS_ANDROID)
349 return new QFFmpeg::QAndroidVideoDevices(
this);
350#elif QT_CONFIG(linux_v4l)
351 return new QV4L2CameraDevices(
this);
352#elif defined Q_OS_DARWIN
353 return makeQAvfVideoDevices(
355 &QFFmpeg::isCVFormatSupported).release();
356#elif defined(Q_OS_WINDOWS)
357 return new QWindowsVideoDevices(
this);
363QPlatformCapturableWindows *QFFmpegMediaIntegration::createCapturableWindows()
366 if (QX11SurfaceCapture::isSupported())
367 return new QX11CapturableWindows;
368#elif defined Q_OS_MACOS
369 return QFFmpeg::makeQSckCapturableWindows().release();
370#elif defined(Q_OS_WINDOWS)
371 return new QWinCapturableWindows;
380extern "C" Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm,
void * )
382 static bool initialized =
false;
384 return JNI_VERSION_1_6;
388 if (vm->GetEnv(&environment, JNI_VERSION_1_6))
392 if (av_jni_set_java_vm(vm,
nullptr))
395 if (!QFFmpeg::QAndroidCamera::registerNativeMethods()
396 || !QAndroidScreenCapture::registerNativeMethods()
397 || !QFFmpeg::QAndroidVideoDevices::registerNativeMethods()) {
401 return JNI_VERSION_1_6;
QT_BEGIN_NAMESPACE Q_STATIC_LOGGING_CATEGORY(lcSynthesizedIterableAccess, "qt.iterable.synthesized", QtWarningMsg)