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: Separate VisionCamera into two subspecs #2761

Merged
merged 22 commits into from
Apr 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/build-ios.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ jobs:
run: yarn install --frozen-lockfile --cwd ..
- name: Remove worklets, skia and reanimated
run: yarn remove react-native-worklets-core @shopify/react-native-skia react-native-reanimated --cwd ..
- name: Remove Example Plugins
run: rm -rf "Frame Processor Plugins/"

- name: Restore buildcache
uses: mikehardy/buildcache-action@v2
Expand Down
115 changes: 69 additions & 46 deletions package/VisionCamera.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,33 @@ package = JSON.parse(File.read(File.join(__dir__, "package.json")))

nodeModules = File.join(File.dirname(`cd "#{Pod::Config.instance.installation_root.to_s}" && node --print "require.resolve('react-native/package.json')"`), '..')

enableFrameProcessors = true
if defined?($VCEnableFrameProcessors)
Pod::UI.puts "[VisionCamera] $VCEnableFrameProcessors is set to #{$VCEnableFrameProcessors}!"
enableFrameProcessors = $VCEnableFrameProcessors
end
Pod::UI.puts "[VisionCamera] Thank you for using VisionCamera ❤️"

enableLocation = true
if defined?($VCEnableLocation)
Pod::UI.puts "[VisionCamera] $VCEnableLocation is set to #{$VCEnableLocation}!"
enableLocation = $VCEnableLocation
else
Pod::UI.puts "[VisionCamera] Building with CLLocation APIs as $VCEnableLocation is not set.."
Pod::UI.puts "[VisionCamera] $VCEnableLocation is not set, enabling CLLocation APIs by default..."
end

enableFrameProcessors = true
if defined?($VCEnableFrameProcessors)
Pod::UI.puts "[VisionCamera] $VCEnableFrameProcessors is set to #{$VCEnableFrameProcessors}!"
enableFrameProcessors = $VCEnableFrameProcessors
else
Pod::UI.puts "[VisionCamera] $VCEnableFrameProcessors is not set, enabling Frame Processors if Worklets is installed..."
end

Pod::UI.puts("[VisionCamera] node modules #{Dir.exist?(nodeModules) ? "found at #{nodeModules}" : "not found!"}")
workletsPath = File.join(nodeModules, "react-native-worklets-core")
hasWorklets = File.exist?(workletsPath) && enableFrameProcessors
Pod::UI.puts("[VisionCamera] react-native-worklets-core #{hasWorklets ? "found" : "not found"}, Frame Processors #{hasWorklets ? "enabled" : "disabled"}!")
hasWorklets = File.exist?(workletsPath)
if hasWorklets
Pod::UI.puts("[VisionCamera] react-native-worklets-core found, Frame Processors #{enableFrameProcessors ? "enabled" : "disabled"}!")
else
Pod::UI.puts("[VisionCamera] react-native-worklets-core not found - Frame Processors are #{hasWorklets ? "enabled" : "disabled"}!")
enableFrameProcessors = false
end

Pod::Spec.new do |s|
s.name = "VisionCamera"
Expand All @@ -36,49 +45,63 @@ Pod::Spec.new do |s|
s.source = { :git => "https://github.com/mrousavy/react-native-vision-camera.git", :tag => "#{s.version}" }

s.pod_target_xcconfig = {
"GCC_PREPROCESSOR_DEFINITIONS" => "$(inherited) VISION_CAMERA_ENABLE_FRAME_PROCESSORS=#{hasWorklets}",
"SWIFT_ACTIVE_COMPILATION_CONDITIONS" => "$(inherited) #{hasWorklets ? "VISION_CAMERA_ENABLE_FRAME_PROCESSORS" : ""} #{enableLocation ? "VISION_CAMERA_ENABLE_LOCATION" : ""}",
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
"HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/cpp/\"/** "
"GCC_PREPROCESSOR_DEFINITIONS" => "$(inherited) VISION_CAMERA_ENABLE_FRAME_PROCESSORS=#{enableFrameProcessors}",
"SWIFT_ACTIVE_COMPILATION_CONDITIONS" => "$(inherited) #{enableFrameProcessors ? "VISION_CAMERA_ENABLE_FRAME_PROCESSORS" : ""}",
}

s.requires_arc = true

# All source files that should be publicly visible
# Note how this does not include headers, since those can nameclash.
s.source_files = [
# Core
"ios/*.{m,mm,swift}",
"ios/Core/*.{m,mm,swift}",
"ios/Extensions/*.{m,mm,swift}",
"ios/Parsers/*.{m,mm,swift}",
"ios/React Utils/*.{m,mm,swift}",
"ios/Types/*.{m,mm,swift}",
"ios/CameraBridge.h",

# Frame Processors
hasWorklets ? "ios/Frame Processor/*.{m,mm,swift}" : "",
hasWorklets ? "ios/Frame Processor/Frame.h" : "",
hasWorklets ? "ios/Frame Processor/FrameProcessor.h" : "",
hasWorklets ? "ios/Frame Processor/FrameProcessorPlugin.h" : "",
hasWorklets ? "ios/Frame Processor/FrameProcessorPluginRegistry.h" : "",
hasWorklets ? "ios/Frame Processor/SharedArray.h" : "",
hasWorklets ? "ios/Frame Processor/VisionCameraProxy.h" : "",
hasWorklets ? "cpp/**/*.{cpp}" : "",
]
# Any private headers that are not globally unique should be mentioned here.
# Otherwise there will be a nameclash, since CocoaPods flattens out any header directories
# See https://github.com/firebase/firebase-ios-sdk/issues/4035 for more details.
s.preserve_paths = [
"cpp/**/*.h",
"ios/**/*.h"
]

s.dependency "React"
s.dependency "React-Core"
s.dependency "React-callinvoker"

if hasWorklets
s.dependency "react-native-worklets-core"
s.subspec 'Core' do |core|
# VisionCamera Core Swift codebase
core.source_files = [
"ios/*.{m,mm,swift}",
"ios/Core/*.{m,mm,swift}",
"ios/Extensions/*.{m,mm,swift}",
"ios/Parsers/*.{m,mm,swift}",
"ios/React Utils/*.{m,mm,swift}",
"ios/Types/*.{m,mm,swift}",
"ios/CameraBridge.h",
]

core.pod_target_xcconfig = {
"SWIFT_ACTIVE_COMPILATION_CONDITIONS" => "$(inherited) #{enableLocation ? "VISION_CAMERA_ENABLE_LOCATION" : ""}",
}

if enableFrameProcessors
core.dependency "VisionCamera/FrameProcessors"
end
end

if enableFrameProcessors
s.subspec 'FrameProcessors' do |fp|
# VisionCamera Frame Processors C++ codebase (optional)
fp.dependency "React"
fp.dependency "React-callinvoker"
fp.dependency "react-native-worklets-core"

fp.source_files = [
# C++ sources
"ios/Frame Processor/*.{h,m,mm,cpp}",
"cpp/**/*.{h,cpp}",
]
fp.public_header_files = [
# Swift/Objective-C visible headers
"ios/Frame Processor/Frame.h",
"ios/Frame Processor/FrameProcessor.h",
"ios/Frame Processor/FrameProcessorPlugin.h",
"ios/Frame Processor/FrameProcessorPluginRegistry.h",
"ios/Frame Processor/SharedArray.h",
"ios/Frame Processor/VisionCameraProxyDelegate.h",
"ios/Frame Processor/VisionCameraProxyHolder.h",
"ios/Frame Processor/VisionCameraInstaller.h",
]

fp.pod_target_xcconfig = {
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
"HEADER_SEARCH_PATHS" => "$(inherited) \"$(PODS_TARGET_SRCROOT)/cpp/\"/** "
}
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
#if __has_include(<VisionCamera/FrameProcessorPlugin.h>)
#import <Foundation/Foundation.h>
#import <VisionCamera/FrameProcessorPlugin.h>
#import <VisionCamera/FrameProcessorPluginRegistry.h>
#import <VisionCamera/Frame.h>
#import <VisionCamera/SharedArray.h>

Expand Down
15 changes: 11 additions & 4 deletions package/example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,14 @@ PODS:
- RCT-Folly (= 2021.07.22.00)
- React-Core
- SocketRocket (0.6.1)
- VisionCamera (4.0.0-beta.15):
- VisionCamera (4.0.0-beta.16):
- React-Core
- VisionCamera/Core (= 4.0.0-beta.16)
- VisionCamera/FrameProcessors (= 4.0.0-beta.16)
- VisionCamera/Core (4.0.0-beta.16):
- React-Core
- VisionCamera/FrameProcessors
- VisionCamera/FrameProcessors (4.0.0-beta.16):
- React
- React-callinvoker
- React-Core
Expand Down Expand Up @@ -701,9 +708,9 @@ SPEC CHECKSUMS:
RNStaticSafeAreaInsets: 055ddbf5e476321720457cdaeec0ff2ba40ec1b8
RNVectorIcons: 23b6e11af4aaf104d169b1b0afa7e5cf96c676ce
SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17
VisionCamera: e31119ce6f25cf982100e62db2846bee6653f52b
VisionCamera: 129f7e33050d9f45660e4510565ebbd1a0c15126
Yoga: 4c3aa327e4a6a23eeacd71f61c81df1bcdf677d5

PODFILE CHECKSUM: 299b350392623e1b01615935e236438d90fd2cff
PODFILE CHECKSUM: 29d07573cd9f2aa1ecf53c481819da07fd66822e

COCOAPODS: 1.11.3
COCOAPODS: 1.14.3
7 changes: 5 additions & 2 deletions package/ios/CameraBridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,16 @@

#import <React/RCTEventEmitter.h>
#import <React/RCTFPSGraph.h>
#import <React/RCTLog.h>
#import <React/RCTUIManager.h>
#import <React/RCTViewManager.h>

#if VISION_CAMERA_ENABLE_FRAME_PROCESSORS
#import "Frame.h"
#import "FrameProcessor.h"
#import "FrameProcessorPlugin.h"
#import "FrameProcessorPluginRegistry.h"
#import "SharedArray.h"
#import "VisionCameraProxy.h"
#import "VisionCameraInstaller.h"
#import "VisionCameraProxyDelegate.h"
#import "VisionCameraProxyHolder.h"
#endif
36 changes: 36 additions & 0 deletions package/ios/CameraViewManager+VisionCameraProxyDelegate.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//
// CameraViewManager+VisionCameraProxyDelegate.swift
// VisionCamera
//
// Created by Marc Rousavy on 20.04.24.
//

import Foundation

#if VISION_CAMERA_ENABLE_FRAME_PROCESSORS

extension CameraViewManager: VisionCameraProxyDelegate {
func getDispatchQueue() -> DispatchQueue {
return CameraQueues.videoQueue
}

func getBridge() -> RCTBridge {
return bridge
}

func setFrameProcessor(_ frameProcessor: FrameProcessor, forView viewTag: NSNumber) {
DispatchQueue.main.async {
let view = self.getCameraView(withTag: viewTag)
view.frameProcessor = frameProcessor
}
}

func removeFrameProcessor(forView viewTag: NSNumber) {
DispatchQueue.main.async {
let view = self.getCameraView(withTag: viewTag)
view.frameProcessor = nil
}
}
}

#endif
4 changes: 2 additions & 2 deletions package/ios/CameraViewManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ final class CameraViewManager: RCTViewManager {
final func installFrameProcessorBindings() -> NSNumber {
#if VISION_CAMERA_ENABLE_FRAME_PROCESSORS
// Called on JS Thread (blocking sync method)
let result = VisionCameraInstaller.install(to: bridge)
let result = VisionCameraInstaller.install(with: self)
return NSNumber(value: result)
#else
return false as NSNumber
Expand Down Expand Up @@ -148,7 +148,7 @@ final class CameraViewManager: RCTViewManager {

// MARK: Private

private func getCameraView(withTag tag: NSNumber) -> CameraView {
func getCameraView(withTag tag: NSNumber) -> CameraView {
// swiftlint:disable force_cast
return bridge.uiManager.view(forReactTag: tag) as! CameraView
// swiftlint:enable force_cast
Expand Down
14 changes: 9 additions & 5 deletions package/ios/Core/LocationProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,15 @@ class LocationProvider {
}

private var authorizationStatus: CLAuthorizationStatus {
if #available(iOS 14.0, *) {
return locationManager.authorizationStatus
} else {
return CLLocationManager.authorizationStatus()
}
#if VISION_CAMERA_ENABLE_LOCATION
if #available(iOS 14.0, *) {
return locationManager.authorizationStatus
} else {
return CLLocationManager.authorizationStatus()
}
#else
return .restricted
#endif
}

var hasPermission: Bool {
Expand Down
3 changes: 2 additions & 1 deletion package/ios/Frame Processor/FrameProcessorPlugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
#pragma once

#import "Frame.h"
#import "VisionCameraProxy.h"
#import "FrameProcessorPluginRegistry.h"
#import "VisionCameraProxyHolder.h"
#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN
Expand Down
5 changes: 4 additions & 1 deletion package/ios/Frame Processor/FrameProcessorPluginRegistry.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@

#import "Frame.h"
#import "FrameProcessorPlugin.h"
#import "VisionCameraProxy.h"
#import "VisionCameraProxyHolder.h"
#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

// forward-declare the Plugin - caller should always include anyways.
@class FrameProcessorPlugin;

@interface FrameProcessorPluginRegistry : NSObject

typedef FrameProcessorPlugin* _Nonnull (^PluginInitializerFunction)(VisionCameraProxyHolder* proxy, NSDictionary* _Nullable options);
Expand Down
6 changes: 3 additions & 3 deletions package/ios/Frame Processor/JSINSObjectConversion.mm
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
//

#import "JSINSObjectConversion.h"
#import "../Frame Processor/Frame.h"
#import "../Frame Processor/FrameHostObject.h"
#import "../Frame Processor/SharedArray.h"
#import "Frame.h"
#import "FrameHostObject.h"
#import "SharedArray.h"
#import <Foundation/Foundation.h>
#import <React/RCTBridge.h>
#import <ReactCommon/CallInvoker.h>
Expand Down
2 changes: 1 addition & 1 deletion package/ios/Frame Processor/SharedArray.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

#pragma once

#import "VisionCameraProxy.h"
#import "VisionCameraProxyHolder.h"
#import <Foundation/Foundation.h>

#ifdef __cplusplus
Expand Down
23 changes: 23 additions & 0 deletions package/ios/Frame Processor/VisionCameraInstaller.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// VisionCameraInstaller.h
// Pods
//
// Created by Marc Rousavy on 20.04.24.
//

#pragma once

#import "VisionCameraProxyDelegate.h"

NS_ASSUME_NONNULL_BEGIN

/**
A static class to install/inject the VisionCameraProxy into the global JS runtime.
*/
@interface VisionCameraInstaller : NSObject

+ (BOOL)installWithDelegate:(id<VisionCameraProxyDelegate>)delegate;

@end

NS_ASSUME_NONNULL_END
35 changes: 35 additions & 0 deletions package/ios/Frame Processor/VisionCameraInstaller.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//
// VisionCameraInstaller.mm
// DoubleConversion
//
// Created by Marc Rousavy on 20.04.24.
//

#import "VisionCameraInstaller.h"
#import "VisionCameraProxy.h"
#import <Foundation/Foundation.h>

#import <React/RCTBridge+Private.h>
#import <React/RCTBridge.h>
#import <ReactCommon/RCTTurboModuleManager.h>

@implementation VisionCameraInstaller

+ (BOOL)installWithDelegate:(id<VisionCameraProxyDelegate>)delegate {
// TODO: Migrate away from RCTBridge to support new arch.
RCTBridge* bridge = delegate.getBridge;
RCTCxxBridge* cxxBridge = (RCTCxxBridge*)bridge;
if (!cxxBridge.runtime) {
return NO;
}

jsi::Runtime& runtime = *(jsi::Runtime*)cxxBridge.runtime;

// global.VisionCameraProxy
auto visionCameraProxy = std::make_shared<VisionCameraProxy>(runtime, bridge.jsCallInvoker, delegate);
runtime.global().setProperty(runtime, "VisionCameraProxy", jsi::Object::createFromHostObject(runtime, visionCameraProxy));

return YES;
}

@end
Loading
Loading