Skip to content

Commit c2159a1

Browse files
gschintgenKuleRucket
authored andcommitted
Improve frametiming for linux capture (LizardByte#2333)
1 parent 6dd56ad commit c2159a1

File tree

6 files changed

+93
-44
lines changed

6 files changed

+93
-44
lines changed

src/platform/common.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
#include <mutex>
1111
#include <string>
1212

13+
#include "src/config.h"
1314
#include "src/logging.h"
15+
#include "src/stat_trackers.h"
1416
#include "src/thread_safe.h"
1517
#include "src/utility.h"
1618
#include "src/video_colorspace.h"
@@ -19,6 +21,8 @@ extern "C" {
1921
#include <moonlight-common-c/src/Limelight.h>
2022
}
2123

24+
using namespace std::literals;
25+
2226
struct sockaddr;
2327
struct AVFrame;
2428
struct AVBufferRef;
@@ -499,6 +503,22 @@ namespace platf {
499503
int env_width, env_height;
500504

501505
int width, height;
506+
507+
protected:
508+
// collect capture timing data (at loglevel debug)
509+
stat_trackers::min_max_avg_tracker<double> sleep_overshoot_tracker;
510+
void
511+
log_sleep_overshoot(std::chrono::nanoseconds overshoot_ns) {
512+
if (config::sunshine.min_log_level <= 1) {
513+
// Print sleep overshoot stats to debug log every 20 seconds
514+
auto print_info = [&](double min_overshoot, double max_overshoot, double avg_overshoot) {
515+
auto f = stat_trackers::one_digit_after_decimal();
516+
BOOST_LOG(debug) << "Sleep overshoot (min/max/avg): " << f % min_overshoot << "ms/" << f % max_overshoot << "ms/" << f % avg_overshoot << "ms";
517+
};
518+
// std::chrono::nanoseconds overshoot_ns = std::chrono::steady_clock::now() - next_frame;
519+
sleep_overshoot_tracker.collect_and_callback_on_interval(overshoot_ns.count() / 1000000., print_info, 20s);
520+
}
521+
}
502522
};
503523

504524
class mic_t {

src/platform/linux/cuda.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -800,16 +800,21 @@ namespace cuda {
800800
handle.reset();
801801
});
802802

803+
sleep_overshoot_tracker.reset();
804+
803805
while (true) {
804806
auto now = std::chrono::steady_clock::now();
805807
if (next_frame > now) {
806-
std::this_thread::sleep_for((next_frame - now) / 3 * 2);
808+
std::this_thread::sleep_for(next_frame - now);
807809
}
808-
while (next_frame > now) {
809-
std::this_thread::sleep_for(1ns);
810-
now = std::chrono::steady_clock::now();
810+
now = std::chrono::steady_clock::now();
811+
std::chrono::nanoseconds overshoot_ns = now - next_frame;
812+
log_sleep_overshoot(overshoot_ns);
813+
814+
next_frame += delay;
815+
if (next_frame < now) { // some major slowdown happened; we couldn't keep up
816+
next_frame = now + delay;
811817
}
812-
next_frame = now + delay;
813818

814819
std::shared_ptr<platf::img_t> img_out;
815820
auto status = snapshot(pull_free_image_cb, img_out, 150ms, *cursor);

src/platform/linux/kmsgrab.cpp

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,17 +1193,22 @@ namespace platf {
11931193
capture(const push_captured_image_cb_t &push_captured_image_cb, const pull_free_image_cb_t &pull_free_image_cb, bool *cursor) override {
11941194
auto next_frame = std::chrono::steady_clock::now();
11951195

1196+
sleep_overshoot_tracker.reset();
1197+
11961198
while (true) {
11971199
auto now = std::chrono::steady_clock::now();
11981200

11991201
if (next_frame > now) {
1200-
std::this_thread::sleep_for((next_frame - now) / 3 * 2);
1202+
std::this_thread::sleep_for(next_frame - now);
12011203
}
1202-
while (next_frame > now) {
1203-
std::this_thread::sleep_for(1ns);
1204-
now = std::chrono::steady_clock::now();
1204+
now = std::chrono::steady_clock::now();
1205+
std::chrono::nanoseconds overshoot_ns = now - next_frame;
1206+
log_sleep_overshoot(overshoot_ns);
1207+
1208+
next_frame += delay;
1209+
if (next_frame < now) { // some major slowdown happened; we couldn't keep up
1210+
next_frame = now + delay;
12051211
}
1206-
next_frame = now + delay;
12071212

12081213
std::shared_ptr<platf::img_t> img_out;
12091214
auto status = snapshot(pull_free_image_cb, img_out, 1000ms, *cursor);
@@ -1412,17 +1417,22 @@ namespace platf {
14121417
capture(const push_captured_image_cb_t &push_captured_image_cb, const pull_free_image_cb_t &pull_free_image_cb, bool *cursor) {
14131418
auto next_frame = std::chrono::steady_clock::now();
14141419

1420+
sleep_overshoot_tracker.reset();
1421+
14151422
while (true) {
14161423
auto now = std::chrono::steady_clock::now();
14171424

14181425
if (next_frame > now) {
1419-
std::this_thread::sleep_for((next_frame - now) / 3 * 2);
1426+
std::this_thread::sleep_for(next_frame - now);
14201427
}
1421-
while (next_frame > now) {
1422-
std::this_thread::sleep_for(1ns);
1423-
now = std::chrono::steady_clock::now();
1428+
now = std::chrono::steady_clock::now();
1429+
std::chrono::nanoseconds overshoot_ns = now - next_frame;
1430+
log_sleep_overshoot(overshoot_ns);
1431+
1432+
next_frame += delay;
1433+
if (next_frame < now) { // some major slowdown happened; we couldn't keep up
1434+
next_frame = now + delay;
14241435
}
1425-
next_frame = now + delay;
14261436

14271437
std::shared_ptr<platf::img_t> img_out;
14281438
auto status = snapshot(pull_free_image_cb, img_out, 1000ms, *cursor);

src/platform/linux/wlgrab.cpp

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -129,16 +129,22 @@ namespace wl {
129129
capture(const push_captured_image_cb_t &push_captured_image_cb, const pull_free_image_cb_t &pull_free_image_cb, bool *cursor) override {
130130
auto next_frame = std::chrono::steady_clock::now();
131131

132+
sleep_overshoot_tracker.reset();
133+
132134
while (true) {
133135
auto now = std::chrono::steady_clock::now();
134136

135137
if (next_frame > now) {
136-
std::this_thread::sleep_for((next_frame - now) / 3 * 2);
138+
std::this_thread::sleep_for(next_frame - now);
137139
}
138-
while (next_frame > now) {
139-
now = std::chrono::steady_clock::now();
140+
now = std::chrono::steady_clock::now();
141+
std::chrono::nanoseconds overshoot_ns = now - next_frame;
142+
log_sleep_overshoot(overshoot_ns);
143+
144+
next_frame += delay;
145+
if (next_frame < now) { // some major slowdown happened; we couldn't keep up
146+
next_frame = now + delay;
140147
}
141-
next_frame = now + delay;
142148

143149
std::shared_ptr<platf::img_t> img_out;
144150
auto status = snapshot(pull_free_image_cb, img_out, 1000ms, *cursor);
@@ -259,16 +265,22 @@ namespace wl {
259265
capture(const push_captured_image_cb_t &push_captured_image_cb, const pull_free_image_cb_t &pull_free_image_cb, bool *cursor) override {
260266
auto next_frame = std::chrono::steady_clock::now();
261267

268+
sleep_overshoot_tracker.reset();
269+
262270
while (true) {
263271
auto now = std::chrono::steady_clock::now();
264272

265273
if (next_frame > now) {
266-
std::this_thread::sleep_for((next_frame - now) / 3 * 2);
274+
std::this_thread::sleep_for(next_frame - now);
267275
}
268-
while (next_frame > now) {
269-
now = std::chrono::steady_clock::now();
276+
now = std::chrono::steady_clock::now();
277+
std::chrono::nanoseconds overshoot_ns = now - next_frame;
278+
log_sleep_overshoot(overshoot_ns);
279+
280+
next_frame += delay;
281+
if (next_frame < now) { // some major slowdown happened; we couldn't keep up
282+
next_frame = now + delay;
270283
}
271-
next_frame = now + delay;
272284

273285
std::shared_ptr<platf::img_t> img_out;
274286
auto status = snapshot(pull_free_image_cb, img_out, 1000ms, *cursor);

src/platform/linux/x11grab.cpp

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -481,17 +481,22 @@ namespace platf {
481481
capture(const push_captured_image_cb_t &push_captured_image_cb, const pull_free_image_cb_t &pull_free_image_cb, bool *cursor) override {
482482
auto next_frame = std::chrono::steady_clock::now();
483483

484+
sleep_overshoot_tracker.reset();
485+
484486
while (true) {
485487
auto now = std::chrono::steady_clock::now();
486488

487489
if (next_frame > now) {
488-
std::this_thread::sleep_for((next_frame - now) / 3 * 2);
490+
std::this_thread::sleep_for(next_frame - now);
489491
}
490-
while (next_frame > now) {
491-
std::this_thread::sleep_for(1ns);
492-
now = std::chrono::steady_clock::now();
492+
now = std::chrono::steady_clock::now();
493+
std::chrono::nanoseconds overshoot_ns = now - next_frame;
494+
log_sleep_overshoot(overshoot_ns);
495+
496+
next_frame += delay;
497+
if (next_frame < now) { // some major slowdown happened; we couldn't keep up
498+
next_frame = now + delay;
493499
}
494-
next_frame = now + delay;
495500

496501
std::shared_ptr<platf::img_t> img_out;
497502
auto status = snapshot(pull_free_image_cb, img_out, 1000ms, *cursor);
@@ -622,17 +627,22 @@ namespace platf {
622627
capture(const push_captured_image_cb_t &push_captured_image_cb, const pull_free_image_cb_t &pull_free_image_cb, bool *cursor) override {
623628
auto next_frame = std::chrono::steady_clock::now();
624629

630+
sleep_overshoot_tracker.reset();
631+
625632
while (true) {
626633
auto now = std::chrono::steady_clock::now();
627634

628635
if (next_frame > now) {
629-
std::this_thread::sleep_for((next_frame - now) / 3 * 2);
636+
std::this_thread::sleep_for(next_frame - now);
630637
}
631-
while (next_frame > now) {
632-
std::this_thread::sleep_for(1ns);
633-
now = std::chrono::steady_clock::now();
638+
now = std::chrono::steady_clock::now();
639+
std::chrono::nanoseconds overshoot_ns = now - next_frame;
640+
log_sleep_overshoot(overshoot_ns);
641+
642+
next_frame += delay;
643+
if (next_frame < now) { // some major slowdown happened; we couldn't keep up
644+
next_frame = now + delay;
634645
}
635-
next_frame = now + delay;
636646

637647
std::shared_ptr<platf::img_t> img_out;
638648
auto status = snapshot(pull_free_image_cb, img_out, 1000ms, *cursor);

src/platform/windows/display_base.cpp

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ namespace platf::dxgi {
154154
SetThreadExecutionState(ES_CONTINUOUS);
155155
});
156156

157-
stat_trackers::min_max_avg_tracker<double> sleep_overshoot_tracker;
157+
sleep_overshoot_tracker.reset();
158158

159159
while (true) {
160160
// This will return false if the HDR state changes or for any number of other
@@ -184,16 +184,8 @@ namespace platf::dxgi {
184184
}
185185
else {
186186
high_precision_sleep(sleep_period);
187-
188-
if (config::sunshine.min_log_level <= 1) {
189-
// Print sleep overshoot stats to debug log every 20 seconds
190-
auto print_info = [&](double min_overshoot, double max_overshoot, double avg_overshoot) {
191-
auto f = stat_trackers::one_digit_after_decimal();
192-
BOOST_LOG(debug) << "Sleep overshoot (min/max/avg): " << f % min_overshoot << "ms/" << f % max_overshoot << "ms/" << f % avg_overshoot << "ms";
193-
};
194-
std::chrono::nanoseconds overshoot_ns = std::chrono::steady_clock::now() - sleep_target;
195-
sleep_overshoot_tracker.collect_and_callback_on_interval(overshoot_ns.count() / 1000000., print_info, 20s);
196-
}
187+
std::chrono::nanoseconds overshoot_ns = std::chrono::steady_clock::now() - sleep_target;
188+
log_sleep_overshoot(overshoot_ns);
197189

198190
status = snapshot(pull_free_image_cb, img_out, 0ms, *cursor);
199191

0 commit comments

Comments
 (0)