• Android Camera2 SessionConfiguration介绍和使用


    一、介绍

    最近在相机开发中发现 createCaptureSession(List, CameraCaptureSession.StateCallback, Handler) 已经被标记为过时(@Deprecated)的函数了,取而代之的是 createCaptureSession(SessionConfiguration) 函数。

    缘由

    随着 Camera 功能越来越复杂,创建 Session 的方法也随之越来越多,比如:

    createCaptureSession(List<Surface>, CameraCaptureSession.StateCallback, Handler)
    
    createCaptureSessionByOutputConfigurations(List<OutputConfiguration>, CameraCaptureSession.StateCallback, Handler)
    
    createReprocessableCaptureSession(InputConfiguration, List<Surface>, CameraCaptureSession.StateCallback, Handler)
    
    createReprocessableCaptureSessionByConfigurations(InputConfiguration, List<OutputConfiguration>, CameraCaptureSession.StateCallback, Handler)
    
    createConstrainedHighSpeedCaptureSession(List<Surface>, CameraCaptureSession.StateCallback, Handler)
    
    createCustomCaptureSession(InputConfiguration, List<OutputConfiguration>, int, CameraCaptureSession.StateCallback, Handler)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    于是便推出了 createCaptureSession(SessionConfiguration) 来统一。SessionConfiguration 是 Android API 28 新增的类,用于聚合捕获会话初始化的所有支持的参数。

    二、常用方法

    1. 构造函数

    只有一个构造函数如下:

    /**
     * @param sessionType 会话类型,目前有SESSION_REGULAR和SESSION_HIGH_SPEED两个值,
              后者为高速帧率范围,通常用于拍摄高速动作或慢动作视频
     * @param outputs 该会话输出的集合,不能为空
     * @param executor 用于调用回调的执行器,不建议使用主线程
     * @param cb 创建状态的回调函数,不能为空
     */
    public SessionConfiguration (int sessionType, 
                    List<OutputConfiguration> outputs, 
                    Executor executor, 
                    CameraCaptureSession.StateCallback cb)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    2. 设置参数

    用于设置Session创建时的使用的一些初始值。
    因为这些值可以通过 CaptureRequest.Builder 在创建前就设置好然后传递给 Session 使用,可以用来根据不同的值选择相机Hal层使用的pipeline。

    /**
     * @param params CaptureRequest.Builder的输出目标和不在
              CameraCharacteristics#getAvailableSessionKeys 中的参数值将会忽略,
              建议使用初始捕获请求相同的模板类型构建会话参数,以便会话和初始请求的参数尽可能匹配。
     */
    public void setSessionParameters (CaptureRequest params)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3. 判断 SessionConfiguration 是否支持

    这个是 CemeraDevice 类的函数,一般也会使用到。

    /**
     * @param sessionConfig 目标SessionConfiguration
     */
    public boolean isSessionConfigurationSupported (SessionConfiguration sessionConfig)
    
    • 1
    • 2
    • 3
    • 4

    其余一些方法很少用,感兴趣的可以参考官网文档。

    链接:https://developer.android.com/reference/android/hardware/camera2/params/SessionConfiguration

    三、简单示例

    一个简单的使用流程,熟悉一下创建流程。

    // 创建一个 CaptureRequest.Builder 用于配置捕获请求
    CaptureRequest.Builder previewRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
    previewRequestBuilder.addTarget(surface); // surface 是用于显示预览的 Surface 对象
    ArrayList<OutputConfiguration> outputConfigurations = new ArrayList<>();
    for (Surface surface : allSessionOutputs) { // allSessionOutputs是所有的 Surface 集合,包含预览+拍照等
        if (surface != null) {
            OutputConfiguration configuration = new OutputConfiguration(surface);
            outputConfigurations.add(configuration);
        }
    }
    // 创建和设置 SessionConfiguration
    CameraCaptureSession.StateCallback sessionCreateCallback = new CameraCaptureSession.StateCallback() {
        @Override
        public void onConfigured(@NonNull CameraCaptureSession session) {
            // 会话创建成功,您可以开始处理预览或拍照操作
        }
        @Override
        public void onConfigureFailed(@NonNull CameraCaptureSession session) {
            // 会话创建失败,处理错误情况
        }
    };
    SessionConfiguration sessionConfiguration = new SessionConfiguration(
            SessionConfiguration.SESSION_REGULAR, // SESSION_REGULAR或SESSION_HIGH_SPEED
            outputConfigurations,                 // 上面创建的ArrayList
            Context.getMainExecutor(),            // 回调的执行器,注意这里是不建议使用主线程的
            sessionCreateCallback);               // 回调函数
    sessionConfiguration.setSessionParameters(previewRequestBuilder.build());
    // 判断是否支持
    try {
        boolean supported = cameraDevice.isSessionConfigurationSupported(sessionConfig);
        if (!supported) {
            // 处理不支持的情况
        }
    } catch (CameraAccessException | IllegalArgumentException | NullPointerException e) {
        e.printStackTrace();
        // 处理异常的情况
    }
    // 创建捕捉会话
    cameraDevice.createCaptureSession(sessionConfiguration);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    四、自定义的回调执行器

    因为不建议在主线程中执行回调,所以通常我们会创建一个相机的执行器。

    1. 创建相机后台线程

    这里的 mCameraHandler 同样可以用于 openCamera() 等函数使用。

    private Handler mCameraHandler;
    private HandlerThread mCameraThread;
    
    // 在打开相机的时候启动线程
    private void startBackgroundThread() {
        if (mCameraThread == null || mCameraHandler == null) {
            mCameraThread = new HandlerThread("CameraBackground");
            mCameraThread.start();
            mCameraHandler = new Handler(mCameraThread.getLooper());
        }
    }
    
    // 在关闭相机的时候停止线程
    private void stopBackgroundThread() {
        if (mCameraThread != null) {
            mCameraThread.quitSafely();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    2. HandlerExecutor类

    单独声明一个类或者内部类都可以。

    public class HandlerExecutor implements Executor {
        private final Handler ihandler;
    
        public HandlerExecutor(Handler handler) {
            ihandler = handler;
        }
    
        @Override
        public void execute(Runnable runCmd) {
            ihandler.post(runCmd);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    3. 使用

    只需要替换掉之前例子中的 Context.getMainExecutor() 即可。

    SessionConfiguration sessionConfiguration = new SessionConfiguration(
            SessionConfiguration.SESSION_REGULAR, // SESSION_REGULAR或SESSION_HIGH_SPEED
            outputConfigurations,                 // 上面创建的ArrayList
            new HandlerExecutor(mCameraHandler),  // 回调的执行器,注意这里是不建议使用主线程的
            sessionCreateCallback);               // 回调函数
    
    • 1
    • 2
    • 3
    • 4
    • 5
  • 相关阅读:
    mysql笔记
    水库大坝安全评价导则:大坝运行管理评价
    二级缓存j2cache和SpringBoot整合
    Java-Web-Servlet入门2.0
    FastAPI学习-26 并发 async / await
    Nginx的使用
    QT、ffmpeg视频监控分屏
    python命令找不到 pip 命令找不到解决方案
    coding持续集成
    R语言使用MASS包的polr函数构建有序多分类logistic回归模型、使用summary函数获取模型汇总统计信息
  • 原文地址:https://blog.csdn.net/afei__/article/details/133653865