2. v4l2-compliance 工具介绍
v4l2-compliance 是 Linux 内核 V4L2 框架的官方合规性测试工具,由内核社区维护,用于验证 V4L2 设备驱动对 V4L2 规范(specification)的符合程度。它通过调用一系列 ioctl 接口,检查驱动在格式协商、缓冲区管理、流控制、裁剪/缩放、控制属性等方面的行为是否与内核期望一致。本章将深入分析该工具的源码结构、编译方法以及核心命令行参数的使用方式。
2.1 工具源码结构
v4l2-compliance 的源码位于 Linux 内核源码树的 tools/testing/selftests/media/v4l2-compliance/ 目录下,也可从 v4l-utils 仓库 独立获取。其核心源码文件及职责如下表所示:
| 源文件 | 职责说明 |
|---|---|
v4l2-compliance.cpp |
主入口文件,解析命令行参数,调度测试流程,输出测试报告 |
v4l2-test-debug.cpp |
测试 VIDIOC_LOG_STATUS、VIDIOC_DBG_G/S_REGISTER 等调试 ioctl |
v4l2-test-input-output.cpp |
测试输入/输出(input/output)枚举、查询、切换相关 ioctl |
v4l2-test-audio.cpp |
测试音频输入/输出 ioctl(VIDIOC_ENUMAUDIO、VIDIOC_G/S_AUDIO 等) |
v4l2-test-tuner.cpp |
测试调谐器(tuner)与调制器(modulator)相关 ioctl |
v4l2-test-formats.cpp |
测试格式枚举、获取、设置(VIDIOC_ENUM_FMT、VIDIOC_G/S_FMT、VIDIOC_TRY_FMT) |
v4l2-test-buffers.cpp |
测试缓冲区申请、入队、出队、流控制(VIDIOC_REQBUFS、VIDIOC_QBUF/DQBUF、VIDIOC_STREAMON/OFF) |
v4l2-test-controls.cpp |
测试控制属性(controls)的枚举、查询、获取、设置、事件订阅 |
v4l2-test-selection.cpp |
测试裁剪/缩放(VIDIOC_G/S_SELECTION)与 compose 区域 |
v4l2-test-ioctl.cpp |
测试通用 ioctl 调用(VIDIOC_QUERYCAP、VIDIOC_ENUM_FRAMESIZES、VIDIOC_ENUM_FRAMEINTERVALS 等) |
0(通过)、1(失败)或 -1(跳过/不适用)。这种模块化设计便于开发者快速定位驱动在哪个功能域存在合规性问题。
下图展示了 v4l2-compliance 的源码模块调用关系与测试流程:
2.2 编译方法
v4l2-compliance 的编译有两种主流方式:作为内核 selftests 的一部分编译,或从 v4l-utils 独立编译。推荐使用后者,因为独立编译更灵活且不依赖完整内核源码树。
2.2.1 从 v4l-utils 仓库编译(推荐)
# 克隆 v4l-utils 仓库
git clone https://git.linuxtv.org/v4l-utils.git
cd v4l-utils
# 配置编译环境(需要 meson 和 ninja)
meson setup builddir
cd builddir
# 编译 v4l2-compliance(只编译该工具,不编译其他组件)
ninja v4l2-compliance
# 编译完成后,二进制位于 builddir/utils/v4l2-compliance
./utils/v4l2-compliance --help
meson(≥0.55)、ninja、libudev-dev、libv4l-dev。如果只需要 v4l2-compliance,可以在 meson setup 时添加 -Dutils=enabled -Dlibv4l=false -Dv4l-utils=false 来减少编译时间。
2.2.2 作为内核 selftests 编译
# 进入内核源码树
cd /path/to/linux-kernel
# 配置 selftests
make -C tools/testing/selftests TARGETS=media
# 单独编译 v4l2-compliance
make -C tools/testing/selftests/media/v4l2-compliance
# 编译产物位于 tools/testing/selftests/media/v4l2-compliance/
ls -l tools/testing/selftests/media/v4l2-compliance/v4l2-compliance
2.3 基本命令行参数详解
v4l2-compliance 提供了丰富的命令行参数来控制测试范围、设备选择、输出格式等。以下是最核心的五个参数:-s、-m、-d、-c、-f。
| 参数 | 全称 | 功能说明 | 典型用法 |
|---|---|---|---|
-s |
--stream |
启用流式测试(streaming test),包括缓冲区申请、入队/出队、STREAMON/OFF 等 | v4l2-compliance -s |
-m |
--multiple |
多平面(multi-planar)测试模式,针对 MPLANE 类型的视频设备 | v4l2-compliance -m |
-d |
--device |
指定要测试的 V4L2 设备节点路径 | v4l2-compliance -d /dev/video0 |
-c |
--color |
启用彩色输出,使 PASS/FAIL/SKIP 结果更易区分 | v4l2-compliance -c |
-f |
--force |
强制测试所有用例,即使某些前置条件不满足(如无视频输入) | v4l2-compliance -f |
2.3.1 -s(流式测试)
默认情况下,v4l2-compliance 只执行静态 ioctl 测试(如 QUERYCAP、ENUM_FMT、G/S_FMT 等),不涉及数据流。添加 -s 参数后,工具会执行完整的流式测试流程:
- REQBUFS: 申请缓冲区(默认 4 个缓冲区)。
- QUERYBUF: 查询每个缓冲区的状态和内存信息。
- QBUF: 将所有缓冲区入队到驱动。
- STREAMON: 启动视频流。
- DQBUF: 出队缓冲区(等待驱动填充数据)。
- STREAMOFF: 停止视频流。
- REQBUFS(0): 释放所有缓冲区。
STREAMON 后无法产生数据,或 DQBUF 超时,-s 测试会直接报 FAIL。对于 capture 设备,建议始终使用 -s 进行完整测试。
2.3.2 -m(多平面模式)
V4L2 支持单平面(SINGLE_PLANE)和多平面(MULTI_PLANE)两种缓冲区模型。多平面模式用于 YUV 分量分离存储或元数据附加等场景。使用 -m 参数时,v4l2-compliance 会:
- 在
REQBUFS时使用V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE或V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE。 - 在
QBUF/DQBUF时使用struct v4l2_plane数组。 - 检查驱动是否正确处理
V4L2_BUF_FLAG_MULTIPLANE标志。
-m 跑一次,再带 -m 跑一次,对比结果。
2.3.3 -d(指定设备)
默认情况下,v4l2-compliance 会扫描 /dev/video0 到 /dev/video63 以及 /dev/v4l-subdev* 等所有 V4L2 设备节点。使用 -d 可以精确指定单个设备:
# 测试 /dev/video2
v4l2-compliance -d /dev/video2 -s
# 测试 /dev/v4l-subdev1(子设备)
v4l2-compliance -d /dev/v4l-subdev1
Permission denied,使用 sudo 或以 root 身份运行。
2.3.4 -c(彩色输出)
添加 -c 参数后,测试结果会使用 ANSI 转义码着色:
- PASS: 绿色高亮
- FAIL: 红色高亮
- SKIP: 黄色高亮
在终端中,这能显著提升测试结果的可读性,尤其是在大量测试用例输出时。
2.3.5 -f(强制测试)
某些测试用例需要前置条件(如设备必须有视频输入、必须有音频输入等)。默认情况下,如果前置条件不满足,v4l2-compliance 会跳过该测试。使用 -f 后,即使前置条件不满足,也会执行测试并报告 FAIL(如果驱动返回错误)或 PASS(如果驱动优雅地返回 EINVAL 或 ENOTTY)。
-f 可以确保所有 ioctl 都被调用到,即使某些功能尚未实现。这有助于发现驱动是否在未实现的功能上返回了错误的错误码(如返回 EIO 而不是 ENOTTY)。
下图展示了 v4l2-compliance 命令行参数与测试流程的对应关系:
2.4 参数组合使用示例
在实际测试中,通常需要组合多个参数来覆盖完整的测试场景。以下是一些典型组合:
| 命令 | 适用场景 | 说明 |
|---|---|---|
v4l2-compliance -d /dev/video0 -s -c |
单摄像头设备完整测试 | 指定设备、启用流式测试、彩色输出 |
v4l2-compliance -d /dev/video0 -s -m -c |
多平面摄像头设备测试 | 在单平面基础上增加多平面模式 |
v4l2-compliance -d /dev/video0 -f -c |
驱动开发阶段强制测试 | 即使前置条件不满足也执行所有用例 |
v4l2-compliance -s -c 2>&1 | tee test.log |
全设备扫描并保存日志 | 扫描所有设备,结果同时输出到终端和文件 |
1.
v4l2-compliance -d /dev/videoX -s -c(单平面流式测试)2.
v4l2-compliance -d /dev/videoX -s -m -c(多平面流式测试)3.
v4l2-compliance -d /dev/videoX -f -c(强制测试,检查错误码合规性)所有测试必须返回 0 FAIL,否则驱动存在合规性问题。
2.5 测试输出解读
v4l2-compliance 的输出格式清晰,每行包含测试名称、测试结果和简要说明。以下是一个典型输出片段:
# v4l2-compliance -d /dev/video0 -s -c
v4l2-compliance SHA: 1234567890ab, 64 bits, 64-bit time_t
Compliance test for device /dev/video0:
Driver Info:
Driver name : uvcvideo
Card type : USB Camera
Bus info : usb-0000:00:14.0-1
Driver version : 6.1.0
Capabilities : 0x84a00001
Video Capture
Streaming
Extended Pix Format
Device Capabilities
Required ioctls:
VIDIOC_QUERYCAP: OK
...
Streaming ioctls:
VIDIOC_REQBUFS: OK
VIDIOC_QUERYBUF: OK
VIDIOC_QBUF: OK
VIDIOC_DQBUF: OK
VIDIOC_STREAMON: OK
VIDIOC_STREAMOFF: OK
...
Total for /dev/video0: 45 PASS, 0 FAIL, 3 SKIP
PASS 表示测试通过;FAIL 表示驱动行为与 V4L2 规范不符,需要修复;SKIP 表示该测试因前置条件不满足(如设备不支持该功能)而被跳过。理想情况下,FAIL 应为 0,SKIP 数量应合理(取决于设备功能集)。