我在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时……
The lens will remain stationary until the AF mode (android.control.afMode) is changed or a new AF trigger is sent to the camera device (android.control.afTrigger).
我想知道这种差异是否是因为硬件级别是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,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,"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);