闪光灯问题

时间:2018-08-16 17:40:08

标签: android android-camera2

我正在将相机应用程序从camera1迁移到camera2。我在Motorola G5和Samsung Galaxy S4上遇到了一个奇怪的问题,它们的闪光灯模式处于开启状态,每次我点击预览视图进行手动对焦时,闪光灯都会闪光。

有人遇到同样的问题吗? 这是我用于点击聚焦功能的代码:

        val focusAreaTouch = calculateFocusArea(pointOfInterestX, pointOfInterestY, sensorArraySize)

        //cancel any existing AF trigger
        previewRequestBuilder?.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL)
        previewRequestBuilder?.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_OFF)

        try {
            captureSession?.capture(previewRequestBuilder?.build(), captureCallback, null)
        }catch (ex: Exception) {
            Log.e(TAG, "Tap To Focus -> Failed to cancel any existing AF trigger.", ex)
        }

        Log.e(TAG, "AF Regions: " + previewRequestBuilder?.get(CaptureRequest.CONTROL_AF_REGIONS)?.first()?.rect)

        //Then we add a new AF trigger with focus region
        previewRequestBuilder?.set(CaptureRequest.CONTROL_AF_REGIONS, arrayOf(focusAreaTouch))

        previewRequestBuilder?.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO)
        previewRequestBuilder?.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO)
        previewRequestBuilder?.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START)

这是我检查AE状态的方法:

private fun process(result: CaptureResult) {
    when (state) {
        CameraState.STATE_LOCKING -> {
            val af = result.get(CaptureResult.CONTROL_AF_STATE) ?: return
            if (af == CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED
                    || af == CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED
                    || af == CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED) {
                val ae = result.get(CaptureResult.CONTROL_AE_STATE)
                if (ae == null || ae == CaptureResult.CONTROL_AE_STATE_CONVERGED) {
                    state = CameraState.STATE_CAPTURING
                    onReady()
                } else {
                    state = CameraState.STATE_LOCKED
                    onPreCaptureRequired()
                }
            }
        }
        CameraState.STATE_PRECAPTURE -> {
            val ae = result.get(CaptureResult.CONTROL_AE_STATE)
            if (ae == null || ae == CaptureResult.CONTROL_AE_STATE_PRECAPTURE ||
                    ae == CaptureRequest.CONTROL_AE_STATE_FLASH_REQUIRED ||
                    ae == CaptureResult.CONTROL_AE_STATE_CONVERGED) {
                state = CameraState.STATE_WAITING
            }
        }
        CameraState.STATE_WAITING -> {
            val ae = result.get(CaptureResult.CONTROL_AE_STATE)
            if (ae == null || ae != CaptureResult.CONTROL_AE_STATE_PRECAPTURE) {
                state = CameraState.STATE_CAPTURING
                onReady()
            }
        }
    }
}

1 个答案:

答案 0 :(得分:1)

原因是如果您还设置了自动曝光,则自动曝光算法会根据需要根据当前的光照条件适当地调整曝光,从而触发闪光灯。

要解决此问题,请为预览和照片捕获会话分别处理Flash配置。使用下一个功能配置您的请求构建器


调用 setFlash()时有4个地方。请注意,该方法仅设置给定的构建器Flash配置,您仍然需要将构建器传递给目标会话。对于预览会话,将作为重复请求

  1. 在最初配置预览时,将 isPreviewSession 设置为 True ,因此诸如点击聚焦之类的操作不会触发Flash。
  2. 拍照时,就在用户按下快门按钮时, 使用 isPreviewSession 设置配置预览请求构建器 设为 False 。将其设置为 False 意味着这次 Preview构建器实际上将具有所需的目标Flash配置,因此 Capture Session Callback (捕获会话回调)知道何时焦点, AE等使用目标闪光灯配置收敛 AE算法可能需要。
  3. 然后,在融合并准备开始捕获会话时,致电 再次 setFlash 传递了从 cameraDevice。 createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE), 再次将 isPreviewSession 设置为 False
  4. 最后,当捕获结束时,在通知的回调中 关于捕获完成,必须再次重新配置预览请求构建器 但这一次将 isPreviewSession 设置为 True ,因此闪光灯 状态再次设置为“关闭”。

static final int FLASH_MODE_OFF = 0;
static final int FLASH_MODE_AUTO = 1;
static final int FLASH_MODE_ON = 2;
static final int FLASH_MODE_TORCH = 3;


public void setFlash(@NonNull final CaptureRequest.Builder builder, 
                             final boolean isPreviewSession, final int flashMode)
{
    if (isPreviewSession == true)
    {
        // For preview session

        builder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON);

        if (flashMode == FLASH_MODE_TORCH)
        {
            builder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_TORCH);
        }
        else
        {
            builder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_OFF);
        }
    }
    else
    {
        // For capture session

        if (flashMode == FLASH_MODE_OFF)
        {
            builder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON);
            builder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_OFF);
        }
        else if (flashMode == FLASH_MODE_AUTO)
        {
            builder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH);
            builder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_OFF);
        }
        else if (flashMode == FLASH_MODE_ON)
        {
            builder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON_ALWAYS_FLASH);
            builder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_SINGLE);
        }
        else if (flashMode == FLASH_MODE_TORCH)
        {
            builder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON);
            builder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_TORCH);
        }
    }
}