Linux 内核 Intel IPU3 成像驱动实战指南:CIO2 采集与 ImgU 图像处理管线配置
【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux
导读
本文以 Linux 内核文档 Documentation/admin-guide/media/ipu3.rst 为主体,系统讲解 Intel 第三代图像处理单元(IPU3)在 Linux V4L2 框架下的两个驱动模块:负责 MIPI CSI-2 原始数据接收的 CIO2(ipu3-csi2)与负责图像处理的 ImgU(ipu3-imgu)。读完本文,你将掌握如何在 Kaby Lake / Sky Lake 平台上通过 media-ctl、yavta、v4l2n 等工具完成传感器原始 Bayer 帧采集、ImgU 多节点管线配置、运行模式切换以及图像处理结果转换,并理解 IPU3 图像处理管线各算法块的底层实现与对应的 uAPI 数据结构。
IPU3 硬件与驱动总览
Intel IPU3(第三代图像处理单元)存在于部分 Kaby Lake 及 Sky Lake 平台(U/Y 处理器系列)中,由两大部件组成:
- CIO2 设备(MIPI CSI-2 接收器):接收来自传感器的原始 Bayer 数据,并以 IPU3 专用的打包格式输出帧,供 ImgU 消费。
- 成像单元 ImgU(Imaging Unit):负责对 CIO2 捕获的图像进行处理,输出 YUV 格式图像与 3A 统计数据。
两个驱动模块分别位于内核源码的drivers/media/pci/intel/ipu3(CIO2,文件为ipu3-cio2.c/ipu3-cio2.h)与drivers/staging/media/ipu3(ImgU)目录下,模块名分别为ipu3_csi2和ipu3_imgu。二者均实现了 V4L2、Media Controller 与 V4L2 sub-device 接口;CIO2 驱动通过 V4L2 sub-device 传感器驱动支持连接在 CIO2 MIPI CSI-2 接口上的相机传感器。
两个驱动在内核配置中的使能选项如下(见 drivers/media/pci/intel/ipu3/Kconfig 与 drivers/staging/media/ipu3/Kconfig):
CONFIG_VIDEO_IPU3_CIO2:Intel ipu3-cio2 驱动,依赖VIDEO_DEV && PCI && X86,自动选择MEDIA_CONTROLLER、VIDEO_V4L2_SUBDEV_API、V4L2_FWNODE与VIDEOBUF2_DMA_SG,编译产物为ipu3-cio2模块。CONFIG_VIDEO_IPU3_IMGU:Intel ipu3-imgu 驱动,依赖PCI && VIDEO_DEV && X86,自动选择MEDIA_CONTROLLER、VIDEO_V4L2_SUBDEV_API、IOMMU_IOVA与VIDEOBUF2_DMA_SG,编译产物为ipu3-imgu模块。
CIO2:MIPI CSI-2 原始 Bayer 帧采集
CIO2 设备模型
CIO2 在 V4L2 框架中以单个 V4L2 subdev 呈现,向用户空间提供 subdev 接口;每个 CSI-2 接收器对应一个 video node,整个设备共用一个 media controller 接口。CIO2 内部包含四个独立的捕获通道,每个通道拥有独立的 MIPI CSI-2 接收器与 DMA 引擎,每个通道以 V4L2 sub-device 节点暴露给用户空间,并带有两个 pad:
| Pad | 方向 | 用途 |
|---|---|---|
| 0 | sink | MIPI CSI-2 输入,连接传感器 subdev |
| 1 | source | 原始视频捕获,连接 V4L2 video 接口 |
V4L2 video 接口对 DMA 引擎进行建模,以 V4L2 video device 节点暴露给用户空间。从源码看,CIO2 在探测时通过v4l2_async_nf_parse_fwnode(ipu3-cio2.c 附近的 sensor 异步注册逻辑)异步绑定挂在 CSI-2 端口上的传感器 subdev,并在流启动/停止时调用v4l2_subdev_call(q->sensor, video, s_stream, ...)(见 ipu3-cio2.c)来联动传感器出流。
使用 CIO2 捕获原始 Bayer 帧
CIO2 MIPI CSI-2 接收器用于从连接在 CSI-2 端口上的原始传感器捕获打包格式的原始 Bayer 帧,捕获结果作为 ImgU 驱动的输入。由于以下两点特殊性,实际使用 IPU3 图像处理需要借助raw2pnm、yavta等工具:
- CIO2 输出的是 IPU3 专用的打包原始 Bayer 格式;
- 使用过程中需要同时操作多个 video node。
以下以 ov5670 传感器连接在 CSI-2 port 0、捕获 2592x1944 图像为例(假设/dev/media0为 CIO2 media 设备,ov5670 连接在 i2c bus 10 地址 0x36):
export MDEV=/dev/media0 # 获取 ov5670 传感器的 subdev 实体 export SDEV=$(media-ctl -d $MDEV -e "ov5670 10-0036") # 建立传感器到 CSI2 接收器的 media link media-ctl -d $MDEV -l "ov5670:0 -> ipu3-csi2 0:0[1]" # 设置 media 设备各 pad 的格式(打包原始 Bayer,10bit sGRBG) media-ctl -d $MDEV -V "ov5670:0 [fmt:SGRBG10/2592x1944]" media-ctl -d $MDEV -V "ipu3-csi2 0:0 [fmt:SGRBG10/2592x1944]" media-ctl -d $MDEV -V "ipu3-csi2 0:1 [fmt:SGRBG10/2592x1944]"media 管线配置完成后,可使用 yavta 设置传感器相关参数(如曝光与增益,这里通过 V4L2 user control ID 写入):
yavta -w 0x009e0903 444 $SDEV yavta -w 0x009e0913 1024 $SDEV yavta -w 0x009e0911 2046 $SDEV随后即可进行帧捕获。下面的命令以 2592x1944 分辨率、sGRBG10 格式捕获 10 帧,并以IPU3_SGRBG10格式输出:
yavta --data-prefix -u -c10 -n5 -I -s2592x1944 --file=/tmp/frame-#.bin \ -f IPU3_SGRBG10 $(media-ctl -d $MDEV -e "ipu3-cio2 0")捕获的帧保存在/tmp/frame-#.bin文件中,这些文件正是后续 ImgU 处理阶段的输入。
IPU3 专用 Bayer 格式
关于 CIO2 输出的打包原始 Bayer 格式,内核文档 Documentation/userspace-api/media/v4l/pixfmt-srggb10-ipu3.rst 给出了精确定义:V4L2_PIX_FMT_IPU3_SBGGR10('ip3b')、V4L2_PIX_FMT_IPU3_SGBRG10('ip3g')、V4L2_PIX_FMT_IPU3_SGRBG10('ip3G')、V4L2_PIX_FMT_IPU3_SRGGB10('ip3r')四种格式均为每样本 10 bit 的原始 sRGB/Bayer 格式,每 25 个像素打包进 32 字节(最后一个字节留 6 个最高有效位填充),小端字节序,其余方面与标准的V4L2_PIX_FMT_SRGGB10类似。该格式在文档中以逐字节的字节序表格完整描述了打包布局,实际进行字节解析与帧处理时应严格参照该布局。
ImgU:图像处理单元驱动
ImgU 设备模型与管道
ImgU 以两个 V4L2 subdev 呈现(对应两条独立管道),每个 subdev 向用户空间提供 V4L2 subdev 接口。每个管道最多支持 2 条流,从而支撑连续取景器(Continuous View Finder,CVF)与视频中抓拍(Snapshot During Video,SDV)等高级相机功能。
每条管道具有 2 个 sink pad 与 3 个 source pad:
| Pad | 方向 | 用途 |
|---|---|---|
| 0 | sink | 输入原始视频流 |
| 1 | sink | 处理参数 |
| 2 | source | 输出处理后的视频流 |
| 3 | source | 输出取景器视频流 |
| 4 | source | 3A 统计 |
每个 pad 连接一个对应的 V4L2 video 接口,以 V4L2 video device 节点暴露给用户空间。这一模型在源码中与 drivers/staging/media/ipu3/ipu3.h 定义的节点枚举一一对应:IMGU_NODE_IN(输入 RAW 图像)、IMGU_NODE_PARAMS(输入参数)、IMGU_NODE_OUT(主输出)、IMGU_NODE_VF(预览)、IMGU_NODE_STAT_3A(3A 统计),共 5 个节点(IMGU_NODE_NUM 5),并且每个imgu_media_pipe结构通过imgu_pipe[IMGU_MAX_PIPE_NUM]数组管理两条管道(见 ipu3.h)。
设备操作流程
使用 ImgU 时,一旦输入 video node("ipu3-imgu 0/1":0,即<entity>:<pad-number>格式)入队了缓冲区(打包原始 Bayer 格式),ImgU 即开始处理该缓冲区,并在对应输出节点上产生 YUV 格式视频输出与统计输出。驱动要求:当输入 video node 入队缓冲区时,参数、输出与统计节点都必须已备好缓冲区。至少需要同时使能输入、主输出、3A 统计与取景器 video node,IPU3 才能启动图像处理。
各 video node 的职责
input、output 与 viewfinder video nodes
输入 video node 接收的帧(IPU3 专用的打包原始 Bayer 格式)经 IPU3 成像单元处理后,输出到两个 video node,分别对应主输出与取景器输出。该驱动仅支持 V4L2 多平面(multi-planar)API,并遵循 V4L2 Video Capture Interface 规范。
Parameters video node
参数 video node 接收用于配置 ImgU 各算法如何处理图像的参数。参数格式细节见 Documentation/userspace-api/media/v4l/metafmt-intel-ipu3.rst:处理参数通过"ipu3-imgu [01] parameters"元数据输出 video node、以v4l2_meta_format接口传入,格式由ipu3_uapi_params结构描述。该结构包含ipu3_uapi_flags use(标识哪些设置将被应用)、ipu3_uapi_acc_param acc_param(加速器簇参数)、ISP 向量地址空间参数(lin_vmem_params、tnr3_vmem_params、xnr3_vmem_params)、ISP 数据内存(DMEM)参数(tnr3_dmem_params、xnr3_dmem_params)以及光学黑电平补偿参数obgrid_param。uAPI 头文件位于 drivers/staging/media/ipu3/include/uapi/intel-ipu3.h。
3A statistics video node
3A 统计 video node 用于输出 ImgU 正在处理的帧的 3A(自动对焦、自动曝光、自动白平衡)统计数据给用户空间应用。用户空间应用可利用这些统计数据计算所需的 ImgU 算法参数。统计数据的格式同样定义在 metafmt-intel-ipu3.rst 中,由ipu3_uapi_stats_3a结构描述,包含 AWB RGBS 单元、AWB 滤波响应、AF 滤波响应与 AE 直方图,以及可配置参数结构ipu3_uapi_4a_config;统计数据从"ipu3-imgu [01] 3a stat"元数据捕获 video node 获取。
配置 Intel IPU3
IPU3 ImgU 管线可通过 Media Controller 接口配置。
运行模式与固件二进制选择
ImgU 基于固件运行,目前固件支持以时间分片方式用单路输入帧数据运行 2 条管道。每条管道可运行于 "VIDEO" 或 "STILL" 模式:
- VIDEO 模式:常用于视频帧捕获;也可以用它抓拍静态帧,以获得较低的系统负载与功耗。
- STILL 模式:用于静态帧捕获。ImgU 会使用更小的 BDS(Bayer Down Scaler)因子、输出更大的 Bayer 帧供后续 YUV 处理,从而获得高质量图像;同时 STILL 模式需要 XNR3 做降噪,因此功耗与内存带宽需求高于 VIDEO 模式。TNR(时域降噪)在 VIDEO 模式下启用、在 STILL 模式下被旁路。
ImgU 默认运行于 VIDEO 模式,用户可通过 V4L2 controlV4L2_CID_INTEL_IPU3_MODE查询和设置运行模式。该 control 定义于 drivers/staging/media/ipu3/include/uapi/intel-ipu3.h(V4L2_CID_INTEL_IPU3_BASE + 1)。从 drivers/staging/media/ipu3/ipu3-v4l2.c 的源码实现可以看到,它是一个菜单型 control,菜单项为 "Video mode" / "Still mode",默认值为IPU3_RUNNING_MODE_VIDEO,s_ctrl回调把选择值原子写入imgu_sd->running_mode(ipu3-v4l2.c)。
对用户而言,两种模式在缓冲区入队方面没有区别:必须使能输入与主输出节点并入队缓冲区,统计与取景器队列则是可选的。
固件二进制会按当前运行模式选择:若开启 ImgU 动态调试,可观察到 "using binary if_to_osys_striped"(VIDEO 模式)或 "using binary if_to_osys_primary_striped"(STILL 模式)的日志。对应地,源码中二进制选择逻辑在 drivers/staging/media/ipu3/ipu3-css.c 打印using binary %s id = %u调试信息,并根据输入/输出格式与分辨率逐一筛选满足条件的 ISP 二进制。
原始 Bayer 图像处理配置
配置 ImgU V4L2 subdev
ImgU V4L2 subdev 必须通过 media controller API 配置,使所有 video node 正确就位。以 "ipu3-imgu 0" subdev 为例:
media-ctl -d $MDEV -r media-ctl -d $MDEV -l "ipu3-imgu 0 input":0 -> "ipu3-imgu 0":0[1] media-ctl -d $MDEV -l "ipu3-imgu 0":2 -> "ipu3-imgu 0 output":0[1] media-ctl -d $MDEV -l "ipu3-imgu 0":3 -> "ipu3-imgu 0 viewfinder":0[1] media-ctl -d $MDEV -l "ipu3-imgu 0":4 -> "ipu3-imgu 0 3a stat":0[1]同时应通过 control id0x009819a1设置对应 V4L2 subdev 的管道模式(0 为 video 模式,1 为 still 模式):
yavta -w "0x009819A1 1" /dev/v4l-subdev7分辨率可变硬件块
ImgU 管线中有若干硬件块可通过裁剪或缩放改变帧分辨率,包括:
- Input Feeder(IF):从传感器获取 Bayer 帧数据,可对帧的行、列进行裁剪,然后将像素存入设备内部像素缓冲,供后续块读出。
- Bayer Down Scaler(BDS):在 Bayer 域执行图像缩放,每个轴的下采样因子可配置为 1X 到 1/4X,配置步进为 0.03125(1/32)。
- Geometric Distortion Correction(GDC):执行畸变校正与图像滤波。它需要额外的滤波与包围填充像素,因此 GDC 的输入分辨率应大于输出分辨率。
- YUV Scaler:与 BDS 类似,主要在 YUV 域做下采样,最多支持 1/12X 下采样,但不能应用于主输出,仅适用于次级输出。
这些硬件块对应的示意图为 Documentation/admin-guide/media/ipu3_rcb.svg(IPU3 分辨率改变硬件块)。
对于给定的输入分辨率,ImgU V4L2 subdev 必须在上述所有硬件块上配置所支持的分辨率;由于每个硬件块都有自己的对齐要求,Input Feeder、BDS 与 GDC 块都需要按各自支持的分辨率配置。
配置时应"聪明地"设置各硬件块的输出分辨率,既满足硬件要求又尽量保留最大视场(field of view)。中间分辨率可由专用工具 intel-ipu3-pipecfg 生成(仓库文档中指向https://github.com/intel/intel-ipu3-pipecfg与 Chromium OS 的 board-overlays 仓库baseboard-poppy/media-libs/cros-camera-hal-configs-poppy/files/gcss目录下的graph_settings_ov5670.xml作为参考示例)。
通过 V4L2 subdev ioctl 配置 ImgU 管线
以下步骤准备 ImgU 管线以进行图像处理:
- 设置数据格式:通过
VIDIOC_SUBDEV_S_FMT在 pad 0 设置 ImgU V4L2 subdev 的数据格式,使用上一步获得的GDC 宽高。 - 设置裁剪:通过
VIDIOC_SUBDEV_S_SELECTION在 pad 0 设置裁剪,目标为V4L2_SEL_TGT_CROP,使用Input Feeder 的宽高。 - 设置合成(compose):通过
VIDIOC_SUBDEV_S_SELECTION在 pad 0 设置合成,目标为V4L2_SEL_TGT_COMPOSE,使用BDS 的宽高。
以 ov5670 为例,对于输入帧分辨率 2592x1944(输入到 ImgU subdev pad 0),对应的 Input Feeder、BDS 与 GDC 分辨率分别为2592x1944、2592x1944、2560x1920。
使用 v4l2n 处理原始 Bayer 帧
配置完成后,即可将接收到的原始 Bayer 帧输入 ImgU V4L2 subdev。对于 2592x1944 分辨率捕获的图像,期望主输出分辨率 2560x1920、取景器分辨率 2560x1920,可用如下 v4l2n 命令处理原始 Bayer 帧,在主输出与取景器输出上以 NV12 格式产出结果:
v4l2n --pipe=4 --load=/tmp/frame-#.bin --open=/dev/video4 --fmt=type:VIDEO_OUTPUT_MPLANE,width=2592,height=1944,pixelformat=0X47337069 \ --reqbufs=type:VIDEO_OUTPUT_MPLANE,count:1 --pipe=1 \ --output=/tmp/frames.out --open=/dev/video5 \ --fmt=type:VIDEO_CAPTURE_MPLANE,width=2560,height=1920,pixelformat=NV12 \ --reqbufs=type:VIDEO_CAPTURE_MPLANE,count:1 --pipe=2 \ --output=/tmp/frames.vf --open=/dev/video6 \ --fmt=type:VIDEO_CAPTURE_MPLANE,width=2560,height=1920,pixelformat=NV12 \ --reqbufs=type:VIDEO_CAPTURE_MPLANE,count:1 --pipe=3 --open=/dev/video7 \ --output=/tmp/frames.3A --fmt=type:META_CAPTURE,? \ --reqbufs=count:1,type:META_CAPTURE --pipe=1,2,3,4 --stream=5其中0X47337069即小端字节序下 'ip3G'(V4L2_PIX_FMT_IPU3_SGRBG10)的 fourcc 数值。
也可使用 yavta 完成同样操作:
yavta --data-prefix -Bcapture-mplane -c10 -n5 -I -s2592x1944 \ --file=frame-#.out-f NV12 /dev/video5 & \ yavta --data-prefix -Bcapture-mplane -c10 -n5 -I -s2592x1944 \ --file=frame-#.vf -f NV12 /dev/video6 & \ yavta --data-prefix -Bmeta-capture -c10 -n5 -I \ --file=frame-#.3a /dev/video7 & \ yavta --data-prefix -Boutput-mplane -c10 -n5 -I -s2592x1944 \ --file=/tmp/frame-in.cio2 -f IPU3_SGRBG10 /dev/video4这里/dev/video4、/dev/video5、/dev/video6、/dev/video7分别对应 input、output、viewfinder 与 3A statistics 四个 video node。注意 ImgU 有一个限制:所有输入分辨率都需要额外的 16x16 边距。
将原始 Bayer 图像转换到 YUV 域
上述步骤处理后的图像可转换到 YUV 域,使用raw2pnm工具:
主输出帧:
raw2pnm -x2560 -y1920 -fNV12 /tmp/frames.out /tmp/frames.out.ppm取景器输出帧:
raw2pnm -x2560 -y1920 -fNV12 /tmp/frames.vf /tmp/frames.vf.ppm命令格式为:分辨率、视频格式(NV12),后跟输入帧文件与输出 PNM 文件。
IPU3 图像处理管线概述
IPU3 管线包含大量图像处理阶段,每个阶段都以一组参数作为输入。管线的核心流程为:
Raw pixels -> Bayer Downscaling -> Optical Black Correction -> Linearization -> Lens Shading Correction -> White Balance/Exposure/Focus Apply -> Bayer Noise Reduction -> ANR -> Demosaicing -> Color Correction Matrix -> Gamma correction -> Color Space Conversion -> Chroma Down Scaling -> Chromatic Noise Reduction -> Total Color Correction -> XNR3 -> TNR -> DDR(输出)次级输出路径在此基础上经 YUV Downscaling 后写入 DDR。各主要算法块的说明与对应 uAPI 结构如下表:
| 名称 | 描述 | 对应结构体 |
|---|---|---|
| Optical Black Correction | 从各像素减去预设值以获得更佳画质 | ipu3_uapi_obgrid_param |
| Linearization | 用查找表处理传感器非线性效应 | ipu3_uapi_isp_lin_vmem_params |
| SHD(镜头阴影校正) | 对每个像素施加不同增益校正镜头阴影导致的空间不均匀性 | ipu3_uapi_shd_config_static |
| BNR(Bayer 噪声抑制) | 通过双边滤波器去除图像噪声 | ipu3_uapi_bnr_static_config |
| ANR(高级噪声抑制) | 基于块的 Bayer 域降噪算法 | ipu3_uapi_anr_config |
| DM(去马赛克) | 将 Bayer 格式原始传感器数据转为 RGB 表示,并输出 Y 通道估计供固件后续流处理 | ipu3_uapi_dm_config |
| Color Correction | 用 3x3 矩阵将传感器色彩空间转换到标准 sRGB 色彩空间 | ipu3_uapi_ccm_mat_config |
| Gamma correction | 逐像素、逐分量施加的基本非线性色调映射校正 | ipu3_uapi_gamma_config |
| CSC(色彩空间转换) | 用 3x3 矩阵将 RGB 表示转为 YUV 表示 | ipu3_uapi_csc_mat_config |
| CDS(色度下采样) | CSC 之后对 UV 平面在每方向按因子 2 下采样为 YUV 4:2:0,使用 4x2 可配置滤波器 | ipu3_uapi_cds_params |
| CHNR(色度降噪) | 仅处理色度像素,清除高频噪声 | ipu3_uapi_yuvp1_chnr_config |
| TCC(总色彩校正) | 总色彩校正 | ipu3_uapi_yuvp2_tcc_static_config |
| XNR3 | 第三代极值降噪,去除捕获图像中的低频噪声 | ipu3_uapi_isp_xnr3_params(ISP 数据内存)、ipu3_uapi_isp_xnr3_vmem_params(向量内存) |
| TNR(时域降噪) | 比较连续帧以去除像素值中的异常/噪声 | ipu3_uapi_isp_tnr3_vmem_params、ipu3_uapi_isp_tnr3_params |
其余常见缩略语:ACC(加速器簇)、AWB_FR(自动白平衡滤波响应统计)、BDS(Bayer 下采样器参数)、CCM(色彩校正矩阵系数)、IEFd(定向图像增强滤波)、Obgrid(光学黑电平补偿)、OSYS(输出系统配置)、ROI(感兴趣区域)、YDS(Y 下采样)、YTM(Y 色调映射)。
从实现上看,管线的部分阶段由运行在 ISP 处理器上的固件执行,另有许多阶段使用一组固定硬件块(即加速器簇 ACC)来运算像素数据并产生统计。ACC 中各算法的参数由ipu3_uapi_acc_param结构定义,用户空间可通过内嵌于ipu3_uapi_params结构中的ipu3_uapi_flags选择哪些参数生效;未使能的参数对应结构会被驱动忽略,相应算法的既有配置将保持不变。相关 uAPI 数据类型的完整 kernel-doc 定义见 drivers/staging/media/ipu3/include/uapi/intel-ipu3.h,并可在 metafmt-intel-ipu3.rst 中查看ipu3_uapi_params与ipu3_uapi_stats_3a的结构骨架。
用户空间参考实现
配置与使用 IPU3 的用户空间参考代码位于 Chromium OS 的 arc-camera 平台仓库hal/intel目录(文档中指向https://chromium.googlesource.com/chromiumos/platform/arc-camera/+/master/)。此外,生成 ImgU 管线中间分辨率的工具 intel-ipu3-pipecfg 与本文涉及的 raw2pnm(Intel nvt 工具集)、yavta 等用户空间工具,是完成 IPU3 端到端图像采集与处理链路不可或缺的组成部分。
小结
本文完整梳理了 Linux 内核中 Intel IPU3 的两级驱动架构:CIO2 负责从 MIPI CSI-2 传感器接收打包原始 Bayer 帧,ImgU 负责将原始帧处理为 YUV 输出与 3A 统计。通过 media-ctl 建立管线、yavta 设置传感器与运行模式、v4l2n 驱动多节点抓取,再到 raw2pnm 将结果转成可查看的 PNM 图像,即可在 Kaby Lake / Sky Lake 平台上跑通完整的 IPU3 相机通路。深入理解管线中各算法块及其 uAPI 结构(定义于 intel-ipu3.h),则是编写相机 HAL 或进行 3A 调优的基础。
【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考