我正在开发一个应用程序,它将通过桌面复制API(使用DirectX 11)捕获屏幕(仅对前一个屏幕更新的差异)并在另一个窗口上呈现它(查看器可能在通过LAN连接的另一台机器上运行) .该代码是MSDN中提供的示例的改进版本.一切正常,除了设备没有给出任何屏幕更新,虽然在中间有一次,大约10%的时间在一些机器上发生(大多数在Windows 8/8.1机器上,很少在Windows 10机器上).我尝试了所有可能的方法来解决这个问题.减少了设备重置的次数,这为我提供了一些可靠的输出,但并不总能正常工作100%.
设备有时无法提供初始屏幕(全屏)(这种情况在所有支持桌面复制的Windows操作系统上有60%的时间发生),我想出了一个可以重新进行初步更新的工作.设备,直到它提供一个,但也导致多个问题,设备可能甚至不提供初始屏幕.
我已经投入了数周的时间来解决这个问题,但没有找到合适的解决方案,而且我所知道的论坛没有讨论这些问题.任何帮助,将不胜感激.
下面是我的代码,以获得前一个屏幕差异,初始化设备,填充适配器和监视器.
请耐心等待一段很长的代码片段,在此先感谢.
要获取屏幕更新:
INT getChangedRegions(int timeout, rectangles &dirtyRects, std::vector <MOVE_RECT> &moveRects, UINT &rect_count, RECT ScreenRect)
{
UINT diffArea = 0;
FRAME_DATA currentFrameData;
bool isTimeOut = false;
TRY
{
m_LastErrorCode = m_DuplicationManager.GetFrame(¤tFrameData, timeout, &isTimeOut);
if(SUCCEEDED(m_LastErrorCode) && (!isTimeOut))
{
if(currentFrameData.FrameInfo.TotalMetadataBufferSize)
{
m_CurrentFrameTexture = currentFrameData.Frame;
if(currentFrameData.MoveCount)
{
DXGI_OUTDUPL_MOVE_RECT* moveRectArray = reinterpret_cast<DXGI_OUTDUPL_MOVE_RECT*> (currentFrameData.MetaData);
if (moveRectArray)
{
for(UINT index = 0; index < currentFrameData.MoveCount; index++)
{
//WebRTC
// DirectX capturer API may randomly return unmoved move_rects, …Run Code Online (Sandbox Code Playgroud) 我使用AcquireNextFrame从桌面复制API截取屏幕.屏幕刷新率为120Hz.当以120FPS运行游戏时,屏幕捕获可以捕获120FPS的帧.但是当将游戏的帧速率提高到240FPS时,屏幕截图实际上会下降到70FPS左右.我的猜测是额外的帧正在积累,增加了开销,但我不确定.有没有办法避免这种性能下降?
我正在尝试使用 Windows桌面复制 API来捕获屏幕并将原始输出保存到视频中。我使用的AcquireNextFrame具有非常高的超时值(999 毫秒)。这样我就应该从 Windows 中获取每个新帧,无论如何,它自然应该是 60fps。我最终得到了一切看起来都很好的序列(第 6-11 帧),然后是看起来很糟糕的序列(第 12-14 帧)。如果我检查AccumulatedFrames
lFrameInfo.AccumulatedFrames
Run Code Online (Sandbox Code Playgroud)
该值通常为 2 或更高。根据我的理解,这意味着 Windows 会说“嘿等一下,我还没有适合你的框架”,因为调用 AcquireNextFrame 需要很长时间。但是一旦 Windows 最终给了我一个框架,它就会说“嘿,你实际上太慢了,最终错过了一个框架”。如果我能以某种方式获得这些帧,我想我会获得 60hz。
这可以通过日志记录进一步阐明:
I0608 10:40:16.964375 4196 window_capturer_dd.cc:438] 206 - Frame 6 start acquire
I0608 10:40:16.973867 4196 window_capturer_dd.cc:451] 216 - Frame 6 acquired
I0608 10:40:16.981364 4196 window_capturer_dd.cc:438] 223 - Frame 7 start acquire
I0608 10:40:16.990864 4196 window_capturer_dd.cc:451] 233 - Frame 7 acquired
I0608 10:40:16.998364 4196 window_capturer_dd.cc:438] 240 - Frame 8 start acquire
I0608 10:40:17.007876 4196 window_capturer_dd.cc:451] …Run Code Online (Sandbox Code Playgroud) 我正在使用桌面复制API(DirectX11)捕获屏幕.DuplicateOutput API返回访问被拒绝的错误,并且在登录屏幕上的Windows 8.1计算机上发生的情况非常罕见(可能是10%),尽管我的应用程序正在以SYSTEM级别权限运行并正确调用SetThreadDesktop.我曾经在我收到的每一个错误之后重置并调用SetThreadDesktop,但是即使在多个设备重置和启动之后,应用程序也无法从错误中恢复.在多次重试或重新启动应用程序后,我不得不回退到GDI(应用程序在从directx切换到GDI之后工作正常),但这个想法似乎很糟糕.
注意:我确实在Windows 10/Windows 8计算机上遇到了同样的问题,但与特定的Windows 8.1计算机相比并不常见.
这里是E_ACCESSDENIED错误的描述,该错误仅告知此错误可能的情况(没有系统级权限或SetThreadDesktop未被正确调用).我尝试了所有可能的方法来找出问题,但不能.
任何帮助将不胜感激,提前致谢.
以下是初始化设备的代码:
//
// Initialize duplication interfaces
//
HRESULT cDuplicationManager::InitDupl(_In_ ID3D11Device* Device, _In_ IDXGIAdapter *_pAdapter, _In_ IDXGIOutput *_pOutput, _In_ UINT Output)
{
HRESULT hr = E_FAIL;
if(!_pOutput || !_pAdapter || !Device)
{
return hr;
}
m_OutputNumber = Output;
// Take a reference on the device
m_Device = Device;
m_Device->AddRef();
_pOutput->GetDesc(&m_OutputDesc);
// QI for Output 1
IDXGIOutput1* DxgiOutput1 = nullptr;
hr = _pOutput->QueryInterface(__uuidof(DxgiOutput1), reinterpret_cast<void**>(&DxgiOutput1));
if (FAILED(hr))
{
return ProcessFailure(nullptr, _T("Failed to QI …Run Code Online (Sandbox Code Playgroud) screen-capture directx-11 visual-c++ dxgi desktop-duplication
我的应用程序的用户在使用DesktopDuplication API.
开始捕获时,应用程序崩溃,因为应用程序无法释放OutputDuplication.
用户的PC详细信息:
Windows 10.0.18362.0, 64 bits
Nvidia GeForce GTX 960, driver version 441.66
Run Code Online (Sandbox Code Playgroud)
错误日志:
? Message -
HRESULT: [0x887A0001], Module: [SharpDX.DXGI], ApiCode: [DXGI_ERROR_INVALID_CALL/InvalidCall],
Message: The application made a call that is invalid. Either the parameters of the call or the state of some object was incorrect.
Enable the D3D debug layer in order to see details via debug messages.
? Type -
SharpDX.SharpDXException
? Source -
SharpDX
? TargetSite -
Void CheckError()
? StackTrace …Run Code Online (Sandbox Code Playgroud) 我正在使用DDA来捕获桌面图像帧并将它们发送到服务器,这些帧应该用于创建带有MMF 的视频。我想了解,需要与做的事情MMF,如果我将使用源读取器和接收器作家,以从捕捉到的帧渲染视频。
有两个问题:
1) 嗯,首先,我不能完全理解,如果我已经从DDA接收到视频帧,实际上是否需要带有Media Source的Source Reader?我可以将它们发送到Sink Writer并渲染视频吗?
2)据我所知,首先要做的是,如果仍然需要Source Reader和Media Source,那就编写我自己的Media Source,它将理解用DDA捕获的DXGI_FORMAT_B8G8R8A8_UNORM帧。然后我应该使用带有合适的Decoders \Encoders 的Souce Reader和Sink Writer并将媒体数据发送到Media Sinks。您能否更详细地解释一下在这种情况下需要做什么?
dxgi ×3
c# ×2
c++ ×2
directx-11 ×2
visual-c++ ×2
winapi ×2
directx ×1
sharpdx ×1
webrtc ×1
windows-10 ×1