full capture

This commit is contained in:
Boki 2026-02-13 18:13:38 -05:00
parent d71c1d97c5
commit 6ea373f2c3
10 changed files with 291 additions and 173 deletions

View file

@ -43,7 +43,7 @@ public sealed class DesktopDuplication : IScreenCapture
Log.Debug("DXGI Desktop Duplication created");
}
public unsafe Mat? CaptureRegion(Region region)
public unsafe ScreenFrame? CaptureFrame()
{
if (_duplication == null) return null;
@ -70,52 +70,36 @@ public sealed class DesktopDuplication : IScreenCapture
{
if (ex.ResultCode == Vortice.DXGI.ResultCode.AccessLost)
_needsRecreate = true;
// WaitTimeout is normal when screen hasn't changed
return null;
}
try
var srcTexture = resource!.QueryInterface<ID3D11Texture2D>();
var desc = srcTexture.Description;
var w = (int)desc.Width;
var h = (int)desc.Height;
EnsureStaging(w, h);
_context.CopySubresourceRegion(_staging!, 0, 0, 0, 0, srcTexture, 0);
var mapped = _context.Map(_staging!, 0, MapMode.Read);
var mat = Mat.FromPixelData(h, w, MatType.CV_8UC4, mapped.DataPointer, (int)mapped.RowPitch);
var duplication = _duplication!;
return new ScreenFrame(mat, () =>
{
using var srcTexture = resource!.QueryInterface<ID3D11Texture2D>();
EnsureStaging(region.Width, region.Height);
_context.Unmap(_staging!, 0);
srcTexture.Dispose();
resource.Dispose();
duplication.ReleaseFrame();
});
}
// Copy only the region we need from the desktop texture
_context.CopySubresourceRegion(
_staging!, 0, 0, 0, 0,
srcTexture, 0,
new Vortice.Mathematics.Box(region.X, region.Y, 0,
region.X + region.Width, region.Y + region.Height, 1));
var mapped = _context.Map(_staging!, 0, MapMode.Read);
try
{
var mat = new Mat(region.Height, region.Width, MatType.CV_8UC4);
var rowBytes = region.Width * 4;
for (var row = 0; row < region.Height; row++)
{
Buffer.MemoryCopy(
(void*)(mapped.DataPointer + row * mapped.RowPitch),
(void*)mat.Ptr(row),
rowBytes, rowBytes);
}
// BGRA → BGR
var bgr = new Mat();
Cv2.CvtColor(mat, bgr, ColorConversionCodes.BGRA2BGR);
mat.Dispose();
return bgr;
}
finally
{
_context.Unmap(_staging!, 0);
}
}
finally
{
resource?.Dispose();
_duplication!.ReleaseFrame();
}
public unsafe Mat? CaptureRegion(Region region)
{
using var frame = CaptureFrame();
if (frame == null) return null;
return frame.CropBgr(region);
}
private void EnsureStaging(int w, int h)