feat: Use clang-format to keep the C++ codebase clean (#1741)
* Use clang-format * Create .clang-format * Update .clang-format * Update .clang-format * Update .clang-format * Only search in cpp dirs * Update clang-format.sh * Update .clang-format * Update .clang-format * Update .clang-format * Format C++ code! * Use version 16 * Update clang-format.sh * Remove Shaders.ts * fix: Lint Swift
This commit is contained in:
@@ -8,8 +8,8 @@
|
||||
#include <GLES2/gl2.h>
|
||||
#include <GLES2/gl2ext.h>
|
||||
|
||||
#include <android/native_window.h>
|
||||
#include <android/log.h>
|
||||
#include <android/native_window.h>
|
||||
|
||||
#include "OpenGLError.h"
|
||||
|
||||
@@ -49,29 +49,40 @@ void OpenGLContext::ensureOpenGL() {
|
||||
if (display == EGL_NO_DISPLAY) {
|
||||
__android_log_print(ANDROID_LOG_INFO, TAG, "Initializing EGLDisplay..");
|
||||
display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
if (display == EGL_NO_DISPLAY) throw OpenGLError("Failed to get default OpenGL Display!");
|
||||
if (display == EGL_NO_DISPLAY)
|
||||
throw OpenGLError("Failed to get default OpenGL Display!");
|
||||
|
||||
EGLint major;
|
||||
EGLint minor;
|
||||
successful = eglInitialize(display, &major, &minor);
|
||||
if (!successful) throw OpenGLError("Failed to initialize OpenGL!");
|
||||
if (!successful)
|
||||
throw OpenGLError("Failed to initialize OpenGL!");
|
||||
}
|
||||
|
||||
// EGLConfig
|
||||
if (config == nullptr) {
|
||||
__android_log_print(ANDROID_LOG_INFO, TAG, "Initializing EGLConfig..");
|
||||
EGLint attributes[] = {EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||
EGL_RED_SIZE, 8,
|
||||
EGL_GREEN_SIZE, 8,
|
||||
EGL_BLUE_SIZE, 8,
|
||||
EGL_ALPHA_SIZE, 8,
|
||||
EGL_DEPTH_SIZE, 0,
|
||||
EGL_STENCIL_SIZE, 0,
|
||||
EGLint attributes[] = {EGL_RENDERABLE_TYPE,
|
||||
EGL_OPENGL_ES2_BIT,
|
||||
EGL_SURFACE_TYPE,
|
||||
EGL_WINDOW_BIT,
|
||||
EGL_RED_SIZE,
|
||||
8,
|
||||
EGL_GREEN_SIZE,
|
||||
8,
|
||||
EGL_BLUE_SIZE,
|
||||
8,
|
||||
EGL_ALPHA_SIZE,
|
||||
8,
|
||||
EGL_DEPTH_SIZE,
|
||||
0,
|
||||
EGL_STENCIL_SIZE,
|
||||
0,
|
||||
EGL_NONE};
|
||||
EGLint numConfigs;
|
||||
successful = eglChooseConfig(display, attributes, &config, 1, &numConfigs);
|
||||
if (!successful || numConfigs == 0) throw OpenGLError("Failed to choose OpenGL config!");
|
||||
if (!successful || numConfigs == 0)
|
||||
throw OpenGLError("Failed to choose OpenGL config!");
|
||||
}
|
||||
|
||||
// EGLContext
|
||||
@@ -79,18 +90,18 @@ void OpenGLContext::ensureOpenGL() {
|
||||
__android_log_print(ANDROID_LOG_INFO, TAG, "Initializing EGLContext..");
|
||||
EGLint contextAttributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
|
||||
context = eglCreateContext(display, config, nullptr, contextAttributes);
|
||||
if (context == EGL_NO_CONTEXT) throw OpenGLError("Failed to create OpenGL context!");
|
||||
if (context == EGL_NO_CONTEXT)
|
||||
throw OpenGLError("Failed to create OpenGL context!");
|
||||
}
|
||||
|
||||
// EGLSurface
|
||||
if (offscreenSurface == EGL_NO_SURFACE) {
|
||||
// If we don't have a surface at all
|
||||
__android_log_print(ANDROID_LOG_INFO, TAG, "Initializing 1x1 offscreen pbuffer EGLSurface..");
|
||||
EGLint attributes[] = {EGL_WIDTH, 1,
|
||||
EGL_HEIGHT, 1,
|
||||
EGL_NONE};
|
||||
EGLint attributes[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
|
||||
offscreenSurface = eglCreatePbufferSurface(display, config, attributes);
|
||||
if (offscreenSurface == EGL_NO_SURFACE) throw OpenGLError("Failed to create OpenGL Surface!");
|
||||
if (offscreenSurface == EGL_NO_SURFACE)
|
||||
throw OpenGLError("Failed to create OpenGL Surface!");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,21 +110,24 @@ void OpenGLContext::use() {
|
||||
}
|
||||
|
||||
void OpenGLContext::use(EGLSurface surface) {
|
||||
if (surface == EGL_NO_SURFACE) throw OpenGLError("Cannot render to a null Surface!");
|
||||
if (surface == EGL_NO_SURFACE)
|
||||
throw OpenGLError("Cannot render to a null Surface!");
|
||||
|
||||
// 1. Make sure the OpenGL context is initialized
|
||||
this->ensureOpenGL();
|
||||
|
||||
// 2. Make the OpenGL context current
|
||||
bool successful = eglMakeCurrent(display, surface, surface, context);
|
||||
if (!successful || eglGetError() != EGL_SUCCESS) throw OpenGLError("Failed to use current OpenGL context!");
|
||||
if (!successful || eglGetError() != EGL_SUCCESS)
|
||||
throw OpenGLError("Failed to use current OpenGL context!");
|
||||
|
||||
// 3. Caller can now render to this surface
|
||||
}
|
||||
|
||||
void OpenGLContext::flush() const {
|
||||
bool successful = eglSwapBuffers(display, eglGetCurrentSurface(EGL_DRAW));
|
||||
if (!successful || eglGetError() != EGL_SUCCESS) throw OpenGLError("Failed to swap OpenGL buffers!");
|
||||
if (!successful || eglGetError() != EGL_SUCCESS)
|
||||
throw OpenGLError("Failed to swap OpenGL buffers!");
|
||||
}
|
||||
|
||||
OpenGLTexture OpenGLContext::createTexture(OpenGLTexture::Type type, int width, int height) {
|
||||
@@ -122,7 +136,8 @@ OpenGLTexture OpenGLContext::createTexture(OpenGLTexture::Type type, int width,
|
||||
|
||||
// 2. Make the OpenGL context current
|
||||
bool successful = eglMakeCurrent(display, offscreenSurface, offscreenSurface, context);
|
||||
if (!successful || eglGetError() != EGL_SUCCESS) throw OpenGLError("Failed to use current OpenGL context!");
|
||||
if (!successful || eglGetError() != EGL_SUCCESS)
|
||||
throw OpenGLError("Failed to use current OpenGL context!");
|
||||
|
||||
GLuint textureId;
|
||||
glGenTextures(1, &textureId);
|
||||
@@ -142,12 +157,7 @@ OpenGLTexture OpenGLContext::createTexture(OpenGLTexture::Type type, int width,
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
return {
|
||||
.id = textureId,
|
||||
.target = target,
|
||||
.width = width,
|
||||
.height = height
|
||||
};
|
||||
return {.id = textureId, .target = target, .width = width, .height = height};
|
||||
}
|
||||
|
||||
} // namespace vision
|
||||
|
@@ -7,11 +7,11 @@
|
||||
#include <EGL/egl.h>
|
||||
#include <GLES2/gl2.h>
|
||||
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
#include "PassThroughShader.h"
|
||||
#include "OpenGLTexture.h"
|
||||
#include "PassThroughShader.h"
|
||||
|
||||
namespace vision {
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace vision {
|
||||
* By default, it creates an off-screen PixelBuffer surface.
|
||||
*/
|
||||
class OpenGLContext {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Create a new instance of the OpenGLContext that draws to an off-screen PixelBuffer surface.
|
||||
* This will not perform any OpenGL operations yet, and is therefore safe to call from any Thread.
|
||||
@@ -52,21 +52,21 @@ class OpenGLContext {
|
||||
*/
|
||||
OpenGLTexture createTexture(OpenGLTexture::Type type, int width, int height);
|
||||
|
||||
public:
|
||||
public:
|
||||
EGLDisplay display = EGL_NO_DISPLAY;
|
||||
EGLContext context = EGL_NO_CONTEXT;
|
||||
EGLSurface offscreenSurface = EGL_NO_SURFACE;
|
||||
EGLConfig config = nullptr;
|
||||
|
||||
private:
|
||||
private:
|
||||
OpenGLContext() = default;
|
||||
void destroy();
|
||||
void ensureOpenGL();
|
||||
|
||||
private:
|
||||
private:
|
||||
PassThroughShader _passThroughShader;
|
||||
|
||||
private:
|
||||
private:
|
||||
static constexpr auto TAG = "OpenGLContext";
|
||||
};
|
||||
|
||||
|
@@ -4,27 +4,31 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <GLES2/gl2.h>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
namespace vision {
|
||||
|
||||
inline std::string getEglErrorIfAny() {
|
||||
EGLint error = glGetError();
|
||||
if (error != GL_NO_ERROR) return " Error: " + std::to_string(error);
|
||||
if (error != GL_NO_ERROR)
|
||||
return " Error: " + std::to_string(error);
|
||||
error = eglGetError();
|
||||
if (error != EGL_SUCCESS) return " Error: " + std::to_string(error);
|
||||
if (error != EGL_SUCCESS)
|
||||
return " Error: " + std::to_string(error);
|
||||
return "";
|
||||
}
|
||||
|
||||
class OpenGLError: public std::runtime_error {
|
||||
public:
|
||||
explicit OpenGLError(const std::string&& message): std::runtime_error(message + getEglErrorIfAny()) {}
|
||||
class OpenGLError : public std::runtime_error {
|
||||
public:
|
||||
explicit OpenGLError(const std::string&& message)
|
||||
: std::runtime_error(message + getEglErrorIfAny()) {}
|
||||
|
||||
static inline void checkIfError(const std::string&& message) {
|
||||
auto error = getEglErrorIfAny();
|
||||
if (error.length() > 0) throw std::runtime_error(message + error);
|
||||
if (error.length() > 0)
|
||||
throw std::runtime_error(message + error);
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -8,8 +8,8 @@
|
||||
#include <GLES2/gl2.h>
|
||||
#include <GLES2/gl2ext.h>
|
||||
|
||||
#include <android/native_window.h>
|
||||
#include <android/log.h>
|
||||
#include <android/native_window.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
@@ -17,7 +17,9 @@
|
||||
|
||||
namespace vision {
|
||||
|
||||
std::unique_ptr<OpenGLRenderer> OpenGLRenderer::CreateWithWindowSurface(std::shared_ptr<OpenGLContext> context, ANativeWindow* surface) {
|
||||
std::unique_ptr<OpenGLRenderer>
|
||||
OpenGLRenderer::CreateWithWindowSurface(std::shared_ptr<OpenGLContext> context,
|
||||
ANativeWindow* surface) {
|
||||
return std::unique_ptr<OpenGLRenderer>(new OpenGLRenderer(std::move(context), surface));
|
||||
}
|
||||
|
||||
|
@@ -4,11 +4,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "PassThroughShader.h"
|
||||
#include <EGL/egl.h>
|
||||
#include <GLES2/gl2.h>
|
||||
#include <android/native_window.h>
|
||||
#include <memory>
|
||||
#include "PassThroughShader.h"
|
||||
|
||||
#include "OpenGLContext.h"
|
||||
#include "OpenGLTexture.h"
|
||||
@@ -16,14 +16,16 @@
|
||||
namespace vision {
|
||||
|
||||
class OpenGLRenderer {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Create a new instance of the OpenGLRenderer that draws to an on-screen window surface.
|
||||
* This will not perform any OpenGL operations yet, and is therefore safe to call from any Thread.
|
||||
*
|
||||
* Note: The `surface` is considered moved, and the OpenGL context will release it when it is being deleted.
|
||||
* Note: The `surface` is considered moved, and the OpenGL context will release it when it is
|
||||
* being deleted.
|
||||
*/
|
||||
static std::unique_ptr<OpenGLRenderer> CreateWithWindowSurface(std::shared_ptr<OpenGLContext> context, ANativeWindow* surface);
|
||||
static std::unique_ptr<OpenGLRenderer>
|
||||
CreateWithWindowSurface(std::shared_ptr<OpenGLContext> context, ANativeWindow* surface);
|
||||
/**
|
||||
* Destroy the OpenGL Context. This needs to be called on the same thread that `use()` was called.
|
||||
*/
|
||||
@@ -35,24 +37,25 @@ class OpenGLRenderer {
|
||||
void renderTextureToSurface(const OpenGLTexture& texture, float* transformMatrix);
|
||||
|
||||
/**
|
||||
* Destroys the OpenGL context. This needs to be called on the same thread that `use()` was called.
|
||||
* After calling `destroy()`, it is legal to call `use()` again, which will re-construct everything.
|
||||
* Destroys the OpenGL context. This needs to be called on the same thread that `use()` was
|
||||
* called. After calling `destroy()`, it is legal to call `use()` again, which will re-construct
|
||||
* everything.
|
||||
*/
|
||||
void destroy();
|
||||
|
||||
private:
|
||||
private:
|
||||
explicit OpenGLRenderer(std::shared_ptr<OpenGLContext> context, ANativeWindow* surface);
|
||||
|
||||
private:
|
||||
private:
|
||||
int _width = 0, _height = 0;
|
||||
std::shared_ptr<OpenGLContext> _context;
|
||||
ANativeWindow* _outputSurface;
|
||||
EGLSurface _surface = EGL_NO_SURFACE;
|
||||
|
||||
private:
|
||||
private:
|
||||
PassThroughShader _passThroughShader;
|
||||
|
||||
private:
|
||||
private:
|
||||
static constexpr auto TAG = "OpenGLRenderer";
|
||||
};
|
||||
|
||||
|
@@ -3,11 +3,11 @@
|
||||
//
|
||||
|
||||
#include "PassThroughShader.h"
|
||||
#include "OpenGLError.h"
|
||||
#include <EGL/egl.h>
|
||||
#include <GLES2/gl2.h>
|
||||
#include <GLES2/gl2ext.h>
|
||||
#include <memory>
|
||||
#include "OpenGLError.h"
|
||||
#include <string>
|
||||
|
||||
namespace vision {
|
||||
@@ -30,12 +30,12 @@ void PassThroughShader::draw(const OpenGLTexture& texture, float* transformMatri
|
||||
_programId = createProgram();
|
||||
glUseProgram(_programId);
|
||||
_vertexParameters = {
|
||||
.aPosition = glGetAttribLocation(_programId, "aPosition"),
|
||||
.aTexCoord = glGetAttribLocation(_programId, "aTexCoord"),
|
||||
.uTransformMatrix = glGetUniformLocation(_programId, "uTransformMatrix"),
|
||||
.aPosition = glGetAttribLocation(_programId, "aPosition"),
|
||||
.aTexCoord = glGetAttribLocation(_programId, "aTexCoord"),
|
||||
.uTransformMatrix = glGetUniformLocation(_programId, "uTransformMatrix"),
|
||||
};
|
||||
_fragmentParameters = {
|
||||
.uTexture = glGetUniformLocation(_programId, "uTexture"),
|
||||
.uTexture = glGetUniformLocation(_programId, "uTexture"),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -50,19 +50,11 @@ void PassThroughShader::draw(const OpenGLTexture& texture, float* transformMatri
|
||||
|
||||
// 3. Pass all uniforms/attributes for vertex shader
|
||||
glEnableVertexAttribArray(_vertexParameters.aPosition);
|
||||
glVertexAttribPointer(_vertexParameters.aPosition,
|
||||
2,
|
||||
GL_FLOAT,
|
||||
GL_FALSE,
|
||||
sizeof(Vertex),
|
||||
glVertexAttribPointer(_vertexParameters.aPosition, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
|
||||
reinterpret_cast<void*>(offsetof(Vertex, position)));
|
||||
|
||||
glEnableVertexAttribArray(_vertexParameters.aTexCoord);
|
||||
glVertexAttribPointer(_vertexParameters.aTexCoord,
|
||||
2,
|
||||
GL_FLOAT,
|
||||
GL_FALSE,
|
||||
sizeof(Vertex),
|
||||
glVertexAttribPointer(_vertexParameters.aTexCoord, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
|
||||
reinterpret_cast<void*>(offsetof(Vertex, texCoord)));
|
||||
|
||||
glUniformMatrix4fv(_vertexParameters.uTransformMatrix, 1, GL_FALSE, transformMatrix);
|
||||
@@ -78,7 +70,8 @@ void PassThroughShader::draw(const OpenGLTexture& texture, float* transformMatri
|
||||
|
||||
GLuint PassThroughShader::loadShader(GLenum shaderType, const char* shaderCode) {
|
||||
GLuint shader = glCreateShader(shaderType);
|
||||
if (shader == 0) throw OpenGLError("Failed to load shader!");
|
||||
if (shader == 0)
|
||||
throw OpenGLError("Failed to load shader!");
|
||||
|
||||
glShaderSource(shader, 1, &shaderCode, nullptr);
|
||||
glCompileShader(shader);
|
||||
@@ -96,7 +89,8 @@ GLuint PassThroughShader::createProgram() {
|
||||
GLuint fragmentShader = loadShader(GL_FRAGMENT_SHADER, FRAGMENT_SHADER);
|
||||
|
||||
GLuint program = glCreateProgram();
|
||||
if (program == 0) throw OpenGLError("Failed to create pass-through program!");
|
||||
if (program == 0)
|
||||
throw OpenGLError("Failed to create pass-through program!");
|
||||
|
||||
glAttachShader(program, vertexShader);
|
||||
OpenGLError::checkIfError("Failed to attach Vertex Shader!");
|
||||
|
@@ -21,7 +21,7 @@ struct Vertex {
|
||||
};
|
||||
|
||||
class PassThroughShader {
|
||||
public:
|
||||
public:
|
||||
PassThroughShader() = default;
|
||||
~PassThroughShader();
|
||||
|
||||
@@ -31,12 +31,12 @@ class PassThroughShader {
|
||||
*/
|
||||
void draw(const OpenGLTexture& texture, float* transformMatrix);
|
||||
|
||||
private:
|
||||
private:
|
||||
// Loading
|
||||
static GLuint loadShader(GLenum shaderType, const char* shaderCode);
|
||||
static GLuint createProgram();
|
||||
|
||||
private:
|
||||
private:
|
||||
// Parameters
|
||||
GLuint _programId = NO_SHADER;
|
||||
GLuint _vertexBuffer = NO_BUFFER;
|
||||
@@ -49,7 +49,7 @@ class PassThroughShader {
|
||||
GLint uTexture = NO_POSITION;
|
||||
} _fragmentParameters;
|
||||
|
||||
private:
|
||||
private:
|
||||
// Statics
|
||||
static constexpr Vertex VERTICES[] = {
|
||||
{{-1.0f, -1.0f}, {0.0f, 0.0f}}, // bottom-left
|
||||
|
@@ -5,25 +5,27 @@
|
||||
#include "VideoPipeline.h"
|
||||
#include "OpenGLError.h"
|
||||
|
||||
#include <android/native_window_jni.h>
|
||||
#include <GLES2/gl2.h>
|
||||
#include <GLES2/gl2ext.h>
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
#include <GLES/gl.h>
|
||||
#include <GLES2/gl2.h>
|
||||
#include <GLES2/gl2ext.h>
|
||||
#include <android/native_window_jni.h>
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#include "OpenGLTexture.h"
|
||||
#include "JFrameProcessor.h"
|
||||
#include "OpenGLTexture.h"
|
||||
|
||||
namespace vision {
|
||||
|
||||
jni::local_ref<VideoPipeline::jhybriddata> VideoPipeline::initHybrid(jni::alias_ref<jhybridobject> jThis, int width, int height) {
|
||||
jni::local_ref<VideoPipeline::jhybriddata>
|
||||
VideoPipeline::initHybrid(jni::alias_ref<jhybridobject> jThis, int width, int height) {
|
||||
return makeCxxInstance(jThis, width, height);
|
||||
}
|
||||
|
||||
VideoPipeline::VideoPipeline(jni::alias_ref<jhybridobject> jThis, int width, int height): _javaPart(jni::make_global(jThis)) {
|
||||
VideoPipeline::VideoPipeline(jni::alias_ref<jhybridobject> jThis, int width, int height)
|
||||
: _javaPart(jni::make_global(jThis)) {
|
||||
_width = width;
|
||||
_height = height;
|
||||
_context = OpenGLContext::CreateWithOffscreenSurface();
|
||||
@@ -43,7 +45,8 @@ VideoPipeline::~VideoPipeline() {
|
||||
}
|
||||
|
||||
void VideoPipeline::removeFrameProcessorOutputSurface() {
|
||||
if (_frameProcessorOutput) _frameProcessorOutput->destroy();
|
||||
if (_frameProcessorOutput)
|
||||
_frameProcessorOutput->destroy();
|
||||
_frameProcessorOutput = nullptr;
|
||||
}
|
||||
|
||||
@@ -57,7 +60,8 @@ void VideoPipeline::setFrameProcessorOutputSurface(jobject surface) {
|
||||
}
|
||||
|
||||
void VideoPipeline::removeRecordingSessionOutputSurface() {
|
||||
if (_recordingSessionOutput) _recordingSessionOutput->destroy();
|
||||
if (_recordingSessionOutput)
|
||||
_recordingSessionOutput->destroy();
|
||||
_recordingSessionOutput = nullptr;
|
||||
}
|
||||
|
||||
@@ -103,14 +107,18 @@ void VideoPipeline::onFrame(jni::alias_ref<jni::JArrayFloat> transformMatrixPara
|
||||
|
||||
void VideoPipeline::registerNatives() {
|
||||
registerHybrid({
|
||||
makeNativeMethod("initHybrid", VideoPipeline::initHybrid),
|
||||
makeNativeMethod("setFrameProcessorOutputSurface", VideoPipeline::setFrameProcessorOutputSurface),
|
||||
makeNativeMethod("removeFrameProcessorOutputSurface", VideoPipeline::removeFrameProcessorOutputSurface),
|
||||
makeNativeMethod("setRecordingSessionOutputSurface", VideoPipeline::setRecordingSessionOutputSurface),
|
||||
makeNativeMethod("removeRecordingSessionOutputSurface", VideoPipeline::removeRecordingSessionOutputSurface),
|
||||
makeNativeMethod("getInputTextureId", VideoPipeline::getInputTextureId),
|
||||
makeNativeMethod("onBeforeFrame", VideoPipeline::onBeforeFrame),
|
||||
makeNativeMethod("onFrame", VideoPipeline::onFrame),
|
||||
makeNativeMethod("initHybrid", VideoPipeline::initHybrid),
|
||||
makeNativeMethod("setFrameProcessorOutputSurface",
|
||||
VideoPipeline::setFrameProcessorOutputSurface),
|
||||
makeNativeMethod("removeFrameProcessorOutputSurface",
|
||||
VideoPipeline::removeFrameProcessorOutputSurface),
|
||||
makeNativeMethod("setRecordingSessionOutputSurface",
|
||||
VideoPipeline::setRecordingSessionOutputSurface),
|
||||
makeNativeMethod("removeRecordingSessionOutputSurface",
|
||||
VideoPipeline::removeRecordingSessionOutputSurface),
|
||||
makeNativeMethod("getInputTextureId", VideoPipeline::getInputTextureId),
|
||||
makeNativeMethod("onBeforeFrame", VideoPipeline::onBeforeFrame),
|
||||
makeNativeMethod("onFrame", VideoPipeline::onFrame),
|
||||
});
|
||||
}
|
||||
|
||||
|
@@ -4,13 +4,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <jni.h>
|
||||
#include <fbjni/fbjni.h>
|
||||
#include "OpenGLContext.h"
|
||||
#include "OpenGLRenderer.h"
|
||||
#include "PassThroughShader.h"
|
||||
#include <EGL/egl.h>
|
||||
#include <android/native_window.h>
|
||||
#include "PassThroughShader.h"
|
||||
#include "OpenGLRenderer.h"
|
||||
#include "OpenGLContext.h"
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <jni.h>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
@@ -18,13 +18,14 @@ namespace vision {
|
||||
|
||||
using namespace facebook;
|
||||
|
||||
class VideoPipeline: public jni::HybridClass<VideoPipeline> {
|
||||
public:
|
||||
class VideoPipeline : public jni::HybridClass<VideoPipeline> {
|
||||
public:
|
||||
static auto constexpr kJavaDescriptor = "Lcom/mrousavy/camera/utils/VideoPipeline;";
|
||||
static jni::local_ref<jhybriddata> initHybrid(jni::alias_ref<jhybridobject> jThis, int width, int height);
|
||||
static jni::local_ref<jhybriddata> initHybrid(jni::alias_ref<jhybridobject> jThis, int width,
|
||||
int height);
|
||||
static void registerNatives();
|
||||
|
||||
public:
|
||||
public:
|
||||
~VideoPipeline();
|
||||
|
||||
// -> SurfaceTexture input
|
||||
@@ -42,11 +43,11 @@ class VideoPipeline: public jni::HybridClass<VideoPipeline> {
|
||||
void onBeforeFrame();
|
||||
void onFrame(jni::alias_ref<jni::JArrayFloat> transformMatrix);
|
||||
|
||||
private:
|
||||
private:
|
||||
// Private constructor. Use `create(..)` to create new instances.
|
||||
explicit VideoPipeline(jni::alias_ref<jhybridobject> jThis, int width, int height);
|
||||
|
||||
private:
|
||||
private:
|
||||
// Input Surface Texture
|
||||
std::optional<OpenGLTexture> _inputTexture = std::nullopt;
|
||||
int _width = 0;
|
||||
@@ -57,7 +58,7 @@ class VideoPipeline: public jni::HybridClass<VideoPipeline> {
|
||||
std::unique_ptr<OpenGLRenderer> _frameProcessorOutput = nullptr;
|
||||
std::unique_ptr<OpenGLRenderer> _recordingSessionOutput = nullptr;
|
||||
|
||||
private:
|
||||
private:
|
||||
friend HybridBase;
|
||||
jni::global_ref<javaobject> _javaPart;
|
||||
static constexpr auto TAG = "VideoPipeline";
|
||||
|
@@ -1,12 +1,12 @@
|
||||
#include <jni.h>
|
||||
#include <fbjni/fbjni.h>
|
||||
#include "JVisionCameraScheduler.h"
|
||||
#include "JFrameProcessor.h"
|
||||
#include "JVisionCameraProxy.h"
|
||||
#include "VisionCameraProxy.h"
|
||||
#include "JVisionCameraScheduler.h"
|
||||
#include "VideoPipeline.h"
|
||||
#include "VisionCameraProxy.h"
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <jni.h>
|
||||
|
||||
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
|
||||
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) {
|
||||
return facebook::jni::initialize(vm, [] {
|
||||
vision::VisionCameraInstaller::registerNatives();
|
||||
vision::JVisionCameraProxy::registerNatives();
|
||||
|
@@ -9,14 +9,15 @@
|
||||
|
||||
#include "JSITypedArray.h"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace vision {
|
||||
|
||||
using namespace facebook;
|
||||
|
||||
FrameHostObject::FrameHostObject(const jni::alias_ref<JFrame::javaobject>& frame): frame(make_global(frame)) { }
|
||||
FrameHostObject::FrameHostObject(const jni::alias_ref<JFrame::javaobject>& frame)
|
||||
: frame(make_global(frame)) {}
|
||||
|
||||
FrameHostObject::~FrameHostObject() {
|
||||
// Hermes' Garbage Collector (Hades GC) calls destructors on a separate Thread
|
||||
@@ -50,38 +51,29 @@ jsi::Value FrameHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pr
|
||||
auto name = propName.utf8(runtime);
|
||||
|
||||
if (name == "incrementRefCount") {
|
||||
jsi::HostFunctionType incrementRefCount = [=](jsi::Runtime& runtime,
|
||||
const jsi::Value& thisArg,
|
||||
jsi::HostFunctionType incrementRefCount = [=](jsi::Runtime& runtime, const jsi::Value& thisArg,
|
||||
const jsi::Value* args,
|
||||
size_t count) -> jsi::Value {
|
||||
// Increment retain count by one.
|
||||
this->frame->incrementRefCount();
|
||||
return jsi::Value::undefined();
|
||||
};
|
||||
return jsi::Function::createFromHostFunction(runtime,
|
||||
jsi::PropNameID::forUtf8(runtime, "incrementRefCount"),
|
||||
0,
|
||||
incrementRefCount);
|
||||
return jsi::Function::createFromHostFunction(
|
||||
runtime, jsi::PropNameID::forUtf8(runtime, "incrementRefCount"), 0, incrementRefCount);
|
||||
}
|
||||
if (name == "decrementRefCount") {
|
||||
auto decrementRefCount = [=](jsi::Runtime& runtime,
|
||||
const jsi::Value& thisArg,
|
||||
const jsi::Value* args,
|
||||
size_t count) -> jsi::Value {
|
||||
auto decrementRefCount = [=](jsi::Runtime& runtime, const jsi::Value& thisArg,
|
||||
const jsi::Value* args, size_t count) -> jsi::Value {
|
||||
// Decrement retain count by one. If the retain count is zero, the Frame gets closed.
|
||||
this->frame->decrementRefCount();
|
||||
return jsi::Value::undefined();
|
||||
};
|
||||
return jsi::Function::createFromHostFunction(runtime,
|
||||
jsi::PropNameID::forUtf8(runtime, "decrementRefCount"),
|
||||
0,
|
||||
decrementRefCount);
|
||||
return jsi::Function::createFromHostFunction(
|
||||
runtime, jsi::PropNameID::forUtf8(runtime, "decrementRefCount"), 0, decrementRefCount);
|
||||
}
|
||||
if (name == "toString") {
|
||||
jsi::HostFunctionType toString = [=](jsi::Runtime& runtime,
|
||||
const jsi::Value& thisArg,
|
||||
const jsi::Value* args,
|
||||
size_t count) -> jsi::Value {
|
||||
jsi::HostFunctionType toString = [=](jsi::Runtime& runtime, const jsi::Value& thisArg,
|
||||
const jsi::Value* args, size_t count) -> jsi::Value {
|
||||
if (!this->frame) {
|
||||
return jsi::String::createFromUtf8(runtime, "[closed frame]");
|
||||
}
|
||||
@@ -90,16 +82,16 @@ jsi::Value FrameHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pr
|
||||
auto str = std::to_string(width) + " x " + std::to_string(height) + " Frame";
|
||||
return jsi::String::createFromUtf8(runtime, str);
|
||||
};
|
||||
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 == "toArrayBuffer") {
|
||||
jsi::HostFunctionType toArrayBuffer = [=](jsi::Runtime& runtime,
|
||||
const jsi::Value& thisArg,
|
||||
const jsi::Value* args,
|
||||
size_t count) -> jsi::Value {
|
||||
jsi::HostFunctionType toArrayBuffer = [=](jsi::Runtime& runtime, const jsi::Value& thisArg,
|
||||
const jsi::Value* args, size_t count) -> jsi::Value {
|
||||
auto buffer = this->frame->toByteBuffer();
|
||||
if (!buffer->isDirect()) {
|
||||
throw std::runtime_error("Failed to get byte content of Frame - array is not direct ByteBuffer!");
|
||||
throw std::runtime_error(
|
||||
"Failed to get byte content of Frame - array is not direct ByteBuffer!");
|
||||
}
|
||||
auto size = buffer->getDirectSize();
|
||||
|
||||
@@ -110,8 +102,10 @@ jsi::Value FrameHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pr
|
||||
}
|
||||
|
||||
// Get from global JS cache
|
||||
auto arrayBufferCache = runtime.global().getPropertyAsObject(runtime, ARRAYBUFFER_CACHE_PROP_NAME);
|
||||
auto arrayBuffer = vision::getTypedArray(runtime, arrayBufferCache).get<vision::TypedArrayKind::Uint8ClampedArray>(runtime);
|
||||
auto arrayBufferCache =
|
||||
runtime.global().getPropertyAsObject(runtime, ARRAYBUFFER_CACHE_PROP_NAME);
|
||||
auto arrayBuffer = vision::getTypedArray(runtime, arrayBufferCache)
|
||||
.get<vision::TypedArrayKind::Uint8ClampedArray>(runtime);
|
||||
if (arrayBuffer.size(runtime) != size) {
|
||||
arrayBuffer = vision::TypedArray<vision::TypedArrayKind::Uint8ClampedArray>(runtime, size);
|
||||
runtime.global().setProperty(runtime, ARRAYBUFFER_CACHE_PROP_NAME, arrayBuffer);
|
||||
@@ -123,7 +117,8 @@ jsi::Value FrameHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pr
|
||||
|
||||
return arrayBuffer;
|
||||
};
|
||||
return jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forUtf8(runtime, "toArrayBuffer"), 0, toArrayBuffer);
|
||||
return jsi::Function::createFromHostFunction(
|
||||
runtime, jsi::PropNameID::forUtf8(runtime, "toArrayBuffer"), 0, toArrayBuffer);
|
||||
}
|
||||
|
||||
if (name == "isValid") {
|
||||
|
@@ -4,11 +4,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <jsi/jsi.h>
|
||||
#include <jni.h>
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <vector>
|
||||
#include <jni.h>
|
||||
#include <jsi/jsi.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "JFrame.h"
|
||||
|
||||
@@ -17,15 +17,15 @@ namespace vision {
|
||||
using namespace facebook;
|
||||
|
||||
class JSI_EXPORT FrameHostObject : public jsi::HostObject {
|
||||
public:
|
||||
public:
|
||||
explicit FrameHostObject(const jni::alias_ref<JFrame::javaobject>& frame);
|
||||
~FrameHostObject();
|
||||
|
||||
public:
|
||||
jsi::Value get(jsi::Runtime &, const jsi::PropNameID &name) override;
|
||||
std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime &rt) override;
|
||||
public:
|
||||
jsi::Value get(jsi::Runtime&, const jsi::PropNameID& name) override;
|
||||
std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime& rt) override;
|
||||
|
||||
public:
|
||||
public:
|
||||
jni::global_ref<JFrame> frame;
|
||||
};
|
||||
|
||||
|
@@ -3,48 +3,49 @@
|
||||
//
|
||||
|
||||
#include "FrameProcessorPluginHostObject.h"
|
||||
#include <vector>
|
||||
#include "FrameHostObject.h"
|
||||
#include "JSIJNIConversion.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace vision {
|
||||
|
||||
using namespace facebook;
|
||||
|
||||
std::vector<jsi::PropNameID> FrameProcessorPluginHostObject::getPropertyNames(jsi::Runtime& runtime) {
|
||||
std::vector<jsi::PropNameID>
|
||||
FrameProcessorPluginHostObject::getPropertyNames(jsi::Runtime& runtime) {
|
||||
std::vector<jsi::PropNameID> result;
|
||||
result.push_back(jsi::PropNameID::forUtf8(runtime, std::string("call")));
|
||||
return result;
|
||||
}
|
||||
|
||||
jsi::Value FrameProcessorPluginHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& propName) {
|
||||
jsi::Value FrameProcessorPluginHostObject::get(jsi::Runtime& runtime,
|
||||
const jsi::PropNameID& propName) {
|
||||
auto name = propName.utf8(runtime);
|
||||
|
||||
if (name == "call") {
|
||||
return jsi::Function::createFromHostFunction(runtime,
|
||||
jsi::PropNameID::forUtf8(runtime, "call"),
|
||||
2,
|
||||
[=](jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
// Frame is first argument
|
||||
auto frameHostObject = arguments[0].asObject(runtime).asHostObject<FrameHostObject>(runtime);
|
||||
auto frame = frameHostObject->frame;
|
||||
return jsi::Function::createFromHostFunction(
|
||||
runtime, jsi::PropNameID::forUtf8(runtime, "call"), 2,
|
||||
[=](jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
// Frame is first argument
|
||||
auto frameHostObject =
|
||||
arguments[0].asObject(runtime).asHostObject<FrameHostObject>(runtime);
|
||||
auto frame = frameHostObject->frame;
|
||||
|
||||
// Options are second argument (possibly undefined)
|
||||
local_ref<JMap<jstring, jobject>> options = nullptr;
|
||||
if (count > 1) {
|
||||
options = JSIJNIConversion::convertJSIObjectToJNIMap(runtime, arguments[1].asObject(runtime));
|
||||
}
|
||||
// Options are second argument (possibly undefined)
|
||||
local_ref<JMap<jstring, jobject>> options = nullptr;
|
||||
if (count > 1) {
|
||||
options =
|
||||
JSIJNIConversion::convertJSIObjectToJNIMap(runtime, arguments[1].asObject(runtime));
|
||||
}
|
||||
|
||||
// Call actual plugin
|
||||
auto result = _plugin->callback(frame, options);
|
||||
// Call actual plugin
|
||||
auto result = _plugin->callback(frame, options);
|
||||
|
||||
// Convert result value to jsi::Value (possibly undefined)
|
||||
return JSIJNIConversion::convertJNIObjectToJSIValue(runtime, result);
|
||||
});
|
||||
// Convert result value to jsi::Value (possibly undefined)
|
||||
return JSIJNIConversion::convertJNIObjectToJSIValue(runtime, result);
|
||||
});
|
||||
}
|
||||
|
||||
return jsi::Value::undefined();
|
||||
|
@@ -4,27 +4,27 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <jsi/jsi.h>
|
||||
#include "JFrameProcessorPlugin.h"
|
||||
#include <memory>
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <jsi/jsi.h>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace vision {
|
||||
|
||||
using namespace facebook;
|
||||
|
||||
class FrameProcessorPluginHostObject: public jsi::HostObject {
|
||||
public:
|
||||
explicit FrameProcessorPluginHostObject(jni::alias_ref<JFrameProcessorPlugin::javaobject> plugin):
|
||||
_plugin(make_global(plugin)) { }
|
||||
~FrameProcessorPluginHostObject() { }
|
||||
class FrameProcessorPluginHostObject : public jsi::HostObject {
|
||||
public:
|
||||
explicit FrameProcessorPluginHostObject(jni::alias_ref<JFrameProcessorPlugin::javaobject> plugin)
|
||||
: _plugin(make_global(plugin)) {}
|
||||
~FrameProcessorPluginHostObject() {}
|
||||
|
||||
public:
|
||||
public:
|
||||
std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime& runtime) override;
|
||||
jsi::Value get(jsi::Runtime& runtime, const jsi::PropNameID& name) override;
|
||||
|
||||
private:
|
||||
private:
|
||||
jni::global_ref<JFrameProcessorPlugin::javaobject> _plugin;
|
||||
};
|
||||
|
||||
|
@@ -4,14 +4,14 @@
|
||||
|
||||
#include "JSIJNIConversion.h"
|
||||
|
||||
#include <jsi/jsi.h>
|
||||
#include <jni.h>
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <android/log.h>
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <jni.h>
|
||||
#include <jsi/jsi.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <memory>
|
||||
|
||||
#include "FrameHostObject.h"
|
||||
#include "JFrame.h"
|
||||
@@ -20,7 +20,8 @@ namespace vision {
|
||||
|
||||
using namespace facebook;
|
||||
|
||||
jni::local_ref<jni::JMap<jstring, jobject>> JSIJNIConversion::convertJSIObjectToJNIMap(jsi::Runtime& runtime, const jsi::Object& object) {
|
||||
jni::local_ref<jni::JMap<jstring, jobject>>
|
||||
JSIJNIConversion::convertJSIObjectToJNIMap(jsi::Runtime& runtime, const jsi::Object& object) {
|
||||
auto propertyNames = object.getPropertyNames(runtime);
|
||||
auto size = propertyNames.size(runtime);
|
||||
auto hashMap = jni::JHashMap<jstring, jobject>::create();
|
||||
@@ -34,25 +35,21 @@ jni::local_ref<jni::JMap<jstring, jobject>> JSIJNIConversion::convertJSIObjectTo
|
||||
// null
|
||||
|
||||
hashMap->put(key, nullptr);
|
||||
|
||||
} else if (value.isBool()) {
|
||||
// Boolean
|
||||
|
||||
auto boolean = value.getBool();
|
||||
hashMap->put(key, jni::JBoolean::valueOf(boolean));
|
||||
|
||||
} else if (value.isNumber()) {
|
||||
// Double
|
||||
|
||||
auto number = value.getNumber();
|
||||
hashMap->put(key, jni::JDouble::valueOf(number));
|
||||
|
||||
} else if (value.isString()) {
|
||||
// String
|
||||
|
||||
auto str = value.getString(runtime).utf8(runtime);
|
||||
hashMap->put(key, jni::make_jstring(str));
|
||||
|
||||
} else if (value.isObject()) {
|
||||
// Object
|
||||
|
||||
@@ -60,7 +57,6 @@ jni::local_ref<jni::JMap<jstring, jobject>> JSIJNIConversion::convertJSIObjectTo
|
||||
|
||||
if (valueAsObject.isArray(runtime)) {
|
||||
// List<Object>
|
||||
|
||||
} else if (valueAsObject.isHostObject(runtime)) {
|
||||
throw std::runtime_error("You can't pass HostObjects here.");
|
||||
} else {
|
||||
@@ -69,48 +65,47 @@ jni::local_ref<jni::JMap<jstring, jobject>> JSIJNIConversion::convertJSIObjectTo
|
||||
auto map = convertJSIObjectToJNIMap(runtime, valueAsObject);
|
||||
hashMap->put(key, map);
|
||||
}
|
||||
|
||||
} else {
|
||||
auto stringRepresentation = value.toString(runtime).utf8(runtime);
|
||||
throw std::runtime_error("Failed to convert jsi::Value to JNI value - unsupported type!" + stringRepresentation);
|
||||
throw std::runtime_error("Failed to convert jsi::Value to JNI value - unsupported type!" +
|
||||
stringRepresentation);
|
||||
}
|
||||
}
|
||||
|
||||
return hashMap;
|
||||
}
|
||||
|
||||
jsi::Value JSIJNIConversion::convertJNIObjectToJSIValue(jsi::Runtime &runtime, const jni::local_ref<jobject>& object) {
|
||||
jsi::Value JSIJNIConversion::convertJNIObjectToJSIValue(jsi::Runtime& runtime,
|
||||
const jni::local_ref<jobject>& object) {
|
||||
if (object == nullptr) {
|
||||
// null
|
||||
|
||||
return jsi::Value::undefined();
|
||||
|
||||
} else if (object->isInstanceOf(jni::JBoolean::javaClassStatic())) {
|
||||
// Boolean
|
||||
|
||||
static const auto getBooleanFunc = jni::findClassLocal("java/lang/Boolean")->getMethod<jboolean()>("booleanValue");
|
||||
static const auto getBooleanFunc =
|
||||
jni::findClassLocal("java/lang/Boolean")->getMethod<jboolean()>("booleanValue");
|
||||
auto boolean = getBooleanFunc(object.get());
|
||||
return jsi::Value(boolean == true);
|
||||
|
||||
} else if (object->isInstanceOf(jni::JDouble::javaClassStatic())) {
|
||||
// Double
|
||||
|
||||
static const auto getDoubleFunc = jni::findClassLocal("java/lang/Double")->getMethod<jdouble()>("doubleValue");
|
||||
static const auto getDoubleFunc =
|
||||
jni::findClassLocal("java/lang/Double")->getMethod<jdouble()>("doubleValue");
|
||||
auto d = getDoubleFunc(object.get());
|
||||
return jsi::Value(d);
|
||||
|
||||
} else if (object->isInstanceOf(jni::JInteger::javaClassStatic())) {
|
||||
// Integer
|
||||
|
||||
static const auto getIntegerFunc = jni::findClassLocal("java/lang/Integer")->getMethod<jint()>("intValue");
|
||||
static const auto getIntegerFunc =
|
||||
jni::findClassLocal("java/lang/Integer")->getMethod<jint()>("intValue");
|
||||
auto i = getIntegerFunc(object.get());
|
||||
return jsi::Value(i);
|
||||
|
||||
} else if (object->isInstanceOf(jni::JString::javaClassStatic())) {
|
||||
// String
|
||||
|
||||
return jsi::String::createFromUtf8(runtime, object->toString());
|
||||
|
||||
} else if (object->isInstanceOf(JList<jobject>::javaClassStatic())) {
|
||||
// List<E>
|
||||
|
||||
@@ -124,7 +119,6 @@ jsi::Value JSIJNIConversion::convertJNIObjectToJSIValue(jsi::Runtime &runtime, c
|
||||
i++;
|
||||
}
|
||||
return result;
|
||||
|
||||
} else if (object->isInstanceOf(JMap<jstring, jobject>::javaClassStatic())) {
|
||||
// Map<K, V>
|
||||
|
||||
|
@@ -4,19 +4,21 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <jsi/jsi.h>
|
||||
#include <jni.h>
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <jni.h>
|
||||
#include <jsi/jsi.h>
|
||||
|
||||
namespace vision {
|
||||
|
||||
namespace JSIJNIConversion {
|
||||
|
||||
using namespace facebook;
|
||||
using namespace facebook;
|
||||
|
||||
jni::local_ref<jni::JMap<jstring, jobject>> convertJSIObjectToJNIMap(jsi::Runtime& runtime, const jsi::Object& object);
|
||||
jni::local_ref<jni::JMap<jstring, jobject>> convertJSIObjectToJNIMap(jsi::Runtime& runtime,
|
||||
const jsi::Object& object);
|
||||
|
||||
jsi::Value convertJNIObjectToJSIValue(jsi::Runtime& runtime, const jni::local_ref<jobject>& object);
|
||||
jsi::Value convertJNIObjectToJSIValue(jsi::Runtime& runtime,
|
||||
const jni::local_ref<jobject>& object);
|
||||
|
||||
} // namespace JSIJNIConversion
|
||||
|
||||
|
@@ -12,12 +12,12 @@
|
||||
#include <android/log.h>
|
||||
#include <fbjni/fbjni.h>
|
||||
|
||||
#include "JSITypedArray.h"
|
||||
#include "FrameProcessorPluginHostObject.h"
|
||||
#include "JSITypedArray.h"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#if VISION_CAMERA_ENABLE_FRAME_PROCESSORS
|
||||
#include <react-native-worklets-core/WKTJsiWorkletContext.h>
|
||||
@@ -27,12 +27,12 @@ namespace vision {
|
||||
|
||||
using namespace facebook;
|
||||
|
||||
VisionCameraProxy::VisionCameraProxy(const jni::alias_ref<JVisionCameraProxy::javaobject>& javaProxy) {
|
||||
VisionCameraProxy::VisionCameraProxy(
|
||||
const jni::alias_ref<JVisionCameraProxy::javaobject>& javaProxy) {
|
||||
_javaProxy = make_global(javaProxy);
|
||||
}
|
||||
|
||||
VisionCameraProxy::~VisionCameraProxy() {
|
||||
}
|
||||
VisionCameraProxy::~VisionCameraProxy() {}
|
||||
|
||||
std::vector<jsi::PropNameID> VisionCameraProxy::getPropertyNames(jsi::Runtime& runtime) {
|
||||
std::vector<jsi::PropNameID> result;
|
||||
@@ -42,7 +42,8 @@ std::vector<jsi::PropNameID> VisionCameraProxy::getPropertyNames(jsi::Runtime& r
|
||||
return result;
|
||||
}
|
||||
|
||||
void VisionCameraProxy::setFrameProcessor(int viewTag, jsi::Runtime& runtime, const jsi::Object& object) {
|
||||
void VisionCameraProxy::setFrameProcessor(int viewTag, jsi::Runtime& runtime,
|
||||
const jsi::Object& object) {
|
||||
_javaProxy->cthis()->setFrameProcessor(viewTag, runtime, object);
|
||||
}
|
||||
|
||||
@@ -65,61 +66,50 @@ jsi::Value VisionCameraProxy::get(jsi::Runtime& runtime, const jsi::PropNameID&
|
||||
auto name = propName.utf8(runtime);
|
||||
|
||||
if (name == "setFrameProcessor") {
|
||||
return jsi::Function::createFromHostFunction(runtime,
|
||||
jsi::PropNameID::forUtf8(runtime, "setFrameProcessor"),
|
||||
1,
|
||||
[this](jsi::Runtime& runtime,
|
||||
const jsi::Value& thisValue,
|
||||
const jsi::Value* arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
auto viewTag = arguments[0].asNumber();
|
||||
auto object = arguments[1].asObject(runtime);
|
||||
this->setFrameProcessor(static_cast<int>(viewTag), runtime, object);
|
||||
return jsi::Value::undefined();
|
||||
});
|
||||
return jsi::Function::createFromHostFunction(
|
||||
runtime, jsi::PropNameID::forUtf8(runtime, "setFrameProcessor"), 1,
|
||||
[this](jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
auto viewTag = arguments[0].asNumber();
|
||||
auto object = arguments[1].asObject(runtime);
|
||||
this->setFrameProcessor(static_cast<int>(viewTag), runtime, object);
|
||||
return jsi::Value::undefined();
|
||||
});
|
||||
}
|
||||
if (name == "removeFrameProcessor") {
|
||||
return jsi::Function::createFromHostFunction(runtime,
|
||||
jsi::PropNameID::forUtf8(runtime, "removeFrameProcessor"),
|
||||
1,
|
||||
[this](jsi::Runtime& runtime,
|
||||
const jsi::Value& thisValue,
|
||||
const jsi::Value* arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
auto viewTag = arguments[0].asNumber();
|
||||
this->removeFrameProcessor(static_cast<int>(viewTag));
|
||||
return jsi::Value::undefined();
|
||||
});
|
||||
return jsi::Function::createFromHostFunction(
|
||||
runtime, jsi::PropNameID::forUtf8(runtime, "removeFrameProcessor"), 1,
|
||||
[this](jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
auto viewTag = arguments[0].asNumber();
|
||||
this->removeFrameProcessor(static_cast<int>(viewTag));
|
||||
return jsi::Value::undefined();
|
||||
});
|
||||
}
|
||||
if (name == "getFrameProcessorPlugin") {
|
||||
return jsi::Function::createFromHostFunction(runtime,
|
||||
jsi::PropNameID::forUtf8(runtime, "getFrameProcessorPlugin"),
|
||||
1,
|
||||
[this](jsi::Runtime& runtime,
|
||||
const jsi::Value& thisValue,
|
||||
const jsi::Value* arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
if (count < 1 || !arguments[0].isString()) {
|
||||
throw jsi::JSError(runtime, "First argument needs to be a string (pluginName)!");
|
||||
}
|
||||
auto pluginName = arguments[0].asString(runtime).utf8(runtime);
|
||||
auto options = count > 1 ? arguments[1].asObject(runtime) : jsi::Object(runtime);
|
||||
return jsi::Function::createFromHostFunction(
|
||||
runtime, jsi::PropNameID::forUtf8(runtime, "getFrameProcessorPlugin"), 1,
|
||||
[this](jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
if (count < 1 || !arguments[0].isString()) {
|
||||
throw jsi::JSError(runtime, "First argument needs to be a string (pluginName)!");
|
||||
}
|
||||
auto pluginName = arguments[0].asString(runtime).utf8(runtime);
|
||||
auto options = count > 1 ? arguments[1].asObject(runtime) : jsi::Object(runtime);
|
||||
|
||||
return this->getFrameProcessorPlugin(runtime, pluginName, options);
|
||||
});
|
||||
return this->getFrameProcessorPlugin(runtime, pluginName, options);
|
||||
});
|
||||
}
|
||||
|
||||
return jsi::Value::undefined();
|
||||
}
|
||||
|
||||
|
||||
void VisionCameraInstaller::install(jni::alias_ref<jni::JClass>,
|
||||
jni::alias_ref<JVisionCameraProxy::javaobject> proxy) {
|
||||
// global.VisionCameraProxy
|
||||
auto visionCameraProxy = std::make_shared<VisionCameraProxy>(proxy);
|
||||
jsi::Runtime& runtime = *proxy->cthis()->getJSRuntime();
|
||||
runtime.global().setProperty(runtime,
|
||||
"VisionCameraProxy",
|
||||
runtime.global().setProperty(runtime, "VisionCameraProxy",
|
||||
jsi::Object::createFromHostObject(runtime, visionCameraProxy));
|
||||
}
|
||||
|
||||
|
@@ -6,43 +6,43 @@
|
||||
|
||||
#include <jsi/jsi.h>
|
||||
|
||||
#include "JVisionCameraScheduler.h"
|
||||
#include "JVisionCameraProxy.h"
|
||||
#include "JVisionCameraScheduler.h"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace vision {
|
||||
|
||||
using namespace facebook;
|
||||
|
||||
class VisionCameraProxy: public jsi::HostObject {
|
||||
public:
|
||||
class VisionCameraProxy : public jsi::HostObject {
|
||||
public:
|
||||
explicit VisionCameraProxy(const jni::alias_ref<JVisionCameraProxy::javaobject>& javaProxy);
|
||||
~VisionCameraProxy();
|
||||
|
||||
public:
|
||||
public:
|
||||
std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime& runtime) override;
|
||||
jsi::Value get(jsi::Runtime& runtime, const jsi::PropNameID& name) override;
|
||||
|
||||
private:
|
||||
private:
|
||||
void setFrameProcessor(int viewTag, jsi::Runtime& runtime, const jsi::Object& frameProcessor);
|
||||
void removeFrameProcessor(int viewTag);
|
||||
jsi::Value getFrameProcessorPlugin(jsi::Runtime& runtime, const std::string& name, const jsi::Object& options);
|
||||
jsi::Value getFrameProcessorPlugin(jsi::Runtime& runtime, const std::string& name,
|
||||
const jsi::Object& options);
|
||||
|
||||
private:
|
||||
private:
|
||||
jni::global_ref<JVisionCameraProxy::javaobject> _javaProxy;
|
||||
static constexpr const char* TAG = "VisionCameraProxy";
|
||||
};
|
||||
|
||||
|
||||
class VisionCameraInstaller: public jni::JavaClass<VisionCameraInstaller> {
|
||||
public:
|
||||
static auto constexpr kJavaDescriptor = "Lcom/mrousavy/camera/frameprocessor/VisionCameraInstaller;";
|
||||
class VisionCameraInstaller : public jni::JavaClass<VisionCameraInstaller> {
|
||||
public:
|
||||
static auto constexpr kJavaDescriptor =
|
||||
"Lcom/mrousavy/camera/frameprocessor/VisionCameraInstaller;";
|
||||
static void registerNatives() {
|
||||
javaClassStatic()->registerNatives({
|
||||
makeNativeMethod("install", VisionCameraInstaller::install)
|
||||
});
|
||||
javaClassStatic()->registerNatives(
|
||||
{makeNativeMethod("install", VisionCameraInstaller::install)});
|
||||
}
|
||||
static void install(jni::alias_ref<jni::JClass> clazz,
|
||||
jni::alias_ref<JVisionCameraProxy::javaobject> proxy);
|
||||
|
@@ -4,9 +4,9 @@
|
||||
|
||||
#include "JFrame.h"
|
||||
|
||||
#include <jni.h>
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <fbjni/ByteBuffer.h>
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <jni.h>
|
||||
|
||||
namespace vision {
|
||||
|
||||
|
@@ -4,9 +4,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <jni.h>
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <fbjni/ByteBuffer.h>
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <jni.h>
|
||||
|
||||
namespace vision {
|
||||
|
||||
@@ -16,7 +16,7 @@ using namespace jni;
|
||||
struct JFrame : public JavaClass<JFrame> {
|
||||
static constexpr auto kJavaDescriptor = "Lcom/mrousavy/camera/frameprocessor/Frame;";
|
||||
|
||||
public:
|
||||
public:
|
||||
int getWidth() const;
|
||||
int getHeight() const;
|
||||
bool getIsValid() const;
|
||||
|
@@ -5,11 +5,11 @@
|
||||
#if VISION_CAMERA_ENABLE_FRAME_PROCESSORS
|
||||
|
||||
#include "JFrameProcessor.h"
|
||||
#include <jni.h>
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <jni.h>
|
||||
|
||||
#include <utility>
|
||||
#include "JFrame.h"
|
||||
#include <utility>
|
||||
|
||||
namespace vision {
|
||||
|
||||
@@ -17,9 +17,7 @@ using namespace facebook;
|
||||
using namespace jni;
|
||||
|
||||
void JFrameProcessor::registerNatives() {
|
||||
registerHybrid({
|
||||
makeNativeMethod("call", JFrameProcessor::call)
|
||||
});
|
||||
registerHybrid({makeNativeMethod("call", JFrameProcessor::call)});
|
||||
}
|
||||
|
||||
using TSelf = jni::local_ref<JFrameProcessor::javaobject>;
|
||||
@@ -35,7 +33,8 @@ TSelf JFrameProcessor::create(const std::shared_ptr<RNWorklet::JsiWorklet>& work
|
||||
return JFrameProcessor::newObjectCxxArgs(worklet, context);
|
||||
}
|
||||
|
||||
void JFrameProcessor::callWithFrameHostObject(const std::shared_ptr<FrameHostObject>& frameHostObject) const {
|
||||
void JFrameProcessor::callWithFrameHostObject(
|
||||
const std::shared_ptr<FrameHostObject>& frameHostObject) const {
|
||||
// Call the Frame Processor on the Worklet Runtime
|
||||
jsi::Runtime& runtime = _workletContext->getWorkletRuntime();
|
||||
|
||||
@@ -51,8 +50,11 @@ void JFrameProcessor::callWithFrameHostObject(const std::shared_ptr<FrameHostObj
|
||||
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));
|
||||
auto logFn = jsRuntime.global()
|
||||
.getPropertyAsObject(jsRuntime, "console")
|
||||
.getPropertyAsFunction(jsRuntime, "error");
|
||||
logFn.call(jsRuntime, jsi::String::createFromUtf8(
|
||||
jsRuntime, "Frame Processor threw an error: " + message));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -6,43 +6,44 @@
|
||||
|
||||
#if VISION_CAMERA_ENABLE_FRAME_PROCESSORS
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <jni.h>
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <jni.h>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <react-native-worklets-core/WKTJsiWorklet.h>
|
||||
#include <react-native-worklets-core/WKTJsiHostObject.h>
|
||||
#include <react-native-worklets-core/WKTJsiWorklet.h>
|
||||
|
||||
#include "JFrame.h"
|
||||
#include "FrameHostObject.h"
|
||||
#include "JFrame.h"
|
||||
|
||||
namespace vision {
|
||||
|
||||
using namespace facebook;
|
||||
|
||||
struct JFrameProcessor : public jni::HybridClass<JFrameProcessor> {
|
||||
public:
|
||||
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);
|
||||
static jni::local_ref<JFrameProcessor::javaobject>
|
||||
create(const std::shared_ptr<RNWorklet::JsiWorklet>& worklet,
|
||||
const std::shared_ptr<RNWorklet::JsiWorkletContext>& context);
|
||||
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Call the JS Frame Processor.
|
||||
*/
|
||||
void call(alias_ref<JFrame::javaobject> frame);
|
||||
|
||||
private:
|
||||
private:
|
||||
// Private constructor. Use `create(..)` to create new instances.
|
||||
explicit JFrameProcessor(std::shared_ptr<RNWorklet::JsiWorklet> worklet,
|
||||
std::shared_ptr<RNWorklet::JsiWorkletContext> context);
|
||||
|
||||
private:
|
||||
private:
|
||||
void callWithFrameHostObject(const std::shared_ptr<FrameHostObject>& frameHostObject) const;
|
||||
|
||||
private:
|
||||
private:
|
||||
friend HybridBase;
|
||||
std::shared_ptr<RNWorklet::WorkletInvoker> _workletInvoker;
|
||||
std::shared_ptr<RNWorklet::JsiWorkletContext> _workletContext;
|
||||
|
@@ -4,8 +4,8 @@
|
||||
|
||||
#include "JFrameProcessorPlugin.h"
|
||||
|
||||
#include <jni.h>
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <jni.h>
|
||||
|
||||
namespace vision {
|
||||
|
||||
@@ -14,8 +14,9 @@ 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 {
|
||||
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);
|
||||
|
@@ -4,8 +4,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <jni.h>
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <jni.h>
|
||||
#include <string>
|
||||
|
||||
#include "JFrame.h"
|
||||
@@ -16,9 +16,10 @@ using namespace facebook;
|
||||
using namespace jni;
|
||||
|
||||
struct JFrameProcessorPlugin : public JavaClass<JFrameProcessorPlugin> {
|
||||
static constexpr auto kJavaDescriptor = "Lcom/mrousavy/camera/frameprocessor/FrameProcessorPlugin;";
|
||||
static constexpr auto kJavaDescriptor =
|
||||
"Lcom/mrousavy/camera/frameprocessor/FrameProcessorPlugin;";
|
||||
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Call the plugin.
|
||||
*/
|
||||
|
@@ -5,8 +5,8 @@
|
||||
#include "JVisionCameraProxy.h"
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <jsi/jsi.h>
|
||||
|
||||
@@ -25,10 +25,10 @@ using TJSCallInvokerHolder = jni::alias_ref<facebook::react::CallInvokerHolder::
|
||||
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) {
|
||||
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;
|
||||
|
||||
@@ -41,13 +41,9 @@ JVisionCameraProxy::JVisionCameraProxy(const jni::alias_ref<JVisionCameraProxy::
|
||||
};
|
||||
auto runOnWorklet = [scheduler](std::function<void()>&& f) {
|
||||
// Run on Frame Processor Worklet Runtime
|
||||
scheduler->cthis()->dispatchAsync([f = std::move(f)](){
|
||||
f();
|
||||
});
|
||||
scheduler->cthis()->dispatchAsync([f = std::move(f)]() { f(); });
|
||||
};
|
||||
_workletContext = std::make_shared<RNWorklet::JsiWorkletContext>("VisionCamera",
|
||||
runtime,
|
||||
runOnJS,
|
||||
_workletContext = std::make_shared<RNWorklet::JsiWorkletContext>("VisionCamera", runtime, runOnJS,
|
||||
runOnWorklet);
|
||||
__android_log_write(ANDROID_LOG_INFO, TAG, "Worklet Context created!");
|
||||
#else
|
||||
@@ -64,14 +60,13 @@ JVisionCameraProxy::~JVisionCameraProxy() {
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
void JVisionCameraProxy::setFrameProcessor(int viewTag,
|
||||
jsi::Runtime& runtime,
|
||||
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"));
|
||||
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") {
|
||||
@@ -80,7 +75,9 @@ void JVisionCameraProxy::setFrameProcessor(int viewTag,
|
||||
throw std::runtime_error("Unknown FrameProcessor.type passed! Received: " + frameProcessorType);
|
||||
}
|
||||
|
||||
auto setFrameProcessorMethod = javaClassLocal()->getMethod<void(int, alias_ref<JFrameProcessor::javaobject>)>("setFrameProcessor");
|
||||
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!");
|
||||
@@ -92,23 +89,21 @@ void JVisionCameraProxy::removeFrameProcessor(int viewTag) {
|
||||
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");
|
||||
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)
|
||||
});
|
||||
registerHybrid({makeNativeMethod("initHybrid", JVisionCameraProxy::initHybrid)});
|
||||
}
|
||||
|
||||
TSelf JVisionCameraProxy::initHybrid(
|
||||
alias_ref<jhybridobject> jThis,
|
||||
jlong jsRuntimePointer,
|
||||
TJSCallInvokerHolder jsCallInvokerHolder,
|
||||
const TScheduler& scheduler) {
|
||||
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
|
||||
|
@@ -4,16 +4,16 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ReactCommon/CallInvokerHolder.h>
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <jsi/jsi.h>
|
||||
#include <ReactCommon/CallInvokerHolder.h>
|
||||
|
||||
#include "JFrameProcessor.h"
|
||||
#include "JFrameProcessorPlugin.h"
|
||||
#include "JVisionCameraScheduler.h"
|
||||
#include "JFrameProcessor.h"
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#if VISION_CAMERA_ENABLE_FRAME_PROCESSORS
|
||||
#include <react-native-worklets-core/WKTJsiWorkletContext.h>
|
||||
@@ -24,20 +24,20 @@ namespace vision {
|
||||
using namespace facebook;
|
||||
|
||||
class JVisionCameraProxy : public jni::HybridClass<JVisionCameraProxy> {
|
||||
public:
|
||||
public:
|
||||
~JVisionCameraProxy();
|
||||
static void registerNatives();
|
||||
|
||||
void setFrameProcessor(int viewTag,
|
||||
jsi::Runtime& runtime,
|
||||
const jsi::Object& frameProcessor);
|
||||
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);
|
||||
jni::local_ref<JFrameProcessorPlugin::javaobject>
|
||||
getFrameProcessorPlugin(const std::string& name, jni::local_ref<JMap<jstring, jobject>> options);
|
||||
|
||||
jsi::Runtime* getJSRuntime() { return _runtime; }
|
||||
jsi::Runtime* getJSRuntime() {
|
||||
return _runtime;
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
friend HybridBase;
|
||||
jni::global_ref<JVisionCameraProxy::javaobject> _javaPart;
|
||||
jsi::Runtime* _runtime;
|
||||
@@ -52,10 +52,10 @@ class JVisionCameraProxy : public jni::HybridClass<JVisionCameraProxy> {
|
||||
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);
|
||||
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
|
||||
|
@@ -36,8 +36,8 @@ void JVisionCameraScheduler::trigger() {
|
||||
|
||||
void JVisionCameraScheduler::registerNatives() {
|
||||
registerHybrid({
|
||||
makeNativeMethod("initHybrid", JVisionCameraScheduler::initHybrid),
|
||||
makeNativeMethod("trigger", JVisionCameraScheduler::trigger),
|
||||
makeNativeMethod("initHybrid", JVisionCameraScheduler::initHybrid),
|
||||
makeNativeMethod("trigger", JVisionCameraScheduler::trigger),
|
||||
});
|
||||
}
|
||||
|
||||
|
@@ -4,10 +4,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <jni.h>
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <queue>
|
||||
#include <jni.h>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
|
||||
namespace vision {
|
||||
|
||||
@@ -19,26 +19,28 @@ using namespace facebook;
|
||||
*
|
||||
* 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
|
||||
* 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;";
|
||||
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:
|
||||
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)) {}
|
||||
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();
|
||||
|
Reference in New Issue
Block a user