Xcb-Damage扩展
一,Windows截屏变化区域
https://www.pianshen.com/article/1554879856/
https://blog.csdn.net/qwerty448/article/details/53056576
windows8以上的系统,则实现了一个DXGI,用来截取桌面,它是集成在DirectX之中,成为DX的一个子功能。 你需要简单熟悉DirectX技术才能使用DXGI,他通过一堆啰嗦的创建和查询各种接口,最终获取到IDXGIOutputDuplication接口。 截屏的时候,使用这个接口的AcquireNextFrame函数获取当前桌面图像,当然这个接口还提供GetFrameDirtyRects等函数获取发生了变化的矩形区域。
从上面描述可以看到,Windows有个名为IDXGIOutputDuplication::GetFrameDirtyRects的API接口,可以捕获发生变化的桌面区域,这对桌面的远程接入有很大帮助,可以减少桌面图像流量。
二,Linux截屏变化区域
X11下找到一个damage扩展,应该是与桌面变化区域相关的功能。
https://www.x.org/releases/X11R7.7/doc/damageproto/damageproto.txt
https://www.x.org/releases/X11R7.7/doc/index.html
https://www.x.org/releases/current/doc/man/man3/xcb_damage_create.3.xhtml
https://www.x.org/releases/current/doc/man/man3/
https://xcb.freedesktop.org/manual/group__XCB__Damage__API.html
https://gitlab.freedesktop.org/xorg/lib/libxdamage
https://github.com/freedesktop
0,测试环境
硬件:VirtualBox 7.0
操作系统:UbuntuKylin 20.04.3 LTS
1,在这里找到一份damage的相关测试代码,试试:
https://forum.kde.org/viewtopic.php?t=132167
// filename: main.c #include <cstring> #include <iostream> #include <memory> #include <sys/select.h> #include <xcb/xcb.h> #include <xcb/xcb_event.h> #include <xcb/damage.h> using namespace std; struct xcb_connection_deleter { void operator()(xcb_connection_t* c) { if (c) { xcb_disconnect(c); } } }; xcb_screen_t* screen_of_display(xcb_connection_t* c, int screen) { for (auto iter = xcb_setup_roots_iterator(xcb_get_setup(c)); iter.rem; --screen, xcb_screen_next(&iter)) { if (screen == 0) { return iter.data; } } return nullptr; } int main() { unique_ptr<xcb_connection_t, xcb_connection_deleter> connection{xcb_connect(nullptr, nullptr)}; int rc = xcb_connection_has_error(connection.get()); if (rc != 0) { cout << "xcb connection error: " << rc << endl; exit(1); } const auto extreply = xcb_get_extension_data(connection.get(), &xcb_damage_id); if (!extreply->present) { cout << "xcb-damage is not present\n"; exit(1); } uint8_t damageEvent = extreply->first_event; auto cookie = xcb_damage_query_version(connection.get(), XCB_DAMAGE_MAJOR_VERSION, XCB_DAMAGE_MINOR_VERSION); xcb_generic_error_t* e = 0; auto reply = xcb_damage_query_version_reply(connection.get(), cookie, &e); if (!reply) { cout << "xcb_damage_use_extension error: " << e->error_code << endl; exit(1); } free(reply); auto damage_handle = xcb_generate_id(connection.get()); xcb_damage_create(connection.get(), damage_handle, screen_of_display(connection.get(), 0)->root, XCB_DAMAGE_REPORT_LEVEL_RAW_RECTANGLES); xcb_flush(connection.get()); auto xfd = xcb_get_file_descriptor(connection.get()); if (xfd <= 0) { cout << "invalid xcb file descriptor\n"; exit(1); } while (1) { auto tv = timeval{0, 20000}; fd_set fds; FD_ZERO(&fds); FD_SET(xfd, &fds); int result = select(xfd + 1, &fds, nullptr, nullptr, &tv); if (result == 0) { continue; } else if (result < 0) { cerr << "select failed with error: " << strerror(errno) << endl; exit(1); } xcb_generic_event_t* event; while ((event = xcb_poll_for_event(connection.get()))) { if (XCB_EVENT_RESPONSE_TYPE(event) != damageEvent) { free(event); continue; } auto d = reinterpret_cast<xcb_damage_notify_event_t&>(*event); cout << "--------- damage event ----------" << endl; cout << "area: x: " << d.area.x << ", y: " << d.area.y << ", w: " << d.area.width << ", h: " << d.area.height << endl; cout << "geometry: x: " << d.geometry.x << ", y: " << d.geometry.y << ", w: " << d.geometry.width << ", h: " << d.geometry.height << endl; free(event); } } xcb_damage_destroy(connection.get(), damage_handle); return 0; }
2,编译
$ sudo apt install g++
$ sudo apt install libx11-xcb-dev
$ sudo apt install libxcb-util-dev
$ sudo apt install libxcb-damage0-dev
$ $ g++ main.c -o demo -lxcb -lxcb-damage -O0 -g
3,运行
在远程ssh终端里执行,显示如下:
$ ./demo
——— damage event ———-
area: x: 0, y: 0, w: 1366, h: 768
geometry: x: 0, y: 0, w: 1366, h: 768
^C
在VirtualBox本地桌面里操作,demo没有动静,应该是代码里抓的屏幕不对。
修改下代码:
将:xcb_connect(nullptr, nullptr)
改为:xcb_connect(“:0.0″, nullptr)
再编译执行:
$ ./demo
——— damage event ———-
area: x: 0, y: 0, w: 1360, h: 768
geometry: x: 0, y: 0, w: 1360, h: 768
——— damage event ———-
area: x: 0, y: 0, w: 1360, h: 768
geometry: x: 0, y: 0, w: 1360, h: 768
——— damage event ———-
area: x: 0, y: 0, w: 1360, h: 768
geometry: x: 0, y: 0, w: 1360, h: 768
——— damage event ———-
area: x: 10, y: 8, w: 90, h: 100
geometry: x: 0, y: 0, w: 1360, h: 768
——— damage event ———-
area: x: 10, y: 8, w: 90, h: 100
geometry: x: 0, y: 0, w: 1360, h: 768
——— damage event ———-
area: x: 10, y: 114, w: 90, h: 100
geometry: x: 0, y: 0, w: 1360, h: 768
…
就能正常获取到所有在VirtualBox本地桌面里操作的改变区域了。
over~
参考:
https://linux.tutorialink.com/xcb_poll_for_event-causes-100-usage-of-one-cpu-core/
https://www.itcodet.com/cpp/cpp-xcb_poll_for_event-function-examples.html
转载请保留地址:http://www.lenky.info/archives/2022/11/3227 或 http://lenky.info/?p=3227
备注:如无特殊说明,文章内容均出自Lenky个人的真实理解而并非存心妄自揣测来故意愚人耳目。由于个人水平有限,虽力求内容正确无误,但仍然难免出错,请勿见怪,如果可以则请留言告之,并欢迎来信讨论。另外值得说明的是,Lenky的部分文章以及部分内容参考借鉴了网络上各位网友的热心分享,特别是一些带有完全参考的文章,其后附带的链接内容也许更直接、更丰富,而我只是做了一下归纳&转述,在此也一并表示感谢。关于本站的所有技术文章,欢迎转载,但请遵从CC创作共享协议,而一些私人性质较强的心情随笔,建议不要转载。
法律:根据最新颁布的《信息网络传播权保护条例》,如果您认为本文章的任何内容侵犯了您的权利,请以Email或书面等方式告知,本站将及时删除相关内容或链接。