Android Camera System
Android Camera硬件抽象层(HAL,Hardware Abstraction Layer)主要用于把底层camera drive与硬件和位于android.hardware中的framework APIs连接起来。Camera子系统主要包含了camera pipeline components 的各种实现,而camera HAL提供了这些组件的使用接口。
注:camera HAL起着承上启下的作用。在camera HAL层实现中,芯片厂商一般将camera HAL层的实现分为两层:interface层和OEM层。OEM层为下层,它用于屏蔽不同的camera硬件。不同的camera硬件必须支持OEM层提供的对外接口。Interface层为上层,它调用OEM层的对外接口来实现camera HAL所定义的接口。对于Interface层,它并不知道底层camera硬件到底是哪一个版本。同时,interface层完成了屏蔽camera HAL版本的作用。对于OEM层,它也不知道上层是哪一个camera HAL版本,及android版本。两层分离架构,可以很容易地实现不同芯片支持同一个android版本和同一款芯片支持不同android版本(前提条件是该款芯片能够支持这些android版本的各个需求)。
-
Camera System Architecture
下图所示为Android官方给出的Camera System架构。
图 1 Android Camera System Architecture
从图 1中可以看出,Camera System主要包含如下几个重要组成部分:
-
Application Framework
Application framework层主要是应用代码(app's code),这个代码主要利用android.hardware.Camera API与Camera硬件进行交互。这些代码调用相关的JNI类来访问与Camera进行交互的原生代码(native code)。
-
JNI
与android.hardware.Camera有关的JNI代码主要frameworks/base/core/jni/ android_hardware_Camera.cpp。这些代码调用下一层的原生代码以获得物理camera的访问权,然后返回用于在framework层创建android.hardware.Camera对象的数据。
-
Native framework
Native framework的定义位于 frameworks/av/camera/Camera.cpp中,它提供了android.hardware.Camera类在本地的实现。这些类调用IPC binder来获得camera service。
-
Binder IPC proxies
IPC binder代理可以现实进程间通信。在frameworks/av/camera目录下有三个camera binder类的定义。ICameraService是cameraservice的接口,ICamera是被打开的camera设备的接口,ICameraClient是camera设备返回给application framework层的接口。
-
Camera Service
Camera service位于frameworks/av/services/camera/libcameraservice/CameraService.cpp,它是与HAL直接进行交互的真正代码。
-
HAL
硬件抽象层定义了一套标准接口,你必须实现这些接口,以保证你的APP能够与你的Camera硬件正确的协调工作,从而使保证你的Camera的所有功能能够正常进行工作。以下是google原文:
The hardware abstraction layer defines the standard interface that the camera service calls into and that you must implement to have your camera hardware function correctly.
-
Kernel Driver
Camera驱动向下与真实的camera硬件进行交互,向上与HAL实现进行交互。Camera硬件和驱动必须能够提供YV12和NV21格式的图像数据,以支持camera图像数据在显示屏上的预览和视频录制。
注:YV12是YUV420P,三个plane,即Y,V,U三个plane依次存储,如:YYYYYYYY VV UU;NV21是YUV420SP,两plane,即Y,VU作为两个plane存储,且VU交织,即一个V,一个U,依次存储,如:YYYYYYYY VUVU。
-
HAL的实现
-
Implementation of HAL
HAL层位于camera驱动和上层Android framework层之间,它定义了一些标准接口,你必须正确地实现这些接口,以保证你的APP能够正确的操作你的camera硬件进行正常工作。HAL接口定义位于hardware/libhardware/include/hardware/camera.h 和hardware/libhardware/include/hardware/camera_common.h头文件中。
camera_common.h文件定义了一个重要的struct——camera_module。camera_module定义了一套标准结构以获取与camera相关的基本信息,比如ID和一些camera的基本属性等,如是否为前置或后置camera等。
Camera.h则包含了与android.hardware.Camera相关的代码。该头文件声明了camera_device结构体,camera_device结构体包含一个camera_device_ops结构体,camera_device_ops结构体包含了指向HAL接口实现函数的函数指针。开发者可以查看frameworks/av/include/camera/CameraParameters.h 文件以了解更多不同类型的camera参数的相关文档。这些参数都通过HAL中的 int (*set_parameters)(struct camera_device *, const char *parms) 函数指针进行设置。
关于HAL实现的一个例子,可以查看Galaxy Nexus HAL的实现,它位于hardware/ti/omap4xxx/camera。
-
Configuring the Shared Library
你必须设置Android的build system以保证将自己的HAL实现打包进一个共享库(shared library),然后通过创建一个android.mk文件来将其复制到一个合适的目录中,这主要包含如下几个步骤:
-
创建一个包含你的library源代码的目录:device/<company_name>/<device_name>/camera。
-
创建一个Android.mk文件来build你的library。确保该Makefild文件包含如下几行:
LOCAL_MODULE := camera.<device_name>
LOCAL_MODULE_RELATIVE_PATH := hw
注意,你的library必须按如下格式进行命名:camera.<device_camera>(.so会自动添加)。这样Android才可以正确的加载你的library。可以查看Galaxy Nexus camera的例子了解具体情况,例子位于hardware/ti/omap4xxx/Android.mk。
-
通过从目录frameworks/native/data/etc下拷贝必要功能XML文件,在你的设备的Makefile文件中明确指出你的设备有哪些功能。例如,明确指出你的设备有闪光灯,而且能自动聚焦,那就需要在你的设备所对应的<device>/<company_name>/<device_name> /device.mk Makefile文件中增加下面几行:
PRODUCT_COPY_FILES := ...
PRODUCT_COPY_FILES +=
frameworks/native/data/etc/android.hardware.camera.flash-autofocus.xml:system/etc/permissions/android.hardware.camera.flash-autofocus.xml
可以查看device/samsung/tuna/device.mk这个例子。
-
在device/<company_name>/<device_name>/media_profiles.xml和device/<company_name> /<device_name>/media_codecs.xml两个XML文件中,声明你的camera设备支持的多媒体编解码器,格式和分辨率。
-
在你的设备的device/<company_name>/<device_name>/device.mk文件中添加如下几行,将media_profiles.xml 和 media_codecs.xml复制到合适的位置。
# media config xml file
PRODUCT_COPY_FILES +=
<device>/<company_name>/<device_name>/media_profiles.xml:system/etc/media_profiles.xml
# media codec config xml file
PRODUCT_COPY_FILES +=
<device>/<company_name>/<device_name>/media_codecs.xml:system/etc/media_codecs.xml
-
通过在你的设备device/<company_name>/<device_name>/device.mk Makefile中的PRODUCT_PACKAGES变量里添加app名称,声明你想将哪些camera app添加到你的设备的系统image中:
PRODUCT_PACKAGES :=
Gallery2
...
-
Camera HAL v3概述
Android硬件抽象层(Hardware Abstraction Layer,HAL)向上连接camera framework 层APIs,向下连接底层Camera驱动和硬件。最新版的Android引进了一种全新的camera stack底层实现方案。如果你有之前开发的适用于老版本Android的camera HAL module和驱动,那么注意了,因为新版本与老版本在camera pipeline的实现上面有非常大的改动。
由于很多设备仍然依赖于老版本的camera HAL,因此,未来的Android发布版本依然会支持第一版的camera HAL。Android camera service也支持同时实现两种HAL,这种设计有一定的好处,比如你想使用HAL v1支持一个能力比较有限的前置camera,同时使用HAL v3支持一个具有强大功能的后置camera,此时这种设计就有了用武之地。HAL v2是v1向v3的一个过渡版本,将不在支持。
系统中只会有一个camera HAL module(这个module拥有自己的版本号,当前是1、2或2.1),该module可以维护多个独立的camera device,每个device都会有自己的版本号。Camera module v2或更新版本的module会支持device v2及更新的版本,这个 camera module可以支持多个不同版本的camera device。这也就是我们为什么说Android支持两个HAL的实现。
注意:新的camera HAL仍然处于开发过程中,以后随时有可能改变,本文只是从一个比较高的层面来介绍camera 子系统的设计和结构,忽略了很多细节的东西。
-
概述
第1版的camera subsystem被设计成由顶层控制黑箱结构。简单的说,老的camera子系统有3种操作模式:
-
预览
-
视频录制
-
继续拍照
每种模式都有所不同,也有一定的功能重叠。这使得很以后在功能扩展方面变得比较困难,比如说burst mode,它属于上面三种中的两种。
图 2 Camera components
-
第3版的改进
重新设计Camera API的目的是从本质是提升Android应用对Android设备上Camera Subsystem的控制能力,同时确保Camera API的可维护性。
加强控制能力主要为了在Android设备上为开发出更高质量的camera应用,尽可能地利用设备最大性能,提升应用的使用效果与用户体验。
第3版的camera子系统将所有的操作模式都归一成一个单一的视图,这种视图可以实现之前的斜体一种模式,也可以方便地进行模式扩展。这样做的好处是用户可以更加灵活的控制对焦、曝光和一些后续的处理,如降噪、对比度和锐化等。此外,简化的视图使得应用开发者可以使用camera的不同功能。新的API将camera子系统建立成一种pipeline,将捕获帧的输入请求转换为帧,以1:1的方式。该请求封装了所有关于捕获和处理一帧的配置信息,主要包括:分辨率、像素格式,手动控制sensor、lens和flash,3A制作模型,RAW转YUV处理控制等等。
举个简单的例子,application framework向camera subsystem请求一帧,camera subsystem返回一个输出流作为结果。另外,metadata包含了如颜色空间、镜头阴影等信息,每一个返回结果都会包含这些信息,下面的图表会详细介绍每个一个组件。
你可以将Camera v3想象成一个pipeline,它将每一个拍照请求转化为sensor捕获的一帧图像,其处理如下:
-
返回一个拍照相关的拥有元数据的对象。
-
一个或者多个图像数据buffer,每个都有自己的目标surface。
可能的输出surface被预先配置:
-
每一个surface是固定分辨率的多个图像buffer的目标。
-
只有很少数量的surface可以被配置为立即输出。
一个请求包含了所有拍照的配置,输出surface的列表被添加到图像buffer中(所有被配置的单元的输出)。一个请求可能只发送一次,也有可能会被多次发送。拍照优先于被重复发送的请求。
图 3 Camera core operation model
-
Supported Version
支持camera HAL v3版本的camera设备,在camera_device_t.common.version和camera_info_t.device_version (来自于camera_module_t.get_camera_info)中,必须返回CAMERA_DEVICE_API_VERSION_3_1。包含v3.1设备的camera模块至少需要实现camera模块接口的v2.0版本(由camera_module_t.common.module_api_version定义)。
-
HAL Subsystem
-
Requests
Application framework层向camera子系统发出一系列捕获数据的请求。一个请求对应于结果中的一个单元。请求封装了这些结果关于捕获数据和处理数据的所有配置信息。这些信息包括:分辨率,像素格式,sensor调整,镜头和闪光灯控制,3A操作模式,RAW转YUV处理,统计信息产生,等等。这里考虑了很多关于对结果数据的输出和处理的控制。多个请求可以一次性发出,提交请求是非阻塞模式。这些请求总是按照被接收到的顺序来处理。
图 4 Camera model
-
The HAL and camera subsystem
Camera子系统包括camera流水线上各个组件的实现,比如3A算法及其处理控制。Camera HAL层为你实现这些组件提供了接口。为了保持对多个设备制造商和图像信号处理器(ISP,或者camera sensor)供应商之间的跨平台兼容性,camera流水线模块是虚拟的,并没有直接对应任何真实的ISP。但是,它与真实的处理流水线很相似,以便你能够高效地将它映射到你的硬件。另外,它很抽象,在质量,性能或者跨设备兼容性方面,不需要任何妥协就可以支持多个不同算法和操作指令。
The camera pipeline also supports triggersthat the app framework can initiate to turn on things such as auto-focus. Italso sends notifications back to the app framework, notifying apps of eventssuch as an auto-focus lock or errors.
Camera流水线也支持触发器,app framework能够初始化并打开它,比如自动聚焦。它也能向app framework发送通知,通知app关于自动聚焦被锁或者错误的事件。
图 5 Camera pipeline
请注意,在最初发布的版本中,上述图表中的一些图像处理模块并没有被很好地定义。Camera pipeline做了如下的假设:
-
输出的RAW Bayer数据在ISP内部没有经过任何处理;
-
生成的统计数据是基于raw sensor的输出数据;
-
ISP中,将raw sensor的输出数据转换为YUV格式的各个处理模块没有严格的先后次序;
-
虽然展示了多个缩放和裁剪单元,但是所有的缩放单元共用一个输出区域控制(比如数字变焦)。但是每个单元可以有不同的输出分辨率和像素格式。
注:数字变焦是根据变焦倍数,从原始图像中裁剪一部分,然后放大到原始分辨率。由于是使用缩放算法直接放大的,所以其图像质量会降低。上图有三个缩放/裁剪单元,但它们共用一个输出控制器,即request control,由它来决定输出到外部缓冲区。根据application framework层的需求,最上面的缩放/裁剪单元会对从raw sensor采集的数据进行裁剪和缩放,最后输出到外边缓冲区。中间和下面的缩放/裁剪单元都是对ISP处理之后的YUV数据进行处理。中间的单元对YUV进行裁剪并缩放后,调用JPEG编码器对其进行编码,输出JPEG图像。下面的单元对YUV进行裁剪并缩放后,输出不同分辨率的YUV数据。这三个缩放/裁剪单元对输入数据也可以不进行裁剪和缩放处理。
API使用总结
这是android camera API使用步骤的简单总结。查看" Startup and expected operation sequence"可以获得这些步骤的详细分解,以及API的调用。
-
监听并枚举所有camera设备;
-
打开设备并连接监听器;
-
配置目标用例所需的输出信息(比如静态图片,视频录制等)
-
根据目标用例创建请求;
-
发送或者重复发送这些请求;
-
接收输出的元数据和图像数据;
-
切换用例,则跳转到第3步;
HAL层操作总结
-
Framework层发送捕获数据的异步请求。
-
HAL层设备必须按照次序处理请求。对于每个请求,HAL层需要输出元数据和一个或者多个图像数据。
-
对于请求和结果都需要遵循先进先出的原则;这个数据流将被后续的请求所参考。
-
对于同一个请求,所有输出数据的时间戳必须相同,以便framework层同步输出数据,如果需要的话。
-
在请求和结果数据总,所有捕获数据的配置和状态(除了3A处理),都需要封装起来。
图 6 Camera HAL overview
-
Startup and expected operation sequence
这段描述了使用camera API的详细步骤。其中涉及到的结构体和函数请参考文件:platform/hardware/libhardware/include/hardware/camera3.h
-
Framework层调用函数camera_module_t->common.open(),将返回一个hardware_device_t类型的结构体。
-
Framework层检查字段hardware_device_t->version,根据版本信息,实例化一个适合这个版本的camera硬件设备的句柄。例如版本号是CAMERA_DEVICE_API_VERSION_3_0,则这个设备将被转化为camera3_device_t。
-
Framework层调用函数camera3_device_t->ops->initialize(),并传递了framework层的回调函数指针。这个函数只能被调用一次,且在调用函数open()之后,在其他函数被调用之前。
-
Framework层调用函数camera3_device_t->ops->configure_streams(),向这个HAL层设备传递了输入输出的流信息。
-
Framework层分配grallocbuffer;调用函数camera3_device_t->ops->register_stream_buffers(),至少使用一个configure_streams中列举的输出流。同一个流只能被注册一次。
-
Framework层通过调用camera3_device_t->ops->construct_default_request_settings()获取用例的默认设置。这个在第三步之后任意地方进行调用。
-
Framework层使用默认设置集合中某一套设置,且保证之前注册了至少一个输出流,创建并向HAL层发第一个捕获请求。这个请求将通过调用函数camera3_device_t->ops->process_capture_request()发送到HAL层。HAL必须阻止函数返回,直到HAL准备好接收下一个请求。
-
Framework层连续地提交请求。可能会调用函数register_stream_buffers()来注册没有注册过的流,调用函数construct_default_request_settings获取其他用例所需的默认设置。
-
当一个请求的捕获开始时(sensor开始曝光),HAL层将调用函数camera3_callback_ops_t->notify()通知上层SHUTTER事件,其中包括sensor开始曝光的帧号和时间戳。调用函数process_capture_result()处理这个帧号对应的数据之前,HAL层必须发出SHUTTER通知。
-
流水线持续一些时间后,HAL层开始使用函数camera3_callback_ops_t->process_capture_result()向framework层返回处理完的图像数据。返回结果的次序与提交请求的次序完全一致。多个请求可以被一次提交,但这取决于camera HAL层设备的流水线深度。
-
工作一段时间之后,framework层可能会停止提交新的请求,等待其他请求被完成(所有buffer被填充,所有结果被返回),然后再次调用函数configure_streams()。这是为一组新的输入输出流重启camera硬件和流水线。前面配置的一些流可能会被重复使用;如果流的buffer已经注册到了HAL层,它们将不再被注册。如果有一个被注册的输出流还存在,则framework层将从第七步重新开始(否则,将从第五步开始)。
-
Framework层将调用函数camera3_device_t->common->close()结束camera会话。当framework层没有其他调用时,可以在任何时间调用这个函数,尽管这个调用会阻塞,直到所有正在处理的捕获被完成(所有结果被返回,所有buffer被填充)。函数close()返回之后,不允许HAL调用camera3_callback_ops_t的任何函数。一旦函数close()被调用,framework层将不能调用其他任何HAL层设备函数。
-
如果发生错误或者其他异步事件,HAL层必须调用函数camera3_callback_ops_t->notify()告知上层对应的错误或者事件信息。一个与设备相关的致命错误被通知上层后,HAL应该像被调用了函数close()一样。但是,在调用函数notify()之前,HAL必须取消或者完成所有未结束的数据捕获操作,以便致命错误被上报之后,framework不会收到设备的任何回调函数。除了函数close(),致命错误信息发出后,其他函数只能返回-ENODEV或者NULL。
图 7 Camera operational flow
-
Operational modes
Camera HAL层v3版本的设备实现两种可能的操作模式之一:limited模式和full模式。新的高端设备预计会支持full模式。Limited模式与camera HAL层v1版本一样,对硬件需求很低,用于旧的或者低价设备。Full模式是limited模式的超集,如上面所述,它们有着基本上一样的操作流程。
Camera HAL层必须使用静态元数据android.info.supportedHardwareLevel指明其所支持的模式。0表示支持limited模式,1表示支持full模式。
简单来讲,limited模式设备不允许应用程序控制捕获数据信息的设置(3A控制除外),大分辨率图像的高帧率捕获,raw数据的获取,或者上面所说的最大视频分辨率的YUV输出流(对于大图像只支持JPEG)。
Limited模式行为的细节如下:
-
Limited模式的设备不需要实现请求配置与实际捕获图像数据的完全匹配。相反,将来有时改变配置将更高效,可能也不需要一个配置必须对应一个同样的输出帧。快速改变配置可能会使得某些配置从来没有被使用过。但是,有高分辨率(大于1080P)输出buffer的捕获必须使用指定的配置(处理速度的描述如下)。
-
在limited模式下,有高分辨率(大于1080P)输出buffer的捕获在函数process_capture_request()中会阻塞,直到所有输出buffer都被填充。Full模式HAL层设备必须按照静态元数据中指定的速率,处理相应像素格式的高分辨率请求的序列。HAL层调用函数process_capture_result()产生输出结果;framework层需要为函数process_capture_request()做好准备,然后阻塞,直到limited模式设备的高分辨率捕获请求被函数process_capture_result()执行完毕。
-
Limited设备不需要支持大多数的配置、结果、静态信息。只有下面的配置期待被limited模式HAL层设备所支持:
- android.control.aeAntibandingMode (controls)
- android.control.aeExposureCompensation (controls)
- android.control.aeLock (controls)
- android.control.aeMode (controls)
- [OFF means ON_FLASH_TORCH]
- android.control.aeRegions (controls)
- android.control.aeTargetFpsRange (controls)
- android.control.afMode (controls)
- [OFF means infinity focus]
- android.control.afRegions (controls)
- android.control.awbLock (controls)
- android.control.awbMode (controls)
- [OFF not supported]
- android.control.awbRegions (controls)
- android.control.captureIntent (controls)
- android.control.effectMode (controls)
- android.control.mode (controls)
- [OFF not supported]
- android.control.sceneMode (controls)
- android.control.videoStabilizationMode (controls)
- android.control.aeAvailableAntibandingModes (static)
- android.control.aeAvailableModes (static)
- android.control.aeAvailableTargetFpsRanges (static)
- android.control.aeCompensationRange (static)
- android.control.aeCompensationStep (static)
- android.control.afAvailableModes (static)
- android.control.availableEffects (static)
- android.control.availableSceneModes (static)
- android.control.availableVideoStabilizationModes (static)
- android.control.awbAvailableModes (static)
- android.control.maxRegions (static)
- android.control.sceneModeOverrides (static)
- android.control.aeRegions (dynamic)
- android.control.aeState (dynamic)
- android.control.afMode (dynamic)
- android.control.afRegions (dynamic)
- android.control.afState (dynamic)
- android.control.awbMode (dynamic)
- android.control.awbRegions (dynamic)
- android.control.awbState (dynamic)
- android.control.mode (dynamic)
- android.flash.info.available (static)
- android.info.supportedHardwareLevel (static)
- android.jpeg.gpsCoordinates (controls)
- android.jpeg.gpsProcessingMethod (controls)
- android.jpeg.gpsTimestamp (controls)
- android.jpeg.orientation (controls)
- android.jpeg.quality (controls)
- android.jpeg.thumbnailQuality (controls)
- android.jpeg.thumbnailSize (controls)
- android.jpeg.availableThumbnailSizes (static)
- android.jpeg.maxSize (static)
- android.jpeg.gpsCoordinates (dynamic)
- android.jpeg.gpsProcessingMethod (dynamic)
- android.jpeg.gpsTimestamp (dynamic)
- android.jpeg.orientation (dynamic)
- android.jpeg.quality (dynamic)
- android.jpeg.size (dynamic)
- android.jpeg.thumbnailQuality (dynamic)
- android.jpeg.thumbnailSize (dynamic)
- android.lens.info.minimumFocusDistance (static)
- android.request.id (controls)
- android.request.id (dynamic)
- android.scaler.cropRegion (controls)
- [ignores (x,y), assumes center-zoom]
- android.scaler.availableFormats (static)
- [RAW not supported]
- android.scaler.availableJpegMinDurations (static)
- android.scaler.availableJpegSizes (static)
- android.scaler.availableMaxDigitalZoom (static)
- android.scaler.availableProcessedMinDurations (static)
- android.scaler.availableProcessedSizes (static)
- [full resolution not supported]
- android.scaler.maxDigitalZoom (static)
- android.scaler.cropRegion (dynamic)
- android.sensor.orientation (static)
- android.sensor.timestamp (dynamic)
- android.statistics.faceDetectMode (controls)
- android.statistics.info.availableFaceDetectModes (static)
- android.statistics.faceDetectMode (dynamic)
- android.statistics.faceIds (dynamic)
- android.statistics.faceLandmarks (dynamic)
- android.statistics.faceRectangles (dynamic)
- android.statistics.faceScores (dynamic)
-
Interaction between the application capture request, 3A control, and the processing pipeline
根据3A控制模块的配置,camera流水线会忽略应用程序请求中的一些参数,而使用3A控制模块提供的值代替。例如,当自动曝光开启时,曝光时间,帧率,sensor的敏感参数都由3A算法控制,应用程序提供的值全被忽略。3A事务为帧所设置的参数值必须包含在输出的元数据中。下面的表格描述了3A模块的不同模式和被这些模式所控制的属性。属性的定义见文件platform/system/media/camera/docs/docs.html。
Parameter |
State |
Properties controlled |
android.control.aeMode |
OFF |
None |
ON |
android.sensor.exposureTime android.sensor.frameDuration android.sensor.sensitivity android.lens.aperture (if supported) android.lens.filterDensity (if supported) |
|
ON_AUTO_FLASH |
Everything is ON, plus android.flash.firingPower, android.flash.firingTime, and android.flash.mode |
|
ON_ALWAYS_FLASH |
Same as ON_AUTO_FLASH |
|
ON_AUTO_FLASH_RED_EYE |
Same as ON_AUTO_FLASH |
|
android.control.awbMode |
OFF |
None |
WHITE_BALANCE_* |
android.colorCorrection.transform. Platform-specific adjustments if android.colorCorrection.mode is FAST or HIGH_QUALITY. |
|
android.control.afMode |
OFF |
None |
FOCUS_MODE_* |
android.lens.focusDistance |
|
android.control.videoStabilization |
OFF |
None |
ON |
Can adjust android.scaler.cropRegion to implement video stabilization |
|
android.control.mode |
OFF |
AE, AWB, and AF are disabled |
AUTO |
Individual AE, AWB, and AF settings are used |
|
SCENE_MODE_* |
Can override all parameters listed above. Individual 3A controls are disabled. |
所列的3A算法的控制大部分都是与旧的API参数一一匹配(例如曝光补偿,场景模式,或者白平衡模式)。
图2中的图像处理模块的控制都是基于一个相似的原则,通常每个模块有三中模式:
-
OFF:这个处理模块不使能。去马赛克,颜色校正和tone曲线调整模块必须使能。
-
FAST:在这种模式,与off模式相比,处理模块不会降低输出帧率,但是对于产生高质量输出时就不受这个限制了。典型地,它被用于预览或者视频录制模式,或者静态图片的快速捕获。在一些设备中,这种模式与OFF模式一样(不工作就不会降低帧率);在一些设备中,它与HIGH_QUALITY模式一样(高质量处理也不会降低帧率)。
-
HIGHQUALITY:在这种模式中,处理模块产生最高质量的结果,如果需要会降低输出帧率。典型地,它被用于高质量静态图片的捕获。一些包括手动控制的模块,可以替代FAST或者HIGHQUALITY。例如,图像校正模块支持一个颜色转换矩阵,而tone曲线调整支持一个任意全局tone映射曲线。
一个camera子系统能够支持的最大帧率是多个元素的函数:
-
输出图像流所需要的分辨率
-
Imager对binning / skipping模式的支持
-
imager接口的带宽
-
各个ISP处理模块的带宽
因为对于不同的ISP和sensor,这些因子有很大的变化,camera HAL层接口想要抽象一个尽可能简单的带宽限制模型。这个模型有如下特性:
-
Sensor总是输出能满足应用程序请求的输出流大小的最小分辨率图像数据。这个最小分辨率至少与被请求的最大输出流大小一样大。
-
因为任何情况可能会用到被配置的输出流的几个或者所有,所以sensor和ISP必须被配置为能够将一个图像同时缩放到所有输出流中。
-
JPEG流就像请求的被处理的YUV流;在请求中,它们直接被当作JPEG流来引用。
-
JPEG处理器能够同时处理camera流水线的剩余部分,但不能在同一个时刻处理多于一张的图片。
-
Metadata and Controls
-
Metadata support
Android framework层为了支持保存raw图像文件,增加了大量关于sensor特性的元数据。这些元数据包括大量信息,例如颜色空间和lens shading。
在camera子系统中,大多数元数据信息都是以静态属性的方式存在,因此在配置输出流水线或者提交请求之前获取这些元数据。在新的camera API中,通过getCameraInfo()方法向application极大地扩展了这些元数据信息。
另外,camera子系统的手动控制需要各类设备提供关于设备当前状态和捕获当前帧时所用的参数的反馈。硬件所使用的实际参数值(曝光时间,帧周期,敏感度)必须包括在输出的元数据中。这些信息对application是必须的,它可以知道clamping 或rounding何时发生,修正图像捕获的配置。
例如,如果application在某个请求中设置的帧周期是0,HAL层必须将那个请求中的帧周期强制为真正的最小帧周期,然后将这个最小周期添加到输出结果的元数据中。
如果一个application要实现定制的3A事例(例如,HDR burst的某些检测),它需要知道所返回的结果中最新一帧的配置信息,以更新下一个请求的配置。因此,新的camera API为每一个捕获的帧添加了大量动态元数据。这些元数据包括这次捕获时设置的和实际使用的参数值,也包括每帧其他的元数据,比如时间戳和统计数据。
-
Per-setting control
对于大多数设置,期望它们能够在每一帧都被改变,对输出帧数据流不会引入明显的卡顿或者延迟。理想情况下,输出帧率只受请求中帧周期字段的控制,不依赖于处理模块配置的改变。实际上,一些特殊控制可以使其变慢;这些控制包括camera流水线的输出分辨率和输出格式,以及影响物理设备的控制,例如镜头焦距。对于每个控制,精确的需求如下描述。
-
Raw sensor data support
除了旧API所支持的像素格式,新的API增加了对raw sensor数据(Bayer RAW)的支持,高级camera application还支持raw图像文件的保存。
-
3A Modes and State Transition
虽然HAL层负责实现3A算法,但HAL interface定义了一个高层次的状态机描述,允许HAL层设备和framework层交流3A当前状态和3A事件的触发情况。
当设备被打开时,所有3A状态都应该是STATE_INACTIVE。码流配置不需重置3A。例如,需要通过调用configure()来修改固定焦点。
要触发3A行为,需要为下一个请求简单地设置相关触发器实体,以引导触发器的启动。例如,启动自动聚焦的触发器需要在一个请求中将ANDROID_CONTROL_AF_TRIGGER设置为ANDROID_CONTROL_AF_TRIGGER_START。停止自动聚焦需要将ANDROID_ CONTROL_AF_TRIGGER设置为ANDROID_CONTRL_AF_TRIGGER_CANCEL。否则,实体不存在或者被设置为ANDROID_CONTROL_AF_TRIGGER_IDLE。每个请求对触发器设置一个非IDLE的值,都会引发一个独立的触发器事件。
在顶层,通过设置ANDROID_CONTROL_MODE控制3A。可以选择没有3A(ANDROID_CONTROL_MODE_OFF),自动模式(ANDROID_CONTROL_MODE_AUTO)和场景模式(ANDROID_CONTROL_USE_SCENE_MODE)。
-
在OFF模式下,自动聚焦(AF),自动曝光(AE)和自动白平衡(AEB)模式都被关闭。3A事例不会重置捕获控制中的任何设置。
-
在AUTO模式下,AF,AE和AWB模式运行各自的独立算法,它们有自己的模式,状态和触发器元数据实体,如下段描述。
-
在USE_SCENE_MODE模式下,ANDROID_CONTROL_SCENE_MODE的值决定3A事例的行为。在除了FACE_PRIORITY的SCENE_MODE中,HAL层必须将ANDROID_CONTROL_AE/AWB/AF_MODE的值重置为更适合被选择的SCENE_MODE的模式。例如,HAL层喜欢在SCENE_MODE_NIGHT场景中使用AF的CONTINUOUS_FOCUS模式。当这些场景模式被忽略时,将使用用户对AE/AWB/AF_MODE的选择。
-
对SCENE_MODE_FACE_PRIORITY的场景,AE/AWB/AFMODE工作在ANDROID_CONTROL_MODE_AUTO模式下。但是3A算法需要侧重对场景中检测出来的脸进行测光和聚焦。
-
Auto-focus settings and result entries
Main metadata entries:
-
ANDROID_CONTROL_AF_MODE:控制当前自动聚焦模式的选择。通过framework层在请求中设置。
AF_MODE_OFF:AF关闭;framework/app直接控制镜头的位置。
AF_MODE_AUTO:Single-sweep自动聚焦。只有AF被触发,镜头才会移动。 -
AF_MODE_MACRO:Single-sweep微距自动聚焦。只有AF被触发,镜头才会移动。
-
AF_MODE_CONTINUOUS_VIDEO:平滑的持续聚焦,用于视频录制。触发则立即在当前位置锁住焦点。取消而继续持续聚焦。
-
AF_MODE_CONTINUOUS_PICTURE:快速持续聚焦,用于静态图片的ZSL捕获。一旦达到扫描目标,触发则立即锁住焦点。取消而继续持续聚焦。
-
AF_MODE_EDOF:高级的景深聚焦。没有自动聚焦的浏览,触发和取消没有意义。通过HAL层控制图像的聚集。
-
ANDROID_CONTROL_AF_STATE:描述当前AF算法状态的动态元数据,HAL层在结果的元数据中报告该信息。
-
AF_STATE_INACTIVE:不做聚焦,或者算法被重置。镜头不移动。这个状态总是用于MODE_OFF或者MODE_EDOF。当设备刚被打开时,必须处于这个状态。
-
AF_STATE_PASSIVE_SCAN:一个持续聚焦的算法正在做扫描。镜头正在移动中。
-
AF_STATE_PASSIVE_FOCUSED:一个持续聚焦的算法认为已经聚焦成功。镜头不在移动。HAL层会自动地离开这个状态。
-
AF_STATE_PASSIVE_UNFOCUSED:一个持续聚焦的算法认为聚焦失败。镜头不在移动。HAL层会自动地离开这个状态。
-
AF_STATE_ACTIVE_SCAN:用户触发的扫描正在进行中。
-
AF_STATE_FOCUSED_LOCKED:AF算法认为聚焦结束。镜头不再移动。
-
AF_STATE_NOT_FOCUSED_LOCKED:AF算法没能完成聚焦。镜头不再移动。
-
ANDROID_CONTROL_AFTRIGGER:控制启动自动聚集扫描,其意义由所选择的模式和状态决定。Framework层在请求中设置该值。
-
AF_TRIGGER_IDLE:没有触发器。
-
AF_TRIGGER_START:触发AF扫描。其作用取决于模式和状态。
-
AF_TRIGGER_CANCEL:停止当前的AF扫描,重置算法到默认状态。
-
其他元数据实体:
-
ANDROID_CONTROL_AF_REGIONS:控制视角区域的选择,用于检测好的聚焦点。用于所有可进行聚焦扫描的AF模式。Framework层在请求中设置该值。
-
Auto-exposure settings and result entries
Main metadata entries:
-
ANDROID_CONTROL_AE_MODE:控制当前自动曝光模式的选择。Framework层在请求中设置该值。
-
AE_MODE_OFF:关闭自动曝光;用户控制曝光,增益,帧周期和闪光灯。
-
AE_MODE_ON:标准的自动聚焦,闪光灯关闭。用户设置闪光灯启动或者手电筒模式。
-
AE_MODE_ON_AUTO_FLASH:标准自动曝光,开启闪光灯。HAL层精确控制捕获前和捕获静态图片时闪光。用户可控制闪光灯关闭。
-
AE_MODE_ON_ALWAYS_FLASH:标准自动曝光,拍照时闪光灯一直开启。HAL层精确控制捕获前闪光。用户可控制闪光灯关闭。
-
AE_MODE_ON_AUTO_FLASH_REDEYE:标准自动曝光。HAL层精确控制预闪和捕获静态图片时闪光。在前面捕获序列的最后一帧启动一次闪光灯,以减少后面图片中的红眼现象。用户可控制闪光灯关闭。
-
ANDROID_CONTROL_AE_STATE:描述当前AE算法状态的动态元数据,HAL层在结果的元数据中报告该信息。
-
AE_STATE_INACTIVE:模式切换后AE初始状态。当设备刚打开时,AE必须处于这个状态。
-
AE_STATE_SEARCHING:AE没有达到曝光目标,正在调整曝光参数。
-
AE_STATE_CONVERGED:AE已经找到当前场景的正确的曝光值,曝光参数不再改变。HAL层会自动离开这个状态,寻找更好的解决方案。
-
AE_STATE_LOCKED:使用AE_LOCK已经锁住了AE。曝光值不再改变。
-
AE_STATE_FLASH_REQUIRED:HAL层已经曝光成功,但为了获取更亮的图片,需要开启闪光灯。用于ZSL模式。
-
AE_STATE_PRECAPTURE:HAL在捕获序列中间进行控制。根据AE模式,这种模式采用启动闪光灯测光或者瞬间开启关闭闪光灯预防红眼。
-
ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER:在捕获一张高质量图像之前,控制启动一个测光序列。Framework层在请求中设置该值。
-
PRECAPTURE_TRIGGER_IDLE:没有触发器。
-
PRECAPTURE_TRIGGER_START:启动一个捕获序列。HAL层使用后续的请求为获取高分辨率图像决定理想的曝光/白平衡。
Additional metadata entries:
-
ANDROID_CONTROL_AE_LOCK:控制锁住AE当前的值。
-
ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION:控制调整AE算法目标亮度点。
-
ANDROID_CONTROL_AE_TARGET_FPS_RANGE:控制选择AE算法的目标帧率区间。AE事例不能使用这个区间之外的帧率值。
-
ANDROID_CONTROL_AE_REGIONS:控制视角区域的选择,用于检测好的曝光值。用于所有除了OOF的AE模式。
-
Auto-whitebalance settings and resultentries
Main metadata entries:
-
ANDROID_CONTROL_AWB_MODE:控制当前白平衡模式的选择。
-
AWB_MODE_OFF:关闭自动白平衡。用户控制颜色矩阵。
-
AWB_MODE_AUTO:使能自动白平衡;3A控制颜色转换,可能会使用比简单矩阵更复杂的转换。
-
AWB_MODE_INCANDESCENT:用于室内白zhi灯的白平衡设置,色温大概2700K。
-
AWB_MODE_FLUORESCENT:用于荧光灯的白平衡设置,色温大概5000K。
-
AWB_MODE_WARM_FLUORESCENT:用于荧光灯的白平衡设置,色温大概3000K。
-
AWB_MODE_DAYLIGHT:用于晴天的白平衡设置,色温大概5500K。
-
AWB_MODE_CLOUDY_DAYLIGHT:用于阴天的白平衡设置,色温大概6500K。
-
AWB_MODE_TWILIGHT:用于日出/日落的白平衡设置,色温大概15000K。
-
AWB_MODE_SHADE:用于阴影处的白平衡设置,色温大概7500K。
-
ANDROID_CONTROL_AWB_STATE:描述当前AWB算法状态的动态元数据,HAL层在结果的元数据中报告该信息。
-
AWB_STATE_INACTIVE:切换模式后AWB的初始状态。当设备刚打开时,AWB必须处于这个状态。
-
AWB_STATE_SEARCHING:AWB没有收敛到目标值,在改变颜色调整参数。
-
AWB_STATE_CONVERGED:AWB为当前场景已经找到了理想的颜色调整值,这些参数不再改变。HAL层会自动离开该状态去寻找更好的解决方案。
-
AWB_STATE_LOCKED:使用AWB_LOCK锁住了AWB。颜色调整值不再改变。
Additional metadata entries:
-
ANDROID_CONTROL_AWB_LOCK:控制锁住当前AWB的值。
-
ANDROID_CONTROL_AWB_REGIONS:控制视角区域的选择,用于检测好的颜色平衡值。只用于自动白平衡模式。
-
General state machine transition notes
在切换AF,AE和AWB的不同模式是总会将算法的状态重置为INACTIVE。同样地,在CONTROL_MODE和CONTROL_SCENE_MODE(CONTROL_MODE == USE_SCENE_ MODE)之间切换时,也需要将算法的状态重置为INACTIVE。
-
AF state machines
mode = AF_MODE_OFF or AF_MODE_EDOF |
|||
State |
Transformation cause |
New state |
Notes |
INACTIVE |
AF is disabled |
||
mode = AF_MODE_AUTO or AF_MODE_MACRO |
|||
State |
Transformation cause |
New state |
Notes |
INACTIVE |
AF_TRIGGER |
ACTIVE_SCAN |
Start AF sweep Lens now moving |
ACTIVE_SCAN |
AF sweep done |
FOCUSED_LOCKED |
If AF successful Lens now locked |
ACTIVE_SCAN |
AF sweep done |
NOT_FOCUSED_LOCKED |
If AF successful Lens now locked |
ACTIVE_SCAN |
AF_CANCEL |
INACTIVE |
Cancel/reset AF Lens now locked |
FOCUSED_LOCKED |
AF_CANCEL |
INACTIVE |
Cancel/reset AF |
FOCUSED_LOCKED |
AF_TRIGGER |
ACTIVE_SCAN |
Start new sweep Lens now moving |
NOT_FOCUSED_LOCKED |
AF_CANCEL |
INACTIVE |
Cancel/reset AF |
NOT_FOCUSED_LOCKED |
AF_TRIGGER |
ACTIVE_SCAN |
Start new sweep Lens now moving |
All states |
mode change |
INACTIVE |
|
mode = AF_MODE_CONTINUOUS_VIDEO |
|||
State |
Transformation cause |
New state |
Notes |
INACTIVE |
HAL initiates new scan |
PASSIVE_SCAN |
Start AF sweep Lens now moving |
INACTIVE |
AF_TRIGGER |
NOT_FOCUSED_LOCKED |
AF state query Lens now locked |
PASSIVE_SCAN |
HAL completes current scan |
PASSIVE_FOCUSED |
End AF scan Lens now locked |
PASSIVE_SCAN |
AF_TRIGGER |
FOCUSED_LOCKED |
Immediate transformation if focus is good Lens now locked |
PASSIVE_SCAN |
AF_TRIGGER |
NOT_FOCUSED_LOCKED |
Immediate transformation if focus is bad Lens now locked |
PASSIVE_SCAN |
AF_CANCEL |
INACTIVE |
Reset lens position Lens now locked |
PASSIVE_FOCUSED |
HAL initiates new scan |
PASSIVE_SCAN |
Start AF scan Lens now moving |
PASSIVE_FOCUSED |
AF_TRIGGER |
FOCUSED_LOCKED |
Immediate transformation if focus is good Lens now locked |
PASSIVE_FOCUSED |
AF_TRIGGER |
NOT_FOCUSED_LOCKED |
Immediate transformation if focus is bad Lens now locked |
FOCUSED_LOCKED |
AF_TRIGGER |
FOCUSED_LOCKED |
No effect |
FOCUSED_LOCKED |
AF_CANCEL |
INACTIVE |
Restart AF scan |
NOT_FOCUSED_LOCKED |
AF_TRIGGER |
NOT_FOCUSED_LOCKED |
No effect |
NOT_FOCUSED_LOCKED |
AF_CANCEL |
INACTIVE |
Restart AF scan |
mode = AF_MODE_CONTINUOUS_PICTURE |
|||
State |
Transformation cause |
New state |
Notes |
INACTIVE |
HAL initiates new scan |
PASSIVE_SCAN |
Start AF scan Lens now moving |
INACTIVE |
AF_TRIGGER |
NOT_FOCUSED_LOCKED |
AF state query Lens now locked |
PASSIVE_SCAN |
HAL completes current scan |
PASSIVE_FOCUSED |
End AF scan Lens now locked |
PASSIVE_SCAN |
AF_TRIGGER |
FOCUSED_LOCKED |
Eventual transformation once focus good Lens now locked |
PASSIVE_SCAN |
AF_TRIGGER |
NOT_FOCUSED_LOCKED |
Eventual transformation if cannot focus Lens now locked |
PASSIVE_SCAN |
AF_CANCEL |
INACTIVE |
Reset lens position Lens now locked |
PASSIVE_FOCUSED |
HAL initiates new scan |
PASSIVE_SCAN |
Start AF scan Lens now moving |
PASSIVE_FOCUSED |
AF_TRIGGER |
FOCUSED_LOCKED |
Immediate transformation if focus is good Lens now locked |
PASSIVE_FOCUSED |
AF_TRIGGER |
NOT_FOCUSED_LOCKED |
Immediate transformation if focus is bad Lens now locked |
FOCUSED_LOCKED |
AF_TRIGGER |
FOCUSED_LOCKED |
No effect |
FOCUSED_LOCKED |
AF_CANCEL |
INACTIVE |
Restart AF scan |
NOT_FOCUSED_LOCKED |
AF_TRIGGER |
NOT_FOCUSED_LOCKED |
No effect |
NOT_FOCUSED_LOCKED |
AF_CANCEL |
INACTIVE |
Restart AF scan |
-
AE and AWB state machines
AE和AWB的状态机基本上是完全相同的。AE有额外的FLASH_REQUIRED和PRECAPTURE状态。所以下面行中涉及这两个状态时,AWB状态机忽略之。
mode = AE_MODE_OFF / AWB mode not AUTO |
|||
State |
Transformation cause |
New state |
Notes |
INACTIVE |
AE/AWB disabled |
||
mode = AE_MODE_ON_* / AWB_MODE_AUTO |
|||
State |
Transformation cause |
New state |
Notes |
INACTIVE |
HAL initiates AE/AWB scan |
SEARCHING |
|
INACTIVE |
AE/AWB_LOCK on |
LOCKED |
Values locked |
SEARCHING |
HAL finishes AE/AWB scan |
CONVERGED |
Good values, not changing |
SEARCHING |
HAL finishes AE scan |
FLASH_REQUIRED |
Converged but too dark without flash |
SEARCHING |
AE/AWB_LOCK on |
LOCKED |
Values locked |
CONVERGED |
HAL initiates AE/AWB scan |
SEARCHING |
Values locked |
CONVERGED |
AE/AWB_LOCK on |
LOCKED |
Values locked |
FLASH_REQUIRED |
HAL initiates AE/AWB scan |
SEARCHING |
Values locked |
FLASH_REQUIRED |
AE/AWB_LOCK on |
LOCKED |
Values locked |
LOCKED |
AE/AWB_LOCK off |
SEARCHING |
Values not good after unlock |
LOCKED |
AE/AWB_LOCK off |
CONVERGED |
Values good after unlock |
LOCKED |
AE_LOCK off |
FLASH_REQUIRED |
Exposure good, but too dark |
All AE states |
PRECAPTURE_START |
PRECAPTURE |
Start precapture sequence |
PRECAPTURE |
Sequence done, AE_LOCK off |
CONVERGED |
Ready for high-quality capture |
PRECAPTURE |
Sequence done, AE_LOCK on |
LOCKED |
Ready for high-quality capture |
-
Enabling manual control
在配置3A模块中所涉及的一些控制,允许application直接控制。
对于每个请求,HAL层负责3A控制的模块会检查3A控制字段的状态。如果有3A事例使能,这些事例可能会重置该事例相关的控制变量,重置的值会放置于此次捕获的结果元数据中。例如,如果在一个请求中自动曝光使能,HAL层会重置这个请求中的曝光值,增益和帧周期字段(和潜在的闪光灯字段,依赖于AE模式)。相关控制如下
Control name |
Unit |
Notes |
android.control.mode |
enum: OFF, AUTO, USE_SCENE_MODE |
High-level 3A control. When set to OFF, all 3A control by the HAL is disabled. The application must set the fields for capture parameters itself. When set to AUTO, the individual algorithm controls in android.control.* are in effect, such as android.control.afMode. When set to USE_SCENE_MODE, the individual controls in android.control.* are mostly disabled, and the HAL implements one of the scene mode settings (such as ACTION, SUNSET, or PARTY) as it wishes. |
android.control.afMode |
enum |
OFF means manual control of lens focusing through android.lens.focusDistance. |
android.control.aeMode |
enum |
OFF means manual control of exposure/gain/frame duration through android.sensor.exposureTime / .sensitivity / .frameDuration |
android.control.awbMode |
enum |
OFF means manual control of white balance. |
-
Output streams and cropping
-
Output streams
与老的Camera子系统不同,老系统从camera输出的数据有3~4种不同的类型(ANativeWindow-based preview operations, preview callbacks, video callbacks, and takePicture callbacks),而在新的camera子系统中,对于所有解决方案和输出数据格式,系统只输出ANativeWindow-based preview operations。可以一次配置多个这样的数据流,发送单帧给多个不同的目标,如GPU、视频编码器、渲染脚本(RenderScript)或应用程序的可见缓冲区(RAE Bayer、YUV buffer、或JPEG-encoded buffers)。
为了优化处理,所有输出流都必须提前配置,一次只能配置有限的数量。这样做的好处,就是允许提前分配内存缓冲区和配置camera硬件。于是,当一次提交多个请求或输出到多个不同pipeline时,就不会有请求延时。
为了实现新版Camera API的向后兼容,必须至少同时支持3路输出流,外加一路JPEG流。这是支持视频快拍的必须条件。
-
One stream to the GPU/SurfaceView (opaque YUV format) for preview
-
One stream to the video encoder (opaque YUV format) for recording
-
One stream to the application (known YUV format) for preview frame callbacks
-
One stream to the application (JPEG) for video snapshots.
具体的需求仍然处于商定之中,还没有最终确定。
-
Cropping