feat: Make Reanimated optional (disable Frame Processors if REA v2 is not installed) (#412)

* Fix building iOS without Reanimated

* Conditionally compile Frame Processors (gradle)

* Conditionally use externalNativeBuild

* Remove Reanimated import

* fix: Conditionally load REA/VisionCamera libraries

* fix: Add disable FP to docs

* fix: Fix dummy placeholder for Scheduler.mm

* fix: Fix dummy `Scheduler` declaration

* fix: Only init `CameraView` C++ side if frame processors are enabled

* fix: Install JSI Bindings on Frame Processor Manager ctor

* fix: Wrong conditional

* whoops
This commit is contained in:
Marc Rousavy
2022-01-02 17:35:26 +01:00
committed by GitHub
parent 77e065d961
commit be5ec69b02
10 changed files with 316 additions and 267 deletions

View File

@@ -26,6 +26,7 @@ import com.facebook.proguard.annotations.DoNotStrip
import com.facebook.react.bridge.*
import com.facebook.react.uimanager.events.RCTEventEmitter
import com.mrousavy.camera.frameprocessor.FrameProcessorPerformanceDataCollector
import com.mrousavy.camera.frameprocessor.FrameProcessorRuntimeManager
import com.mrousavy.camera.utils.*
import kotlinx.coroutines.*
import kotlinx.coroutines.guava.await
@@ -159,7 +160,7 @@ class CameraView(context: Context, private val frameProcessorThread: ExecutorSer
}
@DoNotStrip
private var mHybridData: HybridData
private var mHybridData: HybridData? = null
@Suppress("LiftReturnOrAssignment", "RedundantIf")
internal val fallbackToSnapshot: Boolean
@@ -192,7 +193,9 @@ class CameraView(context: Context, private val frameProcessorThread: ExecutorSer
}
init {
mHybridData = initHybrid()
if (FrameProcessorRuntimeManager.enableFrameProcessors) {
mHybridData = initHybrid()
}
previewView = PreviewView(context)
previewView.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)

View File

@@ -57,10 +57,6 @@ class CameraViewModule(reactContext: ReactApplicationContext) : ReactContextBase
if (frameProcessorManager == null) {
frameProcessorThread.execute {
frameProcessorManager = FrameProcessorRuntimeManager(reactApplicationContext, frameProcessorThread)
reactApplicationContext.runOnJSQueueThread {
frameProcessorManager!!.installJSIBindings()
}
}
}
}

View File

@@ -8,7 +8,6 @@ import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.turbomodule.core.CallInvokerHolderImpl
import com.mrousavy.camera.CameraView
import com.mrousavy.camera.ViewNotFoundError
import com.swmansion.reanimated.Scheduler
import java.lang.ref.WeakReference
import java.util.concurrent.ExecutorService
@@ -17,39 +16,52 @@ class FrameProcessorRuntimeManager(context: ReactApplicationContext, frameProces
companion object {
const val TAG = "FrameProcessorRuntime"
val Plugins: ArrayList<FrameProcessorPlugin> = ArrayList()
var enableFrameProcessors = true
init {
System.loadLibrary("reanimated")
System.loadLibrary("VisionCamera")
try {
System.loadLibrary("reanimated")
System.loadLibrary("VisionCamera")
} catch (e: UnsatisfiedLinkError) {
Log.w(TAG, "Failed to load Reanimated/VisionCamera C++ library. Frame Processors are disabled!")
enableFrameProcessors = false
}
}
}
@DoNotStrip
private var mHybridData: HybridData
private var mContext: WeakReference<ReactApplicationContext>
private var mScheduler: VisionCameraScheduler
private var mHybridData: HybridData? = null
private var mContext: WeakReference<ReactApplicationContext>? = null
private var mScheduler: VisionCameraScheduler? = null
init {
val holder = context.catalystInstance.jsCallInvokerHolder as CallInvokerHolderImpl
mScheduler = VisionCameraScheduler(frameProcessorThread)
mContext = WeakReference(context)
mHybridData = initHybrid(context.javaScriptContextHolder.get(), holder, mScheduler)
initializeRuntime()
if (enableFrameProcessors) {
val holder = context.catalystInstance.jsCallInvokerHolder as CallInvokerHolderImpl
mScheduler = VisionCameraScheduler(frameProcessorThread)
mContext = WeakReference(context)
mHybridData = initHybrid(context.javaScriptContextHolder.get(), holder, mScheduler!!)
initializeRuntime()
Log.i(TAG, "Installing Frame Processor Plugins...")
Plugins.forEach { plugin ->
registerPlugin(plugin)
Log.i(TAG, "Installing Frame Processor Plugins...")
Plugins.forEach { plugin ->
registerPlugin(plugin)
}
Log.i(TAG, "Successfully installed ${Plugins.count()} Frame Processor Plugins!")
Log.i(TAG, "Installing JSI Bindings on JS Thread...")
context.runOnJSQueueThread {
installJSIBindings()
}
}
Log.i(TAG, "Successfully installed ${Plugins.count()} Frame Processor Plugins!")
}
@Suppress("unused")
@DoNotStrip
@Keep
fun findCameraViewById(viewId: Int): CameraView {
Log.d(TAG, "finding view $viewId...")
val view = mContext.get()?.currentActivity?.findViewById<CameraView>(viewId)
Log.d(TAG, "found view $viewId! is null: ${view == null}")
Log.d(TAG, "Finding view $viewId...")
val view = mContext?.get()?.currentActivity?.findViewById<CameraView>(viewId)
Log.d(TAG, if (view != null) "Found view $viewId!" else "Couldn't find view $viewId!")
return view ?: throw ViewNotFoundError(viewId)
}
@@ -61,7 +73,5 @@ class FrameProcessorRuntimeManager(context: ReactApplicationContext, frameProces
): HybridData
private external fun initializeRuntime()
private external fun registerPlugin(plugin: FrameProcessorPlugin)
// public C++ funcs
external fun installJSIBindings()
private external fun installJSIBindings()
}