一、Camera HAL架构概览:Android Camera整体框架、HAL3 vs HAL1区别、Buffer管理流程

各位同学,咱们今天正式开讲。做Camera HAL优化,第一件事不是调参数,而是把架构吃透。我见过太多工程师一上来就改代码,结果改了半天发现是框架层的问题——说白了,方向错了。

这一节,我会带你从三个维度把地基打牢:Android Camera的整体框架长什么样?HAL3和HAL1到底差在哪?Buffer是怎么在管道里跑起来的?嗯,这些搞清楚了,后面讲延迟优化你才能听得懂。

1.1 Android Camera整体框架:从App到Sensor的完整链路

先看一张宏观图。Android Camera框架从上到下分四层:

  • 应用层:你的相机App,调用Camera2 API
  • 框架层:CameraService、CameraDeviceClient这些系统服务
  • HAL层:我们Camera HAL工程师的主战场
  • 内核层:V4L2、ISP驱动、Sensor驱动

数据流是怎么走的?我举个例子:你按下快门,App发一个capture请求,经过框架层封装成CaptureRequest,下发给HAL。HAL拿到请求后,配置Sensor、ISP,然后把填满数据的Buffer一路往回传。整个过程就像一条流水线——任何一个环节卡住,延迟就上去了。

关键点:整个链路中,HAL层是承上启下的枢纽。框架层不直接操作硬件,所有硬件细节对上层透明。这也是为什么HAL优化能带来最直接的性能提升——你改一个参数,整个管道都受益。

我个人习惯把Camera HAL比作「翻译官」。上层说「我要拍一张1080p、30fps、HDR开启的照片」,HAL得翻译成Sensor能听懂的寄存器配置。翻译得不好,延迟就高。我在项目中遇到过一种情况:框架层发了precapture请求,HAL没及时响应,结果预览画面卡了整整两帧——这就是翻译官没干好活。

1.2 HAL3 vs HAL1:新老架构的生死对决

说到HAL1和HAL3的区别,很多同学觉得「不就是API版本号不同吗?」——其实差远了。我刚开始做HAL时也是从HAL1入手的,后来切到HAL3,感觉就像从手动挡换到了自动挡,但操作复杂度反而更高了。

对比维度 HAL1 HAL3
架构模式 同步、阻塞式 异步、流水线式
请求模型 单一请求,一次一帧 多请求并发,Pipeline并行
Buffer管理 HAL内部管理,不透明 Gralloc + 框架统一管理
延迟表现 较高,约50-100ms 较低,可做到10-30ms
灵活性 低,功能固定 高,可自定义Request参数

为什么HAL3延迟更低?说白了,HAL1是「等」出来的——上一帧处理完才能处理下一帧。而HAL3是「流水线」——Sensor在曝光第N帧时,ISP已经在处理第N-1帧,同时HAL已经在准备第N+1帧的配置。你想想看,三件事同时干,延迟自然就降下来了。

我的建议:新项目直接上HAL3,别犹豫。HAL1虽然简单,但性能天花板太低。我见过一些老平台还在用HAL1,预览延迟死活降不到30ms以下——架构决定了上限,不是调参数能解决的。

不过HAL3也有坑。它的异步模型意味着你要处理更多的状态机、回调、超时。我曾经在一个项目里,因为process_capture_request返回太慢,导致框架层认为HAL卡死,直接重启了CameraService——嗯,那场面,你懂的。

1.3 Buffer管理流程:数据在管道里怎么跑?

Buffer管理是延迟优化的核心。你想想看,一帧画面从Sensor采集到显示在屏幕上,中间要经过多少次Buffer拷贝?每一次拷贝都是延迟的元凶。

在HAL3架构下,Buffer管理遵循以下流程:

  1. 框架层分配Buffer:通过Gralloc分配GraphicBuffer,传给HAL
  2. HAL填充Buffer:Sensor数据经过ISP处理后,写入Buffer
  3. Buffer返回框架:HAL通过process_capture_result回调,把填好的Buffer还给框架
  4. 框架送显/编码:Buffer被送到SurfaceFlinger显示,或者MediaCodec编码

这里有个关键点:Buffer是「借」的,不是「送」的。框架把Buffer借给HAL用,HAL用完必须还。如果HAL占着Buffer不还,框架那边就卡住了——这就是常见的「Buffer饥饿」问题。

避坑指南:我曾经在一个项目里,HAL的ISP处理速度跟不上Sensor输出速度,导致Buffer队列越积越长。最后框架层检测到Buffer超时未返回,直接丢帧。解决方法是调整Buffer池大小,或者降低Sensor帧率——但最根本的,还是优化ISP处理管线。

Buffer管理还有一个容易被忽略的点:内存格式转换。Sensor输出的是RAW图,但上层要的是YUV或JPEG。这个转换过程如果放在HAL里做,会占用大量CPU时间。我建议能交给硬件ISP做的,就别用CPU软转——延迟能差出10-20ms。

嗯,说到这,我想起一个经典案例。某款手机预览延迟偏高,排查后发现是HAL在每一帧都做了NV21到YV12的格式转换。其实上层根本不需要YV12,是HAL自己多此一举。去掉这个转换后,延迟直接降了15ms——有时候优化就是这么简单,但得先知道问题在哪。

小结

这一节我们讲了三个核心概念:

  • Camera整体框架是四层结构,HAL是中间枢纽
  • HAL3比HAL1延迟更低,但复杂度更高
  • Buffer管理要避免饥饿和多余拷贝

下一节,我们会深入HAL3的Pipeline模型,看看Request是怎么在流水线上跑起来的。到时候我会拿一个实际项目的代码片段来拆解——准备好了吗?