Throttling adjustments. Refactoring and cleanup.

This commit is contained in:
Jared Goodwin 2020-01-17 00:06:05 -08:00
parent 071fe5df29
commit 3082ed9773
24 changed files with 2106 additions and 128 deletions

View File

@ -50,17 +50,6 @@ namespace Remotely.Agent
SetWorkingDirectory();
var argDict = ProcessArgs(args);
JsonConvert.DefaultSettings = () =>
{
var settings = new JsonSerializerSettings();
settings.Error = (sender, arg) =>
{
arg.ErrorContext.Handled = true;
};
return settings;
};
if (argDict.ContainsKey("update"))
{
Updater.CoreUpdate();

View File

@ -73,7 +73,7 @@ namespace Remotely.ScreenCast.Core.Capture
{
try
{
if (viewer.Latency > 30000)
if (viewer.IsStalled())
{
// Viewer isn't responding. Abort sending.
break;
@ -88,19 +88,9 @@ namespace Remotely.ScreenCast.Core.Capture
fpsQueue.Enqueue(DateTime.Now);
Debug.WriteLine($"Capture FPS: {fpsQueue.Count}");
}
if (viewer.OutputBuffer > 150_000)
{
Debug.WriteLine($"Waiting for buffer to clear. Size: {viewer.OutputBuffer}");
await Task.Delay(50);
continue;
}
if (viewer.RtcSession?.CurrentBuffer > 100_000)
{
Debug.WriteLine($"Throttling output due to WebRTC buffer. Size: {viewer.RtcSession.CurrentBuffer}");
await Task.Delay((int)(viewer.RtcSession.CurrentBuffer - 100_000));
}
await viewer.ThrottleIfNeeded();
capturer.GetNextFrame();
@ -118,10 +108,10 @@ namespace Remotely.ScreenCast.Core.Capture
capturer.CaptureFullscreen = false;
}
if (viewer.AutoAdjustQuality && viewer.Latency > 1000)
if (viewer.ShouldAdjustQuality())
{
var quality = (int)(viewer.ImageQuality * 1000 / viewer.Latency);
Debug.WriteLine($"Auto-adjusting image quality. Latency: {viewer.Latency}. Quality: {quality}");
Logger.Debug($"Auto-adjusting image quality. Latency: {viewer.Latency}. Quality: {quality}");
encodedImageBytes = ImageUtils.EncodeBitmap(newImage, new EncoderParameters()
{
Param = new[]
@ -137,16 +127,18 @@ namespace Remotely.ScreenCast.Core.Capture
if (encodedImageBytes?.Length > 0)
{
if (viewer.RtcSession.IsDataChannelOpen)
if (viewer.IsUsingWebRtc())
{
viewer.RtcSession.SendCaptureFrame(diffArea.Left, diffArea.Top, diffArea.Width, diffArea.Height, encodedImageBytes);
viewer.WebSocketBuffer = 0;
viewer.Latency = 0;
}
else
{
await casterSocket.SendScreenCapture(encodedImageBytes, viewerID, diffArea.Left, diffArea.Top, diffArea.Width, diffArea.Height, DateTime.UtcNow);
viewer.Latency += 300;
viewer.OutputBuffer += encodedImageBytes.Length;
// Shave some off so it doesn't get deadlocked by dropped frames.
viewer.WebSocketBuffer += (int)(encodedImageBytes.Length * .9);
}
}
}
@ -165,6 +157,8 @@ namespace Remotely.ScreenCast.Core.Capture
Logger.Write($"Ended screen cast. Requester: {requesterName}. Viewer ID: {viewerID}.");
viewers.TryRemove(viewerID, out _);
viewer.Dispose();
capturer.Dispose();
// Close if no one is viewing.

View File

@ -316,7 +316,7 @@ namespace Remotely.ScreenCast.Core.Communication
{
var latency = DateTime.UtcNow - sentTime;
viewer.Latency = latency.TotalMilliseconds;
viewer.OutputBuffer -= bytesReceived;
viewer.WebSocketBuffer = Math.Max(0, viewer.WebSocketBuffer - bytesReceived);
}
});

View File

@ -1,6 +1,7 @@
using MessagePack;
using Microsoft.MixedReality.WebRTC;
using Remotely.ScreenCast.Core.Models;
using Remotely.ScreenCast.Core.Services;
using System;
using System.Collections.Generic;
using System.Diagnostics;
@ -26,8 +27,16 @@ namespace Remotely.ScreenCast.Core.Communication
PeerConnection.AddIceCandidate(sdpMid, sdpMlineIndex, candidate);
}
public void Dispose()
{
PeerConnection?.Dispose();
CaptureChannel?.Dispose();
}
public async Task Init()
{
CaptureChannel?.Dispose();
PeerConnection?.Dispose();
PeerConnection = new PeerConnection();
var config = new PeerConnectionConfiguration()
@ -51,7 +60,6 @@ namespace Remotely.ScreenCast.Core.Communication
CaptureChannel.StateChanged += CaptureChannel_StateChanged;
PeerConnection.CreateOffer();
}
public void SendCaptureFrame(int left, int top, int width, int height, byte[] imageBytes)
{
CaptureChannel.SendMessage(MessagePackSerializer.Serialize(new FrameInfo()
@ -75,39 +83,43 @@ namespace Remotely.ScreenCast.Core.Communication
private void CaptureChannel_MessageReceived(byte[] obj)
{
Debug.WriteLine($"DataChannel message received. Size: {obj.Length}");
Logger.Debug($"DataChannel message received. Size: {obj.Length}");
}
private void CaptureChannel_StateChanged()
private async void CaptureChannel_StateChanged()
{
Debug.WriteLine($"DataChannel state changed. New State: {CaptureChannel.State}");
Logger.Debug($"DataChannel state changed. New State: {CaptureChannel.State}");
if (CaptureChannel.State == DataChannel.ChannelState.Closed)
{
await Init();
}
}
private void DataChannel_BufferingChanged(ulong previous, ulong current, ulong limit)
{
Debug.WriteLine($"DataChannel buffering changed. Previous: {previous}. Current: {current}. Limit: {limit}.");
Logger.Debug($"DataChannel buffering changed. Previous: {previous}. Current: {current}. Limit: {limit}.");
CurrentBuffer = current;
}
private void PeerConnection_Connected()
{
Debug.WriteLine("PeerConnection connected.");
Logger.Debug("PeerConnection connected.");
}
private void PeerConnection_IceCandidateReadytoSend(string candidate, int sdpMlineindex, string sdpMid)
{
Debug.WriteLine("Ice candidate ready to send.");
Logger.Debug("Ice candidate ready to send.");
IceCandidateReady?.Invoke(this, (candidate, sdpMlineindex, sdpMid));
}
private void PeerConnection_IceStateChanged(IceConnectionState newState)
{
Debug.WriteLine($"Ice state changed to {newState}.");
Logger.Debug($"Ice state changed to {newState}.");
}
private void PeerConnection_LocalSdpReadytoSend(string type, string sdp)
{
Debug.WriteLine($"Local SDP ready.");
Logger.Debug($"Local SDP ready.");
LocalSdpReady?.Invoke(this, sdp);
}
}

View File

@ -1,6 +1,7 @@
using Remotely.ScreenCast.Core.Capture;
using Remotely.ScreenCast.Core.Communication;
using Remotely.ScreenCast.Core.Interfaces;
using Remotely.ScreenCast.Core.Services;
using System;
using System.Collections.Generic;
using System.Drawing;
@ -10,7 +11,7 @@ using System.Threading.Tasks;
namespace Remotely.ScreenCast.Core.Models
{
public class Viewer
public class Viewer : IDisposable
{
private long imageQuality = 50;
@ -54,8 +55,44 @@ namespace Remotely.ScreenCast.Core.Models
public double Latency { get; set; } = 1;
public string Name { get; set; }
public int OutputBuffer { get; set; }
public int WebSocketBuffer { get; set; }
public WebRtcSession RtcSession { get; set; }
public string ViewerConnectionID { get; set; }
public void Dispose()
{
EncoderParams?.Dispose();
Capturer?.Dispose();
RtcSession?.Dispose();
}
public bool IsStalled()
{
return RtcSession?.IsDataChannelOpen != true && Latency > 30000;
}
public async Task ThrottleIfNeeded()
{
if (IsUsingWebRtc() && RtcSession?.CurrentBuffer > 100_000)
{
Logger.Debug($"Throttling output due to WebRTC buffer. Size: {RtcSession.CurrentBuffer}");
await Task.Delay((int)Math.Ceiling((RtcSession.CurrentBuffer - 100_000) * .0025));
}
else if (!IsUsingWebRtc() && WebSocketBuffer > 150_000)
{
Logger.Debug($"Throttling output due to websocket buffer. Size: {WebSocketBuffer}");
await Task.Delay((int)Math.Ceiling((WebSocketBuffer - 150_000) * .0025));
}
}
public bool ShouldAdjustQuality()
{
return !IsUsingWebRtc() && AutoAdjustQuality && Latency > 1000;
}
public bool IsUsingWebRtc()
{
return RtcSession?.IsDataChannelOpen == true;
}
}
}

View File

@ -1,45 +1,38 @@
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
namespace Remotely.ScreenCast.Core.Services
{
public static class Logger
{
public static object WriteLock { get; } = new object();
private static string LogPath => Path.Combine(Path.GetTempPath(), "Remotely_Logs.log");
private static object WriteLock { get; } = new object();
public static void Debug(string message)
{
lock (WriteLock)
{
#if DEBUG
CheckLogFileExists();
File.AppendAllText(LogPath, $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}\t[DEBUG]\t{message}{Environment.NewLine}");
#endif
System.Diagnostics.Debug.WriteLine(message);
}
}
public static void Write(string message)
{
try
{
lock (WriteLock)
{
var path = Path.Combine(Path.GetTempPath(), "Remotely_Logs.log");
if (!File.Exists(path))
{
File.Create(path).Close();
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
Process.Start("sudo", $"chmod 666 {path}").WaitForExit();
}
}
if (File.Exists(path))
{
var fi = new FileInfo(path);
while (fi.Length > 1000000)
{
var content = File.ReadAllLines(path);
File.WriteAllLines(path, content.Skip(10));
fi = new FileInfo(path);
}
}
File.AppendAllText(path, $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}\t[INFO]\t{message}{Environment.NewLine}");
CheckLogFileExists();
File.AppendAllText(LogPath, $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}\t[INFO]\t{message}{Environment.NewLine}");
Console.WriteLine(message);
}
}
@ -52,39 +45,13 @@ namespace Remotely.ScreenCast.Core.Services
{
try
{
var exception = ex;
var path = Path.Combine(Path.GetTempPath(), "Remotely_Logs.log");
CheckLogFileExists();
if (!File.Exists(path))
{
File.Create(path).Close();
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
Process.Start("sudo", $"chmod 666 {path}").WaitForExit();
}
}
var exception = ex;
while (exception != null)
{
var jsonError = new
{
Type = "Error",
Timestamp = DateTime.Now.ToString(),
Message = exception?.Message,
Source = exception?.Source,
StackTrace = exception?.StackTrace,
};
if (File.Exists(path))
{
var fi = new FileInfo(path);
while (fi.Length > 1000000)
{
var content = File.ReadAllLines(path);
File.WriteAllLines(path, content.Skip(10));
fi = new FileInfo(path);
}
}
File.AppendAllText(path, $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}\t[ERROR]\t{exception?.Message}\t{exception?.StackTrace}\t{exception?.Source}{Environment.NewLine}");
File.AppendAllText(LogPath, $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}\t[ERROR]\t{exception?.Message}\t{exception?.StackTrace}\t{exception?.Source}{Environment.NewLine}");
Console.WriteLine(exception.Message);
exception = exception.InnerException;
}
@ -92,5 +59,27 @@ namespace Remotely.ScreenCast.Core.Services
catch { }
}
}
private static void CheckLogFileExists()
{
if (!File.Exists(LogPath))
{
File.Create(LogPath).Close();
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
Process.Start("sudo", $"chmod 666 {LogPath}").WaitForExit();
}
}
if (File.Exists(LogPath))
{
var fi = new FileInfo(LogPath);
while (fi.Length > 1000000)
{
var content = File.ReadAllLines(LogPath);
File.WriteAllLines(LogPath, content.Skip(10));
fi = new FileInfo(LogPath);
}
}
}
}
}

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<PublishProtocol>FileSystem</PublishProtocol>
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
<TargetFramework>netcoreapp3.1</TargetFramework>
<PublishDir>..\Agent\bin\Release\netcoreapp3.1\win10-x64\publish\ScreenCast</PublishDir>
<SelfContained>false</SelfContained>
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
<PublishSingleFile>True</PublishSingleFile>
<PublishReadyToRun>False</PublishReadyToRun>
</PropertyGroup>
</Project>

View File

@ -33,12 +33,14 @@
<script src="~/lib/signalr/signalr.js"></script>
<script src="~/lib/signalr/msgpack5.js"></script>
<script src="~/lib/signalr/signalr-protocol-msgpack.js"></script>
<script src="~/lib/msgpack/msgpack.js"></script>
</environment>
<environment exclude="Development">
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/signalr/signalr.min.js"></script>
<script src="~/lib/signalr/msgpack5.min.js"></script>
<script src="~/lib/signalr/signalr-protocol-msgpack.min.js"></script>
<script src="~/lib/msgpack/msgpack.min.js"></script>
</environment>
</head>
<body>

View File

@ -19,26 +19,28 @@
</div>
</div>
</div>
<table id="deviceGrid" class="table table-hover table-striped">
<thead>
<tr>
<th>Online</th>
<th>Device Name</th>
<th>Alias</th>
<th>Current User</th>
<th>Last Online</th>
<th>Platform</th>
<th>OS Description</th>
<th>Free Storage</th>
<th>Total Storage (GB)</th>
<th>Free Memory</th>
<th>Total Memory (GB)</th>
<th></th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<div style="overflow-y: scroll">
<table id="deviceGrid" class="table table-hover table-striped">
<thead>
<tr>
<th>Online</th>
<th>Device Name</th>
<th>Alias</th>
<th>Current User</th>
<th>Last Online</th>
<th>Platform</th>
<th>OS Description</th>
<th>Free Storage</th>
<th>Total Storage (GB)</th>
<th>Free Memory</th>
<th>Total Memory (GB)</th>
<th></th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</div>

View File

@ -89,6 +89,10 @@
<None Include="wwwroot\lib\%40types\jquery\README.md" />
<None Include="wwwroot\lib\%40types\sizzle\LICENSE" />
<None Include="wwwroot\lib\%40types\sizzle\README.md" />
<None Include="wwwroot\lib\msgpack\msgpack.js" />
<None Include="wwwroot\lib\msgpack\msgpack.js.map" />
<None Include="wwwroot\lib\msgpack\msgpack.min.js" />
<None Include="wwwroot\lib\msgpack\msgpack.min.js.map" />
<None Include="wwwroot\lib\fontawesome\webfonts\fa-brands-400.svg" />
<None Include="wwwroot\lib\fontawesome\webfonts\fa-brands-400.woff2" />
<None Include="wwwroot\lib\fontawesome\webfonts\fa-regular-400.svg" />

View File

@ -8,5 +8,8 @@
"@types/bootstrap": "^4.3.1",
"@types/jquery": "^3.3.31",
"msgpack5": "^4.2.1"
},
"dependencies": {
"@msgpack/msgpack": "^1.11.0"
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -18,6 +18,9 @@ export function EvaluateCurrentCommandText() {
DisplayCommandShortcuts(UI.ConsoleTextArea.value.slice(1));
return;
}
if (UI.ConsoleTextArea.value.endsWith(" ")) {
return;
}
var relevantText = GetRelevantCommandText(UI.ConsoleTextArea.value);
var commandInputArray = Main.Utilities.Split(relevantText, " ", 2);
var matchingCommands = GetCommandCompletions(commandInputArray[0]);

File diff suppressed because one or more lines are too long

View File

@ -21,6 +21,9 @@ export function EvaluateCurrentCommandText() {
DisplayCommandShortcuts(UI.ConsoleTextArea.value.slice(1));
return;
}
if (UI.ConsoleTextArea.value.endsWith(" ")) {
return;
}
var relevantText = GetRelevantCommandText(UI.ConsoleTextArea.value);
var commandInputArray = Main.Utilities.Split(relevantText, " ", 2);
var matchingCommands = GetCommandCompletions(commandInputArray[0]);

View File

@ -37,6 +37,9 @@ export class RCBrowserSockets {
if (candidate) {
this.Connection.invoke("SendIceCandidateToAgent", candidate.candidate, candidate.sdpMLineIndex, candidate.sdpMid);
}
else {
this.Connection.invoke("SendIceCandidateToAgent", "", 0, "");
}
}
SendRtcAnswer(sessionDescription) {
this.Connection.invoke("SendRtcAnswerToAgent", sessionDescription.sdp);
@ -136,6 +139,7 @@ export class RCBrowserSockets {
UI.Screen2DContext.clearRect(0, 0, width, height);
});
hubConnection.on("ScreenCapture", (buffer, left, top, width, height, captureTime) => {
console.log("Websocket frame received.");
this.SendLatencyUpdate(captureTime, buffer.byteLength);
var url = window.URL.createObjectURL(new Blob([buffer]));
var img = document.createElement("img");

File diff suppressed because one or more lines are too long

View File

@ -51,6 +51,9 @@ export class RCBrowserSockets {
if (candidate) {
this.Connection.invoke("SendIceCandidateToAgent", candidate.candidate, candidate.sdpMLineIndex, candidate.sdpMid);
}
else {
this.Connection.invoke("SendIceCandidateToAgent", "", 0, "");
}
}
SendRtcAnswer(sessionDescription: RTCSessionDescription) {
this.Connection.invoke("SendRtcAnswerToAgent", sessionDescription.sdp);
@ -152,7 +155,7 @@ export class RCBrowserSockets {
UI.Screen2DContext.clearRect(0, 0, width, height);
});
hubConnection.on("ScreenCapture", (buffer: Uint8Array, left:number, top:number, width:number, height:number, captureTime: Date) => {
console.log("Websocket frame received.");
this.SendLatencyUpdate(captureTime, buffer.byteLength);
var url = window.URL.createObjectURL(new Blob([buffer]));

View File

@ -3,7 +3,7 @@ import * as Utilities from "../Utilities.js";
import { RemoteControl } from "./Main.js";
export class RtcSession {
constructor() {
this.MsgPack5 = new window['msgpack5']();
this.MessagePack = window['MessagePack'];
}
Init() {
this.PeerConnection = new RTCPeerConnection({
@ -24,8 +24,13 @@ export class RtcSession {
this.DataChannel.onerror = (ev) => {
console.log("Data channel error.", ev.error);
};
this.DataChannel.onmessage = (ev) => {
var frameInfo = this.MsgPack5.decode(ev.data);
this.DataChannel.onmessage = async (ev) => {
var data = ev.data;
if (ev.data.arrayBuffer) {
data = await ev.data.arrayBuffer();
}
console.log("WebRTC frame received. Size: " + data.byteLength);
var frameInfo = this.MessagePack.decode(data);
var url = window.URL.createObjectURL(new Blob([frameInfo.ImageBytes]));
var img = document.createElement("img");
img.onload = () => {

View File

@ -1 +1 @@
{"version":3,"file":"RtcSession.js","sourceRoot":"","sources":["RtcSession.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"RtcSession.js","sourceRoot":"","sources":["RtcSession.ts"],"names":[],"mappings":"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"}

View File

@ -6,7 +6,7 @@ import { RemoteControl } from "./Main.js";
export class RtcSession {
PeerConnection: RTCPeerConnection;
DataChannel: RTCDataChannel;
MsgPack5: any = new window['msgpack5']();
MessagePack: any = window['MessagePack'];
Init() {
this.PeerConnection = new RTCPeerConnection({
iceServers: [
@ -27,8 +27,14 @@ export class RtcSession {
this.DataChannel.onerror = (ev) => {
console.log("Data channel error.", ev.error);
};
this.DataChannel.onmessage = (ev) => {
var frameInfo = this.MsgPack5.decode(ev.data) as FrameInfo;
this.DataChannel.onmessage = async (ev) => {
var data = ev.data;
if (ev.data.arrayBuffer) {
data = await ev.data.arrayBuffer();
}
console.log("WebRTC frame received. Size: " + data.byteLength);
var frameInfo = this.MessagePack.decode(data) as FrameInfo;
var url = window.URL.createObjectURL(new Blob([frameInfo.ImageBytes]));
var img = document.createElement("img");
img.onload = () => {