2.15 V4L2 controls
V4L2 controls 用于控制和调整视频设备的各种参数.
2.15.2 Objects in the framework
struct v4l2_ctrl
描述了 control properties 和对应的 value.
struct v4l2_ctrl_handler
用来跟踪 v4l2_ctrl objects.
2.15.3 Basic usage for V4L2 and sub-device drivers
prepare the driver
通常把 v4l2_ctrl_handler 放在 top-level struct:
// v4l2 drvier:
struct foo_dev {
...
struct v4l2_device v4l2_dev;
...
struct v4l2_ctrl_handler ctrl_handler;
...
};
// sub-dev driver:
struct foo_dev {
...
struct v4l2_subdev sd;
...
struct v4l2_ctrl_handler ctrl_handler;
...
};
通过 v4l2_ctrl_handler_init(&foo->ctrl_handler, nr_of_controls)
初始化 v4l2_ctrl_handler
.
其中 nr_of_controls 表示这个 v4l2_ctrl_handler 控制多少个 v4l2_control.
再把v4l2_ctrl_handler hook 到对应的结构体:
// v4l2 driver:
foo->v4l2_dev.ctrl_handler = &foo->ctrl_handler;
// sub-dev driver:
foo->sd.ctrl_handler = &foo->ctrl_handler;
清理:
v4l2_ctrl_handler_free(&foo->ctrl_handler);
add control
之后通过一系列 api 创建不同的 controls:
struct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops,
u32 id, s64 min, s64 max, u64 step, s64 def)
struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops,
u32 id, u8 _max, u64 mask, u8 _def)
struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops, u32 id, u8 _max,
u64 mask, u8 _def, const char * const *qmenu)
struct v4l2_ctrl *v4l2_ctrl_new_std_compound(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops, u32 id,
const union v4l2_ctrl_ptr p_def)
struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops,
u32 id, u8 _max, u8 _def, const s64 *qmenu_int)
struct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_config *cfg, void *priv)
v4l2_ctrl_new_std()
: add standard non-menu control. non-menu control 是一些数值的 control, 比如 brightness, contrast, saturation 等.
v4l2_ctrl_new_std_menu()
: add standard menu control. menu control 是一些可供选择的 predefined options, 比如 input source, video format 等.
v4l2_ctrl_new_std_menu_items()
: add standard menu control, 不过 menu 值是 driver 自定义的*qmenu, driver specific menu control.
v4l2_ctrl_new_std_compound()
: 一些复合的 standard controls, 比如mpeg2, h264, 这时候需要传入v4l2_ctrl_ptr, 不同的结构体指针.
v4l2_ctrl_new_int_menu()
: add standard menu control, 这里 control 的值是 integer.
v4l2_ctrl_new_custom
: add custom control. 不是v4l2 规范的自定义 control.
这些函数通常紧跟在 v4l2_ctrl_handler_init()
初始化后.
force initial control setup
v4l2_ctrl_handler_setup(&foo->ctrl_handler)
强制对所有 v4l2_ctrl 调用 s_ctrl 来初始化.
实现 v4l2_ctrl_ops
通常只需要实现 .s_ctrl 回调.
static const struct v4l2_ctrl_ops foo_ctrl_ops = {
.s_ctrl = foo_s_ctrl,
};
2.15.4 Inheriting Sub-device Controls
subdev driver 的 v4l2-controls 会自动的加入到 v4l2 driver.
如果 subdev 包含 v4l2 driver 已经有的 controls, 那么会被跳过.
2.15.5 Accessing Control Values
2.15.6 Menu Controls
2.15.7 Custom Controls
driver specific controls 可以通过 v4l2_ctrl_new_custom()
来创建.
static const struct v4l2_ctrl_config ctrl_filter = {
.ops = &ctrl_custom_ops,
.id = V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER,
.name = "Spatial Filter",
.type = V4L2_CTRL_TYPE_INTEGER,
.flags = V4L2_CTRL_FLAG_SLIDER,
.max = 15,
.step = 1,
};
ctrl = v4l2_ctrl_new_custom(&foo->ctrl_handler, &ctrl_filter, NULL);
2.15.7 v4l2_ctrl functions and data structures
#define v4l2_ctrl_handler_init(hdl, nr_of_controls_hint);
void v4l2_ctrl_handler_free(struct v4l2_ctrl_handler *hdl);
int v4l2_ctrl_handler_setup(struct v4l2_ctrl_handler *hdl);
void v4l2_ctrl_handler_log_status(struct v4l2_ctrl_handler *hdl,
const char *prefix);
struct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops,
u32 id, s64 min, s64 max, u64 step, s64 def)
struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops,
u32 id, u8 _max, u64 mask, u8 _def)
struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops, u32 id, u8 _max,
u64 mask, u8 _def, const char * const *qmenu)
struct v4l2_ctrl *v4l2_ctrl_new_std_compound(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops, u32 id,
const union v4l2_ctrl_ptr p_def)
struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops,
u32 id, u8 _max, u8 _def, const s64 *qmenu_int)
struct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_config *cfg, void *priv)
int v4l2_ctrl_add_handler(struct v4l2_ctrl_handler *hdl,
struct v4l2_ctrl_handler *add,
v4l2_ctrl_filter filter,
bool from_other_dev);
void v4l2_ctrl_cluster(unsigned int ncontrols, struct v4l2_ctrl **controls);
void v4l2_ctrl_auto_cluster(unsigned int ncontrols,
struct v4l2_ctrl **controls,
u8 manual_val, bool set_volatile);
struct v4l2_ctrl *v4l2_ctrl_find(struct v4l2_ctrl_handler *hdl, u32 id);
void v4l2_ctrl_activate(struct v4l2_ctrl *ctrl, bool active);
static inline void v4l2_ctrl_grab(struct v4l2_ctrl *ctrl, bool grabbed);
static inline int v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl,
s64 min, s64 max, u64 step, s64 def);
static inline int v4l2_ctrl_modify_dimensions(struct v4l2_ctrl *ctrl,
u32 dims[V4L2_CTRL_MAX_DIMS]);
void v4l2_ctrl_notify(struct v4l2_ctrl *ctrl, v4l2_ctrl_notify_fnc notify,
void *priv);
const char *v4l2_ctrl_get_name(u32 id);
const char * const *v4l2_ctrl_get_menu(u32 id);
const s64 *v4l2_ctrl_get_int_menu(u32 id, u32 *len);
s32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl);
static inline int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val);
static inline int v4l2_ctrl_s_ctrl_string(struct v4l2_ctrl *ctrl, const char *s);
static inline int v4l2_ctrl_s_ctrl_compound(struct v4l2_ctrl *ctrl,
enum v4l2_ctrl_type type,
const void *p);