三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

003、高通骁龙Spectra ISP架构深度解析:IFE/BPS/IPE流水线与Chromatix调优实战

003、高通骁龙Spectra ISP架构深度解析:IFE/BPS/IPE流水线与Chromatix调优实战

003、高通骁龙Spectra ISP架构深度解析:IFE/BPS/IPE流水线与Chromatix调优实战

开篇:一个让我在产线上蹲了三天的鬼问题

去年做一款骁龙8 Gen2平台的旗舰机型,客户反馈夜景预览画面在暗部区域出现明显的“水波纹”状噪点,而且只在特定色温下复现。当时第一反应是3A(自动对焦/自动曝光/自动白平衡)跑飞了,查了半天tuning参数,纹丝不动。后来用Qualcomm的trace工具抓了IFE和IPE的实时统计信息,才发现问题根本不在3A,而是IFE输出的YUV数据在进入IPE做多帧降噪时,因为temporal filter的motion vector计算窗口和IFE的HDR合并输出尺寸不匹配,导致运动估计错乱。这个案例特别典型,它说明了一个核心问题:Spectra ISP不是一堆独立模块的堆叠,而是一条有严格时序和带宽约束的流水线,任何一层的配置错位,都会在下游被放大成诡异的图像缺陷。

今天这篇笔记,咱们不聊PPT上的架构图,直接钻进代码和寄存器层面,看看IFE、BPS、IPE这三兄弟到底怎么分工协作,以及Chromatix里那些看着头疼的XML节点,背后到底在调什么鬼东西。

先理清流水线:谁在前,谁在后,谁在偷懒

高通Spectra ISP在骁龙平台上的典型处理链路是:传感器RAW数据进来,先经过IFE(Image Front End),然后是BPS(Bayer Processing Segment),最后是IPE(Image Processing Engine)。但注意,这条链路的“串行”程度取决于你用的是哪一代Spectra以及当前的工作模式。

IFE是前端硬件的“急先锋”,它干的是最脏最累的活:坏点校正、黑电平校正、镜头阴影校正、去马赛克(在某些架构里,去马赛克会放到BPS)、色彩校正矩阵、Gamma校正,还有最关键的——HDR合成。IFE处理的是RAW域数据,它的输出通常是YUV422或者经过压缩的RAW格式。这里有个关键点:IFE的带宽占用是巨大的,因为它要处理全分辨率的RAW数据。所以高通在IFE内部设计了多个子模块并行处理,比如针对HDR的多曝光帧合成,IFE内部有专门的HDR流水线,可以同时接收长中短曝光帧,在硬件层面完成对齐和合成。如果你在Chromatix里看到IFEHDRControl节点,那就是在调这个。

BPS是“中间商”,它主要做的是高精度的降噪和细节增强。为什么需要BPS?因为IFE处理完的数据虽然干净了一些,但噪声水平还很高,如果直接给IPE做多帧处理,会浪费IPE的算力。BPS的核心功能包括:时域降噪(TNR)、空域降噪(SNR)、坏点校正的二次处理、以及镜头畸变校正。BPS的输入是IFE的输出,输出是给IPE的YUV数据。这里有个容易踩坑的地方:BPS的时域降噪依赖前一帧的参考数据,这个参考数据存储在DDR里,带宽占用极大。如果你在调BPS_TNR参数时发现帧率掉得厉害,别怀疑,就是DDR带宽被吃满了。解决办法是调整TNR的搜索窗口大小,或者降低参考帧的分辨率(高通支持TNR的降采样模式)。

IPE是“精装修师傅”,它工作在YUV域,负责最终的色彩风格、锐化、对比度、局部色调映射(LTM)、以及多帧融合的最终合成。IPE的算力最强,但也是最容易“过度处理”的地方。很多工程师喜欢把锐化强度拉满,结果画面边缘出现白边(overshoot),这就是IPE的细节增强模块没调好。IPE内部有多个子模块,比如IPE_ANR(自适应噪声降低)、IPE_EE(边缘增强)、IPE_LTM(局部色调映射)。这些模块的调优顺序有讲究:先降噪,再锐化,最后做LTM。如果你先做了LTM再锐化,暗部的噪声会被锐化放大,画面会非常脏。

Chromatix调优实战:从XML节点到寄存器映射

Chromatix是高通的调优数据格式,本质是一堆XML文件,描述了每个ISP模块在不同场景下的参数。但别被它的“高级”外表骗了,它最终会被编译成二进制数据,直接烧录到ISP的寄存器里。所以,你在Chromatix里改一个参数,实际上是在改某个寄存器的值。

以IFE的镜头阴影校正(LSC)为例。在Chromatix里,你看到的是chromatix_ife_lsc节点,里面有r_gaingr_gaingb_gainb_gain四个数组,每个数组对应一个网格点的增益值。但实际硬件里,LSC模块是一个二维插值器,它根据当前像素坐标,在网格点之间做双线性插值。这里踩过坑:如果你在Chromatix里把网格点数量设得太多(比如超过32x32),编译出来的二进制文件会非常大,而且ISP的LSC模块可能不支持这么密的网格,导致插值计算溢出,画面出现网格状色块。高通官方推荐的是16x16或24x24,别贪多。

再说BPS的时域降噪。Chromatix里chromatix_bps_tnr节点有个motion_strength参数,控制运动检测的灵敏度。这个参数调大了,静止区域的降噪效果很好,但运动物体会出现拖影;调小了,运动物体清晰了,但静止区域噪点压不住。别指望一个参数打天下,高通提供了基于场景的tuning表,你可以根据环境照度、色温、场景内容(人像/风景/夜景)来分别设置。但这里有个隐藏的坑:TNR的参考帧是上一帧的输出,如果你在调参时改了分辨率或者裁剪区域,参考帧的尺寸会不匹配,导致TNR失效。所以,改分辨率之前,先检查TNR的参考帧配置。

IPE的LTM(局部色调映射)是调优的重灾区。Chromatix里chromatix_ipe_ltm节点有strengthtone_curvespatial_filter等参数。LTM的原理是把图像分成多个局部区域,每个区域单独做色调映射,然后融合。如果你把strength调得太高,画面会出现“光晕”现象,尤其是在高反差边缘(比如窗户和室内)。这是因为局部区域的映射差异太大,融合时产生了不自然的过渡。解决办法是降低strength,同时调整spatial_filter的sigma值,让融合过渡更平滑。

实战案例:夜景预览水波纹的根因与修复

回到开头的那个问题。我们用trace工具抓了IFE的输出和IPE的输入,发现IFE输出的YUV数据在暗部区域的噪声分布是“条纹状”的,而不是随机颗粒状。进一步检查,发现是IFE的HDR合成模块在低照度下,长曝光帧和短曝光帧的对齐精度不够,导致运动物体边缘出现了“撕裂”,这种撕裂在暗部被BPS的TNR误判为运动区域,于是TNR没有做降噪,反而做了锐化,最终在IPE里被放大成水波纹。

修复方案分两步:第一步,调整IFE的HDR对齐参数,在Chromatix里把hdr_alignment_strength调高,同时增加对齐搜索范围。但注意,这会增加带宽消耗,需要确认DDR带宽是否够用。第二步,在BPS的TNR里,把motion_strength调低,让TNR更倾向于降噪而不是运动保护。这样改完之后,水波纹消失了,但暗部噪点稍微多了一点,客户能接受。

个人经验性建议

第一,调ISP参数之前,先花半天时间看懂trace工具的输出。高通提供了CamXChi-CDK的调试接口,能实时查看每个模块的输入输出统计信息。很多问题,看一眼统计信息就能定位,比瞎猜参数快得多。

第二,Chromatix里的参数不是越多越好。高通的tuning数据有几百个节点,但真正影响画质的核心参数就那么十几个。把核心参数吃透,比盲目调一堆边缘参数有用得多。我见过有些工程师把chromatix_common里的参数全改了一遍,结果画质反而变差了。

第三,量产调优一定要做“场景矩阵”测试。不要只在实验室的D65光源下调,拿到户外、室内暖光、夜景霓虹灯下都测一遍。很多问题在实验室里根本复现不了,一上产线就冒出来。

第四,别忽视带宽和功耗约束。ISP调优不只是画质问题,还是系统问题。你调高了TNR的搜索窗口,帧率可能就掉了;你调高了LTM的strength,功耗可能就上去了。在量产项目里,画质、帧率、功耗、发热,永远是一个平衡游戏。

最后,多看看高通的Release Notes和Kernel代码。很多已知问题,高通会在Release Notes里说明,包括推荐的参数范围。Kernel代码里的注释,有时候比文档还详细,尤其是那些TODOFIXME,往往就是坑的标记。

这篇笔记先写到这,下次咱们聊聊联发科Imagiq的架构差异,以及怎么在高通和MTK之间做平台移植。有问题评论区见。

← 返回列表