DXGI抓屏优化扩展:鼠标功能+数据获取+多显示器捕获(屏幕共享源码)
先列个标题,争取这2天写完。。。
标题写错了居然,
我们一般要实现某个功能,首先希望能找到对应的DEMO,比如我们做屏幕共享,在WIN10下,首先想到的就是DXGI技术,帧率和效率是非常不错的,这里不讲性能,讲下怎么扩展某些功能:
- 鼠标功能:
- 数据获取
- 多显示器需求(多屏,副显,扩展屏说法很多)
先说第一个:
本人下载的DEMO不含鼠标功能,好的,我们加上,直接上代码就是这么简单粗暴:
D3D11_MAPPED_SUBRESOURCE mapdesc;HRESULT hRes = m_hContext->Map((ID3D11Texture2D *)hNewDesktopImage, m_Subresource, D3D11_MAP_READ_WRITE, 0, &mapdesc);if (FAILED(hRes)){return m_pBuf;}if (m_bHaveCursor)//画鼠标hRes = DrawCursor2(mapdesc, frameDescriptor, FrameInfo);m_hContext->Unmap(hAcquiredDesktopImage, m_Subresource);
上面这段代码可以控制是否画鼠标,下面是DrawCursor2的实现函数:
HRESULT VideoDXGICaptor::DrawCursor2(D3D11_MAPPED_SUBRESOURCE mapdesc, D3D11_TEXTURE2D_DESC desc, DXGI_OUTDUPL_FRAME_INFO frameInfo)
{HRESULT hRes = S_OK;bool bShowCursor = true;if (mapdesc.pData){CURSORINFO ci;memset(&ci, 0, sizeof(ci));ci.cbSize = sizeof(ci);if (GetCursorInfo(&ci)){memcpy(&m_CursorPos, &ci.ptScreenPos, sizeof(m_CursorPos));if (ci.flags & CURSOR_SHOWING){if (ci.hCursor != m_hCurrentCursor) // re-get cursor data{HICON hIcon = CopyIcon(ci.hCursor);m_hCurrentCursor = ci.hCursor;free(m_CursorData);m_CursorData = NULL;if (hIcon){ICONINFO ii;if (GetIconInfo(hIcon, &ii)){xHotspot = int(ii.xHotspot);yHotspot = int(ii.yHotspot);m_CursorData = GetCursorData(hIcon, ii, m_CursorWidth, m_CursorHeight, m_CursorPitch);DeleteObject(ii.hbmColor);DeleteObject(ii.hbmMask);}DestroyIcon(hIcon);}}}else{bShowCursor = false;}}if (m_CursorData && bShowCursor){// Not supporting mono and masked pointers at the moment//printf("Drawing pointer at %d %d\n", data->PointerPosition.Position.x, data->PointerPosition.Position.y);const int ptrx = m_CursorPos.x - xHotspot;const int ptry = m_CursorPos.y - yHotspot;uint8_t* ptr = m_CursorData;uint8_t* dst;// ### Should really do the blending on the GPU (Using DirectX) rather than using SSE2 on the CPUconst int ptrw = min(m_CursorWidth, desc.Width - ptrx);for (unsigned int y = 0; y < m_CursorHeight; ++y){if (y + ptry >= desc.Height)break;dst = static_cast<uint8_t*>(mapdesc.pData) + (((y + ptry) * mapdesc.RowPitch) + (ptrx * 4));//memcpy(dst, ptr, data->PointerShape.Width * 4);ARGBBlendRow_SSE2(ptr, dst, dst, ptrw);ptr += m_CursorPitch;}}}return hRes;
}
完成!收工!完美!
第二个问题:数据的获取,我们要从GPU获取数据到CPU内存:
原DEMO的例子是直接将数据大小默认为宽X高X4,这样对于大多数分辨率可能没问题,但是对于一些特殊分辨率比如1366X768,这样是有问题的,得到的数据是错位的。这牵涉到数据对齐问题,一定要注意。
原始:memcpy((BYTE*)m_pBuf, mappedRect.pBits, m_dxgiOutDesc.DesktopCoordinates.right * m_dxgiOutDesc.DesktopCoordinates.bottom * 4);
修改为:
int nImagePitch = m_iWidth * 4;
for (int i = 0; i < m_iHeight; i++)
{
memcpy(m_pBuf + i * nImagePitch, mappedRect.pBits + i * mapdesc.RowPitch, mapdesc.RowPitch);
}
OK!最后一个问题,多显示器需求,共享主屏幕都可以的,但是也有接副显的需求啊,这方面的资料比较难找。遇到问题我一般会先思考,能自己解决最好,比如第二个问题,因为接触类似问题多了,闭着眼睛也知道什么原因。第一个问题原来做GDI的时候也遇到过,所以稍微查下资料也可以解决。第3个比较难找,自己也不是很熟悉,但是问题始终还是要解决的,具体解决过程就不说了,反正现在知道了,呵呵。
先贴代码:
//定义一个数据结构,这里面是每个DXGI的输出和对应的适配器(显示器),没理解错的话
struct DxgiData
{IDXGIAdapter* pAdapter;IDXGIOutput *pOutput;
};std::vector<DxgiData> m_vOutputs;int Enum(){IDXGIFactory1* pFactory1;HRESULT hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)(&pFactory1));if (FAILED(hr)){return 0;}for (UINT i = 0;; i++){IDXGIAdapter1* pAdapter1 = nullptr;hr = pFactory1->EnumAdapters1(i, &pAdapter1);if (hr == DXGI_ERROR_NOT_FOUND){// no more adaptersbreak;}if (FAILED(hr)){return 0;}DXGI_ADAPTER_DESC1 desc;hr = pAdapter1->GetDesc1(&desc);if (FAILED(hr)){return 0;}desc.Description;for (UINT j = 0;; j++){IDXGIOutput *pOutput = nullptr;HRESULT hr = pAdapter1->EnumOutputs(j, &pOutput);if (hr == DXGI_ERROR_NOT_FOUND){// no more outputsbreak;}if (FAILED(hr)){return 0;}DXGI_OUTPUT_DESC desc;hr = pOutput->GetDesc(&desc);if (FAILED(hr)){return 0;}desc.DeviceName;desc.DesktopCoordinates.left;desc.DesktopCoordinates.top;int width=desc.DesktopCoordinates.right - desc.DesktopCoordinates.left;int height=desc.DesktopCoordinates.bottom - desc.DesktopCoordinates.top;DxgiData data;data.pAdapter = pAdapter1;data.pOutput = pOutput;m_vOutputs.push_back(data);}}return m_vOutputs.size();}
上面是枚举显示器适配器信息:
下面贴初始化调用代码:
HRESULT hr = S_OK;if (m_bInit){return FALSE;}int nCount=Enum();if (nCount <= 0)return FALSE;m_iWidth = m_iHeight = 0;// Driver types supportedD3D_DRIVER_TYPE DriverTypes[] ={D3D_DRIVER_TYPE_HARDWARE,D3D_DRIVER_TYPE_WARP,D3D_DRIVER_TYPE_REFERENCE,};UINT NumDriverTypes = ARRAYSIZE(DriverTypes);// Feature levels supportedD3D_FEATURE_LEVEL FeatureLevels[] ={D3D_FEATURE_LEVEL_11_0,D3D_FEATURE_LEVEL_10_1,D3D_FEATURE_LEVEL_10_0,D3D_FEATURE_LEVEL_9_1};//// Get output//INT nOutput = 0;DxgiData data;IDXGIAdapter *pAdapter = NULL;IDXGIOutput *hDxgiOutput = NULL;int nSize = m_vOutputs.size();if (m_nDisPlay<0||m_nDisPlay >= nSize)m_nDisPlay = 0;data = m_vOutputs.at(m_nDisPlay);hDxgiOutput = data.pOutput;pAdapter = data.pAdapter;hDxgiOutput->GetDesc(&m_dxgiOutDesc);UINT NumFeatureLevels = ARRAYSIZE(FeatureLevels);for (int i = 0; i < NumFeatureLevels; i++){D3D_FEATURE_LEVEL FeatureLevel = FeatureLevels[i];hr = D3D11CreateDevice(pAdapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, 0, 0, 0, D3D11_SDK_VERSION, &m_hDevice, &FeatureLevel, &m_hContext);if (SUCCEEDED(hr)){break;}}//// Get DXGI device//IDXGIDevice *hDxgiDevice = NULL;hr = m_hDevice->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&hDxgiDevice));if (FAILED(hr)){return FALSE;}//// Get DXGI adapter//IDXGIAdapter *hDxgiAdapter = NULL;hr = hDxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&hDxgiAdapter));RESET_OBJECT(hDxgiDevice);if (FAILED(hr)){return FALSE;}IDXGIOutput1 *hDxgiOutput1 = NULL;hr = hDxgiOutput->QueryInterface(__uuidof(hDxgiOutput1), reinterpret_cast<void**>(&hDxgiOutput1));RESET_OBJECT(hDxgiOutput);if (FAILED(hr)){return FALSE;}//// Create desktop duplication//hr = hDxgiOutput1->DuplicateOutput(m_hDevice, &m_hDeskDupl);RESET_OBJECT(hDxgiOutput1);if (FAILED(hr)){return FALSE;}m_Subresource = D3D11CalcSubresource(0, 0, 0);AttatchToThread();// 初始化成功m_bInit = TRUE;return TRUE;
好了,到此为止,我也无话可说,简直就是完美,没人比我更懂DXGI了(听上去好熟悉,逗逼川普的名言)。。。
m_nDisPlay随意指定,看看效果吧
本人QQ35744025,寻求合作随时骚扰即可
最后附上一个GDI多屏的下载链接:
https://download.csdn.net/download/xjb2006/12570425
这dxgi的抓屏demo(包含捕获数据,实时显示,鼠标,副屏)
https://download.csdn.net/download/xjb2006/16126779
DXGI抓屏优化扩展:鼠标功能+数据获取+多显示器捕获(屏幕共享源码)相关推荐
- 如何用DXGI抓屏,并识别视频文件中的数字
项目内容 DXGI 抓屏,设计定时器,获取数据之后回调函数,多屏 建立数字图片数据库,pytorch 训练模型 回调函数,识别数字框,存取drop位置,copy drop位置内存,存到queue 新建 ...
- C#图像处理(各种旋转、改变大小、柔化、锐化、雾化、底片、浮雕、黑白、滤镜效果,滤波,图像截取) 对图片的处理 : 亮度调整 抓屏 翻转 随鼠标画矩形
C#图像处理(各种旋转.改变大小.柔化.锐化.雾化.底片.浮雕.黑白.滤镜效果) C#图像处理(各种旋转.改变大小.柔化.锐化.雾化.底片.浮雕.黑白.滤镜效果,滤波,图像截取) 对图片的处理 : 亮 ...
- 【风电功率预测】基于matlab帝国殖民竞争算法优化BP神经网络风电功率预测【含Matlab源码 1314期】
⛄一.获取代码方式 获取代码方式1: 完整代码已上传我的资源: [风电功率预测]基于matlab帝国殖民竞争算法优化BP神经网络风电功率预测[含Matlab源码 1314期] ⛄二.帝国殖民竞争算法简 ...
- python 抓取解析接口数据_[干货]用python抓取摩拜单车API数据并做可视化分析(源码)...
原标题:[干货]用python抓取摩拜单车API数据并做可视化分析(源码) 在APP中能看到很多单车,但走到那里的时候,才发现车并不在那里.有些车不知道藏到了哪里:有些车或许是在高楼的后面,由于有GP ...
- 【图像处理】基于matlab GUI多功能图像处理系统【含Matlab源码 1876期】
⛄一.获取代码方式 获取代码方式1: 完整代码已上传我的资源:[图像处理]基于matlab GUI多功能图像处理系统[含Matlab源码 1876期] 点击上面蓝色字体,直接付费下载,即可. 获取代码 ...
- 【Matlab电力负荷预测】粒子群优化支持向量机短期电力负荷预测【含GUI源码 751期】
一.代码运行视频(哔哩哔哩) [Matlab电力负荷预测]粒子群优化支持向量机短期电力负荷预测[含GUI源码 751期] 二.matlab版本及参考文献 1 matlab版本 2014a 2 参考文献 ...
- 分享一款超多功能工具箱组合微信小程序源码_支持流量主,无需服务器和域名!适合小白
分享一款超多功能工具箱组合微信小程序源码_支持流量主,无需服务器和域名!适合小白操作! 简介: 超多功能工具箱组合微信小程序功能实用性质特别的高,用户还能覆盖的广一些具体功能列表如下: 1.证件照制作 ...
- 基于Android Studio实现的功能强大的购物商城APP源码,可做Android Studio毕业设计、大作业
Android 购物商城app 完整代码下载地址:基于Android Studio实现的功能强大的购物商城APP源码 实现的功能: 注册 登录 修改密码 重置密码(邮箱验证,考核结束将移除授权码) 商 ...
- 分享一款超40款多功能工具箱组合微信小程序源码_支持流量主,聚集市面上大部分功能的小程序,无需服务器和域名!源码拿去!
分享一款超多功能工具箱组合微信小程序源码_支持流量主,无需服务器和域名!适合小白操作! 简介: 超多功能工具箱组合微信小程序功能实用性质特别的高,用户还能覆盖的广一些具体功能列表如下: 1.证件照制作 ...
- 2023新版 多功能去水印工具微信小程序源码_带流量主功能(已更新)
简介: 2023新版 多功能去水印工具微信小程序源码_带流量主功能 自带去水印接口的多功能小程序 支持各大平台短视频去水印 支持保存封面,图集,标题等等 支持本地图片去水印 支持图片拼接 支持九宫格切 ...
最新文章
- 五彩进化树与热图更配-ggtree美颜进化树(宏基因组扩增子)
- 解决360浏览器兼容模式的页面显示问题
- SQL语句统计每天、每月、每年的 数据
- QString之arg用法
- 基于Bootstrap的网站后台模板Metronic
- linux c语言 电子相册,纯C语言开发(电子相册).doc
- Python中的分片和索引方法
- 人口预测模型及matlab代码
- 国外有哪些免费软件可以实现华为的多屏协同功能
- 分享个PDF文件签名盖章 DEMO
- 股票涨跌和买卖预测计算公式
- 应用特征值矩阵对角方法
- 阿里云centos7.4安装并部署svn1.10.0版本(配置多仓库,加入开机自启动)
- 优化UE4性能 、减少DrawCall——材质中使用自定义基元数据
- 怎样在photoshop中把字体加粗并倒影
- 机器学习(周志华) 第一章 引言
- 吉他C大调和弦高把位图
- Cause: com.microsoft.sqlserver.jdbc.SQLServerException: 关键字 'user' 附近有语法错误
- Windows11、10,安装最新版ENSP和最新版HCL模拟器教程、无脑下一步!带下载链接
- stl库的使用——队列queue和优先队列和优先队列小根堆(全家桶哎)