基于RV1126 Video分析-----图像处理media模块注册

工作:

在这里插入图片描述

在这里插入图片描述

kernel\drivers\media\platform\rockchip\cif\dev.c

static int rkcif_plat_probe(struct platform_device *pdev)
{
	const struct of_device_id *match;
	struct device_node *node = pdev->dev.of_node;
	struct device *dev = &pdev->dev;
	struct rkcif_device *cif_dev;
	const struct rkcif_match_data *data;
	int ret;
	
	...
	
	rkcif_plat_init(cif_dev, node, data->inf_id);
}


int rkcif_plat_init(struct rkcif_device *cif_dev, struct device_node *node, int inf_id)
{
	struct device *dev = cif_dev->dev;
	struct v4l2_device *v4l2_dev;
	int ret;
	
	...
	
	/* create & register platefom subdev (from of_node) */
	ret = rkcif_register_platform_subdevs(cif_dev);
}

static int rkcif_register_platform_subdevs(struct rkcif_device *cif_dev)
{
	...
	
	ret = rkcif_register_stream_vdevs(cif_dev, stream_num,  false);
	...
}



/*注册 rkcif_device ISP平台设备的四个流 。 video节点

参数1 struct rkcif_device  ISP平台设备
参数2 4
参数3 true

*/
int rkcif_register_stream_vdevs(struct rkcif_device *dev,
				int stream_num,
				bool is_multi_input)
{
	struct rkcif_stream *stream;
	int i, j, ret;

	//注册 rkcif_device ISP平台设备的四个流 。分别对应四个video节点
	for (i = 0; i < stream_num; i++) {
		
		/*
			+---struct rkcif_device {
			|		struct rkcif_stream		stream[RKCIF_MULTI_STREAMS_NUM];
			+-----------struct rkcif_device		*cifdev;
			
		*/
		stream = &dev->stream[i];
		stream->cifdev = dev;//每个流 都属于 rkcif_device
		
		/*
			初始化,注册四个 video_device 设备。 用于创建和管理V4L2设备的结构
		
			参数1  rkcif 某个流 rkcif_stream
			
			struct rkcif_device {
				struct rkcif_stream		stream[i]
		*/
		ret = rkcif_register_stream_vdev(stream, is_multi_input);
		if (ret < 0)
			goto err;
	}
	...
}


/*
参数1   rkcif 某个流 rkcif_stream

	+---struct rkcif_device {
	|		struct rkcif_stream		stream[RKCIF_MULTI_STREAMS_NUM];
	+-----------struct rkcif_device		*cifdev;
*/
static int rkcif_register_stream_vdev(struct rkcif_stream *stream,
				      bool is_multi_input)
{
	
	/*
	+---struct rkcif_device {
	|		struct rkcif_stream		stream[RKCIF_MULTI_STREAMS_NUM];
	+-----------struct rkcif_device		*cifdev;
			struct v4l2_device		v4l2_dev;
	*/
	
	struct rkcif_device *dev = stream->cifdev;
	struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
	
	// struct video_device 用于创建和管理V4L2设备的结构
	/*
	+---struct rkcif_device {
	|		struct rkcif_stream		stream[RKCIF_MULTI_STREAMS_NUM];
	+-----------struct rkcif_device		*cifdev;
				struct rkcif_vdev_node		vnode;
					struct video_device vdev;
						struct v4l2_device *v4l2_dev;
			struct v4l2_device		v4l2_dev;
	*/
	struct video_device *vdev = &stream->vnode.vdev;
	struct rkcif_vdev_node *node;
	int ret = 0;
	char *vdev_name;

	...
	
	//tp2855_read_reg(client, 0x34, &chip_id);

	/*
		初始化,注册四个 video_device 设备。 用于创建和管理V4L2设备的结构
		
			
	+---struct rkcif_device {
	|		struct rkcif_stream		stream[RKCIF_MULTI_STREAMS_NUM];
	+-----------struct rkcif_device		*cifdev;
				struct rkcif_vdev_node		vnode;
					struct video_device vdev;
						const struct v4l2_ioctl_ops *ioctl_ops = rkcif_v4l2_ioctl_ops
						const struct v4l2_file_operations *fops = rkcif_fops
						struct v4l2_device *v4l2_dev;---+
			struct v4l2_device		v4l2_dev;-----------+
	
		
	*/
	
	//vdev_name = CIF_VIDEODEVICE_NAME;//"stream_cif"
	
	//如 "stream_cif"
	strlcpy(vdev->name, vdev_name, sizeof(vdev->name));
	node = vdev_to_node(vdev);
	mutex_init(&node->vlock);

	vdev->ioctl_ops = &rkcif_v4l2_ioctl_ops;
	vdev->release = video_device_release_empty;
	vdev->fops = &rkcif_fops;
	vdev->minor = -1;
	vdev->v4l2_dev = v4l2_dev;
	vdev->lock = &node->vlock;
	vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE |
			    V4L2_CAP_STREAMING;
	video_set_drvdata(vdev, stream);
	vdev->vfl_dir = VFL_DIR_RX;
	node->pad.flags = MEDIA_PAD_FL_SINK;

	rkcif_init_vb2_queue(&node->buf_queue, stream,
			     V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
	vdev->queue = &node->buf_queue;

	//注册
	/*
		参数
	+---struct rkcif_device {
	|		struct rkcif_stream		stream[RKCIF_MULTI_STREAMS_NUM];
	+-----------struct rkcif_device		*cifdev;
				struct rkcif_vdev_node		vnode;
					struct video_device vdev;
	*/
	ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
	if (ret < 0) {
		v4l2_err(v4l2_dev,
			 "video_register_device failed with error %d\n", ret);
		return ret;
	}

video_register_device() 工作在这里插入图片描述

	/* 
	绑定  多媒体设备media_device---------硬件设备模块entity------------硬件设备端口 pads

			struct rkcif_device
				struct rkcif_stream 
					struct rkcif_vdev_node		vnode;
						struct video_device vdev; 
							struct media_entity entity;
						struct media_pad pad;	
		*/				

	ret = media_entity_pads_init(&vdev->entity, 1, &node->pad);


	return 0;
unreg:
	video_unregister_device(vdev);
	return ret;
}

media_entity_pads_init() 工作
在这里插入图片描述

所以整理后 每个流 都有如下关系状态

在这里插入图片描述


分析:

static inline int __must_check video_register_device(struct video_device *vdev,
						     enum vfl_devnode_type type,
						     int nr)
{
	/*
			参数
	+---struct rkcif_device {
	|		struct rkcif_stream		stream[RKCIF_MULTI_STREAMS_NUM];
	+-----------struct rkcif_device		*cifdev;
				struct rkcif_vdev_node		vnode;
					struct video_device vdev;
					
		VFL_TYPE_GRABBER
		-1
		1
		
	+---struct rkcif_device {
	|		struct rkcif_stream		stream[RKCIF_MULTI_STREAMS_NUM];
	+-----------struct rkcif_device		*cifdev;
				struct rkcif_vdev_node		vnode;
					struct video_device vdev;
						const struct v4l2_file_operations *fops = rkcif_fops
							struct module *owner;//指向拥有这个结构的模块的指针,理解为 vdev 地址
		
	*/
	return __video_register_device(vdev, type, nr, 1, vdev->fops->owner);
}

kernel\drivers\media\v4l2-core\v4l2-dev.c

static struct video_device *video_devices[VIDEO_NUM_DEVICES];


int __video_register_device(struct video_device *vdev,
			    enum vfl_devnode_type type,
			    int nr, int warn_if_nr_in_use,
			    struct module *owner)
{
	int i = 0;
	int ret;
	int minor_offset = 0;
	int minor_cnt = VIDEO_NUM_DEVICES;
	const char *name_base;

	...

	//设备名 相关
	switch (type) {
	case VFL_TYPE_GRABBER:
		name_base = "video";
		break;
	...
	}

	...

	//struct video_device 设备号 相关                         
	/*
	
																				全局 video_devices[] 数组
	+---struct rkcif_device {															 |
	|		struct rkcif_stream		stream[RKCIF_MULTI_STREAMS_NUM];                     | 存储,下标:minor
	+-----------struct rkcif_device		*cifdev;                                         |
				struct rkcif_vdev_node		vnode;                                       |
					struct video_device vdev;--------------------------------------------+
						int minor;
	*/
#ifdef CONFIG_VIDEO_FIXED_MINOR_RANGES
	switch (type) {
	case VFL_TYPE_GRABBER:
		minor_offset = 0;
		minor_cnt = 64;
		break;
	...
	}
#endif

	/* Pick a device node number */
	mutex_lock(&videodev_lock);
	nr = devnode_find(vdev, nr == -1 ? 0 : nr, minor_cnt);
	...
	vdev->minor = i + minor_offset;
	vdev->num = nr;//video 设备号

	/* Should not happen since we thought this minor was free */
	if (WARN_ON(video_devices[vdev->minor])) {
		mutex_unlock(&videodev_lock);
		pr_err("video_device not empty!\n");
		return -ENFILE;
	}
	devnode_set(vdev);
	vdev->index = get_index(vdev);
	//全局 video_devices[] 数组
	/*
	以 video_device 以minor 为数组下标 !!! 保存当前 video_device 设备
	*/
	video_devices[vdev->minor] = vdev;
	...

	//字符设备 相关
	
	/*	
																			全局 video_devices[] 数组
																	    		  |
	+---struct rkcif_device {				                                      |
	|		struct rkcif_stream		stream[RKCIF_MULTI_STREAMS_NUM];              |
	+-----------struct rkcif_device		*cifdev;                                  | 存储,下标:minor
				struct rkcif_vdev_node		vnode;                                |
					struct video_device vdev;                                     |
						int minor;------------------------------------------------+
						const struct v4l2_file_operations *fops = rkcif_fops
							//指向拥有这个结构的模块的指针
							struct module *owner;---------------------------------+
						//sysfs  name : videoX                                    |
						struct cdev *cdev;                                        |
							const struct file_operations *ops = v4l2_fops         |
								struct module *owner;-----------------------------+
																				  
	*/
	vdev->cdev = cdev_alloc();
	vdev->cdev->ops = &v4l2_fops;
	vdev->cdev->owner = owner;//??
	ret = cdev_add(vdev->cdev, MKDEV(VIDEO_MAJOR, vdev->minor), 1);
	...
	//注册 video_device中的字符设备 到 sysfs
	/* Part 4: register the device with sysfs */
	vdev->dev.class = &video_class;
	vdev->dev.devt = MKDEV(VIDEO_MAJOR, vdev->minor);
	vdev->dev.parent = vdev->dev_parent;
	//videoX
	dev_set_name(&vdev->dev, "%s%d", name_base, vdev->num);
	ret = device_register(&vdev->dev);
	if (ret < 0) {
		pr_err("%s: device_register failed\n", __func__);
		goto cleanup;
	}
	...
	
	//至此
	
	/*

	
																				全局 video_devices[] 数组
	+---struct rkcif_device {															 |
	|		struct rkcif_stream		stream[RKCIF_MULTI_STREAMS_NUM];                     | 存储,下标:minor
	+-----------struct rkcif_device		*cifdev;                                         |
				struct rkcif_vdev_node		vnode;                                       |
					struct video_device vdev;--------------------------------------------+
						int minor;
						const struct v4l2_file_operations *fops = rkcif_fops
							//指向拥有这个结构的模块的指针
							struct module *owner;---------------------------------+
						//sysfs  name : videoX                                    |
						struct cdev *cdev;                                        |
							const struct file_operations *ops = v4l2_fops         |
								struct module *owner;-----------------------------+
								
								
	*/


	//注册 entity
	/* Part 5: Register the entity. */
	ret = video_register_media_controller(vdev);
	

	...
	
	return ret;
}
EXPORT_SYMBOL(__video_register_device);

kernel\drivers\media\v4l2-core\v4l2-dev.c

video_register_media_controller()工作:

在这里插入图片描述

/*

参数

	+---struct rkcif_device {
	|		struct rkcif_stream		stream[RKCIF_MULTI_STREAMS_NUM];
	+-----------struct rkcif_device		*cifdev;
				struct rkcif_vdev_node		vnode;
					struct video_device vdev;
		
*/
static int video_register_media_controller(struct video_device *vdev)
{
#if defined(CONFIG_MEDIA_CONTROLLER)
	u32 intf_type;
	int ret;

	/* Memory-to-memory devices are more complex and use
	 * their own function to register its mc entities.
	 */
	if (!vdev->v4l2_dev->mdev || vdev->vfl_dir == VFL_DIR_M2M)
		return 0;


	 /*
        vdev->entity 可以认为就是rkcif_mipi的entity
		
        obj_type表示当前entity的类型:
        对于video 就是 MEDIA_ENTITY_TYPE_VIDEO_DEVICE
        对于subdev 则是 MEDIA_ENTITY_TYPE_V4L2_SUBDEV
		
        function的值 :
        对于video - VFL_TYPE_GRABBER
            值为 MEDIA_ENT_F_IO_V4L
        对于subdev,就需要看情况而定,驱动自己设置
            比如subdev是个sensor,则值为 MEDIA_ENT_F_CAM_SENSOR
            比如subdev是个flash,则值为 MEDIA_ENT_F_FLASH
            比如subdev是个连接部件,则值为 MEDA_ENT_F_VID_IF_BRIDGE
            比如...
     */
	vdev->entity.obj_type = MEDIA_ENTITY_TYPE_VIDEO_DEVICE;
	vdev->entity.function = MEDIA_ENT_F_UNKNOWN;

	switch (vdev->vfl_type) {
	case VFL_TYPE_GRABBER:
		intf_type = MEDIA_INTF_T_V4L_VIDEO;
		vdev->entity.function = MEDIA_ENT_F_IO_V4L;
		break;
	...
	}

	// MEDIA_ENT_F_IO_V4L
	if (vdev->entity.function != MEDIA_ENT_F_UNKNOWN) {
		
		//如 "stream_cif"
		/*
	
			+---struct rkcif_device {
			|		struct rkcif_stream		stream[RKCIF_MULTI_STREAMS_NUM];
			+-----------struct rkcif_device		*cifdev;
						struct rkcif_vdev_node		vnode;
							struct video_device vdev;
								char name[32];--------------------+
								struct media_entity entity;       | 如 "stream_cif"
									const char *name; ------------+
																  
		*/
		vdev->entity.name = vdev->name;

		/* Needed just for backward compatibility with legacy MC API */
		vdev->entity.info.dev.major = VIDEO_MAJOR;
		vdev->entity.info.dev.minor = vdev->minor;

	
		/*
			1 
				+---struct rkcif_device {
				|		struct rkcif_stream		stream[RKCIF_MULTI_STREAMS_NUM];
				+-----------struct rkcif_device		*cifdev;
							struct rkcif_vdev_node		vnode;
								struct video_device vdev;
					+---------------struct v4l2_device *v4l2_dev;
					+---struct v4l2_device		v4l2_dev;
							struct media_device *mdev;	
			
			2
			
					
				+---struct rkcif_device {
				|		struct rkcif_stream		stream[RKCIF_MULTI_STREAMS_NUM];
				+-----------struct rkcif_device		*cifdev;
							struct rkcif_vdev_node		vnode;
								struct video_device vdev;
									struct media_entity entity;
					+---------------struct v4l2_device *v4l2_dev;
					+---struct v4l2_device		v4l2_dev;
							struct media_device *mdev;
		*/
		ret = media_device_register_entity(vdev->v4l2_dev->mdev,
						   &vdev->entity);
		if (ret < 0) {
			pr_warn("%s: media_device_register_entity failed\n",
				__func__);
			return ret;
		}
	}


	.....

	/* FIXME: how to create the other interface links? */

#endif
	return 0;
}

\kernel\drivers\media\media-device.c

media_device_register_entity() 工作
在这里插入图片描述

/**
	向多媒体设备 注册一个 模块entity
 * media_device_register_entity - Register an entity with a media device
 * @mdev:	The media device
 * @entity:	The entity
 */
/*
	  1 
			+---struct rkcif_device {
			|		struct rkcif_stream		stream[RKCIF_MULTI_STREAMS_NUM];
			+-----------struct rkcif_device		*cifdev;
						struct rkcif_vdev_node		vnode;
							struct video_device vdev;
				+---------------struct v4l2_device *v4l2_dev;
				+---struct v4l2_device		v4l2_dev;
						struct media_device *mdev;	
		
		2
	
			
			+---struct rkcif_device {
			|		struct rkcif_stream		stream[RKCIF_MULTI_STREAMS_NUM];
			+-----------struct rkcif_device		*cifdev;
						struct rkcif_vdev_node		vnode;
							struct video_device vdev;
								struct media_entity entity;
				+---------------struct v4l2_device *v4l2_dev;
				+---struct v4l2_device		v4l2_dev;
						struct media_device *mdev;	
*/
int __must_check media_device_register_entity(struct media_device *mdev,
					      struct media_entity *entity)
{
	struct media_entity_notify *notify, *next;
	unsigned int i;
	int ret;

	if (entity->function == MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN ||
	    entity->function == MEDIA_ENT_F_UNKNOWN)
		dev_warn(mdev->dev,
			 "Entity type for entity %s was not initialized!\n",
			 entity->name);

	/* Warn if we apparently re-register an entity */
	
	/*
	
	+---struct rkcif_device {
	|		struct rkcif_stream		stream[RKCIF_MULTI_STREAMS_NUM];
	+-----------struct rkcif_device		*cifdev;
				struct rkcif_vdev_node		vnode;
					struct video_device vdev;
						struct media_entity entity;
							struct media_gobj graph_obj;
								struct media_device	*mdev;----+
		+---------------struct v4l2_device *v4l2_dev;         |
		+---struct v4l2_device		v4l2_dev;                 |
				struct media_device *mdev;--------------------+
	
	*/
	WARN_ON(entity->graph_obj.mdev != NULL);
	entity->graph_obj.mdev = mdev;
	INIT_LIST_HEAD(&entity->links);
	entity->num_links = 0;
	entity->num_backlinks = 0;

	ret = ida_alloc_min(&mdev->entity_internal_idx, 1, GFP_KERNEL);
	if (ret < 0)
		return ret;
	entity->internal_idx = ret;

	mutex_lock(&mdev->graph_mutex);
	mdev->entity_internal_idx_max =
		max(mdev->entity_internal_idx_max, entity->internal_idx);

	/* Initialize media_gobj embedded at the entity */
	/*
	1
	+---struct rkcif_device {
	|		struct rkcif_stream		stream[RKCIF_MULTI_STREAMS_NUM];
	+-----------struct rkcif_device		*cifdev;
				struct rkcif_vdev_node		vnode;
					struct video_device vdev;
		+---------------struct v4l2_device *v4l2_dev;
		+---struct v4l2_device		v4l2_dev;
				struct media_device *mdev;	
	
	3		
	+---struct rkcif_device {
	|		struct rkcif_stream		stream[RKCIF_MULTI_STREAMS_NUM];
	+-----------struct rkcif_device		*cifdev;
				struct rkcif_vdev_node		vnode;
					struct video_device vdev;
						struct media_entity entity;
							struct media_gobj graph_obj;
	
	工作:
	
								
	+---struct rkcif_device {
	|		struct rkcif_stream		stream[RKCIF_MULTI_STREAMS_NUM];
	+-----------struct rkcif_device		*cifdev;
				struct rkcif_vdev_node		vnode;
					struct video_device vdev;
						struct media_entity entity;//当前 video 模块
							struct media_gobj graph_obj;
								struct list_head	list;-------+
		+---------------struct v4l2_device *v4l2_dev;           |
		+---struct v4l2_device		v4l2_dev;                   | 挂载到多媒体的模块entities链表
				//多媒体设备                                    |
				struct media_device *mdev;	                    |
					struct list_head  entities; ----------------+

	
	*/
	media_gobj_create(mdev, MEDIA_GRAPH_ENTITY, &entity->graph_obj);


	/*
	工作:
	
	+---struct rkcif_device {
	|		struct rkcif_stream		stream[RKCIF_MULTI_STREAMS_NUM];
	+-----------struct rkcif_device		*cifdev;
				struct rkcif_vdev_node		vnode;
					struct video_device vdev;
						struct media_entity entity;//当前 video 模块
							struct media_pad pads[i];//包含的 pad
								struct media_gobj graph_obj;
									struct list_head	list;---+
																|
		+---------------struct v4l2_device *v4l2_dev;           |
		+---struct v4l2_device		v4l2_dev;                   | 挂载到多媒体的模块pads链表
				//多媒体设备                                     |
				struct media_device *mdev;	                    |
					struct list_head  pads; --------------------+
	
	*/
	/* Initialize objects at the pads */
	for (i = 0; i < entity->num_pads; i++)
		media_gobj_create(mdev, MEDIA_GRAPH_PAD,
			       &entity->pads[i].graph_obj);

...	
	

	return 0;
}
EXPORT_SYMBOL_GPL(media_device_register_entity);



	/*
	1
	+---struct rkcif_device {
	|		struct rkcif_stream		stream[RKCIF_MULTI_STREAMS_NUM];
	+-----------struct rkcif_device		*cifdev;
				struct rkcif_vdev_node		vnode;
					struct video_device vdev;
		+---------------struct v4l2_device *v4l2_dev;
		+---struct v4l2_device		v4l2_dev;
				struct media_device *mdev;	
	
			
	+---struct rkcif_device {
	|		struct rkcif_stream		stream[RKCIF_MULTI_STREAMS_NUM];
	+-----------struct rkcif_device		*cifdev;
				struct rkcif_vdev_node		vnode;
					struct video_device vdev;
						struct media_entity entity;
							struct media_gobj graph_obj;
	
	
	*/
void media_gobj_create(struct media_device *mdev,
			   enum media_gobj_type type,
			   struct media_gobj *gobj)
{
	BUG_ON(!mdev);

	gobj->mdev = mdev;

	/* Create a per-type unique object ID */
	gobj->id = media_gobj_gen_id(type, ++mdev->id);


/*
					
							
	+---struct rkcif_device {
	|		struct rkcif_stream		stream[RKCIF_MULTI_STREAMS_NUM];
	+-----------struct rkcif_device		*cifdev;
				struct rkcif_vdev_node		vnode;
					struct video_device vdev;
						struct media_entity entity;
							struct media_gobj graph_obj;
								struct list_head	list;-------+
		+---------------struct v4l2_device *v4l2_dev;           |
		+---struct v4l2_device		v4l2_dev;                   | 挂载到多媒体的模块entities链表
				struct media_device *mdev;	                    |
					struct list_head  entities; ----------------+

*/	

	switch (type) {
	case MEDIA_GRAPH_ENTITY://!!!
		list_add_tail(&gobj->list, &mdev->entities);
		break;
	case MEDIA_GRAPH_PAD:
		list_add_tail(&gobj->list, &mdev->pads);
		break;
	case MEDIA_GRAPH_LINK:
		list_add_tail(&gobj->list, &mdev->links);
		break;
	case MEDIA_GRAPH_INTF_DEVNODE:
		list_add_tail(&gobj->list, &mdev->interfaces);
		break;
	}

	mdev->topology_version++;

	dev_dbg_obj(__func__, gobj);
}

/*
		
	struct rkcif_device
		struct rkcif_stream 
			struct rkcif_vdev_node		vnode;
				struct video_device vdev; 
					struct media_entity entity;
				struct media_pad pad;	
				
	num_pads==1
	
	工作:
					struct rkcif_device
						struct rkcif_stream 
							struct rkcif_vdev_node		vnode;
								struct video_device vdev; 
						+-----------struct media_entity entity;
						|				struct media_gobj graph_obj;  
	绑定 entity -- pad	|					struct media_device	*mdev;--+
						|	+-----------struct media_pad *pads;//1个pad |
						|	+---struct media_pad pad;                   | 
						+-----------struct media_entity *entity;        | 
									struct media_gobj graph_obj         |
										struct media_device	*mdev;------+ 绑定 多媒体 -- entity
										struct list_head	list;--+    | 绑定 多媒体 -- pad
						struct v4l2_device		v4l2_dev;          |    | 
							//多媒体设备                           |    |
							struct media_device *mdev;-------------|----+
								struct list_head  entities;        |
								struct list_head  pads;------------+ 
*/
int media_entity_pads_init(struct media_entity *entity, u16 num_pads,
			   struct media_pad *pads)
{

	struct media_device *mdev = entity->graph_obj.mdev;
	unsigned int i;

	if (num_pads >= MEDIA_ENTITY_MAX_PADS)
		return -E2BIG;

	/*
	
	
					struct rkcif_device
						struct rkcif_stream 
							struct rkcif_vdev_node		vnode;
								struct video_device vdev; 
						+-----------struct media_entity entity;
						|				struct media_gobj graph_obj;  
	绑定 entity--pad	|					struct media_device	*mdev;
						|	+-----------struct media_pad *pads;
						|	+---struct media_pad pad;
						+-----------struct media_entity *entity;

	*/
	entity->num_pads = num_pads;
	entity->pads = pads;

	if (mdev)
		mutex_lock(&mdev->graph_mutex);

	// num_pads == 1
	for (i = 0; i < num_pads; i++) {
		pads[i].entity = entity;
		pads[i].index = i;
		if (mdev){
			/*
			工作
					struct rkcif_device
						struct rkcif_stream 
							struct rkcif_vdev_node		vnode;
								struct video_device vdev; 
						+-----------struct media_entity entity;
						|				struct media_gobj graph_obj;  
	绑定 entity -- pad	|					struct media_device	*mdev;--+
						|	+-----------struct media_pad *pads;//1个pad |
						|	+---struct media_pad pad;                   | 
						+-----------struct media_entity *entity;        | 
									struct media_gobj graph_obj         |
										struct media_device	*mdev;------+ 绑定 多媒体 -- entity
										struct list_head	list;--+    | 绑定 多媒体 -- pad
						struct v4l2_device		v4l2_dev;          |    | 
							//多媒体设备                           |    |
							struct media_device *mdev;-------------|----+
								struct list_head  entities;        |
								struct list_head  pads;------------+ 
										
							
			*/
			media_gobj_create(mdev, MEDIA_GRAPH_PAD,
					&entity->pads[i].graph_obj);
			}
	}

	if (mdev)
		mutex_unlock(&mdev->graph_mutex);

	return 0;
}
EXPORT_SYMBOL_GPL(media_entity_pads_init);
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Linux老A

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值