本文将基于android6.0的源码,对Camera API2.0下Camera的preview的流程进行分析。在文章android6.0源码分析之Camera API2.0下的初始化流程分析中,已经对Camera2内置应用的Open即初始化流程进行了详细的分析,而在open过程中,定义了一个PreviewCallback,当时并未详细分析,即Open过程中,会自动开启预览过程,即会调用OneCameraImpl的startPreview方法,它是捕获和绘制屏幕预览帧的开始,预览才会真正开始提供一个表面。
Camera2文章分析目录:
android6.0源码分析之Camera API2.0简介
android6.0源码分析之Camera2 HAL分析
android6.0源码分析之Camera API2.0下的初始化流程分析
android6.0源码分析之Camera API2.0下的Preview(预览)流程分析
android6.0源码分析之Camera API2.0下的Capture流程分析
android6.0源码分析之Camera API2.0下的video流程分析
Camera API2.0的应用
1、Camera2 preview的应用层流程分析
preview流程都是从startPreview开始的,所以来看startPreview方法的代码:
//OneCameraImpl.java
@Override
public void startPreview(Surface previewSurface, CaptureReadyCallback listener) {
mPreviewSurface = previewSurface;
//根据Surface以及CaptureReadyCallback回调来建立preview环境
setupAsync(mPreviewSurface, listener);
}
这其中有一个比较重要的回调CaptureReadyCallback,先分析setupAsync方法:
//OneCameraImpl.java
private void setupAsync(final Surface previewSurface, final CaptureReadyCallback listener) {
mCameraHandler.post(new Runnable() {
@Override
public void run() {
//建立preview环境
setup(previewSurface, listener);
}
});
}
这里通过CameraHandler来post一个Runnable对象,它只会调用Runnable的run方法,它仍然属于UI线程,并没有创建新的线程。所以,继续分析setup方法:
// OneCameraImpl.java
private void setup(Surface previewSurface, final CaptureReadyCallback listener) {
try {
if (mCaptureSession != null) {
mCaptureSession.abortCaptures();
mCaptureSession = null;
}
List<Surface> outputSurfaces = new ArrayList<Surface>(2);
outputSurfaces.add(previewSurface);
outputSurfaces.add(mCaptureImageReader.getSurface());
//创建CaptureSession会话来与Camera Device发送Preview请求
mDevice.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateCallback() {
@Override
public void onConfigureFailed(CameraCaptureSession session) {
//如果配置失败,则回调CaptureReadyCallback的onSetupFailed方法
listener.onSetupFailed();
}
@Override
public void onConfigured(CameraCaptureSession session) {
mCaptureSession = session;
mAFRegions = ZERO_WEIGHT_3A_REGION;
mAERegions = ZERO_WEIGHT_3A_REGION;
mZoomValue = 1f;
mCropRegion = cropRegionForZoom(mZoomValue);
//调用repeatingPreview来启动preview
boolean success = repeatingPreview(null);
if (success) {
//若启动成功,则回调CaptureReadyCallback的onReadyForCapture,表示准备拍照成功
listener.onReadyForCapture();
} else {
//若启动失败,则回调CaptureReadyCallback的onSetupFailed,表示preview建立失败
listener.onSetupFailed();
}
}
@Override
public void onClosed(CameraCaptureSession session) {
super.onClosed(session);
}
}, mCameraHandler);
} catch (CameraAccessException ex) {
Log.e(TAG, "Could not set up capture session", ex);
listener.onSetupFailed();
}
}
首先,调用Device的createCaptureSession方法来创建一个会话,并定义了会话的状态回调CameraCaptureSession.StateCallback(),其中,当会话创建成功,则会回调onConfigured()方法,在其中,首先调用repeatingPreview来启动preview,然后处理preview的结果并调用先前定义的CaptureReadyCallback来通知用户进行Capture操作。先分析repeatingPreview方法:
// OneCameraImpl.java
private boolean repeatingPreview(Object tag) {
try {
//通过CameraDevice对象创建一个CaptureRequest的preview请求
CaptureRequest.Builder builder = mDevice.createCaptureRequest(
CameraDevice.TEMPLATE_PREVIEW);
//添加预览的目标Surface
builder.addTarget(mPreviewSurface);
//设置预览模式
builder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
addBaselineCaptureKeysToRequest(builder);
//利用会话发送请求,mCaptureCallback为
mCaptureSession.setRepeatingRequest(builder.build(), mCaptureCallback,mCameraHandler);
Log.v(TAG, String.format("Sent repeating Preview request, zoom = %.2f", mZoomValue));
return true;
} catch (CameraAccessException ex) {
Log.e(TAG, "Could not access camera setting up preview.", ex);
return false;
}
}
首先调用CameraDeviceImpl的createCaptureRequest方法创建类型为TEMPLATE_PREVIEW 的CaptureRequest,然后调用CameraCaptureSessionImpl的setRepeatingRequest方法将此请求发送出去:
//CameraCaptureSessionImpl.java