Skip to content

Commit

Permalink
Add RTC message DTOs.
Browse files Browse the repository at this point in the history
  • Loading branch information
bitbound committed Apr 13, 2020
1 parent 6ce2b1b commit 9fc6aa1
Show file tree
Hide file tree
Showing 60 changed files with 672 additions and 351 deletions.
1 change: 1 addition & 0 deletions Desktop.Linux/ViewModels/MainWindowViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ private void BuildServices()
serviceCollection.AddSingleton<IdleTimer>();
serviceCollection.AddSingleton<Conductor>();
serviceCollection.AddTransient<IScreenCapturer, ScreenCapturerLinux>();
serviceCollection.AddTransient<Viewer>();


ServiceContainer.Instance = serviceCollection.BuildServiceProvider();
Expand Down
1 change: 1 addition & 0 deletions Desktop.Win/ViewModels/MainWindowViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ private void BuildServices()
serviceCollection.AddSingleton<IdleTimer>();
serviceCollection.AddSingleton<Conductor>();
serviceCollection.AddTransient<IScreenCapturer, ScreenCapturerWin>();
serviceCollection.AddTransient<Viewer>();


ServiceContainer.Instance = serviceCollection.BuildServiceProvider();
Expand Down
71 changes: 36 additions & 35 deletions ScreenCast.Core/Communication/CasterSocket.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,9 @@ public async Task SendAudioSample(byte[] buffer, List<string> viewerIDs)
await Connection.SendAsync("SendAudioSample", buffer, viewerIDs);
}

public async Task SendClipboardText(string clipboardText, List<string> viewerIDs)
public async Task SendClipboardText(string clipboardText, string viewerID)
{
await Connection.SendAsync("SendClipboardText", clipboardText, viewerIDs);
await Connection.SendAsync("SendClipboardText", clipboardText, viewerID);
}

public async Task SendConnectionFailedToViewers(List<string> viewerIDs)
Expand Down Expand Up @@ -118,7 +118,7 @@ public async Task SendRtcOfferToBrowser(string sdp, string viewerID)
await Connection.SendAsync("SendRtcOfferToBrowser", sdp, viewerID);
}

public async Task SendScreenCapture(byte[] captureBytes, string viewerID, int left, int top, int width, int height, long imageQuality)
public async Task SendScreenCapture(byte[] captureBytes, string viewerID, int left, int top, int width, int height, int imageQuality)
{
await Connection.SendAsync("SendScreenCapture", captureBytes, viewerID, left, top, width, height, imageQuality);
}
Expand Down Expand Up @@ -405,35 +405,36 @@ private void ApplyConnectionHandlers()
KeyboardMouseInput.SendLeftMouseUp(percentX, percentY, viewer);
}
});
Connection.On("SharedFileIDs", (List<string> fileIDs) =>
{
fileIDs.ForEach(id =>
{
var url = $"{conductor.Host}/API/FileSharing/{id}";
var webRequest = WebRequest.CreateHttp(url);
var response = webRequest.GetResponse();
var contentDisp = response.Headers["Content-Disposition"];
var fileName = contentDisp
.Split(";".ToCharArray())
.FirstOrDefault(x => x.Trim().StartsWith("filename"))
.Split("=".ToCharArray())[1];

var legalChars = fileName.ToCharArray().Where(x => !Path.GetInvalidFileNameChars().Any(y => x == y));

fileName = new string(legalChars.ToArray());

var dirPath = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), "RemotelySharedFiles")).FullName;
var filePath = Path.Combine(dirPath, fileName);
using (var fs = new FileStream(filePath, FileMode.Create))
{
using (var rs = response.GetResponseStream())
{
rs.CopyTo(fs);
}
}
Process.Start("explorer.exe", dirPath);
});
});

//Connection.On("SharedFileIDs", (List<string> fileIDs) =>
//{
// fileIDs.ForEach(id =>
// {
// var url = $"{conductor.Host}/API/FileSharing/{id}";
// var webRequest = WebRequest.CreateHttp(url);
// var response = webRequest.GetResponse();
// var contentDisp = response.Headers["Content-Disposition"];
// var fileName = contentDisp
// .Split(";".ToCharArray())
// .FirstOrDefault(x => x.Trim().StartsWith("filename"))
// .Split("=".ToCharArray())[1];

// var legalChars = fileName.ToCharArray().Where(x => !Path.GetInvalidFileNameChars().Any(y => x == y));

// fileName = new string(legalChars.ToArray());

// var dirPath = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), "RemotelySharedFiles")).FullName;
// var filePath = Path.Combine(dirPath, fileName);
// using (var fs = new FileStream(filePath, FileMode.Create))
// {
// using (var rs = response.GetResponseStream())
// {
// rs.CopyTo(fs);
// }
// }
// Process.Start("explorer.exe", dirPath);
// });
//});

Connection.On("SessionID", (string sessionID) =>
{
Expand All @@ -444,10 +445,10 @@ private void ApplyConnectionHandlers()
private async void ClipboardService_ClipboardTextChanged(object sender, string clipboardText)
{
var conductor = ServiceContainer.Instance.GetRequiredService<Conductor>();
var viewerIDs = conductor.Viewers.Keys.ToList();
if (viewerIDs.Any())
var viewerIDs = conductor.Viewers.Values.ToList();
foreach (var viewer in viewerIDs)
{
await SendClipboardText(clipboardText, viewerIDs);
await viewer.SendClipboardText(clipboardText);
}
}
}
Expand Down
42 changes: 32 additions & 10 deletions ScreenCast.Core/Communication/WebRtcSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Microsoft.MixedReality.WebRTC;
using Remotely.ScreenCast.Core.Services;
using Remotely.Shared.Models;
using Remotely.Shared.Models.RtcDtos;
using System;
using System.Collections.Generic;
using System.Linq;
Expand Down Expand Up @@ -62,28 +63,46 @@ public void SendCaptureFrame(int left, int top, int width, int height, byte[] im
{
for (var i = 0; i < imageBytes.Length; i += 50_000)
{
CaptureChannel.SendMessage(MessagePackSerializer.Serialize(new FrameInfo()
SendDto(new CaptureFrameDto()
{
Left = left,
Top = top,
Width = width,
Height = height,
EndOfFrame = false,
ImageBytes = imageBytes.Skip(i).Take(50_000).ToArray(),
ImageQuality = imageQuality,
DtoType = Shared.Enums.DynamicDtoType.FrameInfo
}));
ImageQuality = imageQuality
});
}
CaptureChannel.SendMessage(MessagePackSerializer.Serialize(new FrameInfo()
SendDto(new CaptureFrameDto()
{
Left = left,
Top = top,
Width = width,
Height = height,
EndOfFrame = true,
ImageQuality = imageQuality,
DtoType = Shared.Enums.DynamicDtoType.FrameInfo
}));
ImageQuality = imageQuality
});
}

public void SendClipboardText(string clipboardText)
{
SendDto(new ClipboardTextDto(clipboardText));
}

public void SendMachineName(string machineName)
{
SendDto(new MachineNameDto(machineName));
}

public void SendScreenData(string selectedScreen, string[] displayNames)
{
SendDto(new ScreenDataDto(selectedScreen, displayNames));
}

public void SendScreenSize(int width, int height)
{
SendDto(new ScreenSizeDto(width, height));
}

public void SetRemoteDescription(string type, string sdp)
Expand All @@ -94,7 +113,6 @@ public void SetRemoteDescription(string type, string sdp)
PeerConnection.CreateAnswer();
}
}

private void CaptureChannel_MessageReceived(byte[] obj)
{
Logger.Debug($"DataChannel message received. Size: {obj.Length}");
Expand All @@ -108,7 +126,6 @@ private async void CaptureChannel_StateChanged()
await Init();
}
}

private void DataChannel_BufferingChanged(ulong previous, ulong current, ulong limit)
{
Logger.Debug($"DataChannel buffering changed. Previous: {previous}. Current: {current}. Limit: {limit}.");
Expand Down Expand Up @@ -136,5 +153,10 @@ private void PeerConnection_LocalSdpReadytoSend(string type, string sdp)
Logger.Debug($"Local SDP ready.");
LocalSdpReady?.Invoke(this, sdp);
}

private void SendDto<T>(T dto)
{
CaptureChannel.SendMessage(MessagePackSerializer.Serialize(dto));
}
}
}
95 changes: 88 additions & 7 deletions ScreenCast.Core/Models/Viewer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,19 @@ public class Viewer : IDisposable
{
private int imageQuality;

public Viewer()
public Viewer(IScreenCapturer screenCapturer,
CasterSocket casterSocket)
{
Capturer = screenCapturer;
CasterSocket = casterSocket;
EncoderParams = new EncoderParameters();
ImageQuality = 60;
}
public bool AutoAdjustQuality { get; internal set; } = true;
public IScreenCapturer Capturer { get; set; }
public bool AutoAdjustQuality { get; set; } = true;
public IScreenCapturer Capturer { get; }
public bool DisconnectRequested { get; set; }
public EncoderParameters EncoderParams { get; private set; }
public bool FullScreenRefreshNeeded { get; internal set; }
public bool HasControl { get; set; }
public bool HasControl { get; set; } = true;
public int ImageQuality
{
get
Expand All @@ -43,15 +45,44 @@ public int ImageQuality
EncoderParams.Param[0] = new EncoderParameter(Encoder.Quality, value);
}
}

public bool IsConnected => CasterSocket.IsConnected;
public string Name { get; set; }
public WebRtcSession RtcSession { get; set; }
public string ViewerConnectionID { get; set; }
public int WebSocketBuffer { get; set; }
private CasterSocket CasterSocket { get; }
public void Disconnect()
{
RtcSession.Dispose();
}

public void Dispose()
{
RtcSession?.Dispose();
}

public async Task InitializeWebRtc()
{
try
{
RtcSession = new WebRtcSession();
RtcSession.LocalSdpReady += async (sender, sdp) =>
{
await CasterSocket.SendRtcOfferToBrowser(sdp, ViewerConnectionID);
};
RtcSession.IceCandidateReady += async (sender, args) =>
{
await CasterSocket.SendIceCandidateToBrowser(args.candidate, args.sdpMlineIndex, args.sdpMid, ViewerConnectionID);
};
await RtcSession.Init();
}
catch (Exception ex)
{
Logger.Write(ex);
}
}

public bool IsStalled()
{
return RtcSession?.CurrentBuffer > 1_000_000 || WebSocketBuffer > 1_000_000;
Expand All @@ -62,9 +93,46 @@ public bool IsUsingWebRtc()
return RtcSession?.IsPeerConnected == true && RtcSession?.IsDataChannelOpen == true;
}

public async Task SendClipboardText(string clipboardText)
{
await SendToViewer(() => RtcSession.SendClipboardText(clipboardText),
() => CasterSocket.SendClipboardText(clipboardText, ViewerConnectionID));
}

public async Task SendMachineName(string machineName, string viewerID)
{
await SendToViewer(()=> RtcSession.SendMachineName(machineName),
() => CasterSocket.SendMachineName(machineName, viewerID));
}

public async Task SendScreenCapture(byte[] encodedImageBytes, string viewerID, int left, int top, int width, int height, int imageQuality)
{
await SendToViewer(() =>
{
RtcSession.SendCaptureFrame(left, top, width, height, encodedImageBytes, ImageQuality);
WebSocketBuffer = 0;
}, async () =>
{
await CasterSocket.SendScreenCapture(encodedImageBytes, viewerID, left, top, width, height, imageQuality);
WebSocketBuffer += encodedImageBytes.Length;
});
}

public async Task SendScreenData(string selectedScreen, string[] displayNames, string viewerID)
{
await SendToViewer(() => RtcSession.SendScreenData(selectedScreen, displayNames),
() => CasterSocket.SendScreenData(selectedScreen, displayNames, viewerID));
}

public async Task SendScreenSize(int width, int height, string viewerID)
{
await SendToViewer(() => RtcSession.SendScreenSize(width, height),
() => CasterSocket.SendScreenSize(width, height, viewerID));
}

public async Task ThrottleIfNeeded()
{
var currentBuffer = IsUsingWebRtc() ?
var currentBuffer = IsUsingWebRtc() ?
(int)RtcSession.CurrentBuffer :
WebSocketBuffer;

Expand All @@ -75,7 +143,7 @@ public async Task ThrottleIfNeeded()
ImageQuality = Math.Max(ImageQuality - (150_000 / currentBuffer), 0);
Logger.Debug($"Auto-adjusting image quality. Quality: {ImageQuality}");
}

var delay = (int)Math.Ceiling((currentBuffer - 150_000) * .0025);
Logger.Debug($"Throttling output due to buffer size. Size: {currentBuffer}. Delay: {delay}");
await Task.Delay(delay);
Expand All @@ -85,5 +153,18 @@ public async Task ThrottleIfNeeded()
ImageQuality = Math.Min(ImageQuality + 1, 60);
}
}

private Task SendToViewer(Action webRtcSend, Func<Task> websocketSend)
{
if (IsUsingWebRtc())
{
webRtcSend();
return Task.CompletedTask;
}
else
{
return websocketSend();
}
}
}
}
Loading

0 comments on commit 9fc6aa1

Please sign in to comment.