Android 5.0 (API Level 21)重新设计Camera,并提供了一个全新的API——Camera2。Camera2基本上和Camera1没什么继承性,完全是重新设计。在Camera2中Google引入了Session/Request的概念,从使用上更加复杂,同时也支持更多特性,比如可以控制曝光、控制感光度、支持Raw格式输出。当然坑也更多。
本文简单介绍Camera2使用的基本流程,只会实现一个最简单的预览功能。在后续的文章中会介绍如何使用Camera2进行对焦,控制曝光、对焦等等。
这里先简要介绍下Camera2 API主要用到哪些类,先有个印象;之后介绍Camera从打开到预览的流程;最后介绍Camera2中一些详细的接口。
摄像头管理器,用来获取CameraDevice对象,获取Camera属性。
在Camera打开之前主要操作CameraManager,打开后主要操作CameraCaptureSession
mCameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
摄像头属性,相当于原CameraInfo。通过CameraManager获取制定id的摄像头属性。
通过获取Camera属性信息,配置Camera输出,如FPS,大小,旋转等
mCameraCharacteristics = mCameraManager.getCameraCharacteristics(currentCameraId);
代表摄像头,相当于于早期的Camera类。
用于创建CameraCaptureSession和关闭摄像头。
通过CameraManager打开Camera,在StateCallback中会得到CameraDevice实例。
如前文所述,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;
}
mCameraManager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
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查询到该相机的属性信息,包括:
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[] fpsRanges =
cameraCharacteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES);
//选择合适分辨率
mCameraManager.openCamera(currentCameraId, mStateCallback, mMainHandler);
StateCallback
Camera2中有两个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 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的核心,主要有两大类:
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