以下是一个简单的V4L2相机程序,可以设置图像格式(如YUYV或MJPEG等)并捕获图像:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
// V4L2头文件
#include <linux/videodev2.h>
#define DEVICE "/dev/video0"
int main(int argc, char **argv)
{
int fd;
struct v4l2_capability cap;
struct v4l2_format fmt;
struct v4l2_requestbuffers reqbuf;
struct v4l2_buffer buf;
void *mem[4];
unsigned int nbufs;
// 打开设备文件
fd = open(DEVICE, O_RDWR);
if (fd == -1) {
perror("open");
exit(EXIT_FAILURE);
}
// 查询设备功能
if (ioctl(fd, VIDIOC_QUERYCAP, &cap) == -1) {
perror("VIDIOC_QUERYCAP");
exit(EXIT_FAILURE);
}
printf("Driver: %s\n", cap.driver);
printf("Card: %s\n", cap.card);
// 设置图像格式为YUYV 640x480
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;
if (ioctl(fd, VIDIOC_S_FMT, &fmt) == -1) {
perror("VIDIOC_S_FMT");
exit(EXIT_FAILURE);
}
// 请求内存映射缓冲区
memset(&reqbuf, 0, sizeof(reqbuf));
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
reqbuf.memory = V4L2_MEMORY_MMAP;
reqbuf.count = 4;
if (ioctl(fd, VIDIOC_REQBUFS, &reqbuf) == -1) {
perror("VIDIOC_REQBUFS");
exit(EXIT_FAILURE);
}
nbufs = reqbuf.count;
// 映射内存
for (int i = 0; i < nbufs; ++i) {
memset(&buf, 0, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
if (ioctl(fd, VIDIOC_QUERYBUF, &buf) == -1) {
perror("VIDIOC_QUERYBUF");
exit(EXIT_FAILURE);
}
mem[i] = mmap(NULL, buf.length, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, buf.m.offset);
if (mem[i] == MAP_FAILED) {
perror("mmap");
exit(EXIT_FAILURE);
}
}
// 入队请求缓冲区
for (int i = 0; i < nbufs; ++i) {
memset(&buf, 0, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
if (ioctl(fd, VIDIOC_QBUF, &buf) == -1) {
perror("VIDIOC_QBUF");
exit(EXIT_FAILURE);
}
}
// 启动视频采集
int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl(fd, VIDIOC_STREAMON, &type) == -1) {
perror("VIDIOC_STREAMON");
exit(EXIT_FAILURE);
}
// 捕获一帧图像
memset(&buf, 0, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
if (ioctl(fd, VIDIOC_DQBUF, &buf) == -1) {
perror("VIDIOC_DQBUF");
exit(EXIT_FAILURE);
}
printf("Captured frame %d\n", buf.index);
// 停止视频采集
if (ioctl(fd, VIDIOC_STREAMOFF, &type) == -1) {
perror("VIDIOC_STREAMOFF");
exit(EXIT_FAILURE);
}
// 解除内存映射
for (int i = 0; i < nbufs; ++i)
munmap(mem[i], buf.length);
close(fd);
return EXIT_SUCCESS;
}
如果要设置不同的格式,可以更改V4L2_PIX_FMT_YUYV
。常见的格式包括MJPEG、H.264等,请参考V4L2 API文档进行设置。
内容由零声教学AI助手生成,来源于学员提问