原文:Android Camera2 API Explained 与旧的Camera API相比,L中引入的Camera2 API要复杂得多:涉及十多个类,通过callback进行异步操作,同时增加了许多令人困惑的捕获控制(capture controls)和元数据(meta data)。
面对一个复杂的系统时,通常用UML类图来进行一下概览。以下是Camera2 API的类图。
按照上图中的步骤编号,我们一一对应起来分析:
1.CameraManager这个类, 我们可以通过它来获取系统中所有可用的camer设备,每个camera都有一个指定的cameraId来标识。通过cameraId,我们可以获得指定camera设备的属性, 这些属性由CameraCharacteristics类存储,其中包括了“前置或后置摄像头”,“支持的输出分辨率”等属性。
2.对于camera捕获的图像数据,应该有一个最终的接收者来处理:比如使用SurfaceView或SurfaceTexture进行预览处理、使用ImageReader进行静态图片处理、或者使用MediaRecoder进行视频录制处理,这些处理操作都会有一个接收者——Surface。也就是说,对于这些操作来说,我们需要想办法获取到一个Surface,然后设置到CamerDevice中,才可以接收到camera捕获的图像数据。 在下面的步骤中会讲述如何创建CaptureSession列表、如何将Surface添加到CaptureRequest中,届时将会明白Surface的作用。
3.通过调用CameraManager.open(cameraId,callback)来获取CameraDevice。 由于调用是异步的,因此需要在onOpened()回调中获取CameraDevice。
4.从CameraDevice创建CaptureRequest,CaptureRequest实际上是一个固定的数据包(immutable package),我们从camera获取单张图像后,通过CaptureRequest对其设置和输出。这里应用了Builder模式,如上面的类图所示,CaptureReques.Builder是从CameraDevice中的createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)方法来创建的。 然后,我们使用构建器来设置变其他属性,比如addTarget(Surface)来设置CaptureRequest的接收者。注意,我们通常不直接创建CaptureRequest,因为这样比较容易出错。
5.从CameraDevice创建CaptureRequestSession, CaptureRequestSession用于提交上面创建好的CaptureRequest。要初始化CaptureRequestSession,必须提供初始化好的Surface,这在步骤2中已经讨论过。另请注意,CaptureRequestSession的创建也是异步的。
6.通过CaptureRequestSession发送CaptureRequest,有几个API可以做到这一点:capture()用于发出一次性拍照命令,setRepeatingRequest()用于发出显示预览的重复请求。此外,在发送CaptureRequest请求之前,需要设置自动对焦模式、白平衡模式等内容。
7.获取捕获的图像结果。捕获到的结果将通过CameraCaptureSession.CaptureCallback异步返回,你可以在这个回调中播放拍照声音(例如“咔嚓”的声音),也可以在onCaptureProcessed方法里接收一张张的CaptureResult。
8.对于步骤7来说,我们也可以在onCaptureComplete方法的TotalCaptureResult中一次性获取所有数据。
最后总结一下,camera捕获到的图像数据输出到surface处理,正如步骤2中所讨论的。camera是生产者,surface是消费者。camera保持对图像数据进行排队,一旦数据可用,将通知消费者surface处理它们:TextureView会将图片数据转换为纹理,并在绘制到屏幕;MediaRecoder会将图像传递给编解码器进行处理;对于ImageReader,由我们自己处理数据。