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!") }) }) }, []) ```
This commit is contained in:
parent
a0590dccb5
commit
30b56153db
@ -8,12 +8,13 @@
|
||||
#include <jni.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <JsiHostObject.h>
|
||||
|
||||
namespace vision {
|
||||
|
||||
using namespace facebook;
|
||||
|
||||
FrameHostObject::FrameHostObject(jni::alias_ref<JImageProxy::javaobject> image): frame(make_global(image)) { }
|
||||
FrameHostObject::FrameHostObject(jni::alias_ref<JImageProxy::javaobject> 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<jsi::PropNameID> FrameHostObject::getPropertyNames(jsi::Runtime& rt) {
|
||||
std::vector<jsi::PropNameID> 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
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
|
||||
#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<jsi::PropNameID> getPropertyNames(jsi::Runtime &rt) override;
|
||||
|
||||
void close();
|
||||
|
||||
public:
|
||||
jni::global_ref<JImageProxy> 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
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <utility>
|
||||
#include <string>
|
||||
#include <JsiWorklet.h>
|
||||
#include <JsiHostObject.h>
|
||||
|
||||
#include "CameraView.h"
|
||||
#include "FrameHostObject.h"
|
||||
@ -36,9 +37,7 @@ FrameProcessorRuntimeManager::FrameProcessorRuntimeManager(jni::alias_ref<FrameP
|
||||
// Run on Frame Processor Worklet Runtime
|
||||
scheduler->dispatchAsync(std::move(f));
|
||||
};
|
||||
|
||||
_workletContext = std::make_shared<RNWorklet::JsiWorkletContext>("VisionCamera");
|
||||
_workletContext->initialize("VisionCamera",
|
||||
_workletContext = std::make_shared<RNWorklet::JsiWorkletContext>("VisionCamera",
|
||||
jsRuntime,
|
||||
runOnJS,
|
||||
runOnWorklet);
|
||||
@ -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<RNWorklet::JsiWorklet>(runtime, frameProcessor);
|
||||
auto workletInvoker = std::make_shared<RNWorklet::WorkletInvoker>(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<int>(viewTag));
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
// Call JS Frame Processor
|
||||
frameProcessorCallback(image)
|
||||
perfSample.endPerformanceSampleCollection()
|
||||
}
|
||||
image.close()
|
||||
|
||||
if (isReadyForNewEvaluation) {
|
||||
// last evaluation was more than a second ago, evaluate again
|
||||
evaluateNewPerformanceSamples()
|
||||
}
|
||||
})
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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<Double> = 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()
|
||||
}
|
||||
}
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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",
|
||||
|
@ -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 (
|
||||
<View style={styles.container}>
|
||||
{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}
|
||||
/>
|
||||
</TapGestureHandler>
|
||||
</Reanimated.View>
|
||||
|
@ -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"
|
||||
|
@ -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,
|
||||
|
@ -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()
|
||||
// Call the JavaScript Frame Processor func (worklet)
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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).
|
||||
*/
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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<jsi::PropNameID> getPropertyNames(jsi::Runtime& rt) override;
|
||||
void close();
|
||||
|
||||
public:
|
||||
Frame* frame;
|
||||
|
||||
private:
|
||||
void assertIsFrameStrong(jsi::Runtime& runtime, const std::string& accessedPropName);
|
||||
};
|
||||
|
@ -9,16 +9,21 @@
|
||||
#import "FrameHostObject.h"
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <jsi/jsi.h>
|
||||
#import "JsiHostObject.h"
|
||||
#import "JsiSharedValue.h"
|
||||
|
||||
std::vector<jsi::PropNameID> FrameHostObject::getPropertyNames(jsi::Runtime& rt) {
|
||||
std::vector<jsi::PropNameID> 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);
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
@ -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<RNWorklet::JsiWorkletContext> workletContext;
|
||||
}
|
||||
|
||||
@ -59,13 +61,12 @@ __attribute__((objc_runtime_name("_TtC12VisionCamera10CameraView")))
|
||||
};
|
||||
auto runOnWorklet = [](std::function<void()>&& 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<RNWorklet::JsiWorkletContext>("VisionCamera");
|
||||
workletContext->initialize("VisionCamera",
|
||||
workletContext = std::make_shared<RNWorklet::JsiWorkletContext>("VisionCamera",
|
||||
&runtime,
|
||||
runOnJS,
|
||||
runOnWorklet);
|
||||
@ -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<RNWorklet::JsiWorklet>(runtime, arguments[1]);
|
||||
|
||||
RCTExecuteOnMainQueue([=]() {
|
||||
RCTExecuteOnMainQueue(^{
|
||||
auto currentBridge = [RCTBridge currentBridge];
|
||||
auto anonymousView = [currentBridge.uiManager viewForReactTag:[NSNumber numberWithDouble:viewTag]];
|
||||
auto view = static_cast<CameraView*>(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<CameraView*>(anonymousView);
|
||||
view.frameProcessorCallback = nil;
|
||||
NSLog(@"FrameProcessorBindings: Frame processor removed!");
|
||||
});
|
||||
|
||||
return jsi::Value::undefined();
|
||||
|
@ -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<FrameHostObject>(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<FrameHostObject>(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();
|
||||
};
|
||||
}
|
||||
|
@ -138,7 +138,6 @@
|
||||
B887518425E0102000DB86D6 /* CameraView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CameraView.swift; sourceTree = "<group>"; };
|
||||
B88873E5263D46C7008B1D0E /* FrameProcessorPlugin.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FrameProcessorPlugin.h; sourceTree = "<group>"; };
|
||||
B88B47462667C8E00091F538 /* AVCaptureSession+setVideoStabilizationMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AVCaptureSession+setVideoStabilizationMode.swift"; sourceTree = "<group>"; };
|
||||
B8948BDF26DCEE2B00B430E2 /* FrameProcessorPerformanceDataCollector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FrameProcessorPerformanceDataCollector.swift; sourceTree = "<group>"; };
|
||||
B8994E6B263F03E100069589 /* JSIUtils.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = JSIUtils.mm; sourceTree = "<group>"; };
|
||||
B8A751D62609E4980011C623 /* FrameProcessorRuntimeManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FrameProcessorRuntimeManager.h; sourceTree = "<group>"; };
|
||||
B8A751D72609E4B30011C623 /* FrameProcessorRuntimeManager.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FrameProcessorRuntimeManager.mm; sourceTree = "<group>"; };
|
||||
@ -273,7 +272,6 @@
|
||||
B88873E5263D46C7008B1D0E /* FrameProcessorPlugin.h */,
|
||||
B80416F026AB16E8000DEB6A /* VisionCameraScheduler.mm */,
|
||||
B80416F126AB16F3000DEB6A /* VisionCameraScheduler.h */,
|
||||
B8948BDF26DCEE2B00B430E2 /* FrameProcessorPerformanceDataCollector.swift */,
|
||||
);
|
||||
path = "Frame Processor";
|
||||
sourceTree = "<group>";
|
||||
|
@ -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"
|
||||
},
|
||||
|
@ -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<CameraProps, 'device' | 'onInitialized' | 'onError' | 'frameProcessor'> & {
|
||||
cameraId: string;
|
||||
frameProcessorFps?: number; // native cannot use number | string, so we use '-1' for 'auto'
|
||||
enableFrameProcessor: boolean;
|
||||
onInitialized?: (event: NativeSyntheticEvent<void>) => void;
|
||||
onError?: (event: NativeSyntheticEvent<OnErrorEvent>) => void;
|
||||
onFrameProcessorPerformanceSuggestionAvailable?: (event: NativeSyntheticEvent<FrameProcessorPerformanceSuggestion>) => void;
|
||||
onViewReady: () => void;
|
||||
};
|
||||
type RefType = React.Component<NativeCameraViewProps> & Readonly<NativeMethods>;
|
||||
@ -86,7 +81,6 @@ export class Camera extends React.PureComponent<CameraProps> {
|
||||
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<RefType>();
|
||||
this.lastFrameProcessor = undefined;
|
||||
}
|
||||
@ -422,11 +416,6 @@ export class Camera extends React.PureComponent<CameraProps> {
|
||||
private onInitialized(): void {
|
||||
this.props.onInitialized?.();
|
||||
}
|
||||
|
||||
private onFrameProcessorPerformanceSuggestionAvailable(event: NativeSyntheticEvent<FrameProcessorPerformanceSuggestion>): void {
|
||||
if (this.props.onFrameProcessorPerformanceSuggestionAvailable != null)
|
||||
this.props.onFrameProcessorPerformanceSuggestionAvailable(event.nativeEvent);
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//#region Lifecycle
|
||||
@ -479,17 +468,15 @@ export class Camera extends React.PureComponent<CameraProps> {
|
||||
/** @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 (
|
||||
<NativeCameraView
|
||||
{...props}
|
||||
frameProcessorFps={frameProcessorFps === 'auto' ? -1 : frameProcessorFps}
|
||||
cameraId={device.id}
|
||||
ref={this.ref}
|
||||
onViewReady={this.onViewReady}
|
||||
onInitialized={this.onInitialized}
|
||||
onError={this.onError}
|
||||
onFrameProcessorPerformanceSuggestionAvailable={this.onFrameProcessorPerformanceSuggestionAvailable}
|
||||
enableFrameProcessor={frameProcessor != null}
|
||||
/>
|
||||
);
|
||||
|
@ -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
|
||||
}
|
||||
|
30
src/Frame.ts
30
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;
|
||||
}
|
||||
|
@ -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<string, BasicParameterType | undefined>;
|
||||
type FrameProcessor = (frame: Frame, parameters?: Record<string, ParameterType | undefined>) => unknown;
|
||||
type TFrameProcessorPlugins = Record<string, FrameProcessor>;
|
||||
|
||||
/**
|
||||
* 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<T>(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);
|
||||
}
|
||||
|
@ -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 {
|
||||
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
|
||||
return useCallback(frameProcessor, dependencies);
|
||||
}, dependencies);
|
||||
}
|
||||
|
@ -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';
|
||||
|
42
yarn.lock
42
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"
|
||||
|
Loading…
Reference in New Issue
Block a user