音视频开发---linux下V4L2拍照

2024-06-16 14:18

本文主要是介绍音视频开发---linux下V4L2拍照,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 

目录

1. 流程说明

2. 代码说明

2.1 摄像头初始化

2.2 启动摄像头

2.3 拍照

2.4 停止摄像头

3. 参考链接


 

         V4L2(Video4linux2),是linux中关于视频设备的内核驱动。在Linux中,我们可以像访问普通文件一样对视频设备进行操作,V4L2也为我们在用户空间操作视频设备提供了一系列接口,使得应用程序可以使用统一的API操作不同的视频设备,极大简化了视频系统的开发和维护。本文基于一个拍照程序来介绍V4L2的使用。

1. 流程说明

        首先借用大神https://blog.csdn.net/eastmoon502136/article/details/8190262的一个流程图, 本人认为这个图还是很清晰的,就直接拿来了。

                  

      从流程图中也可以看出, 大部分操作都是借助ioctl来完成的, 我们更多需要关注的是调用合适的命令来完成相应的操作,涉及到的一些命令如下:

VIDIOC_REQBUFS:分配内存
VIDIOC_QUERYBUF:把VIDIOC_REQBUFS中分配的数据缓存转换成物理地址
VIDIOC_QUERYCAP:查询驱动功能
VIDIOC_ENUM_FMT:获取当前驱动支持的视频格式
VIDIOC_S_FMT:设置当前驱动的频捕获格式
VIDIOC_G_FMT:读取当前驱动的频捕获格式
VIDIOC_TRY_FMT:验证当前驱动的显示格式
VIDIOC_CROPCAP:查询驱动的修剪能力
VIDIOC_S_CROP:设置视频信号的边框
VIDIOC_G_CROP:读取视频信号的边框
VIDIOC_QBUF:把数据放回缓存队列
VIDIOC_DQBUF:把数据从缓存中读取出来
VIDIOC_STREAMON:开始视频显示函数
VIDIOC_STREAMOFF:结束视频显示函数
VIDIOC_QUERYSTD:检查当前视频设备支持的标准,例如PAL或NTSC。

2. 代码说明

2.1 摄像头初始化

int cameral_init()
{// open camera deviceint ret;if( (video_fd = open(VIDEO_DEV_NAME,O_RDWR)) == -1){printf("open %s failed.\n", VIDEO_DEV_NAME);return -1;}// ioctl VIDIOC_QUERYCAP, 查询驱动功能信息, 通过VIDIOC_QUERYCAP也能判断当前是支持V4L还是V4L2struct v4l2_capability cap;if(ioctl(video_fd,VIDIOC_QUERYCAP,&cap)==-1){printf("VIDIOC_QUERYCAP failed.\n");return -1;}printf("ioctl VIDIOC_QUERYCAP:\n");printf("\tv4l2_capability.driver:%s\n", cap.driver);printf("\tv4l2_capability.card:%s\n", cap.card);printf("\tv4l2_capability.bus_info:%s\n", cap.bus_info);printf("\tv4l2_capability.version:%d\n", cap.version);printf("\tv4l2_capability.capabilities:%x\n", cap.capabilities);printf("\tv4l2_capability.reserved:%x %x %x %x\n", cap.reserved[0],cap.reserved[1],cap.reserved[2],cap.reserved[3]);printf("\n\n");//设置格式struct v4l2_format  format ; format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE ; format.fmt.pix.width  = WIDTH; format.fmt.pix.height = HIGHT; format.fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG;//可通过函数ioctl_VIDIOC_ENUM_FMT来获取摄像头支持的格式,我这里获取的是Motion-JPEGret = ioctl(video_fd , VIDIOC_S_FMT , &format);if(ret != 0){printf("VIDIOC_S_FMT fail");return -1 ; }//获取当前格式, 从而可以判断设置操作是否成功.ioctl_VIDIOC_G_FMT();//申请bufferstruct v4l2_requestbuffers  requestbuffer ; requestbuffer.count = VIDEO_BUFFER_COUNT ; requestbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE ; requestbuffer.memory = V4L2_MEMORY_MMAP ; ret = ioctl(video_fd , VIDIOC_REQBUFS , &requestbuffer);if(ret != 0){printf("VIDIOC_REQBUFS fail\n");return -1  ;}printf("VIDIOC_REQBUFS  success.\n");struct v4l2_buffer buf; int i;for(i = 0 ; i < VIDEO_BUFFER_COUNT ; i++){buf.type =  V4L2_BUF_TYPE_VIDEO_CAPTURE ; buf.memory = V4L2_MEMORY_MMAP ; buf.index = i;//VIDIOC_QUERYBUF: 把VIDIOC_REQBUFS中分配的第i个数据缓存转换成物理地址if( (ret = ioctl(video_fd , VIDIOC_QUERYBUF , &buf)) != 0){printf("VIDIOC_QUERYBUF failed\n");return -1;}video_frame_length = buf.length;//将内核中的摄像头内存映射到用户空间,并返回用户空间的地址video_frame[i] = mmap(NULL,buf.length , PROT_READ | PROT_WRITE , MAP_SHARED , video_fd , buf.m.offset );//将缓冲区放入队列if( (ret = ioctl(video_fd , VIDIOC_QBUF , &buf)) != 0){printf("VIDIOC_REQBUFS failed\n");}}printf("camera init success\n");
}

 

2.2 启动摄像头

int cameral_start()
{//开启摄像头int ret ; int on = 1 ; ret = ioctl(video_fd , VIDIOC_STREAMON , &on);if(ret != 0){printf("cameral start fail\n");return -1 ; }return 0 ; 
}

2.3 拍照


void save_picture(char * frame, int frame_len)
{FILE *fp = fopen(PICTURE_FILE_NAME, "wb");if (fp < 0) {printf("open %s failed.\n",PICTURE_FILE_NAME);return ;}printf("open %s success.\n",PICTURE_FILE_NAME);fwrite(frame, 1, frame_len, fp);fclose(fp);printf("save %s success.\n",PICTURE_FILE_NAME); //%s, CAPTURE_FILE
}int take_picture()
{int ret;struct v4l2_buffer  dqbuf,qbuf; dqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE ; qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE ; dqbuf.memory = V4L2_MEMORY_MMAP ; qbuf.memory = V4L2_MEMORY_MMAP ; //从队列中取出一个缓冲区if( (ret = ioctl(video_fd , VIDIOC_DQBUF , &dqbuf)) != 0){printf("VIDIOC_DQBUF failed\n");return -1;}// 把数据保存成图片save_picture(video_frame[dqbuf.index], dqbuf.length);//把缓冲区还给队列qbuf.index = dqbuf.index;if( (ret = ioctl(video_fd , VIDIOC_QBUF , &qbuf)) != 0){printf("VIDIOC_QBUF failed\n");return -1;}return 0;
}

 

2.4 停止摄像头

int cameral_stop()
{//停止摄像头int ret ; int off= 1 ; ret = ioctl(video_fd , VIDIOC_STREAMOFF, &off);if(ret != 0){printf("cameral stop fail\n");return -1 ; }return 0 ;}

编译: gcc main.c

3. 参考链接

https://blog.csdn.net/eastmoon502136/article/details/8190262

https://blog.csdn.net/morixinguan/article/details/51001713

代码下载:https://download.csdn.net/download/u011734326/11191689

 

这篇关于音视频开发---linux下V4L2拍照的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1066673

相关文章

防止Linux rm命令误操作的多场景防护方案与实践

《防止Linuxrm命令误操作的多场景防护方案与实践》在Linux系统中,rm命令是删除文件和目录的高效工具,但一旦误操作,如执行rm-rf/或rm-rf/*,极易导致系统数据灾难,本文针对不同场景... 目录引言理解 rm 命令及误操作风险rm 命令基础常见误操作案例防护方案使用 rm编程 别名及安全删除

Linux下MySQL数据库定时备份脚本与Crontab配置教学

《Linux下MySQL数据库定时备份脚本与Crontab配置教学》在生产环境中,数据库是核心资产之一,定期备份数据库可以有效防止意外数据丢失,本文将分享一份MySQL定时备份脚本,并讲解如何通过cr... 目录备份脚本详解脚本功能说明授权与可执行权限使用 Crontab 定时执行编辑 Crontab添加定

SpringBoot 多环境开发实战(从配置、管理与控制)

《SpringBoot多环境开发实战(从配置、管理与控制)》本文详解SpringBoot多环境配置,涵盖单文件YAML、多文件模式、MavenProfile分组及激活策略,通过优先级控制灵活切换环境... 目录一、多环境开发基础(单文件 YAML 版)(一)配置原理与优势(二)实操示例二、多环境开发多文件版

使用docker搭建嵌入式Linux开发环境

《使用docker搭建嵌入式Linux开发环境》本文主要介绍了使用docker搭建嵌入式Linux开发环境,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录1、前言2、安装docker3、编写容器管理脚本4、创建容器1、前言在日常开发全志、rk等不同

Python实战之SEO优化自动化工具开发指南

《Python实战之SEO优化自动化工具开发指南》在数字化营销时代,搜索引擎优化(SEO)已成为网站获取流量的重要手段,本文将带您使用Python开发一套完整的SEO自动化工具,需要的可以了解下... 目录前言项目概述技术栈选择核心模块实现1. 关键词研究模块2. 网站技术seo检测模块3. 内容优化分析模

linux系统上安装JDK8全过程

《linux系统上安装JDK8全过程》文章介绍安装JDK的必要性及Linux下JDK8的安装步骤,包括卸载旧版本、下载解压、配置环境变量等,强调开发需JDK,运行可选JRE,现JDK已集成JRE... 目录为什么要安装jdk?1.查看linux系统是否有自带的jdk:2.下载jdk压缩包2.解压3.配置环境

Linux搭建ftp服务器的步骤

《Linux搭建ftp服务器的步骤》本文给大家分享Linux搭建ftp服务器的步骤,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录ftp搭建1:下载vsftpd工具2:下载客户端工具3:进入配置文件目录vsftpd.conf配置文件4:

Linux实现查看某一端口是否开放

《Linux实现查看某一端口是否开放》文章介绍了三种检查端口6379是否开放的方法:通过lsof查看进程占用,用netstat区分TCP/UDP监听状态,以及用telnet测试远程连接可达性... 目录1、使用lsof 命令来查看端口是否开放2、使用netstat 命令来查看端口是否开放3、使用telnet

基于Java开发一个极简版敏感词检测工具

《基于Java开发一个极简版敏感词检测工具》这篇文章主要为大家详细介绍了如何基于Java开发一个极简版敏感词检测工具,文中的示例代码简洁易懂,感兴趣的小伙伴可以跟随小编一起学习一下... 目录你是否还在为敏感词检测头疼一、极简版Java敏感词检测工具的3大核心优势1.1 优势1:DFA算法驱动,效率提升10

Linux系统管理与进程任务管理方式

《Linux系统管理与进程任务管理方式》本文系统讲解Linux管理核心技能,涵盖引导流程、服务控制(Systemd与GRUB2)、进程管理(前台/后台运行、工具使用)、计划任务(at/cron)及常用... 目录引言一、linux系统引导过程与服务控制1.1 系统引导的五个关键阶段1.2 GRUB2的进化优