Camera 基础

光子的奇幻漂流:Android Camera 到底该怎么学


做了快十年 Camera,有不少同学问我:想转行做相机、或者刚毕业想往这走,从哪学起?这篇不是教程,是个过来人给完全没碰过 Camera、但会 Java 和 Android 的人,理的一条能落地的路。但我先不讲 API、不讲架构——我先带你去相机工厂"卧底"一天。

主角介绍:下面这位叫小光,是一缕从你拍的风景里出发的光子。它要闯过的每一道关卡,就是一张照片诞生的全过程。你顺着它的脚印走一遍,再回头看 Camera2、CamX、那些 ISP 缩写,就跟看同事花名册一样亲切。
小光:终于有人带我逛工厂了!别看我现在亮晶晶的,待会儿你就知道我一路多折腾——下五层楼、跨两个部门,被十几道车间轮番盘问。

先问你一件你八成从没想过的事:你昨天发朋友圈那张照片,在被你"看到"之前,光,在手机里跑了一场什么样的接力赛?

如果你脱口而出"不就是相机 App 调个接口嘛"——那今天这篇,就是专门写给你看的。

真相是:你按下快门那一下,小光要穿过五层楼、跨两个部门、被十几道车间轮番盘问、被十几种算法挨个收拾,才从"外面那个世界"变成"相册里那张图"。而且这场接力赛,在你按快门之前就偷偷开跑了——你屏幕上那个实时预览,就是小光在跑第一棒。

网上能搜到的教程,两极分化得厉害。一头太浅,通篇"Camera 就是调 Camera2 API 拍照",看完你还是不知道相机为啥卡、竖屏拍出来为啥歪、夜景为啥能拍亮。另一头太深,上来让你啃 CamX 源码、读 Usecase 那堆 C++ 模板,三天基本劝退。

我自己前后写了 57 篇笔记(后来叫"小驰私房菜")。这篇就当个过来人,先把"从哪开始、学什么、以及你手机上那些怪现象到底是哪一层的锅"给你理清楚。文中所有平台代号、sensor 型号、项目路径都按通用写法给出,只讲原理和思路,具体代号你以手头平台为准。

小光要过的六道关,也是你该学顺序——别一上来就闯第四关
报案录:小光出过的那些"事故",根因在哪一关?
下面这张表建议先扫一眼,后面讲到对应关时你会回来翻它。它也是整篇的目录。
你遇到过的怪事
技术根因(先有个印象)
主要在哪一层
竖屏拍出来是横的 / 歪的
orientation、mount angle 的 roll/pitch/yaw
驱动 / HAL
夜景能拍亮、手持不糊
多帧降噪 MFNR + 对齐
ISP(IPE)
逆光人脸不死黑、亮处不过曝
人脸不死黑=Face AE(人脸区域加权测光);亮处不过曝/暗部不死黑=HDR 多曝融合 + LTM 局部提亮
3A(AE)/ ISP
人像背景虚化
双摄视差 / 单摄分割出深度图
算法 / HAL
自拍美颜、肤色好看了
肤色 SCE + 记忆色 MCE + 磨皮类降噪
ISP
变焦丝滑、主摄长焦切换无感
多摄逻辑、不同 sensor 切换
HAL / Framework
微信扫码"秒开"
小分辨率 preview + 独立检测通路
App / HAL
自拍预览"镜子"、照片却反的
预览镜像 vs 存储不镜像
App / HAL
连拍、抓拍不卡
ZSL(零快门延迟)环形 buffer
HAL / ISP
慢动作
高速 sensor mode + 高帧率
驱动 / 算法
专业模式能调 ISO / 快门
3A 转手动(MANUAL_SENSOR)
Framework / HAL
RAW 格式灰蒙蒙
没经过 demosaic / ISP 调色
ISP(BPS)
照片运动模糊、抖
EIS/OIS 没生效或 AF 没对上
ISP / 3A
明明配 60fps 实际 30
帧率瓶颈、slowJpegMode、SOF 间隔
HAL / Kernel
出发前:先盘点你的「弹药」(第零步)

小光要进厂打工,得先过几道岗前体检——不是考它,是考你。很多初学者不是不聪明,是一上来直接扎进 HAL 源码,结果卡在「这行 C++ 在干啥」「这份 datasheet 哪个表是分辨率」。下面这张单子,按「方向 → 要懂啥 → 哪层用得上 → 怎么补」列清楚。先别急着全会,对着勾,知道自己缺哪块、去哪补,就够了。

方向
上岗前要懂啥(点到为止)
主要用在这层
怎么补(不啃全本)
① 图像 / 信号处理
数字图像(像素 / 位深 / RGB·YUV / gamma)、Bayer 为啥只采一色、噪声模型(散粒 / 读出 / 固定模式)、曝光三角(ISO / 快门 / 光圈)、AE / AWB / AF 原理
3A、ISP 全算法、HDR / 夜景
《数字图像处理》前几章 + 边看边对照你手机拍的图
② 硬件 / sensor
sensor 原理(光电效应 / BSI / 卷帘快门)、光学(焦距 / 光圈 / 景深 / FOV / 畸变)、怎么读 datasheet:mode table(分辨率×帧率)、上电时序、I2C 地址、电气特性、OTP / EEPROM 寄存器、模组构成(sensor + lens + VCM + EEPROM,模组厂烧 golden)、MIPI CSI-2 / CCI 物理层
驱动 bring-up、sensor 移植、orientation
拿手头一颗 sensor 的 datasheet 当练习,照 mode table 填 dtsi
③ 软件 / C++
C++(指针 / 内存 / 类继承 —— HAL 大量用抽象类做接口)、多线程与实时流水线、设计模式(CamX 里工厂 / 策略到处是)、Android 基础(Binder / HAL 接口 HIDL·AIDL / SELinux / 分区)、构建系统(Soong / Android.bp,怎么改重编 HAL)、调试(adb / logcat / trace / dump)
HAL / Framework / 平台代码
先能独立编过一次 HAL,再谈改
④ 我补的三块(你没提但必卡)
Linux 驱动(设备树 DTS / DTSI、sysfs / proc、kernel 驱动模型);工具链(git / Ubuntu 编译环境 / repo / 厂商 tuning 工具 / python·shell 做日志分析);轻量数学(线性代数看色彩矩阵、概率统计看降噪与对齐融合)
Kernel / 全链路 / 日常效率
orientation、上电日志全在 DTS;日志分析靠 shell / python 提效
小光:上岗前我也得"考证"。不会读 datasheet,我连门都进不去;不懂 C++ 抽象类,到了 HAL 车间连扳手都不会拿。你先把这几本证混个脸熟,后面进厂就不慌了。
书的角度说一句:这一节不是要你当场学会,是让你心里有张地图。后面每一关学到哪、对应哪块弹药,你回头翻这张单子就懂了——这跟看书先翻目录一个道理。
能力自测:对着勾,知道自己差哪
你能不能……
对应方向
现在状态(打勾)
说出 RGB 和 YUV 的区别、Bayer 为啥绿点多
① 图像
☐ 能 ☐ 还不会
看懂一份 sensor datasheet 的 mode table(分辨率 / 帧率)
② 硬件
☐ 能 ☐ 还不会
独立编译过一次 HAL / Framework
③ 软件
☐ 能 ☐ 还不会
在 dtsi 里找到 sensor 的供电 / 时钟 / I2C 节点
② 硬件 + ④ Linux
☐ 能 ☐ 还不会
用 git / shell / python 从一堆 logcat 里捞出 camera 相关行
④ 工具链
☐ 能 ☐ 还不会
讲清曝光三角(ISO / 快门 / 光圈)怎么影响一张图
① 图像
☐ 能 ☐ 还不会
别被这单子吓到。它是一张地图,不是作业。标"还不会"的,就是后面各关要补的弹药——带着问题往下读,比 blank 状态硬啃源码,效率高十倍。
第一关:小光进门,先搞懂这栋工厂有几层楼

很多人学 Camera 卡住,是因为一开始的认知就歪了:以为相机开发 = 会调 API 就行。其实 Android 相机是分五层的——你写的 App 调用的那点接口,只是顶楼

咱们把手机相机想成一栋工厂大楼,一共五层:

  • 顶楼 · App 办公室
    ——你写的相机 App,负责"接单"。
  • 四楼 · Framework 经理层
    ——CameraService 坐这,它就住在"厂长"cameraserver 的大办公室里(和 App 不在同一进程,但跟 cameraserver 同住)。
  • 三楼 · HAL 外包部
    ——叫 CameraProvider,注意,它是个独立部门,不在 Framework 那栋楼里(这是 Treble 改革后的事)。
  • 二楼 · Kernel 后勤
    ——驱动、内核,管上电、配时钟这些脏活。
  • 一楼 · Hardware 车间
    ——Sensor 等真硬件,小光就是从这儿"出生"的。
小光每下一层楼,都得在门口填单子——Binder / HIDL 就是跑腿的快递员
小光:这栋楼我熟。从顶楼 App 一路下到一楼 Hardware,每层门口都要填单子——Binder 那哥们儿就是跑腿的快递员,跨部门的活儿全靠它送。
有个坑初学者必须提前懂:Treble 之后,HAL 不再住 cameraserver 里,而是单开一个 CameraProvider 进程。四楼的 CameraService 和在三楼的 CameraProvider 不在一栋楼,两者靠 HIDL/Binder 通信。我笔记第 23 篇专门讲它俩的启动流程——你可能觉得"启动流程跟我写业务有啥关系"。这关系其实大得很:你后面看 log,得先知道日志该去哪个进程捞,不然对着 logcat 一脸懵。进程模型不清,debug 时你连"这段逻辑跑在哪"都搞不准。
口诀一:相机不是调一个 API,是让小光下五层楼、跨两个部门。
第一步别读源码,先把"从点开相机到第一帧出来"在脑子里走一遍。
第二关:硬件团队,小光出生的一窝同事

新手最爱把 sensor 当黑盒。其实做 Camera 驱动,第一件事就是跟硬件打交道。小光不是孤身一人——它出生在一整个模组团队里。

新增一个 driver,就是先跟硬件同事 / 模组厂把这一圈人要齐
团队花名册: -Lens(镜头大叔):把四面八方来的光聚到 Sensor 脸上。 -VCM 马达:推着 Lens 前后挪,这就是对焦 AF。 -Sensor(小光它妈,感光工厂):把光变成电信号。 -EEPROM/OTP(身份证):模组厂烧进去的校准数据。 -模组厂 golden(标准答案):出厂时标定的基准。

我笔记第 02 篇讲"新增一个 driver 要准备什么",清单很实在:原理图、sensor 规格书、马达规格、lens 参数、EEPROM/OTP 数据、模组厂给的 golden……这些不是文档套话,是你真要去跟硬件同事和模组厂要的东西。少一样,bring-up 的时候你就知道什么叫寸步难行。

趁早弄懂这几块,不然后面看代码全靠猜:

  • facing / orientation / mount angle
    。facing 是前后摄,orientation 是旋转角,但真正坑人的是 mount angle 那套 roll/pitch/yaw——它是从 dtsi 里读出来的。第 06 篇专门捋过,因为这几个值散在 camx 代码好几个地方,新手看一个懵一个。
  • Remosaic / QuadCFA / Binning
    。现在主流 sensor 基本都是 QuadCFA(四合一),不懂这个你看不懂它输出尺寸为啥那么怪,也理解不了"四合一"模式下拍照和预览的区别。第 03 篇讲的。
  • OTP / EEPROM 校准
    。sensor 出厂每个都不一样,模组厂烧一份 golden,开机读出来用。第 10 篇讲怎么 dump,以及 camx 和老框架开关不一样。
  • 3A(AE/AF/AWB)
    。先扫个盲:AE 管曝光、AF 管对焦、AWB 管白平衡。AE 还能加人脸权重(Face AE)——逆光人脸不死黑就靠它,第四关讲。别一上来扎进去。
日常钩子①:为什么竖屏拍出来是歪的 / 横的?
你拿着手机竖拍,但 Sensor 在模组里是固定方向焊死的,它"认为"的上下和你握的方向不一定一致。Framework 拿 orientation 和 dtsi 里的 mount angle(roll/pitch/yaw)来把图转正。这套值配错了,就会出现"预览是正的、存下来是歪的",或者"某些机型旋转怎么都不对"——根因往往就在驱动里这几个角度参数。所以 facing/orientation 看着枯燥,真出问题能让你调一下午。
自拍"镜子感"是预览层玩的戏法,落盘的照片是没翻转的
第三关:ISP 车间,小光第一次"变身"

小光从 Sensor 出来时,是个"黑白盲盒"——咱稍后解释。ISP 干的事,就是把"生"的小光做成能看的图。高通把 ISP 拆成三道车间:IFE、BPS、IPE。但有个点特别容易看漏,也是我当年踩过的坑:

我踩过这个坑:有次排查预览卡顿,第一反应是去 BPS 里找问题,折腾半天发现预览压根不经过 BPS,纯属白忙。所以记住 debug 铁律第一条——先想清楚你现在是预览场景还是拍照场景,通路都不同,问题位置当然不同
整篇 ISP 最该钉死的一张:BPS 是拍照专属 VIP 通道,预览不进
小光:预览的时候我抄近路直接去显示,根本不进 BPS;只有拍照才被拉进 BPS 魔法院"上色"。所以你排查预览卡顿,别来 BPS 找我——我压根没在那儿。

IFE 是流水线第一道,直接吃 Sensor 的 raw,干坏点校正(ABF)、镜头暗角、PDAF 那些前端脏活。BPS 只活在拍照线,做 demosaic(下面细说)和一部分拜耳域处理。IPE 是真正的"精修化妆间":缩放、锐化(ASF)、降噪(WNR/HNR/MFNR)、局部色调映射(LTM)、各种颜色增强,最后送显示或编码。你照片里"通透感""夜景干净程度"大半是 IPE 的功劳。

为什么小光刚出来是"黑白盲盒"?这就得说拜耳阵列(Bayer)。Sensor 上面盖了张"筛子":每个像素只让一种颜色过——红、绿、绿、蓝,按 RGGB 排。所以小光刚出生,每个像素只认识一种颜色,剩下俩颜色全是空的,图看着就是绿油油、灰蒙蒙的"马赛克"。demosaic 就是 BPS 替每个像素"脑补"出邻居那两种颜色——这也是为啥预览敢跳过 BPS:预览要快,手机偷懒直接用降采样,不费劲去猜颜色;拍照要质量,才进 BPS 认真补全。
"RAW 灰蒙蒙"的真相:不是相机坏了,是小光还没上色
小光:刚出生时我是"色盲"——每个像素只认一种颜色,图看着绿油油、灰蒙蒙。进了 BPS,那位算命先生帮我把邻居的颜色脑补出来,这才有彩色。RAW 之所以灰,就是因为我还没进这道门。
日常钩子②:为什么 RAW 灰蒙蒙、JPEG 却鲜艳?
RAW/DNG 就是小光刚出厂、还没进 BPS 的素颜——没 demosaic、没 ISP 调色,所以平、灰、偏色。但这恰恰是后期空间大的原因:你拿到的是最原始的信号。JPEG 则是小光走完 IFE+BPS+IPE 全套精修后的"妆后照"。理解它,你就懂了"为什么专业模式 RAW+JPG 双出"。

ISP 里那一串缩写 ABF/LTM/ASF/WNR/CC/ACE/MCE/SCE,初学者最容易被劝退。但它们每一个都是"先有毛病,才造出这个工匠"。我把每个 ISP 模块的"病症"和"治法"整理成卡片——理解了"它在修什么",比背名字有用十倍

ABF自适应拜耳滤波
毛病:暗部常灰区一堆噪点,越往后越难压
治法:在 demosaic 之前的拜耳域就先去噪,给后面减负
工匠:门口橡皮擦大叔
Lens Rolloff镜头暗角校正
毛病:镜头漏斗效应,四角发暗、部分区域偏色
治法:按像素位置查 2D 增益表乘回去
工匠:四角打光师
CC色彩校正
毛病:相机感光和人眼不一样,直出颜色"不对"
治法:3×3 矩阵把相机色彩拉回人眼观感
工匠:色弱矫正师
ACE色度增强
毛病:颜色不够鲜艳、发闷
治法:(B-G,R-G)→(Cb,Cr) 的 2×2 矩阵调饱和
工匠:调色画师
MCE记忆色增强
毛病:绿叶、蓝天、某种红不够生动
治法:只增强指定"记忆色"区,不拖累其他色
工匠:记忆色画师
SCE肤色增强
毛病:肤色不合偏好(地域/文化不同)
治法:肤色三角变换,调到"大家喜欢的那档"
工匠:肤色化妆师
LTM局部色调映射
毛病:大光比下暗部死黑、亮部过曝
治法:只提亮暗部,亮部/中间调不动(区别于全局 GTM)
工匠:局部调光师
ASF自适应空间滤波
毛病:图发糊、缺细节和边缘
治法:9×9 边缘检测锐化,可分别调横/纵强度
工匠:描边刀客
WNR小波降噪
毛病:sensor 噪点明显,尤其暗处
治法:4 级小波分解,分层提噪、保住边缘细节
工匠:扫沙僧
Demosaic去马赛克
毛病:拜耳每个像素只认一色,图是"马赛克"
治法:猜出另两色(拍照线由 BPS 完成)
工匠:算命先生(在 BPS 魔法院)

你照片里"通透感""夜景干净""肤色好看",拆开看全是上面这些工匠在分别干活;而"逆光人脸不死黑"第一功臣是 3A 里的 Face AE(人脸区域加权测光),LTM 这类局部提亮工匠再搭把手。调图(tuning)工程师一辈子就在调这些工匠的表和强度。

口诀二:预览抄近路跳过 BPS,拍照走全套进 BPS 上色。
记不住就念——"预览不进 BPS,拍照才进 BPS",这句值一千行代码。
第四关:小光遇到的"日常怪事"大解密

前面铺垫够了,现在回头看你每天用手机拍照那些"玄学现象"。每一个,都能在小光的旅行里找到对应的一站。

夜景能拍亮、手持不糊 → 多帧降噪 MFNR
钩子③:夜景模式本质是"多帧"。暗环境单帧曝光不足、噪点爆炸,算法连拍好几张(常是长曝光或同场景多帧),先靠陀螺仪/图像对齐(常借 EIS 的对齐能力),再融合——信号叠起来、噪点相互抵消,最后整体提亮。所以你按完夜景常要"稳一下、等一两秒",那是在等多帧收齐和对齐。预览和拍照通路不同,也意味着夜景多帧发生在拍照线(走 BPS/IPE),不是你眼睛看到的实时预览。
夜景"手稳等一下"不是在装,是在等 MFNR 收齐分身
小光:夜景时我得叫几个分身一起拍几张暗帧,再对齐融合。所以你按完夜景要"稳一下"——那是在等我们分身收齐呢,不是手机卡了。
逆光人脸不死黑、亮处不过曝 → 其实是两件事
钩子④(上):先戳破一个误会
逆光人脸不死黑,主要功臣不是 HDR,是 Face AE。普通 AE 对整个画面平均测光,逆光时背景亮得晃眼、人脸却黑乎乎,一平均就按背景曝光——人脸直接糊成剪影。Face AE 不一样:3A 里先做人脸检测框出脸,把测光权重死死压在人脸区域,曝光就按"让人脸正常亮"来定。所以"人脸不死黑"第一负责人是 Face AE。
钩子④(下):HDR 管的是整场景动态范围
而"亮处不过曝、暗处不死黑"才是 HDR 的活儿:连拍几张不同曝光的图——一张欠曝保住天空高光、一张正常、一张过曝保住暗部——对齐融合成"亮暗都清"的图;融合完再由 IPE 里的 LTM 做局部色调映射,只把暗部提亮、亮部原样不动,所以不会"为了救暗部把整张图弄得灰扑扑"。后面进阶篇给 HDR / Face AE 的开关和 dump 命令。
LTM 只提暗部,所以高光细节也留得住
人像背景虚化 → 双摄兄弟量"身高差"出深度
钩子⑤:自拍"肤色变好看了",核心是 SCE(肤色偏好变换)+ MCE(记忆色让嘴唇/脸颊更生动),再叠一层类似 WNR 的"磨皮"柔化皮肤。人像虚化,要么双摄用左右视差算深度图(硬件上要多一颗副摄),要么单摄用分割算法把人抠出来再对背景模糊——属于"算法层"的活,不一定动 ISP。这些在 HAL/Framework 层会走专门的 usecase(人像 usecase 多挂深度相关的 pipeline),进平台代码会见到。
扫码秒开、变焦无感 → 轻量通路 + 多摄接力
钩子⑥:微信扫码走的是"员工通道"——它不需要完整 ISP 精修,只要一个小分辨率 preview 流喂给识别算法,所以一开相机就能识别,比正式拍照快得多。变焦则靠多摄:手机里往往躺着超广角、主摄、长焦好几颗 sensor,系统按倍率无缝切换(中间还可能用算法做融合补帧),让你感觉"一直是一颗镜头在变焦"。这些在 CamX 里就是不同的 Usecase / Feature 组合。
多摄不是噱头,是几颗 sensor 在 HAL/Framework 调度下接力
小光:变焦时我们三兄弟(超广角 / 主摄 / 长焦)轮流上,Framework 按倍率点名。你感觉是"一颗在变焦",其实是我们接力跑,中间还有算法补帧。
还有个几乎人人都踩的坑:YUV_420_888 和 Stride

Camera2 把格式设成 YUV_420_888,ImageReader 会给你三个 Plane(Y/U/V)。但每个 Plane 在内存里怎么排,厂商实现不一样。我笔记第 04 篇举了个真事:我手头两台不同品牌的手机,一台(华为 P20)getRowStride 等于宽度,另一台(小米 8)不等——比如 width=8,RowStride 可能是 10,后面有补齐。所以你取数据不能直接 memcpy,必须按 RowStride 跳着读,否则出来就是花屏

像买一盒蛋每排 8 个,托盘却每排 10 格——闭眼按 8 搬就串行了

怎么算 Stride?width 宽、每像素 N 字节:stride = N * width,不是 4 的倍数再补齐到 4 的倍数。排查时,高通 camx 框架下 logcat 过滤StrideXsliceHeight就能看到 dump 出来的 stride 和 sliceHeight,一帧 1920×1080 用 yuv 工具看时把 size 设成 2048×1536 就能正常显示——多出来的就是对齐 padding。

第五关:管理层,高通 CamX 的"公司汇报链"

前面的铺垫都为了这一步不劝退。CamX-CHI 的几层你先记:Usecase(一个具体配置)→ Feature(要开的若干功能)→ Pipeline(实际的数据加工流,驱动层靠它理解数据怎么走)→ Node(流水线上的一个操作块)。这里有个特别容易搞反的点:Pipeline 内部长什么样,是用一张「有向无环图(DAG)」来描述的,这张图就叫 Topology——它不是 Pipeline 上面再叠一层,而是 Pipeline 的"图纸":一串 Node 被 link 串起来、中间用 buffer 传数据,Node 串起来就构成了 Topology。整张图写在 XML 里(这套描述也叫 "Pipeline – XML Topology Graph")。CHI 全称 Camera Hardware Interface。

把它想成一家大公司的汇报链就通了:

  • Usecase = 公司接的一个具体单子
    ,比如"20MP 连拍 ZSL + 2K 预览"算一个 usecase。一个 usecase 可以带好几个 Feature。
  • Feature = 单子里的"功能开关"
    (ZSL / 夜景 / 人像…),开哪些,决定这条流水线要干哪些活。
  • Pipeline = 这条数据加工流水线本身
    ,驱动层靠它理解数据怎么流。
  • Topology = Pipeline 内部的 DAG 图纸
    ——一串 Node 用 link 连起来、中间用 buffer 传数据,这就是 topology。它不是 Pipeline 的上一层,而是"Pipeline 长什么样"的描述,写在 XML 里(也叫 "Pipeline – XML Topology Graph")。
  • Node = 图纸上的一个操作工
    ,干一件具体事(比如"把水印贴上去")。Node 串起来,就构成了 Topology。

而且——整张图写在 XML 里,等于说这家公司的"组织架构图"是一份可改的配置文件。你要加个新工人(自定义 Node),改改 XML + 写个 Node 类就行。

Usecase→Feature→Pipeline;Pipeline 内部由 Topology(DAG) 的一串 Node 落地
小光:每次来拍照,App 下的单子(Usecase)会带上一串功能需求(Feature),落到具体就是一条数据流水线 Pipeline;而这条流水线真正长啥样,由一张 Topology 图(DAG,写在 XML 里)说清楚——一堆 Node 用 link 串起来、buffer 传数据。想加道工序?往 topology 里加个 Node 类、改改 XML 就行。

真要动手,从两件事切入最划算:

  • 加一个自己的 Node
    。我第 05 篇以"加水印"为例,讲怎么在 camxnode.cpp 里加一个Node::WatermarkImage。这是理解 Node 机制最快的方式——你改的不是某个神秘配置,而是实实在在地往流水线里塞了一道工序(相当于给车间加一名新工人)。
  • 学会 debug
    。camx 有个camxoverridesettings.txt,配合persist.vendor.camera.*那堆属性,能开关各种日志、强制走某条路径。帧率怎么查、EIS 怎么开,我第 07、08、18–22 篇都有具体命令。这些不是理论知识,是每天干活都要用的。
老法师的锦囊(debug 三件套): - 想看 raw 直出:设persist.vendor.camera.raw.dump 1(代码在 QCamera3HWI.cpp 附近)。 - 想看 HDR 中间结果:设persist.vendor.camera.imglib.dump 1persist.vendor.camera.imglib.hdr.dump inout,连输入输出一起 dump。 - 这些命令在不同平台属性名可能略有差异,但套路一样——先把数据落盘,再拿工具一点点看。

新一点的平台还有 Feature2 框架(GraphSelector/GraphManager、TBM、FRO 那些)。我的建议是:先把上面老架构逻辑吃透,再去看 Feature2,不然容易被新名词带着跑。

进阶钩子:RawHDR 是怎么用 Feature2 拼出来的?
我笔记第 057 篇分析过一个真实的 Feature2 图:输入 3 张 Raw、输出 1 张 Raw 的 RawHDR,它的 feature graph 是RT → RawHDR → Bayer2YUV → JPEG。意思是:RealTime 实时流先跑,RawHDR 这颗 feature 把 3 张 raw 融成 1 张,再交给 Bayer2YUV 转 YUV、最后 JPEG 编码。你看,Usecase→Feature→Pipeline→Node 那套抽象,到这就能对应上一个真实串接。进代码后,这种图就是你的地图。
这就是 Usecase→Feature→… 抽象在真实代码里的样子
第六关:隔壁的 MTK 工厂(一笔带过)

MTK 是 mtkcam3 那套,imgsensor 的玩法和高通不一样,路径、命名、调优入口全两样。但背后的思想——分层、数据流、3A、ISP 处理——是相通的。这篇先不展开,免得你一开始两头抓,后面单独写。

第七关:小光出师,你该怎么练(进阶实战)

入门之后,真正拉开差距的是这几块——它们也是如今做相机最吃香的方向:

  • 帧率和性能优化
    。为什么配了 60fps 实际只有 30?一个很实的思路:看 SOF(sensor 每帧起始)间隔,比如日志里 frame 37、38 间隔约 33ms,那实际就是 30fps;如果看到requestID=0,说明是无效帧被 Kernel 丢掉了(KMD drop)。还有个坑叫slowJpegMode——一旦被选中,ZSL 就不支持了,整条配置都会变。这些我在第 08、18–20 篇有实战思路。
  • 应用层集成 Raw 域算法
    。比如用createReprocessableCaptureSession把 raw 拿出来自己算,再塞回去。第 09 篇讲的,涉及 privapp 权限那套坑:高通平台要在persist.vendor.camera.privapp.list里加你应用的包名(注意 selinux,最好setenforce 0再设)。MTK 和高通思路一致——App 层先查REQUEST_AVAILABLE_CAPABILITIES里有没有 RAW,再看availableStreamConfigurations里 OUTPUT 有没有 32(RAW16)。
  • 常见问题怎么查
    。没捷径,就是踩出来的。比如 sensor 上电:日志里能看到 Mclk 给到 24MHz、i2c slave address、搜到具体 sensor 名,这些是 bring-up 时确认"硬件通了没"的第一手信号。我笔记后面那些篇幅,大半是踩坑复盘。
  • 功耗与发热控制
    。相机是整机耗电和发热的大户:sensor 上电、ISP 全速跑、DDR 带宽拉满,再加夜景那种"连拍好几张"的长曝光,电量肉眼可见往下掉。更坑的是发热会触发 thermal throttle(降频),直接表现为"拍一会儿就掉帧、画质也跟着降"——所以功耗和前面的帧率其实是一根绳上的。进阶思路是低功耗流水线:能跳过的不跑、预览分辨率往下降、stream on/off 时序掐准,还得算清楚 ZSL 那批环形 buffer 的内存和功耗代价。
  • 多摄协同与一致性
    。现在的旗舰卖点大半在"几颗镜头像一个人"。难点不在单摄,而在主摄 / 超广角 / 长焦之间:色彩、白平衡、曝光要对齐,切换要无感,双摄还要算景深做虚化。你前面看的小光"三兄弟接力",到进阶就是"怎么让三兄弟拍出来像同一台机器"。
  • 计算摄影与 AI(跑在 DSP / NPU 上)
    。夜景、人像、超分、虚化,越来越多不是纯 ISP 硬算,而是把模型丢到 hexagon DSP / NPU 上跑。这意味着进阶工程师得懂算法怎么部署、模型在功耗和性能之间怎么权衡——这也是这几年行业最明显的一个方向。
  • 视频能力与防抖
    。录像和拍照是两条不同的通路,市场又最看重:4K/8K 能不能稳、EIS/OIS 防抖到不到位、高动态视频(HDR video)能不能压住。稳定性(不卡顿、不掉帧)和首帧延迟(冷启动多快出画面)都是硬指标,后面会单列来讲。
  • 画质调优(tuning)与客观评测
    。前面那些玩意儿最终都得"落到画面上好看"。每个模组都要做 tuning:AE/AWB/AF 的表、ISP 各模块的参数、镜头 shading,靠 Chromatix7 那类工具一点点调。还要会看 IQ 测试 chart、读客观指标、做竞品对比——这是 Camera 工程师最日常、也最见功力的活。
口诀三:Camera 不难在某个绝世知识点,难在它"长"。
从 App 到 Kernel 一条线,任何一环你不懂,小光的旅行就卡在那。
顺着小光的脚印走一遍,比背十本手册都管用。
最后,说点实在的

我这些笔记也是踩了好几年坑才攒出来的。不指望你照着看一遍就全会,但按这个顺序走——先建立分层认知(顺手把"每天拍照那些怪事"对上号),再啃硬件和驱动,然后理解 ISP 和数据流(记住预览跳过 BPS、拍照走 BPS),最后进平台代码动手改——至少不会一上来就被源码劝退。

具体每一块怎么往深了挖,后面我按这个路线一篇篇写。这篇先解决"从哪开始、学什么、以及你手机上那些现象到底是哪一层的锅"的问题。


图片

《更多交流,欢迎加入知识星球》

推荐阅读:

关于博主 

采用v4l2loopback来实现 虚拟Camera

Camera基础及一些基本概念

Android Camera 学习路线 | 个人推荐

Android Camera开发系列(干货满满)

Camera Hal|如何学习一个新平台

一篇文章带你了解Android 最新Camera框架

学习完Camera入门课程视频,可以去找工作了?


欢迎扫码关注「小驰行动派」公众号 10 年Camera开发 | Camera技术干货 | 行业洞察 | Camera实战分享
小驰行动派公众号 扫一扫关注
分享到: 复制链接
← 上一篇 MTK Camera性能优化:冷启动全链路八阶段分析与优化实战 下一篇 → Camera ISP Overflow排查全攻略:三类溢出问题一网打尽

相关文章

推荐课程

想系统学习 Camera 开发?看看这些课程

评论 (0)

暂无评论,快来抢沙发吧