给设备写编程视频通常涉及以下步骤:
打开设备文件
```c
int fd = open("/dev/video0", O_RDWR);
```
获取设备的capability
```c
struct v4l2_capability cap;
int ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);
if (ret < 0) {
perror("VIDIOC_QUERYCAP");
return -1;
}
```
选择视频输入
```c
int num_inputs = cap.num_inputs;
struct v4l2_input input;
for (int i = 0; i < num_inputs; i++) {
ret = ioctl(fd, VIDIOC_S_INPUT, &input);
if (ret < 0) {
perror("VIDIOC_S_INPUT");
return -1;
}
if (input.index == desired_input) {
break;
}
}
```
设置视频的制式和帧格式
```c
struct v4l2_std_id std_id;
ret = ioctl(fd, VIDIOC_S_STD, &std_id);
if (ret < 0) {
perror("VIDIOC_S_STD");
return -1;
}
struct v4l2_format fmt;
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = width;
fmt.fmt.pix.height = height;
fmt.fmt.pix.pix_fmt = V4L2_PIX_FMT_YUYV;
ret = ioctl(fd, VIDIOC_S_FMT, &fmt);
if (ret < 0) {
perror("VIDIOC_S_FMT");
return -1;
}
```
向驱动申请帧缓冲
```c
struct v4l2_requestbuffers req;
req.count = num_buffers;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
ret = ioctl(fd, VIDIOC_REQBUFS, &req);
if (ret < 0) {
perror("VIDIOC_REQBUFS");
return -1;
}
```
将申请到的帧缓冲映射到用户空间
```c
unsigned char *buffer;
buffer = mmap(NULL, req.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (buffer == MAP_FAILED) {
perror("mmap");
return -1;
}
```
将申请到的帧缓冲全部入队列
```c
for (int i = 0; i < num_buffers; i++) {
struct v4l2_buffer buf;
buf.index = i;
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.length = req.length;
ret = ioctl(fd, VIDIOC_QBUF, &buf);
if (ret < 0) {
perror("VIDIOC_QBUF");
return -1;
}
}
```
开始视频的采集
```c
ret = ioctl(fd, VIDIOC_STREAMON, &input.index);
if (ret < 0) {
perror("VIDIOC_STREAMON");
return -1;
}
```
出队列以取得已采集数据的帧缓冲
```c
struct v4l2_buffer buf;
buf.index = 0;
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ret = ioctl(fd, VIDIOC_DQBUF, &buf);
if (ret < 0) {
perror("VIDIOC_DQBUF");
return -1;
}
```