Android set camera2只在timelapse开始时聚焦一次

Android set camera2只在timelapse开始时聚焦一次,android,android-camera2,camera2,Android,Android Camera2,Camera2,我想制作一个简单的应用程序,为timelapse制作捕获。我终于成功了。但我想知道是否有可能只在第一张照片上锁定一次焦点?然后使用保存的焦点值(如果可能)?一般来说这是个好主意?我认为每隔几秒钟调用lockFocus()太贵了。当设备固定放置时,不动 事实上,我有类似谷歌示例代码的代码。我正在将CaptureRequest.BuilderfieldCONTROL\u AF\u TRIGGER设置为CONTROL\u AF\u TRIGGER\u START并在CaptureCallback中检查

我想制作一个简单的应用程序,为timelapse制作捕获。我终于成功了。但我想知道是否有可能只在第一张照片上锁定一次焦点?然后使用保存的焦点值(如果可能)?一般来说这是个好主意?我认为每隔几秒钟调用
lockFocus()
太贵了。当设备固定放置时,不动

事实上,我有类似谷歌示例代码的代码。我正在将
CaptureRequest.Builder
field
CONTROL\u AF\u TRIGGER
设置为
CONTROL\u AF\u TRIGGER\u START
并在
CaptureCallback
中检查
CaptureResult.CONTROL\u AF\u STATE
,如果
ok
则拍摄最终照片。可能在第一张照片中获得
镜头的焦距
,然后以某种方式设置该值

另外,我不向用户显示预览,整个摄像头逻辑正在服务和其他线程中运行。我还实现了
ImageReader

我的代码是:

// before is `CameraManager`, setting outputs, opening camera - all ok

public void makePhoto() { // this I call from outer 
// plus some observer, not important conditions for this issue

createCameraPreviewSession();
}

private void createCameraPreviewSession() {
    mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
    mPreviewRequestBuilder.addTarget(previewSurface);

    mCameraDevice.createCaptureSession(Arrays.asList(previewSurface, mImageReader.getSurface()), new CameraCaptureSession.StateCallback() {
        public void onConfigured(CameraCaptureSession session) {
            mCaptureSession = session;
            mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
            mPreviewRequest = mPreviewRequestBuilder.build();

            startedRepeatedRequest = false; // simple flag to start lockFocus after below request has started, once
            mCaptureSession.setRepeatingRequest(mPreviewRequest, mCaptureCallback, null);
        }
    }
}


private CameraCaptureSession.CaptureCallback mCaptureCallback = new CameraCaptureSession.CaptureCallback() {
    public void onCaptureProgressed(CameraCaptureSession session, CaptureRequest request, CaptureResult partialResult) {
        process(partialResult);
    }

    private void process(CaptureResult result) {
        if(!startedRepeatedRequest) {
            // this is called only once, on the beginning of session
            lockFocus();
            startedRepeatedRequest = true;
        }

        switch(mState) {
            case STATE_PREVIEW:
                break;
            case STATE_WAITING_LOCK:
                Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);
                if (afState == null) {
                    captureStillPicture();
                } else if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState || CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState) {
                    Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
                    if (aeState == null || aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED) {
                        mState = STATE_PICTURE_TAKEN;
                        captureStillPicture(); // this leads to final capture photo
                    } else {
                        runPrecaptureSequence();
                    }
                }
                break;
            // There are also flags for STATE_PRECAPTURE, and STATE_WAITING_NON_PRECAPTURE but this doesn't matter here
        }
    }
}

private void lockFocus() {
        mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);
        mState = STATE_WAITING_LOCK;
        mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback, null);
}

private void captureStillPicture() {
    final CaptureRequest.Builder captureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
    Surface surfaceTarget = mImageReader.getSurface();
    captureBuilder.addTarget(surfaceTarget);
    captureBuilder.set(CaptureRequest.JPEG_QUALITY, (byte) 90);
    captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);

    // callback for final capture
    CameraCaptureSession.CaptureCallback CaptureCallback = new CameraCaptureSession.CaptureCallback() {
        mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
        mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback, null);
        mState = STATE_PREVIEW;
        session.close();
    }

    mCaptureSession.stopRepeating();
    mCaptureSession.capture(captureBuilder.build(), CaptureCallback, null);
}

您只需在设置好相机预览后调用lockfocus,在拍摄完成之前不要释放它。重要的是调用lockfocus和unlockfocus都不能被调用两次。从进程方法中删除lockfocus Too抱歉回复时间太长。你们介意锁定和解锁一次捕获吗?否-锁定、捕获、捕获..、解锁?可能是这样。所以,如果我想抓拍得很快,我应该使用录像。@user2209414你是如何解决这个问题的?@ShivamPokhriyal我放弃了。我不再那么在乎了。这个项目只是一个业余应用程序。通常我把每一张照片都称为对焦程序。我懒得再去调查了。你只需要在设置好相机预览后调用lockfocus,在拍摄完成之前不要释放它。重要的是调用lockfocus和unlockfocus都不能被调用两次。从进程方法中删除lockfocus Too抱歉回复时间太长。你们介意锁定和解锁一次捕获吗?否-锁定、捕获、捕获..、解锁?可能是这样。所以,如果我想抓拍得很快,我应该使用录像。@user2209414你是如何解决这个问题的?@ShivamPokhriyal我放弃了。我不再那么在乎了。这个项目只是一个业余应用程序。通常我把每一张照片都称为对焦程序。我懒得再去调查这件事了。