我正在尝试在C#中开发基本的屏幕共享和协作应用程序。我目前正在捕获屏幕,查找已更改的屏幕区域,随后需要将其传输到最终客户端。
我遇到的问题是屏幕捕获的整体帧速率太低。我有一个相当不错的算法来查找已更改的屏幕区域。给定屏幕上的字节像素阵列,它计算在2-4ms内改变的区域,但是我得到的总帧速率是15-18fps(即每帧约60ms)。瓶颈是将屏幕上的数据捕获为字节数组,大约需要35-50ms。我尝试了几种不同的技术,并且不能将fps推到20岁以上。
起初我尝试过这样的事情:
var _bmp = new Bitmap(screenSectionToMonitor.Width, screenSectionToMonitor.Height);
var _gfx = Graphics.FromImage(_bmp);
_gfx.CopyFromScreen(_screenSectionToMonitor.X, _screenSectionToMonitor.Y, 0, 0, new Size(_screenSectionToMonitor.Width, _screenSectionToMonitor.Height), CopyPixelOperation.SourceCopy);
var data = _bmp.LockBits(new Rectangle(0, 0, _screenSectionToMonitor.Width, _screenSectionToMonitor.Height), ImageLockMode.ReadOnly, _bmp.PixelFormat);
var ptr = data.Scan0;
Marshal.Copy(ptr, _screenshot, 0, _screenSectionToMonitor.Height * _screenSectionToMonitor.Width * _bytesPerPixel);
_bmp.UnlockBits(data);
对于单个1080p屏幕,只需运行上面的代码大约需要45毫秒。这使得整体帧速率太慢而不能平滑,因此我尝试使用DirectX,如下例所示:
http://www.codeproject.com/Articles/274461/Very-fast-screen-capture-using-DirectX-in-Csharp
然而,这并没有真正取得任何成果。它略微提高了屏幕捕获的速度,但它仍然太慢(大约需要25-40ms,并且小的增加不值得额外的DLL,代码等的开销。
在谷歌搜索后我无法找到更好的解决方案,所以我的问题是捕获当前显示在屏幕上的像素的最佳方法是什么?理想的解决方案是:
所有这些要点都可以通过一个可以返回合适的整体帧率的解决方案,在实际捕获的5-10ms范围内,因此帧率可以是40-60fps。
或者,如果没有与上述匹配的解决方案,我是否采用了错误的路径来计算屏幕更改。有没有更好的方法来计算已更改的屏幕区域?
答案 0 :(得分:0)
也许您可以在较低级别的代码中访问屏幕缓冲区并直接挂钩到Windows用作其屏幕更新的一部分的区域和区域。听起来你是在原始显示更改之后,Windows已经必须跟踪这些数据。只是在找到更有知识的人时,为你提供指导。