跳转到正文
知识笔记
通用📖 学习中

V4L2 子系统 ​

V4L2(Video for Linux 2)是 Linux 内核中用于视频采集、输出和处理的标准子系统。


什么是 V4L2 ​

V4L2 是 Linux 下视频设备的统一接口框架,向上为用户空间提供统一的 ioctl 接口,向下对接各类视频硬件驱动(Camera、TV Tuner、Codec 等)。

用户空间
    ↓  (open / ioctl / mmap / read)
V4L2 核心 (videobuf2 等)
    ↓
具体硬件驱动 (Sensor / ISP / MIPI CSI 等)
    ↓
硬件

设备节点 ​

V4L2 设备通常以 /dev/videoX 的形式存在:

bash
ls -la /dev/video*
设备号用途
/dev/video0通常是第一个视频采集设备
/dev/video1可能是第二个设备或同一设备的另一个节点
/dev/media0Media Controller 设备
/dev/v4l-subdevXV4L2 子设备节点

常用 ioctl 命令 ​

查询设备能力 ​

c
struct v4l2_capability cap;
ioctl(fd, VIDIOC_QUERYCAP, &cap);

关键字段:

  • cap.driver — 驱动名称
  • cap.card — 设备名称
  • cap.bus_info — 总线信息
  • cap.capabilities — 设备能力标志

枚举支持的格式 ​

c
struct v4l2_fmtdesc fmt_desc;
fmt_desc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt_desc.index = 0;
while (ioctl(fd, VIDIOC_ENUM_FMT, &fmt_desc) == 0) {
    printf("Format: %s\n", fmt_desc.description);
    fmt_desc.index++;
}

设置视频格式 ​

c
struct v4l2_format fmt;
memset(&fmt, 0, sizeof(fmt));
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = 1920;
fmt.fmt.pix.height = 1080;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
fmt.fmt.pix.field = V4L2_FIELD_NONE;
ioctl(fd, VIDIOC_S_FMT, &fmt);

常用像素格式:

  • V4L2_PIX_FMT_YUYV — YUYV422 格式
  • V4L2_PIX_FMT_NV12 — NV12 格式(Y 平面 + UV 交错平面)
  • V4L2_PIX_FMT_MJPEG — MJPEG 格式
  • V4L2_PIX_FMT_H264 — H.264 格式

缓冲管理方式 ​

V4L2 支持多种缓冲管理方式:

1. READ 模式(最简单) ​

直接使用 read() 读取帧数据。

c
read(fd, buffer, buffer_size);
  • 优点:简单
  • 缺点:有数据拷贝,性能低

2. MMAP 模式(最常用) ​

将内核缓冲区映射到用户空间,零拷贝。

c
// 请求缓冲
struct v4l2_requestbuffers req;
req.count = 4;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
ioctl(fd, VIDIOC_REQBUFS, &req);

// 映射每帧缓冲
for (int i = 0; i < req.count; i++) {
    struct v4l2_buffer buf;
    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    buf.memory = V4L2_MEMORY_MMAP;
    buf.index = i;
    ioctl(fd, VIDIOC_QUERYBUF, &buf);
    buffers[i] = mmap(NULL, buf.length, PROT_READ, MAP_SHARED, fd, buf.m.offset);
}
  • 优点:零拷贝,性能高
  • 缺点:编程稍复杂

3. USERPTR 模式 ​

用户空间自己分配缓冲,传递指针给内核。

  • 优点:缓冲管理灵活
  • 缺点:需要内核和用户空间之间的内存一致性处理

4. DMABUF 模式 ​

通过 DMA-BUF 在不同硬件模块间共享缓冲(如 V4L2 → MPP → RGA 零拷贝流水线)。

  • 优点:硬件间零拷贝,性能最高
  • 缺点:编程最复杂

采集流程(MMAP 模式) ​

1. open 设备
2. VIDIOC_QUERYCAP  查询能力
3. VIDIOC_S_FMT     设置格式
4. VIDIOC_REQBUFS  请求缓冲
5. VIDIOC_QUERYBUF 查询缓冲 + mmap 映射
6. VIDIOC_QBUF     将缓冲入队
7. VIDIOC_STREAMON 启动流
8. VIDIOC_DQBUF    取出一帧处理
9. VIDIOC_QBUF     重新入队
   ... 循环 8-9 ...
10. VIDIOC_STREAMOFF 停止流
11. munmap 释放映射
12. close 关闭设备

v4l2-ctl 常用命令 ​

shellbash
# 列出设备信息
v4l2-ctl -d /dev/video0 --all

# 列出支持的格式
v4l2-ctl -d /dev/video0 --list-formats-ext

# 设置格式
v4l2-ctl -d /dev/video0 --set-fmt-video=width=1920,height=1080,pixelformat=YUYV

# 抓取一帧保存
v4l2-ctl -d /dev/video0 --stream-mmap --stream-count=1 --stream-to=output.yuv

# 查看控件列表
v4l2-ctl -d /dev/video0 --list-ctrls

# 设置曝光
v4l2-ctl -d /dev/video0 --set-ctrl=exposure=1000

常见问题 ​

DQBUF 超时 ​

VIDIOC_DQBUF 阻塞返回 ETIMEDOUT,常见原因:

  1. Sensor 未正常输出数据(电源、时钟、复位)
  2. MIPI CSI 链路未建立
  3. 设备树配置错误
  4. ISP 未正确配置

→ 详见 Debug 记录:VIDIOC_DQBUF Timeout

帧数据不对 ​

  1. 像素格式不匹配
  2. stride/对齐问题
  3. 分辨率设置错误

相关实验 ​


参考资料 ​