首页 > 解决方案 > 整个 Windows 桌面的实时视频处理

问题描述

我想将动态视频效果添加到完整的 Windows 桌面。

我希望能够将屏幕变为灰色,斜切边缘并添加一些扫描线,使其看起来像旧的 CRT 屏幕,或者使屏幕出现故障,就像他们在不懂技术的电影中显示被黑系统的方式一样,等等

效果本身超出了这个问题的范围。这个问题是如何应用它们,即如何获得Windows 生成的桌面图像,应用我的效果,并将结果呈现在同一个显示器上。

我知道几种可能有效的方法。

  1. 挂钩到绘制内容的 WinAPI 调用。
  2. 创建一个假的辅助监视器,使其成为主要显示设备,从中获取视频流,应用我的效果,并呈现在真正的监视器上
  3. 创建应用效果的自定义显示驱动程序。

它们都有缺点:复杂性、驱动程序签名要求、复杂的设置。有什么更好的方法来实现我想要的吗?

标签: c#c++windows

解决方案


1 非常难,太多不同的 API。

2 困难的部分是制作一个假显示器。如果您改为购买名为“HDMI 虚拟插头”的 10 美元设备,它会变得相对简单,具有 100% 记录的 API。使用桌面复制 API 获取监视器 1 的纹理,应用您想要的任何效果并在监视器 2 上显示。如果您想要良好的性能,您最好完全在 GPU 上实现处理,例如使用自定义像素着色器渲染四边形。

3会工作,但很难做到。

还有另一种方式。实现和使用未记录的 API 很棘手,但根据我的经验,它非常可靠,至少在 Windows 7 上是如此。编写一个将自身注入 dwm.exe 的 DLL。这是一个 Windows 进程“桌面窗口管理器”,它包含桌面上可见的任何内容。DLL 注入后,创建一个新线程,在该线程中调用 D3D11CreateDeviceAndSwapChain,然后使用例如MinHook进行拦截Present,最好还ResizeBuffers使用IDXGISwapChain接口方法。如果成功,dwm.exe 将在每次呈现帧或桌面分辨率更改时从您的 DLL 调用函数。然后,在当前函数中,您可以做自己的事情,例如添加另一个渲染通道来实现您的效果,然后调用原始实现将结果实际呈现到桌面。

这在理论上很容易,但在实践中实施起来却相当棘手。例如,很难调试 dwm.exe,您将不得不依赖日志记录,或者可能使用带有远程调试器的虚拟机。这也不能跨 Windows 版本移植。另一个限制,它不适用于视频游戏等全屏应用程序,它们绕过 dwm.exe。对于电子游戏,仅适用于“无边框全屏窗口”游戏设置。

更新:另一种方法,更简单。创建具有每像素透明度的最顶层全屏窗口。操作系统支持它们数十年,设置WS_EX_LAYEREDWS_EX_TRANSPARENT扩展样式位。你不能做灰度,因为你只能覆盖你的东西,但不能读取下面的东西,但边缘、扫描线和毛刺是完全可行的。为获得最佳性能,请使用一些以 GPU 为中心的 API 来呈现该窗口,例如 C++ 中的 Direct2D 或 D3D。它也更容易调试,要么使用 2 个监视器,要么放置透明窗口,使其占据角落的一个矩形,为 IDE 留出足够的屏幕空间。这是一个例子(不是我的)。


推荐阅读