Camera 2 api 中自动对焦和手动对焦焦点锁定错误

问题描述 投票:0回答:1

我有一个相机应用程序,其中我为用户提供 2 个选项手动对焦和自动对焦,然后连续捕捉 6 张图像 但我的问题是,当我调用自动对焦然后捕获图像时,它会卡住,但如果我开始捕获而不调用自动对焦,它工作正常

state: STATE_WAITING_LOCK
17:55:14.621 com....extureView  V  Current afState: 4
17:55:14.626 com....extureView  V  state: STATE_WAITING_LOCK
17:55:14.626 com....extureView  V  Current afState: 4
17:55:14.651 com....extureView  V  state: STATE_WAITING_LOCK
17:55:14.651 com....extureView  V  Current afState: 4
17:55:14.674 com....extureView  V  state: STATE_WAITING_LOCK
17:55:14.674 com....extureView  V  Current afState: 4
17:55:14.688 com....extureView  V  state: STATE_WAITING_LOCK
17:55:14.688 com....extureView  V  Current afState: 4

自动对焦

 protected CameraCaptureSession.CaptureCallback mCaptureCallback = new CameraCaptureSession.CaptureCallback() {
        @SuppressWarnings("ConstantConditions")
        private void process(CaptureResult result) {
            switch (mState) {
                case STATE_STREAMING: {
                    break;
                }
                case STATE_WAITING_LOCK: {
                    Log.v(TAG, "state: STATE_WAITING_LOCK");
                    final int afState = result.get(CaptureResult.CONTROL_AF_STATE);
                    Log.v(TAG, "Current afState: " + afState); // Add this line
                    if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState ||
                            CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState) {
                        // Check if focusLockLatch is null before calling countDown()
                        if (focusLockLatch == null) {
                            focusLockLatch = new CountDownLatch(1);
                        }
                        focusLockLatch.countDown();
                    }
                    break;
                }
                case STATE_WAITING_PRECAPTURE: {
                    Log.v(TAG, "state: STATE_WAITING_PRECAPTURE");
                    mState = STATE_WAITING_NON_PRECAPTURE;
                    break;
                }
            }
        }

        @Override
        public void onCaptureStarted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, long timestamp, long frameNumber) {
            super.onCaptureStarted(session, request, timestamp, frameNumber);
            //Log.v( TAG, "onCaptureStarted( session, request, timestamp, frameNumber )" );
        }

        @Override
        public void onCaptureProgressed(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull CaptureResult partialResult) {
            super.onCaptureProgressed(session, request, partialResult);
            process(partialResult);
        }

        @Override
        public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
            super.onCaptureCompleted(session, request, result);
            process(result);
        }

        @Override
        public void onCaptureFailed(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull CaptureFailure failure) {
            super.onCaptureFailed(session, request, failure);
            Log.v(TAG, "onCaptureFailed( session, request, failure )");
        }
    };


public void autoFocus() {
        try {
            focusSeekBar.setCurrentValue(0);
            setFocusMode(Mode.AUTO);
            mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CameraMetadata.CONTROL_AF_MODE_AUTO);
            // Trigger an autofocus scan
            mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);
            Log.v(TAG, "autoFocus()");
            mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(), mCaptureCallback, null);

            // set seekbar  to focus distance
        } catch (CameraAccessException e) {
            OnCameraErrorListener.handle(mCameraErrorCallback, e);
        }
    }


 protected void lockFocus() {
        Log.v(TAG, "lockFocus()");

        if (mCaptureSession == null) {
            return;
        }
        try {

            if (focusMode == Mode.AUTO) {
                // This is how to tell the camera to lock focus.
                mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);
                mState = STATE_WAITING_LOCK;
                mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback, mBackgroundHandler);

                // check fo focus state
                // if focus is locked call start capture
                // if focus is not locked call unlock focus

                if (focusLockLatch.await(500, TimeUnit.MILLISECONDS)) {
                    startCapture();
                } else {
                    unlockFocus();
                }
            } else {
                startCapture();
            }
        } catch (CameraAccessException e) {
            OnCameraErrorListener.handle(mCameraErrorCallback, e);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    protected void unlockFocus() {
        Log.v(TAG, "unlockFocus()");
        try {
            // Reset the auto-focus trigger
            mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
            mCaptureSession.capture(mPreviewRequestBuilder.build(), null, null);
            // After this, the camera will go back to the normal state of preview.
            mState = STATE_STREAMING;
            //resume Zoom effect after taking a picture
            mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
            if (mZoom != null) {
                mPreviewRequestBuilder.set(CaptureRequest.SCALER_CROP_REGION, mZoom);
            }
            mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(), mCaptureCallback, mBackgroundHandler);
        } catch (CameraAccessException e) {
            OnCameraErrorListener.handle(mCameraErrorCallback, e);
        }
    }


    protected void unlockFocus() {
        Log.v(TAG, "unlockFocus()");
        try {
            // Reset the auto-focus trigger
            mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
            mCaptureSession.capture(mPreviewRequestBuilder.build(), null, null);
            // After this, the camera will go back to the normal state of preview.
            mState = STATE_STREAMING;
            //resume Zoom effect after taking a picture
            mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
            if (mZoom != null) {
                mPreviewRequestBuilder.set(CaptureRequest.SCALER_CROP_REGION, mZoom);
            }
            mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(), mCaptureCallback, mBackgroundHandler);
        } catch (CameraAccessException e) {
            OnCameraErrorListener.handle(mCameraErrorCallback, e);
        }
    }


自动对焦

 protected CameraCaptureSession.CaptureCallback mCaptureCallback = new CameraCaptureSession.CaptureCallback() {
        @SuppressWarnings("ConstantConditions")
        private void process(CaptureResult result) {
            switch (mState) {
                case STATE_STREAMING: {
                    break;
                }
                case STATE_WAITING_LOCK: {
                    Log.v(TAG, "state: STATE_WAITING_LOCK");
                    final int afState = result.get(CaptureResult.CONTROL_AF_STATE);
                    Log.v(TAG, "Current afState: " + afState); // Add this line
                    if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState ||
                            CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState) {
                        // Check if focusLockLatch is null before calling countDown()
                        if (focusLockLatch == null) {
                            focusLockLatch = new CountDownLatch(1);
                        }
                        focusLockLatch.countDown();
                    }
                    break;
                }
                case STATE_WAITING_PRECAPTURE: {
                    Log.v(TAG, "state: STATE_WAITING_PRECAPTURE");
                    mState = STATE_WAITING_NON_PRECAPTURE;
                    break;
                }
            }
        }

        @Override
        public void onCaptureStarted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, long timestamp, long frameNumber) {
            super.onCaptureStarted(session, request, timestamp, frameNumber);
            //Log.v( TAG, "onCaptureStarted( session, request, timestamp, frameNumber )" );
        }

        @Override
        public void onCaptureProgressed(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull CaptureResult partialResult) {
            super.onCaptureProgressed(session, request, partialResult);
            process(partialResult);
        }

        @Override
        public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
            super.onCaptureCompleted(session, request, result);
            process(result);
        }

        @Override
        public void onCaptureFailed(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull CaptureFailure failure) {
            super.onCaptureFailed(session, request, failure);
            Log.v(TAG, "onCaptureFailed( session, request, failure )");
        }
    };


public void autoFocus() {
        try {
            focusSeekBar.setCurrentValue(0);
            setFocusMode(Mode.AUTO);
            mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CameraMetadata.CONTROL_AF_MODE_AUTO);
            // Trigger an autofocus scan
            mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);
            Log.v(TAG, "autoFocus()");
            mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(), mCaptureCallback, null);

            // set seekbar  to focus distance
        } catch (CameraAccessException e) {
            OnCameraErrorListener.handle(mCameraErrorCallback, e);
        }
    }


 protected void lockFocus() {
        Log.v(TAG, "lockFocus()");

        if (mCaptureSession == null) {
            return;
        }
        try {

            if (focusMode == Mode.AUTO) {
                // This is how to tell the camera to lock focus.
                mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);
                mState = STATE_WAITING_LOCK;
                mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback, mBackgroundHandler);

                // check fo focus state
                // if focus is locked call start capture
                // if focus is not locked call unlock focus

                if (focusLockLatch.await(500, TimeUnit.MILLISECONDS)) {
                    startCapture();
                } else {
                    unlockFocus();
                }
            } else {
                startCapture();
            }
        } catch (CameraAccessException e) {
            OnCameraErrorListener.handle(mCameraErrorCallback, e);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    protected void unlockFocus() {
        Log.v(TAG, "unlockFocus()");
        try {
            // Reset the auto-focus trigger
            mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
            mCaptureSession.capture(mPreviewRequestBuilder.build(), null, null);
            // After this, the camera will go back to the normal state of preview.
            mState = STATE_STREAMING;
            //resume Zoom effect after taking a picture
            mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
            if (mZoom != null) {
                mPreviewRequestBuilder.set(CaptureRequest.SCALER_CROP_REGION, mZoom);
            }
            mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(), mCaptureCallback, mBackgroundHandler);
        } catch (CameraAccessException e) {
            OnCameraErrorListener.handle(mCameraErrorCallback, e);
        }
    }


    protected void unlockFocus() {
        Log.v(TAG, "unlockFocus()");
        try {
            // Reset the auto-focus trigger
            mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
            mCaptureSession.capture(mPreviewRequestBuilder.build(), null, null);
            // After this, the camera will go back to the normal state of preview.
            mState = STATE_STREAMING;
            //resume Zoom effect after taking a picture
            mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
            if (mZoom != null) {
                mPreviewRequestBuilder.set(CaptureRequest.SCALER_CROP_REGION, mZoom);
            }
            mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(), mCaptureCallback, mBackgroundHandler);
        } catch (CameraAccessException e) {
            OnCameraErrorListener.handle(mCameraErrorCallback, e);
        }
    }


java android android-camera android-camera2
1个回答
0
投票

您使用同一线程进行

focusLockLatch
await()
countdown()
调用。因此,如果先调用
await
,则线程已经处于等待状态,直到调用
countdown
,但无法再调用
countdown
来释放线程。

同一个线程进行回调的原因是

mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(), mCaptureCallback, null);

由于您将此处的

handler
即第三个参数设置为 null,因此正在使用当前线程的循环程序,因此回调将在当前线程上执行。我发现您已经在其他地方使用了
mBackgroundHandler
,只需在这里也使用它即可,即
mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(), mCaptureCallback, mBackgroundHandler);

另外,由于您的

mBackgroundHandler
初始化不在这里,也许请仔细检查 mBackgroundHandler 确实在后台线程上执行,而不是在同一个线程上(如果需要,添加一些日志来检查它)。

© www.soinside.com 2019 - 2024. All rights reserved.