示例#1
0
        /// <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();
        }
示例#2
0
        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);
        }
        /// <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 */
                        }
                    }
                }
            }
        }
示例#4
0
        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);
        }
            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();
                    }
                }
            }
        IntPtr GetSharedHandle(SharpDX.Direct3D10.Texture2D Texture)
        {
            SharpDX.DXGI.Resource resource = Texture.QueryInterface <SharpDX.DXGI.Resource>();
            IntPtr result = resource.SharedHandle;

            resource.Dispose();
            return(result);
        }
示例#7
0
 public void DisposeSnapshot()
 {
     //systemBitmap.Dispose();
     //DeleteObject(hBitmap);
     screenResource.Dispose();
     duplicatedOutput.ReleaseFrame();
     device.ImmediateContext.UnmapSubresource(screenTexture, 0);
 }
示例#8
0
        public void ConstructRenderAndResource(double width, double height)
        {
            float dpiX, dpiY;

            this.GetDpi(out dpiX, out dpiY);
            D2D.RenderTargetProperties prop = new D2D.RenderTargetProperties(
                D2D.RenderTargetType.Default,
                new D2D.PixelFormat(DXGI.Format.B8G8R8A8_UNorm, D2D.AlphaMode.Premultiplied),
                dpiX,
                dpiY,
                D2D.RenderTargetUsage.None,
                D2D.FeatureLevel.Level_DEFAULT);

            D3D11.Texture2DDescription desc = new D3D11.Texture2DDescription();
            desc.Width             = (int)width;
            desc.Height            = (int)height;
            desc.MipLevels         = 1;
            desc.ArraySize         = 1;
            desc.Format            = DXGI.Format.B8G8R8A8_UNorm;
            desc.SampleDescription = new DXGI.SampleDescription(1, 0);
            desc.Usage             = D3D11.ResourceUsage.Default;
            desc.BindFlags         = D3D11.BindFlags.RenderTarget | D3D11.BindFlags.ShaderResource;
            desc.CpuAccessFlags    = D3D11.CpuAccessFlags.None;
            desc.OptionFlags       = D3D11.ResourceOptionFlags.Shared;
            this.d3d11Texture      = new D3D11.Texture2D(this.device, desc);

            this.surface = this.d3d11Texture.QueryInterface <DXGI.Surface>();

            DXGI.Resource resource = this.d3d11Texture.QueryInterface <DXGI.Resource>();
            IntPtr        handel   = resource.SharedHandle;

            D3D9.Texture texture = new D3D9.Texture(
                this.device9,
                this.d3d11Texture.Description.Width,
                this.d3d11Texture.Description.Height,
                1,
                D3D9.Usage.RenderTarget,
                D3D9.Format.A8R8G8B8,
                D3D9.Pool.Default,
                ref handel);
            this.surface9 = texture.GetSurfaceLevel(0);
            resource.Dispose();
            texture.Dispose();

            D2D.BitmapProperties bmpProp = new D2D.BitmapProperties();
            bmpProp.DpiX        = dpiX;
            bmpProp.DpiY        = dpiY;
            bmpProp.PixelFormat = new D2D.PixelFormat(DXGI.Format.B8G8R8A8_UNorm, D2D.AlphaMode.Premultiplied);
            this.bmpd2d         = new D2D.Bitmap(this.render, this.surface, bmpProp);
            this.cachedBitMap   = new D2D.Bitmap(this.render, new Size2((int)width, (int)height), bmpProp);
            this.hasCache       = false;

            this.render.Target = this.bmpd2d;

            this.renderSize = new Size(width, height);
        }
示例#9
0
        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 D3DImage_OnRender(IntPtr surface, bool isNewSurface)
        {
            if (isNewSurface)
            {
                Context.DestroyBuffers();

                // Yikes - from https://github.com/microsoft/WPFDXInterop/blob/master/samples/D3D11Image/D3D11Visualization/D3DVisualization.cpp#L384
                ComObject             res      = ComObject.FromPointer <ComObject>(surface);
                SharpDX.DXGI.Resource resource = res.QueryInterface <SharpDX.DXGI.Resource>();
                IntPtr sharedHandle            = resource.SharedHandle;
                resource.Dispose();
                SharpDX.Direct3D11.Resource d3dres = Context.Device.OpenSharedResource <SharpDX.Direct3D11.Resource>(sharedHandle);
                Context.UpdateSize(RenderWidth, RenderHeight, (int width, int height) => d3dres.QueryInterface <Texture2D>());
                d3dres.Dispose();
            }
            Context.UpdateScene(0.1f); // TODO: Measure elapsed time!
            Context.RenderScene();
            Render?.Invoke(this, new EventArgs());
            Context.ImmediateContext.Flush();
        }
示例#11
0
        public void Dispose()
        {
            if (pinnedMemBuffer.IsAllocated)
            {
                pinnedMemBuffer.Free();
            }

            TryReleaseFrame();
            if (Settings.SettingsHwnd != IntPtr.Zero)  // restore window background color
            {
                try {
                    device?.ImmediateContext.ClearRenderTargetView(renderTarget, SharpDX.Color.WhiteSmoke);
                    renderWindow?.Present(0, PresentFlags.None);
                } catch { }
            }

            Settings.Model.PropertyChanged -= LedsChanged;
            fpsCounter?.Dispose();
            fpsColor?.Dispose();
            fpsFont?.Dispose();
            renderOverlay?.Dispose();
            renderTarget?.Dispose();
            renderTexture?.Dispose();
            renderWindow?.Dispose();

            try {
                device?.ImmediateContext?.ClearState();
                device?.ImmediateContext?.Flush();
                device?.ImmediateContext?.Dispose();
            } catch { }

            adapter?.Dispose();
            output?.Dispose();
            device?.Dispose();
            duplicator?.Dispose();
            capture?.Dispose();
            scaler?.Dispose();
            gpuTexture?.Dispose();
            cpuTexture?.Dispose();
        }
示例#12
0
 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);
         }
     }
 }
示例#13
0
        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;
            //}
        }
            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);
            }
        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 { }
            }
        }
示例#16
0
    /* Код взят с:
     * 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);
    }
示例#17
0
        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);
            }
        }
        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();
                    }
                }
            }
        }
        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);
        }
示例#20
0
        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();
                    }
                }
            }
        }