以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":
builder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH);
builder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_OFF);
break;
case "flash_on":
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":
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( 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();
if( MyDebug.LOG )
Log.i(TAG, "capture with precaptureBuilder");
captureSession.capture(precaptureBuilder.build(), previewCaptureCallback, handler);
captureSession.setRepeatingRequest(precaptureBuilder.build(), previewCaptureCallback, handler);
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);
}
|