Conversation
| @@ -26,7 +27,12 @@ | |||
| "backgroundColor": "#ffffff" | |||
| }, | |||
| "package": "com.anonymous.computervision", | |||
| "permissions": ["android.permission.CAMERA"] | |||
| "permissions": [ | |||
| "android.permission.CAMERA", | |||
| "android.permission.INTERNET", | |||
| "android.permission.RECORD_AUDIO", | |||
| "android.permission.ACCESS_NETWORK_STATE" | |||
| ] | |||
| // Pre-allocate buffers | ||
| g_resizedRgb = cv::Mat(g_modelHeight, g_modelWidth, CV_8UC3); | ||
|
|
||
| g_modelLoaded = true; |
There was a problem hiding this comment.
Thread safety on the model lifecycle
Three issues stacked on this line:
-
Publication ordering — plain
bool g_modelLoadedis written here without ordering vs the prior writes tog_segmentation(L69) and dims (L75–76). The frame thread reading at L105 can observeg_modelLoaded == truewithg_segmentation == nullptr→ null deref. Data race per the C++ memory model regardless. -
TOCTOU vs
unloadModel— L105 checks the flag, L143 dereferencesg_segmentationfor tens of ms.unloadModelruns fromrelease()on a different thread andreset()s theunique_ptr→ UAF. -
Process-global state — these are file-scope globals; two
ExecutorchFrameProcessorinstances clobber each other. The per-instance KotlinmodelLoadedflag misleadingly suggests isolation.
Suggested fix: hold a std::shared_ptr<BaseSemanticSegmentation> and snapshot it locally under a mutex at the start of runSegmentation, so unload just drops a refcount.
The iOS side (ExecutorchFrameProcessor.mm) has the same bugs and they're more reachable: load is explicitly dispatch_async'd to a background queue (L80), unloadModel is on the public API (L112), and the whole class is a +sharedInstance singleton. Worth converging both platforms on the same synchronization model.
Drive-by in this file: g_resizedRgb (L33) is allocated but never used; g_lastDebugLogTime (L36) is unused.
| cv::Mat rgbRotated; | ||
| if (rotation == 90) { | ||
| cv::rotate(rgb, rgbRotated, cv::ROTATE_90_CLOCKWISE); | ||
| } else if (rotation == 180) { | ||
| cv::rotate(rgb, rgbRotated, cv::ROTATE_180); | ||
| } else if (rotation == 270) { | ||
| cv::rotate(rgb, rgbRotated, cv::ROTATE_90_COUNTERCLOCKWISE); | ||
| } else { | ||
| rgbRotated = rgb; | ||
| } |
There was a problem hiding this comment.
Maybe we can refactor this into separate function?
| static int g_modelHeight = 256; | ||
| static int g_modelWidth = 256; | ||
|
|
||
| // Pre-allocated buffers | ||
| static cv::Mat g_resizedRgb; | ||
|
|
||
| // Debug logging rate limiter | ||
| static long long g_lastDebugLogTime = 0; |
There was a problem hiding this comment.
Plain int and long long types, may use int32_t and int64_t instead.



Description
Adds react-native-executorch-webrtc package for real-time background blur in Fishjam WebRTC video calls using on-device ExecuTorch segmentation models.
Key features:
Architecture:
Introduces a breaking change?
Type of change
Tested on
Testing instructions
You'll need to setup your fishjam account, and verify this example works properly:
Screenshots
Related issues
Checklist
Additional notes