c++ - 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);
解决方案
推荐阅读
- gcc - printf 与 utf-8 编码字符串的兼容性
- android-studio - 我想用我的 android 手机作为模拟器在 windows 7 上运行颤振。在我的调试模式下进行了调整。如何解决颤振医生命令的问题
- microsoft-graph-api - Microsoft Graph:NextLink...上一个链接呢?
- android - AppCompatDialogs 在使用 alpha 版本的各种操作系统版本上崩溃 Material Components
- python - Python 2.7 的 input() 和 raw_input() 问题。用户输入的数据未正确读取。到底是怎么回事?
- shell - sqlplus 命令在 linux 中从 crontab 执行时返回帮助页面
- r - 清理具有获得姓氏和名字的分隔空间的列,以便我可以从我的数据框中过滤它
- c# - 无法将文件或程序集加载为 exe 文件
- python - 如何使用切片索引变量在 for 循环中切片数组
- python - Sentinel 5 Data - Problems in importing Basemap from mpl_toolkits.basemap in Python 3.7