Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qeglfsscreencapture.cpp
Go to the documentation of this file.
1// Copyright (C) 2023 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5
7#include "qguiapplication.h"
9#include "private/qimagevideobuffer_p.h"
10
11#include <QtOpenGL/private/qopenglcompositor_p.h>
12#include <QtOpenGL/private/qopenglframebufferobject_p.h>
13
14#include <QtQuick/qquickwindow.h>
15
17
19{
20public:
23 {
26 // Limit frame rate to 30 fps for performance reasons,
27 // to be reviewed at the next optimization round
28 setFrameRate(std::min(screen->refreshRate(), 30.0));
29 }
30
31 ~Grabber() override { stop(); }
32
34
35protected:
37 {
38 auto nativeSize = QOpenGLCompositor::instance()->nativeTargetGeometry().size();
39 auto fbo = std::make_unique<QOpenGLFramebufferObject>(nativeSize);
40
41 if (!QOpenGLCompositor::instance()->grabToFrameBufferObject(
43 updateError(Error::InternalError, QLatin1String("Couldn't grab to framebuffer object"));
44 return {};
45 }
46
47 if (!fbo->isValid()) {
48 updateError(Error::InternalError, QLatin1String("Framebuffer object invalid"));
49 return {};
50 }
51
52 auto videoBuffer = std::make_unique<QOpenGLVideoBuffer>(std::move(fbo));
53
54 if (!m_format.isValid()) {
55 auto image = videoBuffer->ensureImageBuffer().underlyingImage();
58 }
59
60 return QVideoFrame(videoBuffer.release(), m_format);
61 }
62
64};
65
67{
68public:
70 : Grabber(screenCapture, screen), m_quickWindow(quickWindow)
71 {
72 Q_ASSERT(m_quickWindow);
73 }
74
75protected:
77 {
78 if (!m_quickWindow) {
80 return {};
81 }
82
83 QImage image = m_quickWindow->grabWindow();
84
85 if (image.isNull()) {
87 return {};
88 }
89
90 if (!m_format.isValid()) {
91 m_format = { image.size(),
94 }
95
96 return QVideoFrame(new QImageVideoBuffer(std::move(image)), m_format);
97 }
98
99private:
100 QPointer<QQuickWindow> m_quickWindow;
101};
102
104
106
108{
109 return m_grabber ? m_grabber->format() : QVideoFrameFormat();
110}
111
113{
114 if (static_cast<bool>(m_grabber) == active)
115 return true;
116
117 if (m_grabber)
118 m_grabber.reset();
119
120 if (!active)
121 return true;
122
123 m_grabber = createGrabber();
124
125 if (!m_grabber) {
126 // TODO: This could mean that the UI is not started yet, so we should wait and try again,
127 // and then give error if still not started. Might not be possible here.
128 return false;
129 }
130
131 m_grabber->start();
132 return true;
133}
134
139
140std::unique_ptr<QEglfsScreenCapture::Grabber> QEglfsScreenCapture::createGrabber()
141{
142 auto screen = source<ScreenSource>();
144 return nullptr;
145
147
148 if (compositor->context()) {
149 // Create OpenGL grabber
150 if (!compositor->targetWindow()) {
152 QLatin1String("Target window is not set for OpenGL compositor"));
153 return nullptr;
154 }
155
156 return std::make_unique<Grabber>(*this, screen);
157 }
158
159 // Check for QQuickWindow
160 auto windows = QGuiApplication::topLevelWindows();
161 auto it = std::find_if(windows.begin(), windows.end(), [screen](QWindow *window) {
162 auto quickWindow = qobject_cast<QQuickWindow *>(window);
163 if (!quickWindow)
164 return false;
165
166 return quickWindow->screen() == screen;
167 });
168
169 if (it != windows.end()) {
170 // Create grabber that calls QQuickWindow::grabWindow
171 return std::make_unique<QuickGrabber>(*this, screen, qobject_cast<QQuickWindow *>(*it));
172 }
173
174 updateError(Error::CaptureFailed, QLatin1String("No existing OpenGL context or QQuickWindow"));
175 return nullptr;
176}
177
Grabber(QEglfsScreenCapture &screenCapture, QScreen *screen)
QuickGrabber(QEglfsScreenCapture &screenCapture, QScreen *screen, QQuickWindow *quickWindow)
~QEglfsScreenCapture() override
QVideoFrameFormat frameFormat() const override
bool setActiveInternal(bool active) override
void errorUpdated(QPlatformSurfaceCapture::Error error, const QString &description)
void addFrameCallback(Object &object, Method method)
void updateError(QPlatformSurfaceCapture::Error error, const QString &description={})
static QWindowList topLevelWindows()
Returns a list of the top-level windows in the application.
QString platformName
The name of the underlying platform plugin.
\inmodule QtGui
Definition qimage.h:37
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
A generic OpenGL-based compositor.
static QOpenGLCompositor * instance()
void updateError(Error error, const QString &errorString)
bool checkScreenWithError(ScreenSource &screen)
void newVideoFrame(const QVideoFrame &)
\qmltype Window \instantiates QQuickWindow \inqmlmodule QtQuick
The QScreen class is used to query screen properties. \inmodule QtGui.
Definition qscreen.h:32
qreal refreshRate
the approximate vertical refresh rate of the screen in Hz
Definition qscreen.h:64
iterator end()
Definition qset.h:140
The QVideoFrameFormat class specifies the stream format of a video presentation surface.
bool isValid() const
Identifies if a video surface format has a valid pixel format and frame size.
void setStreamFrameRate(qreal rate)
Sets the frame rate of a video stream in frames per second.
static PixelFormat pixelFormatFromImageFormat(QImage::Format format)
Returns a video pixel format equivalent to an image format.
The QVideoFrame class represents a frame of video data.
Definition qvideoframe.h:27
\inmodule QtGui
Definition qwindow.h:63
QSet< QString >::iterator it
Combined button and popup list for selecting options.
Definition image.cpp:4
static QOpenGLCompositor * compositor
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
QScreen * screen
[1]
Definition main.cpp:29
aWidget window() -> setWindowTitle("New Window Title")
[2]