Android Camera2 API 顺利通过ISO和EXP

Android Camera2 API traversing through ISO and EXP smoothly

我有一个 ISO 和 EXP 的搜索栏。当我移动任何搜索栏时,相机显示会随之改变。一切正常,但它会抖动很多,如果我快速移动搜索栏,有时会使应用程序崩溃。防止这种情况发生的正确方法是什么?

    @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_calibration);
    SeekBar seekbarISO = findViewById(R.id.seekbarISO);
                seekbarISO.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
                    @Override
                    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                        newIsoSetting(progress);
                        restartCameraSetup();
                    }
        
                    @Override
                    public void onStartTrackingTouch(SeekBar seekBar) {
        
                    }
        
                    @Override
                    public void onStopTrackingTouch(SeekBar seekBar) {
        
                    }
                });
        }

这就是我处理相机设置的方式

private void createCaptureSession() {
        try {
            cameraDevice.createCaptureSession(Arrays.asList(previewSurface, imageReader.getSurface()), onCreateSessionStateCallback, handler);
        } catch (CameraAccessException | NullPointerException e) {
            Log.e(TAG, Objects.requireNonNull(e.getLocalizedMessage()));
            restartCameraSetup();
        }
    }

public void restartCameraSetup() {
        try {
            startBackgroundThread();
            if (textureView.isAvailable()) {
                connectCameraSeq(textureView.getSurfaceTexture());
            } else {
                iniTextureViewComp();
            }
        } catch (NullPointerException npe) {
            Log.i(TAG, Objects.requireNonNull(npe.getLocalizedMessage()));
        }
    }

private final CameraCaptureSession.StateCallback onCreateSessionStateCallback = new CameraCaptureSession.StateCallback() {
        @Override
        public void onConfigured(@NonNull CameraCaptureSession session) {
            try {
                CaptureRequest.Builder captureRequestBuilder;
                captureRequestBuilder = getFramingRequestBuilder();
                captureRequestBuilder.addTarget(previewSurface);
                captureRequestBuilder.addTarget(imageReader.getSurface());
                session.setRepeatingRequest(captureRequestBuilder.build(), null, handler);
            } catch (CameraAccessException | NullPointerException | IllegalStateException e) {
                Log.i(TAG, Objects.requireNonNull(e.getLocalizedMessage()));
            }
        }

private CaptureRequest.Builder getFramingRequestBuilder() throws CameraAccessException {
        CameraSetting cameraSetting = SharedPrefUtil.getCameraSetting(this);

        CaptureRequest.Builder framingRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_MANUAL);
        framingRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.INFO_SUPPORTED_HARDWARE_LEVEL_FULL);
        framingRequestBuilder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_OFF);

        if (cameraSetting.exp <= 0 && cameraSetting.iso <= 0) {
            cameraSetting = getDefaultCameraSetting();
            SharedPrefUtil.storeCameraSetting(this, cameraSetting);
        }

        framingRequestBuilder.set(CaptureRequest.SENSOR_SENSITIVITY, cameraSetting.iso);
        framingRequestBuilder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, cameraSetting.exp); // NANO SECONDS.

        return framingRequestBuilder;
    }

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

每次要更新 ISO 或曝光设置时,您都需要重新启动整个相机会话。这非常慢,因为刷新相机管道并重新启动它需要几百毫秒。

没有必要这样做,只需使用您的新参数在同一会话中设置一个新的重复请求。

也就是说,每次移动滑块时,运行 您当前在 onConfigured 中的代码,但不要执行任何其他操作。

此外,行:

        framingRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.INFO_SUPPORTED_HARDWARE_LEVEL_FULL);

不执行任何操作,因为下一行将 CONTROL_MODE 更改为 OFF;此外,INFO_SUPPORTED_HARDWARE_LEVEL_FULL 无论如何都不是 CONTROL_MODE 的有效值。