private async Task InitializeRemoteComponents(CaptureType captureType, ImageCompressionType compressionType) { await ConnectionInfo.SendCommand(this, new[] { (byte)RemoteDesktopCommunication.Initialize, (byte)captureType, (byte)CurrentScreen.Number, (byte)ImageQuality, ShowCursor ? (byte)1 : (byte)0, (byte)compressionType }); /*ConnectionInfo.Sender.UnsafeSendCommand(ConnectionInfo.ClientInformation.Id, Identifier, * new WriterCall(new[] * { * (byte) RemoteDesktopCommunication.Initialize, (byte) captureType, (byte) CurrentScreen.Number, * (byte) ImageQuality, ShowCursor ? (byte) 1 : (byte) 0, (byte) compressionType * }));*/ // ConnectionInfo.UnsafeSendCommand(this, new WriterCall(new[] // { // (byte) RemoteDesktopCommunication.Initialize, (byte) captureType, (byte) CurrentScreen.Number, // (byte) ImageQuality, ShowCursor ? (byte) 1 : (byte) 0, (byte) compressionType // })); CaptureType = captureType; _currentlyStreamedMonitor = CurrentScreen.Number; _streamCodec?.Dispose(); _cursorStreamCodec?.Dispose(); _streamCodec = new UnsafeStreamCodec(GetImageCompression(compressionType), UnsafeStreamCodecParameters.DontDisposeImageCompressor); _cursorStreamCodec = new CursorStreamCodec(); }
private void InitializeStreamingComponents(CaptureType captureType, int monitor, int quality, IConnectionInfo connectionInfo, bool drawCursor, ImageCompressionType compressionType) { var oldScreenCaptureService = _screenCaptureService; _screenCaptureService = _screenCaptureServices[captureType](); try { _screenCaptureService.Initialize(monitor); } catch (Exception ex) { _screenCaptureService = oldScreenCaptureService; ResponseBytes((byte)RemoteDesktopCommunication.ResponseInitializationFailed, Encoding.UTF8.GetBytes(ex.Message), connectionInfo); return; } Program.WriteLine($"InitializeStreamingComponents: oldScreenCaptureService == null: {oldScreenCaptureService == null} (else dispose)"); oldScreenCaptureService?.Dispose(); Program.WriteLine("Dispose other stuff in InitializeStreamingComponents"); _unsafeCodec?.Dispose(); _cursorStreamCodec?.Dispose(); _unsafeCodec = new UnsafeStreamCodec(GetImageCompression(compressionType), UnsafeStreamCodecParameters.DontDisposeImageCompressor | UnsafeStreamCodecParameters.UpdateImageEveryTwoSeconds); _currentImageCompression.Quality = quality; if (drawCursor) { _cursorStreamCodec = new CursorStreamCodec(); } _compressionType = compressionType; _currentMonitor = monitor; _drawCursor = drawCursor; ResponseByte((byte)RemoteDesktopCommunication.ResponseInitializationSucceeded, connectionInfo); Debug.Print("Initialized"); }
private async Task Stop(bool remoteCancelled) { if (!IsStreaming) { return; } if (!remoteCancelled) { await ConnectionInfo.SendCommand(this, (byte)RemoteDesktopCommunication.Stop); } //important, else dead lock because this is UI thread and lock invokdes into UI thread -> block await Task.Run(() => { lock (_updateLock) { IsStreaming = false; } }); FramesPerSecond = 0; _framesReceived = 0; _cursorStreamCodec?.Dispose(); _streamCodec?.Dispose(); _currentImageCompression?.Dispose(); _remoteConnection?.Dispose(); _remoteConnection = null; _currentImageCompression = null; _cursorStreamCodec = null; _streamCodec = null; LogService.Send((string)Application.Current.Resources["StopRemoteDesktop"]); }
public override void ProcessCommand(byte[] parameter, IConnectionInfo connectionInfo) { Program.WriteLine("Remote Desktop command received: " + (RemoteDesktopCommunication)parameter[0]); switch ((RemoteDesktopCommunication)parameter[0]) { case RemoteDesktopCommunication.GetInfo: var remoteDesktopInformation = new RemoteDesktopInformation { Screens = new List <ScreenInfo>() }; var screens = Screen.AllScreens; var allNames = ScreenExtensions.GetAllMonitorsFriendlyNames().ToArray(); for (int i = 0; i < screens.Length; i++) { remoteDesktopInformation.Screens.Add(new ScreenInfo { Number = i, Width = screens[i].Bounds.Width, Height = screens[i].Bounds.Height, Name = allNames.Length >= i && !string.IsNullOrEmpty(allNames[i]) ? allNames[i] : screens[i].DeviceName }); } foreach (var screenCaptureService in _screenCaptureServices) { if (screenCaptureService.Value().IsSupported) { remoteDesktopInformation.AvailableCaptureTypes |= screenCaptureService.Key; } } ResponseBytes((byte)RemoteDesktopCommunication.ResponseInfo, new Serializer(typeof(RemoteDesktopInformation)).Serialize(remoteDesktopInformation), connectionInfo); break; case RemoteDesktopCommunication.InitializeConnection: var connectionGuid = new Guid(parameter.Skip(1).Take(16).ToArray()); _connection?.Dispose(); _connection = connectionInfo.ConnectionInitializer.TakeConnection(connectionGuid); break; case RemoteDesktopCommunication.InitializeDirectConnection: _connection = new ServerConnection(connectionInfo, this, (byte)RemoteDesktopCommunication.ResponseFrame); break; case RemoteDesktopCommunication.Initialize: var captureType = (CaptureType)parameter[1]; var monitor = (int)parameter[2]; var quality = (int)parameter[3]; var drawCursor = parameter[4] == 1; var compression = (ImageCompressionType)parameter[5]; Program.WriteLine("Lock _streamComponents, InitializeStreamingComponents"); lock (_streamComponentsLock) InitializeStreamingComponents(captureType, monitor, quality, connectionInfo, drawCursor, compression); break; case RemoteDesktopCommunication.ChangeQuality: var newQuality = (int)parameter[1]; lock (_streamComponentsLock) { if (_unsafeCodec.ImageQuality != newQuality) { _unsafeCodec.ImageQuality = newQuality; } } break; case RemoteDesktopCommunication.Start: if (_isStreaming) { return; } Program.WriteLine("Start streaming; _isStreaming = true"); _connectionInfo = connectionInfo; _isStreaming = true; new Thread(Streaming) { IsBackground = true }.Start(); break; case RemoteDesktopCommunication.Stop: Program.WriteLine("Stop streaming...; _isStreaming = false; Lock _streamComponentsLock"); _isStreaming = false; //important, it locks this command until the stuff is stopped lock (_streamComponentsLock) { } Program.WriteLine("Stopped streaming"); break; case RemoteDesktopCommunication.ChangeMonitor: monitor = parameter[1]; lock (_streamComponentsLock) { _screenCaptureService.ChangeMonitor(monitor); _unsafeCodec?.Dispose(); _unsafeCodec = new UnsafeStreamCodec(GetImageCompression(_compressionType), UnsafeStreamCodecParameters.UpdateImageEveryTwoSeconds | UnsafeStreamCodecParameters.DontDisposeImageCompressor); _currentMonitor = monitor; } break; case RemoteDesktopCommunication.DesktopAction: DoDesktopAction((RemoteDesktopAction)parameter[1], parameter, 2); break; case RemoteDesktopCommunication.ChangeDrawCursor: lock (_streamComponentsLock) { if (parameter[1] == 1) { _drawCursor = true; _cursorStreamCodec = new CursorStreamCodec(); } else { _cursorStreamCodec?.Dispose(); _drawCursor = false; } } break; } }
private void button_Click(object sender, RoutedEventArgs e) { _dispatcherTimer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) }; _dispatcherTimer.Tick += DispatcherTimerOnTick; _dispatcherTimer.Start(); new Thread(() => { using (var streamCodec = new UnsafeStreamCodec(new JpgCompression(70), UnsafeStreamCodecParameters.None)) using (var decoderCodec = new UnsafeStreamCodec(new JpgCompression(70), UnsafeStreamCodecParameters.None)) using (var cursorCodec = new CursorStreamCodec()) using (var decodeCursorCodec = new CursorStreamCodec()) using (var screenService = new FrontBufferService()) { streamCodec.ImageQuality = 70; screenService.Initialize(0); WriteableBitmap currentWriteableBitmap = null; while (!_isClosed) { var sw = Stopwatch.StartNew(); var data = screenService.CaptureScreen(streamCodec, cursorCodec, true); if (data == null) { continue; } //Debug.Print($"Screen captured ({sw.ElapsedMilliseconds})"); unsafe { byte[] bytes; using (var ms = new MemoryStream()) { data.WriteIntoStream(ms); bytes = ms.ToArray(); } var cursorData = cursorCodec.CodeCursor(); fixed(byte *bytePtr = bytes) { sw.Reset(); //Debug.Print("Decode " + bytes.Length); var newBitmap = decoderCodec.AppendModifier(decodeCursorCodec.CreateModifierTask(cursorData, 0, cursorData.Length)).DecodeData(bytePtr, (uint)bytes.Length, Dispatcher); //Debug.Print($"Screen decoded ({sw.ElapsedMilliseconds})"); if (newBitmap != currentWriteableBitmap) { currentWriteableBitmap = newBitmap; Dispatcher.Invoke(() => ImageAsd.Source = currentWriteableBitmap); } Interlocked.Increment(ref _currentFps); } } } } }).Start(); }