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();
        }
Exemplo n.º 2
0
        public RemoteDesktopDataInfo CaptureScreen(IStreamCodec streamCodec, ICursorStreamCodec cursorStreamCodec, bool updateCursor)
        {
            if (updateCursor)
            {
                _screenHelper.UpdateCursor(cursorStreamCodec, _currentMonitor);
            }

            using (var graphics = Graphics.FromImage(_currentImage))
            {
                var deviceContext = graphics.GetHdc();
                NativeMethods.BitBlt(deviceContext, 0, 0, _boundsRectangle.Width, _boundsRectangle.Height,
                                     _scrDeviceContext, _boundsRectangle.X, _boundsRectangle.Y, SRCCOPY);
                graphics.ReleaseHdc(deviceContext);

                var bitmapData = _currentImage.LockBits(new Rectangle(0, 0, _currentImage.Width, _currentImage.Height),
                                                        ImageLockMode.ReadOnly, _currentImage.PixelFormat);

                try
                {
                    return(streamCodec.CodeImage(bitmapData.Scan0, _boundsRectangle, _currentImage.Size,
                                                 _currentImage.PixelFormat));
                }
                finally
                {
                    _currentImage.UnlockBits(bitmapData);
                }
            }
        }
Exemplo n.º 3
0
        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");
        }
Exemplo n.º 4
0
        public RemoteDesktopDataInfo CaptureScreen(IStreamCodec streamCodec, ICursorStreamCodec cursorStreamCodec, bool updateCursor)
        {
            if (updateCursor)
            {
                _screenHelper.UpdateCursor(cursorStreamCodec, _currentMonitor);
            }

            _device.GetFrontBufferData(0, _surface);
            var rectangle = _surface.LockRectangle(LockFlags.None);

            try
            {
                return(streamCodec.CodeImage(rectangle.DataPointer,
                                             new Rectangle(0, 0, _displayMode.Width, _displayMode.Height),
                                             new Size(_displayMode.Width, _displayMode.Height), PixelFormat.Format32bppArgb));
            }
            finally
            {
                _surface.UnlockRectangle();
            }
        }
        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"]);
        }
Exemplo n.º 6
0
        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 unsafe void ConnectionOnDataReceived(object sender, DataReceivedEventArgs dataReceivedEventArgs)
        {
            if (_isDisposed || !IsStreaming)
            {
                return;
            }

            lock (_updateLock)
            {
                if (_isDisposed || !IsStreaming)
                {
                    return;
                }

                var position = dataReceivedEventArgs.Index;
                var flags    = (ScreenResponseFlags)dataReceivedEventArgs.Buffer[position];
                position++;

                var cursorDataLength = 0;

                if ((flags & ScreenResponseFlags.Cursor) == ScreenResponseFlags.Cursor)
                {
                    cursorDataLength = BitConverter.ToInt32(dataReceivedEventArgs.Buffer, position);
                    position        += cursorDataLength + 4;
                }

                var monitor = dataReceivedEventArgs.Buffer[position];
                position++;

                if (monitor != _currentlyStreamedMonitor)
                {
                    _streamCodec?.Dispose();
                    _streamCodec = new UnsafeStreamCodec(GetImageCompression(_compressionType),
                                                         UnsafeStreamCodecParameters.DontDisposeImageCompressor);

                    _currentlyStreamedMonitor = monitor;
                }

                try
                {
                    fixed(byte *bufferPointer = dataReceivedEventArgs.Buffer)
                    {
                        if (cursorDataLength != 0)
                        {
                            WriteableBitmap = _streamCodec.AppendModifier(
                                _cursorStreamCodec.CreateModifierTask(dataReceivedEventArgs.Buffer,
                                                                      dataReceivedEventArgs.Index + 5, cursorDataLength)).DecodeData(bufferPointer + position,
                                                                                                                                     (uint)(dataReceivedEventArgs.Length - (position - dataReceivedEventArgs.Index)),
                                                                                                                                     Application.Current.Dispatcher);
                        }
                        else
                        {
                            WriteableBitmap = _streamCodec.DecodeData(bufferPointer + position,
                                                                      (uint)(dataReceivedEventArgs.Length - (position - dataReceivedEventArgs.Index)),
                                                                      Application.Current.Dispatcher);
                        }
                    }
                }
                catch (InvalidOperationException)
                {
                    //this happens when the main window closes and the writeablebitmap is already disposed
                    try
                    {
                        if (WriteableBitmap.BackBufferStride == 0)
                        {
                            return;
                        }
                    }
                    catch (Exception)
                    {
                        return;
                    }

                    throw;
                }
            }

            var framesReceived = Interlocked.Increment(ref _framesReceived);

            if (FramesPerSecond == 0 && framesReceived == 0)
            {
                _frameTimestamp = DateTime.UtcNow;
            }
            else if (DateTime.UtcNow - _frameTimestamp > TimeSpan.FromSeconds(1))
            {
                FramesPerSecond = framesReceived;
                Interlocked.Exchange(ref _framesReceived, 0);
                _frameTimestamp = DateTime.UtcNow;
            }
        }
Exemplo n.º 8
0
        public RemoteDesktopDataInfo CaptureScreen(IStreamCodec streamCodec, ICursorStreamCodec cursorStreamCodec, bool updateCursor)
        {
            //Debug.Print("_desktopDupl == null: " + (_deskDupl == null));
            if (!RetrieveFrame())
            {
                return(null);
            }

            // Get the desktop capture texture
            var mapSource = _device.ImmediateContext.MapSubresource(_desktopImageTexture, 0, MapMode.Read,
                                                                    MapFlags.None);

            try
            {
                if (updateCursor)
                {
                    _screenHelper.UpdateCursor(cursorStreamCodec, _currentMonitor);
                }
#if FALSE
                if (updateCursor)
                {
                    cursorStreamCodec.UpdateCursorInfo(_frameInfo.PointerPosition.Position.X,
                                                       _frameInfo.PointerPosition.Position.Y, _frameInfo.PointerPosition.Visible);

                    if (_frameInfo.LastMouseUpdateTime != 0 && _frameInfo.PointerShapeBufferSize > 0)
                    {
                        var buffer = new byte[_frameInfo.PointerShapeBufferSize];

                        unsafe
                        {
                            fixed(byte *ptrShapeBufferPtr = buffer)
                            {
                                int bufferSize;
                                OutputDuplicatePointerShapeInformation shapeInfo;

                                _deskDupl.GetFramePointerShape(_frameInfo.PointerShapeBufferSize,
                                                               (IntPtr)ptrShapeBufferPtr, out bufferSize, out shapeInfo);

                                switch (shapeInfo.Type)
                                {
                                case 0x1:     //DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MONOCHROME
                                    var size = Image.GetPixelFormatSize(PixelFormat.Format1bppIndexed);
                                    //var bitmap = new Bitmap(32, 32, 4, PixelFormat.Format1bppIndexed, (IntPtr)ptrShapeBufferPtr);
                                    cursorStreamCodec.UpdateCursorImage((IntPtr)ptrShapeBufferPtr,
                                                                        shapeInfo.Pitch, 32, 32,
                                                                        PixelFormat.Format1bppIndexed);
                                    Debug.Print("DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MONOCHROME");
                                    break;

                                case 0x2:     //DXGI_OUTDUPL_POINTER_SHAPE_TYPE_COLOR
                                    cursorStreamCodec.UpdateCursorImage((IntPtr)ptrShapeBufferPtr,
                                                                        shapeInfo.Pitch, shapeInfo.Width, shapeInfo.Height,
                                                                        PixelFormat.Format32bppArgb);
                                    Debug.Print("DXGI_OUTDUPL_POINTER_SHAPE_TYPE_COLOR");
                                    break;

                                case 0x4:     //DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MASKED_COLOR
                                    Debug.Print("DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MASKED_COLOR");
                                    break;
                                }
                            }
                        }
                    }
                }
#endif

                if (_frameInfo.TotalMetadataBufferSize > 0)
                {
                    int movedRegionsLength;
                    OutputDuplicateMoveRectangle[] movedRectangles =
                        new OutputDuplicateMoveRectangle[_frameInfo.TotalMetadataBufferSize];
                    _deskDupl.GetFrameMoveRects(movedRectangles.Length, movedRectangles, out movedRegionsLength);
                    var movedRegions =
                        new MovedRegion[movedRegionsLength / Marshal.SizeOf(typeof(OutputDuplicateMoveRectangle))];

                    for (int i = 0; i < movedRegions.Length; i++)
                    {
                        var moveRectangle = movedRectangles[i];
                        movedRegions[i] = new MovedRegion
                        {
                            Source      = new Point(moveRectangle.SourcePoint.X, moveRectangle.SourcePoint.Y),
                            Destination =
                                new Rectangle(moveRectangle.DestinationRect.Left,
                                              moveRectangle.DestinationRect.Top,
                                              moveRectangle.DestinationRect.GetWidth(),
                                              moveRectangle.DestinationRect.GetHeight())
                        };
                    }

                    int dirtyRegionsLength;
                    var dirtyRectangles = new RawRectangle[_frameInfo.TotalMetadataBufferSize - movedRegionsLength];
                    _deskDupl.GetFrameDirtyRects(dirtyRectangles.Length, dirtyRectangles, out dirtyRegionsLength);
                    var updatedAreas = new Rectangle[dirtyRegionsLength / Marshal.SizeOf(typeof(Rectangle))];

                    for (int i = 0; i < updatedAreas.Length; i++)
                    {
                        var dirtyRectangle = dirtyRectangles[i];
                        updatedAreas[i] = new Rectangle(dirtyRectangle.Left, dirtyRectangle.Top,
                                                        dirtyRectangle.GetWidth(), dirtyRectangle.GetHeight());
                    }

                    return(streamCodec.CodeImage(mapSource.DataPointer, updatedAreas, movedRegions,
                                                 new Size(_outputDesc.DesktopBounds.GetWidth(), _outputDesc.DesktopBounds.GetHeight()),
                                                 PixelFormat.Format32bppArgb));
                }
                else
                {
                    return(streamCodec.CodeImage(mapSource.DataPointer,
                                                 new Rectangle(0, 0, _outputDesc.DesktopBounds.GetWidth(), _outputDesc.DesktopBounds.GetHeight()),
                                                 new Size(_outputDesc.DesktopBounds.GetWidth(), _outputDesc.DesktopBounds.GetHeight()),
                                                 PixelFormat.Format32bppArgb));
                }
            }
            finally
            {
                _device.ImmediateContext.UnmapSubresource(_desktopImageTexture, 0);
                ReleaseFrame();
            }
        }