Android Camera AE和AF的设置

在这里插入图片描述
以geekcamera为例,当关闭闪光灯时,flash mode = 0,代表flash为off模式;
ae mode = 1,代表ae为off模式,flash state = 2,代表flash处于 ready状态,表示没有打闪。
在这里插入图片描述
当闪光灯设置为auto时,是通过设置ae mode 控制的。flash mode = 0,代表flash为off模式;
ae mode = 2,代表ae为on模式,flash state = 2,代表flash处于 ready状态,表示没有打闪;flash state = 3,代表flash处于 fired状态,表示打闪了。在这里插入图片描述
在这里插入图片描述

具体代码逻辑

switch(flash_value) {
	case "flash_off":
		builder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON);
		builder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_OFF);
		break;
	case "flash_auto":
		// note we set this even in fake flash mode (where we manually turn torch on and off to simulate flash) so we
		// can read the FLASH_REQUIRED state to determine if flash is required
	/*if( use_fake_precapture || CameraController2.this.want_expo_bracketing )
		builder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON);
	else*/
		builder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH);
		//这里FLASH_MODE可以设置为任意值,因为AE_MODE优先级高
		builder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_OFF);
		break;
	case "flash_on":
		// see note above for "flash_auto" for why we set this even fake flash mode - arguably we don't need to know
		// about FLASH_REQUIRED in flash_on mode, but we set it for consistency...
	/*if( use_fake_precapture || CameraController2.this.want_expo_bracketing )
		builder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON);
	else*/
		builder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON_ALWAYS_FLASH);
		builder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_OFF);
		break;
	case "flash_torch":
		builder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON);
		builder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_TORCH);
		break;
	case "flash_red_eye":
		// not supported for expo bracketing or burst
		if( CameraController2.this.burst_type != BurstType.BURSTTYPE_NONE )
			builder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON);
		else
			builder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE);
		builder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_OFF);
		break;
	case "flash_frontscreen_auto":
	case "flash_frontscreen_on":
	case "flash_frontscreen_torch":
		builder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON);
		builder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_OFF);
		break;
}

只要flash mode不是auto,并且需要打闪的时候,就需要做预闪(precapture)

boolean needs_flash = capture_result_ae != null && capture_result_ae != CaptureResult.CONTROL_AE_STATE_CONVERGED;
if( camera_settings.flash_value.equals("flash_auto") && !needs_flash ) {
	// if we call precapture anyway, flash wouldn't fire - but we tend to have a pause
	// so skipping the precapture if flash isn't going to fire makes this faster
	if( MyDebug.LOG )
		Log.i(TAG, "flash auto, but we don't need flash");
	call_takePictureAfterPrecapture = true;
}
else {
	call_runPrecapture = true;
}

if( call_runPrecapture ) {
	runPrecapture();
}

runPrecapture逻辑

runPrecapture() {
	final CaptureRequest.Builder precaptureBuilder = mCameraDevice.createCaptureRequest(previewIsVideoMode ? CameraDevice.TEMPLATE_VIDEO_SNAPSHOT : CameraDevice.TEMPLATE_STILL_CAPTURE);
	precaptureBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT, CaptureRequest.CONTROL_CAPTURE_INTENT_STILL_CAPTURE);

	camera_settings.setupBuilder(precaptureBuilder, false);
	precaptureBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_IDLE);
	precaptureBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, CameraMetadata.CONTROL_AE_PRECAPTURE_TRIGGER_IDLE);

	precaptureBuilder.addTarget(getPreviewSurface());

	state = STATE_WAITING_PRECAPTURE_START;
	precapture_state_change_time_ms = System.currentTimeMillis();

	// first set precapture to idle - this is needed, otherwise we hang in state STATE_WAITING_PRECAPTURE_START, because precapture already occurred whilst autofocusing, and it doesn't occur again unless we first set the precapture trigger to idle
	if( MyDebug.LOG )
	Log.i(TAG, "capture with precaptureBuilder");
	captureSession.capture(precaptureBuilder.build(), previewCaptureCallback, handler);
	captureSession.setRepeatingRequest(precaptureBuilder.build(), previewCaptureCallback, handler);

	// now set precapture
	precaptureBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, CameraMetadata.CONTROL_AE_PRECAPTURE_TRIGGER_START);
	captureSession.capture(precaptureBuilder.build(), previewCaptureCallback, handler);
}

这里将state 设置为了STATE_WAITING_PRECAPTURE_START,当captureSession.capture()调用完后,会执行到CameraCaptureSession的回调函数onCaptureCompleted(),在此回调函数中我们需要判断AE的状态是否等于CaptureResult.CONTROL_AE_STATE_PRECAPTURE,如果等于,那么执行takePictureAfterPrecapture()
takePictureAfterPrecapture()的逻辑

takePictureAfterPrecapture(){
	stillBuilder = mCameraDevice.createCaptureRequest(previewIsVideoMode ? CameraDevice.TEMPLATE_VIDEO_SNAPSHOT : CameraDevice.TEMPLATE_STILL_CAPTURE);
	stillBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT, CaptureRequest.CONTROL_CAPTURE_INTENT_STILL_CAPTURE);
	stillBuilder.setTag(new RequestTagObject(RequestTagType.CAPTURE));
	camera_settings.setupBuilder(stillBuilder, true);
	stillBuilder.addTarget(imageReader.getSurface());
	captureSession.capture(stillBuilder.build(), previewCaptureCallback, handler);
	playSound(MediaActionSound.SHUTTER_CLICK);
}

版权声明:本文为CSDN博主「胡刚2021」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Redmoon955331/article/details/121393310

在这里插入图片描述
以geekcamera为例,当关闭闪光灯时,flash mode = 0,代表flash为off模式;
ae mode = 1,代表ae为off模式,flash state = 2,代表flash处于 ready状态,表示没有打闪。
在这里插入图片描述
当闪光灯设置为auto时,是通过设置ae mode 控制的。flash mode = 0,代表flash为off模式;
ae mode = 2,代表ae为on模式,flash state = 2,代表flash处于 ready状态,表示没有打闪;flash state = 3,代表flash处于 fired状态,表示打闪了。在这里插入图片描述
在这里插入图片描述

具体代码逻辑

switch(flash_value) {
	case "flash_off":
		builder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON);
		builder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_OFF);
		break;
	case "flash_auto":
		// note we set this even in fake flash mode (where we manually turn torch on and off to simulate flash) so we
		// can read the FLASH_REQUIRED state to determine if flash is required
	/*if( use_fake_precapture || CameraController2.this.want_expo_bracketing )
		builder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON);
	else*/
		builder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH);
		//这里FLASH_MODE可以设置为任意值,因为AE_MODE优先级高
		builder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_OFF);
		break;
	case "flash_on":
		// see note above for "flash_auto" for why we set this even fake flash mode - arguably we don't need to know
		// about FLASH_REQUIRED in flash_on mode, but we set it for consistency...
	/*if( use_fake_precapture || CameraController2.this.want_expo_bracketing )
		builder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON);
	else*/
		builder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON_ALWAYS_FLASH);
		builder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_OFF);
		break;
	case "flash_torch":
		builder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON);
		builder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_TORCH);
		break;
	case "flash_red_eye":
		// not supported for expo bracketing or burst
		if( CameraController2.this.burst_type != BurstType.BURSTTYPE_NONE )
			builder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON);
		else
			builder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE);
		builder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_OFF);
		break;
	case "flash_frontscreen_auto":
	case "flash_frontscreen_on":
	case "flash_frontscreen_torch":
		builder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON);
		builder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_OFF);
		break;
}

只要flash mode不是auto,并且需要打闪的时候,就需要做预闪(precapture)

boolean needs_flash = capture_result_ae != null && capture_result_ae != CaptureResult.CONTROL_AE_STATE_CONVERGED;
if( camera_settings.flash_value.equals("flash_auto") && !needs_flash ) {
	// if we call precapture anyway, flash wouldn't fire - but we tend to have a pause
	// so skipping the precapture if flash isn't going to fire makes this faster
	if( MyDebug.LOG )
		Log.i(TAG, "flash auto, but we don't need flash");
	call_takePictureAfterPrecapture = true;
}
else {
	call_runPrecapture = true;
}

if( call_runPrecapture ) {
	runPrecapture();
}

runPrecapture逻辑

runPrecapture() {
	final CaptureRequest.Builder precaptureBuilder = mCameraDevice.createCaptureRequest(previewIsVideoMode ? CameraDevice.TEMPLATE_VIDEO_SNAPSHOT : CameraDevice.TEMPLATE_STILL_CAPTURE);
	precaptureBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT, CaptureRequest.CONTROL_CAPTURE_INTENT_STILL_CAPTURE);

	camera_settings.setupBuilder(precaptureBuilder, false);
	precaptureBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_IDLE);
	precaptureBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, CameraMetadata.CONTROL_AE_PRECAPTURE_TRIGGER_IDLE);

	precaptureBuilder.addTarget(getPreviewSurface());

	state = STATE_WAITING_PRECAPTURE_START;
	precapture_state_change_time_ms = System.currentTimeMillis();

	// first set precapture to idle - this is needed, otherwise we hang in state STATE_WAITING_PRECAPTURE_START, because precapture already occurred whilst autofocusing, and it doesn't occur again unless we first set the precapture trigger to idle
	if( MyDebug.LOG )
	Log.i(TAG, "capture with precaptureBuilder");
	captureSession.capture(precaptureBuilder.build(), previewCaptureCallback, handler);
	captureSession.setRepeatingRequest(precaptureBuilder.build(), previewCaptureCallback, handler);

	// now set precapture
	precaptureBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, CameraMetadata.CONTROL_AE_PRECAPTURE_TRIGGER_START);
	captureSession.capture(precaptureBuilder.build(), previewCaptureCallback, handler);
}

这里将state 设置为了STATE_WAITING_PRECAPTURE_START,当captureSession.capture()调用完后,会执行到CameraCaptureSession的回调函数onCaptureCompleted(),在此回调函数中我们需要判断AE的状态是否等于CaptureResult.CONTROL_AE_STATE_PRECAPTURE,如果等于,那么执行takePictureAfterPrecapture()
takePictureAfterPrecapture()的逻辑

takePictureAfterPrecapture(){
	stillBuilder = mCameraDevice.createCaptureRequest(previewIsVideoMode ? CameraDevice.TEMPLATE_VIDEO_SNAPSHOT : CameraDevice.TEMPLATE_STILL_CAPTURE);
	stillBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT, CaptureRequest.CONTROL_CAPTURE_INTENT_STILL_CAPTURE);
	stillBuilder.setTag(new RequestTagObject(RequestTagType.CAPTURE));
	camera_settings.setupBuilder(stillBuilder, true);
	stillBuilder.addTarget(imageReader.getSurface());
	captureSession.capture(stillBuilder.build(), previewCaptureCallback, handler);
	playSound(MediaActionSound.SHUTTER_CLICK);
}

版权声明:本文为CSDN博主「胡刚2021」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Redmoon955331/article/details/121393310

生成海报
点赞 0

胡刚2021

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

Android Camera AE和AF的设置

以geekcamera为例,当关闭闪光灯时,flash mode 0,代表flash为off模式; ae mode 1,代表ae为off模式,flash state 2

Camera HIDL接口实现camera preview功能

项目背景 为了在工厂测试中快速启动芯片外设测试项目,而不启动Android系统,使用fastmmi(FFBM: Fast Factory Boot Mode)测试框架。本人负责测试芯片中

定时器触发STM32 ADC的采样转换示例

开发板:STM32F446 Nucleo开发板IDE:  keil MDK初始化配置工具:stm32cubeMx例程内容:通过定时器触发ADC规则通道及注入通道的模数转换工作。下面基于STM32CubeMx进行些必要

STM32F103C8T6点亮LED流水灯详解

目录 一、STM32寄存器简介 二、keil5添加stm32固件库 三、编译代码部分 四、将程序烧录到STM32F103C8t6中去 一、STM32寄存器简介 简单来说,寄存器就是存放东西的东西。从名字来看,跟