private void ProcessFrame(DesktopFrame frame) { // Get the desktop capture texture var mapSource = _device.ImmediateContext.MapSubresource(_desktopImageTexture, 0, MapMode.Read, MapFlags.None); FinalImage = new Bitmap(_outputDescription.DesktopBounds.Width, _outputDescription.DesktopBounds.Height, PixelFormat.Format32bppRgb); var boundsRect = new System.Drawing.Rectangle(0, 0, _outputDescription.DesktopBounds.Width, _outputDescription.DesktopBounds.Height); // Copy pixels from screen capture Texture to GDI bitmap var mapDest = FinalImage.LockBits(boundsRect, ImageLockMode.WriteOnly, FinalImage.PixelFormat); var sourcePtr = mapSource.DataPointer; var destPtr = mapDest.Scan0; for (int y = 0; y < _outputDescription.DesktopBounds.Height; y++) { // Copy a single line Utilities.CopyMemory(destPtr, sourcePtr, _outputDescription.DesktopBounds.Width * 4); // Advance pointers sourcePtr = IntPtr.Add(sourcePtr, mapSource.RowPitch); destPtr = IntPtr.Add(destPtr, mapDest.Stride); } // Release source and dest locks FinalImage.UnlockBits(mapDest); _device.ImmediateContext.UnmapSubresource(_desktopImageTexture, 0); frame.DesktopImage = FinalImage; }
private void RetrieveFrameMetadata(DesktopFrame frame) { if (_frameInfo.TotalMetadataBufferSize > 0) { // Get moved regions int movedRegionsLength; OutputDuplicateMoveRectangle[] movedRectangles = new OutputDuplicateMoveRectangle[_frameInfo.TotalMetadataBufferSize]; _outputDuplication.GetFrameMoveRects(movedRectangles.Length, movedRectangles, out movedRegionsLength); frame.MovedRegions = new MovedRegion[movedRegionsLength / Marshal.SizeOf(typeof(OutputDuplicateMoveRectangle))]; for (int i = 0; i < frame.MovedRegions.Length; i++) { frame.MovedRegions[i] = new MovedRegion() { Source = new System.Drawing.Point(movedRectangles[i].SourcePoint.X, movedRectangles[i].SourcePoint.Y), Destination = new System.Drawing.Rectangle(movedRectangles[i].DestinationRect.X, movedRectangles[i].DestinationRect.Y, movedRectangles[i].DestinationRect.Width, movedRectangles[i].DestinationRect.Height) }; } // Get dirty regions int dirtyRegionsLength; Rectangle[] dirtyRectangles = new Rectangle[_frameInfo.TotalMetadataBufferSize]; _outputDuplication.GetFrameDirtyRects(dirtyRectangles.Length, dirtyRectangles, out dirtyRegionsLength); frame.UpdatedRegions = new System.Drawing.Rectangle[dirtyRegionsLength / Marshal.SizeOf(typeof(Rectangle))]; for (int i = 0; i < frame.UpdatedRegions.Length; i++) { frame.UpdatedRegions[i] = new System.Drawing.Rectangle(dirtyRectangles[i].X, dirtyRectangles[i].Y, dirtyRectangles[i].Width, dirtyRectangles[i].Height); } } else { frame.MovedRegions = new MovedRegion[0]; frame.UpdatedRegions = new System.Drawing.Rectangle[0]; } }
/// <summary> /// Retrieves the latest desktop image and associated metadata. /// </summary> public DesktopFrame GetLatestFrame() { var frame = new DesktopFrame(); // Try to get the latest frame; this may timeout bool succeeded = RetrieveFrame(); if (!succeeded) { return(null); } try { RetrieveFrameMetadata(frame); RetrieveCursorMetadata(frame); ProcessFrame(frame); } finally { try { ReleaseFrame(); } catch { //ignored } } return(frame); }
private void RetrieveCursorMetadata(DesktopFrame frame) { //var pointerInfo = new PointerInfo(); //// A non-zero mouse update timestamp indicates that there is a mouse position update and optionally a shape change //if (_frameInfo.LastMouseUpdateTime == 0) // return; //bool updatePosition = true; //// Make sure we don't update pointer position wrongly //// If pointer is invisible, make sure we did not get an update from another output that the last time that said pointer //// was visible, if so, don't set it to invisible or update. //if (!_frameInfo.PointerPosition.Visible && (pointerInfo.WhoUpdatedPositionLast != _mWhichOutputDevice)) // updatePosition = false; //// If two outputs both say they have a visible, only update if new update has newer timestamp //if (_frameInfo.PointerPosition.Visible && pointerInfo.Visible && (pointerInfo.WhoUpdatedPositionLast != _mWhichOutputDevice) && (pointerInfo.LastTimeStamp > _frameInfo.LastMouseUpdateTime)) // updatePosition = false; //// Update position //if (updatePosition) //{ // pointerInfo.Position = new SharpDX.Point(_frameInfo.PointerPosition.Position.X, _frameInfo.PointerPosition.Position.Y); // pointerInfo.WhoUpdatedPositionLast = _mWhichOutputDevice; // pointerInfo.LastTimeStamp = _frameInfo.LastMouseUpdateTime; // pointerInfo.Visible = _frameInfo.PointerPosition.Visible; //} //// No new shape //if (_frameInfo.PointerShapeBufferSize == 0) // return; //if (_frameInfo.PointerShapeBufferSize > pointerInfo.BufferSize) //{ // pointerInfo.PtrShapeBuffer = new byte[_frameInfo.PointerShapeBufferSize]; // pointerInfo.BufferSize = _frameInfo.PointerShapeBufferSize; //} //try //{ // unsafe // { // fixed (byte* ptrShapeBufferPtr = pointerInfo.PtrShapeBuffer) // { // _outputDuplication.GetFramePointerShape(_frameInfo.PointerShapeBufferSize, (IntPtr)ptrShapeBufferPtr, out pointerInfo.BufferSize, out pointerInfo.ShapeInfo); // } // } //} //catch (SharpDXException ex) //{ // if (ex.ResultCode.Failure) // { // throw new DesktopDuplicationException("Failed to get frame pointer shape."); // } //} }