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 <jni.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <JsiHostObject.h>
|
||||||
|
|
||||||
namespace vision {
|
namespace vision {
|
||||||
|
|
||||||
using namespace facebook;
|
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() {
|
FrameHostObject::~FrameHostObject() {
|
||||||
// Hermes' Garbage Collector (Hades GC) calls destructors on a separate Thread
|
// 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> FrameHostObject::getPropertyNames(jsi::Runtime& rt) {
|
||||||
std::vector<jsi::PropNameID> result;
|
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("width")));
|
||||||
result.push_back(jsi::PropNameID::forUtf8(rt, std::string("height")));
|
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("bytesPerRow")));
|
||||||
result.push_back(jsi::PropNameID::forUtf8(rt, std::string("planesCount")));
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
jsi::Value FrameHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& propNameId) {
|
jsi::Value FrameHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& propName) {
|
||||||
auto name = propNameId.utf8(runtime);
|
auto name = propName.utf8(runtime);
|
||||||
|
|
||||||
if (name == "toString") {
|
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) {
|
if (!this->frame) {
|
||||||
return jsi::String::createFromUtf8(runtime, "[closed 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);
|
return jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forUtf8(runtime, "toString"), 0, toString);
|
||||||
}
|
}
|
||||||
if (name == "close") {
|
if (name == "incrementRefCount") {
|
||||||
auto close = [this] (jsi::Runtime& runtime, const jsi::Value&, const jsi::Value*, size_t) -> jsi::Value {
|
auto incrementRefCount = JSI_HOST_FUNCTION_LAMBDA {
|
||||||
if (!this->frame) {
|
// Increment retain count by one so ARC doesn't destroy the Frame Buffer.
|
||||||
throw jsi::JSError(runtime, "Trying to close an already closed frame! Did you call frame.close() twice?");
|
std::lock_guard lock(this->_refCountMutex);
|
||||||
}
|
this->_refCount++;
|
||||||
this->close();
|
|
||||||
return jsi::Value::undefined();
|
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") {
|
if (name == "isValid") {
|
||||||
return jsi::Value(this->frame && this->frame->getIsValid());
|
return jsi::Value(this->frame && this->frame->getIsValid());
|
||||||
}
|
}
|
||||||
if (name == "width") {
|
if (name == "width") {
|
||||||
this->assertIsFrameStrong(runtime, name);
|
|
||||||
return jsi::Value(this->frame->getWidth());
|
return jsi::Value(this->frame->getWidth());
|
||||||
}
|
}
|
||||||
if (name == "height") {
|
if (name == "height") {
|
||||||
this->assertIsFrameStrong(runtime, name);
|
|
||||||
return jsi::Value(this->frame->getHeight());
|
return jsi::Value(this->frame->getHeight());
|
||||||
}
|
}
|
||||||
if (name == "bytesPerRow") {
|
if (name == "bytesPerRow") {
|
||||||
this->assertIsFrameStrong(runtime, name);
|
|
||||||
return jsi::Value(this->frame->getBytesPerRow());
|
return jsi::Value(this->frame->getBytesPerRow());
|
||||||
}
|
}
|
||||||
if (name == "planesCount") {
|
if (name == "planesCount") {
|
||||||
this->assertIsFrameStrong(runtime, name);
|
|
||||||
return jsi::Value(this->frame->getPlanesCount());
|
return jsi::Value(this->frame->getPlanesCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
return jsi::Value::undefined();
|
// fallback to base implementation
|
||||||
}
|
return HostObject::get(runtime, propName);
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace vision
|
} // namespace vision
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include <fbjni/fbjni.h>
|
#include <fbjni/fbjni.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
#include "java-bindings/JImageProxy.h"
|
#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;
|
jsi::Value get(jsi::Runtime &, const jsi::PropNameID &name) override;
|
||||||
std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime &rt) override;
|
std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime &rt) override;
|
||||||
|
|
||||||
void close();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
jni::global_ref<JImageProxy> frame;
|
jni::global_ref<JImageProxy> frame;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static auto constexpr TAG = "VisionCamera";
|
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
|
} // namespace vision
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <JsiWorklet.h>
|
#include <JsiWorklet.h>
|
||||||
|
#include <JsiHostObject.h>
|
||||||
|
|
||||||
#include "CameraView.h"
|
#include "CameraView.h"
|
||||||
#include "FrameHostObject.h"
|
#include "FrameHostObject.h"
|
||||||
@ -36,12 +37,10 @@ FrameProcessorRuntimeManager::FrameProcessorRuntimeManager(jni::alias_ref<FrameP
|
|||||||
// Run on Frame Processor Worklet Runtime
|
// Run on Frame Processor Worklet Runtime
|
||||||
scheduler->dispatchAsync(std::move(f));
|
scheduler->dispatchAsync(std::move(f));
|
||||||
};
|
};
|
||||||
|
_workletContext = std::make_shared<RNWorklet::JsiWorkletContext>("VisionCamera",
|
||||||
_workletContext = std::make_shared<RNWorklet::JsiWorkletContext>("VisionCamera");
|
jsRuntime,
|
||||||
_workletContext->initialize("VisionCamera",
|
runOnJS,
|
||||||
jsRuntime,
|
runOnWorklet);
|
||||||
runOnJS,
|
|
||||||
runOnWorklet);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// JNI binding
|
// JNI binding
|
||||||
@ -96,8 +95,7 @@ void FrameProcessorRuntimeManager::logErrorToJS(const std::string& message) {
|
|||||||
void FrameProcessorRuntimeManager::setFrameProcessor(jsi::Runtime& runtime,
|
void FrameProcessorRuntimeManager::setFrameProcessor(jsi::Runtime& runtime,
|
||||||
int viewTag,
|
int viewTag,
|
||||||
const jsi::Value& frameProcessor) {
|
const jsi::Value& frameProcessor) {
|
||||||
__android_log_write(ANDROID_LOG_INFO, TAG,
|
__android_log_write(ANDROID_LOG_INFO, TAG, "Setting new Frame Processor...");
|
||||||
"Setting new Frame Processor...");
|
|
||||||
|
|
||||||
if (!_workletContext) {
|
if (!_workletContext) {
|
||||||
throw jsi::JSError(runtime,
|
throw jsi::JSError(runtime,
|
||||||
@ -106,13 +104,10 @@ void FrameProcessorRuntimeManager::setFrameProcessor(jsi::Runtime& runtime,
|
|||||||
|
|
||||||
// find camera view
|
// find camera view
|
||||||
auto cameraView = findCameraViewById(viewTag);
|
auto cameraView = findCameraViewById(viewTag);
|
||||||
__android_log_write(ANDROID_LOG_INFO, TAG, "Found CameraView!");
|
|
||||||
|
|
||||||
// convert jsi::Function to a Worklet (can be shared across runtimes)
|
// 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 worklet = std::make_shared<RNWorklet::JsiWorklet>(runtime, frameProcessor);
|
||||||
auto workletInvoker = std::make_shared<RNWorklet::WorkletInvoker>(worklet);
|
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) {
|
_workletContext->invokeOnWorkletThread([=](RNWorklet::JsiWorkletContext*, jsi::Runtime& rt) {
|
||||||
// Set Frame Processor as callable C++ lambda - this will then call the Worklet
|
// 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
|
// call Java method to unset frame processor
|
||||||
cameraView->cthis()->unsetFrameProcessor();
|
cameraView->cthis()->unsetFrameProcessor();
|
||||||
|
|
||||||
__android_log_write(ANDROID_LOG_INFO, TAG, "Frame Processor removed!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// actual JSI installer
|
// actual JSI installer
|
||||||
@ -158,21 +151,8 @@ void FrameProcessorRuntimeManager::installJSIBindings() {
|
|||||||
|
|
||||||
auto& jsiRuntime = *_jsRuntime;
|
auto& jsiRuntime = *_jsRuntime;
|
||||||
|
|
||||||
auto setFrameProcessor = [this](jsi::Runtime &runtime,
|
auto setFrameProcessor = JSI_HOST_FUNCTION_LAMBDA {
|
||||||
const jsi::Value &thisValue,
|
__android_log_write(ANDROID_LOG_INFO, TAG, "Setting new Frame Processor...");
|
||||||
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!");
|
|
||||||
}
|
|
||||||
|
|
||||||
double viewTag = arguments[0].asNumber();
|
double viewTag = arguments[0].asNumber();
|
||||||
const jsi::Value& frameProcessor = arguments[1];
|
const jsi::Value& frameProcessor = arguments[1];
|
||||||
@ -190,15 +170,8 @@ void FrameProcessorRuntimeManager::installJSIBindings() {
|
|||||||
setFrameProcessor));
|
setFrameProcessor));
|
||||||
|
|
||||||
|
|
||||||
auto unsetFrameProcessor = [this](jsi::Runtime &runtime,
|
auto unsetFrameProcessor = JSI_HOST_FUNCTION_LAMBDA {
|
||||||
const jsi::Value &thisValue,
|
|
||||||
const jsi::Value *arguments,
|
|
||||||
size_t count) -> jsi::Value {
|
|
||||||
__android_log_write(ANDROID_LOG_INFO, TAG, "Removing Frame Processor...");
|
__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();
|
auto viewTag = arguments[0].asNumber();
|
||||||
this->unsetFrameProcessor(static_cast<int>(viewTag));
|
this->unsetFrameProcessor(static_cast<int>(viewTag));
|
||||||
|
@ -31,17 +31,6 @@ fun CameraView.invokeOnError(error: Throwable) {
|
|||||||
reactContext.getJSModule(RCTEventEmitter::class.java).receiveEvent(id, "cameraError", event)
|
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() {
|
fun CameraView.invokeOnViewReady() {
|
||||||
val event = Arguments.createMap()
|
val event = Arguments.createMap()
|
||||||
val reactContext = context as ReactContext
|
val reactContext = context as ReactContext
|
||||||
|
@ -25,7 +25,6 @@ import com.facebook.jni.HybridData
|
|||||||
import com.facebook.proguard.annotations.DoNotStrip
|
import com.facebook.proguard.annotations.DoNotStrip
|
||||||
import com.facebook.react.bridge.*
|
import com.facebook.react.bridge.*
|
||||||
import com.facebook.react.uimanager.events.RCTEventEmitter
|
import com.facebook.react.uimanager.events.RCTEventEmitter
|
||||||
import com.mrousavy.camera.frameprocessor.FrameProcessorPerformanceDataCollector
|
|
||||||
import com.mrousavy.camera.frameprocessor.FrameProcessorRuntimeManager
|
import com.mrousavy.camera.frameprocessor.FrameProcessorRuntimeManager
|
||||||
import com.mrousavy.camera.utils.*
|
import com.mrousavy.camera.utils.*
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
@ -103,13 +102,6 @@ class CameraView(context: Context, private val frameProcessorThread: ExecutorSer
|
|||||||
field = value
|
field = value
|
||||||
setOnTouchListener(if (value) touchEventListener else null)
|
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 properties
|
||||||
private var isMounted = false
|
private var isMounted = false
|
||||||
@ -166,16 +158,6 @@ class CameraView(context: Context, private val frameProcessorThread: ExecutorSer
|
|||||||
private var minZoom: Float = 1f
|
private var minZoom: Float = 1f
|
||||||
private var maxZoom: 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
|
@DoNotStrip
|
||||||
private var mHybridData: HybridData? = null
|
private var mHybridData: HybridData? = null
|
||||||
|
|
||||||
@ -480,21 +462,8 @@ class CameraView(context: Context, private val frameProcessorThread: ExecutorSer
|
|||||||
Log.i(TAG, "Adding ImageAnalysis use-case...")
|
Log.i(TAG, "Adding ImageAnalysis use-case...")
|
||||||
imageAnalysis = imageAnalysisBuilder.build().apply {
|
imageAnalysis = imageAnalysisBuilder.build().apply {
|
||||||
setAnalyzer(cameraExecutor, { image ->
|
setAnalyzer(cameraExecutor, { image ->
|
||||||
val now = System.currentTimeMillis()
|
// Call JS Frame Processor
|
||||||
val intervalMs = (1.0 / actualFrameProcessorFps) * 1000.0
|
frameProcessorCallback(image)
|
||||||
if (now - lastFrameProcessorCall > intervalMs) {
|
|
||||||
lastFrameProcessorCall = now
|
|
||||||
|
|
||||||
val perfSample = frameProcessorPerformanceDataCollector.beginPerformanceSampleCollection()
|
|
||||||
frameProcessorCallback(image)
|
|
||||||
perfSample.endPerformanceSampleCollection()
|
|
||||||
}
|
|
||||||
image.close()
|
|
||||||
|
|
||||||
if (isReadyForNewEvaluation) {
|
|
||||||
// last evaluation was more than a second ago, evaluate again
|
|
||||||
evaluateNewPerformanceSamples()
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
useCases.add(imageAnalysis!!)
|
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("cameraViewReady", MapBuilder.of("registrationName", "onViewReady"))
|
||||||
.put("cameraInitialized", MapBuilder.of("registrationName", "onInitialized"))
|
.put("cameraInitialized", MapBuilder.of("registrationName", "onInitialized"))
|
||||||
.put("cameraError", MapBuilder.of("registrationName", "onError"))
|
.put("cameraError", MapBuilder.of("registrationName", "onError"))
|
||||||
.put("cameraPerformanceSuggestionAvailable", MapBuilder.of("registrationName", "onFrameProcessorPerformanceSuggestionAvailable"))
|
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,13 +107,6 @@ class CameraViewManager(reactContext: ReactApplicationContext) : ViewGroupManage
|
|||||||
view.fps = if (fps > 0) fps else null
|
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")
|
@ReactProp(name = "hdr")
|
||||||
fun setHdr(view: CameraView, hdr: Boolean?) {
|
fun setHdr(view: CameraView, hdr: Boolean?) {
|
||||||
if (view.hdr != hdr)
|
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
|
### 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
|
### ESLint react-hooks plugin
|
||||||
|
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
PODS:
|
PODS:
|
||||||
- boost (1.76.0)
|
- boost (1.76.0)
|
||||||
- DoubleConversion (1.1.6)
|
- DoubleConversion (1.1.6)
|
||||||
- FBLazyVector (0.71.2)
|
- FBLazyVector (0.71.3)
|
||||||
- FBReactNativeSpec (0.71.2):
|
- FBReactNativeSpec (0.71.3):
|
||||||
- RCT-Folly (= 2021.07.22.00)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- RCTRequired (= 0.71.2)
|
- RCTRequired (= 0.71.3)
|
||||||
- RCTTypeSafety (= 0.71.2)
|
- RCTTypeSafety (= 0.71.3)
|
||||||
- React-Core (= 0.71.2)
|
- React-Core (= 0.71.3)
|
||||||
- React-jsi (= 0.71.2)
|
- React-jsi (= 0.71.3)
|
||||||
- ReactCommon/turbomodule/core (= 0.71.2)
|
- ReactCommon/turbomodule/core (= 0.71.3)
|
||||||
- fmt (6.2.1)
|
- fmt (6.2.1)
|
||||||
- glog (0.3.5)
|
- glog (0.3.5)
|
||||||
- hermes-engine (0.71.2):
|
- hermes-engine (0.71.3):
|
||||||
- hermes-engine/Pre-built (= 0.71.2)
|
- hermes-engine/Pre-built (= 0.71.3)
|
||||||
- hermes-engine/Pre-built (0.71.2)
|
- hermes-engine/Pre-built (0.71.3)
|
||||||
- libevent (2.1.12)
|
- libevent (2.1.12)
|
||||||
- RCT-Folly (2021.07.22.00):
|
- RCT-Folly (2021.07.22.00):
|
||||||
- boost
|
- boost
|
||||||
@ -32,26 +32,26 @@ PODS:
|
|||||||
- fmt (~> 6.2.1)
|
- fmt (~> 6.2.1)
|
||||||
- glog
|
- glog
|
||||||
- libevent
|
- libevent
|
||||||
- RCTRequired (0.71.2)
|
- RCTRequired (0.71.3)
|
||||||
- RCTTypeSafety (0.71.2):
|
- RCTTypeSafety (0.71.3):
|
||||||
- FBLazyVector (= 0.71.2)
|
- FBLazyVector (= 0.71.3)
|
||||||
- RCTRequired (= 0.71.2)
|
- RCTRequired (= 0.71.3)
|
||||||
- React-Core (= 0.71.2)
|
- React-Core (= 0.71.3)
|
||||||
- React (0.71.2):
|
- React (0.71.3):
|
||||||
- React-Core (= 0.71.2)
|
- React-Core (= 0.71.3)
|
||||||
- React-Core/DevSupport (= 0.71.2)
|
- React-Core/DevSupport (= 0.71.3)
|
||||||
- React-Core/RCTWebSocket (= 0.71.2)
|
- React-Core/RCTWebSocket (= 0.71.3)
|
||||||
- React-RCTActionSheet (= 0.71.2)
|
- React-RCTActionSheet (= 0.71.3)
|
||||||
- React-RCTAnimation (= 0.71.2)
|
- React-RCTAnimation (= 0.71.3)
|
||||||
- React-RCTBlob (= 0.71.2)
|
- React-RCTBlob (= 0.71.3)
|
||||||
- React-RCTImage (= 0.71.2)
|
- React-RCTImage (= 0.71.3)
|
||||||
- React-RCTLinking (= 0.71.2)
|
- React-RCTLinking (= 0.71.3)
|
||||||
- React-RCTNetwork (= 0.71.2)
|
- React-RCTNetwork (= 0.71.3)
|
||||||
- React-RCTSettings (= 0.71.2)
|
- React-RCTSettings (= 0.71.3)
|
||||||
- React-RCTText (= 0.71.2)
|
- React-RCTText (= 0.71.3)
|
||||||
- React-RCTVibration (= 0.71.2)
|
- React-RCTVibration (= 0.71.3)
|
||||||
- React-callinvoker (0.71.2)
|
- React-callinvoker (0.71.3)
|
||||||
- React-Codegen (0.71.2):
|
- React-Codegen (0.71.3):
|
||||||
- FBReactNativeSpec
|
- FBReactNativeSpec
|
||||||
- hermes-engine
|
- hermes-engine
|
||||||
- RCT-Folly
|
- RCT-Folly
|
||||||
@ -62,209 +62,209 @@ PODS:
|
|||||||
- React-jsiexecutor
|
- React-jsiexecutor
|
||||||
- ReactCommon/turbomodule/bridging
|
- ReactCommon/turbomodule/bridging
|
||||||
- ReactCommon/turbomodule/core
|
- ReactCommon/turbomodule/core
|
||||||
- React-Core (0.71.2):
|
- React-Core (0.71.3):
|
||||||
- glog
|
- glog
|
||||||
- hermes-engine
|
- hermes-engine
|
||||||
- RCT-Folly (= 2021.07.22.00)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-Core/Default (= 0.71.2)
|
- React-Core/Default (= 0.71.3)
|
||||||
- React-cxxreact (= 0.71.2)
|
- React-cxxreact (= 0.71.3)
|
||||||
- React-hermes
|
- React-hermes
|
||||||
- React-jsi (= 0.71.2)
|
- React-jsi (= 0.71.3)
|
||||||
- React-jsiexecutor (= 0.71.2)
|
- React-jsiexecutor (= 0.71.3)
|
||||||
- React-perflogger (= 0.71.2)
|
- React-perflogger (= 0.71.3)
|
||||||
- Yoga
|
- Yoga
|
||||||
- React-Core/CoreModulesHeaders (0.71.2):
|
- React-Core/CoreModulesHeaders (0.71.3):
|
||||||
- glog
|
- glog
|
||||||
- hermes-engine
|
- hermes-engine
|
||||||
- RCT-Folly (= 2021.07.22.00)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-Core/Default
|
- React-Core/Default
|
||||||
- React-cxxreact (= 0.71.2)
|
- React-cxxreact (= 0.71.3)
|
||||||
- React-hermes
|
- React-hermes
|
||||||
- React-jsi (= 0.71.2)
|
- React-jsi (= 0.71.3)
|
||||||
- React-jsiexecutor (= 0.71.2)
|
- React-jsiexecutor (= 0.71.3)
|
||||||
- React-perflogger (= 0.71.2)
|
- React-perflogger (= 0.71.3)
|
||||||
- Yoga
|
- Yoga
|
||||||
- React-Core/Default (0.71.2):
|
- React-Core/Default (0.71.3):
|
||||||
- glog
|
- glog
|
||||||
- hermes-engine
|
- hermes-engine
|
||||||
- RCT-Folly (= 2021.07.22.00)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-cxxreact (= 0.71.2)
|
- React-cxxreact (= 0.71.3)
|
||||||
- React-hermes
|
- React-hermes
|
||||||
- React-jsi (= 0.71.2)
|
- React-jsi (= 0.71.3)
|
||||||
- React-jsiexecutor (= 0.71.2)
|
- React-jsiexecutor (= 0.71.3)
|
||||||
- React-perflogger (= 0.71.2)
|
- React-perflogger (= 0.71.3)
|
||||||
- Yoga
|
- Yoga
|
||||||
- React-Core/DevSupport (0.71.2):
|
- React-Core/DevSupport (0.71.3):
|
||||||
- glog
|
- glog
|
||||||
- hermes-engine
|
- hermes-engine
|
||||||
- RCT-Folly (= 2021.07.22.00)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-Core/Default (= 0.71.2)
|
- React-Core/Default (= 0.71.3)
|
||||||
- React-Core/RCTWebSocket (= 0.71.2)
|
- React-Core/RCTWebSocket (= 0.71.3)
|
||||||
- React-cxxreact (= 0.71.2)
|
- React-cxxreact (= 0.71.3)
|
||||||
- React-hermes
|
- React-hermes
|
||||||
- React-jsi (= 0.71.2)
|
- React-jsi (= 0.71.3)
|
||||||
- React-jsiexecutor (= 0.71.2)
|
- React-jsiexecutor (= 0.71.3)
|
||||||
- React-jsinspector (= 0.71.2)
|
- React-jsinspector (= 0.71.3)
|
||||||
- React-perflogger (= 0.71.2)
|
- React-perflogger (= 0.71.3)
|
||||||
- Yoga
|
- Yoga
|
||||||
- React-Core/RCTActionSheetHeaders (0.71.2):
|
- React-Core/RCTActionSheetHeaders (0.71.3):
|
||||||
- glog
|
- glog
|
||||||
- hermes-engine
|
- hermes-engine
|
||||||
- RCT-Folly (= 2021.07.22.00)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-Core/Default
|
- React-Core/Default
|
||||||
- React-cxxreact (= 0.71.2)
|
- React-cxxreact (= 0.71.3)
|
||||||
- React-hermes
|
- React-hermes
|
||||||
- React-jsi (= 0.71.2)
|
- React-jsi (= 0.71.3)
|
||||||
- React-jsiexecutor (= 0.71.2)
|
- React-jsiexecutor (= 0.71.3)
|
||||||
- React-perflogger (= 0.71.2)
|
- React-perflogger (= 0.71.3)
|
||||||
- Yoga
|
- Yoga
|
||||||
- React-Core/RCTAnimationHeaders (0.71.2):
|
- React-Core/RCTAnimationHeaders (0.71.3):
|
||||||
- glog
|
- glog
|
||||||
- hermes-engine
|
- hermes-engine
|
||||||
- RCT-Folly (= 2021.07.22.00)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-Core/Default
|
- React-Core/Default
|
||||||
- React-cxxreact (= 0.71.2)
|
- React-cxxreact (= 0.71.3)
|
||||||
- React-hermes
|
- React-hermes
|
||||||
- React-jsi (= 0.71.2)
|
- React-jsi (= 0.71.3)
|
||||||
- React-jsiexecutor (= 0.71.2)
|
- React-jsiexecutor (= 0.71.3)
|
||||||
- React-perflogger (= 0.71.2)
|
- React-perflogger (= 0.71.3)
|
||||||
- Yoga
|
- Yoga
|
||||||
- React-Core/RCTBlobHeaders (0.71.2):
|
- React-Core/RCTBlobHeaders (0.71.3):
|
||||||
- glog
|
- glog
|
||||||
- hermes-engine
|
- hermes-engine
|
||||||
- RCT-Folly (= 2021.07.22.00)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-Core/Default
|
- React-Core/Default
|
||||||
- React-cxxreact (= 0.71.2)
|
- React-cxxreact (= 0.71.3)
|
||||||
- React-hermes
|
- React-hermes
|
||||||
- React-jsi (= 0.71.2)
|
- React-jsi (= 0.71.3)
|
||||||
- React-jsiexecutor (= 0.71.2)
|
- React-jsiexecutor (= 0.71.3)
|
||||||
- React-perflogger (= 0.71.2)
|
- React-perflogger (= 0.71.3)
|
||||||
- Yoga
|
- Yoga
|
||||||
- React-Core/RCTImageHeaders (0.71.2):
|
- React-Core/RCTImageHeaders (0.71.3):
|
||||||
- glog
|
- glog
|
||||||
- hermes-engine
|
- hermes-engine
|
||||||
- RCT-Folly (= 2021.07.22.00)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-Core/Default
|
- React-Core/Default
|
||||||
- React-cxxreact (= 0.71.2)
|
- React-cxxreact (= 0.71.3)
|
||||||
- React-hermes
|
- React-hermes
|
||||||
- React-jsi (= 0.71.2)
|
- React-jsi (= 0.71.3)
|
||||||
- React-jsiexecutor (= 0.71.2)
|
- React-jsiexecutor (= 0.71.3)
|
||||||
- React-perflogger (= 0.71.2)
|
- React-perflogger (= 0.71.3)
|
||||||
- Yoga
|
- Yoga
|
||||||
- React-Core/RCTLinkingHeaders (0.71.2):
|
- React-Core/RCTLinkingHeaders (0.71.3):
|
||||||
- glog
|
- glog
|
||||||
- hermes-engine
|
- hermes-engine
|
||||||
- RCT-Folly (= 2021.07.22.00)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-Core/Default
|
- React-Core/Default
|
||||||
- React-cxxreact (= 0.71.2)
|
- React-cxxreact (= 0.71.3)
|
||||||
- React-hermes
|
- React-hermes
|
||||||
- React-jsi (= 0.71.2)
|
- React-jsi (= 0.71.3)
|
||||||
- React-jsiexecutor (= 0.71.2)
|
- React-jsiexecutor (= 0.71.3)
|
||||||
- React-perflogger (= 0.71.2)
|
- React-perflogger (= 0.71.3)
|
||||||
- Yoga
|
- Yoga
|
||||||
- React-Core/RCTNetworkHeaders (0.71.2):
|
- React-Core/RCTNetworkHeaders (0.71.3):
|
||||||
- glog
|
- glog
|
||||||
- hermes-engine
|
- hermes-engine
|
||||||
- RCT-Folly (= 2021.07.22.00)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-Core/Default
|
- React-Core/Default
|
||||||
- React-cxxreact (= 0.71.2)
|
- React-cxxreact (= 0.71.3)
|
||||||
- React-hermes
|
- React-hermes
|
||||||
- React-jsi (= 0.71.2)
|
- React-jsi (= 0.71.3)
|
||||||
- React-jsiexecutor (= 0.71.2)
|
- React-jsiexecutor (= 0.71.3)
|
||||||
- React-perflogger (= 0.71.2)
|
- React-perflogger (= 0.71.3)
|
||||||
- Yoga
|
- Yoga
|
||||||
- React-Core/RCTSettingsHeaders (0.71.2):
|
- React-Core/RCTSettingsHeaders (0.71.3):
|
||||||
- glog
|
- glog
|
||||||
- hermes-engine
|
- hermes-engine
|
||||||
- RCT-Folly (= 2021.07.22.00)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-Core/Default
|
- React-Core/Default
|
||||||
- React-cxxreact (= 0.71.2)
|
- React-cxxreact (= 0.71.3)
|
||||||
- React-hermes
|
- React-hermes
|
||||||
- React-jsi (= 0.71.2)
|
- React-jsi (= 0.71.3)
|
||||||
- React-jsiexecutor (= 0.71.2)
|
- React-jsiexecutor (= 0.71.3)
|
||||||
- React-perflogger (= 0.71.2)
|
- React-perflogger (= 0.71.3)
|
||||||
- Yoga
|
- Yoga
|
||||||
- React-Core/RCTTextHeaders (0.71.2):
|
- React-Core/RCTTextHeaders (0.71.3):
|
||||||
- glog
|
- glog
|
||||||
- hermes-engine
|
- hermes-engine
|
||||||
- RCT-Folly (= 2021.07.22.00)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-Core/Default
|
- React-Core/Default
|
||||||
- React-cxxreact (= 0.71.2)
|
- React-cxxreact (= 0.71.3)
|
||||||
- React-hermes
|
- React-hermes
|
||||||
- React-jsi (= 0.71.2)
|
- React-jsi (= 0.71.3)
|
||||||
- React-jsiexecutor (= 0.71.2)
|
- React-jsiexecutor (= 0.71.3)
|
||||||
- React-perflogger (= 0.71.2)
|
- React-perflogger (= 0.71.3)
|
||||||
- Yoga
|
- Yoga
|
||||||
- React-Core/RCTVibrationHeaders (0.71.2):
|
- React-Core/RCTVibrationHeaders (0.71.3):
|
||||||
- glog
|
- glog
|
||||||
- hermes-engine
|
- hermes-engine
|
||||||
- RCT-Folly (= 2021.07.22.00)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-Core/Default
|
- React-Core/Default
|
||||||
- React-cxxreact (= 0.71.2)
|
- React-cxxreact (= 0.71.3)
|
||||||
- React-hermes
|
- React-hermes
|
||||||
- React-jsi (= 0.71.2)
|
- React-jsi (= 0.71.3)
|
||||||
- React-jsiexecutor (= 0.71.2)
|
- React-jsiexecutor (= 0.71.3)
|
||||||
- React-perflogger (= 0.71.2)
|
- React-perflogger (= 0.71.3)
|
||||||
- Yoga
|
- Yoga
|
||||||
- React-Core/RCTWebSocket (0.71.2):
|
- React-Core/RCTWebSocket (0.71.3):
|
||||||
- glog
|
- glog
|
||||||
- hermes-engine
|
- hermes-engine
|
||||||
- RCT-Folly (= 2021.07.22.00)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-Core/Default (= 0.71.2)
|
- React-Core/Default (= 0.71.3)
|
||||||
- React-cxxreact (= 0.71.2)
|
- React-cxxreact (= 0.71.3)
|
||||||
- React-hermes
|
- React-hermes
|
||||||
- React-jsi (= 0.71.2)
|
- React-jsi (= 0.71.3)
|
||||||
- React-jsiexecutor (= 0.71.2)
|
- React-jsiexecutor (= 0.71.3)
|
||||||
- React-perflogger (= 0.71.2)
|
- React-perflogger (= 0.71.3)
|
||||||
- Yoga
|
- Yoga
|
||||||
- React-CoreModules (0.71.2):
|
- React-CoreModules (0.71.3):
|
||||||
- RCT-Folly (= 2021.07.22.00)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- RCTTypeSafety (= 0.71.2)
|
- RCTTypeSafety (= 0.71.3)
|
||||||
- React-Codegen (= 0.71.2)
|
- React-Codegen (= 0.71.3)
|
||||||
- React-Core/CoreModulesHeaders (= 0.71.2)
|
- React-Core/CoreModulesHeaders (= 0.71.3)
|
||||||
- React-jsi (= 0.71.2)
|
- React-jsi (= 0.71.3)
|
||||||
- React-RCTBlob
|
- React-RCTBlob
|
||||||
- React-RCTImage (= 0.71.2)
|
- React-RCTImage (= 0.71.3)
|
||||||
- ReactCommon/turbomodule/core (= 0.71.2)
|
- ReactCommon/turbomodule/core (= 0.71.3)
|
||||||
- React-cxxreact (0.71.2):
|
- React-cxxreact (0.71.3):
|
||||||
- boost (= 1.76.0)
|
- boost (= 1.76.0)
|
||||||
- DoubleConversion
|
- DoubleConversion
|
||||||
- glog
|
- glog
|
||||||
- hermes-engine
|
- hermes-engine
|
||||||
- RCT-Folly (= 2021.07.22.00)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-callinvoker (= 0.71.2)
|
- React-callinvoker (= 0.71.3)
|
||||||
- React-jsi (= 0.71.2)
|
- React-jsi (= 0.71.3)
|
||||||
- React-jsinspector (= 0.71.2)
|
- React-jsinspector (= 0.71.3)
|
||||||
- React-logger (= 0.71.2)
|
- React-logger (= 0.71.3)
|
||||||
- React-perflogger (= 0.71.2)
|
- React-perflogger (= 0.71.3)
|
||||||
- React-runtimeexecutor (= 0.71.2)
|
- React-runtimeexecutor (= 0.71.3)
|
||||||
- React-hermes (0.71.2):
|
- React-hermes (0.71.3):
|
||||||
- DoubleConversion
|
- DoubleConversion
|
||||||
- glog
|
- glog
|
||||||
- hermes-engine
|
- hermes-engine
|
||||||
- RCT-Folly (= 2021.07.22.00)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- RCT-Folly/Futures (= 2021.07.22.00)
|
- RCT-Folly/Futures (= 2021.07.22.00)
|
||||||
- React-cxxreact (= 0.71.2)
|
- React-cxxreact (= 0.71.3)
|
||||||
- React-jsi
|
- React-jsi
|
||||||
- React-jsiexecutor (= 0.71.2)
|
- React-jsiexecutor (= 0.71.3)
|
||||||
- React-jsinspector (= 0.71.2)
|
- React-jsinspector (= 0.71.3)
|
||||||
- React-perflogger (= 0.71.2)
|
- React-perflogger (= 0.71.3)
|
||||||
- React-jsi (0.71.2):
|
- React-jsi (0.71.3):
|
||||||
- boost (= 1.76.0)
|
- boost (= 1.76.0)
|
||||||
- DoubleConversion
|
- DoubleConversion
|
||||||
- glog
|
- glog
|
||||||
- hermes-engine
|
- hermes-engine
|
||||||
- RCT-Folly (= 2021.07.22.00)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-jsiexecutor (0.71.2):
|
- React-jsiexecutor (0.71.3):
|
||||||
- DoubleConversion
|
- DoubleConversion
|
||||||
- glog
|
- glog
|
||||||
- hermes-engine
|
- hermes-engine
|
||||||
- RCT-Folly (= 2021.07.22.00)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-cxxreact (= 0.71.2)
|
- React-cxxreact (= 0.71.3)
|
||||||
- React-jsi (= 0.71.2)
|
- React-jsi (= 0.71.3)
|
||||||
- React-perflogger (= 0.71.2)
|
- React-perflogger (= 0.71.3)
|
||||||
- React-jsinspector (0.71.2)
|
- React-jsinspector (0.71.3)
|
||||||
- React-logger (0.71.2):
|
- React-logger (0.71.3):
|
||||||
- glog
|
- glog
|
||||||
- react-native-blur (4.3.0):
|
- react-native-blur (4.3.0):
|
||||||
- React-Core
|
- React-Core
|
||||||
@ -287,90 +287,90 @@ PODS:
|
|||||||
- React
|
- React
|
||||||
- React-callinvoker
|
- React-callinvoker
|
||||||
- React-Core
|
- React-Core
|
||||||
- React-perflogger (0.71.2)
|
- React-perflogger (0.71.3)
|
||||||
- React-RCTActionSheet (0.71.2):
|
- React-RCTActionSheet (0.71.3):
|
||||||
- React-Core/RCTActionSheetHeaders (= 0.71.2)
|
- React-Core/RCTActionSheetHeaders (= 0.71.3)
|
||||||
- React-RCTAnimation (0.71.2):
|
- React-RCTAnimation (0.71.3):
|
||||||
- RCT-Folly (= 2021.07.22.00)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- RCTTypeSafety (= 0.71.2)
|
- RCTTypeSafety (= 0.71.3)
|
||||||
- React-Codegen (= 0.71.2)
|
- React-Codegen (= 0.71.3)
|
||||||
- React-Core/RCTAnimationHeaders (= 0.71.2)
|
- React-Core/RCTAnimationHeaders (= 0.71.3)
|
||||||
- React-jsi (= 0.71.2)
|
- React-jsi (= 0.71.3)
|
||||||
- ReactCommon/turbomodule/core (= 0.71.2)
|
- ReactCommon/turbomodule/core (= 0.71.3)
|
||||||
- React-RCTAppDelegate (0.71.2):
|
- React-RCTAppDelegate (0.71.3):
|
||||||
- RCT-Folly
|
- RCT-Folly
|
||||||
- RCTRequired
|
- RCTRequired
|
||||||
- RCTTypeSafety
|
- RCTTypeSafety
|
||||||
- React-Core
|
- React-Core
|
||||||
- ReactCommon/turbomodule/core
|
- ReactCommon/turbomodule/core
|
||||||
- React-RCTBlob (0.71.2):
|
- React-RCTBlob (0.71.3):
|
||||||
- hermes-engine
|
- hermes-engine
|
||||||
- RCT-Folly (= 2021.07.22.00)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-Codegen (= 0.71.2)
|
- React-Codegen (= 0.71.3)
|
||||||
- React-Core/RCTBlobHeaders (= 0.71.2)
|
- React-Core/RCTBlobHeaders (= 0.71.3)
|
||||||
- React-Core/RCTWebSocket (= 0.71.2)
|
- React-Core/RCTWebSocket (= 0.71.3)
|
||||||
- React-jsi (= 0.71.2)
|
- React-jsi (= 0.71.3)
|
||||||
- React-RCTNetwork (= 0.71.2)
|
- React-RCTNetwork (= 0.71.3)
|
||||||
- ReactCommon/turbomodule/core (= 0.71.2)
|
- ReactCommon/turbomodule/core (= 0.71.3)
|
||||||
- React-RCTImage (0.71.2):
|
- React-RCTImage (0.71.3):
|
||||||
- RCT-Folly (= 2021.07.22.00)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- RCTTypeSafety (= 0.71.2)
|
- RCTTypeSafety (= 0.71.3)
|
||||||
- React-Codegen (= 0.71.2)
|
- React-Codegen (= 0.71.3)
|
||||||
- React-Core/RCTImageHeaders (= 0.71.2)
|
- React-Core/RCTImageHeaders (= 0.71.3)
|
||||||
- React-jsi (= 0.71.2)
|
- React-jsi (= 0.71.3)
|
||||||
- React-RCTNetwork (= 0.71.2)
|
- React-RCTNetwork (= 0.71.3)
|
||||||
- ReactCommon/turbomodule/core (= 0.71.2)
|
- ReactCommon/turbomodule/core (= 0.71.3)
|
||||||
- React-RCTLinking (0.71.2):
|
- React-RCTLinking (0.71.3):
|
||||||
- React-Codegen (= 0.71.2)
|
- React-Codegen (= 0.71.3)
|
||||||
- React-Core/RCTLinkingHeaders (= 0.71.2)
|
- React-Core/RCTLinkingHeaders (= 0.71.3)
|
||||||
- React-jsi (= 0.71.2)
|
- React-jsi (= 0.71.3)
|
||||||
- ReactCommon/turbomodule/core (= 0.71.2)
|
- ReactCommon/turbomodule/core (= 0.71.3)
|
||||||
- React-RCTNetwork (0.71.2):
|
- React-RCTNetwork (0.71.3):
|
||||||
- RCT-Folly (= 2021.07.22.00)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- RCTTypeSafety (= 0.71.2)
|
- RCTTypeSafety (= 0.71.3)
|
||||||
- React-Codegen (= 0.71.2)
|
- React-Codegen (= 0.71.3)
|
||||||
- React-Core/RCTNetworkHeaders (= 0.71.2)
|
- React-Core/RCTNetworkHeaders (= 0.71.3)
|
||||||
- React-jsi (= 0.71.2)
|
- React-jsi (= 0.71.3)
|
||||||
- ReactCommon/turbomodule/core (= 0.71.2)
|
- ReactCommon/turbomodule/core (= 0.71.3)
|
||||||
- React-RCTSettings (0.71.2):
|
- React-RCTSettings (0.71.3):
|
||||||
- RCT-Folly (= 2021.07.22.00)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- RCTTypeSafety (= 0.71.2)
|
- RCTTypeSafety (= 0.71.3)
|
||||||
- React-Codegen (= 0.71.2)
|
- React-Codegen (= 0.71.3)
|
||||||
- React-Core/RCTSettingsHeaders (= 0.71.2)
|
- React-Core/RCTSettingsHeaders (= 0.71.3)
|
||||||
- React-jsi (= 0.71.2)
|
- React-jsi (= 0.71.3)
|
||||||
- ReactCommon/turbomodule/core (= 0.71.2)
|
- ReactCommon/turbomodule/core (= 0.71.3)
|
||||||
- React-RCTText (0.71.2):
|
- React-RCTText (0.71.3):
|
||||||
- React-Core/RCTTextHeaders (= 0.71.2)
|
- React-Core/RCTTextHeaders (= 0.71.3)
|
||||||
- React-RCTVibration (0.71.2):
|
- React-RCTVibration (0.71.3):
|
||||||
- RCT-Folly (= 2021.07.22.00)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-Codegen (= 0.71.2)
|
- React-Codegen (= 0.71.3)
|
||||||
- React-Core/RCTVibrationHeaders (= 0.71.2)
|
- React-Core/RCTVibrationHeaders (= 0.71.3)
|
||||||
- React-jsi (= 0.71.2)
|
- React-jsi (= 0.71.3)
|
||||||
- ReactCommon/turbomodule/core (= 0.71.2)
|
- ReactCommon/turbomodule/core (= 0.71.3)
|
||||||
- React-runtimeexecutor (0.71.2):
|
- React-runtimeexecutor (0.71.3):
|
||||||
- React-jsi (= 0.71.2)
|
- React-jsi (= 0.71.3)
|
||||||
- ReactCommon/turbomodule/bridging (0.71.2):
|
- ReactCommon/turbomodule/bridging (0.71.3):
|
||||||
- DoubleConversion
|
- DoubleConversion
|
||||||
- glog
|
- glog
|
||||||
- hermes-engine
|
- hermes-engine
|
||||||
- RCT-Folly (= 2021.07.22.00)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-callinvoker (= 0.71.2)
|
- React-callinvoker (= 0.71.3)
|
||||||
- React-Core (= 0.71.2)
|
- React-Core (= 0.71.3)
|
||||||
- React-cxxreact (= 0.71.2)
|
- React-cxxreact (= 0.71.3)
|
||||||
- React-jsi (= 0.71.2)
|
- React-jsi (= 0.71.3)
|
||||||
- React-logger (= 0.71.2)
|
- React-logger (= 0.71.3)
|
||||||
- React-perflogger (= 0.71.2)
|
- React-perflogger (= 0.71.3)
|
||||||
- ReactCommon/turbomodule/core (0.71.2):
|
- ReactCommon/turbomodule/core (0.71.3):
|
||||||
- DoubleConversion
|
- DoubleConversion
|
||||||
- glog
|
- glog
|
||||||
- hermes-engine
|
- hermes-engine
|
||||||
- RCT-Folly (= 2021.07.22.00)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-callinvoker (= 0.71.2)
|
- React-callinvoker (= 0.71.3)
|
||||||
- React-Core (= 0.71.2)
|
- React-Core (= 0.71.3)
|
||||||
- React-cxxreact (= 0.71.2)
|
- React-cxxreact (= 0.71.3)
|
||||||
- React-jsi (= 0.71.2)
|
- React-jsi (= 0.71.3)
|
||||||
- React-logger (= 0.71.2)
|
- React-logger (= 0.71.3)
|
||||||
- React-perflogger (= 0.71.2)
|
- React-perflogger (= 0.71.3)
|
||||||
- RNGestureHandler (2.9.0):
|
- RNGestureHandler (2.9.0):
|
||||||
- React-Core
|
- React-Core
|
||||||
- RNReanimated (3.0.0-rc.10):
|
- RNReanimated (3.0.0-rc.10):
|
||||||
@ -400,7 +400,7 @@ PODS:
|
|||||||
- React-RCTText
|
- React-RCTText
|
||||||
- ReactCommon/turbomodule/core
|
- ReactCommon/turbomodule/core
|
||||||
- Yoga
|
- Yoga
|
||||||
- RNScreens (3.19.0):
|
- RNScreens (3.20.0):
|
||||||
- React-Core
|
- React-Core
|
||||||
- React-RCTImage
|
- React-RCTImage
|
||||||
- RNStaticSafeAreaInsets (2.2.0):
|
- RNStaticSafeAreaInsets (2.2.0):
|
||||||
@ -566,52 +566,52 @@ EXTERNAL SOURCES:
|
|||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
boost: 57d2868c099736d80fcd648bf211b4431e51a558
|
boost: 57d2868c099736d80fcd648bf211b4431e51a558
|
||||||
DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
|
DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
|
||||||
FBLazyVector: d58428b28fe1f5070fe993495b0e2eaf701d3820
|
FBLazyVector: 60195509584153283780abdac5569feffb8f08cc
|
||||||
FBReactNativeSpec: 225fb0f0ab00493ce0731f954da3658638d9b191
|
FBReactNativeSpec: 9c191fb58d06dc05ab5559a5505fc32139e9e4a2
|
||||||
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
|
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
|
||||||
glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b
|
glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b
|
||||||
hermes-engine: 6351580c827b3b03e5f25aadcf989f582d0b0a86
|
hermes-engine: 38bfe887e456b33b697187570a08de33969f5db7
|
||||||
libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913
|
libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913
|
||||||
RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1
|
RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1
|
||||||
RCTRequired: c154ebcfbf41d6fef86c52674fc1aa08837ff538
|
RCTRequired: bec48f07daf7bcdc2655a0cde84e07d24d2a9e2a
|
||||||
RCTTypeSafety: 3063e5a1e5b1dc2cbeda5c8f8926c0ad1a6b0871
|
RCTTypeSafety: 171394eebacf71e1cfad79dbfae7ee8fc16ca80a
|
||||||
React: 0a1a36e8e81cfaac244ed88b97f23ab56e5434f0
|
React: d7433ccb6a8c36e4cbed59a73c0700fc83c3e98a
|
||||||
React-callinvoker: 679a09fbfe1a8bbf0c8588b588bf3ef85e7e4922
|
React-callinvoker: 15f165009bd22ae829b2b600e50bcc98076ce4b8
|
||||||
React-Codegen: 78f8966839f22b54d3303a6aca2679bce5723c3f
|
React-Codegen: b5910000eaf1e0c2f47d29be6f82f5f1264420d7
|
||||||
React-Core: 679e5ff1eb0e3122463976d0b2049bebcb7b33d6
|
React-Core: b6f2f78d580a90b83fd7b0d1c6911c799f6eac82
|
||||||
React-CoreModules: 06cbf15185e6daf9fb3aec02c963f4807bd794b3
|
React-CoreModules: e0cbc1a4f4f3f60e23c476fef7ab37be363ea8c1
|
||||||
React-cxxreact: 645dc75c9deba4c15698b1b5902236d6a766461f
|
React-cxxreact: c87f3f124b2117d00d410b35f16c2257e25e50fa
|
||||||
React-hermes: bc7bcfeaaa7cb98dc9f9252f2f3eca66f06f01e2
|
React-hermes: c64ca6bdf16a7069773103c9bedaf30ec90ab38f
|
||||||
React-jsi: 82625f9f1f8d7abf716d897612a9ea06ecf6db6e
|
React-jsi: 39729361645568e238081b3b3180fbad803f25a4
|
||||||
React-jsiexecutor: c7e028406112db456ac3cf5720d266bc7bc20938
|
React-jsiexecutor: 515b703d23ffadeac7687bc2d12fb08b90f0aaa1
|
||||||
React-jsinspector: ea8101acf525ec08b2d87ddf0637d45f8e3b4148
|
React-jsinspector: 9f7c9137605e72ca0343db4cea88006cb94856dd
|
||||||
React-logger: 97987f46779d8dd24656474ad0c43a5b459f31d6
|
React-logger: 957e5dc96d9dbffc6e0f15e0ee4d2b42829ff207
|
||||||
react-native-blur: 50c9feabacbc5f49b61337ebc32192c6be7ec3c3
|
react-native-blur: 50c9feabacbc5f49b61337ebc32192c6be7ec3c3
|
||||||
react-native-cameraroll: 5b25d0be40185d02e522bf2abf8a1ba4e8faa107
|
react-native-cameraroll: 5b25d0be40185d02e522bf2abf8a1ba4e8faa107
|
||||||
react-native-safe-area-context: 39c2d8be3328df5d437ac1700f4f3a4f75716acc
|
react-native-safe-area-context: 39c2d8be3328df5d437ac1700f4f3a4f75716acc
|
||||||
react-native-slider: 33b8d190b59d4f67a541061bb91775d53d617d9d
|
react-native-slider: 33b8d190b59d4f67a541061bb91775d53d617d9d
|
||||||
react-native-video: c26780b224543c62d5e1b2a7244a5cd1b50e8253
|
react-native-video: c26780b224543c62d5e1b2a7244a5cd1b50e8253
|
||||||
react-native-worklets: c7576ad4ad0f030ff41e8d74ad0077c96054a6c1
|
react-native-worklets: c7576ad4ad0f030ff41e8d74ad0077c96054a6c1
|
||||||
React-perflogger: c7ccda3d1d1da837f7ff4e54e816022a6803ee87
|
React-perflogger: af8a3d31546077f42d729b949925cc4549f14def
|
||||||
React-RCTActionSheet: 01c125aebbad462a24228f68c584c7a921d6c28e
|
React-RCTActionSheet: 57cc5adfefbaaf0aae2cf7e10bccd746f2903673
|
||||||
React-RCTAnimation: 5277a9440acffc4a5b7baa6ae3880fe467277ae6
|
React-RCTAnimation: 11c61e94da700c4dc915cf134513764d87fc5e2b
|
||||||
React-RCTAppDelegate: 3977201606125157aa94872b4171ca316478939b
|
React-RCTAppDelegate: c3980adeaadcfd6cb495532e928b36ac6db3c14a
|
||||||
React-RCTBlob: 8e15fc9091d8947f406ba706f11505b38b1b5e40
|
React-RCTBlob: ccc5049d742b41971141415ca86b83b201495695
|
||||||
React-RCTImage: 65319acfe82b85219b2d410725a593abe19ac795
|
React-RCTImage: 7a9226b0944f1e76e8e01e35a9245c2477cdbabb
|
||||||
React-RCTLinking: a5fc2b9d7a346d6e7d34de8093bb5d1064042508
|
React-RCTLinking: bbe8cc582046a9c04f79c235b73c93700263e8b4
|
||||||
React-RCTNetwork: 5d1efcd01ca7f08ebf286d68be544f747a5d315a
|
React-RCTNetwork: fc2ca322159dc54e06508d4f5c3e934da63dc013
|
||||||
React-RCTSettings: fa760b0add819ac3ad73b06715f9547316acdf20
|
React-RCTSettings: f1e9db2cdf946426d3f2b210e4ff4ce0f0d842ef
|
||||||
React-RCTText: 05c244b135d75d4395eb35c012949a5326f8ab70
|
React-RCTText: 1c41dd57e5d742b1396b4eeb251851ce7ff0fca1
|
||||||
React-RCTVibration: 0af3babdeee1b2d052811a2f86977d1e1c81ebd1
|
React-RCTVibration: 5199a180d04873366a83855de55ac33ce60fe4d5
|
||||||
React-runtimeexecutor: 4bf9a9086d27f74065fce1dddac274aa95216952
|
React-runtimeexecutor: 7bf0dafc7b727d93c8cb94eb00a9d3753c446c3e
|
||||||
ReactCommon: f697c0ac52e999aa818e43e2b6f277787c735e2d
|
ReactCommon: 6f65ea5b7d84deb9e386f670dd11ce499ded7b40
|
||||||
RNGestureHandler: 071d7a9ad81e8b83fe7663b303d132406a7d8f39
|
RNGestureHandler: 071d7a9ad81e8b83fe7663b303d132406a7d8f39
|
||||||
RNReanimated: fbc356493970e3acddc15586b1bccb5eab3ff1ec
|
RNReanimated: fbc356493970e3acddc15586b1bccb5eab3ff1ec
|
||||||
RNScreens: ea4cd3a853063cda19a4e3c28d2e52180c80f4eb
|
RNScreens: 218801c16a2782546d30bd2026bb625c0302d70f
|
||||||
RNStaticSafeAreaInsets: 055ddbf5e476321720457cdaeec0ff2ba40ec1b8
|
RNStaticSafeAreaInsets: 055ddbf5e476321720457cdaeec0ff2ba40ec1b8
|
||||||
RNVectorIcons: fcc2f6cb32f5735b586e66d14103a74ce6ad61f8
|
RNVectorIcons: fcc2f6cb32f5735b586e66d14103a74ce6ad61f8
|
||||||
VisionCamera: 312151eb95370d1d764720de3b7dad33d8c7fb40
|
VisionCamera: 312151eb95370d1d764720de3b7dad33d8c7fb40
|
||||||
Yoga: 5b0304b3dbef2b52e078052138e23a19c7dacaef
|
Yoga: 5ed1699acbba8863755998a4245daa200ff3817b
|
||||||
|
|
||||||
PODFILE CHECKSUM: d53724fe402c2547f1dd1cc571bbe77d9820e636
|
PODFILE CHECKSUM: d53724fe402c2547f1dd1cc571bbe77d9820e636
|
||||||
|
|
||||||
|
@ -20,16 +20,16 @@
|
|||||||
"@react-navigation/native": "^6.1.3",
|
"@react-navigation/native": "^6.1.3",
|
||||||
"@react-navigation/native-stack": "^6.9.9",
|
"@react-navigation/native-stack": "^6.9.9",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-native": "^0.71.2",
|
"react-native": "^0.71.3",
|
||||||
"react-native-gesture-handler": "^2.9.0",
|
"react-native-gesture-handler": "^2.9.0",
|
||||||
"react-native-pressable-opacity": "^1.0.10",
|
"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-safe-area-context": "^4.5.0",
|
||||||
"react-native-screens": "^3.19.0",
|
"react-native-screens": "^3.19.0",
|
||||||
"react-native-static-safe-area-insets": "^2.2.0",
|
"react-native-static-safe-area-insets": "^2.2.0",
|
||||||
"react-native-vector-icons": "^9.2.0",
|
"react-native-vector-icons": "^9.2.0",
|
||||||
"react-native-video": "^5.2.1",
|
"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": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.20.12",
|
"@babel/core": "^7.20.12",
|
||||||
|
@ -5,7 +5,6 @@ import { PinchGestureHandler, PinchGestureHandlerGestureEvent, TapGestureHandler
|
|||||||
import {
|
import {
|
||||||
CameraDeviceFormat,
|
CameraDeviceFormat,
|
||||||
CameraRuntimeError,
|
CameraRuntimeError,
|
||||||
FrameProcessorPerformanceSuggestion,
|
|
||||||
PhotoFile,
|
PhotoFile,
|
||||||
sortFormats,
|
sortFormats,
|
||||||
useCameraDevices,
|
useCameraDevices,
|
||||||
@ -203,10 +202,6 @@ export function CameraPage({ navigation }: Props): React.ReactElement {
|
|||||||
console.log(`Return Values: ${JSON.stringify(values)}`);
|
console.log(`Return Values: ${JSON.stringify(values)}`);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const onFrameProcessorSuggestionAvailable = useCallback((suggestion: FrameProcessorPerformanceSuggestion) => {
|
|
||||||
console.log(`Suggestion available! ${suggestion.type}: Can do ${suggestion.suggestedFrameProcessorFps} FPS`);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
{device != null && (
|
{device != null && (
|
||||||
@ -231,8 +226,6 @@ export function CameraPage({ navigation }: Props): React.ReactElement {
|
|||||||
audio={hasMicrophonePermission}
|
audio={hasMicrophonePermission}
|
||||||
frameProcessor={device.supportsParallelVideoProcessing ? frameProcessor : undefined}
|
frameProcessor={device.supportsParallelVideoProcessing ? frameProcessor : undefined}
|
||||||
orientation="portrait"
|
orientation="portrait"
|
||||||
frameProcessorFps={1}
|
|
||||||
onFrameProcessorPerformanceSuggestionAvailable={onFrameProcessorSuggestionAvailable}
|
|
||||||
/>
|
/>
|
||||||
</TapGestureHandler>
|
</TapGestureHandler>
|
||||||
</Reanimated.View>
|
</Reanimated.View>
|
||||||
|
@ -781,38 +781,38 @@
|
|||||||
integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==
|
integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==
|
||||||
|
|
||||||
"@jest/create-cache-key-function@^29.2.1":
|
"@jest/create-cache-key-function@^29.2.1":
|
||||||
version "29.4.2"
|
version "29.4.3"
|
||||||
resolved "https://registry.yarnpkg.com/@jest/create-cache-key-function/-/create-cache-key-function-29.4.2.tgz#cc8e966c28fd3bed309b0487de2e0bd12cbf519f"
|
resolved "https://registry.yarnpkg.com/@jest/create-cache-key-function/-/create-cache-key-function-29.4.3.tgz#ea37769f69523019d81ee089a25a62550f209eb7"
|
||||||
integrity sha512-o2weIg3h8/7+jXF6EjcOiz9TAlNMtcmeH5IARTVgHs3IoQGbh5E/ZLLskfEsHVIYoCKgx+v093Vf8hOgMWggvg==
|
integrity sha512-AJVFQTTy6jnZAQiAZrdOaTAPzJUrvAE/4IMe+Foav6WPhypFszqg7a4lOTyuzYQEEiT5RSrGYg9IY+/ivxiyXw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jest/types" "^29.4.2"
|
"@jest/types" "^29.4.3"
|
||||||
|
|
||||||
"@jest/environment@^29.4.2":
|
"@jest/environment@^29.4.3":
|
||||||
version "29.4.2"
|
version "29.4.3"
|
||||||
resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.4.2.tgz#ee92c316ee2fbdf0bcd9d2db0ef42d64fea26b56"
|
resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.4.3.tgz#9fe2f3169c3b33815dc4bd3960a064a83eba6548"
|
||||||
integrity sha512-JKs3VUtse0vQfCaFGJRX1bir9yBdtasxziSyu+pIiEllAQOe4oQhdCYIf3+Lx+nGglFktSKToBnRJfD5QKp+NQ==
|
integrity sha512-dq5S6408IxIa+lr54zeqce+QgI+CJT4nmmA+1yzFgtcsGK8c/EyiUb9XQOgz3BMKrRDfKseeOaxj2eO8LlD3lA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jest/fake-timers" "^29.4.2"
|
"@jest/fake-timers" "^29.4.3"
|
||||||
"@jest/types" "^29.4.2"
|
"@jest/types" "^29.4.3"
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
jest-mock "^29.4.2"
|
jest-mock "^29.4.3"
|
||||||
|
|
||||||
"@jest/fake-timers@^29.4.2":
|
"@jest/fake-timers@^29.4.3":
|
||||||
version "29.4.2"
|
version "29.4.3"
|
||||||
resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.4.2.tgz#af43ee1a5720b987d0348f80df98f2cb17d45cd0"
|
resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.4.3.tgz#31e982638c60fa657d310d4b9d24e023064027b0"
|
||||||
integrity sha512-Ny1u0Wg6kCsHFWq7A/rW/tMhIedq2siiyHyLpHCmIhP7WmcAmd2cx95P+0xtTZlj5ZbJxIRQi4OPydZZUoiSQQ==
|
integrity sha512-4Hote2MGcCTWSD2gwl0dwbCpBRHhE6olYEuTj8FMowdg3oQWNKr2YuxenPQYZ7+PfqPY1k98wKDU4Z+Hvd4Tiw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jest/types" "^29.4.2"
|
"@jest/types" "^29.4.3"
|
||||||
"@sinonjs/fake-timers" "^10.0.2"
|
"@sinonjs/fake-timers" "^10.0.2"
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
jest-message-util "^29.4.2"
|
jest-message-util "^29.4.3"
|
||||||
jest-mock "^29.4.2"
|
jest-mock "^29.4.3"
|
||||||
jest-util "^29.4.2"
|
jest-util "^29.4.3"
|
||||||
|
|
||||||
"@jest/schemas@^29.4.2":
|
"@jest/schemas@^29.4.3":
|
||||||
version "29.4.2"
|
version "29.4.3"
|
||||||
resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.4.2.tgz#cf7cfe97c5649f518452b176c47ed07486270fc1"
|
resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.4.3.tgz#39cf1b8469afc40b6f5a2baaa146e332c4151788"
|
||||||
integrity sha512-ZrGzGfh31NtdVH8tn0mgJw4khQuNHiKqdzJAFbCaERbyCP9tHlxWuL/mnMu8P7e/+k4puWjI1NOzi/sFsjce/g==
|
integrity sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@sinclair/typebox" "^0.25.16"
|
"@sinclair/typebox" "^0.25.16"
|
||||||
|
|
||||||
@ -838,12 +838,12 @@
|
|||||||
"@types/yargs" "^16.0.0"
|
"@types/yargs" "^16.0.0"
|
||||||
chalk "^4.0.0"
|
chalk "^4.0.0"
|
||||||
|
|
||||||
"@jest/types@^29.4.2":
|
"@jest/types@^29.4.3":
|
||||||
version "29.4.2"
|
version "29.4.3"
|
||||||
resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.4.2.tgz#8f724a414b1246b2bfd56ca5225d9e1f39540d82"
|
resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.4.3.tgz#9069145f4ef09adf10cec1b2901b2d390031431f"
|
||||||
integrity sha512-CKlngyGP0fwlgC1BRUtPZSiWLBhyS9dKwKmyGxk8Z6M82LBEGB2aLQSg+U1MyLsU+M7UjnlLllBM2BLWKVm/Uw==
|
integrity sha512-bPYfw8V65v17m2Od1cv44FH+SiKW7w2Xu7trhcdTLUmSv85rfKsP+qXSjO4KGJr4dtPSzl/gvslZBXctf1qGEA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jest/schemas" "^29.4.2"
|
"@jest/schemas" "^29.4.3"
|
||||||
"@types/istanbul-lib-coverage" "^2.0.0"
|
"@types/istanbul-lib-coverage" "^2.0.0"
|
||||||
"@types/istanbul-reports" "^3.0.0"
|
"@types/istanbul-reports" "^3.0.0"
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
@ -1153,23 +1153,23 @@
|
|||||||
react-is "^16.13.0"
|
react-is "^16.13.0"
|
||||||
use-latest-callback "^0.1.5"
|
use-latest-callback "^0.1.5"
|
||||||
|
|
||||||
"@react-navigation/elements@^1.3.14":
|
"@react-navigation/elements@^1.3.15":
|
||||||
version "1.3.14"
|
version "1.3.15"
|
||||||
resolved "https://registry.yarnpkg.com/@react-navigation/elements/-/elements-1.3.14.tgz#ee9ef7f57e0877700ebb359947728b255bbb9c65"
|
resolved "https://registry.yarnpkg.com/@react-navigation/elements/-/elements-1.3.15.tgz#b8aebf101080057508b98cb5da4173c72c095db0"
|
||||||
integrity sha512-RBbPhYq+KNFPAkWPaHB9gypq0jTGp/0fkMwRLToJ8jkLtWG4LV+JoQ/erFQnVARkR3Q807n0VnES15EYP4ITMQ==
|
integrity sha512-CR4CEYJVY0OLyeLQi9N3Z2o4K47gXctvFxfZizDuW1xFtCJbA0eGvpjSLXEWHoY0hFjrlC6KinpdepGHVxhYIg==
|
||||||
|
|
||||||
"@react-navigation/native-stack@^6.9.9":
|
"@react-navigation/native-stack@^6.9.9":
|
||||||
version "6.9.9"
|
version "6.9.10"
|
||||||
resolved "https://registry.yarnpkg.com/@react-navigation/native-stack/-/native-stack-6.9.9.tgz#346c393e48d681c15e5831d7749fb807f76dcdce"
|
resolved "https://registry.yarnpkg.com/@react-navigation/native-stack/-/native-stack-6.9.10.tgz#5a5d5de9f49b72e603d0cdca9771e0324f65c1c7"
|
||||||
integrity sha512-FIbTCEjqAt6guQ90lKIDvOfTo5vtKGG+aQTtHMdTV9JLGnS6gFsBgXmv5hvWLkyd426Nc04mpZXPTK7d80v/LQ==
|
integrity sha512-dSazcWNxHg4qkid/AxFRvbhRtNXy/RqE00h/Qp+d7aBN0TwrOJn8mH/Inkkf4pHAntMbj0+mVAlKfxKmyLEGlA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@react-navigation/elements" "^1.3.14"
|
"@react-navigation/elements" "^1.3.15"
|
||||||
warn-once "^0.1.0"
|
warn-once "^0.1.0"
|
||||||
|
|
||||||
"@react-navigation/native@^6.1.3":
|
"@react-navigation/native@^6.1.3":
|
||||||
version "6.1.3"
|
version "6.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/@react-navigation/native/-/native-6.1.3.tgz#06064c5e49c417a3dbe210b3f00841beefd326c5"
|
resolved "https://registry.yarnpkg.com/@react-navigation/native/-/native-6.1.4.tgz#49666596c9df16e22284f35f482d05d6b5d47d60"
|
||||||
integrity sha512-DB5FyG6aqGfcjjVozljF5NEkjWaSymIbQHfWwsjL0YrvC1gfc7E53QXDOjxZ/wfbCo8qZs8RIC/LAgclP2YK/w==
|
integrity sha512-8IGpMFvD21XINpSf9gyU19yv4O+NyF9FQAxEzwbJSef19W5XEJKXPN/0RINc43Tt+YnQyFGQ2+qJM1uoB9pKcA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@react-navigation/core" "^6.4.6"
|
"@react-navigation/core" "^6.4.6"
|
||||||
escape-string-regexp "^4.0.0"
|
escape-string-regexp "^4.0.0"
|
||||||
@ -1201,9 +1201,9 @@
|
|||||||
integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==
|
integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==
|
||||||
|
|
||||||
"@sinclair/typebox@^0.25.16":
|
"@sinclair/typebox@^0.25.16":
|
||||||
version "0.25.21"
|
version "0.25.22"
|
||||||
resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.25.21.tgz#763b05a4b472c93a8db29b2c3e359d55b29ce272"
|
resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.25.22.tgz#2808d895e9c2722b20a622a9c8cb332f6720eb4a"
|
||||||
integrity sha512-gFukHN4t8K4+wVC+ECqeqwzBDeFeTzBXroBTqE6vcWrQGbEUpHO7LYdG0f4xnvYq4VOEwITSlHlp0JBAIFMS/g==
|
integrity sha512-6U6r2L7rnM7EG8G1tWzIjdB3QlsHF4slgcqXNN/SF0xJOAr0nDmT2GedlkyO3mrv8mDTJ24UuOMWR3diBrCvQQ==
|
||||||
|
|
||||||
"@sinonjs/commons@^2.0.0":
|
"@sinonjs/commons@^2.0.0":
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
@ -1275,23 +1275,23 @@
|
|||||||
"@types/react-native" "*"
|
"@types/react-native" "*"
|
||||||
|
|
||||||
"@types/react-native@*", "@types/react-native@^0.71.2":
|
"@types/react-native@*", "@types/react-native@^0.71.2":
|
||||||
version "0.71.2"
|
version "0.71.3"
|
||||||
resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.71.2.tgz#b8ba52c2fd07d3d64fa87ae5d9b4fbbd3b9cbffd"
|
resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.71.3.tgz#537f669ed6b38b5ae47444bd9d253c4cff23bed7"
|
||||||
integrity sha512-RJ0slxB/aVh6gDBZcGusDLIMW+ydsigzOVva9nODPfZApvIY4UgacV5PAlyk/CScJaN7Frh4sZaD9bD73uc9HQ==
|
integrity sha512-0Uqw1YZ0qbVla0MMWFTANFm6W8KYWNvGQmYfucdecbXivLMcQ2v4PovuYFKr7bE6Bc5nDCUEaga962Y8gcDF7A==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/react" "*"
|
"@types/react" "*"
|
||||||
|
|
||||||
"@types/react-native@^0.70":
|
"@types/react-native@^0.70":
|
||||||
version "0.70.10"
|
version "0.70.11"
|
||||||
resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.70.10.tgz#494576e0dc20aa319003f0cdd99192124d64038d"
|
resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.70.11.tgz#50c3d81e1351aac0562c3341c9bd57885651a2fe"
|
||||||
integrity sha512-m9B9hJk1w/c04zj5PCYTjJNXt+1UvKtzJj4nO/BjiS4s/zmUdkLdnbLqRQCQiTA0wuvvMbrffuPdheRtYu/M1Q==
|
integrity sha512-FobPtzoNPNHugBKMfzs4Li0Q9ei4tgU8SI1M5Ayg7+t5/+noCm2sknI8uwij22wMkcHcefv8RFx4q28nNVJtCQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/react" "*"
|
"@types/react" "*"
|
||||||
|
|
||||||
"@types/react@*", "@types/react@^18.0.27":
|
"@types/react@*", "@types/react@^18.0.27":
|
||||||
version "18.0.27"
|
version "18.0.28"
|
||||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.27.tgz#d9425abe187a00f8a5ec182b010d4fd9da703b71"
|
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.28.tgz#accaeb8b86f4908057ad629a26635fe641480065"
|
||||||
integrity sha512-3vtRKHgVxu3Jp9t718R9BuzoD4NcQ8YJ5XRzsSKxNDiDonD2MXIT1TmSkenxuCycZJoQT5d2vE8LwWJxBC1gmA==
|
integrity sha512-RD0ivG1kEztNBdoAK7lekI9M+azSnitIn85h4iOiaLjaTrMjzslhaqCGaI4IyCJ1RljWiLCEu4jyrLLgqxBTew==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/prop-types" "*"
|
"@types/prop-types" "*"
|
||||||
"@types/scheduler" "*"
|
"@types/scheduler" "*"
|
||||||
@ -1339,13 +1339,13 @@
|
|||||||
"@types/yargs-parser" "*"
|
"@types/yargs-parser" "*"
|
||||||
|
|
||||||
"@typescript-eslint/eslint-plugin@^5.30.5":
|
"@typescript-eslint/eslint-plugin@^5.30.5":
|
||||||
version "5.51.0"
|
version "5.52.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.51.0.tgz#da3f2819633061ced84bb82c53bba45a6fe9963a"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.52.0.tgz#5fb0d43574c2411f16ea80f5fc335b8eaa7b28a8"
|
||||||
integrity sha512-wcAwhEWm1RgNd7dxD/o+nnLW8oH+6RK1OGnmbmkj/GGoDPV1WWMVP0FXYQBivKHdwM1pwii3bt//RC62EriIUQ==
|
integrity sha512-lHazYdvYVsBokwCdKOppvYJKaJ4S41CgKBcPvyd0xjZNbvQdhn/pnJlGtQksQ/NhInzdaeaSarlBjDXHuclEbg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@typescript-eslint/scope-manager" "5.51.0"
|
"@typescript-eslint/scope-manager" "5.52.0"
|
||||||
"@typescript-eslint/type-utils" "5.51.0"
|
"@typescript-eslint/type-utils" "5.52.0"
|
||||||
"@typescript-eslint/utils" "5.51.0"
|
"@typescript-eslint/utils" "5.52.0"
|
||||||
debug "^4.3.4"
|
debug "^4.3.4"
|
||||||
grapheme-splitter "^1.0.4"
|
grapheme-splitter "^1.0.4"
|
||||||
ignore "^5.2.0"
|
ignore "^5.2.0"
|
||||||
@ -1355,71 +1355,71 @@
|
|||||||
tsutils "^3.21.0"
|
tsutils "^3.21.0"
|
||||||
|
|
||||||
"@typescript-eslint/parser@^5.30.5":
|
"@typescript-eslint/parser@^5.30.5":
|
||||||
version "5.51.0"
|
version "5.52.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.51.0.tgz#2d74626652096d966ef107f44b9479f02f51f271"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.52.0.tgz#73c136df6c0133f1d7870de7131ccf356f5be5a4"
|
||||||
integrity sha512-fEV0R9gGmfpDeRzJXn+fGQKcl0inIeYobmmUWijZh9zA7bxJ8clPhV9up2ZQzATxAiFAECqPQyMDB4o4B81AaA==
|
integrity sha512-e2KiLQOZRo4Y0D/b+3y08i3jsekoSkOYStROYmPUnGMEoA0h+k2qOH5H6tcjIc68WDvGwH+PaOrP1XRzLJ6QlA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@typescript-eslint/scope-manager" "5.51.0"
|
"@typescript-eslint/scope-manager" "5.52.0"
|
||||||
"@typescript-eslint/types" "5.51.0"
|
"@typescript-eslint/types" "5.52.0"
|
||||||
"@typescript-eslint/typescript-estree" "5.51.0"
|
"@typescript-eslint/typescript-estree" "5.52.0"
|
||||||
debug "^4.3.4"
|
debug "^4.3.4"
|
||||||
|
|
||||||
"@typescript-eslint/scope-manager@5.51.0":
|
"@typescript-eslint/scope-manager@5.52.0":
|
||||||
version "5.51.0"
|
version "5.52.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.51.0.tgz#ad3e3c2ecf762d9a4196c0fbfe19b142ac498990"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.52.0.tgz#a993d89a0556ea16811db48eabd7c5b72dcb83d1"
|
||||||
integrity sha512-gNpxRdlx5qw3yaHA0SFuTjW4rxeYhpHxt491PEcKF8Z6zpq0kMhe0Tolxt0qjlojS+/wArSDlj/LtE69xUJphQ==
|
integrity sha512-AR7sxxfBKiNV0FWBSARxM8DmNxrwgnYMPwmpkC1Pl1n+eT8/I2NAUPuwDy/FmDcC6F8pBfmOcaxcxRHspgOBMw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@typescript-eslint/types" "5.51.0"
|
"@typescript-eslint/types" "5.52.0"
|
||||||
"@typescript-eslint/visitor-keys" "5.51.0"
|
"@typescript-eslint/visitor-keys" "5.52.0"
|
||||||
|
|
||||||
"@typescript-eslint/type-utils@5.51.0":
|
"@typescript-eslint/type-utils@5.52.0":
|
||||||
version "5.51.0"
|
version "5.52.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.51.0.tgz#7af48005531700b62a20963501d47dfb27095988"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.52.0.tgz#9fd28cd02e6f21f5109e35496df41893f33167aa"
|
||||||
integrity sha512-QHC5KKyfV8sNSyHqfNa0UbTbJ6caB8uhcx2hYcWVvJAZYJRBo5HyyZfzMdRx8nvS+GyMg56fugMzzWnojREuQQ==
|
integrity sha512-tEKuUHfDOv852QGlpPtB3lHOoig5pyFQN/cUiZtpw99D93nEBjexRLre5sQZlkMoHry/lZr8qDAt2oAHLKA6Jw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@typescript-eslint/typescript-estree" "5.51.0"
|
"@typescript-eslint/typescript-estree" "5.52.0"
|
||||||
"@typescript-eslint/utils" "5.51.0"
|
"@typescript-eslint/utils" "5.52.0"
|
||||||
debug "^4.3.4"
|
debug "^4.3.4"
|
||||||
tsutils "^3.21.0"
|
tsutils "^3.21.0"
|
||||||
|
|
||||||
"@typescript-eslint/types@5.51.0":
|
"@typescript-eslint/types@5.52.0":
|
||||||
version "5.51.0"
|
version "5.52.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.51.0.tgz#e7c1622f46c7eea7e12bbf1edfb496d4dec37c90"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.52.0.tgz#19e9abc6afb5bd37a1a9bea877a1a836c0b3241b"
|
||||||
integrity sha512-SqOn0ANn/v6hFn0kjvLwiDi4AzR++CBZz0NV5AnusT2/3y32jdc0G4woXPWHCumWtUXZKPAS27/9vziSsC9jnw==
|
integrity sha512-oV7XU4CHYfBhk78fS7tkum+/Dpgsfi91IIDy7fjCyq2k6KB63M6gMC0YIvy+iABzmXThCRI6xpCEyVObBdWSDQ==
|
||||||
|
|
||||||
"@typescript-eslint/typescript-estree@5.51.0":
|
"@typescript-eslint/typescript-estree@5.52.0":
|
||||||
version "5.51.0"
|
version "5.52.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.51.0.tgz#0ec8170d7247a892c2b21845b06c11eb0718f8de"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.52.0.tgz#6408cb3c2ccc01c03c278cb201cf07e73347dfca"
|
||||||
integrity sha512-TSkNupHvNRkoH9FMA3w7TazVFcBPveAAmb7Sz+kArY6sLT86PA5Vx80cKlYmd8m3Ha2SwofM1KwraF24lM9FvA==
|
integrity sha512-WeWnjanyEwt6+fVrSR0MYgEpUAuROxuAH516WPjUblIrClzYJj0kBbjdnbQXLpgAN8qbEuGywiQsXUVDiAoEuQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@typescript-eslint/types" "5.51.0"
|
"@typescript-eslint/types" "5.52.0"
|
||||||
"@typescript-eslint/visitor-keys" "5.51.0"
|
"@typescript-eslint/visitor-keys" "5.52.0"
|
||||||
debug "^4.3.4"
|
debug "^4.3.4"
|
||||||
globby "^11.1.0"
|
globby "^11.1.0"
|
||||||
is-glob "^4.0.3"
|
is-glob "^4.0.3"
|
||||||
semver "^7.3.7"
|
semver "^7.3.7"
|
||||||
tsutils "^3.21.0"
|
tsutils "^3.21.0"
|
||||||
|
|
||||||
"@typescript-eslint/utils@5.51.0", "@typescript-eslint/utils@^5.10.0":
|
"@typescript-eslint/utils@5.52.0", "@typescript-eslint/utils@^5.10.0":
|
||||||
version "5.51.0"
|
version "5.52.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.51.0.tgz#074f4fabd5b12afe9c8aa6fdee881c050f8b4d47"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.52.0.tgz#b260bb5a8f6b00a0ed51db66bdba4ed5e4845a72"
|
||||||
integrity sha512-76qs+5KWcaatmwtwsDJvBk4H76RJQBFe+Gext0EfJdC3Vd2kpY2Pf//OHHzHp84Ciw0/rYoGTDnIAr3uWhhJYw==
|
integrity sha512-As3lChhrbwWQLNk2HC8Ree96hldKIqk98EYvypd3It8Q1f8d5zWyIoaZEp2va5667M4ZyE7X8UUR+azXrFl+NA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/json-schema" "^7.0.9"
|
"@types/json-schema" "^7.0.9"
|
||||||
"@types/semver" "^7.3.12"
|
"@types/semver" "^7.3.12"
|
||||||
"@typescript-eslint/scope-manager" "5.51.0"
|
"@typescript-eslint/scope-manager" "5.52.0"
|
||||||
"@typescript-eslint/types" "5.51.0"
|
"@typescript-eslint/types" "5.52.0"
|
||||||
"@typescript-eslint/typescript-estree" "5.51.0"
|
"@typescript-eslint/typescript-estree" "5.52.0"
|
||||||
eslint-scope "^5.1.1"
|
eslint-scope "^5.1.1"
|
||||||
eslint-utils "^3.0.0"
|
eslint-utils "^3.0.0"
|
||||||
semver "^7.3.7"
|
semver "^7.3.7"
|
||||||
|
|
||||||
"@typescript-eslint/visitor-keys@5.51.0":
|
"@typescript-eslint/visitor-keys@5.52.0":
|
||||||
version "5.51.0"
|
version "5.52.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.51.0.tgz#c0147dd9a36c0de758aaebd5b48cae1ec59eba87"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.52.0.tgz#e38c971259f44f80cfe49d97dbffa38e3e75030f"
|
||||||
integrity sha512-Oh2+eTdjHjOFjKA27sxESlA87YPSOJafGCR0md5oeMdh1ZcCfAGCIOL216uTBAkAIptvLIfKQhl7lHxMJet4GQ==
|
integrity sha512-qMwpw6SU5VHCPr99y274xhbm+PRViK/NATY6qzt+Et7+mThGuFSl/ompj2/hrBlRP/kq+BFdgagnOSgw9TB0eA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@typescript-eslint/types" "5.51.0"
|
"@typescript-eslint/types" "5.52.0"
|
||||||
eslint-visitor-keys "^3.3.0"
|
eslint-visitor-keys "^3.3.0"
|
||||||
|
|
||||||
abort-controller@^3.0.0:
|
abort-controller@^3.0.0:
|
||||||
@ -1777,7 +1777,7 @@ braces@^3.0.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
fill-range "^7.0.1"
|
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"
|
version "4.21.5"
|
||||||
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.5.tgz#75c5dae60063ee641f977e00edd3cfb2fb7af6a7"
|
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.5.tgz#75c5dae60063ee641f977e00edd3cfb2fb7af6a7"
|
||||||
integrity sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==
|
integrity sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==
|
||||||
@ -1870,9 +1870,9 @@ camelcase@^6.0.0:
|
|||||||
integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
|
integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
|
||||||
|
|
||||||
caniuse-lite@^1.0.30001449:
|
caniuse-lite@^1.0.30001449:
|
||||||
version "1.0.30001451"
|
version "1.0.30001452"
|
||||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001451.tgz#2e197c698fc1373d63e1406d6607ea4617c613f1"
|
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001452.tgz#dff7b8bb834b3a91808f0a9ff0453abb1fbba02a"
|
||||||
integrity sha512-XY7UbUpGRatZzoRft//5xOa69/1iGJRBlrieH6QYrkKLIFn3m7OVEJ81dSrKoy2BnKsdbX5cLrOispZNYo9v2w==
|
integrity sha512-Lkp0vFjMkBB3GTpLR8zk4NwW5EdRdnitwYJHDOOKIU85x4ckYCPQ+9WlVvSVClHxVReefkUMtWZH2l9KGlD51w==
|
||||||
|
|
||||||
chalk@^2.0.0:
|
chalk@^2.0.0:
|
||||||
version "2.4.2"
|
version "2.4.2"
|
||||||
@ -1897,9 +1897,9 @@ ci-info@^2.0.0:
|
|||||||
integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==
|
integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==
|
||||||
|
|
||||||
ci-info@^3.2.0:
|
ci-info@^3.2.0:
|
||||||
version "3.7.1"
|
version "3.8.0"
|
||||||
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.7.1.tgz#708a6cdae38915d597afdf3b145f2f8e1ff55f3f"
|
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.8.0.tgz#81408265a5380c929f0bc665d62256628ce9ef91"
|
||||||
integrity sha512-4jYS4MOAaCIStSRwiuxc4B8MYhIe676yO1sYGzARnjXkWpmzZMMYxY6zu8WYWDhSuth5zhrQ1rhNSibyyvv4/w==
|
integrity sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==
|
||||||
|
|
||||||
class-utils@^0.3.5:
|
class-utils@^0.3.5:
|
||||||
version "0.3.6"
|
version "0.3.6"
|
||||||
@ -2077,11 +2077,11 @@ copy-descriptor@^0.1.0:
|
|||||||
integrity sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==
|
integrity sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==
|
||||||
|
|
||||||
core-js-compat@^3.25.1:
|
core-js-compat@^3.25.1:
|
||||||
version "3.27.2"
|
version "3.28.0"
|
||||||
resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.27.2.tgz#607c50ad6db8fd8326af0b2883ebb987be3786da"
|
resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.28.0.tgz#c08456d854608a7264530a2afa281fadf20ecee6"
|
||||||
integrity sha512-welaYuF7ZtbYKGrIy7y3eb40d37rG1FvzEOfe7hSLd2iD6duMDqUhRfSvCGyC46HhR6Y8JXXdZ2lnRUMkPBpvg==
|
integrity sha512-myzPgE7QodMg4nnd3K1TDoES/nADRStM8Gpz0D6nhkwbmwEnE0ZGJgoWsvQ722FR8D7xS0n0LV556RcEicjTyg==
|
||||||
dependencies:
|
dependencies:
|
||||||
browserslist "^4.21.4"
|
browserslist "^4.21.5"
|
||||||
|
|
||||||
core-util-is@~1.0.0:
|
core-util-is@~1.0.0:
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
@ -2170,9 +2170,9 @@ defaults@^1.0.3:
|
|||||||
clone "^1.0.2"
|
clone "^1.0.2"
|
||||||
|
|
||||||
define-properties@^1.1.3, define-properties@^1.1.4:
|
define-properties@^1.1.3, define-properties@^1.1.4:
|
||||||
version "1.1.4"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1"
|
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5"
|
||||||
integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==
|
integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==
|
||||||
dependencies:
|
dependencies:
|
||||||
has-property-descriptors "^1.0.0"
|
has-property-descriptors "^1.0.0"
|
||||||
object-keys "^1.1.1"
|
object-keys "^1.1.1"
|
||||||
@ -2259,9 +2259,9 @@ ee-first@1.1.1:
|
|||||||
integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==
|
integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==
|
||||||
|
|
||||||
electron-to-chromium@^1.4.284:
|
electron-to-chromium@^1.4.284:
|
||||||
version "1.4.294"
|
version "1.4.296"
|
||||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.294.tgz#ad80317b85f0859a9454680fbc1c726fefa7e6fd"
|
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.296.tgz#dbc84a25c25a432a12fbf62903cae4a87461eb8c"
|
||||||
integrity sha512-PuHZB3jEN7D8WPPjLmBQAsqQz8tWHlkkB4n0E2OYw8RwVdmBYV0Wn+rUFH8JqYyIRb4HQhhedgxlZL163wqLrQ==
|
integrity sha512-i/6Q+Y9bluDa2a0NbMvdtG5TuS/1Fr3TKK8L+7UUL9QjRS5iFJzCC3r70xjyOnLiYG8qGV4/mMpe6HuAbdJW4w==
|
||||||
|
|
||||||
eme-encryption-scheme-polyfill@^2.0.1:
|
eme-encryption-scheme-polyfill@^2.0.1:
|
||||||
version "2.1.1"
|
version "2.1.1"
|
||||||
@ -2509,9 +2509,9 @@ eslint-visitor-keys@^3.3.0:
|
|||||||
integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==
|
integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==
|
||||||
|
|
||||||
eslint@^8.33.0:
|
eslint@^8.33.0:
|
||||||
version "8.33.0"
|
version "8.34.0"
|
||||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.33.0.tgz#02f110f32998cb598c6461f24f4d306e41ca33d7"
|
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.34.0.tgz#fe0ab0ef478104c1f9ebc5537e303d25a8fb22d6"
|
||||||
integrity sha512-WjOpFQgKK8VrCnAtl8We0SUOy/oVZ5NHykyMiagV1M9r8IFpIJX7DduK6n1mpfhlG7T1NLWm2SuD8QB7KFySaA==
|
integrity sha512-1Z8iFsucw+7kSqXNZVslXS8Ioa4u2KM7GPwuKtkTFAqZ/cHMcEaR+1+Br0wLlot49cNxIiZk5wp8EAbPcYZxTg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@eslint/eslintrc" "^1.4.1"
|
"@eslint/eslintrc" "^1.4.1"
|
||||||
"@humanwhocodes/config-array" "^0.11.8"
|
"@humanwhocodes/config-array" "^0.11.8"
|
||||||
@ -3451,45 +3451,45 @@ isobject@^3.0.0, isobject@^3.0.1:
|
|||||||
integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==
|
integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==
|
||||||
|
|
||||||
jest-environment-node@^29.2.1:
|
jest-environment-node@^29.2.1:
|
||||||
version "29.4.2"
|
version "29.4.3"
|
||||||
resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.4.2.tgz#0eab835b41e25fd0c1a72f62665fc8db08762ad2"
|
resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.4.3.tgz#579c4132af478befc1889ddc43c2413a9cdbe014"
|
||||||
integrity sha512-MLPrqUcOnNBc8zTOfqBbxtoa8/Ee8tZ7UFW7hRDQSUT+NGsvS96wlbHGTf+EFAT9KC3VNb7fWEM6oyvmxtE/9w==
|
integrity sha512-gAiEnSKF104fsGDXNkwk49jD/0N0Bqu2K9+aMQXA6avzsA9H3Fiv1PW2D+gzbOSR705bWd2wJZRFEFpV0tXISg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jest/environment" "^29.4.2"
|
"@jest/environment" "^29.4.3"
|
||||||
"@jest/fake-timers" "^29.4.2"
|
"@jest/fake-timers" "^29.4.3"
|
||||||
"@jest/types" "^29.4.2"
|
"@jest/types" "^29.4.3"
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
jest-mock "^29.4.2"
|
jest-mock "^29.4.3"
|
||||||
jest-util "^29.4.2"
|
jest-util "^29.4.3"
|
||||||
|
|
||||||
jest-get-type@^26.3.0:
|
jest-get-type@^26.3.0:
|
||||||
version "26.3.0"
|
version "26.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.3.0.tgz#e97dc3c3f53c2b406ca7afaed4493b1d099199e0"
|
resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.3.0.tgz#e97dc3c3f53c2b406ca7afaed4493b1d099199e0"
|
||||||
integrity sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig==
|
integrity sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig==
|
||||||
|
|
||||||
jest-message-util@^29.4.2:
|
jest-message-util@^29.4.3:
|
||||||
version "29.4.2"
|
version "29.4.3"
|
||||||
resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.4.2.tgz#309a2924eae6ca67cf7f25781a2af1902deee717"
|
resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.4.3.tgz#65b5280c0fdc9419503b49d4f48d4999d481cb5b"
|
||||||
integrity sha512-SElcuN4s6PNKpOEtTInjOAA8QvItu0iugkXqhYyguRvQoXapg5gN+9RQxLAkakChZA7Y26j6yUCsFWN+hlKD6g==
|
integrity sha512-1Y8Zd4ZCN7o/QnWdMmT76If8LuDv23Z1DRovBj/vcSFNlGCJGoO8D1nJDw1AdyAGUk0myDLFGN5RbNeJyCRGCw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/code-frame" "^7.12.13"
|
"@babel/code-frame" "^7.12.13"
|
||||||
"@jest/types" "^29.4.2"
|
"@jest/types" "^29.4.3"
|
||||||
"@types/stack-utils" "^2.0.0"
|
"@types/stack-utils" "^2.0.0"
|
||||||
chalk "^4.0.0"
|
chalk "^4.0.0"
|
||||||
graceful-fs "^4.2.9"
|
graceful-fs "^4.2.9"
|
||||||
micromatch "^4.0.4"
|
micromatch "^4.0.4"
|
||||||
pretty-format "^29.4.2"
|
pretty-format "^29.4.3"
|
||||||
slash "^3.0.0"
|
slash "^3.0.0"
|
||||||
stack-utils "^2.0.3"
|
stack-utils "^2.0.3"
|
||||||
|
|
||||||
jest-mock@^29.4.2:
|
jest-mock@^29.4.3:
|
||||||
version "29.4.2"
|
version "29.4.3"
|
||||||
resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.4.2.tgz#e1054be66fb3e975d26d4528fcde6979e4759de8"
|
resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.4.3.tgz#23d84a20a74cdfff0510fdbeefb841ed57b0fe7e"
|
||||||
integrity sha512-x1FSd4Gvx2yIahdaIKoBjwji6XpboDunSJ95RpntGrYulI1ByuYQCKN/P7hvk09JB74IonU3IPLdkutEWYt++g==
|
integrity sha512-LjFgMg+xed9BdkPMyIJh+r3KeHt1klXPJYBULXVVAkbTaaKjPX1o1uVCAZADMEp/kOxGTwy/Ot8XbvgItOrHEg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jest/types" "^29.4.2"
|
"@jest/types" "^29.4.3"
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
jest-util "^29.4.2"
|
jest-util "^29.4.3"
|
||||||
|
|
||||||
jest-regex-util@^27.0.6:
|
jest-regex-util@^27.0.6:
|
||||||
version "27.5.1"
|
version "27.5.1"
|
||||||
@ -3516,12 +3516,12 @@ jest-util@^27.2.0:
|
|||||||
graceful-fs "^4.2.9"
|
graceful-fs "^4.2.9"
|
||||||
picomatch "^2.2.3"
|
picomatch "^2.2.3"
|
||||||
|
|
||||||
jest-util@^29.4.2:
|
jest-util@^29.4.3:
|
||||||
version "29.4.2"
|
version "29.4.3"
|
||||||
resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.4.2.tgz#3db8580b295df453a97de4a1b42dd2578dabd2c2"
|
resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.4.3.tgz#851a148e23fc2b633c55f6dad2e45d7f4579f496"
|
||||||
integrity sha512-wKnm6XpJgzMUSRFB7YF48CuwdzuDIHenVuoIb1PLuJ6F+uErZsuDkU+EiExkChf6473XcawBrSfDSnXl+/YG4g==
|
integrity sha512-ToSGORAz4SSSoqxDSylWX8JzkOQR7zoBtNRsA7e+1WUX5F8jrOwaNpuh1YfJHJKDHXLHmObv5eOjejUd+/Ws+Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jest/types" "^29.4.2"
|
"@jest/types" "^29.4.3"
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
chalk "^4.0.0"
|
chalk "^4.0.0"
|
||||||
ci-info "^3.2.0"
|
ci-info "^3.2.0"
|
||||||
@ -3585,10 +3585,10 @@ js-yaml@^4.1.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
argparse "^2.0.1"
|
argparse "^2.0.1"
|
||||||
|
|
||||||
jsc-android@^250230.2.1:
|
jsc-android@^250231.0.0:
|
||||||
version "250230.2.1"
|
version "250231.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/jsc-android/-/jsc-android-250230.2.1.tgz#3790313a970586a03ab0ad47defbc84df54f1b83"
|
resolved "https://registry.yarnpkg.com/jsc-android/-/jsc-android-250231.0.0.tgz#91720f8df382a108872fa4b3f558f33ba5e95262"
|
||||||
integrity sha512-KmxeBlRjwoqCnBBKGsihFtvsBHyUFlBxJPK4FzeYcIuBfdjv6jFys44JITAgSTbQD+vIdwMEfyZklsuQX0yI1Q==
|
integrity sha512-rS46PvsjYmdmuz1OAWXY/1kCYG7pnf1TBqeTiOJr1iDz7s5DLxxC9n/ZMknLDxzYzNVfI7R95MH10emSSG1Wuw==
|
||||||
|
|
||||||
jscodeshift@^0.13.1:
|
jscodeshift@^0.13.1:
|
||||||
version "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"
|
ansi-styles "^4.0.0"
|
||||||
react-is "^17.0.1"
|
react-is "^17.0.1"
|
||||||
|
|
||||||
pretty-format@^29.4.2:
|
pretty-format@^29.4.3:
|
||||||
version "29.4.2"
|
version "29.4.3"
|
||||||
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.4.2.tgz#64bf5ccc0d718c03027d94ac957bdd32b3fb2401"
|
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.4.3.tgz#25500ada21a53c9e8423205cf0337056b201244c"
|
||||||
integrity sha512-qKlHR8yFVCbcEWba0H0TOC8dnLlO4vPlyEjRPw31FZ2Rupy9nLa8ZLbYny8gWEl8CkEhJqAE6IzdNELTBVcBEg==
|
integrity sha512-cvpcHTc42lcsvOOAzd3XuNWTcvk1Jmnzqeu+WsOuiPmxUJTnkbAcFNsRKvEpBEUFVUgy/GTZLulZDcDEi+CIlA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jest/schemas" "^29.4.2"
|
"@jest/schemas" "^29.4.3"
|
||||||
ansi-styles "^5.0.0"
|
ansi-styles "^5.0.0"
|
||||||
react-is "^18.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"
|
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
|
||||||
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
|
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
|
||||||
|
|
||||||
react-native-codegen@^0.71.3:
|
react-native-codegen@^0.71.5:
|
||||||
version "0.71.3"
|
version "0.71.5"
|
||||||
resolved "https://registry.yarnpkg.com/react-native-codegen/-/react-native-codegen-0.71.3.tgz#75fbc591819050791319ebdb9fe341ee4df5c288"
|
resolved "https://registry.yarnpkg.com/react-native-codegen/-/react-native-codegen-0.71.5.tgz#454a42a891cd4ca5fc436440d301044dc1349c14"
|
||||||
integrity sha512-5AvdHVU1sAaXg05i0dG664ZTaCaIFaY1znV5vNsj+wUu6MGxNEUNbDKk9dxKUkkxOyk2KZOK5uhzWL0p5H5yZQ==
|
integrity sha512-rfsuc0zkuUuMjFnrT55I1mDZ+pBRp2zAiRwxck3m6qeGJBGK5OV5JH66eDQ4aa+3m0of316CqrJDRzVlYufzIg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/parser" "^7.14.0"
|
"@babel/parser" "^7.14.0"
|
||||||
flow-parser "^0.185.0"
|
flow-parser "^0.185.0"
|
||||||
@ -5032,20 +5032,19 @@ react-native-gesture-handler@^2.9.0:
|
|||||||
lodash "^4.17.21"
|
lodash "^4.17.21"
|
||||||
prop-types "^15.7.2"
|
prop-types "^15.7.2"
|
||||||
|
|
||||||
react-native-gradle-plugin@^0.71.14:
|
react-native-gradle-plugin@^0.71.15:
|
||||||
version "0.71.14"
|
version "0.71.15"
|
||||||
resolved "https://registry.yarnpkg.com/react-native-gradle-plugin/-/react-native-gradle-plugin-0.71.14.tgz#cc399662f04fbfcc0e352d03eae1d3efbd5f635a"
|
resolved "https://registry.yarnpkg.com/react-native-gradle-plugin/-/react-native-gradle-plugin-0.71.15.tgz#9e6b506f30729fe8eb086981702f4e3c891d2b13"
|
||||||
integrity sha512-nnLawTZEPPRAKq92UqDkzoGgCBl9aa9zAihFHMwmwzn4WRVdK4O6Cd4XYiyoNOiQzx3Hh9k5WOckHE80C92ivQ==
|
integrity sha512-7S3pAuPaQJlhax6EZ4JMsDNpj05TfuzX9gPgWLrFfAIWIFLuJ6aDQYAZy2TEI9QJALPoWrj8LWaqP/DGYh14pw==
|
||||||
|
|
||||||
react-native-pressable-opacity@^1.0.10:
|
react-native-pressable-opacity@^1.0.10:
|
||||||
version "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"
|
resolved "https://registry.yarnpkg.com/react-native-pressable-opacity/-/react-native-pressable-opacity-1.0.10.tgz#799df1a913d3b28f42ada765465fe7723eb7166d"
|
||||||
integrity sha512-Py9YH9TlS3Lv1so5JCj6bgiqkeYYGupF4ZImlpoyhhId/t/RiSqR68LlASOHgdctqQuqVJObQiFfzX8oZI9+6w==
|
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"
|
version "3.0.0-rc.10"
|
||||||
resolved "https://registry.yarnpkg.com/react-native-reanimated/-/react-native-reanimated-3.0.0-rc.10.tgz#40e5b628759aa81f94317fd0301231292b4eacf5"
|
resolved "https://github.com/software-mansion/react-native-reanimated#6cf9713a44ec61318bbb12c311f79c08eda95d10"
|
||||||
integrity sha512-0P2jSO+dXHRxSzqSxNp08VaUy89nqeUIvqBS0wlI8lsli8CJcqulL3pjNqTGzBkxXjt13mGdIzJv4u9lSjHPzg==
|
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/plugin-transform-object-assign" "^7.16.7"
|
"@babel/plugin-transform-object-assign" "^7.16.7"
|
||||||
"@babel/preset-typescript" "^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==
|
integrity sha512-0WORnk9SkREGUg2V7jHZbuN5x4vcxj/1B0QOcXJjdYWrzZHgLcUzYWWIUecUPJh747Mwjt/42RZDOaFn3L8kPQ==
|
||||||
|
|
||||||
react-native-screens@^3.19.0:
|
react-native-screens@^3.19.0:
|
||||||
version "3.19.0"
|
version "3.20.0"
|
||||||
resolved "https://registry.yarnpkg.com/react-native-screens/-/react-native-screens-3.19.0.tgz#ec68685e04b074ebce4641b3a0ae7e2571629b75"
|
resolved "https://registry.yarnpkg.com/react-native-screens/-/react-native-screens-3.20.0.tgz#4d154177395e5541387d9a05bc2e12e54d2fb5b1"
|
||||||
integrity sha512-Ehsmy7jr3H3j5pmN+/FqsAaIAD+k+xkcdePfLcg4rYRbN5X7fJPgaqhcmiCcZ0YxsU8ttsstP9IvRLNQuIkRRA==
|
integrity sha512-joWUKWAVHxymP3mL9gYApFHAsbd9L6ZcmpoZa6Sl3W/82bvvNVMqcfP7MeNqVCg73qZ8yL4fW+J/syusHleUgg==
|
||||||
dependencies:
|
dependencies:
|
||||||
react-freeze "^1.0.0"
|
react-freeze "^1.0.0"
|
||||||
warn-once "^0.1.0"
|
warn-once "^0.1.0"
|
||||||
@ -5091,14 +5090,14 @@ react-native-video@^5.2.1:
|
|||||||
prop-types "^15.7.2"
|
prop-types "^15.7.2"
|
||||||
shaka-player "^2.5.9"
|
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"
|
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:
|
react-native@^0.71.3:
|
||||||
version "0.71.2"
|
version "0.71.3"
|
||||||
resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.71.2.tgz#b6977eda2a6dc10baa006bf4ab1ee08318607ce9"
|
resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.71.3.tgz#0faab799c49e61ba12df9e6525c3ac7d595d673c"
|
||||||
integrity sha512-ZSianM+j+09LoEdVIhrAP/uP8sQhT7dH6olCqM2xlpxmfCgA5NubsK6NABIuZiBlmmqjigyijm5Y/GhBIHDvEg==
|
integrity sha512-RYJXCcQGa4NTfKiPgl92eRDUuQ6JGDnHqFEzRwJSqEx9lWvlvRRIebstJfurzPDKLQWQrvITR7aI7e09E25mLw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jest/create-cache-key-function" "^29.2.1"
|
"@jest/create-cache-key-function" "^29.2.1"
|
||||||
"@react-native-community/cli" "10.1.3"
|
"@react-native-community/cli" "10.1.3"
|
||||||
@ -5114,7 +5113,7 @@ react-native@^0.71.2:
|
|||||||
event-target-shim "^5.0.1"
|
event-target-shim "^5.0.1"
|
||||||
invariant "^2.2.4"
|
invariant "^2.2.4"
|
||||||
jest-environment-node "^29.2.1"
|
jest-environment-node "^29.2.1"
|
||||||
jsc-android "^250230.2.1"
|
jsc-android "^250231.0.0"
|
||||||
memoize-one "^5.0.0"
|
memoize-one "^5.0.0"
|
||||||
metro-react-native-babel-transformer "0.73.7"
|
metro-react-native-babel-transformer "0.73.7"
|
||||||
metro-runtime "0.73.7"
|
metro-runtime "0.73.7"
|
||||||
@ -5124,8 +5123,8 @@ react-native@^0.71.2:
|
|||||||
pretty-format "^26.5.2"
|
pretty-format "^26.5.2"
|
||||||
promise "^8.3.0"
|
promise "^8.3.0"
|
||||||
react-devtools-core "^4.26.1"
|
react-devtools-core "^4.26.1"
|
||||||
react-native-codegen "^0.71.3"
|
react-native-codegen "^0.71.5"
|
||||||
react-native-gradle-plugin "^0.71.14"
|
react-native-gradle-plugin "^0.71.15"
|
||||||
react-refresh "^0.4.0"
|
react-refresh "^0.4.0"
|
||||||
react-shallow-renderer "^16.15.0"
|
react-shallow-renderer "^16.15.0"
|
||||||
regenerator-runtime "^0.13.2"
|
regenerator-runtime "^0.13.2"
|
||||||
|
@ -17,20 +17,13 @@ public class CameraQueues: NSObject {
|
|||||||
autoreleaseFrequency: .inherit,
|
autoreleaseFrequency: .inherit,
|
||||||
target: nil)
|
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",
|
@objc public static let videoQueue = DispatchQueue(label: "mrousavy/VisionCamera.video",
|
||||||
qos: .userInteractive,
|
qos: .userInteractive,
|
||||||
attributes: [],
|
attributes: [],
|
||||||
autoreleaseFrequency: .inherit,
|
autoreleaseFrequency: .inherit,
|
||||||
target: nil)
|
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.
|
/// The serial execution queue for output processing of audio buffers.
|
||||||
@objc public static let audioQueue = DispatchQueue(label: "mrousavy/VisionCamera.audio",
|
@objc public static let audioQueue = DispatchQueue(label: "mrousavy/VisionCamera.audio",
|
||||||
qos: .userInteractive,
|
qos: .userInteractive,
|
||||||
|
@ -190,8 +190,8 @@ extension CameraView: AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureAud
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final func captureOutput(_ captureOutput: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from _: AVCaptureConnection) {
|
public final func captureOutput(_ captureOutput: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from _: AVCaptureConnection) {
|
||||||
// Video Recording runs in the same queue
|
|
||||||
if isRecording {
|
if isRecording {
|
||||||
|
// Write Video / Audio frame to file
|
||||||
guard let recordingSession = recordingSession else {
|
guard let recordingSession = recordingSession else {
|
||||||
invokeOnError(.capture(.unknown(message: "isRecording was true but the RecordingSession was null!")))
|
invokeOnError(.capture(.unknown(message: "isRecording was true but the RecordingSession was null!")))
|
||||||
return
|
return
|
||||||
@ -211,54 +211,9 @@ extension CameraView: AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureAud
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let frameProcessor = frameProcessorCallback, captureOutput is AVCaptureVideoDataOutput {
|
if let frameProcessor = frameProcessorCallback, captureOutput is AVCaptureVideoDataOutput {
|
||||||
// check if last frame was x nanoseconds ago, effectively throttling FPS
|
// Call the JavaScript Frame Processor func (worklet)
|
||||||
let frameTime = UInt64(CMSampleBufferGetPresentationTimeStamp(sampleBuffer).seconds * 1_000_000_000.0)
|
let frame = Frame(buffer: sampleBuffer, orientation: self.bufferOrientation)
|
||||||
let lastFrameProcessorCallElapsedTime = frameTime - lastFrameProcessorCall
|
frameProcessor(frame)
|
||||||
let secondsPerFrame = 1.0 / actualFrameProcessorFps
|
|
||||||
let nanosecondsPerFrame = secondsPerFrame * 1_000_000_000.0
|
|
||||||
if lastFrameProcessorCallElapsedTime >= UInt64(nanosecondsPerFrame) {
|
|
||||||
if !isRunningFrameProcessor {
|
|
||||||
// we're not in the middle of executing the Frame Processor, so prepare for next call.
|
|
||||||
CameraQueues.frameProcessorQueue.async {
|
|
||||||
self.isRunningFrameProcessor = true
|
|
||||||
|
|
||||||
let perfSample = self.frameProcessorPerformanceDataCollector.beginPerformanceSampleCollection()
|
|
||||||
let frame = Frame(buffer: sampleBuffer, orientation: self.bufferOrientation)
|
|
||||||
frameProcessor(frame)
|
|
||||||
perfSample.endPerformanceSampleCollection()
|
|
||||||
|
|
||||||
self.isRunningFrameProcessor = false
|
|
||||||
}
|
|
||||||
lastFrameProcessorCall = frameTime
|
|
||||||
} else {
|
|
||||||
// we're still in the middle of executing a Frame Processor for a previous frame, so a frame was dropped.
|
|
||||||
ReactLogger.log(level: .warning, message: "The Frame Processor took so long to execute that a frame was dropped.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if isReadyForNewEvaluation {
|
|
||||||
// last evaluation was more than 1sec ago, evaluate again
|
|
||||||
evaluateNewPerformanceSamples()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func evaluateNewPerformanceSamples() {
|
|
||||||
lastFrameProcessorPerformanceEvaluation = DispatchTime.now()
|
|
||||||
guard let videoDevice = videoDeviceInput?.device else { return }
|
|
||||||
guard frameProcessorPerformanceDataCollector.hasEnoughData else { return }
|
|
||||||
|
|
||||||
let maxFrameProcessorFps = Double(videoDevice.activeVideoMinFrameDuration.timescale) * Double(videoDevice.activeVideoMinFrameDuration.value)
|
|
||||||
let averageFps = 1.0 / frameProcessorPerformanceDataCollector.averageExecutionTimeSeconds
|
|
||||||
let suggestedFrameProcessorFps = max(floor(min(averageFps, maxFrameProcessorFps)), 1)
|
|
||||||
|
|
||||||
if frameProcessorFps.intValue == -1 {
|
|
||||||
// frameProcessorFps="auto"
|
|
||||||
actualFrameProcessorFps = suggestedFrameProcessorFps
|
|
||||||
} else {
|
|
||||||
// frameProcessorFps={someCustomFpsValue}
|
|
||||||
invokeOnFrameProcessorPerformanceSuggestionAvailable(currentFps: frameProcessorFps.doubleValue,
|
|
||||||
suggestedFps: suggestedFrameProcessorFps)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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).
|
Gets the orientation of the CameraView's images (CMSampleBuffers).
|
||||||
*/
|
*/
|
||||||
|
@ -52,7 +52,6 @@ public final class CameraView: UIView {
|
|||||||
// props that require format reconfiguring
|
// props that require format reconfiguring
|
||||||
@objc var format: NSDictionary?
|
@objc var format: NSDictionary?
|
||||||
@objc var fps: NSNumber?
|
@objc var fps: NSNumber?
|
||||||
@objc var frameProcessorFps: NSNumber = -1.0 // "auto"
|
|
||||||
@objc var hdr: NSNumber? // nullable bool
|
@objc var hdr: NSNumber? // nullable bool
|
||||||
@objc var lowLightBoost: NSNumber? // nullable bool
|
@objc var lowLightBoost: NSNumber? // nullable bool
|
||||||
@objc var colorSpace: NSString?
|
@objc var colorSpace: NSString?
|
||||||
@ -65,7 +64,6 @@ public final class CameraView: UIView {
|
|||||||
// events
|
// events
|
||||||
@objc var onInitialized: RCTDirectEventBlock?
|
@objc var onInitialized: RCTDirectEventBlock?
|
||||||
@objc var onError: RCTDirectEventBlock?
|
@objc var onError: RCTDirectEventBlock?
|
||||||
@objc var onFrameProcessorPerformanceSuggestionAvailable: RCTDirectEventBlock?
|
|
||||||
@objc var onViewReady: RCTDirectEventBlock?
|
@objc var onViewReady: RCTDirectEventBlock?
|
||||||
// zoom
|
// zoom
|
||||||
@objc var enableZoomGesture = false {
|
@objc var enableZoomGesture = false {
|
||||||
@ -105,13 +103,6 @@ public final class CameraView: UIView {
|
|||||||
internal let videoQueue = CameraQueues.videoQueue
|
internal let videoQueue = CameraQueues.videoQueue
|
||||||
internal let audioQueue = CameraQueues.audioQueue
|
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)
|
/// Returns whether the AVCaptureSession is currently running (reflected by isActive)
|
||||||
var isRunning: Bool {
|
var isRunning: Bool {
|
||||||
return captureSession.isRunning
|
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) {
|
internal final func setTorchMode(_ torchMode: String) {
|
||||||
@ -343,18 +322,4 @@ public final class CameraView: UIView {
|
|||||||
guard let onInitialized = onInitialized else { return }
|
guard let onInitialized = onInitialized else { return }
|
||||||
onInitialized([String: Any]())
|
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
|
// device format
|
||||||
RCT_EXPORT_VIEW_PROPERTY(format, NSDictionary);
|
RCT_EXPORT_VIEW_PROPERTY(format, NSDictionary);
|
||||||
RCT_EXPORT_VIEW_PROPERTY(fps, NSNumber);
|
RCT_EXPORT_VIEW_PROPERTY(fps, NSNumber);
|
||||||
RCT_EXPORT_VIEW_PROPERTY(frameProcessorFps, NSNumber);
|
|
||||||
RCT_EXPORT_VIEW_PROPERTY(hdr, NSNumber); // nullable bool
|
RCT_EXPORT_VIEW_PROPERTY(hdr, NSNumber); // nullable bool
|
||||||
RCT_EXPORT_VIEW_PROPERTY(lowLightBoost, NSNumber); // nullable bool
|
RCT_EXPORT_VIEW_PROPERTY(lowLightBoost, NSNumber); // nullable bool
|
||||||
RCT_EXPORT_VIEW_PROPERTY(colorSpace, NSString);
|
RCT_EXPORT_VIEW_PROPERTY(colorSpace, NSString);
|
||||||
@ -49,7 +48,6 @@ RCT_EXPORT_VIEW_PROPERTY(orientation, NSString);
|
|||||||
// Camera View Events
|
// Camera View Events
|
||||||
RCT_EXPORT_VIEW_PROPERTY(onError, RCTDirectEventBlock);
|
RCT_EXPORT_VIEW_PROPERTY(onError, RCTDirectEventBlock);
|
||||||
RCT_EXPORT_VIEW_PROPERTY(onInitialized, RCTDirectEventBlock);
|
RCT_EXPORT_VIEW_PROPERTY(onInitialized, RCTDirectEventBlock);
|
||||||
RCT_EXPORT_VIEW_PROPERTY(onFrameProcessorPerformanceSuggestionAvailable, RCTDirectEventBlock);
|
|
||||||
RCT_EXPORT_VIEW_PROPERTY(onViewReady, RCTDirectEventBlock);
|
RCT_EXPORT_VIEW_PROPERTY(onViewReady, RCTDirectEventBlock);
|
||||||
|
|
||||||
// Camera View Functions
|
// Camera View Functions
|
||||||
|
@ -16,16 +16,12 @@ using namespace facebook;
|
|||||||
|
|
||||||
class JSI_EXPORT FrameHostObject: public jsi::HostObject {
|
class JSI_EXPORT FrameHostObject: public jsi::HostObject {
|
||||||
public:
|
public:
|
||||||
explicit FrameHostObject(Frame* frame): frame(frame) {}
|
explicit FrameHostObject(Frame* frame): frame(frame) { }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
jsi::Value get(jsi::Runtime&, const jsi::PropNameID& name) override;
|
jsi::Value get(jsi::Runtime&, const jsi::PropNameID& name) override;
|
||||||
std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime& rt) override;
|
std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime& rt) override;
|
||||||
void close();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Frame* frame;
|
Frame* frame;
|
||||||
|
|
||||||
private:
|
|
||||||
void assertIsFrameStrong(jsi::Runtime& runtime, const std::string& accessedPropName);
|
|
||||||
};
|
};
|
||||||
|
@ -9,16 +9,21 @@
|
|||||||
#import "FrameHostObject.h"
|
#import "FrameHostObject.h"
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
#import <jsi/jsi.h>
|
#import <jsi/jsi.h>
|
||||||
|
#import "JsiHostObject.h"
|
||||||
|
#import "JsiSharedValue.h"
|
||||||
|
|
||||||
std::vector<jsi::PropNameID> FrameHostObject::getPropertyNames(jsi::Runtime& rt) {
|
std::vector<jsi::PropNameID> FrameHostObject::getPropertyNames(jsi::Runtime& rt) {
|
||||||
std::vector<jsi::PropNameID> result;
|
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("width")));
|
||||||
result.push_back(jsi::PropNameID::forUtf8(rt, std::string("height")));
|
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("bytesPerRow")));
|
||||||
result.push_back(jsi::PropNameID::forUtf8(rt, std::string("planesCount")));
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,7 +31,7 @@ jsi::Value FrameHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pr
|
|||||||
auto name = propName.utf8(runtime);
|
auto name = propName.utf8(runtime);
|
||||||
|
|
||||||
if (name == "toString") {
|
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) {
|
if (this->frame == nil) {
|
||||||
return jsi::String::createFromUtf8(runtime, "[closed frame]");
|
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);
|
return jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forUtf8(runtime, "toString"), 0, toString);
|
||||||
}
|
}
|
||||||
if (name == "close") {
|
if (name == "incrementRefCount") {
|
||||||
auto close = [this] (jsi::Runtime& runtime, const jsi::Value&, const jsi::Value*, size_t) -> jsi::Value {
|
auto incrementRefCount = JSI_HOST_FUNCTION_LAMBDA {
|
||||||
if (this->frame == nil) {
|
// Increment retain count by one so ARC doesn't destroy the Frame Buffer.
|
||||||
throw jsi::JSError(runtime, "Trying to close an already closed frame! Did you call frame.close() twice?");
|
CFRetain(frame.buffer);
|
||||||
}
|
|
||||||
this->close();
|
|
||||||
return jsi::Value::undefined();
|
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") {
|
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);
|
return jsi::Value(isValid);
|
||||||
}
|
}
|
||||||
if (name == "width") {
|
if (name == "width") {
|
||||||
this->assertIsFrameStrong(runtime, name);
|
|
||||||
auto imageBuffer = CMSampleBufferGetImageBuffer(frame.buffer);
|
auto imageBuffer = CMSampleBufferGetImageBuffer(frame.buffer);
|
||||||
auto width = CVPixelBufferGetWidth(imageBuffer);
|
auto width = CVPixelBufferGetWidth(imageBuffer);
|
||||||
return jsi::Value((double) width);
|
return jsi::Value((double) width);
|
||||||
}
|
}
|
||||||
if (name == "height") {
|
if (name == "height") {
|
||||||
this->assertIsFrameStrong(runtime, name);
|
|
||||||
auto imageBuffer = CMSampleBufferGetImageBuffer(frame.buffer);
|
auto imageBuffer = CMSampleBufferGetImageBuffer(frame.buffer);
|
||||||
auto height = CVPixelBufferGetHeight(imageBuffer);
|
auto height = CVPixelBufferGetHeight(imageBuffer);
|
||||||
return jsi::Value((double) height);
|
return jsi::Value((double) height);
|
||||||
}
|
}
|
||||||
if (name == "bytesPerRow") {
|
if (name == "bytesPerRow") {
|
||||||
this->assertIsFrameStrong(runtime, name);
|
|
||||||
auto imageBuffer = CMSampleBufferGetImageBuffer(frame.buffer);
|
auto imageBuffer = CMSampleBufferGetImageBuffer(frame.buffer);
|
||||||
auto bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
|
auto bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
|
||||||
return jsi::Value((double) bytesPerRow);
|
return jsi::Value((double) bytesPerRow);
|
||||||
}
|
}
|
||||||
if (name == "planesCount") {
|
if (name == "planesCount") {
|
||||||
this->assertIsFrameStrong(runtime, name);
|
|
||||||
auto imageBuffer = CMSampleBufferGetImageBuffer(frame.buffer);
|
auto imageBuffer = CMSampleBufferGetImageBuffer(frame.buffer);
|
||||||
auto planesCount = CVPixelBufferGetPlaneCount(imageBuffer);
|
auto planesCount = CVPixelBufferGetPlaneCount(imageBuffer);
|
||||||
return jsi::Value((double) planesCount);
|
return jsi::Value((double) planesCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
return jsi::Value::undefined();
|
// fallback to base implementation
|
||||||
}
|
return HostObject::get(runtime, propName);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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 "JsiWorkletContext.h"
|
||||||
#import "JsiWorkletApi.h"
|
#import "JsiWorkletApi.h"
|
||||||
#import "JsiWorklet.h"
|
#import "JsiWorklet.h"
|
||||||
|
#import "JsiHostObject.h"
|
||||||
|
|
||||||
#import "FrameProcessorUtils.h"
|
#import "FrameProcessorUtils.h"
|
||||||
#import "FrameProcessorCallback.h"
|
#import "FrameProcessorCallback.h"
|
||||||
@ -30,7 +31,7 @@
|
|||||||
// Forward declarations for the Swift classes
|
// Forward declarations for the Swift classes
|
||||||
__attribute__((objc_runtime_name("_TtC12VisionCamera12CameraQueues")))
|
__attribute__((objc_runtime_name("_TtC12VisionCamera12CameraQueues")))
|
||||||
@interface CameraQueues : NSObject
|
@interface CameraQueues : NSObject
|
||||||
@property (nonatomic, class, readonly, strong) dispatch_queue_t _Nonnull frameProcessorQueue;
|
@property (nonatomic, class, readonly, strong) dispatch_queue_t _Nonnull videoQueue;
|
||||||
@end
|
@end
|
||||||
__attribute__((objc_runtime_name("_TtC12VisionCamera10CameraView")))
|
__attribute__((objc_runtime_name("_TtC12VisionCamera10CameraView")))
|
||||||
@interface CameraView : UIView
|
@interface CameraView : UIView
|
||||||
@ -38,6 +39,7 @@ __attribute__((objc_runtime_name("_TtC12VisionCamera10CameraView")))
|
|||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation FrameProcessorRuntimeManager {
|
@implementation FrameProcessorRuntimeManager {
|
||||||
|
// Running Frame Processors on camera's video thread (synchronously)
|
||||||
std::shared_ptr<RNWorklet::JsiWorkletContext> workletContext;
|
std::shared_ptr<RNWorklet::JsiWorkletContext> workletContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,16 +61,15 @@ __attribute__((objc_runtime_name("_TtC12VisionCamera10CameraView")))
|
|||||||
};
|
};
|
||||||
auto runOnWorklet = [](std::function<void()>&& f) {
|
auto runOnWorklet = [](std::function<void()>&& f) {
|
||||||
// Run on Frame Processor Worklet Runtime
|
// Run on Frame Processor Worklet Runtime
|
||||||
dispatch_async(CameraQueues.frameProcessorQueue, [f = std::move(f)](){
|
dispatch_async(CameraQueues.videoQueue, [f = std::move(f)](){
|
||||||
f();
|
f();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
workletContext = std::make_shared<RNWorklet::JsiWorkletContext>("VisionCamera");
|
workletContext = std::make_shared<RNWorklet::JsiWorkletContext>("VisionCamera",
|
||||||
workletContext->initialize("VisionCamera",
|
&runtime,
|
||||||
&runtime,
|
runOnJS,
|
||||||
runOnJS,
|
runOnWorklet);
|
||||||
runOnWorklet);
|
|
||||||
|
|
||||||
NSLog(@"FrameProcessorBindings: Worklet Context Created!");
|
NSLog(@"FrameProcessorBindings: Worklet Context Created!");
|
||||||
|
|
||||||
@ -136,28 +137,17 @@ __attribute__((objc_runtime_name("_TtC12VisionCamera10CameraView")))
|
|||||||
NSLog(@"FrameProcessorBindings: Installing global functions...");
|
NSLog(@"FrameProcessorBindings: Installing global functions...");
|
||||||
|
|
||||||
// setFrameProcessor(viewTag: number, frameProcessor: (frame: Frame) => void)
|
// setFrameProcessor(viewTag: number, frameProcessor: (frame: Frame) => void)
|
||||||
auto setFrameProcessor = [self](jsi::Runtime& runtime,
|
auto setFrameProcessor = JSI_HOST_FUNCTION_LAMBDA {
|
||||||
const jsi::Value& thisValue,
|
|
||||||
const jsi::Value* arguments,
|
|
||||||
size_t count) -> jsi::Value {
|
|
||||||
NSLog(@"FrameProcessorBindings: Setting new frame processor...");
|
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();
|
auto viewTag = arguments[0].asNumber();
|
||||||
NSLog(@"FrameProcessorBindings: Converting JSI Function to Worklet...");
|
|
||||||
auto worklet = std::make_shared<RNWorklet::JsiWorklet>(runtime, arguments[1]);
|
auto worklet = std::make_shared<RNWorklet::JsiWorklet>(runtime, arguments[1]);
|
||||||
|
|
||||||
RCTExecuteOnMainQueue([=]() {
|
RCTExecuteOnMainQueue(^{
|
||||||
auto currentBridge = [RCTBridge currentBridge];
|
auto currentBridge = [RCTBridge currentBridge];
|
||||||
auto anonymousView = [currentBridge.uiManager viewForReactTag:[NSNumber numberWithDouble:viewTag]];
|
auto anonymousView = [currentBridge.uiManager viewForReactTag:[NSNumber numberWithDouble:viewTag]];
|
||||||
auto view = static_cast<CameraView*>(anonymousView);
|
auto view = static_cast<CameraView*>(anonymousView);
|
||||||
|
auto callback = convertWorkletToFrameProcessorCallback(self->workletContext->getWorkletRuntime(), worklet);
|
||||||
NSLog(@"FrameProcessorBindings: Converting worklet to Objective-C callback...");
|
view.frameProcessorCallback = callback;
|
||||||
|
|
||||||
view.frameProcessorCallback = convertWorkletToFrameProcessorCallback(workletContext->getWorkletRuntime(), worklet);
|
|
||||||
|
|
||||||
NSLog(@"FrameProcessorBindings: Frame processor set!");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return jsi::Value::undefined();
|
return jsi::Value::undefined();
|
||||||
@ -168,12 +158,8 @@ __attribute__((objc_runtime_name("_TtC12VisionCamera10CameraView")))
|
|||||||
setFrameProcessor));
|
setFrameProcessor));
|
||||||
|
|
||||||
// unsetFrameProcessor(viewTag: number)
|
// unsetFrameProcessor(viewTag: number)
|
||||||
auto unsetFrameProcessor = [](jsi::Runtime& runtime,
|
auto unsetFrameProcessor = JSI_HOST_FUNCTION_LAMBDA {
|
||||||
const jsi::Value& thisValue,
|
|
||||||
const jsi::Value* arguments,
|
|
||||||
size_t count) -> jsi::Value {
|
|
||||||
NSLog(@"FrameProcessorBindings: Removing frame processor...");
|
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();
|
auto viewTag = arguments[0].asNumber();
|
||||||
|
|
||||||
RCTExecuteOnMainQueue(^{
|
RCTExecuteOnMainQueue(^{
|
||||||
@ -185,7 +171,6 @@ __attribute__((objc_runtime_name("_TtC12VisionCamera10CameraView")))
|
|||||||
|
|
||||||
auto view = static_cast<CameraView*>(anonymousView);
|
auto view = static_cast<CameraView*>(anonymousView);
|
||||||
view.frameProcessorCallback = nil;
|
view.frameProcessorCallback = nil;
|
||||||
NSLog(@"FrameProcessorBindings: Frame processor removed!");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return jsi::Value::undefined();
|
return jsi::Value::undefined();
|
||||||
|
@ -28,13 +28,15 @@ FrameProcessorCallback convertWorkletToFrameProcessorCallback(jsi::Runtime& runt
|
|||||||
// Converts a Worklet to a callable Objective-C block function
|
// Converts a Worklet to a callable Objective-C block function
|
||||||
return ^(Frame* frame) {
|
return ^(Frame* frame) {
|
||||||
|
|
||||||
auto frameHostObject = std::make_shared<FrameHostObject>(frame);
|
|
||||||
try {
|
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);
|
auto argument = jsi::Object::createFromHostObject(runtime, frameHostObject);
|
||||||
jsi::Value jsValue(std::move(argument));
|
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);
|
workletInvoker->call(runtime, jsi::Value::undefined(), &jsValue, 1);
|
||||||
} catch (jsi::JSError& jsError) {
|
} catch (jsi::JSError& jsError) {
|
||||||
|
// JS Error occured, print it to console.
|
||||||
auto stack = std::regex_replace(jsError.getStack(), std::regex("\n"), "\n ");
|
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()];
|
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);
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
B8A751D72609E4B30011C623 /* FrameProcessorRuntimeManager.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FrameProcessorRuntimeManager.mm; sourceTree = "<group>"; };
|
||||||
@ -273,7 +272,6 @@
|
|||||||
B88873E5263D46C7008B1D0E /* FrameProcessorPlugin.h */,
|
B88873E5263D46C7008B1D0E /* FrameProcessorPlugin.h */,
|
||||||
B80416F026AB16E8000DEB6A /* VisionCameraScheduler.mm */,
|
B80416F026AB16E8000DEB6A /* VisionCameraScheduler.mm */,
|
||||||
B80416F126AB16F3000DEB6A /* VisionCameraScheduler.h */,
|
B80416F126AB16F3000DEB6A /* VisionCameraScheduler.h */,
|
||||||
B8948BDF26DCEE2B00B430E2 /* FrameProcessorPerformanceDataCollector.swift */,
|
|
||||||
);
|
);
|
||||||
path = "Frame Processor";
|
path = "Frame Processor";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -80,8 +80,9 @@
|
|||||||
"pod-install": "^0.1.38",
|
"pod-install": "^0.1.38",
|
||||||
"prettier": "^2.8.4",
|
"prettier": "^2.8.4",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-native": "^0.71.2",
|
"react-native": "^0.71.3",
|
||||||
"react-native-builder-bob": "^0.20.3",
|
"react-native-builder-bob": "^0.20.3",
|
||||||
|
"react-native-worklets": "https://github.com/chrfalch/react-native-worklets#15d52dd",
|
||||||
"release-it": "^15.6.0",
|
"release-it": "^15.6.0",
|
||||||
"typescript": "^4.9.5"
|
"typescript": "^4.9.5"
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { requireNativeComponent, NativeModules, NativeSyntheticEvent, findNodeHandle, NativeMethods, Platform } from 'react-native';
|
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 { CameraDevice } from './CameraDevice';
|
||||||
import type { ErrorWithCause } from './CameraError';
|
import type { ErrorWithCause } from './CameraError';
|
||||||
import { CameraCaptureError, CameraRuntimeError, tryParseNativeCameraError, isErrorWithCause } from './CameraError';
|
import { CameraCaptureError, CameraRuntimeError, tryParseNativeCameraError, isErrorWithCause } from './CameraError';
|
||||||
@ -20,16 +20,11 @@ interface OnErrorEvent {
|
|||||||
message: string;
|
message: string;
|
||||||
cause?: ErrorWithCause;
|
cause?: ErrorWithCause;
|
||||||
}
|
}
|
||||||
type NativeCameraViewProps = Omit<
|
type NativeCameraViewProps = Omit<CameraProps, 'device' | 'onInitialized' | 'onError' | 'frameProcessor'> & {
|
||||||
CameraProps,
|
|
||||||
'device' | 'onInitialized' | 'onError' | 'onFrameProcessorPerformanceSuggestionAvailable' | 'frameProcessor' | 'frameProcessorFps'
|
|
||||||
> & {
|
|
||||||
cameraId: string;
|
cameraId: string;
|
||||||
frameProcessorFps?: number; // native cannot use number | string, so we use '-1' for 'auto'
|
|
||||||
enableFrameProcessor: boolean;
|
enableFrameProcessor: boolean;
|
||||||
onInitialized?: (event: NativeSyntheticEvent<void>) => void;
|
onInitialized?: (event: NativeSyntheticEvent<void>) => void;
|
||||||
onError?: (event: NativeSyntheticEvent<OnErrorEvent>) => void;
|
onError?: (event: NativeSyntheticEvent<OnErrorEvent>) => void;
|
||||||
onFrameProcessorPerformanceSuggestionAvailable?: (event: NativeSyntheticEvent<FrameProcessorPerformanceSuggestion>) => void;
|
|
||||||
onViewReady: () => void;
|
onViewReady: () => void;
|
||||||
};
|
};
|
||||||
type RefType = React.Component<NativeCameraViewProps> & Readonly<NativeMethods>;
|
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.onViewReady = this.onViewReady.bind(this);
|
||||||
this.onInitialized = this.onInitialized.bind(this);
|
this.onInitialized = this.onInitialized.bind(this);
|
||||||
this.onError = this.onError.bind(this);
|
this.onError = this.onError.bind(this);
|
||||||
this.onFrameProcessorPerformanceSuggestionAvailable = this.onFrameProcessorPerformanceSuggestionAvailable.bind(this);
|
|
||||||
this.ref = React.createRef<RefType>();
|
this.ref = React.createRef<RefType>();
|
||||||
this.lastFrameProcessor = undefined;
|
this.lastFrameProcessor = undefined;
|
||||||
}
|
}
|
||||||
@ -422,11 +416,6 @@ export class Camera extends React.PureComponent<CameraProps> {
|
|||||||
private onInitialized(): void {
|
private onInitialized(): void {
|
||||||
this.props.onInitialized?.();
|
this.props.onInitialized?.();
|
||||||
}
|
}
|
||||||
|
|
||||||
private onFrameProcessorPerformanceSuggestionAvailable(event: NativeSyntheticEvent<FrameProcessorPerformanceSuggestion>): void {
|
|
||||||
if (this.props.onFrameProcessorPerformanceSuggestionAvailable != null)
|
|
||||||
this.props.onFrameProcessorPerformanceSuggestionAvailable(event.nativeEvent);
|
|
||||||
}
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
//#region Lifecycle
|
//#region Lifecycle
|
||||||
@ -479,17 +468,15 @@ export class Camera extends React.PureComponent<CameraProps> {
|
|||||||
/** @internal */
|
/** @internal */
|
||||||
public render(): React.ReactNode {
|
public render(): React.ReactNode {
|
||||||
// We remove the big `device` object from the props because we only need to pass `cameraId` to native.
|
// 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 (
|
return (
|
||||||
<NativeCameraView
|
<NativeCameraView
|
||||||
{...props}
|
{...props}
|
||||||
frameProcessorFps={frameProcessorFps === 'auto' ? -1 : frameProcessorFps}
|
|
||||||
cameraId={device.id}
|
cameraId={device.id}
|
||||||
ref={this.ref}
|
ref={this.ref}
|
||||||
onViewReady={this.onViewReady}
|
onViewReady={this.onViewReady}
|
||||||
onInitialized={this.onInitialized}
|
onInitialized={this.onInitialized}
|
||||||
onError={this.onError}
|
onError={this.onError}
|
||||||
onFrameProcessorPerformanceSuggestionAvailable={this.onFrameProcessorPerformanceSuggestionAvailable}
|
|
||||||
enableFrameProcessor={frameProcessor != null}
|
enableFrameProcessor={frameProcessor != null}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -4,11 +4,6 @@ import type { CameraRuntimeError } from './CameraError';
|
|||||||
import type { CameraPreset } from './CameraPreset';
|
import type { CameraPreset } from './CameraPreset';
|
||||||
import type { Frame } from './Frame';
|
import type { Frame } from './Frame';
|
||||||
|
|
||||||
export interface FrameProcessorPerformanceSuggestion {
|
|
||||||
type: 'can-use-higher-fps' | 'should-use-lower-fps';
|
|
||||||
suggestedFrameProcessorFps: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface CameraProps extends ViewProps {
|
export interface CameraProps extends ViewProps {
|
||||||
/**
|
/**
|
||||||
* The Camera Device to use.
|
* The Camera Device to use.
|
||||||
@ -171,11 +166,7 @@ export interface CameraProps extends ViewProps {
|
|||||||
*/
|
*/
|
||||||
onInitialized?: () => void;
|
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.
|
* A worklet which will be called for every frame the Camera "sees".
|
||||||
*/
|
|
||||||
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}.
|
|
||||||
*
|
*
|
||||||
* > See [the Frame Processors documentation](https://mrousavy.github.io/react-native-vision-camera/docs/guides/frame-processors) for more information
|
* > 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;
|
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
|
//#endregion
|
||||||
}
|
}
|
||||||
|
30
src/Frame.ts
30
src/Frame.ts
@ -31,19 +31,19 @@ export interface Frame {
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
toString(): string;
|
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.
|
export interface FrameInternal extends Frame {
|
||||||
*
|
/**
|
||||||
* @example
|
* Increment the Frame Buffer ref-count by one.
|
||||||
* ```ts
|
*
|
||||||
* const frameProcessor = useFrameProcessor((frame) => {
|
* This is a private API, do not use this.
|
||||||
* const smallerCopy = resize(frame, 480, 270)
|
*/
|
||||||
* // run AI ...
|
incrementRefCount(): void;
|
||||||
* smallerCopy.close()
|
/**
|
||||||
* // don't close `frame`!
|
* Increment the Frame Buffer ref-count by one.
|
||||||
* })
|
*
|
||||||
* ```
|
* This is a private API, do not use this.
|
||||||
*/
|
*/
|
||||||
close(): void;
|
decrementRefCount(): void;
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,101 @@
|
|||||||
import type { Frame } from './Frame';
|
import type { Frame, FrameInternal } from './Frame';
|
||||||
import { Camera } from './Camera';
|
import { Camera } from './Camera';
|
||||||
|
import { Worklets } from 'react-native-worklets/src';
|
||||||
|
|
||||||
// Install VisionCamera Frame Processor JSI Bindings and Plugins
|
// Install VisionCamera Frame Processor JSI Bindings and Plugins
|
||||||
Camera.installFrameProcessorBindings();
|
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>;
|
type TFrameProcessorPlugins = Record<string, FrameProcessor>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All natively installed Frame Processor Plugins.
|
* All natively installed Frame Processor Plugins.
|
||||||
*/
|
*/
|
||||||
export const FrameProcessorPlugins = global.FrameProcessorPlugins as TFrameProcessorPlugins;
|
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 { DependencyList, useCallback } from 'react';
|
||||||
import type { Frame } from '../Frame';
|
import type { Frame, FrameInternal } from '../Frame';
|
||||||
// Install RN Worklets by importing it
|
// Install RN Worklets by importing it
|
||||||
import 'react-native-worklets/src';
|
import 'react-native-worklets/src';
|
||||||
|
|
||||||
@ -23,6 +23,17 @@ type FrameProcessor = (frame: Frame) => void;
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export function useFrameProcessor(frameProcessor: FrameProcessor, dependencies: DependencyList): FrameProcessor {
|
export function useFrameProcessor(frameProcessor: FrameProcessor, dependencies: DependencyList): FrameProcessor {
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
return useCallback((frame: Frame) => {
|
||||||
return useCallback(frameProcessor, dependencies);
|
'worklet';
|
||||||
|
// Increment ref-count by one
|
||||||
|
(frame as FrameInternal).incrementRefCount();
|
||||||
|
try {
|
||||||
|
// Call sync frame processor
|
||||||
|
frameProcessor(frame);
|
||||||
|
} finally {
|
||||||
|
// Potentially delete Frame if we were the last ref (no runAsync)
|
||||||
|
(frame as FrameInternal).decrementRefCount();
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, dependencies);
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ export * from './CameraError';
|
|||||||
export * from './CameraPosition';
|
export * from './CameraPosition';
|
||||||
export * from './CameraPreset';
|
export * from './CameraPreset';
|
||||||
export * from './CameraProps';
|
export * from './CameraProps';
|
||||||
export * from './Frame';
|
export { Frame } from './Frame';
|
||||||
export * from './FrameProcessorPlugins';
|
export * from './FrameProcessorPlugins';
|
||||||
export * from './CameraProps';
|
export * from './CameraProps';
|
||||||
export * from './PhotoFile';
|
export * from './PhotoFile';
|
||||||
|
42
yarn.lock
42
yarn.lock
@ -5217,10 +5217,10 @@ js-yaml@^4.1.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
argparse "^2.0.1"
|
argparse "^2.0.1"
|
||||||
|
|
||||||
jsc-android@^250230.2.1:
|
jsc-android@^250231.0.0:
|
||||||
version "250230.2.1"
|
version "250231.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/jsc-android/-/jsc-android-250230.2.1.tgz#3790313a970586a03ab0ad47defbc84df54f1b83"
|
resolved "https://registry.yarnpkg.com/jsc-android/-/jsc-android-250231.0.0.tgz#91720f8df382a108872fa4b3f558f33ba5e95262"
|
||||||
integrity sha512-KmxeBlRjwoqCnBBKGsihFtvsBHyUFlBxJPK4FzeYcIuBfdjv6jFys44JITAgSTbQD+vIdwMEfyZklsuQX0yI1Q==
|
integrity sha512-rS46PvsjYmdmuz1OAWXY/1kCYG7pnf1TBqeTiOJr1iDz7s5DLxxC9n/ZMknLDxzYzNVfI7R95MH10emSSG1Wuw==
|
||||||
|
|
||||||
jscodeshift@^0.13.1:
|
jscodeshift@^0.13.1:
|
||||||
version "0.13.1"
|
version "0.13.1"
|
||||||
@ -6867,25 +6867,29 @@ react-native-builder-bob@^0.20.3:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
jetifier "^2.0.0"
|
jetifier "^2.0.0"
|
||||||
|
|
||||||
react-native-codegen@^0.71.3:
|
react-native-codegen@^0.71.5:
|
||||||
version "0.71.3"
|
version "0.71.5"
|
||||||
resolved "https://registry.yarnpkg.com/react-native-codegen/-/react-native-codegen-0.71.3.tgz#75fbc591819050791319ebdb9fe341ee4df5c288"
|
resolved "https://registry.yarnpkg.com/react-native-codegen/-/react-native-codegen-0.71.5.tgz#454a42a891cd4ca5fc436440d301044dc1349c14"
|
||||||
integrity sha512-5AvdHVU1sAaXg05i0dG664ZTaCaIFaY1znV5vNsj+wUu6MGxNEUNbDKk9dxKUkkxOyk2KZOK5uhzWL0p5H5yZQ==
|
integrity sha512-rfsuc0zkuUuMjFnrT55I1mDZ+pBRp2zAiRwxck3m6qeGJBGK5OV5JH66eDQ4aa+3m0of316CqrJDRzVlYufzIg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/parser" "^7.14.0"
|
"@babel/parser" "^7.14.0"
|
||||||
flow-parser "^0.185.0"
|
flow-parser "^0.185.0"
|
||||||
jscodeshift "^0.13.1"
|
jscodeshift "^0.13.1"
|
||||||
nullthrows "^1.1.1"
|
nullthrows "^1.1.1"
|
||||||
|
|
||||||
react-native-gradle-plugin@^0.71.14:
|
react-native-gradle-plugin@^0.71.15:
|
||||||
version "0.71.14"
|
version "0.71.15"
|
||||||
resolved "https://registry.yarnpkg.com/react-native-gradle-plugin/-/react-native-gradle-plugin-0.71.14.tgz#cc399662f04fbfcc0e352d03eae1d3efbd5f635a"
|
resolved "https://registry.yarnpkg.com/react-native-gradle-plugin/-/react-native-gradle-plugin-0.71.15.tgz#9e6b506f30729fe8eb086981702f4e3c891d2b13"
|
||||||
integrity sha512-nnLawTZEPPRAKq92UqDkzoGgCBl9aa9zAihFHMwmwzn4WRVdK4O6Cd4XYiyoNOiQzx3Hh9k5WOckHE80C92ivQ==
|
integrity sha512-7S3pAuPaQJlhax6EZ4JMsDNpj05TfuzX9gPgWLrFfAIWIFLuJ6aDQYAZy2TEI9QJALPoWrj8LWaqP/DGYh14pw==
|
||||||
|
|
||||||
react-native@^0.71.2:
|
"react-native-worklets@https://github.com/chrfalch/react-native-worklets#15d52dd":
|
||||||
version "0.71.2"
|
version "0.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.71.2.tgz#b6977eda2a6dc10baa006bf4ab1ee08318607ce9"
|
resolved "https://github.com/chrfalch/react-native-worklets#15d52dd1289831cecc7906823f613172e0c6cd2e"
|
||||||
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:
|
dependencies:
|
||||||
"@jest/create-cache-key-function" "^29.2.1"
|
"@jest/create-cache-key-function" "^29.2.1"
|
||||||
"@react-native-community/cli" "10.1.3"
|
"@react-native-community/cli" "10.1.3"
|
||||||
@ -6901,7 +6905,7 @@ react-native@^0.71.2:
|
|||||||
event-target-shim "^5.0.1"
|
event-target-shim "^5.0.1"
|
||||||
invariant "^2.2.4"
|
invariant "^2.2.4"
|
||||||
jest-environment-node "^29.2.1"
|
jest-environment-node "^29.2.1"
|
||||||
jsc-android "^250230.2.1"
|
jsc-android "^250231.0.0"
|
||||||
memoize-one "^5.0.0"
|
memoize-one "^5.0.0"
|
||||||
metro-react-native-babel-transformer "0.73.7"
|
metro-react-native-babel-transformer "0.73.7"
|
||||||
metro-runtime "0.73.7"
|
metro-runtime "0.73.7"
|
||||||
@ -6911,8 +6915,8 @@ react-native@^0.71.2:
|
|||||||
pretty-format "^26.5.2"
|
pretty-format "^26.5.2"
|
||||||
promise "^8.3.0"
|
promise "^8.3.0"
|
||||||
react-devtools-core "^4.26.1"
|
react-devtools-core "^4.26.1"
|
||||||
react-native-codegen "^0.71.3"
|
react-native-codegen "^0.71.5"
|
||||||
react-native-gradle-plugin "^0.71.14"
|
react-native-gradle-plugin "^0.71.15"
|
||||||
react-refresh "^0.4.0"
|
react-refresh "^0.4.0"
|
||||||
react-shallow-renderer "^16.15.0"
|
react-shallow-renderer "^16.15.0"
|
||||||
regenerator-runtime "^0.13.2"
|
regenerator-runtime "^0.13.2"
|
||||||
|
Loading…
Reference in New Issue
Block a user