基于X11/Xlib的虚拟显示RGB像素获取及CPU优化问询
优化方案:生成RGB格式像素数据并降低CPU占用
可以实现直接(或高效)生成RGBRGBRGB格式的像素数据,同时通过减少内存拷贝开销、优化循环逻辑、改用更高效的截图方式来降低CPU占用。以下是具体方案:
1. 修正像素顺序(匹配RGB格式需求)
原代码存储的是BGRBGRBGR顺序,若需严格的RGBRGBRGB格式,需调整赋值顺序:
// 原BGR顺序赋值 img_packets[i].arr[j+2] = image->data[w+2];//red img_packets[i].arr[j+1] = image->data[w+1];//green img_packets[i].arr[j+0] = image->data[w+0];//blue // 修改为RGB顺序赋值 img_packets[i].arr[j+0] = image->data[w+2];//red img_packets[i].arr[j+1] = image->data[w+1];//green img_packets[i].arr[j+2] = image->data[w+0];//blue
2. 优化循环逻辑:用指针代替数组下标
数组下标访问需要额外偏移计算,改用指针直接操作可显著提升循环效率:
while(1) { XImage *image = XGetImage(Display, root, 0, 0, display_width, display_height, AllPlanes, ZPixmap); if (!image) continue; // 新增空指针判断 int line_size_src = image->bytes_per_line; unsigned char *src_base = image->data; for(int i = 1; i <= display_height; i++) { unsigned char *src = src_base + line_size_src * (i-1); unsigned char *dst = img_packets[i].arr + header_size; int pixel_count = display_width; // 逐像素转换,指针直接移动 for (int k = 0; k < pixel_count; k++) { *dst++ = src[2]; // Red *dst++ = src[1]; // Green *dst++ = src[0]; // Blue src += 4; // 跳过Alpha通道 } } XDestroyImage(image); // 添加帧率控制,避免CPU满载(按60fps设置延迟) usleep(16667); }
3. 改用共享内存截图(XShm):大幅降低数据拷贝开销
XGetImage通过X协议跨进程拷贝数据,开销极大。XShmCreateImage使用共享内存直接映射服务器端图像数据,避免冗余拷贝,能显著降低CPU占用:
#include <X11/extensions/XShm.h> void func(struct data *img_packets) { Display *display = XOpenDisplay(NULL); if(!display) { fprintf(stderr, "%s\n", strerror(errno)); return; } Window root = DefaultRootWindow(display); XWindowAttributes attributes; XGetWindowAttributes(display, root, &attributes); int width = display_width; int height = display_height; // 创建共享内存图像 XShmSegmentInfo shminfo; XImage *image = XShmCreateImage(display, DefaultVisual(display, 0), attributes.depth, ZPixmap, NULL, &shminfo, width, height); if (!image) { fprintf(stderr, "Failed to create shared memory image\n"); XCloseDisplay(display); return; } // 分配并挂载共享内存 shminfo.shmid = shmget(IPC_PRIVATE, image->bytes_per_line * height, IPC_CREAT|0777); shminfo.shmaddr = image->data = (char*)shmat(shminfo.shmid, NULL, 0); shminfo.readOnly = False; if (!XShmAttach(display, &shminfo)) { fprintf(stderr, "Failed to attach shared memory\n"); shmdt(shminfo.shmaddr); shmctl(shminfo.shmid, IPC_RMID, NULL); XDestroyImage(image); XCloseDisplay(display); return; } while(1) { // 从共享内存获取图像 XShmGetImage(display, root, image, 0, 0, AllPlanes); unsigned char *src_base = image->data; int line_size_src = image->bytes_per_line; for(int i = 1; i <= height; i++) { unsigned char *src = src_base + line_size_src * (i-1); unsigned char *dst = img_packets[i].arr + header_size; int pixel_count = width; // 批量转换为RGB格式 for (int k = 0; k < pixel_count; k++) { *dst++ = src[2]; // Red *dst++ = src[1]; // Green *dst++ = src[0]; // Blue src += 4; } } // 控制帧率,降低CPU占用 usleep(16667); } // 资源清理(需添加退出逻辑才能执行到此处) XShmDetach(display, &shminfo); shmdt(shminfo.shmaddr); shmctl(shminfo.shmid, IPC_RMID, NULL); XDestroyImage(image); XCloseDisplay(display); }
4. 额外优化细节
- 帧率控制:原代码无限循环无延迟会导致CPU满载,添加
usleep可按需求控制帧率(如60fps对应16ms左右延迟)。 - 错误处理:新增
XGetImage、XShmCreateImage等操作的错误判断,避免空指针访问或资源泄漏。 - 预计算常量:提前计算
display_width、display_height等常量,避免循环内重复计算。
内容的提问来源于stack exchange,提问作者Bpwnz
相关产品推荐
相关产品推荐

