Android camera2 框架学习记录

本文详细介绍了Android相机框架的层级结构,包括App、Service、Provider、Driver和Hardware,重点分析了从App到硬件的图像处理流程。在App层,解释了相机应用如何初始化、创建预览会话、拍照请求等步骤;在Service层,讨论了Camera Service通过AIDL与Framework交互,以及处理请求的机制。硬件部分,详细探讨了镜头、感光器、ISP的工作原理。文章指出,尽管手机相机受限于体积和功耗,但通过ISP和不断优化的算法,其成像质量已接近专业相机。
摘要由CSDN通过智能技术生成

安卓相机架构概览

Android系统利用分层思想,将各层的接口定义与实现分离开来,以接口作为各层的脉络连接整体框架,将具体实现的主导权交由各自有具体实现需求的平台厂商或者Android 开发者,这样既做到把控全局,也给予了众多开发者足够大的创作空间,这体现出了一个优秀的开源系统应有的胸怀和远见。其中,谷歌根据职能的不同将Camera框架一共划分成了五层,分别是App、Service、Provider、Driver以及Hardware,下面的Camera的整体架构图很清晰地显示出了其五层架构以及相互的关联接口。

Camera App

应用层处于整个框架的顶端,承担着于用户直接进行交互的责任,承接来自用户直接或者间接的比如预览/拍照/录像等一系列具体需求,一旦接收到用户相关UI操作,便会通过Camera Api v2标准接口将需求发送至Camera Framework部分,并且等待Camera Framework回传处理结果,其中包括了图像数据以及整体相机系统状态参数,之后将结果以一定方式反馈给用户,达到记录显示种种美好瞬间的目的。

Camera Framework

该层主要位于Camera App与Camera Service之间,以jar包的形式运行在App进程中,它封装了Camera Api v2接口的实现细节,暴露接口给App进行调用,进而接收来自App的请求,同时维护着请求在内部流转的业务逻辑,最终通过调用Camera AIDL跨进程接口将请求发送至Camera Service中进行处理,紧接着,等待Camera Service结果的回传,进而将最终结果发送至App。

Camera Service

该层位于Camera Framework与Camera Provider之间,作为一个独立进程存在于Android系统中,在系统启动初期会运行起来,它封装了Camera AIDL跨进程接口,提供给Framework进行调用,进而接收来自Framework的图像请求,同时内部维护着关于请求在该层的处理逻辑,最终通过调用Camera HIDL跨进程接口将请求再次下发到Camera Provider中,并且等待结果的回传,进而将结果上传至Framework中。

Camera Provider

该层位于Camera Service与Camera Driver之间,作为一个独立的进程存在于Android系统中,同时在系统启动初期被运行,提供Camera HIDL跨进程接口供Camera Service进行调用,封装了该接口的实现细节,接收来自Service的图像请求,并且内部加载了Camera HAL Module,该Module由OEM/ODM实现,遵循谷歌制定的标准Camera HAL3接口,进而通过该接口控制Camera HAL部分,最后等待Camera HAL的结果回传,紧接着Provider通过Camera HIDL接口将结果发送至Camera Service。

CamX-CHI(Camera HAL)

该部分是高通对谷歌Camera HAL3接口的实现,以so库的形式被加载至Camera Provider中,之前采用的是QCamera & MM-Camera架构,但是为了更好灵活性和可扩展性,而今高通又提出了CamX-CHI架构,该架构提供HAL3接口给Provider进行调用,接收来自Provider的请求,而内部对HAL3接口进行了实现,并且通过V4L2标准框架控制着相机驱动层,将请求下发至驱动部分,并且等待结果回传,进而上报给Camera Provider。

CamX-CHI架构由CamX和CHI两个部分组成,CamX负责一些基础服务代码的实现,不经常改动,CHI负责实现一些可扩展性和定制化的需求,方便OEM/ODM添加自己的扩展功能。CamX主要包括实现HAL3入口的hal模块,实现与V4L2驱动交互的csl模块,实现硬件node的hwl和实现软件node的swl。CHI通过抽象出Usecase、Feature、Session、Pipeline、Node的概念,使厂商可以通过实现Node接口来接入自己的算法,并通过XML文件灵活配置Usecase、Pipeline、Node的结构关系。

Camera Driver

Linux为视频采集设备制定了标准的V4L2接口,并在内核中实现了其基础框架V4L2 Core。用户空间进程可以通过V4L2接口调用相关设备功能,而不用考虑其实现细节。V4L2提出了总设备和子设备的概念,并通过media controller机制向用户空间暴露自己的硬件拓扑结构。视频采集设备驱动厂商按照V4L2 Core的要求开发自己的驱动程序,只需要实现相应的结构体和函数接口并调用注册函数注册自己就行。

在高通平台上,高通对相机驱动部分进行了实现,利用了V4L2框架的可扩展特性,设计出了一套独特的KMD框架。在该框架内部主要包含了三个部分,CRM、Camera Sync以及一系列子设备,首先,作为框架顶层管理者,CRM创建了一个V4L2主设备用来管理所有的子设备,并且暴露设备节点video0给用户空间,同时内部维护着整个底层驱动业务逻辑。其次,Camera Sync创建了一个V4L2主设备,同时暴露了设备节点video1给用户空间,主要用于向用户空间反馈图像数据处理状态。最后,子设备模块被抽象成v4l2_subdev设备,同样也暴露设备节点v4l2-subdev给用户空间进行更精细化的控制。另外,在整个框架初始化的过程中,通过media controller机制,保持了在用户空间进行枚举底层硬件设备的能力。

Camera Hardware

相机硬件处在整个相机体系的最底层,是相机系统的物理实现部分,该部分包括镜头、感光器、ISP三个最重要的模块,还有对焦马达、闪光灯、滤光片、光圈等辅助模块。镜头的作用是汇聚光线,利用光的折射性把射入的光线汇聚到感光器上。感光器的作用是负责光电转换,通过内部感光元件将接收到的光信号转换为电子信号进而通过数电转换模块转为数字信号,并最后传给ISP。ISP负责对数字图像进行一些算法处理,如白平衡、降噪、去马赛克等。

通过上面的介绍,我们可以发现,谷歌通过以上五级分层,形成了整个相机框架体系,其中层与层之间通过行业协会、开源社区或者谷歌制订的标准接口进行连接,上层通过调用标准接口下发请求到下层,下层负责对标准接口进行实现,最终将请求再次封装并调用下一层级的对外接口下发到下层。所以总得来说,谷歌使用标准接口作为骨架搭建整体框架,而其具体实现交由各层自己负责,从整体上来看,职责划分明确,界限分明,这样的设计,一来利用标准接口,保持了整个框架业务正常流转,二来极大地降低了各层耦合度,保持了各层的相互独立,最终让整个框架处于一个稳定同时高效的运行状态。

重点关注camera框架的后三层,即provider、driver、hardware,前两层大致了解流程框架。

一、App:

一个简单的相机应用流程如下:

a) 初始化

随着应用的打开,首先在MainActivity的onResume方法中去初始化用于拍照的按钮和接收数据的ImageReader,并且设置其各自回调方法。

b) 获取CameraManager/打开Camera 设备

其次在TextureView.SurfaceTextureListener中的回调方法onSurfaceTextureAvailable会被调用,在该方法中会去获取CameraManager服务,并打调用其openCamera方法打开后主摄相机设备,并通过回调接口获取该设备,紧接着调用startPreview方法。

c) 创建Camera Capture Session/下发预览需求

在startPreview方法中会去下发预览需求,主要工作有设置TextureView缓冲区大小,创建用于接收预览数据的Surface,并调用CameraDevice的createCaptureSession方法创建CameraCaptureSession,在其回调接口onConfigured方法中,去创建CaptureRequest,并调用CameraCaptureSession的setRepeatingRequest方法下发Request到相机框架中。

d) 返回预览Metadata/图像数据

在完成了预览需求的Request的下发工作后,相机框架便会不断通过传入的CaptureCallback中的onCaptureComplete方法上传Meta Data以及通过BufferQueue框架上传图像数据进行预览显示。

e) 下发拍照需求

当点击应用界面的拍照按钮的时候,会触发按钮的View.OnClickListener监听类中的onClick方法,在该方法中,初始化了一个用于拍照的CaptureRequest,并且通过调用CameraCaptureSession的capture方法下发拍照需求.

f) 返回拍照Metadata/图像数据

一旦拍照图像数据生成,便会通过回调接口CaptureCallback中的onCaptureComplete方法上传Meta Data以及通过BufferQueue框架上传图像数据到ImageReader中,触发其onImageAvailable方法,在该方法中通过ImageReader的acquireNextImage获取到拍照图像数据,并通过doByte2JpegFile将其转存外JPEG格式的图片保存在设备中。

Camera App作为整个框架体系的最上层,直接面向的主体是普通用户,其关键性不言而喻,一点点的卡顿或者停滞都会降低用户体验,所以为了保证整个框架的稳定性以及高效性,谷歌重新设计了Camera 接口Api v2,由于该接口将控制逻辑高度抽象成了一个控制视图,因此可以逐帧控制硬件参数,进而实现一系列强大的功能,比如可以直接在预览过程中,手动控制曝光、感光度、对焦以及白平衡的参数,动态地输出不同效果的图像,又比如可以利用该接口与HDR算法相配合,实现高动态成像效果。而其中,对于Api v2接口的实现是在Camera Framework中完成的,由上面分析可以看出,其内部并没有采用十分复杂的控制逻辑,整套代码流程清晰明朗,而这样的设计,进一步保证了该层的稳定性以及高效性,为整个相机框架体系的稳定奠定了坚实的基础。

谷歌提出Camera Api v2接口的同时,将其具体实现放入了Camera Framework中来完成,Framework内部负责解析来自App的请求,并且通过AIDL跨进程接口下发到Camera Service中进行处理,并且等待结果的回传。

二、Service:

Camera Service被设计成一个独立进程,作为一个服务端,处理来自Camera Framework 客户端的跨进程请求,并在内部进行一定的操作,随后作为客户端将请求再一次发送至作为服务端的Camera Provider,整个流程涉及到了两个跨进程操作,前者通过AIDL机制实现,后者通过HIDL机制实现,由于在于Camera Provider通信的过程中,Service是作为客户端存在的,所以此处我们重点关注AIDL以及Camera Service 主程序的实现。

Camera AIDL 接口:

在Android系统中,两个进程通常无法相互访问对方的内存,为了解决该问题,谷歌提出了Messager/广播以及后来的Binder,来解决这个问题,但是如果某个进程需要对另一个进程中进行多线程的并发访问,Messager和广播效果往往不是很好,所以Binder会作为主要实现方式,但是Binder的接口使用起来比较复杂,对开发者特别是初学者并不是很友好,所以为了降低跨进程开发门槛,谷歌开创性地提出了AIDL(自定义语言)机制,主动封装了Binder的实现细节,提供给开发者较为简单的使用接口,极大地提升了广大开发者的开发效率。

按照谷歌的针对AIDL机制的要求,需要服务端创建一系列*.aidl文件,并在其中定义需要提供给客户端的公共接口,并且予以实现,接下来我们来看下几个主要的aidl文件。

ICameraService.aidl定义了ICameraService 接口,实现主要通过CameraService类来实现,主要接口如下:
getNumberOfCameras: 获取系统中支持的Camera 个数
connectDevice():打开一个Camera 设备
addListener(): 添加针对Camera 设备以及闪光灯的监听对象

ICameraDeviceCallbacks.aidl文件中定义了ICameraDeviceCallbacks接口,其实现主要由Framework中的CameraDeviceCallbacks类进行实现,主要接口如下:
onResultReceived: 一旦Service收到结果数据,便会调用该接口发送至Framework
onCaptureStarted(): 一旦开始进行图像的采集,便调用该接口将部分信息以及时间戳上传至Framework
onDeviceError(): 一旦发生了错误,通过调用该接口通知Framework

ICameraDeviceUser.aidl定义了ICameraDeviceUser接口,由CameraDeviceClient最终实现,主要接口如下:

disconnect: 关闭Camera 设备
submitRequestList:发送request
beginConfigure: 开始配置Camera 设备,需要在所有关于数据流的操作之前
endConfigure: 结束关于Camera 设备的配置,该接口需要在所有Request下发之前被调用
createDefaultRequest: 创建一个具有默认配置的Request
ICameraServiceListener.aidl定义了ICameraServiceListener接口,由Framework中的CameraManagerGlobal类实现,主要接口如下:
onStatusChanged: 用于告知当前Camera 设备的状态的变更

Camera Service 主程序:

Camera Service 主程序,是随着系统启动而运行,主要目的是向外暴露AIDL接口给Framework进行调用&

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值