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
This commit is contained in:
Marc Rousavy 2024-01-30 14:26:55 +01:00 committed by GitHub
parent af14f912fb
commit 8c5b60355f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 8 additions and 12 deletions

View File

@ -23,7 +23,6 @@ import com.mrousavy.camera.types.PixelFormat
import com.mrousavy.camera.types.ResizeMode import com.mrousavy.camera.types.ResizeMode
import com.mrousavy.camera.types.Torch import com.mrousavy.camera.types.Torch
import com.mrousavy.camera.types.VideoStabilizationMode import com.mrousavy.camera.types.VideoStabilizationMode
import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -39,7 +38,6 @@ import kotlinx.coroutines.launch
@SuppressLint("ClickableViewAccessibility", "ViewConstructor", "MissingPermission") @SuppressLint("ClickableViewAccessibility", "ViewConstructor", "MissingPermission")
class CameraView(context: Context) : class CameraView(context: Context) :
FrameLayout(context), FrameLayout(context),
CoroutineScope,
CameraSession.Callback { CameraSession.Callback {
companion object { companion object {
const val TAG = "CameraView" const val TAG = "CameraView"
@ -98,7 +96,7 @@ class CameraView(context: Context) :
internal var frameProcessor: FrameProcessor? = null internal var frameProcessor: FrameProcessor? = null
override val coroutineContext: CoroutineContext = CameraQueues.cameraQueue.coroutineDispatcher private val coroutineScope = CoroutineScope(CameraQueues.cameraQueue.coroutineDispatcher)
init { init {
this.installHierarchyFitter() this.installHierarchyFitter()
@ -131,7 +129,7 @@ class CameraView(context: Context) :
val now = System.currentTimeMillis() val now = System.currentTimeMillis()
currentConfigureCall = now currentConfigureCall = now
launch { coroutineScope.launch {
cameraSession.configure { config -> cameraSession.configure { config ->
if (currentConfigureCall != now) { if (currentConfigureCall != now) {
// configure waits for a lock, and if a new call to update() happens in the meantime we can drop this one. // configure waits for a lock, and if a new call to update() happens in the meantime we can drop this one.

View File

@ -10,6 +10,7 @@ import com.facebook.react.modules.core.PermissionAwareActivity
import com.facebook.react.modules.core.PermissionListener import com.facebook.react.modules.core.PermissionListener
import com.facebook.react.uimanager.UIManagerHelper import com.facebook.react.uimanager.UIManagerHelper
import com.mrousavy.camera.core.CameraError import com.mrousavy.camera.core.CameraError
import com.mrousavy.camera.core.CameraQueues
import com.mrousavy.camera.core.ViewNotFoundError import com.mrousavy.camera.core.ViewNotFoundError
import com.mrousavy.camera.frameprocessor.VisionCameraInstaller import com.mrousavy.camera.frameprocessor.VisionCameraInstaller
import com.mrousavy.camera.frameprocessor.VisionCameraProxy 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() { override fun invalidate() {
super.invalidate() super.invalidate()

View File

@ -49,7 +49,6 @@ import com.mrousavy.camera.utils.ImageFormatUtils
import java.io.Closeable import java.io.Closeable
import java.lang.IllegalStateException import java.lang.IllegalStateException
import java.util.concurrent.CancellationException import java.util.concurrent.CancellationException
import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking 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) : class CameraSession(private val context: Context, private val cameraManager: CameraManager, private val callback: Callback) :
CameraManager.AvailabilityCallback(), CameraManager.AvailabilityCallback(),
Closeable, Closeable {
CoroutineScope {
companion object { companion object {
private const val TAG = "CameraSession" private const val TAG = "CameraSession"
} }
@ -95,8 +93,7 @@ class CameraSession(private val context: Context, private val cameraManager: Cam
field = value field = value
} }
override val coroutineContext: CoroutineContext private val coroutineScope = CoroutineScope(CameraQueues.cameraQueue.coroutineDispatcher)
get() = CameraQueues.cameraQueue.coroutineDispatcher
// Video Outputs // Video Outputs
private var recording: RecordingSession? = null private var recording: RecordingSession? = null
@ -139,7 +136,7 @@ class CameraSession(private val context: Context, private val cameraManager: Cam
super.onCameraAvailable(cameraId) super.onCameraAvailable(cameraId)
if (this.configuration?.cameraId == cameraId && cameraDevice == null && configuration?.isActive == true) { 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...") Log.i(TAG, "Camera #$cameraId is now available again, trying to re-open it now...")
launch { coroutineScope.launch {
configure { configure {
// re-open CameraDevice if needed // re-open CameraDevice if needed
} }
@ -252,7 +249,7 @@ class CameraSession(private val context: Context, private val cameraManager: Cam
private fun createPreviewOutput(surface: Surface) { private fun createPreviewOutput(surface: Surface) {
Log.i(TAG, "Setting Preview Output...") Log.i(TAG, "Setting Preview Output...")
launch { coroutineScope.launch {
configure { config -> configure { config ->
config.preview = CameraConfiguration.Output.Enabled.create(CameraConfiguration.Preview(surface)) config.preview = CameraConfiguration.Output.Enabled.create(CameraConfiguration.Preview(surface))
} }