Android 5.0 (API Level 21)重新设计Camera,并提供了一个全新的API――Camera2。Camera2基本上和Camera1没什么继承性,完全是重新设计。在Camera2中Google引入了Session/Request的概念,从使用上更加复杂,同时也支持更多特性,比如可以控制曝光、控制感光度、支持Raw格式输出。当然坑也更多。
本文简单介绍Camera2使用的基本流程,只会实现一个最简单的预览功能。在后续的文章中会介绍如何使用Camera2进行对焦,控制曝光、对焦等等。
这里先简要介绍下Camera2 API主要用到哪些类,先有个印象;之后介绍Camera从打开到预览的流程;最后介绍Camera2中一些详细的接口。
CameraManager
摄像头管理器,用来获取CameraDevice对象,获取Camera属性。
在Camera打开之前主要操作CameraManager,打开后主要操作CameraCaptureSession
mCameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
CameraCharacteristics
摄像头属性,相当于原CameraInfo。通过CameraManager获取制定id的摄像头属性。
通过获取Camera属性信息,配置Camera输出,如FPS,大小,旋转等
mCameraCharacteristics = mCameraManager.getCameraCharacteristics(currentCameraId);
CameraDevice
代表摄像头,相当于于早期的Camera类。
用于创建CameraCaptureSession和关闭摄像头。
通过CameraManager打开Camera,在StateCallback中会得到CameraDevice实例。
CameraCaptureSession
如前文所述,Camera打开后,我们就主要和CameraCaptureSession打交道了。CameraCaptureSession建立了一个和Camera设备的通道,当这个通道建立完成后就可以向Camera发送请求获取图像。
CameraRequest.Builder配置CameraRequest,具体功能就是告诉Camera想要什么样的图像。Builder中主要结构是一个Map。Builder构建后得到CameraRequest。
然后通过CameraCaptureSession发送CameraRequest。
流程如下
主要类
这个阶段大部分工作都是由CameraManager完成的。
- 检查权限
if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { requestCameraPermission(); return; }
- 获取CameraManager
mCameraManager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
- 获取Camera设备
CameraManager中能够获取CameraID的列表,一般都是前置相机和后置相机。
String[] cameraList = mCameraManager.getCameraIdList(); if (position < 0 || position > 2) { mMainHandler.post(new Runnable() { @Override public void run() { if (mCameraListener != null) { mCameraListener.onOpenFail(IESCameraInterface.CAMERA_2); } } }); return false; } if (position >= cameraList.length) position = CAMERA_FRONT; currentCameraPosition = position;
获取Camera设备属性
拿到对应的CameraID后,可以通过CameraManager查询到该相机的属性信息,包括:- 硬件兼容信息
- orientation
- facing
- FPS Range
- Frame Size
- Frame Format
mCameraCharacteristics = mCameraManager.getCameraCharacteristics(currentCameraId); //Device Level int deviceLevel = c.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL); //旋转角度 mCameraRotate = mCameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION); StreamConfigurationMap streamConfigurationMap = mCameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); // //支持的分辨率 mOutputSizes = streamConfigurationMap.getOutputSizes(SurfaceTexture.class); //FPS Range<Integer>[] fpsRanges = cameraCharacteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES); //选择合适分辨率
- 打开Camera
打开Camera需要传入StateCallback
mCameraManager.openCamera(currentCameraId, mStateCallback, mMainHandler);
StateCallback
Camera2中有两个StateCallback:- CameraDevice.StateCallback
- CameraCaptureSession.StateCallback
此处介绍的是前者。
private CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() { @Override public void onOpened(@NonNull CameraDevice camera) { mCameraDevice = camera; //Create Camera Session } @Override public void onDisconnected(@NonNull CameraDevice camera) { //Close Camera //... } @Override public void onError(@NonNull CameraDevice camera, int error) { //... } };
这部分核心是Surface和CameraCaptureSession.StateCallback:
Surface是Camera的输出,可以添加多个;
CameraCaptureSession.StateCallback: Session是否创建成功。
try { surfaceTexture.setDefaultBufferSize(sWidth, sHeight); mCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD); List<Surface> surfaces = new ArrayList<>(); mPreviewSurface = new Surface(surfaceTexture); surfaces.add(mPreviewSurface); mCaptureRequestBuilder.addTarget(mPreviewSurface); mCameraDevice.createCaptureSession(surfaces, new CameraCaptureSession.StateCallback() { @Override public void onConfigured(CameraCaptureSession cameraCaptureSession) { mCameraCaptureSession = cameraCaptureSession; //Config Capture Request } @Override public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) { } }, mMainHandler); } catch (CameraAccessException e) { e.printStackTrace(); }
CaptureRequest的配置项非常多,可以配置防抖,对焦,曝光……(在后续的文章中会详细介绍如何设置这些特性)。
CaptureRequest是Camera2的核心,主要有两大类:
- capture:只请求一帧图像,可以重复请求,每次请求的配置可以不同。
- setRepeatingRequest:连续请求图像,每帧的请求配置相同,如果配置改变,比如改变了曝光时间,需要停止request,从新Build Request然后重新请求。
try { mCaptureRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO); mCaptureRequest = mCaptureRequestBuilder.build(); mCameraCaptureSession.setRepeatingRequest(mCaptureRequest, mSessionCaptureCallback, mMainHandler); } catch (CameraAccessException e) { e.printStackTrace(); }
CameraCaptureSession.CaptureCallback:捕获的结果,比如是否对焦成功等等…………
源代码直接参考Google的Demo就好了:Camera2Basic