public async Task CaptureTest() { var request = new ScreenCastRequest() { NotifyUser = true, RequesterName = "Batman", ViewerID = "asdf" }; var timeout = Debugger.IsAttached ? 20_000 : 5_000; _ = Task.Run(async() => await _screenCaster.BeginScreenCasting(request)); 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(); }
private void ScreenCastRequested(object sender, ScreenCastRequest screenCastRequest) { App.Current.Dispatcher.Invoke(() => { var result = MessageBox.Show($"You've received a connection request from {screenCastRequest.RequesterName}. Accept?", "Connection Request", MessageBoxButton.YesNo, MessageBoxImage.Question); if (result == MessageBoxResult.Yes) { Task.Run(async() => { ICapturer capturer; try { if (Conductor.Viewers.Count == 0) { capturer = new DXCapture(); } else { capturer = new BitBltCapture(); } } catch (Exception ex) { Logger.Write(ex); capturer = new BitBltCapture(); } await Conductor.CasterSocket.SendCursorChange(CursorIconWatcher.GetCurrentCursor(), new List <string>() { screenCastRequest.ViewerID }); ScreenCaster.BeginScreenCasting(screenCastRequest.ViewerID, screenCastRequest.RequesterName, capturer, Conductor); }); } }); }
private static async void ScreenCastInitiated(object sender, ScreenCastRequest screenCastRequest) { ICapturer capturer; try { if (Conductor.Viewers.Count == 0) { capturer = new DXCapture(); } else { capturer = new BitBltCapture(); } } catch (Exception ex) { Logger.Write(ex); capturer = new BitBltCapture(); } await Conductor.CasterSocket.SendCursorChange(CursorIconWatcher.GetCurrentCursor(), new List <string>() { screenCastRequest.ViewerID }); ScreenCaster.BeginScreenCasting(screenCastRequest.ViewerID, screenCastRequest.RequesterName, capturer, Conductor); BeginAudioCapture(); }
public async Task BeginScreenCasting(ScreenCastRequest screenCastRequest) { try { await Conductor.Current.CasterSocket.SendCursorChange(new CursorInfo(null, Point.Empty, "default"), new List <string>() { screenCastRequest.ViewerID }); _ = BeginScreenCasting(screenCastRequest.ViewerID, screenCastRequest.RequesterName, new X11Capture()); } catch (Exception ex) { Logger.Write(ex); } }
private static async void ScreenCastInitiated(object sender, ScreenCastRequest screenCastRequest) { try { var capturer = new X11Capture(Display); await Conductor.OutgoingMessages.SendCursorChange(new CursorInfo(null, Point.Empty, "default"), new List <string>() { screenCastRequest.ViewerID }); ScreenCaster.BeginScreenCasting(screenCastRequest.ViewerID, screenCastRequest.RequesterName, capturer, Conductor); } catch (Exception ex) { Logger.Write(ex); } }
public async Task BeginScreenCasting(ScreenCastRequest screenCastRequest) { try { var conductor = ServiceContainer.Instance.GetRequiredService <Conductor>(); await conductor.CasterSocket.SendCursorChange(new CursorInfo(null, Point.Empty, "default"), new List <string>() { screenCastRequest.ViewerID }); _ = BeginScreenCasting(screenCastRequest.ViewerID, screenCastRequest.RequesterName, ServiceContainer.Instance.GetRequiredService <ICapturer>()); } catch (Exception ex) { Logger.Write(ex); } }
public async Task BeginScreenCasting(ScreenCastRequest screenCastRequest) { if (Win32Interop.GetCurrentDesktop(out var currentDesktopName)) { Logger.Write($"Setting desktop to {currentDesktopName} before screen casting."); Win32Interop.SwitchToInputDesktop(); } else { Logger.Write("Failed to get current desktop before screen casting."); } await Conductor.Current.CasterSocket.SendCursorChange(CursorIconWatcher.GetCurrentCursor(), new List <string>() { screenCastRequest.ViewerID }); _ = BeginScreenCasting(screenCastRequest.ViewerID, screenCastRequest.RequesterName, GetCapturer()); }
public async Task BeginScreenCasting(ScreenCastRequest screenCastRequest) { try { var sendFramesLock = new SemaphoreSlim(1, 1); var refreshTimer = Stopwatch.StartNew(); var refreshNeeded = false; var currentQuality = _maxQuality; Bitmap currentFrame = null; Bitmap previousFrame = null; var sw = Stopwatch.StartNew(); var viewer = ServiceContainer.Instance.GetRequiredService <Viewer>(); viewer.Name = screenCastRequest.RequesterName; viewer.ViewerConnectionID = screenCastRequest.ViewerID; var screenBounds = viewer.Capturer.CurrentScreenBounds; Logger.Write($"Starting screen cast. Requester: {viewer.Name}. " + $"Viewer ID: {viewer.ViewerConnectionID}. App Mode: {_conductor.Mode}"); _conductor.Viewers.AddOrUpdate(viewer.ViewerConnectionID, viewer, (id, v) => viewer); if (_conductor.Mode == AppMode.Normal) { _conductor.InvokeViewerAdded(viewer); } if (_conductor.Mode == AppMode.Unattended && screenCastRequest.NotifyUser) { _sessionIndicator.Show(); } await viewer.SendViewerConnected(); await viewer.SendMachineName(Environment.MachineName); await viewer.SendScreenData( viewer.Capturer.SelectedScreen, viewer.Capturer.GetDisplayNames().ToArray()); await viewer.SendScreenSize(screenBounds.Width, screenBounds.Height); await viewer.SendCursorChange(_cursorIconWatcher.GetCurrentCursor()); await viewer.SendWindowsSessions(); viewer.Capturer.ScreenChanged += async(sender, bounds) => { await viewer.SendScreenSize(bounds.Width, bounds.Height); }; using (var initialFrame = viewer.Capturer.GetNextFrame()) { if (initialFrame != null) { await viewer.SendScreenCapture(new CaptureFrame() { EncodedImageBytes = ImageUtils.EncodeJpeg(initialFrame, _maxQuality), Left = screenBounds.Left, Top = screenBounds.Top, Width = screenBounds.Width, Height = screenBounds.Height }); } } if (EnvironmentHelper.IsWindows && screenCastRequest.UseWebRtc) { await viewer.InitializeWebRtc(); } // Wait until the first image is received. TaskHelper.DelayUntil(() => !viewer.PendingSentFrames.Any(), TimeSpan.MaxValue); while (!viewer.DisconnectRequested && viewer.IsConnected) { try { TaskHelper.DelayUntil(() => sw.Elapsed.TotalMilliseconds > 40, TimeSpan.FromSeconds(5)); sw.Restart(); if (viewer.IsUsingWebRtcVideo) { Thread.Sleep(100); continue; } if (viewer.IsStalled) { // Viewer isn't responding. Abort sending. Logger.Write("Viewer stalled. Ending send loop."); break; } viewer.ThrottleIfNeeded(); if (currentFrame != null) { previousFrame?.Dispose(); previousFrame = (Bitmap)currentFrame.Clone(); } currentFrame?.Dispose(); currentFrame = viewer.Capturer.GetNextFrame(); if (currentFrame is null) { continue; } if (refreshTimer.Elapsed.TotalSeconds > 10 || refreshNeeded && refreshTimer.Elapsed.TotalSeconds > 5) { viewer.Capturer.CaptureFullscreen = true; } var diffArea = ImageUtils.GetDiffArea(currentFrame, previousFrame, viewer.Capturer.CaptureFullscreen); if (diffArea.IsEmpty) { continue; } if (viewer.Capturer.CaptureFullscreen) { refreshTimer.Restart(); refreshNeeded = false; } byte[] encodedImageBytes; if (viewer.Capturer.CaptureFullscreen) { // Recalculate Bps. viewer.AverageBytesPerSecond = 0; encodedImageBytes = ImageUtils.EncodeJpeg(currentFrame, _maxQuality); } else { if (viewer.AverageBytesPerSecond > 0) { var expectedSize = diffArea.Height * diffArea.Width * 4 * .1; var timeToSend = expectedSize / viewer.AverageBytesPerSecond; currentQuality = Math.Max(_minQuality, Math.Min(_maxQuality, (int)(.1 / timeToSend * _maxQuality))); if (currentQuality < _maxQuality - 10) { refreshNeeded = true; Debug.WriteLine($"Quality Reduced: {currentQuality}"); } } using var clone = currentFrame.Clone(diffArea, currentFrame.PixelFormat); //var resizeW = diffArea.Width * currentQuality / _maxQuality; //var resizeH = diffArea.Height * currentQuality / _maxQuality; //using var resized = new Bitmap(clone, new Size(resizeW, resizeH)); encodedImageBytes = ImageUtils.EncodeJpeg(clone, currentQuality); } viewer.Capturer.CaptureFullscreen = false; await sendFramesLock.WaitAsync(); SendFrame(encodedImageBytes, diffArea, viewer, sendFramesLock); } catch (Exception ex) { Logger.Write(ex); } } Logger.Write($"Ended screen cast. " + $"Requester: {viewer.Name}. " + $"Viewer ID: {viewer.ViewerConnectionID}. " + $"Viewer WS Connected: {viewer.IsConnected}. " + $"Viewer Stalled: {viewer.IsStalled}. " + $"Viewer Disconnected Requested: {viewer.DisconnectRequested}"); _conductor.Viewers.TryRemove(viewer.ViewerConnectionID, out _); viewer.Dispose(); } catch (Exception ex) { Logger.Write(ex); } finally { // Close if no one is viewing. if (_conductor.Viewers.IsEmpty && _conductor.Mode == AppMode.Unattended) { Logger.Write("No more viewers. Calling shutdown service."); await _shutdownService.Shutdown(); } } }
public async Task BeginScreenCasting(ScreenCastRequest screenCastRequest) { try { var sendFramesLock = new SemaphoreSlim(1, 1); Bitmap currentFrame = null; Bitmap previousFrame = null; var fpsQueue = new Queue <DateTimeOffset>(); var viewer = ServiceContainer.Instance.GetRequiredService <Viewer>(); viewer.Name = screenCastRequest.RequesterName; viewer.ViewerConnectionID = screenCastRequest.ViewerID; Logger.Write($"Starting screen cast. Requester: {viewer.Name}. " + $"Viewer ID: {viewer.ViewerConnectionID}. App Mode: {_conductor.Mode}"); _conductor.Viewers.AddOrUpdate(viewer.ViewerConnectionID, viewer, (id, v) => viewer); if (_conductor.Mode == AppMode.Normal) { _conductor.InvokeViewerAdded(viewer); } if (_conductor.Mode == AppMode.Unattended && screenCastRequest.NotifyUser) { _sessionIndicator.Show(); } await viewer.SendViewerConnected(); await viewer.SendMachineName(Environment.MachineName); await viewer.SendScreenData( viewer.Capturer.SelectedScreen, viewer.Capturer.GetDisplayNames().ToArray()); await viewer.SendScreenSize(viewer.Capturer.CurrentScreenBounds.Width, viewer.Capturer.CurrentScreenBounds.Height); await viewer.SendCursorChange(_cursorIconWatcher.GetCurrentCursor()); await viewer.SendWindowsSessions(); viewer.Capturer.ScreenChanged += async(sender, bounds) => { await viewer.SendScreenSize(bounds.Width, bounds.Height); }; using (var initialFrame = viewer.Capturer.GetNextFrame()) { if (initialFrame != null) { await viewer.SendScreenCapture(new CaptureFrame[] { new CaptureFrame() { EncodedImageBytes = ImageUtils.EncodeBitmap(initialFrame, viewer.EncoderParams), Left = viewer.Capturer.CurrentScreenBounds.Left, Top = viewer.Capturer.CurrentScreenBounds.Top, Width = viewer.Capturer.CurrentScreenBounds.Width, Height = viewer.Capturer.CurrentScreenBounds.Height } }); } } if (EnvironmentHelper.IsWindows) { await viewer.InitializeWebRtc(); } // Wait until the first image is received. TaskHelper.DelayUntil(() => !viewer.PendingSentFrames.Any(), TimeSpan.MaxValue); while (!viewer.DisconnectRequested && viewer.IsConnected) { try { if (viewer.IsUsingWebRtcVideo) { Thread.Sleep(100); continue; } if (viewer.IsStalled) { // Viewer isn't responding. Abort sending. break; } if (EnvironmentHelper.IsDebug) { while (fpsQueue.Any() && DateTimeOffset.Now - fpsQueue.Peek() > TimeSpan.FromSeconds(1)) { fpsQueue.Dequeue(); } fpsQueue.Enqueue(DateTimeOffset.Now); Debug.WriteLine($"Capture FPS: {fpsQueue.Count}"); } viewer.ThrottleIfNeeded(); if (currentFrame != null) { previousFrame?.Dispose(); previousFrame = (Bitmap)currentFrame.Clone(); } currentFrame?.Dispose(); currentFrame = viewer.Capturer.GetNextFrame(); var diffAreas = ImageUtils.GetDiffAreas(currentFrame, previousFrame, viewer.Capturer.CaptureFullscreen); if (!diffAreas.Any()) { continue; } viewer.Capturer.CaptureFullscreen = false; var frameClone = (Bitmap)currentFrame.Clone(); Debug.WriteLine($"Sending {diffAreas.Count} frames."); await sendFramesLock.WaitAsync(); SendFrames(frameClone, diffAreas, viewer, sendFramesLock); } catch (Exception ex) { Logger.Write(ex); } } Logger.Write($"Ended screen cast. Requester: {viewer.Name}. Viewer ID: {viewer.ViewerConnectionID}."); _conductor.Viewers.TryRemove(viewer.ViewerConnectionID, out _); viewer.Dispose(); } catch (Exception ex) { Logger.Write(ex); } finally { // Close if no one is viewing. if (_conductor.Viewers.IsEmpty && _conductor.Mode == AppMode.Unattended) { Logger.Write("No more viewers. Calling shutdown service."); await _shutdownService.Shutdown(); } } }
public void InvokeScreenCastRequested(ScreenCastRequest viewerIdAndRequesterName) { ScreenCastRequested?.Invoke(null, viewerIdAndRequesterName); }
public async Task BeginScreenCasting(ScreenCastRequest screenCastRequest) { var viewers = new ConcurrentDictionary <string, Viewer>(); var mode = AppMode.Unattended; try { byte[] encodedImageBytes; var fpsQueue = new Queue <DateTimeOffset>(); mode = Conductor.Mode; var viewer = ServiceContainer.Instance.GetRequiredService <Viewer>(); viewer.Name = screenCastRequest.RequesterName; viewer.ViewerConnectionID = screenCastRequest.ViewerID; viewers = Conductor.Viewers; Logger.Write($"Starting screen cast. Requester: {viewer.Name}. Viewer ID: {viewer.ViewerConnectionID}. App Mode: {mode}"); viewers.AddOrUpdate(viewer.ViewerConnectionID, viewer, (id, v) => viewer); if (mode == AppMode.Normal) { Conductor.InvokeViewerAdded(viewer); } if (EnvironmentHelper.IsWindows) { Win32Interop.SwitchToInputDesktop(); await viewer.InitializeWebRtc(); } await viewer.SendMachineName(Environment.MachineName, viewer.ViewerConnectionID); await viewer.SendScreenData( viewer.Capturer.SelectedScreen, viewer.Capturer.GetDisplayNames().ToArray(), viewer.ViewerConnectionID); await viewer.SendScreenSize(viewer.Capturer.CurrentScreenBounds.Width, viewer.Capturer.CurrentScreenBounds.Height, viewer.ViewerConnectionID); await viewer.SendCursorChange(CursorIconWatcher.GetCurrentCursor()); viewer.Capturer.ScreenChanged += async(sender, bounds) => { await viewer.SendScreenSize(bounds.Width, bounds.Height, viewer.ViewerConnectionID); }; await viewer.SendScreenCapture( ImageUtils.EncodeBitmap(viewer.Capturer.CurrentFrame, viewer.EncoderParams), viewer.ViewerConnectionID, viewer.Capturer.CurrentScreenBounds.Left, viewer.Capturer.CurrentScreenBounds.Top, viewer.Capturer.CurrentScreenBounds.Width, viewer.Capturer.CurrentScreenBounds.Height); while (!viewer.DisconnectRequested && viewer.IsConnected) { try { if (viewer.IsStalled()) { // Viewer isn't responding. Abort sending. break; } if (EnvironmentHelper.IsDebug) { while (fpsQueue.Any() && DateTimeOffset.Now - fpsQueue.Peek() > TimeSpan.FromSeconds(1)) { fpsQueue.Dequeue(); } fpsQueue.Enqueue(DateTimeOffset.Now); Debug.WriteLine($"Capture FPS: {fpsQueue.Count}"); } await viewer.ThrottleIfNeeded(); viewer.Capturer.GetNextFrame(); var diffArea = ImageUtils.GetDiffArea(viewer.Capturer.CurrentFrame, viewer.Capturer.PreviousFrame, viewer.Capturer.CaptureFullscreen); if (diffArea.IsEmpty) { continue; } using (var newImage = viewer.Capturer.CurrentFrame.Clone(diffArea, PixelFormat.Format32bppArgb)) { if (viewer.Capturer.CaptureFullscreen) { viewer.Capturer.CaptureFullscreen = false; } encodedImageBytes = ImageUtils.EncodeBitmap(newImage, viewer.EncoderParams); if (encodedImageBytes?.Length > 0) { await viewer.SendScreenCapture(encodedImageBytes, viewer.ViewerConnectionID, diffArea.Left, diffArea.Top, diffArea.Width, diffArea.Height); } } } catch (Exception ex) { Logger.Write(ex); } } Logger.Write($"Ended screen cast. Requester: {viewer.Name}. Viewer ID: {viewer.ViewerConnectionID}."); viewers.TryRemove(viewer.ViewerConnectionID, out _); viewer.Dispose(); } catch (Exception ex) { Logger.Write(ex); } finally { // Close if no one is viewing. if (viewers.Count == 0 && mode == AppMode.Unattended) { Logger.Debug($"Exiting process ID {Process.GetCurrentProcess().Id}."); Environment.Exit(0); } } }
internal void InvokeScreenCastInitiated(ScreenCastRequest viewerIdAndRequesterName) { ScreenCastInitiated?.Invoke(null, viewerIdAndRequesterName); }
private async Task CastScreen(ScreenCastRequest screenCastRequest) { try { Bitmap currentFrame = null; Bitmap previousFrame = null; long sequence = 0; var viewer = ServiceContainer.Instance.GetRequiredService <Viewer>(); viewer.Name = screenCastRequest.RequesterName; viewer.ViewerConnectionID = screenCastRequest.ViewerID; var screenBounds = viewer.Capturer.CurrentScreenBounds; Logger.Write($"Starting screen cast. Requester: {viewer.Name}. " + $"Viewer ID: {viewer.ViewerConnectionID}. App Mode: {_conductor.Mode}"); _conductor.Viewers.AddOrUpdate(viewer.ViewerConnectionID, viewer, (id, v) => viewer); if (_conductor.Mode == AppMode.Normal) { _conductor.InvokeViewerAdded(viewer); } if (_conductor.Mode == AppMode.Unattended && screenCastRequest.NotifyUser) { _sessionIndicator.Show(); } await viewer.SendViewerConnected(); await viewer.SendScreenData( viewer.Capturer.SelectedScreen, viewer.Capturer.GetDisplayNames(), screenBounds.Width, screenBounds.Height); await viewer.SendScreenSize(screenBounds.Width, screenBounds.Height); await viewer.SendCursorChange(_cursorIconWatcher.GetCurrentCursor()); await viewer.SendWindowsSessions(); viewer.Capturer.ScreenChanged += async(sender, bounds) => { await viewer.SendScreenSize(bounds.Width, bounds.Height); }; using (var initialFrame = viewer.Capturer.GetNextFrame()) { if (initialFrame != null) { await viewer.SendScreenCapture(new CaptureFrame() { EncodedImageBytes = ImageUtils.EncodeJpeg(initialFrame), Left = screenBounds.Left, Top = screenBounds.Top, Width = screenBounds.Width, Height = screenBounds.Height, Sequence = sequence++ }); } } if (EnvironmentHelper.IsWindows && screenCastRequest.UseWebRtc) { await viewer.InitializeWebRtc(); } // Wait until the first image is received. if (!TaskHelper.DelayUntil(() => !viewer.PendingSentFrames.Any(), TimeSpan.FromSeconds(30))) { Logger.Write("Timed out while waiting for first frame receipt."); _conductor.Viewers.TryRemove(viewer.ViewerConnectionID, out _); viewer.Dispose(); return; } while (!viewer.DisconnectRequested && viewer.IsConnected) { try { if (viewer.IsUsingWebRtcVideo) { Thread.Sleep(100); continue; } if (viewer.IsStalled) { // Viewer isn't responding. Abort sending. Logger.Write("Viewer stalled. Ending send loop."); break; } viewer.CalculateFps(); viewer.ApplyAutoQuality(); if (currentFrame != null) { previousFrame?.Dispose(); previousFrame = (Bitmap)currentFrame.Clone(); } currentFrame?.Dispose(); currentFrame = viewer.Capturer.GetNextFrame(); if (currentFrame is null) { continue; } var diffArea = ImageUtils.GetDiffArea(currentFrame, previousFrame, viewer.Capturer.CaptureFullscreen); if (diffArea.IsEmpty) { continue; } viewer.Capturer.CaptureFullscreen = false; using var croppedFrame = currentFrame.Clone(diffArea, currentFrame.PixelFormat); byte[] encodedImageBytes; if (viewer.ImageQuality == Viewer.DefaultQuality) { encodedImageBytes = ImageUtils.EncodeJpeg(croppedFrame); } else { encodedImageBytes = ImageUtils.EncodeJpeg(croppedFrame, viewer.ImageQuality); } await SendFrame(encodedImageBytes, diffArea, sequence ++, viewer); } catch (Exception ex) { Logger.Write(ex); } } Logger.Write($"Ended screen cast. " + $"Requester: {viewer.Name}. " + $"Viewer ID: {viewer.ViewerConnectionID}. " + $"Viewer WS Connected: {viewer.IsConnected}. " + $"Viewer Stalled: {viewer.IsStalled}. " + $"Viewer Disconnected Requested: {viewer.DisconnectRequested}"); _conductor.Viewers.TryRemove(viewer.ViewerConnectionID, out _); viewer.Dispose(); } catch (Exception ex) { Logger.Write(ex); } finally { // Close if no one is viewing. if (_conductor.Viewers.IsEmpty && _conductor.Mode == AppMode.Unattended) { Logger.Write("No more viewers. Calling shutdown service."); await _shutdownService.Shutdown(); } } }
public void BeginScreenCasting(ScreenCastRequest screenCastRequest) { _ = Task.Run(async() => await CastScreen(screenCastRequest)); }
public async Task BeginScreenCasting(ScreenCastRequest screenCastRequest) { var mode = AppMode.Unattended; try { Bitmap currentFrame = null; Bitmap previousFrame = null; byte[] encodedImageBytes; var fpsQueue = new Queue <DateTimeOffset>(); mode = Conductor.Mode; var viewer = ServiceContainer.Instance.GetRequiredService <Viewer>(); viewer.Name = screenCastRequest.RequesterName; viewer.ViewerConnectionID = screenCastRequest.ViewerID; Logger.Write($"Starting screen cast. Requester: {viewer.Name}. Viewer ID: {viewer.ViewerConnectionID}. App Mode: {mode}"); Conductor.Viewers.AddOrUpdate(viewer.ViewerConnectionID, viewer, (id, v) => viewer); if (mode == AppMode.Normal) { Conductor.InvokeViewerAdded(viewer); } if (mode == AppMode.Unattended && screenCastRequest.NotifyUser) { SessionIndicator.Show(); } await viewer.SendViewerConnected(); await viewer.SendMachineName(Environment.MachineName); await viewer.SendScreenData( viewer.Capturer.SelectedScreen, viewer.Capturer.GetDisplayNames().ToArray()); await viewer.SendScreenSize(viewer.Capturer.CurrentScreenBounds.Width, viewer.Capturer.CurrentScreenBounds.Height); await viewer.SendCursorChange(CursorIconWatcher.GetCurrentCursor()); await viewer.SendWindowsSessions(); viewer.Capturer.ScreenChanged += async(sender, bounds) => { await viewer.SendScreenSize(bounds.Width, bounds.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); } if (EnvironmentHelper.IsWindows) { await viewer.InitializeWebRtc(); } while (!viewer.DisconnectRequested && viewer.IsConnected) { try { if (viewer.IsUsingWebRtcVideo) { Thread.Sleep(100); continue; } if (viewer.IsStalled) { // Viewer isn't responding. Abort sending. break; } if (EnvironmentHelper.IsDebug) { while (fpsQueue.Any() && DateTimeOffset.Now - fpsQueue.Peek() > TimeSpan.FromSeconds(1)) { fpsQueue.Dequeue(); } fpsQueue.Enqueue(DateTimeOffset.Now); Debug.WriteLine($"Capture FPS: {fpsQueue.Count}"); } viewer.ThrottleIfNeeded(); if (currentFrame != null) { previousFrame?.Dispose(); previousFrame = (Bitmap)currentFrame.Clone(); } currentFrame?.Dispose(); currentFrame = viewer.Capturer.GetNextFrame(); var diffAreas = ImageUtils.GetDiffAreas(currentFrame, previousFrame, viewer.Capturer.CaptureFullscreen); if (diffAreas.Count == 0) { continue; } foreach (var diffArea in diffAreas) { using var newImage = currentFrame.Clone(diffArea, PixelFormat.Format32bppArgb); if (viewer.Capturer.CaptureFullscreen) { viewer.Capturer.CaptureFullscreen = false; } encodedImageBytes = ImageUtils.EncodeBitmap(newImage, viewer.EncoderParams); if (encodedImageBytes?.Length > 0) { await viewer.SendScreenCapture(encodedImageBytes, diffArea.Left, diffArea.Top, diffArea.Width, diffArea.Height); } } } catch (Exception ex) { Logger.Write(ex); } } Logger.Write($"Ended screen cast. Requester: {viewer.Name}. Viewer ID: {viewer.ViewerConnectionID}."); Conductor.Viewers.TryRemove(viewer.ViewerConnectionID, out _); viewer.Dispose(); } catch (Exception ex) { Logger.Write(ex); } finally { // Close if no one is viewing. if (Conductor.Viewers.Count == 0 && mode == AppMode.Unattended) { await ShutdownService.Shutdown(); } } }
public async Task BeginScreenCasting(ScreenCastRequest screenCastRequest) { await Conductor.Current.CasterSocket.SendCursorChange(CursorIconWatcher.GetCurrentCursor(), new List <string>() { screenCastRequest.ViewerID }); _ = BeginScreenCasting(screenCastRequest.ViewerID, screenCastRequest.RequesterName, GetCapturer()); }