-
Notifications
You must be signed in to change notification settings - Fork 2
V4L2Param_ParamControl
SweerItTer edited this page Feb 21, 2026
·
4 revisions
ParamControl 是 utilsCore V4L2 参数模块的核心类,提供 V4L2 设备参数的查询、设置和控制功能。
- 查询 V4L2 设备的控制参数
- 设置和获取 V4L2 参数值
- 提供参数信息的缓存机制
- 参数变更检测
- 摄像头参数调整(亮度、对比度、饱和度等)
- 自动曝光和白平衡控制
- 参数监控和日志记录
- 动态参数调整
- 依赖: V4L2 设备文件描述符
- 被依赖: ParamProcessor, ParamLogger 等上层模块
ParamControl 是 V4L2 参数控制的封装类,提供:
- 参数查询和信息获取
- 参数设置和获取
- 参数信息缓存
- 参数变更检测
- RAII: 自动管理资源
V4L2ControlInfo 存储 V4L2 控制参数的详细信息。
struct V4L2ControlInfo {
__u32 id = 0; // 控制ID
std::string name = ""; // 控制名称
int32_t min = 0; // 最小值
int32_t max = 0; // 最大值
int32_t step = 0; // 步进值
uint32_t type = 0; // 控制类型(值调整/状态开关)
int32_t current = 0; // 当前值
};| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
id |
__u32 |
0 | V4L2 控制ID(如 V4L2_CID_BRIGHTNESS) |
name |
string |
"" | 控制名称 |
min |
int32_t |
0 | 最小值 |
max |
int32_t |
0 | 最大值 |
step |
int32_t |
0 | 步进值 |
type |
`uint32_t | 0 | 控制类型(值调整/状态开关) |
current |
int32_t |
0 | 当前值 |
explicit ParamControl(const std::string& devicePath);
explicit ParamControl(int externalFd);
~ParamControl();参数说明:
-
devicePath(输入): V4L2 设备路径(如 "/dev/video0") -
externalFd(输入): 外部文件描述符
返回值: 无
所有权归属:
- devicePath 构造: ParamControl 打开设备 fd,负责关闭
- externalFd 构造: ParamControl 不负责关闭 fd
注意事项:
- 构造时会查询所有可用的控制参数
- devicePath 构造会打开设备并拥有 fd
- externalFd 构造使用外部 fd,不负责关闭
- fd 必须有效且已打开
使用例程:
// 使用设备路径构造(ParamControl 负责打开和关闭)
ParamControl paramControl("/dev/video0");
// 使用外部 fd 构造(不负责关闭)
int camera_fd = open("/dev/video0", O_RDWR);
ParamControl paramControl(cameraFd);
// ...
close(camera_fd); // 调用者负责关闭bool setControl(__u32 id, int32_t value);参数说明:
-
id(输入): 控制ID(如 V4L2_CID_BRIGHTNESS) -
value(输入): 要设置的值
返回值:
-
true: 成功 -
false: 失败
所有权归属: 无所有权转移
注意事项:
- 值必须在 min 和 max 范围内
- 某些控制可能被禁用
- 设置后会自动更新 current 字段
使用例程:
ParamControl paramControl("/dev/video0");
// 设置亮度
if (paramControl.setControl(V4L2_CID_BRIGHTNESS, 50)) {
printf("Brightness set to 50\n");
}
// 设置曝光
if (paramControl.setControl(V4L2_CID_EXPOSURE_ABSOLUTE, 100)) {
printf("Exposure set to 100\n");
}bool getControl(__u32 id, int32_t& value) const;参数说明:
-
id(输入): 控制ID -
value(输出): 控制参数值
返回值:
-
true: 成功 -
false: 失败
所有权归属:
- 返回值由调用者持有
注意事项:
- 控制ID 必须有效
- 如果控制不存在,返回 false
- 使用前检查返回值
使用例程:
ParamControl paramControl("/dev/video0");
int32_t brightness;
if (paramControl.getControl(V4L2_CID_BRIGHTNESS, brightness)) {
printf("Current brightness: %d\n", brightness);
}
int32_t exposure;
if (paramControl.getControl(V4L2_CID_EXPOSURE_ABSOLUTE, exposure)) {
printf("Current exposure: %d\n", exposure);
}bool queryControl(__u32 id);参数说明:
-
id(input): 控制ID
返回值:
-
true: 控制存在 -
false: 控制不存在
注意事项:
- 查询单个控制参数是否存在
- 不返回参数信息
- 用于验证控制ID 是否有效
ControlInfos queryAllControls() const;参数说明: 无
返回值:
- 成功: 返回所有控制参数的列表(ControlInfos = std::vector)
- 失败: 返回空列表
所有权归属:
- 返回的列表由调用者持有
- ParamControl 内部缓存参数信息
注意事项:
- 返回类型为
ControlInfos(std::vector<V4L2ControlInfo>) - 每个控制包含 id, name, min, max, step, type, current 字段
- 首次调用时会查询设备,后续调用使用缓存
使用例程:
ParamControl paramControl("/dev/video0");
// 查询所有控制参数
auto controls = paramControl.queryAllControls();
for (const auto& ctrl : controls) {
printf("%s: id=%u, range=[%d, %d], current=%d, type=%u\n",
ctrl.name.c_str(), ctrl.id, ctrl.min, ctrl.max, ctrl.current, ctrl.type);
}
// 查找曝光控制
for (const auto& ctrl : controls) {
if (ctrl.name.find("Exposure") != std::string::npos) {
printf("Found exposure control: %s (id=%u)\n", ctrl.name.c_str(), ctrl.id);
}
}static ControlInfos diffParamInfo(const ControlInfos& oldInfo, const ControlInfos& newInfo);参数说明:
-
oldInfo(输入): 旧的参数信息列表 -
newInfo(输入): 新的参数信息列表
返回值: 返回发生变化的控制参数列表
所有权归属: 无所有权转移
注意事项:
- 静态方法,不需要实例
- 对比 current 字段是否变化
- 返回值包含 current 不同的 V4L2ControlInfo
使用例程:
ParamControl paramControl("/dev/video0");
// 第一次查询
auto controls1 = paramControl.queryAllControls();
// 修改参数
paramControl.setControl(V4L2_CID_BRIGHTNESS, 50);
// 第二次查询
auto controls2 = paramControl.queryAllControls();
// 对比差异
auto diff = ParamControl::diffParamInfo(controls1, controls2);
for (const auto& ctrl : diff) {
printf("Changed: %s: %d → %d\n", ctrl.name.c_str(), ctrl.min, ctrl.max);
}static bool isSwitchControl(const V4L2ControlInfo& info);参数说明:
-
info(输入): V4L2ControlInfo 引用
返回值:
-
true: 是开关控制(如 V4L2_CID_POWER_LINE_FREQUENCY) -
false: 不是开关控制
注意事项:
- 静态方法,不需要实例
- 根据 type 字段判断
static bool isValueControl(const V4L2ControlInfo& info);参数说明- info (输入): V4L2ControlInfo 引用
返回值:
-
true: 是值控制(如 V4L2_CID_BRIGHTNESS) -
false: 不是值控制
注意事项:
- 静态方法,不需要实例
- 根据 type 字段判断
class ParamControl {
private:
int fd_ = -1; // V4L2 设备文件描述符
bool ownsFd_ = false; // 是否拥有 fd(构造时决定)
};-
devicePath构造:ownsFd_ = true,析构时自动关闭 fd -
externalFd构造:ownsFd_ = false,析构时不关闭 fd - 调用者负责管理 externalFd 的生命周期
// src/pipeline/visionPipeline.cpp:178-189
void VisionPipeline::Impl::v4l2ControllerInit() {
int cameraFd = camera->getDeviceFd();
v4l2Controller = std::make_unique<ParamControl>(cameraFd);
currentControls_ = v4l2Controller->queryAllControls();
size_t size = currentControls_.size();
for(size_t index=0; index<size; ++index){
auto& controlInfo = currentControls_[index];
if (controlInfo.id != V4L2_CID_EXPOSURE) continue;
exposureIdInControls = index;
break;
}
}ParamControl paramControl("/dev/video0");
// 设置镜像模式
paramControl.setControl(V4L2_CID_HFLIP, 1); // 水平镜像
paramControl.setControl(V4L2_CID_VFLIP, 0); // 不垂直镜像
// 设置曝光百分比(需要计算实际值)
auto controls = paramControl.queryAllControls();
for (const auto& ctrl : controls) {
if (ctrl.id == V4L2_CID_EXPOSURE_ABSOLUTE) {
int32_t target = ctrl.min + (ctrl.max - ctrl.min) * percentage / 100;
paramControl.setControl(ctrl.id, target);
}
}ParamControl paramControl("/dev/video0");
// 保存原始值
auto controls_old = paramControl.queryAllControls();
// 修改参数
paramControl.setControl(V4L2_CID_BRIGHTNESS, 50);
// 获取新值
auto controls_new = paramControl.queryAllControls();
// 检测变化
auto diff = ParamControl::diffParamInfo(controls_old, controls_new);
for (const auto& ctrl : diff) {
printf("%s: %d → %d\n", ctrl.name.c_str(), ctrl.min, ctrl.current);
}- 构造方式: 两种构造方式(devicePath 和 externalFd),所有权管理不同
- fd 所有权: devicePath 构造时 ParamControl 拥有 fd,externalFd 构造时调用者拥有 fd
- 参数范围: 设置值必须在 min 和 max �范围内
- 控制类型: 使用 isSwitchControl() 和 isValueControl() 判断控制类型
- 缓存机制: queryAllControls() 使用缓存,首次调用时查询设备
- 线程安全: ParamControl 本身不是线程安全的,需要外部同步
- 错误处理: 所有方法返回 bool,调用者需要检查返回值
- 参数名称: name 字段可用于查找特定参数
- ParamProcessor - 参数自动处理
- ParamLogger - 参数日志记录
- V4L2Param 模块总览
主页
API 文档
DMA 模块
DRM 模块
- DRM 模块总览
- DeviceController - DRM 设备控制器
- DrmLayer - DRM 图层管理
- PlanesCompositor - DRM 平面合成器
- DrmBpp - DRM 格式定义
NET 模块
- NET 模块总览
- TcpServer - TCP 服务器
- SocketConnection - Socket 连接管理
- CommandHandler - 命令处理器
- DataPacket - 数据包
V4L2 模块
- V4L2 模块总览
- CameraController - V4L2 摄像头控制器
- Frame - V4L2 帧数据结构
- FormatTool - V4L2 格式工具
- Exception - V4L2 异常类
V4L2Param 模块
- V4L2Param 模块总览
- ParamControl - 参数控制
- ParamLogger - 参数日志
- ParamProcessor - 参数处理器
RGA 模块
- RGA 模块总览
- RgaConverter - RGA 转换器
- RgaProcessor - RGA 处理器
- FormatTool - RGA 格式工具
MPP 模块
- MPP 模块总览
- EncoderContext - 编码器上下文
- EncoderCore - 编码器核心
- JpegEncoder - JPEG 编码器
- StreamWriter - 流写入器
- MppResourceGuard - MPP 资源守护
- FileTools - 文件工具
- FormatTool - 格式工具
Sys 模块
- Sys 模块总览
- CpuMonitor - CPU 监控器
- MemoryMonitor - 内存监控器
- Base - 基础类
Mouse 模块
- Mouse 模块总览
- Watcher - 鼠标监视器
Utils 模块
- Utils 模块总览
- AsyncThreadPool - 异步线程池
- ConcurrentQueue - 并发队列
- FdWrapper - 文件描述符包装器
- FenceWatcher - 围栏监视器
- FixedSizePool - 固定大小对象池
- Logger - 日志记录器
- ObjectsPool - 对象池
- OrderedQueue - 有序队列
- ProgressBar - 进度条
- SafeQueue - 安全队列
- SharedBufferState - 共享缓冲区状态
- SimpleVariant - 简单变体类型
- ThreadPauser - 线程暂停器
- ThreadUtils - 线程工具
- Types - 类型定义
- UdevMonitor - Udev 监视器