一、V4L2应用层调用流程

一、V4L2应用层调用流程


二、V4L2设备注册
三、video设备初始化
四、V4L2 control结构框架图
五、v4l2 ctrl 函数初始化—增加标准接口v4l2_ctrl_new_std
六、v4l2 ctrl 函数初始化—增加自定义接口v4l2_ctrl_new_custom
七、V4L2 ioctl 标准接口 调用流程
八、V4L2 ioctl 控制接口 调用流程

1、打开设备

相机设备基本上都是videox节点,以/dev/video0节点为例

	int fd = open("/dev/video0",O_RDWR);

2. 获取摄像支持的格式

	struct v4l2_fmtdesc v4l2fmt;
	v4l2fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	int i = 0;
	while(1)
	{
		v4l2fmt.index = i++;
		ioctl(fd, VIDIOC_ENUM_FMT, &v4l2fmt);
	}

3.设置像素格式

这里设置输出的宽、高、像素格式

    preview.format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    preview.format.fmt.pix.field = V4L2_FIELD_INTERLACED;
    preview.format.fmt.pix.pixelformat = V4L2_PIX_FMT_NV21;
    preview.format.fmt.pix.width = 1920;
    preview.format.fmt.pix.height = 1080;
	preview.format.fmt.pix.priv = 1;
    ioctl(fd, VIDIOC_S_FMT, &preview.format);

4、查看设置的像素格式

    ioctl(fd, VIDIOC_G_FMT, &preview.format);
    printf("pix.pixelformat:\t%c%c%c%c\n",preview.format.fmt.pix.pixelformat & 0xFF, (preview.format.fmt.pix.pixelformat >> 8) & 0xFF,(preview.format.fmt.pix.pixelformat >> 16) & 0xFF, (preview.format.fmt.pix.pixelformat >> 24) & 0xFF);
    printf("pix.height:\t\t%d\n",preview.format.fmt.pix.height);
    printf("pix.width:\t\t%d\n",preview.format.fmt.pix.width);
    printf("pix.field:\t\t%d\n",preview.format.fmt.pix.field);

5、请求队列大小

	memset(&preview.rb,0,sizeof(preview.rb));
    preview.rb.count=4;
    preview.rb.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
    preview.rb.memory=V4L2_MEMORY_MMAP;
	ioctl(fd,VIDIOC_REQBUFS,&preview.rb);

6、内存映射到用户空间

根据请求的队列 buffer个数,把每一个buffer映射到用户空间对应的mem

    for (i = 0; i < preview.rb.count; i++)
    {
		memset(&preview.buf,0,sizeof(preview.buf));
		preview.buf.index = i;
		preview.buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
		preview.buf.memory = V4L2_MEMORY_MMAP;
		ioctl(fd,VIDIOC_QUERYBUF,&preview.buf);
		mem[i].size = preview.buf.length;
        mem[i].addr = mmap(NULL,mem[i].size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,preview.buf.m.offset);
    }

7、请求到的buffer全部执行入队操作

	for (i = 0; i < preview.rb.count; i++)
	{
		preview.buf.type    = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        preview.buf.memory  = V4L2_MEMORY_MMAP;
        preview.buf.index   = i;
		ioctl(fd, VIDIOC_QBUF, &preview.buf);

8、开始获取流数据

	enum v4l2_buf_type type;
    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    ioctl(fd, VIDIOC_STREAMON, &type);

9、出队

preview.buf就保存了读到的数据信息,根据preview.buf.index的下标对应到用户的mem[preview.buf.index].addr 和mem[preview.buf.index].size就能获取到读到的数据

	preview.buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	preview.buf.memory = V4L2_MEMORY_MMAP;
	ioctl(fd, VIDIOC_DQBUF, &preview.buf);

10、入队

把读完的buffer再进行入队操作

ioctl(fd, VIDIOC_QBUF, &preview.buf)

      
      
  • 1

11、循环 入队 出队

如果需要抓连续的帧数据,就保持9、10两个步骤连续 入队出队即可

12、关闭流数据

当数据抓取完毕后,需要关闭流

	int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    for(i = 0; i < preview.rb.count; i++)
    {
        ret = munmap(mem[i].addr,mem[i].size);
        if(ret < 0) {
            printf("munmap fail \n");
        }
    }
    ret = ioctl(fd, VIDIOC_STREAMOFF, &type);
            </div><div data-report-view="{&quot;mod&quot;:&quot;1585297308_001&quot;,&quot;spm&quot;:&quot;1001.2101.3001.6548&quot;,&quot;dest&quot;:&quot;https://blog.csdn.net/zzsxyl/article/details/124478369&quot;,&quot;extend1&quot;:&quot;pc&quot;,&quot;ab&quot;:&quot;new&quot;}"><div></div></div>
            <link href="https://csdnimg.cn/release/blogv2/dist/mdeditor/css/editerView/markdown_views-98b95bb57c.css" rel="stylesheet">
            <link href="https://csdnimg.cn/release/blogv2/dist/mdeditor/css/style-c216769e99.css" rel="stylesheet">
    </div>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值