16. 厂商定制化优化:高通平台(mm-camera)、MTK平台(hal3a)、展讯平台适配
做相机启动优化,最头疼的是什么?
不是算法不够快,也不是代码写得不够好。而是——同一套代码,换了个平台,表现天差地别。
我这些年跟高通、MTK、展讯三家平台都打过交道。说实话,每个平台都有自己的脾气。你想想看,高通喜欢搞底层抽象,MTK 偏爱黑盒封装,展讯则是轻量级路线。摸清它们的性格,优化才能事半功倍。
高通平台:mm-camera 架构
高通用的是 mm-camera 架构。这个名字你可能听过,但它的启动流程,我估计很多人没仔细看过。
核心思路:高通把相机 HAL 层拆成了多个模块,每个模块跑在独立的进程里。这样做的好处是隔离性好,坏处是——进程间通信(IPC)开销大。
我在项目中遇到过一个问题:相机启动时,从 HAL 打开到第一帧预览,花了整整 800ms。排查下来,发现光是 mm-camera 的进程初始化就占了 300ms。
怎么优化?我总结了几个关键点:
- 预加载 mm-camera 守护进程:在系统启动阶段就把 mm-qcamera-daemon 拉起来,别等用户打开相机才初始化。
- 减少 IPC 调用次数:把多个小的 setParameter 调用合并成一个 batch 操作。我见过有人一次打开相机调了 20 多次 set,每次都要跨进程,不慢才怪。
- 调整 stream 配置顺序:高通对 preview 和 snapshot 的 stream 配置有依赖关系。先配 preview,再配 snapshot,能省掉一次 reconfig。
// 优化前:多次 IPC 调用
camera->setParameter("preview-size", "1920x1080");
camera->setParameter("preview-fps", "30");
camera->setParameter("preview-format", "NV12");
// 优化后:合并为一次
camera->setParameters(batchParams);
小技巧:高通平台有个隐藏的 debug 节点 /d/mm-camera/debug。打开它,你能看到每个模块的耗时分布。我一般先看这个,再决定从哪里下手。
MTK 平台:hal3a 的优化策略
MTK 的 hal3a 跟高通完全不同。它更像一个黑盒,很多逻辑封装在闭源库里。你没法直接改底层代码,只能通过配置和策略来优化。
我记得第一次接触 MTK 平台时,被它的启动流程搞懵了。明明代码里没做什么,启动却要 1.2 秒。后来才发现,hal3a 内部有个「预热」机制,默认会做很多初始化操作。
优化 MTK 平台,我建议从这几个方向入手:
- 关闭不必要的 feature:hal3a 默认开启了很多 feature,比如 HDR、美颜、场景检测。如果这些不是你需要的,在配置里关掉它们。我曾经关掉一个「智能场景识别」,启动时间直接降了 150ms。
- 调整 pipeline 深度:MTK 的 pipeline 默认深度是 4,意味着它会预申请 4 帧的 buffer。改成 2 或 3,能减少内存分配时间。
- 利用 vendor tag 控制行为:MTK 提供了很多 vendor tag,比如 "vendor.mtk.prewarm.enable"。设置成 1,可以让 hal3a 在系统启动时提前初始化一部分资源。
// 关闭不必要的 feature
camera->set("vendor.mtk.feature.hdr", "off");
camera->set("vendor.mtk.feature.beauty", "off");
// 调整 pipeline 深度
camera->set("vendor.mtk.pipeline.depth", "2");
注意:MTK 的 vendor tag 在不同芯片型号上可能不一样。我踩过坑,在 MT6779 上能用的 tag,到了 MT6785 上就失效了。适配前一定要查清楚目标平台的文档。
展讯平台:轻量级适配
展讯平台的特点是「轻」。它没有高通那么复杂的进程架构,也没有 MTK 那么多闭源黑盒。说白了,它更像一个传统的 Linux 摄像头驱动。
但轻不代表没坑。展讯的 HAL 层代码是开源的,你可以直接改。这既是好事也是坏事——好事是自由度大,坏事是容易改出问题。
我优化展讯平台时,主要做了三件事:
- 精简 sensor 初始化流程:展讯的 sensor 驱动默认会做很多校准操作。如果这些校准在工厂已经做过了,可以跳过,直接加载校准参数。
- 优化 buffer 分配策略:展讯默认用 ion 分配 buffer,但分配速度慢。我改成预分配 + 复用池的方式,启动时不再临时申请。
- 减少 log 输出:展讯的 HAL 层默认开了大量 debug log。每行 log 虽然只花几微秒,但几百行加起来就是几十毫秒。上线前记得关掉。
// 预分配 buffer 池
static buffer_pool_t g_preview_pool;
void init_buffer_pool() {
for (int i = 0; i < 4; i++) {
g_preview_pool.buffers[i] = ion_alloc(1920 * 1080 * 3 / 2);
}
}
三平台对比总结
说了这么多,我画了一张对比图,帮你快速理解三个平台的差异:
我的建议:如果你刚开始做相机优化,先从展讯入手。代码开源,容易调试。等摸清了相机 HAL 的整体流程,再去啃高通和 MTK 的定制化优化。别一上来就碰 MTK 的黑盒,容易劝退。
避坑指南
最后分享几个我踩过的坑:
- 不要盲目照搬优化方案:在高通上有效的优化,搬到 MTK 上可能反而变慢。每个平台的内部实现不同,优化策略要因地制宜。
- 注意平台版本差异:同样是高通平台,SM8250 和 SM8350 的 mm-camera 版本就不一样。我遇到过在 8250 上能用的优化,到了 8350 上直接 crash。
- 预留回退机制:我曾经在展讯平台上改 sensor 初始化流程,结果某批次的 sensor 不兼容,导致相机打不开。从那以后,我每次改底层都会加一个 feature flag,方便快速回退。
一句话总结:平台适配没有银弹。理解每个平台的架构特点,针对性地做优化,才是正道。