Improve frametiming for linux capture (#2333)
This commit is contained in:
@@ -10,7 +10,9 @@
|
|||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "src/config.h"
|
||||||
#include "src/logging.h"
|
#include "src/logging.h"
|
||||||
|
#include "src/stat_trackers.h"
|
||||||
#include "src/thread_safe.h"
|
#include "src/thread_safe.h"
|
||||||
#include "src/utility.h"
|
#include "src/utility.h"
|
||||||
#include "src/video_colorspace.h"
|
#include "src/video_colorspace.h"
|
||||||
@@ -19,6 +21,8 @@ extern "C" {
|
|||||||
#include <moonlight-common-c/src/Limelight.h>
|
#include <moonlight-common-c/src/Limelight.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using namespace std::literals;
|
||||||
|
|
||||||
struct sockaddr;
|
struct sockaddr;
|
||||||
struct AVFrame;
|
struct AVFrame;
|
||||||
struct AVBufferRef;
|
struct AVBufferRef;
|
||||||
@@ -499,6 +503,22 @@ namespace platf {
|
|||||||
int env_width, env_height;
|
int env_width, env_height;
|
||||||
|
|
||||||
int width, height;
|
int width, height;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// collect capture timing data (at loglevel debug)
|
||||||
|
stat_trackers::min_max_avg_tracker<double> sleep_overshoot_tracker;
|
||||||
|
void
|
||||||
|
log_sleep_overshoot(std::chrono::nanoseconds overshoot_ns) {
|
||||||
|
if (config::sunshine.min_log_level <= 1) {
|
||||||
|
// Print sleep overshoot stats to debug log every 20 seconds
|
||||||
|
auto print_info = [&](double min_overshoot, double max_overshoot, double avg_overshoot) {
|
||||||
|
auto f = stat_trackers::one_digit_after_decimal();
|
||||||
|
BOOST_LOG(debug) << "Sleep overshoot (min/max/avg): " << f % min_overshoot << "ms/" << f % max_overshoot << "ms/" << f % avg_overshoot << "ms";
|
||||||
|
};
|
||||||
|
// std::chrono::nanoseconds overshoot_ns = std::chrono::steady_clock::now() - next_frame;
|
||||||
|
sleep_overshoot_tracker.collect_and_callback_on_interval(overshoot_ns.count() / 1000000., print_info, 20s);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class mic_t {
|
class mic_t {
|
||||||
|
|||||||
@@ -800,16 +800,21 @@ namespace cuda {
|
|||||||
handle.reset();
|
handle.reset();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
sleep_overshoot_tracker.reset();
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
auto now = std::chrono::steady_clock::now();
|
auto now = std::chrono::steady_clock::now();
|
||||||
if (next_frame > now) {
|
if (next_frame > now) {
|
||||||
std::this_thread::sleep_for((next_frame - now) / 3 * 2);
|
std::this_thread::sleep_for(next_frame - now);
|
||||||
}
|
}
|
||||||
while (next_frame > now) {
|
now = std::chrono::steady_clock::now();
|
||||||
std::this_thread::sleep_for(1ns);
|
std::chrono::nanoseconds overshoot_ns = now - next_frame;
|
||||||
now = std::chrono::steady_clock::now();
|
log_sleep_overshoot(overshoot_ns);
|
||||||
|
|
||||||
|
next_frame += delay;
|
||||||
|
if (next_frame < now) { // some major slowdown happened; we couldn't keep up
|
||||||
|
next_frame = now + delay;
|
||||||
}
|
}
|
||||||
next_frame = now + delay;
|
|
||||||
|
|
||||||
std::shared_ptr<platf::img_t> img_out;
|
std::shared_ptr<platf::img_t> img_out;
|
||||||
auto status = snapshot(pull_free_image_cb, img_out, 150ms, *cursor);
|
auto status = snapshot(pull_free_image_cb, img_out, 150ms, *cursor);
|
||||||
|
|||||||
@@ -1193,17 +1193,22 @@ namespace platf {
|
|||||||
capture(const push_captured_image_cb_t &push_captured_image_cb, const pull_free_image_cb_t &pull_free_image_cb, bool *cursor) override {
|
capture(const push_captured_image_cb_t &push_captured_image_cb, const pull_free_image_cb_t &pull_free_image_cb, bool *cursor) override {
|
||||||
auto next_frame = std::chrono::steady_clock::now();
|
auto next_frame = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
|
sleep_overshoot_tracker.reset();
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
auto now = std::chrono::steady_clock::now();
|
auto now = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
if (next_frame > now) {
|
if (next_frame > now) {
|
||||||
std::this_thread::sleep_for((next_frame - now) / 3 * 2);
|
std::this_thread::sleep_for(next_frame - now);
|
||||||
}
|
}
|
||||||
while (next_frame > now) {
|
now = std::chrono::steady_clock::now();
|
||||||
std::this_thread::sleep_for(1ns);
|
std::chrono::nanoseconds overshoot_ns = now - next_frame;
|
||||||
now = std::chrono::steady_clock::now();
|
log_sleep_overshoot(overshoot_ns);
|
||||||
|
|
||||||
|
next_frame += delay;
|
||||||
|
if (next_frame < now) { // some major slowdown happened; we couldn't keep up
|
||||||
|
next_frame = now + delay;
|
||||||
}
|
}
|
||||||
next_frame = now + delay;
|
|
||||||
|
|
||||||
std::shared_ptr<platf::img_t> img_out;
|
std::shared_ptr<platf::img_t> img_out;
|
||||||
auto status = snapshot(pull_free_image_cb, img_out, 1000ms, *cursor);
|
auto status = snapshot(pull_free_image_cb, img_out, 1000ms, *cursor);
|
||||||
@@ -1412,17 +1417,22 @@ namespace platf {
|
|||||||
capture(const push_captured_image_cb_t &push_captured_image_cb, const pull_free_image_cb_t &pull_free_image_cb, bool *cursor) {
|
capture(const push_captured_image_cb_t &push_captured_image_cb, const pull_free_image_cb_t &pull_free_image_cb, bool *cursor) {
|
||||||
auto next_frame = std::chrono::steady_clock::now();
|
auto next_frame = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
|
sleep_overshoot_tracker.reset();
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
auto now = std::chrono::steady_clock::now();
|
auto now = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
if (next_frame > now) {
|
if (next_frame > now) {
|
||||||
std::this_thread::sleep_for((next_frame - now) / 3 * 2);
|
std::this_thread::sleep_for(next_frame - now);
|
||||||
}
|
}
|
||||||
while (next_frame > now) {
|
now = std::chrono::steady_clock::now();
|
||||||
std::this_thread::sleep_for(1ns);
|
std::chrono::nanoseconds overshoot_ns = now - next_frame;
|
||||||
now = std::chrono::steady_clock::now();
|
log_sleep_overshoot(overshoot_ns);
|
||||||
|
|
||||||
|
next_frame += delay;
|
||||||
|
if (next_frame < now) { // some major slowdown happened; we couldn't keep up
|
||||||
|
next_frame = now + delay;
|
||||||
}
|
}
|
||||||
next_frame = now + delay;
|
|
||||||
|
|
||||||
std::shared_ptr<platf::img_t> img_out;
|
std::shared_ptr<platf::img_t> img_out;
|
||||||
auto status = snapshot(pull_free_image_cb, img_out, 1000ms, *cursor);
|
auto status = snapshot(pull_free_image_cb, img_out, 1000ms, *cursor);
|
||||||
|
|||||||
@@ -129,16 +129,22 @@ namespace wl {
|
|||||||
capture(const push_captured_image_cb_t &push_captured_image_cb, const pull_free_image_cb_t &pull_free_image_cb, bool *cursor) override {
|
capture(const push_captured_image_cb_t &push_captured_image_cb, const pull_free_image_cb_t &pull_free_image_cb, bool *cursor) override {
|
||||||
auto next_frame = std::chrono::steady_clock::now();
|
auto next_frame = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
|
sleep_overshoot_tracker.reset();
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
auto now = std::chrono::steady_clock::now();
|
auto now = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
if (next_frame > now) {
|
if (next_frame > now) {
|
||||||
std::this_thread::sleep_for((next_frame - now) / 3 * 2);
|
std::this_thread::sleep_for(next_frame - now);
|
||||||
}
|
}
|
||||||
while (next_frame > now) {
|
now = std::chrono::steady_clock::now();
|
||||||
now = std::chrono::steady_clock::now();
|
std::chrono::nanoseconds overshoot_ns = now - next_frame;
|
||||||
|
log_sleep_overshoot(overshoot_ns);
|
||||||
|
|
||||||
|
next_frame += delay;
|
||||||
|
if (next_frame < now) { // some major slowdown happened; we couldn't keep up
|
||||||
|
next_frame = now + delay;
|
||||||
}
|
}
|
||||||
next_frame = now + delay;
|
|
||||||
|
|
||||||
std::shared_ptr<platf::img_t> img_out;
|
std::shared_ptr<platf::img_t> img_out;
|
||||||
auto status = snapshot(pull_free_image_cb, img_out, 1000ms, *cursor);
|
auto status = snapshot(pull_free_image_cb, img_out, 1000ms, *cursor);
|
||||||
@@ -259,16 +265,22 @@ namespace wl {
|
|||||||
capture(const push_captured_image_cb_t &push_captured_image_cb, const pull_free_image_cb_t &pull_free_image_cb, bool *cursor) override {
|
capture(const push_captured_image_cb_t &push_captured_image_cb, const pull_free_image_cb_t &pull_free_image_cb, bool *cursor) override {
|
||||||
auto next_frame = std::chrono::steady_clock::now();
|
auto next_frame = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
|
sleep_overshoot_tracker.reset();
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
auto now = std::chrono::steady_clock::now();
|
auto now = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
if (next_frame > now) {
|
if (next_frame > now) {
|
||||||
std::this_thread::sleep_for((next_frame - now) / 3 * 2);
|
std::this_thread::sleep_for(next_frame - now);
|
||||||
}
|
}
|
||||||
while (next_frame > now) {
|
now = std::chrono::steady_clock::now();
|
||||||
now = std::chrono::steady_clock::now();
|
std::chrono::nanoseconds overshoot_ns = now - next_frame;
|
||||||
|
log_sleep_overshoot(overshoot_ns);
|
||||||
|
|
||||||
|
next_frame += delay;
|
||||||
|
if (next_frame < now) { // some major slowdown happened; we couldn't keep up
|
||||||
|
next_frame = now + delay;
|
||||||
}
|
}
|
||||||
next_frame = now + delay;
|
|
||||||
|
|
||||||
std::shared_ptr<platf::img_t> img_out;
|
std::shared_ptr<platf::img_t> img_out;
|
||||||
auto status = snapshot(pull_free_image_cb, img_out, 1000ms, *cursor);
|
auto status = snapshot(pull_free_image_cb, img_out, 1000ms, *cursor);
|
||||||
|
|||||||
@@ -481,17 +481,22 @@ namespace platf {
|
|||||||
capture(const push_captured_image_cb_t &push_captured_image_cb, const pull_free_image_cb_t &pull_free_image_cb, bool *cursor) override {
|
capture(const push_captured_image_cb_t &push_captured_image_cb, const pull_free_image_cb_t &pull_free_image_cb, bool *cursor) override {
|
||||||
auto next_frame = std::chrono::steady_clock::now();
|
auto next_frame = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
|
sleep_overshoot_tracker.reset();
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
auto now = std::chrono::steady_clock::now();
|
auto now = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
if (next_frame > now) {
|
if (next_frame > now) {
|
||||||
std::this_thread::sleep_for((next_frame - now) / 3 * 2);
|
std::this_thread::sleep_for(next_frame - now);
|
||||||
}
|
}
|
||||||
while (next_frame > now) {
|
now = std::chrono::steady_clock::now();
|
||||||
std::this_thread::sleep_for(1ns);
|
std::chrono::nanoseconds overshoot_ns = now - next_frame;
|
||||||
now = std::chrono::steady_clock::now();
|
log_sleep_overshoot(overshoot_ns);
|
||||||
|
|
||||||
|
next_frame += delay;
|
||||||
|
if (next_frame < now) { // some major slowdown happened; we couldn't keep up
|
||||||
|
next_frame = now + delay;
|
||||||
}
|
}
|
||||||
next_frame = now + delay;
|
|
||||||
|
|
||||||
std::shared_ptr<platf::img_t> img_out;
|
std::shared_ptr<platf::img_t> img_out;
|
||||||
auto status = snapshot(pull_free_image_cb, img_out, 1000ms, *cursor);
|
auto status = snapshot(pull_free_image_cb, img_out, 1000ms, *cursor);
|
||||||
@@ -622,17 +627,22 @@ namespace platf {
|
|||||||
capture(const push_captured_image_cb_t &push_captured_image_cb, const pull_free_image_cb_t &pull_free_image_cb, bool *cursor) override {
|
capture(const push_captured_image_cb_t &push_captured_image_cb, const pull_free_image_cb_t &pull_free_image_cb, bool *cursor) override {
|
||||||
auto next_frame = std::chrono::steady_clock::now();
|
auto next_frame = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
|
sleep_overshoot_tracker.reset();
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
auto now = std::chrono::steady_clock::now();
|
auto now = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
if (next_frame > now) {
|
if (next_frame > now) {
|
||||||
std::this_thread::sleep_for((next_frame - now) / 3 * 2);
|
std::this_thread::sleep_for(next_frame - now);
|
||||||
}
|
}
|
||||||
while (next_frame > now) {
|
now = std::chrono::steady_clock::now();
|
||||||
std::this_thread::sleep_for(1ns);
|
std::chrono::nanoseconds overshoot_ns = now - next_frame;
|
||||||
now = std::chrono::steady_clock::now();
|
log_sleep_overshoot(overshoot_ns);
|
||||||
|
|
||||||
|
next_frame += delay;
|
||||||
|
if (next_frame < now) { // some major slowdown happened; we couldn't keep up
|
||||||
|
next_frame = now + delay;
|
||||||
}
|
}
|
||||||
next_frame = now + delay;
|
|
||||||
|
|
||||||
std::shared_ptr<platf::img_t> img_out;
|
std::shared_ptr<platf::img_t> img_out;
|
||||||
auto status = snapshot(pull_free_image_cb, img_out, 1000ms, *cursor);
|
auto status = snapshot(pull_free_image_cb, img_out, 1000ms, *cursor);
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ namespace platf::dxgi {
|
|||||||
SetThreadExecutionState(ES_CONTINUOUS);
|
SetThreadExecutionState(ES_CONTINUOUS);
|
||||||
});
|
});
|
||||||
|
|
||||||
stat_trackers::min_max_avg_tracker<double> sleep_overshoot_tracker;
|
sleep_overshoot_tracker.reset();
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
// This will return false if the HDR state changes or for any number of other
|
// This will return false if the HDR state changes or for any number of other
|
||||||
@@ -184,16 +184,8 @@ namespace platf::dxgi {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
high_precision_sleep(sleep_period);
|
high_precision_sleep(sleep_period);
|
||||||
|
std::chrono::nanoseconds overshoot_ns = std::chrono::steady_clock::now() - sleep_target;
|
||||||
if (config::sunshine.min_log_level <= 1) {
|
log_sleep_overshoot(overshoot_ns);
|
||||||
// Print sleep overshoot stats to debug log every 20 seconds
|
|
||||||
auto print_info = [&](double min_overshoot, double max_overshoot, double avg_overshoot) {
|
|
||||||
auto f = stat_trackers::one_digit_after_decimal();
|
|
||||||
BOOST_LOG(debug) << "Sleep overshoot (min/max/avg): " << f % min_overshoot << "ms/" << f % max_overshoot << "ms/" << f % avg_overshoot << "ms";
|
|
||||||
};
|
|
||||||
std::chrono::nanoseconds overshoot_ns = std::chrono::steady_clock::now() - sleep_target;
|
|
||||||
sleep_overshoot_tracker.collect_and_callback_on_interval(overshoot_ns.count() / 1000000., print_info, 20s);
|
|
||||||
}
|
|
||||||
|
|
||||||
status = snapshot(pull_free_image_cb, img_out, 0ms, *cursor);
|
status = snapshot(pull_free_image_cb, img_out, 0ms, *cursor);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user