RK3588:MIPI底层驱动学习——入门第五篇(一文梳理media、video、v4l-subdev关系)
引言
上篇文章提到ov13855的驱动代码会创建一个
设备节点:v4l-subdev[N]
但是当我们查看dev设备节点的时候我们惊讶的发现
竟然有有如此多的设备节点!
他们是怎么被创建的?
他们的作用是什么?
为什么要创建如此多的设备节点?
这里引入出一个非常实用的工具v4l2-ctl
1. 工具存在的原因
V4L2驱动加载后,会创建 /dev/videoX
和 /dev/v4l-subdevX
设备节点。应用程序通过这些设备节点与驱动交互。但直接编写应用程序测试驱动太麻烦,需要一个命令行工具来快速验证驱动是否正常工作、查看设备状态、测试数据采集。
v4l2-ctl 就是这个工具——它封装了V4L2的各种ioctl调用,可以在命令行直接操作video设备和subdev设备。
2. 最常用命令:
# 0. 查看有哪些设备
v4l2-ctl --list-devices# 1. 查看media拓扑关系media-ctl -d /dev/media0 --print-topology# 2. 查看video设备支持的格式
v4l2-ctl -d /dev/video20 --list-formats-ext# 3. 设置想要的格式
v4l2-ctl -d /dev/video20 --set-fmt-video=width=1920,height=1080,pixelformat=NV12# 4. 查看subdev的输出格式是否匹配
v4l2-ctl -d /dev/v4l-subdev3 --get-subdev-fmt# 5. 调整曝光/增益
v4l2-ctl -d /dev/v4l-subdev3 --set-ctrl=exposure=800
v4l2-ctl -d /dev/v4l-subdev3 --set-ctrl=analogue_gain=256# 6. 采集一帧测试
v4l2-ctl -d /dev/video20 --stream-mmap --stream-count=1 --stream-to=/tmp/test.raw
3.视频设备分组、介绍
每个分组代表一个功能模块,这个模块可能包含:
v4l2-ctl --list-devices列出了系统中所有的视频设备分组。
每个分组代表一个功能模块,这个模块可能包含:
若干个video设备节点(/dev/videoX)
若干个media设备节点(/dev/mediaX)
为什么要分组显示?
因为一个功能模块内部的多个设备节点是配合工作的,分组显示能让你知道哪些节点属于同一个硬件单元。
orangepi[@orangepi5pro: ~/RK3588-rkaiq/camera_engine_rkaiq/rkaiq_3A_server$]v4l2-ctl --list-devices
rkisp-statistics (platform: rkisp):/dev/video18/dev/video19/dev/video27/dev/video28rkcif-mipi-lvds (platform:rkcif):/dev/media0rkcif (platform:rkcif-mipi-lvds):/dev/video0/dev/video1/dev/video2/dev/video3/dev/video4/dev/video5/dev/video6/dev/video7/dev/video8/dev/video9/dev/video10rkisp_mainpath (platform:rkisp0-vir0):/dev/video11/dev/video12/dev/video13/dev/video14/dev/video15/dev/video16/dev/video17/dev/media1rkisp_mainpath (platform:rkisp1-vir0):/dev/video20/dev/video21/dev/video22/dev/video23/dev/video24/dev/video25/dev/video26/dev/media2
第一组:rkcif-mipi-lvds
rkcif-mipi-lvds (platform:rkcif):/dev/media0
platform:rkcif:表示这是rkcif平台驱动创建的。只有1个设备节点:
作用:
这个设备不传输图像数据,只负责管理和配置数据通路。
/dev/media0
:用于查看和控制整个VICAP子系统的拓扑结构
VICAP = 增强版的 CIF VICAP 是 Rockchip 在 newer 芯片(如 RK3588)中引入的,用于替代和扩展传统的
CIF 功能。它提供了更强大、更灵活的视频输入处理能力。
在 RK3588 等新平台上,虽然驱动名称可能还保留 rkcif,但底层架构已经是 VICAP
第二组:rkcif
rkcif (platform:rkcif-mipi-lvds):/dev/video0/dev/video1/dev/video2/dev/video3/dev/video4/dev/video5/dev/video6/dev/video7/dev/video8/dev/video9/dev/video10
这是VICAP模块的数据输出设备。
platform:rkcif-mipi-lvds:这些video节点由rkcif-mipi-lvds驱动创建。
11个video设备:对应你之前在拓扑中看到的11个entity:
- video0-3:原始数据流通道(stream_cif_mipi_id0~3)
- video4-7:缩放处理通道(rkcif_scale_ch0~3)
- video8-10:工具调试通道(rkcif_tools_id0~2)
作用:
从这些设备节点可以直接读取VICAP处理后的图像数据。
数据特点:
- 格式:与sensor输出相同(SBGGR10)
- 分辨率:与sensor输出相同(4224x3136)
- 未经过ISP处理,是原始Bayer数据
第三组:rkisp_mainpath (rkisp0-vir0)
、讲解这个之前需要说明两点信息:
1.ISP能做什么:
去马赛克(把Bayer转成RGB)
白平衡、色彩校正
降噪、锐化
输出NV12、YUV等格式
rkisp_mainpath (platform:rkisp0-vir0):/dev/video11/dev/video12/dev/video13/dev/video14/dev/video15/dev/video16/dev/video17/dev/media1
这是ISP0的主路径输出设备。
1)media1的作用
用于查看和配置ISP0的内部拓扑,包括:
- ISP的输入来源(连接到哪个VICAP通道)
- ISP内部处理模块的连接关系
- 输出路径的配置
2)platform:rkisp0-vir0:
- rkisp0:第1个ISP硬件单元
- vir0:虚拟设备0(一个ISP可以虚拟出多个设备)
8个设备节点:
/dev/video11-17
:7个video数据输出节点/dev/media1
:ISP0的media控制设备
7个video节点的分工
video11:主路径输出(mainpath)
- 输出ISP处理后的完整分辨率图像
- 通常是NV12或YUV格式
- 用于录像、拍照等需要高质量的场景
video12-17:其他输出路径
设备节点 | 创建源码 | 设备名称 | 作用 |
---|---|---|---|
video11 | capture.c: RKISP1_STREAM_MP | rkisp_mainpath | 主路径,输出4416x3312高分辨率 |
video12 | capture.c: RKISP1_STREAM_SP | rkisp_selfpath | 自路径,输出1920x1920缩放小图 |
video13 | capture.c: RKISP1_STREAM_RAW | rkisp_rawpath | RAW数据输出(仅V12/V13) |
video14 | dmarx.c: RKISP1_STREAM_DMARX | rkisp_dmarx | DMA读取通道 |
video15 | isp_stats.c | rkisp1-statistics | ISP统计数据输出给3A |
video16 | isp_params.c | rkisp1-input-params | 3A参数输入到ISP |
第四组:rkisp_mainpath (rkisp1-vir0)
rkisp_mainpath (platform:rkisp1-vir0):/dev/video20/dev/video21/dev/video22/dev/video23/dev/video24/dev/video25/dev/video26/dev/media2
这是ISP1的主路径输出设备。
platform:rkisp1-vir0:
- rkisp1:第2个ISP硬件单元
- vir0:虚拟设备0
结构与ISP0完全相同:
为什么有两个ISP?
RK3588有2个独立的ISP硬件单元,可以:
- 同时处理2路摄像头
- 或者一个摄像头的数据同时送给2个ISP做不同处理
第五组:rkisp-statistics
rkisp-statistics (platform: rkisp):/dev/video18/dev/video19/dev/video27/dev/video28
这是ISP的统计和参数设备。
4个设备的分工:
video18和video27:统计数据输出
- ISP每帧会产生统计信息(亮度分布、色彩信息等)
- 3A算法程序从这里读取统计数据
- video18可能对应ISP0,video27对应ISP1
video19和video28:参数输入
- 3A算法计算出的参数(白平衡增益、曝光时间等)
- 从这里写入ISP硬件
- video19可能对应ISP0,video28对应ISP1
与3A服务的关系
rkaiq_3A_server的工作流程:
1. 从video27读取ISP统计数据
2. 运行3A算法计算参数
3. 把参数写入video28
4. ISP应用新参数处理下一帧
这就是3A服务必须访问这些设备的原因。
总结:
从摄像头到最终图像的路径
OV13855摄像头↓ 输出MIPI信号
DPHY + CSI2(在media0拓扑中)↓ 解析MIPI协议
VICAP模块├→ 输出到 /dev/video0~10(原始Bayer数据)└→ 送给ISP处理↓
ISP0或ISP1├→ 输出到 /dev/video11~17 或 video20~26(彩色图像)├→ 统计信息到 video18/27(给3A算法)└← 控制参数从 video19/28(3A算法写入)
路径1:VICAP直接输出(原始数据)
OV13855 → DPHY → CSI2 → VICAP → /dev/video0~10
输出:原始Bayer数据,未经ISP处理
路径2:经过ISP处理后输出(处理后数据)
OV13855 → DPHY → CSI2 → VICAP → ISP0 → /dev/video11~17→ ISP1 → /dev/video20~26
输出:NV12/YUV等格式,已经过ISP处理
路径3:3A控制回路
ISP内部统计 → /dev/video27 → rkaiq_3A_server → /dev/video28 → ISP参数寄存器
media设备的用途
-
media0:
- 配置VICAP的数据路由
- 设置sensor的输出格式
-
media1/media2:
- 配置ISP的输入源
- 设置ISP的处理参数
- 建立VICAP到ISP的连接
1.platform:rkcif——media0:注册media设备,用于管理整个VICAP的拓扑结构
2.rkcif-mipi-lvds——video0-10——摄像头接口——原始数据
3.rkisp_mainpath——media1+video11-17——接收来自CIF的原始数据+去马赛克、降噪、锐化、色彩校正等
4.rkisp-statistics
——video18 :统计数据输出(亮度分布、色彩信息等)提供给3A算法程序
——video19 :3A算法计算出参数(白平衡增益、曝光时间),通过这个写入ISP
命令2
附录: 具体命令使用方法
命令1:查看完整拓扑图
media-ctl -d /dev/media0 --print-topology
media-ctl
: Media Controller 的用户空间工具
-d /dev/media0
: 指定要操作的 Media Controller 设备
--print-topology
:打印设备的完整拓扑结构
命令2:查看video设备的完整信息
v4l2-ctl -d /dev/video20 --all
输出示例:
Driver Info:Driver name : rkisp_v6Card type : rkisp_mainpathBus info : platform:rkisp1-vir0Driver version : 2.3.0Format Video Capture Multiplanar:Width/Height : 4224/3136Pixel Format : 'NV12' (Y/CbCr 4:2:0)Field : NoneNumber of planes : 1Colorspace : SMPTE 170M
含义:
- Driver name:驱动名称
- Card type:设备类型
- Format:当前设置的图像格式、分辨率、像素格式
命令3:查看设备支持的所有格式
v4l2-ctl -d /dev/video40 --list-formats-ext
输出示例:
Type: Video Capture Multiplanar[0]: 'UYVY' (UYVY 4:2:2)Size: Stepwise 32x32 - 4224x3136 with step 8/8
[1]: 'NV16' (Y/CbCr 4:2:2)Size: Stepwise 32x32 - 4224x3136 with step 8/8
[2]: 'NV12' (Y/CbCr 4:2:0)Size: Stepwise 32x32 - 4224x3136 with step 8/8
含义:列出设备支持的像素格式和分辨率范围。
命令4:设置video设备的图像格式
v4l2-ctl -d /dev/video40 --set-fmt-video=width=4224,height=3136,pixelformat=NV12
验证设置:
v4l2-ctl -d /dev/video40 --get-fmt-video
输出:
Format Video Capture Multiplanar:Width/Height : 4224/3136Pixel Format : 'NV12' (Y/CbCr 4:2:0)
含义:向驱动发送 VIDIOC_S_FMT
ioctl,设置输出图像的宽度、高度和像素格式。
命令5:查看subdev的当前格式
v4l2-ctl -d /dev/v4l-subdev3 --get-subdev-fmt
输出示例:
ioctl: VIDIOC_SUBDEV_G_FMT (pad=0)Width/Height : 4224/3136Mediabus Code : 0x3007 (MEDIA_BUS_FMT_SBGGR10_1X10)Field : NoneColorspace : Default
含义:
- Mediabus Code:MIPI数据总线上传输的数据格式编码
- SBGGR10_1X10:Bayer格式,10bit,BGGR排列
命令6:设置subdev的控制参数
v4l2-ctl -d /dev/v4l-subdev3 --set-ctrl=analogue_gain=512
含义:设置sensor的模拟增益值为512(增益值的具体含义由sensor datasheet定义)。
查看所有可控制参数:
v4l2-ctl -d /dev/v4l-subdev3 --list-ctrls
输出示例:
exposure 0x00980911 (int) : min=4 max=3136 step=1 default=1600
analogue_gain 0x00980913 (int): min=16 max=1023 step=1 default=128
hflip 0x00980914 (bool) : default=0 value=0
vflip 0x00980915 (bool) : default=0 value=0
命令7:采集图像到文件
v4l2-ctl -d /dev/video40 --stream-mmap --stream-count=1 --stream-to=/tmp/test.raw
参数说明:
- –stream-mmap:使用内存映射方式传输数据
- –stream-count=1:采集1帧
- –stream-to:保存到文件路径
查看采集结果:
ls -lh /tmp/test.raw
输出:
-rw-rw-r-- 1 orangepi orangepi 19M Oct 2 23:31 /tmp/test.raw
含义:向驱动发送一系列ioctl(REQBUFS
、QUERYBUF
、QBUF
、STREAMON
、DQBUF
),完成数据采集。