问题标签 [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 回答
1143 浏览

c++ - AcquireNextFrame 不工作(桌面复制 API 和 D3D11)

我将这段代码放在一起,截取桌面的屏幕截图并将其映射为原始像素数据访问,但输出全为零。我不知道我做错了什么。在网上查看了许多 Desktop Duplication Api 示例后,我看不出它们与我的有任何区别。

这是我初始化所有内容的方法,并且不会引发任何错误。

我正在使用的 CHECKHR 宏已经过我的测试并且可以工作,只是为了澄清这不是问题。

这是我用来实际抓取框架的代码:

所发生的只是 2000000 个零被打印到控制台。有什么我遗漏或看不到的东西吗?

0 投票
0 回答
543 浏览

directx - 如何在桌面复制 API 中禁用光标指针

我正在使用此解决方案DXGI 桌面复制示例,它可以很好地捕获单个监视器,但是当我进行扩展监视器(下图:启用扩展监视器)时,鼠标光标嵌入了捕获的图像。此问题仅在扩展启用期间出现。

实际上AcquireNextFrameAPI 将返回图像缓冲区(DesktopResource)和 FrameInfo,DesktopResource 没有光标图像,我们使用 FrameInfo(光标坐标)以编程方式绘制光标,但在这里我禁用了绘制鼠标指针,但即使在图像上获取光标指针。

如何在扩展期间禁用图像上的光标。

在此处输入图像描述

0 投票
1 回答
1430 浏览

c++ - DesktopDuplication API 在某些应用程序处于全屏模式时产生黑框

我正在构建一个应用程序,用于通过网络在多个客户端之间实时获取和共享屏幕截图。

我正在使用MS Desktop Duplication API来获取图像数据,除了某些边缘情况外,它工作顺利。

我一直在使用四款游戏作为测试应用程序来测试屏幕截图在全屏时的表现,它们是风暴英雄、彩虹六号围攻、反恐精英和绝地求生。

在我自己的具有 GeForce GTX 1070 显卡的机器上;对于所有测试应用程序,在全屏和全屏外一切正常。然而,在另外两台运行 GeForce GTX 980 的机器上;除 PUBG 外的所有测试应用程序都有效。当 PUBG 全屏运行时,我的桌面复制会生成全黑图像,我无法弄清楚为什么 桌面复制示例适用于所有测试机器和测试应用程序。

我所做的与示例基本相同,只是我正在提取像素数据并从该数据中创建自己的 SDL(OpenGL) 纹理,而不是直接使用获取的 ID3D11Texture2D。

为什么 GTX 980 上的全屏 PUBG 是唯一失败的测试用例?

我获取帧的方式、处理“DXGI_ERROR_ACCESS_LOST”错误或我如何从 GPU 复制数据是否有问题?

声明:

初始化:

屏幕截图:

一些注意事项:

  • 我修改了我的原始代码以使其更具可读性,因此缺少一些清理和登录错误处理。
  • 在任何测试场景中都不会触发任何错误或超时情况(DXGI_ERROR_ACCESS_LOST 除外)。
  • 在任何测试场景中,“attemptCounter”都不会超过 2。
  • 测试用例是有限的,因为我无法访问产生黑色图像案例的计算机。
0 投票
1 回答
1239 浏览

c++ - DXGI API:AcquireNextFrame() 从不抓取更新的图像,始终为空白

我一直在玩别人的实现 DXGI 桌面复制 API 的代码,我遇到了一个奇怪的问题。这是我正在使用的代码的 github 链接。

https://github.com/diederickh/screen_capture/blob/master/src/test/test_win_api_directx_research.cpp

所有代码都可以正常工作,直到我尝试查看 D3D11_MAPPED_SUBRESOURCE map.pData 中的内容,我得到的只是一个空白屏幕,特别是它是一组重复的 0xFF000000,全 alpha 为黑色。在寻找其他解决方案时,我发现有人使用 while 循环来检查框架何时成功更新,从而解决了这个问题。

但是,当我运行此代码时,控制台永远不会退出并继续永远运行。显然,根据 frame_info.LastPresentTime.QuadPart,框架永远不会更新。这可能是什么原因造成的?是否存在可能导致这种情况的已知情况?

0 投票
0 回答
1303 浏览

c# - 桌面复制 API 捕获特定窗口

我一直在尝试找到一种使用桌面复制 API 捕获特定窗口的方法,而不是剪切捕获的桌面的一部分。

剪辑的问题是任何重叠的应用程序都会显示在我试图捕获的应用程序之上。我知道可以捕获特定窗口,即使它最终位于另一个窗口之后,但是,我不确定 Destkop Duplication API 是否可以实现这一点,或者是否正在使用其他东西。

对于上下文,我正在开发一个 Unity 应用程序来查看虚拟现实中的桌面;目前,我正在使用uDesktopDuplication将桌面呈现为材质,并提供一种将 API 与 C# 一起使用的方法。

任何有关如何克服此问题的建议将不胜感激。根据我在发布此之前的研究,我很难找到有关该主题的许多相关信息。:)

0 投票
1 回答
704 浏览

directx - 桌面复制 API 中的 AcquireNextFrame() 和 ReleaseFrame() 随机死锁

我正在尝试编写一个用于将 Windows 桌面录制到视频文件的应用程序。我正在使用桌面复制 API 和媒体基础 API。更具体地说,我正在使用SinkWriterMedia Foundation 的课程。我正在使用Texture2D来自 Desktop Duplication API 的对象并将它们传递给SinkWriter,这使得一个很好的硬件加速管道。我也在使用 C# 和SharpDX.

整个项目在大多数情况下运行良好。它在我的 Surface Pro 上完美运行,毫无问题地捕捉相当一致的 fps 视频。

问题出在其他硬件上。具体来说,我已经在带有独立 Nvidia GPU 的 AMD Ryzen 上进行了测试。这也很好用.. 除了通常在 8 到 20 秒之间录制桌面后,程序将被锁定在outputDuplication.ReleaseFrame()outputDuplication.AcquireNextFrame(). 它不会崩溃,它只是锁定,所以我不确定如何弄清楚发生了什么。我确实知道它与将桌面纹理传递给sinkWriter.WriteSample()函数有关。如果我删除这一行,并保持所有其他内容相同,如继续创建MediaBuffersMediaSamples像往常一样,将它们与我的桌面纹理相关联,但只是不将示例传递给WriteSample方法,那么应用程序可以愉快地“记录”看似无限期。

我已经检查了我能想到的每一个潜在错误。我确保所有对象都在应该处理的时候被处理。我看不到内存泄漏。代码使用 上的SetAllocator()方法MediaSample,因此我传递给 的纹理SinkWriter被回收。据我所知,这一切正常。

我怀疑这里有一些我不理解的基本内容。感觉好像我在正确管理背后的非托管资源方面犯了一些错误SharpDX,但我真的不知道从哪里开始寻找。在这一点上,任何指针都会受到极大的赞赏。

这是主要的捕获代码。这不是全部,而是大部分。我怀疑问题出在此处。

谢谢

0 投票
0 回答
373 浏览

opencl - 如何在没有设备到主机传输的情况下将 2D 纹理 DXGI_FORMAT_B8G8R8A8_UNORM 转换为 DXGI_FORMAT_R8G8B8A8_UNORM?

我有一个项目,它使用 Microsoft Desktop Duplication Api 捕获屏幕截图,并使用一组 OpenCL 内核实时处理它们。屏幕截图本身永远不会传输到主机(CPU)。它是一个控制台应用程序。

我在 Nvidia OpenCL 运行时遇到了一些可移植性问题。Microsoft 桌面复制 Api 结果/屏幕截图使用 DXGI_FORMAT_B8G8R8A8_UNORM 格式,Nvidia 实现不支持它。仅支持 DXGI_FORMAT_R8G8B8A8_UNORM。

0 投票
0 回答
632 浏览

c++ - Windows 桌面复制 API AcquireNextFrame 避免 DXGI_ERROR_WAIT_TIMEOUT

我现在正在使用桌面复制 API 来记录我的桌面。我希望它记录至少 30FPS。我注意到如果我将超时期限设置为 33(33ms 大约等于 30FPS),而屏幕上什么都没有发生(甚至很少),AcquireNextFrame 通常会返回 DXGI_ERROR_WAIT_TIMEOUT。为了避免这种情况,我一直在做的是我每 30FPS 在屏幕的左下角绘制一个像素。像这样:

这实际上工作得很好,但它仍然偶尔会返回 DXGI_ERROR_WAIT_TIMEOUT,这会损害我的性能。考虑到我对这个问题的解决方案有点笨拙,而且它甚至不太有效,我想弄清楚如何解决这个问题。如何强制 AcquireNextFrame 以至少 30FPS 的速率成功返回?

0 投票
1 回答
417 浏览

c++ - 使用 NvPipe 编码桌面复制 API ID3D11Texture2D 帧

我正在尝试使用 Desktop Duplication API 捕获桌面帧,并立即使用 NvPipe 对其进行编码,而无需通过 CPU 访问像素。

有什么方法可以将 ID3D11Texture2D 数据作为 NvPipe 的输入,或者其他一些有效的方法?我正在开发一个需要尽可能低延迟的 VR 解决方案,因此即使节省 1 毫秒也是一件大事。

编辑:在遵循@Soonts 的建议之后,我得到了这个似乎不起作用的代码:

NvPipe_Encode 导致内存访问冲突并且什么都不做。我不知道我搞砸了哪一步,因为我似乎无法在网上找到任何关于任何函数或变量/结构的文档,并且将手表放在变量上除了它们在内存中的地址之外没有显示任何有价值的信息。

0 投票
1 回答
442 浏览

c++ - 使用 Media Foundation 对通过桌面复制获得的 D3D 表面进行编码

我想在使用 Media Foundation 对桌面复制 API 帧进行编码后通过网络发送它们。当我调用 IMFTransform::ProcessInput 时,我遇到了 E_NOTIMPL 错误,这让我有点不知所措。

这些是我到目前为止所做的步骤,我正在详细说明它们,因为我花了几天时间从网络上稀缺的分散信息中收集所有内容,所以如果它得到解决,它希望能帮助其他人。下面的所有内容都会遇到 S_OK:

  • 我通过 Duplication API 获取表面,使用 MFCreateVideoSampleFromSurface 从它创建一个 IMFSample
  • 我正在使用 IMFActivate::ActivateObject 从使用 MFT_CATEGORY_VIDEO_ENCODER 和 MFVideoFormat_H264 初始化的 IMFActivate 获取视频编码器
  • 我正在使用比特率、帧率、纵横比等在输入上初始化 IMFMediaType。最重要的是:MFVideoFormat_NV12,似乎是唯一一个与桌面复制 API 的 DXGI_FORMAT_B8G8R8A8_UNORM 一起使用的。
  • 除了将 MFVideoFormat_H264 设置为 SUB_TYPE 之外,我在输出上设置 IMFMediatype 与上述相同。
  • 我用上面的 2 调用 IMFTransform::SetOutputType 然后 IMFTransform::SetInputType 。
  • 我将 IMFSample 时间设置为 0,因为它似乎不是由 MFCreateVideaSampleFromSurface 设置的。还使用输入 FPS 设置带有 MFFrameRateToAverageTimePerFrame 的 SampleDuration。

在这一切之后,我使用上面创建的 IMFSample 调用 MFTransform::ProcessInput,并获得一个“E_NOTIMPL 未实现”作为 HRESULT。我已经读到我应该在上面的 IMFTransform 编码器中设置一个 IMFDXGIDeviceManager,所以我使用了:

  • 我的 ID3D11Device 中的 MFCreateDXGIDeviceManager 与桌面复制 API 和任意重置令牌一起使用。
  • 使用设备和令牌执行 IMFDXGIDeviceManager::ResetDevice。
  • 调用 IMFTransform::ProcessMessage(MFT_MESSAGE_SET_D3D_MANAGER, reinterpret_cast(m_pDXDeviceManager)。

在这最后一步中,我的 HRESULT 上出现了另一个“E_NOTIMPL 未实现”,这就是我不知道自己做错了什么或需要做什么的地方。