引言
应用框架要通过拍照预览摄像获得照片或者视频,就需要向相机子系统发出请求,
一个请求对应一组结果
一次可发起多个请求,并且提交请求是非阻塞的,始终按照接收的顺序以队列的形式先进先出地进行顺序处理
一个请求包含了拍摄和拍照配置的所有信息,以及处理这些的结果,
(一般包括:分辨率,像素格式,手动传感器、镜头,闪光灯控件,3A操作模式,RAW到YUV处理控制,统计信息的生成等等,这就是说可以对输出结果和处理有很多的控制。这就是Camera2对比Camera1的一个最主要的变化)
相机请求模型:
相机pipeline
相机子系统中,包括pipeline中组件的实现。如:3A算法和处理控件。
相机HAL提供接口,用户可以实现自己的版本的这些组件接口。比如高通或者MTK等各自根据标准HAL接口来实现自己的组件接口。这样的标准接口既保证了多个设备制造商和ISP之间的跨平台兼容性,又能保证各自实现的独特性。
相机pipeline是虚拟的,整个相机数据的处理流程跟管道是一样的。完全可以管道的概念来映射硬件。以这种pipeline的抽象的组件方式,来支持多种不同的算法和运算顺序,不会影响质量,效率和跨设备的兼容性。
相机pipeline也支持通知或者事件触发:app框架可以启动的一些如自动对焦的功能,它还将通知发送回应用程序框架,向应用程序通知自动对焦锁定或错误等事件。
上述的相机pipeline的图种,既包括了实际的硬件设备处理,又包括了软件处理:
CameraSensor,ISP,统计信息,3A算法,Bayer处理,Jpeg处理,YUV处理
ISP又包含有:热像素校准,去马赛克,降噪,阴影校准,几何校准,色差校准,边缘增强,色调曲线调整,
值得注意的,一些图像处理块,如在图中显示的,并没有明确定义的,相机pipeline做出如下的假设。:
1)RAW Bayer输出在ISP内部不经过任何处理
2)统计信息根据原始传感器数据生成
3)原始数据转换成YUV的各种处理块可以按照任意顺序排列
4)当显示多个刻度和裁剪单元时,所有缩放单元共享区域控件(数字缩放)。不过每个单元都可能具有不同的输出分辨率和像素格式。
HAL的操作摘要
来自FW的拍照或者录像的异步requests
HAL设备必须按照顺序处理requests 。每个requests 均生成输出结果的metadata以及一个或多个output image buffers
requests and results以及后续的流请求都遵守先进先出规则(队列的规则)。
指定请求的所有输出的时间戳必须完全相同,以便框架可以根据需要将它们匹配在一起。
所有拍照或者录像的配置和状态(不包括 3A 例程)都包含在请求和结果中。
相机HAL 概述 :
相机的启动与预期操作顺序
AndroidCamera API的使用流程
- 监听和枚举相机设备。
- 打开设备并连接监听器。
- 配置目标使用情形的输出(如静态拍照、录制等)。
- 为目标使用情形创建请求。
- 捕获/重复请求和连拍。
- 接收结果metadata 和 image data。
- 切换 usecases(使用情形)时,返回到第 3 步
相机操作流程
HIDL接口定义位于:
hardware/interfaces/camera
1)枚举、打开相机设备并创建有效会话:
- a. 在初始化之后,框架开始监听任何一个现有的CameraProvider(ICameraProvider接口的实现)如果存在一个或者多个CameraProvider,FW就会尝试建立connection
b. FW枚举相机设备是通过:ICameraProvider::getCameraIdList()
c. FW实例化一个新的ICameraDevice 相应的调用:
ICameraProvider::getCameraDeviceInterface_VX_X()
d. FW通过调用ICameraDevice::open() 来创建一个新的激活的 capture session(ICameraDeviceSession)
2)使用有效相机会话:
a. FW调用HAL设备的输入/输出流列表来调用: ICameraDeviceSession::configureStreams()
b. 只要ICameraDeviceSession被ICameraDevice::open() 创建好之后,在任何时候,FW在一些usecase中,都可以调用默认设置的请求:ICameraDeviceSession::constructDefaultRequestSettings();
c. 框架通过调用基于某一组默认设置的设置,以及框架之前注册的至少一个输出流来构造第一个capture request,并将其发送到HAL。此请求是通过ICameraDeviceSession::processCaptureRequest() 发送到HAL。HAL必须阻塞这次调用的返回,直到准备好发送下一个请求为止。
d. 框架继续提交请求,并根据需要调用ICameraDeviceSession::constructDefaultRequestSettings()以获取其他用例的默认设置缓冲区。
e. 当请求捕获开始(传感器开始曝光以进行捕获)时,HAL 用SHUTTER 消息 来调用ICameraDeviceCallback::notify() 包括:帧号和开始曝光的时间戳。此通知回调不必在给第一个请求调用processCaptureResult()之前发生。但直到针对相应的捕获调用 notify() 之后,才会向应用提供有关该捕获的结果。
f. 经过一定的流水线延迟后,HAL 开始使用 ICameraDeviceCallback::processCaptureResult() 将完成的捕获返回到框架。这些捕获按照与提交请求相同的顺序返回。一次可发起多个请求,具体取决于相机 HAL 设备的管道深度。
3)在打开了相机之后会出现以下的某种情况:
a. 完成拍照或者摄像后,重新设置,重新下发请求,则会重新进行配流重新获取数据。
重新配流就是调用:ICameraDeviceSession::configureStreams()
b. 关闭相机
关闭相机会调用:ICameraDeviceSession::close()
c. 相机出现错误或者异常。
返回 错误或事件 消息:ICamaeraDeviceCallback::notify()