diff --git a/android/CMakeLists.txt b/android/CMakeLists.txt index adf597b..1fb1ad1 100644 --- a/android/CMakeLists.txt +++ b/android/CMakeLists.txt @@ -15,12 +15,12 @@ add_library( SHARED src/main/cpp/VisionCamera.cpp src/main/cpp/JSIJNIConversion.cpp + src/main/cpp/FrameHostObject.cpp src/main/cpp/FrameProcessorRuntimeManager.cpp - src/main/cpp/FrameProcessorPlugin.cpp src/main/cpp/CameraView.cpp src/main/cpp/VisionCameraScheduler.cpp + src/main/cpp/java-bindings/JFrameProcessorPlugin.cpp src/main/cpp/java-bindings/JImageProxy.cpp - src/main/cpp/java-bindings/JImageProxyHostObject.cpp src/main/cpp/java-bindings/JHashMap.cpp ) diff --git a/android/src/main/cpp/CameraView.cpp b/android/src/main/cpp/CameraView.cpp index 0e5b04c..bb6733c 100644 --- a/android/src/main/cpp/CameraView.cpp +++ b/android/src/main/cpp/CameraView.cpp @@ -15,7 +15,7 @@ namespace vision { using namespace facebook; using namespace jni; -using TSelf = local_ref::jhybriddata>; +using TSelf = local_ref; TSelf CameraView::initHybrid(alias_ref jThis) { return makeCxxInstance(jThis); @@ -42,7 +42,7 @@ void CameraView::frameProcessorCallback(const alias_ref } } -void CameraView::setFrameProcessor(const FrameProcessor&& frameProcessor) { +void CameraView::setFrameProcessor(const TFrameProcessor&& frameProcessor) { frameProcessor_ = frameProcessor; } diff --git a/android/src/main/cpp/CameraView.h b/android/src/main/cpp/CameraView.h index d1f04cf..a1ca070 100644 --- a/android/src/main/cpp/CameraView.h +++ b/android/src/main/cpp/CameraView.h @@ -14,7 +14,7 @@ namespace vision { using namespace facebook; -using FrameProcessor = std::function)>; +using TFrameProcessor = std::function)>; class CameraView : public jni::HybridClass { public: @@ -24,13 +24,13 @@ class CameraView : public jni::HybridClass { static void registerNatives(); // TODO: Use template<> to avoid heap allocation for std::function<> - void setFrameProcessor(const FrameProcessor&& frameProcessor); + void setFrameProcessor(const TFrameProcessor&& frameProcessor); void unsetFrameProcessor(); private: friend HybridBase; jni::global_ref javaPart_; - FrameProcessor frameProcessor_; + TFrameProcessor frameProcessor_; void frameProcessorCallback(const jni::alias_ref& frame); diff --git a/android/src/main/cpp/java-bindings/JImageProxyHostObject.cpp b/android/src/main/cpp/FrameHostObject.cpp similarity index 85% rename from android/src/main/cpp/java-bindings/JImageProxyHostObject.cpp rename to android/src/main/cpp/FrameHostObject.cpp index cb1875e..7a003cf 100644 --- a/android/src/main/cpp/java-bindings/JImageProxyHostObject.cpp +++ b/android/src/main/cpp/FrameHostObject.cpp @@ -2,7 +2,7 @@ // Created by Marc on 19/06/2021. // -#include "JImageProxyHostObject.h" +#include "FrameHostObject.h" #include #include #include @@ -13,9 +13,9 @@ namespace vision { using namespace facebook; -JImageProxyHostObject::JImageProxyHostObject(jni::alias_ref image): frame(make_local(image)) { } +FrameHostObject::FrameHostObject(jni::alias_ref image): frame(make_local(image)) { } -JImageProxyHostObject::~JImageProxyHostObject() { +FrameHostObject::~FrameHostObject() { // Hermes' Garbage Collector (Hades GC) calls destructors on a separate Thread // which might not be attached to JNI. Ensure that we use the JNI class loader when // deallocating the `frame` HybridClass, because otherwise JNI cannot call the Java @@ -23,7 +23,7 @@ JImageProxyHostObject::~JImageProxyHostObject() { jni::ThreadScope::WithClassLoader([=] { frame.reset(); }); } -std::vector JImageProxyHostObject::getPropertyNames(jsi::Runtime& rt) { +std::vector FrameHostObject::getPropertyNames(jsi::Runtime& rt) { std::vector result; result.push_back(jsi::PropNameID::forUtf8(rt, std::string("toString"))); result.push_back(jsi::PropNameID::forUtf8(rt, std::string("isValid"))); @@ -35,7 +35,7 @@ std::vector JImageProxyHostObject::getPropertyNames(jsi::Runtim return result; } -jsi::Value JImageProxyHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& propNameId) { +jsi::Value FrameHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& propNameId) { auto name = propNameId.utf8(runtime); if (name == "toString") { @@ -84,14 +84,14 @@ jsi::Value JImageProxyHostObject::get(jsi::Runtime& runtime, const jsi::PropName return jsi::Value::undefined(); } -void JImageProxyHostObject::assertIsFrameStrong(jsi::Runtime& runtime, const std::string& accessedPropName) const { +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 JImageProxyHostObject::close() { +void FrameHostObject::close() { if (this->frame) { this->frame->close(); } diff --git a/android/src/main/cpp/java-bindings/JImageProxyHostObject.h b/android/src/main/cpp/FrameHostObject.h similarity index 76% rename from android/src/main/cpp/java-bindings/JImageProxyHostObject.h rename to android/src/main/cpp/FrameHostObject.h index bb9d909..896e870 100644 --- a/android/src/main/cpp/java-bindings/JImageProxyHostObject.h +++ b/android/src/main/cpp/FrameHostObject.h @@ -10,16 +10,16 @@ #include #include -#include "JImageProxy.h" +#include "java-bindings/JImageProxy.h" namespace vision { using namespace facebook; -class JSI_EXPORT JImageProxyHostObject : public jsi::HostObject { +class JSI_EXPORT FrameHostObject : public jsi::HostObject { public: - explicit JImageProxyHostObject(jni::alias_ref image); - ~JImageProxyHostObject(); + explicit FrameHostObject(jni::alias_ref image); + ~FrameHostObject(); public: jsi::Value get(jsi::Runtime &, const jsi::PropNameID &name) override; diff --git a/android/src/main/cpp/FrameProcessorPlugin.cpp b/android/src/main/cpp/FrameProcessorPlugin.cpp deleted file mode 100644 index 5cb6306..0000000 --- a/android/src/main/cpp/FrameProcessorPlugin.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// -// Created by Marc Rousavy on 22.06.21. -// - -#include "FrameProcessorPlugin.h" -#include - -namespace vision { - -using namespace facebook; -using namespace jni; - -using TSelf = local_ref::jhybriddata>; -using TFrameProcessorPlugin = jobject(alias_ref, alias_ref>); - -TSelf vision::FrameProcessorPlugin::initHybrid(alias_ref jThis, const std::string& name) { - return makeCxxInstance(jThis, name); -} - -void FrameProcessorPlugin::registerNatives() { - registerHybrid({ - makeNativeMethod("initHybrid", - FrameProcessorPlugin::initHybrid), - }); -} - -local_ref FrameProcessorPlugin::callback(alias_ref image, alias_ref> params) { - auto func = javaPart_->getClass()->getMethod("callback"); - - auto result = func(javaPart_.get(), image, params); - return make_local(result); -} - -std::string FrameProcessorPlugin::getName() { - return name; -} - -} // namespace vision diff --git a/android/src/main/cpp/FrameProcessorPlugin.h b/android/src/main/cpp/FrameProcessorPlugin.h deleted file mode 100644 index fe440bc..0000000 --- a/android/src/main/cpp/FrameProcessorPlugin.h +++ /dev/null @@ -1,39 +0,0 @@ -// -// Created by Marc Rousavy on 22.06.21. -// - -#pragma once - -#include -#include -#include - -#include "java-bindings/JImageProxy.h" - -namespace vision { - -using namespace facebook; -using namespace jni; - -class FrameProcessorPlugin: public HybridClass { - public: - static auto constexpr kJavaDescriptor = "Lcom/mrousavy/camera/frameprocessor/FrameProcessorPlugin;"; - static jni::local_ref initHybrid(jni::alias_ref jThis, - const std::string& name); - static void registerNatives(); - - local_ref callback(alias_ref image, alias_ref> params); - std::string getName(); - - private: - friend HybridBase; - jni::global_ref javaPart_; - std::string name; - - FrameProcessorPlugin(alias_ref jThis, - std::string name): javaPart_(make_global(jThis)), - name(name) - {} -}; - -} // namespace vision diff --git a/android/src/main/cpp/FrameProcessorRuntimeManager.cpp b/android/src/main/cpp/FrameProcessorRuntimeManager.cpp index b76a465..ebbf3ef 100644 --- a/android/src/main/cpp/FrameProcessorRuntimeManager.cpp +++ b/android/src/main/cpp/FrameProcessorRuntimeManager.cpp @@ -15,17 +15,18 @@ #include "MakeJSIRuntime.h" #include "CameraView.h" -#include "java-bindings/JImageProxy.h" -#include "java-bindings/JImageProxyHostObject.h" +#include "FrameHostObject.h" #include "JSIJNIConversion.h" #include "VisionCameraScheduler.h" +#include "java-bindings/JImageProxy.h" +#include "java-bindings/JFrameProcessorPlugin.h" namespace vision { // type aliases using TSelf = local_ref::jhybriddata>; -using JSCallInvokerHolder = jni::alias_ref; -using AndroidScheduler = jni::alias_ref; +using TJSCallInvokerHolder = jni::alias_ref; +using TAndroidScheduler = jni::alias_ref; // JNI binding void vision::FrameProcessorRuntimeManager::registerNatives() { @@ -44,18 +45,19 @@ void vision::FrameProcessorRuntimeManager::registerNatives() { // JNI init TSelf vision::FrameProcessorRuntimeManager::initHybrid( alias_ref jThis, - jlong jsContext, - JSCallInvokerHolder jsCallInvokerHolder, - AndroidScheduler androidScheduler) { + jlong jsRuntimePointer, + TJSCallInvokerHolder jsCallInvokerHolder, + TAndroidScheduler androidScheduler) { __android_log_write(ANDROID_LOG_INFO, TAG, "Initializing FrameProcessorRuntimeManager..."); // cast from JNI hybrid objects to C++ instances + auto runtime = reinterpret_cast(jsRuntimePointer); auto jsCallInvoker = jsCallInvokerHolder->cthis()->getCallInvoker(); auto scheduler = std::shared_ptr(androidScheduler->cthis()); scheduler->setJSCallInvoker(jsCallInvoker); - return makeCxxInstance(jThis, reinterpret_cast(jsContext), jsCallInvoker, scheduler); + return makeCxxInstance(jThis, runtime, jsCallInvoker, scheduler); } void vision::FrameProcessorRuntimeManager::initializeRuntime() { @@ -78,10 +80,10 @@ void vision::FrameProcessorRuntimeManager::initializeRuntime() { "Initialized Vision JS-Runtime!"); } -CameraView* FrameProcessorRuntimeManager::findCameraViewById(int viewId) { - static const auto func = javaPart_->getClass()->getMethod("findCameraViewById"); - auto result = func(javaPart_.get(), viewId); - return result->cthis(); +global_ref FrameProcessorRuntimeManager::findCameraViewById(int viewId) { + static const auto findCameraViewByIdMethod = javaPart_->getClass()->getMethod("findCameraViewById"); + auto weakCameraView = findCameraViewByIdMethod(javaPart_.get(), viewId); + return make_global(weakCameraView); } void FrameProcessorRuntimeManager::logErrorToJS(const std::string& message) { @@ -103,6 +105,63 @@ void FrameProcessorRuntimeManager::logErrorToJS(const std::string& message) { }); } +void FrameProcessorRuntimeManager::setFrameProcessor(jsi::Runtime& runtime, + int viewTag, + const jsi::Value& frameProcessor) { + __android_log_write(ANDROID_LOG_INFO, TAG, + "Setting new Frame Processor..."); + + if (!_runtimeManager || !_runtimeManager->runtime) { + throw jsi::JSError(runtime, + "setFrameProcessor(..): VisionCamera's RuntimeManager is not yet initialized!"); + } + + // find camera view + auto cameraView = findCameraViewById(viewTag); + __android_log_write(ANDROID_LOG_INFO, TAG, "Found CameraView!"); + + // convert jsi::Function to a ShareableValue (can be shared across runtimes) + __android_log_write(ANDROID_LOG_INFO, TAG, + "Adapting Shareable value from function (conversion to worklet)..."); + auto worklet = reanimated::ShareableValue::adapt(runtime, + frameProcessor, + _runtimeManager.get()); + __android_log_write(ANDROID_LOG_INFO, TAG, "Successfully created worklet!"); + + scheduler_->scheduleOnUI([=]() { + // cast worklet to a jsi::Function for the new runtime + auto& rt = *_runtimeManager->runtime; + auto function = std::make_shared(worklet->getValue(rt).asObject(rt).asFunction(rt)); + + // assign lambda to frame processor + cameraView->cthis()->setFrameProcessor([this, &rt, function](jni::alias_ref frame) { + try { + // create HostObject which holds the Frame (JImageProxy) + auto hostObject = std::make_shared(frame); + function->callWithThis(rt, *function, jsi::Object::createFromHostObject(rt, hostObject)); + } catch (jsi::JSError& jsError) { + auto message = "Frame Processor threw an error: " + jsError.getMessage(); + __android_log_write(ANDROID_LOG_ERROR, TAG, message.c_str()); + this->logErrorToJS(message); + } + }); + + __android_log_write(ANDROID_LOG_INFO, TAG, "Frame Processor set!"); + }); +} + +void FrameProcessorRuntimeManager::unsetFrameProcessor(int viewTag) { + __android_log_write(ANDROID_LOG_INFO, TAG, "Removing Frame Processor..."); + + // find camera view + auto cameraView = findCameraViewById(viewTag); + + // call Java method to unset frame processor + cameraView->cthis()->unsetFrameProcessor(); + + __android_log_write(ANDROID_LOG_INFO, TAG, "Frame Processor removed!"); +} + // actual JSI installer void FrameProcessorRuntimeManager::installJSIBindings() { __android_log_write(ANDROID_LOG_INFO, TAG, "Installing JSI bindings..."); @@ -113,7 +172,7 @@ void FrameProcessorRuntimeManager::installJSIBindings() { return; } - auto &jsiRuntime = *runtime_; + auto& jsiRuntime = *runtime_; auto setFrameProcessor = [this](jsi::Runtime &runtime, const jsi::Value &thisValue, @@ -130,43 +189,10 @@ void FrameProcessorRuntimeManager::installJSIBindings() { throw jsi::JSError(runtime, "Camera::setFrameProcessor: Second argument ('frameProcessor') must be a function!"); } - if (!_runtimeManager || !_runtimeManager->runtime) { - throw jsi::JSError(runtime, - "Camera::setFrameProcessor: The RuntimeManager is not yet initialized!"); - } - // find camera view - auto viewTag = arguments[0].asNumber(); - auto cameraView = findCameraViewById(static_cast(viewTag)); - __android_log_write(ANDROID_LOG_INFO, TAG, "Found CameraView!"); - - // convert jsi::Function to a ShareableValue (can be shared across runtimes) - __android_log_write(ANDROID_LOG_INFO, TAG, "Adapting Shareable value from function (conversion to worklet)..."); - auto worklet = reanimated::ShareableValue::adapt(runtime, arguments[1], - _runtimeManager.get()); - __android_log_write(ANDROID_LOG_INFO, TAG, "Successfully created worklet!"); - - - scheduler_->scheduleOnUI([=]() { - // cast worklet to a jsi::Function for the new runtime - auto &rt = *_runtimeManager->runtime; - auto function = std::make_shared(worklet->getValue(rt).asObject(rt).asFunction(rt)); - - // assign lambda to frame processor - cameraView->setFrameProcessor([this, &rt, function](jni::alias_ref frame) { - try { - // create HostObject which holds the Frame (JImageProxy) - auto hostObject = std::make_shared(frame); - function->callWithThis(rt, *function, jsi::Object::createFromHostObject(rt, hostObject)); - } catch (jsi::JSError& jsError) { - auto message = "Frame Processor threw an error: " + jsError.getMessage(); - __android_log_write(ANDROID_LOG_ERROR, TAG, message.c_str()); - this->logErrorToJS(message); - } - }); - - __android_log_write(ANDROID_LOG_INFO, TAG, "Frame Processor set!"); - }); + double viewTag = arguments[0].asNumber(); + const jsi::Value& frameProcessor = arguments[1]; + this->setFrameProcessor(runtime, static_cast(viewTag), frameProcessor); return jsi::Value::undefined(); }; @@ -190,14 +216,8 @@ void FrameProcessorRuntimeManager::installJSIBindings() { "Camera::unsetFrameProcessor: First argument ('viewTag') must be a number!"); } - // find camera view auto viewTag = arguments[0].asNumber(); - auto cameraView = findCameraViewById(static_cast(viewTag)); - - // call Java method to unset frame processor - cameraView->unsetFrameProcessor(); - - __android_log_write(ANDROID_LOG_INFO, TAG, "Frame Processor removed!"); + this->unsetFrameProcessor(static_cast(viewTag)); return jsi::Value::undefined(); }; @@ -213,7 +233,7 @@ void FrameProcessorRuntimeManager::installJSIBindings() { __android_log_write(ANDROID_LOG_INFO, TAG, "Finished installing JSI bindings!"); } -void FrameProcessorRuntimeManager::registerPlugin(alias_ref plugin) { +void FrameProcessorRuntimeManager::registerPlugin(alias_ref plugin) { // _runtimeManager might never be null, but we can never be too sure. if (!_runtimeManager || !_runtimeManager->runtime) { throw std::runtime_error("Tried to register plugin before initializing JS runtime! Call `initializeRuntime()` first."); @@ -224,7 +244,7 @@ void FrameProcessorRuntimeManager::registerPlugin(alias_refcthis()->getName(); + auto name = "__" + pluginGlobal->getName(); __android_log_print(ANDROID_LOG_INFO, TAG, "Installing Frame Processor Plugin \"%s\"...", name.c_str()); @@ -234,7 +254,7 @@ void FrameProcessorRuntimeManager::registerPlugin(alias_ref jsi::Value { // Unbox object and get typed HostObject auto boxedHostObject = arguments[0].asObject(runtime).asHostObject(runtime); - auto frameHostObject = dynamic_cast(boxedHostObject.get()); + auto frameHostObject = static_cast(boxedHostObject.get()); // parse params - we are offset by `1` because the frame is the first parameter. auto params = JArrayClass::newArray(count - 1); @@ -243,7 +263,7 @@ void FrameProcessorRuntimeManager::registerPlugin(alias_refcthis()->callback(frameHostObject->frame, params); + auto result = pluginGlobal->callback(frameHostObject->frame, params); // convert result from JNI to JSI value return JSIJNIConversion::convertJNIObjectToJSIValue(runtime, result); diff --git a/android/src/main/cpp/FrameProcessorRuntimeManager.h b/android/src/main/cpp/FrameProcessorRuntimeManager.h index d06b852..14d3701 100644 --- a/android/src/main/cpp/FrameProcessorRuntimeManager.h +++ b/android/src/main/cpp/FrameProcessorRuntimeManager.h @@ -14,8 +14,8 @@ #include "reanimated-headers/AndroidScheduler.h" #include "CameraView.h" -#include "FrameProcessorPlugin.h" #include "VisionCameraScheduler.h" +#include "java-bindings/JFrameProcessorPlugin.h" namespace vision { @@ -31,7 +31,6 @@ class FrameProcessorRuntimeManager : public jni::HybridClass androidScheduler); static void registerNatives(); - FrameProcessorRuntimeManager() {} explicit FrameProcessorRuntimeManager(jni::alias_ref jThis, jsi::Runtime* runtime, std::shared_ptr jsCallInvoker, @@ -50,11 +49,16 @@ class FrameProcessorRuntimeManager : public jni::HybridClass _runtimeManager; std::shared_ptr scheduler_; - CameraView* findCameraViewById(int viewId); + jni::global_ref findCameraViewById(int viewId); void initializeRuntime(); void installJSIBindings(); - void registerPlugin(alias_ref plugin); + void registerPlugin(alias_ref plugin); void logErrorToJS(const std::string& message); + + void setFrameProcessor(jsi::Runtime& runtime, // NOLINT(runtime/references) + int viewTag, + const jsi::Value& frameProcessor); + void unsetFrameProcessor(int viewTag); }; } // namespace vision diff --git a/android/src/main/cpp/JSIJNIConversion.cpp b/android/src/main/cpp/JSIJNIConversion.cpp index 82a0f29..390d2d8 100644 --- a/android/src/main/cpp/JSIJNIConversion.cpp +++ b/android/src/main/cpp/JSIJNIConversion.cpp @@ -19,7 +19,7 @@ #include #include -#include "java-bindings/JImageProxyHostObject.h" +#include "FrameHostObject.h" #include "java-bindings/JImageProxy.h" #include "java-bindings/JArrayList.h" #include "java-bindings/JHashMap.h" @@ -68,7 +68,7 @@ jobject JSIJNIConversion::convertJSIValueToJNIObject(jsi::Runtime &runtime, cons // jsi::HostObject auto boxedHostObject = object.getHostObject(runtime); - auto hostObject = dynamic_cast(boxedHostObject.get()); + auto hostObject = dynamic_cast(boxedHostObject.get()); if (hostObject != nullptr) { // return jni local_ref to the JImageProxy return hostObject->frame.get(); diff --git a/android/src/main/cpp/VisionCamera.cpp b/android/src/main/cpp/VisionCamera.cpp index b841854..6b91b8e 100644 --- a/android/src/main/cpp/VisionCamera.cpp +++ b/android/src/main/cpp/VisionCamera.cpp @@ -1,14 +1,12 @@ #include #include #include "FrameProcessorRuntimeManager.h" -#include "FrameProcessorPlugin.h" #include "CameraView.h" #include "VisionCameraScheduler.h" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) { return facebook::jni::initialize(vm, [] { vision::FrameProcessorRuntimeManager::registerNatives(); - vision::FrameProcessorPlugin::registerNatives(); vision::CameraView::registerNatives(); vision::VisionCameraScheduler::registerNatives(); }); diff --git a/android/src/main/cpp/java-bindings/JFrameProcessorPlugin.cpp b/android/src/main/cpp/java-bindings/JFrameProcessorPlugin.cpp new file mode 100644 index 0000000..54a162b --- /dev/null +++ b/android/src/main/cpp/java-bindings/JFrameProcessorPlugin.cpp @@ -0,0 +1,30 @@ +// +// Created by Marc Rousavy on 29.09.21. +// + +#include "JFrameProcessorPlugin.h" + +#include +#include + +namespace vision { + +using namespace facebook; +using namespace jni; + +using TCallback = jobject(alias_ref, alias_ref>); + +local_ref JFrameProcessorPlugin::callback(alias_ref image, + alias_ref> params) const { + auto callbackMethod = getClass()->getMethod("callback"); + + auto result = callbackMethod(self(), image, params); + return make_local(result); +} + +std::string JFrameProcessorPlugin::getName() const { + auto getNameMethod = getClass()->getMethod("getName"); + return getNameMethod(self())->toStdString(); +} + +} // namespace vision diff --git a/android/src/main/cpp/java-bindings/JFrameProcessorPlugin.h b/android/src/main/cpp/java-bindings/JFrameProcessorPlugin.h new file mode 100644 index 0000000..ad66c5d --- /dev/null +++ b/android/src/main/cpp/java-bindings/JFrameProcessorPlugin.h @@ -0,0 +1,33 @@ +// +// Created by Marc Rousavy on 29.09.21 +// + +#pragma once + +#include +#include +#include + +#include "JImageProxy.h" + +namespace vision { + +using namespace facebook; +using namespace jni; + +struct JFrameProcessorPlugin : public JavaClass { + static constexpr auto kJavaDescriptor = "Lcom/mrousavy/camera/frameprocessor/FrameProcessorPlugin;"; + + public: + /** + * Call the plugin. + */ + local_ref callback(alias_ref image, + alias_ref> params) const; + /** + * Get the user-defined name of the Frame Processor Plugin + */ + std::string getName() const; +}; + +} // namespace vision diff --git a/android/src/main/cpp/java-bindings/JImageProxy.cpp b/android/src/main/cpp/java-bindings/JImageProxy.cpp index b804f0a..0aec4d5 100644 --- a/android/src/main/cpp/java-bindings/JImageProxy.cpp +++ b/android/src/main/cpp/java-bindings/JImageProxy.cpp @@ -12,12 +12,12 @@ namespace vision { using namespace facebook; using namespace jni; -int JImageProxy::getWidth() { +int JImageProxy::getWidth() const { static const auto getWidthMethod = getClass()->getMethod("getWidth"); return getWidthMethod(self()); } -int JImageProxy::getHeight() { +int JImageProxy::getHeight() const { static const auto getWidthMethod = getClass()->getMethod("getHeight"); return getWidthMethod(self()); } @@ -27,19 +27,19 @@ alias_ref getUtilsClass() { return ImageProxyUtilsClass; } -bool JImageProxy::getIsValid() { +bool JImageProxy::getIsValid() const { auto utilsClass = getUtilsClass(); static const auto isImageProxyValidMethod = utilsClass->getStaticMethod("isImageProxyValid"); return isImageProxyValidMethod(utilsClass, self()); } -int JImageProxy::getPlanesCount() { +int JImageProxy::getPlanesCount() const { auto utilsClass = getUtilsClass(); static const auto getPlanesCountMethod = utilsClass->getStaticMethod("getPlanesCount"); return getPlanesCountMethod(utilsClass, self()); } -int JImageProxy::getBytesPerRow() { +int JImageProxy::getBytesPerRow() const { auto utilsClass = getUtilsClass(); static const auto getBytesPerRowMethod = utilsClass->getStaticMethod("getBytesPerRow"); return getBytesPerRowMethod(utilsClass, self()); diff --git a/android/src/main/cpp/java-bindings/JImageProxy.h b/android/src/main/cpp/java-bindings/JImageProxy.h index cf9fda4..c293cd8 100644 --- a/android/src/main/cpp/java-bindings/JImageProxy.h +++ b/android/src/main/cpp/java-bindings/JImageProxy.h @@ -9,15 +9,18 @@ namespace vision { -struct JImageProxy : public facebook::jni::JavaClass { +using namespace facebook; +using namespace jni; + +struct JImageProxy : public JavaClass { static constexpr auto kJavaDescriptor = "Landroidx/camera/core/ImageProxy;"; public: - int getWidth(); - int getHeight(); - bool getIsValid(); - int getPlanesCount(); - int getBytesPerRow(); + int getWidth() const; + int getHeight() const; + bool getIsValid() const; + int getPlanesCount() const; + int getBytesPerRow() const; void close(); }; diff --git a/android/src/main/java/com/mrousavy/camera/frameprocessor/FrameProcessorPlugin.java b/android/src/main/java/com/mrousavy/camera/frameprocessor/FrameProcessorPlugin.java index 6aa006e..7e5c5b6 100644 --- a/android/src/main/java/com/mrousavy/camera/frameprocessor/FrameProcessorPlugin.java +++ b/android/src/main/java/com/mrousavy/camera/frameprocessor/FrameProcessorPlugin.java @@ -4,21 +4,13 @@ import androidx.annotation.Keep; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.camera.core.ImageProxy; -import com.facebook.jni.HybridData; import com.facebook.proguard.annotations.DoNotStrip; /** * Declares a Frame Processor Plugin. */ -@SuppressWarnings("JavaJniMissingFunction") public abstract class FrameProcessorPlugin { - static { - System.loadLibrary("VisionCamera"); - } - - @DoNotStrip - @SuppressWarnings({"FieldCanBeLocal", "unused"}) - private final HybridData mHybridData; + private final @NonNull String mName; /** * The actual Frame Processor plugin callback. Called for every frame the ImageAnalyzer receives. @@ -37,10 +29,15 @@ public abstract class FrameProcessorPlugin { * The actual name in the JS Runtime will be prefixed with two underscores (`__`) */ protected FrameProcessorPlugin(@NonNull String name) { - mHybridData = initHybrid(name); + mName = name; } - private native @NonNull HybridData initHybrid(@NonNull String name); + /** + * Get the user-defined name of the Frame Processor Plugin. + */ + public @NonNull String getName() { + return mName; + } /** * Registers the given plugin in the Frame Processor Runtime.