FFMPEG录屏(22)--- Linux 下基于X11枚举所有显示屏,并获取大小和截图等信息

众人拾柴火焰高,github给个star行不行?
open-traa/traa
traa is a versatile project aimed at recording anything, anywhere. The primary focus is to provide robust solutions for various recording scenarios, making it a highly adaptable tool for multiple use cases.

在 Linux X11 窗口系统下枚举显示屏

在 Linux 系统中,X11 是一个广泛使用的窗口系统,它提供了丰富的 API 用于管理和操作显示屏。在这篇博客中,我们将介绍如何使用 X11 枚举系统中的显示屏,并获取显示屏的 ID、坐标和截图等信息。

前置条件

在开始之前,请确保你已经安装了 X11 相关的开发库,例如 libX11libXrandr。你可以使用以下命令进行安装:

sudo apt-get install libx11-dev libxrandr-dev

额外的说明

现在的Ubuntu系统,默认是Wayland的,所以一些X11功能可能会报错,尤其是 获取屏幕截图, 作为LInux新手…我搞了好久,切换X11环境后,一次就成了,可以在Login界面选择
在这里插入图片描述

枚举显示屏的基本步骤

我们将通过以下几个步骤来实现枚举显示屏的功能:

  1. 打开 X11 显示连接。
  2. 检查 Xrandr 扩展是否可用。
  3. 获取根窗口。
  4. 获取显示屏信息。
  5. 获取显示屏的截图。

代码实现

以下是一个完整的代码示例,展示了如何实现上述功能:

#include <X11/Xlib.h>
#include <X11/extensions/Xrandr.h>
#include <iostream>
#include <vector>
#include <string>
#include <memory>
#include <cstring>// 获取显示屏的截图
bool get_screen_image_data(Display *display, ::Window root, const XRRMonitorInfo &monitor, const int thumbnail_width, const int thumbnail_height, std::vector<uint8_t> &data) {XImage *image = XGetImage(display, root, monitor.x, monitor.y, monitor.width, monitor.height, AllPlanes, ZPixmap);if (!image) {std::cerr << "Failed to get image for screen" << std::endl;return false;}int scaled_width = thumbnail_width;int scaled_height = thumbnail_height;data.resize(scaled_width * scaled_height * 4);// 使用 libyuv 进行图像缩放libyuv::ARGBScale(reinterpret_cast<uint8_t *>(image->data), image->bytes_per_line, image->width, image->height, data.data(), scaled_width * 4, scaled_width, scaled_height, libyuv::kFilterBox);XDestroyImage(image);return true;
}// 枚举显示屏
void enum_screens(int thumbnail_width, int thumbnail_height) {Display *display = XOpenDisplay(NULL);if (!display) {std::cerr << "Failed to open display" << std::endl;return;}// 检查 Xrandr 扩展是否可用int event_base, error_base;if (!XRRQueryExtension(display, &event_base, &error_base)) {std::cerr << "Xrandr extension is not available" << std::endl;XCloseDisplay(display);return;}// 获取根窗口::Window root = DefaultRootWindow(display);// 获取显示屏信息int monitor_count = 0;XRRMonitorInfo *monitors = XRRGetMonitors(display, root, True, &monitor_count);if (!monitors) {std::cerr << "Failed to get monitors" << std::endl;XCloseDisplay(display);return;}for (int i = 0; i < monitor_count; ++i) {std::cout << "Monitor ID: " << i << std::endl;std::cout << "Position: (" << monitors[i].x << ", " << monitors[i].y << ")" << std::endl;std::cout << "Size: " << monitors[i].width << "x" << monitors[i].height << std::endl;// 获取显示屏的截图std::vector<uint8_t> image_data;if (get_screen_image_data(display, root, monitors[i], thumbnail_width, thumbnail_height, image_data)) {std::cout << "Captured screen image" << std::endl;}}XRRFreeMonitors(monitors);XCloseDisplay(display);
}int main() {int thumbnail_width = 200;  // 缩略图宽度int thumbnail_height = 150; // 缩略图高度enum_screens(thumbnail_width, thumbnail_height);return 0;
}

代码说明

  1. 获取显示屏的截图:使用

XGetImage

函数获取显示屏的截图数据,并使用 libyuv 进行图像缩放。
2. 枚举显示屏:使用

XRRGetMonitors

函数获取显示屏信息,并遍历每个显示屏获取其详细信息。

总结

通过上述步骤,我们可以在 Linux X11 窗口系统下枚举系统中的显示屏,并获取显示屏的 ID、坐标和截图等信息。这些功能可以用于开发桌面管理工具、屏幕录制软件等应用。希望这篇博客对你有所帮助!

更多细节请前往 TRAA

额外的实现

真实的获取图片的代码是用了一个额外的辅助类,参考了webrtc的代码,本系列会大量借鉴webrtc代码,比较大树底下好乘凉?XServerPixelBuffer

这个东西,有一个坑点,搞了许久,也不知道为什么,望大佬赐教,我们是利用Xrandr插件来获取每个显示屏的坐标的,一旦你先调用了XRRGetMonitors枚举函数,XServerPixelBuffer::Init中的XGetWindowAttributes必然失败,错误是什么BadMatch。。。你懂的,X11的错误我至今不知道应该如何调查,所以一定要在XRRGetMonitors之前把pixelBuffer初始化掉
如下

  std::unique_ptr<basic_desktop_frame> full_screen_frame;if (thumbnail_size.width > 0 && thumbnail_size.height > 0) {// must init the pixel buffer before calling XRRGetMonitors, ohterwise init will raise an// BadMatch error.I don't know why, just do it.x_server_pixel_buffer pixel_buffer;if (!pixel_buffer.init(&atom_cache, root)) {LOG_ERROR("failed to init pixel buffer for window {}", root);return false;}// capture the whole screenfull_screen_frame = std::make_unique<basic_desktop_frame>(pixel_buffer.window_size());pixel_buffer.synchronize();if (!pixel_buffer.capture_rect(desktop_rect::make_size(full_screen_frame->size()),full_screen_frame.get())) {LOG_ERROR("failed to capture rect for screen {}", root);return false;}#if 0// create a file to save the full screensave_pixel_to_ppm("full_screen.ppm", full_screen_frame->data(), full_screen_frame->size().width(),full_screen_frame->size().height());
#endif}int monitor_count = 0;XRRMonitorInfo *monitors = XRRGetMonitors(display, root, True, &monitor_count);if (!monitors) {LOG_ERROR("failed to get monitors");XCloseDisplay(display);return traa_error::TRAA_ERROR_UNKNOWN;}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/60366.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

多线程和线程同步复习

多线程和线程同步复习 进程线程区别创建线程线程退出线程回收全局写法传参写法 线程分离线程同步同步方式 互斥锁互斥锁进行线程同步 死锁读写锁api细说读写锁进行线程同步 条件变量生产者消费者案例问题解答加强版生产者消费者 总结信号量信号量实现生产者消费者同步-->一个…

FlinkPipelineComposer 详解

FlinkPipelineComposer 详解 原文 背景 在flink-cdc 3.0中引入了pipeline机制&#xff0c;提供了除Datastream api/flink sql以外的一种方式定义flink 任务 通过提供一个yaml文件&#xff0c;描述source sink transform等主要信息 由FlinkPipelineComposer解析&#xff0c…

Zustand浅学习

道阻且长&#xff0c;行而不辍&#xff0c;未来可期 之前只是会使用zustand,也没仔细看过zustand的文档&#xff0c;前段时间一个合约朋友问我前端的zustand怎么用&#xff0c;啊&#xff0c;这&#xff0c;是那个笑起来明媚的不像话的帅哥问我问题诶&#xff0c;那我得认真一下…

海量数据迁移:Elasticsearch到OpenSearch的无缝迁移策略与实践

文章目录 一&#xff0e;迁移背景二&#xff0e;迁移分析三&#xff0e;方案制定3.1 使用工具迁移3.2 脚本迁移 四&#xff0e;方案建议 一&#xff0e;迁移背景 目前有两个es集群&#xff0c;版本为5.2.2和7.16.0&#xff0c;总数据量为700T。迁移过程需要不停服务迁移&#…

【贪心算法】贪心算法三

贪心算法三 1.买卖股票的最佳时机2.买卖股票的最佳时机 II3.K 次取反后最大化的数组和4.按身高排序5.优势洗牌&#xff08;田忌赛马&#xff09; 点赞&#x1f44d;&#x1f44d;收藏&#x1f31f;&#x1f31f;关注&#x1f496;&#x1f496; 你的支持是对我最大的鼓励&#…

Devops业务价值流:敏捷测试最佳实践

在迭代增量开发模式下&#xff0c;我们强调按照用户故事的优先级进行软件小功能的频繁交付。由于迭代周期紧凑&#xff0c;测试与开发活动往往并行进行&#xff0c;测试时间相对有限。为确保在这种快节奏的开发环境中依然能够保持产品质量&#xff0c;我们特制定以下测试阶段的…

el-table 纵向垂直表头处理

项目中表格展示会遇到需要纵向垂直表头情况&#xff0c;下面&#xff0c;我们基于el-table组件来实现这种表格。 以下是这次需要用到的数据表格&#xff0c;已知左侧违章名称是固定的&#xff0c;而月份是不固定的&#xff0c;在后端返回数据格式已确定的情况下&#xff0c;需…

HDFS和HBase跨集群数据迁移 源码

HDFS集群间数据迁移&#xff08;hadoop distcp&#xff09; hadoop distcp \ -pb \ hdfs://XX.14.36.205:8020/user/hive/warehouse/dp_fk_tmp.db/ph_cash_order \ hdfs://XX.18.32.21:8020/user/hive/warehouse/dp_fksx_mart.db/HBase集群间数据&#xff08;hbase ExportSnap…

浅谈单片机的gcc优化级别__以双音频信号发生器为例

IDE&#xff1a; CLion HOST&#xff1a; Windows 11 MinGW&#xff1a;x86_64-14.2.0-release-posix-seh-ucrt-rt_v12-rev0 GCC&#xff1a; arm-gnu-toolchain-13.3.rel1-mingw-w64-i686-arm-none-eabi 一、简介 gcc有多种优化级别&#xff0c;一般不选择的情况下&#x…

Ceph MDS高可用架构探索:从零到一构建多主一备MDS服务

文章目录 Ceph实现MDS服务多主一备高可用架构当前 mds 服务器状态添加 MDS 服务器验证ceph集群当前状态当前的文件系统状态设置处于激活状态 mds 的数量MDS 高可用优化分发配置文件并重启 mds 服务 Ceph实现MDS服务多主一备高可用架构 Ceph 的元数据服务&#xff08;MDS&#…

PySpark 数据处理实战:从基础操作到案例分析

Spark 的介绍与搭建&#xff1a;从理论到实践_spark环境搭建-CSDN博客 Spark 的Standalone集群环境安装与测试-CSDN博客 PySpark 本地开发环境搭建与实践-CSDN博客 Spark 程序开发与提交&#xff1a;本地与集群模式全解析-CSDN博客 Spark on YARN&#xff1a;Spark集群模式…

使用GPT-SoVITS训练语音模型

1.项目演示 阅读单句话 1725352713141 读古诗 1725353700203 2.项目环境 开发环境&#xff1a;linux 机器配置如下&#xff1a;实际使用率百分之二十几&#xff0c; 3.开发步骤 1.首先是准备数据集&#xff0c;要求是wav格式&#xff0c;一到两个小时即可&#xff0c; 2.…

Python学习从0到1 day27 Python 高阶技巧 ③ 设计模式 — 单例模式

此去经年&#xff0c;再难同游 —— 24.11.11 一、什么是设计模式 设计模式是一种编程套路&#xff0c;可以极大的方便程序的开发最常见、最经典的设计模式&#xff0c;就是我们所学习的面向对象了。 除了面向对象外,在编程中也有很多既定的套路可以方便开发,我们称之为设计模…

3.2 软件需求:面对过程分析模型

面对过程分析模型 1. 需求分析的模型概述1.1 面对过程分析模型-结构化分析方法1.2 结构化分析的过程 2. 功能模型&#xff1a;数据流图初步2.1 加工2.2 外部实体&#xff08;数据源点/终点&#xff09;2.3 数据流2.4 数据存储2.5 注意事项 3. 功能模型&#xff1a;数据流图进阶…

Android Studio 运行模拟器无法打开avd

问题&#xff1a;已经下载了HAXM 打开模拟器时还是提示未下载HAXM&#xff0c;无法打开avd 解决方案&#xff1a; 控制面板 -> 启动或关闭Windows功能&#xff0c;打开图下两项&#xff0c;后重启电脑重启Android Studio&#xff1a;

Qt文件系统-二进制文件读写

实例功能概述 除了文本文件之外&#xff0c;其他需要按照一定的格式定义读写的文件都称为二进制文件。每种格式的二进制文件都有自己的格式定义&#xff0c;写入数据时按照一定的顺写入&#xff0c;读出时也按照相应的顺读出。例如地球物理中常用的SEG-Y格式文件&#xff0c;必…

ARXML汽车可扩展标记性语言规范讲解

ARXML: Automotive Extensible Markup Language &#xff08;汽车可扩展标记语言&#xff09; xmlns: Xml name space &#xff08;xml 命名空间&#xff09; xsd: Xml Schema Definition (xml 架构定义) 1、XML与HTML的区别&#xff0c;可扩展。 可扩展&#xff0c;主要是…

游戏引擎学习第六天

这节讲的内容比较多: 参考视频:https://www.bilibili.com/video/BV1apmpYVEQu/ XInput 是微软提供的一个 API&#xff0c;用于处理 Windows 平台上 Xbox 控制器&#xff08;包括有线和无线&#xff09;及其他游戏控制器的输入。它为开发者提供了一组函数&#xff0c;用于查询控…

vivado+modelsim: xxx is not a function name

xxx is not a function name vivado问题:xxx is not a function name原因 vivado问题:xxx is not a function name 在写verilog modelsim仿真时&#xff0c;遇到error&#xff1a;xxx is not a function name。 原因 该变量xxx在仿真文件里&#xff0c;如下图红框所示&#…

云计算在教育领域的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 云计算在教育领域的应用 云计算在教育领域的应用 云计算在教育领域的应用 引言 云计算概述 定义与原理 发展历程 云计算的关键技…