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(screenCapture.frameRate().value_or(qMin(screen->refreshRate(), 30.f)));
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(),
62 QVideoFrameFormat::pixelFormatFromImageFormat(image.format()) };
65 if (m_format.streamFrameRate() != frameRate())
66 m_format.setStreamFrameRate(frameRate());
68 return QVideoFramePrivate::createFrame(std::move(videoBuffer), m_format);
78 QuickGrabber(QEglfsScreenCapture &screenCapture, QScreen *screen, QQuickWindow *quickWindow)
81 Q_ASSERT(m_quickWindow);
88 updateError(Error::InternalError, QLatin1String(
"Window deleted"));
92 QImage image = m_quickWindow->grabWindow();
95 updateError(Error::InternalError, QLatin1String(
"Image invalid"));
99 if (!m_format.isValid()) {
100 m_format = { image.size(),
101 QVideoFrameFormat::pixelFormatFromImageFormat(image.format()) };
104 if (m_format.streamFrameRate() != frameRate())
105 m_format.setStreamFrameRate(frameRate());
107 return QVideoFramePrivate::createFrame(
108 std::make_unique<QImageVideoBuffer>(std::move(image)), m_format);
112 QPointer<QQuickWindow> m_quickWindow;
116QEglfsScreenCapture::QEglfsScreenCapture() : QPlatformSurfaceCapture(ScreenSource{}) { }
118QEglfsScreenCapture::~QEglfsScreenCapture() =
default;
120QVideoFrameFormat QEglfsScreenCapture::frameFormat()
const
122 return m_grabber ? m_grabber->format() : QVideoFrameFormat();
125bool QEglfsScreenCapture::setActiveInternal(
bool active)
127 if (
static_cast<
bool>(m_grabber) == active)
136 m_grabber = createGrabber();
148bool QEglfsScreenCapture::isSupported()
150 return QGuiApplication::platformName() == QLatin1String(
"eglfs");
153std::unique_ptr<QEglfsScreenCapture::Grabber> QEglfsScreenCapture::createGrabber()
155 auto screen = source<ScreenSource>();
156 if (!checkScreenWithError(screen))
159 QOpenGLCompositor *compositor = QOpenGLCompositor::instance();
161 if (compositor->context() && QOpenGLContext::currentContext()) {
163 if (!compositor->targetWindow()) {
164 updateError(Error::CaptureFailed,
165 QLatin1String(
"Target window is not set for OpenGL compositor"));
169 return std::make_unique<
Grabber>(*
this, screen);
174 auto windows = QGuiApplication::topLevelWindows();
175 auto it = ranges::find_if(windows, [screen](QWindow *window) {
176 auto quickWindow = qobject_cast<QQuickWindow *>(window);
180 return quickWindow->screen() == screen;
183 if (it != windows.end()) {
185 return std::make_unique<
QuickGrabber>(*
this, screen, qobject_cast<QQuickWindow *>(*it));
189 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.