问题遇到的现象和发生背景
v4l2 在运行到 VIDIOC_DQBUF 时卡住
这个情况只出现咋pixformat为YUYV的时候,使用MJPG就没有这个问题
遇到的现象和发生背景,请写出第一个错误信息
需要提一嘴的是,我用的WSL(虚拟机软件我带不动)
用代码块功能插入代码,请勿粘贴截图。 不用代码块回答率下降 50%
#define BUFCOUNT 4
int Vvideo::initBuffers() {
struct v4l2_requestbuffers req;
std::memset(&req, 0, sizeof(req));
req.count = BUFCOUNT;
req.type = type;
req.memory = V4L2_MEMORY_MMAP;
if (ioctl(fd, VIDIOC_REQBUFS, &req) == -1) {
perror("Failed to request buffers");
close(fd);
return -1;
}
for (int num = 0; num < BUFCOUNT; num++) {
std::memset(&buffer, 0, sizeof(buffer));
buffer.type = type;
buffer.memory = V4L2_MEMORY_MMAP;
buffer.index = num;
if (ioctl(fd, VIDIOC_QUERYBUF, &buffer) == -1) {
perror("Failed to query buffer");
goto cleanup;
}
framebuf[num].start = mmap(NULL, buffer.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buffer.m.offset);
if (framebuf[num].start == MAP_FAILED) {
perror("Failed to map buffer");
goto cleanup;
}
framebuf[num].length = buffer.length;
if (ioctl(fd, VIDIOC_QBUF, &buffer) == -1) {
perror("Failed to queue buffer");
goto cleanup;
}
}
if (ioctl(fd, VIDIOC_STREAMON, &buffer.type) == -1) {
perror("Failed to start streaming");
goto cleanup;
}
return 0;
cleanup:
for (int i = 0; i < BUFCOUNT; i++) {
if (framebuf[i].start && framebuf[i].start != MAP_FAILED) {
munmap(framebuf[i].start, framebuf[i].length);
}
}
close(fd);
return -1;
}
QImage Vvideo::captureFrame() {
QMutexLocker locker(&mutex); // 加锁
memset(&buffer, 0, sizeof(buffer));
buffer.type = type;
buffer.memory = V4L2_MEMORY_MMAP;
struct timeval tv;
tv.tv_sec = 2;
tv.tv_usec = 0;
fd_set fds;
FD_ZERO(&fds);
FD_SET(fd, &fds);
int r = select(fd + 1, &fds, NULL, NULL, &tv);
if (r == -1) {
perror("select");
return QImage();
} else if (r == 0) {
qDebug() << "Timeout waiting for buffer";
return QImage();
}
if (ioctl(fd, VIDIOC_DQBUF, &buffer) == -1) {
perror("Failed to dequeue buffer");
return QImage();
}
QImage image_;
if (fmt == V4L2_PIX_FMT_MJPEG || fmt == V4L2_PIX_FMT_JPEG) {
MJPG2RGB(image_, framebuf[buffer.index].start, framebuf[buffer.index].length);
} else if (fmt == V4L2_PIX_FMT_YUYV) {
YUYV2RGB(image_, framebuf[buffer.index].start, framebuf[buffer.index].length);
} else {
qDebug() << "Unsupported format";
}
if (ioctl(fd, VIDIOC_QBUF, &buffer) == -1) {
perror("Failed to queue buffer");
}
return image_;
}
运行结果及详细报错内容
Timeout waiting for buffer
Capture frame failed!
其实没有报错信息,就是会卡住
我的解答思路和尝试过的方法,不写自己思路的,回答率下降 60%
看来许多博客,提到的有扩充缓冲区(我现在用的4个),有说设置超时的(select已经加上了,2秒还是超时)
我想要达到的结果,如果你需要快速回答,请尝试 “付费悬赏”
只需要拿到数据就行