예제 #1
0
        public void StartCapture(IntPtr hWnd, Device device, Factory factory)
        {
            var capturePicker = new GraphicsCapturePicker();

            // ReSharper disable once PossibleInvalidCastException
            // ReSharper disable once SuspiciousTypeConversion.Global
            var initializer = (IInitializeWithWindow)(object)capturePicker;

            initializer.Initialize(hWnd);

            _captureItem = capturePicker.PickSingleItemAsync().AsTask().Result;
            if (_captureItem == null)
            {
                return;
            }

            _captureItem.Closed += CaptureItemOnClosed;

            var hr = NativeMethods.CreateDirect3D11DeviceFromDXGIDevice(device.NativePointer, out var pUnknown);

            if (hr != 0)
            {
                StopCapture();
                return;
            }

            var winrtDevice = (IDirect3DDevice)Marshal.GetObjectForIUnknown(pUnknown);

            Marshal.Release(pUnknown);

            _captureFramePool = Direct3D11CaptureFramePool.Create(winrtDevice, DirectXPixelFormat.B8G8R8A8UIntNormalized, 2, _captureItem.Size);
            _captureSession   = _captureFramePool.CreateCaptureSession(_captureItem);
            _captureSession.StartCapture();
            IsCapturing = true;
        }
예제 #2
0
        private void CreateCaptureItemDependendStuff()
        {
            _framePool = Direct3D11CaptureFramePool.Create(_device, PixelFormat, 2, _item.Size);
            _framePool.FrameArrived += OnFrameArrived;
            _session = _framePool.CreateCaptureSession(_item);
            _session.IsCursorCaptureEnabled = !PresentationToNDIAddIn.Properties.Settings.Default.HideMouse;

            var description = new SwapChainDescription1
            {
                Width             = _item.Size.Width,
                Height            = _item.Size.Height,
                Format            = SharpDxFormat,
                Stereo            = false,
                SampleDescription = new SampleDescription {
                    Count = 1, Quality = 0
                },
                Usage       = Usage.RenderTargetOutput,
                BufferCount = 2,
                Scaling     = Scaling.Stretch,
                SwapEffect  = SwapEffect.FlipSequential,
                AlphaMode   = AlphaMode.Premultiplied,
                Flags       = SwapChainFlags.None
            };

            _swapChain = new SwapChain1(_factory, _d3dDevice, ref description);
            _session.StartCapture();
        }
예제 #3
0
        public void UpdateResolution(SizeInt32 size)
        {
            if (size.Height <= 0 || size.Width <= 0)
            {
                return;
            }

            if (_framePool is not null && _session is not null)
            {
                // Unsubscribe from old framePool
                _framePool.FrameArrived -= OnFrameArrived;

                // Dispose old session and framePool
                _session.Dispose();
                _framePool.Dispose();
            }

            _canvasDevice = CanvasDevice.GetSharedDevice();

            // Create a frame pool with room for only 1 frame because we're getting a single frame, not a video.
            _framePool =
                Direct3D11CaptureFramePool.Create(_canvasDevice, DirectXPixelFormat.B8G8R8A8UIntNormalized, 1, size);

            _session = _framePool.CreateCaptureSession(GraphicsCaptureItem.CreateFromVisual(_capturedVisual));

            _framePool.FrameArrived += OnFrameArrived;

            _session.StartCapture();
        }
예제 #4
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)
                {
                    newSize   = true;
                    _lastSize = frame.ContentSize;
                    _swapChain.Resize(
                        DirectXPixelFormat.B8G8R8A8UIntNormalized,
                        2,
                        _lastSize);
                }

                using (var backBuffer = _swapChain.GetBuffer(0))
                    using (var lockSession = _multithread.Lock())
                    {
                        _deviceContext.CopyResource(backBuffer, frame.Surface);
                    }
            }

            _swapChain.Present();

            if (newSize)
            {
                _framePool.Recreate(
                    _device,
                    DirectXPixelFormat.B8G8R8A8UIntNormalized,
                    2,
                    _lastSize);
            }
        }
예제 #5
0
        public void SetGraphicItem(GraphicsCaptureItem item)
        {
            this.ResetState();
            this.item = item;

            if (this.item != null)
            {
                this.renderTargetDescription = new Texture2DDescription
                {
                    CpuAccessFlags    = CpuAccessFlags.None,
                    Width             = item.Size.Width,
                    Height            = item.Size.Height,
                    Usage             = ResourceUsage.Default,
                    Format            = SharpDX.DXGI.Format.B8G8R8A8_UNorm,
                    ArraySize         = 1,
                    BindFlags         = BindFlags.RenderTarget | BindFlags.ShaderResource,
                    OptionFlags       = ResourceOptionFlags.Shared,
                    MipLevels         = 1,
                    SampleDescription = new SampleDescription(1, 0),
                };
                this.renderTarget = new Texture2D(d3dDevice, this.renderTargetDescription);

                framePool = Direct3D11CaptureFramePool.Create(device, DirectXPixelFormat.B8G8R8A8UIntNormalized, 2, this.item.Size);
                session   = framePool.CreateCaptureSession(this.item);
                lastSize  = this.item.Size;

                framePool.FrameArrived += this.OnFrameArrived;
                session.StartCapture();
            }
        }
예제 #6
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 our swap chain first, then blit the pixels.
                    // After we do that, retire the frame and then recreate our frame pool.
                    newSize   = true;
                    _lastSize = frame.ContentSize;
                    _swapChain.ResizeBuffers(_lastSize.Width, _lastSize.Height);
                }

                using (var bitmap = CanvasBitmap.CreateFromDirect3D11Surface(_device, frame.Surface))
                    using (var drawingSession = _swapChain.CreateDrawingSession(Colors.Transparent))
                    {
                        drawingSession.DrawImage(bitmap);
                    }
            } // retire the frame

            _swapChain.Present();

            if (newSize)
            {
                _framePool.Recreate(
                    _device,
                    DirectXPixelFormat.B8G8R8A8UIntNormalized,
                    2,
                    _lastSize);
            }
        }
예제 #7
0
        public void StartCaptureInternal(GraphicsCaptureItem item)
        {
            StopCapture();
            _item      = item;
            _lastSize  = _item.Size;
            _swapChain = new CanvasSwapChain(_canvasDevice, _item.Size.Width, _item.Size.Height, 96);

            swapChain.SwapChain = _swapChain;

            _framePool = Direct3D11CaptureFramePool.Create(
                _canvasDevice,                             // D3D device
                DirectXPixelFormat.B8G8R8A8UIntNormalized, // Pixel format
                60,                                        // Number of frames
                _item.Size);                               // Size of the buffers
            _session = _framePool.CreateCaptureSession(_item);
            _framePool.FrameArrived += (s, a) =>
            {
                using (var frame = _framePool.TryGetNextFrame())
                {
                    ProcessFrame(frame);
                }
            };
            _item.Closed += (s, a) =>
            {
                StopCapture();
            };
            _session.StartCapture();
        }
        private async Task StartCaptureInternal(GraphicsCaptureItem item)
        {
            // Stop the previous capture if we had one.
            StopCapture();

            _item     = item;
            _lastSize = _item.Size;

            _canvasDevice = new CanvasDevice();

            _framePool = Direct3D11CaptureFramePool.Create(
                _canvasDevice,                             // D3D device
                DirectXPixelFormat.B8G8R8A8UIntNormalized, // Pixel format
                2,                                         // Number of frames
                _item.Size);                               // Size of the buffers

            _item.Closed += (s, a) =>
            {
                StopCapture();
            };

            _session = _framePool.CreateCaptureSession(_item);
            _session.StartCapture();

            await Task.Delay(500);

            var frame = _framePool.TryGetNextFrame();

            await ProcessFrame(frame);

            StopCapture();
        }
        private async void OnFrameArrived(Direct3D11CaptureFramePool sender, object args)
        {
            _currentFrame = sender.TryGetNextFrame();


            BarcodeReader reader = new BarcodeReader();

            reader.AutoRotate              = true;
            reader.Options.TryHarder       = true;
            reader.Options.PureBarcode     = false;
            reader.Options.PossibleFormats = new List <BarcodeFormat>();
            reader.Options.PossibleFormats.Add(BarcodeFormat.QR_CODE);

            var bitmap = await SoftwareBitmap.CreateCopyFromSurfaceAsync(_currentFrame.Surface).AsTask();

            var result = reader.Decode(bitmap);

            if (!string.IsNullOrEmpty(result?.Text) && (result.Text.StartsWith("suavekeys|expression") || result.Text.StartsWith("suavekeys|gesture")))
            {
                Debug.WriteLine("WOOHOO WE FOUND A CODE");
                if (!_isSending)
                {
                    _isSending = true;
                    var command = result.Text.Split('|')[2];
                    await _suaveKeysService.SendCommandAsync(command);

                    _isSending = false;
                }
            }
            _frameEvent.Set();
        }
예제 #10
0
 public void Stop()
 {
     _captureItem = null;
     _framePool.Dispose();
     _framePool = null;
     _session.Dispose();
     _session = null;
 }
예제 #11
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);
            }
        }
예제 #12
0
        private void OnFrameArrived(Direct3D11CaptureFramePool sender, object args)
        {
            using (var frame = sender.TryGetNextFrame())
            {
                var needsReset     = false;
                var recreateDevice = false;

                if ((frame.ContentSize.Width != _lastSize.Width) || (frame.ContentSize.Height != _lastSize.Height))
                {
                    needsReset = true;
                    _lastSize  = frame.ContentSize;
                }

                try
                {
                    using (var backBuffer = _swapChain.GetBackBuffer <Texture2D>(0))
                    {
                        using (var bitmap = Direct3D11Helper.CreateSharpDXTexture2D(frame.Surface))
                        {
                            // copy current surface to backbuffer
                            _d3dDevice.ImmediateContext.CopyResource(bitmap, backBuffer);

                            // Create buffer for the resized copy
                            var width  = StreamWidth;
                            var height = StreamHeight;

                            using (var copy = new Texture2D(_d3dDevice, new Texture2DDescription {
                                Width = width, Height = height, MipLevels = 1, ArraySize = 1, Format = bitmap.Description.Format,
                                Usage = ResourceUsage.Staging, SampleDescription = new SampleDescription(1, 0), BindFlags = BindFlags.None, CpuAccessFlags = CpuAccessFlags.Read, OptionFlags = ResourceOptionFlags.None
                            }))
                            {
                                // Copy region from captured bitmap to stream bitmap
                                _d3dDevice.ImmediateContext.CopySubresourceRegion(backBuffer, 0, ROI, copy, 0);

                                // access the copied data in a stream
                                _d3dDevice.ImmediateContext.MapSubresource(copy, 0, 0, MapMode.Read, SharpDX.Direct3D11.MapFlags.None, out DataStream stream);
                                _buf.Add(new BufferedFrame(stream, new SizeInt32 {
                                    Width = width, Height = height
                                }, bitmap.Description.Format));
                                _d3dDevice.ImmediateContext.UnmapSubresource(copy, 0);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    needsReset     = true;
                    recreateDevice = true;
                }

                if (needsReset)
                {
                    _swapChain.ResizeBuffers(_swapChain.Description1.BufferCount, _lastSize.Width, _lastSize.Height, _swapChain.Description1.Format, _swapChain.Description1.Flags);
                    ResetFramePool(_lastSize, recreateDevice);
                }
            }
        }
예제 #13
0
 public ModernCaptureMonitorSession(IDirect3DDevice device, ModernCaptureMonitorDescription description) : base(description)
 {
     this.CaptureItem = WinRTCaptureHelper.CreateItemForMonitor(description.MonitorInfo.Hmon);
     this.FramePool   = Direct3D11CaptureFramePool.Create(device,
                                                          description.HdrMetadata.EnableHdrProcessing ? DirectXPixelFormat.R16G16B16A16Float : DirectXPixelFormat.B8G8R8A8UIntNormalized,
                                                          2, CaptureItem.Size);
     this.Session = FramePool.CreateCaptureSession(CaptureItem);
     this.Session.IsCursorCaptureEnabled = description.CaptureCursor;
 }
        private void OnFrameArrived(Direct3D11CaptureFramePool sender, object args)
        {
            _frameCounter++;
            System.Diagnostics.Debug.WriteLine("Frame Arrived Here 2: " + _frameCounter);
            Direct3D11CaptureFrame frame = sender.TryGetNextFrame();

            DisplayFrame(frame);
            SetResult(frame);
        }
 public void StopCapture() // ...or release resources
 {
     _captureSession?.Dispose();
     _captureFramePool?.Dispose();
     _captureSession   = null;
     _captureFramePool = null;
     _captureItem      = null;
     IsCapturing       = false;
 }
예제 #16
0
        public ScreenGrabberWindowsCapture(MonitorInfo screen) : base(screen)
        {
            Application.Current.Dispatcher.Invoke(() =>
            {
                var device = WindowsCaptureHelper.CreateDirect3DDeviceFromSharpDXDevice(new SharpDX.Direct3D11.Device(DriverType.Hardware, DeviceCreationFlags.BgraSupport));
                _d3dDevice = WindowsCaptureHelper.CreateSharpDXDevice(device);
                var item   = WindowsCaptureHelper.CreateItemForMonitor(Screen.HMon);

                var factory = new Factory2();

                var description = new SwapChainDescription1
                {
                    Width             = item.Size.Width,
                    Height            = item.Size.Height,
                    Format            = Format.B8G8R8A8_UNorm,
                    Stereo            = false,
                    SampleDescription = new SampleDescription
                    {
                        Count   = 1,
                        Quality = 0
                    },
                    Usage       = Usage.RenderTargetOutput,
                    BufferCount = 2,
                    Scaling     = Scaling.Stretch,
                    SwapEffect  = SwapEffect.FlipSequential,
                    AlphaMode   = AlphaMode.Premultiplied,
                    Flags       = SwapChainFlags.None
                };

                _swapChain = new SwapChain1(factory, _d3dDevice, ref description);
                _framePool = Direct3D11CaptureFramePool.Create(device, DirectXPixelFormat.B8G8R8A8UIntNormalized, 2, item.Size);
                _session   = _framePool.CreateCaptureSession(item);
                _session.IsCursorCaptureEnabled = false;

                _swapChain.ResizeBuffers(2, item.Size.Width, item.Size.Height, Format.B8G8R8A8_UNorm, SwapChainFlags.None);

                _screenTexture = new Texture2D(_d3dDevice, new Texture2DDescription
                {
                    CpuAccessFlags    = CpuAccessFlags.Read,
                    BindFlags         = BindFlags.None,
                    Format            = Format.B8G8R8A8_UNorm,
                    Width             = item.Size.Width,
                    Height            = item.Size.Height,
                    OptionFlags       = ResourceOptionFlags.None,
                    MipLevels         = 1,
                    ArraySize         = 1,
                    SampleDescription = { Count = 1, Quality = 0 },
                    Usage             = ResourceUsage.Staging
                });

                _framePool.FrameArrived += OnFrameArrived;

                _session.StartCapture();
            });
        }
예제 #17
0
 public async Task Record(GraphicsCaptureItem _field)
 {
     canvasDevice = new CanvasDevice();
     field        = _field;
     framePool    = Direct3D11CaptureFramePool.Create(
         canvasDevice,            // D3D device
         DirectXPixelFormat.A8P8, // Pixel format
         2,                       // Number of frames
         field.Size);             // Size of the buffers
     session = framePool.CreateCaptureSession(field);
 }
예제 #18
0
 void OnFrameArrived(Direct3D11CaptureFramePool sender, object args)
 {
     if (Active)
     {
         using (var frame = sender.TryGetNextFrame())
         {
             CanvasBitmap bitmap = CanvasBitmap.CreateFromDirect3D11Surface(_canvasDevice !, frame.Surface);
             _ = ShowBitmapOnTargetAsync(bitmap);
         }
     }
 }
예제 #19
0
 private void OnFrameArrived(Direct3D11CaptureFramePool sender, object args)
 {
     using (var frame = sender.TryGetNextFrame())
         using (var bitmap = WindowsCaptureHelper.CreateSharpDXTexture2D(frame.Surface))
         {
             _d3dDevice.ImmediateContext.CopyResource(bitmap, _screenTexture);
             var mapSource = _d3dDevice.ImmediateContext.MapSubresource(_screenTexture, 0, MapMode.Read, MapFlags.None);
             CopyFromMapSource(mapSource);
             _d3dDevice.ImmediateContext.UnmapSubresource(_screenTexture, 0);
         }
 }
예제 #20
0
        public void Dispose()
        {
            _session?.Dispose();
            _framePool?.Dispose();
            _swapChain?.Dispose();

            _swapChain = null;
            _framePool = null;
            _session   = null;
            _item      = null;
        }
예제 #21
0
        public CaptureEngine(IDirect3DDevice device, GraphicsCaptureItem item)
        {
            _device    = device;
            _d3dDevice = Direct3D11Helper.CreateSharpDXDevice(_device);

            _framePool = Direct3D11CaptureFramePool.Create(
                _device, DirectXPixelFormat.B8G8R8A8UIntNormalized, 2, item.Size);
            _session  = _framePool.CreateCaptureSession(item);
            _lastSize = item.Size;

            _framePool.FrameArrived += OnFrameArrived;
        }
예제 #22
0
        private async void OnFrameArrived(Direct3D11CaptureFramePool sender, object args)
        {
            using (var frame = sender.TryGetNextFrame())
            {
                var sbmp = await CreateSoftwareBitmapFromSurface(frame.Surface);

                var frameFile =
                    await _outputFolder.CreateFileAsync("frame.jpg", CreationCollisionOption.GenerateUniqueName);

                SaveSoftwareBitmapToFile(sbmp, frameFile);
            }
        }
예제 #23
0
        //
        // Renders a the given <see cref="Visual"/> to a <see cref="CanvasBitmap"/>. If <paramref name="size"/> is not
        // specified, uses the size of <paramref name="visual"/>.
        //
        static async Task <CanvasBitmap> RenderVisualToBitmapAsync(Visual visual, SizeInt32?size = null)
        {
            // Get an object that enables capture from a visual.
            var graphicsItem = GraphicsCaptureItem.CreateFromVisual(visual);

            var canvasDevice = CanvasDevice.GetSharedDevice();

            var tcs = new TaskCompletionSource <CanvasBitmap>();

            // Create a frame pool with room for only 1 frame because we're getting a single frame, not a video.
            const int numberOfBuffers = 1;

            using (var framePool = Direct3D11CaptureFramePool.Create(
                       canvasDevice,
                       DirectXPixelFormat.B8G8R8A8UIntNormalized,
                       numberOfBuffers,
                       size ?? graphicsItem.Size))
            {
                void OnFrameArrived(Direct3D11CaptureFramePool sender, object args)
                {
                    using (var frame = sender.TryGetNextFrame())
                    {
                        tcs.SetResult(frame != null
                            ? CanvasBitmap.CreateFromDirect3D11Surface(canvasDevice, frame.Surface)
                            : null);
                    }
                }

                using (var session = framePool.CreateCaptureSession(graphicsItem))
                {
                    framePool.FrameArrived += OnFrameArrived;

                    // Start capturing. The FrameArrived event will occur shortly.
                    session.StartCapture();

                    // Wait for the frame to arrive.
                    var result = await tcs.Task;

                    // !!!!!!!! NOTE !!!!!!!!
                    // This thread is now running inside the OnFrameArrived callback method.

                    // Unsubscribe now that we have captured the frame.
                    framePool.FrameArrived -= OnFrameArrived;

                    // Yield to allow the OnFrameArrived callback to unwind so that it is safe to
                    // Dispose the session and framepool.
                    await Task.Yield();
                }
            }

            return(await tcs.Task);
        }
예제 #24
0
        private void OnFrameArrived(Direct3D11CaptureFramePool sender, object args)
        {
            using (var frame = sender.TryGetNextFrame())
            {
                using (var bitmap = CanvasBitmap.CreateFromDirect3D11Surface(_device, frame.Surface))
                    using (var drawingSession = _swapChain.CreateDrawingSession(Colors.Transparent))
                    {
                        drawingSession.DrawImage(bitmap);
                    }
            } // retire the frame

            _swapChain.Present();
        }
예제 #25
0
 private void InitializeCapture()
 {
     this.initializationThread = Thread.CurrentThread.ManagedThreadId;
     this.CurrentItem.Closed  += this.OnClosed;
     this.framePool            = Direct3D11CaptureFramePool.CreateFreeThreaded(
         this.device,
         DirectXPixelFormat.B8G8R8A8UIntNormalized,
         1,
         this.CurrentItem.Size);
     this.framePool.FrameArrived += this.OnFrameArrived;
     this.session = this.framePool.CreateCaptureSession(this.CurrentItem);
     this.session.StartCapture();
 }
예제 #26
0
 private void StartCapture(GraphicsCaptureItem item)
 {
     _framePool = Direct3D11CaptureFramePool.CreateFreeThreaded(
         _device,
         DirectXPixelFormat.B8G8R8A8UIntNormalized,
         2,
         item.Size);
     _session = _framePool.CreateCaptureSession(item);
     _framePool.FrameArrived += OnFrameArrived;
     _session.StartCapture();
     _item         = item;
     _item.Closed += OnCaptureItemClosed;
 }
예제 #27
0
        private async void StartCaptureInternal(GraphicsCaptureItem item)
        {
            // Stop the previous capture if we had one.
            StopCapture();

            var  scale  = DisplayInformation.GetForCurrentView().RawPixelsPerViewPixel;
            var  height = item.Size.Height - 32;
            bool result = Windows.UI.ViewManagement.ApplicationView.GetForCurrentView().TryResizeView(new Size {
                Width = item.Size.Width / scale, Height = height / scale
            });

            if (!result)
            {
                bool result_full = Windows.UI.ViewManagement.ApplicationView.GetForCurrentView().TryEnterFullScreenMode();
            }

            _item     = item;
            _lastSize = _item.Size;

            _framePool = Direct3D11CaptureFramePool.Create(
                _canvasDevice,                             // D3D device
                DirectXPixelFormat.B8G8R8A8UIntNormalized, // Pixel format
                2,                                         // Number of frames
                _item.Size);                               // Size of the buffers

            _framePool.FrameArrived += (s, a) =>
            {
                // The FrameArrived event is raised for every frame on the thread
                // that created the Direct3D11CaptureFramePool. This means we
                // don't have to do a null-check here, as we know we're the only
                // one dequeueing frames in our application.

                // NOTE: Disposing the frame retires it and returns
                // the buffer to the pool.

                using (var frame = _framePool.TryGetNextFrame())
                {
                    ProcessFrame(frame);
                }
            };

            _item.Closed += (s, a) =>
            {
                StopCapture();
            };

            _session = _framePool.CreateCaptureSession(_item);
            _session.StartCapture();
            await SaveRecordingAsync("a.mp4", 5000);
        }