我在ubuntu14.04中,使用v4l2采集免驱的(UVC)logitech摄像头视频,使用阻塞模式打开摄像头。
每次调用ioctl(fd,VIDIOC_DQBUF,&buf)时,会阻塞1-20秒,导致采集的视频画面非常不流畅,出现卡顿的现象。
麻烦有这方面经年的大侠,如何解决这个问题呢?我不想用非阻塞模式。
我也会出现这种情况。采集不流畅,老会卡顿
您可以尝试通过设置摄像头的帧间间隔来减少阻塞时间,以获得更流畅的视频画面。以下是一个示例代码,展示如何在采集视频时配置帧间间隔:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
#define VIDEO_DEVICE "/dev/video0"
#define IMAGE_WIDTH 640
#define IMAGE_HEIGHT 480
#define FRAME_INTERVAL 2 // 设置帧间间隔
int main() {
// 打开V4L2设备
int fd = open(VIDEO_DEVICE, O_RDWR | O_NONBLOCK); // 使用非阻塞模式
if (fd == -1) {
perror("无法打开设备");
return -1;
}
// 设置图像格式等参数
struct v4l2_format format = {0};
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
format.fmt.pix.width = IMAGE_WIDTH;
format.fmt.pix.height = IMAGE_HEIGHT;
format.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;
if (ioctl(fd, VIDIOC_S_FMT, &format) == -1) {
perror("无法设置图像格式");
return -1;
}
// 设置帧间间隔
struct v4l2_streamparm streamparm = {0};
streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
streamparm.parm.capture.timeperframe.numerator = 1;
streamparm.parm.capture.timeperframe.denominator = FRAME_INTERVAL;
if (ioctl(fd, VIDIOC_S_PARM, &streamparm) == -1) {
perror("无法设置帧间间隔");
return -1;
}
// 请求缓冲区
struct v4l2_requestbuffers req = {0};
req.count = 1;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
if (ioctl(fd, VIDIOC_REQBUFS, &req) == -1) {
perror("无法请求缓冲区");
return -1;
}
// 采集图像数据
struct v4l2_buffer buf = {0};
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = 0;
if (ioctl(fd, VIDIOC_QUERYBUF, &buf) == -1) {
perror("无法查询缓冲区");
return -1;
}
void* buffer = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset);
if (buffer == MAP_FAILED) {
perror("内存映射失败");
return -1;
}
// 将图像数据保存到文件(示例)
FILE* file = fopen("image.jpg", "wb");
if (file == NULL) {
perror("无法创建文件");
return -1;
}
// 将buffer中的图像数据写入文件
fwrite(buffer, 1, buf.length, file);
fclose(file);
munmap(buffer, buf.length);
// 关闭V4L2设备
close(fd);
return 0;
}
在上述示例中,我们通过设置FRAME_INTERVAL变量来控制帧间间隔,从而减少阻塞时间。请根据实际需求调整FRAME_INTERVAL的值,较小的值将导致更流畅的画面,但可能会增加系统负载。
此外,请注意示例代码中设置了O_NONBLOCK标志来打开V4L2设备,以避免阻塞模式。如果您确实不想使用非阻塞模式,请将O_NONBLOCK标志从open函数中删除。