fix: Add extra sanity-checks for CaptureRequest
(#2571)
* fix: Add extra sanity-checks for `CaptureRequest` * Update CameraDeviceDetails.kt * Refactor zoom a bit * fix: Remove unneeded flash * Move to AE instead of FLASH control * Revert "Move to AE instead of FLASH control" This reverts commit 755689411535803d156a4e84f143d0c9d08c858f. * Set AE Mode to ON for manual flash control
This commit is contained in:
parent
57c6431353
commit
b105de0194
@ -30,10 +30,12 @@ suspend fun CameraView.takePhoto(optionsMap: ReadableMap): WritableMap {
|
|||||||
|
|
||||||
val qualityPrioritization = options["qualityPrioritization"] as? String ?: "balanced"
|
val qualityPrioritization = options["qualityPrioritization"] as? String ?: "balanced"
|
||||||
val flash = options["flash"] as? String ?: "off"
|
val flash = options["flash"] as? String ?: "off"
|
||||||
val enableAutoRedEyeReduction = options["enableAutoRedEyeReduction"] == true
|
|
||||||
val enableAutoStabilization = options["enableAutoStabilization"] == true
|
val enableAutoStabilization = options["enableAutoStabilization"] == true
|
||||||
val enableShutterSound = options["enableShutterSound"] as? Boolean ?: true
|
val enableShutterSound = options["enableShutterSound"] as? Boolean ?: true
|
||||||
|
|
||||||
|
// TODO: Implement Red Eye Reduction
|
||||||
|
options["enableAutoRedEyeReduction"]
|
||||||
|
|
||||||
val flashMode = Flash.fromUnionValue(flash)
|
val flashMode = Flash.fromUnionValue(flash)
|
||||||
val qualityPrioritizationMode = QualityPrioritization.fromUnionValue(qualityPrioritization)
|
val qualityPrioritizationMode = QualityPrioritization.fromUnionValue(qualityPrioritization)
|
||||||
|
|
||||||
@ -41,7 +43,6 @@ suspend fun CameraView.takePhoto(optionsMap: ReadableMap): WritableMap {
|
|||||||
qualityPrioritizationMode,
|
qualityPrioritizationMode,
|
||||||
flashMode,
|
flashMode,
|
||||||
enableShutterSound,
|
enableShutterSound,
|
||||||
enableAutoRedEyeReduction,
|
|
||||||
enableAutoStabilization,
|
enableAutoStabilization,
|
||||||
orientation
|
orientation
|
||||||
)
|
)
|
||||||
|
@ -58,7 +58,10 @@ class CameraDeviceDetails(private val cameraManager: CameraManager, val cameraId
|
|||||||
val isMultiCam by lazy { capabilities.contains(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA) }
|
val isMultiCam by lazy { capabilities.contains(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA) }
|
||||||
val supportsDepthCapture by lazy { capabilities.contains(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT) }
|
val supportsDepthCapture by lazy { capabilities.contains(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT) }
|
||||||
val supportsRawCapture by lazy { capabilities.contains(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW) }
|
val supportsRawCapture by lazy { capabilities.contains(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW) }
|
||||||
val supportsLowLightBoost by lazy { extensions.contains(CameraExtensionCharacteristics.EXTENSION_NIGHT) }
|
val supportsLowLightBoost by lazy {
|
||||||
|
extensions.contains(CameraExtensionCharacteristics.EXTENSION_NIGHT) &&
|
||||||
|
modes.contains(CameraCharacteristics.CONTROL_MODE_USE_SCENE_MODE)
|
||||||
|
}
|
||||||
val lensFacing by lazy { LensFacing.fromCameraCharacteristics(characteristics) }
|
val lensFacing by lazy { LensFacing.fromCameraCharacteristics(characteristics) }
|
||||||
val hasFlash by lazy { characteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE) ?: false }
|
val hasFlash by lazy { characteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE) ?: false }
|
||||||
val focalLengths by lazy {
|
val focalLengths by lazy {
|
||||||
@ -122,6 +125,7 @@ class CameraDeviceDetails(private val cameraManager: CameraManager, val cameraId
|
|||||||
val supportsExposureRegions by lazy { (characteristics.get(CameraCharacteristics.CONTROL_MAX_REGIONS_AE) ?: 0) > 0 }
|
val supportsExposureRegions by lazy { (characteristics.get(CameraCharacteristics.CONTROL_MAX_REGIONS_AE) ?: 0) > 0 }
|
||||||
val supportsWhiteBalanceRegions by lazy { (characteristics.get(CameraCharacteristics.CONTROL_MAX_REGIONS_AWB) ?: 0) > 0 }
|
val supportsWhiteBalanceRegions by lazy { (characteristics.get(CameraCharacteristics.CONTROL_MAX_REGIONS_AWB) ?: 0) > 0 }
|
||||||
|
|
||||||
|
val modes by lazy { characteristics.get(CameraCharacteristics.CONTROL_AVAILABLE_MODES)?.toList() ?: emptyList() }
|
||||||
val afModes by lazy { characteristics.get(CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES)?.toList() ?: emptyList() }
|
val afModes by lazy { characteristics.get(CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES)?.toList() ?: emptyList() }
|
||||||
val aeModes by lazy { characteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES)?.toList() ?: emptyList() }
|
val aeModes by lazy { characteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES)?.toList() ?: emptyList() }
|
||||||
val awbModes by lazy { characteristics.get(CameraCharacteristics.CONTROL_AWB_AVAILABLE_MODES)?.toList() ?: emptyList() }
|
val awbModes by lazy { characteristics.get(CameraCharacteristics.CONTROL_AWB_AVAILABLE_MODES)?.toList() ?: emptyList() }
|
||||||
|
@ -368,7 +368,6 @@ class CameraSession(private val context: Context, private val cameraManager: Cam
|
|||||||
qualityPrioritization: QualityPrioritization,
|
qualityPrioritization: QualityPrioritization,
|
||||||
flash: Flash,
|
flash: Flash,
|
||||||
enableShutterSound: Boolean,
|
enableShutterSound: Boolean,
|
||||||
enableRedEyeReduction: Boolean,
|
|
||||||
enableAutoStabilization: Boolean,
|
enableAutoStabilization: Boolean,
|
||||||
outputOrientation: Orientation
|
outputOrientation: Orientation
|
||||||
): CapturedPhoto {
|
): CapturedPhoto {
|
||||||
@ -378,7 +377,6 @@ class CameraSession(private val context: Context, private val cameraManager: Cam
|
|||||||
val result = captureSession.capture(
|
val result = captureSession.capture(
|
||||||
qualityPrioritization,
|
qualityPrioritization,
|
||||||
flash,
|
flash,
|
||||||
enableRedEyeReduction,
|
|
||||||
enableAutoStabilization,
|
enableAutoStabilization,
|
||||||
photoOutput.enableHdr,
|
photoOutput.enableHdr,
|
||||||
outputOrientation,
|
outputOrientation,
|
||||||
|
@ -140,7 +140,6 @@ class PersistentCameraCaptureSession(private val cameraManager: CameraManager, p
|
|||||||
suspend fun capture(
|
suspend fun capture(
|
||||||
qualityPrioritization: QualityPrioritization,
|
qualityPrioritization: QualityPrioritization,
|
||||||
flash: Flash,
|
flash: Flash,
|
||||||
enableRedEyeReduction: Boolean,
|
|
||||||
enableAutoStabilization: Boolean,
|
enableAutoStabilization: Boolean,
|
||||||
enablePhotoHdr: Boolean,
|
enablePhotoHdr: Boolean,
|
||||||
orientation: Orientation,
|
orientation: Orientation,
|
||||||
@ -157,8 +156,6 @@ class PersistentCameraCaptureSession(private val cameraManager: CameraManager, p
|
|||||||
val photoRequest = PhotoCaptureRequest(
|
val photoRequest = PhotoCaptureRequest(
|
||||||
repeatingRequest,
|
repeatingRequest,
|
||||||
qualityPrioritization,
|
qualityPrioritization,
|
||||||
flash,
|
|
||||||
enableRedEyeReduction,
|
|
||||||
enableAutoStabilization,
|
enableAutoStabilization,
|
||||||
enablePhotoHdr,
|
enablePhotoHdr,
|
||||||
orientation
|
orientation
|
||||||
@ -195,6 +192,7 @@ class PersistentCameraCaptureSession(private val cameraManager: CameraManager, p
|
|||||||
// 2. Once precapture AF/AE/AWB successfully locked, capture the actual photo
|
// 2. Once precapture AF/AE/AWB successfully locked, capture the actual photo
|
||||||
val singleRequest = photoRequest.createCaptureRequest(device, deviceDetails, outputs)
|
val singleRequest = photoRequest.createCaptureRequest(device, deviceDetails, outputs)
|
||||||
if (result.needsFlash) {
|
if (result.needsFlash) {
|
||||||
|
singleRequest.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON)
|
||||||
singleRequest.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_SINGLE)
|
singleRequest.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_SINGLE)
|
||||||
}
|
}
|
||||||
return session.capture(singleRequest.build(), enableShutterSound)
|
return session.capture(singleRequest.build(), enableShutterSound)
|
||||||
|
@ -75,7 +75,7 @@ abstract class CameraCaptureRequest(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set Zoom
|
// Set Zoom
|
||||||
builder.setZoom(zoom, deviceDetails.characteristics)
|
builder.setZoom(zoom, deviceDetails)
|
||||||
|
|
||||||
// Set Torch
|
// Set Torch
|
||||||
if (torch == Torch.ON) {
|
if (torch == Torch.ON) {
|
||||||
|
@ -7,7 +7,6 @@ import android.os.Build
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.mrousavy.camera.core.CameraDeviceDetails
|
import com.mrousavy.camera.core.CameraDeviceDetails
|
||||||
import com.mrousavy.camera.core.outputs.SurfaceOutput
|
import com.mrousavy.camera.core.outputs.SurfaceOutput
|
||||||
import com.mrousavy.camera.types.Flash
|
|
||||||
import com.mrousavy.camera.types.HardwareLevel
|
import com.mrousavy.camera.types.HardwareLevel
|
||||||
import com.mrousavy.camera.types.Orientation
|
import com.mrousavy.camera.types.Orientation
|
||||||
import com.mrousavy.camera.types.QualityPrioritization
|
import com.mrousavy.camera.types.QualityPrioritization
|
||||||
@ -16,8 +15,6 @@ import com.mrousavy.camera.types.Torch
|
|||||||
class PhotoCaptureRequest(
|
class PhotoCaptureRequest(
|
||||||
repeatingRequest: RepeatingCaptureRequest,
|
repeatingRequest: RepeatingCaptureRequest,
|
||||||
private val qualityPrioritization: QualityPrioritization,
|
private val qualityPrioritization: QualityPrioritization,
|
||||||
private val flash: Flash,
|
|
||||||
private val enableRedEyeReduction: Boolean,
|
|
||||||
private val enableAutoStabilization: Boolean,
|
private val enableAutoStabilization: Boolean,
|
||||||
enablePhotoHdr: Boolean,
|
enablePhotoHdr: Boolean,
|
||||||
private val outputOrientation: Orientation
|
private val outputOrientation: Orientation
|
||||||
@ -138,26 +135,6 @@ class PhotoCaptureRequest(
|
|||||||
val targetOrientation = outputOrientation.toSensorRelativeOrientation(deviceDetails)
|
val targetOrientation = outputOrientation.toSensorRelativeOrientation(deviceDetails)
|
||||||
builder.set(CaptureRequest.JPEG_ORIENTATION, targetOrientation.toDegrees())
|
builder.set(CaptureRequest.JPEG_ORIENTATION, targetOrientation.toDegrees())
|
||||||
|
|
||||||
// TODO: Fix flash.
|
|
||||||
when (flash) {
|
|
||||||
// Set the Flash Mode
|
|
||||||
Flash.OFF -> {
|
|
||||||
builder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON)
|
|
||||||
builder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF)
|
|
||||||
}
|
|
||||||
Flash.ON -> {
|
|
||||||
builder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON)
|
|
||||||
builder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_TORCH)
|
|
||||||
}
|
|
||||||
Flash.AUTO -> {
|
|
||||||
if (enableRedEyeReduction) {
|
|
||||||
builder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE)
|
|
||||||
} else {
|
|
||||||
builder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set stabilization for this Frame
|
// Set stabilization for this Frame
|
||||||
if (enableAutoStabilization) {
|
if (enableAutoStabilization) {
|
||||||
if (deviceDetails.opticalStabilizationModes.contains(CameraCharacteristics.LENS_OPTICAL_STABILIZATION_MODE_ON)) {
|
if (deviceDetails.opticalStabilizationModes.contains(CameraCharacteristics.LENS_OPTICAL_STABILIZATION_MODE_ON)) {
|
||||||
|
@ -11,6 +11,7 @@ import com.mrousavy.camera.core.InvalidVideoStabilizationMode
|
|||||||
import com.mrousavy.camera.core.PropRequiresFormatToBeNonNullError
|
import com.mrousavy.camera.core.PropRequiresFormatToBeNonNullError
|
||||||
import com.mrousavy.camera.core.outputs.SurfaceOutput
|
import com.mrousavy.camera.core.outputs.SurfaceOutput
|
||||||
import com.mrousavy.camera.types.CameraDeviceFormat
|
import com.mrousavy.camera.types.CameraDeviceFormat
|
||||||
|
import com.mrousavy.camera.types.HardwareLevel
|
||||||
import com.mrousavy.camera.types.Torch
|
import com.mrousavy.camera.types.Torch
|
||||||
import com.mrousavy.camera.types.VideoStabilizationMode
|
import com.mrousavy.camera.types.VideoStabilizationMode
|
||||||
|
|
||||||
@ -51,7 +52,9 @@ class RepeatingCaptureRequest(
|
|||||||
): CaptureRequest.Builder {
|
): CaptureRequest.Builder {
|
||||||
val builder = super.createCaptureRequest(template, device, deviceDetails, outputs)
|
val builder = super.createCaptureRequest(template, device, deviceDetails, outputs)
|
||||||
|
|
||||||
builder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO)
|
if (deviceDetails.modes.contains(CameraCharacteristics.CONTROL_MODE_AUTO)) {
|
||||||
|
builder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO)
|
||||||
|
}
|
||||||
|
|
||||||
// Set AF
|
// Set AF
|
||||||
if (enableVideoPipeline && deviceDetails.afModes.contains(CameraCharacteristics.CONTROL_AF_MODE_CONTINUOUS_VIDEO)) {
|
if (enableVideoPipeline && deviceDetails.afModes.contains(CameraCharacteristics.CONTROL_AF_MODE_CONTINUOUS_VIDEO)) {
|
||||||
@ -95,7 +98,11 @@ class RepeatingCaptureRequest(
|
|||||||
builder.set(CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE, getBestDigitalStabilizationMode(deviceDetails))
|
builder.set(CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE, getBestDigitalStabilizationMode(deviceDetails))
|
||||||
}
|
}
|
||||||
VideoStabilizationMode.CINEMATIC, VideoStabilizationMode.CINEMATIC_EXTENDED -> {
|
VideoStabilizationMode.CINEMATIC, VideoStabilizationMode.CINEMATIC_EXTENDED -> {
|
||||||
builder.set(CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE, CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE_ON)
|
if (deviceDetails.hardwareLevel.isAtLeast(HardwareLevel.LIMITED)) {
|
||||||
|
builder.set(CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE, CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE_ON)
|
||||||
|
} else {
|
||||||
|
builder.set(CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE, getBestDigitalStabilizationMode(deviceDetails))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else -> throw InvalidVideoStabilizationMode(videoStabilizationMode)
|
else -> throw InvalidVideoStabilizationMode(videoStabilizationMode)
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,18 @@
|
|||||||
package com.mrousavy.camera.extensions
|
package com.mrousavy.camera.extensions
|
||||||
|
|
||||||
import android.hardware.camera2.CameraCharacteristics
|
|
||||||
import android.hardware.camera2.CaptureRequest
|
import android.hardware.camera2.CaptureRequest
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.util.Range
|
import com.mrousavy.camera.core.CameraDeviceDetails
|
||||||
|
import com.mrousavy.camera.types.HardwareLevel
|
||||||
|
|
||||||
fun CaptureRequest.Builder.setZoom(zoom: Float, cameraCharacteristics: CameraCharacteristics) {
|
fun CaptureRequest.Builder.setZoom(zoom: Float, deviceDetails: CameraDeviceDetails) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
val zoomRange = deviceDetails.zoomRange
|
||||||
val zoomRange = cameraCharacteristics.get(CameraCharacteristics.CONTROL_ZOOM_RATIO_RANGE) ?: Range(1f, 1f)
|
val zoomClamped = zoomRange.clamp(zoom)
|
||||||
val zoomClamped = zoomRange.clamp(zoom)
|
|
||||||
|
if (deviceDetails.hardwareLevel.isAtLeast(HardwareLevel.LIMITED) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
this.set(CaptureRequest.CONTROL_ZOOM_RATIO, zoomClamped)
|
this.set(CaptureRequest.CONTROL_ZOOM_RATIO, zoomClamped)
|
||||||
} else {
|
} else {
|
||||||
val maxZoom = cameraCharacteristics.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM)
|
val size = deviceDetails.activeSize
|
||||||
val zoomRange = Range(1f, maxZoom ?: 1f)
|
|
||||||
val size = cameraCharacteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE)!!
|
|
||||||
val zoomClamped = zoomRange.clamp(zoom)
|
|
||||||
this.set(CaptureRequest.SCALER_CROP_REGION, size.zoomed(zoomClamped))
|
this.set(CaptureRequest.SCALER_CROP_REGION, size.zoomed(zoomClamped))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user