3. Media Controller框架
Media Controller(MC)是 Linux 内核中用于管理复杂多媒体设备数据流的框架。在 ISP Pipeline 中,一个 ISP 设备通常包含多个硬件模块(如 CSI 接收器、ISP 前端、统计处理单元、缩放器),这些模块通过内部硬件通路连接。V4L2 的传统接口只能描述单个视频设备节点,无法表达模块间的内部连接关系。Media Controller 通过 entity(实体)、pad(垫片) 和 link(连接) 三个核心抽象,将 ISP 内部的硬件拓扑暴露给用户空间,使驱动开发者能够精确控制数据流路径。
3.1 Media Controller 核心架构
Media Controller 位于 V4L2 框架之下,为 V4L2 子设备提供拓扑管理能力。其核心数据结构定义在 include/media/media-device.h 和 include/media/media-entity.h 中。
| 核心概念 | 数据结构 | 描述 |
|---|---|---|
| Media Device | struct media_device |
代表整个多媒体设备,管理所有 entity 和 link,提供设备节点 /dev/media0 |
| Entity | struct media_entity |
代表一个硬件功能模块(如 sensor、ISP core、scaler),可包含多个 pad |
| Pad | struct media_pad |
实体上的数据输入/输出端口,分为 source pad(源端)和 sink pad(接收端) |
| Link | struct media_link |
连接两个 pad 的数据通路,可配置为 enable/disable 状态 |
3.2 Entity / Pad / Link 模型详解
3.2.1 Entity(实体)
每个 entity 对应 ISP 内部一个独立的硬件处理单元。在驱动中,entity 通常与 V4L2 subdev 绑定。例如,一个 ISP 驱动可能注册以下 entity:
- Sensor entity:图像传感器,通常只有 1 个 source pad
- CSI-2 Receiver entity:MIPI CSI-2 接收器,1 个 sink pad + 1 个 source pad
- ISP Frontend entity:Bayer 处理、黑电平校正、去噪,1 sink + 1 source
- Statistics entity:3A 统计信息输出,1 sink pad(仅输出元数据)
- Scaler entity:图像缩放,1 sink + 1 source
3.2.2 Pad(垫片)
Pad 是 entity 的数据接口,分为两种类型:
- MEDIA_PAD_FL_SINK:接收数据的输入端口
- MEDIA_PAD_FL_SOURCE:发送数据的输出端口
一个 entity 可以有多个 pad。例如,ISP 统计 entity 可能有一个 sink pad 接收图像数据,同时有多个 source pad 分别输出不同统计结果。
3.2.3 Link(连接)
Link 定义了两个 pad 之间的连接关系。Link 的状态可以通过 MEDIA_LNK_FL_ENABLED 标志控制。在 ISP 中,某些 link 是硬件固定的(不可更改),某些是软件可配置的(如选择不同的 sensor 输入源)。
media_create_pad_link() 建立 entity 之间的默认连接。用户空间通过 MEDIA_IOC_SETUP_LINK ioctl 在运行时动态切换链路,实现 ISP 数据流重配置。
3.3 拓扑结构建立
ISP Pipeline 的拓扑结构在驱动初始化时建立,通常分为三个步骤:
- 注册 Media Device:调用
media_device_register(),创建/dev/mediaX节点 - 注册 Entity:为每个硬件模块调用
media_entity_pads_init()初始化 pad 数组,然后通过 V4L2 subdev 注册时自动关联 entity - 建立 Link:调用
media_create_pad_link()连接 source pad 到 sink pad
以下是一个典型的 ISP 拓扑建立代码片段:
// 定义 entity 和 pad
static struct media_pad sensor_pads[] = {
{ .flags = MEDIA_PAD_FL_SOURCE }
};
static struct media_pad isp_frontend_pads[] = {
{ .flags = MEDIA_PAD_FL_SINK },
{ .flags = MEDIA_PAD_FL_SOURCE }
};
// 在 probe 函数中建立拓扑
media_device_register(&isp->media_dev);
// sensor -> ISP frontend
media_create_pad_link(
&sensor->sd.entity, 0, // sensor source pad 0
&isp_fe->sd.entity, 0, // ISP frontend sink pad 0
MEDIA_LNK_FL_ENABLED
);
// ISP frontend -> scaler
media_create_pad_link(
&isp_fe->sd.entity, 1, // ISP frontend source pad 1
&scaler->sd.entity, 0, // scaler sink pad 0
MEDIA_LNK_FL_ENABLED
);
3.4 与 V4L2 的协同工作
Media Controller 与 V4L2 的协同是 ISP 驱动开发的核心难点。两者通过 V4L2 subdev 和 video device node 实现交互。
| 组件 | V4L2 角色 | Media Controller 角色 |
|---|---|---|
| Sensor | V4L2 subdev,提供 s_power、s_fmt 操作 |
Entity,暴露 source pad |
| ISP Core | V4L2 subdev,提供 s_fmt、s_ctrl 操作 |
Entity,暴露 sink + source pad |
| Video Capture | V4L2 video device,提供 VIDIOC_QBUF、VIDIOC_DQBUF |
Entity,通常作为 pipeline 的末端 |
协同工作流程如下:
- 拓扑发现:用户空间通过
MEDIA_IOC_ENUM_ENTITIES和MEDIA_IOC_ENUM_LINKS获取 ISP 内部连接图 - Pipeline 配置:通过
MEDIA_IOC_SETUP_LINK启用/禁用特定数据通路 - 格式协商:V4L2 subdev 的
pad ops(如get_fmt、set_fmt)在 entity 之间传递格式信息,确保 pipeline 各阶段格式一致 - 数据流启动:V4L2 video device 调用
streamon,触发 subdev 的s_stream回调,沿 pipeline 逐级启动硬件
pad ops 是 MC 与 V4L2 的桥梁。驱动在 set_fmt 回调中不仅要更新当前 subdev 的格式,还需要通过 media_pipeline 通知上下游 entity 进行格式同步。这种“链式传播”保证了 ISP pipeline 中每个模块的配置一致性。
3.5 ISP Pipeline 拓扑结构图
下图展示了一个典型的 ISP Pipeline 拓扑结构,包含 sensor、CSI 接收器、ISP 前端、统计模块和缩放器:
3.6 用户空间拓扑操作示例
用户空间通过 media-ctl 工具或直接调用 ioctl 操作拓扑。以下是一个典型的 ISP pipeline 配置流程:
# 1. 枚举所有 entity
media-ctl -d /dev/media0 -e
# 2. 查看当前拓扑
media-ctl -d /dev/media0 -p
# 3. 设置 sensor 格式(通过 V4L2 subdev)
v4l2-ctl -d /dev/v4l-subdev0 --set-fmt-video=width=1920,height=1080,code=SRGGB10_1X10
# 4. 启用统计链路(将 link 3 从 DISABLED 改为 ENABLED)
media-ctl -d /dev/media0 -l '"ISP Frontend":1 -> "Statistics":0 [1]'
# 5. 设置 video 节点格式并开始采集
v4l2-ctl -d /dev/video0 --set-fmt-video=width=1920,height=1080,pixelformat=NV12
v4l2-ctl -d /dev/video0 --stream-mmap --stream-count=100
media-ctl -p 打印完整拓扑时,注意检查每个 link 的 [ENABLED] 或 [DISABLED] 状态。如果采集无数据输出,首先确认从 sensor 到 video node 的整条链路是否全部为 ENABLED 状态。常见错误是统计链路意外使能导致 ISP 内部带宽分配异常。