我的代码基于来自Google Camera2-Basic的示例,并且添加了Flash始终支持。但看起来照片是在闪光灯发生后立即拍摄的。即使闪光灯被触发,我(几乎)总是得到非闪光的照片。
修改后的预览请求构建器:
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH);
我还将此控制模式添加到captureStillPicture()
captureBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH);
并修改了process()开关:
case STATE_WAITING_PRECAPTURE: {
// CONTROL_AE_STATE can be null on some devices
Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
Log.i(TAG, "aeState = " + aeState);
if (aeState == null ||
aeState == CaptureResult.CONTROL_AE_STATE_PRECAPTURE ||
aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED ||
aeState == CaptureRequest.CONTROL_AE_STATE_FLASH_REQUIRED) {
mState = STATE_WAITING_NON_PRECAPTURE;
}
break;
}
答案 0 :(得分:0)
我在Nexus 5上遇到了同样的问题。我通过检查CaptureResult.FLASH_STATE
来解决这个问题,如果它等于CaptureResult.FLASH_STATE_FIRED
则立即触发捕获。基本上,如果闪光灯闪光,那么无论你处于什么状态,你都需要在那里进行捕捉,因为它只会发射一次。如果自动对焦/曝光等在这一点上没有正确收敛,那么你无能为力。
你可以在onCaptureCompleted
开头检查一下:
if(mFlashAvailable && mWaitingForFlash)
{
Integer flashState = result.get(CaptureResult.FLASH_STATE);
if(flashState != null && flashState==CaptureResult.FLASH_STATE_FIRED)
{
mWaitingForFlash = false;
// do the capture...
mState = STATE_PICTURE_TAKEN;
captureStillPicture();
return; // don't call process()
}
}
打开相机时, mFlashAvailable
是从CameraCharacteristics设置的:
mFlashAvailable = characteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
mWaitingForFlash
只是您在启动预捕获时可以设置的标记,因此您不会捕获多个帧。但是,在您的特定情况下,这可能不是必需的。
如果您在问题中描述,那将在状态收敛之前(即照片在闪光之后)闪光灯闪光时进行处理。然而,当闪光灯开始播放时你也需要处理这种情况(我从未见过这种情况实际发生但是以防万一)。您可以通过在将mExpectingFlash = true;
设置为CONTROL_AE_MODE
时设置CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH
这样的标记,并且如果它是真的则不捕获通常的方式(因为您将在检测到闪光灯时捕获)相反)。如果您使用aeState == CaptureRequest.CONTROL_AE_STATE_FLASH_REQUIRED
,则可以在获得CONTROL_AE_MODE_ON_AUTO_FLASH
时设置此标记。作为一个安全网,我有一个超时,所以我不会等待一个永远不会出现的闪光灯,如果检测到CONTROL_AE_STATE_FLASH_REQUIRED
但是闪光灯没有闪光。
如果捕获多个帧,则可以在检测到闪光灯闪光时读取时间戳,如下所示:
long timestamp = result.get(CaptureResult.SENSOR_TIMESTAMP);
然后将其与onImageAvailable
Image image = reader.acquireLatestImage();
if (image != null)
{
long timestamp = image.getTimestamp();
// ....
}