9#include "private/qimagevideobuffer_p.h"
10#include "private/qvideoframe_p.h"
12#include <QtMultimedia/private/qmultimedia_ranges_p.h>
13#include <QtOpenGL/private/qopenglcompositor_p.h>
14#include <QtOpenGL/private/qopenglframebufferobject_p.h>
17#include <QtQuick/qquickwindow.h>
21namespace ranges = QtMultimediaPrivate::ranges;
26 Grabber(QEglfsScreenCapture &screenCapture, QScreen *screen)
29 addFrameCallback(screenCapture, &QEglfsScreenCapture::newVideoFrame);
30 connect(
this, &Grabber::errorUpdated, &screenCapture, &QEglfsScreenCapture::updateError);
33 setFrameRate(std::min(screen->refreshRate(), qreal(30.0)));
43 auto nativeSize = QOpenGLCompositor::instance()->nativeTargetGeometry().size();
44 auto fbo =
std::make_unique<QOpenGLFramebufferObject>(nativeSize);
46 if (!QOpenGLCompositor::instance()->grabToFrameBufferObject(
47 fbo.get(), QOpenGLCompositor::NotFlipped)) {
48 updateError(Error::InternalError, QLatin1String(
"Couldn't grab to framebuffer object"));
52 if (!fbo->isValid()) {
53 updateError(Error::InternalError, QLatin1String(
"Framebuffer object invalid"));
59 if (!m_format.isValid()) {
60 auto image = videoBuffer->ensureImageBuffer().underlyingImage();
61 m_format = { image.size(), QVideoFrameFormat::pixelFormatFromImageFormat(image.format()) };
62 m_format.setStreamFrameRate(frameRate());
65 return QVideoFramePrivate::createFrame(std::move(videoBuffer), m_format);
75 QuickGrabber(QEglfsScreenCapture &screenCapture, QScreen *screen, QQuickWindow *quickWindow)
78 Q_ASSERT(m_quickWindow);
85 updateError(Error::InternalError, QLatin1String(
"Window deleted"));
89 QImage image = m_quickWindow->grabWindow();
92 updateError(Error::InternalError, QLatin1String(
"Image invalid"));
96 if (!m_format.isValid()) {
97 m_format = { image.size(),
98 QVideoFrameFormat::pixelFormatFromImageFormat(image.format()) };
99 m_format.setStreamFrameRate(frameRate());
102 return QVideoFramePrivate::createFrame(
103 std::make_unique<QImageVideoBuffer>(std::move(image)), m_format);
107 QPointer<QQuickWindow> m_quickWindow;
111QEglfsScreenCapture::QEglfsScreenCapture() : QPlatformSurfaceCapture(ScreenSource{}) { }
113QEglfsScreenCapture::~QEglfsScreenCapture() =
default;
115QVideoFrameFormat QEglfsScreenCapture::frameFormat()
const
117 return m_grabber ? m_grabber->format() : QVideoFrameFormat();
120bool QEglfsScreenCapture::setActiveInternal(
bool active)
122 if (
static_cast<
bool>(m_grabber) == active)
131 m_grabber = createGrabber();
143bool QEglfsScreenCapture::isSupported()
145 return QGuiApplication::platformName() == QLatin1String(
"eglfs");
148std::unique_ptr<QEglfsScreenCapture::Grabber> QEglfsScreenCapture::createGrabber()
150 auto screen = source<ScreenSource>();
151 if (!checkScreenWithError(screen))
154 QOpenGLCompositor *compositor = QOpenGLCompositor::instance();
156 if (compositor->context()) {
158 if (!compositor->targetWindow()) {
159 updateError(Error::CaptureFailed,
160 QLatin1String(
"Target window is not set for OpenGL compositor"));
164 return std::make_unique<
Grabber>(*
this, screen);
169 auto windows = QGuiApplication::topLevelWindows();
170 auto it = ranges::find_if(windows, [screen](QWindow *window) {
171 auto quickWindow = qobject_cast<QQuickWindow *>(window);
175 return quickWindow->screen() == screen;
178 if (it != windows.end()) {
180 return std::make_unique<
QuickGrabber>(*
this, screen, qobject_cast<QQuickWindow *>(*it));
184 updateError(Error::CaptureFailed, QLatin1String(
"No existing OpenGL context or QQuickWindow"));
Grabber(QEglfsScreenCapture &screenCapture, QScreen *screen)
QVideoFrameFormat m_format
QVideoFrameFormat format()
QVideoFrame grabFrame() override
QVideoFrame grabFrame() override
QuickGrabber(QEglfsScreenCapture &screenCapture, QScreen *screen, QQuickWindow *quickWindow)
Combined button and popup list for selecting options.