我有一个相机应用程序,其中我为用户提供 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);
}
}
您使用同一线程进行
focusLockLatch
await()
和 countdown()
调用。因此,如果先调用 await
,则线程已经处于等待状态,直到调用 countdown
,但无法再调用 countdown
来释放线程。
同一个线程进行回调的原因是
mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(), mCaptureCallback, null);
由于您将此处的
handler
即第三个参数设置为 null,因此正在使用当前线程的循环程序,因此回调将在当前线程上执行。我发现您已经在其他地方使用了 mBackgroundHandler
,只需在这里也使用它即可,即 mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(), mCaptureCallback, mBackgroundHandler);
。
另外,由于您的
mBackgroundHandler
初始化不在这里,也许请仔细检查 mBackgroundHandler 确实在后台线程上执行,而不是在同一个线程上(如果需要,添加一些日志来检查它)。