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);
}
posted @ 2025-11-13 20:41  moonのsun  阅读(3)  评论(0)    收藏  举报