Android Camera2使用笔记

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xiyanlgu/article/details/80693537

1. Android Camera2简介

Android 5.0 (API Level 21)重新设计Camera,并提供了一个全新的API——Camera2。Camera2基本上和Camera1没什么继承性,完全是重新设计。在Camera2中Google引入了Session/Request的概念,从使用上更加复杂,同时也支持更多特性,比如可以控制曝光、控制感光度、支持Raw格式输出。当然坑也更多。
本文简单介绍Camera2使用的基本流程,只会实现一个最简单的预览功能。在后续的文章中会介绍如何使用Camera2进行对焦,控制曝光、对焦等等。

2. Camera2基础

这里先简要介绍下Camera2 API主要用到哪些类,先有个印象;之后介绍Camera从打开到预览的流程;最后介绍Camera2中一些详细的接口。

2.1 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和CameraRequest.Builder

CameraRequest.Builder配置CameraRequest,具体功能就是告诉Camera想要什么样的图像。Builder中主要结构是一个Map。Builder构建后得到CameraRequest。
然后通过CameraCaptureSession发送CameraRequest。

2.2 Camera2从打开到预览基础流程

流程如下
Camera2流程图

主要类
Camera Classes

2.2.1 初始化

这个阶段大部分工作都是由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) {
            //...
        }
    };

2.2.2. 创建 CameraSession

这部分核心是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();
        }

2.2.3 配置CaptureRequest

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:捕获的结果,比如是否对焦成功等等…………

3. 源代码

源代码直接参考Google的Demo就好了:Camera2Basic

猜你喜欢

转载自blog.csdn.net/xiyanlgu/article/details/80693537