问题标签 [desktop-duplication]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
167 浏览

windows - 桌面复制和 C++ AMP 不兼容?

我想在 GPU 上捕获和压缩屏幕。C++ AMP 和 DXGI 桌面复制各自单独工作,但似乎不能一起工作。

例子:

该项目运行良好,但在 DesktopDuplication.cpp 顶部附近添加最少的 C++ AMP 代码使其失败:

即使f()从未被调用,也会m_Factory->CreateSwapChainForHwnd(...)返回E_ACCESSDENIED. (注释的版本f()产生相同的结果。)

在我自己的项目中,当我尝试使用 C++ AMP 时IDXGIOutput1::DuplicateOutput()返回。DXGI_ERROR_UNSUPPORTED

这是怎么回事?


更新:在 NVIDIA 控制面板中,将“首选图形处理器”更改为“集成图形”有效。(但是,最好使用 NVIDIA 卡。)

0 投票
4 回答
2303 浏览

dxgi - 有没有办法从桌面复制中省略一个窗口?

我希望能够显示一个包含向用户显示但桌面复制未捕获的消息的窗口。那可能吗?

或者,有没有一种方法可以在向用户显示之前在桌面表面的顶部进行绘制?(理想情况下不会大量停止 GPU)

背景:我正在编写一个远程查看/支持应用程序,并希望允许远程用户在隐私中工作——在不干扰捕获的同时使用户的屏幕空白。

我想避免回到 WM_PRINT 和 BitBlt 的黑暗日子,但我不确定 DXGI 是否允许我想做的事情。

0 投票
3 回答
2502 浏览

c# - 在 Windows 10 中获取夜灯模式的状态

我正在使用桌面复制 api来抓取屏幕内容,事实证明,新的夜灯模式(德语中的“Nachtmodus”)并未应用于抓取的屏幕内容。

如何读取(如果可能直接在 C# 中)夜间模式状态(启用,颜色偏移量)?

或者

如何告诉 Windows 使用桌面复制 api 给我颜色偏移的图像?

基本上,我想知道这些红框中的配置状态:

夜灯设置(德语)


背景:我正在研究流光溢彩的实现,如果启用了夜灯模式,颜色偏移不会反映在我屏幕周围的 LED 中,因此屏幕内容和“屏幕周围”之间的颜色会关闭。

0 投票
3 回答
7925 浏览

c++ - DirectX 屏幕捕获 - 桌面复制 API - AcquireNextFrame 的有限帧速率

我正在尝试使用 Windows桌面复制 API来捕获屏幕并将原始输出保存到视频中。我正在使用具有非常高的超时值(999 毫秒)的AcquireNextFrame 。这样一来,我就应该从 windows 中获取每个新帧,不管怎样,它自然应该是 60fps。我最终得到一切看起来都不错的序列(第 6-11 帧),然后是看起来很糟糕的序列(第 12-14 帧)。如果我检查AccumulatedFrames

该值通常为 2 或更高。据我了解,这意味着 Windows 正在说“嘿,等等,我还没有给你的框架”,因为对 AcquireNextFrame 的调用需要很长时间。但是一旦windows最终给了我一个框架,它就会说“嘿,你实际上太慢了,最终错过了一个框架”。如果我能以某种方式得到这些帧,我想我会得到 60hz。

这可以通过日志进一步澄清:

第 6-11 帧看起来不错,采集间隔大约 17 毫秒。第 12 帧应在 (300+17=317ms) 获取。第 12 帧在 308 开始等待,但直到 336 毫秒才得到任何东西。在 (300+17+17~=336ms) 之后的帧之前,Windows 对我没有任何帮助。好吧,也许 windows 只是错过了一个帧,但是当我终于得到它时,我可以检查 AccumulatedFrames 并且它的值为 2(这意味着我错过了一个帧,因为我在调用 AcquireNextFrame 之前等待了太长时间)。据我了解,如果 AcquireNextFrame 立即返回,则 AccumulatedFrames 大于 1 才有意义。

此外,我可以在我的捕获软件运行时使用 PresentMon。日志显示每一帧的 MsBetweenDisplayChange,相当稳定在 16.666 毫秒(有几个异常值,但比我的捕获软件看到的要少得多)。

这些人(12)似乎已经能够获得 60fps,所以我想知道我做错了什么。

我的代码基于

**编辑 - 根据我的测量,您必须在帧实际出现约 10 毫秒之前调用 AcquireNextFrame(),否则 Windows 将无法获取它并让您获得下一个。每次我的录制程序需要超过 7 毫秒的时间来回绕(在获取第 i 帧之后直到在 i+1 上调用 AcquireNextFrame()),都会错过第 i+1 帧。

***编辑 -这是GPU视图的屏幕截图,显示了我在说什么。前 6 帧很快处理,然后第 7 帧需要 119 毫秒。“capture_to_argb.exe”旁边的长矩形对应于我被困在 AcquireNextFrame() 中。如果您查看硬件队列,您可以看到它以 60fps 清晰地呈现,即使我被困在 AcquireNextFrame() 中。至少这是我的解释(我不知道我在做什么)。

0 投票
1 回答
4497 浏览

visual-c++ - 桌面复制 (DirectX) 屏幕捕获无法提供屏幕更新

我正在开发一个应用程序,该应用程序将通过桌面复制 API(使用 DirectX 11)捕获屏幕(仅与上一个屏幕更新的差异)并将其呈现在另一个窗口上(查看器可能在通过 LAN 连接的另一台机器上运行) . 该代码是MSDN 中提供的示例的改进版本。一切正常,除了设备没有提供任何屏幕更新,尽管中间有几次,在某些机器上大约有 10% 的时间发生这种情况(主要在 windows 8/8.1 机器上,很少在 windows 10 机器上)。我尝试了所有可能的方法来解决这个问题。减少了设备重置的次数,这为我提供了一些可靠的输出,但并不总是能 100% 正常工作。

设备有时无法提供初始屏幕(全屏)(在支持桌面复制的所有 Windows 操作系统上,这种情况发生率为 60%),我想出了一个解决方法,重试从设备,直到它提供一个但也导致了多个问题,设备甚至可能永远不会给出初始屏幕。

我已经投入了数周的时间来解决这个问题,但没有找到合适的解决方案,而且我知道没有讨论这类问题的论坛。任何帮助,将不胜感激。

下面是我的代码,用于获取与前一个屏幕差异、初始化设备、填充适配器和监视器。

请耐心等待很长的代码片段,在此先感谢。

要获取屏幕更新:

这是初始化设备的代码

最后得到当前帧和与前一帧的区别:

更新 :

每当设备挂起时,无法在 DUPLICATIONMANAGER 中获取下一帧(即在流式传输屏幕的过程中,例如:连续捕获视频并将其发送到另一端)

这是详细的错误信息:

Id3d11DuplicationManager::ProcessFailure - 错误:无法在 DUPLICATIONMANAGER 中获取下一帧,详细信息:已放弃键控互斥锁。

更新 2: 每当设备无法永远提供屏幕更新时,我都会收到错误代码,这里是一样的

Id3d11DuplicationManager::ProcessFailure - 错误:无法在 DUPLICATIONMANAGER 中获取重复输出,详细信息:访问被拒绝。

错误代码是 E_ACCESSDENIED。

我不明白为什么会出现此错误,因为我已经在 SYSTEM 模式下运行并且 SetThreadDesktop 已执行两次(一次在初始化期间,另一次在检测到故障后)

这是 MSDN 上错误的解释:如果应用程序没有访问当前桌面图像的权限,则为 E_ACCESSDENIED。例如,只有在 LOCAL_SYSTEM 运行的应用程序才能访问安全桌面。

还有什么会导致这种问题的吗?

0 投票
0 回答
1174 浏览

visual-c++ - 桌面复制屏幕捕获 - DuplicateOutput 返回 E_ACCESSDENIED 错误

我正在使用桌面复制 API (DirectX11) 捕获屏幕。DuplicateOutput API 返回访问被拒绝错误,这在登录屏幕上的 Windows 8.1 机器上也非常罕见(可能是 10% 的时间),尽管我的应用程序以 SYSTEM 级别权限运行并且 SetThreadDesktop 被正确调用。我曾经在遇到每个错误后都重置并调用 SetThreadDesktop,但即使在多次设备重置和初始化之后,应用程序也无法从错误中恢复。在多次重试或重新启动应用程序后,我不得不回退到基于 GDI(从 directx 切换到 GDI 后应用程序工作正常)的方法,但这个想法似乎很糟糕。

注意:我确实在 Windows 10/Windows 8 机器上遇到了同样的问题,但与特定的 Windows 8.1 机器相比并不常见。

是 E_ACCESSDENIED 错误的描述,它仅说明此错误的可能情况(没有系统级权限或未正确调用 SetThreadDesktop)。我尝试了所有可能的方法来找出问题,但不能。

任何帮助将不胜感激,在此先感谢。

下面是初始化设备的代码:

将桌面设置为当前线程的代码:

以下是处理错误码后返回的错误信息:

Id3d11DuplicationManager::ProcessFailure - 错误:无法在 DUPLICATIONMANAGER 中获取重复输出,详细信息:访问被拒绝。

0 投票
0 回答
756 浏览

c++ - 如何使用 api 以每秒 60 帧的速度捕获 Windows 屏幕?

我努力了

  1. GDI 方法需要 75 毫秒才能捕获 1920x1080 屏幕。

  2. DirectX 前端缓冲区方法需要 84 毫秒才能捕获 1920x1080 屏幕。

  3. 播放视频时非常快的桌面复制 API 每次捕获需要 9 毫秒,但当屏幕空闲/较少变化时,捕获时间增加到 300 毫秒或更多。

  4. 尝试了 windows 媒体编码器方法,但找不到 windows 媒体编码器 sdk。

有没有其他方法可以使用 60 fps 的能力做同样的事情?我最近知道像 Microsoft Expression 编码器这样的软件可以捕获 60 fps。我想知道正在使用哪个api!

任何方向将不胜感激。提前致谢。我正在使用 C++。关于微软表达的可能重复的答案吗?

0 投票
0 回答
430 浏览

windows - GDI 和 DirectX 都失败的 Windows 屏幕捕获返回 ACCESS_DENIED

我分别使用基于操作系统的 DirectX 和 GDI 在 Windows 上捕获屏幕(DirectX(桌面复制) - 适用于 Win8 及以上和 GDI 适用于 Win7 及以下或作为 DirectX 方法出现任何错误的后备)。

很少在某些机器上,我在 winlogon 屏幕上同时收到 GDI 和 DirectX 返回 ACCESS_DENIED 错误。

正在检测并正确设置桌面开关,并且应用程序正在以提升的用户权限运行,桌面设置期间没有错误。捕获屏幕的同一线程正在调用将当前桌面设置为当前线程的函数。该应用程序未在任何 RDP 会话上运行,例如此处此处提到的问题。

我做了很多分析和研究。我确实浏览了开源屏幕捕获应用程序的源代码,但没有发现任何有用的东西。我已经花了一周的时间在这个问题上没有任何进展。

这是设置当前桌面的代码

截屏的代码类似如下

我用当前监视器的名称调用 GetDC。这与使用 NULL 作为参数调用 GetDC 有关吗?但这看起来不像这个问题

任何帮助,将不胜感激。提前致谢。

0 投票
1 回答
6727 浏览

c++ - DXGI 桌面复制屏幕捕获速度

我正在使用桌面复制 API中的AcquireNextFrame来捕获屏幕。屏幕刷新率为120Hz。以 120FPS 运行游戏时,屏幕截图可以以 120FPS 的速度捕获帧。但是当游戏的帧率增加到 240FPS 时,屏幕截图实际上下降到了 70FPS 左右。我的猜测是额外的帧正在累积,这会增加开销,但我不确定。有没有办法避免这种性能下降?

0 投票
1 回答
523 浏览

visual-c++ - 桌面复制:旋转框架以支持纵向模式

我正在使用 d3d11(桌面复制)来捕获屏幕并在 Windows 8 及更高版本的操作系统上通过网络发送它们。问题是如果监视器设置为纵向模式并且无法正确渲染,帧会翻转/旋转。

经过分析,我知道我必须处理以下旋转模式,但我确实只获得了与此相关的有限资源,

在花了很多时间浏览资源之后,我在 webrtc 中遇到了一个使用 libyuv 旋转捕获的缓冲区的代码。

这是我从 Webrtc 获得的用于旋转捕获的图像缓冲区的代码:

参考:desktop_frame_rotation.cc

很好,但是 libYuv 没有 GPU 支持,使用 CPU 能力旋转屏幕会很慢。

我也得到了一个stackoverflow线程,讨论了通过directX本身的帧旋转,但这太不完整了。

如果有人可以帮助我解决这个问题,那将是非常可观的。