Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: ✨ V3 ✨ #1466

Merged
merged 115 commits into from Sep 1, 2023
Merged

feat: ✨ V3 ✨ #1466

merged 115 commits into from Sep 1, 2023

Conversation

mrousavy
Copy link
Owner

@mrousavy mrousavy commented Feb 9, 2023

See #1376

Breaking Changes

  • Frame Processors are now synchronous. Previously they ran on a separate Thread. If you want to run something on a separate Thread now, use runAsync inside a Frame Processor
  • Frame Processor Plugins are no longer in the global object with the __ prefix, but rather stored directly in the FrameProcessorPlugins object exported by react-native-vision-camera. (e.g. replace __scanQRCodes(frame) with FrameProcessorPlugins.scanQRCodes(frame))
  • frameProcessorFps no longer exists. Use runAtTargetFps inside a Frame Processor to throttle some calls.
  • onFrameProcessorPerformanceSuggestionAvailable no longer exists. Use the FPS display (enableFpsGraph={true}) to see how your Frame Processor performs over time. This is more in-line with how React Native works (Dev Tools / Perf Monitor)
  • VisionCamera V3 will not work on RN 0.70 or below. You need to use RN 0.71. This is because the build script got way simpler and smaller, making it faster to build and way less error prone. Backwards compatibility is just too complex here.
  • Reanimated is no longer used as a Worklet Runtime. Instead, VisionCamera now uses react-native-worklets-core.

Progress

You can test the latest V3 release by creating a new RN project with RN 0.71 and installing VisionCamera + RNWorklets:

yarn add react-native-vision-camera@3.0.0-rc.5
yarn add react-native-worklets-core
yarn add @shopify/react-native-skia

Things to test:

  • TensorFlow Lite plugin to load any .tflite model!! ✨ (see this PR for more info, will be a separate library soon)
  • Drawing onto a Frame using Skia!! 🎉
  • Using frame.toArrayBuffer() to get the Frame's byte content in JS
  • New Android build script. This should drastically speed up the build time! 💨
  • New Worklet library. This replaces Reanimated Worklets. Should be faster and more stable :)
  • New synchronous Frame Processors. Should be faster :)
  • runAtTargetFps and runAsync in Frame Processors
  • Using HostObjects or HostFunctions (like models from PyTorch) inside a Frame Processor. This will probably require a few native bindings on PyTorch's end to make the integration work (cc @raedle)

Overall V3 is close to completion. I have a few things to do the coming days so not sure how much work I can put into this. If anyone wants to support the development of v3, I'd appreciate donations / sponsors: https://github.com/sponsors/mrousavy ❤️ :)

Related issues

features

...and then pretty much every Android issue lol

.. maybe also (not tested):

mrousavy and others added 2 commits February 8, 2023 17:48
* chore: Upgrade Example to RN 0.71

* chore: Upgrade all libs

* fix: Fix CameraRoll installation

* Update Gradle Tools

* fix: Fix buildscripts

* Clean out build.gradle

* fix: Fix Kotlin setup

* fix: Move kotlin-android dependency to lib

* Move `_setGlobalConsole`

* Update gradle-wrapper.properties

* Rebuild lockfiles

* chore: Update build:gradle

* Update StatusBarBlurBackground.tsx

* Use Java 11 in Workflows

* Update MediaPage.tsx

* Add `google` repository to build.gradle

* Double Java Heap size

* Increase heap size

* Alternative args

* Update build.gradle
@github-actions

This comment was marked as off-topic.

* Setup RN Worklets

* Use RN Worklets on iOS

* Fix console

* Add `installFrameProcessorBindings()` function

* Add `FrameProcessorPlugins` proxy (BREAKING CHANGE)

* Clean up docs

* Update FRAME_PROCESSORS.mdx

* Use RN Worklets 0.2.5

* feat: Android build setup

* Rewrite Android Frame Processor Part

* Update CMakeLists.txt

* fix: Add react-native-worklets Gradle dependency

* Update Podfile.lock

* fix build

* gradle:7.4.1

* Init JSI Bindings in method on Android

* Fix Folly flags

* fix: Init `FrameProcessorRuntimeManager` later

* fix: Wrap in `<GestureHandlerRootView>`

* Refactor plugins

* fix: Remove enableFrameProcessors

* Install RN Worklets from current GH master

* Update babel.config.js

* Update CameraViewModule.kt

* Update ImageProxyUtils.java

* feat: Upgrade to Reanimated v3

* fix: Fix crash on Worklet init

* Update RN Worklets to latest master

* fix: Simplify FP Plugins Proxy
…1472)

Before, Frame Processors ran on a separate Thread.

After, Frame Processors run fully synchronous and always at the same FPS as the Camera.

Two new functions have been introduced:

* `runAtTargetFps(fps: number, func: () => void)`: Runs the given code as often as the given `fps`, effectively throttling it's calls.
* `runAsync(frame: Frame, func: () => void)`: Runs the given function on a separate Thread for Frame Processing. A strong reference to the Frame is held as long as the function takes to execute.

You can use `runAtTargetFps` to throttle calls to a specific API (e.g. if your Camera is running at 60 FPS, but you only want to run face detection at ~25 FPS, use `runAtTargetFps(25, ...)`.)

You can use `runAsync` to run a heavy algorithm asynchronous, so that the Camera is not blocked while your algorithm runs. This is useful if your main sync processor draws something, and your async processor is doing some image analysis on the side. 

You can also combine both functions.

Examples:

```js
const frameProcessor = useFrameProcessor((frame) => {
  'worklet'
  console.log("I'm running at 60 FPS!")
}, [])
```

```js
const frameProcessor = useFrameProcessor((frame) => {
  'worklet'
  console.log("I'm running at 60 FPS!")

  runAtTargetFps(10, () => {
    'worklet'
    console.log("I'm running at 10 FPS!")
  })
}, [])
```



```js
const frameProcessor = useFrameProcessor((frame) => {
  'worklet'
  console.log("I'm running at 60 FPS!")

  runAsync(frame, () => {
    'worklet'
    console.log("I'm running on another Thread, I can block for longer!")
  })
}, [])
```

```js
const frameProcessor = useFrameProcessor((frame) => {
  'worklet'
  console.log("I'm running at 60 FPS!")

  runAtTargetFps(10, () => {
    'worklet'
    runAsync(frame, () => {
      'worklet'
      console.log("I'm running on another Thread at 10 FPS, I can block for longer!")
    })
  })
}, [])
```
* fix: Fix CI for "Build Android"

* update versions

* Update Gemfile.lock

* format swift

* fix: Fix swift lint

* Update .swiftlint.yml

* Use C++17 for lint

* fix: Fix C++ lints
@alexstanbury

This comment was marked as resolved.

@mrousavy

This comment was marked as outdated.

@alexstanbury

This comment was marked as resolved.

* Create Shaders.ts

* Add `previewType` and `enableFpsGraph`

* Add RN Skia native dependency

* Add Skia Preview View on iOS

* Pass 1

* Update FrameHostObject.mm

* Wrap Canvas

* Lockfiles

* fix: Fix stuff

* chore: Upgrade RNWorklets

* Add `previewType` to set the Preview

* feat: Add Example

* Update project.pbxproj

* `enableFpsGraph`

* Cache the `std::shared_ptr<FrameHostObject>`

* Update CameraView+RecordVideo.swift

* Update SkiaMetalCanvasProvider.mm

* Android: Integrate Skia Dependency

* fix: Use new Prefix

* Add example for rendering shader

* chore: Upgrade CameraX

* Remove KTX

* Enable `viewBinding`

* Revert "Enable `viewBinding`"

This reverts commit f2a603f.

* Revert "chore: Upgrade CameraX"

This reverts commit 8dc832c.

* Remove unneeded `ProcessCameraProvider.getInstance()` call

* fix: Add REA hotfix patch

* fix: Fix FrameHostObject dead in runAsync

* fix: Make `runAsync` run truly async by dropping new Frames while executing

* chore: Upgrade RN Worklets to latest

* chore: Upgrade RN Skia

* Revert "Remove KTX"

This reverts commit 253f586.

* Make Skia optional in CMake

* Fix import

* Update CMakeLists.txt

* Update build.gradle

* Update CameraView.kt

* Update CameraView.kt

* Update CameraView.kt

* Update Shaders.ts

* Center Blur

* chore: Upgrade RN Worklets

* feat: Add `toByteArray()`, `orientation`, `isMirrored` and `timestamp` to `Frame` (#1487)

* feat: Implement `orientation` and `isMirrored` on Frame

* feat: Add `toArrayBuffer()` func

* perf: Do faster buffer copy

* feat: Implement `toArrayBuffer()` on Android

* feat: Add `orientation` and `isMirrored` to Android

* feat: Add `timestamp` to Frame

* Update Frame.ts

* Update JImageProxy.h

* Update FrameHostObject.cpp

* Update FrameHostObject.cpp

* Update CameraPage.tsx

* fix: Format Swift
Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remaining comments which cannot be posted as a review comment to avoid GitHub Rate Limit

cpp/JSITypedArray.cpp Outdated Show resolved Hide resolved
cpp/JSITypedArray.cpp Outdated Show resolved Hide resolved
cpp/JSITypedArray.cpp Outdated Show resolved Hide resolved
cpp/JSITypedArray.cpp Outdated Show resolved Hide resolved
cpp/JSITypedArray.cpp Outdated Show resolved Hide resolved
cpp/JSITypedArray.h Outdated Show resolved Hide resolved
cpp/JSITypedArray.h Outdated Show resolved Hide resolved
cpp/JSITypedArray.h Outdated Show resolved Hide resolved
cpp/JSITypedArray.h Outdated Show resolved Hide resolved
cpp/JSITypedArray.h Outdated Show resolved Hide resolved
@mrousavy
Copy link
Owner Author

Notice you spelt it workets in the package name, not worklets.

Ahh, thank you!

I think I just assumed you weren't supporting Paper due to this #1376 (comment)

Edited the comment :)

I am getting build errors on Android.

Yep I mainly focused on iOS for now, am currently looking more into Android. thanks for the logs, will investigate!

cpp/JSITypedArray.h Outdated Show resolved Hide resolved
cpp/JSITypedArray.h Outdated Show resolved Hide resolved
cpp/JSITypedArray.h Outdated Show resolved Hide resolved
cpp/JSITypedArray.h Outdated Show resolved Hide resolved
cpp/JSITypedArray.h Outdated Show resolved Hide resolved
cpp/JSITypedArray.h Outdated Show resolved Hide resolved
cpp/JSITypedArray.h Outdated Show resolved Hide resolved
cpp/JSITypedArray.h Outdated Show resolved Hide resolved
cpp/JSITypedArray.h Outdated Show resolved Hide resolved
cpp/JSITypedArray.h Outdated Show resolved Hide resolved
@mrousavy
Copy link
Owner Author

mrousavy commented Feb 21, 2023

Update 21.2.2023:

I just released VisionCamera v3.0.0-rc.2, which includes the following features:

  • Drawing onto the Frame using Skia!! 🎉 (iOS only for now, I will probably need to rewrite the entire Android part from CameraX to Camera2 (one of Android's worst APIs) for this)
  • Frame now has .toByteArray() to read the bytes straight from JS!
  • Frame now also has .orientation, .isMirrored and .timestamp
  • Add fpsGraph to show the Camera's preview FPS. Good for debugging performance
  • Fixed the regex thing build error
  • Makes runAsync truly async.
  • Uses latest Skia and RN Worklets for more compatibility

Try it:

yarn add react-native-vision-camera@rc
yarn add react-native-worklets@https://github.com/chrfalch/react-native-worklets#d62d76c
yarn add @shopify/react-native-skia@0.1.175

Things to test: all of the features above

@alexstanbury

This comment was marked as off-topic.

@mrousavy

This comment was marked as off-topic.

…me`'s lifecycle (#1488)

* fix: fix C++ lint

* fix: attach `InvalidateCacheOnDestroy` to `jsi::Runtime`
@mrousavy
Copy link
Owner Author

Okay I had a mistake in android/src/main/AndroidManifest.xml, test on iOS for now (or hotpatch this commit if you want to test Android) :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment