/// <inheritdoc /> /// <summary> /// Acquires a single frame /// </summary> /// <inheritdoc /> /// <summary> /// Acquires a single frame from this provider /// </summary> public override void AcquireFrame() { for (int i = 0; i < this.sources.Length; i++) { DxgiCaptureSource source = this.sources[i]; try { OutputDuplicateFrameInformation info; Resource desktopResource = null; do { // release previous frame if last capture attempt failed if (desktopResource != null) { desktopResource.Dispose(); source.Duplication.ReleaseFrame(); } // try to capture a frame source.Duplication.AcquireNextFrame(DuplicationFrameTimeout, out info, out desktopResource); } while (info.TotalMetadataBufferSize == 0); this.lastPresentTime = info.LastPresentTime; using (var srcResource = desktopResource.QueryInterface <SharpDX.Direct3D11.Resource>()) using (var destResource = source.Texture.QueryInterface <SharpDX.Direct3D11.Resource>()) { // copy the entire screen region to the target texture source.Context.CopySubresourceRegion( srcResource, 0, source.Subregion, destResource, 0); } // release resources desktopResource.Dispose(); source.Duplication.ReleaseFrame(); } catch (SharpDXException exception) when(exception.ResultCode == ResultCode.AccessLost || exception.ResultCode == ResultCode.DeviceHung || exception.ResultCode == ResultCode.DeviceRemoved) { // device has been lost - we can't ignore this and should try to reinitialize the D3D11 device until it's // available again (...) // we'll be receiving black/unsynced frames beyond this point - it is OK until we restore the device while (true) { try { this.sources[i] = DxgiCaptureSource.Recreate(this.virtualRect); break; // successfully restored capture source } catch (SharpDXException) { /* could not restore the capture source - keep trying */ } } } } }
private void ProcessScreen(SharpDX.DXGI.Resource screenResource, int depth, int saturation) { try { using (var screenTexture2D = screenResource.QueryInterface <Texture2D>()) _wiring.Device.ImmediateContext.CopyResource(screenTexture2D, _wiring.Texture); var mapSource = _wiring.Device.ImmediateContext.MapSubresource(_wiring.Texture, 0, MapMode.Read, MapFlags.None); var sidePtr = mapSource.DataPointer; var tasks = new Task <int[, ]>[4] { ProcessHorizontal(mapSource.DataPointer, mapSource.RowPitch, depth, saturation), ProcessHorizontal(IntPtr.Add(mapSource.DataPointer, mapSource.RowPitch * (_wiring.Height - depth)), mapSource.RowPitch, depth, saturation), ProcessVertical(mapSource.DataPointer, mapSource.RowPitch, depth, saturation), ProcessVertical(IntPtr.Add(mapSource.DataPointer, _wiring.Width * 4 - depth * 4), mapSource.RowPitch, depth, saturation) }; Task.WaitAll(tasks); var messages = new List <RangeMessage>(); messages.AddRange(BuildHorizontalMessages(tasks[0].Result, Strip.Top)); messages.AddRange(BuildHorizontalMessages(tasks[1].Result, Strip.Bottom)); messages.AddRange(BuildVerticalMessages(tasks[2].Result, Strip.Left)); messages.AddRange(BuildVerticalMessages(tasks[3].Result, Strip.Right)); if (_running) { _packageHandler.SendRange(messages); } } finally { _wiring.Device.ImmediateContext.UnmapSubresource(_wiring.Texture, 0); } }
private bool CaptureFrameGPU() { //uncomment for double vsync //output.WaitForVerticalBlank(); output.WaitForVerticalBlank(); var result = duplicator.TryAcquireNextFrame(500, out _, out capture); using (capture) { if (result.Code == WaitTimeout) { return(false); } if (result.Failure) { result.CheckError(); //throw } using (var texture = capture.QueryInterface <Texture2D>()) device.ImmediateContext.CopySubresourceRegion(texture, 0, null, gpuTexture, 0); } TryReleaseFrame(); device.ImmediateContext.GenerateMips(scaler); device.ImmediateContext.CopySubresourceRegion(gpuTexture, gpuTexture.Description.MipLevels - 1, null, cpuTexture, 0); return(true); }
public bool Capture() { try { OutputDuplicateFrameInformation duplicateFrameInformation; duplicatedOutput.AcquireNextFrame(0, out duplicateFrameInformation, out screenResource); if (screenResource == null) { return(false); } using (Texture2D screenTexture2D = screenResource.QueryInterface <Texture2D>()) { device.ImmediateContext.CopyResource(screenTexture2D, screenTexture); } DataBox mapSource = device.ImmediateContext.MapSubresource(screenTexture, 0, MapMode.Read, SharpDX.Direct3D11.MapFlags.None); bitmapIntPtr = mapSource.DataPointer; return(true); } catch (SharpDXException e) { if (e.ResultCode.Code != SharpDX.DXGI.ResultCode.WaitTimeout.Result.Code) { Debug.WriteLine(e.Message); Debug.WriteLine(e.StackTrace); } return(false); } }
private bool RetrieveFrame() { if (desktopImageTexture == null) { desktopImageTexture = new Texture2D(mDevice, mTextureDesc); } SharpDX.DXGI.Resource desktopResource = null; frameInfo = new OutputDuplicateFrameInformation(); try { if (mDeskDupl == null) { return(true); } mDeskDupl.AcquireNextFrame(-1, out frameInfo, out desktopResource); } catch (SharpDXException ex) { if (ex.ResultCode.Code == SharpDX.DXGI.ResultCode.WaitTimeout.Result.Code) { return(true); } if (ex.ResultCode.Failure) { throw new DesktopDuplicationException("Failed to acquire next frame."); } } using (var tempTexture = desktopResource.QueryInterface <Texture2D>()) mDevice.ImmediateContext.CopyResource(tempTexture, desktopImageTexture); desktopResource.Dispose(); return(false); }
private bool RetrieveFrame() { if (_desktopImageTexture == null) { _desktopImageTexture = new Texture2D(_mDevice, _mTextureDesc); } Resource desktopResource = null; _frameInfo = new OutputDuplicateFrameInformation(); try { _mDeskDupl.AcquireNextFrame(500, out _frameInfo, out desktopResource); } catch (SharpDXException ex) { if (ex.ResultCode.Code == ResultCode.WaitTimeout.Result.Code) { return(true); } if (ex.ResultCode.Failure) { //return true; desktopResource?.Dispose(); throw new DesktopDuplicationException("Failed to acquire next frame."); } } using (var tempTexture = desktopResource?.QueryInterface <Texture2D>()) { _mDevice.ImmediateContext.CopyResource(tempTexture, _desktopImageTexture); } desktopResource?.Dispose(); return(false); }
/// <summary> /// Acquires a frame from the desktop duplication instance with the specified index /// </summary> /// <param name="index">Index of the desktop duplication instance</param> private void AcquireFrame(int index) { OutputDuplicateFrameInformation info; Resource desktopResource = null; OutputDuplication duplication = this.duplications[index]; do { // release previous frame if last capture attempt failed if (desktopResource != null) { desktopResource.Dispose(); duplication.ReleaseFrame(); } // try to capture a frame duplication.AcquireNextFrame(DuplicationFrameTimeout, out info, out desktopResource); } while (info.TotalMetadataBufferSize == 0); LastPresentTime = info.LastPresentTime; this.devices[index] .ImmediateContext.CopySubresourceRegion(desktopResource.QueryInterface <SharpDX.Direct3D11.Resource>(), 0, this.regions[index], StagingTextures[index], 0); // release resources desktopResource.Dispose(); duplication.ReleaseFrame(); }
internal bool Snap(BitmapData bitmap, int timeout) { ThrowIfDisposed(); SharpDX.DXGI.Resource screenResource = null; var acquiredFrame = false; try { try { OutputDuplicateFrameInformation dfi; _duplicatedOutput.AcquireNextFrame(timeout, out dfi, out screenResource); acquiredFrame = true; } catch (SharpDXException e) when(e.ResultCode.Code == SharpDX.DXGI.ResultCode.WaitTimeout.Result.Code) { return(false); } using (var queryInterface = screenResource.QueryInterface <SharpDX.Direct3D11.Resource>()) _device.ImmediateContext.CopyResource(queryInterface, _screenTexture); var databox = _device.ImmediateContext.MapSubresource(_screenTexture, 0, MapMode.Read, SharpDX.Direct3D11.MapFlags.None); Render(databox, bitmap); return(true); } finally { _device.ImmediateContext.UnmapSubresource(_screenTexture, 0); screenResource?.Dispose(); if (acquiredFrame) { _duplicatedOutput?.ReleaseFrame(); } } }
public (int x, int y) Capture() { while (true) { try { using (SharpDX.DXGI.Resource screenResource = BeginCapture(out var pointerPos)) { // copy resource into memory that can be accessed by the CPU using (var screenTexture2D = screenResource.QueryInterface <Texture2D>()) device.ImmediateContext.CopyResource(screenTexture2D, screenTexture); // Get the desktop capture texture var mapSource = device.ImmediateContext.MapSubresource(screenTexture, 0, MapMode.Read, MapFlags.None); // Copy pixels from screen capture Texture to GDI bitmap var sourcePtr = mapSource.DataPointer; // Save the output if (SaveScreenshot) { using (Bitmap bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb)) { var bmpData = bmp.LockBits(new System.Drawing.Rectangle(System.Drawing.Point.Empty, bmp.Size), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); unsafe { GPUColorBGRA *dst = (GPUColorBGRA *)bmpData.Scan0; GPUColorBGRA *src = (GPUColorBGRA *)sourcePtr; for (int i = 0; i < width * height; i++, dst++, src++) { *dst = *src; } } bmp.UnlockBits(bmpData); bmp.Save(OutputFileName); } } _gpu.CopyToDevice(sourcePtr, 0, rgbValues, 0, width * height); device.ImmediateContext.UnmapSubresource(screenTexture, 0); // Capture done duplicatedOutput.ReleaseFrame(); return(pointerPos.X, pointerPos.Y); }; } catch (SharpDXException e) { if (e.ResultCode.Code != SharpDX.DXGI.ResultCode.WaitTimeout.Result.Code) { throw e; } } } }
private void GetDirtyAndMoveRects(ref FrameData data, Resource screenResource, OutputDuplicateFrameInformation duplicateFrameInformation) { //copy resource into memory that can be accessed by the CPU using (var screenTexture2D = screenResource.QueryInterface <Texture2D>()) device.ImmediateContext.CopyResource(screenTexture2D, screenTexture); screenResource.Dispose(); int bufSize = duplicateFrameInformation.TotalMetadataBufferSize; if (bufSize <= 0) { return; } var moveRectangles = new OutputDuplicateMoveRectangle [ (int) Math.Ceiling((double)bufSize / Marshal.SizeOf(typeof(OutputDuplicateMoveRectangle))) ]; Console.WriteLine("Move : {0} {1} {2} {3}", moveRectangles.Length, bufSize, Marshal.SizeOf(typeof(OutputDuplicateMoveRectangle)), bufSize / Marshal.SizeOf(typeof(OutputDuplicateMoveRectangle))); //get move rects if (moveRectangles.Length > 0) { duplicatedOutput.GetFrameMoveRects(bufSize, moveRectangles, out bufSize); } data.MoveRectangles = moveRectangles; data.MoveCount = bufSize; bufSize = duplicateFrameInformation.TotalMetadataBufferSize - bufSize; var dirtyRectangles = new Rectangle[bufSize / Marshal.SizeOf(typeof(Rectangle))]; Console.WriteLine("Dirty : {0} {1} {2} {3}", dirtyRectangles.Length, bufSize, Marshal.SizeOf(typeof(Rectangle)), bufSize / Marshal.SizeOf(typeof(Rectangle))); //get dirty rects if (dirtyRectangles.Length > 0) { duplicatedOutput.GetFrameDirtyRects(bufSize, dirtyRectangles, out bufSize); } data.DirtyRectangles = dirtyRectangles; data.DirtyCount = bufSize; data.Frame = screenTexture; data.FrameInfo = duplicateFrameInformation; }
private void CaptureDX(Bitmap outputBMP) { // Try to get duplicated frame within given time is ms try { duplicatedOutput.AcquireNextFrame(5, out duplicateFrameInformation, out screenResource); // copy resource into memory that can be accessed by the CPU using (Texture2D screenTexture2D = screenResource.QueryInterface <Texture2D>()) { device.ImmediateContext.CopyResource(screenTexture2D, screenTexture); } // Get the desktop capture texture SharpDX.DataBox mapSource = device.ImmediateContext.MapSubresource(screenTexture, 0, MapMode.Read, SharpDX.Direct3D11.MapFlags.None); BitmapData mapDest = outputBMP.LockBits(screenBounds, ImageLockMode.WriteOnly, outputBMP.PixelFormat); IntPtr sourcePtr = mapSource.DataPointer; IntPtr destPtr = mapDest.Scan0; for (int y = 0; y < screenBounds.Height; y++) { // Copy a single line Utilities.CopyMemory(destPtr, sourcePtr, screenBounds.Width * 4); // Advance pointers sourcePtr = IntPtr.Add(sourcePtr, mapSource.RowPitch); destPtr = IntPtr.Add(destPtr, mapDest.Stride); } outputBMP.UnlockBits(mapDest); device.ImmediateContext.UnmapSubresource(screenTexture, 0); duplicatedOutput.ReleaseFrame(); } catch (SharpDXException e) { if (e.ResultCode.Code != SharpDX.DXGI.ResultCode.WaitTimeout.Result.Code) { Trace.TraceError(e.Message); Trace.TraceError(e.StackTrace); } } }
private void CaptureFrame(object sender, DoWorkEventArgs ea) { SharpDX.DXGI.Resource screenResource = null; try { OutputDuplicateFrameInformation duplicateFrameInformation; // Try to get duplicated frame within given time this.duplicatedOutput.AcquireNextFrame(1000, out duplicateFrameInformation, out screenResource); // copy resource into memory that can be accessed by the CPU using (Texture2D screenTexture2D = screenResource.QueryInterface <Texture2D>()) device.ImmediateContext.CopyResource(screenTexture2D, screenTexture); DataBox mapSource = device.ImmediateContext.MapSubresource(screenTexture, 0, MapMode.Read, SharpDX.Direct3D11.MapFlags.None); int size = RLocalUtils.GetSizeBGRA(DisplayWidth, DisplayHeight); Marshal.Copy(mapSource.DataPointer, FrameBytes, 0, size); duplicatedOutput.ReleaseFrame(); } catch (SharpDXException e) { if (e.ResultCode.Code != SharpDX.DXGI.ResultCode.WaitTimeout.Result.Code) { throw e; } } catch (Exception e) { throw e; } framesCapped++; }
private void RenderLoop() { while (!threadStop) { SharpDX.DXGI.Resource resource = screenCapture.AcquireFrame(); if (resource == null && OnScreenCaptured != null) { OnScreenCaptured(null, 0, 0, 0); continue; } Texture2D original = resource.QueryInterface <Texture2D>(); cDev.context.CopySubresourceRegion(original, 0, null, mipTexture, 0, 0, 0, 0); original.Dispose(); resource.Dispose(); screenCapture.ReleaseFrame(); cDev.context.GenerateMips(mipView); float scale = topPosition - bottomPosition; float offset = topPosition + bottomPosition - 1f; cDev.context.ClearRenderTargetView(intermediateView, Color4.Black); passThroughFilter.Apply(cDev.context, mipView, intermediateView, scale, offset); cDev.context.CopyResource(intermediateTexture, cpuTexture); cDev.context.ClearRenderTargetView(cDev.renderView, Color.Black); passThroughFilter.Apply(cDev.context, mipView, cDev.renderView, 1f, 0f); cDev.Present(); DataStream stream; DataBox dataBox = cDev.context.MapSubresource(cpuTexture, 0, MapMode.Read, SharpDX.Direct3D11.MapFlags.None, out stream); int count = dataBox.RowPitch / 16 * screenCaptureHeight; System.Numerics.Vector4[] pixels = stream.ReadRange <System.Numerics.Vector4>(count); stream.Dispose(); cDev.context.UnmapSubresource(cpuTexture, 0); if (OnScreenCaptured != null) { OnScreenCaptured(pixels, screenCaptureWidth, screenCaptureHeight, dataBox.RowPitch / 16); } } }
public System.Drawing.Bitmap Capture() { isInCapture = true; try { // init bool captureDone = false; bitmap = new System.Drawing.Bitmap(captureRect.Width, captureRect.Height, PixelFormat.Format32bppArgb); // the capture needs some time for (int i = 0; !captureDone; i++) { try { //capture duplicatedOutput.AcquireNextFrame(-1, out duplicateFrameInformation, out screenResource); // only for wait if (i > 0) { using (var screenTexture2D = screenResource.QueryInterface <Texture2D>()) device.ImmediateContext.CopyResource(screenTexture2D, screenTexture); mapSource = device.ImmediateContext.MapSubresource(screenTexture, 0, MapMode.Read, MapFlags.None); mapDest = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, captureRect.Width, captureRect.Height), ImageLockMode.WriteOnly, bitmap.PixelFormat); sourcePtr = mapSource.DataPointer; destPtr = mapDest.Scan0; // set x position offset to rect.x int rowPitch = mapSource.RowPitch - offsetX; // set pointer to y position sourcePtr = IntPtr.Add(sourcePtr, mapSource.RowPitch * captureRect.Y); for (int y = 0; y < captureRect.Height; y++) // needs to speed up!! { // set pointer to x position sourcePtr = IntPtr.Add(sourcePtr, offsetX); // copy pixel to bmp Utilities.CopyMemory(destPtr, sourcePtr, pWidth); // incement pointert to next line sourcePtr = IntPtr.Add(sourcePtr, rowPitch); destPtr = IntPtr.Add(destPtr, mapDest.Stride); } bitmap.UnlockBits(mapDest); device.ImmediateContext.UnmapSubresource(screenTexture, 0); captureDone = true; } screenResource.Dispose(); duplicatedOutput.ReleaseFrame(); } catch//(Exception ex) // catch (SharpDXException e) { //if (e.ResultCode.Code != SharpDX.DXGI.ResultCode.WaitTimeout.Result.Code) //{ // // throw e; //} return(new Bitmap(captureRect.Width, captureRect.Height, PixelFormat.Format32bppArgb)); } } } catch { return(new Bitmap(captureRect.Width, captureRect.Height, PixelFormat.Format32bppArgb)); } isInCapture = false; return(bitmap); }
void RenderLoop() { while (true) { lock (renderLock) { var deviceContext = device.ImmediateContext; // render user view deviceContext.ClearRenderTargetView(userViewRenderTargetView, Color4.Black); deviceContext.ClearDepthStencilView(userViewDepthStencilView, DepthStencilClearFlags.Depth, 1, 0); SharpDX.Vector3 headPosition = new SharpDX.Vector3(0f, 1.1f, -1.4f); // may need to change this default if (localHeadTrackingEnabled) { float distanceSquared = 0; lock (headCameraSpacePointLock) { headPosition = new SharpDX.Vector3(headCameraSpacePoint.X, headCameraSpacePoint.Y, headCameraSpacePoint.Z); float dx = handLeftCameraSpacePoint.X - handRightCameraSpacePoint.X; float dy = handLeftCameraSpacePoint.Y - handRightCameraSpacePoint.Y; float dz = handLeftCameraSpacePoint.Z - handRightCameraSpacePoint.Z; distanceSquared = dx * dx + dy * dy + dz * dz; } var transform = SharpDX.Matrix.RotationY((float)Math.PI) * SharpDX.Matrix.Translation(0, 0.45f, 0); headPosition = SharpDX.Vector3.TransformCoordinate(headPosition, transform); if (trackingValid && (distanceSquared < 0.02f) && (alpha > 1)) { alpha = 0; } //Console.WriteLine(distanceSquared); } var userView = GraphicsTransforms.LookAt(headPosition, headPosition + SharpDX.Vector3.UnitZ, SharpDX.Vector3.UnitY); userView.Transpose(); //Console.WriteLine("headPosition = " + headPosition); float aspect = (float)userViewTextureWidth / (float)userViewTextureHeight; var userProjection = GraphicsTransforms.PerspectiveFov(55.0f / 180.0f * (float)Math.PI, aspect, 0.001f, 1000.0f); userProjection.Transpose(); // smooth depth images foreach (var camera in ensemble.cameras) { var cameraDeviceResource = cameraDeviceResources[camera]; if (cameraDeviceResource.depthImageChanged) { fromUIntPS.Render(deviceContext, cameraDeviceResource.depthImageTextureRV, cameraDeviceResource.floatDepthImageRenderTargetView); for (int i = 0; i < 1; i++) { bilateralFilter.Render(deviceContext, cameraDeviceResource.floatDepthImageRV, cameraDeviceResource.floatDepthImageRenderTargetView2); bilateralFilter.Render(deviceContext, cameraDeviceResource.floatDepthImageRV2, cameraDeviceResource.floatDepthImageRenderTargetView); } cameraDeviceResource.depthImageChanged = false; } } // wobble effect if (wobbleEffectEnabled) { foreach (var camera in ensemble.cameras) { var cameraDeviceResource = cameraDeviceResources[camera]; var world = new SharpDX.Matrix(); for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { world[i, j] = (float)camera.pose[i, j]; } } world.Transpose(); // view and projection matrix are post-multiply var userWorldViewProjection = world * userView * userProjection; depthAndColorShader.SetConstants(deviceContext, camera.calibration, userWorldViewProjection); depthAndColorShader.Render(deviceContext, cameraDeviceResource.floatDepthImageRV, cameraDeviceResource.colorImageTextureRV, cameraDeviceResource.vertexBuffer, userViewRenderTargetView, userViewDepthStencilView, userViewViewport); } } // 3d object if (threeDObjectEnabled) { var world = SharpDX.Matrix.Scaling(1.0f) * SharpDX.Matrix.RotationY(90.0f / 180.0f * (float)Math.PI) * SharpDX.Matrix.RotationX(-40.0f / 180.0f * (float)Math.PI) * SharpDX.Matrix.Translation(0, 0.7f, 0.0f); var pointLight = new PointLight(); pointLight.position = new Vector3(0, 2, 0); pointLight.Ia = new Vector3(0.1f, 0.1f, 0.1f); meshShader.SetVertexShaderConstants(deviceContext, world, userView * userProjection, pointLight.position); meshShader.Render(deviceContext, meshDeviceResources, pointLight, userViewRenderTargetView, userViewDepthStencilView, userViewViewport); } // wobble effect if (wobbleEffectEnabled) { alpha += 0.05f; if (alpha > 1) { radialWobbleShader.SetConstants(deviceContext, 0); } else { radialWobbleShader.SetConstants(deviceContext, alpha); } radialWobbleShader.Render(deviceContext, userViewSRV, filteredUserViewRenderTargetView); } // desktop duplication if (desktopDuplicationEnabled) { // update the desktop texture; this will block until there is some change var outputDuplicateFrameInformation = default(OutputDuplicateFrameInformation); SharpDX.DXGI.Resource resource = null; outputDuplication.AcquireNextFrame(1000, out outputDuplicateFrameInformation, out resource); var texture = resource.QueryInterface <Texture2D>(); // pick up the window under the cursor var cursorPos = new POINT(); GetCursorPos(out cursorPos); var hwnd = WindowFromPoint(cursorPos); var rect = new RECT(); GetWindowRect(hwnd, out rect); // adjust bounds so falls within source texture if (rect.Left < 0) { rect.Left = 0; } if (rect.Top < 0) { rect.Top = 0; } if (rect.Right > texture.Description.Width - 1) { rect.Right = texture.Description.Width; } if (rect.Bottom > texture.Description.Height - 1) { rect.Bottom = texture.Description.Height; } int width = rect.Right - rect.Left; int height = rect.Bottom - rect.Top; // resize our texture if necessary if ((desktopTexture == null) || (desktopTexture.Description.Width != width) || (desktopTexture.Description.Height != height)) { if (desktopTexture != null) { desktopTextureSRV.Dispose(); desktopTexture.Dispose(); } var desktopTextureDesc = new Texture2DDescription() { Width = width, Height = height, MipLevels = 1, // revisit this; we may benefit from mipmapping? ArraySize = 1, Format = SharpDX.DXGI.Format.B8G8R8A8_UNorm, SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0), Usage = ResourceUsage.Default, BindFlags = BindFlags.ShaderResource, CpuAccessFlags = CpuAccessFlags.None, }; desktopTexture = new Texture2D(device, desktopTextureDesc); desktopTextureSRV = new ShaderResourceView(device, desktopTexture); } // copy the winodw region into our texture var sourceRegion = new ResourceRegion() { Left = rect.Left, Right = rect.Right, Top = rect.Top, Bottom = rect.Bottom, Front = 0, Back = 1, }; deviceContext.CopySubresourceRegion(texture, 0, sourceRegion, desktopTexture, 0); texture.Dispose(); } // render user view to seperate form passThroughShader.viewport = new Viewport(0, 0, userViewForm.videoPanel1.Width, userViewForm.videoPanel1.Height); // TODO: clean this up by simply using a pointer to the userViewSRV if (threeDObjectEnabled) { passThroughShader.Render(deviceContext, userViewSRV, userViewForm.renderTargetView); } if (wobbleEffectEnabled) { passThroughShader.Render(deviceContext, filteredUserViewSRV, userViewForm.renderTargetView); } if (desktopDuplicationEnabled) { passThroughShader.Render(deviceContext, desktopTextureSRV, userViewForm.renderTargetView); } userViewForm.swapChain.Present(0, PresentFlags.None); // projection puts x and y in [-1,1]; adjust to obtain texture coordinates [0,1] // TODO: put this in SetContants? userProjection[0, 0] /= 2; userProjection[1, 1] /= -2; // y points down userProjection[2, 0] += 0.5f; userProjection[2, 1] += 0.5f; // projection mapping for each projector foreach (var form in projectorForms) { deviceContext.ClearRenderTargetView(form.renderTargetView, Color4.Black); deviceContext.ClearDepthStencilView(form.depthStencilView, DepthStencilClearFlags.Depth, 1, 0); foreach (var camera in ensemble.cameras) { var cameraDeviceResource = cameraDeviceResources[camera]; var world = new SharpDX.Matrix(); for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { world[i, j] = (float)camera.pose[i, j]; } } world.Transpose(); var projectorWorldViewProjection = world * form.view * form.projection; var userWorldViewProjection = world * userView * userProjection; projectiveTexturingShader.SetConstants(deviceContext, userWorldViewProjection, projectorWorldViewProjection); // TODO: clean this up by simply using a pointer to the userViewSRV if (wobbleEffectEnabled) { projectiveTexturingShader.Render(deviceContext, cameraDeviceResource.floatDepthImageRV, filteredUserViewSRV, cameraDeviceResource.vertexBuffer, form.renderTargetView, form.depthStencilView, form.viewport); } if (threeDObjectEnabled) { projectiveTexturingShader.Render(deviceContext, cameraDeviceResource.floatDepthImageRV, userViewSRV, cameraDeviceResource.vertexBuffer, form.renderTargetView, form.depthStencilView, form.viewport); } if (desktopDuplicationEnabled) { projectiveTexturingShader.Render(deviceContext, cameraDeviceResource.floatDepthImageRV, desktopTextureSRV, cameraDeviceResource.vertexBuffer, form.renderTargetView, form.depthStencilView, form.viewport); } } form.swapChain.Present(1, PresentFlags.None); } if (desktopDuplicationEnabled) { outputDuplication.ReleaseFrame(); } //Console.WriteLine(stopwatch.ElapsedMilliseconds); stopwatch.Restart(); } } }
public FragmentedImage Capture() { if (duplicatedOutput == null && !ResetOutputDuplicator()) { return(null); } OutputDuplicateFrameInformation frameInfo; SharpDX.DXGI.Resource screenResource = null; bool success = false; try { int frameDisposeFailures = 0; while (true) { try { screenResource = null; duplicatedOutput.AcquireNextFrame(10000, out frameInfo, out screenResource); if (frameInfo.AccumulatedFrames > 0) { if (screenResource == null) { Logger.Debug("screenResource was null in DxgiOutputDuplicator"); return(null); } // Copy the texture so we can access the pixel data of the copy using (Texture2D screenTexture2D = screenResource.QueryInterface <Texture2D>()) device.ImmediateContext.CopyResource(screenTexture2D, screenTexture); // Learn which rectangles moved OutputDuplicateMoveRectangle[] moveRects = GetMoveRectangles(); // Learn which rectangles were made dirty RawRectangle[] dirtyRects = GetDirtyRectangles(); FragmentedImage img = new FragmentedImage(new MovedImageFragment[moveRects.Length], new DirtyImageFragment[dirtyRects.Length]); int i = 0; foreach (OutputDuplicateMoveRectangle moveRect in moveRects) { img.movedFragments[i++] = new MovedImageFragment( moveRect.DestinationRect.Top , moveRect.DestinationRect.Right , moveRect.DestinationRect.Bottom , moveRect.DestinationRect.Left , moveRect.SourcePoint.X , moveRect.SourcePoint.Y); } // Get the desktop capture pixel data i = 0; DataBox mapSource = device.ImmediateContext.MapSubresource(screenTexture, 0, MapMode.Read, MapFlags.None); foreach (RawRectangle dirtyRect in dirtyRects) { Screenshot screenshot = new Screenshot(dirtyRect.Right - dirtyRect.Left, dirtyRect.Bottom - dirtyRect.Top, 32); IntPtr source = mapSource.DataPointer; source += dirtyRect.Top * mapSource.RowPitch; // Offset source to the correct row source += dirtyRect.Left * 4; // Offset source to the correct column int destOffset = 0; for (int y = dirtyRect.Top; y < dirtyRect.Bottom; y++) { Marshal.Copy(source, screenshot.Buffer, destOffset, screenshot.Stride); source += mapSource.RowPitch; destOffset += screenshot.Stride; } img.dirtyFragments[i++] = new DirtyImageFragment( dirtyRect.Top , dirtyRect.Right , dirtyRect.Bottom , dirtyRect.Left , screenshot); } device.ImmediateContext.UnmapSubresource(screenTexture, 0); //DebugDrawRects(screenshot, moveRects, dirtyRects); success = true; return(img); } } catch (SharpDXException e) { if (e.ResultCode.Code != SharpDX.DXGI.ResultCode.WaitTimeout.Result.Code) { throw e; } } finally { if (screenResource != null) { try { screenResource.Dispose(); duplicatedOutput.ReleaseFrame(); } catch { if (++frameDisposeFailures > 2) { throw; } ResetOutputDuplicator(); } } } } } finally { if (!success) { DestroyOutputDuplicator(); } } // TODO: Delete cursor drawing stuff. //{ // IntPtr dc = _renderSurface.GetDC(new RawBool(true)); // NativeMethods.SelectObject(_hdc, dc); // NativeMethods.BitBlt(dc, 0, 0, bounds.Right - bounds.Left // , bounds.Bottom - bounds.Top, _hdc, bounds.Left // , bounds.Top, System.Drawing.CopyPixelOperation.SourceCopy); // NativeMethods.CURSORINFO pci; // pci.cbSize = NativeMethods.SizeOfCursorInfo; // if (NativeMethods.GetCursorInfo(out pci) && pci.flags > 0) // NativeMethods.DrawIcon(dc, pci.ptScreenPos.X, pci.ptScreenPos.Y, pci.hCursor); // _renderSurface.ReleaseDC(); // return null; //} }
private Bitmap GetDX11ScreenShot() { try { screenShot = null; screenShot = new Bitmap(WIDTH, HEIGHT, this.pixelFormat); if (dx11DuplicatedOutput != null) { dx11DuplicatedOutput.AcquireNextFrame(NEXT_FRAME_TIMEOUT, out dx11DuplFrameInfo, out dx11ScreenResource); dx11Device.ImmediateContext .CopyResource(dx11ScreenResource.QueryInterface <SharpDX.Direct3D11.Resource>(), dx11ScreenTexture); // cast from texture to surface, so we can access its bytes dx11ScreenSurface = dx11ScreenTexture.QueryInterface <SharpDX.DXGI.Surface>(); // map the resource to access it dx11Map = dx11ScreenSurface.Map(SharpDX.DXGI.MapFlags.Read); bmpData = screenShot.LockBits(boundsRect, ImageLockMode.WriteOnly, screenShot.PixelFormat); var sourcePtr = dx11Map.DataPointer; var destPtr = bmpData.Scan0; for (int y = 0; y < HEIGHT; y++) { // Copy a single line Utilities.CopyMemory(destPtr, sourcePtr, ARGB_WIDTH); // Advance pointers sourcePtr = IntPtr.Add(sourcePtr, dx11Map.Pitch); destPtr = IntPtr.Add(destPtr, bmpData.Stride); } dx11Device.ImmediateContext.UnmapSubresource(dx11ScreenTexture, 0); screenShot.UnlockBits(bmpData); dx11ScreenSurface.Unmap(); dx11ScreenSurface.Dispose(); dx11ScreenResource.Dispose(); dx11DuplicatedOutput.ReleaseFrame(); } else { return(screenShot = null); } dx11ScreenSurface = null; bmpData = null; GC.Collect(); return(screenShot); } catch (SharpDX.SharpDXException e) { if (e.ResultCode.Code == SharpDX.DXGI.ResultCode.WaitTimeout.Result.Code) { //screen does not changed LdpLog.Warning("DX11 surface timeout.. Recursion is coming:)"); return(GetDX11ScreenShot()); } else { return(screenShot = null); } } catch (Exception ex) { LdpLog.Error("GetDX11ScreenShot\n" + ex.Message); return(screenShot = null); } }
private byte[] ManagedCapture() { SharpDX.DXGI.Resource screenResource = null; OutputDuplicateFrameInformation duplicateFrameInformation; try { try { // Try to get duplicated frame within given time _duplicatedOutput.AcquireNextFrame(_frameCaptureTimeout, out duplicateFrameInformation, out screenResource); if (duplicateFrameInformation.LastPresentTime == 0 && _lastCapturedFrame != null) { return(_lastCapturedFrame); } } catch (SharpDXException ex) { if (ex.ResultCode.Code == SharpDX.DXGI.ResultCode.WaitTimeout.Code && _lastCapturedFrame != null) { return(_lastCapturedFrame); } if (ex.ResultCode.Code == SharpDX.DXGI.ResultCode.AccessLost.Code) { _desktopDuplicatorInvalid = true; } throw ex; } // Check if scaling is used if (CaptureWidth != _width) { // Copy resource into memory that can be accessed by the CPU using (var screenTexture2D = screenResource.QueryInterface <Texture2D>()) _device.ImmediateContext.CopySubresourceRegion(screenTexture2D, 0, null, _smallerTexture, 0); // Generates the mipmap of the screen _device.ImmediateContext.GenerateMips(_smallerTextureView); // Copy the mipmap of smallerTexture (size/ scalingFactor) to the staging texture: 1 for /2, 2 for /4...etc _device.ImmediateContext.CopySubresourceRegion(_smallerTexture, _scalingFactorLog2, null, _stagingTexture, 0); } else { // Copy resource into memory that can be accessed by the CPU using (var screenTexture2D = screenResource.QueryInterface <Texture2D>()) _device.ImmediateContext.CopyResource(screenTexture2D, _stagingTexture); } // Get the desktop capture texture var mapSource = _device.ImmediateContext.MapSubresource(_stagingTexture, 0, MapMode.Read, SharpDX.Direct3D11.MapFlags.None); _lastCapturedFrame = ToRGBArray(mapSource); return(_lastCapturedFrame); } finally { screenResource?.Dispose(); // Fixed OUT_OF_MEMORY issue on AMD Radeon cards. Ignoring all exceptions during unmapping. try { _device.ImmediateContext.UnmapSubresource(_stagingTexture, 0); } catch { }; // Ignore DXGI_ERROR_INVALID_CALL, DXGI_ERROR_ACCESS_LOST errors since capture is already complete try { _duplicatedOutput.ReleaseFrame(); } catch { } } }
public ErrorCode TryGetScreenTexture(out Texture2D texture, int timeout = 0) { texture = null; ErrorCode Result = ErrorCode.Unexpected; if (!deviceReady) { return(ErrorCode.NotReady); } try { SharpDX.DXGI.Resource desktopResource = null; try { var acquireResult = deskDupl.TryAcquireNextFrame(timeout, out OutputDuplicateFrameInformation frameInfo, out desktopResource); if (acquireResult.Failure) { if (acquireResult == SharpDX.DXGI.ResultCode.WaitTimeout) { return(ErrorCode.Ok); } else { logger.Debug("result.Code " + acquireResult.Code); acquireResult.CheckError(); } } if (duplTexture != null) { duplTexture.Dispose(); duplTexture = null; } duplTexture = desktopResource.QueryInterface <Texture2D>(); #region Update regions info //var frameParams = GetFrameParams(frameInfo); /* * var moveRects = frameParams.MoveRects; * foreach (OutputDuplicateMoveRectangle moveRect in moveRects) * { * //... * var srcPoint = moveRect.SourcePoint; * GDI.Point point = new GDI.Point(srcPoint.X, srcPoint.Y); * * var destRect = moveRect.DestinationRect; * int x = destRect.Left; * int y = destRect.Top; * int width = destRect.Right - destRect.Left; * int height = destRect.Bottom - destRect.Top; * GDI.Rectangle rect = new GDI.Rectangle(x, y, width, height); * * logger.Debug("srcPoint " + point.ToString() + " destRect " + rect.ToString()); * } * var dirtyRects = frameParams.DirtyRects; * foreach (RawRectangle dirtyRect in dirtyRects) * { * int x = dirtyRect.Left; * int y = dirtyRect.Top; * int width = dirtyRect.Right - dirtyRect.Left; * int height = dirtyRect.Bottom - dirtyRect.Top; * GDI.Rectangle rect = new GDI.Rectangle(x, y, width, height); * } */ #endregion UpdateMouseInfo(frameInfo); device.ImmediateContext.CopyResource(duplTexture, screenTexture); device.ImmediateContext.Flush(); if (cursorInfo != null && cursorInfo.Visible && CaptureMouse) { screenTarget.BeginDraw(); //screenTarget.Clear(Color.Green); DrawCursor(screenTarget, cursorInfo); screenTarget.EndDraw(); } texture = screenTexture; //texture = duplTexture; Result = 0; } finally { if (desktopResource != null) { deskDupl.ReleaseFrame(); desktopResource.Dispose(); desktopResource = null; } } } catch (SharpDXException ex) { if (ex.ResultCode == SharpDX.DXGI.ResultCode.WaitTimeout) { return(0); } else { if (ex.ResultCode == SharpDX.DXGI.ResultCode.AccessLost || ex.ResultCode == SharpDX.DXGI.ResultCode.AccessDenied || ex.ResultCode == SharpDX.DXGI.ResultCode.DeviceReset || ex.ResultCode == SharpDX.DXGI.ResultCode.DeviceRemoved || ex.HResult == (int)NativeAPIs.HResult.E_ACCESSDENIED) { logger.Warn(ex.Descriptor.ToString()); Result = ErrorCode.AccessDenied; } else { logger.Error(ex); Result = ErrorCode.Unexpected; } } } return(Result); }
void RenderLoop() { while (true) { lock (renderLock) { var deviceContext = device.ImmediateContext; // render user view deviceContext.ClearRenderTargetView(userViewRenderTargetView, Color4.Black); deviceContext.ClearDepthStencilView(userViewDepthStencilView, DepthStencilClearFlags.Depth, 1, 0); SharpDX.Vector3 headPosition = new SharpDX.Vector3(0f, 1.1f, -1.4f); // may need to change this default if (localHeadTrackingEnabled) { float distanceSquared = 0; lock (headCameraSpacePointLock) { headPosition = new SharpDX.Vector3(headCameraSpacePoint.X, headCameraSpacePoint.Y, headCameraSpacePoint.Z); float dx = handLeftCameraSpacePoint.X - handRightCameraSpacePoint.X; float dy = handLeftCameraSpacePoint.Y - handRightCameraSpacePoint.Y; float dz = handLeftCameraSpacePoint.Z - handRightCameraSpacePoint.Z; distanceSquared = dx * dx + dy * dy + dz * dz; } var transform = SharpDX.Matrix.RotationY((float)Math.PI) * SharpDX.Matrix.Translation(-0.25f, 0.45f, 0); headPosition = SharpDX.Vector3.TransformCoordinate(headPosition, transform); if (trackingValid && (distanceSquared < 0.02f) && (alpha > 1)) { alpha = 0; } //Console.WriteLine(distanceSquared); } var userView = GraphicsTransforms.LookAt(headPosition, headPosition + SharpDX.Vector3.UnitZ, SharpDX.Vector3.UnitY); userView.Transpose(); //Console.WriteLine("headPosition = " + headPosition); float aspect = (float)userViewTextureWidth / (float)userViewTextureHeight; var userProjection = GraphicsTransforms.PerspectiveFov(55.0f / 180.0f * (float)Math.PI, aspect, 0.001f, 1000.0f); userProjection.Transpose(); // smooth depth images foreach (var camera in ensemble.cameras) { var cameraDeviceResource = cameraDeviceResources[camera]; if (cameraDeviceResource.depthImageChanged) { fromUIntPS.Render(deviceContext, cameraDeviceResource.depthImageTextureRV, cameraDeviceResource.floatDepthImageRenderTargetView); for (int i = 0; i < 1; i++) { bilateralFilter.Render(deviceContext, cameraDeviceResource.floatDepthImageRV, cameraDeviceResource.floatDepthImageRenderTargetView2); bilateralFilter.Render(deviceContext, cameraDeviceResource.floatDepthImageRV2, cameraDeviceResource.floatDepthImageRenderTargetView); } cameraDeviceResource.depthImageChanged = false; } } // wobble effect if (wobbleEffectEnabled) { foreach (var camera in ensemble.cameras) { var cameraDeviceResource = cameraDeviceResources[camera]; var world = new SharpDX.Matrix(); for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { world[i, j] = (float)camera.pose[i, j]; } } world.Transpose(); // view and projection matrix are post-multiply var userWorldViewProjection = world * userView * userProjection; depthAndColorShader.SetConstants(deviceContext, camera.calibration, userWorldViewProjection); depthAndColorShader.Render(deviceContext, cameraDeviceResource.floatDepthImageRV, cameraDeviceResource.colorImageTextureRV, cameraDeviceResource.vertexBuffer, userViewRenderTargetView, userViewDepthStencilView, userViewViewport); } } // 3d object if (threeDObjectEnabled) { var world = SharpDX.Matrix.Scaling(1.0f) * SharpDX.Matrix.RotationY(90.0f / 180.0f * (float)Math.PI) * SharpDX.Matrix.RotationX(-40.0f / 180.0f * (float)Math.PI) * SharpDX.Matrix.Translation(0, 0.7f, 0.0f); var pointLight = new PointLight(); pointLight.position = new Vector3(0, 2, 0); pointLight.Ia = new Vector3(0.1f, 0.1f, 0.1f); meshShader.SetVertexShaderConstants(deviceContext, world, userView * userProjection, pointLight.position); meshShader.Render(deviceContext, meshDeviceResources, pointLight, userViewRenderTargetView, userViewDepthStencilView, userViewViewport); } // wobble effect if (wobbleEffectEnabled) { alpha += 0.05f; if (alpha > 1) { radialWobbleShader.SetConstants(deviceContext, 0); } else { radialWobbleShader.SetConstants(deviceContext, alpha); } radialWobbleShader.Render(deviceContext, userViewSRV, filteredUserViewRenderTargetView); } // desktop duplication if (desktopDuplicationEnabled) { var outputDuplicateFrameInformation = default(OutputDuplicateFrameInformation); SharpDX.DXGI.Resource resource = null; outputDuplication.AcquireNextFrame(1000, out outputDuplicateFrameInformation, out resource); var texture = resource.QueryInterface <Texture2D>(); var rect = new RECT(); GetWindowRect(windowPtr, out rect); var sourceRegion = new ResourceRegion() { Left = rect.Left + leftNudge, Right = rect.Right + rightNudge, Top = rect.Top + topNudge, Bottom = rect.Bottom + bottomNudge, Front = 0, Back = 1, }; deviceContext.CopySubresourceRegion(texture, 0, sourceRegion, desktopTexture, 0); texture.Dispose(); } // render user view to seperate form passThroughShader.viewport = new Viewport(0, 0, userViewForm.Width, userViewForm.Height); // TODO: clean this up by simply using a pointer to the userViewSRV if (threeDObjectEnabled) { passThroughShader.Render(deviceContext, userViewSRV, userViewForm.renderTargetView); } if (wobbleEffectEnabled) { passThroughShader.Render(deviceContext, filteredUserViewSRV, userViewForm.renderTargetView); } if (desktopDuplicationEnabled) { passThroughShader.Render(deviceContext, desktopTextureSRV, userViewForm.renderTargetView); } userViewForm.swapChain.Present(0, PresentFlags.None); // projection puts x and y in [-1,1]; adjust to obtain texture coordinates [0,1] // TODO: put this in SetContants? userProjection[0, 0] /= 2; userProjection[1, 1] /= -2; // y points down userProjection[2, 0] += 0.5f; userProjection[2, 1] += 0.5f; // projection mapping for each projector foreach (var form in projectorForms) { deviceContext.ClearRenderTargetView(form.renderTargetView, Color4.Black); deviceContext.ClearDepthStencilView(form.depthStencilView, DepthStencilClearFlags.Depth, 1, 0); foreach (var camera in ensemble.cameras) { var cameraDeviceResource = cameraDeviceResources[camera]; var world = new SharpDX.Matrix(); for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { world[i, j] = (float)camera.pose[i, j]; } } world.Transpose(); var projectorWorldViewProjection = world * form.view * form.projection; var userWorldViewProjection = world * userView * userProjection; projectiveTexturingShader.SetConstants(deviceContext, userWorldViewProjection, projectorWorldViewProjection); // TODO: clean this up by simply using a pointer to the userViewSRV if (wobbleEffectEnabled) { projectiveTexturingShader.Render(deviceContext, cameraDeviceResource.floatDepthImageRV, filteredUserViewSRV, cameraDeviceResource.vertexBuffer, form.renderTargetView, form.depthStencilView, form.viewport); } if (threeDObjectEnabled) { projectiveTexturingShader.Render(deviceContext, cameraDeviceResource.floatDepthImageRV, userViewSRV, cameraDeviceResource.vertexBuffer, form.renderTargetView, form.depthStencilView, form.viewport); } if (desktopDuplicationEnabled) { projectiveTexturingShader.Render(deviceContext, cameraDeviceResource.floatDepthImageRV, desktopTextureSRV, cameraDeviceResource.vertexBuffer, form.renderTargetView, form.depthStencilView, form.viewport); } } form.swapChain.Present(1, PresentFlags.None); } if (desktopDuplicationEnabled) { outputDuplication.ReleaseFrame(); } Console.WriteLine(stopwatch.ElapsedMilliseconds); stopwatch.Restart(); } } }
/*private void compress(object sender, DoWorkEventArgs ea) { * int numBytes = GetNumBytes(); * byte[] duplicate = (byte[])frameBytes.Clone(); * using (var compressIntoMs = new MemoryStream()) * { * using (var gzs = new BufferedStream(new GZipStream(compressIntoMs, CompressionMode.Compress), numBytes)) * { * gzs.Write(duplicate, 0, numBytes); * } * byte[] compressed = compressIntoMs.ToArray(); * Debug.WriteLine(frameBytes.Length); * Debug.WriteLine(compressed.Length); * } * }*/ //private void HandleCapturedFrame(object sender, RunWorkerCompletedEventArgs e) private void CaptureFrame(object sender, DoWorkEventArgs ea) //private void CaptureFrame(object state) { //CaptureFrameAsync(); //Stopwatch timer = new Stopwatch(); //timer.Start(); //System.Drawing.Bitmap bitmap = null; SharpDX.DXGI.Resource screenResource = null; //bool captureDone = false; //for (int i = 0; !captureDone; i++) //{ try { OutputDuplicateFrameInformation duplicateFrameInformation; // Try to get duplicated frame within given time this.duplicatedOutput.AcquireNextFrame(1000, out duplicateFrameInformation, out screenResource); //if (i > 0) //{ // copy resource into memory that can be accessed by the CPU using (Texture2D screenTexture2D = screenResource.QueryInterface <Texture2D>()) device.ImmediateContext.CopyResource(screenTexture2D, screenTexture); DataBox mapSource = device.ImmediateContext.MapSubresource(screenTexture, 0, MapMode.Read, SharpDX.Direct3D11.MapFlags.None); /*int loopCap = dWidth * dHeight; * unsafe * { * uint* destPtr2 = (uint*)mapDest2.Scan0; * //uint* sourcePtr2 = (uint*)sourcePtr; * for (int x = 0; x < loopCap; ++x) * { * destPtr2[x] = (destPtr2[x] & 0x000000ff) << 16 | (destPtr2[x] & 0x0000FF00) | (destPtr2[x] & 0x00FF0000) >> 16 | (destPtr2[x] & 0xFF000000); * //sourcePtr2[x] = (sourcePtr2[x] & 0x000000ff) << 16 | (sourcePtr2[x] & 0x0000FF00) | (sourcePtr2[x] & 0x00FF0000) >> 16 | (sourcePtr2[x] & 0xFF000000); * } * }*/ byte[] byteData = new byte[GetNumBytesDisplay()]; Marshal.Copy(mapSource.DataPointer, byteData, 0, GetNumBytesDisplay()); frameBytes = byteData; //captureDone = true; //} duplicatedOutput.ReleaseFrame(); } catch (SharpDXException e) { if (e.ResultCode.Code != SharpDX.DXGI.ResultCode.WaitTimeout.Result.Code) { throw e; } } catch (Exception e) { throw e; } //} //timer.Stop(); //Debug.WriteLine(timer.ElapsedMilliseconds); //if (!continueCapturing) return; //CaptureFrameAsync(); //frameBytes = byteData; //screenResource.Dispose(); //return bitmap; //ea.Result = bytedata; //ThreadPool.QueueUserWorkItem(DoTheWork, new object[] { dWidth, dHeight, 60, frameBytes, outBytesPtr }); //Stopwatch timer = new Stopwatch(); //timer.Start(); //DoWork(dWidth, dHeight, 60, frameBytes, outBytesPtr); //timer.Stop(); //System.Console.WriteLine("Elapsed: " + timer.ElapsedMilliseconds); framesCapped++; //EncodeFrameAsync(); }
/* Код взят с: * https://github.com/sharpdx/SharpDX-Samples/blob/master/Desktop/Direct3D11.1/ScreenCapture/Program.cs * https://github.com/fabsenet/adrilight/blob/master/adrilight/DesktopDuplication/DesktopDuplicator.cs метод ProcessFrame */ public Bitmap GetFrame() { SharpDX.DXGI.Resource desktopResource = null; var frameInfo = new OutputDuplicateFrameInformation(); // Try to get duplicated frame within given time try { outputDuplication.AcquireNextFrame(500, out frameInfo, out desktopResource); } catch (SharpDXException ex) { if (ex.ResultCode.Code == SharpDX.DXGI.ResultCode.WaitTimeout.Result.Code) { return(null); } MessageBox.Show("Невозможно обработать SharpDXException", "Ошибка"); return(null); } // copy resource into memory that can be accessed by the CPU using (var tempTexture = desktopResource.QueryInterface <Texture2D>()) { device.ImmediateContext.CopyResource(tempTexture, desktopImageTexture); } desktopResource.Dispose(); // Get the desktop capture texture var mapSource = device.ImmediateContext.MapSubresource(desktopImageTexture, 0, MapMode.Read, MapFlags.None); // Copy pixels from screen capture Texture to GDI bitmap BitmapData mapDest = image.LockBits(boundsRect, ImageLockMode.WriteOnly, image.PixelFormat); var sourcePtr = mapSource.DataPointer; var destPtr = mapDest.Scan0; if (mapSource.RowPitch == mapDest.Stride) { // Fast copy Utilities.CopyMemory(destPtr, sourcePtr, height * mapDest.Stride); } else { // Safe copy for (int y = 0; y < height; y++) { // Copy a single line Utilities.CopyMemory(destPtr, sourcePtr, width * 4); // Advance pointers sourcePtr = IntPtr.Add(sourcePtr, mapSource.RowPitch); destPtr = IntPtr.Add(destPtr, mapDest.Stride); } } // Release source and dest locks image.UnlockBits(mapDest); device.ImmediateContext.UnmapSubresource(desktopImageTexture, 0); desktopResource.Dispose(); outputDuplication.ReleaseFrame(); return(image); }
public override async Task Run() { await base.Run(); bool captureDone = false; while (!captureDone) { SharpDX.DXGI.Resource screenResource = null; OutputDuplicateFrameInformation duplicateFrameInformation; try { // Try to get duplicated frame within given time duplicatedOutput.AcquireNextFrame(targetCaptureTime, out duplicateFrameInformation, out screenResource); // copy resource into memory that can be accessed by the CPU using (var screenTexture2D = screenResource.QueryInterface <Texture2D>()) device.ImmediateContext.CopyResource(screenTexture2D, screenTexture); // Get the desktop capture texture var mapSource = device.ImmediateContext.MapSubresource(screenTexture, 0, MapMode.Read, MapFlags.None); var boundsRect = new Rectangle(0, 0, width / Zoom, height / Zoom); await Task.Run(() => { int nWidth = width / Zoom; int nHeight = height / Zoom; int middleX = (int)mousePos.X - nWidth / 2; int startX = Math.Max(Math.Min(middleX, width - nWidth - 1), 0); int middleY = (int)mousePos.Y - nHeight / 2; int startY = Math.Max(Math.Min(middleY, height - nHeight - 1), 0); try { // Create Drawing.Bitmap var bitmap = new Bitmap(nWidth, nHeight, PixelFormat.Format32bppArgb); // Copy pixels from screen capture Texture to GDI bitmap var mapDest = bitmap.LockBits(boundsRect, ImageLockMode.WriteOnly, bitmap.PixelFormat); var sourcePtr = mapSource.DataPointer; var destPtr = mapDest.Scan0; sourcePtr = IntPtr.Add(sourcePtr, mapSource.RowPitch *startY + startX * 4); for (int y = startY; y < nHeight + startY && y < height; y++) { // Copy a single line Utilities.CopyMemory(destPtr, sourcePtr, nWidth * 4); // Advance pointers sourcePtr = IntPtr.Add(sourcePtr, mapSource.RowPitch); destPtr = IntPtr.Add(destPtr, mapDest.Stride); } // Release source and dest locks bitmap.UnlockBits(mapDest); device.ImmediateContext.UnmapSubresource(screenTexture, 0); // Save the output Display = (Bitmap)bitmap.Clone(); // Capture done captureDone = true; } catch (Exception e) { targetCaptureTime++; } }); } catch (SharpDXException e) { if (e.ResultCode.Code != SharpDX.DXGI.ResultCode.WaitTimeout.Result.Code) { throw e; } else { targetCaptureTime++; } } finally { if (screenResource != null) { screenResource.Dispose(); screenResource = null; duplicatedOutput.ReleaseFrame(); } } } }
private static void CaptureMain(Int32 adapterIndex, Int32 displayIndex) { Resource screenResource = null; try { using (Factory1 factory1 = new Factory1()) { using (Adapter1 adapter1 = factory1.GetAdapter1(adapterIndex)) { using (Device device = new Device(adapter1)) { using (Output output = adapter1.GetOutput(displayIndex)) { using (Output1 output1 = output.QueryInterface <Output1>()) { Int32 width = output1.Description.DesktopBounds.Right - output1.Description.DesktopBounds.Left; Int32 height = output1.Description.DesktopBounds.Bottom - output1.Description.DesktopBounds.Top; Rectangle bounds = new Rectangle(Point.Empty, new Size(width, height)); Texture2DDescription texture2DDescription = new Texture2DDescription { CpuAccessFlags = CpuAccessFlags.Read, BindFlags = BindFlags.None, Format = Format.B8G8R8A8_UNorm, Width = width, Height = height, OptionFlags = ResourceOptionFlags.None, MipLevels = 1, ArraySize = 1, SampleDescription = { Count = 1, Quality = 0 }, Usage = ResourceUsage.Staging }; using (Texture2D texture2D = new Texture2D(device, texture2DDescription)) { using (OutputDuplication outputDuplication = output1.DuplicateOutput(device)) { status = Status.Active; Int32 frameNumber = 0; do { try { Result result = outputDuplication.TryAcquireNextFrame(100, out _, out screenResource); if (result.Success) { frameNumber += 1; using (Texture2D screenTexture2D = screenResource.QueryInterface <Texture2D>()) { device.ImmediateContext.CopyResource(screenTexture2D, texture2D); DataBox dataBox = device.ImmediateContext.MapSubresource(texture2D, 0, MapMode.Read, MapFlags.None); Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb); BitmapData bitmapData = bitmap.LockBits(bounds, ImageLockMode.WriteOnly, bitmap.PixelFormat); IntPtr dataBoxPointer = dataBox.DataPointer; IntPtr bitmapDataPointer = bitmapData.Scan0; for (Int32 y = 0; y < height; y++) { Utilities.CopyMemory(bitmapDataPointer, dataBoxPointer, width * 4); dataBoxPointer = IntPtr.Add(dataBoxPointer, dataBox.RowPitch); bitmapDataPointer = IntPtr.Add(bitmapDataPointer, bitmapData.Stride); } bitmap.UnlockBits(bitmapData); device.ImmediateContext.UnmapSubresource(texture2D, 0); while (SkipFrames && bitmapQueue.Count > 1) { bitmapQueue.TryDequeue(out Bitmap dequeuedBitmap); dequeuedBitmap.Dispose(); } if (frameNumber > 1 || SkipFirstFrame == false) { bitmapQueue.Enqueue(bitmap); waitHandle.Set(); } } } else { if (ResultDescriptor.Find(result).ApiCode != Result.WaitTimeout.ApiCode) { result.CheckError(); } } } finally { screenResource?.Dispose(); try { outputDuplication.ReleaseFrame(); } catch { } } } while (status == Status.Active); } } } } } } } } catch (Exception exception) { globalException = exception; status = Status.Stops; } finally { callbackThread.Join(); Exception exception = globalException; while (bitmapQueue.Count > 0) { bitmapQueue.TryDequeue(out Bitmap dequeuedBitmap); dequeuedBitmap.Dispose(); } globalException = null; waitHandle = null; bitmapQueue = null; captureThread = null; callbackThread = null; status = Status.Inactive; if (OnCaptureStop != null) { OnCaptureStop(null, new OnCaptureStopEventArgs(exception != null ? new Exception(exception.Message, exception) : null)); } else { if (exception != null) { ExceptionDispatchInfo.Capture(exception).Throw(); } } } }