-
-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Sync Frame Processors #1472
Conversation
src/FrameProcessorPlugins.ts
Outdated
* }) | ||
* ``` | ||
*/ | ||
export function runAsync(func: () => void): void { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[tsc] <6133> reported by reviewdog 🐶
'func' is declared but its value is never read.
@@ -11,3 +12,77 @@ type TFrameProcessorPlugins = Record<string, FrameProcessor>; | |||
* All natively installed Frame Processor Plugins. | |||
*/ | |||
export const FrameProcessorPlugins = global.FrameProcessorPlugins as TFrameProcessorPlugins; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[tsc] <7017> reported by reviewdog 🐶
Element implicitly has an 'any' type because type 'typeof globalThis' has no index signature.
@@ -80,10 +81,26 @@ jsi::Value FrameHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pr | |||
this->assertIsFrameStrong(runtime, name); | |||
return jsi::Value(this->frame->getPlanesCount()); | |||
} | |||
if (name == "refCount") { | |||
return jsi::Value((double) _refCount); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[cpplint] reported by reviewdog 🐶
Using C-style cast. Use static_cast(...) instead [readability/casting] [4]
auto name = propName.utf8(runtime); | ||
|
||
if (name == "refCount") { | ||
_refCount = (size_t) value.asNumber(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[cpplint] reported by reviewdog 🐶
Using C-style cast. Use static_cast<size_t>(...) instead [readability/casting] [4]
src/FrameProcessorPlugins.ts
Outdated
} | ||
|
||
runAtTargetFps.__initData = { | ||
code: runAtTargetFps.asString, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[tsc] <2339> reported by reviewdog 🐶
Property 'asString' does not exist on type 'typeof runAtTargetFps'.
src/FrameProcessorPlugins.ts
Outdated
|
||
runAtTargetFps.__initData = { | ||
code: runAtTargetFps.asString, | ||
location: runAtTargetFps.__location, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[tsc] <2339> reported by reviewdog 🐶
Property '__location' does not exist on type 'typeof runAtTargetFps'.
src/FrameProcessorPlugins.ts
Outdated
'worklet'; | ||
// Increment ref count by one | ||
frame.refCount++; | ||
func.__initData = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[tsc] <2339> reported by reviewdog 🐶
Property '__initData' does not exist on type '() => void'.
src/FrameProcessorPlugins.ts
Outdated
// Increment ref count by one | ||
frame.refCount++; | ||
func.__initData = { | ||
code: func.asString, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[tsc] <2339> reported by reviewdog 🐶
Property 'asString' does not exist on type '() => void'.
src/FrameProcessorPlugins.ts
Outdated
frame.refCount++; | ||
func.__initData = { | ||
code: func.asString, | ||
location: func.__location, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[tsc] <2339> reported by reviewdog 🐶
Property '__location' does not exist on type '() => void'.
src/FrameProcessorPlugins.ts
Outdated
}; | ||
|
||
const fn = Worklets.createRunInContextFn(wrapper, context); | ||
fn.__initData = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[tsc] <2339> reported by reviewdog 🐶
Property '__initData' does not exist on type '() => Promise'.
src/FrameProcessorPlugins.ts
Outdated
|
||
const fn = Worklets.createRunInContextFn(wrapper, context); | ||
fn.__initData = { | ||
code: fn.asString, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[tsc] <2339> reported by reviewdog 🐶
Property 'asString' does not exist on type '() => Promise'.
src/FrameProcessorPlugins.ts
Outdated
const fn = Worklets.createRunInContextFn(wrapper, context); | ||
fn.__initData = { | ||
code: fn.asString, | ||
location: fn.__location, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[tsc] <2339> reported by reviewdog 🐶
Property '__location' does not exist on type '() => Promise'.
src/FrameProcessorPlugins.ts
Outdated
} | ||
|
||
runAsync.__initData = { | ||
code: runAsync.asString, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[tsc] <2339> reported by reviewdog 🐶
Property 'asString' does not exist on type 'typeof runAsync'.
src/FrameProcessorPlugins.ts
Outdated
|
||
runAsync.__initData = { | ||
code: runAsync.asString, | ||
location: runAsync.__location, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[tsc] <2339> reported by reviewdog 🐶
Property '__location' does not exist on type 'typeof runAsync'.
@@ -80,10 +83,30 @@ jsi::Value FrameHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pr | |||
this->assertIsFrameStrong(runtime, name); | |||
return jsi::Value(this->frame->getPlanesCount()); | |||
} | |||
if (name == "refCount") { | |||
if (!_refCount) { | |||
_refCount = std::make_shared<RNWorklet::JsiSharedValue>(jsi::Value(0), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[cpplint] reported by reviewdog 🐶
Add #include for make_shared<> [build/include_what_you_use] [4]
@@ -34,6 +37,7 @@ class JSI_EXPORT FrameHostObject : public jsi::HostObject { | |||
static auto constexpr TAG = "VisionCamera"; | |||
|
|||
void assertIsFrameStrong(jsi::Runtime& runtime, const std::string& accessedPropName) const; // NOLINT(runtime/references) | |||
std::shared_ptr<RNWorklet::JsiSharedValue> _refCount; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[cpplint] reported by reviewdog 🐶
Add #include for shared_ptr<> [build/include_what_you_use] [4]
src/hooks/useFrameProcessor.ts
Outdated
frameProcessor(frame); | ||
|
||
// Potentially delete Frame if we were the last ref (no runAsync) | ||
frame.refCount.value--; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[tsc] <2339> reported by reviewdog 🐶
Property 'refCount' does not exist on type 'Frame'.
src/hooks/useFrameProcessor.ts
Outdated
|
||
// Potentially delete Frame if we were the last ref (no runAsync) | ||
frame.refCount.value--; | ||
if (frame.refCount.value <= 0) frame.close(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[tsc] <2339> reported by reviewdog 🐶
Property 'refCount' does not exist on type 'Frame'.
src/hooks/useFrameProcessor.ts
Outdated
|
||
// Potentially delete Frame if we were the last ref (no runAsync) | ||
frame.refCount.value--; | ||
if (frame.refCount.value <= 0) frame.close(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[tsc] <2339> reported by reviewdog 🐶
Property 'close' does not exist on type 'Frame'.
…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!") }) }) }, []) ```
What
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 givenfps
, 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, userunAtTargetFps(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:
Changes
Tested on
Related issues