Exemplo n.º 1
0
        /// <summary>
        /// Copies a region of the framebuffer into a bitmap.
        /// </summary>
        /// <param name="source">The framebuffer to read.</param>
        /// <param name="sourceRectangle">The framebuffer region to copy.</param>
        /// <param name="target">The bitmap to copy into.</param>
        /// <param name="targetX">The leftmost X coordinate of the bitmap to draw to.</param>
        /// <param name="targetY">The topmost Y coordinate of the bitmap to draw to.</param>
        public unsafe static void CopyFromFramebuffer(VncFramebuffer source, VncRectangle sourceRectangle,
                                                      Bitmap target, int targetX, int targetY)
        {
            Throw.If.Null(source, "source").Null(target, "target");
            if (sourceRectangle.IsEmpty)
            {
                return;
            }

            var winformsRect = new Rectangle(targetX, targetY, sourceRectangle.Width, sourceRectangle.Height);
            var data         = target.LockBits(winformsRect, ImageLockMode.WriteOnly, PixelFormat.Format32bppRgb);

            try
            {
                fixed(byte *framebufferData = source.GetBuffer())
                {
                    VncPixelFormat.Copy((IntPtr)framebufferData, source.Stride, source.PixelFormat, sourceRectangle,
                                        data.Scan0, data.Stride, new VncPixelFormat());
                }
            }
            finally
            {
                target.UnlockBits(data);
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Captures the screen.
        /// </summary>
        /// <returns>A framebuffer corresponding to the screen.</returns>
        public VncFramebuffer Capture()
        {
            var bounds = this.getScreenBounds();
            int w = bounds.Width, h = bounds.Height;

            if (this.bitmap == null || this.bitmap.Width != w || this.bitmap.Height != h)
            {
                this.bitmap      = new Bitmap(w, h);
                this.framebuffer = new VncFramebuffer(this.name, w, h, new VncPixelFormat());
            }

            using (var g = Graphics.FromImage(this.bitmap))
            {
                g.CopyFromScreen(bounds.X, bounds.Y, 0, 0, bounds.Size);

                lock (this.framebuffer.SyncRoot)
                {
                    VncBitmap.CopyToFramebuffer(
                        this.bitmap,
                        new VncRectangle(0, 0, w, h),
                        this.framebuffer,
                        0,
                        0);
                }
            }

            return(this.framebuffer);
        }
Exemplo n.º 3
0
        /// <summary>
        /// 将需要更新位图的区域复制到framebuffer中
        /// </summary>
        /// <param name="source">图片源.</param>
        /// <param name="sourceRectangle">要复制的位图区域.</param>
        /// <param name="target">目标帧缓冲区</param>
        /// <param name="targetX">帧缓冲区的左顶点X坐标</param>
        /// <param name="targetY">帧缓冲区的左顶点Y坐标</param>
        public unsafe static void CopyToFramebuffer(Bitmap source, VncRectangle sourceRectangle,
                                                    VncFramebuffer target, int targetX, int targetY)
        {
            Throw.If.Null(source, "source").Null(target, "target");
            if (sourceRectangle.IsEmpty)
            {
                return;
            }

            var winformsRect = new Rectangle(sourceRectangle.X, sourceRectangle.Y, sourceRectangle.Width, sourceRectangle.Height);
            var data         = source.LockBits(winformsRect, ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb);

            try
            {
                fixed(byte *framebufferData = target.GetBuffer())
                {
                    VncPixelFormat.Copy(data.Scan0, data.Stride, new VncPixelFormat(32, 24, 8, 16, 8, 8, 8, 0), sourceRectangle,
                                        (IntPtr)framebufferData, target.Stride, target.PixelFormat, targetX, targetY);
                }
            }
            finally
            {
                source.UnlockBits(data);
            }
        }
        public void FramebufferSendChangesTest()
        {
            var session = new VncServerSession();
            var framebufferSourceMock = new Mock <IVncFramebufferSource>();
            var framebuffer           = new VncFramebuffer("My Framebuffer", width: 0x4f4, height: 0x3c1, pixelFormat: VncPixelFormat.RGB32);

            framebufferSourceMock
            .Setup(f => f.Capture())
            .Returns(
                () =>
            {
                return(framebuffer);
            });
            session.FramebufferUpdateRequest = new FramebufferUpdateRequest(false, new VncRectangle(0, 0, 100, 100));
            session.SetFramebufferSource(framebufferSourceMock.Object);
            session.FramebufferSendChanges();

            Assert.Equal(framebuffer, session.Framebuffer);

            framebufferSourceMock = new Mock <IVncFramebufferSource>();
            framebufferSourceMock
            .Setup(f => f.Capture())
            .Throws(new IOException());

            session.FramebufferUpdateRequest = new FramebufferUpdateRequest(false, new VncRectangle(0, 0, 100, 100));
            session.SetFramebufferSource(framebufferSourceMock.Object);

            // should not throw and exception.
            session.FramebufferSendChanges();

            Assert.Equal(framebuffer, session.Framebuffer);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Initializes a new instance of the <see cref="VncFramebufferCache"/> class.
        /// </summary>
        /// <param name="framebuffer">
        /// The <see cref="VncFramebuffer"/> to cache.
        /// </param>
        public VncFramebufferCache(VncFramebuffer framebuffer)
        {
            Throw.If.Null(framebuffer, "framebuffer");
            this.Framebuffer       = framebuffer;
            this.cachedFramebuffer = new VncFramebuffer(framebuffer.Name, framebuffer.Width, framebuffer.Height, framebuffer.PixelFormat);

            this.isLineInvalid = new bool[this.Framebuffer.Height];
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="VncFramebufferCache"/> class.
        /// </summary>
        /// <param name="framebuffer">
        /// The <see cref="VncFramebuffer"/> to cache.
        /// </param>
        public VncFramebufferCache(VncFramebuffer framebuffer)
        {
            Throw.If.Null(framebuffer, "framebuffer");
            this.Framebuffer = framebuffer;
            this.cachedFramebuffer = new VncFramebuffer(framebuffer.Name, framebuffer.Width, framebuffer.Height, framebuffer.PixelFormat);

            this.isLineInvalid = new bool[this.Framebuffer.Height];
        }
        public VncFramebufferCache(VncFramebuffer framebuffer)
        {
            Throw.If.Null(framebuffer, "framebuffer");
            Framebuffer = framebuffer;

            _hashes = new byte[(framebuffer.Height + TileSize - 1) / TileSize,
                               (framebuffer.Width + TileSize - 1) / TileSize][];
            _pixelBuffer = new byte[TileSize * TileSize * Framebuffer.PixelFormat.BytesPerPixel];
        }
Exemplo n.º 8
0
        private float GetScaleFactor(VncFramebuffer framebuffer)
        {
            if (framebuffer == null)
            {
                return(1.0f);
            }
            var scaleFactor = this.GetScaleFactor(framebuffer.Width, framebuffer.Height, this.Width, this.Height);

            return(scaleFactor);
        }
Exemplo n.º 9
0
        /// <inheritdoc/>
        public VncFramebuffer Capture()
        {
            int colorIndex = this.random.Next(this.colors.Length);

            if (this.colors[colorIndex] + this.increments[colorIndex] < byte.MinValue ||
                this.colors[colorIndex] + this.increments[colorIndex] > byte.MaxValue)
            {
                this.increments[colorIndex] *= -1;
            }

            this.colors[colorIndex] = (byte)(this.colors[colorIndex] + this.increments[colorIndex]);

            var color = Color.FromArgb(this.colors[0], this.colors[1], this.colors[2]);

            using (Bitmap image = new Bitmap(this.width, this.height))
                using (Graphics gfx = Graphics.FromImage(image))
                    using (SolidBrush brush = new SolidBrush(color))
                        using (var font = new Font(FontFamily.GenericSansSerif, 12.0f, FontStyle.Bold, GraphicsUnit.Pixel))
                        {
                            gfx.FillRectangle(brush, 0, 0, image.Width, image.Height);

                            var text = $"RemoteViewing {ThisAssembly.AssemblyInformationalVersion}";
                            var size = gfx.MeasureString(text, font);

                            var position = new PointF((image.Width - size.Width) / 2.0f, (image.Height - size.Height) / 2.0f);

                            gfx.DrawString(
                                text,
                                font,
                                Brushes.Black,
                                position);

                            if (this.framebuffer == null ||
                                this.framebuffer.Width != image.Width ||
                                this.framebuffer.Height != image.Height)
                            {
                                this.framebuffer = new VncFramebuffer("Quamotion", image.Width, image.Height, new VncPixelFormat());
                            }

                            lock (this.framebuffer.SyncRoot)
                            {
                                VncBitmap.CopyToFramebuffer(
                                    image,
                                    new VncRectangle(0, 0, image.Width, image.Height),
                                    this.framebuffer,
                                    0,
                                    0);
                            }

                            return(this.framebuffer);
                        }
        }
Exemplo n.º 10
0
        /// <summary>
        /// Initializes a new instance of the <see cref="VncFramebufferCache"/> class.
        /// </summary>
        /// <param name="framebuffer">
        /// The <see cref="VncFramebuffer"/> to cache.
        /// </param>
        /// <param name="logger">
        /// The <see cref="ILog"/> logger to use when logging diagnostic messages.
        /// </param>
        public VncFramebufferCache(VncFramebuffer framebuffer, ILog logger)
        {
            if (framebuffer == null)
            {
                throw new ArgumentNullException(nameof(framebuffer));
            }

            this.Framebuffer       = framebuffer;
            this.cachedFramebuffer = new VncFramebuffer(framebuffer.Name, framebuffer.Width, framebuffer.Height, framebuffer.PixelFormat);

            this.logger        = logger;
            this.isLineInvalid = new bool[this.Framebuffer.Height];
        }
Exemplo n.º 11
0
        public void SetPixelInvalidValueTest()
        {
            var fb = new VncFramebuffer("test", 10, 10, VncPixelFormat.RGB32);

            Assert.Throws <ArgumentOutOfRangeException>(() => fb.SetPixel(0, 10, 0));
            Assert.Throws <ArgumentOutOfRangeException>(() => fb.SetPixel(10, 0, 0));
            Assert.Throws <ArgumentOutOfRangeException>(() => fb.SetPixel(0, 11, 0));
            Assert.Throws <ArgumentOutOfRangeException>(() => fb.SetPixel(11, 0, 0));
            Assert.Throws <ArgumentOutOfRangeException>(() => fb.SetPixel(0, -1, 0));
            Assert.Throws <ArgumentOutOfRangeException>(() => fb.SetPixel(-1, 0, 0));
            Assert.Throws <ArgumentOutOfRangeException>(() => fb.SetPixel(10, -1, 0));
            Assert.Throws <ArgumentOutOfRangeException>(() => fb.SetPixel(-1, 10, 0));
        }
Exemplo n.º 12
0
        void UpdateFramebuffer(bool force, VncFramebuffer framebuffer)
        {
            if (framebuffer == null)
            {
                return;
            }
            int w = framebuffer.Width, h = framebuffer.Height;

            if (_bitmap == null || _bitmap.Width != w || _bitmap.Height != h || force)
            {
                _bitmap = new Bitmap(w, h, PixelFormat.Format32bppRgb);
                VncBitmap.CopyFromFramebuffer(framebuffer, new VncRectangle(0, 0, w, h), _bitmap, 0, 0);
                ClientSize = new Size(w, h); Invalidate();
            }
        }
Exemplo n.º 13
0
        /// <summary>
        /// Copies a region of a bitmap into the framebuffer.
        /// </summary>
        /// <param name="source">The bitmap to read.</param>
        /// <param name="sourceRectangle">The bitmap region to copy.</param>
        /// <param name="target">The framebuffer to copy into.</param>
        /// <param name="targetX">The leftmost X coordinate of the framebuffer to draw to.</param>
        /// <param name="targetY">The topmost Y coordinate of the framebuffer to draw to.</param>
        public static unsafe void CopyToFramebuffer(
            Bitmap source,
            VncRectangle sourceRectangle,
            VncFramebuffer target,
            int targetX,
            int targetY)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            if (target == null)
            {
                throw new ArgumentNullException(nameof(target));
            }

            if (sourceRectangle.IsEmpty)
            {
                return;
            }

            var winformsRect = new Rectangle(sourceRectangle.X, sourceRectangle.Y, sourceRectangle.Width, sourceRectangle.Height);
            var data         = source.LockBits(winformsRect, ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb);

            try
            {
                fixed(byte *framebufferData = target.GetBuffer())
                {
                    VncPixelFormat.Copy(
                        data.Scan0,
                        data.Stride,
                        new VncPixelFormat(),
                        sourceRectangle,
                        (IntPtr)framebufferData,
                        target.Stride,
                        target.PixelFormat,
                        targetX,
                        targetY);
                }
            }
            finally
            {
                source.UnlockBits(data);
            }
        }
Exemplo n.º 14
0
        private void UpdateFramebuffer(bool force, VncFramebuffer framebuffer)
        {
            if (framebuffer == null)
            {
                return;
            }

            int w = framebuffer.Width, h = framebuffer.Height;

            if (this.bitmap == null || this.bitmap.Width != w || this.bitmap.Height != h || force)
            {
                this.bitmap = new Bitmap(w, h, PixelFormat.Format32bppRgb);
                VncBitmap.CopyFromFramebuffer(framebuffer, new VncRectangle(0, 0, w, h), this.bitmap, 0, 0);

                this.ScaleFactor = this.GetScaleFactor(framebuffer);
                this.Invalidate();
            }
        }
Exemplo n.º 15
0
        public VncFramebuffer Capture()
        {
            lock (_lock)
            {
                using (var bmpRef = Window.GetLastRenderedFrame())
                {
                    if (bmpRef?.Item == null)
                    {
                        return(_framebuffer);
                    }
                    var bmp = bmpRef.Item;
                    if (bmp.PixelSize.Width != _framebuffer.Width || bmp.PixelSize.Height != _framebuffer.Height)
                    {
                        _framebuffer = new VncFramebuffer("Avalonia", bmp.PixelSize.Width, bmp.PixelSize.Height,
                                                          VncPixelFormat.RGB32);
                    }

                    using (var fb = bmp.Lock())
                    {
                        var buf = _framebuffer.GetBuffer();
                        if (_framebuffer.Stride == fb.RowBytes)
                        {
                            Marshal.Copy(fb.Address, buf, 0, buf.Length);
                        }
                        else
                        {
                            for (var y = 0; y < fb.Size.Height; y++)
                            {
                                var sourceStart = fb.RowBytes * y;
                                var dstStart    = _framebuffer.Stride * y;
                                var row         = fb.Size.Width * 4;
                                Marshal.Copy(new IntPtr(sourceStart + fb.Address.ToInt64()), buf, dstStart, row);
                            }
                        }
                    }
                }
            }

            return(_framebuffer);
        }
Exemplo n.º 16
0
        /// <inheritdoc/>
        public VncFramebuffer Capture()
        {
            int colorIndex = this.random.Next(this.colors.Length);

            if (this.colors[colorIndex] + this.increments[colorIndex] < byte.MinValue ||
                this.colors[colorIndex] + this.increments[colorIndex] > byte.MaxValue)
            {
                this.increments[colorIndex] *= -1;
            }

            this.colors[colorIndex] = (byte)(this.colors[colorIndex] + this.increments[colorIndex]);

            var color = Color.FromArgb(this.colors[0], this.colors[1], this.colors[2]);

            using (Bitmap image = new Bitmap(400, 400))
                using (Graphics gfx = Graphics.FromImage(image))
                    using (SolidBrush brush = new SolidBrush(color))
                    {
                        gfx.FillRectangle(brush, 0, 0, image.Width, image.Height);

                        if (this.framebuffer == null ||
                            this.framebuffer.Width != image.Width ||
                            this.framebuffer.Height != image.Height)
                        {
                            this.framebuffer = new VncFramebuffer("Quamotion", image.Width, image.Height, new VncPixelFormat());
                        }

                        lock (this.framebuffer.SyncRoot)
                        {
                            VncBitmap.CopyToFramebuffer(
                                image,
                                new VncRectangle(0, 0, image.Width, image.Height),
                                this.framebuffer,
                                0,
                                0);
                        }

                        return(this.framebuffer);
                    }
        }
Exemplo n.º 17
0
        /// <summary>
        /// Copies a region of the framebuffer into a bitmap.
        /// </summary>
        /// <param name="source">The framebuffer to read.</param>
        /// <param name="sourceRectangle">The framebuffer region to copy.</param>
        /// <param name="target">The bitmap to copy into.</param>
        /// <param name="targetX">The leftmost X coordinate of the bitmap to draw to.</param>
        /// <param name="targetY">The topmost Y coordinate of the bitmap to draw to.</param>
        public static unsafe void CopyFromFramebuffer(
            VncFramebuffer source,
            VncRectangle sourceRectangle,
            Bitmap target,
            int targetX,
            int targetY)
        {
            if (target == null)
            {
                throw new ArgumentNullException(nameof(target));
            }

            var winformsRect = new Rectangle(targetX, targetY, sourceRectangle.Width, sourceRectangle.Height);
            var data         = target.LockBits(winformsRect, ImageLockMode.WriteOnly, PixelFormat.Format32bppRgb);

            try
            {
                VncPixelFormat.CopyFromFramebuffer(source, sourceRectangle, data.Scan0, data.Stride, targetX, targetY);
            }
            finally
            {
                target.UnlockBits(data);
            }
        }
        public void SetDesktopSizeTest()
        {
            var framebuffer1 = new VncFramebuffer("test-1", 100, 200, VncPixelFormat.RGB32);
            var framebuffer2 = new VncFramebuffer("test-2", 200, 400, VncPixelFormat.RGB32);
            var framebuffer  = framebuffer1;

            var framebufferSourceMock = new Mock <IVncFramebufferSource>(MockBehavior.Strict);

            framebufferSourceMock
            .Setup(m => m.SetDesktopSize(200, 300))
            .Returns(ExtendedDesktopSizeStatus.Success)
            .Callback(() => { framebuffer = framebuffer2; });

            framebufferSourceMock
            .Setup(m => m.Capture())
            .Returns(() => framebuffer);

            using (var stream = new TestStream())
            {
                VncStream clientStream = new VncStream(stream.Input);

                // Negotiating the dessktop size
                clientStream.SendByte(0); // share desktop setting

                // Send a SetDesktopSize request
                clientStream.SendByte((byte)VncMessageType.SetDesktopSize);
                clientStream.SendByte(0);       // padding
                clientStream.SendUInt16BE(200); // width
                clientStream.SendUInt16BE(300); // height
                clientStream.SendByte(1);       // number of screens
                clientStream.SendByte(0);       // padding
                clientStream.SendUInt32BE(1);   // screen id
                clientStream.SendUInt16BE(0);   // x position
                clientStream.SendUInt16BE(0);   // x position
                clientStream.SendUInt16BE(200); // width
                clientStream.SendUInt16BE(300); // height
                clientStream.SendUInt32BE(0);   // flags

                stream.Input.Position = 0;

                var session = new VncServerSession();
                session.SetFramebufferSource(framebufferSourceMock.Object);
                session.Connect(stream, null, startThread: false);

                // Negotiate the desktop
                session.NegotiateDesktop();
                Assert.Equal(VncPixelFormat.RGB32, session.ClientPixelFormat);

                // Handle the SetDesktopSize request
                session.HandleMessage();

                VncStream serverStream = new VncStream(stream.Output);
                stream.Output.Position = 0;

                // Desktop negotiation result
                Assert.Equal(100, serverStream.ReceiveUInt16BE());
                Assert.Equal(200, serverStream.ReceiveUInt16BE());
                var format = serverStream.Receive(16);
                Assert.Equal("test-1", serverStream.ReceiveString());

                // SetDesktopSize result
                Assert.Equal(0, serverStream.ReceiveUInt16BE());                                         // Update rectangle request
                Assert.Equal(1, serverStream.ReceiveUInt16BE());                                         // 1 rectangle;

                Assert.Equal((ushort)ExtendedDesktopSizeReason.Client, serverStream.ReceiveUInt16BE());  // x
                Assert.Equal((ushort)ExtendedDesktopSizeStatus.Success, serverStream.ReceiveUInt16BE()); // y
                Assert.Equal(100, serverStream.ReceiveUInt16BE());                                       // width
                Assert.Equal(200, serverStream.ReceiveUInt16BE());                                       // height

                Assert.Equal((int)VncEncoding.ExtendedDesktopSize, (int)serverStream.ReceiveUInt32BE()); // encoding

                Assert.Equal(1u, serverStream.ReceiveByte());                                            // Number of screens
                serverStream.Receive(3);                                                                 // Padding
                Assert.Equal(0u, serverStream.ReceiveUInt32BE());                                        // screen ID
                Assert.Equal(0u, serverStream.ReceiveUInt16BE());                                        // x-position
                Assert.Equal(0u, serverStream.ReceiveUInt16BE());                                        // y-position
                Assert.Equal(100u, serverStream.ReceiveUInt16BE());                                      // width
                Assert.Equal(200u, serverStream.ReceiveUInt16BE());                                      // height
                Assert.Equal(0u, serverStream.ReceiveUInt32BE());                                        // flags

                Assert.Equal(stream.Output.Length, stream.Output.Position);
                Assert.Equal(stream.Input.Length, stream.Input.Position);
            }
        }
Exemplo n.º 19
0
        /// <summary>
        /// Asynchronously writes framebuffer packages to a <see cref="Stream"/>.
        /// </summary>
        /// <param name="stream">
        /// The <see cref="Stream"/> to which to write.
        /// </param>
        /// <param name="cancellationToken">
        /// A <see cref="CancellationToken"/> which can be used to cancel the asynchronous operation. This method
        /// will keep recording until cancellation is requested.
        /// </param>
        /// <returns>
        /// A <see cref="Task"/> which represents the asynchronous operation.
        /// </returns>
        public async Task WriteAsync(Stream stream, CancellationToken cancellationToken)
        {
            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream));
            }

            VncFramebuffer framebuffer = this.framebufferSource.Capture();

            // The RIFF header, wraps the entire file.
            await stream.WriteStructAsync(
                new List()
            {
                ListType = FourCC.Riff,
                FourCC   = FourCC.Avi,
                Size     = this.ExpectedSize,
            },
                cancellationToken).ConfigureAwait(false);

            // HDRL list. Defines the format of the data and is the first required LIST chunk.
            await stream.WriteStructAsync(
                new List()
            {
                ListType = FourCC.List,
                FourCC   = FourCC.Hdrl,
                Size     = 0x449c, // TBC
            },
                cancellationToken).ConfigureAwait(false);

            // AVIH chunk. Contains the main AVI header.
            await stream.WriteStructAsync(
                new Chunk()
            {
                FourCC = FourCC.Avih,
                Size   = Unsafe.SizeOf <AviMainHeader>(),
            },
                cancellationToken).ConfigureAwait(false);

            await stream.WriteStructAsync(
                new AviMainHeader()
            {
                Flags               = MainHeaderFlags.HasIndex,
                Height              = framebuffer.Height,
                Width               = framebuffer.Width,
                MaxBytesPerSec      = 1448660, // TBC
                MicroSecPerFrame    = this.MicrosecondsPerFrame,
                Streams             = 1,
                SuggestedBufferSize = 0x046bc4,     // TBC
                TotalFrames         = this.ExpectedTotalFrames,
            },
                cancellationToken).ConfigureAwait(false);

            // STRL list. Contains informatio about a stream.
            await stream.WriteStructAsync(
                new List()
            {
                ListType = FourCC.List,
                FourCC   = FourCC.Strl,
                Size     = 17220,
            },
                cancellationToken).ConfigureAwait(false);

            // STRH chunk
            await stream.WriteStructAsync(
                new Chunk()
            {
                FourCC = FourCC.Strh,
                Size   = 0x38,
            },
                cancellationToken).ConfigureAwait(false);

            await stream.WriteStructAsync(
                new AviStreamHeader()
            {
                Type                = FourCC.Vids,
                Handler             = FourCC.VMnc,
                Length              = this.ExpectedTotalFrames,
                Quality             = -1,
                Rate                = this.Rate,
                Scale               = this.Scale,
                SuggestedBufferSize = 0x00046bc4,
                Bottom              = (short)framebuffer.Height,
                Right               = (short)framebuffer.Width,
            },
                cancellationToken).ConfigureAwait(false);

            // STRF chunk
            await stream.WriteStructAsync(
                new Chunk()
            {
                FourCC = FourCC.Strf,
                Size   = 0x28,
            },
                cancellationToken).ConfigureAwait(false);

            // BitmapInfoHeader
            await stream.WriteStructAsync(
                new BitmapInfoHeader()
            {
                BitCount    = 0x20,
                Compression = FourCC.VMnc,
                Height      = framebuffer.Height,
                Planes      = 1,
                Size        = 0x28, // TBC
                Width       = framebuffer.Width,
            },
                cancellationToken).ConfigureAwait(false);

            // Index chunk
            var indexSize = 0x000042c8; // TBC
            await stream.WriteStructAsync(
                new AviIndexChunck()
            {
                FourCC        = FourCC.Indx,
                Size          = indexSize,
                EntriesInUse  = 1,
                ChunkId       = FourCC.Dc00,
                LongsPerEntry = 4,
                IndexType     = IndexType.IndexOfIndexes,
                IndexSubType  = IndexSubType.None,
            },
                cancellationToken).ConfigureAwait(false);

            // Super index chunk
            await stream.WriteStructAsync(
                new AviSuperIndexEntry()
            {
                Duration = this.ExpectedTotalFrames,
                Offset   = 0x000000000004196a,
                Size     = 0x4000,
            },
                cancellationToken);

            await stream.GrowAsync(indexSize - Unsafe.SizeOf <AviSuperIndexEntry>() - Unsafe.SizeOf <AviIndexChunck>() + Unsafe.SizeOf <Chunk>(), cancellationToken).ConfigureAwait(false);

            // ODML chunk
            await stream.WriteStructAsync(
                new List()
            {
                ListType = FourCC.List,
                FourCC   = FourCC.Odml,
                Size     = 0x00000104,
            },
                cancellationToken).ConfigureAwait(false);

            // DMLH chunk
            indexSize = 0xf8;
            await stream.WriteStructAsync(
                new AviIndexChunck()
            {
                FourCC        = FourCC.Dmlh,
                Size          = indexSize,
                IndexType     = IndexType.IndexOfIndexes,
                IndexSubType  = IndexSubType.None,
                ChunkId       = (FourCC)BinaryPrimitives.ReverseEndianness((uint)VncEncoding.Raw),
                EntriesInUse  = 0,
                LongsPerEntry = 0x13e,
            },
                cancellationToken);

            await stream.GrowAsync(indexSize - Unsafe.SizeOf <AviIndexChunck>() + Unsafe.SizeOf <Chunk>(), cancellationToken).ConfigureAwait(false);

            var junkSize = 0x00000348;
            await stream.WriteStructAsync(
                new Chunk()
            {
                FourCC = FourCC.Junk,
                Size   = junkSize,   // TBC
            },
                cancellationToken).ConfigureAwait(false);

            var junk = "VMware Workstation";

            byte[] buffer = new byte[128];
            Encoding.ASCII.GetBytes(junk, 0, junk.Length, buffer, 0);
            stream.Write(buffer, 0, junk.Length);

            await stream.GrowAsync(junkSize - junk.Length, cancellationToken).ConfigureAwait(false);

            // The movie list
            await stream.WriteStructAsync(
                new List()
            {
                FourCC   = FourCC.Movi,
                ListType = FourCC.List,
                Size     = this.ExpectedSize - 0x4800,
            },
                cancellationToken);

            FramebufferUpdate framebufferUpdate = new FramebufferUpdate()
            {
                MessageType        = 0,
                NumberOfRectangles = 2,
            };

            FramebufferUpdateRectangle rectangle         = new FramebufferUpdateRectangle();
            DisplayModeChange          displayModeChange = new DisplayModeChange();

            Chunk dcChunk = new Chunk()
            {
                FourCC = FourCC.Dc00,
                Size   =
                    4
                    + (2 * framebufferUpdate.Buffer.Length)
                    + displayModeChange.Buffer.Length
                    + (framebuffer.Stride * framebuffer.Width * framebuffer.PixelFormat.BytesPerPixel),
            };

            Stopwatch timer = new Stopwatch();

            while (!cancellationToken.IsCancellationRequested)
            {
                // Start a timer which will timeout after the timeframe allotted to each frame.
                timer.Restart();
                var interval = Task.Delay(this.MicrosecondsPerFrame / 1000, cancellationToken).ConfigureAwait(false);
                framebuffer = this.framebufferSource.Capture();

                if (framebuffer == null)
                {
                    break;
                }

                rectangle.Width  = (ushort)framebuffer.Width;
                rectangle.Height = (ushort)framebuffer.Height;

                await stream.WriteStructAsync(dcChunk, cancellationToken).ConfigureAwait(false);

                // Framebuffer update message, with 2 rectangles
                await stream.WriteAsync(framebufferUpdate.Buffer, cancellationToken).ConfigureAwait(false);

                // Pseudo-rectangle: display mode change pseudo-encoding
                rectangle.EncodingType = VncEncoding.VMWi;
                await stream.WriteAsync(rectangle.Buffer, cancellationToken).ConfigureAwait(false);

                displayModeChange.BitsPerSample = (byte)framebuffer.PixelFormat.BitsPerPixel;
                displayModeChange.Depth         = (byte)framebuffer.PixelFormat.BitDepth;
                displayModeChange.MaxBlue       = framebuffer.PixelFormat.BlueMax;
                displayModeChange.MaxGreen      = framebuffer.PixelFormat.GreenMax;
                displayModeChange.MaxRed        = framebuffer.PixelFormat.RedMax;
                displayModeChange.BlueShift     = (byte)framebuffer.PixelFormat.BlueShift;
                displayModeChange.GreenShift    = (byte)framebuffer.PixelFormat.GreenShift;
                displayModeChange.RedShift      = (byte)framebuffer.PixelFormat.RedShift;
                displayModeChange.TrueColor     = !framebuffer.PixelFormat.IsPalettized;
                await stream.WriteAsync(displayModeChange.Buffer, cancellationToken).ConfigureAwait(false);

                // Rectangle: framebuffer
                rectangle.EncodingType = VncEncoding.Raw;
                await stream.WriteAsync(rectangle.Buffer, cancellationToken).ConfigureAwait(false);

                var rawFramebuffer = framebuffer.GetBuffer();
                await stream.WriteAsync(rawFramebuffer, 0, rawFramebuffer.Length, cancellationToken).ConfigureAwait(false);

                Debug.WriteLine($"Completed in {timer.ElapsedMilliseconds} ms out of allowed {this.MicrosecondsPerFrame / 1000} ms");

                // Wait for the timer to complete.
                await interval;
            }
        }
Exemplo n.º 20
0
 public ConnectEventArgs(TcpClient currentTcpClient, VncFramebuffer currentVncFramebuffer)
 {
     CurrentTcpClient      = currentTcpClient;
     CurrentVncFramebuffer = currentVncFramebuffer;
 }