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
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 316 additions and 267 deletions

View File

@ -84,6 +84,9 @@ def getExtOrIntegerDefault(name) {
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties['VisionCamera_' + name]).toInteger() return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties['VisionCamera_' + name]).toInteger()
} }
def reanimated = rootProject.subprojects.find { it.name == 'react-native-reanimated' }
def ENABLE_FRAME_PROCESSORS = !getExtOrDefault("disableFrameProcessors") && reanimated != null
android { android {
compileSdkVersion getExtOrIntegerDefault('compileSdkVersion') compileSdkVersion getExtOrIntegerDefault('compileSdkVersion')
buildToolsVersion getExtOrDefault('buildToolsVersion') buildToolsVersion getExtOrDefault('buildToolsVersion')
@ -93,6 +96,7 @@ android {
minSdkVersion 21 minSdkVersion 21
targetSdkVersion getExtOrIntegerDefault('targetSdkVersion') targetSdkVersion getExtOrIntegerDefault('targetSdkVersion')
if (ENABLE_FRAME_PROCESSORS) {
externalNativeBuild { externalNativeBuild {
cmake { cmake {
cppFlags "-fexceptions", "-frtti", "-std=c++1y", "-DONANDROID" cppFlags "-fexceptions", "-frtti", "-std=c++1y", "-DONANDROID"
@ -104,16 +108,19 @@ android {
} }
} }
} }
}
dexOptions { dexOptions {
javaMaxHeapSize "4g" javaMaxHeapSize "4g"
} }
if (ENABLE_FRAME_PROCESSORS) {
externalNativeBuild { externalNativeBuild {
cmake { cmake {
path "CMakeLists.txt" path "CMakeLists.txt"
} }
} }
}
packagingOptions { packagingOptions {
// Exclude all Libraries that are already present in the user's app (through React Native or by him installing REA) // Exclude all Libraries that are already present in the user's app (through React Native or by him installing REA)
@ -217,6 +224,8 @@ def kotlin_version = getExtOrDefault('kotlinVersion')
dependencies { dependencies {
// noinspection GradleDynamicVersion // noinspection GradleDynamicVersion
implementation 'com.facebook.react:react-native:+' implementation 'com.facebook.react:react-native:+'
if (ENABLE_FRAME_PROCESSORS) {
implementation project(':react-native-reanimated') implementation project(':react-native-reanimated')
//noinspection GradleDynamicVersion //noinspection GradleDynamicVersion
@ -236,6 +245,7 @@ dependencies {
def reaAAR = "${rootDir}/../node_modules/react-native-reanimated/android/react-native-reanimated-${minor}-${jsEngine}.aar" def reaAAR = "${rootDir}/../node_modules/react-native-reanimated/android/react-native-reanimated-${minor}-${jsEngine}.aar"
extractJNI(files(rnAAR, jscAAR, reaAAR)) extractJNI(files(rnAAR, jscAAR, reaAAR))
}
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-guava:1.5.2" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-guava:1.5.2"
@ -252,39 +262,41 @@ dependencies {
implementation "androidx.exifinterface:exifinterface:1.3.3" implementation "androidx.exifinterface:exifinterface:1.3.3"
} }
// third-party-ndk deps headers
// mostly a copy of https://github.com/software-mansion/react-native-reanimated/blob/master/android/build.gradle#L115
def downloadsDir = new File("$buildDir/downloads") if (ENABLE_FRAME_PROCESSORS) {
def thirdPartyNdkDir = new File("$buildDir/third-party-ndk") // third-party-ndk deps headers
def thirdPartyVersionsFile = new File("${rootDir}/../node_modules/react-native/ReactAndroid/gradle.properties") // mostly a copy of https://github.com/software-mansion/react-native-reanimated/blob/master/android/build.gradle#L115
def thirdPartyVersions = new Properties()
thirdPartyVersions.load(new FileInputStream(thirdPartyVersionsFile))
def BOOST_VERSION = thirdPartyVersions["BOOST_VERSION"] def downloadsDir = new File("$buildDir/downloads")
def boost_file = new File(downloadsDir, "boost_${BOOST_VERSION}.tar.gz") def thirdPartyNdkDir = new File("$buildDir/third-party-ndk")
def DOUBLE_CONVERSION_VERSION = thirdPartyVersions["DOUBLE_CONVERSION_VERSION"] def thirdPartyVersionsFile = new File("${rootDir}/../node_modules/react-native/ReactAndroid/gradle.properties")
def double_conversion_file = new File(downloadsDir, "double-conversion-${DOUBLE_CONVERSION_VERSION}.tar.gz") def thirdPartyVersions = new Properties()
def FOLLY_VERSION = thirdPartyVersions["FOLLY_VERSION"] thirdPartyVersions.load(new FileInputStream(thirdPartyVersionsFile))
def folly_file = new File(downloadsDir, "folly-${FOLLY_VERSION}.tar.gz")
def GLOG_VERSION = thirdPartyVersions["GLOG_VERSION"]
def glog_file = new File(downloadsDir, "glog-${GLOG_VERSION}.tar.gz")
task createNativeDepsDirectories { def BOOST_VERSION = thirdPartyVersions["BOOST_VERSION"]
def boost_file = new File(downloadsDir, "boost_${BOOST_VERSION}.tar.gz")
def DOUBLE_CONVERSION_VERSION = thirdPartyVersions["DOUBLE_CONVERSION_VERSION"]
def double_conversion_file = new File(downloadsDir, "double-conversion-${DOUBLE_CONVERSION_VERSION}.tar.gz")
def FOLLY_VERSION = thirdPartyVersions["FOLLY_VERSION"]
def folly_file = new File(downloadsDir, "folly-${FOLLY_VERSION}.tar.gz")
def GLOG_VERSION = thirdPartyVersions["GLOG_VERSION"]
def glog_file = new File(downloadsDir, "glog-${GLOG_VERSION}.tar.gz")
task createNativeDepsDirectories {
doLast { doLast {
downloadsDir.mkdirs() downloadsDir.mkdirs()
thirdPartyNdkDir.mkdirs() thirdPartyNdkDir.mkdirs()
} }
} }
task downloadBoost(dependsOn: createNativeDepsDirectories, type: Download) { task downloadBoost(dependsOn: createNativeDepsDirectories, type: Download) {
src("https://github.com/react-native-community/boost-for-react-native/releases/download/v${BOOST_VERSION.replace("_", ".")}-0/boost_${BOOST_VERSION}.tar.gz") src("https://github.com/react-native-community/boost-for-react-native/releases/download/v${BOOST_VERSION.replace("_", ".")}-0/boost_${BOOST_VERSION}.tar.gz")
onlyIfNewer(true) onlyIfNewer(true)
overwrite(false) overwrite(false)
dest(boost_file) dest(boost_file)
} }
task prepareBoost(dependsOn: downloadBoost, type: Copy) { task prepareBoost(dependsOn: downloadBoost, type: Copy) {
from(tarTree(resources.gzip(downloadBoost.dest))) from(tarTree(resources.gzip(downloadBoost.dest)))
from("src/main/jni/third-party/boost/Android.mk") from("src/main/jni/third-party/boost/Android.mk")
include("Android.mk", "boost_${BOOST_VERSION}/boost/**/*.hpp", "boost/boost/**/*.hpp") include("Android.mk", "boost_${BOOST_VERSION}/boost/**/*.hpp", "boost/boost/**/*.hpp")
@ -293,48 +305,48 @@ task prepareBoost(dependsOn: downloadBoost, type: Copy) {
doLast { doLast {
file("$thirdPartyNdkDir/boost_${BOOST_VERSION}").renameTo("$thirdPartyNdkDir/boost") file("$thirdPartyNdkDir/boost_${BOOST_VERSION}").renameTo("$thirdPartyNdkDir/boost")
} }
} }
task downloadDoubleConversion(dependsOn: createNativeDepsDirectories, type: Download) { task downloadDoubleConversion(dependsOn: createNativeDepsDirectories, type: Download) {
src("https://github.com/google/double-conversion/archive/v${DOUBLE_CONVERSION_VERSION}.tar.gz") src("https://github.com/google/double-conversion/archive/v${DOUBLE_CONVERSION_VERSION}.tar.gz")
onlyIfNewer(true) onlyIfNewer(true)
overwrite(false) overwrite(false)
dest(double_conversion_file) dest(double_conversion_file)
} }
task prepareDoubleConversion(dependsOn: downloadDoubleConversion, type: Copy) { task prepareDoubleConversion(dependsOn: downloadDoubleConversion, type: Copy) {
from(tarTree(downloadDoubleConversion.dest)) from(tarTree(downloadDoubleConversion.dest))
from("src/main/jni/third-party/double-conversion/Android.mk") from("src/main/jni/third-party/double-conversion/Android.mk")
include("double-conversion-${DOUBLE_CONVERSION_VERSION}/src/**/*", "Android.mk") include("double-conversion-${DOUBLE_CONVERSION_VERSION}/src/**/*", "Android.mk")
filesMatching("*/src/**/*", { fname -> fname.path = "double-conversion/${fname.name}" }) filesMatching("*/src/**/*", { fname -> fname.path = "double-conversion/${fname.name}" })
includeEmptyDirs = false includeEmptyDirs = false
into("$thirdPartyNdkDir/double-conversion") into("$thirdPartyNdkDir/double-conversion")
} }
task downloadFolly(dependsOn: createNativeDepsDirectories, type: Download) { task downloadFolly(dependsOn: createNativeDepsDirectories, type: Download) {
src("https://github.com/facebook/folly/archive/v${FOLLY_VERSION}.tar.gz") src("https://github.com/facebook/folly/archive/v${FOLLY_VERSION}.tar.gz")
onlyIfNewer(true) onlyIfNewer(true)
overwrite(false) overwrite(false)
dest(folly_file) dest(folly_file)
} }
task prepareFolly(dependsOn: downloadFolly, type: Copy) { task prepareFolly(dependsOn: downloadFolly, type: Copy) {
from(tarTree(downloadFolly.dest)) from(tarTree(downloadFolly.dest))
from("src/main/jni/third-party/folly/Android.mk") from("src/main/jni/third-party/folly/Android.mk")
include("folly-${FOLLY_VERSION}/folly/**/*", "Android.mk") include("folly-${FOLLY_VERSION}/folly/**/*", "Android.mk")
eachFile { fname -> fname.path = (fname.path - "folly-${FOLLY_VERSION}/") } eachFile { fname -> fname.path = (fname.path - "folly-${FOLLY_VERSION}/") }
includeEmptyDirs = false includeEmptyDirs = false
into("$thirdPartyNdkDir/folly") into("$thirdPartyNdkDir/folly")
} }
task downloadGlog(dependsOn: createNativeDepsDirectories, type: Download) { task downloadGlog(dependsOn: createNativeDepsDirectories, type: Download) {
src("https://github.com/google/glog/archive/v${GLOG_VERSION}.tar.gz") src("https://github.com/google/glog/archive/v${GLOG_VERSION}.tar.gz")
onlyIfNewer(true) onlyIfNewer(true)
overwrite(false) overwrite(false)
dest(glog_file) dest(glog_file)
} }
task prepareGlog(dependsOn: downloadGlog, type: Copy) { task prepareGlog(dependsOn: downloadGlog, type: Copy) {
from(tarTree(downloadGlog.dest)) from(tarTree(downloadGlog.dest))
from("src/main/jni/third-party/glog/") from("src/main/jni/third-party/glog/")
include("glog-${GLOG_VERSION}/src/**/*", "Android.mk", "config.h") include("glog-${GLOG_VERSION}/src/**/*", "Android.mk", "config.h")
@ -368,9 +380,9 @@ task prepareGlog(dependsOn: downloadGlog, type: Copy) {
into("$thirdPartyNdkDir/glog/exported/glog") into("$thirdPartyNdkDir/glog/exported/glog")
} }
} }
} }
task prepareThirdPartyNdkHeaders { task prepareThirdPartyNdkHeaders {
if (!boost_file.exists()) { if (!boost_file.exists()) {
dependsOn(prepareBoost) dependsOn(prepareBoost)
} }
@ -383,11 +395,11 @@ task prepareThirdPartyNdkHeaders {
if (!glog_file.exists()) { if (!glog_file.exists()) {
dependsOn(prepareGlog) dependsOn(prepareGlog)
} }
} }
prepareThirdPartyNdkHeaders.mustRunAfter createNativeDepsDirectories prepareThirdPartyNdkHeaders.mustRunAfter createNativeDepsDirectories
task prepareHermes() { task prepareHermes() {
doLast { doLast {
def hermesPackagePath = findNodeModulePath(projectDir, "hermes-engine") def hermesPackagePath = findNodeModulePath(projectDir, "hermes-engine")
if (!hermesPackagePath) { if (!hermesPackagePath) {
@ -407,11 +419,11 @@ task prepareHermes() {
into "$thirdPartyNdkDir/hermes" into "$thirdPartyNdkDir/hermes"
} }
} }
} }
prepareHermes.mustRunAfter prepareThirdPartyNdkHeaders prepareHermes.mustRunAfter prepareThirdPartyNdkHeaders
task prepareJSC { task prepareJSC {
doLast { doLast {
def jscPackagePath = findNodeModulePath(projectDir, "jsc-android") def jscPackagePath = findNodeModulePath(projectDir, "jsc-android")
if (!jscPackagePath) { if (!jscPackagePath) {
@ -439,11 +451,11 @@ task prepareJSC {
into("$thirdPartyNdkDir/jsc") into("$thirdPartyNdkDir/jsc")
} }
} }
} }
prepareJSC.mustRunAfter prepareHermes prepareJSC.mustRunAfter prepareHermes
task extractAARHeaders { task extractAARHeaders {
doLast { doLast {
configurations.extractHeaders.files.each { configurations.extractHeaders.files.each {
def file = it.absoluteFile def file = it.absoluteFile
@ -454,11 +466,11 @@ task extractAARHeaders {
} }
} }
} }
} }
extractAARHeaders.mustRunAfter prepareJSC extractAARHeaders.mustRunAfter prepareJSC
task extractJNIFiles { task extractJNIFiles {
doLast { doLast {
configurations.extractJNI.files.each { configurations.extractJNI.files.each {
def file = it.absoluteFile def file = it.absoluteFile
@ -470,13 +482,13 @@ task extractJNIFiles {
} }
} }
} }
} }
extractJNIFiles.mustRunAfter extractAARHeaders extractJNIFiles.mustRunAfter extractAARHeaders
// pre-native build pipeline // pre-native build pipeline
tasks.whenTaskAdded { task -> tasks.whenTaskAdded { task ->
if (!task.name.contains('Clean') && (task.name.contains('externalNative') || task.name.contains('CMake'))) { if (!task.name.contains('Clean') && (task.name.contains('externalNative') || task.name.contains('CMake'))) {
task.dependsOn(extractAARHeaders) task.dependsOn(extractAARHeaders)
task.dependsOn(extractJNIFiles) task.dependsOn(extractJNIFiles)
@ -484,4 +496,5 @@ tasks.whenTaskAdded { task ->
task.dependsOn(prepareHermes) task.dependsOn(prepareHermes)
task.dependsOn(prepareThirdPartyNdkHeaders) task.dependsOn(prepareThirdPartyNdkHeaders)
} }
}
} }

View File

@ -16,5 +16,6 @@ VisionCamera_compileSdkVersion=31
VisionCamera_kotlinVersion=1.5.30 VisionCamera_kotlinVersion=1.5.30
VisionCamera_targetSdkVersion=31 VisionCamera_targetSdkVersion=31
VisionCamera_ndkVersion=21.4.7075529 VisionCamera_ndkVersion=21.4.7075529
VisionCamera_disableFrameProcessors=false
android.enableJetifier=true android.enableJetifier=true
android.useAndroidX=true android.useAndroidX=true

View File

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

View File

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

View File

@ -208,7 +208,21 @@ The Frame Processor gets called with a `Frame` object, which is a **JSI HostObje
### Disabling Frame Processors ### Disabling Frame Processors
The Frame Processor API spawns a secondary JavaScript Runtime which consumes a small amount of extra CPU and RAM. If you're not using Frame Processors at all, you can disable them by setting the `VISION_CAMERA_DISABLE_FRAME_PROCESSORS` flag. Inside your `project.pbxproj`, find the `GCC_PREPROCESSOR_DEFINITIONS` parameter and add the flag: The Frame Processor API spawns a secondary JavaScript Runtime which consumes a small amount of extra CPU and RAM. Additionally, compile time increases since Frame Processors are written in native C++. If you're not using Frame Processors at all, you can disable them:
#### Android
Inside your `gradle.properties` file, add the `disableFrameProcessors` flag:
```
disableFrameProcessors=true
```
Then, clean and rebuild your project.
#### iOS
Inside your `project.pbxproj`, find the `GCC_PREPROCESSOR_DEFINITIONS` group and add the flag:
```txt {3} ```txt {3}
GCC_PREPROCESSOR_DEFINITIONS = ( GCC_PREPROCESSOR_DEFINITIONS = (

View File

@ -25,6 +25,7 @@
#import <RNReanimated/RuntimeManager.h> #import <RNReanimated/RuntimeManager.h>
#import <RNReanimated/RuntimeDecorator.h> #import <RNReanimated/RuntimeDecorator.h>
#import <RNReanimated/REAIOSErrorHandler.h> #import <RNReanimated/REAIOSErrorHandler.h>
#import "VisionCameraScheduler.h"
#define ENABLE_FRAME_PROCESSORS #define ENABLE_FRAME_PROCESSORS
#else #else
#warning Your react-native-reanimated version is not compatible with VisionCamera, Frame Processors are disabled. Make sure you're using reanimated 2.2.0 or above! #warning Your react-native-reanimated version is not compatible with VisionCamera, Frame Processors are disabled. Make sure you're using reanimated 2.2.0 or above!
@ -36,7 +37,6 @@
#import "FrameProcessorUtils.h" #import "FrameProcessorUtils.h"
#import "FrameProcessorCallback.h" #import "FrameProcessorCallback.h"
#import "VisionCameraScheduler.h"
#import "../React Utils/MakeJSIRuntime.h" #import "../React Utils/MakeJSIRuntime.h"
#import "../React Utils/JSIUtils.h" #import "../React Utils/JSIUtils.h"

View File

@ -8,16 +8,28 @@
#pragma once #pragma once
#import <RNReanimated/Scheduler.h> #include <functional>
#import <React-callinvoker/ReactCommon/CallInvoker.h> #import <React-callinvoker/ReactCommon/CallInvoker.h>
#if __has_include(<RNReanimated/RuntimeManager.h>)
#import <RNReanimated/Scheduler.h>
#else
// dummy placeholder
namespace reanimated {
class Scheduler {
public:
virtual void scheduleOnUI(std::function<void()> job);
protected:
std::shared_ptr<facebook::react::CallInvoker> jsCallInvoker_;
};
}
#endif
namespace vision { namespace vision {
using namespace facebook;
class VisionCameraScheduler : public reanimated::Scheduler { class VisionCameraScheduler : public reanimated::Scheduler {
public: public:
VisionCameraScheduler(std::shared_ptr<react::CallInvoker> jsInvoker); VisionCameraScheduler(std::shared_ptr<facebook::react::CallInvoker> jsInvoker);
virtual ~VisionCameraScheduler(); virtual ~VisionCameraScheduler();
void scheduleOnUI(std::function<void()> job) override; void scheduleOnUI(std::function<void()> job) override;