直接把“配置size”这件事讲透。这篇文章不打算从头讲MTK camera整体架构,那些HAL层怎么流转、pipeline怎么构建,网上文档不少,但唯独“metadata里的size到底怎么配、配错了会发生什么、为什么这么配”这件事,很少有人掰开揉碎讲清楚。我结合自己做camera HAL和tuning相关工作的实际经验,把这块内容完整梳理一遍。
1. metadata文件中size配置的整体设计思路
1.1 先搞清楚metadata文件在整个相机体系里的位置
MTK camera的metadata文件,实际指的是camera_custom_*系列配置,以及HAL层用到的各类静态metadata、动态metadata模板。不同平台、不同版本,文件组织方式有差异,但核心逻辑是一致的:metadata就是相机硬件能力和软件行为之间的“契约书”。
这份“契约书”里写了sensor支持哪些尺寸、哪些帧率、哪些能力,也写了ISP pipeline应该怎么配buffer、怎么切场景、怎么限制stream。而size这个字段,几乎是整个metadata体系里最基础又最容易被误解的参数。
我记得刚接触MTK平台时,看到imgsensor_size、capture_size、video_size、preview_size这些字段,以为只是简单的分辨率枚举。后来深入发现完全不是这么回事——这里的size不只是分辨率,它背后关联着buffer分配、ISP吞吐、sensor裁剪、FOV计算、stretch/blending等一系列硬件行为。配错了size,轻则预览变形,重则直接黑屏或crash。
1.2 size在metadata中存在的形式与作用域
在MTK的metadata体系里,size出现的形态大致有这几类:
| 形态 | 典型字段 | 作用 |
|---|---|---|
| sensor原生分辨率 | sensor_size_full | 定义sensor输出最大分辨率 |
| 各场景裁剪尺寸 | capture_size/preview_size/video_size | 定义不同场景下实际使用的输出尺寸 |
| buffer配置尺寸 | buffer_size/max_payload_size | 定义buffer分配大小 |
| JPEG编码相关 | jpeg_size/thumb_size | 定义编码输出及缩略图尺寸 |
| 3A统计相关 | ae_size/af_size/awb_size | 定义3A算法的统计窗口尺寸 |
这些size不是孤立存在的,它们之间有明确的层级关系。比如preview_size不能超过sensor实际输出的最大尺寸,capture_size和video_size之间可能存在restriction(比如4K录像时不能同时支持某些尺寸的预览)。
1.3 为什么单独要把size拿出来做“解读”
很多人在MTK平台做二次开发时,第一个遇到的红线问题就是size配置。原因有三:
第一,size错误的表现极具迷惑性。有时候画面只是轻微裁切,有时候是绿屏,有时候是stall,有时候又是某些sensor模式下完全打不开相机,问题定位链路很长。
第二,size之间不是简单的包含关系。很多size字段之间的限制是隐式的,比如video_stable_size和capture_size之间就有联动,如果只看单字段配,当时可能正常,但切换场景就崩。
第三,定制项目里最常见的需求就是改size。做前摄打孔、做高分辨率预览、做特殊比例视频,都需要动这些配置,但改起来牵一发动全身。
所以这篇文章的核心思路就是,把size相关的配置项逐条讲清楚,把它们之间的逻辑关系串起来,然后结合实操给出一套可复用的排查方法。
2. 核心数据结构与配置项逐一拆解
2.1 sensor output size与scenario size的关系
MTK的camera hal中,每个sensor都有一个SENSOR_OUTPUT_SIZE相关的结构体定义。这里面的第一个坑就是:sensor output size不等于你最终拿到的预览或拍照分辨率。
sensor output size是sensor硬件层面能输出的最大尺寸,它决定了后续所有尺寸的上限。而scenario size(preview/capture/video)是ISP处理之后、送到不同模块的尺寸。
举个例子,某款48M sensor,sensor output size可能是8000x6000,但capture_size实际配的是4000x3000,preview_size配的是1920x1080。中间多出来的尺寸到哪里去了?是被ISP做了binning或者裁剪。
这里有一个关键的机制需要理解:
当MTK平台设置
capture_size小于sensor output size时,HAL层会做两种处理之一——如果sensor有binning模式,就切换到对应的binning输出;如果没有合适的binning档位,就保留sensor全尺寸输出,后续用ISP裁剪。这两种方式的功耗、帧率、FOV都不一样。
所以配置size时,不能只看数值本身,还要确认sensor驱动里注册的binning table是否覆盖了目标尺寸。我在一个项目里就遇到过:sensor只注册了2x2 binning和4x4 binning,metadata里却把video_size配成了介于两者之间的尺寸,结果HAL在切换时找不到匹配档位,直接回退到全尺寸再裁剪,导致FOV变小且功耗异常。
2.2 buffer size相关字段的隐含约束
MTK metadata中,buffer相关的size配置有几个容易踩坑的地方。
第一个是max_payload_size。这个名字看起来像个通用容量,实际上在MTK的实现里,它是用来约束HAL层申请buffer时的大小预算。如果配小了,大分辨率场景下buffer会申请失败;如果配大了,内存占用无谓增加,尤其在多路并发时,OOM风险会明显升高。
第二个是buffer_count。这个虽然不叫size,但和size强相关——每个buffer的size决定了单块内存大小,buffer count决定了这个大小乘以几。在配置metadata时,往往只改了单块size而忘了调count,导致应用层开出的buffer数量不足,出现帧率不稳定或者丢帧。
我自己的习惯是,在改任何size字段之前,先列一张全局buffer预算表,把所有stream(preview、record、capture、depth等)的size和count乘一遍,看总内存是否在平台限制范围内。
2.3 JPEG与thumbnail的size联动逻辑
拍照场景下,jpeg_size和thumb_size是最容易配出问题的两个字段。它们的逻辑关系是:
jpeg_size定义主图的编码尺寸和存储上限thumb_size定义缩略图的尺寸,通常由jpeg_size推导而来,但也可以独立配置- 某些平台上,
thumb_size的宽高比必须和jpeg_size一致,否则生成相册缩略图时会有拉伸
这里有一个实操层面的经验:在MTK平台上,配置thumb_size时建议遵循“等比缩放”原则,不要直接用目标宽高去填,否则JpegEncoder在生成EXIF缩略图时会做额外的scale,增加编码耗时。实测下来,在4:3的主图比例下,缩略图也保持4:3,编码耗时差异可以达到20%左右。
2.4 3A统计窗口size对算法的影响
ae_size、af_size、awb_size这几个字段容易被忽略,因为它们不直接影响输出画面。但它们决定3A算法的统计窗口大小——统计窗口越大,算法获得的信息越多,收敛越准确,但功耗和耗时也会增加。
这个size最终会映射到ISP的统计引擎配置上,配置过小会出现曝光收敛慢、白平衡偏色、对焦犹豫等问题。值得注意的是,统计窗口size和最终输出size可以不同,有些平台甚至建议统计窗口固定为某个尺寸,避免不同场景切换导致的3A扰动。
我在实际项目里遇到过一个问题:预览尺寸从1080p改成720p后,发现暗光下对焦变慢了,查了很久,最后定位到是因为af_size跟着preview size联动更新后变小了,统计信息不足。后来把af_size固定住,问题就消失了。
3. size配置的具体操作流程与参数计算
3.1 从sensor datasheet到metadata size的推导链路
拿到一颗新sensor,配置metadata size的完整链路是这样的:
第一步,确认sensor的datasheet中输出的所有分辨率模式,包括全尺寸、binning尺寸、裁剪窗口、各分辨率下的帧率限制。
第二步,明确产品需求,列出所有要支持的场景(预览、拍照、1080p录像、4K录像等),每个场景的目标分辨率和帧率。
第三步,建立尺寸映射表,把sensor输出模式和场景分辨率对应起来。这一步是核心,需要遵循几个原则:
- 每个场景优先选择sensor原生支持的尺寸,避免额外的ISP scale
- 如果sensor不支持目标尺寸,选择大于目标尺寸的档位,再通过ISP裁剪
- 帧率不达标的档位直接排除
第四步,把映射表填进metadata,同时更新相关的联动字段(比如FOV、crop region、3A窗口)。
这个流程看着简单,但每一步都有细节坑。举个计算例子:
假设sensor datasheet给出:
- 全尺寸:8000x6000,最大帧率15fps
- 2x2 binning:4000x3000,最大帧率30fps
- 4x4 binning:2000x1500,最大帧率60fps
产品需求是:
- 预览:1920x1080 @ 30fps
- 录像:3840x2160 @ 30fps
- 拍照:8000x6000
那么怎么配?重点看录像和预览。
录像3840x2160,不能直接落在sensor原生档位上。如果从8000x6000出,需要像素处理量是8000x6000x30,明显超过sensor输出能力,而且sensor全尺寸只有15fps,这条路走不通。如果从4000x3000出,做一次ISP缩放,4000x3000@30fps可行。所以video_size应该选4000x3000的档位。
预览1920x1080,两个选择:从4000x3000做ISP裁剪,或者从2000x1500做ISP缩放。从功耗角度,选择2000x1500更合理,因为像素量小。但注意2000x1500的比例是4:3,输出1920x1080需要裁剪,FOV会有损失。如果产品不能接受FOV损失,就要改用4000x3000档位。
这一步是典型的“每个选择背后都有代价”的case。
3.2 实操中修改metadata size的推荐步骤
以我常用的修改流程为例,大致分六步:
备份原始metadata文件,这一步不可省略。MTK的camera配置经常有隐性依赖,一旦改崩,还原配置能省下大量排查时间。
全局搜索所有size相关字段,先画出“现状地图”。我一般会把每个size字段当前值、所属场景、关联字段做成一张表,改之前心里有数。
按照上一节的推导链路,确定目标值。注意同时更新scenario size、对应的buffer size、FOV相关配置。
改完配置后,先做静态检查。用MTK提供的工具解析metadata,看是否有冲突项或超范围项。没有工具时,可以写一个简单的解析脚本,把各个size字段提取出来,按约束关系做一次逻辑校验。
上机验证基础功能。包括预览是否正常、缩放是否平滑、拍照是否出图、录像是否卡顿。这个阶段先不用做深度测试,确认能跑通就行。
做全场景回归,重点覆盖切换场景(预览到录像、录像到拍照)时的稳定性,以及前后摄切换、暗光环境。
这套流程我用了很多年,最大的价值不是“改得准”,而是“能回退”。颜色、清晰度、功耗类问题都可能与size改动相关,能快速定位到改动点,效率完全不同。
3.3 具体场景中的参数选择思路
高像素拍照场景:
如果产品主打高像素拍照,capture_size要配成sensor全尺寸,但这会带来两个问题:拍照瞬间内存压力大、快门延迟高。我通常的做法是,保留capture_size为全尺寸,但将拍照流程拆成两段——先预览占用低分辨率buffer,按下快门时再分配全尺寸buffer。这个方案在metadata不需要额外配置,只需要HAL层buffer管理配合。
视频防抖场景:
开了EIS之后,实际输出尺寸会小于sensor裁切后的尺寸,因为需要预留防抖移动空间。MTK平台在metadata中有一个video_stable_size的字段专门处理这个场景。配这个字段时,通常是目标视频尺寸的1.1倍左右,具体系数取决于防抖最大补偿角度。
超高帧率场景:
像720p@240fps这种需求,关键在sensor的binning档位是否能支撑。如果sensor最高只支持120fps,metadata配了240fps也跑不起来,HAL会按最高可用帧率兜底。这种问题在项目前期最好就通过size+frameRate联合检查排除。
4. 常见问题与排查技巧实录
4.1 预览画面裁切比例不对
这个问题出现的概率极高,尤其在定制前摄或者特殊屏幕比例的项目里。
先看metadata里的crop相关字段和FOV相关配置。多数情况下,是因为改大了sensor_size_full或者改小了preview_size,但crop region没有同步更新。MTK的crop region是相对sensor full size的比例坐标,如果sensor full size改了,crop坐标的绝对数值必须跟着变。
实操排查建议:先在HAL log里搜crop、CropRegion关键字,确认HAL计算出的实际crop值是否在sensor输出范围内。如果crop值越界,通常是metadata里的sensor full size和sensor driver注册的输出尺寸不一致。
还有一个隐蔽问题:部分MTK版本存在“二次crop”逻辑,即ISP先crop到scenario size,再做一次display crop。两层crop的size配置在不同字段里,改了一层忘了另一层,就会出现比例对但FOV偏小的情况。
4.2 切到录像模式黑屏或crash
这个问题通常和video size配置有关。黑屏的本质是video stream的buffer没分配成功,或者sensor mode切不过来。
从size角度排查,优先确认三件事:
video_size是否在sensor binning档位支持范围内- 对应
buffer size是否足够大 - video和preview的buffer总数是否超出平台内存限制
我有一个快速定位技巧:抓HAL的buffer alloc log,看requestBuffer的返回值。如果返回的是buffer size不足类错误,就直接查max_payload_size和buffer_size;如果返回的是内存分配失败,就要查总内存预算,而不是单一size字段。
实战中遇到过一个案例:项目在1080p预览正常,一切到4K录像就crash,log显示是buffer alloc失败。全局查下来,video_size配的是3840x2160,max_payload_size也够,但buffer_count只有3,而sensor在4K模式下需要4个buffer才能稳定跑帧,缺一个就崩。这个案例说明,size和count必须一起看,单独看哪个都容易误判。
4.3 拍照出图尺寸和预期不符
出图尺寸不对,一般是capture_size和sensor output size的匹配问题。
HAL的逻辑是:如果capture size正好等于某档binning输出尺寸,就切到对应sensor mode;否则用当前mode做ISP resize。问题是,很多定制项目里capture_size往往填的是产品需求分辨率(比如4000x3000),而sensor刚好又没有这一档原生输出,就会走ISP resize路径。虽然图能出来,但分辨率信息、FOV可能都变了。
检查方法很直接:抓sensor mode切换的log,看拍照瞬间sensor是否切换了mode,以及当前mode是否等于capture size。如果sensor mode一直没切,说明匹配逻辑没有触发。
一个比较容易忽略的细节是,某些平台的capture size匹配是精确匹配,不是范围匹配。比如sensor有4000x3000这一档,但metadata写成4000x3004,匹配会失败。别看就差4个像素,sensor mode就是切不过去。我在这上面栽过一次,后来统计了sensor驱动里所有mclk/pclk对应的输出尺寸,逐一对照metadata,发现这类问题全部可以通过脚本预先检查出来。
4.4 暗光下噪点明显或对焦慢
size配置对画质的影响常被低估。暗光场景下,如果preview_size设置了过大,ISP为了维持帧率会拉高gain,噪点就会明显变多。这种情况不是sensor的问题,是metadata配置的问题。
我踩过的一个具体场景:某项目用同一款sensor,A版本把预览配成全尺寸(8000x6000)再缩到屏幕分辨率,B版本用binning档位(4000x3000)。同样的暗光环境,A版本画面噪点明显更多,而且预览帧率只有B版本的一半。原因就是A版本让ISP一路高负荷工作,没有利用sensor binning在灵敏度上的优势。
改动建议:暗光场景优先选低分辨率binning档位作为preview_size,但要注意画面解析力不能牺牲太多。实际操作中是取一个平衡点——拿产品主打场景,分别用不同档位出图对比,选色彩、噪点、清晰度综合最优的。
4.5 一个容易忽略的内存相关事项
改大的size必然带来更大的内存占用。多路并发(前后摄同时工作、双景录像、画中画)时,尤其要关注总buffer大小。
MTK平台一般有一个整体buffer预算配置,不在metadata里,但在camera service或者HAL的config文件中。很多项目改完metadata后出现OOM,就是只改了单路的size,没看整机内存预算。
我的建议是:每次改完size配置后,做一次全场景内存估算,再跑一遍压力测试,不要只验证功能正常就完事。
5. 配置size时要记住的几条原则
做了这么多MTK camera项目,总结下来,配置size的核心原则其实就几条:
第一,一切size配置从sensor的实际能力出发。脱离datasheet谈size配置,等于闭眼开车。
第二,size是“牵一发动全身”的配置项。改了一个size,必须检查FOV、crop、buffer、3A window、sensor mode这些联动项。
第三,binning优先于ISP resize。硬件binning在功耗、帧率、暗光表现上都优于ISP后期缩放,能走binning就不要走resize。
第四,验证要在真实场景下做。尺寸改完,常规预览、拍照、录像都过了,不代表暗光、切换、多路并发也没问题。MTK platform的很多size问题要特定条件才能触发,必须把场景覆盖做全。
第五,保留完整的修改记录。camera的size配置牵涉面广,哪个版本、哪些字段改过,尽量留痕。我见过太多次排了一两周的疑难问题,最后发现是某次size字段改回来时漏改了一个关联项。
我个人在实际操作中最深的体会是:MTK camera的size配置,看起来只是填几个数字,实际上是一个涉及sensor硬件、ISP pipeline、内存管理、3A算法、编码模块的系统工程。把它的逻辑链条梳理清楚,比背各种平台上的字段名和默认值重要得多,项目也少踩很多坑。希望这篇解读能给正在调试MTK camera size的同行一些参考,少走一些我走过的弯路。