4

我的代码基于来自 Google Camera2-Basic 的示例,并添加了 flash always 支持。但看起来照片是在闪光发生后立即拍摄的。即使触发了闪光灯,我(几乎)总是得到不闪光的照片。

修改后的预览请求生成器:

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;
        }
4

1 回答 1

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_MODEto时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();
     // ....
 }
于 2015-12-28T09:16:06.350 回答