Example #1
0
        public void RequestRender()
        {
            this.fpsCount++;
            using var frame = this.framePool.TryGetNextFrame();
            if (frame != null && this.IsFrontBufferAvailable && this.fpsCount % this.FpsDivider == 0)
            {
                if (this.TryLock(new Duration(TimeSpan.Zero)))
                {
                    var newSize = false;
                    if (frame.ContentSize.Width != lastSize.Width ||
                        frame.ContentSize.Height != lastSize.Height)
                    {
                        // The thing we have been capturing has changed size.
                        // We need to resize the swap chain first, then blit the pixels.
                        // After we do that, retire the frame and then recreate the frame pool.
                        newSize  = true;
                        lastSize = frame.ContentSize;
                        this.renderTargetDescription.Width  = lastSize.Width;
                        this.renderTargetDescription.Height = lastSize.Height;
                        this.renderTarget?.Dispose();
                        this.renderTarget = new Texture2D(d3dDevice, this.renderTargetDescription);
                        backBufferSetted  = false;
                    }

                    using (var bitmap = Direct3D11Helper.CreateSharpDXTexture2D(frame.Surface))
                    {
                        d3dDevice.ImmediateContext.CopyResource(bitmap, this.renderTarget);
                    }

                    if (newSize || !backBufferSetted)
                    {
                        using var resource = this.renderTarget.QueryInterface <SharpDX.DXGI.Resource>();
                        var handle = resource.SharedHandle;

                        using var texture = new Texture(
                                  this.d9device,
                                  this.renderTarget.Description.Width,
                                  this.renderTarget.Description.Height,
                                  1,
                                  SharpDX.Direct3D9.Usage.RenderTarget,
                                  SharpDX.Direct3D9.Format.A8R8G8B8,
                                  Pool.Default,
                                  ref handle);
                        using var surface = texture.GetSurfaceLevel(0);
                        this.SetBackBuffer(D3DResourceType.IDirect3DSurface9, surface.NativePointer, true);
                        backBufferSetted = true;
                    }

                    this.AddDirtyRect(new Int32Rect(0, 0, lastSize.Width, lastSize.Height));

                    if (newSize)
                    {
                        framePool.Recreate(device, DirectXPixelFormat.B8G8R8A8UIntNormalized, 2, lastSize);
                    }
                }

                this.Unlock();
            }
        }
Example #2
0
        private void OnFrameArrived(Direct3D11CaptureFramePool sender, object args)
        {
            var newSize = false;



            using (var frame = sender.TryGetNextFrame())
            {
                if (frame.ContentSize.Width != lastSize.Width ||
                    frame.ContentSize.Height != lastSize.Height)
                {
                    // The thing we have been capturing has changed size.
                    // We need to resize the swap chain first, then blit the pixels.
                    // After we do that, retire the frame and then recreate the frame pool.
                    newSize  = true;
                    lastSize = frame.ContentSize;

                    swapChain.ResizeBuffers(
                        2,
                        lastSize.Width,
                        lastSize.Height,
                        SharpDX.DXGI.Format.B8G8R8A8_UNorm,
                        SharpDX.DXGI.SwapChainFlags.None);
                }

                if (!isWait)
                {
                    if (isStartCapture)
                    {
                        using (var backBuffer = swapChain.GetBackBuffer <SharpDX.Direct3D11.Texture2D>(0))
                            using (var bitmap = Direct3D11Helper.CreateSharpDXTexture2D(frame.Surface))
                            {
                                //d3dDevice.ImmediateContext.CopyResource(bitmap, backBuffer);
                                CopyBitmap(frame.Surface, bitmap, frame.ContentSize.Width, frame.ContentSize.Height);

                                Console.WriteLine("Capture");

                                bitmap.Dispose();
                            };

                        isStartCapture = false;
                    }
                }

                //using (var backBuffer = swapChain.GetBackBuffer<SharpDX.Direct3D11.Texture2D>(0))
            } // Retire the frame.

            swapChain.Present(0, SharpDX.DXGI.PresentFlags.None);

            if (newSize)
            {
                framePool.Recreate(
                    device,
                    DirectXPixelFormat.B8G8R8A8UIntNormalized,
                    2,
                    lastSize);
            }
        }
Example #3
0
        private DirectXVideoSample?GetNextFrame()
        {
            currentFrame?.Dispose();
            frameEvent.Reset();

            var signaledEvent = events[WaitHandle.WaitAny(events)];

            if (signaledEvent == closedEvent)
            {
                // Safe to cleanup non-persistent resources as this method will return and the code below no longer references them
                canCleanupNonPersistentResourcesEvent.Set();
                return(null);
            }

            using (new MultithreadLock(multithread))
            {
                if (currentFrame == null)
                {
                    return(null);
                }

                // Copy the captured frame from the framepool to a useable texture
                using var sourceTexture = Direct3D11Helper.CreateSharpDXTexture2D(currentFrame.Surface);
                if (sourceTexture == null)
                {
                    return(null);
                }

                var description = sourceTexture.Description;
                description.Usage          = ResourceUsage.Default;
                description.BindFlags      = BindFlags.ShaderResource | BindFlags.RenderTarget;
                description.CpuAccessFlags = CpuAccessFlags.None;
                description.OptionFlags    = ResourceOptionFlags.None;

                using var copyTexture = new Texture2D(sharpDXDevice, description);
                var width  = Math.Clamp(currentFrame.ContentSize.Width, 0, currentFrame.Surface.Description.Width);
                var height = Math.Clamp(currentFrame.ContentSize.Height, 0, currentFrame.Surface.Description.Height);

                var region = new ResourceRegion(0, 0, 0, width, height, 1);

                sharpDXDevice.ImmediateContext.CopyResource(blankTexture, copyTexture);
                sharpDXDevice.ImmediateContext.CopySubresourceRegion(sourceTexture, 0, region, copyTexture, 0);

                var surface = Direct3D11Helper.CreateDirect3DSurfaceFromSharpDXTexture(copyTexture);
                if (surface == null)
                {
                    return(null);
                }

                return(new DirectXVideoSample
                {
                    Surface = surface
                });
            }
        }
Example #4
0
        /// <summary>
        /// 帧到达事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void OnFrameArrived(Direct3D11CaptureFramePool sender, object args)
        {
            var newSize = false;

            using Direct3D11CaptureFrame frame = sender.TryGetNextFrame();

            if (frame == null)
            {
                return;
            }

            if (frame.ContentSize.Width != lastSize.Width || frame.ContentSize.Height != lastSize.Height)
            {
                // 我们捕捉到的东西变大了。
                // 我们需要先调整交换链的大小,然后blit像素。
                // 完成此操作后,请注销帧,然后重新创建帧池。
                newSize  = true;
                lastSize = frame.ContentSize;
                swapChain.ResizeBuffers(
                    2,
                    lastSize.Width,
                    lastSize.Height,
                    SharpDX.DXGI.Format.B8G8R8A8_UNorm,
                    SharpDX.DXGI.SwapChainFlags.None);
            }

            using Texture2D backBuffer = swapChain.GetBackBuffer <Texture2D>(0);
            using Texture2D tex        = Direct3D11Helper.CreateSharpDXTexture2D(frame.Surface);
            d3dDevice.ImmediateContext.CopyResource(tex, backBuffer);
            // 保存当前帧到位图
            if (GetOneFrameFromBitmapEvent != null)
            {
                TryGetOneFrameToBitmap(tex);
            }
            // GetOneFrameToBitmap(tex);

            swapChain.Present(0, SharpDX.DXGI.PresentFlags.None);

            if (newSize)
            {
                framePool.Recreate(device, Windows.Graphics.DirectX.DirectXPixelFormat.B8G8R8A8UIntNormalized, 2, lastSize);
            }
        }
Example #5
0
        private void OnFrameArrived(Direct3D11CaptureFramePool sender, object args)
        {
            var newSize = false;

            using (var frame = sender.TryGetNextFrame())
            {
                if (frame.ContentSize.Width != lastSize.Width ||
                    frame.ContentSize.Height != lastSize.Height)
                {
                    // The thing we have been capturing has changed size.
                    // We need to resize the swap chain first, then blit the pixels.
                    // After we do that, retire the frame and then recreate the frame pool.
                    newSize         = true;
                    lastSize        = frame.ContentSize;
                    lastSize.Width  = lastSize.Width / 8 * 8;
                    lastSize.Height = lastSize.Height / 8 * 8;
                    swapChain.ResizeBuffers(
                        2,
                        lastSize.Width,
                        lastSize.Height,
                        Format.B8G8R8A8_UNorm,
                        SwapChainFlags.None);
                }

                using (var backBuffer = swapChain.GetBackBuffer <SharpDX.Direct3D11.Texture2D>(0))
                    using (var bitmap = Direct3D11Helper.CreateSharpDXTexture2D(frame.Surface))
                    {
                        d3dDevice.ImmediateContext.CopyResource(bitmap, backBuffer);

                        if (lastFrame != null)
                        {
                            d3dDevice.ImmediateContext.UnmapSubresource(lastFrame, 0);
                            lastFrame.Dispose();
                        }

                        // Create texture copy
                        lastFrame = new SharpDX.Direct3D11.Texture2D(d3dDevice, new SharpDX.Direct3D11.Texture2DDescription
                        {
                            Width             = bitmap.Description.Width,
                            Height            = bitmap.Description.Height,
                            MipLevels         = 1,
                            ArraySize         = 1,
                            Format            = Format.B8G8R8A8_UNorm,
                            Usage             = ResourceUsage.Staging,
                            SampleDescription = new SampleDescription(1, 0),
                            BindFlags         = BindFlags.None,
                            CpuAccessFlags    = CpuAccessFlags.Read,
                            OptionFlags       = ResourceOptionFlags.None
                        });
                        d3dDevice.ImmediateContext.CopyResource(bitmap, lastFrame);

                        var dataBox = d3dDevice.ImmediateContext.MapSubresource(lastFrame, 0, 0, MapMode.Read, SharpDX.Direct3D11.MapFlags.None, out DataStream stream);
                        var rect    = new DataRectangle
                        {
                            DataPointer = stream.DataPointer,
                            Pitch       = dataBox.RowPitch
                        };
                        lastMat = new Mat(lastFrame.Description.Height, lastFrame.Description.Width, MatType.CV_8UC4, stream.DataPointer); // width % 4 != 0

                        OnFrameReady(EventArgs.Empty);
                    }
            } // Retire the frame.

            // swapChain.Present(0, SharpDX.DXGI.PresentFlags.None);
            if (newSize)
            {
                framePool.Recreate(
                    device,
                    DirectXPixelFormat.B8G8R8A8UIntNormalized,
                    2,
                    lastSize);
            }
        }
Example #6
0
        public async Task <Bitmap> TryGetOneFrameAsync()
        {
            bool      captureDone = false;
            Texture2D tex;
            Bitmap    result = null;

            await Task.Run(() =>
            {
                for (int i = 0; !captureDone; i++)
                {
                    try
                    {
                        if (framePool.TryGetNextFrame() == null)
                        {
                            continue;
                        }

                        tex    = Direct3D11Helper.CreateSharpDXTexture2D(framePool.TryGetNextFrame().Surface);
                        result = new Bitmap(tex.Description.Width, tex.Description.Height, PixelFormat.Format32bppArgb);

                        using Texture2D copy = new Texture2D(d3dDevice, new Texture2DDescription
                        {
                            Height            = tex.Description.Height,
                            Width             = tex.Description.Width,
                            MipLevels         = 1,
                            ArraySize         = 1,
                            Format            = SharpDX.DXGI.Format.B8G8R8A8_UNorm,
                            Usage             = ResourceUsage.Staging,
                            SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0),
                            BindFlags         = BindFlags.None,
                            CpuAccessFlags    = CpuAccessFlags.Read,
                            OptionFlags       = ResourceOptionFlags.None
                        });
                        d3dDevice.ImmediateContext.CopyResource(tex, copy);

                        var dataBox = d3dDevice.ImmediateContext.MapSubresource(copy, 0, MapMode.Read, SharpDX.Direct3D11.MapFlags.None);
                        try
                        {
                            BitmapData bitmapData = result.LockBits(new Rectangle(0, 0, tex.Description.Width, tex.Description.Height),
                                                                    ImageLockMode.WriteOnly, result.PixelFormat);
                            try
                            {
                                var srcPtr = dataBox.DataPointer;
                                var dstPtr = bitmapData.Scan0;

                                for (var y = 0; y < result.Height; y++)
                                {
                                    memcpy(dstPtr, srcPtr, new UIntPtr((uint)(result.Width * 4)));
                                    srcPtr = IntPtr.Add(srcPtr, dataBox.RowPitch);
                                    dstPtr = IntPtr.Add(dstPtr, bitmapData.Stride);
                                }
                            }
                            finally
                            {
                                result.UnlockBits(bitmapData);
                            }
                        }
                        finally
                        {
                            d3dDevice.ImmediateContext.UnmapSubresource(copy, 0);
                        }

                        captureDone = true;
                    }
                    catch (SharpDX.SharpDXException e)
                    {
                        if (e.ResultCode.Code != SharpDX.DXGI.ResultCode.WaitTimeout.Result.Code)
                        {
                            throw e;
                        }
                    }
                }
            });

            return(result);
        }
Example #7
0
        static void Main(string[] args)
        {
            // Get a capture item that represents the primary monitor
            var monitor = MonitorFromWindow(GetDesktopWindow(), MONITOR_DEFAULTTOPRIMARY);
            var item    = CaptureHelper.CreateItemForMonitor(monitor);
            var size    = item.Size;

            // Setup D3D
            var device     = Direct3D11Helper.CreateDevice();
            var d3dDevice  = Direct3D11Helper.CreateSharpDXDevice(device);
            var d3dContext = d3dDevice.ImmediateContext;

            // Create our staging texture
            var description = new SharpDX.Direct3D11.Texture2DDescription
            {
                Width             = size.Width,
                Height            = size.Height,
                MipLevels         = 1,
                ArraySize         = 1,
                Format            = SharpDX.DXGI.Format.B8G8R8A8_UNorm,
                SampleDescription = new SharpDX.DXGI.SampleDescription()
                {
                    Count   = 1,
                    Quality = 0
                },
                Usage          = SharpDX.Direct3D11.ResourceUsage.Staging,
                BindFlags      = SharpDX.Direct3D11.BindFlags.None,
                CpuAccessFlags = SharpDX.Direct3D11.CpuAccessFlags.Read,
                OptionFlags    = SharpDX.Direct3D11.ResourceOptionFlags.None
            };
            var stagingTexture = new SharpDX.Direct3D11.Texture2D(d3dDevice, description);

            // Setup capture
            var framePool = Direct3D11CaptureFramePool.CreateFreeThreaded(
                device,
                DirectXPixelFormat.B8G8R8A8UIntNormalized,
                1,
                size);
            var session = framePool.CreateCaptureSession(item);

            var imageNum = 0;
            var endEvent = new ManualResetEvent(false);

            framePool.FrameArrived += (sender, a) =>
            {
                using (var frame = sender.TryGetNextFrame())
                    using (var bitmap = Direct3D11Helper.CreateSharpDXTexture2D(frame.Surface))
                    {
                        // Copy to our staging texture
                        d3dContext.CopyResource(bitmap, stagingTexture);

                        // Map our texture and get the bits
                        var mapped       = d3dContext.MapSubresource(stagingTexture, 0, SharpDX.Direct3D11.MapMode.Read, SharpDX.Direct3D11.MapFlags.None);
                        var source       = mapped.DataPointer;
                        var sourceStride = mapped.RowPitch;

                        // Allocate some memory to hold our copy
                        var bytes = new byte[size.Width * size.Height * 4]; // 4 bytes per pixel
                        unsafe
                        {
                            fixed(byte *bytesPointer = bytes)
                            {
                                var dest       = (IntPtr)bytesPointer;
                                var destStride = size.Width * 4;

                                for (int i = 0; i < size.Height; i++)
                                {
                                    SharpDX.Utilities.CopyMemory(dest, source, destStride);

                                    source = IntPtr.Add(source, sourceStride);
                                    dest   = IntPtr.Add(dest, destStride);
                                }
                            }
                        }

                        // Don't forget to unmap when you're done!
                        d3dContext.UnmapSubresource(stagingTexture, 0);

                        // Encode it
                        // NOTE: Waiting here will stall the capture
                        EncodeBytesAsync($"image{imageNum}.png", size.Width, size.Height, bytes).Wait();

                        imageNum++;
                        if (imageNum > 10)
                        {
                            framePool.Dispose();
                            session.Dispose();
                            endEvent.Set();
                        }
                    }
            };

            // Start the capture and wait
            session.StartCapture();
            endEvent.WaitOne();
        }