闪光灯问题
Flash light issue
我正在努力将相机应用程序从 camera1 迁移到 camera2。我在摩托罗拉 G5 和三星 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()
}
}
}
}
原因是如果你也设置了AE,那么AE算法会在需要时触发闪光灯,根据当前光线条件适当调整曝光。
要解决此问题,请以不同方式处理预览和照片捕获会话的闪光灯配置。使用下一个函数配置您的 Request Builders。
有4个地方需要调用setFlash()。请注意,该方法仅设置给定的构建器闪存配置,您仍然需要将构建器传递给目标会话。预览会话将作为重复请求。
- 最初配置 Preview 时,isPreviewSession 设置为 True,因此此类操作因为点击对焦不会触发闪光灯。
- 拍照时,在用户按下快门按钮的那一刻,
使用 isPreviewSession 集配置 Preview 请求构建器
错误。将其设置为 False 意味着这次 Preview 构建器 实际上将具有所需的目标 Flash 配置,因此 Capture Session Callback知道什么时候Focus,
AE 等使用目标闪存配置会聚,这
AE算法可能需要。
- 然后,当收敛并准备启动 捕获会话 时,调用
再次 setFlash 传递 Capture Request Builder 从
cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE),
再次将 isPreviewSession 设置为 False.
- 最后,当捕获结束时,在通知的回调中
关于捕获完成,必须再次重新配置 Preview 请求构建器
但是这次 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);
}
}
}
我正在努力将相机应用程序从 camera1 迁移到 camera2。我在摩托罗拉 G5 和三星 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()
}
}
}
}
原因是如果你也设置了AE,那么AE算法会在需要时触发闪光灯,根据当前光线条件适当调整曝光。
要解决此问题,请以不同方式处理预览和照片捕获会话的闪光灯配置。使用下一个函数配置您的 Request Builders。
有4个地方需要调用setFlash()。请注意,该方法仅设置给定的构建器闪存配置,您仍然需要将构建器传递给目标会话。预览会话将作为重复请求。
- 最初配置 Preview 时,isPreviewSession 设置为 True,因此此类操作因为点击对焦不会触发闪光灯。
- 拍照时,在用户按下快门按钮的那一刻, 使用 isPreviewSession 集配置 Preview 请求构建器 错误。将其设置为 False 意味着这次 Preview 构建器 实际上将具有所需的目标 Flash 配置,因此 Capture Session Callback知道什么时候Focus, AE 等使用目标闪存配置会聚,这 AE算法可能需要。
- 然后,当收敛并准备启动 捕获会话 时,调用 再次 setFlash 传递 Capture Request Builder 从 cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE), 再次将 isPreviewSession 设置为 False.
- 最后,当捕获结束时,在通知的回调中 关于捕获完成,必须再次重新配置 Preview 请求构建器 但是这次 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);
}
}
}