Camera2 介绍

这里介绍的是 CameraManager 、 CameraDevice 、 CaptureRequestSession 、CaptureRequest,先来看一下他们的关系:

Camera2 介绍_第1张图片

1. CameraManager

CameraManager主要用于管理系统摄像头。

  • Context.getSystemService(Context.CAMERA_SERVICE) 来完成初始化,
  • 可以 getCameraIdList 获取所有可用和Camera设备的cameraId(唯一标识)
  • 可以通过这个Id getCameraCharacteristics 得到Camera设备的详细数据,由 CameraCharacteristics类 存储
  • 可以通过Cameraid 启动某个设备 openCamera
CameraManager manager = (CameraManager)context.getSystemService(Context.CAMERA_SERVICE);

public String[] getCameraIdList()

public CameraCharacteristics getCameraCharacteristics(@NonNull String cameraId)

public void openCamera(@NonNull String cameraId,
            @NonNull final CameraDevice.StateCallback callback, @Nullable Handler handler)

2. CameraDevice

CameraDevice直接与系统摄像头相联系,相当一个抽象摄像头。

  • 通过CameraDevice.StateCallback监听摄像头的状态(主要包括onOpened、onClosed、onDisconnected、onError四种状态)
  • 创建 CaptureRequestSession 对象,来创建会话。
  • 创建 CaptureRequest 对象 ,来创建捕获请求。
// 创建 CaptureRequestSession 对象
// 因为是异步操作,通过 CameraDevice.StateCallback 的 onOpened 方法返回。
 public abstract void createCaptureSession(@NonNull List outputs,
            @NonNull CameraCaptureSession.StateCallback callback, @Nullable Handler handler)
            

public abstract CaptureRequest.Builder createCaptureRequest(@RequestTemplate int templateType)

当相机被成功开启的时候会通过 CameraStateCallback.onOpened() 方法回调一个 CameraDevice 实例给你,否则的话会通过 CameraStateCallback.onError() 方法回调一个 CameraDevice 实例和一个错误码给你。onOpened() 和 onError() 其实都意味着相机已经被开启了,唯一的区别是 onError() 表示开启过程中出了问题,你必须把传递给你的 CameraDevice 关闭,而不是继续使用它

3. CaptureRequestSession

这个类用于提交创建好的CaptureRequest,要初始化CaptureRequestSession,必须提供初始化好的Surface。

createCaptureSession 这个方法要传入surface参数。CaptureRequestSession 发送 CaptureRequest 可以使用以下api:

// 发送一次性拍照的指令
public abstract int capture(@NonNull CaptureRequest request,
    @Nullable CaptureCallback listener, @Nullable Handler handler)
    
// 发送重复预览的请求
public abstract int setRepeatingRequest(@NonNull CaptureRequest request,
            @Nullable CaptureCallback listener, @Nullable Handler handler)
            throws CameraAccessException;

CaptureRequestSession 里面有两个Callback:

  • 管理CameraCaptureSession.StateCallback状态回调,用于接收有关CameraCaptureSession状态的更新的回调对象,主要回调方法有两个,当CameraDevice 完成配置,对应的会话开始处理捕获请求时触发onConfigured(CameraCaptureSession session)方法,反之配置失败时候触发onConfigureFailed(CameraCaptureSession session)方法。
  • 管理CameraCaptureSession.CaptureCallback捕获回调,用于接收捕获请求状态的回调,当请求触发捕获已启动时;捕获完成时;在捕获图像时发生错误的情况下;都会触发该回调对应的方法
 capture(@NonNull CaptureRequest request,
    @Nullable CaptureCallback listener, @Nullable Handler handler)

capture 方法用于发送一次性拍照的指令,其中 request 参数定义了捕获打个图像的所有参数,每个请求对应返回一个CaptureResult,然后通过CaptureRequest.builder的addTarget(Surface)方法附着对应的Surface上显示,其中的Surface就是创建会话时必须传入的参数,完成Surface的注入之后,通过CaptureCallback返回状态。

4. CaptureRequest

CaptureRequest可以理解为一个数据包,我们从camera获取单张图像后,通过CaptureRequest对其设置和输出。这里应用了Builder模式,CaptureReques.Builder是从CameraDevice中的createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)方法来创建的。

然后,我们使用构建器来设置变其他属性,比如addTarget(Surface)来设置CaptureRequest的接收者,还可以设置对焦模式、曝光模式,处理流水线,控制算法和输出缓冲区等。
CameraRequest.Builder 同时也负责生成 CameraRequest 对象。

上面 CaptureRequestSession 的预览方法setRepeatingRequest 和拍照方法 capture都要传入一个 CaptureRequest 对象,来设置拍摄参数。

5. Surface

Surface 是一块用于填充图像数据的内存空间,例如你可以使用 SurfaceView 的 Surface 接收每一帧预览数据用于显示预览画面,也可以使用 ImageReader 的 Surface 接收 JPEG 或 YUV 数据。每一个 Surface 都可以有自己的尺寸和数据格式,你可以从 CameraCharacteristics 获取某一个数据格式支持的尺寸列表。


6. 使用Camera2

  1. 选择合适的Camera
for (String cameraId : cameraManager.getCameraIdList()) {
    CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
    // 是否支持闪光灯
    Boolean available = characteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
    mFlashSupported = available == null ? false : available;
    // 是否是前置摄像头
    Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
	StreamConfigurationMap configurationMap = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
	if (configurationMap == null) continue;
	//获取图片输出的尺寸
	configurationMap.getOutputSizes(ImageFormat.JPEG);
	//获取预览画面输出的尺寸,因为我使用TextureView作为预览
	configurationMap.getOutputSizes(SurfaceTexture.class)
}

我们可以通过 CameraCharacteristics 的属性来选取符合我们需要的Camera,得到其Id

  1. 打开相机
CameraManager manager = (CameraManager) mActivity.getSystemService(Context.CAMERA_SERVICE);
try {
    manager.openCamera(mCameraId, mStateCallback, mMainHandler);
} catch (CameraAccessException e) {
    e.printStackTrace();
}
  • 第一个参数是我们之前获取的CameraId
  • 第二个参数是当CameraDevice被打开时的回调StateCallback,在这个回调里我们可以获取到CameraDevice对象
  • 第三个参数是一个Handler,决定了回调函数触发的线程,若为null,则选择当前线程。

在StateCallback中,我们要实现三个方法,分别为CameraDevice被打开时触发的方法,失去连接时触发的方法,发生异常时触发的方法。在第一个方法中我们可以成功获取到CameraDevice对象,从而进行接下来的相关操作。

private CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
        @Override
        public void onOpened(@NonNull CameraDevice camera) {
            //打开成功,可以获取CameraDevice对象
        }

        @Override
        public void onDisconnected(@NonNull CameraDevice camera) {
           //断开连接
        }

        @Override
        public void onError(@NonNull CameraDevice camera, final int error) {
            //发生异常
        }
    };
  1. 发出预览请求

我们需要创建一个CameraCaptureSession的会话对象,通过CameraCaptureSession对象发送预览请求。
createCaptureSession 需要三个参数,第一个是相机预览数据输出的Surface的集合,第二个是回调,在这个回调中我们可以获取CameraCaptureSession对象,第三个参数是Handler,回调触发的线程。

 mCameraDevice.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface()),
                   mCallback, mCameraHandler)

StateCallback 需要实现onConfigured方法和onConfigFailed方法,会话开始处理捕获请求时触发onConfigured(CameraCaptureSession session)方法,反之配置失败时候触发onConfigureFailed(CameraCaptureSession session)方法。

 mCallback = new CameraCaptureSession.StateCallback() {
                        @Override
                        public void onConfigured(@NonNull CameraCaptureSession session) {
                            mCaptureSession = session;
                            //发送预览请求
                            sendRepeatPreviewRequest();

                        }

                        @Override
                        public void onConfigureFailed(@NonNull CameraCaptureSession session) {

                        }
                    }

sendRepeatPreviewRequest 函数通过builder模式给CaptureRequest设置好请求参数,再调用 CameraCaptureSession 的 setRepeatingRequest 方法预览。

private boolean sendRepeatPreviewRequest() {
        try {
            CaptureRequest.Builder builder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            builder.addTarget(mPreviewSurface);
            builder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
            builder.setTag(RequestTag.Preview);
            addBaselineCaptureKeysToRequest(builder);

            mCaptureSession.setRepeatingRequest(builder.build(),
                    mFocusStateListener,
                    mCameraHandler);
            return true;
        } catch (CameraAccessException e) {
            e.printStackTrace();
            return false;
        }
    }
  1. 发送拍摄请求

同样地获取 CameraCaptureSession,在 onConfigured 方法中调用 sendShootRequest 方法。

private boolean sendRepeatPreviewRequest() {
	CaptureRequest.Builder builder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE)
	builder.setTag(RequestTag.Capture);
    addBaselineCaptureKeysToRequest(builder);
    builder.set(CaptureRequest.JPEG_ORIENTATION,
    CameraUtil.getJPEGOrientation(parameters.getOrientation(), mCameraCharacteristics));
    builder.addTarget(mPreviewSurface);
    builder.addTarget(mImageReader.getSurface());
    mCaptureSession.capture(builder.build(),
    mFocusStateListener,
    mCameraHandler);
}

你可能感兴趣的:(Camera2,解析,Camera)