Update WebRTC library and accomodate API changes.

This commit is contained in:
Jared Goodwin 2020-08-06 17:20:53 -07:00
parent 71d30765e5
commit dd3b9083bd
9 changed files with 107 additions and 47 deletions

View File

@ -38,7 +38,7 @@
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.1.6" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.1.6" />
<PackageReference Include="Microsoft.Extensions.Logging.EventLog" Version="3.1.6" />
<PackageReference Include="Microsoft.MixedReality.WebRTC" Version="1.0.3" />
<PackageReference Include="Microsoft.MixedReality.WebRTC" Version="2.0.0" />
<PackageReference Include="System.Drawing.Common" Version="4.7.0" />
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="4.7.0" />
</ItemGroup>

View File

@ -92,11 +92,11 @@ namespace Remotely.Desktop.Core.Models
RtcSession = WebRtcSessionFactory.GetNewSession(this);
RtcSession.LocalSdpReady += async (sender, sdp) =>
{
await CasterSocket.SendRtcOfferToBrowser(sdp, ViewerConnectionID, iceServers);
await CasterSocket.SendRtcOfferToBrowser(sdp.Content, ViewerConnectionID, iceServers);
};
RtcSession.IceCandidateReady += async (sender, args) =>
RtcSession.IceCandidateReady += async (sender, candidate) =>
{
await CasterSocket.SendIceCandidateToBrowser(args.candidate, args.sdpMlineIndex, args.sdpMid, ViewerConnectionID);
await CasterSocket.SendIceCandidateToBrowser(candidate.Content, candidate.SdpMlineIndex, candidate.SdpMid, ViewerConnectionID);
};
await RtcSession.Init(iceServers);

View File

@ -1,10 +1,12 @@
using MessagePack;
using Microsoft.MixedReality.WebRTC;
using Remotely.Desktop.Core.Models;
using Remotely.Shared.Models;
using Remotely.Shared.Models.RtcDtos;
using Remotely.Shared.Utilities;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Threading.Tasks;
@ -12,31 +14,40 @@ namespace Remotely.Desktop.Core.Services
{
public class WebRtcSession : IDisposable
{
public WebRtcSession(IRtcMessageHandler rtcMessageHandler)
public WebRtcSession(Viewer viewer, IRtcMessageHandler rtcMessageHandler)
{
Viewer = viewer;
RtcMessageHandler = rtcMessageHandler;
}
public event EventHandler<(string candidate, int sdpMlineIndex, string sdpMid)> IceCandidateReady;
public event EventHandler<IceCandidate> IceCandidateReady;
public event EventHandler<string> LocalSdpReady;
public event EventHandler<SdpMessage> LocalSdpReady;
public ulong CurrentBuffer { get; private set; }
public bool IsDataChannelOpen => CaptureChannel?.State == DataChannel.ChannelState.Open;
public bool IsPeerConnected => PeerConnection?.IsConnected == true;
public bool IsPeerConnected => PeerSession?.IsConnected == true;
private DataChannel CaptureChannel { get; set; }
private IceServerModel[] IceServers { get; set; }
private PeerConnection PeerConnection { get; set; }
private PeerConnection PeerSession { get; set; }
private IRtcMessageHandler RtcMessageHandler { get; }
private Transceiver Transceiver { get; set; }
private ExternalVideoTrackSource VideoSource { get; set; }
private Viewer Viewer { get; }
public void AddIceCandidate(string sdpMid, int sdpMlineIndex, string candidate)
{
PeerConnection.AddIceCandidate(sdpMid, sdpMlineIndex, candidate);
PeerSession.AddIceCandidate(new IceCandidate()
{
Content = candidate,
SdpMid = sdpMid,
SdpMlineIndex = sdpMlineIndex
});
}
public void Dispose()
{
CaptureChannel?.Dispose();
PeerConnection?.Dispose();
PeerSession?.Dispose();
}
public async Task Init(IceServerModel[] iceServers)
@ -45,7 +56,7 @@ namespace Remotely.Desktop.Core.Services
IceServers = iceServers;
PeerConnection = new PeerConnection();
PeerSession = new PeerConnection();
var iceList = IceServers.Select(x => new IceServer()
{
@ -59,18 +70,28 @@ namespace Remotely.Desktop.Core.Services
IceServers = iceList
};
await PeerConnection.InitializeAsync(config);
await PeerSession.InitializeAsync(config);
PeerConnection.LocalSdpReadytoSend += PeerConnection_LocalSdpReadytoSend;
PeerConnection.Connected += PeerConnection_Connected;
PeerConnection.IceStateChanged += PeerConnection_IceStateChanged;
PeerConnection.IceCandidateReadytoSend += PeerConnection_IceCandidateReadytoSend;
CaptureChannel = await PeerConnection.AddDataChannelAsync("ScreenCapture", true, true);
PeerSession.LocalSdpReadytoSend += PeerSession_LocalSdpReadytoSend; ;
PeerSession.Connected += PeerConnection_Connected;
PeerSession.IceStateChanged += PeerConnection_IceStateChanged;
PeerSession.IceCandidateReadytoSend += PeerSession_IceCandidateReadytoSend; ;
CaptureChannel = await PeerSession.AddDataChannelAsync("ScreenCapture", true, true);
CaptureChannel.BufferingChanged += DataChannel_BufferingChanged;
CaptureChannel.MessageReceived += CaptureChannel_MessageReceived;
CaptureChannel.StateChanged += CaptureChannel_StateChanged;
PeerConnection.CreateOffer();
//VideoSource = ExternalVideoTrackSource.CreateFromArgb32Callback(GetCaptureFrame);
//Transceiver = PeerSession.AddTransceiver(MediaKind.Video);
//Transceiver.LocalVideoTrack = LocalVideoTrack.CreateFromSource(VideoSource, new LocalVideoTrackInitConfig()
//{
// trackName = "ScreenCapture"
//});
PeerSession.CreateOffer();
}
public void SendAudioSample(byte[] audioSample)
{
SendDto(new AudioSampleDto(audioSample));
@ -116,6 +137,7 @@ namespace Remotely.Desktop.Core.Services
{
SendDto(new MachineNameDto(machineName));
}
public void SendScreenData(string selectedScreen, string[] displayNames)
{
SendDto(new ScreenDataDto(selectedScreen, displayNames));
@ -125,19 +147,32 @@ namespace Remotely.Desktop.Core.Services
{
SendDto(new ScreenSizeDto(width, height));
}
public void SendWindowsSessions(List<WindowsSession> windowsSessions)
{
SendDto(new WindowsSessionsDto(windowsSessions));
}
public void SetRemoteDescription(string type, string sdp)
public async Task SetRemoteDescription(string type, string sdp)
{
PeerConnection.SetRemoteDescription(type, sdp);
if (type == "offer")
if (!Enum.TryParse<SdpMessageType>(type, true, out var sdpMessageType))
{
PeerConnection.CreateAnswer();
Logger.Write("Unable to parse remote WebRTC description type.");
return;
}
await PeerSession.SetRemoteDescriptionAsync(new SdpMessage()
{
Content = sdp,
Type = sdpMessageType
});
if (sdpMessageType == SdpMessageType.Offer)
{
PeerSession.CreateAnswer();
}
}
private async void CaptureChannel_MessageReceived(byte[] obj)
{
Logger.Debug($"DataChannel message received. Size: {obj.Length}");
@ -152,31 +187,61 @@ namespace Remotely.Desktop.Core.Services
await Init(IceServers);
}
}
private void DataChannel_BufferingChanged(ulong previous, ulong current, ulong limit)
{
CurrentBuffer = current;
}
//private void GetCaptureFrame(in FrameRequest request)
//{
// Viewer.Capturer.GetNextFrame();
// using (var bitmapCopy = (Bitmap)Viewer.Capturer.CurrentFrame.Clone())
// {
// var bitmapData = bitmapCopy.LockBits(
// Viewer.Capturer.CurrentScreenBounds,
// System.Drawing.Imaging.ImageLockMode.ReadOnly,
// System.Drawing.Imaging.PixelFormat.Format32bppArgb);
// try
// {
// var frame = new Argb32VideoFrame()
// {
// data = bitmapData.Scan0,
// height = (uint)bitmapCopy.Height,
// width = (uint)bitmapCopy.Width,
// stride = bitmapData.Stride
// };
// request.CompleteRequest(in frame);
// }
// finally
// {
// bitmapCopy.UnlockBits(bitmapData);
// }
// }
//}
private void PeerConnection_Connected()
{
Logger.Debug("PeerConnection connected.");
}
private void PeerConnection_IceCandidateReadytoSend(string candidate, int sdpMlineindex, string sdpMid)
{
Logger.Debug("Ice candidate ready to send.");
IceCandidateReady?.Invoke(this, (candidate, sdpMlineindex, sdpMid));
}
private void PeerConnection_IceStateChanged(IceConnectionState newState)
{
Logger.Debug($"Ice state changed to {newState}.");
}
private void PeerConnection_LocalSdpReadytoSend(string type, string sdp)
private void PeerSession_IceCandidateReadytoSend(IceCandidate candidate)
{
Logger.Debug("Ice candidate ready to send.");
IceCandidateReady?.Invoke(this, candidate);
}
private void PeerSession_LocalSdpReadytoSend(SdpMessage message)
{
Logger.Debug($"Local SDP ready.");
LocalSdpReady?.Invoke(this, sdp);
LocalSdpReady?.Invoke(this, message);
}
private void SendDto<T>(T dto)
{

View File

@ -44,7 +44,7 @@ namespace Remotely.Desktop.Core.Services
ClipboardService,
FileDownloadService);
return new WebRtcSession(messageHandler);
return new WebRtcSession(viewer, messageHandler);
}
}
}

View File

@ -39,9 +39,9 @@
<None Remove="Assets\Remotely_Icon.png" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="0.9.11" />
<PackageReference Include="Avalonia.Desktop" Version="0.9.11" />
<PackageReference Include="Avalonia.ReactiveUI" Version="0.9.11" />
<PackageReference Include="Avalonia" Version="0.9.12" />
<PackageReference Include="Avalonia.Desktop" Version="0.9.12" />
<PackageReference Include="Avalonia.ReactiveUI" Version="0.9.12" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Desktop.Core\Desktop.Core.csproj" />

View File

@ -36,7 +36,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.MixedReality.WebRTC" Version="1.0.3" />
<PackageReference Include="Microsoft.MixedReality.WebRTC" Version="2.0.0" />
<PackageReference Include="NAudio" Version="1.10.0" />
<PackageReference Include="SharpDX" Version="4.2.0" />
<PackageReference Include="SharpDX.Direct3D11" Version="4.2.0" />

View File

@ -74,19 +74,14 @@ namespace Remotely.Desktop.Win.Services
{
try
{
Win32Interop.SwitchToInputDesktop();
if (NeedsInit)
{
Logger.Write("Init needed in DXCapture. Switching desktops.");
if (Win32Interop.SwitchToInputDesktop())
{
Win32Interop.GetCurrentDesktop(out var desktopName);
Logger.Write($"Switch to desktop {desktopName} after capture error in DXCapture.");
}
Logger.Write("Init needed in GetNextFrame.");
Init();
}
Win32Interop.SwitchToInputDesktop();
PreviousFrame?.Dispose();
PreviousFrame = (Bitmap)CurrentFrame.Clone();

View File

@ -86,7 +86,7 @@
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.1.6" />
<PackageReference Include="Microsoft.Extensions.Logging.EventLog" Version="3.1.6" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.1.3" PrivateAssets="All" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.1.4" PrivateAssets="All" />
<PackageReference Include="NETStandard.Library" Version="2.0.3" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="3.1.4" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.5.1" />

View File

@ -15,7 +15,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="3.1.6" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.1.2" />
<PackageReference Include="MSTest.TestFramework" Version="2.1.2" />
<PackageReference Include="coverlet.collector" Version="1.3.0">