Skip to content

Latest commit

 

History

History
executable file
·
65 lines (35 loc) · 3.12 KB

v4l2流程.md

File metadata and controls

executable file
·
65 lines (35 loc) · 3.12 KB

折腾了一天,总算弄好了:),就简单记录一下遇到的一些问题吧。

首先,可以通过 ls /dev | grep video 来查看相机设备有哪些。

但这里有一个大坑,每个实体相机会有两个/dev/video*文件,如/dev/video0 和/dev/video1, 然而其中只有一个可以用来读取视频信息。

解决方案是v4l2-ctl -d /dev/video0 --all (把0换成其他数字),它会列出设备的具体信息,包括支持的格式。对于可用的和不可用的设备文件,该命令的输出完全不同,可以自己试试。

具体的流程如下图所示(来自V4L2框架解析|极客笔记)

V4L2流程简介

  1. 打开设备

    要注意使用上面说的可用的设备,我就因为这个浪费了一个上午,emo

    open("/dev/video0", O_RDWR | O_NONBLOCK);

        还有这里打开的模式O_RDWR要和mmap中的模式一样, 否则会出现Permission error. 为什么要O_NONBLOCK4.讲帧缓冲区入队, 出队

    2. 查看并设置设备

        可以用ioctl VIDIOC_QUERYCAP来查看设备能力, VIDIOC_ENUM_FMT 来查看支持的格式,其实信息都在v4l2-ctl -d /dev/video0     --all里了。只是个可选项!

        这一步中最主要的是用ioctl VIDIOC_S_FMT 来设置输出的宽度,高度,文件格式(一般只有V4L2_PIX_FMT_JPEGV4L2_PIX_FMT_YYUV. IMPORTANT, 这个设置不一定会生效,若设置了不支持的值,则会使用默认值!所以之后要VIDIOC_G_FMT 获取设置来查看是否成功

 struct v4l2_format fmt;
 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;      /*v4l2_buf_typea,camera must use V4L2_BUF_TYPE_VIDEO_CAPTURE*/
 fmt.fmt.pix.width = 640;
 fmt.fmt.pix.height = 480;
 fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG;	/*V4L2_PIX_FMT_YYUV*/
 fmt.fmt.pix.field = V4L2_FIELD_NONE;   		/*V4L2_FIELD_NONE*/
 if (ioctl(fd, VIDIOC_S_FMT, &fmt)< 0)
 {
     fprintf(stderr,"VIDIOC_S_FMT set err\n");
     exit(EXIT_FAILURE);
 }

3.申请帧缓冲区

    先通过VIDIOC_REQBUFS来申请缓冲区,暂时申请到的缓冲区在内核地址空间,程序访问不到 , 之后再用mmap讲缓冲区映射到用户地址空间。代码在picture_capture.c中,自己看,流程是固定的,很容易懂。

4.讲帧缓冲区入队, 出队

    通过VIDIOC_QBUF 使得一个缓冲区加入帧队列,等待系统载入帧数据,VIDIOC_DQBUF 获取一个已经载人帧数据的缓冲区,并从帧队列中删除。IMPORTANT,就行read和write会阻塞一样,VIDIOC_DQBUF 在帧队列没有已经载入帧数据的缓冲区时也会阻塞,因此需要用select 等io复用函数来避免阻塞带来的影响。具体就是可以VIDIOC_DQBUF时fd可读。将其加入select readset就行了。

5.对数据的处理

    我现在只会拍照处理,直接讲读取到的帧数据保存为jpg文件就行。其他的正在学

详情请见picture_capture.c