写在开头:本文为学习 camera2 过程中的知识点归纳总结。
1. camera2 相机体系结构
https://blog.csdn.net/u012596975/article/details/107138177
对于Camera Api v2的实现,是通过Camera Framework来完成的,而该层也有着一次不小的演变,刚开始Framework层并不是直接通过AIDL接口与Camera Service进行通信,而是通过一个JNI层来完成从Java到Native的转换,而Native部分作为客户端,保持对Service的通信。这种设计,很显然会比较臃肿,并且代码难以维护,所以之后由于AIDL接口的提出,谷歌直接将其加入到相机框架中,用于保持Framework与Service的通信,进而摈弃了JNI层,进一步减少了不必要的层级结构,保持了整个体系简洁性。
更多可参考 深入理解Android相机体系结构 系列。
2. camera1和camera2的使用简单对比
先回顾一下,camera1和camera2的简单使用。
这两篇camera1和camera2的预览demo,十分简洁,功能单一,可供对比。
Android Camera1最简单的预览框显示
Android Camera2最简单的预览框显示
下面这两张思维导图,较为详细得说明了camera的使用流程和API。这不是本篇的重点。
camera1 的 open 简单代码流程可参考这篇:
Android Camera open 从上到下代码流程
camera2 的 open 简单代码流程可参考这篇:
Android CameraManager open 从上到下代码流程
如果需要更详细的demo,可参考官方的 demo:cameraview
camera1和camera2 的调用流程对比,可参考这张图。可以看到,API V2是没有通过JNI的api的,这里是直接调用的service。
谷歌在Andorid 5.0(API Level 21)便重新对Camera进行了设计,摒弃了Camera Api v1的设计逻辑,提出了一个全新的API – camera2,引入了Session以及Request概念,将控制逻辑统一成一个视图,因此在使用上更加复杂,同时也支持了更多特性,比如逐帧控制曝光、感光度以及支持Raw格式的输出等。并且由于对控制逻辑的高度抽象化,使得该接口具有很高的灵活性,可以通过简单的操作实现30fps的全高清连拍的功能,总得来说,该接口极大地提高了对于相机框架的控制能力,同时也进一步大幅度提升了其整体性能。
camera2的应用层与framework层之间的流程如下:
简单来说就是,引入了Session以及Request,使用更加复杂,功能多,更加灵活了。
注意,虽然新增了camera2的api,camera1的代码依然在android源码中。分析的时候要注意。
frameworks/base/core/java/android/hardware/camera2/
这个目录下的是camera2的framework层代码。
Camera整体架构简述
忽略掉驱动层,就是这张图。
了解完Android Camera工作大体流程后,来看看部分细节。
2. 源码简单分析
本篇源码分析,不会涉及驱动层及以下(最多一点点)。另由于MTK和高通camera,还有android原生的,在camera这块差异很大,流程分析查找资料的时候要注意下。
Android Camera工作大体流程:
出处: https://blog.csdn.net/TaylorPotter/article/details/105387109
绿色框中是应用开发者需要做的操作,蓝色为AOSP提供的API,黄色为Native Framework Service,紫色为HAL层Service.
描述一下步骤:
- 1.App一般在MainActivity中使用SurfaceView或者SurfaceTexture + TextureView或者GLSurfaceView等控件作为显示预览界面的控件,共同点都是包含了一个单独的Surface作为取相机数据的容器.
- 2.在MainActivity onCreate的时候调用API 去通知Framework Native Service CameraServer去connect HAL继而打开Camera硬件sensor.
- 3.openCamera成功会有回调从CameraServer通知到App,在onOpenedCamera或类似回调中去调用类似startPreview的操作.此时会创建CameraCaptureSession,创建过程中会向CameraServer调用ConfigureStream的操作,ConfigureStream的参数中包含了第一步中空间中的Surface的引用,相当于App将Surface容器给到了CameraServer,CameraServer包装了下该Surface容器为stream,通过HIDL传递给HAL,继而HAL也做configureStream操作
- 4.ConfigureStream成功后CameraServer会给App回调通知ConfigStream成功,接下来App便会调用AOSP setRepeatingRequest接口给到CameraServer,CameraServer初始化时便起来了一个死循环线程等待来接收Request.
- 5.CameraServer将request交到Hal层去处理,得到HAL处理结果后取出该Request的处理Result中的Buffer填到App给到的容器中,
SetRepeatingRequest 为了预览,则交给Preview的Surface容器,如果是Capture Request则将收到的Buffer交给ImageReader的Surface容器. - 6.Surface本质上是BufferQueue的使用者和封装者,当CameraServer中App设置来的Surface容器被填满了BufferQueue机制将会通知到应用,此时App中控件取出各自容器中的内容消费掉,Preview控件中的Surface中的内容将通过View提供到SurfaceFlinger中进行合成最终显示出来,即预览;而ImageReader中的Surface被填了,则App将会取出保存成图片文件消费掉.
简单图如下:
https://blog.csdn.net/TaylorPotter/article/details/105387109
通过AIDL binder调用向Framework层的CameraServer进程下指令,从CameraServer进程中取的数据.
基本过程都如下:
- 1.openCamera:Sensor上电
- 2.configureStream: 该步就是将控件如GLSurfaceView,ImageReader等中的Surface容器给到CameraServer.
- 3.request: 预览使用SetRepeatingRequest,拍一张可以使用Capture,本质都是setRequest给到CameraServer
- 4.CameraServer将Request的处理结果Buffer数据填到对应的Surface容器中,填完后由BufferQueue机制回调到引用层对应的Surface控件的CallBack处理函数,接下来要显示预览或保图片App中对应的Surface中都有数据了
着重看看以下几点
- CameraService和CameraProvider服务启动
- open
- configure
- request
2.1 CameraService和CameraProvider服务启动
层级架构概览
总体逻辑顺序计
(1) CameraProvider进程启动、注册
(2) CameraServer进程启动、注册、初始化
(3) CameraServer初始化过程中通过HIDL通信获取CameraProvider,并对 CameraProvider进行初始化
CameraService和CameraProvider初始化
CameraServer初始化
具体代码流程可参考:
Android 8.1 Camera2架构解析(1) CameraService和CameraProvider服务启动流程
[Android O] Camera 服务启动流程简析
2.2 open
可直接参考这篇:
camera framework open流程
有道笔记上排版更好。
camera2 open流程
最后来张时序图加深下印象。
2.3 configure
以下代码出自这篇Android Camera2最简单的预览框显示。
/**
* 打开相机,预览是在回调里面执行的。
*/
private void openCamera() {
try {
// 4.权限检查
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
requestCameraPermission();
return;
}
// 5.真正打开相机
Log.i(TAG, "openCamera");
mCameraManager.openCamera(mCameraId, mStateCallback, null);
} catch (CameraAccessException e) {
Log.e(TAG, "openCamera error = " + e.getMessage());
}
/**
* 相机状态监听对象
*/
private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(CameraDevice camera) {
Log.i(TAG, "StateCallback! onOpened");
mCameraDevice = camera; // 打开成功,保存代表相机的CameraDevice实例
SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture();
surfaceTexture.setDefaultBufferSize(mTextureView.getWidth(), mTextureView.getHeight());
Surface surface = new Surface(surfaceTexture);
ArrayList<Surface> previewList = new ArrayList<>();
previewList.add(surface);
try {
// 6.将TextureView的surface传递给CameraDevice
mCameraDevice.createCaptureSession(previewList, new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
try {
CaptureRequest.Builder builder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
builder.addTarget(surface); // 必须设置才能正常预览
CaptureRequest captureRequest = builder.build();
// 7.CameraCaptureSession与CaptureRequest绑定(这是最后一步,已可显示相机预览)
session.setRepeatingRequest(captureRequest, mSessionCaptureCallback, null);
} catch (CameraAccessException e) {
Log.e(TAG, "createCaptureRequest error = " + e.getMessage());
}
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
Log.e(TAG, "onConfigureFailed");
}
}, null);
} catch (CameraAccessException e) {
Log.e(TAG, "createCaptureSession error = " + e.getMessage());
}
}
应用层在openCamera之后,会调用createCaptureSession。
createCaptureSession之后的流程可参考这篇:
camera framework configure流程分析
出处:https://blog.csdn.net/haodada1226/article/details/121719939
总结一下:
① configure为app传入的surface配置相应的stream,然后将gbp、streamid、surfaceid进行绑定,以便于发送request请求的时候去获取;
② 告诉hal层,需要从camera中获取什么样格式的buffer
简单版时序图
复杂版时序图
2.4 request
在 Android Camera2最简单的预览框显示 这篇文的代码中可以看到,
调用createCaptureRequest之后通过build创建CaptureRequest,然后session.setRepeatingRequest
,然后就可以预览了。
然后接下来的流程可直接参考这篇:
camera framework request流程
出处: https://blog.csdn.net/haodada1226/article/details/121848769
这里总结一下:
configure的时候为每个surface创建相应的Camera3OutputStream,然后将相应的信息保存起来(注意CameraDeviceClient中的mStreamMap、mConfiguredOutputs以及Camera3Device中的mOutputStreams等),然后告诉hal层需要配置什么格式、分辨率等的流。request中会将上述的surfaces和outputStreams填充进request请求中,然后在Camera3Device中起一个thread,一直向hal层发送request请求。
最后来张时序图
3.camera中的BufferQueue
https://www.jianshu.com/p/05a8d6f5b4df
BufferQueue可以理解为一个生产者-消费者”模型,对GraphicBuffer管理的一种机制。
需注意的是,可以将BufferQueue当作是一个算法结构,并不是只有Surfaceflinger会使用到,其他进程只要有GraphicBuffer的消费地方都会使用到。
BufferQueue结构
https://www.jianshu.com/p/05a8d6f5b4df
图形生产者(如相机,View绘制等)先向BufferQueue申请GraphicBuffer,填充完GraphicBuffer后,将GraphicBuffer移交给BufferQueue,BufferQueue会通知图形消费者(如Surfaceflinger,ImageReader,GLConsumer等)
相机中preview使用到的TextureView中的成员SurfaceTexture就是个自带BufferQueue的组件。
框架流程汇总
参考链接:
深入理解Android相机体系结构之二
深入理解Android相机体系结构之三
深入理解Android相机体系结构之十
Android Camera简单整理(一)-Camera Android架构(基于Q)
Android Camera简单整理(三)-Mtk Camera MtkCam3架构学习
CameraService启动流程
Android 8.1 Camera2架构解析(1) CameraService和CameraProvider服务启动流程
Camera service服务启动流程
BufferQueue详解 原理
Android-Fk:BufferQueue学习整理
Android Camera2 Framwork+Hal+Surface整体数据流程
Android Camera 打开预览流程分析(三)-- Camera 连接到CameraService 过程分析
camera framework configure流程分析
Camera2 API -- OutputConfiguration
camera framework configure流程分析