From 30b56153dbc4ad7af160e025342b6b46074ccc6a Mon Sep 17 00:00:00 2001 From: Marc Rousavy Date: Wed, 15 Feb 2023 16:47:09 +0100 Subject: [PATCH] feat: Sync Frame Processors (plus `runAsync` and `runAtTargetFps`) (#1472) Before, Frame Processors ran on a separate Thread. After, Frame Processors run fully synchronous and always at the same FPS as the Camera. Two new functions have been introduced: * `runAtTargetFps(fps: number, func: () => void)`: Runs the given code as often as the given `fps`, effectively throttling it's calls. * `runAsync(frame: Frame, func: () => void)`: Runs the given function on a separate Thread for Frame Processing. A strong reference to the Frame is held as long as the function takes to execute. You can use `runAtTargetFps` to throttle calls to a specific API (e.g. if your Camera is running at 60 FPS, but you only want to run face detection at ~25 FPS, use `runAtTargetFps(25, ...)`.) You can use `runAsync` to run a heavy algorithm asynchronous, so that the Camera is not blocked while your algorithm runs. This is useful if your main sync processor draws something, and your async processor is doing some image analysis on the side. You can also combine both functions. Examples: ```js const frameProcessor = useFrameProcessor((frame) => { 'worklet' console.log("I'm running at 60 FPS!") }, []) ``` ```js const frameProcessor = useFrameProcessor((frame) => { 'worklet' console.log("I'm running at 60 FPS!") runAtTargetFps(10, () => { 'worklet' console.log("I'm running at 10 FPS!") }) }, []) ``` ```js const frameProcessor = useFrameProcessor((frame) => { 'worklet' console.log("I'm running at 60 FPS!") runAsync(frame, () => { 'worklet' console.log("I'm running on another Thread, I can block for longer!") }) }, []) ``` ```js const frameProcessor = useFrameProcessor((frame) => { 'worklet' console.log("I'm running at 60 FPS!") runAtTargetFps(10, () => { 'worklet' runAsync(frame, () => { 'worklet' console.log("I'm running on another Thread at 10 FPS, I can block for longer!") }) }) }, []) ``` --- android/src/main/cpp/FrameHostObject.cpp | 70 +-- android/src/main/cpp/FrameHostObject.h | 6 +- .../main/cpp/FrameProcessorRuntimeManager.cpp | 45 +- .../com/mrousavy/camera/CameraView+Events.kt | 11 - .../java/com/mrousavy/camera/CameraView.kt | 53 +- .../com/mrousavy/camera/CameraViewManager.kt | 8 - .../FrameProcessorPerformanceDataCollector.kt | 38 -- docs/docs/guides/FRAME_PROCESSORS.mdx | 2 +- example/ios/Podfile.lock | 454 +++++++++--------- example/package.json | 6 +- example/src/CameraPage.tsx | 7 - example/yarn.lock | 347 +++++++------ ios/CameraQueues.swift | 9 +- ios/CameraView+RecordVideo.swift | 58 +-- ios/CameraView.swift | 35 -- ios/CameraViewManager.m | 2 - ios/Frame Processor/FrameHostObject.h | 6 +- ios/Frame Processor/FrameHostObject.mm | 64 +-- ...ameProcessorPerformanceDataCollector.swift | 67 --- .../FrameProcessorRuntimeManager.mm | 41 +- ios/Frame Processor/FrameProcessorUtils.mm | 12 +- ios/VisionCamera.xcodeproj/project.pbxproj | 2 - package.json | 3 +- src/Camera.tsx | 19 +- src/CameraProps.ts | 26 +- src/Frame.ts | 30 +- src/FrameProcessorPlugins.ts | 92 +++- src/hooks/useFrameProcessor.ts | 17 +- src/index.ts | 2 +- yarn.lock | 42 +- 30 files changed, 660 insertions(+), 914 deletions(-) delete mode 100644 android/src/main/java/com/mrousavy/camera/frameprocessor/FrameProcessorPerformanceDataCollector.kt delete mode 100644 ios/Frame Processor/FrameProcessorPerformanceDataCollector.swift diff --git a/android/src/main/cpp/FrameHostObject.cpp b/android/src/main/cpp/FrameHostObject.cpp index b7d02cd..d4fd223 100644 --- a/android/src/main/cpp/FrameHostObject.cpp +++ b/android/src/main/cpp/FrameHostObject.cpp @@ -8,12 +8,13 @@ #include #include #include +#include namespace vision { using namespace facebook; -FrameHostObject::FrameHostObject(jni::alias_ref image): frame(make_global(image)) { } +FrameHostObject::FrameHostObject(jni::alias_ref image): frame(make_global(image)), _refCount(0) { } FrameHostObject::~FrameHostObject() { // Hermes' Garbage Collector (Hades GC) calls destructors on a separate Thread @@ -25,21 +26,24 @@ FrameHostObject::~FrameHostObject() { std::vector FrameHostObject::getPropertyNames(jsi::Runtime& rt) { std::vector result; - result.push_back(jsi::PropNameID::forUtf8(rt, std::string("toString"))); - result.push_back(jsi::PropNameID::forUtf8(rt, std::string("isValid"))); result.push_back(jsi::PropNameID::forUtf8(rt, std::string("width"))); result.push_back(jsi::PropNameID::forUtf8(rt, std::string("height"))); result.push_back(jsi::PropNameID::forUtf8(rt, std::string("bytesPerRow"))); result.push_back(jsi::PropNameID::forUtf8(rt, std::string("planesCount"))); - result.push_back(jsi::PropNameID::forUtf8(rt, std::string("close"))); + // Debugging + result.push_back(jsi::PropNameID::forUtf8(rt, std::string("toString"))); + // Ref Management + result.push_back(jsi::PropNameID::forUtf8(rt, std::string("isValid"))); + result.push_back(jsi::PropNameID::forUtf8(rt, std::string("incrementRefCount"))); + result.push_back(jsi::PropNameID::forUtf8(rt, std::string("decrementRefCount"))); return result; } -jsi::Value FrameHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& propNameId) { - auto name = propNameId.utf8(runtime); +jsi::Value FrameHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& propName) { + auto name = propName.utf8(runtime); if (name == "toString") { - auto toString = [this] (jsi::Runtime& runtime, const jsi::Value&, const jsi::Value*, size_t) -> jsi::Value { + auto toString = JSI_HOST_FUNCTION_LAMBDA { if (!this->frame) { return jsi::String::createFromUtf8(runtime, "[closed frame]"); } @@ -50,51 +54,53 @@ jsi::Value FrameHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pr }; return jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forUtf8(runtime, "toString"), 0, toString); } - if (name == "close") { - auto close = [this] (jsi::Runtime& runtime, const jsi::Value&, const jsi::Value*, size_t) -> jsi::Value { - if (!this->frame) { - throw jsi::JSError(runtime, "Trying to close an already closed frame! Did you call frame.close() twice?"); - } - this->close(); + if (name == "incrementRefCount") { + auto incrementRefCount = JSI_HOST_FUNCTION_LAMBDA { + // Increment retain count by one so ARC doesn't destroy the Frame Buffer. + std::lock_guard lock(this->_refCountMutex); + this->_refCount++; return jsi::Value::undefined(); }; - return jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forUtf8(runtime, "close"), 0, close); + return jsi::Function::createFromHostFunction(runtime, + jsi::PropNameID::forUtf8(runtime, "incrementRefCount"), + 0, + incrementRefCount); + } + + if (name == "decrementRefCount") { + auto decrementRefCount = JSI_HOST_FUNCTION_LAMBDA { + // Decrement retain count by one. If the retain count is zero, ARC will destroy the Frame Buffer. + std::lock_guard lock(this->_refCountMutex); + this->_refCount--; + if (_refCount < 1) { + this->frame->close(); + } + return jsi::Value::undefined(); + }; + return jsi::Function::createFromHostFunction(runtime, + jsi::PropNameID::forUtf8(runtime, "decrementRefCount"), + 0, + decrementRefCount); } if (name == "isValid") { return jsi::Value(this->frame && this->frame->getIsValid()); } if (name == "width") { - this->assertIsFrameStrong(runtime, name); return jsi::Value(this->frame->getWidth()); } if (name == "height") { - this->assertIsFrameStrong(runtime, name); return jsi::Value(this->frame->getHeight()); } if (name == "bytesPerRow") { - this->assertIsFrameStrong(runtime, name); return jsi::Value(this->frame->getBytesPerRow()); } if (name == "planesCount") { - this->assertIsFrameStrong(runtime, name); return jsi::Value(this->frame->getPlanesCount()); } - return jsi::Value::undefined(); -} - -void FrameHostObject::assertIsFrameStrong(jsi::Runtime& runtime, const std::string& accessedPropName) const { - if (!this->frame) { - auto message = "Cannot get `" + accessedPropName + "`, frame is already closed!"; - throw jsi::JSError(runtime, message.c_str()); - } -} - -void FrameHostObject::close() { - if (this->frame) { - this->frame->close(); - } + // fallback to base implementation + return HostObject::get(runtime, propName); } } // namespace vision diff --git a/android/src/main/cpp/FrameHostObject.h b/android/src/main/cpp/FrameHostObject.h index 90fcf01..eb22db5 100644 --- a/android/src/main/cpp/FrameHostObject.h +++ b/android/src/main/cpp/FrameHostObject.h @@ -9,6 +9,7 @@ #include #include #include +#include #include "java-bindings/JImageProxy.h" @@ -25,15 +26,14 @@ class JSI_EXPORT FrameHostObject : public jsi::HostObject { jsi::Value get(jsi::Runtime &, const jsi::PropNameID &name) override; std::vector getPropertyNames(jsi::Runtime &rt) override; - void close(); - public: jni::global_ref frame; private: static auto constexpr TAG = "VisionCamera"; - void assertIsFrameStrong(jsi::Runtime& runtime, const std::string& accessedPropName) const; // NOLINT(runtime/references) + size_t _refCount; + std::mutex _refCountMutex; }; } // namespace vision diff --git a/android/src/main/cpp/FrameProcessorRuntimeManager.cpp b/android/src/main/cpp/FrameProcessorRuntimeManager.cpp index ebe4715..361649c 100644 --- a/android/src/main/cpp/FrameProcessorRuntimeManager.cpp +++ b/android/src/main/cpp/FrameProcessorRuntimeManager.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include "CameraView.h" #include "FrameHostObject.h" @@ -36,12 +37,10 @@ FrameProcessorRuntimeManager::FrameProcessorRuntimeManager(jni::alias_refdispatchAsync(std::move(f)); }; - - _workletContext = std::make_shared("VisionCamera"); - _workletContext->initialize("VisionCamera", - jsRuntime, - runOnJS, - runOnWorklet); + _workletContext = std::make_shared("VisionCamera", + jsRuntime, + runOnJS, + runOnWorklet); } // JNI binding @@ -96,8 +95,7 @@ void FrameProcessorRuntimeManager::logErrorToJS(const std::string& message) { void FrameProcessorRuntimeManager::setFrameProcessor(jsi::Runtime& runtime, int viewTag, const jsi::Value& frameProcessor) { - __android_log_write(ANDROID_LOG_INFO, TAG, - "Setting new Frame Processor..."); + __android_log_write(ANDROID_LOG_INFO, TAG, "Setting new Frame Processor..."); if (!_workletContext) { throw jsi::JSError(runtime, @@ -106,13 +104,10 @@ void FrameProcessorRuntimeManager::setFrameProcessor(jsi::Runtime& runtime, // find camera view auto cameraView = findCameraViewById(viewTag); - __android_log_write(ANDROID_LOG_INFO, TAG, "Found CameraView!"); // convert jsi::Function to a Worklet (can be shared across runtimes) - __android_log_write(ANDROID_LOG_INFO, TAG, "Creating Worklet..."); auto worklet = std::make_shared(runtime, frameProcessor); auto workletInvoker = std::make_shared(worklet); - __android_log_write(ANDROID_LOG_INFO, TAG, "Successfully created worklet!"); _workletContext->invokeOnWorkletThread([=](RNWorklet::JsiWorkletContext*, jsi::Runtime& rt) { // Set Frame Processor as callable C++ lambda - this will then call the Worklet @@ -142,8 +137,6 @@ void FrameProcessorRuntimeManager::unsetFrameProcessor(int viewTag) { // call Java method to unset frame processor cameraView->cthis()->unsetFrameProcessor(); - - __android_log_write(ANDROID_LOG_INFO, TAG, "Frame Processor removed!"); } // actual JSI installer @@ -158,21 +151,8 @@ void FrameProcessorRuntimeManager::installJSIBindings() { auto& jsiRuntime = *_jsRuntime; - auto setFrameProcessor = [this](jsi::Runtime &runtime, - const jsi::Value &thisValue, - const jsi::Value *arguments, - size_t count) -> jsi::Value { - __android_log_write(ANDROID_LOG_INFO, TAG, - "Setting new Frame Processor..."); - - if (!arguments[0].isNumber()) { - throw jsi::JSError(runtime, - "Camera::setFrameProcessor: First argument ('viewTag') must be a number!"); - } - if (!arguments[1].isObject()) { - throw jsi::JSError(runtime, - "Camera::setFrameProcessor: Second argument ('frameProcessor') must be a function!"); - } + auto setFrameProcessor = JSI_HOST_FUNCTION_LAMBDA { + __android_log_write(ANDROID_LOG_INFO, TAG, "Setting new Frame Processor..."); double viewTag = arguments[0].asNumber(); const jsi::Value& frameProcessor = arguments[1]; @@ -190,15 +170,8 @@ void FrameProcessorRuntimeManager::installJSIBindings() { setFrameProcessor)); - auto unsetFrameProcessor = [this](jsi::Runtime &runtime, - const jsi::Value &thisValue, - const jsi::Value *arguments, - size_t count) -> jsi::Value { + auto unsetFrameProcessor = JSI_HOST_FUNCTION_LAMBDA { __android_log_write(ANDROID_LOG_INFO, TAG, "Removing Frame Processor..."); - if (!arguments[0].isNumber()) { - throw jsi::JSError(runtime, - "Camera::unsetFrameProcessor: First argument ('viewTag') must be a number!"); - } auto viewTag = arguments[0].asNumber(); this->unsetFrameProcessor(static_cast(viewTag)); diff --git a/android/src/main/java/com/mrousavy/camera/CameraView+Events.kt b/android/src/main/java/com/mrousavy/camera/CameraView+Events.kt index 3fdf42a..7e53277 100644 --- a/android/src/main/java/com/mrousavy/camera/CameraView+Events.kt +++ b/android/src/main/java/com/mrousavy/camera/CameraView+Events.kt @@ -31,17 +31,6 @@ fun CameraView.invokeOnError(error: Throwable) { reactContext.getJSModule(RCTEventEmitter::class.java).receiveEvent(id, "cameraError", event) } -fun CameraView.invokeOnFrameProcessorPerformanceSuggestionAvailable(currentFps: Double, suggestedFps: Double) { - Log.e(CameraView.TAG, "invokeOnFrameProcessorPerformanceSuggestionAvailable(suggestedFps: $suggestedFps):") - - val event = Arguments.createMap() - val type = if (suggestedFps > currentFps) "can-use-higher-fps" else "should-use-lower-fps" - event.putString("type", type) - event.putDouble("suggestedFrameProcessorFps", suggestedFps) - val reactContext = context as ReactContext - reactContext.getJSModule(RCTEventEmitter::class.java).receiveEvent(id, "cameraPerformanceSuggestionAvailable", event) -} - fun CameraView.invokeOnViewReady() { val event = Arguments.createMap() val reactContext = context as ReactContext diff --git a/android/src/main/java/com/mrousavy/camera/CameraView.kt b/android/src/main/java/com/mrousavy/camera/CameraView.kt index 210d757..ef1e5ea 100644 --- a/android/src/main/java/com/mrousavy/camera/CameraView.kt +++ b/android/src/main/java/com/mrousavy/camera/CameraView.kt @@ -25,7 +25,6 @@ import com.facebook.jni.HybridData 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.* @@ -103,13 +102,6 @@ class CameraView(context: Context, private val frameProcessorThread: ExecutorSer field = value setOnTouchListener(if (value) touchEventListener else null) } - var frameProcessorFps = 1.0 - set(value) { - field = value - actualFrameProcessorFps = if (value == -1.0) 30.0 else value - lastFrameProcessorPerformanceEvaluation = System.currentTimeMillis() - frameProcessorPerformanceDataCollector.clear() - } // private properties private var isMounted = false @@ -166,16 +158,6 @@ class CameraView(context: Context, private val frameProcessorThread: ExecutorSer private var minZoom: Float = 1f private var maxZoom: Float = 1f - private var actualFrameProcessorFps = 30.0 - private val frameProcessorPerformanceDataCollector = FrameProcessorPerformanceDataCollector() - private var lastSuggestedFrameProcessorFps = 0.0 - private var lastFrameProcessorPerformanceEvaluation = System.currentTimeMillis() - private val isReadyForNewEvaluation: Boolean - get() { - val lastPerformanceEvaluationElapsedTime = System.currentTimeMillis() - lastFrameProcessorPerformanceEvaluation - return lastPerformanceEvaluationElapsedTime > 1000 - } - @DoNotStrip private var mHybridData: HybridData? = null @@ -480,21 +462,8 @@ class CameraView(context: Context, private val frameProcessorThread: ExecutorSer Log.i(TAG, "Adding ImageAnalysis use-case...") imageAnalysis = imageAnalysisBuilder.build().apply { setAnalyzer(cameraExecutor, { image -> - val now = System.currentTimeMillis() - val intervalMs = (1.0 / actualFrameProcessorFps) * 1000.0 - if (now - lastFrameProcessorCall > intervalMs) { - lastFrameProcessorCall = now - - val perfSample = frameProcessorPerformanceDataCollector.beginPerformanceSampleCollection() - frameProcessorCallback(image) - perfSample.endPerformanceSampleCollection() - } - image.close() - - if (isReadyForNewEvaluation) { - // last evaluation was more than a second ago, evaluate again - evaluateNewPerformanceSamples() - } + // Call JS Frame Processor + frameProcessorCallback(image) }) } useCases.add(imageAnalysis!!) @@ -526,22 +495,4 @@ class CameraView(context: Context, private val frameProcessorThread: ExecutorSer } } } - - private fun evaluateNewPerformanceSamples() { - lastFrameProcessorPerformanceEvaluation = System.currentTimeMillis() - val maxFrameProcessorFps = 30 // TODO: Get maxFrameProcessorFps from ImageAnalyser - val averageFps = 1.0 / frameProcessorPerformanceDataCollector.averageExecutionTimeSeconds - val suggestedFrameProcessorFps = floor(min(averageFps, maxFrameProcessorFps.toDouble())) - - if (frameProcessorFps == -1.0) { - // frameProcessorFps="auto" - actualFrameProcessorFps = suggestedFrameProcessorFps - } else { - // frameProcessorFps={someCustomFpsValue} - if (suggestedFrameProcessorFps != lastSuggestedFrameProcessorFps && suggestedFrameProcessorFps != frameProcessorFps) { - invokeOnFrameProcessorPerformanceSuggestionAvailable(frameProcessorFps, suggestedFrameProcessorFps) - lastSuggestedFrameProcessorFps = suggestedFrameProcessorFps - } - } - } } diff --git a/android/src/main/java/com/mrousavy/camera/CameraViewManager.kt b/android/src/main/java/com/mrousavy/camera/CameraViewManager.kt index 35e01e4..cdd6232 100644 --- a/android/src/main/java/com/mrousavy/camera/CameraViewManager.kt +++ b/android/src/main/java/com/mrousavy/camera/CameraViewManager.kt @@ -27,7 +27,6 @@ class CameraViewManager(reactContext: ReactApplicationContext) : ViewGroupManage .put("cameraViewReady", MapBuilder.of("registrationName", "onViewReady")) .put("cameraInitialized", MapBuilder.of("registrationName", "onInitialized")) .put("cameraError", MapBuilder.of("registrationName", "onError")) - .put("cameraPerformanceSuggestionAvailable", MapBuilder.of("registrationName", "onFrameProcessorPerformanceSuggestionAvailable")) .build() } @@ -108,13 +107,6 @@ class CameraViewManager(reactContext: ReactApplicationContext) : ViewGroupManage view.fps = if (fps > 0) fps else null } - @ReactProp(name = "frameProcessorFps", defaultDouble = 1.0) - fun setFrameProcessorFps(view: CameraView, frameProcessorFps: Double) { - if (view.frameProcessorFps != frameProcessorFps) - addChangedPropToTransaction(view, "frameProcessorFps") - view.frameProcessorFps = frameProcessorFps - } - @ReactProp(name = "hdr") fun setHdr(view: CameraView, hdr: Boolean?) { if (view.hdr != hdr) diff --git a/android/src/main/java/com/mrousavy/camera/frameprocessor/FrameProcessorPerformanceDataCollector.kt b/android/src/main/java/com/mrousavy/camera/frameprocessor/FrameProcessorPerformanceDataCollector.kt deleted file mode 100644 index 80cb428..0000000 --- a/android/src/main/java/com/mrousavy/camera/frameprocessor/FrameProcessorPerformanceDataCollector.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.mrousavy.camera.frameprocessor - -data class PerformanceSampleCollection(val endPerformanceSampleCollection: () -> Unit) - -// keep a maximum of `maxSampleSize` historical performance data samples cached. -private const val maxSampleSize = 15 - -class FrameProcessorPerformanceDataCollector { - private var counter = 0 - private var performanceSamples: ArrayList = ArrayList() - - val averageExecutionTimeSeconds: Double - get() = performanceSamples.average() - - fun beginPerformanceSampleCollection(): PerformanceSampleCollection { - val begin = System.currentTimeMillis() - - return PerformanceSampleCollection { - val end = System.currentTimeMillis() - val seconds = (end - begin) / 1_000.0 - - val index = counter % maxSampleSize - - if (performanceSamples.size > index) { - performanceSamples[index] = seconds - } else { - performanceSamples.add(seconds) - } - - counter++ - } - } - - fun clear() { - counter = 0 - performanceSamples.clear() - } -} diff --git a/docs/docs/guides/FRAME_PROCESSORS.mdx b/docs/docs/guides/FRAME_PROCESSORS.mdx index 5c65794..a9d9e6a 100644 --- a/docs/docs/guides/FRAME_PROCESSORS.mdx +++ b/docs/docs/guides/FRAME_PROCESSORS.mdx @@ -161,7 +161,7 @@ This means that **the Frame Processor API only takes ~1ms longer than a fully na ### Avoiding Frame-drops -Frame Processors will be **synchronously** called for each frame the Camera sees and have to finish executing before the next frame arrives, otherwise the next frame(s) will be dropped. For a frame rate of **30 FPS**, you have about **33ms** to finish processing frames. Use [`frameProcessorFps`](/docs/api/interfaces/CameraProps#frameprocessorfps) to throttle the frame processor's FPS. For a QR Code Scanner, **5 FPS** (200ms) might suffice, while a object tracking AI might run at the same frame rate as the Camera itself (e.g. **60 FPS** (16ms)). +Frame Processors will be **synchronously** called for each frame the Camera sees and have to finish executing before the next frame arrives, otherwise the next frame(s) will be dropped. For a frame rate of **30 FPS**, you have about **33ms** to finish processing frames. For a QR Code Scanner, **5 FPS** (200ms) might suffice, while a object tracking AI might run at the same frame rate as the Camera itself (e.g. **60 FPS** (16ms)). ### ESLint react-hooks plugin diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index f2bb549..9df4101 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1,19 +1,19 @@ PODS: - boost (1.76.0) - DoubleConversion (1.1.6) - - FBLazyVector (0.71.2) - - FBReactNativeSpec (0.71.2): + - FBLazyVector (0.71.3) + - FBReactNativeSpec (0.71.3): - RCT-Folly (= 2021.07.22.00) - - RCTRequired (= 0.71.2) - - RCTTypeSafety (= 0.71.2) - - React-Core (= 0.71.2) - - React-jsi (= 0.71.2) - - ReactCommon/turbomodule/core (= 0.71.2) + - RCTRequired (= 0.71.3) + - RCTTypeSafety (= 0.71.3) + - React-Core (= 0.71.3) + - React-jsi (= 0.71.3) + - ReactCommon/turbomodule/core (= 0.71.3) - fmt (6.2.1) - glog (0.3.5) - - hermes-engine (0.71.2): - - hermes-engine/Pre-built (= 0.71.2) - - hermes-engine/Pre-built (0.71.2) + - hermes-engine (0.71.3): + - hermes-engine/Pre-built (= 0.71.3) + - hermes-engine/Pre-built (0.71.3) - libevent (2.1.12) - RCT-Folly (2021.07.22.00): - boost @@ -32,26 +32,26 @@ PODS: - fmt (~> 6.2.1) - glog - libevent - - RCTRequired (0.71.2) - - RCTTypeSafety (0.71.2): - - FBLazyVector (= 0.71.2) - - RCTRequired (= 0.71.2) - - React-Core (= 0.71.2) - - React (0.71.2): - - React-Core (= 0.71.2) - - React-Core/DevSupport (= 0.71.2) - - React-Core/RCTWebSocket (= 0.71.2) - - React-RCTActionSheet (= 0.71.2) - - React-RCTAnimation (= 0.71.2) - - React-RCTBlob (= 0.71.2) - - React-RCTImage (= 0.71.2) - - React-RCTLinking (= 0.71.2) - - React-RCTNetwork (= 0.71.2) - - React-RCTSettings (= 0.71.2) - - React-RCTText (= 0.71.2) - - React-RCTVibration (= 0.71.2) - - React-callinvoker (0.71.2) - - React-Codegen (0.71.2): + - RCTRequired (0.71.3) + - RCTTypeSafety (0.71.3): + - FBLazyVector (= 0.71.3) + - RCTRequired (= 0.71.3) + - React-Core (= 0.71.3) + - React (0.71.3): + - React-Core (= 0.71.3) + - React-Core/DevSupport (= 0.71.3) + - React-Core/RCTWebSocket (= 0.71.3) + - React-RCTActionSheet (= 0.71.3) + - React-RCTAnimation (= 0.71.3) + - React-RCTBlob (= 0.71.3) + - React-RCTImage (= 0.71.3) + - React-RCTLinking (= 0.71.3) + - React-RCTNetwork (= 0.71.3) + - React-RCTSettings (= 0.71.3) + - React-RCTText (= 0.71.3) + - React-RCTVibration (= 0.71.3) + - React-callinvoker (0.71.3) + - React-Codegen (0.71.3): - FBReactNativeSpec - hermes-engine - RCT-Folly @@ -62,209 +62,209 @@ PODS: - React-jsiexecutor - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - - React-Core (0.71.2): + - React-Core (0.71.3): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-Core/Default (= 0.71.2) - - React-cxxreact (= 0.71.2) + - React-Core/Default (= 0.71.3) + - React-cxxreact (= 0.71.3) - React-hermes - - React-jsi (= 0.71.2) - - React-jsiexecutor (= 0.71.2) - - React-perflogger (= 0.71.2) + - React-jsi (= 0.71.3) + - React-jsiexecutor (= 0.71.3) + - React-perflogger (= 0.71.3) - Yoga - - React-Core/CoreModulesHeaders (0.71.2): + - React-Core/CoreModulesHeaders (0.71.3): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.2) + - React-cxxreact (= 0.71.3) - React-hermes - - React-jsi (= 0.71.2) - - React-jsiexecutor (= 0.71.2) - - React-perflogger (= 0.71.2) + - React-jsi (= 0.71.3) + - React-jsiexecutor (= 0.71.3) + - React-perflogger (= 0.71.3) - Yoga - - React-Core/Default (0.71.2): + - React-Core/Default (0.71.3): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-cxxreact (= 0.71.2) + - React-cxxreact (= 0.71.3) - React-hermes - - React-jsi (= 0.71.2) - - React-jsiexecutor (= 0.71.2) - - React-perflogger (= 0.71.2) + - React-jsi (= 0.71.3) + - React-jsiexecutor (= 0.71.3) + - React-perflogger (= 0.71.3) - Yoga - - React-Core/DevSupport (0.71.2): + - React-Core/DevSupport (0.71.3): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-Core/Default (= 0.71.2) - - React-Core/RCTWebSocket (= 0.71.2) - - React-cxxreact (= 0.71.2) + - React-Core/Default (= 0.71.3) + - React-Core/RCTWebSocket (= 0.71.3) + - React-cxxreact (= 0.71.3) - React-hermes - - React-jsi (= 0.71.2) - - React-jsiexecutor (= 0.71.2) - - React-jsinspector (= 0.71.2) - - React-perflogger (= 0.71.2) + - React-jsi (= 0.71.3) + - React-jsiexecutor (= 0.71.3) + - React-jsinspector (= 0.71.3) + - React-perflogger (= 0.71.3) - Yoga - - React-Core/RCTActionSheetHeaders (0.71.2): + - React-Core/RCTActionSheetHeaders (0.71.3): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.2) + - React-cxxreact (= 0.71.3) - React-hermes - - React-jsi (= 0.71.2) - - React-jsiexecutor (= 0.71.2) - - React-perflogger (= 0.71.2) + - React-jsi (= 0.71.3) + - React-jsiexecutor (= 0.71.3) + - React-perflogger (= 0.71.3) - Yoga - - React-Core/RCTAnimationHeaders (0.71.2): + - React-Core/RCTAnimationHeaders (0.71.3): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.2) + - React-cxxreact (= 0.71.3) - React-hermes - - React-jsi (= 0.71.2) - - React-jsiexecutor (= 0.71.2) - - React-perflogger (= 0.71.2) + - React-jsi (= 0.71.3) + - React-jsiexecutor (= 0.71.3) + - React-perflogger (= 0.71.3) - Yoga - - React-Core/RCTBlobHeaders (0.71.2): + - React-Core/RCTBlobHeaders (0.71.3): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.2) + - React-cxxreact (= 0.71.3) - React-hermes - - React-jsi (= 0.71.2) - - React-jsiexecutor (= 0.71.2) - - React-perflogger (= 0.71.2) + - React-jsi (= 0.71.3) + - React-jsiexecutor (= 0.71.3) + - React-perflogger (= 0.71.3) - Yoga - - React-Core/RCTImageHeaders (0.71.2): + - React-Core/RCTImageHeaders (0.71.3): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.2) + - React-cxxreact (= 0.71.3) - React-hermes - - React-jsi (= 0.71.2) - - React-jsiexecutor (= 0.71.2) - - React-perflogger (= 0.71.2) + - React-jsi (= 0.71.3) + - React-jsiexecutor (= 0.71.3) + - React-perflogger (= 0.71.3) - Yoga - - React-Core/RCTLinkingHeaders (0.71.2): + - React-Core/RCTLinkingHeaders (0.71.3): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.2) + - React-cxxreact (= 0.71.3) - React-hermes - - React-jsi (= 0.71.2) - - React-jsiexecutor (= 0.71.2) - - React-perflogger (= 0.71.2) + - React-jsi (= 0.71.3) + - React-jsiexecutor (= 0.71.3) + - React-perflogger (= 0.71.3) - Yoga - - React-Core/RCTNetworkHeaders (0.71.2): + - React-Core/RCTNetworkHeaders (0.71.3): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.2) + - React-cxxreact (= 0.71.3) - React-hermes - - React-jsi (= 0.71.2) - - React-jsiexecutor (= 0.71.2) - - React-perflogger (= 0.71.2) + - React-jsi (= 0.71.3) + - React-jsiexecutor (= 0.71.3) + - React-perflogger (= 0.71.3) - Yoga - - React-Core/RCTSettingsHeaders (0.71.2): + - React-Core/RCTSettingsHeaders (0.71.3): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.2) + - React-cxxreact (= 0.71.3) - React-hermes - - React-jsi (= 0.71.2) - - React-jsiexecutor (= 0.71.2) - - React-perflogger (= 0.71.2) + - React-jsi (= 0.71.3) + - React-jsiexecutor (= 0.71.3) + - React-perflogger (= 0.71.3) - Yoga - - React-Core/RCTTextHeaders (0.71.2): + - React-Core/RCTTextHeaders (0.71.3): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.2) + - React-cxxreact (= 0.71.3) - React-hermes - - React-jsi (= 0.71.2) - - React-jsiexecutor (= 0.71.2) - - React-perflogger (= 0.71.2) + - React-jsi (= 0.71.3) + - React-jsiexecutor (= 0.71.3) + - React-perflogger (= 0.71.3) - Yoga - - React-Core/RCTVibrationHeaders (0.71.2): + - React-Core/RCTVibrationHeaders (0.71.3): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.2) + - React-cxxreact (= 0.71.3) - React-hermes - - React-jsi (= 0.71.2) - - React-jsiexecutor (= 0.71.2) - - React-perflogger (= 0.71.2) + - React-jsi (= 0.71.3) + - React-jsiexecutor (= 0.71.3) + - React-perflogger (= 0.71.3) - Yoga - - React-Core/RCTWebSocket (0.71.2): + - React-Core/RCTWebSocket (0.71.3): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-Core/Default (= 0.71.2) - - React-cxxreact (= 0.71.2) + - React-Core/Default (= 0.71.3) + - React-cxxreact (= 0.71.3) - React-hermes - - React-jsi (= 0.71.2) - - React-jsiexecutor (= 0.71.2) - - React-perflogger (= 0.71.2) + - React-jsi (= 0.71.3) + - React-jsiexecutor (= 0.71.3) + - React-perflogger (= 0.71.3) - Yoga - - React-CoreModules (0.71.2): + - React-CoreModules (0.71.3): - RCT-Folly (= 2021.07.22.00) - - RCTTypeSafety (= 0.71.2) - - React-Codegen (= 0.71.2) - - React-Core/CoreModulesHeaders (= 0.71.2) - - React-jsi (= 0.71.2) + - RCTTypeSafety (= 0.71.3) + - React-Codegen (= 0.71.3) + - React-Core/CoreModulesHeaders (= 0.71.3) + - React-jsi (= 0.71.3) - React-RCTBlob - - React-RCTImage (= 0.71.2) - - ReactCommon/turbomodule/core (= 0.71.2) - - React-cxxreact (0.71.2): + - React-RCTImage (= 0.71.3) + - ReactCommon/turbomodule/core (= 0.71.3) + - React-cxxreact (0.71.3): - boost (= 1.76.0) - DoubleConversion - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-callinvoker (= 0.71.2) - - React-jsi (= 0.71.2) - - React-jsinspector (= 0.71.2) - - React-logger (= 0.71.2) - - React-perflogger (= 0.71.2) - - React-runtimeexecutor (= 0.71.2) - - React-hermes (0.71.2): + - React-callinvoker (= 0.71.3) + - React-jsi (= 0.71.3) + - React-jsinspector (= 0.71.3) + - React-logger (= 0.71.3) + - React-perflogger (= 0.71.3) + - React-runtimeexecutor (= 0.71.3) + - React-hermes (0.71.3): - DoubleConversion - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - RCT-Folly/Futures (= 2021.07.22.00) - - React-cxxreact (= 0.71.2) + - React-cxxreact (= 0.71.3) - React-jsi - - React-jsiexecutor (= 0.71.2) - - React-jsinspector (= 0.71.2) - - React-perflogger (= 0.71.2) - - React-jsi (0.71.2): + - React-jsiexecutor (= 0.71.3) + - React-jsinspector (= 0.71.3) + - React-perflogger (= 0.71.3) + - React-jsi (0.71.3): - boost (= 1.76.0) - DoubleConversion - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-jsiexecutor (0.71.2): + - React-jsiexecutor (0.71.3): - DoubleConversion - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-cxxreact (= 0.71.2) - - React-jsi (= 0.71.2) - - React-perflogger (= 0.71.2) - - React-jsinspector (0.71.2) - - React-logger (0.71.2): + - React-cxxreact (= 0.71.3) + - React-jsi (= 0.71.3) + - React-perflogger (= 0.71.3) + - React-jsinspector (0.71.3) + - React-logger (0.71.3): - glog - react-native-blur (4.3.0): - React-Core @@ -287,90 +287,90 @@ PODS: - React - React-callinvoker - React-Core - - React-perflogger (0.71.2) - - React-RCTActionSheet (0.71.2): - - React-Core/RCTActionSheetHeaders (= 0.71.2) - - React-RCTAnimation (0.71.2): + - React-perflogger (0.71.3) + - React-RCTActionSheet (0.71.3): + - React-Core/RCTActionSheetHeaders (= 0.71.3) + - React-RCTAnimation (0.71.3): - RCT-Folly (= 2021.07.22.00) - - RCTTypeSafety (= 0.71.2) - - React-Codegen (= 0.71.2) - - React-Core/RCTAnimationHeaders (= 0.71.2) - - React-jsi (= 0.71.2) - - ReactCommon/turbomodule/core (= 0.71.2) - - React-RCTAppDelegate (0.71.2): + - RCTTypeSafety (= 0.71.3) + - React-Codegen (= 0.71.3) + - React-Core/RCTAnimationHeaders (= 0.71.3) + - React-jsi (= 0.71.3) + - ReactCommon/turbomodule/core (= 0.71.3) + - React-RCTAppDelegate (0.71.3): - RCT-Folly - RCTRequired - RCTTypeSafety - React-Core - ReactCommon/turbomodule/core - - React-RCTBlob (0.71.2): + - React-RCTBlob (0.71.3): - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-Codegen (= 0.71.2) - - React-Core/RCTBlobHeaders (= 0.71.2) - - React-Core/RCTWebSocket (= 0.71.2) - - React-jsi (= 0.71.2) - - React-RCTNetwork (= 0.71.2) - - ReactCommon/turbomodule/core (= 0.71.2) - - React-RCTImage (0.71.2): + - React-Codegen (= 0.71.3) + - React-Core/RCTBlobHeaders (= 0.71.3) + - React-Core/RCTWebSocket (= 0.71.3) + - React-jsi (= 0.71.3) + - React-RCTNetwork (= 0.71.3) + - ReactCommon/turbomodule/core (= 0.71.3) + - React-RCTImage (0.71.3): - RCT-Folly (= 2021.07.22.00) - - RCTTypeSafety (= 0.71.2) - - React-Codegen (= 0.71.2) - - React-Core/RCTImageHeaders (= 0.71.2) - - React-jsi (= 0.71.2) - - React-RCTNetwork (= 0.71.2) - - ReactCommon/turbomodule/core (= 0.71.2) - - React-RCTLinking (0.71.2): - - React-Codegen (= 0.71.2) - - React-Core/RCTLinkingHeaders (= 0.71.2) - - React-jsi (= 0.71.2) - - ReactCommon/turbomodule/core (= 0.71.2) - - React-RCTNetwork (0.71.2): + - RCTTypeSafety (= 0.71.3) + - React-Codegen (= 0.71.3) + - React-Core/RCTImageHeaders (= 0.71.3) + - React-jsi (= 0.71.3) + - React-RCTNetwork (= 0.71.3) + - ReactCommon/turbomodule/core (= 0.71.3) + - React-RCTLinking (0.71.3): + - React-Codegen (= 0.71.3) + - React-Core/RCTLinkingHeaders (= 0.71.3) + - React-jsi (= 0.71.3) + - ReactCommon/turbomodule/core (= 0.71.3) + - React-RCTNetwork (0.71.3): - RCT-Folly (= 2021.07.22.00) - - RCTTypeSafety (= 0.71.2) - - React-Codegen (= 0.71.2) - - React-Core/RCTNetworkHeaders (= 0.71.2) - - React-jsi (= 0.71.2) - - ReactCommon/turbomodule/core (= 0.71.2) - - React-RCTSettings (0.71.2): + - RCTTypeSafety (= 0.71.3) + - React-Codegen (= 0.71.3) + - React-Core/RCTNetworkHeaders (= 0.71.3) + - React-jsi (= 0.71.3) + - ReactCommon/turbomodule/core (= 0.71.3) + - React-RCTSettings (0.71.3): - RCT-Folly (= 2021.07.22.00) - - RCTTypeSafety (= 0.71.2) - - React-Codegen (= 0.71.2) - - React-Core/RCTSettingsHeaders (= 0.71.2) - - React-jsi (= 0.71.2) - - ReactCommon/turbomodule/core (= 0.71.2) - - React-RCTText (0.71.2): - - React-Core/RCTTextHeaders (= 0.71.2) - - React-RCTVibration (0.71.2): + - RCTTypeSafety (= 0.71.3) + - React-Codegen (= 0.71.3) + - React-Core/RCTSettingsHeaders (= 0.71.3) + - React-jsi (= 0.71.3) + - ReactCommon/turbomodule/core (= 0.71.3) + - React-RCTText (0.71.3): + - React-Core/RCTTextHeaders (= 0.71.3) + - React-RCTVibration (0.71.3): - RCT-Folly (= 2021.07.22.00) - - React-Codegen (= 0.71.2) - - React-Core/RCTVibrationHeaders (= 0.71.2) - - React-jsi (= 0.71.2) - - ReactCommon/turbomodule/core (= 0.71.2) - - React-runtimeexecutor (0.71.2): - - React-jsi (= 0.71.2) - - ReactCommon/turbomodule/bridging (0.71.2): + - React-Codegen (= 0.71.3) + - React-Core/RCTVibrationHeaders (= 0.71.3) + - React-jsi (= 0.71.3) + - ReactCommon/turbomodule/core (= 0.71.3) + - React-runtimeexecutor (0.71.3): + - React-jsi (= 0.71.3) + - ReactCommon/turbomodule/bridging (0.71.3): - DoubleConversion - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-callinvoker (= 0.71.2) - - React-Core (= 0.71.2) - - React-cxxreact (= 0.71.2) - - React-jsi (= 0.71.2) - - React-logger (= 0.71.2) - - React-perflogger (= 0.71.2) - - ReactCommon/turbomodule/core (0.71.2): + - React-callinvoker (= 0.71.3) + - React-Core (= 0.71.3) + - React-cxxreact (= 0.71.3) + - React-jsi (= 0.71.3) + - React-logger (= 0.71.3) + - React-perflogger (= 0.71.3) + - ReactCommon/turbomodule/core (0.71.3): - DoubleConversion - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-callinvoker (= 0.71.2) - - React-Core (= 0.71.2) - - React-cxxreact (= 0.71.2) - - React-jsi (= 0.71.2) - - React-logger (= 0.71.2) - - React-perflogger (= 0.71.2) + - React-callinvoker (= 0.71.3) + - React-Core (= 0.71.3) + - React-cxxreact (= 0.71.3) + - React-jsi (= 0.71.3) + - React-logger (= 0.71.3) + - React-perflogger (= 0.71.3) - RNGestureHandler (2.9.0): - React-Core - RNReanimated (3.0.0-rc.10): @@ -400,7 +400,7 @@ PODS: - React-RCTText - ReactCommon/turbomodule/core - Yoga - - RNScreens (3.19.0): + - RNScreens (3.20.0): - React-Core - React-RCTImage - RNStaticSafeAreaInsets (2.2.0): @@ -566,52 +566,52 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 57d2868c099736d80fcd648bf211b4431e51a558 DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54 - FBLazyVector: d58428b28fe1f5070fe993495b0e2eaf701d3820 - FBReactNativeSpec: 225fb0f0ab00493ce0731f954da3658638d9b191 + FBLazyVector: 60195509584153283780abdac5569feffb8f08cc + FBReactNativeSpec: 9c191fb58d06dc05ab5559a5505fc32139e9e4a2 fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9 glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b - hermes-engine: 6351580c827b3b03e5f25aadcf989f582d0b0a86 + hermes-engine: 38bfe887e456b33b697187570a08de33969f5db7 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1 - RCTRequired: c154ebcfbf41d6fef86c52674fc1aa08837ff538 - RCTTypeSafety: 3063e5a1e5b1dc2cbeda5c8f8926c0ad1a6b0871 - React: 0a1a36e8e81cfaac244ed88b97f23ab56e5434f0 - React-callinvoker: 679a09fbfe1a8bbf0c8588b588bf3ef85e7e4922 - React-Codegen: 78f8966839f22b54d3303a6aca2679bce5723c3f - React-Core: 679e5ff1eb0e3122463976d0b2049bebcb7b33d6 - React-CoreModules: 06cbf15185e6daf9fb3aec02c963f4807bd794b3 - React-cxxreact: 645dc75c9deba4c15698b1b5902236d6a766461f - React-hermes: bc7bcfeaaa7cb98dc9f9252f2f3eca66f06f01e2 - React-jsi: 82625f9f1f8d7abf716d897612a9ea06ecf6db6e - React-jsiexecutor: c7e028406112db456ac3cf5720d266bc7bc20938 - React-jsinspector: ea8101acf525ec08b2d87ddf0637d45f8e3b4148 - React-logger: 97987f46779d8dd24656474ad0c43a5b459f31d6 + RCTRequired: bec48f07daf7bcdc2655a0cde84e07d24d2a9e2a + RCTTypeSafety: 171394eebacf71e1cfad79dbfae7ee8fc16ca80a + React: d7433ccb6a8c36e4cbed59a73c0700fc83c3e98a + React-callinvoker: 15f165009bd22ae829b2b600e50bcc98076ce4b8 + React-Codegen: b5910000eaf1e0c2f47d29be6f82f5f1264420d7 + React-Core: b6f2f78d580a90b83fd7b0d1c6911c799f6eac82 + React-CoreModules: e0cbc1a4f4f3f60e23c476fef7ab37be363ea8c1 + React-cxxreact: c87f3f124b2117d00d410b35f16c2257e25e50fa + React-hermes: c64ca6bdf16a7069773103c9bedaf30ec90ab38f + React-jsi: 39729361645568e238081b3b3180fbad803f25a4 + React-jsiexecutor: 515b703d23ffadeac7687bc2d12fb08b90f0aaa1 + React-jsinspector: 9f7c9137605e72ca0343db4cea88006cb94856dd + React-logger: 957e5dc96d9dbffc6e0f15e0ee4d2b42829ff207 react-native-blur: 50c9feabacbc5f49b61337ebc32192c6be7ec3c3 react-native-cameraroll: 5b25d0be40185d02e522bf2abf8a1ba4e8faa107 react-native-safe-area-context: 39c2d8be3328df5d437ac1700f4f3a4f75716acc react-native-slider: 33b8d190b59d4f67a541061bb91775d53d617d9d react-native-video: c26780b224543c62d5e1b2a7244a5cd1b50e8253 react-native-worklets: c7576ad4ad0f030ff41e8d74ad0077c96054a6c1 - React-perflogger: c7ccda3d1d1da837f7ff4e54e816022a6803ee87 - React-RCTActionSheet: 01c125aebbad462a24228f68c584c7a921d6c28e - React-RCTAnimation: 5277a9440acffc4a5b7baa6ae3880fe467277ae6 - React-RCTAppDelegate: 3977201606125157aa94872b4171ca316478939b - React-RCTBlob: 8e15fc9091d8947f406ba706f11505b38b1b5e40 - React-RCTImage: 65319acfe82b85219b2d410725a593abe19ac795 - React-RCTLinking: a5fc2b9d7a346d6e7d34de8093bb5d1064042508 - React-RCTNetwork: 5d1efcd01ca7f08ebf286d68be544f747a5d315a - React-RCTSettings: fa760b0add819ac3ad73b06715f9547316acdf20 - React-RCTText: 05c244b135d75d4395eb35c012949a5326f8ab70 - React-RCTVibration: 0af3babdeee1b2d052811a2f86977d1e1c81ebd1 - React-runtimeexecutor: 4bf9a9086d27f74065fce1dddac274aa95216952 - ReactCommon: f697c0ac52e999aa818e43e2b6f277787c735e2d + React-perflogger: af8a3d31546077f42d729b949925cc4549f14def + React-RCTActionSheet: 57cc5adfefbaaf0aae2cf7e10bccd746f2903673 + React-RCTAnimation: 11c61e94da700c4dc915cf134513764d87fc5e2b + React-RCTAppDelegate: c3980adeaadcfd6cb495532e928b36ac6db3c14a + React-RCTBlob: ccc5049d742b41971141415ca86b83b201495695 + React-RCTImage: 7a9226b0944f1e76e8e01e35a9245c2477cdbabb + React-RCTLinking: bbe8cc582046a9c04f79c235b73c93700263e8b4 + React-RCTNetwork: fc2ca322159dc54e06508d4f5c3e934da63dc013 + React-RCTSettings: f1e9db2cdf946426d3f2b210e4ff4ce0f0d842ef + React-RCTText: 1c41dd57e5d742b1396b4eeb251851ce7ff0fca1 + React-RCTVibration: 5199a180d04873366a83855de55ac33ce60fe4d5 + React-runtimeexecutor: 7bf0dafc7b727d93c8cb94eb00a9d3753c446c3e + ReactCommon: 6f65ea5b7d84deb9e386f670dd11ce499ded7b40 RNGestureHandler: 071d7a9ad81e8b83fe7663b303d132406a7d8f39 RNReanimated: fbc356493970e3acddc15586b1bccb5eab3ff1ec - RNScreens: ea4cd3a853063cda19a4e3c28d2e52180c80f4eb + RNScreens: 218801c16a2782546d30bd2026bb625c0302d70f RNStaticSafeAreaInsets: 055ddbf5e476321720457cdaeec0ff2ba40ec1b8 RNVectorIcons: fcc2f6cb32f5735b586e66d14103a74ce6ad61f8 VisionCamera: 312151eb95370d1d764720de3b7dad33d8c7fb40 - Yoga: 5b0304b3dbef2b52e078052138e23a19c7dacaef + Yoga: 5ed1699acbba8863755998a4245daa200ff3817b PODFILE CHECKSUM: d53724fe402c2547f1dd1cc571bbe77d9820e636 diff --git a/example/package.json b/example/package.json index 95faa75..92c5a74 100644 --- a/example/package.json +++ b/example/package.json @@ -20,16 +20,16 @@ "@react-navigation/native": "^6.1.3", "@react-navigation/native-stack": "^6.9.9", "react": "^18.2.0", - "react-native": "^0.71.2", + "react-native": "^0.71.3", "react-native-gesture-handler": "^2.9.0", "react-native-pressable-opacity": "^1.0.10", - "react-native-reanimated": "^3.0.0-rc.10", + "react-native-reanimated": "https://github.com/software-mansion/react-native-reanimated#6cf9713a44ec61318bbb12c311f79c08eda95d10", "react-native-safe-area-context": "^4.5.0", "react-native-screens": "^3.19.0", "react-native-static-safe-area-insets": "^2.2.0", "react-native-vector-icons": "^9.2.0", "react-native-video": "^5.2.1", - "react-native-worklets": "https://github.com/chrfalch/react-native-worklets#50950aa" + "react-native-worklets": "https://github.com/chrfalch/react-native-worklets#15d52dd" }, "devDependencies": { "@babel/core": "^7.20.12", diff --git a/example/src/CameraPage.tsx b/example/src/CameraPage.tsx index 7d01fbb..c42dfb4 100644 --- a/example/src/CameraPage.tsx +++ b/example/src/CameraPage.tsx @@ -5,7 +5,6 @@ import { PinchGestureHandler, PinchGestureHandlerGestureEvent, TapGestureHandler import { CameraDeviceFormat, CameraRuntimeError, - FrameProcessorPerformanceSuggestion, PhotoFile, sortFormats, useCameraDevices, @@ -203,10 +202,6 @@ export function CameraPage({ navigation }: Props): React.ReactElement { console.log(`Return Values: ${JSON.stringify(values)}`); }, []); - const onFrameProcessorSuggestionAvailable = useCallback((suggestion: FrameProcessorPerformanceSuggestion) => { - console.log(`Suggestion available! ${suggestion.type}: Can do ${suggestion.suggestedFrameProcessorFps} FPS`); - }, []); - return ( {device != null && ( @@ -231,8 +226,6 @@ export function CameraPage({ navigation }: Props): React.ReactElement { audio={hasMicrophonePermission} frameProcessor={device.supportsParallelVideoProcessing ? frameProcessor : undefined} orientation="portrait" - frameProcessorFps={1} - onFrameProcessorPerformanceSuggestionAvailable={onFrameProcessorSuggestionAvailable} /> diff --git a/example/yarn.lock b/example/yarn.lock index 2e3b322..3115250 100644 --- a/example/yarn.lock +++ b/example/yarn.lock @@ -781,38 +781,38 @@ integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== "@jest/create-cache-key-function@^29.2.1": - version "29.4.2" - resolved "https://registry.yarnpkg.com/@jest/create-cache-key-function/-/create-cache-key-function-29.4.2.tgz#cc8e966c28fd3bed309b0487de2e0bd12cbf519f" - integrity sha512-o2weIg3h8/7+jXF6EjcOiz9TAlNMtcmeH5IARTVgHs3IoQGbh5E/ZLLskfEsHVIYoCKgx+v093Vf8hOgMWggvg== + version "29.4.3" + resolved "https://registry.yarnpkg.com/@jest/create-cache-key-function/-/create-cache-key-function-29.4.3.tgz#ea37769f69523019d81ee089a25a62550f209eb7" + integrity sha512-AJVFQTTy6jnZAQiAZrdOaTAPzJUrvAE/4IMe+Foav6WPhypFszqg7a4lOTyuzYQEEiT5RSrGYg9IY+/ivxiyXw== dependencies: - "@jest/types" "^29.4.2" + "@jest/types" "^29.4.3" -"@jest/environment@^29.4.2": - version "29.4.2" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.4.2.tgz#ee92c316ee2fbdf0bcd9d2db0ef42d64fea26b56" - integrity sha512-JKs3VUtse0vQfCaFGJRX1bir9yBdtasxziSyu+pIiEllAQOe4oQhdCYIf3+Lx+nGglFktSKToBnRJfD5QKp+NQ== +"@jest/environment@^29.4.3": + version "29.4.3" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.4.3.tgz#9fe2f3169c3b33815dc4bd3960a064a83eba6548" + integrity sha512-dq5S6408IxIa+lr54zeqce+QgI+CJT4nmmA+1yzFgtcsGK8c/EyiUb9XQOgz3BMKrRDfKseeOaxj2eO8LlD3lA== dependencies: - "@jest/fake-timers" "^29.4.2" - "@jest/types" "^29.4.2" + "@jest/fake-timers" "^29.4.3" + "@jest/types" "^29.4.3" "@types/node" "*" - jest-mock "^29.4.2" + jest-mock "^29.4.3" -"@jest/fake-timers@^29.4.2": - version "29.4.2" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.4.2.tgz#af43ee1a5720b987d0348f80df98f2cb17d45cd0" - integrity sha512-Ny1u0Wg6kCsHFWq7A/rW/tMhIedq2siiyHyLpHCmIhP7WmcAmd2cx95P+0xtTZlj5ZbJxIRQi4OPydZZUoiSQQ== +"@jest/fake-timers@^29.4.3": + version "29.4.3" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.4.3.tgz#31e982638c60fa657d310d4b9d24e023064027b0" + integrity sha512-4Hote2MGcCTWSD2gwl0dwbCpBRHhE6olYEuTj8FMowdg3oQWNKr2YuxenPQYZ7+PfqPY1k98wKDU4Z+Hvd4Tiw== dependencies: - "@jest/types" "^29.4.2" + "@jest/types" "^29.4.3" "@sinonjs/fake-timers" "^10.0.2" "@types/node" "*" - jest-message-util "^29.4.2" - jest-mock "^29.4.2" - jest-util "^29.4.2" + jest-message-util "^29.4.3" + jest-mock "^29.4.3" + jest-util "^29.4.3" -"@jest/schemas@^29.4.2": - version "29.4.2" - resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.4.2.tgz#cf7cfe97c5649f518452b176c47ed07486270fc1" - integrity sha512-ZrGzGfh31NtdVH8tn0mgJw4khQuNHiKqdzJAFbCaERbyCP9tHlxWuL/mnMu8P7e/+k4puWjI1NOzi/sFsjce/g== +"@jest/schemas@^29.4.3": + version "29.4.3" + resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.4.3.tgz#39cf1b8469afc40b6f5a2baaa146e332c4151788" + integrity sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg== dependencies: "@sinclair/typebox" "^0.25.16" @@ -838,12 +838,12 @@ "@types/yargs" "^16.0.0" chalk "^4.0.0" -"@jest/types@^29.4.2": - version "29.4.2" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.4.2.tgz#8f724a414b1246b2bfd56ca5225d9e1f39540d82" - integrity sha512-CKlngyGP0fwlgC1BRUtPZSiWLBhyS9dKwKmyGxk8Z6M82LBEGB2aLQSg+U1MyLsU+M7UjnlLllBM2BLWKVm/Uw== +"@jest/types@^29.4.3": + version "29.4.3" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.4.3.tgz#9069145f4ef09adf10cec1b2901b2d390031431f" + integrity sha512-bPYfw8V65v17m2Od1cv44FH+SiKW7w2Xu7trhcdTLUmSv85rfKsP+qXSjO4KGJr4dtPSzl/gvslZBXctf1qGEA== dependencies: - "@jest/schemas" "^29.4.2" + "@jest/schemas" "^29.4.3" "@types/istanbul-lib-coverage" "^2.0.0" "@types/istanbul-reports" "^3.0.0" "@types/node" "*" @@ -1153,23 +1153,23 @@ react-is "^16.13.0" use-latest-callback "^0.1.5" -"@react-navigation/elements@^1.3.14": - version "1.3.14" - resolved "https://registry.yarnpkg.com/@react-navigation/elements/-/elements-1.3.14.tgz#ee9ef7f57e0877700ebb359947728b255bbb9c65" - integrity sha512-RBbPhYq+KNFPAkWPaHB9gypq0jTGp/0fkMwRLToJ8jkLtWG4LV+JoQ/erFQnVARkR3Q807n0VnES15EYP4ITMQ== +"@react-navigation/elements@^1.3.15": + version "1.3.15" + resolved "https://registry.yarnpkg.com/@react-navigation/elements/-/elements-1.3.15.tgz#b8aebf101080057508b98cb5da4173c72c095db0" + integrity sha512-CR4CEYJVY0OLyeLQi9N3Z2o4K47gXctvFxfZizDuW1xFtCJbA0eGvpjSLXEWHoY0hFjrlC6KinpdepGHVxhYIg== "@react-navigation/native-stack@^6.9.9": - version "6.9.9" - resolved "https://registry.yarnpkg.com/@react-navigation/native-stack/-/native-stack-6.9.9.tgz#346c393e48d681c15e5831d7749fb807f76dcdce" - integrity sha512-FIbTCEjqAt6guQ90lKIDvOfTo5vtKGG+aQTtHMdTV9JLGnS6gFsBgXmv5hvWLkyd426Nc04mpZXPTK7d80v/LQ== + version "6.9.10" + resolved "https://registry.yarnpkg.com/@react-navigation/native-stack/-/native-stack-6.9.10.tgz#5a5d5de9f49b72e603d0cdca9771e0324f65c1c7" + integrity sha512-dSazcWNxHg4qkid/AxFRvbhRtNXy/RqE00h/Qp+d7aBN0TwrOJn8mH/Inkkf4pHAntMbj0+mVAlKfxKmyLEGlA== dependencies: - "@react-navigation/elements" "^1.3.14" + "@react-navigation/elements" "^1.3.15" warn-once "^0.1.0" "@react-navigation/native@^6.1.3": - version "6.1.3" - resolved "https://registry.yarnpkg.com/@react-navigation/native/-/native-6.1.3.tgz#06064c5e49c417a3dbe210b3f00841beefd326c5" - integrity sha512-DB5FyG6aqGfcjjVozljF5NEkjWaSymIbQHfWwsjL0YrvC1gfc7E53QXDOjxZ/wfbCo8qZs8RIC/LAgclP2YK/w== + version "6.1.4" + resolved "https://registry.yarnpkg.com/@react-navigation/native/-/native-6.1.4.tgz#49666596c9df16e22284f35f482d05d6b5d47d60" + integrity sha512-8IGpMFvD21XINpSf9gyU19yv4O+NyF9FQAxEzwbJSef19W5XEJKXPN/0RINc43Tt+YnQyFGQ2+qJM1uoB9pKcA== dependencies: "@react-navigation/core" "^6.4.6" escape-string-regexp "^4.0.0" @@ -1201,9 +1201,9 @@ integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== "@sinclair/typebox@^0.25.16": - version "0.25.21" - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.25.21.tgz#763b05a4b472c93a8db29b2c3e359d55b29ce272" - integrity sha512-gFukHN4t8K4+wVC+ECqeqwzBDeFeTzBXroBTqE6vcWrQGbEUpHO7LYdG0f4xnvYq4VOEwITSlHlp0JBAIFMS/g== + version "0.25.22" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.25.22.tgz#2808d895e9c2722b20a622a9c8cb332f6720eb4a" + integrity sha512-6U6r2L7rnM7EG8G1tWzIjdB3QlsHF4slgcqXNN/SF0xJOAr0nDmT2GedlkyO3mrv8mDTJ24UuOMWR3diBrCvQQ== "@sinonjs/commons@^2.0.0": version "2.0.0" @@ -1275,23 +1275,23 @@ "@types/react-native" "*" "@types/react-native@*", "@types/react-native@^0.71.2": - version "0.71.2" - resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.71.2.tgz#b8ba52c2fd07d3d64fa87ae5d9b4fbbd3b9cbffd" - integrity sha512-RJ0slxB/aVh6gDBZcGusDLIMW+ydsigzOVva9nODPfZApvIY4UgacV5PAlyk/CScJaN7Frh4sZaD9bD73uc9HQ== + version "0.71.3" + resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.71.3.tgz#537f669ed6b38b5ae47444bd9d253c4cff23bed7" + integrity sha512-0Uqw1YZ0qbVla0MMWFTANFm6W8KYWNvGQmYfucdecbXivLMcQ2v4PovuYFKr7bE6Bc5nDCUEaga962Y8gcDF7A== dependencies: "@types/react" "*" "@types/react-native@^0.70": - version "0.70.10" - resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.70.10.tgz#494576e0dc20aa319003f0cdd99192124d64038d" - integrity sha512-m9B9hJk1w/c04zj5PCYTjJNXt+1UvKtzJj4nO/BjiS4s/zmUdkLdnbLqRQCQiTA0wuvvMbrffuPdheRtYu/M1Q== + version "0.70.11" + resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.70.11.tgz#50c3d81e1351aac0562c3341c9bd57885651a2fe" + integrity sha512-FobPtzoNPNHugBKMfzs4Li0Q9ei4tgU8SI1M5Ayg7+t5/+noCm2sknI8uwij22wMkcHcefv8RFx4q28nNVJtCQ== dependencies: "@types/react" "*" "@types/react@*", "@types/react@^18.0.27": - version "18.0.27" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.27.tgz#d9425abe187a00f8a5ec182b010d4fd9da703b71" - integrity sha512-3vtRKHgVxu3Jp9t718R9BuzoD4NcQ8YJ5XRzsSKxNDiDonD2MXIT1TmSkenxuCycZJoQT5d2vE8LwWJxBC1gmA== + version "18.0.28" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.28.tgz#accaeb8b86f4908057ad629a26635fe641480065" + integrity sha512-RD0ivG1kEztNBdoAK7lekI9M+azSnitIn85h4iOiaLjaTrMjzslhaqCGaI4IyCJ1RljWiLCEu4jyrLLgqxBTew== dependencies: "@types/prop-types" "*" "@types/scheduler" "*" @@ -1339,13 +1339,13 @@ "@types/yargs-parser" "*" "@typescript-eslint/eslint-plugin@^5.30.5": - version "5.51.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.51.0.tgz#da3f2819633061ced84bb82c53bba45a6fe9963a" - integrity sha512-wcAwhEWm1RgNd7dxD/o+nnLW8oH+6RK1OGnmbmkj/GGoDPV1WWMVP0FXYQBivKHdwM1pwii3bt//RC62EriIUQ== + version "5.52.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.52.0.tgz#5fb0d43574c2411f16ea80f5fc335b8eaa7b28a8" + integrity sha512-lHazYdvYVsBokwCdKOppvYJKaJ4S41CgKBcPvyd0xjZNbvQdhn/pnJlGtQksQ/NhInzdaeaSarlBjDXHuclEbg== dependencies: - "@typescript-eslint/scope-manager" "5.51.0" - "@typescript-eslint/type-utils" "5.51.0" - "@typescript-eslint/utils" "5.51.0" + "@typescript-eslint/scope-manager" "5.52.0" + "@typescript-eslint/type-utils" "5.52.0" + "@typescript-eslint/utils" "5.52.0" debug "^4.3.4" grapheme-splitter "^1.0.4" ignore "^5.2.0" @@ -1355,71 +1355,71 @@ tsutils "^3.21.0" "@typescript-eslint/parser@^5.30.5": - version "5.51.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.51.0.tgz#2d74626652096d966ef107f44b9479f02f51f271" - integrity sha512-fEV0R9gGmfpDeRzJXn+fGQKcl0inIeYobmmUWijZh9zA7bxJ8clPhV9up2ZQzATxAiFAECqPQyMDB4o4B81AaA== + version "5.52.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.52.0.tgz#73c136df6c0133f1d7870de7131ccf356f5be5a4" + integrity sha512-e2KiLQOZRo4Y0D/b+3y08i3jsekoSkOYStROYmPUnGMEoA0h+k2qOH5H6tcjIc68WDvGwH+PaOrP1XRzLJ6QlA== dependencies: - "@typescript-eslint/scope-manager" "5.51.0" - "@typescript-eslint/types" "5.51.0" - "@typescript-eslint/typescript-estree" "5.51.0" + "@typescript-eslint/scope-manager" "5.52.0" + "@typescript-eslint/types" "5.52.0" + "@typescript-eslint/typescript-estree" "5.52.0" debug "^4.3.4" -"@typescript-eslint/scope-manager@5.51.0": - version "5.51.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.51.0.tgz#ad3e3c2ecf762d9a4196c0fbfe19b142ac498990" - integrity sha512-gNpxRdlx5qw3yaHA0SFuTjW4rxeYhpHxt491PEcKF8Z6zpq0kMhe0Tolxt0qjlojS+/wArSDlj/LtE69xUJphQ== +"@typescript-eslint/scope-manager@5.52.0": + version "5.52.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.52.0.tgz#a993d89a0556ea16811db48eabd7c5b72dcb83d1" + integrity sha512-AR7sxxfBKiNV0FWBSARxM8DmNxrwgnYMPwmpkC1Pl1n+eT8/I2NAUPuwDy/FmDcC6F8pBfmOcaxcxRHspgOBMw== dependencies: - "@typescript-eslint/types" "5.51.0" - "@typescript-eslint/visitor-keys" "5.51.0" + "@typescript-eslint/types" "5.52.0" + "@typescript-eslint/visitor-keys" "5.52.0" -"@typescript-eslint/type-utils@5.51.0": - version "5.51.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.51.0.tgz#7af48005531700b62a20963501d47dfb27095988" - integrity sha512-QHC5KKyfV8sNSyHqfNa0UbTbJ6caB8uhcx2hYcWVvJAZYJRBo5HyyZfzMdRx8nvS+GyMg56fugMzzWnojREuQQ== +"@typescript-eslint/type-utils@5.52.0": + version "5.52.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.52.0.tgz#9fd28cd02e6f21f5109e35496df41893f33167aa" + integrity sha512-tEKuUHfDOv852QGlpPtB3lHOoig5pyFQN/cUiZtpw99D93nEBjexRLre5sQZlkMoHry/lZr8qDAt2oAHLKA6Jw== dependencies: - "@typescript-eslint/typescript-estree" "5.51.0" - "@typescript-eslint/utils" "5.51.0" + "@typescript-eslint/typescript-estree" "5.52.0" + "@typescript-eslint/utils" "5.52.0" debug "^4.3.4" tsutils "^3.21.0" -"@typescript-eslint/types@5.51.0": - version "5.51.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.51.0.tgz#e7c1622f46c7eea7e12bbf1edfb496d4dec37c90" - integrity sha512-SqOn0ANn/v6hFn0kjvLwiDi4AzR++CBZz0NV5AnusT2/3y32jdc0G4woXPWHCumWtUXZKPAS27/9vziSsC9jnw== +"@typescript-eslint/types@5.52.0": + version "5.52.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.52.0.tgz#19e9abc6afb5bd37a1a9bea877a1a836c0b3241b" + integrity sha512-oV7XU4CHYfBhk78fS7tkum+/Dpgsfi91IIDy7fjCyq2k6KB63M6gMC0YIvy+iABzmXThCRI6xpCEyVObBdWSDQ== -"@typescript-eslint/typescript-estree@5.51.0": - version "5.51.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.51.0.tgz#0ec8170d7247a892c2b21845b06c11eb0718f8de" - integrity sha512-TSkNupHvNRkoH9FMA3w7TazVFcBPveAAmb7Sz+kArY6sLT86PA5Vx80cKlYmd8m3Ha2SwofM1KwraF24lM9FvA== +"@typescript-eslint/typescript-estree@5.52.0": + version "5.52.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.52.0.tgz#6408cb3c2ccc01c03c278cb201cf07e73347dfca" + integrity sha512-WeWnjanyEwt6+fVrSR0MYgEpUAuROxuAH516WPjUblIrClzYJj0kBbjdnbQXLpgAN8qbEuGywiQsXUVDiAoEuQ== dependencies: - "@typescript-eslint/types" "5.51.0" - "@typescript-eslint/visitor-keys" "5.51.0" + "@typescript-eslint/types" "5.52.0" + "@typescript-eslint/visitor-keys" "5.52.0" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/utils@5.51.0", "@typescript-eslint/utils@^5.10.0": - version "5.51.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.51.0.tgz#074f4fabd5b12afe9c8aa6fdee881c050f8b4d47" - integrity sha512-76qs+5KWcaatmwtwsDJvBk4H76RJQBFe+Gext0EfJdC3Vd2kpY2Pf//OHHzHp84Ciw0/rYoGTDnIAr3uWhhJYw== +"@typescript-eslint/utils@5.52.0", "@typescript-eslint/utils@^5.10.0": + version "5.52.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.52.0.tgz#b260bb5a8f6b00a0ed51db66bdba4ed5e4845a72" + integrity sha512-As3lChhrbwWQLNk2HC8Ree96hldKIqk98EYvypd3It8Q1f8d5zWyIoaZEp2va5667M4ZyE7X8UUR+azXrFl+NA== dependencies: "@types/json-schema" "^7.0.9" "@types/semver" "^7.3.12" - "@typescript-eslint/scope-manager" "5.51.0" - "@typescript-eslint/types" "5.51.0" - "@typescript-eslint/typescript-estree" "5.51.0" + "@typescript-eslint/scope-manager" "5.52.0" + "@typescript-eslint/types" "5.52.0" + "@typescript-eslint/typescript-estree" "5.52.0" eslint-scope "^5.1.1" eslint-utils "^3.0.0" semver "^7.3.7" -"@typescript-eslint/visitor-keys@5.51.0": - version "5.51.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.51.0.tgz#c0147dd9a36c0de758aaebd5b48cae1ec59eba87" - integrity sha512-Oh2+eTdjHjOFjKA27sxESlA87YPSOJafGCR0md5oeMdh1ZcCfAGCIOL216uTBAkAIptvLIfKQhl7lHxMJet4GQ== +"@typescript-eslint/visitor-keys@5.52.0": + version "5.52.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.52.0.tgz#e38c971259f44f80cfe49d97dbffa38e3e75030f" + integrity sha512-qMwpw6SU5VHCPr99y274xhbm+PRViK/NATY6qzt+Et7+mThGuFSl/ompj2/hrBlRP/kq+BFdgagnOSgw9TB0eA== dependencies: - "@typescript-eslint/types" "5.51.0" + "@typescript-eslint/types" "5.52.0" eslint-visitor-keys "^3.3.0" abort-controller@^3.0.0: @@ -1777,7 +1777,7 @@ braces@^3.0.2: dependencies: fill-range "^7.0.1" -browserslist@^4.21.3, browserslist@^4.21.4: +browserslist@^4.21.3, browserslist@^4.21.5: version "4.21.5" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.5.tgz#75c5dae60063ee641f977e00edd3cfb2fb7af6a7" integrity sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w== @@ -1870,9 +1870,9 @@ camelcase@^6.0.0: integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== caniuse-lite@^1.0.30001449: - version "1.0.30001451" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001451.tgz#2e197c698fc1373d63e1406d6607ea4617c613f1" - integrity sha512-XY7UbUpGRatZzoRft//5xOa69/1iGJRBlrieH6QYrkKLIFn3m7OVEJ81dSrKoy2BnKsdbX5cLrOispZNYo9v2w== + version "1.0.30001452" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001452.tgz#dff7b8bb834b3a91808f0a9ff0453abb1fbba02a" + integrity sha512-Lkp0vFjMkBB3GTpLR8zk4NwW5EdRdnitwYJHDOOKIU85x4ckYCPQ+9WlVvSVClHxVReefkUMtWZH2l9KGlD51w== chalk@^2.0.0: version "2.4.2" @@ -1897,9 +1897,9 @@ ci-info@^2.0.0: integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== ci-info@^3.2.0: - version "3.7.1" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.7.1.tgz#708a6cdae38915d597afdf3b145f2f8e1ff55f3f" - integrity sha512-4jYS4MOAaCIStSRwiuxc4B8MYhIe676yO1sYGzARnjXkWpmzZMMYxY6zu8WYWDhSuth5zhrQ1rhNSibyyvv4/w== + version "3.8.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.8.0.tgz#81408265a5380c929f0bc665d62256628ce9ef91" + integrity sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw== class-utils@^0.3.5: version "0.3.6" @@ -2077,11 +2077,11 @@ copy-descriptor@^0.1.0: integrity sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw== core-js-compat@^3.25.1: - version "3.27.2" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.27.2.tgz#607c50ad6db8fd8326af0b2883ebb987be3786da" - integrity sha512-welaYuF7ZtbYKGrIy7y3eb40d37rG1FvzEOfe7hSLd2iD6duMDqUhRfSvCGyC46HhR6Y8JXXdZ2lnRUMkPBpvg== + version "3.28.0" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.28.0.tgz#c08456d854608a7264530a2afa281fadf20ecee6" + integrity sha512-myzPgE7QodMg4nnd3K1TDoES/nADRStM8Gpz0D6nhkwbmwEnE0ZGJgoWsvQ722FR8D7xS0n0LV556RcEicjTyg== dependencies: - browserslist "^4.21.4" + browserslist "^4.21.5" core-util-is@~1.0.0: version "1.0.3" @@ -2170,9 +2170,9 @@ defaults@^1.0.3: clone "^1.0.2" define-properties@^1.1.3, define-properties@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" - integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== + version "1.2.0" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5" + integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA== dependencies: has-property-descriptors "^1.0.0" object-keys "^1.1.1" @@ -2259,9 +2259,9 @@ ee-first@1.1.1: integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== electron-to-chromium@^1.4.284: - version "1.4.294" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.294.tgz#ad80317b85f0859a9454680fbc1c726fefa7e6fd" - integrity sha512-PuHZB3jEN7D8WPPjLmBQAsqQz8tWHlkkB4n0E2OYw8RwVdmBYV0Wn+rUFH8JqYyIRb4HQhhedgxlZL163wqLrQ== + version "1.4.296" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.296.tgz#dbc84a25c25a432a12fbf62903cae4a87461eb8c" + integrity sha512-i/6Q+Y9bluDa2a0NbMvdtG5TuS/1Fr3TKK8L+7UUL9QjRS5iFJzCC3r70xjyOnLiYG8qGV4/mMpe6HuAbdJW4w== eme-encryption-scheme-polyfill@^2.0.1: version "2.1.1" @@ -2509,9 +2509,9 @@ eslint-visitor-keys@^3.3.0: integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== eslint@^8.33.0: - version "8.33.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.33.0.tgz#02f110f32998cb598c6461f24f4d306e41ca33d7" - integrity sha512-WjOpFQgKK8VrCnAtl8We0SUOy/oVZ5NHykyMiagV1M9r8IFpIJX7DduK6n1mpfhlG7T1NLWm2SuD8QB7KFySaA== + version "8.34.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.34.0.tgz#fe0ab0ef478104c1f9ebc5537e303d25a8fb22d6" + integrity sha512-1Z8iFsucw+7kSqXNZVslXS8Ioa4u2KM7GPwuKtkTFAqZ/cHMcEaR+1+Br0wLlot49cNxIiZk5wp8EAbPcYZxTg== dependencies: "@eslint/eslintrc" "^1.4.1" "@humanwhocodes/config-array" "^0.11.8" @@ -3451,45 +3451,45 @@ isobject@^3.0.0, isobject@^3.0.1: integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== jest-environment-node@^29.2.1: - version "29.4.2" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.4.2.tgz#0eab835b41e25fd0c1a72f62665fc8db08762ad2" - integrity sha512-MLPrqUcOnNBc8zTOfqBbxtoa8/Ee8tZ7UFW7hRDQSUT+NGsvS96wlbHGTf+EFAT9KC3VNb7fWEM6oyvmxtE/9w== + version "29.4.3" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.4.3.tgz#579c4132af478befc1889ddc43c2413a9cdbe014" + integrity sha512-gAiEnSKF104fsGDXNkwk49jD/0N0Bqu2K9+aMQXA6avzsA9H3Fiv1PW2D+gzbOSR705bWd2wJZRFEFpV0tXISg== dependencies: - "@jest/environment" "^29.4.2" - "@jest/fake-timers" "^29.4.2" - "@jest/types" "^29.4.2" + "@jest/environment" "^29.4.3" + "@jest/fake-timers" "^29.4.3" + "@jest/types" "^29.4.3" "@types/node" "*" - jest-mock "^29.4.2" - jest-util "^29.4.2" + jest-mock "^29.4.3" + jest-util "^29.4.3" jest-get-type@^26.3.0: version "26.3.0" resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.3.0.tgz#e97dc3c3f53c2b406ca7afaed4493b1d099199e0" integrity sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig== -jest-message-util@^29.4.2: - version "29.4.2" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.4.2.tgz#309a2924eae6ca67cf7f25781a2af1902deee717" - integrity sha512-SElcuN4s6PNKpOEtTInjOAA8QvItu0iugkXqhYyguRvQoXapg5gN+9RQxLAkakChZA7Y26j6yUCsFWN+hlKD6g== +jest-message-util@^29.4.3: + version "29.4.3" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.4.3.tgz#65b5280c0fdc9419503b49d4f48d4999d481cb5b" + integrity sha512-1Y8Zd4ZCN7o/QnWdMmT76If8LuDv23Z1DRovBj/vcSFNlGCJGoO8D1nJDw1AdyAGUk0myDLFGN5RbNeJyCRGCw== dependencies: "@babel/code-frame" "^7.12.13" - "@jest/types" "^29.4.2" + "@jest/types" "^29.4.3" "@types/stack-utils" "^2.0.0" chalk "^4.0.0" graceful-fs "^4.2.9" micromatch "^4.0.4" - pretty-format "^29.4.2" + pretty-format "^29.4.3" slash "^3.0.0" stack-utils "^2.0.3" -jest-mock@^29.4.2: - version "29.4.2" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.4.2.tgz#e1054be66fb3e975d26d4528fcde6979e4759de8" - integrity sha512-x1FSd4Gvx2yIahdaIKoBjwji6XpboDunSJ95RpntGrYulI1ByuYQCKN/P7hvk09JB74IonU3IPLdkutEWYt++g== +jest-mock@^29.4.3: + version "29.4.3" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.4.3.tgz#23d84a20a74cdfff0510fdbeefb841ed57b0fe7e" + integrity sha512-LjFgMg+xed9BdkPMyIJh+r3KeHt1klXPJYBULXVVAkbTaaKjPX1o1uVCAZADMEp/kOxGTwy/Ot8XbvgItOrHEg== dependencies: - "@jest/types" "^29.4.2" + "@jest/types" "^29.4.3" "@types/node" "*" - jest-util "^29.4.2" + jest-util "^29.4.3" jest-regex-util@^27.0.6: version "27.5.1" @@ -3516,12 +3516,12 @@ jest-util@^27.2.0: graceful-fs "^4.2.9" picomatch "^2.2.3" -jest-util@^29.4.2: - version "29.4.2" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.4.2.tgz#3db8580b295df453a97de4a1b42dd2578dabd2c2" - integrity sha512-wKnm6XpJgzMUSRFB7YF48CuwdzuDIHenVuoIb1PLuJ6F+uErZsuDkU+EiExkChf6473XcawBrSfDSnXl+/YG4g== +jest-util@^29.4.3: + version "29.4.3" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.4.3.tgz#851a148e23fc2b633c55f6dad2e45d7f4579f496" + integrity sha512-ToSGORAz4SSSoqxDSylWX8JzkOQR7zoBtNRsA7e+1WUX5F8jrOwaNpuh1YfJHJKDHXLHmObv5eOjejUd+/Ws+Q== dependencies: - "@jest/types" "^29.4.2" + "@jest/types" "^29.4.3" "@types/node" "*" chalk "^4.0.0" ci-info "^3.2.0" @@ -3585,10 +3585,10 @@ js-yaml@^4.1.0: dependencies: argparse "^2.0.1" -jsc-android@^250230.2.1: - version "250230.2.1" - resolved "https://registry.yarnpkg.com/jsc-android/-/jsc-android-250230.2.1.tgz#3790313a970586a03ab0ad47defbc84df54f1b83" - integrity sha512-KmxeBlRjwoqCnBBKGsihFtvsBHyUFlBxJPK4FzeYcIuBfdjv6jFys44JITAgSTbQD+vIdwMEfyZklsuQX0yI1Q== +jsc-android@^250231.0.0: + version "250231.0.0" + resolved "https://registry.yarnpkg.com/jsc-android/-/jsc-android-250231.0.0.tgz#91720f8df382a108872fa4b3f558f33ba5e95262" + integrity sha512-rS46PvsjYmdmuz1OAWXY/1kCYG7pnf1TBqeTiOJr1iDz7s5DLxxC9n/ZMknLDxzYzNVfI7R95MH10emSSG1Wuw== jscodeshift@^0.13.1: version "0.13.1" @@ -4912,12 +4912,12 @@ pretty-format@^26.5.2, pretty-format@^26.6.2: ansi-styles "^4.0.0" react-is "^17.0.1" -pretty-format@^29.4.2: - version "29.4.2" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.4.2.tgz#64bf5ccc0d718c03027d94ac957bdd32b3fb2401" - integrity sha512-qKlHR8yFVCbcEWba0H0TOC8dnLlO4vPlyEjRPw31FZ2Rupy9nLa8ZLbYny8gWEl8CkEhJqAE6IzdNELTBVcBEg== +pretty-format@^29.4.3: + version "29.4.3" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.4.3.tgz#25500ada21a53c9e8423205cf0337056b201244c" + integrity sha512-cvpcHTc42lcsvOOAzd3XuNWTcvk1Jmnzqeu+WsOuiPmxUJTnkbAcFNsRKvEpBEUFVUgy/GTZLulZDcDEi+CIlA== dependencies: - "@jest/schemas" "^29.4.2" + "@jest/schemas" "^29.4.3" ansi-styles "^5.0.0" react-is "^18.0.0" @@ -5011,10 +5011,10 @@ react-is@^17.0.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== -react-native-codegen@^0.71.3: - version "0.71.3" - resolved "https://registry.yarnpkg.com/react-native-codegen/-/react-native-codegen-0.71.3.tgz#75fbc591819050791319ebdb9fe341ee4df5c288" - integrity sha512-5AvdHVU1sAaXg05i0dG664ZTaCaIFaY1znV5vNsj+wUu6MGxNEUNbDKk9dxKUkkxOyk2KZOK5uhzWL0p5H5yZQ== +react-native-codegen@^0.71.5: + version "0.71.5" + resolved "https://registry.yarnpkg.com/react-native-codegen/-/react-native-codegen-0.71.5.tgz#454a42a891cd4ca5fc436440d301044dc1349c14" + integrity sha512-rfsuc0zkuUuMjFnrT55I1mDZ+pBRp2zAiRwxck3m6qeGJBGK5OV5JH66eDQ4aa+3m0of316CqrJDRzVlYufzIg== dependencies: "@babel/parser" "^7.14.0" flow-parser "^0.185.0" @@ -5032,20 +5032,19 @@ react-native-gesture-handler@^2.9.0: lodash "^4.17.21" prop-types "^15.7.2" -react-native-gradle-plugin@^0.71.14: - version "0.71.14" - resolved "https://registry.yarnpkg.com/react-native-gradle-plugin/-/react-native-gradle-plugin-0.71.14.tgz#cc399662f04fbfcc0e352d03eae1d3efbd5f635a" - integrity sha512-nnLawTZEPPRAKq92UqDkzoGgCBl9aa9zAihFHMwmwzn4WRVdK4O6Cd4XYiyoNOiQzx3Hh9k5WOckHE80C92ivQ== +react-native-gradle-plugin@^0.71.15: + version "0.71.15" + resolved "https://registry.yarnpkg.com/react-native-gradle-plugin/-/react-native-gradle-plugin-0.71.15.tgz#9e6b506f30729fe8eb086981702f4e3c891d2b13" + integrity sha512-7S3pAuPaQJlhax6EZ4JMsDNpj05TfuzX9gPgWLrFfAIWIFLuJ6aDQYAZy2TEI9QJALPoWrj8LWaqP/DGYh14pw== react-native-pressable-opacity@^1.0.10: version "1.0.10" resolved "https://registry.yarnpkg.com/react-native-pressable-opacity/-/react-native-pressable-opacity-1.0.10.tgz#799df1a913d3b28f42ada765465fe7723eb7166d" integrity sha512-Py9YH9TlS3Lv1so5JCj6bgiqkeYYGupF4ZImlpoyhhId/t/RiSqR68LlASOHgdctqQuqVJObQiFfzX8oZI9+6w== -react-native-reanimated@^3.0.0-rc.10: +"react-native-reanimated@https://github.com/software-mansion/react-native-reanimated#6cf9713a44ec61318bbb12c311f79c08eda95d10": version "3.0.0-rc.10" - resolved "https://registry.yarnpkg.com/react-native-reanimated/-/react-native-reanimated-3.0.0-rc.10.tgz#40e5b628759aa81f94317fd0301231292b4eacf5" - integrity sha512-0P2jSO+dXHRxSzqSxNp08VaUy89nqeUIvqBS0wlI8lsli8CJcqulL3pjNqTGzBkxXjt13mGdIzJv4u9lSjHPzg== + resolved "https://github.com/software-mansion/react-native-reanimated#6cf9713a44ec61318bbb12c311f79c08eda95d10" dependencies: "@babel/plugin-transform-object-assign" "^7.16.7" "@babel/preset-typescript" "^7.16.7" @@ -5061,9 +5060,9 @@ react-native-safe-area-context@^4.5.0: integrity sha512-0WORnk9SkREGUg2V7jHZbuN5x4vcxj/1B0QOcXJjdYWrzZHgLcUzYWWIUecUPJh747Mwjt/42RZDOaFn3L8kPQ== react-native-screens@^3.19.0: - version "3.19.0" - resolved "https://registry.yarnpkg.com/react-native-screens/-/react-native-screens-3.19.0.tgz#ec68685e04b074ebce4641b3a0ae7e2571629b75" - integrity sha512-Ehsmy7jr3H3j5pmN+/FqsAaIAD+k+xkcdePfLcg4rYRbN5X7fJPgaqhcmiCcZ0YxsU8ttsstP9IvRLNQuIkRRA== + version "3.20.0" + resolved "https://registry.yarnpkg.com/react-native-screens/-/react-native-screens-3.20.0.tgz#4d154177395e5541387d9a05bc2e12e54d2fb5b1" + integrity sha512-joWUKWAVHxymP3mL9gYApFHAsbd9L6ZcmpoZa6Sl3W/82bvvNVMqcfP7MeNqVCg73qZ8yL4fW+J/syusHleUgg== dependencies: react-freeze "^1.0.0" warn-once "^0.1.0" @@ -5091,14 +5090,14 @@ react-native-video@^5.2.1: prop-types "^15.7.2" shaka-player "^2.5.9" -"react-native-worklets@https://github.com/chrfalch/react-native-worklets#50950aa": +"react-native-worklets@https://github.com/chrfalch/react-native-worklets#15d52dd": version "0.1.0" - resolved "https://github.com/chrfalch/react-native-worklets#50950aa1b671a0d8a9e79878e63a3445991e7192" + resolved "https://github.com/chrfalch/react-native-worklets#15d52dd1289831cecc7906823f613172e0c6cd2e" -react-native@^0.71.2: - version "0.71.2" - resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.71.2.tgz#b6977eda2a6dc10baa006bf4ab1ee08318607ce9" - integrity sha512-ZSianM+j+09LoEdVIhrAP/uP8sQhT7dH6olCqM2xlpxmfCgA5NubsK6NABIuZiBlmmqjigyijm5Y/GhBIHDvEg== +react-native@^0.71.3: + version "0.71.3" + resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.71.3.tgz#0faab799c49e61ba12df9e6525c3ac7d595d673c" + integrity sha512-RYJXCcQGa4NTfKiPgl92eRDUuQ6JGDnHqFEzRwJSqEx9lWvlvRRIebstJfurzPDKLQWQrvITR7aI7e09E25mLw== dependencies: "@jest/create-cache-key-function" "^29.2.1" "@react-native-community/cli" "10.1.3" @@ -5114,7 +5113,7 @@ react-native@^0.71.2: event-target-shim "^5.0.1" invariant "^2.2.4" jest-environment-node "^29.2.1" - jsc-android "^250230.2.1" + jsc-android "^250231.0.0" memoize-one "^5.0.0" metro-react-native-babel-transformer "0.73.7" metro-runtime "0.73.7" @@ -5124,8 +5123,8 @@ react-native@^0.71.2: pretty-format "^26.5.2" promise "^8.3.0" react-devtools-core "^4.26.1" - react-native-codegen "^0.71.3" - react-native-gradle-plugin "^0.71.14" + react-native-codegen "^0.71.5" + react-native-gradle-plugin "^0.71.15" react-refresh "^0.4.0" react-shallow-renderer "^16.15.0" regenerator-runtime "^0.13.2" diff --git a/ios/CameraQueues.swift b/ios/CameraQueues.swift index 01a7003..01704a9 100644 --- a/ios/CameraQueues.swift +++ b/ios/CameraQueues.swift @@ -17,20 +17,13 @@ public class CameraQueues: NSObject { autoreleaseFrequency: .inherit, target: nil) - /// The serial execution queue for output processing of videos for recording. + /// The serial execution queue for output processing of videos for recording or synchronous frame processing. @objc public static let videoQueue = DispatchQueue(label: "mrousavy/VisionCamera.video", qos: .userInteractive, attributes: [], autoreleaseFrequency: .inherit, target: nil) - /// The serial execution queue for output processing of videos for frame processing. - @objc public static let frameProcessorQueue = DispatchQueue(label: "mrousavy/VisionCamera.frame-processor", - qos: .userInteractive, - attributes: [], - autoreleaseFrequency: .inherit, - target: nil) - /// The serial execution queue for output processing of audio buffers. @objc public static let audioQueue = DispatchQueue(label: "mrousavy/VisionCamera.audio", qos: .userInteractive, diff --git a/ios/CameraView+RecordVideo.swift b/ios/CameraView+RecordVideo.swift index 7fdf962..43d9619 100644 --- a/ios/CameraView+RecordVideo.swift +++ b/ios/CameraView+RecordVideo.swift @@ -190,8 +190,8 @@ extension CameraView: AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureAud } public final func captureOutput(_ captureOutput: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from _: AVCaptureConnection) { - // Video Recording runs in the same queue if isRecording { + // Write Video / Audio frame to file guard let recordingSession = recordingSession else { invokeOnError(.capture(.unknown(message: "isRecording was true but the RecordingSession was null!"))) return @@ -211,54 +211,9 @@ extension CameraView: AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureAud } if let frameProcessor = frameProcessorCallback, captureOutput is AVCaptureVideoDataOutput { - // check if last frame was x nanoseconds ago, effectively throttling FPS - let frameTime = UInt64(CMSampleBufferGetPresentationTimeStamp(sampleBuffer).seconds * 1_000_000_000.0) - let lastFrameProcessorCallElapsedTime = frameTime - lastFrameProcessorCall - let secondsPerFrame = 1.0 / actualFrameProcessorFps - let nanosecondsPerFrame = secondsPerFrame * 1_000_000_000.0 - if lastFrameProcessorCallElapsedTime >= UInt64(nanosecondsPerFrame) { - if !isRunningFrameProcessor { - // we're not in the middle of executing the Frame Processor, so prepare for next call. - CameraQueues.frameProcessorQueue.async { - self.isRunningFrameProcessor = true - - let perfSample = self.frameProcessorPerformanceDataCollector.beginPerformanceSampleCollection() - let frame = Frame(buffer: sampleBuffer, orientation: self.bufferOrientation) - frameProcessor(frame) - perfSample.endPerformanceSampleCollection() - - self.isRunningFrameProcessor = false - } - lastFrameProcessorCall = frameTime - } else { - // we're still in the middle of executing a Frame Processor for a previous frame, so a frame was dropped. - ReactLogger.log(level: .warning, message: "The Frame Processor took so long to execute that a frame was dropped.") - } - } - - if isReadyForNewEvaluation { - // last evaluation was more than 1sec ago, evaluate again - evaluateNewPerformanceSamples() - } - } - } - - private func evaluateNewPerformanceSamples() { - lastFrameProcessorPerformanceEvaluation = DispatchTime.now() - guard let videoDevice = videoDeviceInput?.device else { return } - guard frameProcessorPerformanceDataCollector.hasEnoughData else { return } - - let maxFrameProcessorFps = Double(videoDevice.activeVideoMinFrameDuration.timescale) * Double(videoDevice.activeVideoMinFrameDuration.value) - let averageFps = 1.0 / frameProcessorPerformanceDataCollector.averageExecutionTimeSeconds - let suggestedFrameProcessorFps = max(floor(min(averageFps, maxFrameProcessorFps)), 1) - - if frameProcessorFps.intValue == -1 { - // frameProcessorFps="auto" - actualFrameProcessorFps = suggestedFrameProcessorFps - } else { - // frameProcessorFps={someCustomFpsValue} - invokeOnFrameProcessorPerformanceSuggestionAvailable(currentFps: frameProcessorFps.doubleValue, - suggestedFps: suggestedFrameProcessorFps) + // Call the JavaScript Frame Processor func (worklet) + let frame = Frame(buffer: sampleBuffer, orientation: self.bufferOrientation) + frameProcessor(frame) } } @@ -270,11 +225,6 @@ extension CameraView: AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureAud } } - private var isReadyForNewEvaluation: Bool { - let lastPerformanceEvaluationElapsedTime = DispatchTime.now().uptimeNanoseconds - lastFrameProcessorPerformanceEvaluation.uptimeNanoseconds - return lastPerformanceEvaluationElapsedTime > 1_000_000_000 - } - /** Gets the orientation of the CameraView's images (CMSampleBuffers). */ diff --git a/ios/CameraView.swift b/ios/CameraView.swift index e3cd1e0..519a417 100644 --- a/ios/CameraView.swift +++ b/ios/CameraView.swift @@ -52,7 +52,6 @@ public final class CameraView: UIView { // props that require format reconfiguring @objc var format: NSDictionary? @objc var fps: NSNumber? - @objc var frameProcessorFps: NSNumber = -1.0 // "auto" @objc var hdr: NSNumber? // nullable bool @objc var lowLightBoost: NSNumber? // nullable bool @objc var colorSpace: NSString? @@ -65,7 +64,6 @@ public final class CameraView: UIView { // events @objc var onInitialized: RCTDirectEventBlock? @objc var onError: RCTDirectEventBlock? - @objc var onFrameProcessorPerformanceSuggestionAvailable: RCTDirectEventBlock? @objc var onViewReady: RCTDirectEventBlock? // zoom @objc var enableZoomGesture = false { @@ -105,13 +103,6 @@ public final class CameraView: UIView { internal let videoQueue = CameraQueues.videoQueue internal let audioQueue = CameraQueues.audioQueue - /// Specifies whether the frameProcessor() function is currently executing. used to drop late frames. - internal var isRunningFrameProcessor = false - internal let frameProcessorPerformanceDataCollector = FrameProcessorPerformanceDataCollector() - internal var actualFrameProcessorFps = 30.0 - internal var lastSuggestedFrameProcessorFps = 0.0 - internal var lastFrameProcessorPerformanceEvaluation = DispatchTime.now() - /// Returns whether the AVCaptureSession is currently running (reflected by isActive) var isRunning: Bool { return captureSession.isRunning @@ -259,18 +250,6 @@ public final class CameraView: UIView { } } } - - // Frame Processor FPS Configuration - if changedProps.contains("frameProcessorFps") { - if frameProcessorFps.doubleValue == -1 { - // "auto" - actualFrameProcessorFps = 30.0 - } else { - actualFrameProcessorFps = frameProcessorFps.doubleValue - } - lastFrameProcessorPerformanceEvaluation = DispatchTime.now() - frameProcessorPerformanceDataCollector.clear() - } } internal final func setTorchMode(_ torchMode: String) { @@ -343,18 +322,4 @@ public final class CameraView: UIView { guard let onInitialized = onInitialized else { return } onInitialized([String: Any]()) } - - internal final func invokeOnFrameProcessorPerformanceSuggestionAvailable(currentFps: Double, suggestedFps: Double) { - ReactLogger.log(level: .info, message: "Frame Processor Performance Suggestion available!") - guard let onFrameProcessorPerformanceSuggestionAvailable = onFrameProcessorPerformanceSuggestionAvailable else { return } - - if lastSuggestedFrameProcessorFps == suggestedFps { return } - if suggestedFps == currentFps { return } - - onFrameProcessorPerformanceSuggestionAvailable([ - "type": suggestedFps > currentFps ? "can-use-higher-fps" : "should-use-lower-fps", - "suggestedFrameProcessorFps": suggestedFps, - ]) - lastSuggestedFrameProcessorFps = suggestedFps - } } diff --git a/ios/CameraViewManager.m b/ios/CameraViewManager.m index e1d8e85..ec4d6d1 100644 --- a/ios/CameraViewManager.m +++ b/ios/CameraViewManager.m @@ -35,7 +35,6 @@ RCT_EXPORT_VIEW_PROPERTY(enableFrameProcessor, BOOL); // device format RCT_EXPORT_VIEW_PROPERTY(format, NSDictionary); RCT_EXPORT_VIEW_PROPERTY(fps, NSNumber); -RCT_EXPORT_VIEW_PROPERTY(frameProcessorFps, NSNumber); RCT_EXPORT_VIEW_PROPERTY(hdr, NSNumber); // nullable bool RCT_EXPORT_VIEW_PROPERTY(lowLightBoost, NSNumber); // nullable bool RCT_EXPORT_VIEW_PROPERTY(colorSpace, NSString); @@ -49,7 +48,6 @@ RCT_EXPORT_VIEW_PROPERTY(orientation, NSString); // Camera View Events RCT_EXPORT_VIEW_PROPERTY(onError, RCTDirectEventBlock); RCT_EXPORT_VIEW_PROPERTY(onInitialized, RCTDirectEventBlock); -RCT_EXPORT_VIEW_PROPERTY(onFrameProcessorPerformanceSuggestionAvailable, RCTDirectEventBlock); RCT_EXPORT_VIEW_PROPERTY(onViewReady, RCTDirectEventBlock); // Camera View Functions diff --git a/ios/Frame Processor/FrameHostObject.h b/ios/Frame Processor/FrameHostObject.h index 7cdadab..360c10f 100644 --- a/ios/Frame Processor/FrameHostObject.h +++ b/ios/Frame Processor/FrameHostObject.h @@ -16,16 +16,12 @@ using namespace facebook; class JSI_EXPORT FrameHostObject: public jsi::HostObject { public: - explicit FrameHostObject(Frame* frame): frame(frame) {} + explicit FrameHostObject(Frame* frame): frame(frame) { } public: jsi::Value get(jsi::Runtime&, const jsi::PropNameID& name) override; std::vector getPropertyNames(jsi::Runtime& rt) override; - void close(); public: Frame* frame; - -private: - void assertIsFrameStrong(jsi::Runtime& runtime, const std::string& accessedPropName); }; diff --git a/ios/Frame Processor/FrameHostObject.mm b/ios/Frame Processor/FrameHostObject.mm index a4967a9..2d4a093 100644 --- a/ios/Frame Processor/FrameHostObject.mm +++ b/ios/Frame Processor/FrameHostObject.mm @@ -9,16 +9,21 @@ #import "FrameHostObject.h" #import #import +#import "JsiHostObject.h" +#import "JsiSharedValue.h" std::vector FrameHostObject::getPropertyNames(jsi::Runtime& rt) { std::vector result; - result.push_back(jsi::PropNameID::forUtf8(rt, std::string("toString"))); - result.push_back(jsi::PropNameID::forUtf8(rt, std::string("isValid"))); result.push_back(jsi::PropNameID::forUtf8(rt, std::string("width"))); result.push_back(jsi::PropNameID::forUtf8(rt, std::string("height"))); result.push_back(jsi::PropNameID::forUtf8(rt, std::string("bytesPerRow"))); result.push_back(jsi::PropNameID::forUtf8(rt, std::string("planesCount"))); - result.push_back(jsi::PropNameID::forUtf8(rt, std::string("close"))); + // Debugging + result.push_back(jsi::PropNameID::forUtf8(rt, std::string("toString"))); + // Ref Management + result.push_back(jsi::PropNameID::forUtf8(rt, std::string("isValid"))); + result.push_back(jsi::PropNameID::forUtf8(rt, std::string("incrementRefCount"))); + result.push_back(jsi::PropNameID::forUtf8(rt, std::string("decrementRefCount"))); return result; } @@ -26,7 +31,7 @@ jsi::Value FrameHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pr auto name = propName.utf8(runtime); if (name == "toString") { - auto toString = [this] (jsi::Runtime& runtime, const jsi::Value&, const jsi::Value*, size_t) -> jsi::Value { + auto toString = JSI_HOST_FUNCTION_LAMBDA { if (this->frame == nil) { return jsi::String::createFromUtf8(runtime, "[closed frame]"); } @@ -39,60 +44,55 @@ jsi::Value FrameHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pr }; return jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forUtf8(runtime, "toString"), 0, toString); } - if (name == "close") { - auto close = [this] (jsi::Runtime& runtime, const jsi::Value&, const jsi::Value*, size_t) -> jsi::Value { - if (this->frame == nil) { - throw jsi::JSError(runtime, "Trying to close an already closed frame! Did you call frame.close() twice?"); - } - this->close(); + if (name == "incrementRefCount") { + auto incrementRefCount = JSI_HOST_FUNCTION_LAMBDA { + // Increment retain count by one so ARC doesn't destroy the Frame Buffer. + CFRetain(frame.buffer); return jsi::Value::undefined(); }; - return jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forUtf8(runtime, "close"), 0, close); + return jsi::Function::createFromHostFunction(runtime, + jsi::PropNameID::forUtf8(runtime, "incrementRefCount"), + 0, + incrementRefCount); + } + + if (name == "decrementRefCount") { + auto decrementRefCount = JSI_HOST_FUNCTION_LAMBDA { + // Decrement retain count by one. If the retain count is zero, ARC will destroy the Frame Buffer. + CFRelease(frame.buffer); + return jsi::Value::undefined(); + }; + return jsi::Function::createFromHostFunction(runtime, + jsi::PropNameID::forUtf8(runtime, "decrementRefCount"), + 0, + decrementRefCount); } if (name == "isValid") { - auto isValid = frame != nil && CMSampleBufferIsValid(frame.buffer); + auto isValid = frame != nil && frame.buffer != nil && CFGetRetainCount(frame.buffer) > 0 && CMSampleBufferIsValid(frame.buffer); return jsi::Value(isValid); } if (name == "width") { - this->assertIsFrameStrong(runtime, name); auto imageBuffer = CMSampleBufferGetImageBuffer(frame.buffer); auto width = CVPixelBufferGetWidth(imageBuffer); return jsi::Value((double) width); } if (name == "height") { - this->assertIsFrameStrong(runtime, name); auto imageBuffer = CMSampleBufferGetImageBuffer(frame.buffer); auto height = CVPixelBufferGetHeight(imageBuffer); return jsi::Value((double) height); } if (name == "bytesPerRow") { - this->assertIsFrameStrong(runtime, name); auto imageBuffer = CMSampleBufferGetImageBuffer(frame.buffer); auto bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); return jsi::Value((double) bytesPerRow); } if (name == "planesCount") { - this->assertIsFrameStrong(runtime, name); auto imageBuffer = CMSampleBufferGetImageBuffer(frame.buffer); auto planesCount = CVPixelBufferGetPlaneCount(imageBuffer); return jsi::Value((double) planesCount); } - return jsi::Value::undefined(); -} - -void FrameHostObject::assertIsFrameStrong(jsi::Runtime &runtime, const std::string &accessedPropName) { - if (frame == nil) { - auto message = "Cannot get `" + accessedPropName + "`, frame is already closed!"; - throw jsi::JSError(runtime, message.c_str()); - } -} - -void FrameHostObject::close() { - if (frame != nil) { - CMSampleBufferInvalidate(frame.buffer); - // ARC will hopefully delete it lol - this->frame = nil; - } + // fallback to base implementation + return HostObject::get(runtime, propName); } diff --git a/ios/Frame Processor/FrameProcessorPerformanceDataCollector.swift b/ios/Frame Processor/FrameProcessorPerformanceDataCollector.swift deleted file mode 100644 index c87c941..0000000 --- a/ios/Frame Processor/FrameProcessorPerformanceDataCollector.swift +++ /dev/null @@ -1,67 +0,0 @@ -// -// FrameProcessorPerformanceDataCollector.swift -// VisionCamera -// -// Created by Marc Rousavy on 30.08.21. -// Copyright © 2021 mrousavy. All rights reserved. -// - -import Foundation - -// keep a maximum of `maxSampleSize` historical performance data samples cached. -private let maxSampleSize = 15 - -// MARK: - PerformanceSampleCollection - -struct PerformanceSampleCollection { - var endPerformanceSampleCollection: () -> Void - - init(end: @escaping () -> Void) { - endPerformanceSampleCollection = end - } -} - -// MARK: - FrameProcessorPerformanceDataCollector - -class FrameProcessorPerformanceDataCollector { - private var performanceSamples: [Double] = [] - private var counter = 0 - private var lastEvaluation = -1 - - var hasEnoughData: Bool { - return !performanceSamples.isEmpty - } - - var averageExecutionTimeSeconds: Double { - let sum = performanceSamples.reduce(0, +) - let average = sum / Double(performanceSamples.count) - - lastEvaluation = counter - - return average - } - - func beginPerformanceSampleCollection() -> PerformanceSampleCollection { - let begin = DispatchTime.now() - - return PerformanceSampleCollection { - let end = DispatchTime.now() - let seconds = Double(end.uptimeNanoseconds - begin.uptimeNanoseconds) / 1_000_000_000.0 - - let index = self.counter % maxSampleSize - - if self.performanceSamples.count > index { - self.performanceSamples[index] = seconds - } else { - self.performanceSamples.append(seconds) - } - - self.counter += 1 - } - } - - func clear() { - counter = 0 - performanceSamples.removeAll() - } -} diff --git a/ios/Frame Processor/FrameProcessorRuntimeManager.mm b/ios/Frame Processor/FrameProcessorRuntimeManager.mm index fe8b483..14d336b 100644 --- a/ios/Frame Processor/FrameProcessorRuntimeManager.mm +++ b/ios/Frame Processor/FrameProcessorRuntimeManager.mm @@ -22,6 +22,7 @@ #import "JsiWorkletContext.h" #import "JsiWorkletApi.h" #import "JsiWorklet.h" +#import "JsiHostObject.h" #import "FrameProcessorUtils.h" #import "FrameProcessorCallback.h" @@ -30,7 +31,7 @@ // Forward declarations for the Swift classes __attribute__((objc_runtime_name("_TtC12VisionCamera12CameraQueues"))) @interface CameraQueues : NSObject -@property (nonatomic, class, readonly, strong) dispatch_queue_t _Nonnull frameProcessorQueue; +@property (nonatomic, class, readonly, strong) dispatch_queue_t _Nonnull videoQueue; @end __attribute__((objc_runtime_name("_TtC12VisionCamera10CameraView"))) @interface CameraView : UIView @@ -38,6 +39,7 @@ __attribute__((objc_runtime_name("_TtC12VisionCamera10CameraView"))) @end @implementation FrameProcessorRuntimeManager { + // Running Frame Processors on camera's video thread (synchronously) std::shared_ptr workletContext; } @@ -59,16 +61,15 @@ __attribute__((objc_runtime_name("_TtC12VisionCamera10CameraView"))) }; auto runOnWorklet = [](std::function&& f) { // Run on Frame Processor Worklet Runtime - dispatch_async(CameraQueues.frameProcessorQueue, [f = std::move(f)](){ + dispatch_async(CameraQueues.videoQueue, [f = std::move(f)](){ f(); }); }; - workletContext = std::make_shared("VisionCamera"); - workletContext->initialize("VisionCamera", - &runtime, - runOnJS, - runOnWorklet); + workletContext = std::make_shared("VisionCamera", + &runtime, + runOnJS, + runOnWorklet); NSLog(@"FrameProcessorBindings: Worklet Context Created!"); @@ -136,28 +137,17 @@ __attribute__((objc_runtime_name("_TtC12VisionCamera10CameraView"))) NSLog(@"FrameProcessorBindings: Installing global functions..."); // setFrameProcessor(viewTag: number, frameProcessor: (frame: Frame) => void) - auto setFrameProcessor = [self](jsi::Runtime& runtime, - const jsi::Value& thisValue, - const jsi::Value* arguments, - size_t count) -> jsi::Value { + auto setFrameProcessor = JSI_HOST_FUNCTION_LAMBDA { NSLog(@"FrameProcessorBindings: Setting new frame processor..."); - if (!arguments[0].isNumber()) throw jsi::JSError(runtime, "Camera::setFrameProcessor: First argument ('viewTag') must be a number!"); - if (!arguments[1].isObject()) throw jsi::JSError(runtime, "Camera::setFrameProcessor: Second argument ('frameProcessor') must be a function!"); - auto viewTag = arguments[0].asNumber(); - NSLog(@"FrameProcessorBindings: Converting JSI Function to Worklet..."); auto worklet = std::make_shared(runtime, arguments[1]); - RCTExecuteOnMainQueue([=]() { + RCTExecuteOnMainQueue(^{ auto currentBridge = [RCTBridge currentBridge]; auto anonymousView = [currentBridge.uiManager viewForReactTag:[NSNumber numberWithDouble:viewTag]]; auto view = static_cast(anonymousView); - - NSLog(@"FrameProcessorBindings: Converting worklet to Objective-C callback..."); - - view.frameProcessorCallback = convertWorkletToFrameProcessorCallback(workletContext->getWorkletRuntime(), worklet); - - NSLog(@"FrameProcessorBindings: Frame processor set!"); + auto callback = convertWorkletToFrameProcessorCallback(self->workletContext->getWorkletRuntime(), worklet); + view.frameProcessorCallback = callback; }); return jsi::Value::undefined(); @@ -168,12 +158,8 @@ __attribute__((objc_runtime_name("_TtC12VisionCamera10CameraView"))) setFrameProcessor)); // unsetFrameProcessor(viewTag: number) - auto unsetFrameProcessor = [](jsi::Runtime& runtime, - const jsi::Value& thisValue, - const jsi::Value* arguments, - size_t count) -> jsi::Value { + auto unsetFrameProcessor = JSI_HOST_FUNCTION_LAMBDA { NSLog(@"FrameProcessorBindings: Removing frame processor..."); - if (!arguments[0].isNumber()) throw jsi::JSError(runtime, "Camera::unsetFrameProcessor: First argument ('viewTag') must be a number!"); auto viewTag = arguments[0].asNumber(); RCTExecuteOnMainQueue(^{ @@ -185,7 +171,6 @@ __attribute__((objc_runtime_name("_TtC12VisionCamera10CameraView"))) auto view = static_cast(anonymousView); view.frameProcessorCallback = nil; - NSLog(@"FrameProcessorBindings: Frame processor removed!"); }); return jsi::Value::undefined(); diff --git a/ios/Frame Processor/FrameProcessorUtils.mm b/ios/Frame Processor/FrameProcessorUtils.mm index 233bdcf..47e7eb5 100644 --- a/ios/Frame Processor/FrameProcessorUtils.mm +++ b/ios/Frame Processor/FrameProcessorUtils.mm @@ -28,13 +28,15 @@ FrameProcessorCallback convertWorkletToFrameProcessorCallback(jsi::Runtime& runt // Converts a Worklet to a callable Objective-C block function return ^(Frame* frame) { - auto frameHostObject = std::make_shared(frame); try { - // Call JS Frame Processor function with boxed Frame Host Object + // Box the Frame to a JS Host Object + auto frameHostObject = std::make_shared(frame); auto argument = jsi::Object::createFromHostObject(runtime, frameHostObject); jsi::Value jsValue(std::move(argument)); + // Call the Worklet with the Frame JS Host Object as an argument workletInvoker->call(runtime, jsi::Value::undefined(), &jsValue, 1); } catch (jsi::JSError& jsError) { + // JS Error occured, print it to console. auto stack = std::regex_replace(jsError.getStack(), std::regex("\n"), "\n "); auto message = [NSString stringWithFormat:@"Frame Processor threw an error: %s\nIn: %s", jsError.getMessage().c_str(), stack.c_str()]; @@ -48,11 +50,5 @@ FrameProcessorCallback convertWorkletToFrameProcessorCallback(jsi::Runtime& runt NSLog(@"%@", message); } } - - // Manually free the buffer because: - // 1. we are sure we don't need it anymore, the frame processor worklet has finished executing. - // 2. we don't know when the JS runtime garbage collects this object, it might be holding it for a few more frames - // which then blocks the camera queue from pushing new frames (memory limit) - frameHostObject->close(); }; } diff --git a/ios/VisionCamera.xcodeproj/project.pbxproj b/ios/VisionCamera.xcodeproj/project.pbxproj index 0b56817..4097254 100644 --- a/ios/VisionCamera.xcodeproj/project.pbxproj +++ b/ios/VisionCamera.xcodeproj/project.pbxproj @@ -138,7 +138,6 @@ B887518425E0102000DB86D6 /* CameraView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CameraView.swift; sourceTree = ""; }; B88873E5263D46C7008B1D0E /* FrameProcessorPlugin.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FrameProcessorPlugin.h; sourceTree = ""; }; B88B47462667C8E00091F538 /* AVCaptureSession+setVideoStabilizationMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AVCaptureSession+setVideoStabilizationMode.swift"; sourceTree = ""; }; - B8948BDF26DCEE2B00B430E2 /* FrameProcessorPerformanceDataCollector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FrameProcessorPerformanceDataCollector.swift; sourceTree = ""; }; B8994E6B263F03E100069589 /* JSIUtils.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = JSIUtils.mm; sourceTree = ""; }; B8A751D62609E4980011C623 /* FrameProcessorRuntimeManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FrameProcessorRuntimeManager.h; sourceTree = ""; }; B8A751D72609E4B30011C623 /* FrameProcessorRuntimeManager.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FrameProcessorRuntimeManager.mm; sourceTree = ""; }; @@ -273,7 +272,6 @@ B88873E5263D46C7008B1D0E /* FrameProcessorPlugin.h */, B80416F026AB16E8000DEB6A /* VisionCameraScheduler.mm */, B80416F126AB16F3000DEB6A /* VisionCameraScheduler.h */, - B8948BDF26DCEE2B00B430E2 /* FrameProcessorPerformanceDataCollector.swift */, ); path = "Frame Processor"; sourceTree = ""; diff --git a/package.json b/package.json index 5bd79f4..77145a9 100644 --- a/package.json +++ b/package.json @@ -80,8 +80,9 @@ "pod-install": "^0.1.38", "prettier": "^2.8.4", "react": "^18.2.0", - "react-native": "^0.71.2", + "react-native": "^0.71.3", "react-native-builder-bob": "^0.20.3", + "react-native-worklets": "https://github.com/chrfalch/react-native-worklets#15d52dd", "release-it": "^15.6.0", "typescript": "^4.9.5" }, diff --git a/src/Camera.tsx b/src/Camera.tsx index 32ffb63..2b45ab2 100644 --- a/src/Camera.tsx +++ b/src/Camera.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { requireNativeComponent, NativeModules, NativeSyntheticEvent, findNodeHandle, NativeMethods, Platform } from 'react-native'; -import type { FrameProcessorPerformanceSuggestion, VideoFileType } from '.'; +import type { VideoFileType } from '.'; import type { CameraDevice } from './CameraDevice'; import type { ErrorWithCause } from './CameraError'; import { CameraCaptureError, CameraRuntimeError, tryParseNativeCameraError, isErrorWithCause } from './CameraError'; @@ -20,16 +20,11 @@ interface OnErrorEvent { message: string; cause?: ErrorWithCause; } -type NativeCameraViewProps = Omit< - CameraProps, - 'device' | 'onInitialized' | 'onError' | 'onFrameProcessorPerformanceSuggestionAvailable' | 'frameProcessor' | 'frameProcessorFps' -> & { +type NativeCameraViewProps = Omit & { cameraId: string; - frameProcessorFps?: number; // native cannot use number | string, so we use '-1' for 'auto' enableFrameProcessor: boolean; onInitialized?: (event: NativeSyntheticEvent) => void; onError?: (event: NativeSyntheticEvent) => void; - onFrameProcessorPerformanceSuggestionAvailable?: (event: NativeSyntheticEvent) => void; onViewReady: () => void; }; type RefType = React.Component & Readonly; @@ -86,7 +81,6 @@ export class Camera extends React.PureComponent { this.onViewReady = this.onViewReady.bind(this); this.onInitialized = this.onInitialized.bind(this); this.onError = this.onError.bind(this); - this.onFrameProcessorPerformanceSuggestionAvailable = this.onFrameProcessorPerformanceSuggestionAvailable.bind(this); this.ref = React.createRef(); this.lastFrameProcessor = undefined; } @@ -422,11 +416,6 @@ export class Camera extends React.PureComponent { private onInitialized(): void { this.props.onInitialized?.(); } - - private onFrameProcessorPerformanceSuggestionAvailable(event: NativeSyntheticEvent): void { - if (this.props.onFrameProcessorPerformanceSuggestionAvailable != null) - this.props.onFrameProcessorPerformanceSuggestionAvailable(event.nativeEvent); - } //#endregion //#region Lifecycle @@ -479,17 +468,15 @@ export class Camera extends React.PureComponent { /** @internal */ public render(): React.ReactNode { // We remove the big `device` object from the props because we only need to pass `cameraId` to native. - const { device, frameProcessor, frameProcessorFps, ...props } = this.props; + const { device, frameProcessor, ...props } = this.props; return ( ); diff --git a/src/CameraProps.ts b/src/CameraProps.ts index dc00166..a723eee 100644 --- a/src/CameraProps.ts +++ b/src/CameraProps.ts @@ -4,11 +4,6 @@ import type { CameraRuntimeError } from './CameraError'; import type { CameraPreset } from './CameraPreset'; import type { Frame } from './Frame'; -export interface FrameProcessorPerformanceSuggestion { - type: 'can-use-higher-fps' | 'should-use-lower-fps'; - suggestedFrameProcessorFps: number; -} - export interface CameraProps extends ViewProps { /** * The Camera Device to use. @@ -171,11 +166,7 @@ export interface CameraProps extends ViewProps { */ onInitialized?: () => void; /** - * Called when a new performance suggestion for a Frame Processor is available - either if your Frame Processor is running too fast and frames are being dropped, or because it is able to run faster. Optionally, you can adjust your `frameProcessorFps` accordingly. - */ - onFrameProcessorPerformanceSuggestionAvailable?: (suggestion: FrameProcessorPerformanceSuggestion) => void; - /** - * A worklet which will be called for every frame the Camera "sees". Throttle the Frame Processor's frame rate with {@linkcode frameProcessorFps}. + * A worklet which will be called for every frame the Camera "sees". * * > See [the Frame Processors documentation](https://mrousavy.github.io/react-native-vision-camera/docs/guides/frame-processors) for more information * @@ -193,20 +184,5 @@ export interface CameraProps extends ViewProps { * ``` */ frameProcessor?: (frame: Frame) => void; - /** - * Specifies the maximum frame rate the frame processor can use, independent of the Camera's frame rate (`fps` property). - * - * * A value of `'auto'` (default) indicates that the frame processor should execute as fast as it can, without dropping frames. This is achieved by collecting historical data for previous frame processor calls and adjusting frame rate accordingly. - * * A value of `1` indicates that the frame processor gets executed once per second, perfect for code scanning. - * * A value of `10` indicates that the frame processor gets executed 10 times per second, perfect for more realtime use-cases. - * * A value of `25` indicates that the frame processor gets executed 25 times per second, perfect for high-speed realtime use-cases. - * * ...and so on - * - * If you're using higher values, always check your Xcode/Android Studio Logs to make sure your frame processors are executing fast enough - * without blocking the video recording queue. - * - * @default 'auto' - */ - frameProcessorFps?: number | 'auto'; //#endregion } diff --git a/src/Frame.ts b/src/Frame.ts index bb747e1..9907bfc 100644 --- a/src/Frame.ts +++ b/src/Frame.ts @@ -31,19 +31,19 @@ export interface Frame { * ``` */ toString(): string; - /** - * Closes and disposes the Frame. - * Only close frames that you have created yourself, e.g. by copying the frame you receive in a frame processor. - * - * @example - * ```ts - * const frameProcessor = useFrameProcessor((frame) => { - * const smallerCopy = resize(frame, 480, 270) - * // run AI ... - * smallerCopy.close() - * // don't close `frame`! - * }) - * ``` - */ - close(): void; +} + +export interface FrameInternal extends Frame { + /** + * Increment the Frame Buffer ref-count by one. + * + * This is a private API, do not use this. + */ + incrementRefCount(): void; + /** + * Increment the Frame Buffer ref-count by one. + * + * This is a private API, do not use this. + */ + decrementRefCount(): void; } diff --git a/src/FrameProcessorPlugins.ts b/src/FrameProcessorPlugins.ts index bb5363e..d0550f7 100644 --- a/src/FrameProcessorPlugins.ts +++ b/src/FrameProcessorPlugins.ts @@ -1,13 +1,101 @@ -import type { Frame } from './Frame'; +import type { Frame, FrameInternal } from './Frame'; import { Camera } from './Camera'; +import { Worklets } from 'react-native-worklets/src'; // Install VisionCamera Frame Processor JSI Bindings and Plugins Camera.installFrameProcessorBindings(); -type FrameProcessor = (frame: Frame, ...args: unknown[]) => unknown; +type BasicParameterType = string | number | boolean | undefined; +type ParameterType = BasicParameterType | BasicParameterType[] | Record; +type FrameProcessor = (frame: Frame, parameters?: Record) => unknown; type TFrameProcessorPlugins = Record; /** * All natively installed Frame Processor Plugins. */ export const FrameProcessorPlugins = global.FrameProcessorPlugins as TFrameProcessorPlugins; + +const lastFrameProcessorCall = Worklets.createSharedValue(performance.now()); + +/** + * Runs the given function at the given target FPS rate. + * + * For example, if you want to run a heavy face detection algorithm + * only once per second, you can use `runAtTargetFps(1, ...)` to + * throttle it to 1 FPS. + * + * @param fps The target FPS rate at which the given function should be executed + * @param func The function to execute. + * @returns The result of the function if it was executed, or `undefined` otherwise. + * @example + * + * ```ts + * const frameProcessor = useFrameProcessor((frame) => { + * 'worklet' + * console.log('New Frame') + * const face = runAtTargetFps(5, () => { + * 'worklet' + * const faces = detectFaces(frame) + * return faces[0] + * }) + * if (face != null) console.log(`Detected a new face: ${face}`) + * }) + * ``` + */ +export function runAtTargetFps(fps: number, func: () => T): T | undefined { + 'worklet'; + const targetIntervalMs = 1000 / fps; // <-- 60 FPS => 16,6667ms interval + const now = performance.now(); + const diffToLastCall = now - lastFrameProcessorCall.value; + if (diffToLastCall >= targetIntervalMs) { + lastFrameProcessorCall.value = now; + // Last Frame Processor call is already so long ago that we want to make a new call + return func(); + } + return undefined; +} + +const asyncContext = Worklets.createContext('VisionCamera.async'); +const runOnAsyncContext = Worklets.createRunInContextFn((frame: Frame, func: () => void) => { + 'worklet'; + try { + // Call long-running function + func(); + } finally { + // Potentially delete Frame if we were the last ref + (frame as FrameInternal).decrementRefCount(); + } +}, asyncContext); + +/** + * Runs the given function asynchronously, while keeping a strong reference to the Frame. + * + * For example, if you want to run a heavy face detection algorithm + * while still drawing to the screen at 60 FPS, you can use `runAsync(...)` + * to offload the face detection algorithm to a separate thread. + * + * @param frame The current Frame of the Frame Processor. + * @param func The function to execute. + * @example + * + * ```ts + * const frameProcessor = useFrameProcessor((frame) => { + * 'worklet' + * console.log('New Frame') + * runAsync(frame, () => { + * 'worklet' + * const faces = detectFaces(frame) + * const face = [faces0] + * console.log(`Detected a new face: ${face}`) + * }) + * }) + * ``` + */ +export function runAsync(frame: Frame, func: () => void): void { + 'worklet'; + // Increment ref count by one + (frame as FrameInternal).incrementRefCount(); + + // Call in separate background context + runOnAsyncContext(frame, func); +} diff --git a/src/hooks/useFrameProcessor.ts b/src/hooks/useFrameProcessor.ts index cdf314c..506523f 100644 --- a/src/hooks/useFrameProcessor.ts +++ b/src/hooks/useFrameProcessor.ts @@ -1,5 +1,5 @@ import { DependencyList, useCallback } from 'react'; -import type { Frame } from '../Frame'; +import type { Frame, FrameInternal } from '../Frame'; // Install RN Worklets by importing it import 'react-native-worklets/src'; @@ -23,6 +23,17 @@ type FrameProcessor = (frame: Frame) => void; * ``` */ export function useFrameProcessor(frameProcessor: FrameProcessor, dependencies: DependencyList): FrameProcessor { - // eslint-disable-next-line react-hooks/exhaustive-deps - return useCallback(frameProcessor, dependencies); + return useCallback((frame: Frame) => { + 'worklet'; + // Increment ref-count by one + (frame as FrameInternal).incrementRefCount(); + try { + // Call sync frame processor + frameProcessor(frame); + } finally { + // Potentially delete Frame if we were the last ref (no runAsync) + (frame as FrameInternal).decrementRefCount(); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, dependencies); } diff --git a/src/index.ts b/src/index.ts index 206b87f..783eef9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,7 +4,7 @@ export * from './CameraError'; export * from './CameraPosition'; export * from './CameraPreset'; export * from './CameraProps'; -export * from './Frame'; +export { Frame } from './Frame'; export * from './FrameProcessorPlugins'; export * from './CameraProps'; export * from './PhotoFile'; diff --git a/yarn.lock b/yarn.lock index 06a03f3..433aac3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5217,10 +5217,10 @@ js-yaml@^4.1.0: dependencies: argparse "^2.0.1" -jsc-android@^250230.2.1: - version "250230.2.1" - resolved "https://registry.yarnpkg.com/jsc-android/-/jsc-android-250230.2.1.tgz#3790313a970586a03ab0ad47defbc84df54f1b83" - integrity sha512-KmxeBlRjwoqCnBBKGsihFtvsBHyUFlBxJPK4FzeYcIuBfdjv6jFys44JITAgSTbQD+vIdwMEfyZklsuQX0yI1Q== +jsc-android@^250231.0.0: + version "250231.0.0" + resolved "https://registry.yarnpkg.com/jsc-android/-/jsc-android-250231.0.0.tgz#91720f8df382a108872fa4b3f558f33ba5e95262" + integrity sha512-rS46PvsjYmdmuz1OAWXY/1kCYG7pnf1TBqeTiOJr1iDz7s5DLxxC9n/ZMknLDxzYzNVfI7R95MH10emSSG1Wuw== jscodeshift@^0.13.1: version "0.13.1" @@ -6867,25 +6867,29 @@ react-native-builder-bob@^0.20.3: optionalDependencies: jetifier "^2.0.0" -react-native-codegen@^0.71.3: - version "0.71.3" - resolved "https://registry.yarnpkg.com/react-native-codegen/-/react-native-codegen-0.71.3.tgz#75fbc591819050791319ebdb9fe341ee4df5c288" - integrity sha512-5AvdHVU1sAaXg05i0dG664ZTaCaIFaY1znV5vNsj+wUu6MGxNEUNbDKk9dxKUkkxOyk2KZOK5uhzWL0p5H5yZQ== +react-native-codegen@^0.71.5: + version "0.71.5" + resolved "https://registry.yarnpkg.com/react-native-codegen/-/react-native-codegen-0.71.5.tgz#454a42a891cd4ca5fc436440d301044dc1349c14" + integrity sha512-rfsuc0zkuUuMjFnrT55I1mDZ+pBRp2zAiRwxck3m6qeGJBGK5OV5JH66eDQ4aa+3m0of316CqrJDRzVlYufzIg== dependencies: "@babel/parser" "^7.14.0" flow-parser "^0.185.0" jscodeshift "^0.13.1" nullthrows "^1.1.1" -react-native-gradle-plugin@^0.71.14: - version "0.71.14" - resolved "https://registry.yarnpkg.com/react-native-gradle-plugin/-/react-native-gradle-plugin-0.71.14.tgz#cc399662f04fbfcc0e352d03eae1d3efbd5f635a" - integrity sha512-nnLawTZEPPRAKq92UqDkzoGgCBl9aa9zAihFHMwmwzn4WRVdK4O6Cd4XYiyoNOiQzx3Hh9k5WOckHE80C92ivQ== +react-native-gradle-plugin@^0.71.15: + version "0.71.15" + resolved "https://registry.yarnpkg.com/react-native-gradle-plugin/-/react-native-gradle-plugin-0.71.15.tgz#9e6b506f30729fe8eb086981702f4e3c891d2b13" + integrity sha512-7S3pAuPaQJlhax6EZ4JMsDNpj05TfuzX9gPgWLrFfAIWIFLuJ6aDQYAZy2TEI9QJALPoWrj8LWaqP/DGYh14pw== -react-native@^0.71.2: - version "0.71.2" - resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.71.2.tgz#b6977eda2a6dc10baa006bf4ab1ee08318607ce9" - integrity sha512-ZSianM+j+09LoEdVIhrAP/uP8sQhT7dH6olCqM2xlpxmfCgA5NubsK6NABIuZiBlmmqjigyijm5Y/GhBIHDvEg== +"react-native-worklets@https://github.com/chrfalch/react-native-worklets#15d52dd": + version "0.1.0" + resolved "https://github.com/chrfalch/react-native-worklets#15d52dd1289831cecc7906823f613172e0c6cd2e" + +react-native@^0.71.3: + version "0.71.3" + resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.71.3.tgz#0faab799c49e61ba12df9e6525c3ac7d595d673c" + integrity sha512-RYJXCcQGa4NTfKiPgl92eRDUuQ6JGDnHqFEzRwJSqEx9lWvlvRRIebstJfurzPDKLQWQrvITR7aI7e09E25mLw== dependencies: "@jest/create-cache-key-function" "^29.2.1" "@react-native-community/cli" "10.1.3" @@ -6901,7 +6905,7 @@ react-native@^0.71.2: event-target-shim "^5.0.1" invariant "^2.2.4" jest-environment-node "^29.2.1" - jsc-android "^250230.2.1" + jsc-android "^250231.0.0" memoize-one "^5.0.0" metro-react-native-babel-transformer "0.73.7" metro-runtime "0.73.7" @@ -6911,8 +6915,8 @@ react-native@^0.71.2: pretty-format "^26.5.2" promise "^8.3.0" react-devtools-core "^4.26.1" - react-native-codegen "^0.71.3" - react-native-gradle-plugin "^0.71.14" + react-native-codegen "^0.71.5" + react-native-gradle-plugin "^0.71.15" react-refresh "^0.4.0" react-shallow-renderer "^16.15.0" regenerator-runtime "^0.13.2"