1.2Camera Preview流程及源码分析

时间:2024-03-22 14:56:52

Camera API2的预览实现在网上有非常多的代码可以参考,包括Google官方提供的Demo。直接看代码,模仿、改写当然是最快的实现方式,但如果其中的逻辑关系可能没有捋顺清楚,在没有参考代码的情况下,能否同样实现相关功能就值得商榷了。

 

1.2Camera Preview流程及源码分析

1API2架构图

这个图是一个常见的用于展示API2架构的图,但事实上这个图并不能对架构和开发起到很好的帮助。这个图的主要问题是无法搞清楚Camera APP与Camera Device之间到底是什么逻辑关系。本文中,我将从类逻辑出发,逐步串起preview的全过程。

PS:想直接看结论的可以到最后看总结的部分,跳过中间的实现环节,和代码分析。

一、Camera Manager类和open camera的方法

我们在上一节中说过,CameraManager是一个System Service,也就是Camera Service,Camera的软件行为都是发生在这个Service中的。所以当我们想要使用Camera、想要获取Camera信息时,首先要获取到CameraManager对象。1.2Camera Preview流程及源码分析2CameraManager类

Kotlin代码

val manager = activity!!.getSystemService(Context.CAMERA_SERVICE) as CameraManager

此时,我们来详细的看一下CameraManager类的属性和方法,在图2中可以看到有4个方法以openCamera开头,区别仅仅是参数不同。此处选择

1.2Camera Preview流程及源码分析方法,这个方法应该时使用频率最高的一个open方法。

Kotlin代码

manager.openCamera(mCameraId!!, mStateCallback, mBackgroundHandler)

源码:

1.2Camera Preview流程及源码分析

可以看到对内部直接调用了openCameraForUid方法,并且出现了CameraDeviceImpl类,这个类前面提到过是非公开API暂时不管,继续查看该方法源码。


该方法在进行了非空和异常处理之后调用了openCameraDeviceUserAsync方法。如果我们查看剩下的一个open方法,会发现也是调用的openCameraForUid方法。换言之,Camera的真正open方法只有一个,就是openCameraDeviceUserAsync()方法。

该方法的核心部分进行了一次API support的判断,如果支持将进入HAL3.2以上通道;如果不支持将进入legacy HAL1通道。至此Camera open    经完成,方法返回CameraDevice对象。
我们回溯到最初的方法。可以看到三个需要传入的参数,除了第一个Camera id,还需要传入一个CameraDevice.StateCallback对象。
如前所述,StateCallback是表示CameraDevice状态的回调,分别对应已打开、已关闭、失去连接、出错四种状态。对于预览来说,需要在onOpened方法中进行处理,并获得CameraDevice对象。
二、CameraDevice类和创建会话
CameraDevice对象可以理解为设备本身。

从提供的公开方法可以看出,CameraDevice的主要行为就是创建不同作用的session,会话机制作为API2中引入的新机制,是区别于API1的主要特点,关于session机制将在下一节专门进行分析。

首选我们选择1.2Camera Preview流程及源码分析方法作为创建session方法。

之所以选择这个方法是因为这个方法的第一个参数是Surface的List,而我们知道SurfaceVIew/TextureView/GLSurfaceView等都是我们通常用来显示Preview的载体,很容易才想到二者之间存在某种关系

Kotlin代码

1.2Camera Preview流程及源码分析

所以这个List的第一个值代表的就是SurfaceVIew的surface。这里再多提一句第二个值是ImageReader的surface,第三个值一般是缩略图的surface。

方法的第二个参数是StateCallback,不用于openCamera方法中的StateCallback,这里是CameraCaptureSession的状态回调。

1.2Camera Preview流程及源码分析

内部的方法代表了会话的各种状态,方法名一目了然不多做解释了。

其中onConfigured()方法,即Camera配置完成的回调无疑就是我们处理后续逻辑的方法,在这个方法中我们将得到CameraDevice建立的session对象。

至此,在整个逻辑上就只有最后一步生成预览。

三、生成预览

在上一步我们得到了CameraCaptureSession对象。

1.2Camera Preview流程及源码分析

可以看到用于拍照的capture方法,以及用于连续捕捉的方法。对于preview无疑是连续捕捉画面,所以setRepeatingRequest方法就是我们所需要的方法。
Kotlin代码

mCaptureSession!!.setRepeatingRequest(

mPreviewRequest!!,

mCaptureCallback, mBackgroundHandler
)

   方法中的第一个参数CaptureRequest就是用来表述要捕获的单幅图像的,所以通过配置CaptureRequest的参数,就完成了对preview画面的配置,包括对焦、白平衡等配置,具体的配置将在后续章节中展开讲解。

四、总结

在实现Camera Preview功能的过程中,通过层层推进的方式,我们可以看到API2的逻辑是:

  1. CameraManager管理CameraDevice
  2. CameraDevice管理CameraCaptureSession
  3. CameraDeviceCameraCaptureSession的状态反馈到各自的StateCallback回调中,用户需要实现的部分都在这些回调中。

1.2Camera Preview流程及源码分析

这里给出一个完整的流程图例。

 

经过分析后,再回头看图一,就会发现这个图很有迷惑性,左侧的APP是指实现了全部API的整个相机实现,而右侧的Device是指实体硬件。

 

下一节将详细分析API2 session机制。