Added auto image quality.

This commit is contained in:
Jared Goodwin 2019-12-29 09:36:55 -08:00
parent 8a626e6406
commit 2b6a8bc342
9 changed files with 67 additions and 31 deletions

View File

@ -15,6 +15,7 @@ using Remotely.Shared.Win32;
using Remotely.ScreenCast.Core.Interfaces;
using System.Diagnostics;
using System.Threading;
using System.Drawing.Imaging;
namespace Remotely.ScreenCast.Core.Capture
{
@ -72,16 +73,6 @@ namespace Remotely.ScreenCast.Core.Capture
{
try
{
if (Conductor.Current.IsDebug)
{
while (fpsQueue.Any() && DateTime.Now - fpsQueue.Peek() > TimeSpan.FromSeconds(1))
{
fpsQueue.Dequeue();
}
fpsQueue.Enqueue(DateTime.Now);
Debug.WriteLine("Capture FPS: " + fpsQueue.Count);
}
if (OSUtils.IsWindows)
{
var currentDesktopName = Win32Interop.GetCurrentDesktop();
@ -95,13 +86,14 @@ namespace Remotely.ScreenCast.Core.Capture
}
if (viewer.PendingFrames > 10)
if (Conductor.Current.IsDebug)
{
Logger.Write($"Throttling screen capture. Latency: {viewer.Latency}. Pending Frames: {viewer.PendingFrames}");
// This is to prevent dead-lock in case updates are missed from the browser.
viewer.PendingFrames = Math.Max(0, viewer.PendingFrames - 1);
await Task.Delay(10);
continue;
while (fpsQueue.Any() && DateTime.Now - fpsQueue.Peek() > TimeSpan.FromSeconds(1))
{
fpsQueue.Dequeue();
}
fpsQueue.Enqueue(DateTime.Now);
Debug.WriteLine("Capture FPS: " + fpsQueue.Count);
}
capturer.GetNextFrame();
@ -120,12 +112,27 @@ namespace Remotely.ScreenCast.Core.Capture
capturer.CaptureFullscreen = false;
}
encodedImageBytes = ImageUtils.EncodeBitmap(newImage, viewer.EncoderParams);
if (viewer.AutoAdjustQuality && viewer.Latency > 1000)
{
var quality = (int)(viewer.ImageQuality * 1000 / viewer.Latency);
Logger.Write($"Auto-adjusting image quality. Latency: {viewer.Latency}. Quality: {quality}");
encodedImageBytes = ImageUtils.EncodeBitmap(newImage, new EncoderParameters()
{
Param = new[]
{
new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality)
}
});
}
else
{
encodedImageBytes = ImageUtils.EncodeBitmap(newImage, viewer.EncoderParams);
}
if (encodedImageBytes?.Length > 0)
{
await conductor.CasterSocket.SendScreenCapture(encodedImageBytes, viewerID, diffArea.Left, diffArea.Top, diffArea.Width, diffArea.Height, DateTime.UtcNow);
viewer.PendingFrames++;
viewer.Latency += 300;
}
}
}

View File

@ -11,20 +11,18 @@ namespace Remotely.ScreenCast.Core.Models
{
public class Viewer
{
private long imageQuality = 50;
public Viewer()
{
ImageQuality = 50;
}
public string ViewerConnectionID { get; set; }
public string Name { get; set; }
public bool AutoAdjustQuality { get; internal set; }
public ICapturer Capturer { get; set; }
public bool DisconnectRequested { get; set; }
public EncoderParameters EncoderParams { get; private set; }
public bool FullScreenRefreshNeeded { get; internal set; }
public bool HasControl { get; set; }
public double Latency { get; set; } = 1;
public int PendingFrames { get; set; }
private long imageQuality = 50;
public long ImageQuality
{
get
@ -42,17 +40,19 @@ namespace Remotely.ScreenCast.Core.Models
return;
}
imageQuality = value;
EncoderParams = new EncoderParameters()
{
Param = new []
Param = new[]
{
new EncoderParameter(Encoder.Quality, value)
}
};
}
}
public bool FullScreenRefreshNeeded { get; internal set; }
public double Latency { get; set; } = 1;
public string Name { get; set; }
public string ViewerConnectionID { get; set; }
}
}

View File

@ -277,7 +277,6 @@ namespace Remotely.ScreenCast.Core.Sockets
{
var latency = DateTime.UtcNow - sentTime;
viewer.Latency = latency.TotalMilliseconds;
viewer.PendingFrames = Math.Max(0, viewer.PendingFrames - 1);
}
});
@ -297,6 +296,14 @@ namespace Remotely.ScreenCast.Core.Sockets
}
});
Connection.On("AutoQualityAdjust", (bool isOn, string viewerID) =>
{
if (conductor.Viewers.TryGetValue(viewerID, out var viewer))
{
viewer.AutoAdjustQuality = isOn;
}
});
Connection.On("ToggleAudio", (bool toggleOn, string viewerID) =>
{
if (conductor.Viewers.TryGetValue(viewerID, out var viewer) && viewer.HasControl)

View File

@ -90,7 +90,13 @@
<div style="color:white; font-size:12px">
Image Quality
</div>
<input id="qualityRangeInput" value="50" max="100" class="form-control-range" type="range" />
<div>
<input id="qualityRangeInput" value="50" max="100" class="form-control-range" type="range" />
<div style="color:white; font-size:12px; text-align: left">
<input id="autoAdjustQualityCheckBox" type="checkbox" checked />
<label>Auto Adjust</label>
</div>
</div>
</div>
<div id="clipboardTransferBar" class="horizontal-button-bar">

View File

@ -160,6 +160,11 @@ namespace Remotely.Server.Services
await RCDeviceHub.Clients.Client(ScreenCasterID).SendAsync("QualityChange", qualityLevel, Context.ConnectionId);
}
public async Task SendAutoQualityAdjust(bool isOn)
{
await RCDeviceHub.Clients.Client(ScreenCasterID).SendAsync("AutoQualityAdjust", isOn, Context.ConnectionId);
}
public async Task SendScreenCastRequestToDevice(string screenCasterID, string requesterName, int remoteControlMode)
{
if ((RemoteControlMode)remoteControlMode == RemoteControlMode.Normal)

View File

@ -101,6 +101,9 @@ export class RCBrowserSockets {
SendQualityChange(qualityLevel: number) {
this.Connection.invoke("SendQualityChange", qualityLevel);
}
SendAutoQualityAdjust(isOn: boolean) {
this.Connection.invoke("SendAutoQualityAdjust", isOn);
}
SendToggleAudio(toggleOn: boolean) {
this.Connection.invoke("SendToggleAudio", toggleOn);
};

View File

@ -16,6 +16,7 @@ export var ConnectBox = document.getElementById("connectBox");
export var ScreenSelectBar = document.getElementById("screenSelectBar");
export var QualityBar = document.getElementById("qualityBar");
export var QualitySlider = document.getElementById("qualityRangeInput");
export var AutoQualityAdjustCheckBox = document.getElementById("autoAdjustQualityCheckBox");
export var ActionsBar = document.getElementById("actionsBar");
export var ViewBar = document.getElementById("viewBar");
export var ChangeScreenButton = document.getElementById("changeScreenButton");
@ -150,6 +151,9 @@ export function ApplyInputHandlers(sockets) {
QualitySlider.addEventListener("change", (ev) => {
sockets.SendQualityChange(Number(QualitySlider.value));
});
AutoQualityAdjustCheckBox.addEventListener("change", ev => {
sockets.SendAutoQualityAdjust(AutoQualityAdjustCheckBox.checked);
});
ScreenViewer.addEventListener("pointermove", function (e) {
currentPointerDevice = e.pointerType;
});

File diff suppressed because one or more lines are too long

View File

@ -19,6 +19,7 @@ export var ConnectBox = document.getElementById("connectBox") as HTMLDivElement;
export var ScreenSelectBar = document.getElementById("screenSelectBar") as HTMLDivElement;
export var QualityBar = document.getElementById("qualityBar") as HTMLDivElement;
export var QualitySlider = document.getElementById("qualityRangeInput") as HTMLInputElement;
export var AutoQualityAdjustCheckBox = document.getElementById("autoAdjustQualityCheckBox") as HTMLInputElement;
export var ActionsBar = document.getElementById("actionsBar") as HTMLDivElement;
export var ViewBar = document.getElementById("viewBar") as HTMLDivElement;
export var ChangeScreenButton = document.getElementById("changeScreenButton") as HTMLButtonElement;
@ -155,7 +156,10 @@ export function ApplyInputHandlers(sockets: RCBrowserSockets) {
})
QualitySlider.addEventListener("change", (ev) => {
sockets.SendQualityChange(Number(QualitySlider.value));
})
});
AutoQualityAdjustCheckBox.addEventListener("change", ev => {
sockets.SendAutoQualityAdjust(AutoQualityAdjustCheckBox.checked);
});
ScreenViewer.addEventListener("pointermove", function (e) {
currentPointerDevice = e.pointerType;
});