fix: Fix blackscreen issues and lifecycle when closing Camera (#2339)
* fix: Fix Blackscreen by deterministically destroying session if `isActive=false`
* Re-open Camera if session died
* Simplify Camera
* Disconnect is optional, block when resetting state
* fix: Log in `configure { ... }`
* fix: Make concurrent configure safe
* fix: Don't resize preview
* fix: Use current `CameraConfiguration`
* Don't start if no outputs are available
* Only mount with preview outputs
* Update CameraSession.kt
* Update PreviewView.kt
* Better logging
* Update CameraSession.kt
* Extract
* fix: Rebuild entire session if `isActive` changed
* isActive safe
* Start session at 1
* Create ActiveCameraDevice.kt
* interrupts
* chore: Freeze `frame` in `useFrameProcessor`
* Revert "chore: Freeze `frame` in `useFrameProcessor`"
This reverts commit dff93d506e29a791d8dea8842b880ab5c892211e.
* chore: Better logging
* fix: Move HDR to `video`/`photo` config
* fix: Fix hdr usage
* fix: Ignore any updates after destroying Camera
* fix: Fix video HDR
* chore: Format code
* fix: Check Camera permission
* Remove unneeded error
* Update CameraSession.kt
* Update CameraPage.tsx
* Delete OutputConfiguration.toDebugString.kt
* Update CameraSession.kt
This commit is contained in:
@@ -84,6 +84,7 @@ public final class CameraView: UIView, CameraSessionDelegate {
|
||||
// CameraView+Zoom
|
||||
var pinchGestureRecognizer: UIPinchGestureRecognizer?
|
||||
var pinchScaleOffset: CGFloat = 1.0
|
||||
private var currentConfigureCall: DispatchTime?
|
||||
|
||||
var previewView: PreviewView
|
||||
#if DEBUG
|
||||
@@ -150,8 +151,18 @@ public final class CameraView: UIView, CameraSessionDelegate {
|
||||
// pragma MARK: Props updating
|
||||
override public final func didSetProps(_ changedProps: [String]!) {
|
||||
ReactLogger.log(level: .info, message: "Updating \(changedProps.count) props: [\(changedProps.joined(separator: ", "))]")
|
||||
let now = DispatchTime.now()
|
||||
currentConfigureCall = now
|
||||
|
||||
cameraSession.configure { [self] config in
|
||||
// Check if we're still the latest call to configure { ... }
|
||||
guard currentConfigureCall == now else {
|
||||
// configure waits for a lock, and if a new call to update() happens in the meantime we can drop this one.
|
||||
// this works similar to how React implemented concurrent rendering, the newer call to update() has higher priority.
|
||||
ReactLogger.log(level: .info, message: "A new configure { ... } call arrived, aborting this one...")
|
||||
return
|
||||
}
|
||||
|
||||
cameraSession.configure { config in
|
||||
// Input Camera Device
|
||||
config.cameraId = cameraId as? String
|
||||
|
||||
|
||||
@@ -98,29 +98,21 @@ class CameraSession: NSObject, AVCaptureVideoDataOutputSampleBufferDelegate, AVC
|
||||
Any changes in here will be re-configured only if required, and under a lock.
|
||||
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.
|
||||
let config = CameraConfiguration(copyOf: configuration)
|
||||
do {
|
||||
try lambda(config)
|
||||
} catch {
|
||||
onConfigureError(error)
|
||||
}
|
||||
let difference = CameraConfiguration.Difference(between: configuration, and: config)
|
||||
func configure(_ lambda: @escaping (_ configuration: CameraConfiguration) throws -> Void) {
|
||||
ReactLogger.log(level: .info, message: "configure { ... }: Waiting for lock...")
|
||||
|
||||
// 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
|
||||
// Let caller configure a new configuration for the Camera.
|
||||
let config = CameraConfiguration(copyOf: self.configuration)
|
||||
do {
|
||||
try lambda(config)
|
||||
} catch {
|
||||
self.onConfigureError(error)
|
||||
}
|
||||
let difference = CameraConfiguration.Difference(between: self.configuration, and: config)
|
||||
|
||||
ReactLogger.log(level: .info, message: "configure { ... }: Updating CameraSession Configuration... \(difference)")
|
||||
|
||||
do {
|
||||
// If needed, configure the AVCaptureSession (inputs, outputs)
|
||||
|
||||
Reference in New Issue
Block a user