目前,我正在尝试根据Camera2Basic示例创建一个相机Fragment。主要区别在于用户可以在闪光模式(自动,开启,关闭)之间切换以及显示拍摄静止拍摄的预览的可能性,因此用户可以决定是否应该保存或丢弃拍摄的照片。登记/> 在始终开启模式下使用闪光灯时出现问题。有时,预捕获序列无法完成,应用程序卡住了。预览仍然有效,并且UI具有响应性,但处理会达到“无限循环” 根据Camera2Basic,我使用了这个CaptureCallback。
private CameraCaptureSession.CaptureCallback mPreviewCaptureCallback =
new CameraCaptureSession.CaptureCallback() {
private int counter = 0; // Counts failed attempts to gain AF or complete precapture
@Override
public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
process(result);
}
@Override
public void onCaptureProgressed(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull CaptureResult partialResult) {
process(partialResult);
}
private void process(CaptureResult result) {
Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);
switch (mState) {
case STATE_PREVIEW:
// Do nothing
break;
case STATE_WAIT_LOCK:
if (afState == null) {
counter = 0;
captureStillImage();
} else if (afState == CaptureRequest.CONTROL_AF_STATE_FOCUSED_LOCKED ||
afState == CaptureRequest.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED) {
if (aeState == null ||
aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED) {
mState = STATE_PICTURE_CAPTURED;
captureStillImage();
} else {
runPrecaptureSequence();
}
counter = 0;
} else if(counter > 50) {
counter = 0;
restartFocus();
} else {
counter++;
Log.d(TAG, "STATE_WAIT_LOCK - Counter : " + counter);
}
break;
case STATE_WAIT_PRECAPTURE:
if (aeState == null ||
aeState == CaptureResult.CONTROL_AE_STATE_PRECAPTURE ||
aeState == CaptureRequest.CONTROL_AE_STATE_FLASH_REQUIRED) {
mState = STATE_WAIT_NON_PRECAPTURE;
}
break;
case STATE_WAIT_NON_PRECAPTURE:
if (aeState == null || aeState != CaptureResult.CONTROL_AE_STATE_PRECAPTURE) {
mState = STATE_PICTURE_CAPTURED;
captureStillImage();
} else if (counter > 50) {
Log.d(TAG, "STATE_WAIT_NON_PRECAPTURE - Restart");
counter = 0;
restartPrecapture();
} else {
counter++;
Log.d(TAG, "STATE_WAIT_NON_PRECAPTURE - Counter : " + counter);
}
break;
}
}
};
由于我在过去遇到一个类似的问题,AF未被锁定,我创建了一种重启AF的方法。
private void restartFocus() {
try {
mPreviewRequestBuilder.set(
CaptureRequest.CONTROL_AF_TRIGGER,
CaptureRequest.CONTROL_AF_TRIGGER_CANCEL);
mCaptureSession.capture(
mPreviewRequestBuilder.build(),
mPreviewCaptureCallback,
mBackgroundHandler);
lockFocus();
} catch (CameraAccessException cae) {
cae.printStackTrace();
}
}
private void lockFocus() {
try {
mPreviewRequestBuilder.set(
CaptureRequest.CONTROL_AF_TRIGGER,
CaptureRequest.CONTROL_AF_TRIGGER_START);
mState = STATE_WAIT_LOCK;
mCaptureSession.capture(
mPreviewRequestBuilder.build(),
mPreviewCaptureCallback,
mBackgroundHandler);
} catch (CameraAccessException cae) {
cae.printStackTrace();
}
}
所以我决定第二次使用这个想法并重新启动预捕获序列。
private void restartPrecapture() {
try {
mPreviewRequestBuilder.set(
CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL);
mCaptureSession.capture(mPreviewRequestBuilder.build(),
mPreviewCaptureCallback,
mBackgroundHandler);
runPrecaptureSequence();
} catch (CameraAccessException cae) {
cae.printStackTrace();
}
}
private void runPrecaptureSequence() {
try {
setFlash(mPreviewRequestBuilder);
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START);
mState = STATE_WAIT_PRECAPTURE;
mCaptureSession.capture(mPreviewRequestBuilder.build(),
mPreviewCaptureCallback,
mBackgroundHandler);
} catch (CameraAccessException cae) {
cae.printStackTrace();
}
}
检查Logcat显示,应用程序有时卡在STATE_WAIT_NON_PRECAPTURE中,而aeState仍然是CaptureResult.CONTROL_AE_STATE_PRECAPTURE。如果计数器在此状态下达到50,则按预期调用 restartPrecapture()。
目前我在使用CONTROL_AE_MODE_ON_ALWAYS_FLASH时只遇到这个问题,但有时我会在此之前拍摄几十张照片,所以可能使用自动或禁用闪光灯,可能性要小得多。
private void setFlash(CaptureRequest.Builder requestBuilder) {
switch(mFlashMode) {
case FLASH_AUTO:
setFlashAuto(requestBuilder);
break;
case FLASH_ON:
setFlashOn(requestBuilder);
break;
case FLASH_OFF:
setFlashOff(requestBuilder);
break;
}
}
private void setFlashAuto(CaptureRequest.Builder requestBuilder) {
requestBuilder.set(CaptureRequest.CONTROL_AE_MODE,
CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH);
}
private void setFlashOn(CaptureRequest.Builder requestBuilder) {
requestBuilder.set(CaptureRequest.CONTROL_AE_MODE,
CameraMetadata.CONTROL_AE_MODE_ON_ALWAYS_FLASH);
}
private void setFlashOff(CaptureRequest.Builder requestBuilder) {
requestBuilder.set(CaptureRequest.CONTROL_AE_MODE,
CameraMetadata.CONTROL_AE_MODE_ON);
requestBuilder.set(CaptureRequest.FLASH_MODE,
CameraMetadata.FLASH_MODE_OFF);
}
当预捕获序列似乎无法完成时,我该如何处理这种情况?
答案 0 :(得分:0)
经过一些研究后,我找不到理由,为什么CONTROL_AE_MODE_ON_ALWAYS_FLASH无法正常工作,所以我做了一个解决方法。我像这样改变了我的setFlashOn()方法
private void setFlashOn(CaptureRequest.Builder requestBuilder) {
requestBuilder.set(CaptureRequest.CONTROL_AE_MODE,
CameraMetadata.CONTROL_AE_MODE_ON);
requestBuilder.set(CaptureRequest.FLASH_MODE,
CameraMetadata.FLASH_MODE_SINGLE);
}
也许这是我正在使用的设备的问题,总是闪存的设置不起作用。