Throttling and capture tweaks.

This commit is contained in:
Jared Goodwin 2021-08-27 14:46:26 -07:00
parent 14291e0920
commit e68c05f1fc
3 changed files with 36 additions and 52 deletions

View File

@ -94,7 +94,7 @@ namespace Remotely.Desktop.Core.Services
ImageQuality = Math.Min(DefaultQuality, ImageQuality + 2);
}
// Limit to 20 FPS.
// Limit FPS.
_ = TaskHelper.DelayUntil(() =>
!PendingSentFrames.TryPeek(out var result) || DateTimeOffset.Now - result.Timestamp > TimeSpan.FromMilliseconds(50),
TimeSpan.FromSeconds(5));

View File

@ -82,66 +82,47 @@ namespace Remotely.Desktop.Win.Services
{
lock (_screenBoundsLock)
{
Bitmap returnFrame = null;
var frameCompletedEvent = new ManualResetEventSlim();
// This is necessary to ensure SwitchToInputDesktop works. Threads
// that have hooks in the current desktop will not succeed.
var captureThread = new Thread(() =>
try
{
try
{
Win32Interop.SwitchToInputDesktop();
Win32Interop.SwitchToInputDesktop();
if (NeedsInit)
if (NeedsInit)
{
Logger.Write("Init needed in GetNextFrame.");
Init();
}
// Sometimes DX will result in a timeout, even when there are changes
// on the screen. I've observed this when a laptop lid is closed, or
// on some machines that aren't connected to a monitor. This will
// have it fall back to BitBlt in those cases.
// TODO: Make DX capture work with changed screen orientation.
if (_directxScreens.TryGetValue(SelectedScreen, out var dxDisplay) &&
dxDisplay.Rotation == DisplayModeRotation.Identity)
{
var (result, frame) = GetDirectXFrame();
if (result == GetDirectXFrameResult.Timeout)
{
Logger.Write("Init needed in GetNextFrame.");
Init();
NeedsInit = false;
return null;
}
// Sometimes DX will result in a timeout, even when there are changes
// on the screen. I've observed this when a laptop lid is closed, or
// on some machines that aren't connected to a monitor. This will
// have it fall back to BitBlt in those cases.
// TODO: Make DX capture work with changed screen orientation.
if (_directxScreens.TryGetValue(SelectedScreen, out var dxDisplay) &&
dxDisplay.Rotation == DisplayModeRotation.Identity)
if (result == GetDirectXFrameResult.Success)
{
var (result, frame) = GetDirectXFrame();
if (result == GetDirectXFrameResult.Timeout)
{
return;
}
if (result == GetDirectXFrameResult.Success)
{
returnFrame = frame;
return;
}
return frame;
}
returnFrame = GetBitBltFrame();
}
catch (Exception e)
{
Logger.Write(e);
NeedsInit = true;
}
finally
{
frameCompletedEvent.Set();
}
});
captureThread.SetApartmentState(ApartmentState.STA);
captureThread.Start();
return GetBitBltFrame();
frameCompletedEvent.Wait();
}
catch (Exception e)
{
Logger.Write(e);
NeedsInit = true;
}
return returnFrame;
return null;
}
}
@ -168,6 +149,8 @@ namespace Remotely.Desktop.Win.Services
InitDirectX();
ScreenChanged?.Invoke(this, CurrentScreenBounds);
NeedsInit = false;
}
public void SetSelectedScreen(string displayName)

View File

@ -207,16 +207,17 @@ namespace Remotely.Shared.Win32
public static bool SwitchToInputDesktop()
{
var inputDesktop = OpenInputDesktop();
try
{
CloseDesktop(_lastInputDesktop);
var inputDesktop = OpenInputDesktop();
if (inputDesktop == IntPtr.Zero)
{
return false;
}
var result = SetThreadDesktop(inputDesktop) && SwitchDesktop(inputDesktop);
CloseDesktop(_lastInputDesktop);
_lastInputDesktop = inputDesktop;
return result;
}