Remove Latency updates.

This commit is contained in:
Jared Goodwin 2020-04-05 17:43:36 -07:00
parent 95e0d284ab
commit b5810fd149
11 changed files with 51 additions and 52 deletions

View File

@ -123,9 +123,9 @@ namespace Remotely.ScreenCast.Core.Communication
await Connection.SendAsync("SendRtcOfferToBrowser", sdp, viewerID);
}
public async Task SendScreenCapture(byte[] captureBytes, string viewerID, int left, int top, int width, int height, DateTime captureTime)
public async Task SendScreenCapture(byte[] captureBytes, string viewerID, int left, int top, int width, int height, long imageQuality)
{
await Connection.SendAsync("SendScreenCapture", captureBytes, viewerID, left, top, width, height, captureTime);
await Connection.SendAsync("SendScreenCapture", captureBytes, viewerID, left, top, width, height, imageQuality);
}
public async Task SendScreenData(string selectedScreen, string[] displayNames, string viewerID)
@ -321,12 +321,10 @@ namespace Remotely.ScreenCast.Core.Communication
conductor.InvokeViewerRemoved(viewerID);
});
Connection.On("LatencyUpdate", (DateTime sentTime, int bytesReceived, string viewerID) =>
Connection.On("BufferUpdate", (int bytesReceived, string viewerID) =>
{
if (conductor.Viewers.TryGetValue(viewerID, out var viewer))
{
var latency = DateTime.UtcNow - sentTime;
viewer.Latency = latency.TotalMilliseconds;
viewer.WebSocketBuffer = Math.Max(0, viewer.WebSocketBuffer - bytesReceived);
}
});

View File

@ -61,7 +61,7 @@ namespace Remotely.ScreenCast.Core.Communication
CaptureChannel.StateChanged += CaptureChannel_StateChanged;
PeerConnection.CreateOffer();
}
public void SendCaptureFrame(int left, int top, int width, int height, byte[] imageBytes)
public void SendCaptureFrame(int left, int top, int width, int height, byte[] imageBytes, long imageQuality)
{
for (var i = 0; i < imageBytes.Length; i += 50_000)
{
@ -73,6 +73,7 @@ namespace Remotely.ScreenCast.Core.Communication
Height = height,
EndOfFrame = false,
ImageBytes = imageBytes.Skip(i).Take(50_000).ToArray(),
ImageQuality = imageQuality,
DtoType = Shared.Enums.DynamicDtoType.FrameInfo
}));
}
@ -83,6 +84,7 @@ namespace Remotely.ScreenCast.Core.Communication
Width = width,
Height = height,
EndOfFrame = true,
ImageQuality = imageQuality,
DtoType = Shared.Enums.DynamicDtoType.FrameInfo
}));
}

View File

@ -16,14 +16,8 @@ namespace Remotely.ScreenCast.Core.Models
public Viewer()
{
EncoderParams = new EncoderParameters();
ImageQuality = 60;
EncoderParams = new EncoderParameters()
{
Param = new[]
{
new EncoderParameter(Encoder.Quality, ImageQuality)
}
};
}
public bool AutoAdjustQuality { get; internal set; } = true;
public IScreenCapturer Capturer { get; set; }
@ -52,8 +46,6 @@ namespace Remotely.ScreenCast.Core.Models
EncoderParams.Param[0] = new EncoderParameter(Encoder.Quality, value);
}
}
public double Latency { get; set; } = 1;
public string Name { get; set; }
public int WebSocketBuffer { get; set; }
public WebRtcSession RtcSession { get; set; }
@ -66,30 +58,30 @@ namespace Remotely.ScreenCast.Core.Models
public bool IsStalled()
{
return RtcSession?.IsDataChannelOpen != true && Latency > 30000;
return RtcSession?.CurrentBuffer > 1_000_000 || WebSocketBuffer > 1_000_000;
}
public async Task ThrottleIfNeeded()
{
if (IsUsingWebRtc() && RtcSession?.CurrentBuffer > 100_000)
var currentBuffer = IsUsingWebRtc() ?
RtcSession.CurrentBuffer :
(ulong)WebSocketBuffer;
if (currentBuffer > 150_000)
{
ImageQuality -= 5;
Logger.Debug($"Auto-adjusting image quality for WebRTC. Latency: {Latency}. Quality: {ImageQuality}");
var delay = (int)Math.Ceiling((RtcSession.CurrentBuffer - 100_000) * .0025);
Logger.Debug($"Throttling output due to WebRTC buffer. Size: {RtcSession.CurrentBuffer}. Delay: {delay}");
await Task.Delay(delay);
}
else if (!IsUsingWebRtc() && WebSocketBuffer > 150_000)
{
ImageQuality -= 5;
Logger.Debug($"Auto-adjusting image quality for WebSocket. Latency: {Latency}. Quality: {ImageQuality}");
var delay = (int)Math.Ceiling((WebSocketBuffer - 150_000) * .0025);
Logger.Debug($"Throttling output due to websocket buffer. Size: {WebSocketBuffer}. Delay: {delay}");
if (AutoAdjustQuality)
{
ImageQuality -= 10;
Logger.Debug($"Auto-adjusting image quality. Quality: {ImageQuality}");
}
var delay = (int)Math.Ceiling((currentBuffer - 100_000) * .0025);
Logger.Debug($"Throttling output due to buffer size. Size: {currentBuffer}. Delay: {delay}");
await Task.Delay(delay);
}
else
{
ImageQuality = 60;
ImageQuality = Math.Min(ImageQuality + 10, 60);
}
}

View File

@ -93,7 +93,6 @@ namespace Remotely.ScreenCast.Core.Services
}
await viewer.ThrottleIfNeeded();
capturer.GetNextFrame();
@ -117,14 +116,12 @@ namespace Remotely.ScreenCast.Core.Services
{
if (viewer.IsUsingWebRtc())
{
viewer.RtcSession.SendCaptureFrame(diffArea.Left, diffArea.Top, diffArea.Width, diffArea.Height, encodedImageBytes);
viewer.RtcSession.SendCaptureFrame(diffArea.Left, diffArea.Top, diffArea.Width, diffArea.Height, encodedImageBytes, viewer.ImageQuality);
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;
await casterSocket.SendScreenCapture(encodedImageBytes, viewerID, diffArea.Left, diffArea.Top, diffArea.Width, diffArea.Height, viewer.ImageQuality);
// Shave some off so it doesn't get deadlocked by dropped frames.
viewer.WebSocketBuffer += (int)(encodedImageBytes.Length * .9);
}

View File

@ -142,9 +142,9 @@ namespace Remotely.Server.Services
return RCDeviceHub.Clients.Client(ScreenCasterID).SendAsync("ClipboardTransfer", transferText, typeText, Context.ConnectionId);
}
public Task SendLatencyUpdate(DateTime sentTime, int bytesRecieved)
public Task SendBufferUpdate(int bytesReceived)
{
return RCDeviceHub.Clients.Client(ScreenCasterID).SendAsync("LatencyUpdate", sentTime, bytesRecieved, Context.ConnectionId);
return RCDeviceHub.Clients.Client(ScreenCasterID).SendAsync("BufferUpdate", bytesReceived, Context.ConnectionId);
}
public Task SendQualityChange(int qualityLevel)

View File

@ -199,7 +199,7 @@ namespace Remotely.Server.Services
return Task.CompletedTask;
}
public Task SendScreenCapture(byte[] captureBytes, string rcBrowserHubConnectionID, int left, int top, int width, int height, DateTime captureTime)
public Task SendScreenCapture(byte[] captureBytes, string rcBrowserHubConnectionID, int left, int top, int width, int height, long imageQuality)
{
if (AppConfig.RecordRemoteControlSessions)
{
@ -207,7 +207,7 @@ namespace Remotely.Server.Services
rcBrowserHubConnectionID, SessionInfo.MachineName, SessionInfo.StartTime);
}
return RCBrowserHub.Clients.Client(rcBrowserHubConnectionID).SendAsync("ScreenCapture", captureBytes, left, top, width, height, captureTime);
return RCBrowserHub.Clients.Client(rcBrowserHubConnectionID).SendAsync("ScreenCapture", captureBytes, left, top, width, height, imageQuality);
}
public Task SendScreenDataToBrowser(string selectedDisplay, string[] displayNames, string browserHubConnectionId)

View File

@ -5,4 +5,5 @@
Width: number;
Height: number;
ImageBytes: Uint8Array;
ImageQuality: number;
}

View File

@ -51,8 +51,8 @@ export class RCBrowserSockets {
SendScreenCastRequestToDevice() {
this.Connection.invoke("SendScreenCastRequestToDevice", Remotely.ClientID, Remotely.RequesterName, Remotely.Mode);
}
SendLatencyUpdate(sentTime, bytesReceived) {
this.Connection.invoke("SendLatencyUpdate", sentTime, bytesReceived);
SendBufferUpdate(bytesReceived) {
this.Connection.invoke("SendBufferUpdate", bytesReceived);
}
SendSelectScreen(displayName) {
this.Connection.invoke("SelectScreen", displayName);
@ -144,9 +144,12 @@ export class RCBrowserSockets {
UI.ScreenViewer.height = height;
UI.Screen2DContext.clearRect(0, 0, width, height);
});
hubConnection.on("ScreenCapture", (buffer, left, top, width, height, captureTime) => {
hubConnection.on("ScreenCapture", (buffer, left, top, width, height, imageQuality) => {
//console.log("Websocket frame received.");
this.SendLatencyUpdate(captureTime, buffer.byteLength);
this.SendBufferUpdate(buffer.byteLength);
if (Number(UI.QualitySlider.value) != imageQuality) {
UI.QualitySlider.value = String(imageQuality);
}
var url = window.URL.createObjectURL(new Blob([buffer]));
var img = document.createElement("img");
img.onload = () => {

File diff suppressed because one or more lines are too long

View File

@ -65,8 +65,8 @@ export class RCBrowserSockets {
SendScreenCastRequestToDevice() {
this.Connection.invoke("SendScreenCastRequestToDevice", Remotely.ClientID, Remotely.RequesterName, Remotely.Mode);
}
SendLatencyUpdate(sentTime: Date, bytesReceived: number) {
this.Connection.invoke("SendLatencyUpdate", sentTime, bytesReceived);
SendBufferUpdate(bytesReceived: number) {
this.Connection.invoke("SendBufferUpdate", bytesReceived);
}
SendSelectScreen(displayName: string) {
this.Connection.invoke("SelectScreen", displayName);
@ -158,9 +158,13 @@ export class RCBrowserSockets {
UI.ScreenViewer.height = height;
UI.Screen2DContext.clearRect(0, 0, width, height);
});
hubConnection.on("ScreenCapture", (buffer: Uint8Array, left:number, top:number, width:number, height:number, captureTime: Date) => {
hubConnection.on("ScreenCapture", (buffer: Uint8Array, left:number, top:number, width:number, height:number, imageQuality: number) => {
//console.log("Websocket frame received.");
this.SendLatencyUpdate(captureTime, buffer.byteLength);
this.SendBufferUpdate(buffer.byteLength);
if (Number(UI.QualitySlider.value) != imageQuality) {
UI.QualitySlider.value = String(imageQuality);
}
var url = window.URL.createObjectURL(new Blob([buffer]));
var img = document.createElement("img");

View File

@ -10,6 +10,9 @@ namespace Remotely.Shared.Models
[DataContract]
public class FrameInfo : IDynamicDto
{
[DataMember(Name = "DtoType")]
public DynamicDtoType DtoType { get; set; }
[DataMember(Name = "EndOfFrame")]
public bool EndOfFrame { get; set; }
@ -19,12 +22,11 @@ namespace Remotely.Shared.Models
[DataMember(Name = "ImageBytes")]
public byte[] ImageBytes { get; set; }
[DataMember(Name = "ImageQuality")]
public long ImageQuality { get; set; }
[DataMember(Name = "Left")]
public int Left { get; set; }
[DataMember(Name = "DtoType")]
public DynamicDtoType DtoType { get; set; }
[DataMember(Name = "Top")]
public int Top { get; set; }
[DataMember(Name = "Width")]