我正在使用Samsung S5上的新Camera2 API。该设备报告的支持的硬件级别是LEGACY
,这很好。
但是,我似乎无法自动专注于此设备。触发自动对焦的请求如下所示:
previewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO);
previewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_START);
state = STATE_PREVIEW;
try {
captureSession.setRepeatingRequest(previewRequestBuilder.build(), captureCallback, backgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
发送请求后,请求的结果始终为
CONTROL_AF_STATE_ACTIVE_SCAN
,有时为CONTROL_AF_STATE_NOT_FOCUSED_LOCKED
。奇怪的是,当状态为
CONTROL_AF_STATE_NOT_FOCUSED_LOCKED
时,自动对焦会暂时回到CONTROL_AF_STATE_ACTIVE_SCAN
状态,然后再返回到CONTROL_AF_STATE_NOT_FOCUSED_LOCKED
,从而导致无限的对焦循环。根据文档,当状态为CONTROL_AF_STATE_NOT_FOCUSED_LOCKED
时...我想知道这种差异是否是因为硬件级别为
LEGACY
,并且我应该重新使用不赞成使用的Camera API,但是对于诸如自动对焦之类的普遍功能而言,这似乎太疯狂了。有什么建议如何处理报告
LEGACY
的设备? 最佳答案
我分支了google's Camera2Basic example表单,并将其更改为使用CaptureRequest.CONTROL_AF_MODE_AUTO
而不是CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE
您可以从git中提取项目并进行测试-https://github.com/pinhassi/android-Camera2Basic
或者只是将其添加到Camera2BasicFragment
:
private static final long LOCK_FOCUS_DELAY_ON_FOCUSED = 5000;
private static final long LOCK_FOCUS_DELAY_ON_UNFOCUSED = 1000;
private Integer mLastAfState = null;
private Handler mUiHandler = new Handler(); // UI handler
private Runnable mLockAutoFocusRunnable = new Runnable() {
@Override
public void run() {
lockAutoFocus();
}
};
public void lockAutoFocus() {
try {
// This is how to tell the camera to lock focus.
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);
CaptureRequest captureRequest = mPreviewRequestBuilder.build();
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, null); // prevent CONTROL_AF_TRIGGER_START from calling over and over again
mCaptureSession.capture(captureRequest, mCaptureCallback, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
/**
*
* @return
*/
private float getMinimumFocusDistance() {
if (mCameraId == null)
return 0;
Float minimumLens = null;
try {
CameraManager manager = (CameraManager) getActivity().getSystemService(Context.CAMERA_SERVICE);
CameraCharacteristics c = manager.getCameraCharacteristics(mCameraId);
minimumLens = c.get(CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE);
} catch (Exception e) {
Log.e(TAG, "isHardwareLevelSupported Error", e);
}
if (minimumLens != null)
return minimumLens;
return 0;
}
/**
*
* @return
*/
private boolean isAutoFocusSupported() {
return isHardwareLevelSupported(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY) || getMinimumFocusDistance() > 0;
}
// Returns true if the device supports the required hardware level, or better.
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private boolean isHardwareLevelSupported(int requiredLevel) {
boolean res = false;
if (mCameraId == null)
return res;
try {
CameraManager manager = (CameraManager) getActivity().getSystemService(Context.CAMERA_SERVICE);
CameraCharacteristics cameraCharacteristics = manager.getCameraCharacteristics(mCameraId);
int deviceLevel = cameraCharacteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
switch (deviceLevel) {
case CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_3:
Log.d(TAG, "Camera support level: INFO_SUPPORTED_HARDWARE_LEVEL_3");
break;
case CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL:
Log.d(TAG, "Camera support level: INFO_SUPPORTED_HARDWARE_LEVEL_FULL");
break;
case CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY:
Log.d(TAG, "Camera support level: INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY");
break;
case CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED:
Log.d(TAG, "Camera support level: INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED");
break;
default:
Log.d(TAG, "Unknown INFO_SUPPORTED_HARDWARE_LEVEL: " + deviceLevel);
break;
}
if (deviceLevel == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY) {
res = requiredLevel == deviceLevel;
} else {
// deviceLevel is not LEGACY, can use numerical sort
res = requiredLevel <= deviceLevel;
}
} catch (Exception e) {
Log.e(TAG, "isHardwareLevelSupported Error", e);
}
return res;
}
然后,添加到
STATE_PREVIEW
块: case STATE_PREVIEW: {
// We have nothing to do when the camera preview is working normally.
// TODO: handle auto focus
Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);
if (afState != null && !afState.equals(mLastAfState)) {
switch (afState) {
case CaptureResult.CONTROL_AF_STATE_INACTIVE:
Log.d(TAG, "CaptureResult.CONTROL_AF_STATE_INACTIVE");
lockAutoFocus();
break;
case CaptureResult.CONTROL_AF_STATE_ACTIVE_SCAN:
Log.d(TAG, "CaptureResult.CONTROL_AF_STATE_ACTIVE_SCAN");
break;
case CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED:
Log.d(TAG, "CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED");
mUiHandler.removeCallbacks(mLockAutoFocusRunnable);
mUiHandler.postDelayed(mLockAutoFocusRunnable, LOCK_FOCUS_DELAY_ON_FOCUSED);
break;
case CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED:
mUiHandler.removeCallbacks(mLockAutoFocusRunnable);
mUiHandler.postDelayed(mLockAutoFocusRunnable, LOCK_FOCUS_DELAY_ON_UNFOCUSED);
Log.d(TAG, "CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED");
break;
case CaptureResult.CONTROL_AF_STATE_PASSIVE_UNFOCUSED:
mUiHandler.removeCallbacks(mLockAutoFocusRunnable);
//mUiHandler.postDelayed(mLockAutoFocusRunnable, LOCK_FOCUS_DELAY_ON_UNFOCUSED);
Log.d(TAG, "CaptureResult.CONTROL_AF_STATE_PASSIVE_UNFOCUSED");
break;
case CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN:
Log.d(TAG, "CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN");
break;
case CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED:
mUiHandler.removeCallbacks(mLockAutoFocusRunnable);
//mUiHandler.postDelayed(mLockAutoFocusRunnable, LOCK_FOCUS_DELAY_ON_FOCUSED);
Log.d(TAG, "CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED");
break;
}
}
mLastAfState = afState;
break;
}
并替换所有出现的情况:
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
和:
if (isAutoFocusSupported())
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_AUTO);
else
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);