Android Camera2 之 CameraDevice 详解

翟淇
2023-12-01

一、简介

CameraDevice 是一个连接的相机设备代表,你可以把它看作为相机设备在 java 代码中的表现。类比于旧 API 中的 Camera 类。

官方文档链接:https://developer.android.google.cn/reference/android/hardware/camera2/CameraDevice

二、获取 CameraDevice 实例

通过 CameraManageropenCamera() 方法打开相机,在 CameraDevice.StateCallbackonOpened(CameraDevice camera) 方法中可获得 CameraDevice 的实例。

示例:

    private int mCameraId = CameraCharacteristics.LENS_FACING_FRONT;
    private CameraManager mCameraManager; // 相机管理者
    private CameraDevice mCameraDevice; // 相机对象
    private Handler mBackgroundHandler;
    private HandlerThread mBackgroundThread;

    private CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
        @Override
        public void onOpened(@NonNull CameraDevice camera) {
            mCameraDevice = camera; // 获取到可用的 CameraDevice 实例
            // 当相机成功打开时回调该方法,接下来可以执行创建预览的操作
        }

        @Override
        public void onDisconnected(@NonNull CameraDevice camera) {
            // 当相机断开连接时回调该方法,应该在此执行释放相机的操作
        }

        @Override
        public void onError(@NonNull CameraDevice camera, int error) {
            // 当相机打开失败时,应该在此执行释放相机的操作
        }

        @Override
        public void onClosed(@NonNull CameraDevice camera) {
            // 当相机关闭时回调该方法,这个方法可以不用实现
        }
    };

    public void openCamera() {
        try {
            // 前处理
            mCameraManager.openCamera(Integer.toString(mCameraId), mStateCallback, mBackgroundHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

三、内部类

只有一个 CameraDevice.StateCallback 的内部类,当相机状态发生变化时,会调用该类相应的回调方法。

相应的回调方法介绍在上面的示例中已经说明了,下面介绍一下 onError 回调方法中相应的错误码把:

错误码描述
CameraDevice.StateCallback.ERROR_CAMERA_IN_USE当前相机设备已经在一个更高优先级的地方打开了
CameraDevice.StateCallback.ERROR_MAX_CAMERAS_IN_USE已打开相机数量到上限了,无法再打开新的相机了
CameraDevice.StateCallback.ERROR_CAMERA_DISABLED由于相关设备策略该相机设备无法打开,详细可见 DevicePolicyManagersetCameraDisabled(ComponentName, boolean) 方法
CameraDevice.StateCallback.ERROR_CAMERA_DEVICE相机设备发生了一个致命错误
CameraDevice.StateCallback.ERROR_CAMERA_SERVICE相机服务发生了一个致命错误

四、常用方法

1. void close()

关闭对应的相机设备。

2. CaptureRequest.Builder createCaptureRequest(int templateType)

使用指定模板创建一个 CaptureRequest.Builder 用于新的捕获请求构建。

templateType描述适用性
TEMPLATE_PREVIEW用于创建一个相机预览请求。相机会优先保证高帧率而不是高画质所有相机设备
TEMPLATE_STILL_CAPTURE用于创建一个拍照请求。相机会优先保证高画质而不是高帧率所有相机设备
TEMPLATE_RECORD用于创建一个录像请求。相机会使用标准帧率,并设置录像级别的画质所有相机设备
TEMPLATE_VIDEO_SNAPSHOT用于创建一个录像时拍照的请求。相机会尽可能的保证照片质量的同时不破坏正在录制的视频质量硬件支持级别高于 LEGACY 的相机设备
TEMPLATE_ZERO_SHUTTER_LAG用于创建一个零延迟拍照的请求。相机会尽可能的保证照片质量的同时不损失预览图像的帧率,3A(自动曝光、自动聚焦、自动白平衡)都为 auto 模式支持 PRIVATE_REPROCESSINGYUV_REPROCESSING 的相机设备
TEMPLATE_MANUAL用于创建一个手动控制相机参数的请求。相机所有自动控制将被禁用,后期处理参数为预览质量,手动控制参数被设置为合适的默认值,需要用户自己根据需求来调整各参数支持 MANUAL_SENSOR 的相机设备

3. void createCaptureSession(List outputs, CameraCaptureSession.StateCallback callback, Handler handler)

使用一个指定的 Surface 输出列表创建一个相机捕捉会话。

参数说明:

  • outputs : 输出的 Surface 集合,每个 CaptureRequest 的输出 Surface 都应该是 outputs 的一个子元素。
  • callback : 创建会话的回调。成功时将调用 CameraCaptureSession.StateCallback 的 onConfigured(CameraCaptureSession session) 方法。
  • handler : 指定回调执行的线程,传 null 时默认使用当前线程的 Looper。

4. String getId()

获得当前相机设备的 id。

5. 示例

针对第二条和第三条,简单的使用如下:

try {
    // templateType 使用 TEMPLATE_PREVIEW,即创建一个相机预览请求
    mCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
    mCaptureRequestBuilder.addTarget(mPreviewSurface); // 设置预览输出的 Surface
    // mPreviewSurface 是用于预览输出的 Surface
    // mImageReader.getSurface() 是用于拍照输出的 Surface
    mCameraDevice.createCaptureSession(Arrays.asList(mPreviewSurface, mImageReader.getSurface()),
            new CameraCaptureSession.StateCallback() {

        @Override
        public void onConfigured(@NonNull CameraCaptureSession session) {
            if (mCameraDevice == null) {
                return;
            }
            mCaptureSession = session;
            try {
                // 设置连续自动对焦
                mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
                // 设置关闭闪光灯
                mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.FLASH_MODE_OFF);
                // 生成一个预览的请求
                mPreviewRequest = mPreviewRequestBuilder.build();
                // 开始预览,即设置反复请求
                mCaptureSession.setRepeatingRequest(mPreviewRequest, null, mBackgroundHandler);
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onConfigureFailed(@NonNull CameraCaptureSession session) {
            Log.e(TAG, "ConfigureFailed.");
        }
    }, mBackgroundHandler);
} catch (CameraAccessException e) {
    e.printStackTrace();
}

五、硬件支持等级

上面介绍适用性时提到了硬件支持级别。在 Camera2 中,相机设备支持的硬件等级有

LEVEL_3 > FULL > LIMIT > LEGACY

对于大多数的手机而言,都会支持到 FULLLIMIT。当支持到 FULL 等级的相机设备,将拥有比旧 API 强大的新特性,如 30fps 全高清连拍,帧之间的手动设置,RAW 格式的图片拍摄,快门零延迟以及视频速拍等,否则和旧 API 功能差别不大。

获取方式:

通过 CameraCharacteristics 类获取相机设备的特性,包括硬件等级的支持等级.

CameraCharacteristics characteristics = mCameraManager.getCameraCharacteristics(mCameraId);
int hardwareLevel = characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
 类似资料: