Android Camera2 API指南

匿名 (未验证) 提交于 2019-12-03 00:27:02

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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!