v4l2打开摄像头代码 c++
时间: 2023-09-17 07:07:57 浏览: 149
以下是一个简单的v4l2打开摄像头的C代码示例:
```
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <linux/videodev2.h>
#define CAMERA_DEVICE "/dev/video0"
struct buffer {
void *start;
size_t length;
};
int main(int argc, char **argv)
{
int fd = -1;
struct buffer *buffers = NULL;
unsigned int n_buffers = 0;
// 1. 打开摄像头设备
fd = open(CAMERA_DEVICE, O_RDWR | O_NONBLOCK, 0);
if (fd == -1) {
fprintf(stderr, "Error opening device %s: %d, %s\n", CAMERA_DEVICE, errno, strerror(errno));
return EXIT_FAILURE;
}
// 2. 查询摄像头设备信息
struct v4l2_capability cap;
if (ioctl(fd, VIDIOC_QUERYCAP, &cap) == -1) {
fprintf(stderr, "Error querying device %s: %d, %s\n", CAMERA_DEVICE, errno, strerror(errno));
goto fail;
}
// 3. 设置摄像头采集格式
struct v4l2_format fmt;
memset(&fmt, 0, sizeof(fmt));
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = 640;
fmt.fmt.pix.height = 480;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
if (ioctl(fd, VIDIOC_S_FMT, &fmt) == -1) {
fprintf(stderr, "Error setting format on device %s: %d, %s\n", CAMERA_DEVICE, errno, strerror(errno));
goto fail;
}
// 4. 请求摄像头缓冲区
struct v4l2_requestbuffers req;
memset(&req, 0, sizeof(req));
req.count = 4;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
if (ioctl(fd, VIDIOC_REQBUFS, &req) == -1) {
fprintf(stderr, "Error requesting buffers on device %s: %d, %s\n", CAMERA_DEVICE, errno, strerror(errno));
goto fail;
}
// 5. 映射摄像头缓冲区到用户空间
buffers = calloc(req.count, sizeof(*buffers));
if (buffers == NULL) {
fprintf(stderr, "Error allocating memory for buffers: %d, %s\n", errno, strerror(errno));
goto fail;
}
for (n_buffers = 0; n_buffers < req.count; n_buffers++) {
struct v4l2_buffer buf;
memset(&buf, 0, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = n_buffers;
if (ioctl(fd, VIDIOC_QUERYBUF, &buf) == -1) {
fprintf(stderr, "Error querying buffer %d on device %s: %d, %s\n", n_buffers, CAMERA_DEVICE, errno, strerror(errno));
goto fail;
}
buffers[n_buffers].length = buf.length;
buffers[n_buffers].start = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset);
if (buffers[n_buffers].start == MAP_FAILED) {
fprintf(stderr, "Error mapping buffer %d on device %s: %d, %s\n", n_buffers, CAMERA_DEVICE, errno, strerror(errno));
goto fail;
}
}
// 6. 启动摄像头采集
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl(fd, VIDIOC_STREAMON, &type) == -1) {
fprintf(stderr, "Error starting capture on device %s: %d, %s\n", CAMERA_DEVICE, errno, strerror(errno));
goto fail;
}
// 7. 采集图像并处理
printf("Press Ctrl-C to stop.\n");
while (1) {
fd_set fds;
FD_ZERO(&fds);
FD_SET(fd, &fds);
struct timeval tv = {0};
tv.tv_sec = 2;
int r = select(fd + 1, &fds, NULL, NULL, &tv);
if (r == -1) {
if (errno == EINTR) continue;
fprintf(stderr, "Error waiting for frame on device %s: %d, %s\n", CAMERA_DEVICE, errno, strerror(errno));
goto fail;
}
if (r == 0) {
fprintf(stderr, "Error waiting for frame on device %s: select timeout\n", CAMERA_DEVICE);
goto fail;
}
struct v4l2_buffer buf;
memset(&buf, 0, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
if (ioctl(fd, VIDIOC_DQBUF, &buf) == -1) {
fprintf(stderr, "Error dequeueing buffer on device %s: %d, %s\n", CAMERA_DEVICE, errno, strerror(errno));
goto fail;
}
// 在这里处理采集到的图像数据
printf("Got a frame with %d bytes\n", buf.bytesused);
if (ioctl(fd, VIDIOC_QBUF, &buf) == -1) {
fprintf(stderr, "Error queueing buffer on device %s: %d, %s\n", CAMERA_DEVICE, errno, strerror(errno));
goto fail;
}
}
return EXIT_SUCCESS;
fail:
if (buffers != NULL) {
for (unsigned int i = 0; i < n_buffers; i++) {
if (buffers[i].start != MAP_FAILED) munmap(buffers[i].start, buffers[i].length);
}
free(buffers);
}
if (fd != -1) close(fd);
return EXIT_FAILURE;
}
```
阅读全文