【Linux】V4L2框架分析绪论
0 引言
初学者代码学习,感谢指正。
我们介绍v4l2的整体框架,整体框架从何而来,肯定是要看数据结构。看数据结构是如何关联的。就能知道v4l2的大体框架。
首先明确一个大体方向:
v4l2是主题,media_controller只是一个管理拓扑的工具,即使没有它,也能正常工作。它的主要作用,是帮忙链接整条链路,看看数据链是否打通。一般是__media_start_pipeline函数。
1 结构体

这里是几个核心结构体,他们通过如图所示的链表相互关联。能看到,基本都挂载到了v4l2-device这个结构体上,所以它是老大,也是最顶层的结构体。v4l2框架,实际就是围绕着它进行注册。
2 v4l2_device
struct v4l2_device {
struct device *dev;
struct media_device *mdev;
struct list_head subdevs;
spinlock_t lock;
char name[V4L2_DEVICE_NAME_SIZE];
void (*notify)(struct v4l2_subdev *sd,
unsigned int notification, void *arg);
struct v4l2_ctrl_handler *ctrl_handler;
struct v4l2_prio_state prio;
struct kref ref;
void (*release)(struct v4l2_device *v4l2_dev);
};
它里面的核心是:
struct media_device *mdev;
struct list_head subdevs;
struct list_head subdevs,里面挂载了v4l2所有的子设备,当需要使用子系统的函数时,使用v4l2-call_xxx,即可调用。subdev里的const struct v4l2_subdev_ops *ops; 字段,即是这个subdev所支持的回调函数。
3 subdev
struct v4l2_subdev_ops {
const struct v4l2_subdev_core_ops *core;
const struct v4l2_subdev_tuner_ops *tuner;
const struct v4l2_subdev_audio_ops *audio;
const struct v4l2_subdev_video_ops *video;
const struct v4l2_subdev_vbi_ops *vbi;
const struct v4l2_subdev_ir_ops *ir;
const struct v4l2_subdev_sensor_ops *sensor;
const struct v4l2_subdev_pad_ops *pad;
};
struct v4l2_subdev {
#if defined(CONFIG_MEDIA_CONTROLLER)
struct media_entity entity;
#endif
struct list_head list;
struct module *owner;
bool owner_v4l2_dev;
u32 flags;
struct v4l2_device *v4l2_dev;
const struct v4l2_subdev_ops *ops;
const struct v4l2_subdev_internal_ops *internal_ops;
struct v4l2_ctrl_handler *ctrl_handler;
char name[V4L2_SUBDEV_NAME_SIZE];
u32 grp_id;
void *dev_priv;
void *host_priv;
struct video_device *devnode;
struct device *dev;
struct fwnode_handle *fwnode;
struct list_head async_list;
struct v4l2_async_subdev *asd;
struct v4l2_async_notifier *notifier;
struct v4l2_async_notifier *subdev_notifier;
struct v4l2_subdev_platform_data *pdata;
struct mutex *state_lock;
/*
* The fields below are private, and should only be accessed via
* appropriate functions.
*/
/*
* TODO: active_state should most likely be changed from a pointer to an
* embedded field. For the time being it's kept as a pointer to more
* easily catch uses of active_state in the cases where the driver
* doesn't support it.
*/
struct v4l2_subdev_state *active_state;
};
V4L2中,为了使得多个子设备级联,创建了subdev结构体,里面的核心成员:
const struct v4l2_subdev_ops *ops;
const struct v4l2_subdev_internal_ops *internal_ops;
在创建subdev的时候,需要实现这两个函数指针,如 2所说,
当需要使用子系统的函数时,使用v4l2-call_xxx,即可调用。subdev里的const struct v4l2_subdev_ops *ops; 字段。
4 video_device
struct video_device {
#if defined(CONFIG_MEDIA_CONTROLLER)
struct media_entity entity;
struct media_intf_devnode *intf_devnode;
struct media_pipeline pipe;
#endif
const struct v4l2_file_operations *fops;
u32 device_caps;
/* sysfs */
struct device dev;
struct cdev *cdev;
struct v4l2_device *v4l2_dev;
struct device *dev_parent;
struct v4l2_ctrl_handler *ctrl_handler;
struct vb2_queue *queue;
struct v4l2_prio_state *prio;
/* device info */
char name[32];
enum vfl_devnode_type vfl_type;
enum vfl_devnode_direction vfl_dir;
int minor;
u16 num;
unsigned long flags;
int index;
/* V4L2 file handles */
spinlock_t fh_lock;
struct list_head fh_list;
int dev_debug;
v4l2_std_id tvnorms;
/* callbacks */
void (*release)(struct video_device *vdev);
const struct v4l2_ioctl_ops *ioctl_ops;
DECLARE_BITMAP(valid_ioctls, BASE_VIDIOC_PRIVATE);
struct mutex *lock;
};
struct subdev里,有一个* devnode指针,video_device通过它挂靠到v4l2_subdev里,它的核心功能,是数据的转运,以及向用户空间暴露/dev/videox设备文件。用户的所有操作,其实都是操作它。在v4l2-dev.c里,就是实现这个函数注册的的核心文件。里面的__video_reigser_device,注册了/dev/videox,以及提供了用户空间的ioctl(cmd)的分发。
4.1 videobuf
管理整个videobuf的是,
struct vb2_buffer {
struct list_head queued_entry;
struct list_head done_entry;
}
结构体。而vb2_queue *queue 才是实际干活的。
这个指针,指向实际的video_buf,负责整个数据的转运。一般会在申请的中断里,传输完成后,执行 vb2_buffer_done,标记完成,这时,完成的buf会挂载到 struct list_head done_entry; 里,这时,用户层就能收到完成的buf,取出数据了。
5 media_controller
5.1 media_device
media_controller一般以media_entity挂靠在v4l2_subdev里。而media_entity被media_device所管理。而v4l2_device又能被v4l2_device来索引到。这也正好论证了我们之前的绪论,v4l2-device来管理所有的子组件,它是骨架。
struct media_device{
struct list_head entities;
struct list_head pads;
struct list_head links;
}
media_device的核心,就是上面三个链表,来管理所有的entity,pads,links。我们先来看entity。
5.2 media_entity
struct media_entity {
struct media_gobj graph_obj; /* must be first field in struct */
const char *name;
enum media_entity_type obj_type;
u32 function;
unsigned long flags;
u16 num_pads;
u16 num_links;
u16 num_backlinks;
int internal_idx;
struct media_pad *pads;
struct list_head links;
const struct media_entity_operations *ops;
int use_count;
struct media_pipeline *pipe;
union {
struct {
u32 major;
u32 minor;
} dev;
} info;
};
entity里定义了标准的graph_obj,定义meida_entity的基础组件。然后就是pads和links。分别代表他们的功能和链接。
media_device又两个总的链表,来管理全部的pads和links。
更多推荐




所有评论(0)