diff options
author | Mikko Hallamaa <mikko.hallamaa@qt.io> | 2023-12-28 13:42:04 +0100 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2023-12-29 18:22:36 +0000 |
commit | afb03fdf7b8c1f0bc63de9921bf99c6bbddf819e (patch) | |
tree | e8773735d161c3e07a608ab5658ec75a08ddf779 /src | |
parent | 474962490ba59a9f27530423ae557edc474004d0 (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.txt | 2 | ||||
-rw-r--r-- | src/plugins/multimedia/ffmpeg/qeglfsscreencapture.cpp | 57 |
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 |