I have a seek bar for ISO and EXP. As I move any of the seek bar, the camera display change with it. Everything works fine but it jitters a lot and sometimes crashes the application if I move the seek bar very quickly. What is the correct way to prevent this from happening?
@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) {
}
});
}
This is how I handle my camera setup
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) {
}
};
You're restarting the entire camera session every time you want to update the ISO or exposure setting. That's very slow, since it takes several hundred milliseconds to flush the camera pipeline and restart it.
There's no need to do that, just set a new repeating request on the same session with your new parameters.
That is, just run the code you currently have inside onConfigured
each time you move the slider, but don't do anything else.
Also, the line:
framingRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.INFO_SUPPORTED_HARDWARE_LEVEL_FULL);
doesn't do anything since the next line changes CONTROL_MODE to OFF; in addition, INFO_SUPPORTED_HARDWARE_LEVEL_FULL is not a valid value for CONTROL_MODE anyway.