问题描述
我目前尝试创建一个 PowerPoint 插件,在开始幻灯片放映后抓取演示窗口并将其发送到 NDI 目的地。
我取得了一些成功(NDI 显示了一些东西),但图片似乎是...可以说:与来源不同。 我想将它用于我们的“灵曦堂”项目。
非常感谢任何帮助! 这是当前的一段代码...:
using NewTek.NDI;
using SharpDX;
using SharpDX.Direct3D11;
using SharpDX.DXGI;
using System;
using System.Runtime.InteropServices;
using System.Threading;
namespace test
{
internal class DxCapturer : IDisposable
{
private IntPtr _hWnd;
private SharpDX.Direct3D11.Device _device;
private OutputDuplication _duplicatedOutput;
private bool _disposing;
private Sender _sender;
private Thread _captureThread;
[DllImport("user32.dll",SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetWindowRect(IntPtr hWnd,ref RECT lpRect);
[StructLayout(LayoutKind.Sequential)]
private struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
public DxCapturer(IntPtr hWnd)
{
_hWnd = hWnd;
_sender = new Sender("Powerpoint",true,false,null,"Powerpoint");
var numAdapter = 0;
var numOutput = 0;
var factory = new Factory1();
var adapter = factory.GetAdapter1(numAdapter);
_device = new SharpDX.Direct3D11.Device(adapter);
var output = adapter.GetOutput(numOutput);
var output1 = output.QueryInterface<Output1>();
_duplicatedOutput = output1.DuplicateOutput(_device);
_disposing = false;
_captureThread = new Thread(Capturer) { IsBackground = true,Priority = ThreadPriority.BelowNormal };
_captureThread.Start();
}
public void Dispose()
{
_disposing = true;
_captureThread.Join();
_device.Dispose();
_duplicatedOutput.Dispose();
_sender.Dispose();
}
private void Capturer()
{
while(!_disposing)
{
try
{
SharpDX.DXGI.Resource screenResource;
OutputDuplicateFrameInformation duplicateFrameInformation;
// Try to get duplicated frame within given time
_duplicatedOutput.AcquireNextFrame(10000,out duplicateFrameInformation,out screenResource);
RECT r = new RECT();
GetWindowRect(_hWnd,ref r);
var width = r.Right - r.Left;
var height = r.Bottom - r.Top;
if (width == 0 || height == 0)
continue;
using (var screenTexture = new Texture2D(_device,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
}))
{
// copy resource into memory that can be accessed by the CPU
using (var screenTexture2D = screenResource.QueryInterface<Texture2D>())
{
_device.ImmediateContext.CopySubresourceRegion(screenTexture2D,new ResourceRegion { Top = r.Top,Bottom = r.Bottom,Left = r.Left,Right = r.Right,Back = 1,Front = 0 },screenTexture,0);
}
// Get the desktop capture texture
var mapSource = _device.ImmediateContext.MapSubresource(screenTexture,MapMode.Read,SharpDX.Direct3D11.MapFlags.None);
using (var vf = new VideoFrame(width,height,width / height,30000,1001))
{
var sourcePtr = mapSource.DataPointer;
var destPtr = vf.BufferPtr;
Utilities.CopyMemory(destPtr,sourcePtr,width * 4 * height);
_sender.Send(vf);
}
_device.ImmediateContext.UnmapSubresource(screenTexture,0);
}
screenResource.Dispose();
_duplicatedOutput.ReleaseFrame();
}
catch { }
}
}
}
}
我使用“普通”GDI 功能完成了这项工作,但在配备至强 E3-1505M v5 的工作站上,这会将 CPU 负载推高至约 25% 的 FHD。
我希望使用 DirectX 时负载会低得多 - 但似乎很难抓取屏幕的一部分,尤其是在连接多个屏幕时...
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)