public BasicSampleApplication(Compositor c) { compositor = c; device = Direct3D11Helper.CreateDevice(false); // Setup the root. root = compositor.CreateContainerVisual(); root.RelativeSizeAdjustment = Vector2.One; // Setup the content. brush = compositor.CreateSurfaceBrush(); brush.HorizontalAlignmentRatio = 0.5f; brush.VerticalAlignmentRatio = 0.5f; brush.Stretch = CompositionStretch.Uniform; var shadow = compositor.CreateDropShadow(); shadow.Mask = brush; content = compositor.CreateSpriteVisual(); content.AnchorPoint = new Vector2(0.5f); content.RelativeOffsetAdjustment = new Vector3(0.5f, 0.5f, 0); content.RelativeSizeAdjustment = Vector2.One; content.Size = new Vector2(-80, -80); content.Brush = brush; content.Shadow = shadow; root.Children.InsertAtTop(content); }
public async Task <SoftwareBitmap> GetCaptureAsync() { var d2d = swapChain.GetBackBuffer <SharpDX.Direct3D11.Texture2D>(0); var frame = Direct3D11Helper.CreateDirect3DSurfaceFromSharpDXTexture(d2d); return(await SoftwareBitmap.CreateCopyFromSurfaceAsync(frame)); }
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(); } }
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); } }
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 }); } }
#pragma warning restore CS8618 // Non-nullable field is uninitialized. Consider declaring as nullable. #endregion #region Initialization private void InitializeDevices() { var createdDevice = Direct3D11Helper.CreateDevice(); device = createdDevice ?? throw new Exception("Failed to create Direct3D device."); var createdSharpDXDevice = Direct3D11Helper.CreateSharpDXDevice(device); sharpDXDevice = createdSharpDXDevice ?? throw new Exception("Failed to create SharpDX device."); multithread = sharpDXDevice.QueryInterface <Multithread>(); multithread.SetMultithreadProtected(true); }
public BasicCapture(IDirect3DDevice d, GraphicsCaptureItem i) { item = i; device = d; d3dDevice = Direct3D11Helper.CreateSharpDXDevice(device); wicFactory = new ImagingFactory(); // 建立DirectX图形基础设施工厂(DirectX Graphics Infrastructure,DXGI) var dxgiFactory = new SharpDX.DXGI.Factory2(); // 建立交换链 var description = new SharpDX.DXGI.SwapChainDescription1() { Width = item.Size.Width, Height = item.Size.Height, Format = SharpDX.DXGI.Format.B8G8R8A8_UNorm, Stereo = false, // 立体声 SampleDescription = new SharpDX.DXGI.SampleDescription() { Count = 1, Quality = 0 }, Usage = SharpDX.DXGI.Usage.RenderTargetOutput, BufferCount = 2, Scaling = SharpDX.DXGI.Scaling.Stretch, SwapEffect = SharpDX.DXGI.SwapEffect.FlipSequential, // 连续翻转 AlphaMode = SharpDX.DXGI.AlphaMode.Premultiplied, // 预乘 Flags = SharpDX.DXGI.SwapChainFlags.None }; swapChain = new SharpDX.DXGI.SwapChain1(dxgiFactory, d3dDevice, ref description); framePool = Direct3D11CaptureFramePool.Create( device, Windows.Graphics.DirectX.DirectXPixelFormat.B8G8R8A8UIntNormalized, 2, i.Size); // 创建捕获会话 session = framePool.CreateCaptureSession(i); // 记录最后帧尺寸 lastSize = i.Size; // 帧已到达事件添加 framePool.FrameArrived += OnFrameArrived; }
public ScreenCapture(GraphicsCaptureItem i) { item = i; device = Direct3D11Helper.CreateDevice(); d3dDevice = Direct3D11Helper.CreateSharpDXDevice(device); SizeInt32 correctedSize = item.Size; correctedSize.Width = correctedSize.Width / 8 * 8; correctedSize.Height = correctedSize.Height / 8 * 8; var dxgiFactory = new Factory2(); var description = new SwapChainDescription1() { Width = correctedSize.Width, Height = correctedSize.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(dxgiFactory, d3dDevice, ref description); framePool = Direct3D11CaptureFramePool.Create( device, DirectXPixelFormat.B8G8R8A8UIntNormalized, 2, correctedSize); session = framePool.CreateCaptureSession(i); lastSize = correctedSize; framePool.FrameArrived += OnFrameArrived; }
/// <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); } }
public GraphicsItemD3DImage() { if (App.Current.MainWindow != null) { IntPtr window = new WindowInteropHelper(App.Current.MainWindow).Handle; var presentparams = new SharpDX.Direct3D9.PresentParameters { Windowed = true, SwapEffect = SharpDX.Direct3D9.SwapEffect.Discard, DeviceWindowHandle = window, PresentationInterval = PresentInterval.Immediate, }; const CreateFlags deviceFlags = CreateFlags.HardwareVertexProcessing | CreateFlags.Multithreaded | CreateFlags.FpuPreserve; this.direct3d = new Direct3DEx(); this.device = Direct3D11Helper.CreateDevice(); this.d3dDevice = Direct3D11Helper.CreateSharpDXDevice(this.device); this.d9device = new DeviceEx(this.direct3d, 0, DeviceType.Hardware, IntPtr.Zero, deviceFlags, presentparams); this.IsFrontBufferAvailableChanged += this.GraphicItemD3DImageIsFrontBufferAvailableChanged; } }
public BasicSampleApplication(Compositor c) { compositor = c; device = Direct3D11Helper.CreateDevice(); // Setup the root. containerVisual = compositor.CreateContainerVisual(); containerVisual.RelativeSizeAdjustment = Vector2.One; // Setup the content. brush = compositor.CreateSurfaceBrush(); brush.HorizontalAlignmentRatio = 0.1f; brush.VerticalAlignmentRatio = 0.1f; brush.Stretch = CompositionStretch.Uniform; spriteVisual = compositor.CreateSpriteVisual(); spriteVisual.AnchorPoint = new Vector2(0.1f); spriteVisual.RelativeOffsetAdjustment = new Vector3(0.1f, 0.1f, 0); spriteVisual.RelativeSizeAdjustment = Vector2.One; //spriteVisual.Size = new Vector2(-80, -80); spriteVisual.Brush = brush; containerVisual.Children.InsertAtTop(spriteVisual); }
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); } }
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); }
public BasicCapturer() { device = Direct3D11Helper.CreateDevice(); }
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(); }