介绍
日期 | 作者 | 备注 |
---|---|---|
2025/04/06 | Manfredxxc | 初版 |
- 内核版本:kernel-4.1.15
- 参考源码:drivers/media/platform/omap3isp/isp.c
在v4l2框架里,media framework通过硬件抽象和动态拓扑管理,管理复杂多媒体设备的子系统(如camera、isp等),定制视频处理流水线
- 通过将硬件设备抽象成一个个的
entity
,并通过pads
和links
建立联系,形成Pipeline
- 运行时调整
Pipeline
即可动态改变数据流
media_device
struct media_device
表示一个media设备,通常会嵌入到一个更大的私有结构体
数据类型简要说明
struct media_device {
/* dev->driver_data points to this struct. */
struct device *dev;
struct media_devnode devnode; // cdev封装,用于创建/dev/media<X>
char model[32]; // 设备型号描述,会通过sysfs设备属性导出,例:/sys/bus/media/devices/media0/model
char serial[40]; // 设备序列号
char bus_info[32]; // 唯一的设备位置标识符 todo@Manfredxxc:查清作用
u32 hw_revision; // 硬件设备版本
u32 driver_version; // 驱动版本
u32 entity_id; // 下一个要注册的entity的ID,初始化值为1
struct list_head entities; // entity链表
// link状态变化回调
int (*link_notify)(struct media_link *link, u32 flags,
unsigned int notification);
};
API简要说明
media_device_register
- 描述:注册一个media设备
- 原型:
media_device_register(struct media_device *mdev)
- 注意:调用前需要初始化
mdev
,mdev->model
必须得到填充 - 详情:初始化mdev->devnode,注册一个字符设备节点/dev/media,该节点的fops仅
ioctl
有意义:`media_device_ioctl
media_device_ioctl
- 描述:media设备支持的
ioctl
操作 - 原型:
static long media_device_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
- @cmd:
- MEDIA_IOC_DEVICE_INFO :查看媒体设备信息
- MEDIA_IOC_ENUM_ENTITIES :枚举entity信息
- MEDIA_IOC_ENUM_LINKS :枚举links信息
- MEDIA_IOC_SETUP_LINK :设置link flag (ENABLE | IMMUTABLE | DYNAMIC)
media_graph
media framework中,通过struct media_entity
、struct media_link
、struct media_pad
抽象出一个硬件拓扑关系media graph
#------------# #------------#
| __|__ __|__ |
| | | link | | |
| | pad |--------->| pad | |
| | |<---------| | |
| |__ __| backlink |__ __| |
| entity | | entity |
#------------# #------------#
通过动态配置硬件拓扑来控制数据流Pipeline,并提供开启/关闭、效果/节点控制等功能
例:sensor => isp => encoder => /dev/video
数据类型简要说明
struct media_link
:代表一个link,链接两个pad
struct media_link {
struct media_pad *source; /* Source pad */
struct media_pad *sink; /* Sink pad */
struct media_link *reverse; /* 反向link */
unsigned long flags; /* ENABLE | IMMUTABLE | DYNAMIC */
};
struct media_pad
:代表entity上的一个pad
struct media_pad {
struct media_entity *entity; /* 指向所属entity */
u16 index; /* 在所属entity的pad数组上的索引 */
unsigned long flags; /* SINK | SOURCE | MUST_CONNECT */
};
struct entity
在media graph中表示一个entity
struct media_entity {
struct list_head list; // media_device->entities链表
struct media_device *parent; /* 该entity所属的 Media device */
u32 id; /* 所属 Media device上下文的唯一entity ID */
const char *name; /* Entity名 */
u32 type; /* Entity类型 (MEDIA_ENT_T_*) */
u32 revision; /* 驱动指定的entity版本 */
unsigned long flags; /* Entity flags (MEDIA_ENT_FL_*) */
u32 group_id; /* Entity group ID */
u16 num_pads; /* sink/source pad数量 */
u16 num_links; /* 已经创建的enable/disable links数量(分配内存后,起始为0,每次create_link,num_link++) */
u16 num_backlinks; /* backlinks数量 */
u16 max_links; /* inks最大值 */
struct media_pad *pads; /* Pads数组 */
struct media_link *links; /* Links数组 */
const struct media_entity_operations *ops; /* Entity支持的操作 */
int stream_count; /* 该entity上的stream数量 */
int use_count; /* 该entity引用计数 */
struct media_pipeline *pipe; /* 该entity从属的Pipeline */
union {
/* Node specifications */
struct {
u32 major;
u32 minor;
} dev;
/* Sub-device specifications */
/* Nothing needed yet */
} info;
};
struct media_entity_graph
:显示栈+位图,实现非递归的拓扑遍历,对深度和ID进行限制保证健壮性
struct media_entity_graph {
struct {
struct media_entity *entity; // 当前处理的entity
int link; // 当前处理的link索引
} stack[MEDIA_ENTITY_ENUM_MAX_DEPTH]; // 栈空间
DECLARE_BITMAP(entities, MEDIA_ENTITY_ENUM_MAX_ID); // entity标记位图
int top;
};
API简要说明
media_entity_init
-
描述:初始化一个media entity,为
entity->links
分配num_pads+extra_links
个link
大小的内存,绑定相应的entity、pads、links -
原型:
int media_entity_init(struct media_entity *entity, u16 num_pads, struct media_pad *pads, u16 extra_links)
-
参数:
- @entity:待初始化entity
- @num_pads:该entity上的pads数量
- @pads:pads数组
- @extra_links:预估的额外links数量
media_device_register_entity
- 描述:注册一个entity到media device,为
entity->id
分配一个唯一ID,并将其添加到media_device->entities
链表上 - 原型:
int __must_check media_device_register_entity(struct media_device *mdev, struct media_entity *entity)
media_entity_create_link
- 描述:在两个entity pad之间创建一个link和一个backlink
- 原型:
int media_entity_create_link(struct media_entity *source, u16 source_pad, struct media_entity *sink, u16 sink_pad, u32 flag)
- 参数:
- @source:source entity
- @souce_pad:link连接到的source pad,backlink的sink pad
- @sink:sink entity
- @sink_pad:link链接到的sink pad,backlink的source pad
- @flag:ENABLE(开启) | IMMUTABLE(不可变的) | DYNAMIC(动态的)
media_entity_setup_link
-
描述:配置media link,配置link的大部分工作由该link链接的entity处理,此函数会通知这两个entity,它们的link配置发生了变化。如果link不可变或者与设置的相同,直接返回
-
原型:
int media_entity_setup_link(struct media_link *link, u32 flag)
-
细节:
- 配置前后都会调用media_device->link_notify()
,分别传递 MEDIA_DEV_NOTIFY_PRE_LINK_CH、MEDIA_DEV_NOTIFY_POST_LINK_CH
- 配置函数:__media_entity_setup_link_notify(link, flag)
,分别调用source/sink pad的 entity->ops->link_setup()
media_entity_find_link
- 描述:返回连接两个pad的link,如果不存在则返回NULL
- 原型:
struct media_link *media_entity_find_link(struct media_pad *source, struct media_pad *sink)
media_entity_remote_pad
- 描述:返回与local pad相连(link必须是enable)的remote pad,不存在则返回NULL
- 原型:
struct media_pad *media_entity_remote_pad(struct media_pad *pad)
media_entity_pipeline_start
- 描述:图遍历给定的初始entity,利用位图将管道标记为streaming(流式传输状态)
- 原型:
__must_check int media_entity_pipeline_start(struct media_entity *entity, struct media_pipeline *pipe)
、
media_entity_call
- 描述:辅助宏,调用entity->ops->operation(entity, args)
- 原型:
media_entity_call(entity, operation, args...)