feat: Concurrent/Cancellable configure (#2282)

* feat: Cancellable `configure`

* Android

* Update Podfile.lock

* Configure outside of lock

* Update lockfiles

* Use `bundle` for CI

* Update script

* Update Podfile.lock

* fix: Set config at end

* Lint
This commit is contained in:
Marc Rousavy
2023-12-13 16:38:02 +01:00
committed by GitHub
parent 5a81fabedd
commit 977bf56c6d
9 changed files with 4362 additions and 5059 deletions

View File

@@ -16,6 +16,7 @@ import Foundation
class CameraSession: NSObject, AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureAudioDataOutputSampleBufferDelegate {
// Configuration
var configuration: CameraConfiguration?
var currentConfigureCall: DispatchTime = .now()
// Capture Session
let captureSession = AVCaptureSession()
let audioCaptureSession = AVCaptureSession()
@@ -98,6 +99,10 @@ class CameraSession: NSObject, AVCaptureVideoDataOutputSampleBufferDelegate, AVC
The `configuration` object is a copy of the currently active configuration that can be modified by the caller in the lambda.
*/
func configure(_ lambda: (_ configuration: CameraConfiguration) throws -> Void) {
// This is the latest call to configure()
let time = DispatchTime.now()
currentConfigureCall = time
ReactLogger.log(level: .info, message: "Updating Session Configuration...")
// Let caller configure a new configuration for the Camera.
@@ -109,8 +114,14 @@ class CameraSession: NSObject, AVCaptureVideoDataOutputSampleBufferDelegate, AVC
}
let difference = CameraConfiguration.Difference(between: configuration, and: config)
// Set up Camera (Video) Capture Session (on camera queue)
// Set up Camera (Video) Capture Session (on camera queue, acts like a lock)
CameraQueues.cameraQueue.async {
// Cancel configuration if there has already been a new config
guard self.currentConfigureCall == time else {
// configure() has been called again just now, skip this one so the new call takes over.
return
}
do {
// If needed, configure the AVCaptureSession (inputs, outputs)
if difference.isSessionConfigurationDirty {
@@ -175,32 +186,32 @@ class CameraSession: NSObject, AVCaptureVideoDataOutputSampleBufferDelegate, AVC
if difference.inputChanged {
self.delegate?.onSessionInitialized()
}
// After configuring, set this to the new configuration.
self.configuration = config
} catch {
self.onConfigureError(error)
}
}
// Set up Audio Capture Session (on audio queue)
if difference.audioSessionChanged {
CameraQueues.audioQueue.async {
do {
// Lock Capture Session for configuration
ReactLogger.log(level: .info, message: "Beginning AudioSession configuration...")
self.audioCaptureSession.beginConfiguration()
// Set up Audio Capture Session (on audio queue)
if difference.audioSessionChanged {
CameraQueues.audioQueue.async {
do {
// Lock Capture Session for configuration
ReactLogger.log(level: .info, message: "Beginning AudioSession configuration...")
self.audioCaptureSession.beginConfiguration()
try self.configureAudioSession(configuration: config)
try self.configureAudioSession(configuration: config)
// Unlock Capture Session again and submit configuration to Hardware
self.audioCaptureSession.commitConfiguration()
ReactLogger.log(level: .info, message: "Committed AudioSession configuration!")
} catch {
self.onConfigureError(error)
// Unlock Capture Session again and submit configuration to Hardware
self.audioCaptureSession.commitConfiguration()
ReactLogger.log(level: .info, message: "Committed AudioSession configuration!")
} catch {
self.onConfigureError(error)
}
}
}
}
// After configuring, set this to the new configuration.
configuration = config
}
/**