v4l2用户侧使用流程
前言
v4l2的用户侧使用方法的简单demo,参考:media/v4l/v4l2grab.c
实际上,v4l2的用户侧有libv4l开源库。用户可以使用此开源库快速搭建其用户侧代码。
流程
int main()
{
// open
fd = v4l2_open("/dev/video0", O_RDWR | O_NONBLOCK, 0);
// set format
CLEAR(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_RGB24;
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
xioctl(fd, VIDIOC_S_FMT, &fmt);
// request buffer
// 申请的buffer留在内核
CLEAR(req);
req.count = 2;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
xioctl(fd, VIDIOC_REQBUFS, &req);
buffers = calloc(req.count, sizeof(*buffers));
// query buffer
// 根据index获取buffer信息(length和offset),然后mmap获取虚拟地址并保存
for (n_buffers = 0; n_buffers < req.count; ++n_buffers) {
CLEAR(buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = n_buffers;
xioctl(fd, VIDIOC_QUERYBUF, &buf);
buffers[n_buffers].length = buf.length;
buffers[n_buffers].start = v4l2_mmap(NULL, buf.length,
PROT_READ | PROT_WRITE, MAP_SHARED,
fd, buf.m.offset);
}
// queue buffer
// buffer保存在内核,只需要告知index即可完成queue
for (i = 0; i < n_buffers; ++i) {
CLEAR(buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
xioctl(fd, VIDIOC_QBUF, &buf);
}
// stream on
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
xioctl(fd, VIDIOC_STREAMON, &type);
// dequeue buffer + queue buffer
for (i = 0; i < 20; i++) {
// 使用select或poll或epoll监控fd是否可读,如果可读则往下走
CLEAR(buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
xioctl(fd, VIDIOC_DQBUF, &buf);
// 处理buffer,比如写到文件中
xioctl(fd, VIDIOC_QBUF, &buf);
}
// stream off
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
xioctl(fd, VIDIOC_STREAMOFF, &type);
// munmap
for (i = 0; i < n_buffers; ++i)
v4l2_munmap(buffers[i].start, buffers[i].length);
// close
v4l2_close(fd);
}
本文来自博客园,作者:moonのsun,转载请注明原文链接:https://www.cnblogs.com/moon-sun-blog/p/19219509

浙公网安备 33010602011771号