Linux--V4L2应用程序开发(二)获取数据

一、采集数据流程

申请buffer用来放置摄像头数据

  • ioctl VIDIOC_REQBUFS:申请buffer,APP可以申请很多个buffer,但是驱动程序不一定能申请到

  • ioctl VIDIOC_QUERYBUF和mmap:查询buffer信息、映射

    • 如果申请到了N个buffer,这个ioctl就应该执行N次

    • 执行mmap后,APP就可以直接读写这些buffer

  • ioctl VIDIOC_QBUF:把buffer放入"空闲链表"

    • 如果申请到了N个buffer,这个ioctl就应该执行N次

获取数据

  • ioctl VIDIOC_STREAMON:启动摄像头

存储数据

  • 这里是一个循环:使用poll/select监测buffer,然后从"完成链表"中取出buffer,处理后再放入"空闲链表"

    • poll/select

    • ioctl VIDIOC_DQBUF:从"完成链表"中取出buffer

    • 处理:前面使用mmap映射了每个buffer的地址,处理时就可以直接使用地址来访问buffer

    • ioclt VIDIOC_QBUF:把buffer放入"空闲链表"

  • ioctl VIDIOC_STREAMOFF:停止摄像头

二、代码如下:

struct v4l2_requestbuffers rb;memset(&rb, 0,sizeof(struct v4l2_requestbuffers));rb.count =32;rb.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;rb.memory = V4L2_MEMORY_MMAP;  /*申请buffer*/if(0 == ioctl(fd, VIDIOC_REQBUFS,&rb)){buf_cnt = rb.count;       for(i = 0; i<rb.count;i++){struct v4l2_buffer buf;memset(&buf, 0, sizeof(struct v4l2_buffer));buf.index = i;buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;buf.memory = V4L2_MEMORY_MMAP;if(0==ioctl(fd, VIDIOC_QUERYBUF,&buf))/*查询申请到buf是否成功*/{bufs[i] = mmap(0, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED,fd, buf.m.offset);/*申请成功后,mmap这些buffer*/if(bufs[i]==MAP_FAILED){perror("Unable to map buffer");return -1;}}else{printf("can not query buffer\n");return -1;}}printf("map %d buffers ok\n",buf_cnt) ; }else{printf("can not request buffers\n ");}/*把所有buffer放入空闲链表中*/for(i =0; i<buf_cnt;i++){struct v4l2_buffer buf;memset(&buf ,0, sizeof(struct v4l2_buffer));buf.index = i;buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;buf.memory = V4L2_MEMORY_MMAP;if(0 != ioctl(fd, VIDIOC_QBUF,&buf)){perror("Uable to queue buffer");return -1;}}printf("queue buffers ok\n");/*启动摄像头*/int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;if(0 != ioctl(fd,VIDIOC_STREAMON, &type)){perror("Uable to start capture");return -1;}printf("start capture ok\n");while(1){/*poll*/memset(fds, 0, sizeof(fds));fds[0].fd = fd;fds[0].events = POLLIN;if(1 ==poll(fds,1,-1)){/*把buffer取出队列*/struct v4l2_buffer buf;memset(&buf ,0, sizeof(struct v4l2_buffer));buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;buf.memory = V4L2_MEMORY_MMAP;if(0 != ioctl(fd, VIDIOC_DQBUF,&buf)){perror("Unable to dequeue buffer");return -1;}/*把buffer数据存为文件*/sprintf(filename, "video_raw_DATA_%04d.jpg",file_cnt++);int fd_file =open(filename, O_RDWR|O_CREAT,0666);if(fd_file < 0){printf("can not creat file :%s \n", filename);return -1;}write(fd_file, bufs[buf.index], buf.bytesused);close(fd_file);/*把buffer放入队列*/if(0 != ioctl(fd, VIDIOC_QBUF,&buf)){perror("Uable to queue buffer");return -1;}       }}if(0 != ioctl(fd,VIDIOC_STREAMOFF, &type));{perror("Uable to stop capture");return -1;}printf("stop capture ok\n");close(fd);

输出结果为:将每一帧数据采集为jpg格式保存在当前目录下。

三、代码知识点补充

1、mmap()

bufs[i] = mmap(0, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED,fd, buf.m.offset);

        mmap 函数用于将一个文件或设备(如视频设备)的内容映射到进程的地址空间。这样,可以通过指针直接访问文件或设备的内容,而不需要使用系统调用,如 readwrite,从而提高了访问效率。

参数解释

  • addr: 指定映射的起始地址。通常设为 0NULL,表示由内核决定映射区域的起始地址。
  • length: 要映射的文件部分的长度。这里是 buf.length,表示需要映射的缓冲区的大小。
  • prot: 映射区域的保护方式。可以是以下几个值的组合:
    • PROT_READ:页内容可以被读取。
    • PROT_WRITE:页内容可以被写入。
    • PROT_EXEC:页内容可以被执行。
  • flags: 映射对象的类型、映射选项和页是否可以共享等。常用值有:
    • MAP_SHARED:映射区内的写入数据会写回到原文件,同时对其他映射到该文件的进程可见。
    • MAP_PRIVATE:写入数据会产生一个写时拷贝(copy-on-write),对其他映射到该文件的进程不可见。
  • fd: 要映射到内存的文件描述符。这里是视频设备文件描述符 fd
  • offset: 文件映射的起始位置。通常是缓冲区的偏移量,这里是 buf.m.offset

返回值

mmap 成功时返回映射区的指针,失败时返回 MAP_FAILED,并设置 errno 以指示错误。

2、perror()

        perror 函数是 C 标准库中的一个函数,用于输出描述最近一次函数调用发生错误的错误信息。它会根据 errno 的值输出对应的错误消息。errno 是一个全局变量,用于记录最近一次系统调用或库函数调用错误的错误码。

        perror 函数根据 errno 的值,查找并输出对应的错误消息。错误消息通常来自系统定义的一系列错误描述字符串。errno 由最近一次出错的系统调用或标准库函数设置。

  • errno: errno 是由库函数和系统调用设置的全局变量,表示上一次操作的错误码。每个错误码对应一个错误消息。
  • 错误消息查找perror 根据当前 errno 的值,在系统预定义的错误消息列表中查找并输出相应的错误消息。

3、poll()函数

        外部阻塞式,内部监视多路 I/O,系统调用 poll()select()函数很相似,但函数接口有所不同。在 select()函数中,我们提供三个 fd_set 集 合,在每个集合中添加我们关心的文件描述符;而在 poll()函数中,则需要构造一个 struct pollfd 类型的数组,每个数组元素指定一个文件描述符以及我们对该文件描述符所关心的条件(数据可读、可写或异常情况)。

poll 函数的内部轮询主要发生在有多个文件描述符时,它需要检查每一个文件描述符的状态。虽然这种检查会有一定的 CPU 开销,但相比纯轮询而言,开销要小得多,因为在大多数时间里,poll 函数处于阻塞状态,只有在事件发生时才会进行一次所有文件描述符状态的检查,已确定哪些文件描述符上有时间发生。

struct pollfd {int fd;         /* 文件描述符 */short events;   /* 要监视的事件 */short revents;  /* 发生的事件 */
};

4、memset()函数

       函数原型: void *memset(void *s, int c, size_t n);

memset 函数将内存块 s 的前 n 个字节设置为值 c。具体来说,它会把每个字节都设置为 c 的值(取 unsigned char 的值)。通常用于以下情况:

  • 初始化数组或结构体。
  • 重置缓冲区。
  • 为数据结构分配内存后进行清零。

四、遇到的问题

    /*启动摄像头*/int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;if(0 != ioctl(fd,VIDIOC_STREAMON, &type)){perror("Uable to start capture");return -1;}printf("start capture ok\n");

在if语句后误加了;分号,导致if语句判断没有执行,而perror会一直执行

我是用Windows上的vscode通过ssh链接Ubuntu开发的,VScode没有报错且交叉编译也通过了,所以执行后一直报错Uable to start capture: Invalid argument

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

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

相关文章

Web前端开发——HTML快速入门

HTML&#xff1a;控制网页的结构CSS&#xff1a;控制网页的表现 一、什么是HTML、CSS &#xff08;1&#xff09;HTML &#xff08;HyperText Markup Languaqe&#xff1a;超文本标记语言&#xff09; 超文本&#xff1a;超越了文本的限制&#xff0c;比普通文本更强大。除了…

Aigtek高压功率放大器主要应用场景是什么

高压功率放大器是一种关键的电子设备&#xff0c;其主要功能是将低电压信号放大到较高电压水平&#xff0c;以满足特定应用的需求。这种类型的放大器在各种领域都发挥着至关重要的作用。安泰电子官网将为大家介绍高压功率放大器的主要应用场景&#xff0c;并介绍其在这些领域中…

关于Web开发的详细介绍

目录 一、什么是Web&#xff1f; 二、Web网站的工作流程和开发模式 &#xff08;1&#xff09;简单介绍 &#xff08;2&#xff09;工作流程 1、第一步 2、第二步 &#xff08;3&#xff09;Web网站的开发模式 1、前后端分离开发模式 ​编辑2、混合开发模式 三、开发W…

数据库设计 物理模型和逻辑模型

在数据库设计中&#xff0c;物理模型和逻辑模型是两个关键阶段&#xff0c;它们分别代表了数据库设计的不同层面和细节。以下是对这两个模型的详细解释及涉及到的内容&#xff1a; 逻辑模型&#xff08;Logical Data Model, LDM&#xff09; 定义与概述&#xff1a; 逻辑数据…

智慧矿山:EasyCVR助力矿井视频多业务融合及视频转发服务建设

一、方案背景 随着矿井安全生产要求的不断提高&#xff0c;视频监控、数据传输、通讯联络等业务的需求日益增长。为满足矿井生产管理的多元化需求&#xff0c;提高矿井作业的安全性和效率&#xff0c;TSINGSEE青犀EasyCVR视频汇聚/安防监控综合管理平台&#xff0c;旨在构建一…

一款优秀、亮眼的开源堡垒机

介绍 在运维的日常工作中&#xff0c;登陆服务器操作不可避免&#xff0c;为了更安全的管控服务器&#xff0c;但凡有点规模的公司都会上线堡垒机系统&#xff0c;堡垒机能够做到事前授权、事中监控、事后审计&#xff0c;同时也可以满足等保合规要求。 提到堡垒机&#xff0…

Go语言中的时间与日期处理:time包详解

在Go语言中&#xff0c;time包提供了丰富而强大的功能来处理时间和日期&#xff0c;这对于构建精确计时、定时任务、日期格式化等应用场景至关重要。本文将深入浅出地探讨time包的核心概念、常见问题、易错点及其规避策略&#xff0c;并通过实用代码示例加深理解。 一、时间与…

3D虚拟会议室打破传统会议局限,提供沉浸式会议体验

一、身临其境的虚拟会议体验 1、沉浸感提升参会效果 3D虚拟会议室借助虚拟现实技术为用户创造出一个仿佛置身真实会议场所的感觉。用户可以进入一个虚拟的会议室&#xff0c;感受到空间的深度和互动性。这种身临其境的体验&#xff0c;使得参会者不仅仅是被动地观看屏幕&…

音乐剪辑免费软件有哪些?7个音频剪辑技巧!

音乐剪辑免费软件有很多&#xff0c;但是适合自己或适合剪辑小白的却屈指可数。 音频剪辑软件千千万&#xff0c;如果是没有任何剪辑经验的小白用户&#xff0c;个人建议使用知名度较高的音频剪辑软件。不管是免费还是收费的音频剪辑软件&#xff0c;只要能够解决问题&#xf…

[Mysql] 的基础知识和sql 语句.教你速成(下)——数据库的约束篇

目录 前言 约束 一.我们为什么需要约束 二.常见的约束类型 NOT NULL 约束 UNIQUE 约束 DEFAULT 约束 PRIMARY KEY FOREIGN KEY CHECK约束 原因&#xff1a; 结尾 前言 距离上篇的更新已经快两周了,这个时候大伙都已经考完了吧!现在更新多少有点马后炮,但是没办法呀…

gin框架解决跨域问题

文章目录 前言一、使用github.com/gin-contrib/cors 前言 今天遇到了前后端跨域问题&#xff0c;前后端跨域解决蛮简单的&#xff0c;下面是解决方案 一、使用github.com/gin-contrib/cors go get github.com/gin-contrib/cors在路由的地方 r : gin.Default()corsConfig : c…

Spring源码十:BeanPostProcess

上一篇Spring源码九&#xff1a;BeanFactoryPostProcessor&#xff0c;我们看到ApplicationContext容器通过refresh方法中的postProcessBeanFactory方法和BeanFactoryPostProcessor类提供预留扩展点&#xff0c;他可以在Spring容器的层面对BeanFactroy或其他属性进行修改&#…

科技赋能智慧应急:“数字孪生+无人机”在防汛救灾中的应用

近期&#xff0c;全国多地暴雨持续&#xff0c;“麻辣王子工厂停工”“水上派出所成水上的派出所了”等相关词条冲上热搜&#xff0c;让人们看到了全国各地城市内涝、洪涝带来的严重灾情。暴雨带来的影响可见一斑&#xff0c;潜在的洪水、泥石流、山体滑坡等地质灾害更应提高警…

Keil Map文件分析

以前查看map&#xff0c;基本就是看一下Flash大小、和RAM总大小&#xff0c;或者是debug时确认下 函数编译地址。 最近心血来潮&#xff0c;想用C#做个上位机来解一下这个map文件&#xff0c;所以又回过头来关注下map文件具体格式和细节。 map文件的具体结构&#xff1a; 1、…

MYSQL的简易安装

先下载好安装包 官网&#xff1a;https://www.mysql.com 双击运行进入界面 打开之后将左侧的产品移到右侧 点击使用的产品设置路径 之后一直下一步即可 选择主机类型 同时要记住端口号 设置密码 设置系统服务列表中的服务名称 之后一直下一步就可以了 安装完成记得配置环…

解决前端登录成功之后,往后端发请求携带cookie问题

项目背景&#xff1a; 今天在做伙伴匹配系统&#xff1a; 我现在实现的功能是&#xff1a; 在我登录成功之后&#xff0c;就进入了主页&#xff08;默认页&#xff09;&#xff0c;在我访问用户页的时候产生的问题 首先说明一下这个Cookie的问题&#xff1a; 我们登录成功…

钽电容、电解电容、陶瓷电容的区别

电容是一种常见的电子元件&#xff0c;在电路中起着多种重要作用&#xff0c;并广泛应用于各种电子设备和系统中。 一、钽电容 1. 基本概述 钽电容&#xff0c;全称为钽电解电容器&#xff0c;是电解电容器的一种。它使用金属钽作为阳极&#xff0c;并在其表面形成一层五氧化…

Echarts折线图 自适应窗口大小

实现效果&#xff1a; 代码&#xff1a; <template><div class"echarts"><div class"select-box"><div v-for"(item,index) in trendList":key"index":class"[period item.id?active:,item]"click&…

2024微信小程序期末大作业-点奶茶微信小程序(后端nodejs-server)(附下载链接)_微信小程序期末大作业百度网盘下载

菜单展示 购物车展示&#xff1a; 提交订单&#xff1a; 支付详情页展示&#xff1a; 订单查看&#xff1a; 查看历史消费&#xff1a; 部分代码展示&#xff1a; <!--pages/home/home.wxml--> <block wx:for"{{listData}}" wx:key"itemlist&qu…

Python 项目依赖离线管理 pip + requirements.txt

背景 项目研发环境不支持联网&#xff0c;无法通过常规 pip install 来安装依赖&#xff0c;此时需要在联网设备下载依赖&#xff0c;然后拷贝到离线设备进行本地安装。 两台设备的操作系统、Python 版本尽可能一致。 离线安装依赖 # 在联网设备上安装项目所需的依赖 # -d …