chore: Move everything into package/ (#1745)
* Move everything into package * Remove .DS_Store * Move scripts and eslintrc to package * Create CODE_OF_CONDUCT.md * fix some links * Update all links (I think) * Update generated docs * Update notice-yarn-changes.yml * Update validate-android.yml * Update validate-cpp.yml * Delete notice-yarn-changes.yml * Update validate-cpp.yml * Update validate-cpp.yml * Update validate-js.yml * Update validate-cpp.yml * Update validate-cpp.yml * wrong c++ style * Revert "wrong c++ style" This reverts commit 55a3575589c6f13f8b05134d83384f55e0601ab2.
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
//
|
||||
// Created by Marc on 21.07.2023.
|
||||
//
|
||||
|
||||
#include "JFrame.h"
|
||||
|
||||
#include <fbjni/ByteBuffer.h>
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <jni.h>
|
||||
|
||||
namespace vision {
|
||||
|
||||
using namespace facebook;
|
||||
using namespace jni;
|
||||
|
||||
int JFrame::getWidth() const {
|
||||
static const auto getWidthMethod = getClass()->getMethod<jint()>("getWidth");
|
||||
return getWidthMethod(self());
|
||||
}
|
||||
|
||||
int JFrame::getHeight() const {
|
||||
static const auto getWidthMethod = getClass()->getMethod<jint()>("getHeight");
|
||||
return getWidthMethod(self());
|
||||
}
|
||||
|
||||
bool JFrame::getIsValid() const {
|
||||
static const auto getIsValidMethod = getClass()->getMethod<jboolean()>("getIsValid");
|
||||
return getIsValidMethod(self());
|
||||
}
|
||||
|
||||
bool JFrame::getIsMirrored() const {
|
||||
static const auto getIsMirroredMethod = getClass()->getMethod<jboolean()>("getIsMirrored");
|
||||
return getIsMirroredMethod(self());
|
||||
}
|
||||
|
||||
jlong JFrame::getTimestamp() const {
|
||||
static const auto getTimestampMethod = getClass()->getMethod<jlong()>("getTimestamp");
|
||||
return getTimestampMethod(self());
|
||||
}
|
||||
|
||||
local_ref<JString> JFrame::getOrientation() const {
|
||||
static const auto getOrientationMethod = getClass()->getMethod<JString()>("getOrientation");
|
||||
return getOrientationMethod(self());
|
||||
}
|
||||
|
||||
local_ref<JString> JFrame::getPixelFormat() const {
|
||||
static const auto getPixelFormatMethod = getClass()->getMethod<JString()>("getPixelFormat");
|
||||
return getPixelFormatMethod(self());
|
||||
}
|
||||
|
||||
int JFrame::getPlanesCount() const {
|
||||
static const auto getPlanesCountMethod = getClass()->getMethod<jint()>("getPlanesCount");
|
||||
return getPlanesCountMethod(self());
|
||||
}
|
||||
|
||||
int JFrame::getBytesPerRow() const {
|
||||
static const auto getBytesPerRowMethod = getClass()->getMethod<jint()>("getBytesPerRow");
|
||||
return getBytesPerRowMethod(self());
|
||||
}
|
||||
|
||||
local_ref<JByteBuffer> JFrame::toByteBuffer() const {
|
||||
static const auto toByteBufferMethod = getClass()->getMethod<JByteBuffer()>("toByteBuffer");
|
||||
return toByteBufferMethod(self());
|
||||
}
|
||||
|
||||
void JFrame::incrementRefCount() {
|
||||
static const auto incrementRefCountMethod = getClass()->getMethod<void()>("incrementRefCount");
|
||||
incrementRefCountMethod(self());
|
||||
}
|
||||
|
||||
void JFrame::decrementRefCount() {
|
||||
static const auto decrementRefCountMethod = getClass()->getMethod<void()>("decrementRefCount");
|
||||
decrementRefCountMethod(self());
|
||||
}
|
||||
|
||||
void JFrame::close() {
|
||||
static const auto closeMethod = getClass()->getMethod<void()>("close");
|
||||
closeMethod(self());
|
||||
}
|
||||
|
||||
} // namespace vision
|
||||
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// Created by Marc on 21.07.2023.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <fbjni/ByteBuffer.h>
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <jni.h>
|
||||
|
||||
namespace vision {
|
||||
|
||||
using namespace facebook;
|
||||
using namespace jni;
|
||||
|
||||
struct JFrame : public JavaClass<JFrame> {
|
||||
static constexpr auto kJavaDescriptor = "Lcom/mrousavy/camera/frameprocessor/Frame;";
|
||||
|
||||
public:
|
||||
int getWidth() const;
|
||||
int getHeight() const;
|
||||
bool getIsValid() const;
|
||||
bool getIsMirrored() const;
|
||||
int getPlanesCount() const;
|
||||
int getBytesPerRow() const;
|
||||
jlong getTimestamp() const;
|
||||
local_ref<JString> getOrientation() const;
|
||||
local_ref<JString> getPixelFormat() const;
|
||||
local_ref<JByteBuffer> toByteBuffer() const;
|
||||
void incrementRefCount();
|
||||
void decrementRefCount();
|
||||
void close();
|
||||
};
|
||||
|
||||
} // namespace vision
|
||||
@@ -0,0 +1,70 @@
|
||||
//
|
||||
// Created by Marc Rousavy on 29.09.21.
|
||||
//
|
||||
|
||||
#if VISION_CAMERA_ENABLE_FRAME_PROCESSORS
|
||||
|
||||
#include "JFrameProcessor.h"
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <jni.h>
|
||||
|
||||
#include "JFrame.h"
|
||||
#include <utility>
|
||||
|
||||
namespace vision {
|
||||
|
||||
using namespace facebook;
|
||||
using namespace jni;
|
||||
|
||||
void JFrameProcessor::registerNatives() {
|
||||
registerHybrid({makeNativeMethod("call", JFrameProcessor::call)});
|
||||
}
|
||||
|
||||
using TSelf = jni::local_ref<JFrameProcessor::javaobject>;
|
||||
|
||||
JFrameProcessor::JFrameProcessor(std::shared_ptr<RNWorklet::JsiWorklet> worklet,
|
||||
std::shared_ptr<RNWorklet::JsiWorkletContext> context) {
|
||||
_workletContext = std::move(context);
|
||||
_workletInvoker = std::make_shared<RNWorklet::WorkletInvoker>(worklet);
|
||||
}
|
||||
|
||||
TSelf JFrameProcessor::create(const std::shared_ptr<RNWorklet::JsiWorklet>& worklet,
|
||||
const std::shared_ptr<RNWorklet::JsiWorkletContext>& context) {
|
||||
return JFrameProcessor::newObjectCxxArgs(worklet, context);
|
||||
}
|
||||
|
||||
void JFrameProcessor::callWithFrameHostObject(
|
||||
const std::shared_ptr<FrameHostObject>& frameHostObject) const {
|
||||
// Call the Frame Processor on the Worklet Runtime
|
||||
jsi::Runtime& runtime = _workletContext->getWorkletRuntime();
|
||||
|
||||
try {
|
||||
// Wrap HostObject as JSI Value
|
||||
auto argument = jsi::Object::createFromHostObject(runtime, frameHostObject);
|
||||
jsi::Value jsValue(std::move(argument));
|
||||
|
||||
// Call the Worklet with the Frame JS Host Object as an argument
|
||||
_workletInvoker->call(runtime, jsi::Value::undefined(), &jsValue, 1);
|
||||
} catch (jsi::JSError& jsError) {
|
||||
// JS Error occured, print it to console.
|
||||
const std::string& message = jsError.getMessage();
|
||||
|
||||
_workletContext->invokeOnJsThread([message](jsi::Runtime& jsRuntime) {
|
||||
auto logFn = jsRuntime.global()
|
||||
.getPropertyAsObject(jsRuntime, "console")
|
||||
.getPropertyAsFunction(jsRuntime, "error");
|
||||
logFn.call(jsRuntime, jsi::String::createFromUtf8(
|
||||
jsRuntime, "Frame Processor threw an error: " + message));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void JFrameProcessor::call(jni::alias_ref<JFrame::javaobject> frame) {
|
||||
// Create the Frame Host Object wrapping the internal Frame
|
||||
auto frameHostObject = std::make_shared<FrameHostObject>(frame);
|
||||
callWithFrameHostObject(frameHostObject);
|
||||
}
|
||||
|
||||
} // namespace vision
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// Created by Marc Rousavy on 29.09.21
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#if VISION_CAMERA_ENABLE_FRAME_PROCESSORS
|
||||
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <jni.h>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <react-native-worklets-core/WKTJsiHostObject.h>
|
||||
#include <react-native-worklets-core/WKTJsiWorklet.h>
|
||||
|
||||
#include "FrameHostObject.h"
|
||||
#include "JFrame.h"
|
||||
|
||||
namespace vision {
|
||||
|
||||
using namespace facebook;
|
||||
|
||||
struct JFrameProcessor : public jni::HybridClass<JFrameProcessor> {
|
||||
public:
|
||||
static auto constexpr kJavaDescriptor = "Lcom/mrousavy/camera/frameprocessor/FrameProcessor;";
|
||||
static void registerNatives();
|
||||
static jni::local_ref<JFrameProcessor::javaobject>
|
||||
create(const std::shared_ptr<RNWorklet::JsiWorklet>& worklet,
|
||||
const std::shared_ptr<RNWorklet::JsiWorkletContext>& context);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Call the JS Frame Processor.
|
||||
*/
|
||||
void call(alias_ref<JFrame::javaobject> frame);
|
||||
|
||||
private:
|
||||
// Private constructor. Use `create(..)` to create new instances.
|
||||
explicit JFrameProcessor(std::shared_ptr<RNWorklet::JsiWorklet> worklet,
|
||||
std::shared_ptr<RNWorklet::JsiWorkletContext> context);
|
||||
|
||||
private:
|
||||
void callWithFrameHostObject(const std::shared_ptr<FrameHostObject>& frameHostObject) const;
|
||||
|
||||
private:
|
||||
friend HybridBase;
|
||||
std::shared_ptr<RNWorklet::WorkletInvoker> _workletInvoker;
|
||||
std::shared_ptr<RNWorklet::JsiWorkletContext> _workletContext;
|
||||
};
|
||||
|
||||
} // namespace vision
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,26 @@
|
||||
//
|
||||
// Created by Marc Rousavy on 29.09.21.
|
||||
//
|
||||
|
||||
#include "JFrameProcessorPlugin.h"
|
||||
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <jni.h>
|
||||
|
||||
namespace vision {
|
||||
|
||||
using namespace facebook;
|
||||
using namespace jni;
|
||||
|
||||
using TCallback = jobject(alias_ref<JFrame::javaobject>, alias_ref<JMap<jstring, jobject>> params);
|
||||
|
||||
local_ref<jobject>
|
||||
JFrameProcessorPlugin::callback(const alias_ref<JFrame::javaobject>& frame,
|
||||
const alias_ref<JMap<jstring, jobject>>& params) const {
|
||||
auto callbackMethod = getClass()->getMethod<TCallback>("callback");
|
||||
|
||||
auto result = callbackMethod(self(), frame, params);
|
||||
return make_local(result);
|
||||
}
|
||||
|
||||
} // namespace vision
|
||||
@@ -0,0 +1,30 @@
|
||||
//
|
||||
// Created by Marc Rousavy on 29.09.21
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <jni.h>
|
||||
#include <string>
|
||||
|
||||
#include "JFrame.h"
|
||||
|
||||
namespace vision {
|
||||
|
||||
using namespace facebook;
|
||||
using namespace jni;
|
||||
|
||||
struct JFrameProcessorPlugin : public JavaClass<JFrameProcessorPlugin> {
|
||||
static constexpr auto kJavaDescriptor =
|
||||
"Lcom/mrousavy/camera/frameprocessor/FrameProcessorPlugin;";
|
||||
|
||||
public:
|
||||
/**
|
||||
* Call the plugin.
|
||||
*/
|
||||
local_ref<jobject> callback(const alias_ref<JFrame::javaobject>& frame,
|
||||
const alias_ref<JMap<jstring, jobject>>& params) const;
|
||||
};
|
||||
|
||||
} // namespace vision
|
||||
@@ -0,0 +1,117 @@
|
||||
//
|
||||
// Created by Marc Rousavy on 21.07.23.
|
||||
//
|
||||
|
||||
#include "JVisionCameraProxy.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <jsi/jsi.h>
|
||||
|
||||
#include "FrameProcessorPluginHostObject.h"
|
||||
#include "JSITypedArray.h"
|
||||
|
||||
#if VISION_CAMERA_ENABLE_FRAME_PROCESSORS
|
||||
#include <react-native-worklets-core/WKTJsiWorklet.h>
|
||||
#include <react-native-worklets-core/WKTJsiWorkletContext.h>
|
||||
#endif
|
||||
|
||||
namespace vision {
|
||||
|
||||
using TSelf = local_ref<HybridClass<JVisionCameraProxy>::jhybriddata>;
|
||||
using TJSCallInvokerHolder = jni::alias_ref<facebook::react::CallInvokerHolder::javaobject>;
|
||||
using TScheduler = jni::alias_ref<JVisionCameraScheduler::javaobject>;
|
||||
using TOptions = jni::local_ref<JMap<jstring, jobject>>;
|
||||
|
||||
JVisionCameraProxy::JVisionCameraProxy(
|
||||
const jni::alias_ref<JVisionCameraProxy::jhybridobject>& javaThis, jsi::Runtime* runtime,
|
||||
const std::shared_ptr<facebook::react::CallInvoker>& callInvoker,
|
||||
const jni::global_ref<JVisionCameraScheduler::javaobject>& scheduler) {
|
||||
_javaPart = make_global(javaThis);
|
||||
_runtime = runtime;
|
||||
|
||||
#if VISION_CAMERA_ENABLE_FRAME_PROCESSORS
|
||||
__android_log_write(ANDROID_LOG_INFO, TAG, "Creating Worklet Context...");
|
||||
|
||||
auto runOnJS = [callInvoker](std::function<void()>&& f) {
|
||||
// Run on React JS Runtime
|
||||
callInvoker->invokeAsync(std::move(f));
|
||||
};
|
||||
auto runOnWorklet = [scheduler](std::function<void()>&& f) {
|
||||
// Run on Frame Processor Worklet Runtime
|
||||
scheduler->cthis()->dispatchAsync([f = std::move(f)]() { f(); });
|
||||
};
|
||||
_workletContext = std::make_shared<RNWorklet::JsiWorkletContext>("VisionCamera", runtime, runOnJS,
|
||||
runOnWorklet);
|
||||
__android_log_write(ANDROID_LOG_INFO, TAG, "Worklet Context created!");
|
||||
#else
|
||||
__android_log_write(ANDROID_LOG_INFO, TAG, "Frame Processors are disabled!");
|
||||
#endif
|
||||
}
|
||||
|
||||
JVisionCameraProxy::~JVisionCameraProxy() {
|
||||
#if VISION_CAMERA_ENABLE_FRAME_PROCESSORS
|
||||
__android_log_write(ANDROID_LOG_INFO, TAG, "Destroying Context...");
|
||||
// Destroy ArrayBuffer cache for both the JS and the Worklet Runtime.
|
||||
invalidateArrayBufferCache(*_workletContext->getJsRuntime());
|
||||
invalidateArrayBufferCache(_workletContext->getWorkletRuntime());
|
||||
#endif
|
||||
}
|
||||
|
||||
void JVisionCameraProxy::setFrameProcessor(int viewTag, jsi::Runtime& runtime,
|
||||
const jsi::Object& frameProcessorObject) {
|
||||
#if VISION_CAMERA_ENABLE_FRAME_PROCESSORS
|
||||
auto frameProcessorType =
|
||||
frameProcessorObject.getProperty(runtime, "type").asString(runtime).utf8(runtime);
|
||||
auto worklet = std::make_shared<RNWorklet::JsiWorklet>(
|
||||
runtime, frameProcessorObject.getProperty(runtime, "frameProcessor"));
|
||||
|
||||
jni::local_ref<JFrameProcessor::javaobject> frameProcessor;
|
||||
if (frameProcessorType == "frame-processor") {
|
||||
frameProcessor = JFrameProcessor::create(worklet, _workletContext);
|
||||
} else {
|
||||
throw std::runtime_error("Unknown FrameProcessor.type passed! Received: " + frameProcessorType);
|
||||
}
|
||||
|
||||
auto setFrameProcessorMethod =
|
||||
javaClassLocal()->getMethod<void(int, alias_ref<JFrameProcessor::javaobject>)>(
|
||||
"setFrameProcessor");
|
||||
setFrameProcessorMethod(_javaPart, viewTag, frameProcessor);
|
||||
#else
|
||||
throw std::runtime_error("system/frame-processors-unavailable: Frame Processors are disabled!");
|
||||
#endif
|
||||
}
|
||||
|
||||
void JVisionCameraProxy::removeFrameProcessor(int viewTag) {
|
||||
auto removeFrameProcessorMethod = javaClassLocal()->getMethod<void(int)>("removeFrameProcessor");
|
||||
removeFrameProcessorMethod(_javaPart, viewTag);
|
||||
}
|
||||
|
||||
local_ref<JFrameProcessorPlugin::javaobject>
|
||||
JVisionCameraProxy::getFrameProcessorPlugin(const std::string& name, TOptions options) {
|
||||
auto getFrameProcessorPluginMethod =
|
||||
javaClassLocal()->getMethod<JFrameProcessorPlugin(local_ref<jstring>, TOptions)>(
|
||||
"getFrameProcessorPlugin");
|
||||
return getFrameProcessorPluginMethod(_javaPart, make_jstring(name), std::move(options));
|
||||
}
|
||||
|
||||
void JVisionCameraProxy::registerNatives() {
|
||||
registerHybrid({makeNativeMethod("initHybrid", JVisionCameraProxy::initHybrid)});
|
||||
}
|
||||
|
||||
TSelf JVisionCameraProxy::initHybrid(alias_ref<jhybridobject> jThis, jlong jsRuntimePointer,
|
||||
TJSCallInvokerHolder jsCallInvokerHolder,
|
||||
const TScheduler& scheduler) {
|
||||
__android_log_write(ANDROID_LOG_INFO, TAG, "Initializing VisionCameraProxy...");
|
||||
|
||||
// cast from JNI hybrid objects to C++ instances
|
||||
auto jsRuntime = reinterpret_cast<jsi::Runtime*>(jsRuntimePointer);
|
||||
auto jsCallInvoker = jsCallInvokerHolder->cthis()->getCallInvoker();
|
||||
auto sharedScheduler = make_global(scheduler);
|
||||
|
||||
return makeCxxInstance(jThis, jsRuntime, jsCallInvoker, sharedScheduler);
|
||||
}
|
||||
|
||||
} // namespace vision
|
||||
@@ -0,0 +1,61 @@
|
||||
//
|
||||
// Created by Marc Rousavy on 21.07.23.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ReactCommon/CallInvokerHolder.h>
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <jsi/jsi.h>
|
||||
|
||||
#include "JFrameProcessor.h"
|
||||
#include "JFrameProcessorPlugin.h"
|
||||
#include "JVisionCameraScheduler.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#if VISION_CAMERA_ENABLE_FRAME_PROCESSORS
|
||||
#include <react-native-worklets-core/WKTJsiWorkletContext.h>
|
||||
#endif
|
||||
|
||||
namespace vision {
|
||||
|
||||
using namespace facebook;
|
||||
|
||||
class JVisionCameraProxy : public jni::HybridClass<JVisionCameraProxy> {
|
||||
public:
|
||||
~JVisionCameraProxy();
|
||||
static void registerNatives();
|
||||
|
||||
void setFrameProcessor(int viewTag, jsi::Runtime& runtime, const jsi::Object& frameProcessor);
|
||||
void removeFrameProcessor(int viewTag);
|
||||
jni::local_ref<JFrameProcessorPlugin::javaobject>
|
||||
getFrameProcessorPlugin(const std::string& name, jni::local_ref<JMap<jstring, jobject>> options);
|
||||
|
||||
jsi::Runtime* getJSRuntime() {
|
||||
return _runtime;
|
||||
}
|
||||
|
||||
private:
|
||||
friend HybridBase;
|
||||
jni::global_ref<JVisionCameraProxy::javaobject> _javaPart;
|
||||
jsi::Runtime* _runtime;
|
||||
#if VISION_CAMERA_ENABLE_FRAME_PROCESSORS
|
||||
std::shared_ptr<RNWorklet::JsiWorkletContext> _workletContext;
|
||||
#endif
|
||||
|
||||
static auto constexpr TAG = "VisionCameraProxy";
|
||||
static auto constexpr kJavaDescriptor = "Lcom/mrousavy/camera/frameprocessor/VisionCameraProxy;";
|
||||
|
||||
explicit JVisionCameraProxy(const jni::alias_ref<JVisionCameraProxy::jhybridobject>& javaThis,
|
||||
jsi::Runtime* jsRuntime,
|
||||
const std::shared_ptr<facebook::react::CallInvoker>& jsCallInvoker,
|
||||
const jni::global_ref<JVisionCameraScheduler::javaobject>& scheduler);
|
||||
static jni::local_ref<jhybriddata>
|
||||
initHybrid(jni::alias_ref<jhybridobject> javaThis, jlong jsRuntimePointer,
|
||||
jni::alias_ref<facebook::react::CallInvokerHolder::javaobject> jsCallInvokerHolder,
|
||||
const jni::alias_ref<JVisionCameraScheduler::javaobject>& scheduler);
|
||||
};
|
||||
|
||||
} // namespace vision
|
||||
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// Created by Marc Rousavy on 25.07.21.
|
||||
//
|
||||
|
||||
#include "JVisionCameraScheduler.h"
|
||||
#include <fbjni/fbjni.h>
|
||||
|
||||
namespace vision {
|
||||
|
||||
using namespace facebook;
|
||||
using TSelf = jni::local_ref<JVisionCameraScheduler::jhybriddata>;
|
||||
|
||||
TSelf JVisionCameraScheduler::initHybrid(jni::alias_ref<jhybridobject> jThis) {
|
||||
return makeCxxInstance(jThis);
|
||||
}
|
||||
|
||||
void JVisionCameraScheduler::dispatchAsync(const std::function<void()>& job) {
|
||||
// 1. add job to queue
|
||||
_jobs.push(job);
|
||||
scheduleTrigger();
|
||||
}
|
||||
|
||||
void JVisionCameraScheduler::scheduleTrigger() {
|
||||
// 2. schedule `triggerUI` to be called on the java thread
|
||||
static auto method = _javaPart->getClass()->getMethod<void()>("scheduleTrigger");
|
||||
method(_javaPart.get());
|
||||
}
|
||||
|
||||
void JVisionCameraScheduler::trigger() {
|
||||
std::unique_lock<std::mutex> lock(_mutex);
|
||||
// 3. call job we enqueued in step 1.
|
||||
auto job = _jobs.front();
|
||||
job();
|
||||
_jobs.pop();
|
||||
}
|
||||
|
||||
void JVisionCameraScheduler::registerNatives() {
|
||||
registerHybrid({
|
||||
makeNativeMethod("initHybrid", JVisionCameraScheduler::initHybrid),
|
||||
makeNativeMethod("trigger", JVisionCameraScheduler::trigger),
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace vision
|
||||
@@ -0,0 +1,51 @@
|
||||
//
|
||||
// Created by Marc Rousavy on 25.07.21.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <jni.h>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
|
||||
namespace vision {
|
||||
|
||||
using namespace facebook;
|
||||
|
||||
/**
|
||||
* A Scheduler that runs methods on the Frame Processor Thread (which is a Java Thread).
|
||||
* In order to call something on the Java Frame Processor Thread, you have to:
|
||||
*
|
||||
* 1. Call `dispatchAsync(..)` with the given C++ Method.
|
||||
* 2. Internally, `scheduleTrigger()` will get called, which is a Java Method.
|
||||
* 3. The `scheduleTrigger()` Java Method will switch to the Frame Processor Java Thread and call
|
||||
* `trigger()` on there
|
||||
* 4. `trigger()` is a C++ function here that just calls the passed C++ Method from step 1.
|
||||
*/
|
||||
class JVisionCameraScheduler : public jni::HybridClass<JVisionCameraScheduler> {
|
||||
public:
|
||||
static auto constexpr kJavaDescriptor =
|
||||
"Lcom/mrousavy/camera/frameprocessor/VisionCameraScheduler;";
|
||||
static jni::local_ref<jhybriddata> initHybrid(jni::alias_ref<jhybridobject> jThis);
|
||||
static void registerNatives();
|
||||
|
||||
// schedules the given job to be run on the VisionCamera FP Thread at some future point in time
|
||||
void dispatchAsync(const std::function<void()>& job);
|
||||
|
||||
private:
|
||||
friend HybridBase;
|
||||
jni::global_ref<JVisionCameraScheduler::javaobject> _javaPart;
|
||||
std::queue<std::function<void()>> _jobs;
|
||||
std::mutex _mutex;
|
||||
|
||||
explicit JVisionCameraScheduler(jni::alias_ref<JVisionCameraScheduler::jhybridobject> jThis)
|
||||
: _javaPart(jni::make_global(jThis)) {}
|
||||
|
||||
// Schedules a call to `trigger` on the VisionCamera FP Thread
|
||||
void scheduleTrigger();
|
||||
// Calls the latest job in the job queue
|
||||
void trigger();
|
||||
};
|
||||
|
||||
} // namespace vision
|
||||
Reference in New Issue
Block a user