react-native-vision-camera
Version:
A powerful, high-performance React Native Camera library.
105 lines (98 loc) • 3.42 kB
JavaScript
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.runAsync = runAsync;
var _WorkletsProxy = require("../dependencies/WorkletsProxy");
var _FrameProcessorsUnavailableError = require("./FrameProcessorsUnavailableError");
var _throwErrorOnJS = require("./throwErrorOnJS");
/**
* A synchronized Shared Value to indicate whether the async context is currently executing
*/
let isAsyncContextBusy;
/**
* Runs the given function on the async context, and sets {@linkcode isAsyncContextBusy} to false after it finished executing.
*/
let runOnAsyncContext;
try {
const Worklets = _WorkletsProxy.WorkletsProxy.Worklets;
isAsyncContextBusy = Worklets.createSharedValue(false);
const asyncContext = Worklets.createContext('VisionCamera.async');
runOnAsyncContext = asyncContext.createRunAsync((frame, func) => {
'worklet';
try {
// Call long-running function
func();
} catch (e) {
// Re-throw error on JS Thread
(0, _throwErrorOnJS.throwErrorOnJS)(e);
} finally {
// Potentially delete Frame if we were the last ref
const internal = frame;
internal.decrementRefCount();
// free up async context again, new calls can be made
isAsyncContextBusy.value = false;
}
});
} catch (e) {
// react-native-worklets-core is not installed!
// Just use dummy implementations that will throw when the user tries to use Frame Processors.
isAsyncContextBusy = {
value: false
};
runOnAsyncContext = () => {
throw new _FrameProcessorsUnavailableError.FrameProcessorsUnavailableError(e);
};
}
/**
* Runs the given {@linkcode func} asynchronously on a separate thread,
* allowing the Frame Processor to continue executing without dropping a Frame.
*
* Only one {@linkcode runAsync} call will execute at the same time,
* so {@linkcode runAsync} is **not parallel**, **but asynchronous**.
*
*
* For example, if your Camera is running at 60 FPS (16ms per frame), and a
* heavy ML face detection Frame Processor Plugin takes 500ms to execute,
* you have two options:
* - Run the plugin normally (synchronously in `useFrameProcessor`)
* but drop a lot of Frames, as we can only run at 2 FPS (500ms per frame)
* - Call the plugin inside {@linkcode runAsync} to allow the Camera to still
* run at 60 FPS, but offload the heavy ML face detection plugin to the
* asynchronous context, where it will run at 2 FPS.
*
* @note {@linkcode runAsync} cannot be used to draw to a Frame in a Skia Frame Processor.
* @param frame The current Frame of the Frame Processor.
* @param func The function to execute.
* @worklet
* @example
*
* ```ts
* const frameProcessor = useFrameProcessor((frame) => {
* 'worklet'
* console.log('New Frame arrived!')
*
* runAsync(frame, () => {
* 'worklet'
* const faces = detectFaces(frame)
* const face = faces[0]
* console.log(`Detected a new face: ${face}`)
* })
* })
* ```
*/
function runAsync(frame, func) {
'worklet';
if (isAsyncContextBusy.value) {
// async context is currently busy, we cannot schedule new work in time.
// drop this frame/runAsync call.
return;
}
// Increment ref count by one
const internal = frame;
internal.incrementRefCount();
isAsyncContextBusy.value = true;
// Call in separate background context
runOnAsyncContext(frame, func);
}
//# sourceMappingURL=runAsync.js.map
;