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 的有效值。
我有一个 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 的有效值。