目录
[1. struct v4l2_capability](#1. struct v4l2_capability)
[2. struct v4l2_format](#2. struct v4l2_format)
[子结构:struct v4l2_pix_format](#子结构:struct v4l2_pix_format)
[3. struct v4l2_requestbuffers](#3. struct v4l2_requestbuffers)
[4. struct v4l2_buffer](#4. struct v4l2_buffer)
[5. struct v4l2_control / struct v4l2_ext_controls](#5. struct v4l2_control / struct v4l2_ext_controls)
[6.struct v4l2_fmtdesc](#6.struct v4l2_fmtdesc)
[7.struct v4l2_frmsizeenum / struct v4l2_frmivalenum](#7.struct v4l2_frmsizeenum / struct v4l2_frmivalenum)
[1. enum v4l2_buf_type](#1. enum v4l2_buf_type)
[注意:单平面 vs 多平面格式需匹配正确类型!](#注意:单平面 vs 多平面格式需匹配正确类型!)
[2. enum v4l2_memory](#2. enum v4l2_memory)
[3. enum v4l2_field](#3. enum v4l2_field)
[建议:IPC 摄像头基本都是逐行,设为 V4L2_FIELD_NONE。](#建议:IPC 摄像头基本都是逐行,设为 V4L2_FIELD_NONE。)
[4. enum v4l2_colorspace](#4. enum v4l2_colorspace)
[5. 像素格式枚举(__u32 pixelformat)](#5. 像素格式枚举(__u32 pixelformat))
[6. 控制 ID 枚举(V4L2_CID_*)](#6. 控制 ID 枚举(V4L2_CID_*))
[四、核心 VIDIOC_* 命令详解](#四、核心 VIDIOC_* 命令详解)
[五、ioctl 方向说明](#五、ioctl 方向说明)
一、前言
V4L2(Video for Linux 2)通过一组精心设计的 ioctl 命令 和 配套的数据结构/枚举类型,实现了对视频采集设备的统一抽象。
二、核心数据结构体
1. struct v4l2_capability
作用:查询设备基本信息和能力(只读)
cpp
struct v4l2_capability {
__u8 driver[16]; // 驱动名称(如 "uvcvideo")
__u8 card[32]; // 设备名(如 "USB Camera: USB Camera")
__u8 bus_info[32]; // 总线信息(如 "usb-0000:00:14.0-1")
__u32 version; // 驱动版本(主<<16 | 次<<8 | 修订)
__u32 capabilities; // 设备支持的功能位掩码
__u32 device_caps; // 当前设备节点的具体能力(Linux 3.1+)
__u32 reserved[3];
};
关键字段说明:
-
capabilities:常用标志位包括:V4L2_CAP_VIDEO_CAPTURE:支持视频采集(IPC 必需)V4L2_CAP_STREAMING:支持流式 I/O(mmap/userptr)V4L2_CAP_READWRITE:支持 read/write 接口(性能差,不推荐)
-
使用方式 :
cppstruct v4l2_capability cap; ioctl(fd, VIDIOC_QUERYCAP, &cap); if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { fprintf(stderr, "Not a capture device!\n"); }
2. struct v4l2_format
作用:设置或获取视频格式(分辨率、像素格式等)
cpp
struct v4l2_format {
enum v4l2_buf_type type; // 缓冲区类型(如 V4L2_BUF_TYPE_VIDEO_CAPTURE)
union {
struct v4l2_pix_format pix; // 用于视频帧
struct v4l2_pix_format_mplane pix_mp; // 多平面格式(如 NV12)
struct v4l2_window win; // Overlay 输出(已弃用)
struct v4l2_vbi_format vbi; // 垂直消隐期数据
struct v4l2_sliced_vbi_format sliced; // 切片 VBI
__u8 raw_data[200]; // 原始数据
};
};
子结构:struct v4l2_pix_format
cpp
struct v4l2_pix_format {
__u32 width; // 图像宽度(像素)
__u32 height; // 图像高度(像素)
__u32 pixelformat; // 像素格式(四字符编码,如 'YUYV')
__u32 field; // 场序(逐行/隔行)
__u32 bytesperline; // 每行字节数(可为 0 表示由驱动计算)
__u32 sizeimage; // 单帧图像总大小(字节)
__u32 colorspace; // 色彩空间(如 sRGB、Rec.709)
__u32 priv; // 私有数据(已弃用,改用 flags)
__u32 flags; // 格式标志(如 V4L2_PIX_FMT_FLAG_PREMUL_ALPHA)
};
##
IPC 开发注意:
设置后务必检查返回值!驱动可能调整 width/height/sizeimage。
bytesperline 若设为 0,驱动会自动对齐(通常按 16 字节对齐)。
3. struct v4l2_requestbuffers
作用:请求内核分配缓冲区队列
cpp
struct v4l2_requestbuffers {
__u32 count; // 请求的缓冲区数量(≥2)
enum v4l2_buf_type type; // 缓冲区类型
enum v4l2_memory memory; // 内存类型(mmap / userptr / dmabuf)
__u32 reserved[2];
};
关键点:
count:通常设为 3~8。太少易丢帧,太多增加延迟。memory:IPC 最常用V4L2_MEMORY_MMAP(零拷贝)。
4. struct v4l2_buffer
作用:描述单个缓冲区的状态(入队/出队/元数据)
cpp
struct v4l2_buffer {
__u32 index; // 缓冲区索引(0 ~ count-1)
enum v4l2_buf_type type; // 类型
__u32 bytesused; // 实际数据字节数(关键!)
__u32 flags; // 状态标志(如时间戳有效性)
enum v4l2_field field; // 场信息
struct timeval timestamp; // 帧捕获时间戳
struct v4l2_timecode timecode; // 时间码(专业视频)
__u32 sequence; // 帧序号(从0开始递增)
enum v4l2_memory memory; // 内存类型
union {
__u32 offset; // mmap 偏移量
unsigned long userptr; // 用户指针地址
struct v4l2_plane *planes; // 多平面指针
__s32 fd; // dma-buf 文件描述符
} m;
__u32 length; // 缓冲区总大小(字节)
__u32 reserved2;
__u32 reserved;
};
IPC 关键字段:
index:标识是哪个缓冲区(对应 mmap 映射数组)bytesused:实际帧大小(对 MJPEG/H.264 至关重要)timestamp:用于计算帧率、同步sequence:检测丢帧(应连续递增)
5. struct v4l2_control / struct v4l2_ext_controls
作用:控制摄像头参数(曝光、增益、白平衡等)
cpp
struct v4l2_control {
__u32 id; // 控制 ID(如 V4L2_CID_BRIGHTNESS)
__s32 value; // 控制值
};
// 批量控制(推荐)
struct v4l2_ext_controls {
__u32 ctrl_class; // 控制类别(如 V4L2_CTRL_CLASS_CAMERA)
__u32 count; // 控制项数量
__u32 error_idx; // 出错项索引
__u32 reserved[2];
struct v4l2_ext_control *controls; // 控制数组
};
struct v4l2_ext_control {
__u32 id;
__u32 size; // 用于字符串控件
__u32 reserved2[1];
union {
__s32 value; // 整数值
__s64 value64; // 64位值
char *string; // 字符串(如 camera name)
__u8 *p_u8; // 8位数组
__u16 *p_u16; // 16位数组
__u32 *p_u32; // 32位数组
void *ptr; // 通用指针
};
};
IPC 常用控制 ID:
V4L2_CID_EXPOSURE_AUTO:自动曝光开关V4L2_CID_EXPOSURE:手动曝光值V4L2_CID_GAIN:模拟增益V4L2_CID_WHITE_BALANCE_TEMPERATURE:色温(K)
6.struct v4l2_fmtdesc
作用:枚举设备支持的所有像素格式
cpp
struct v4l2_fmtdesc {
__u32 index; // 格式索引(从0开始)
enum v4l2_buf_type type; // 类型
__u32 flags; // 格式标志(如压缩)
__u8 description[32]; // 格式描述字符串
__u32 pixelformat; // 像素格式 FourCC
__u32 reserved[4];
};
用法:
cpp
struct v4l2_fmtdesc fmtdesc = {0};
fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
for (fmtdesc.index = 0; ; fmtdesc.index++) {
if (ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc) < 0) break;
printf("Format %d: %.4s (%s)\n", fmtdesc.index,
(char*)&fmtdesc.pixelformat, fmtdesc.description);
}
7.struct v4l2_frmsizeenum / struct v4l2_frmivalenum
作用:枚举某格式支持的分辨率和帧率
cpp
// 查询分辨率
struct v4l2_frmsizeenum fsize = {0};
fsize.pixel_format = V4L2_PIX_FMT_YUYV;
for (fsize.index = 0; ; fsize.index++) {
if (ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &fsize) < 0) break;
if (fsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
printf("Resolution: %dx%d\n", fsize.discrete.width, fsize.discrete.height);
}
}
// 查询帧率(需先指定分辨率)
struct v4l2_frmivalenum fival = {0};
fival.pixel_format = V4L2_PIX_FMT_YUYV;
fival.width = 640; fival.height = 480;
for (fival.index = 0; ; fival.index++) {
if (ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &fival) < 0) break;
if (fival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
printf("FPS: %d/%d = %.2f\n",
fival.discrete.denominator, fival.discrete.numerator,
(double)fival.discrete.denominator / fival.discrete.numerator);
}
}
8.struct v4l2_queryctrl
作用:查询 control 能力的 ioctl 命令
cpp
struct v4l2_queryctrl {
__u32 id; // 控制ID(如 V4L2_CID_BRIGHTNESS)
__u32 type; // 控制类型(见下表)
__u8 name[32]; // 控制名称(如 "Brightness")
__s32 minimum; // 最小值
__s32 maximum; // 最大值
__s32 step; // 步长
__s32 default_value; // 默认值
__u32 flags; // 标志(如 disabled)
__u32 reserved[2];
};
三、核心枚举类型
1. enum v4l2_buf_type
作用:指定缓冲区用途类型
| 枚举值 | 说明 |
|---|---|
V4L2_BUF_TYPE_VIDEO_CAPTURE |
视频采集(IPC 主要用此) |
V4L2_BUF_TYPE_VIDEO_OUTPUT |
视频输出(如 HDMI 输出) |
V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE |
多平面采集(如 NV12 分 Y/UV 平面) |
V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE |
多平面输出 |
注意:单平面 vs 多平面格式需匹配正确类型!
2. enum v4l2_memory
作用:指定缓冲区内存管理方式
| 枚举值 | 说明 | IPC 适用性 |
|---|---|---|
V4L2_MEMORY_MMAP |
内核分配,用户 mmap 映射 | 最常用,零拷贝 |
V4L2_MEMORY_USERPTR |
用户分配内存,传指针给驱动 | 需物理连续内存(ARM 通常不可用) |
V4L2_MEMORY_DMABUF |
使用 dma-buf 共享缓冲区 | 适用于多进程/硬件加速(如 GPU/NPU) |
3. enum v4l2_field
作用:指定视频场序(逐行 or 隔行)
| 枚举值 | 说明 |
|---|---|
V4L2_FIELD_NONE |
逐行扫描(IPC 绝大多数用此) |
V4L2_FIELD_INTERLACED |
隔行扫描(先顶场后底场) |
V4L2_FIELD_TOP / V4L2_FIELD_BOTTOM |
单一场 |
建议 :IPC 摄像头基本都是逐行,设为 V4L2_FIELD_NONE。
4. enum v4l2_colorspace
作用:定义色彩空间标准
| 枚举值 | 说明 |
|---|---|
V4L2_COLORSPACE_SRGB |
sRGB(普通摄像头) |
V4L2_COLORSPACE_REC709 |
HDTV(Rec.709) |
V4L2_COLORSPACE_JPEG |
Full-range YUV(0-255) |
V4L2_COLORSPACE_SMPTE170M |
SDTV(NTSC/PAL) |
注意 :错误的色彩空间会导致颜色失真!通常摄像头默认为 V4L2_COLORSPACE_SRGB 或 V4L2_COLORSPACE_JPEG。
5. 像素格式枚举(__u32 pixelformat)
虽然不是 C 枚举,但以宏形式定义,本质是四字符编码(FourCC):
| 宏 | FourCC | 说明 |
|---|---|---|
V4L2_PIX_FMT_YUYV |
'YUYV' | YUV 4:2:2 packed(最通用) |
V4L2_PIX_FMT_UYVY |
'UYVY' | 同上,UV 顺序不同 |
V4L2_PIX_FMT_MJPEG |
'MJPG' | Motion JPEG(压缩流) |
V4L2_PIX_FMT_H264 |
'H264' | H.264 码流(需硬件编码器) |
V4L2_PIX_FMT_RGB24 |
'RGB3' | 24-bit RGB(低效,慎用) |
V4L2_PIX_FMT_GREY |
'GREY' | 8-bit 灰度图 |
V4L2_PIX_FMT_SRGGB8 |
'RGGB' | Bayer RAW 格式(R-G-G-B 排列) |
V4L2_PIX_FMT_NV12 |
'NV12' | YUV 4:2:0 planar(Y 平面 + UV interleaved) |
IPC 提示:
- UVC 摄像头常用
YUYV或MJPEG - SoC ISP 输出常用
NV12(节省带宽) - AI 推理常需
RGB或GRAY,需软件转换
6. 控制 ID 枚举(V4L2_CID_*)
部分常用控制 ID:
| 控制 ID | 类型 | 说明 |
|---|---|---|
V4L2_CID_BRIGHTNESS |
integer | 亮度 |
V4L2_CID_CONTRAST |
integer | 对比度 |
V4L2_CID_SATURATION |
integer | 饱和度 |
V4L2_CID_HUE |
integer | 色调 |
V4L2_CID_AUTO_WHITE_BALANCE |
boolean | 自动白平衡开关 |
V4L2_CID_WHITE_BALANCE_TEMPERATURE |
integer | 色温(单位:K) |
V4L2_CID_EXPOSURE_AUTO |
menu | 自动曝光模式 |
V4L2_CID_EXPOSURE |
integer | 手动曝光时间(单位依赖驱动) |
V4L2_CID_GAIN |
integer | 模拟增益 |
V4L2_CID_ZOOM_ABSOLUTE |
integer | 数字变焦 |
查询控制范围:
cpp
struct v4l2_queryctrl qctrl = {.id = V4L2_CID_EXPOSURE};
ioctl(fd, VIDIOC_QUERYCTRL, &qctrl);
printf("Exposure: min=%d, max=%d, step=%d\n", qctrl.minimum, qctrl.maximum, qctrl.step);
四、核心 VIDIOC_* 命令详解
V4L2(Video for Linux 2)框架中用于 ioctl 系统调用的命令标识符(ioctl command codes) 。
每个 VIDIOC_XXX 对应一个唯一的整数,用于告诉内核:"我要执行 XXX 操作"。
- 命名规则 :
VIDIOC= V ideo I/O Control - 用途 :用户空间程序通过
ioctl(fd, VIDIOC_XXX, &arg)与 V4L2 驱动通信。 - 本质 :是一组预定义的宏(
#define),由内核提供。 - 位置 :所有
VIDIOC_*宏均定义在 Linux 内核头文件中:#include <linux/videodev2.h>
| 宏名称 | 全称 / 含义 | ioctl 方向 | 参数类型 | 主要作用 | 使用阶段 |
|---|---|---|---|---|---|
VIDIOC_QUERYCAP |
QUERY CAPability | _IOR(只读) |
struct v4l2_capability* |
查询设备基本信息和能力(是否支持 capture/streaming 等) | 初始化 |
VIDIOC_S_FMT |
S et FMT (format) | _IOWR(读写) |
struct v4l2_format* |
设置视频格式(分辨率、像素格式、场序等) | 初始化 |
VIDIOC_G_FMT |
G et FMT | _IOR |
struct v4l2_format* |
获取当前视频格式 | 调试/初始化 |
VIDIOC_TRY_FMT |
TRY FMT | _IOWR |
struct v4l2_format* |
测试格式是否支持(不实际设置) | 初始化前验证 |
VIDIOC_REQBUFS |
REQ uest BUF ferS | _IOWR |
struct v4l2_requestbuffers* |
请求内核分配缓冲区队列(mmap/userptr) | 缓冲区准备 |
VIDIOC_QUERYBUF |
QUERY BUFfer | _IOWR |
struct v4l2_buffer* |
查询缓冲区元数据(如 offset、length),用于 mmap | 缓冲区映射 |
VIDIOC_QBUF |
Q ueue BUFfer | _IOW |
struct v4l2_buffer* |
将空缓冲区入队,交给驱动填充 | 流启动后循环使用 |
VIDIOC_DQBUF |
D eQ ueue BUFfer | _IOWR |
struct v4l2_buffer* |
出队已填充的帧缓冲区 | 主采集循环 |
VIDIOC_STREAMON |
STREAM ON | _IOW |
enum v4l2_buf_type* |
启动视频流(开始 DMA 传输) | 流控制 |
VIDIOC_STREAMOFF |
STREAM OFF | _IOW |
enum v4l2_buf_type* |
停止视频流(停止 DMA) | 流控制 / 退出 |
VIDIOC_QUERYCTRL |
QUERY CTRL (control) | _IOWR |
struct v4l2_queryctrl* |
查询某个 control(如曝光、增益)的能力信息(范围、类型、是否禁用) | 控制参数配置 |
VIDIOC_G_CTRL |
G et CTRL | _IOWR |
struct v4l2_control* |
获取单个 control 的当前值 | 控制读取 |
VIDIOC_S_CTRL |
S et CTRL | _IOWR |
struct v4l2_control* |
设置单个 control 的值 | 控制写入 |
VIDIOC_G_EXT_CTRLS |
G et EXT ended CTRLS | _IOWR |
struct v4l2_ext_controls* |
批量获取 controls 值(推荐) | 高级控制 |
VIDIOC_S_EXT_CTRLS |
S et EXT ended CTRLS | _IOWR |
struct v4l2_ext_controls* |
批量设置 controls 值(推荐) | 高级控制 |
VIDIOC_ENUM_FMT |
ENUM erate FMT | _IOWR |
struct v4l2_fmtdesc* |
枚举设备支持的所有像素格式 | 调试 / 自适应 |
VIDIOC_ENUM_FRAMESIZES |
ENUM erate FRAME SIZES | _IOWR |
struct v4l2_frmsizeenum* |
枚举某格式支持的分辨率 | 调试 |
VIDIOC_ENUM_FRAMEINTERVALS |
ENUM erate FRAME INTERVALS | _IOWR |
struct v4l2_frmivalenum* |
枚举某分辨率下的帧率 | 调试 |
五、ioctl 方向说明
1.位置:(来自 <asm/ioctl.h>)
_IO(type, nr):无数据传递_IOR(type, nr, data_type):从内核读取数据到用户空间(Read)_IOW(type, nr, data_type):向内核写入数据(Write)_IOWR(type, nr, data_type):先写入再读出(Write-Read),最常见
2、实例:
cpp
// VIDIOC_QUERYCAP 是只读:内核填写 capability 结构体返回给用户
#define VIDIOC_QUERYCAP _IOR('V', 0, struct v4l2_capability)
// VIDIOC_S_FMT 是读写:用户传入期望格式,内核返回实际生效格式
#define VIDIOC_S_FMT _IOWR('V', 5, struct v4l2_format)