Skip to content

Commit

Permalink
Refactor IScreenCapturer.
Browse files Browse the repository at this point in the history
  • Loading branch information
bitbound committed Aug 7, 2020
1 parent ca18f3c commit 0f2bd4f
Show file tree
Hide file tree
Showing 25 changed files with 528 additions and 488 deletions.
4 changes: 1 addition & 3 deletions Desktop.Core/Interfaces/IScreenCapturer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,12 @@ public interface IScreenCapturer : IDisposable
event EventHandler<Rectangle> ScreenChanged;

bool CaptureFullscreen { get; set; }
Bitmap CurrentFrame { get; set; }
Rectangle CurrentScreenBounds { get; }
Bitmap PreviousFrame { get; set; }
string SelectedScreen { get; }

IEnumerable<string> GetDisplayNames();

void GetNextFrame();
Bitmap GetNextFrame();

int GetScreenCount();

Expand Down
4 changes: 2 additions & 2 deletions Desktop.Core/Services/CasterSocket.cs
Original file line number Diff line number Diff line change
Expand Up @@ -209,13 +209,13 @@ private void ApplyConnectionHandlers()
});

Connection.On("ReceiveRtcAnswer", (string sdp, string viewerID) =>
Connection.On("ReceiveRtcAnswer", async (string sdp, string viewerID) =>
{
try
{
if (conductor.Viewers.TryGetValue(viewerID, out var viewer))
{
viewer.RtcSession.SetRemoteDescription("answer", sdp);
await viewer.RtcSession.SetRemoteDescription("answer", sdp);
}
}
catch (Exception ex)
Expand Down
29 changes: 20 additions & 9 deletions Desktop.Core/Services/ScreenCaster.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using Remotely.Desktop.Core.Enums;
using Remotely.Shared.Models;
using Remotely.Shared.Win32;
using System.Drawing;

namespace Remotely.Desktop.Core.Services
{
Expand All @@ -35,6 +36,8 @@ public async Task BeginScreenCasting(ScreenCastRequest screenCastRequest)

try
{
Bitmap currentFrame = null;
Bitmap previousFrame = null;
byte[] encodedImageBytes;
var fpsQueue = new Queue<DateTimeOffset>();
mode = Conductor.Mode;
Expand Down Expand Up @@ -76,12 +79,17 @@ public async Task BeginScreenCasting(ScreenCastRequest screenCastRequest)
await viewer.SendScreenSize(bounds.Width, bounds.Height);
};

await viewer.SendScreenCapture(
ImageUtils.EncodeBitmap(viewer.Capturer.CurrentFrame, viewer.EncoderParams),
viewer.Capturer.CurrentScreenBounds.Left,
viewer.Capturer.CurrentScreenBounds.Top,
viewer.Capturer.CurrentScreenBounds.Width,
viewer.Capturer.CurrentScreenBounds.Height);
using (var initialFrame = viewer.Capturer.GetNextFrame())
{
await viewer.SendScreenCapture(
ImageUtils.EncodeBitmap(initialFrame, viewer.EncoderParams),
viewer.Capturer.CurrentScreenBounds.Left,
viewer.Capturer.CurrentScreenBounds.Top,
viewer.Capturer.CurrentScreenBounds.Width,
viewer.Capturer.CurrentScreenBounds.Height);
}



while (!viewer.DisconnectRequested && viewer.IsConnected)
{
Expand All @@ -105,16 +113,19 @@ public async Task BeginScreenCasting(ScreenCastRequest screenCastRequest)

viewer.ThrottleIfNeeded();

viewer.Capturer.GetNextFrame();
previousFrame?.Dispose();
previousFrame = (Bitmap)currentFrame?.Clone();
currentFrame?.Dispose();
currentFrame = viewer.Capturer.GetNextFrame();

var diffArea = ImageUtils.GetDiffArea(viewer.Capturer.CurrentFrame, viewer.Capturer.PreviousFrame, viewer.Capturer.CaptureFullscreen);
var diffArea = ImageUtils.GetDiffArea(currentFrame, previousFrame, viewer.Capturer.CaptureFullscreen);

if (diffArea.IsEmpty)
{
continue;
}

using (var newImage = viewer.Capturer.CurrentFrame.Clone(diffArea, PixelFormat.Format32bppArgb))
using (var newImage = currentFrame.Clone(diffArea, PixelFormat.Format32bppArgb))
{
if (viewer.Capturer.CaptureFullscreen)
{
Expand Down
36 changes: 21 additions & 15 deletions Desktop.Linux/Services/ScreenCapturerLinux.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,47 +8,51 @@
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;

namespace Remotely.Desktop.Linux.Services
{
public class ScreenCapturerLinux : IScreenCapturer
{
private readonly SemaphoreSlim screenCaptureLock = new SemaphoreSlim(1);
private readonly Dictionary<string, int> x11Screens = new Dictionary<string, int>();
public ScreenCapturerLinux()
{
Display = LibX11.XOpenDisplay(null);
Init();
GetNextFrame();
}

public event EventHandler<Rectangle> ScreenChanged;

public bool CaptureFullscreen { get; set; }
public Bitmap CurrentFrame { get; set; }
public Rectangle CurrentScreenBounds { get; private set; }
public IntPtr Display { get; private set; }
public Bitmap PreviousFrame { get; set; }
public string SelectedScreen { get; private set; }

public void Dispose()
{
CurrentFrame.Dispose();
PreviousFrame.Dispose();
LibX11.XCloseDisplay(Display);
}

public IEnumerable<string> GetDisplayNames() => x11Screens.Keys;

public void GetNextFrame()
public Bitmap GetNextFrame()
{
try
{
PreviousFrame?.Dispose();
PreviousFrame = (Bitmap)CurrentFrame.Clone();
RefreshCurrentFrame();
screenCaptureLock.Wait();

return GetX11Screen();
}
catch (Exception ex)
{
Logger.Write(ex);
Init();
return null;
}
finally
{
screenCaptureLock.Release();
}
}
public int GetScreenCount()
Expand Down Expand Up @@ -84,8 +88,6 @@ public void Init()
x11Screens.Add(i.ToString(), i);
}
SetSelectedScreen(x11Screens.Keys.First());
CurrentFrame = new Bitmap(CurrentScreenBounds.Width, CurrentScreenBounds.Height, PixelFormat.Format32bppArgb);
PreviousFrame = new Bitmap(CurrentScreenBounds.Width, CurrentScreenBounds.Height, PixelFormat.Format32bppArgb);
}
catch (Exception ex)
{
Expand Down Expand Up @@ -121,28 +123,32 @@ public void SetSelectedScreen(string displayName)
}
}

private void RefreshCurrentFrame()
private Bitmap GetX11Screen()
{
var currentFrame = new Bitmap(CurrentScreenBounds.Width, CurrentScreenBounds.Height, PixelFormat.Format32bppArgb);

var window = LibX11.XRootWindow(Display, x11Screens[SelectedScreen]);

var imagePointer = LibX11.XGetImage(Display, window, 0, 0, CurrentScreenBounds.Width, CurrentScreenBounds.Height, ~0, 2);
var image = Marshal.PtrToStructure<LibX11.XImage>(imagePointer);

var bd = CurrentFrame.LockBits(new Rectangle(0, 0, CurrentFrame.Width, CurrentFrame.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
var bd = currentFrame.LockBits(new Rectangle(0, 0, CurrentScreenBounds.Width, CurrentScreenBounds.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
unsafe
{
byte* scan1 = (byte*)bd.Scan0.ToPointer();
byte* scan2 = (byte*)image.data.ToPointer();
var bytesPerPixel = Bitmap.GetPixelFormatSize(CurrentFrame.PixelFormat) / 8;
var bytesPerPixel = Bitmap.GetPixelFormatSize(currentFrame.PixelFormat) / 8;
var totalSize = bd.Height * bd.Width * bytesPerPixel;
for (int counter = 0; counter < totalSize - bytesPerPixel; counter++)
{
scan1[counter] = scan2[counter];
}
}

CurrentFrame.UnlockBits(bd);
currentFrame.UnlockBits(bd);
LibX11.XDestroyImage(imagePointer);

return currentFrame;
}
}
}

0 comments on commit 0f2bd4f

Please sign in to comment.