V4L2框架学习

article/2025/9/29 16:15:04

V4L2框架

在这里插入图片描述
在这里插入图片描述

0 查看videodev2

0.1 头文件/usr/include/linux/videodev2.h

在这里插入图片描述

0.2 使用ioctl函数

在这里插入图片描述

使用ioctl函数

// 添加头文件
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>int ioctl (int __fd, unsigned long int __request, ...) 
  • 查看对于结构

/usr/include/linux/videodev2.h

在这里插入图片描述

1打开设备

1.1 查看设备

ls /dev/v*

在这里插入图片描述

1.2 打开摄像头

cheese

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Nw2ylFwy-1666608237389)(D:\Slam\文档\V4L2框架.assets\image-20221024002758756.png)]

video_step1.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{//1.打开设备int fd = open("/dev/video0", O_RDWR);if(fd < 0){perror("打开设备失败");return -1;}printf("打开设备成功");//9.关闭设备close(fd);return 0;
}

2.配置支持格式

获取摄像头格式的命令 :VIDEOC_ENUM_FMT,

对应存储格式的结构体 :v4l2_fmtdesc

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
int main(void)
{//1.打开设备int fd = open("/dev/video0", O_RDWR);if(fd < 0){perror("打开设备失败");return -1;}//2.获取摄像头支持的格式ioctl(文件描述符, 命令, 与命令对应的结构体)struct v4l2_fmtdesc v4fmt;v4fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;int i=0;while(1){v4fmt.index = i++;  int ret = ioctl(fd, VIDIOC_ENUM_FMT, &v4fmt);if(ret < 0){perror("获取失败");break;}printf("index=%d\n", v4fmt.index);printf("flags=%d\n", v4fmt.flags);printf("description=%s\n", v4fmt.description);unsigned char *p = (unsigned char *)&v4fmt.pixelformat;printf("pixelformat=%c%c%c%c\n", p[0],p[1],p[2],p[3]);printf("reserved=%d\n", v4fmt.reserved[0]);printf("--------------------------------------------\n");}//9.关闭设备close(fd);return 0;
}

可以才看到配置

在这里插入图片描述

3、配置摄像头采集格式

配置摄像头采集格式的命令 :VIDIOC_S_FMT ,

对应存储格式的结构体 :v4l2_format

  • 结构体v4l2_format格式
    在这里插入图片描述
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
#include <string.h>int main(void)
{//1.打开设备int fd = open("/dev/video0", O_RDWR);if(fd < 0){perror("打开设备失败");return -1;}//3.设置采集格式struct v4l2_format vfmt;vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;//摄像头采集vfmt.fmt.pix.width = 640;//设置宽(不能任意) vfmt.fmt.pix.height = 480;//设置高//设置视频采集格式 ,根据自己的摄像头配置vfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;int ret = ioctl(fd, VIDIOC_S_FMT, &vfmt);if(ret < 0){perror("设置格式失败");}//结构体清空memset(&vfmt, 0, sizeof(vfmt));//获取配置vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;ret  = ioctl(fd, VIDIOC_G_FMT, &vfmt);if(ret < 0){perror("获取格式失败");}if(vfmt.fmt.pix.width == 640 && vfmt.fmt.pix.height == 480 && vfmt.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV){printf("设置成功\n");}else{printf("设置失败\n");}//9.关闭设备close(fd);return 0;
}

4.申请内核缓冲区队列

申请内核缓冲区队列的命令 : VIDIOC_REQBUFS ,

对应存储格式的结构体 : v4l2_requestbuffers

在这里插入图片描述

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
#include <string.h>int main(void)
{//1.打开设备int fd = open("/dev/video0", O_RDWR);if(fd < 0){perror("打开设备失败");return -1;}//3.设置采集格式struct v4l2_format vfmt;vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;//摄像头采集vfmt.fmt.pix.width = 640;//设置宽(不能任意)vfmt.fmt.pix.height = 480;//设置高vfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;//设置视频采集格式int ret = ioctl(fd, VIDIOC_S_FMT, &vfmt);if(ret < 0){perror("设置格式失败");}//4.申请内核空间struct v4l2_requestbuffers reqbuffer;reqbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;reqbuffer.count = 4; //申请4个缓冲区reqbuffer.memory = V4L2_MEMORY_MMAP ;//映射方式ret  = ioctl(fd, VIDIOC_REQBUFS, &reqbuffer);if(ret < 0){perror("申请队列空间失败");}else{printf("申请队列空间成功");}//9.关闭设备close(fd);return 0;
}

5.把内核的缓冲区队列映射到用户空间

队列映射到用户空间的命令 : VIDIOC_QUERYBUF , VIDIOC_QBUF

对应存储格式的结构体 : v4l2_buffer
在这里插入图片描述

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
#include <string.h>
#include <sys/mman.h>int main(void)
{//1.打开设备int fd = open("/dev/video0", O_RDWR);if(fd < 0){perror("打开设备失败");return -1;}//3.设置采集格式struct v4l2_format vfmt;vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;//摄像头采集vfmt.fmt.pix.width = 640;//设置宽(不能任意)vfmt.fmt.pix.height = 480;//设置高vfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;//设置视频采集格式int ret = ioctl(fd, VIDIOC_S_FMT, &vfmt);if(ret < 0){perror("设置格式失败");}//4.申请内核空间struct v4l2_requestbuffers reqbuffer;reqbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;reqbuffer.count = 4; //申请4个缓冲区reqbuffer.memory = V4L2_MEMORY_MMAP ;//映射方式ret  = ioctl(fd, VIDIOC_REQBUFS, &reqbuffer);if(ret < 0){perror("申请队列空间失败");}//5.映射unsigned char *mptr[4];//保存映射后用户空间的首地址unsigned int  size[4];struct v4l2_buffer mapbuffer;//初始化type, indexmapbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;for(int i=0; i<4; i++){mapbuffer.index = i;ret = ioctl(fd, VIDIOC_QUERYBUF, &mapbuffer);//从内核空间中查询一个空间做映射if(ret < 0){perror("查询内核空间队列失败");}mptr[i] = (unsigned char *)mmap(NULL, mapbuffer.length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, mapbuffer.m.offset);size[i]=mapbuffer.length;//通知使用完毕--‘放回去’ret  = ioctl(fd, VIDIOC_QBUF, &mapbuffer);if(ret < 0){perror("放回失败");}}//9.关闭设备close(fd);return 0;
}

6 开始采集,停止采集,释放映射

采集的命令 :

  • VIDIOC_STREAMON(开始采集写数据到队列中)
  • VIDIOC_DQBUF(告诉内核我要某一个数据,内核不可以修改)
  • VIDIOC_QBUF(告诉内核我已经使用完毕)
  • VIDIOC_STREAMOFF(停止采集-不在向队列中写数据)

在这里插入图片描述

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
#include <string.h>
#include <sys/mman.h>int main(void)
{//1.打开设备int fd = open("/dev/video0", O_RDWR);if(fd < 0){perror("打开设备失败");return -1;}//3.设置采集格式struct v4l2_format vfmt;vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;//摄像头采集vfmt.fmt.pix.width = 640;//设置宽(不能任意)vfmt.fmt.pix.height = 480;//设置高vfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;//设置视频采集格式int ret = ioctl(fd, VIDIOC_S_FMT, &vfmt);if(ret < 0){perror("设置格式失败");}//4.申请内核空间struct v4l2_requestbuffers reqbuffer;reqbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;reqbuffer.count = 4; //申请4个缓冲区reqbuffer.memory = V4L2_MEMORY_MMAP ;//映射方式ret  = ioctl(fd, VIDIOC_REQBUFS, &reqbuffer);if(ret < 0){perror("申请队列空间失败");}//5.映射unsigned char *mptr[4];//保存映射后用户空间的首地址unsigned int  size[4];struct v4l2_buffer mapbuffer;//初始化type, indexmapbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;for(int i=0; i<4; i++){mapbuffer.index = i;ret = ioctl(fd, VIDIOC_QUERYBUF, &mapbuffer);//从内核空间中查询一个空间做映射if(ret < 0){perror("查询内核空间队列失败");}mptr[i] = (unsigned char *)mmap(NULL, mapbuffer.length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, mapbuffer.m.offset);size[i]=mapbuffer.length;//通知使用完毕--‘放回去’ret  = ioctl(fd, VIDIOC_QBUF, &mapbuffer);if(ret < 0){perror("放回失败");}}//6.开始采集int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;ret = ioctl(fd, VIDIOC_STREAMON, &type);if(ret < 0){perror("开启失败");}//从队列中提取一帧数据struct v4l2_buffer  readbuffer;readbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;ret = ioctl(fd, VIDIOC_DQBUF, &readbuffer);if(ret < 0){perror("提取数据失败");}FILE *file=fopen("my.jpg", "w+");//mptr[readbuffer.index]fwrite(mptr[readbuffer.index], readbuffer.length, 1, file);fclose(file);//通知内核已经使用完毕ret = ioctl(fd, VIDIOC_QBUF, &readbuffer);if(ret < 0){perror("放回队列失败");}//停止采集ret = ioctl(fd, VIDIOC_STREAMOFF, &type);//释放映射for(int i=0; i<4; i)munmap(mptr[i], size[i]);//9.关闭设备close(fd);return 0;
}

V4L2框架

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FqvRWjxh-1666608345812)(D:\Slam\文档\V4L2框架.assets\image-20221022154652055.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5JKfpjoW-1666608345814)(D:\Slam\文档\V4L2框架.assets\image-20221023222816576.png)]

0 查看videodev2

0.1 头文件/usr/include/linux/videodev2.h

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DL45KmnX-1666608345816)(D:\Slam\文档\V4L2框架.assets\image-20221024003546390.png)]

0.2 使用ioctl函数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w3WdXvBY-1666608345817)(https://note.youdao.com/yws/public/resource/7c4c0e28888d03ec70d339118c374edb/xmlnote/8D211CB4C14A49C9AD1E4F4214996D25/44230)]

使用ioctl函数

// 添加头文件
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>int ioctl (int __fd, unsigned long int __request, ...) 
  • 查看对于结构

/usr/include/linux/videodev2.h

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QSVYnUY3-1666608345818)(D:\Slam\文档\V4L2框架.assets\image-20221023225848269.png)]

1打开设备

1.1 查看设备

ls /dev/v*

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dg8qfENM-1666608345820)(D:\Slam\文档\V4L2框架.assets\image-20221024002629205.png)]

1.2 打开摄像头

cheese

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V8ndV3hD-1666608345821)(D:\Slam\文档\V4L2框架.assets\image-20221024002758756.png)]

video_step1.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{//1.打开设备int fd = open("/dev/video0", O_RDWR);if(fd < 0){perror("打开设备失败");return -1;}printf("打开设备成功");//9.关闭设备close(fd);return 0;
}

2.配置支持格式

获取摄像头格式的命令 :VIDEOC_ENUM_FMT,

对应存储格式的结构体 :v4l2_fmtdesc

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
int main(void)
{//1.打开设备int fd = open("/dev/video0", O_RDWR);if(fd < 0){perror("打开设备失败");return -1;}//2.获取摄像头支持的格式ioctl(文件描述符, 命令, 与命令对应的结构体)struct v4l2_fmtdesc v4fmt;v4fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;int i=0;while(1){v4fmt.index = i++;  int ret = ioctl(fd, VIDIOC_ENUM_FMT, &v4fmt);if(ret < 0){perror("获取失败");break;}printf("index=%d\n", v4fmt.index);printf("flags=%d\n", v4fmt.flags);printf("description=%s\n", v4fmt.description);unsigned char *p = (unsigned char *)&v4fmt.pixelformat;printf("pixelformat=%c%c%c%c\n", p[0],p[1],p[2],p[3]);printf("reserved=%d\n", v4fmt.reserved[0]);printf("--------------------------------------------\n");}//9.关闭设备close(fd);return 0;
}

可以才看到配置

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AoPEWQ7F-1666608345822)(D:\Slam\文档\V4L2框架.assets\image-20221024002117533.png)]

3、配置摄像头采集格式

配置摄像头采集格式的命令 :VIDIOC_S_FMT ,

对应存储格式的结构体 :v4l2_format

  • 结构体v4l2_format格式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oqoCmlMw-1666608345824)(D:\Slam\文档\V4L2框架.assets\image-20221024003236175.png)]

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
#include <string.h>int main(void)
{//1.打开设备int fd = open("/dev/video0", O_RDWR);if(fd < 0){perror("打开设备失败");return -1;}//3.设置采集格式struct v4l2_format vfmt;vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;//摄像头采集vfmt.fmt.pix.width = 640;//设置宽(不能任意) vfmt.fmt.pix.height = 480;//设置高//设置视频采集格式 ,根据自己的摄像头配置vfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;int ret = ioctl(fd, VIDIOC_S_FMT, &vfmt);if(ret < 0){perror("设置格式失败");}//结构体清空memset(&vfmt, 0, sizeof(vfmt));//获取配置vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;ret  = ioctl(fd, VIDIOC_G_FMT, &vfmt);if(ret < 0){perror("获取格式失败");}if(vfmt.fmt.pix.width == 640 && vfmt.fmt.pix.height == 480 && vfmt.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV){printf("设置成功\n");}else{printf("设置失败\n");}//9.关闭设备close(fd);return 0;
}

4.申请内核缓冲区队列

申请内核缓冲区队列的命令 : VIDIOC_REQBUFS ,

对应存储格式的结构体 : v4l2_requestbuffers

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BGS10VfN-1666608345825)(D:\Slam\文档\V4L2框架.assets\image-20221024163914484.png)]

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
#include <string.h>int main(void)
{//1.打开设备int fd = open("/dev/video0", O_RDWR);if(fd < 0){perror("打开设备失败");return -1;}//3.设置采集格式struct v4l2_format vfmt;vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;//摄像头采集vfmt.fmt.pix.width = 640;//设置宽(不能任意)vfmt.fmt.pix.height = 480;//设置高vfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;//设置视频采集格式int ret = ioctl(fd, VIDIOC_S_FMT, &vfmt);if(ret < 0){perror("设置格式失败");}//4.申请内核空间struct v4l2_requestbuffers reqbuffer;reqbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;reqbuffer.count = 4; //申请4个缓冲区reqbuffer.memory = V4L2_MEMORY_MMAP ;//映射方式ret  = ioctl(fd, VIDIOC_REQBUFS, &reqbuffer);if(ret < 0){perror("申请队列空间失败");}else{printf("申请队列空间成功");}//9.关闭设备close(fd);return 0;
}

5.把内核的缓冲区队列映射到用户空间

队列映射到用户空间的命令 : VIDIOC_QUERYBUF , VIDIOC_QBUF

对应存储格式的结构体 : v4l2_buffer

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Mz8xX0C1-1666608345827)(D:\Slam\文档\V4L2框架.assets\image-20221024163857963.png)]

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
#include <string.h>
#include <sys/mman.h>int main(void)
{//1.打开设备int fd = open("/dev/video0", O_RDWR);if(fd < 0){perror("打开设备失败");return -1;}//3.设置采集格式struct v4l2_format vfmt;vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;//摄像头采集vfmt.fmt.pix.width = 640;//设置宽(不能任意)vfmt.fmt.pix.height = 480;//设置高vfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;//设置视频采集格式int ret = ioctl(fd, VIDIOC_S_FMT, &vfmt);if(ret < 0){perror("设置格式失败");}//4.申请内核空间struct v4l2_requestbuffers reqbuffer;reqbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;reqbuffer.count = 4; //申请4个缓冲区reqbuffer.memory = V4L2_MEMORY_MMAP ;//映射方式ret  = ioctl(fd, VIDIOC_REQBUFS, &reqbuffer);if(ret < 0){perror("申请队列空间失败");}//5.映射unsigned char *mptr[4];//保存映射后用户空间的首地址unsigned int  size[4];struct v4l2_buffer mapbuffer;//初始化type, indexmapbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;for(int i=0; i<4; i++){mapbuffer.index = i;ret = ioctl(fd, VIDIOC_QUERYBUF, &mapbuffer);//从内核空间中查询一个空间做映射if(ret < 0){perror("查询内核空间队列失败");}mptr[i] = (unsigned char *)mmap(NULL, mapbuffer.length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, mapbuffer.m.offset);size[i]=mapbuffer.length;//通知使用完毕--‘放回去’ret  = ioctl(fd, VIDIOC_QBUF, &mapbuffer);if(ret < 0){perror("放回失败");}}//9.关闭设备close(fd);return 0;
}

6 开始采集,停止采集,释放映射

采集的命令 :

  • VIDIOC_STREAMON(开始采集写数据到队列中)
  • VIDIOC_DQBUF(告诉内核我要某一个数据,内核不可以修改)
  • VIDIOC_QBUF(告诉内核我已经使用完毕)
  • VIDIOC_STREAMOFF(停止采集-不在向队列中写数据)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uxfBpLo6-1666608345829)(D:\Slam\文档\V4L2框架.assets\image-20221024153801352.png)]

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
#include <string.h>
#include <sys/mman.h>int main(void)
{//1.打开设备int fd = open("/dev/video0", O_RDWR);if(fd < 0){perror("打开设备失败");return -1;}//3.设置采集格式struct v4l2_format vfmt;vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;//摄像头采集vfmt.fmt.pix.width = 640;//设置宽(不能任意)vfmt.fmt.pix.height = 480;//设置高vfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;//设置视频采集格式int ret = ioctl(fd, VIDIOC_S_FMT, &vfmt);if(ret < 0){perror("设置格式失败");}//4.申请内核空间struct v4l2_requestbuffers reqbuffer;reqbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;reqbuffer.count = 4; //申请4个缓冲区reqbuffer.memory = V4L2_MEMORY_MMAP ;//映射方式ret  = ioctl(fd, VIDIOC_REQBUFS, &reqbuffer);if(ret < 0){perror("申请队列空间失败");}//5.映射unsigned char *mptr[4];//保存映射后用户空间的首地址unsigned int  size[4];struct v4l2_buffer mapbuffer;//初始化type, indexmapbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;for(int i=0; i<4; i++){mapbuffer.index = i;ret = ioctl(fd, VIDIOC_QUERYBUF, &mapbuffer);//从内核空间中查询一个空间做映射if(ret < 0){perror("查询内核空间队列失败");}mptr[i] = (unsigned char *)mmap(NULL, mapbuffer.length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, mapbuffer.m.offset);size[i]=mapbuffer.length;//通知使用完毕--‘放回去’ret  = ioctl(fd, VIDIOC_QBUF, &mapbuffer);if(ret < 0){perror("放回失败");}}//6.开始采集int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;ret = ioctl(fd, VIDIOC_STREAMON, &type);if(ret < 0){perror("开启失败");}//从队列中提取一帧数据struct v4l2_buffer  readbuffer;readbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;ret = ioctl(fd, VIDIOC_DQBUF, &readbuffer);if(ret < 0){perror("提取数据失败");}FILE *file=fopen("my.jpg", "w+");//mptr[readbuffer.index]fwrite(mptr[readbuffer.index], readbuffer.length, 1, file);fclose(file);//通知内核已经使用完毕ret = ioctl(fd, VIDIOC_QBUF, &readbuffer);if(ret < 0){perror("放回队列失败");}//停止采集ret = ioctl(fd, VIDIOC_STREAMOFF, &type);//释放映射for(int i=0; i<4; i)munmap(mptr[i], size[i]);//9.关闭设备close(fd);return 0;
}

http://chatgpt.dhexx.cn/article/I70BotZe.shtml

相关文章

V4L2介绍

V4L2介绍 V4L2介绍主要功能框架v4L2编程 V4L2介绍 V4L2是Video for linux2的简称,为linux中关于视频设备的内核驱动。在Linux中&#xff0c;视频设备是设备文件&#xff0c;可以像访问普通文件一样对其进行读写&#xff0c;摄像头在/dev/video*下&#xff0c;如果只有一个视频…

linux V4L2子系统——v4l2架构(7)之V4L2应用编程

linux V4L2子系统——v4l2架构&#xff08;7&#xff09;之V4L2应用编程 备注&#xff1a;   1. Kernel版本&#xff1a;5.4   2. 使用工具&#xff1a;Source Insight 4.0   3. 参考博客&#xff1a; &#xff08;1&#xff09;Linux V4L2子系统-应用层访问video设备&a…

[2022.8.15]v4l2-ctl基本使用方法

v4l2-ctl使用帮助可以参考&#xff1a;https://www.mankier.com/1/v4l2-ctl 1 v4l2-ctl --list-devices 列出所有设备 USB 2.0 Camera: USB Camera (usb-0000:00:14.0-9):/dev/video0/dev/video1 一个USB camera对应两个设备&#xff1a;一个是图像/视频采集&#xff0c;一…

V4L2应用层分析

V4L2应用层分析 一、总述二、例子 一、总述 V4L2&#xff0c;即Video for Linux 2&#xff0c;是第二代为Linux打造的音频、视频驱动。相比第一代V4L&#xff0c;V4L2支持更多的设备&#xff0c;同时更加稳定。现今的视频设备&#xff0c;如USB摄像头&#xff0c;基本都支持V4…

v4l2数据结构分析

v4l2数据结构分析 文章目录 v4l2数据结构分析Video4Linux2设备v4l2_device媒体设备media_deviceVideo4Linux2子设备v4l2_subdevVideo4Linux2子设备的操作集v4l2_subdev_opsVideo4Linux2子设备的内部操作集v4l2_subdev_internal_opsVideo4Linux2控制处理器v4l2_ctrl_handlerVide…

摄像头V4L2编程应用开发

1.V4L2简介 Video for Linux two(Video4Linux2)简称V4L2&#xff0c;是V4L的改进版。V4L2是linux系统操作系统下一套用于采集图片、视频、和音视频数据的通用API接口&#xff0c;配合适当的视频采集设备和相应的驱动程序&#xff0c;可以实现图片、视频、音频等的采集。 在linu…

V4L2框架

前言 在分析v4l2之前最好具有的知识&#xff1a; 1.字符设备,因为v4l2是被枚举为字符设备。 2.内存分配和映射,比如相关数据结构的分配和buffer。 3.DMA&#xff0c;因为v4l2的数据传输用到了DMA。 4.I2C&#xff0c;因为很多传感器都是用的i2c接口。 5.文件系统的基本操作&am…

V4L2系列 之 V4L2驱动框架

目录 前言一、V4L2驱动框架概览1、应用层 -》中间层-》驱动层2、主要代码文件(Linux 4.19版本内核) 二、怎么写V4L2驱动1、如何写一个设备的驱动&#xff1f;2、Video设备主要结构体3、怎么写V4L2驱动 三、V4L2的调试工具1、v4l2-ctl2、dev_debug3、v4l2-compliance 前言 本篇文…

V4L2框架概述

原文链接 本文开启 linux 内核 V4L2 框架部分的学习之旅&#xff0c;本文仅先对 V4L2 的框架做一个综述性的概括介绍&#xff0c;然后接下来的文章中会对 V4L2 框架的各个子模块进行一个全面的介绍&#xff0c;包括每一部分的实现原理&#xff0c;如何使用&#xff0c;用在什么…

V4l2框架分析

Table of Contents 1.V4L2框架概述 1.1 v4l2设备应用层流程 1.2 内核V4L2模块 1.2.1 video_device 1.2.2 v4l2_subdev 1.2.3 videobuf2 2. video_device结构体 2.1 图像处理模块 2.2 video_device处理流程 2.2.1 video_device 结构体成员介绍: 3. video_buf2 3.1 …

V4L2

V4L2(video 4 linux 2) V4L2有一段历史了。大约在1998的秋天&#xff0c;它的光芒第一次出现在Bill Dirks 的眼中。经过长足的发展&#xff0c;它于2002年11 月&#xff0c;发布2.5.46 时&#xff0c;融入了内核主干之中。然而直到今天&#xff0c;仍有一部分内核驱不支持新的A…

V4L2简介

http://work-blog.readthedocs.org/en/latest/v4l2%20intro.html 第一章 V4L2简介 1.1、什么是v4l2 V4L2&#xff08;Video4Linux的缩写&#xff09;是Linux下关于视频采集相关设备的驱动框架&#xff0c;为驱动和应用程序提供了一套统一的接口规范。 V4L2支持的设备十分广泛&…

我们一起学linux之V4L2摄像头应用流程

一、概述 Video for Linuxtwo(Video4Linux2)简称V4L2&#xff0c;是V4L的改进版。V4L2是linux操作系统下用于采集图片、视频和音频数据的API接口&#xff0c;配合适当的视频采集设备和相应的驱动程序&#xff0c;可以实现图片、视频、音频等的采集。在远程会议、可视电话、视频…

深入学习Linux摄像头(一)v4l2应用编程

深入学习Linux摄像头&#xff08;一&#xff09;v4l2应用编程 一、什么是v4l2 二、v4l2 API介绍 2.1 Querying Capabilities 2.2 Application Priority 2.3 Device Inputs and Outputs 2.4 Video Standards 2.5 Camera Control Reference 2.6 Image Format 2.7 Cropping, compo…

V4L2驱动框架详解

1. V4L2框架概述 1.1 v4l2设备应用层流程 1.2 内核V4L2模块 2 2. video_device 2.1图像处理模块 2.2 video注册流程 3. videobuf2 3.1 与video device的关系: 3.2 buffer类型 3.3 vb2_ops回调函数 3.4 mmap 流程 4. Subdev 4.1 概念 4.2 subdev注册流程 5. media fra…

html背景自动适应,css背景图片如何自适应?

css可以使用background-size属性设置背景图片自适应&#xff0c;为背景图片设置background-size:cover;样式即可使背景图片自适应。 css可以使用background-size属性设置背景图片自适应。background-size属性规定背景图像的尺寸。 background-size属性&#xff1a; 语法&#x…

css实现图片自适应容器的几种方式

css实现图片自适应容器 经常有这样一个场景,需要让图片自适应容器的大小。 1、img标签的方式 我们马上就能想到,把width、height 设置为100%啊。来看一哈效果。 <div class=div1><img src="./peiqi.png" alt=""> </div>.div1 {widt…

css 背景图片自适应属性整理

本篇博客主要记录一些使用 css 对背景图片自适应的操作整合 背景图片取消重复 background-image: url(image.jpg); background-repeat:no-repeat;修改前 修改后 背景图片固定&#xff08;不会随着内容滚动而改变位置&#xff09; background-image: url(image.jpg); back…

CSS实现图片自适应布局

CSS实现图片自适应布局 最轻松的写法 <div class"container">// 这里图片尺寸为440X440像素&#xff0c;<img src"./images/medium.jpg" alt"test"> </div><style>.container {width: 600px;height: 600px;border: 1p…