[camera][v4l2][第四话]: v4l2的框架

以vivi.c为例,说明v4l2的框架。

 
摄像头驱动程序框架:
1. 分配video_device:video_device_alloc

vfd = video_device_alloc();


2. 设置:     *vfd = vivi_template;

static struct video_device vivi_template = {
    .name        = "vivi",
    .fops           = &vivi_fops,
    .ioctl_ops     = &vivi_ioctl_ops,
    .release    = video_device_release,

    .tvnorms              = V4L2_STD_525_60,
    .current_norm         = V4L2_STD_NTSC_M,
};

   .fops
   .ioctl_ops (里面需要设置11项)
   如果要用内核提供的缓冲区操作函数,还需要构造一个videobuf_queue_ops


3. 注册: video_register_device

ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
当然可以,以下是一个简单的v4l2框架camera取流代码示例: ```c++ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <linux/videodev2.h> #define BUFFER_COUNT 4 struct buffer { void *start; size_t length; }; int main(int argc, char **argv) { int fd; struct v4l2_capability cap; struct v4l2_format fmt; struct v4l2_requestbuffers req; struct v4l2_buffer buf; enum v4l2_buf_type type; struct buffer buffers[BUFFER_COUNT]; unsigned int i, n; fd_set fds; struct timeval tv; int r; fd = open("/dev/video0", O_RDWR); if (fd < 0) { perror("open"); return 1; } if (ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0) { perror("VIDIOC_QUERYCAP"); return 1; } if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { fprintf(stderr, "The device does not support video capture.\n"); return 1; } if (!(cap.capabilities & V4L2_CAP_STREAMING)) { fprintf(stderr, "The device does not support streaming I/O.\n"); return 1; } memset(&fmt, 0, sizeof(fmt)); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.fmt.pix.width = 640; fmt.fmt.pix.height = 480; fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0) { perror("VIDIOC_S_FMT"); return 1; } memset(&req, 0, sizeof(req)); req.count = BUFFER_COUNT; req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; req.memory = V4L2_MEMORY_MMAP; if (ioctl(fd, VIDIOC_REQBUFS, &req) < 0) { perror("VIDIOC_REQBUFS"); return 1; } for (i = 0; i < req.count; i++) { memset(&buf, 0, sizeof(buf)); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = i; if (ioctl(fd, VIDIOC_QUERYBUF, &buf) < 0) { perror("VIDIOC_QUERYBUF"); return 1; } buffers[i].length = buf.length; buffers[i].start = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset); if (buffers[i].start == MAP_FAILED) { perror("mmap"); return 1; } } for (i = 0; i < req.count; i++) { memset(&buf, 0, sizeof(buf)); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = i; if (ioctl(fd, VIDIOC_QBUF, &buf) < 0) { perror("VIDIOC_QBUF"); return 1; } } type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (ioctl(fd, VIDIOC_STREAMON, &type) < 0) { perror("VIDIOC_STREAMON"); return 1; } for (n = 0; n < 100; n++) { FD_ZERO(&fds); FD_SET(fd, &fds); tv.tv_sec = 2; tv.tv_usec = 0; r = select(fd + 1, &fds, NULL, NULL, &tv); if (r < 0) { perror("select"); return 1; } if (r == 0) { fprintf(stderr, "select timeout\n"); return 1; } memset(&buf, 0, sizeof(buf)); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; if (ioctl(fd, VIDIOC_DQBUF, &buf) < 0) { perror("VIDIOC_DQBUF"); return 1; } printf("frame %u: %p\n", n, buffers[buf.index].start); if (ioctl(fd, VIDIOC_QBUF, &buf) < 0) { perror("VIDIOC_QBUF"); return 1; } } type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (ioctl(fd, VIDIOC_STREAMOFF, &type) < 0) { perror("VIDIOC_STREAMOFF"); return 1; } for (i = 0; i < req.count; i++) { if (munmap(buffers[i].start, buffers[i].length) < 0) { perror("munmap"); return 1; } } close(fd); return 0; } ``` 这段代码使用了v4l2框架来获取摄像头的视频流数据。它首先通过ioctl函数查询设备的能力,然后设置视频格式和请求缓冲区。接着,它使用mmap函数将缓冲区映射到用户空间,然后将缓冲区加入到队列中。最后,它使用select函数等待摄像头的数据,并将数据从队列中取出,处理完后再将缓冲区重新加入队列。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

change_fate_vs_god

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值