v4l2设备需要在应用重启时重新插入

时间:2019-05-05 19:31:59

标签: c++ linux v4l2

我有一个简单的c ++程序,其中的以下代码在线程中运行,以获取恒定的网络摄像头。第一次,一切正常。但是在关闭应用程序并再次运行之后。 select()函数超时,我从相机无法得到任何图像。尽管LED照应点亮。该摄像头无需重新插入任何其他wecam应用程序即可使用。看来我的代码没有正确重置或关闭?

fd = v4l2_open("/dev/video0", O_RDWR | O_NONBLOCK, 0);

// check if device is ready
v4l2_capability capability{};
ioctl(fd, VIDIOC_QUERYCAP, &capability);

// set Image format
v4l2_format imageFormat;
imageFormat.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
imageFormat.fmt.pix.width = s.width;
imageFormat.fmt.pix.height = s.height;
imageFormat.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
imageFormat.fmt.pix.field = V4L2_FIELD_NONE;
// tell the device you are using this format
ioctl(fd, VIDIOC_S_FMT, &imageFormat);

v4l2_requestbuffers req{};
req.count = buffers.size();
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;

xioctl(fd, VIDIOC_REQBUFS, &req);

for (unsigned i = 0; i < req.count; i++) {
    // query buffer
    v4l2_buffer buf{};
    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    buf.memory = V4L2_MEMORY_MMAP;
    buf.index = i;
    xioctl(fd, VIDIOC_QUERYBUF, &buf);

    // map data to buffer
    auto b = v4l2_mmap(nullptr, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset);
    buffers[i].start = reinterpret_cast<uint8_t *>(b);
    buffers[i].length = buf.length;
}

for (unsigned i = 0; i < req.count; i++) {
    v4l2_buffer buf{};
    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    buf.memory = V4L2_MEMORY_MMAP;
    buf.index = i;
    xioctl(fd, VIDIOC_QBUF, &buf);
}

auto type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
xioctl(fd, VIDIOC_STREAMON, &type);

while (bKeepRunning) {
    fd_set fds;
    timeval tv{};
    int r;

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

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

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

    if (r <= 0) {
        continue;
    }

    v4l2_buffer buf{};

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

    // retreive buffer
    if (-1 == xioctl(fd, VIDIOC_DQBUF, &buf)) {
        continue;
    }

    int jpegSubsamp, jpegW, jpegH;
    auto start = buffers[buf.index].start;
    auto data = jpgd::decompress_jpeg_image_from_memory(start, buf.bytesused, &jpegW, &jpegH, &jpegSubsamp, 3);

    // release buffer
    xioctl(fd, VIDIOC_QBUF, &buf);
}

xioctl(fd, VIDIOC_STREAMOFF, &type);

for (auto &buffer: buffers) {
    if (buffer.length == 0) continue;
    v4l2_munmap(buffer.start, buffer.length);
}
v4l2_close(fd);

0 个答案:

没有答案