Skip to content

Commit

Permalink
Use predictive bandwidth analysis.
Browse files Browse the repository at this point in the history
  • Loading branch information
bitbound committed Mar 19, 2021
1 parent 6d389b4 commit 2d9d4e9
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 29 deletions.
11 changes: 10 additions & 1 deletion Desktop.Core/Services/DtoMessageHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Remotely.Shared.Models.RemoteControlDtos;
using Remotely.Shared.Utilities;
using System;
using System.Diagnostics;
using System.Threading.Tasks;

namespace Remotely.Desktop.Core.Services
Expand Down Expand Up @@ -162,8 +163,16 @@ private void HandleFrameReceived(Services.Viewer viewer)
{
for (int i = 0; i < 5; i++)
{
if (viewer.PendingSentFrames.TryDequeue(out _))
if (viewer.PendingSentFrames.TryDequeue(out var frame))
{
var roundtrip = (DateTimeOffset.Now - frame.Timestamp).TotalSeconds;
var bps = frame.FrameSize / (roundtrip / 2);

if (bps > viewer.PeakBytesPerSecond)
{
viewer.PeakBytesPerSecond = bps;
Debug.WriteLine($"Peak Mbps: {bps / 1024 / 1024 * 8}");
}
break;
}
}
Expand Down
32 changes: 10 additions & 22 deletions Desktop.Core/Services/ScreenCaster.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,8 @@ await viewer.SendScreenCapture(new CaptureFrame()
continue;
}

if (refreshNeeded && refreshTimer.Elapsed.TotalSeconds > 3)
if (refreshTimer.Elapsed.TotalSeconds > 10 ||
refreshNeeded && refreshTimer.Elapsed.TotalSeconds > 3)
{
viewer.Capturer.CaptureFullscreen = true;
}
Expand All @@ -155,44 +156,31 @@ await viewer.SendScreenCapture(new CaptureFrame()

if (diffArea.IsEmpty)
{
if (currentQuality < _maxQuality)
{
currentQuality++;
}
continue;
}


if (viewer.Capturer.CaptureFullscreen)
{
currentQuality = _maxQuality;
refreshTimer.Restart();
refreshNeeded = false;
}

if (viewer.PendingSentFrames.Count > 1)
{
refreshNeeded = true;
currentQuality = Math.Max(_minQuality, currentQuality - viewer.PendingSentFrames.Count);
}
using var clone = currentFrame.Clone(diffArea, currentFrame.PixelFormat);

if (viewer.PendingSentFrames.TryPeek(out var oldestFrame) &&
DateTimeOffset.Now - oldestFrame > TimeSpan.FromMilliseconds(100))
{
refreshNeeded = true;
currentQuality = Math.Max(_minQuality, currentQuality - 10);
}
else
if (viewer.PeakBytesPerSecond > 0)
{
currentQuality = Math.Min(_maxQuality, currentQuality + 5);
var expectedSize = clone.Height * clone.Width * 4 * .1;
var timeToSend = expectedSize / viewer.PeakBytesPerSecond;
currentQuality = Math.Max(_minQuality, Math.Min(_maxQuality, (int)((.1 / timeToSend) * _maxQuality)));
Debug.WriteLine($"Current Quality: {currentQuality}");
}

using var clone = currentFrame.Clone(diffArea, currentFrame.PixelFormat);

byte[] encodedImageBytes;
if (viewer.Capturer.CaptureFullscreen)
{
encodedImageBytes = ImageUtils.EncodeWithSkia(clone, SKEncodedImageFormat.Webp, currentQuality);
viewer.PeakBytesPerSecond = 0;
encodedImageBytes = ImageUtils.EncodeWithSkia(clone, SKEncodedImageFormat.Webp, _maxQuality);
}
else
{
Expand Down
10 changes: 5 additions & 5 deletions Desktop.Core/Services/Viewer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public bool IsStalled
{
get
{
return PendingSentFrames.TryPeek(out var result) && DateTimeOffset.Now - result > TimeSpan.FromSeconds(15);
return PendingSentFrames.TryPeek(out var result) && DateTimeOffset.Now - result.Timestamp > TimeSpan.FromSeconds(15);
}
}

Expand All @@ -64,12 +64,12 @@ public bool IsUsingWebRtcVideo

public string Name { get; set; }

public ConcurrentQueue<DateTimeOffset> PendingSentFrames { get; } = new ConcurrentQueue<DateTimeOffset>();
public double PeakBytesPerSecond { get; set; }
public ConcurrentQueue<SentFrame> PendingSentFrames { get; } = new();

public WebRtcSession RtcSession { get; set; }

public string ViewerConnectionID { get; set; }

private IAudioCapturer AudioCapturer { get; }

private ICasterSocket CasterSocket { get; }
Expand Down Expand Up @@ -212,7 +212,7 @@ public async Task SendMachineName(string machineName)

public async Task SendScreenCapture(CaptureFrame screenFrame)
{
PendingSentFrames.Enqueue(DateTimeOffset.Now);
PendingSentFrames.Enqueue(new SentFrame(DateTimeOffset.Now, screenFrame.EncodedImageBytes.Length));

var left = screenFrame.Left;
var top = screenFrame.Top;
Expand Down Expand Up @@ -279,7 +279,7 @@ public async Task SendWindowsSessions()
public void ThrottleIfNeeded()
{
TaskHelper.DelayUntil(() =>
!PendingSentFrames.TryPeek(out var result) || DateTimeOffset.Now - result < TimeSpan.FromSeconds(1),
!PendingSentFrames.TryPeek(out var result) || DateTimeOffset.Now - result.Timestamp < TimeSpan.FromSeconds(1),
TimeSpan.MaxValue);
}

Expand Down
2 changes: 1 addition & 1 deletion Desktop.Core/Services/WebRtcSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ public async Task Init(IceServerModel[] iceServers)
public Task SendDto<T>(T dto) where T : BaseDto
{
CaptureChannel.SendMessage(MessagePackSerializer.Serialize(dto));
return TaskHelper.DelayUntilAsync(() => CurrentBuffer < 64, TimeSpan.FromSeconds(5));
return Task.CompletedTask;
}

public async Task SetRemoteDescription(string type, string sdp)
Expand Down
20 changes: 20 additions & 0 deletions Shared/Models/SentFrame.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Remotely.Shared.Models
{
public struct SentFrame
{
public SentFrame(DateTimeOffset timestamp, int frameSize)
{
Timestamp = timestamp;
FrameSize = frameSize;
}

public DateTimeOffset Timestamp { get; }
public double FrameSize { get; }
}
}

0 comments on commit 2d9d4e9

Please sign in to comment.