给我写一个调用V4l2 打开摄像头并拍照的c程序,可以在linux上运行
时间: 2024-03-03 13:52:03 浏览: 15
下面是一个简单的 C 语言程序,用于调用 V4L2 接口打开摄像头并拍照。您可以根据自己的需要进行修改和扩展。
```c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <linux/videodev2.h>
#define CAMERA_DEVICE "/dev/video0"
#define CAPTURE_FILE "capture.jpg"
#define IMAGE_WIDTH 640
#define IMAGE_HEIGHT 480
int main(int argc, char *argv[])
{
int fd;
struct v4l2_capability cap;
struct v4l2_format fmt;
struct v4l2_requestbuffers req;
struct v4l2_buffer buf;
void *buffer;
int i;
// 打开摄像头设备
fd = open(CAMERA_DEVICE, O_RDWR);
if (fd < 0) {
perror("open");
return 1;
}
// 查询设备能力
if (ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0) {
perror("VIDIOC_QUERYCAP");
return 1;
}
printf("Driver: %s\n", cap.driver);
printf("Card: %s\n", cap.card);
printf("Bus: %s\n", cap.bus_info);
// 设置视频格式
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = IMAGE_WIDTH;
fmt.fmt.pix.height = IMAGE_HEIGHT;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG;
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0) {
perror("VIDIOC_S_FMT");
return 1;
}
// 请求帧缓冲
req.count = 1;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
if (ioctl(fd, VIDIOC_REQBUFS, &req) < 0) {
perror("VIDIOC_REQBUFS");
return 1;
}
// 映射帧缓冲
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = 0;
if (ioctl(fd, VIDIOC_QUERYBUF, &buf) < 0) {
perror("VIDIOC_QUERYBUF");
return 1;
}
buffer = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset);
if (buffer == MAP_FAILED) {
perror("mmap");
return 1;
}
// 开始视频采集
if (ioctl(fd, VIDIOC_STREAMON, &buf.type) < 0) {
perror("VIDIOC_STREAMON");
return 1;
}
// 捕获视频帧
if (ioctl(fd, VIDIOC_QBUF, &buf) < 0) {
perror("VIDIOC_QBUF");
return 1;
}
if (ioctl(fd, VIDIOC_DQBUF, &buf) < 0) {
perror("VIDIOC_DQBUF");
return 1;
}
// 写入 JPEG 文件
FILE *fp = fopen(CAPTURE_FILE, "wb");
fwrite(buffer, buf.bytesused, 1, fp);
fclose(fp);
// 停止视频采集
if (ioctl(fd, VIDIOC_STREAMOFF, &buf.type) < 0) {
perror("VIDIOC_STREAMOFF");
return 1;
}
// 解除帧缓冲映射
munmap(buffer, buf.length);
// 关闭摄像头设备
close(fd);
return 0;
}
```
该程序使用了 V4L2 API 中的 VIDIOC_* 命令来控制摄像头设备的各种属性和功能,例如 VIDIOC_QUERYCAP、VIDIOC_S_FMT、VIDIOC_REQBUFS、VIDIOC_STREAMON 等。它还使用了 mmap 函数将摄像头设备的帧缓冲映射到内存中,并使用 fwrite 函数将 JPEG 数据写入文件中。
该程序编译后生成可执行文件,您可以在 Linux 系统上直接运行它来打开摄像头并拍照。请注意,该程序可能需要 root 权限才能访问摄像头设备。