I am building a screen recording app in C# using Windows Graphics Capture API. I am using this script. I can select monitor and can record it to mp4 file. I can also select a Window and record it too. But how can we record a region with this? Ideally I need to give x,y coordinates along with width and height to record that specific region.
Here are the functions which return GraphicsCaptureItem for Window or Monitor hwnd, which can be used to record.
public static GraphicsCaptureItem CreateItemForWindow(IntPtr hwnd)
{
var factory = WindowsRuntimeMarshal.GetActivationFactory(typeof(GraphicsCaptureItem));
var interop = (IGraphicsCaptureItemInterop)factory;
var temp = typeof(GraphicsCaptureItem);
var itemPointer = interop.CreateForWindow(hwnd, GraphicsCaptureItemGuid);
var item = Marshal.GetObjectForIUnknown(itemPointer) as GraphicsCaptureItem;
Marshal.Release(itemPointer);
return item;
}
public static GraphicsCaptureItem CreateItemForMonitor(IntPtr hmon)
{
var factory = WindowsRuntimeMarshal.GetActivationFactory(typeof(GraphicsCaptureItem));
var interop = (IGraphicsCaptureItemInterop)factory;
var temp = typeof(GraphicsCaptureItem);
var itemPointer = interop.CreateForMonitor(hmon, GraphicsCaptureItemGuid);
var item = Marshal.GetObjectForIUnknown(itemPointer) as GraphicsCaptureItem;
Marshal.Release(itemPointer);
return item;
}
And this is Recording function
private async void RecordScreen(GraphicsCaptureItem item)
{
_device = Direct3D11Helpers.CreateDevice();
// Get our encoder properties
uint frameRate = 30;
uint bitrate = 3 * 1000000;
var width = (uint)item.Size.Width;
var height = (uint)item.Size.Height;
// Kick off the encoding
try
{
newFile = GetTempFile();
using (var stream = new FileStream(newFile, FileMode.CreateNew).AsRandomAccessStream())
using (_encoder = new Encoder(_device, item))
{
await _encoder.EncodeAsync(
stream,
width, height, bitrate,
frameRate);
}
}
catch (Exception ex)
{}
}
I achieved this by passing a custom region to CopySubresourceRegion
in WaitForNewFrame
method.
public SurfaceWithInfo WaitForNewFrame()
{
.....
using (var multithreadLock = new MultithreadLock(_multithread))
using (var sourceTexture = Direct3D11Helpers.CreateSharpDXTexture2D(_currentFrame.Surface))
{
.....
using (var copyTexture = new SharpDX.Direct3D11.Texture2D(_d3dDevice, description))
{
.....
var region = new SharpDX.Direct3D11.ResourceRegion(
_region.Left,
_region.Top,
0,
_region.Left + _region.Width,
_region.Top + _region.Height,
1
);
_d3dDevice.ImmediateContext.CopyResource(_blankTexture, copyTexture);
_d3dDevice.ImmediateContext.CopySubresourceRegion(sourceTexture, 0, region, copyTexture, 0);
result.Surface = Direct3D11Helpers.CreateDirect3DSurfaceFromSharpDXTexture(copyTexture);
}
}
....
}