perf: Fix double configuration flicker on fast device change (#2537)
* fix: Fix double configuration on device change Fixes a situation that happened on every device change (or initial mount) where the device was configured after the session, separately, instead of just all at once causing an additonal delay/flicker of the prevjew. * Try? * Format * Update CameraSession.swift * Use `defer` * Throw `.device`
This commit is contained in:
parent
919e6c9fe8
commit
b3a88278de
@ -117,51 +117,64 @@ class CameraSession: NSObject, AVCaptureVideoDataOutputSampleBufferDelegate, AVC
|
|||||||
do {
|
do {
|
||||||
// If needed, configure the AVCaptureSession (inputs, outputs)
|
// If needed, configure the AVCaptureSession (inputs, outputs)
|
||||||
if difference.isSessionConfigurationDirty {
|
if difference.isSessionConfigurationDirty {
|
||||||
try self.withSessionLock {
|
self.captureSession.beginConfiguration()
|
||||||
// 1. Update input device
|
|
||||||
if difference.inputChanged {
|
// 1. Update input device
|
||||||
try self.configureDevice(configuration: config)
|
if difference.inputChanged {
|
||||||
}
|
try self.configureDevice(configuration: config)
|
||||||
// 2. Update outputs
|
|
||||||
if difference.outputsChanged {
|
|
||||||
try self.configureOutputs(configuration: config)
|
|
||||||
}
|
|
||||||
// 3. Update Video Stabilization
|
|
||||||
if difference.videoStabilizationChanged {
|
|
||||||
self.configureVideoStabilization(configuration: config)
|
|
||||||
}
|
|
||||||
// 4. Update output orientation
|
|
||||||
if difference.orientationChanged {
|
|
||||||
self.configureOrientation(configuration: config)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// 2. Update outputs
|
||||||
|
if difference.outputsChanged {
|
||||||
|
try self.configureOutputs(configuration: config)
|
||||||
|
}
|
||||||
|
// 3. Update Video Stabilization
|
||||||
|
if difference.videoStabilizationChanged {
|
||||||
|
self.configureVideoStabilization(configuration: config)
|
||||||
|
}
|
||||||
|
// 4. Update output orientation
|
||||||
|
if difference.orientationChanged {
|
||||||
|
self.configureOrientation(configuration: config)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let device = self.videoDeviceInput?.device else {
|
||||||
|
throw CameraError.device(.noDevice)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If needed, configure the AVCaptureDevice (format, zoom, low-light-boost, ..)
|
// If needed, configure the AVCaptureDevice (format, zoom, low-light-boost, ..)
|
||||||
if difference.isDeviceConfigurationDirty {
|
if difference.isDeviceConfigurationDirty {
|
||||||
try self.withDeviceLock { device in
|
try device.lockForConfiguration()
|
||||||
// 4. Configure format
|
defer {
|
||||||
if difference.formatChanged {
|
device.unlockForConfiguration()
|
||||||
try self.configureFormat(configuration: config, device: device)
|
|
||||||
}
|
|
||||||
// 5. After step 2. and 4., we also need to configure the PixelFormat.
|
|
||||||
// This needs to be done AFTER we updated the `format`, as this controls the supported PixelFormats.
|
|
||||||
if difference.outputsChanged || difference.formatChanged {
|
|
||||||
try self.configurePixelFormat(configuration: config)
|
|
||||||
}
|
|
||||||
// 6. Configure side-props (fps, lowLightBoost)
|
|
||||||
if difference.sidePropsChanged {
|
|
||||||
try self.configureSideProps(configuration: config, device: device)
|
|
||||||
}
|
|
||||||
// 7. Configure zoom
|
|
||||||
if difference.zoomChanged {
|
|
||||||
self.configureZoom(configuration: config, device: device)
|
|
||||||
}
|
|
||||||
// 8. Configure exposure bias
|
|
||||||
if difference.exposureChanged {
|
|
||||||
self.configureExposure(configuration: config, device: device)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 4. Configure format
|
||||||
|
if difference.formatChanged {
|
||||||
|
try self.configureFormat(configuration: config, device: device)
|
||||||
|
}
|
||||||
|
// 5. After step 2. and 4., we also need to configure the PixelFormat.
|
||||||
|
// This needs to be done AFTER we updated the `format`, as this controls the supported PixelFormats.
|
||||||
|
if difference.outputsChanged || difference.formatChanged {
|
||||||
|
try self.configurePixelFormat(configuration: config)
|
||||||
|
}
|
||||||
|
// 6. Configure side-props (fps, lowLightBoost)
|
||||||
|
if difference.sidePropsChanged {
|
||||||
|
try self.configureSideProps(configuration: config, device: device)
|
||||||
|
}
|
||||||
|
// 7. Configure zoom
|
||||||
|
if difference.zoomChanged {
|
||||||
|
self.configureZoom(configuration: config, device: device)
|
||||||
|
}
|
||||||
|
// 8. Configure exposure bias
|
||||||
|
if difference.exposureChanged {
|
||||||
|
self.configureExposure(configuration: config, device: device)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if difference.isSessionConfigurationDirty {
|
||||||
|
// We commit the session config updates AFTER the device config,
|
||||||
|
// that way we can also batch those changes into one update instead of doing two updates.
|
||||||
|
self.captureSession.commitConfiguration()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 9. Start or stop the session if needed
|
// 9. Start or stop the session if needed
|
||||||
@ -169,9 +182,11 @@ class CameraSession: NSObject, AVCaptureVideoDataOutputSampleBufferDelegate, AVC
|
|||||||
|
|
||||||
// 10. Enable or disable the Torch if needed (requires session to be running)
|
// 10. Enable or disable the Torch if needed (requires session to be running)
|
||||||
if difference.torchChanged {
|
if difference.torchChanged {
|
||||||
try self.withDeviceLock { device in
|
try device.lockForConfiguration()
|
||||||
try self.configureTorch(configuration: config, device: device)
|
defer {
|
||||||
|
device.unlockForConfiguration()
|
||||||
}
|
}
|
||||||
|
try self.configureTorch(configuration: config, device: device)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify about Camera initialization
|
// Notify about Camera initialization
|
||||||
@ -206,41 +221,6 @@ class CameraSession: NSObject, AVCaptureVideoDataOutputSampleBufferDelegate, AVC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
Runs the given [lambda] under an AVCaptureSession configuration lock (`beginConfiguration()`)
|
|
||||||
*/
|
|
||||||
private func withSessionLock(_ lambda: () throws -> Void) throws {
|
|
||||||
// Lock Capture Session for configuration
|
|
||||||
ReactLogger.log(level: .info, message: "Beginning CameraSession configuration...")
|
|
||||||
captureSession.beginConfiguration()
|
|
||||||
defer {
|
|
||||||
// Unlock Capture Session again and submit configuration to Hardware
|
|
||||||
self.captureSession.commitConfiguration()
|
|
||||||
ReactLogger.log(level: .info, message: "Committed CameraSession configuration!")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call lambda
|
|
||||||
try lambda()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Runs the given [lambda] under an AVCaptureDevice configuration lock (`lockForConfiguration()`)
|
|
||||||
*/
|
|
||||||
private func withDeviceLock(_ lambda: (_ device: AVCaptureDevice) throws -> Void) throws {
|
|
||||||
guard let device = videoDeviceInput?.device else {
|
|
||||||
throw CameraError.session(.cameraNotReady)
|
|
||||||
}
|
|
||||||
ReactLogger.log(level: .info, message: "Beginning CaptureDevice configuration...")
|
|
||||||
try device.lockForConfiguration()
|
|
||||||
defer {
|
|
||||||
device.unlockForConfiguration()
|
|
||||||
ReactLogger.log(level: .info, message: "Committed CaptureDevice configuration!")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call lambda with Device
|
|
||||||
try lambda(device)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Starts or stops the CaptureSession if needed (`isActive`)
|
Starts or stops the CaptureSession if needed (`isActive`)
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user