【C++】开源:Linux端V4L2视频设备库
😏★,°:.☆( ̄▽ ̄)/$:.°★ 😏
这篇文章主要介绍Linux端V4L2视频设备库。
无专精则不能成,无涉猎则不能通。——梁启超
欢迎来到我的博客,一起学习,共同进步。
喜欢的朋友可以关注一下,下次更新不迷路🥞
文章目录
- :smirk:1. 项目介绍
- :blush:2. 环境配置
- :satisfied:3. 使用说明
😏1. 项目介绍
Video4Linux2(V4L2
)是一个用于Linux操作系统的视频设备驱动框架。它提供了一个统一的接口,用于在应用程序和视频设备之间进行通信和交互。
V4L2支持各种类型的视频设备,包括USB摄像头、摄像机、TV调谐器、网络摄像头等。通过使用V4L2,开发者可以轻松地访问和控制视频设备,以捕获视频流、调整图像参数、设置视频格式和分辨率等。
以下是V4L2的一些重要特点和概念:
1.设备节点:每个视频设备在Linux系统中都表示为一个设备节点,通常位于/dev/video*路径下。应用程序通过打开这些设备节点来访问相应的视频设备。
2.视频捕捉:V4L2允许应用程序从视频设备中捕获视频帧或图像。它提供了一系列的API函数,使应用程序能够请求存储视频帧的缓冲区,并在设备准备好时将其读取到内存中。
3.视频输出:除了捕获视频,V4L2还支持将视频数据发送到视频设备,以便在外部显示设备上进行输出。应用程序可以将视频帧写入输出缓冲区,并通过相应的IOCTL调用将其发送到视频设备。
4.控制和参数设置:V4L2允许应用程序对视频设备进行控制和配置。例如,应用程序可以设置摄像头的亮度、对比度、饱和度等参数,选择摄像头的输入源,设置视频格式和分辨率等。
5.帧缓冲管理:V4L2通过Frame Buffer子系统来管理视频帧的缓冲区。它提供了API函数来请求和管理用于存储视频帧的缓冲区,并进行帧缓冲的交换和处理。
😊2. 环境配置
下面进行环境配置:
# v4l2是linux内核的一部分,只需安装开发库
sudo apt-get install libv4l-dev
# 使用v4l2开发
# 在应用程序中使用 #include <linux/videodev2.h> 来引入V4L2的头文件,并使用相关的API函数
😆3. 使用说明
下面进行使用分析:
基于v4l2调用usb摄像头并用opencv显示示例:
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/mman.h> //共享内存
#include <linux/videodev2.h>
#include <opencv2/opencv.hpp>#define WIDTH 640
#define HEIGHT 480int main() {int fd;struct v4l2_capability cap;struct v4l2_format fmt;struct v4l2_requestbuffers req;struct v4l2_buffer buf;enum v4l2_buf_type type;// 打开摄像头设备fd = open("/dev/video0", O_RDWR);if (fd == -1) {std::cerr << "无法打开摄像头设备" << std::endl;return 1;}// 查询摄像头能力if (ioctl(fd, VIDIOC_QUERYCAP, &cap) == -1) {std::cerr << "无法查询摄像头能力" << std::endl;close(fd);return 1;}// 设置视频格式memset(&fmt, 0, sizeof(fmt));fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;fmt.fmt.pix.width = WIDTH;fmt.fmt.pix.height = HEIGHT;fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; // YUV格式if (ioctl(fd, VIDIOC_S_FMT, &fmt) == -1) {std::cerr << "无法设置视频格式" << std::endl;close(fd);return 1;}// 请求视频缓冲区memset(&req, 0, sizeof(req));req.count = 1;req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;req.memory = V4L2_MEMORY_MMAP;if (ioctl(fd, VIDIOC_REQBUFS, &req) == -1) {std::cerr << "无法请求视频缓冲区" << std::endl;close(fd);return 1;}// 映射视频缓冲区到用户空间struct v4l2_buffer* buffers = new v4l2_buffer[req.count];void** frame_buffers = new void*[req.count];for (int i = 0; i < req.count; i++) {memset(&buf, 0, sizeof(buf));buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;buf.memory = V4L2_MEMORY_MMAP;buf.index = i;if (ioctl(fd, VIDIOC_QUERYBUF, &buf) == -1) {std::cerr << "无法查询视频缓冲区" << std::endl;close(fd);return 1;}frame_buffers[i] = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset);if (frame_buffers[i] == MAP_FAILED) {std::cerr << "无法映射视频缓冲区到用户空间" << std::endl;close(fd);return 1;}}// 入队视频缓冲区for (int i = 0; i < req.count; i++) {memset(&buf, 0, sizeof(buf));buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;buf.memory = V4L2_MEMORY_MMAP;buf.index = i;if (ioctl(fd, VIDIOC_QBUF, &buf) == -1) {std::cerr << "无法入队视频缓冲区" << std::endl;close(fd);return 1;}}// 开始视频流采集type = V4L2_BUF_TYPE_VIDEO_CAPTURE;if (ioctl(fd, VIDIOC_STREAMON, &type) == -1) {std::cerr << "无法开始视频流采集" << std::endl;close(fd);return 1;}// 循环获取并显示相机数据cv::Mat frame(HEIGHT, WIDTH, CV_8UC2);cv::namedWindow("Camera", cv::WINDOW_AUTOSIZE);while (true) {// 出队视频缓冲区memset(&buf, 0, sizeof(buf));buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;buf.memory = V4L2_MEMORY_MMAP;if (ioctl(fd, VIDIOC_DQBUF, &buf) == -1) {std::cerr << "无法出队视频缓冲区" << std::endl;close(fd);return 1;}// 处理相机数据(这里只是简单地将YUYV格式的数据转换为RGB格式)cv::cvtColor(cv::Mat(HEIGHT, WIDTH, CV_8UC2, frame_buffers[buf.index]), frame, cv::COLOR_YUV2BGR_YUYV);// 显示相机数据cv::imshow("Camera", frame);if (cv::waitKey(1) == 27) {break; // 按下Esc键退出循环}// 再次入队视频缓冲区if (ioctl(fd, VIDIOC_QBUF, &buf) == -1) {std::cerr << "无法再次入队视频缓冲区" << std::endl;close(fd);return 1;}}// 停止视频流采集type = V4L2_BUF_TYPE_VIDEO_CAPTURE;if (ioctl(fd, VIDIOC_STREAMOFF, &type) == -1) {std::cerr << "无法停止视频流采集" << std::endl;close(fd);return 1;}// 解除映射视频缓冲区for (int i = 0; i < req.count; i++) {munmap(frame_buffers[i], buf.length);}// 关闭摄像头设备close(fd);delete[] buffers;delete[] frame_buffers;return 0;
}
编译运行:
g++ -o main main.cpp `pkg-config --libs opencv`
./main
以上。
相关文章:

【C++】开源:Linux端V4L2视频设备库
😏★,:.☆( ̄▽ ̄)/$:.★ 😏 这篇文章主要介绍Linux端V4L2视频设备库。 无专精则不能成,无涉猎则不能通。——梁启超 欢迎来到我的博客,一起学习,共同进步。 喜欢的朋友可以关注一下,下…...

基于数据驱动的多尺度表示的信号去噪统计方法研究(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
【Golang】Golang进阶系列教程--Go 语言 map 如何顺序读取?
文章目录 前言现象原因如何顺序读取推荐阅读 前言 Go 语言中的 map 是一种非常强大的数据结构,它允许我们快速地存储和检索键值对。 然而,当我们遍历 map 时,会有一个有趣的现象,那就是输出的键值对顺序是不确定的。 现象 先看…...

伊语IM即时通讯源码/im商城系统/纯源码IM通讯系统安卓+IOS前端纯原生源码
伊语IM即时通讯源码/im商城系统/纯源码IM通讯系统安卓IOS前端纯原生源码, 后端是java源码。...
C++推理
YOLOv5 OpenCV DNN C导出的 ONNX 模型示例的推理: https://github.com/Hexmagic/ONNX-yolov5/blob/master/src/test.cpphttps://github.com/doleron/yolov5-opencv-cpp-python YOLOv5 OpenVINO C推理示例: GitHub - dacquaviva/yolov5-openvino-cpp-p…...

Day10-作业(SpringBootWeb案例)
作业1:完成课上预留给大家自己完成的功能 【部门管理的修改功能】 注意: 部门管理的修改功能,需要开发两个接口: 先开发根据ID查询部门信息的接口,该接口用户查询数据并展示 。(一定一定先做这个功能) 再开发根据ID…...
源码阅读:p-limit
源码阅读:p-limit 源码阅读:p-limit简介源码解读学习与收获 源码阅读:p-limit 简介 p-limit是一个用于限制并发操作的包,它可以控制同时执行的异步操作数量。它提供了一种简单的方式来管理并发操作,以避免系统资源过…...

目标检测-击穿黑夜的PE-YOLO
前言 当前的目标检测模型在许多基准数据集上取得了良好的结果,但在暗光条件下检测目标仍然是一个巨大的挑战。为了解决这个问题,作者提出了金字塔增强网络(PENet)并将其与YOLOv3结合,构建了一个名为PE-YOLO的暗光目标检…...

优化性能压力测试的关键策略和技巧
在现代软件开发中,性能压力测试是不可或缺的一环。它可以帮助开发团队评估系统在负载压力下的性能表现,识别潜在的性能瓶颈,并采取适当的措施进行优化。然而,仅仅进行性能压力测试是不够的,关键的在于如何优化测试的过…...

VMware Linux 可视化增加磁盘
1、VMware 增加磁盘 2、disks挂载磁盘 此处我挂载的是20G磁盘,截图只是用5G的做过程演示例子。 3、验证挂载磁盘...

从 axios 源码学习设计模式
文章目录 一、源码分析1.1 axios 为什么可以多种方式调用1.2 拦截器实现注册使用:promise链式调用 二、从 axios 看设计模式axios 的精髓在哪2.1 抽象工厂axios.create -- 创建新实例的工厂 2.2 微内核设计2.3 适配器思想2.4 责任链模式2.5 桥接模式举例:…...
输出不同程序执行的时间
简单的测试工具代码,它可以输出不同程序执行的时间。我们可以使用Python的time模块来实现这个功能。 import timedef test_function(func, *args, **kwargs):"""测试函数执行时间的工具函数:param func: 待测试的函数:param *args: 函数的位置参数:…...
HDU 6391 组合数学 + DP
题意 传送门 HDU 6391 Lord Li’s problem 题解 仅考虑 S i ≠ T i S_i\neq T_i SiTi 的数量 m m m,最后答案除以 ( n m ) \binom{n}{m} (mn) 即可。考虑 X X X 的排列,最后答案除以 k ! k! k! 即可。 d p [ i 1 ] [ j ] dp[i1][j] dp[…...

StopWatch与ThreadLocal
目录 1、StopWatch 1、1作用: 1、2方法: 1、3使用方法 2、ThreadLocal 2、1什么是ThreadLocal 2、2简单例子 2、3使用ThreadLocal带来的四个好处 2、4主要方法 2、5ThreadLocal内存泄漏问题 1、StopWatch 1、1作用: 统计代码块耗时时…...
20. 有效的括号
给定一个只包括 (,),{,},[,] 的字符串 s ,判断字符串是否有效。 有效字符串需满足: 左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。 每个右括号都有一个对应的相同类型的左括…...

微信小程序原生写法传递参数
微信小程序原生写法传递参数 data-xxx 自定义参数名 ,接收参数:方法(变量名) checkVip:function(event) {let that thisconsole.log(event,event)console.log(event.currentTarget.dataset.idx,index)let index Number(eve…...

JavaWeb+jsp+Tomcat的教务查询系统
点击以下链接获取源码: https://download.csdn.net/download/qq_64505944/88134601?spm1001.2014.3001.5503 jsp/tomcat7.05/MySQL5.7或8版本/ssm框架/spring/ Web框架:SpringBoot/ORM框架:Mybatis/安全框架:Shiro/分页插件&am…...
C# FTP下载 采用Ssh.Net方式
不要再用FTPClient了 nuget下载Ssh.Net 然后代码如下: /// <summary>/// SFTP操作类/// </summary>public class SFTPHelper{#region 字段或属性private SftpClient sftp;/// <summary>/// SFTP连接状态/// </summary>public bool Conne…...

【C++】做一个飞机空战小游戏(三)——模块化程序设计
[导读]本系列博文内容链接如下: 【C】做一个飞机空战小游戏(一)——使用getch()函数获得键盘码值 【C】做一个飞机空战小游戏(二)——利用getch()函数实现键盘控制单个字符移动【C】做一个飞机空战小游戏(三)——模块化程设设计 在前两讲当中,介绍了利用…...

Django使用WebSocket
1、websocket 相关 实现一个系统,20 个用户同时打开网站,呈现出来一个群聊界面 解决方案 轮询:让浏览器每隔2s向后台发送一次请求,缺点:延迟,请求太多网站压力大 长轮询:客户端向服务端发送请…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...

C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...

【笔记】WSL 中 Rust 安装与测试完整记录
#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统:Ubuntu 24.04 LTS (WSL2)架构:x86_64 (GNU/Linux)Rust 版本:rustc 1.87.0 (2025-05-09)Cargo 版本:cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能
1. 开发环境准备 安装DevEco Studio 3.1: 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK 项目配置: // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...

毫米波雷达基础理论(3D+4D)
3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文: 一文入门汽车毫米波雷达基本原理 :https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...
书籍“之“字形打印矩阵(8)0609
题目 给定一个矩阵matrix,按照"之"字形的方式打印这个矩阵,例如: 1 2 3 4 5 6 7 8 9 10 11 12 ”之“字形打印的结果为:1,…...

基于开源AI智能名片链动2 + 1模式S2B2C商城小程序的沉浸式体验营销研究
摘要:在消费市场竞争日益激烈的当下,传统体验营销方式存在诸多局限。本文聚焦开源AI智能名片链动2 1模式S2B2C商城小程序,探讨其在沉浸式体验营销中的应用。通过对比传统品鉴、工厂参观等初级体验方式,分析沉浸式体验的优势与价值…...

Xcode 16 集成 cocoapods 报错
基于 Xcode 16 新建工程项目,集成 cocoapods 执行 pod init 报错 ### Error RuntimeError - PBXGroup attempted to initialize an object with unknown ISA PBXFileSystemSynchronizedRootGroup from attributes: {"isa">"PBXFileSystemSynchro…...