使用Samsung S5的Camera2 API AutoFocus

Ale*_* Fu 10 android android-camera

我在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();
}
Run Code Online (Sandbox Code Playgroud)

发送请求后,请求的结果始终是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......

镜头将保持静止,直到AF模式(android.control.afMode)更改或新的AF触发器发送到相机设备(android.control.afTrigger).

我想知道这种差异是否是因为硬件级别的问题LEGACY,我应该回到使用已弃用的Camera API,但这对于像自动对焦这样的流行功能来说似乎很疯狂.

是否有任何建议如何处理报告的设备LEGACY

Asa*_*ssi 14

我分支形式谷歌的Camera2Basic示例并将其更改为使用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;
}
Run Code Online (Sandbox Code Playgroud)

然后,添加到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;
        }
Run Code Online (Sandbox Code Playgroud)

并替换所有出现的:

mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
                                            CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
Run Code Online (Sandbox Code Playgroud)

附:

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);
Run Code Online (Sandbox Code Playgroud)


小智 -3

自动对焦的三星S5回归INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY,这意味着它不支持Camera2api。

我有以下过滤器用于在我的应用程序中使用相机。

if (Build.VERSION.SDK_INT >= 21 &amp;&amp; isDeviceCompatibleOfCamera2()) {
 // Use camera2
} else {
 // Use old camera
}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
 public boolean isDeviceCompatibleOfCamera2() {
 try {
    CameraManager manager = (CameraManager) getActivity().getSystemService(Context.CAMERA_SERVICE);
    String backCameraId = manager.getCameraIdList()[0];
    CameraCharacteristics backCameraInfo = manager.getCameraCharacteristics(backCameraId);

    int level = backCameraInfo.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
    return level == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL;

    } catch (CameraAccessException e) {
     ETLog.d(TAG, &quot;Device not compatible of camera2 api&quot; + e);
    }
    return false;
 }
Run Code Online (Sandbox Code Playgroud)