Ejemplo n.º 1
0
        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();
        }
Ejemplo n.º 2
0
 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);
             });
         }
     });
 }
Ejemplo n.º 3
0
        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();
        }
Ejemplo n.º 4
0
        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);
            }
        }
Ejemplo n.º 5
0
        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);
            }
        }
Ejemplo n.º 6
0
        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);
            }
        }
Ejemplo n.º 7
0
        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());
        }
Ejemplo n.º 8
0
        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();
                }
            }
        }
Ejemplo n.º 9
0
        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();
                }
            }
        }
Ejemplo n.º 10
0
 public void InvokeScreenCastRequested(ScreenCastRequest viewerIdAndRequesterName)
 {
     ScreenCastRequested?.Invoke(null, viewerIdAndRequesterName);
 }
Ejemplo n.º 11
0
        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);
                }
            }
        }
Ejemplo n.º 12
0
 internal void InvokeScreenCastInitiated(ScreenCastRequest viewerIdAndRequesterName)
 {
     ScreenCastInitiated?.Invoke(null, viewerIdAndRequesterName);
 }
Ejemplo n.º 13
0
        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();
                }
            }
        }
Ejemplo n.º 14
0
 public void BeginScreenCasting(ScreenCastRequest screenCastRequest)
 {
     _ = Task.Run(async() => await CastScreen(screenCastRequest));
 }
Ejemplo n.º 15
0
        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();
                }
            }
        }
Ejemplo n.º 16
0
        public async Task BeginScreenCasting(ScreenCastRequest screenCastRequest)
        {
            await Conductor.Current.CasterSocket.SendCursorChange(CursorIconWatcher.GetCurrentCursor(), new List <string>() { screenCastRequest.ViewerID });

            _ = BeginScreenCasting(screenCastRequest.ViewerID, screenCastRequest.RequesterName, GetCapturer());
        }