Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qffmpegsurfacecapturegrabber.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 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
6#include <qchronotimer.h>
7#include <qelapsedtimer.h>
8#include <qloggingcategory.h>
9#include <qthread.h>
10#include <qtimer.h>
11
13
14Q_STATIC_LOGGING_CATEGORY(qLcScreenCaptureGrabber, "qt.multimedia.ffmpeg.surfacecapturegrabber");
15
17{
18public:
19 auto measure()
20 {
21 m_elapsedTimer.start();
22 return qScopeGuard([&]() {
23 const auto nsecsElapsed = m_elapsedTimer.nsecsElapsed();
24 ++m_number;
25 m_wholeTime += nsecsElapsed;
26
27#ifdef DUMP_SCREEN_CAPTURE_PROFILING
28 qDebug() << "screen grabbing time:" << nsecsElapsed << "avg:" << avgTime()
29 << "number:" << m_number;
30#endif
31 });
32 }
33
34 qreal avgTime() const
35 {
36 return m_number ? m_wholeTime / (m_number * 1000000.) : 0.;
37 }
38
39 qint64 number() const
40 {
41 return m_number;
42 }
43
44private:
45 QElapsedTimer m_elapsedTimer;
46 qint64 m_wholeTime = 0;
47 qint64 m_number = 0;
48};
49
57
59{
60public:
62 : m_grabber(grabber)
63 {}
64
65protected:
67 {
69
71 return;
72
73 exec();
75 }
76
77private:
79};
80
82{
83 setFrameRate(DefaultScreenCaptureFrameRate);
84
85 if (threadPolicy == CreateGrabbingThread)
86 m_thread = std::make_unique<GrabbingThread>(*this);
87}
88
90{
91 if (m_thread)
92 m_thread->start();
95}
96
98
99void QFFmpegSurfaceCaptureGrabber::setFrameRate(std::optional<qreal> rate)
100{
101 if (!rate)
102 rate = DefaultScreenCaptureFrameRate;
103
104 // Bound to a minimum
105 if (*rate < MinScreenCaptureFrameRate)
106 rate = MinScreenCaptureFrameRate;
107
108 if (m_rate == *rate)
109 return;
110
111 m_rate = *rate;
112 qCDebug(qLcScreenCaptureGrabber) << "Screen capture rate has been changed:" << m_rate;
113}
114
116{
117 return m_rate;
118}
119
121{
122 if (m_thread)
123 {
124 m_thread->quit();
125 m_thread->wait();
126 }
128 {
130 }
131}
132
133void QFFmpegSurfaceCaptureGrabber::updateError(QPlatformSurfaceCapture::Error error,
134 const QString &description)
135{
136 const auto prevError = std::exchange(m_prevError, error);
137
138 if (error != QPlatformSurfaceCapture::NoError
139 || prevError != QPlatformSurfaceCapture::NoError) {
140 emit errorUpdated(error, description);
141 }
142
144}
145
147{
148 using namespace std::chrono;
149
150 const qreal rate = m_prevError && *m_prevError != QPlatformSurfaceCapture::NoError
151 ? MinScreenCaptureFrameRate
152 : m_rate;
153 const auto interval = round<nanoseconds>(nanoseconds(1s) / rate);
154
155 if (m_context && m_context->timer.interval() != interval)
156 m_context->timer.setInterval(interval);
157}
158
160{
162 qCDebug(qLcScreenCaptureGrabber) << "screen capture started";
163
164 m_context = std::make_unique<GrabbingContext>();
165 m_context->timer.setTimerType(Qt::PreciseTimer);
167
168 m_context->elapsedTimer.start();
169
170 auto doGrab = [this]() {
171 auto measure = m_context->profiler.measure();
172
173 auto frame = grabFrame();
174
175 if (frame.isValid()) {
176 frame.setStartTime(m_context->lastFrameTime);
177 frame.setEndTime(m_context->elapsedTimer.nsecsElapsed() / 1000);
178 m_context->lastFrameTime = frame.endTime();
179
180 updateError(QPlatformSurfaceCapture::NoError);
181
182 emit frameGrabbed(frame);
183 }
184 };
185
186 doGrab();
187
188 m_context->timer.callOnTimeout(&m_context->timer, doGrab);
189 m_context->timer.start();
190}
191
193{
195 qCDebug(qLcScreenCaptureGrabber)
196 << "end screen capture thread; avg grabbing time:" << m_context->profiler.avgTime()
197 << "ms, grabbings number:" << m_context->profiler.number();
198 m_context.reset();
199}
200
202{
203 return m_context != nullptr;
204}
205
206QT_END_NAMESPACE
207
208#include "moc_qffmpegsurfacecapturegrabber_p.cpp"
GrabbingThread(QFFmpegSurfaceCaptureGrabber &grabber)
void setFrameRate(std::optional< qreal >)
~QFFmpegSurfaceCaptureGrabber() override
QFFmpegSurfaceCaptureGrabber(ThreadPolicy threadPolicy=CreateGrabbingThread)
void updateError(QPlatformSurfaceCapture::Error error, const QString &description={})
Combined button and popup list for selecting options.
#define qCDebug(category,...)
#define Q_STATIC_LOGGING_CATEGORY(name,...)