Android Camera HAL3 - 开篇词

好久没有写技术文章了,写这类东西需要耗费的精力太多,但是最近工作中频繁会接触到 Camera 的知识,不总结下看来也是对不起我新买的笔记本,这篇就算是稀里糊涂的开篇文章吧。技术类的文章产出总归是要非常慢的,之前写的 OpenMax 和 V4L2 每一篇都耗费了极长的时间,写的过程中会很苦恼,怎么组织自己的语言都感觉没法很好的表达自己的想法,让人忍不住时不时想口吐芬芳。

Camera 基础模块

Camera 涉及到视频采集端的一系列模块,其中 RAW图像采集、ISP、Scale 模块是必须要有的,只有它们全部组合起来才能够完成完整的最基础的视频采集工作。在此基础上会有其它的扩展项:

  • 畸变校正。其实畸变校正现在也算是个必须有的功能了,至少我见到的需要视频采集的设备基本上都是有畸变校正功能的。
  • 电子防抖。这个我个人觉得相较于畸变校正算是个更高级一点的功能,它的技术难度在开发过程中让我觉得比畸变校正更高,你可能觉得畸变校正难度更高点,但是我不要你觉得,我要我觉得,都听我的,一个人说了算。
  • Jpeg 编码。这个按道理来讲很多产品终端都集成在了编解码模块中,但是在手机上面,你像骁龙8XX系列它是放在 Camera 这个模组里面的,因为现在拍照算是个极其重要且普遍的功能了,干脆直接出 Jpeg,现在除了 Jpeg 也扩展出其它风格了,像苹果的 HEIC 格式等。
  • 人脸检测。人脸检测在手机上面是一个自带的相机功能,有的是用第三方的算法库实现的,有的是有专门的独立于 Camera 之外硬件模块实现,有的呢就是直接集成在 Camera 这个大的模块组里面了。
  • 图像视觉。这个目前还比较少见直接集成在 Camera 模块组里面,大都是单独列出来一个硬件模块或者使用软件的第三方算法实现。

在手机上面,ISP 的功能也是日益完善且不断扩展出新的处理模式,比如在降噪、变焦、超分辨率上面也做了很多的探索与扩展,另外单纯的 ISP 效果也在不断的增强,更大的分辨率,更加接近单反的调色等等。

总之在手机领域,Camera 模块已经不再是以前那个单纯的 Camera 了,它已经超越了视频采集,在妄想一统便携式单反、望远镜、显微镜、整容师的路上渐行渐远了。

非安卓系统的 Camera

之前做的是非安卓系统里面的视频采集,除了内核里面的驱动端框架是基于 V4L2 的之外,用户空间的全部都是自研的致敬式架构,根据我的观察,它的结构与安卓 Camera HAL1 的用法还是比较类似的。基本上的结构就是:

  1. 内核
  2. 用户空间的中间件(类似于安卓 Camera HAL1)
  3. APP,或者中间再加一个业务逻辑框架层

其中我接触比较多的就是内核以及中间件这部分,内核就不必说了,大量依附于 V4L2 为基础进行相关的逻辑构建,涉及的比较多的就是纯 V4L2 的概念,毕竟内核已经帮你想好一整套的解决方案了,在大多数时候这些都是可以满足需求的,只需要按照内核的规定去实现它就好。

用户空间的中间件实现方式比较自由,因为不像内核那样是个非常标准的框架,世界上所有的 Linux 系统都在用。说到这里,我想起来一个想法,就是内核的 V4L2 框架设计脉络十分的清晰,看代码实现也觉得这样实现出来好像也是不复杂的,并且基于此实现具体的业务逻辑看起来也很简单,就会有一种错觉,觉得这个框架让我自己搞一个看起来也不是不可能啊。后来工作中尝试设计一个很小的模块,发现你要把它搞得如此通用,并且让别人理解起来逻辑又是如此的清晰,从 0 到 1 这个过程是极其困难的,你想象不到的那种困难。

之前接触的都是基于组件化进行开发的中间件,这个跟 gstreamer 的以 pipeline 为单位的使用方式是不一样的,gstreamer 在使用上常常是基于 pipeline 为单位进行构建数据流逻辑的,而我之前做的是基于一个个组件进行数据流逻辑建立的。其实基于组件在一定程度上来讲,它的自由度会更加高,类似沙盒游戏一般,但是 pipeline 为单位的会使得上层的集成开发更加简单高效,并且由于 element 的高度统一化抽象,使得内部的扩展更加容易实现,也就是更容易新增模块,并且保持代码的简洁性,完全基于组件的实现,扩展起来就会比较麻烦,需要从下至上一整套的代码适配,工作量会比较大,重复代码也会比较多,但是它设计起来是相对比较简单的。

非安卓系统的 Camera 从另外一个角度来讲,它的业务逻辑也没有那么地复杂,因为用不着安卓系统说明本身这个产品的复杂度与性能不是那么的高,不像手机一样,完全就是瑞士军刀的路子,非安卓系统的通常都是细分领域的产品,功能相对来说比较单一,通常只会关注两到三个主要功能进行开发研制。手机的主要功能那就多了去了,就算是只说相机这一个,手机对相机的要求,目前来看也要远比其它的设备来得复杂。

安卓系统的 Camera

安卓系统的 Camera 从两个角度说下,主要是以手机为例,就不说平板什么的,因为平板体积的限制,Camera 的发展远远抵不上手机,因为不太会有人拿着一个平板到处拍照。

  1. 硬件复杂度更高。因为手机的 Camera 要做到超高分辨率,叠加各种 ISP 效果,要有超广角畸变校正,要有以假乱真的光学变焦(空间连续变换),要有人像模式,要有人脸识别,要有高帧率高分辨率的防抖(或光学或电子),要有各种滤镜效果,要有物体追踪(现在感觉不常见,但是之后会是基础功能,安卓早就已经内置标准命令了)。。。总之,复杂的一批。
  2. 软件设计自由度更高。硬件的复杂带来一个副作用,不可避免的,软件设计也会复杂很多,但是由于处理器的性能足够,软件代码框架的设计上会更加自由,不必像中低端芯片那样要在软件设计上一再让步。这也给了架构师与底层小虾米更多的实现自由,不必太过于考虑性能问题而无法实现一些高扩展性、功能更加强大的架构。

安卓系统的 framework 以及 APP 端已经有人帮你制定好一整套的开发实现方案了,包括命令怎么去发送,怎么使用,数据流应该怎么获取,怎么保存文件等等,都已经有相关的指导文档,并且十分详细,为了保持兼容性你也不太可能说有太大的自由发挥空间,但是 HAL 层的话就针对于 HAL3 来讲,还是有比较大的设计自由的。

因为 HAL3 采用了一种类似于总线式的设计结构,从上层下发下来的命令参数以及 Buffer 等全部都被放置在同一个结构体里面了,其中最重要的就是 Metadata 与 Buffer、Stream。这样一个总线式的结构,我觉得给了 HAL 内部的软件架构更加自由的实现机会。

HAL3 的主要改变

HAL1 其实我没有太关注过,但是大概有了解过它是怎么去使用的。HAL1 的话是分散型的控制,参数都有专门的函数调用去完成传递,比如像设置 ISP 的某一个参数,比如想拍照、录像,都是有专门的函数调用来实现,它们是分开来的。而 HAL3 则是把那些控制全部都给放到同一个函数调用流程里面完成了。

第二个主要的区别的就是 HAL1 从 framework 到 HAL 是直通式调用的,而 HAL3 的 framework 代码和 HAL 之间是通过 AIDL 接口实现 Binder 远程调用的。完成该方式转换的项目叫做 Treble 项目,该项目旨在完成 framework 到 HAL 之间的解耦,以便尽量产生固定化的 framework 代码,对于需要经常更新的 HAL 层代码可以实现动态的更新而不需要动 framework 的代码(无需改动也无需重新编译),一个是方便代码级别的更新,另一个就是方便在线升级,可以只更新 vendor 的东西而不用动到其它地方。

HAL3 的主要流程被拆分为:

  1. 获取现在设备上面可用的相机设备,包括相机每一个相机的属性功能,get_number_of_camera。
  2. 获取想要打开的相机的 information,在调用中被定为 get_camera_info 函数。
  3. 打开一个设备,保存打开设备时获取的 camera_module_t 结构体,该结构体就是一个抽象的 camera module 的连接通道。
  4. 通过新建一个 camera device,来获取一个 camera3_device_t,结构体,该结构体主要用于获取 notify 和 torch 的状态。然后新建一个 session,session 就是后续需要与内部的 camera 硬件设备进行控制交互的抽象媒介。
  5. 通过 session 来配置一个 stream,configure_streams 函数可以完成此项工作。
  6. 向 HAL 内部发送控制命令,可以理解为融合了 HAL1 的各种控制参数,把它们作为一个总线形式的命令分发下去。相关的函数调用就是 process_capture_request。
  7. 内部 HAL 处理完毕之后会返回 notify 事件,一般就是帧的时间戳。并且通过 process_capture_result 来返回给 framework 相关的结果数据,包括控制参数的内容返回,包括 buffer 的返回等。
  8. 重复 6-7,直到用户想退出,此时就调用 flush 来进行整个工作队列的清洗操作。
  9. 关闭整个的 camera 设备,相关函数是 close。

可以看到,HAL3 其实更像是类似 V4L2 的总线式命令设计了,并且整个的过程也和 V4L2 的 ioctl 流程比较相似,就我个人的理解来看,它们的设计有点属于同一宗派,同门师兄弟的感觉。HAL3 主要是给予了 framework 对于 camera 硬件更加强悍和细节的控制权,简直可以达到那样的微操境界,使得更加多样化的 camera 应用变得可能。

End

这个算是开篇词了,但是总归技术类的文章写出来的速度是比较慢的,我也是为了工作才切到这上面,用作定时回顾之用,更新速度估计就没有那么的快,应该中间会穿插些杂七杂八的 C++ 学习文章,慢慢来吧。小欢喜这部剧还是挺推荐看看的,虽说它里面的家庭相对中国这千千万万的家庭来说,还真就不是普通家庭了,但是里面还是有不少可以值得学习的地方的,尤其是沟通和对孩子的教育上面,咱也是孩子来的,有些地方还是蛮有感触的。


想做的事情就去做吧
发布了128 篇原创文章 · 获赞 263 · 访问量 27万+

猜你喜欢

转载自blog.csdn.net/u013904227/article/details/100184440
今日推荐