Linux基于V4L2的视频捕捉

简介

linux环境使用V4l2实现摄像头捕捉,界面流畅播放并可以保存图片到本地。

代码

void VideoCapture::run()
{qDebug() << "VideoCapture start";// 打开设备int fd = open("/dev/video0", O_RDWR);if(fd < 0){qDebug("video设备打开失败\n");return;}else{qDebug("video设备打开成功\n");}//查看设备是否为视频采集设备struct v4l2_capability vcap;ioctl(fd, VIDIOC_QUERYCAP, &vcap);if (!(V4L2_CAP_VIDEO_CAPTURE & vcap.capabilities)){qDebug("No capture video device!\n");return;}// 枚举帧格式struct v4l2_fmtdesc fmtdesc;fmtdesc.index = 0;fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;qDebug("Video支持所有格式如下:");while(ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc) == 0){qDebug("v4l2_format %d:%s",fmtdesc.index, fmtdesc.description);fmtdesc.index++;}// 枚举分辨率struct v4l2_frmsizeenum frmsize;frmsize.index = 0;frmsize.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;qDebug("Video支持分辨率如下:");while(ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frmsize) == 0){qDebug("%d frame_size<%d*%d %d>", frmsize.index, frmsize.discrete.width, frmsize.discrete.height, frmsize.pixel_format);frmsize.index++;}// 枚举某分辨率下的帧速率int pixel_width = 1280;int pixel_height = 720;struct v4l2_frmivalenum frmival;frmival.index = 0;frmival.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;frmival.pixel_format = V4L2_PIX_FMT_MJPEG;frmival.width = pixel_width;frmival.height = pixel_height;while(ioctl(fd,VIDIOC_ENUM_FRAMEINTERVALS, &frmival) == 0){qDebug("<%d*%d> support frame_size %dfps", frmival.width, frmival.height, frmival.discrete.denominator / frmival.discrete.numerator);frmival.index++;}// 设置采集格式struct v4l2_format vfmt;vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;vfmt.fmt.pix.width = pixel_width;vfmt.fmt.pix.height = pixel_height;vfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;if(ioctl(fd, VIDIOC_S_FMT, &vfmt) < 0){qDebug("video设置格式失败\n");return;}// 检查设置参数是否生效if(ioctl(fd, VIDIOC_G_FMT, &vfmt) < 0){qDebug("video获取格式失败\n");return;}// 获取帧信息struct v4l2_streamparm streamparm;streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;ioctl(fd, VIDIOC_G_PARM, &streamparm);qDebug("current frameRate <%d * %d>\n", streamparm.parm.capture.timeperframe.numerator, streamparm.parm.capture.timeperframe.denominator);// 设置帧信息if(V4L2_CAP_TIMEPERFRAME & streamparm.parm.capture.capability){streamparm.parm.capture.timeperframe.numerator = 1;streamparm.parm.capture.timeperframe.denominator = 30;
//        if(ioctl(fd, VIDIOC_S_PARM, &streamparm) < 0)
//        {
//            qDebug("video设置帧率失败 <%d * %d>", streamparm.parm.capture.timeperframe.numerator, streamparm.parm.capture.timeperframe.denominator);
//        }}// 申请缓冲区空间struct v4l2_requestbuffers reqbuf;reqbuf.type  = V4L2_BUF_TYPE_VIDEO_CAPTURE;reqbuf.count = m_frameCount;reqbuf.memory = V4L2_MEMORY_MMAP;if(ioctl(fd, VIDIOC_REQBUFS, &reqbuf) < 0){qDebug("video申请缓冲区失败\n");return;}// 将帧缓冲映射到进程地址空间struct v4l2_buffer buf;buf.type   = V4L2_BUF_TYPE_VIDEO_CAPTURE;buf.memory = V4L2_MEMORY_MMAP;// 将每一帧对应的缓冲区的起始地址保存在m_userVideoBuf数组中,读取采集数据时,只需直接读取映射区即可for(buf.index=0; buf.index<m_frameCount; buf.index++){ioctl(fd, VIDIOC_QUERYBUF, &buf);m_userVideoBuf[buf.index] = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset);m_userVideoBufSize[buf.index] = buf.length;if(m_userVideoBuf[buf.index] == MAP_FAILED){qDebug("video mmap failed\n");return;}// 入队操作if(ioctl(fd, VIDIOC_QBUF, &buf) < 0){qDebug("入队失败\n");return;}}// 开始采集enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;if (ioctl(fd, VIDIOC_STREAMON, &type) < 0){qDebug("video开始采集失败");m_isRun = false;}//持续读取图像数据 使用select监听数据fd_set fds;struct timeval tv;tv.tv_sec  = 2;tv.tv_usec = 0;//图片文件缓存char *fileBuf = new char[3*1024*1024];while(m_isRun){FD_ZERO(&fds);FD_SET(fd, &fds);int ret = select(fd+1, &fds, NULL, NULL, &tv);if(ret < 0){qDebug("select io error\n");break;}// 读取帧struct v4l2_buffer readbuffer;readbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;readbuffer.memory = V4L2_MEMORY_MMAP;if(ioctl(fd, VIDIOC_DQBUF, &readbuffer) < 0){qDebug("读取帧失败\n");}//        qDebug() << QDateTime::currentDateTime().toString("hh:mm:ss:zzz");//重点:帧数据处理const uchar *data = (const uchar *)m_userVideoBuf[readbuffer.index];int length = readbuffer.length;//构造并显示QImage image = QImage::fromData(data, length);emit sigUpdateImage(image.copy());// 再次入队if(ioctl(fd, VIDIOC_QBUF, &readbuffer) < 0){qDebug("再次入队失败\n");}}// 停止采集if (ioctl(fd, VIDIOC_STREAMOFF, &type) < 0){qDebug("停止采集失败\n");}// 释放映射for(uint i=0; i<m_frameCount; i++){munmap(m_userVideoBuf[i], m_userVideoBufSize[i]);}//关闭文件emit sigUpdateImage(QImage());close(fd);delete[] fileBuf;qDebug() << "VideoCapture stop";
}

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

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

相关文章

告别暗黄,唤醒肌肤

&#x1f3ad; 想象一下&#xff0c;你的皮肤是舞台上的主角&#xff0c;但最近它似乎有些“疲惫”和“黯淡”&#xff0c;仿佛失去了往日的星光✨。别急&#xff0c;今天&#xff0c;我要为你揭秘一个能让肌肤重新焕发光彩的“魔法”——胶原蛋白&#xff01;&#x1f3a9; &a…

docker查看容器目录挂载

查看命令 docker inspect --format{{ json .Mounts }} <container_id_or_name> | jq 示例 docker inspect --format{{ json .Mounts }} af656ae540af | jq输出

Python知识点8---公共操作

提前说一点&#xff1a;如果你是专注于Python开发&#xff0c;那么本系列知识点只是带你入个门再详细的开发点就要去看其他资料了&#xff0c;而如果你和作者一样只是操作其他技术的Python API那就足够了。 Python的公共操作谁的是多种数据类型可共用的操作&#xff0c;且这些…

FreeRTOS笔记 - 二(正点原子)

一&#xff0c;任务创建和删除 具体的参数&#xff08;看视频&#xff09; 1&#xff0c;动态和静态创建的区别 动态: 任务的任务控制块以及任务的栈空间所需的内存&#xff0c;均由FreeRTOS从 FreeRTOS 管理的堆中分配。 静态: 任务的任务控制块以及任务的栈空间所需的内存&am…

vscode设置编辑器文件自动保存

步骤 1.打开vscode的设置 2.在搜索栏输入关键字“保存”&#xff1b; 在 Files: Auto Save 设置项&#xff0c;选择自动保存的模式

JavaScript中逻辑或(||)逻辑与()

在JavaScript中&#xff0c;||&#xff08;逻辑或&#xff09;和&&&#xff08;逻辑与&#xff09;是逻辑运算符&#xff0c;它们用于根据操作数的值来返回布尔值或执行短路求值&#xff08;short-circuit evaluation&#xff09;。 逻辑或&#xff08;||&#xff09;…

如何使用 PHP 函数进行网站性能监控和优化?

在构建一个高效、稳定的网站时&#xff0c;性能监控和优化是非常重要的一环。在 PHP 中&#xff0c;有许多内置函数和工具可以帮助我们实现网站的性能监控和优化。本文将介绍几种常用的 PHP 函数&#xff0c;并提供相应的代码示例&#xff0c;来帮助您更好地进行网站性能监控和…

java使用资源过高排查

在生产环境中有可能出现某java程序使用资源特别严重&#xff0c;这就需要找到该java进程&#xff0c;然后通过进程去找到是哪个线程的问题&#xff0c;这里我们就是用pidstat工具来排查一下 安装pidstat工具 yum -y install sysstat 查看java服务的pid jps 通过pid查看线…

C# WinForm —— 25 ProgressBar 介绍与使用

1. 简介 用于显示某个操作的进度 2. 常用属性 属性解释(Name)控件ID&#xff0c;在代码里引用的时候会用到,一般以 pbar 开头ContextMenuStrip右键菜单Enabled控件是否可用ForeColor用于显示进度的颜色MarqueeAnimationSpeed进度条动画更新的速度&#xff0c;以毫秒为单位M…

Python|OpenCV-自动检测并识别车牌号(16)

前言 本文是该专栏的第18篇,后面将持续分享OpenCV计算机视觉的干货知识,记得关注。 在本文中,笔者将详细介绍如何利用OpenCV进行车牌号识别。要知道,车牌号识别是计算机视觉在交通管理领域,以及车辆监控领域的一项重要应用。车牌号识别的主要目的,在于自动检测图像中的车…

M1芯片安装Dart Tips

如果按照 Get the Dart SDK | Dart 提供的方案就会出现 ➜ ~ brew tap dart-lang/dart > Tapping dart-lang/dart Cloning into /opt/homebrew/Library/Taps/dart-lang/homebrew-dart... ^C ➜ ~ brew tap dart-lang/dart > Tapping dart-lang/dart Cloning into /opt…

JZ2440笔记:DM9000C网卡驱动

在厂家提供的dm9dev9000c.c上修改&#xff0c; 1、注释掉#ifdef MODULE #endif 2、用模块化函数修饰入口出口函数 3、在dm9000c_init入口函数&#xff0c;增加iobase (int)ioremap(0x20000000,1024);irq IRQ_EINT7; 4、一路进入&#xff0c;在dmfe_probe1中注释掉if((db…

JavaWeb学习:在SSM框架中配置一个简单的监听器和过滤器

实现效果&#xff1a; 编写一个记录有多少个请求访问的监听器&#xff0c;通过面向全部访问路径的过滤器更新监听器中的visitCount次数。 监听器&#xff1a; WebListener public class VisitCounterListener implements ServletContextListener {private static final Strin…

经常用到的代码段

opencv opencv-图像部分 opencv显示图像 cv2.namedWindow("just for test", 0) cv2.imshow("just for test", index_img) cv2.waitKey(0)Opencv转PIL.Image Image.fromarray(cv2.cvtColor(cv_img,cv2.COLOR_BGR2RGB)) PIL.Image转Opencv cv2.cvtColor(…

chatgpt :怎样学c 指针

现在的感觉&#xff0c;要想学好程序&#xff0c;必须要想法能使用ChatGPT这个工具&#xff0c;它比任何老师和书籍都有用。比Google搜索都强。它给你的答案非常全面&#xff0c;可以作为全面知识的总结。 学习C语言中的指针可以提高你的编程能力和理解计算机内存管理的知识。…

CSAPP Lab08——Proxy Lab完成思路

蓝色的思念 突然演变成了阳光的夏天 空气中的温暖不会很遥远 ——被风吹过的夏天 完整代码见&#xff1a;CSAPP/proxylab-handout at main SnowLegend-star/CSAPP (github.com) Q&#xff1a;计算机网络中port的作用是什么&#xff1f; A&#xff1a;在计算机网络中&#xff…

qt中实现多语言功能

qt中实现多语言功能 原理&#xff1a; 其本质就是生成ts文件&#xff0c;然后使用Linguist软件手工翻译&#xff0c;再生成qm文件&#xff0c;最后在主程序的开始加载不同的qm文件&#xff0c;实现多语言。 步骤&#xff1a; 修改程序文件 在pro文件中加入说明 TRANSLATI…

Socket网络通讯入门(一)

提示&#xff1a;能力有限&#xff0c;不足以及错误之处还请指出&#xff01; 文章目录 前言一、 计算机网络 OSI、TCP/IP、五层协议 体系结构1.OSI七层模型每层的作用2.TCP/IP协议分成3.五层协议体系结构 二、Socket服务端和客户端 简单通信1.服务端代码2.客户端 总结 前言 简…

游戏软件与应用软件的区别

游戏软件和应用软件在功能、目标用户、使用场景以及设计理念上存在显著区别。以下是详细的比较&#xff1a; 功能和目的 游戏软件 娱乐性&#xff1a;游戏软件的主要目的是提供娱乐和休闲体验&#xff0c;用户通过互动、挑战和成就感获得乐趣。 交互性&#xff1a;通常具有…

vs - 在win10中安装vs2013update5

文章目录 vs - 在win10中安装vs2013update5概述笔记直接安装vs2013-update5报错先安装vs2013原版安装 vs2013 update5测试备注END vs - 在win10中安装vs2013update5 概述 用VS2019写的程序&#xff0c;在早期windows(e.g. win7, win8.1)上安装时&#xff0c;需要UCRT。 UCRT是…