Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 0 additions & 21 deletions docs/source/about/advanced_usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -357,27 +357,6 @@ resolutions
3840x1600,
]

dwmflush
^^^^^^^^

**Description**
Invoke DwmFlush() to sync screen capture to the Windows presentation interval.

.. Caution:: Applies to Windows only. Alleviates visual stuttering during mouse movement.
If enabled, this feature will automatically deactivate if the client framerate exceeds
the host monitor's current refresh rate.

.. Note:: If you disable this option, you may see video stuttering during mouse movement in certain scenarios.
It is recommended to leave enabled when possible.

**Default**
``enabled``

**Example**
.. code-block:: text

dwmflush = enabled

Audio
-----

Expand Down
8 changes: 3 additions & 5 deletions src/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -314,10 +314,9 @@ video_t video {
-1,
}, // vt

{}, // encoder
{}, // adapter_name
{}, // output_name
true // dwmflush
{}, // encoder
{}, // adapter_name
{}, // output_name
};

audio_t audio {};
Expand Down Expand Up @@ -834,7 +833,6 @@ void apply_config(std::unordered_map<std::string, std::string> &&vars) {
string_f(vars, "encoder", video.encoder);
string_f(vars, "adapter_name", video.adapter_name);
string_f(vars, "output_name", video.output_name);
bool_f(vars, "dwmflush", video.dwmflush);

path_f(vars, "pkey", nvhttp.pkey);
path_f(vars, "cert", nvhttp.cert);
Expand Down
1 change: 0 additions & 1 deletion src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ struct video_t {
std::string encoder;
std::string adapter_name;
std::string output_name;
bool dwmflush;
};

struct audio_t {
Expand Down
1 change: 0 additions & 1 deletion src/platform/windows/display.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,6 @@ class duplication_t {
public:
dup_t dup;
bool has_frame {};
bool use_dwmflush {};

capture_e next_frame(DXGI_OUTDUPL_FRAME_INFO &frame_info, std::chrono::milliseconds timeout, resource_t::pointer *res_p);
capture_e reset(dup_t::pointer dup_p = dup_t::pointer());
Expand Down
35 changes: 7 additions & 28 deletions src/platform/windows/display_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,6 @@ namespace platf::dxgi {
namespace bp = boost::process;

capture_e duplication_t::next_frame(DXGI_OUTDUPL_FRAME_INFO &frame_info, std::chrono::milliseconds timeout, resource_t::pointer *res_p) {
auto capture_status = release_frame();
if(capture_status != capture_e::ok) {
return capture_status;
}

if(use_dwmflush) {
DwmFlush();
}

auto status = dup->AcquireNextFrame(timeout.count(), &frame_info, res_p);

switch(status) {
Expand All @@ -46,6 +37,7 @@ capture_e duplication_t::next_frame(DXGI_OUTDUPL_FRAME_INFO &frame_info, std::ch
case WAIT_ABANDONED:
case DXGI_ERROR_ACCESS_LOST:
case DXGI_ERROR_ACCESS_DENIED:
case DXGI_ERROR_INVALID_CALL:
return capture_e::reinit;
default:
BOOST_LOG(error) << "Couldn't acquire next frame [0x"sv << util::hex(status).to_string_view();
Expand Down Expand Up @@ -114,32 +106,34 @@ capture_e display_base_t::capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<:
return platf::capture_e::reinit;
}

// If the wait time is between 1 us and 1 second, wait the specified time
// If the wait time is between 1 us and the frame to frame delay interval, wait the specified time
// and offset the next frame time from the exact current frame time target.
auto wait_time_us = std::chrono::duration_cast<std::chrono::microseconds>(next_frame - std::chrono::steady_clock::now()).count();
if(wait_time_us > 0 && wait_time_us < 1000000) {
if(wait_time_us > 0 && wait_time_us < std::chrono::duration_cast<std::chrono::microseconds>(delay).count()) {
LARGE_INTEGER due_time { .QuadPart = -10LL * wait_time_us };
SetWaitableTimer(timer, &due_time, 0, nullptr, nullptr, false);
WaitForSingleObject(timer, INFINITE);
next_frame += delay;
}
else {
// If the wait time is negative (meaning the frame is past due) or the
// computed wait time is beyond a second (meaning possible clock issues),
// computed wait time is beyond the delay interval (meaning possible clock issues),
// just capture the frame now and resynchronize the frame interval with
// the current time.
next_frame = std::chrono::steady_clock::now() + delay;
}

auto status = snapshot(img.get(), 1000ms, *cursor);
auto status = snapshot(img.get(), std::chrono::duration_cast<std::chrono::milliseconds>(delay / 2), *cursor);
switch(status) {
case platf::capture_e::reinit:
case platf::capture_e::error:
return status;
case platf::capture_e::timeout:
next_frame -= (delay / 2); // try to reacquire with remaining delay interval (or force resync)
img = snapshot_cb(img, false);
break;
case platf::capture_e::ok:
dup.release_frame();
img = snapshot_cb(img, true);
break;
default:
Expand Down Expand Up @@ -427,21 +421,6 @@ int display_base_t::init(const ::video::config_t &config, const std::string &dis
<< "Offset : "sv << offset_x << 'x' << offset_y << std::endl
<< "Virtual Desktop : "sv << env_width << 'x' << env_height;

// Enable DwmFlush() only if the current refresh rate can match the client framerate.
auto refresh_rate = config.framerate;
DWM_TIMING_INFO timing_info;
timing_info.cbSize = sizeof(timing_info);

status = DwmGetCompositionTimingInfo(NULL, &timing_info);
if(FAILED(status)) {
BOOST_LOG(warning) << "Failed to detect active refresh rate.";
}
else {
refresh_rate = std::round((double)timing_info.rateRefresh.uiNumerator / (double)timing_info.rateRefresh.uiDenominator);
}

dup.use_dwmflush = config::video.dwmflush && !(config.framerate > refresh_rate) ? true : false;

// Bump up thread priority
{
const DWORD flags = TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY;
Expand Down
13 changes: 0 additions & 13 deletions src_assets/common/assets/web/config.html
Original file line number Diff line number Diff line change
Expand Up @@ -416,18 +416,6 @@ <h1 class="my-4">Configuration</h1>
tools\dxgi-info.exe<br />
</div>
</div>
<!--DwmFlush-->
<div class="mb-3" v-if="platform === 'windows'">
<label for="dwmflush" class="form-label">DwmFlush</label>
<select id="dwmflush" class="form-select" v-model="config.dwmflush">
<option value="disabled">Disabled</option>
<option value="enabled">Enabled</option>
</select>
<div class="form-text">
Improves capture latency/smoothness during mouse movement.<br />
Disable if you encounter any VSync-related issues.
</div>
</div>
<div class="mb-3" class="config-page" v-if="platform === 'linux'">
<label for="output_name" class="form-label">Monitor number</label>
<input
Expand Down Expand Up @@ -900,7 +888,6 @@ <h1 class="my-4">Configuration</h1>
this.config.key_rightalt_to_key_win || "disabled";
this.config.gamepad = this.config.gamepad || "x360";
this.config.upnp = this.config.upnp || "disabled";
this.config.dwmflush = this.config.dwmflush || "enabled";
this.config.min_log_level = this.config.min_log_level || 2;
this.config.origin_pin_allowed =
this.config.origin_pin_allowed || "pc";
Expand Down