private void ProcessFrame(DesktopFrame frame) { // Get the desktop capture texture var mapSource = mDevice.ImmediateContext.MapSubresource(desktopImageTexture, 0, MapMode.Read, MapFlags.None); FinalImage = new System.Drawing.Bitmap(mOutputDesc.DesktopBounds.Right, mOutputDesc.DesktopBounds.Bottom, PixelFormat.Format32bppRgb); var boundsRect = new System.Drawing.Rectangle(0, 0, mOutputDesc.DesktopBounds.Right, mOutputDesc.DesktopBounds.Bottom); // 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 < mOutputDesc.DesktopBounds.Bottom; y++) { // Copy a single line Utilities.CopyMemory(destPtr, sourcePtr, mOutputDesc.DesktopBounds.Right * 4); // Advance pointers sourcePtr = IntPtr.Add(sourcePtr, mapSource.RowPitch); destPtr = IntPtr.Add(destPtr, mapDest.Stride); } // Release source and dest locks FinalImage.UnlockBits(mapDest); mDevice.ImmediateContext.UnmapSubresource(desktopImageTexture, 0); frame.DesktopImage = FinalImage; }
/// <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 retrievalTimedOut = RetrieveFrame(); if (retrievalTimedOut) { return(null); } try { //RetrieveFrameMetadata(frame); RetrieveCursorMetadata(frame); ProcessFrame(frame); } catch { ReleaseFrame(); } try { ReleaseFrame(); } catch { // throw new DesktopDuplicationException("Couldn't release frame."); } return(frame); }
/* * private void RetrieveFrameMetadata(DesktopFrame frame) * { * * if (frameInfo.TotalMetadataBufferSize > 0) * { * // Get moved regions * int movedRegionsLength = 0; * OutputDuplicateMoveRectangle[] movedRectangles = new OutputDuplicateMoveRectangle[frameInfo.TotalMetadataBufferSize]; * mDeskDupl.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(0, 0, movedRectangles[i].DestinationRect.Right, movedRectangles[i].DestinationRect.Bottom) * }; * } * * // Get dirty regions * int dirtyRegionsLength = 0; * Rectangle[] dirtyRectangles = new Rectangle[frameInfo.TotalMetadataBufferSize]; * mDeskDupl.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]; * } * }*/ 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 != this.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 != this.mWhichOutputDevice) && (pointerInfo.LastTimeStamp > frameInfo.LastMouseUpdateTime)) { updatePosition = false; } // Update position if (updatePosition) { pointerInfo.Position = new 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) { mDeskDupl.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."); } } //frame.CursorVisible = pointerInfo.Visible; frame.CursorLocation = new System.Drawing.Point(pointerInfo.Position.X, pointerInfo.Position.Y); }