5、Camera HAL3 Vendor扩展:Vendor Tag定义、自定义Pipeline、扩展特性实现、兼容性注意事项

各位同学,今天我们来聊聊HAL3里一个特别有意思的话题——Vendor扩展。说白了,就是Google给各家厂商留的后门。你想想看,Android的Camera HAL3框架是通用的,但每家手机厂商的硬件都不一样,ISP的处理逻辑也千差万别。这时候就需要Vendor扩展来发挥各家特色了。

我个人习惯把Vendor扩展分成四个维度来看:Tag定义、Pipeline定制、特性实现、兼容性兜底。咱们一个一个来拆解。

5.1 Vendor Tag定义——给相机参数打上自家标签

Vendor Tag是什么?其实就是厂商自定义的metadata key。Google定义了一套标准的android.* tag,但很多时候不够用。比如你要加一个“夜景模式降噪强度”的参数,标准tag里可没有这个。

定义Vendor Tag需要三步:

  1. 声明Tag ID范围——Vendor Tag的ID必须从0x80000000开始,这是硬性规定。
  2. 注册Tag到Camera Metadata框架——通过vendor_tag_ops_t结构体注册。
  3. 在HAL中读写——跟普通tag一样用set/get接口。

来看一个实际例子:

// 定义Vendor Tag
#define VENDOR_CUSTOM_NR_STRENGTH  "com.example.vendor.nr_strength"

// 注册操作函数
vendor_tag_ops_t ops = {
    .get_tag_count = get_vendor_tag_count,
    .get_all_tags = get_all_vendor_tags,
    .get_section_name = get_vendor_section_name,
    .get_tag_name = get_vendor_tag_name,
    .get_tag_type = get_vendor_tag_type,
};

// 在HAL初始化时调用
camera_metadata_register_vendor_tags(&ops);
我的经验:Tag的命名空间一定要用公司域名倒序,比如com.xxx.xxx。我曾经见过有人随便写了个"my_tag",结果跟别的厂商冲突了,调试了整整两天才发现问题。

5.2 自定义Pipeline——打破Google的默认流程

Google的默认Pipeline是通用的,但很多时候不够灵活。比如你要做多帧合成、HDR、或者特殊的降噪算法,就需要自己定制Pipeline。

自定义Pipeline的核心在于重写process_capture_requestprocess_capture_result这两个函数。你可以在这里插入自己的处理逻辑,比如:

  • 多帧对齐与合成
  • 自定义的3A算法
  • 特殊的后处理流程

下面这张图展示了典型的自定义Pipeline流程:

自定义Pipeline流程图 App发送Capture Request HAL接收Request 自定义Pipeline处理 多帧合成 / 自定义降噪 / HDR融合 返回Capture Result ← 这里是厂商发挥空间

嗯,这里要注意:自定义Pipeline虽然灵活,但千万别破坏Google的契约。比如你处理完数据后,必须保证timestamp、sensor_timestamp这些字段是合法的,否则上层会直接报错。

5.3 扩展特性实现——让相机拥有独家卖点

扩展特性是厂商差异化竞争的关键。常见的扩展特性包括:

特性 实现方式 注意事项
超级夜景 多帧长曝光+对齐合成 注意帧率控制和内存占用
AI美颜 在YUV域插入NPU处理 延迟不能超过33ms
视频防抖(EIS) 修改crop region + 陀螺仪数据 需要同步sensor和gyro时间戳
高像素模式 Binning/Remosaic切换 注意带宽和功耗

实现扩展特性时,我建议遵循这个原则:能用Vendor Tag解决的,就别动Pipeline。因为改Pipeline风险太大,一旦出问题,整个相机可能都打不开。

核心思路:扩展特性 = Vendor Tag控制开关 + 自定义处理逻辑 + 标准接口返回结果。这样既保留了兼容性,又实现了差异化。

5.4 兼容性注意事项——别让你的代码变成定时炸弹

这部分我要重点讲,因为踩坑的人太多了。兼容性问题主要来自三个方面:

  • CTS/CTS Verifier测试——Google的兼容性测试套件,你的Vendor扩展不能破坏任何CTS用例。
  • 不同Android版本——Android 12和Android 13的HAL3接口有细微变化,比如camera_metadata_entry_t的count字段在13里变成了size_t。
  • 不同芯片平台——高通、MTK、展锐的HAL实现各有差异,你的Vendor扩展要能适配。

我曾经在一个项目里,为了追求夜景效果,在Pipeline里插入了自定义的帧对齐算法。结果CTS测试时,某个用例要求连续100帧的timestamp严格递增,我的算法因为丢了几帧导致timestamp跳变,直接挂了。后来花了整整一周才定位到问题。

避坑指南:
  1. 所有Vendor Tag必须注册,不能遗漏。
  2. 自定义Pipeline不能改变标准metadata的语义。
  3. 扩展特性必须提供fallback路径,比如硬件不支持时自动降级。
  4. 多平台测试,别只在你的开发板上跑。

最后说一句,Vendor扩展是一把双刃剑。用好了,你的相机可以秒杀竞品;用不好,就是给自己挖坑。我的建议是:能不扩展就不扩展,非要扩展就做好兼容性测试。毕竟,用户可不想看到相机闪退的弹窗。

小技巧:在实现Vendor扩展时,可以加一个debug开关。通过系统属性控制,比如persist.vendor.camera.debug_ext=1。这样线上出问题时,可以快速定位是扩展逻辑的问题还是基础框架的问题。

公众号:蓝海资料掘金营,微信deep3321