From 0d21bc3a579ba8cc31be4c299a5a03a1e807124f Mon Sep 17 00:00:00 2001 From: Marc Rousavy Date: Mon, 8 Jan 2024 11:41:57 +0100 Subject: [PATCH] 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 --- .../mrousavy/camera/CameraDevicesManager.kt | 4 +- .../java/com/mrousavy/camera/CameraView.kt | 25 +- .../camera/core/CameraConfiguration.kt | 28 +- .../com/mrousavy/camera/core/CameraError.kt | 4 +- .../com/mrousavy/camera/core/CameraSession.kt | 328 ++++++++++-------- .../com/mrousavy/camera/core/PreviewView.kt | 20 +- .../mrousavy/camera/core/RecordingSession.kt | 1 + .../camera/core/outputs/PhotoOutput.kt | 10 +- .../camera/core/outputs/SurfaceOutput.kt | 2 +- .../core/outputs/VideoPipelineOutput.kt | 2 +- .../CameraDevice+createCaptureSession.kt | 21 +- .../extensions/CameraManager+openCamera.kt | 12 +- .../com/mrousavy/camera/types/PixelFormat.kt | 8 +- .../mrousavy/camera/utils/ImageFormatUtils.kt | 28 ++ package/ios/CameraView.swift | 13 +- package/ios/Core/CameraSession.swift | 30 +- 16 files changed, 297 insertions(+), 239 deletions(-) create mode 100644 package/android/src/main/java/com/mrousavy/camera/utils/ImageFormatUtils.kt diff --git a/package/android/src/main/java/com/mrousavy/camera/CameraDevicesManager.kt b/package/android/src/main/java/com/mrousavy/camera/CameraDevicesManager.kt index 978d988..abf3b08 100644 --- a/package/android/src/main/java/com/mrousavy/camera/CameraDevicesManager.kt +++ b/package/android/src/main/java/com/mrousavy/camera/CameraDevicesManager.kt @@ -30,7 +30,7 @@ class CameraDevicesManager(private val reactContext: ReactApplicationContext) : } override fun onCameraAvailable(cameraId: String) { - Log.i(TAG, "Camera #$cameraId: Available!") + Log.i(TAG, "Camera #$cameraId is now available.") if (!devices.contains(cameraId)) { devices.add(cameraId) sendAvailableDevicesChangedEvent() @@ -38,7 +38,7 @@ class CameraDevicesManager(private val reactContext: ReactApplicationContext) : } override fun onCameraUnavailable(cameraId: String) { - Log.i(TAG, "Camera #$cameraId: Unavailable!") + Log.i(TAG, "Camera #$cameraId is now unavailable.") if (devices.contains(cameraId) && !isDeviceConnected(cameraId)) { devices.remove(cameraId) sendAvailableDevicesChangedEvent() diff --git a/package/android/src/main/java/com/mrousavy/camera/CameraView.kt b/package/android/src/main/java/com/mrousavy/camera/CameraView.kt index 8337831..4d67098 100644 --- a/package/android/src/main/java/com/mrousavy/camera/CameraView.kt +++ b/package/android/src/main/java/com/mrousavy/camera/CameraView.kt @@ -47,14 +47,6 @@ class CameraView(context: Context) : // react properties // props that require reconfiguring var cameraId: String? = null - set(value) { - if (value != null) { - // TODO: Move this into CameraSession - val f = if (format != null) CameraDeviceFormat.fromJSValue(format!!) else null - previewView.resizeToInputCamera(value, cameraManager, f) - } - field = value - } var enableDepthData = false var enableHighQualityPhotos: Boolean? = null var enablePortraitEffectsMatteDelivery = false @@ -101,6 +93,7 @@ class CameraView(context: Context) : // session internal val cameraSession: CameraSession private val previewView: PreviewView + private var currentConfigureCall: Long = System.currentTimeMillis() internal var frameProcessor: FrameProcessor? = null set(value) { @@ -138,15 +131,24 @@ class CameraView(context: Context) : fun update() { Log.i(TAG, "Updating CameraSession...") + val now = System.currentTimeMillis() + currentConfigureCall = now launch { cameraSession.configure { config -> + if (currentConfigureCall != now) { + // 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. + Log.i(TAG, "A new configure { ... } call arrived, aborting this one...") + return@configure + } + // Input Camera Device config.cameraId = cameraId // Photo if (photo == true) { - config.photo = CameraConfiguration.Output.Enabled.create(CameraConfiguration.Photo(Unit)) + config.photo = CameraConfiguration.Output.Enabled.create(CameraConfiguration.Photo(photoHdr)) } else { config.photo = CameraConfiguration.Output.Disabled.create() } @@ -155,6 +157,7 @@ class CameraView(context: Context) : if (video == true || enableFrameProcessor) { config.video = CameraConfiguration.Output.Enabled.create( CameraConfiguration.Video( + videoHdr, pixelFormat, enableFrameProcessor ) @@ -183,10 +186,6 @@ class CameraView(context: Context) : // Orientation config.orientation = orientation - // HDR - config.videoHdr = videoHdr - config.photoHdr = photoHdr - // Format val format = format if (format != null) { diff --git a/package/android/src/main/java/com/mrousavy/camera/core/CameraConfiguration.kt b/package/android/src/main/java/com/mrousavy/camera/core/CameraConfiguration.kt index ae75ece..a948b41 100644 --- a/package/android/src/main/java/com/mrousavy/camera/core/CameraConfiguration.kt +++ b/package/android/src/main/java/com/mrousavy/camera/core/CameraConfiguration.kt @@ -18,10 +18,6 @@ data class CameraConfiguration( var video: Output