android – 使用Samsung S5的Camera2 API AutoFocus

我在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);

相关文章

这篇“android轻量级无侵入式管理数据库自动升级组件怎么实现...
今天小编给大家分享一下Android实现自定义圆形进度条的常用方...
这篇文章主要讲解了“Android如何解决字符对齐问题”,文中的...
这篇文章主要介绍“Android岛屿数量算法怎么使用”的相关知识...
本篇内容主要讲解“Android如何开发MQTT协议的模型及通信”,...
本文小编为大家详细介绍“Android数据压缩的方法是什么”,内...