/// <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 */ } } } } }
/// <summary> /// Creates a capture source with the same properties as this one /// </summary> /// <param name="bounds">Target screen bounds</param> /// <returns>A new <see cref="DxgiCaptureSource"/> instance</returns> internal static DxgiCaptureSource Recreate(Rectangle bounds) { DxgiCaptureSource source = null; using (var factory = new Factory1()) { if (factory.GetAdapterCount1() == 0) { throw new NotSupportedException("No suitable video adapters found"); } foreach (Adapter1 adapter in factory.Adapters1) { foreach (Output output in adapter.Outputs) { var intersection = Rectangle.Intersect(bounds, output.Description.DesktopBounds); if (intersection.Width > 0 && intersection.Height > 0) { source = new DxgiCaptureSource(adapter, output, new Rectangle(intersection.X, intersection.Y, intersection.Width, intersection.Height)); break; } output.Dispose(); } adapter.Dispose(); if (source != null) { break; } } } return(source ?? throw new Exception("No suitable capture sources were found")); }