7.7. 英特尔图像处理单元 3 (IPU3) 成像单元 (ImgU) 驱动程序

版权所有 © 2018 英特尔公司

7.7.1. 简介

此文件记录了位于 drivers/media/pci/intel/ipu3 (CIO2) 以及 drivers/staging/media/ipu3 (ImgU) 下的英特尔 IPU3(第三代图像处理单元)成像单元驱动程序。

在某些 Kaby Lake(以及某些 Sky Lake)平台(U/Y 处理器系列)中发现的英特尔 IPU3 由两部分组成,即成像单元 (ImgU) 和 CIO2 设备(MIPI CSI2 接收器)。

CIO2 设备从传感器接收原始拜耳数据,并以 IPU3 特有的格式输出帧(供 IPU3 ImgU 使用)。CIO2 驱动程序可在 drivers/media/pci/intel/ipu3/ipu3-cio2* 中找到,并通过 CONFIG_VIDEO_IPU3_CIO2 配置选项启用。

成像单元 (ImgU) 负责处理由 IPU3 CIO2 设备捕获的图像。ImgU 驱动程序的源代码可以在 drivers/staging/media/ipu3 目录中找到。该驱动程序通过 CONFIG_VIDEO_IPU3_IMGU 配置选项启用。

这两个驱动程序模块分别命名为 ipu3_csi2 和 ipu3_imgu。

该驱动程序已在 Kaby Lake 平台(U/Y 处理器系列)上进行了测试。

这两个驱动程序都实现了 V4L2、媒体控制器和 V4L2 子设备接口。IPU3 CIO2 驱动程序通过 V4L2 子设备传感器驱动程序支持连接到 CIO2 MIPI CSI-2 接口的摄像头传感器。

7.7.2. CIO2

CIO2 表示为单个 V4L2 子设备,它为用户空间提供 V4L2 子设备接口。每个 CSI-2 接收器都有一个视频节点,整个设备有一个媒体控制器接口。

CIO2 包含四个独立的捕获通道,每个通道都有自己的 MIPI CSI-2 接收器和 DMA 引擎。每个通道都建模为一个 V4L2 子设备,该子设备作为 V4L2 子设备节点暴露给用户空间,并具有两个衬垫

衬垫

方向

目的

0

接收

MIPI CSI-2 输入,连接到传感器子设备

1

原始视频捕获,连接到 V4L2 视频接口

V4L2 视频接口对 DMA 引擎建模。它们作为 V4L2 视频设备节点暴露给用户空间。

7.7.2.1. 以原始拜耳格式捕获帧

CIO2 MIPI CSI2 接收器用于从连接到 CSI2 端口的原始传感器捕获帧(以打包的原始拜耳格式)。捕获的帧用作 ImgU 驱动程序的输入。

由于以下 IPU3 特有的独特要求和/或功能,使用 IPU3 ImgU 进行图像处理需要 raw2pnm [2] 和 yavta [3] 等工具。

-- IPU3 CSI2 接收器以 IPU3 特有的打包原始拜耳格式输出从传感器捕获的帧。

-- 必须同时操作多个视频节点。

让我们以连接到 CSI2 端口 0 的 ov5670 传感器为例,进行 2592x1944 图像捕获。

使用媒体控制器 API,将 ov5670 传感器配置为以打包的原始拜耳格式向 IPU3 CSI2 接收器发送帧。

# This example assumes /dev/media0 as the CIO2 media device
export MDEV=/dev/media0

# and that ov5670 sensor is connected to i2c bus 10 with address 0x36
export SDEV=$(media-ctl -d $MDEV -e "ov5670 10-0036")

# Establish the link for the media devices using media-ctl [#f3]_
media-ctl -d $MDEV -l "ov5670:0 -> ipu3-csi2 0:0[1]"

# Set the format for the media devices
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]"

配置完媒体管道后,可以使用 yavta 工具设置所需的传感器特定设置(例如曝光和增益设置)。

例如

yavta -w 0x009e0903 444 $SDEV
yavta -w 0x009e0913 1024 $SDEV
yavta -w 0x009e0911 2046 $SDEV

设置所需的传感器设置后,可以按如下方式完成帧捕获。

例如

yavta --data-prefix -u -c10 -n5 -I -s2592x1944 --file=/tmp/frame-#.bin \
      -f IPU3_SGRBG10 $(media-ctl -d $MDEV -e "ipu3-cio2 0")

使用上述命令,以 2592x1944 分辨率捕获 10 帧,格式为 sGRBG10,并以 IPU3_SGRBG10 格式输出。

捕获的帧以 /tmp/frame-#.bin 文件的形式提供。

7.7.3. ImgU

ImgU 表示为两个 V4L2 子设备,每个子设备都为用户空间提供 V4L2 子设备接口。

每个 V4L2 子设备表示一个管道,该管道最多可以支持 2 个流。这有助于支持高级相机功能,如连续取景器 (CVF) 和视频期间快照 (SDV)。

ImgU 包含两个独立的管道,每个管道都建模为一个 V4L2 子设备,该子设备作为 V4L2 子设备节点暴露给用户空间。

每个管道都有两个接收衬垫和三个源衬垫,用于以下目的

衬垫

方向

目的

0

接收

输入原始视频流

1

接收

处理参数

2

输出处理后的视频流

3

输出取景器视频流

4

3A 统计信息

每个衬垫都连接到相应的 V4L2 视频接口,该接口作为 V4L2 视频设备节点暴露给用户空间。

7.7.3.1. 设备操作

对于 ImgU,一旦输入视频节点(“ipu3-imgu 0/1”:0,格式为 <实体>:<衬垫编号>)排队了缓冲区(以打包的原始拜耳格式),ImgU 就会开始处理缓冲区,并在相应的输出节点上生成 YUV 格式的视频输出和统计信息输出。当输入视频节点排队缓冲区时,驱动程序应准备好所有参数、输出和统计信息节点的缓冲区。

至少,应启用所有输入、主输出、3A 统计信息和取景器视频节点,以便 IPU3 开始图像处理。

每个 ImgU V4L2 子设备都具有以下视频节点集。

7.7.3.2. 输入、输出和取景器视频节点

输入视频节点接收到的帧(以 IPU3 特有的打包原始拜耳格式)由 IPU3 成像单元处理,并输出到 2 个视频节点,每个节点都针对不同的目的(主输出和取景器输出)。

有关 IPU3 特有的拜耳格式的详细信息,请参见 V4L2_PIX_FMT_IPU3_SBGGR10 ('ip3b')、V4L2_PIX_FMT_IPU3_SGBRG10 ('ip3g')、V4L2_PIX_FMT_IPU3_SGRBG10 ('ip3G')、V4L2_PIX_FMT_IPU3_SRGGB10 ('ip3r')

该驱动程序支持 接口 中定义的 V4L2 视频捕获接口。

仅支持多平面 API。有关更多详细信息,请参见 单平面和多平面 API

7.7.3.3. 参数视频节点

参数视频节点接收 ImgU 算法参数,这些参数用于配置 ImgU 算法如何处理图像。

有关 IPU3 特定的处理参数的详细信息,请参阅 V4L2_META_FMT_IPU3_PARAMS ('ip3p'), V4L2_META_FMT_IPU3_3A ('ip3s')

7.7.3.4. 3A 统计视频节点

3A 统计视频节点由 ImgU 驱动程序使用,以将 ImgU 处理的帧的 3A(自动对焦、自动曝光和自动白平衡)统计信息输出到用户空间应用程序。用户空间应用程序可以使用此统计数据来计算 ImgU 的所需算法参数。

7.7.4. 配置 Intel IPU3

可以使用媒体控制器配置 IPU3 ImgU 管道,定义请参阅 第四部分 - 媒体控制器 API

7.7.4.1. 运行模式和固件二进制文件选择

ImgU 基于固件工作,目前 ImgU 固件支持以时分方式使用单个输入帧数据运行 2 个管道。每个管道都可以在特定模式下运行 - “VIDEO”或“STILL”。“VIDEO”模式通常用于视频帧捕获,“STILL”模式用于静态帧捕获。但是,如果您想以较低的系统负载和功耗捕获图像,您也可以选择“VIDEO”来捕获静态帧。对于“STILL”模式,ImgU 将尝试使用较小的 BDS 因子并输出较大的拜耳帧以进行进一步的 YUV 处理,从而获得高质量的图像。此外,“STILL”模式需要 XNR3 来进行降噪,因此“STILL”模式将比“VIDEO”模式需要更多的功耗和内存带宽。TNR 将在“VIDEO”模式下启用,并在“STILL”模式下绕过。ImgU 默认以“VIDEO”模式运行,用户可以使用 v4l2 控制 V4L2_CID_INTEL_IPU3_MODE(当前在 drivers/staging/media/ipu3/include/uapi/intel-ipu3.h 中定义)来查询和设置运行模式。对于用户来说,“VIDEO”和“STILL”模式之间的缓冲区排队没有区别,必须启用强制输入和主输出节点,并且需要排队缓冲区,统计信息和取景器队列是可选的。

固件二进制文件将根据当前运行模式选择,如果您启用 ImgU 动态调试,可能会观察到 “using binary if_to_osys_striped “ 或 “using binary if_to_osys_primary_striped” 等日志,二进制文件 if_to_osys_striped 选择用于“VIDEO”,二进制文件 “if_to_osys_primary_striped” 选择用于 “STILL”。

7.7.4.2. 以原始拜耳格式处理图像

7.7.4.2.1. 配置 ImgU V4L2 子设备以进行图像处理

必须使用媒体控制器 API 配置 ImgU V4L2 子设备,以正确设置所有视频节点。

让我们以 “ipu3-imgu 0” 子设备为例。

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]

此外,应通过控制 ID 0x009819a1 将相应 V4L2 子设备的管道模式设置为所需模式(例如,视频模式为 0,静态模式为 1),如下所示。

yavta -w "0x009819A1 1" /dev/v4l-subdev7

ImgU 管道中的某些硬件块可以通过裁剪或缩放来更改帧分辨率,这些硬件块包括输入馈送器(IF)、拜耳下采样器(BDS)和几何失真校正(GDC)。还有一个可以更改帧分辨率的块 - YUV 缩放器,它仅适用于辅助输出。

RAW 拜耳帧通过这些 ImgU 管道硬件块,最终处理后的图像输出到 DDR 内存。

ipu3 resolution blocks image

IPU3 分辨率更改硬件块

输入馈送器

输入馈送器从传感器获取拜耳帧数据,它可以启用对帧的行和列的裁剪,然后将像素存储到设备的内部像素缓冲区中,这些像素缓冲区已准备好被后续块读取。

拜耳下采样器

拜耳下采样器能够在拜耳域中执行图像缩放,可以在每个轴上以 0.03125 (1/32) 的配置步长将下采样因子配置为 1X 到 1/4X。

几何失真校正

几何失真校正用于执行失真校正和图像滤波。它需要一些额外的滤波和包络填充像素才能工作,因此 GDC 的输入分辨率应大于输出分辨率。

YUV 缩放器

YUV 缩放器与 BDS 类似,但它主要在 YUV 域中执行图像下采样,它可以支持高达 1/12X 的下采样,但它不能应用于主输出。

必须使用上述所有硬件块中支持的分辨率配置 ImgU V4L2 子设备,以获得给定的输入分辨率。对于给定的输入帧支持的分辨率,应使用支持的分辨率配置输入馈送器、拜耳下采样器和 GDC 块,因为每个硬件块都有自己的对齐要求。

您必须巧妙地配置硬件块的输出分辨率,以满足硬件要求并保持最大视野。中间分辨率可以由特定工具生成 -

https://github.com/intel/intel-ipu3-pipecfg

此工具可用于生成中间分辨率。可以通过查看以下 IPU3 ImgU 配置表来获得更多信息。

https://chromium.googlesource.com/chromiumos/overlays/board-overlays/+/master

在 baseboard-poppy/media-libs/cros-camera-hal-configs-poppy/files/gcss 目录下,graph_settings_ov5670.xml 可以用作示例。

以下步骤准备 ImgU 管道以进行图像处理。

1. 应使用 VIDIOC_SUBDEV_S_FMT 在 pad 0 上设置 ImgU V4L2 子设备数据格式,使用上面获得的 GDC 宽度和高度。

2. 应使用 VIDIOC_SUBDEV_S_SELECTION 在 pad 0 上设置 ImgU V4L2 子设备裁剪,以 V4L2_SEL_TGT_CROP 作为目标,使用输入馈送器的高度和宽度。

3. 应使用 VIDIOC_SUBDEV_S_SELECTION 在 pad 0 上设置 ImgU V4L2 子设备合成,以 V4L2_SEL_TGT_COMPOSE 作为目标,使用 BDS 的高度和宽度。

对于 ov5670 示例,对于分辨率为 2592x1944 的输入帧(它是到 ImgU 子设备 pad 0 的输入),输入馈送器、BDS 和 GDC 的相应分辨率分别为 2592x1944、2592x1944 和 2560x1920。

完成此操作后,可以将接收到的原始拜耳帧输入到 ImgU V4L2 子设备,如下所示,使用开源应用程序 v4l2n [2]

对于以 2592x1944 [5] 分辨率捕获的图像,所需的输出分辨率为 2560x1920,取景器分辨率为 2560x1920,可以使用以下 v4l2n 命令。这有助于处理原始拜耳帧,并以 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

您还可以使用 yavta [3] 命令执行与上述相同的操作

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 设备分别指向输入、输出、取景器和 3A 统计视频节点。

7.7.4.3. 将原始拜耳图像转换为 YUV 域

经过上述步骤处理后的图像,可以如下所示转换为 YUV 域。

7.7.4.3.1. 主输出帧

raw2pnm -x2560 -y1920 -fNV12 /tmp/frames.out /tmp/frames.out.ppm

其中 2560x1920 是输出分辨率,NV12 是视频格式,后跟输入帧和输出 PNM 文件。

7.7.4.3.2. 取景器输出帧

raw2pnm -x2560 -y1920 -fNV12 /tmp/frames.vf /tmp/frames.vf.ppm

其中 2560x1920 是输出分辨率,NV12 是视频格式,后跟输入帧和输出 PNM 文件。

7.7.5. IPU3 的用户空间代码示例

此处提供了配置和使用 IPU3 的用户空间代码。

https://chromium.googlesource.com/chromiumos/platform/arc-camera/+/master/

源代码位于 hal/intel 目录下。

7.7.6. IPU3 管道概述

IPU3 管道具有多个图像处理阶段,每个阶段都将一组参数作为输入。此处显示了管道的主要阶段

IPU3 ImgU Pipeline

IPU3 ImgU 管道图

下表介绍了上述算法。

名称

描述

光学黑电平校正

光学黑电平校正块从各自的像素值中减去一个预定义的值,以获得更好的图像质量。在 struct ipu3_uapi_obgrid_param 中定义。

线性化

此算法块使用线性化参数来解决非线性传感器效应。查找表在 struct ipu3_uapi_isp_lin_vmem_params 中定义。

SHD

镜头阴影校正用于校正由于光学镜头阴影引起的像素响应的空间不均匀性。这是通过为每个像素应用不同的增益来完成的。增益、黑电平等在 struct ipu3_uapi_shd_config_static 中配置。

BNR

拜耳降噪块通过应用双边滤波器来消除图像噪声。有关详细信息,请参阅 struct ipu3_uapi_bnr_static_config

ANR

高级降噪是一种基于块的算法,可在拜耳域中执行降噪。可以在 struct ipu3_uapi_anr_config 中找到卷积矩阵等。

DM

去马赛克将拜耳格式的原始传感器数据转换为 RGB(红、绿、蓝)表示形式。然后添加 Y 通道估计的输出,以便固件进行后续流处理。该结构定义为 struct ipu3_uapi_dm_config

色彩校正

色彩校正算法将传感器特定的色彩空间转换为标准的 “sRGB” 色彩空间。这是通过应用 struct ipu3_uapi_ccm_mat_config 中定义的 3x3 矩阵来完成的。

伽玛校正

伽玛校正 struct ipu3_uapi_gamma_config 是一种基本的非线性色调映射校正,它针对每个像素的每个像素分量应用。

CSC

色彩空间转换将每个像素从 RGB 原色表示转换为 YUV(Y:亮度,UV:色度)表示。这是通过应用在 struct ipu3_uapi_csc_mat_config 中定义的 3x3 矩阵来完成的。

CDS

色度下采样 在执行 CSC 之后,对于 YUV 4:2:0,应用色度下采样,使用 4x2 可配置滤波器 struct ipu3_uapi_cds_params 对 UV 平面在每个方向上进行 2 倍的下采样。

CHNR

色度噪声降低 此模块仅处理色度像素,并通过清除高频噪声来执行降噪。请参见 struct struct ipu3_uapi_yuvp1_chnr_config。

TCC

总色彩校正,定义在 struct struct ipu3_uapi_yuvp2_tcc_static_config 中。

XNR3

eXtreme 噪声降低 V3 是用于提高图像质量的噪声降低算法的第三次修订。它会消除捕获图像中的低频噪声。定义了两个相关的结构体,struct ipu3_uapi_isp_xnr3_params 用于 ISP 数据存储,struct ipu3_uapi_isp_xnr3_vmem_params 用于矢量存储。

TNR

时间噪声降低模块比较时间上连续的帧,以消除像素值中的异常/噪声。struct ipu3_uapi_isp_tnr3_vmem_paramsstruct ipu3_uapi_isp_tnr3_params 分别为 ISP 矢量和数据存储器定义。

上面表格中未列出的其他常见缩写

ACC

加速器集群

AWB_FR

自动白平衡滤波器响应统计

BDS

拜耳下采样器参数

CCM

色彩校正矩阵系数

IEFd

图像增强滤波器定向

Obgrid

光学黑电平补偿

OSYS

输出系统配置

ROI

感兴趣区域

YDS

Y 下采样

YTM

Y 色调映射

流水线的一些阶段将由在 ISP 处理器上运行的固件执行,而许多其他阶段将使用一组固定的硬件块(也称为加速器集群 (ACC))来处理像素数据并生成统计信息。

用户可以通过嵌入在 struct ipu3_uapi_params 结构体中的 struct struct ipu3_uapi_flags 来选择应用由 struct ipu3_uapi_acc_param 定义的各个算法的 ACC 参数。对于配置为未被用户空间启用的参数,驱动程序会忽略相应的结构体,在这种情况下,将保留该算法的现有配置。

7.7.7. 参考