From 8c5b60355f5dd3ae01bf4f06fc53e2f43650b997 Mon Sep 17 00:00:00 2001 From: Marc Rousavy Date: Tue, 30 Jan 2024 14:26:55 +0100 Subject: [PATCH] perf: Use existing `cameraQueue` instead of yet another Thread (#2459) * perf: Use existing `cameraQueue` instead of yet another Thread * fix: Use `coroutineScope` to avoid wrong use of isActive * fix: Do the same for `CameraSession` * Lint --- .../src/main/java/com/mrousavy/camera/CameraView.kt | 6 ++---- .../main/java/com/mrousavy/camera/CameraViewModule.kt | 3 ++- .../java/com/mrousavy/camera/core/CameraSession.kt | 11 ++++------- 3 files changed, 8 insertions(+), 12 deletions(-) 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 b59af02..ff2b514 100644 --- a/package/android/src/main/java/com/mrousavy/camera/CameraView.kt +++ b/package/android/src/main/java/com/mrousavy/camera/CameraView.kt @@ -23,7 +23,6 @@ import com.mrousavy.camera.types.PixelFormat import com.mrousavy.camera.types.ResizeMode import com.mrousavy.camera.types.Torch import com.mrousavy.camera.types.VideoStabilizationMode -import kotlin.coroutines.CoroutineContext import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch @@ -39,7 +38,6 @@ import kotlinx.coroutines.launch @SuppressLint("ClickableViewAccessibility", "ViewConstructor", "MissingPermission") class CameraView(context: Context) : FrameLayout(context), - CoroutineScope, CameraSession.Callback { companion object { const val TAG = "CameraView" @@ -98,7 +96,7 @@ class CameraView(context: Context) : internal var frameProcessor: FrameProcessor? = null - override val coroutineContext: CoroutineContext = CameraQueues.cameraQueue.coroutineDispatcher + private val coroutineScope = CoroutineScope(CameraQueues.cameraQueue.coroutineDispatcher) init { this.installHierarchyFitter() @@ -131,7 +129,7 @@ class CameraView(context: Context) : val now = System.currentTimeMillis() currentConfigureCall = now - launch { + coroutineScope.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. diff --git a/package/android/src/main/java/com/mrousavy/camera/CameraViewModule.kt b/package/android/src/main/java/com/mrousavy/camera/CameraViewModule.kt index b422815..9b9d909 100644 --- a/package/android/src/main/java/com/mrousavy/camera/CameraViewModule.kt +++ b/package/android/src/main/java/com/mrousavy/camera/CameraViewModule.kt @@ -10,6 +10,7 @@ import com.facebook.react.modules.core.PermissionAwareActivity import com.facebook.react.modules.core.PermissionListener import com.facebook.react.uimanager.UIManagerHelper import com.mrousavy.camera.core.CameraError +import com.mrousavy.camera.core.CameraQueues import com.mrousavy.camera.core.ViewNotFoundError import com.mrousavy.camera.frameprocessor.VisionCameraInstaller import com.mrousavy.camera.frameprocessor.VisionCameraProxy @@ -39,7 +40,7 @@ class CameraViewModule(reactContext: ReactApplicationContext) : ReactContextBase } } - private val coroutineScope = CoroutineScope(Dispatchers.Default) // TODO: or Dispatchers.Main? + private val coroutineScope = CoroutineScope(CameraQueues.cameraQueue.coroutineDispatcher) override fun invalidate() { super.invalidate() diff --git a/package/android/src/main/java/com/mrousavy/camera/core/CameraSession.kt b/package/android/src/main/java/com/mrousavy/camera/core/CameraSession.kt index 0fef58e..5b8d76e 100644 --- a/package/android/src/main/java/com/mrousavy/camera/core/CameraSession.kt +++ b/package/android/src/main/java/com/mrousavy/camera/core/CameraSession.kt @@ -49,7 +49,6 @@ import com.mrousavy.camera.utils.ImageFormatUtils import java.io.Closeable import java.lang.IllegalStateException import java.util.concurrent.CancellationException -import kotlin.coroutines.CoroutineContext import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking @@ -58,8 +57,7 @@ import kotlinx.coroutines.sync.withLock class CameraSession(private val context: Context, private val cameraManager: CameraManager, private val callback: Callback) : CameraManager.AvailabilityCallback(), - Closeable, - CoroutineScope { + Closeable { companion object { private const val TAG = "CameraSession" } @@ -95,8 +93,7 @@ class CameraSession(private val context: Context, private val cameraManager: Cam field = value } - override val coroutineContext: CoroutineContext - get() = CameraQueues.cameraQueue.coroutineDispatcher + private val coroutineScope = CoroutineScope(CameraQueues.cameraQueue.coroutineDispatcher) // Video Outputs private var recording: RecordingSession? = null @@ -139,7 +136,7 @@ class CameraSession(private val context: Context, private val cameraManager: Cam super.onCameraAvailable(cameraId) if (this.configuration?.cameraId == cameraId && cameraDevice == null && configuration?.isActive == true) { Log.i(TAG, "Camera #$cameraId is now available again, trying to re-open it now...") - launch { + coroutineScope.launch { configure { // re-open CameraDevice if needed } @@ -252,7 +249,7 @@ class CameraSession(private val context: Context, private val cameraManager: Cam private fun createPreviewOutput(surface: Surface) { Log.i(TAG, "Setting Preview Output...") - launch { + coroutineScope.launch { configure { config -> config.preview = CameraConfiguration.Output.Enabled.create(CameraConfiguration.Preview(surface)) }