Remotely/Tests/Desktop.Win.Tests/ManualTests.cs

378 lines
12 KiB
C#

#nullable disable
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Remotely.Desktop.Core;
using Remotely.Desktop.Core.Interfaces;
using Remotely.Desktop.Core.Services;
using Remotely.Desktop.Core.Utilities;
using Remotely.Desktop.Win.Services;
using Remotely.Shared.Models;
using Remotely.Shared.Models.RemoteControlDtos;
using SkiaSharp;
using SkiaSharp.Views.Desktop;
using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
namespace Remotely.Tests
{
[TestClass]
public class ManualTests
{
private const int RoundtripLatency = 25;
private double _bytesSent;
private double _frameCount;
private Mock<IAudioCapturer> _audio;
private ScreenCapturerWin _capturer;
private Mock<ICasterSocket> _casterSocket;
private Mock<IClipboardService> _clipboard;
private Conductor _conductor;
private Mock<ICursorIconWatcher> _cursorWatcher;
private ScreenCaster _screenCaster;
private Mock<ISessionIndicator> _sessionIndicator;
private Mock<IShutdownService> _shutdown;
private Mock<IWebRtcSessionFactory> _webrtcFactory;
private Viewer _viewer;
[TestMethod]
[Ignore("Manual test.")]
public async Task CaptureTest()
{
var request = new ScreenCastRequest()
{
NotifyUser = true,
RequesterName = "Batman",
ViewerID = "asdf"
};
_screenCaster.BeginScreenCasting(request);
var timeout = 5_000;
await Task.Delay(timeout);
_viewer.DisconnectRequested = true;
var fps = _frameCount / (timeout / 1000);
Debug.WriteLine($"FPS: {fps}");
Debug.WriteLine($"KB Sent: {Math.Round(_bytesSent / 1024, 2)}");
Assert.IsTrue(fps > 0);
_viewer.Dispose();
}
[TestMethod]
[Ignore("Manual test.")]
public void EncodingTests()
{
for (var i = 0; i < 2; i++)
{
using var frame1 = GetImage("Image1");
using var frame2 = GetImage("Image1");
byte[] imageBytes;
var sw = Stopwatch.StartNew();
sw.Restart();
var diff = ImageUtils.GetDiffArea(frame1, frame2, false);
var diffSize = 0;
using (var tempImage = ImageUtils.CropBitmap(frame1, diff))
{
imageBytes = ImageUtils.EncodeBitmap(tempImage, SKEncodedImageFormat.Jpeg, 60);
diffSize = imageBytes.Length;
}
Debug.WriteLine($"Diff area size: {diffSize}");
Debug.WriteLine($"Diff area time: {sw.Elapsed.TotalMilliseconds}");
sw.Restart();
var diffImage = ImageUtils.GetImageDiff(frame1, frame2, false);
using (var ms = new MemoryStream())
{
diffImage.Value.Encode(ms, SKEncodedImageFormat.Png, 80);
Debug.WriteLine($"Diff image size: {ms.ToArray().Length}");
}
Debug.WriteLine($"Diff Image time: {sw.Elapsed.TotalMilliseconds}");
Debug.WriteLine($"\n");
}
}
[TestMethod]
public void CaptureAndEncodeSpeedTest()
{
var iterations = 30;
var quality = 80;
var sw = Stopwatch.StartNew();
SKBitmap currentFrame = new();
SKBitmap previousFrame = new();
for (var i = 0; i < iterations; i++)
{
previousFrame?.Dispose();
previousFrame = currentFrame.Copy();
currentFrame.Dispose();
currentFrame = _capturer.GetNextFrame().Value;
var diffArea = ImageUtils.GetDiffArea(currentFrame, previousFrame);
using var cropped = ImageUtils.CropBitmap(currentFrame, diffArea);
using var skData = cropped.Encode(SKEncodedImageFormat.Webp, quality);
}
sw.Stop();
Console.WriteLine($"GetNextFrame & WEBP: {GetAverage(sw, iterations)}ms per iteration");
sw.Restart();
for (var i = 0; i < iterations; i++)
{
previousFrame.Dispose();
previousFrame = currentFrame.Copy();
currentFrame.Dispose();
currentFrame = _capturer.GetNextFrame().Value;
var diffArea = ImageUtils.GetDiffArea(currentFrame, previousFrame);
using var cropped = ImageUtils.CropBitmap(currentFrame, diffArea);
using var skData = cropped.Encode(SKEncodedImageFormat.Jpeg, quality);
}
sw.Stop();
Console.WriteLine($"GetNextFrame & JPEG: {GetAverage(sw, iterations)}ms per iteration");
}
[TestMethod]
public void CaptureSpeedTest()
{
var iterations = 30;
var sw = Stopwatch.StartNew();
for (var i = 0; i < iterations; i++)
{
using var bitmap = _capturer.GetNextFrame().Value;
}
sw.Stop();
Console.WriteLine($"GetNextFrame: {GetAverage(sw, iterations)}ms per capture");
sw.Restart();
for (var i = 0; i < iterations; i++)
{
using var bitmap = _capturer.GetDirectXFrame().Value;
}
sw.Stop();
Console.WriteLine($"DirectX: {GetAverage(sw, iterations)}ms per capture");
sw.Restart();
for (var i = 0; i < iterations; i++)
{
using var bitmap = _capturer.GetBitBltFrame().Value;
}
sw.Stop();
Console.WriteLine($"BitBlt: {GetAverage(sw, iterations)}ms per capture");
}
[TestMethod]
public void DiffSpeedTests()
{
using var bitmap1 = GetImage("Image1");
using var bitmap2 = GetImage("Image2");
var iterations = 60;
var sw = Stopwatch.StartNew();
for (var i = 0; i < iterations; i++)
{
_ = ImageUtils.GetDiffArea(bitmap1, bitmap2);
}
sw.Stop();
Console.WriteLine($"Diff Area: {GetAverage(sw, iterations)}ms per call");
sw.Restart();
for (var i = 0; i < iterations; i++)
{
using var imageDiff = ImageUtils.GetImageDiff(bitmap1, bitmap2).Value;
}
sw.Stop();
Console.WriteLine($"Image Diff: {GetAverage(sw, iterations)}ms per call");
}
[TestMethod]
public void EncodeSpeedTest()
{
using var skBitmap = GetImage("Image1");
var quality = 75;
var iterations = 30;
{
using var skData = skBitmap.Encode(SKEncodedImageFormat.Jpeg, quality);
Console.WriteLine($"JPEG size: {skData.Size:N0}");
}
var sw = Stopwatch.StartNew();
for (var i = 0; i < iterations; i++)
{
using var skData = skBitmap.Encode(SKEncodedImageFormat.Jpeg, quality);
}
sw.Stop();
Console.WriteLine($"JPEG: {GetAverage(sw, iterations)}ms per encode");
{
using var skData = skBitmap.Encode(SKEncodedImageFormat.Png, quality);
Console.WriteLine($"PNG size: {skData.Size:N0}");
}
sw.Restart();
for (var i = 0; i < iterations; i++)
{
using var skData = skBitmap.Encode(SKEncodedImageFormat.Png, quality);
}
sw.Stop();
Console.WriteLine($"PNG: {GetAverage(sw, iterations)}ms per encode");
{
using var skData = skBitmap.Encode(SKEncodedImageFormat.Webp, quality);
Console.WriteLine($"WEBP size: {skData.Size:N0}");
}
sw.Restart();
for (var i = 0; i < iterations; i++)
{
using var skData = skBitmap.Encode(SKEncodedImageFormat.Webp, quality);
}
sw.Stop();
Console.WriteLine($"WEBP: {GetAverage(sw, iterations)}ms per encode");
}
[TestMethod]
public void GetDiffAreaTest()
{
using var bitmap1 = GetImage("Image1");
using var bitmap2 = GetImage("Image2");
var diffArea = ImageUtils.GetDiffArea(bitmap1, bitmap2);
using var cropped = ImageUtils.CropBitmap(bitmap2, diffArea);
SaveFile(cropped, "Test.webp");
}
[TestMethod]
public void GetImageDiffTest()
{
using var bitmap1 = GetImage("Image1");
using var bitmap2 = GetImage("Image2");
var diff = ImageUtils.GetImageDiff(bitmap1, bitmap2);
SaveFile(diff.Value, "Test.webp");
}
[TestInitialize]
public void Init()
{
_conductor = new Conductor();
_cursorWatcher = new Mock<ICursorIconWatcher>();
_sessionIndicator = new Mock<ISessionIndicator>();
_clipboard = new Mock<IClipboardService>();
_casterSocket = new Mock<ICasterSocket>();
_audio = new Mock<IAudioCapturer>();
_shutdown = new Mock<IShutdownService>();
_webrtcFactory = new Mock<IWebRtcSessionFactory>();
_capturer = new ScreenCapturerWin();
_screenCaster = new ScreenCaster(_conductor, _cursorWatcher.Object, _sessionIndicator.Object, _shutdown.Object);
_viewer = new Viewer(_casterSocket.Object, _capturer, _clipboard.Object, _webrtcFactory.Object, _audio.Object);
_casterSocket
.Setup(x => x.SendDtoToViewer(It.IsAny<CaptureFrameDto>(), It.IsAny<string>()))
.Callback((CaptureFrameDto dto, string viewerId) =>
{
_bytesSent += dto.ImageBytes.Length;
});
_casterSocket
.Setup(x => x.SendDtoToViewer(It.Is<CaptureFrameDto>(x => x.EndOfFrame), It.IsAny<string>()))
.Callback(() =>
{
Task.Run(() =>
{
Thread.Sleep(RoundtripLatency);
_viewer.PendingSentFrames.TryDequeue(out _);
});
});
_casterSocket
.Setup(x => x.IsConnected)
.Returns(true)
.Callback(() => _frameCount++);
var serviceCollection = new ServiceCollection();
serviceCollection.AddLogging(builder =>
{
builder.AddConsole().AddDebug().AddEventLog();
});
serviceCollection.AddSingleton((e) => _viewer);
ServiceContainer.Instance = serviceCollection.BuildServiceProvider();
}
private static double GetAverage(Stopwatch sw, int iterations)
{
return Math.Round(sw.Elapsed.TotalMilliseconds / iterations, 2);
}
private SKBitmap GetImage(string imageFileName)
{
using var mrs = Assembly.GetExecutingAssembly().GetManifestResourceStream($"Remotely.Desktop.Win.Tests.Resources.{imageFileName}.jpg");
var resourceImage = (Bitmap)Bitmap.FromStream(mrs);
if (resourceImage.PixelFormat != PixelFormat.Format32bppArgb)
{
return resourceImage
.Clone(new Rectangle(0, 0, resourceImage.Width, resourceImage.Height), PixelFormat.Format32bppArgb)
.ToSKBitmap();
}
return resourceImage.ToSKBitmap();
}
private static void SaveFile(
SKBitmap bitmap,
string fileName,
SKEncodedImageFormat format = SKEncodedImageFormat.Webp,
int quality = 80)
{
var savePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), fileName);
using var fs = new FileStream(savePath, FileMode.Create);
bitmap.Encode(fs, format, quality);
}
}
}