了解V4L2请求缓冲区编号

时间:2018-01-11 02:40:13

标签: c embedded v4l2

我是在嵌入式设备上使用V4L2的新手,我有两个与V4L2库使用相关的问题:

首先是v4l2_requestbuffers的缓冲区分配:

    struct v4l2_requestbuffers req;

    CLEAR(req);

    req.count = 4;
    req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    req.memory = V4L2_MEMORY_MMAP;

以后它用于:

if (req.count < 2) {
                fprintf(stderr, "Insufficient buffer memory on %s\n",
                         dev_name);
                exit(EXIT_FAILURE);
        }

        buffers = calloc(req.count, sizeof(*buffers));

        if (!buffers) {
                fprintf(stderr, "Out of memory\n");
                exit(EXIT_FAILURE);
        }

for (n_buffers = 0; n_buffers < req.count; ++n_buffers) {
                struct v4l2_buffer buf;

                CLEAR(buf);

                buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
                buf.memory      = V4L2_MEMORY_MMAP;
                buf.index       = n_buffers;

                if (-1 == xioctl(fd, VIDIOC_QUERYBUF, &buf))
                        errno_exit("VIDIOC_QUERYBUF");

                buffers[n_buffers].length = buf.length;
                buffers[n_buffers].start =
                        mmap(NULL /* start anywhere */,
                              buf.length,
                              PROT_READ | PROT_WRITE /* required */,
                              MAP_SHARED /* recommended */,
                              fd, buf.m.offset);

                if (MAP_FAILED == buffers[n_buffers].start)
                        errno_exit("mmap");
        }

为了捕获静止图像,req.count为1.为了捕获视频,我们是否需要将req.count数字调整为我们获得良好fps的数字? 这意味着我们必须将req.count从2(在此示例中)更改为合适的数字以获得可接受的fps?

第二个问题是在主循环中使用的超时设置:

static void mainloop(void)
{
        unsigned int count;

        count = frame_count;

        while (count-- > 0) {
                for (;;) {
                        fd_set fds;
                        struct timeval tv;
                        int r;

                        FD_ZERO(&fds);
                        FD_SET(fd, &fds);

                        /* Timeout. */
                        tv.tv_sec = 2;
                        tv.tv_usec = 0;

                        r = select(fd + 1, &fds, NULL, NULL, &tv);

                        if (-1 == r) {
                                if (EINTR == errno)
                                        continue;
                                errno_exit("select");
                        }

                        if (0 == r) {
                                fprintf(stderr, "select timeout\n");
                                exit(EXIT_FAILURE);
                        }

                        if (read_frame())
                                break;
                        /* EAGAIN - continue select loop. */
                }
        }
}

如果我设置

/* Timeout. */
tv.tv_sec = 0;
tv.tv_usec = 0;
r = select(fd + 1, &fds, NULL, NULL, &tv);

我的CPU负载是100%,我必须把它设置为1或2以减少CPU负载。如果我删除超时select()函数,我的CPU负载再次为100%。

从我的阅读中,select()操作花费了更多的CPU周期,但是我们如何在mainloop()中删除select()和timeout设置?因为当我查看来自高级软件工程师的其他V4L2捕获代码时,我没有看到他们使用超时功能,如上例所示。

所以我的第二个问题是如何避免使用超时select()但仍然保持低CPU负载。

0 个答案:

没有答案