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

news2024/12/23 13:13:16

众人拾柴火焰高,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 screen
    full_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 screen
    save_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.coloradmin.cn/o/2239141.html

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

相关文章

国标GB28181视频平台EasyCVR私有化部署视频平台对接监控录像机NVR时,录像机“资源不足”是什么原因?

EasyCVR视频融合云平台&#xff0c;是TSINGSEE青犀视频“云边端”架构体系中的“云平台”系列之一&#xff0c;是一款针对大中型项目设计的跨区域、网络化、视频监控综合管理系统平台&#xff0c;通过接入视频监控设备及视频平台&#xff0c;实现视频数据的集中汇聚、融合管理、…

ENSP OSPF和BGP引入

路由协议分为&#xff1a;内部网关协议和外部网关协议。内部网关协议用于自治系统内部的路由&#xff0c;包括&#xff1a;RIP和OSPF。外部网关协议用于自治系统之间的路由&#xff0c;包括BGP。内部网关协议和外部网关协议配合来共同完成网络的路由。 BGP:边界网关路由协议(b…

template和span标签的使用

一&#xff1a;template template是模板占位符&#xff0c;可帮助我们包裹元素&#xff0c;而且循环过程当中&#xff0c;template不会被渲染到页面。 <div>ABC</div> <template v-for"(item, index) in 5"><div>{{ index }}</div>&…

备战软考Day05-数据库系统基础知识

一、基本概念 1.数据库 数据库(Database&#xff0c;缩写为DB)是指长期存储在计算机内的、有组织的、可共享的数据集合。数据库中的数据按一定的数据模型组织、描述和存储&#xff0c;具有较小的冗余度、较高的数据独立性和易扩展性&#xff0c;并可为各种用户共享。 2.数据…

Odoo:免费开源的钢铁冶金行业ERP管理系统

文 / 开源智造 Odoo亚太金牌服务 简介 Odoo免费开源ERP集成计质量设备大宗原料采购&#xff0c;备件设材全生命周期&#xff0c;多业务模式货控销售&#xff0c;全要素追溯单品&#xff0c;无人值守计量物流&#xff0c;大宗贸易交易和精细化成本管理等方案&#xff1b;覆盖…

[免费]SpringBoot+Vue3校园宿舍管理系统(优质版)【论文+源码+SQL脚本】

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的SpringBootVue3校园宿舍管理系统(优质版)&#xff0c;分享下哈。 项目视频演示 【免费】SpringBootVue3校园宿舍管理系统(优质版) Java毕业设计_哔哩哔哩_bilibili 项目介绍 随着信息技术的不断发展&…

Oracle的字符串函数

Oracle Ascii()函数 在Oracle中&#xff0c;Ascii()函数可以返回代表指定字符的数字值代码&#xff0c;那么Ascii()函数具体该如何实用呢&#xff1f; Ascii()函数语法 ASCII( single_character )参数 single_character&#xff1a;指定的字符来检索NUMBER代码。 如果输入多…

cesium 3DTiles之pnts格式详解

Point Cloud 1 概述 点云&#xff08;Point Cloud&#xff09;瓦片格式用于高效流式传输大规模点云数据&#xff0c;常用于 3D 可视化中。每个点由位置&#xff08;Position&#xff09;和可选的属性定义&#xff0c;这些属性用来描述点的外观&#xff08;如颜色、法线等&…

记录一次非常奇怪的MIME type of “text/html“报错

报错现象 访问指定地址&#xff0c;一直转圈打不开&#xff0c;打开游览器控制台发现有如下报错&#xff1a; Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of “text/html”. Strict MIME type checking i…

git新手使用教程

git新手使用教程 一、安装和初始化配置2、新建仓库3.工作区域和文件状态4.添加和提交文件5 git reset回退版本6 使用git diff查看差异7 使用git rm删除文件8 .gitignore忽略文件9 注册GitHub账号10 SSH配置和克隆仓库11 关联本地仓库和远程仓库12 Gitee的使用 由B站视频教程整理…

《TCP/IP网络编程》学习笔记 | Chapter 10:多进程服务器端

《TCP/IP网络编程》学习笔记 | Chapter 10&#xff1a;多进程服务器端 《TCP/IP网络编程》学习笔记 | Chapter 10&#xff1a;多进程服务器端进程概念及应用并发服务端的实现方法理解进程进程ID通过调用 fork 函数创建进程 进程和僵尸进程僵尸进程产生僵尸进程的原因销毁僵尸进…

推荐一款DBF文件查看器:DBF Viewer 2000

DBF Viewer 2000是一款强大、简洁且易于使用的 DBF(Clipper、dBase、FoxBase、Foxpro、Visual Foxpro、Visual DBase、VO、DB2K)文件浏览器和编辑器。 软件特点&#xff1a; - 能够快速、有效地浏览和编辑各种类型的 DBF 文件。 - 支持多种文件格式&#xff0c;包括 dBase、V…

基于构件的软件开发、软件维护、区块链技术及湖仓一体架构的应用

目录 试题一 论基于构件的软件开发方法及其应用 试题二 论软件维护方法及其应用 试题三 论区块链技术及应用 试题四 论湖仓一体架构及其应用 相关推荐 试题一 论基于构件的软件开发方法及其应用 基于构件的软件开发(Component-Based Software Development&#xff0c;CBSD…

SCRFD算法解读及环境安装实践

论文地址&#xff1a;https://arxiv.org/abs/2105.04714&#xff0c;accepted by ICLR-2022 工程地址&#xff1a;https://github.com/deepinsight/insightface/tree/master/detection/scrfd 下一篇博客&#xff0c;如何用SCRFD训练自己的数据 文章目录 1、算法解读2、环境安装…

在IntelliJ IDEA中创建带子模块的SpringBoot工程

前言 在项目开发中&#xff0c;一个工程往往有若干子工程或模块&#xff0c;所以主工程一般是一个容器&#xff0c;本文介绍在IntelliJ IDEA中创建带多模块的SpringBoot工程的详细步骤。 1、首先打开IntellJ IDEA&#xff08;以下简称IDEA&#xff09;,创建一个新项目。假定新…

深入剖析输入URL按下回车,浏览器做了什么

DNS 查询 首先,是去寻找页面资源的位置。如果导航到https://example.com, 假设HTML页面被定位到IP地址为93.184.216.34 的服务器。如果以前没有访问过这个网站&#xff0c;就需要进行DNS查询。 浏览器向域名服务器发起DNS查询请求&#xff0c;最终得到一个IP地址。第一次请求…

提升百度排名的有效策略与技巧解析

内容概要 提升百度排名对于网站的成功至关重要。首先&#xff0c;了解百度排名的基本原则&#xff0c;掌握搜索引擎是如何评估网页质量的&#xff0c;是优化过程中不可或缺的一部分。搜索引擎越来越倾向于将用户需求放在首位&#xff0c;因此提供高质量的内容和良好的用户体验…

【GPTs】MJ Prompt Creator:轻松生成创意Midjourney提示词

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: AIGC | GPTs应用实例 文章目录 &#x1f4af;GPTs指令&#x1f4af;前言&#x1f4af;MJ Prompt Creator主要功能适用场景优点缺点 &#x1f4af; 小结 &#x1f4af;GPTs指令 中文翻译&#xff1a; 任务说明 您是一款为幻灯片工…

机器人领域顶刊TRO十月最新论文一览,覆盖状态估计、任务分配、人机协作等多个领域

No.1 基于可见性的近似追逃方法 论文标题&#xff1a;Approximate Methods for Visibility-Based Pursuit–Evasion 中文标题&#xff1a;基于可见性的近似追逃方法 作者&#xff1a;Emmanuel Antonio; Israel Becerra; Rafael Murrieta-Cid 本文提出了一种基于采样的动态规…

解决编译 fast-lio-lc 算法时遇到的error方法

1.创建工作空间和下载 fast-lio-lc功能包 mkdir -p fast_lio_lc_ws/src cd fast_lio_lc_ws/src/ catkin_init_workspace git clone https://github.com/yanliang-wang/FAST_LIO_LC.git2.进入工作空间,编译 编译 fast-lio-lc遇到的error: 🕐error: fatal error: opencv/cv…