简体   繁体   English

用 Windows Graphics Capture 记录一个区域 API

[英]Recording a region with Windows Graphics Capture API

I am building a screen recording app in C# using Windows Graphics Capture API. I am using this script .我正在使用Windows Graphics Capture API 在 C# 构建一个屏幕录制应用程序。我正在使用这个脚本 I can select monitor and can record it to mp4 file.我可以 select 监控并可以将其录制到 mp4 文件。 I can also select a Window and record it too.我也可以 select 和 Window 也记录下来。 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.理想情况下,我需要提供 x、y 坐标以及宽度和高度来记录该特定区域。

Here are the functions which return GraphicsCaptureItem for Window or Monitor hwnd , which can be used to record.以下是返回GraphicsCaptureItemWindow 或 Monitor hwnd的函数,可用于记录。

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这是录音 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.我通过在WaitForNewFrame方法中将自定义区域传递给CopySubresourceRegion来实现这一点。

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);
        }
    }
    ....
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM