summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMikko Hallamaa <mikko.hallamaa@qt.io>2023-12-28 13:42:04 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2023-12-29 18:22:36 +0000
commitafb03fdf7b8c1f0bc63de9921bf99c6bbddf819e (patch)
treee8773735d161c3e07a608ab5658ec75a08ddf779 /src
parent474962490ba59a9f27530423ae557edc474004d0 (diff)
Add implementation to EGLFS screen capture
Implementation for EGLFS screen capture added in change codereview.qt-project.org/c/qt/qtmultimedia/+/527432. This allows for optimizations as well as handling platform-specific conditions. Task-number: QTBUG-117746 Pick-to: 6.6 6.5 Change-Id: Iadffba1c93bd3bc62c267a096d4ac23f1fedf4fd Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Artem Dyomin <artem.dyomin@qt.io> (cherry picked from commit 0fd782d27e7732040c755a1bf22cc56198d64cac) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/multimedia/ffmpeg/CMakeLists.txt2
-rw-r--r--src/plugins/multimedia/ffmpeg/qeglfsscreencapture.cpp57
2 files changed, 53 insertions, 6 deletions
diff --git a/src/plugins/multimedia/ffmpeg/CMakeLists.txt b/src/plugins/multimedia/ffmpeg/CMakeLists.txt
index 8ba9a9264..0b3005a4d 100644
--- a/src/plugins/multimedia/ffmpeg/CMakeLists.txt
+++ b/src/plugins/multimedia/ffmpeg/CMakeLists.txt
@@ -198,6 +198,8 @@ qt_internal_extend_target(QFFmpegMediaPlugin CONDITION QT_FEATURE_xlib
qt_internal_extend_target(QFFmpegMediaPlugin CONDITION QT_FEATURE_eglfs
SOURCES
qeglfsscreencapture.cpp qeglfsscreencapture_p.h
+ LIBRARIES
+ Qt::OpenGLPrivate
)
set_source_files_properties(qx11surfacecapture.cpp qx11capturablewindows.cpp # X headers
diff --git a/src/plugins/multimedia/ffmpeg/qeglfsscreencapture.cpp b/src/plugins/multimedia/ffmpeg/qeglfsscreencapture.cpp
index 1837c3c57..2f9ad1add 100644
--- a/src/plugins/multimedia/ffmpeg/qeglfsscreencapture.cpp
+++ b/src/plugins/multimedia/ffmpeg/qeglfsscreencapture.cpp
@@ -6,6 +6,10 @@
#include "qffmpegsurfacecapturegrabber_p.h"
#include "qguiapplication.h"
+#include "private/qimagevideobuffer_p.h"
+
+#include <QtOpenGL/private/qopenglcompositor_p.h>
+
QT_BEGIN_NAMESPACE
class QEglfsScreenCapture::Grabber : public QFFmpegSurfaceCaptureGrabber
@@ -14,9 +18,11 @@ public:
Grabber(QEglfsScreenCapture &screenCapture, QScreen *screen)
: QFFmpegSurfaceCaptureGrabber(false)
{
- setFrameRate(screen->refreshRate());
addFrameCallback(screenCapture, &QEglfsScreenCapture::newVideoFrame);
connect(this, &Grabber::errorUpdated, &screenCapture, &QEglfsScreenCapture::updateError);
+ // Limit frame rate to 30 fps for performance reasons, to be reviewed at the next optimization round
+ setFrameRate(std::min(screen->refreshRate(), 30.0));
+ start();
}
~Grabber() override { stop(); }
@@ -25,8 +31,25 @@ public:
QVideoFrame grabFrame() override
{
- // To be implemented: take a frame and updare m_format
- return {};
+ QOpenGLCompositor *compositor = QOpenGLCompositor::instance();
+ QImage img = compositor->grab();
+
+ if (img.isNull()) {
+ updateError(Error::InternalError, QLatin1String("Null image captured"));
+ return {};
+ }
+
+ if (!m_format.isValid()) {
+ // This is a hack to use RGBX8888 video frame format for RGBA8888_Premultiplied image format,
+ // due to the lack of QVideoFrameFormat::Format_RGBA8888_Premultiplied
+ auto videoFrameFormat = img.format() == QImage::Format_RGBA8888_Premultiplied
+ ? QVideoFrameFormat::Format_RGBX8888
+ : QVideoFrameFormat::pixelFormatFromImageFormat(img.format());
+ m_format = { img.size(), videoFrameFormat };
+ m_format.setFrameRate(frameRate());
+ }
+
+ return QVideoFrame(new QImageVideoBuffer(std::move(img)), m_format);
}
private:
@@ -44,18 +67,40 @@ QVideoFrameFormat QEglfsScreenCapture::frameFormat() const
bool QEglfsScreenCapture::setActiveInternal(bool active)
{
+ if (static_cast<bool>(m_grabber) == active)
+ return true;
+
if (m_grabber)
m_grabber.reset();
- else if (auto screen = source<ScreenSource>(); checkScreenWithError(screen))
+ else {
+ auto screen = source<ScreenSource>();
+ if (!checkScreenWithError(screen))
+ return false;
+
+ QOpenGLCompositor *compositor = QOpenGLCompositor::instance();
+ if (!compositor->context()) {
+ updateError(Error::CaptureFailed, QLatin1String("OpenGL context is not found"));
+ return false;
+ }
+
+ if (!compositor->targetWindow()) {
+ updateError(Error::CaptureFailed, QLatin1String("Target window is not set for OpenGL compositor"));
+ return false;
+ }
+
+ // TODO Add check to differentiate between uninitialized UI and QML
+ // If UI not started, wait and try again, and then give error if still not started.
+ // If QML, give not supported error for now.
+
m_grabber = std::make_unique<Grabber>(*this, screen);
+ }
return static_cast<bool>(m_grabber) == active;
}
bool QEglfsScreenCapture::isSupported()
{
- // return QGuiApplication::platformName() == QLatin1String("eglfs"))
- return false;
+ return QGuiApplication::platformName() == QLatin1String("eglfs");
}
QT_END_NAMESPACE