feat: Make Frame Processor Plugins object-oriented on iOS as well (#1496)
* feat: Make Frame Processor Plugins object-oriented on iOS as well * Add Plugin in AppDelegate
This commit is contained in:
		@@ -41,29 +41,35 @@ For reference see the [CLI's docs](https://github.com/mateusz1913/vision-camera-
 | 
				
			|||||||
2. Create an Objective-C source file, for the QR Code Plugin this will be called `QRCodeFrameProcessorPlugin.m`.
 | 
					2. Create an Objective-C source file, for the QR Code Plugin this will be called `QRCodeFrameProcessorPlugin.m`.
 | 
				
			||||||
3. Add the following code:
 | 
					3. Add the following code:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```objc {12}
 | 
					```objc
 | 
				
			||||||
#import <VisionCamera/FrameProcessorPlugin.h>
 | 
					#import <VisionCamera/FrameProcessorPlugin.h>
 | 
				
			||||||
#import <VisionCamera/Frame.h>
 | 
					#import <VisionCamera/Frame.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@interface QRCodeFrameProcessorPlugin : NSObject
 | 
					@interface QRCodeFrameProcessorPlugin : FrameProcessorPlugin
 | 
				
			||||||
@end
 | 
					@end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@implementation QRCodeFrameProcessorPlugin
 | 
					@implementation QRCodeFrameProcessorPlugin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline id scanQRCodes(Frame* frame, NSArray* args) {
 | 
					- (NSString *)name {
 | 
				
			||||||
 | 
					  return @"scanQRCodes";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- (id)callback:(Frame *)frame withArguments:(NSArray<id> *)arguments {
 | 
				
			||||||
  CMSampleBufferRef buffer = frame.buffer;
 | 
					  CMSampleBufferRef buffer = frame.buffer;
 | 
				
			||||||
  UIImageOrientation orientation = frame.orientation;
 | 
					  UIImageOrientation orientation = frame.orientation;
 | 
				
			||||||
  // code goes here
 | 
					  // code goes here
 | 
				
			||||||
  return @[];
 | 
					  return @[];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VISION_EXPORT_FRAME_PROCESSOR(scanQRCodes)
 | 
					+ (void) load {
 | 
				
			||||||
 | 
					  [self registerPlugin:[[ExampleFrameProcessorPlugin alloc] init]];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@end
 | 
					@end
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
:::note
 | 
					:::note
 | 
				
			||||||
The Frame Processor Plugin will be exposed to JS through the `FrameProcessorPlugins` object using the same name as the Objective-C function. In this case, it would be `FrameProcessorPlugins.scanQRCodes(...)`.
 | 
					The Frame Processor Plugin will be exposed to JS through the `FrameProcessorPlugins` object using the name returned from the `name` getter. In this case, it would be `FrameProcessorPlugins.scanQRCodes(...)`.
 | 
				
			||||||
:::
 | 
					:::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
4. **Implement your Frame Processing.** See the [Example Plugin (Objective-C)](https://github.com/mrousavy/react-native-vision-camera/blob/main/example/ios/Frame%20Processor%20Plugins/Example%20Plugin%20%28Objective%2DC%29) for reference.
 | 
					4. **Implement your Frame Processing.** See the [Example Plugin (Objective-C)](https://github.com/mrousavy/react-native-vision-camera/blob/main/example/ios/Frame%20Processor%20Plugins/Example%20Plugin%20%28Objective%2DC%29) for reference.
 | 
				
			||||||
@@ -83,27 +89,16 @@ The Frame Processor Plugin will be exposed to JS through the `FrameProcessorPlug
 | 
				
			|||||||
#import <VisionCamera/Frame.h>
 | 
					#import <VisionCamera/Frame.h>
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
4. Create an Objective-C source file with the same name as the Swift file, for the QR Code Plugin this will be `QRCodeFrameProcessorPlugin.m`. Add the following code:
 | 
					4. In the Swift file, add the following code:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```objc
 | 
					```swift
 | 
				
			||||||
#import <VisionCamera/FrameProcessorPlugin.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@interface VISION_EXPORT_SWIFT_FRAME_PROCESSOR(scanQRCodes, QRCodeFrameProcessorPlugin)
 | 
					 | 
				
			||||||
@end
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
:::note
 | 
					 | 
				
			||||||
The first parameter in the Macro specifies the JS function name. Make sure it is unique across other Frame Processors.
 | 
					 | 
				
			||||||
:::
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
5. In the Swift file, add the following code:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```swift {8}
 | 
					 | 
				
			||||||
@objc(QRCodeFrameProcessorPlugin)
 | 
					@objc(QRCodeFrameProcessorPlugin)
 | 
				
			||||||
public class QRCodeFrameProcessorPlugin: NSObject, FrameProcessorPluginBase {
 | 
					public class QRCodeFrameProcessorPlugin: FrameProcessorPlugin {
 | 
				
			||||||
 | 
					  override public func name() -> String! {
 | 
				
			||||||
 | 
					    return "scanQRCodes"
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @objc
 | 
					  public override func callback(_ frame: Frame!, withArguments arguments: [Any]!) -> Any! {
 | 
				
			||||||
  public static func callback(_ frame: Frame!, withArgs _: [Any]!) -> Any! {
 | 
					 | 
				
			||||||
    let buffer = frame.buffer
 | 
					    let buffer = frame.buffer
 | 
				
			||||||
    let orientation = frame.orientation
 | 
					    let orientation = frame.orientation
 | 
				
			||||||
    // code goes here
 | 
					    // code goes here
 | 
				
			||||||
@@ -112,7 +107,27 @@ public class QRCodeFrameProcessorPlugin: NSObject, FrameProcessorPluginBase {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
6. **Implement your frame processing.** See [Example Plugin (Swift)](https://github.com/mrousavy/react-native-vision-camera/blob/main/example/ios/Frame%20Processor%20Plugins/Example%20Plugin%20%28Swift%29) for reference.
 | 
					5. In your `AppDelegate.m`, add the following imports (you can skip this if your AppDelegate is in Swift):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```objc
 | 
				
			||||||
 | 
					#import "YOUR_XCODE_PROJECT_NAME-Swift.h"
 | 
				
			||||||
 | 
					#import <VisionCamera/FrameProcessorPlugin.h>
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					6. In your `AppDelegate.m`, add the following code to `application:didFinishLaunchingWithOptions:`:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```objc {5}
 | 
				
			||||||
 | 
					- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [FrameProcessorPlugin registerPlugin:[[QRCodeFrameProcessorPlugin alloc] init]];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return [super application:application didFinishLaunchingWithOptions:launchOptions];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					7. **Implement your frame processing.** See [Example Plugin (Swift)](https://github.com/mrousavy/react-native-vision-camera/blob/main/example/ios/Frame%20Processor%20Plugins/Example%20Plugin%20%28Swift%29) for reference.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
</TabItem>
 | 
					</TabItem>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,12 +11,16 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Example for an Objective-C Frame Processor plugin
 | 
					// Example for an Objective-C Frame Processor plugin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@interface ExampleFrameProcessorPlugin : NSObject
 | 
					@interface ExampleFrameProcessorPlugin : FrameProcessorPlugin
 | 
				
			||||||
@end
 | 
					@end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@implementation ExampleFrameProcessorPlugin
 | 
					@implementation ExampleFrameProcessorPlugin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline id example_plugin(Frame* frame, NSArray* arguments) {
 | 
					- (NSString *)name {
 | 
				
			||||||
 | 
					  return @"example_plugin";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- (id)callback:(Frame *)frame withArguments:(NSArray<id> *)arguments {
 | 
				
			||||||
  CVPixelBufferRef imageBuffer = CMSampleBufferGetImageBuffer(frame.buffer);
 | 
					  CVPixelBufferRef imageBuffer = CMSampleBufferGetImageBuffer(frame.buffer);
 | 
				
			||||||
  NSLog(@"ExamplePlugin: %zu x %zu Image. Logging %lu parameters:", CVPixelBufferGetWidth(imageBuffer), CVPixelBufferGetHeight(imageBuffer), (unsigned long)arguments.count);
 | 
					  NSLog(@"ExamplePlugin: %zu x %zu Image. Logging %lu parameters:", CVPixelBufferGetWidth(imageBuffer), CVPixelBufferGetHeight(imageBuffer), (unsigned long)arguments.count);
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
@@ -36,6 +40,8 @@ static inline id example_plugin(Frame* frame, NSArray* arguments) {
 | 
				
			|||||||
  };
 | 
					  };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VISION_EXPORT_FRAME_PROCESSOR(example_plugin)
 | 
					+ (void) load {
 | 
				
			||||||
 | 
					  [self registerPlugin:[[ExampleFrameProcessorPlugin alloc] init]];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@end
 | 
					@end
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,13 +0,0 @@
 | 
				
			|||||||
//
 | 
					 | 
				
			||||||
//  ExamplePluginSwift.m
 | 
					 | 
				
			||||||
//  VisionCamera
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
//  Created by Marc Rousavy on 01.05.21.
 | 
					 | 
				
			||||||
//  Copyright © 2021 mrousavy. All rights reserved.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#import <Foundation/Foundation.h>
 | 
					 | 
				
			||||||
#import <VisionCamera/FrameProcessorPlugin.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@interface VISION_EXPORT_SWIFT_FRAME_PROCESSOR(example_plugin_swift, ExamplePluginSwift)
 | 
					 | 
				
			||||||
@end
 | 
					 | 
				
			||||||
@@ -9,16 +9,20 @@
 | 
				
			|||||||
import AVKit
 | 
					import AVKit
 | 
				
			||||||
import Vision
 | 
					import Vision
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@objc(ExamplePluginSwift)
 | 
					 | 
				
			||||||
public class ExamplePluginSwift: NSObject, FrameProcessorPluginBase {
 | 
					 | 
				
			||||||
@objc
 | 
					@objc
 | 
				
			||||||
    public static func callback(_ frame: Frame!, withArgs args: [Any]!) -> Any! {
 | 
					public class ExamplePluginSwift : FrameProcessorPlugin {
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  override public func name() -> String! {
 | 
				
			||||||
 | 
					    return "example_plugin_swift"
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  public override func callback(_ frame: Frame!, withArguments arguments: [Any]!) -> Any! {
 | 
				
			||||||
      guard let imageBuffer = CMSampleBufferGetImageBuffer(frame.buffer) else {
 | 
					      guard let imageBuffer = CMSampleBufferGetImageBuffer(frame.buffer) else {
 | 
				
			||||||
          return nil
 | 
					          return nil
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
        NSLog("ExamplePlugin: \(CVPixelBufferGetWidth(imageBuffer)) x \(CVPixelBufferGetHeight(imageBuffer)) Image. Logging \(args.count) parameters:")
 | 
					      NSLog("ExamplePlugin: \(CVPixelBufferGetWidth(imageBuffer)) x \(CVPixelBufferGetHeight(imageBuffer)) Image. Logging \(arguments.count) parameters:")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        args.forEach { arg in
 | 
					      arguments.forEach { arg in
 | 
				
			||||||
          var string = "\(arg)"
 | 
					          var string = "\(arg)"
 | 
				
			||||||
          if let array = arg as? NSArray {
 | 
					          if let array = arg as? NSArray {
 | 
				
			||||||
              string = (array as Array).description
 | 
					              string = (array as Array).description
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -436,7 +436,7 @@ PODS:
 | 
				
			|||||||
    - React-Core
 | 
					    - React-Core
 | 
				
			||||||
  - RNVectorIcons (9.2.0):
 | 
					  - RNVectorIcons (9.2.0):
 | 
				
			||||||
    - React-Core
 | 
					    - React-Core
 | 
				
			||||||
  - VisionCamera (3.0.0-rc.1):
 | 
					  - VisionCamera (3.0.0-rc.2):
 | 
				
			||||||
    - React
 | 
					    - React
 | 
				
			||||||
    - React-callinvoker
 | 
					    - React-callinvoker
 | 
				
			||||||
    - React-Core
 | 
					    - React-Core
 | 
				
			||||||
@@ -644,7 +644,7 @@ SPEC CHECKSUMS:
 | 
				
			|||||||
  RNScreens: 218801c16a2782546d30bd2026bb625c0302d70f
 | 
					  RNScreens: 218801c16a2782546d30bd2026bb625c0302d70f
 | 
				
			||||||
  RNStaticSafeAreaInsets: 055ddbf5e476321720457cdaeec0ff2ba40ec1b8
 | 
					  RNStaticSafeAreaInsets: 055ddbf5e476321720457cdaeec0ff2ba40ec1b8
 | 
				
			||||||
  RNVectorIcons: fcc2f6cb32f5735b586e66d14103a74ce6ad61f8
 | 
					  RNVectorIcons: fcc2f6cb32f5735b586e66d14103a74ce6ad61f8
 | 
				
			||||||
  VisionCamera: 0d154cd0ab9043a3c8a4908fb57ad65c9e1f3baf
 | 
					  VisionCamera: e4f19a6c22cfa146736bdfe8df057e2ed5ca8dd3
 | 
				
			||||||
  Yoga: 5ed1699acbba8863755998a4245daa200ff3817b
 | 
					  Yoga: 5ed1699acbba8863755998a4245daa200ff3817b
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PODFILE CHECKSUM: d53724fe402c2547f1dd1cc571bbe77d9820e636
 | 
					PODFILE CHECKSUM: d53724fe402c2547f1dd1cc571bbe77d9820e636
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,10 +11,9 @@
 | 
				
			|||||||
		13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
 | 
							13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
 | 
				
			||||||
		13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
 | 
							13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
 | 
				
			||||||
		81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
 | 
							81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
 | 
				
			||||||
		B8DB3BD5263DE8B7004C18D7 /* BuildFile in Sources */ = {isa = PBXBuildFile; };
 | 
							B8DB3BD5263DE8B7004C18D7 /* (null) in Sources */ = {isa = PBXBuildFile; };
 | 
				
			||||||
		B8DB3BDC263DEA31004C18D7 /* ExampleFrameProcessorPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = B8DB3BD8263DEA31004C18D7 /* ExampleFrameProcessorPlugin.m */; };
 | 
							B8DB3BDC263DEA31004C18D7 /* ExampleFrameProcessorPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = B8DB3BD8263DEA31004C18D7 /* ExampleFrameProcessorPlugin.m */; };
 | 
				
			||||||
		B8DB3BDD263DEA31004C18D7 /* ExamplePluginSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8DB3BDA263DEA31004C18D7 /* ExamplePluginSwift.swift */; };
 | 
							B8DB3BDD263DEA31004C18D7 /* ExamplePluginSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8DB3BDA263DEA31004C18D7 /* ExamplePluginSwift.swift */; };
 | 
				
			||||||
		B8DB3BDE263DEA31004C18D7 /* ExamplePluginSwift.m in Sources */ = {isa = PBXBuildFile; fileRef = B8DB3BDB263DEA31004C18D7 /* ExamplePluginSwift.m */; };
 | 
					 | 
				
			||||||
		B8F0E10825E0199F00586F16 /* File.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8F0E10725E0199F00586F16 /* File.swift */; };
 | 
							B8F0E10825E0199F00586F16 /* File.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8F0E10725E0199F00586F16 /* File.swift */; };
 | 
				
			||||||
		C0B129659921D2EA967280B2 /* libPods-VisionCameraExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3CDCFE89C25C89320B98945E /* libPods-VisionCameraExample.a */; };
 | 
							C0B129659921D2EA967280B2 /* libPods-VisionCameraExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3CDCFE89C25C89320B98945E /* libPods-VisionCameraExample.a */; };
 | 
				
			||||||
/* End PBXBuildFile section */
 | 
					/* End PBXBuildFile section */
 | 
				
			||||||
@@ -31,7 +30,6 @@
 | 
				
			|||||||
		81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = VisionCameraExample/LaunchScreen.storyboard; sourceTree = "<group>"; };
 | 
							81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = VisionCameraExample/LaunchScreen.storyboard; sourceTree = "<group>"; };
 | 
				
			||||||
		B8DB3BD8263DEA31004C18D7 /* ExampleFrameProcessorPlugin.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ExampleFrameProcessorPlugin.m; sourceTree = "<group>"; };
 | 
							B8DB3BD8263DEA31004C18D7 /* ExampleFrameProcessorPlugin.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ExampleFrameProcessorPlugin.m; sourceTree = "<group>"; };
 | 
				
			||||||
		B8DB3BDA263DEA31004C18D7 /* ExamplePluginSwift.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExamplePluginSwift.swift; sourceTree = "<group>"; };
 | 
							B8DB3BDA263DEA31004C18D7 /* ExamplePluginSwift.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExamplePluginSwift.swift; sourceTree = "<group>"; };
 | 
				
			||||||
		B8DB3BDB263DEA31004C18D7 /* ExamplePluginSwift.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ExamplePluginSwift.m; sourceTree = "<group>"; };
 | 
					 | 
				
			||||||
		B8F0E10625E0199F00586F16 /* VisionCameraExample-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "VisionCameraExample-Bridging-Header.h"; sourceTree = "<group>"; };
 | 
							B8F0E10625E0199F00586F16 /* VisionCameraExample-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "VisionCameraExample-Bridging-Header.h"; sourceTree = "<group>"; };
 | 
				
			||||||
		B8F0E10725E0199F00586F16 /* File.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = File.swift; sourceTree = "<group>"; };
 | 
							B8F0E10725E0199F00586F16 /* File.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = File.swift; sourceTree = "<group>"; };
 | 
				
			||||||
		C1D342AD8210E7627A632602 /* Pods-VisionCameraExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-VisionCameraExample.debug.xcconfig"; path = "Target Support Files/Pods-VisionCameraExample/Pods-VisionCameraExample.debug.xcconfig"; sourceTree = "<group>"; };
 | 
							C1D342AD8210E7627A632602 /* Pods-VisionCameraExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-VisionCameraExample.debug.xcconfig"; path = "Target Support Files/Pods-VisionCameraExample/Pods-VisionCameraExample.debug.xcconfig"; sourceTree = "<group>"; };
 | 
				
			||||||
@@ -138,7 +136,6 @@
 | 
				
			|||||||
			isa = PBXGroup;
 | 
								isa = PBXGroup;
 | 
				
			||||||
			children = (
 | 
								children = (
 | 
				
			||||||
				B8DB3BDA263DEA31004C18D7 /* ExamplePluginSwift.swift */,
 | 
									B8DB3BDA263DEA31004C18D7 /* ExamplePluginSwift.swift */,
 | 
				
			||||||
				B8DB3BDB263DEA31004C18D7 /* ExamplePluginSwift.m */,
 | 
					 | 
				
			||||||
			);
 | 
								);
 | 
				
			||||||
			path = "Example Plugin (Swift)";
 | 
								path = "Example Plugin (Swift)";
 | 
				
			||||||
			sourceTree = "<group>";
 | 
								sourceTree = "<group>";
 | 
				
			||||||
@@ -383,11 +380,10 @@
 | 
				
			|||||||
			files = (
 | 
								files = (
 | 
				
			||||||
				13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */,
 | 
									13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */,
 | 
				
			||||||
				B8DB3BDC263DEA31004C18D7 /* ExampleFrameProcessorPlugin.m in Sources */,
 | 
									B8DB3BDC263DEA31004C18D7 /* ExampleFrameProcessorPlugin.m in Sources */,
 | 
				
			||||||
				B8DB3BD5263DE8B7004C18D7 /* BuildFile in Sources */,
 | 
									B8DB3BD5263DE8B7004C18D7 /* (null) in Sources */,
 | 
				
			||||||
				B8DB3BDD263DEA31004C18D7 /* ExamplePluginSwift.swift in Sources */,
 | 
									B8DB3BDD263DEA31004C18D7 /* ExamplePluginSwift.swift in Sources */,
 | 
				
			||||||
				B8F0E10825E0199F00586F16 /* File.swift in Sources */,
 | 
									B8F0E10825E0199F00586F16 /* File.swift in Sources */,
 | 
				
			||||||
				13B07FC11A68108700A75B9A /* main.m in Sources */,
 | 
									13B07FC11A68108700A75B9A /* main.m in Sources */,
 | 
				
			||||||
				B8DB3BDE263DEA31004C18D7 /* ExamplePluginSwift.m in Sources */,
 | 
					 | 
				
			||||||
			);
 | 
								);
 | 
				
			||||||
			runOnlyForDeploymentPostprocessing = 0;
 | 
								runOnlyForDeploymentPostprocessing = 0;
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,8 @@
 | 
				
			|||||||
#import "AppDelegate.h"
 | 
					#import "AppDelegate.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#import <React/RCTBundleURLProvider.h>
 | 
					#import <React/RCTBundleURLProvider.h>
 | 
				
			||||||
 | 
					#import "VisionCameraExample-Swift.h"
 | 
				
			||||||
 | 
					#import <VisionCamera/FrameProcessorPlugin.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@implementation AppDelegate
 | 
					@implementation AppDelegate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -11,6 +13,8 @@
 | 
				
			|||||||
  // They will be passed down to the ViewController used by React Native.
 | 
					  // They will be passed down to the ViewController used by React Native.
 | 
				
			||||||
  self.initialProps = @{};
 | 
					  self.initialProps = @{};
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
 | 
					  [FrameProcessorPlugin registerPlugin:[[ExamplePluginSwift alloc] init]];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return [super application:application didFinishLaunchingWithOptions:launchOptions];
 | 
					  return [super application:application didFinishLaunchingWithOptions:launchOptions];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,57 +6,27 @@
 | 
				
			|||||||
//  Copyright © 2021 mrousavy. All rights reserved.
 | 
					//  Copyright © 2021 mrousavy. All rights reserved.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef FrameProcessorPlugin_h
 | 
					#pragma once
 | 
				
			||||||
#define FrameProcessorPlugin_h
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#import <Foundation/Foundation.h>
 | 
					#import <Foundation/Foundation.h>
 | 
				
			||||||
#import "FrameProcessorPluginRegistry.h"
 | 
					 | 
				
			||||||
#import "Frame.h"
 | 
					#import "Frame.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@protocol FrameProcessorPluginBase
 | 
					/// The base class for a Frame Processor Plugin which can be called synchronously from a JS Frame Processor.
 | 
				
			||||||
+ (id) callback:(Frame*)frame withArgs:(NSArray<id>*)args;
 | 
					///
 | 
				
			||||||
 | 
					/// Subclass this class in a Swift or Objective-C class and override the `callback:withArguments:` method, and
 | 
				
			||||||
 | 
					/// implement your Frame Processing there.
 | 
				
			||||||
 | 
					/// Then, in your App's startup (AppDelegate.m), call `FrameProcessorPluginBase.registerPlugin(YourNewPlugin())`
 | 
				
			||||||
 | 
					@interface FrameProcessorPlugin : NSObject
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Get the name of the Frame Processor Plugin.
 | 
				
			||||||
 | 
					/// This will be exposed to JS under the `FrameProcessorPlugins` Proxy object.
 | 
				
			||||||
 | 
					- (NSString *)name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// The actual callback when calling this plugin. Any Frame Processing should be handled there.
 | 
				
			||||||
 | 
					/// Make sure your code is optimized, as this is a hot path.
 | 
				
			||||||
 | 
					- (id) callback:(Frame*)frame withArguments:(NSArray<id>*)arguments;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Register the given plugin in the Plugin Registry. This should be called on App Startup.
 | 
				
			||||||
 | 
					+ (void) registerPlugin:(FrameProcessorPlugin*)plugin;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@end
 | 
					@end
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define VISION_CONCAT2(A, B) A##B
 | 
					 | 
				
			||||||
#define VISION_CONCAT(A, B) VISION_CONCAT2(A, B)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Use this Macro to register the given function as a Frame Processor.
 | 
					 | 
				
			||||||
 * * Make sure the given function is a C-style function with the following signature: static inline id callback(Frame* frame, NSArray* args)
 | 
					 | 
				
			||||||
 * * Make sure the given function's name is unique across other frame processor plugins
 | 
					 | 
				
			||||||
 * * Make sure your frame processor returns a Value that can be converted to JS
 | 
					 | 
				
			||||||
 * * Make sure to use this Macro in an @implementation, not @interface
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * The JS function will have the same name as the given Objective-C function. It can be accessed through the FrameProcessorPlugins object exposed by VisionCamera.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#define VISION_EXPORT_FRAME_PROCESSOR(frame_processor)                              \
 | 
					 | 
				
			||||||
                                                                                    \
 | 
					 | 
				
			||||||
+(void)load                                                                         \
 | 
					 | 
				
			||||||
{                                                                                   \
 | 
					 | 
				
			||||||
  [FrameProcessorPluginRegistry addFrameProcessorPlugin:@ #frame_processor callback:^id(Frame* frame, NSArray<id>* args) { \
 | 
					 | 
				
			||||||
    return frame_processor(frame, args);                                           \
 | 
					 | 
				
			||||||
  }];                                                                               \
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Same as VISION_EXPORT_FRAME_PROCESSOR, but uses __attribute__((constructor)) for
 | 
					 | 
				
			||||||
 * registration. Useful for registering swift classes that forbids use of +(void)load.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#define VISION_EXPORT_SWIFT_FRAME_PROCESSOR(name, objc_name) \
 | 
					 | 
				
			||||||
objc_name : NSObject<FrameProcessorPluginBase>                                      \
 | 
					 | 
				
			||||||
@end                                                                                \
 | 
					 | 
				
			||||||
                                                                                    \
 | 
					 | 
				
			||||||
@interface objc_name (FrameProcessorPlugin)                                         \
 | 
					 | 
				
			||||||
@end                                                                                \
 | 
					 | 
				
			||||||
@implementation objc_name (FrameProcessorPlugin)                                    \
 | 
					 | 
				
			||||||
                                                                                    \
 | 
					 | 
				
			||||||
+(void)load                                                                          \
 | 
					 | 
				
			||||||
{                                                                                   \
 | 
					 | 
				
			||||||
  [FrameProcessorPluginRegistry addFrameProcessorPlugin:@ #name callback:^id(Frame* frame, NSArray<id>* args) {    \
 | 
					 | 
				
			||||||
    return [objc_name callback:frame withArgs:args];                               \
 | 
					 | 
				
			||||||
  }];                                                                               \
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif /* FrameProcessorPlugin_h */
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										31
									
								
								ios/Frame Processor/FrameProcessorPlugin.m
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								ios/Frame Processor/FrameProcessorPlugin.m
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					//  FrameProcessorPlugin.m
 | 
				
			||||||
 | 
					//  VisionCamera
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//  Created by Marc Rousavy on 24.02.23.
 | 
				
			||||||
 | 
					//  Copyright © 2023 mrousavy. All rights reserved.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#import <Foundation/Foundation.h>
 | 
				
			||||||
 | 
					#import "FrameProcessorPlugin.h"
 | 
				
			||||||
 | 
					#import "FrameProcessorPluginRegistry.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@implementation FrameProcessorPlugin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- (NSString *)name {
 | 
				
			||||||
 | 
					  [NSException raise:NSInternalInconsistencyException
 | 
				
			||||||
 | 
					              format:@"Frame Processor Plugin \"%@\" does not override the `name` getter!", [self name]];
 | 
				
			||||||
 | 
					  return nil;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- (id)callback:(Frame *)frame withArguments:(NSArray<id> *)arguments {
 | 
				
			||||||
 | 
					  [NSException raise:NSInternalInconsistencyException
 | 
				
			||||||
 | 
					              format:@"Frame Processor Plugin \"%@\" does not override the `callback(frame:withArguments:)` method!", [self name]];
 | 
				
			||||||
 | 
					  return nil;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					+ (void)registerPlugin:(FrameProcessorPlugin *)plugin {
 | 
				
			||||||
 | 
					  [FrameProcessorPluginRegistry addFrameProcessorPlugin:plugin];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@end
 | 
				
			||||||
@@ -10,12 +10,11 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#import <Foundation/Foundation.h>
 | 
					#import <Foundation/Foundation.h>
 | 
				
			||||||
#import "Frame.h"
 | 
					#import "Frame.h"
 | 
				
			||||||
 | 
					#import "FrameProcessorPlugin.h"
 | 
				
			||||||
typedef id (^FrameProcessorPlugin) (Frame* frame, NSArray<id>* arguments);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
@interface FrameProcessorPluginRegistry : NSObject
 | 
					@interface FrameProcessorPluginRegistry : NSObject
 | 
				
			||||||
 | 
					
 | 
				
			||||||
+ (NSMutableDictionary<NSString*, FrameProcessorPlugin>*)frameProcessorPlugins;
 | 
					+ (NSMutableDictionary<NSString*, FrameProcessorPlugin*>*)frameProcessorPlugins;
 | 
				
			||||||
+ (void) addFrameProcessorPlugin:(NSString*)name callback:(FrameProcessorPlugin)callback;
 | 
					+ (void) addFrameProcessorPlugin:(FrameProcessorPlugin*)plugin;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@end
 | 
					@end
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,19 +11,19 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
@implementation FrameProcessorPluginRegistry
 | 
					@implementation FrameProcessorPluginRegistry
 | 
				
			||||||
 | 
					
 | 
				
			||||||
+ (NSMutableDictionary<NSString*, FrameProcessorPlugin>*)frameProcessorPlugins {
 | 
					+ (NSMutableDictionary<NSString*, FrameProcessorPlugin*>*)frameProcessorPlugins {
 | 
				
			||||||
  static NSMutableDictionary<NSString*, FrameProcessorPlugin>* plugins = nil;
 | 
					  static NSMutableDictionary<NSString*, FrameProcessorPlugin*>* plugins = nil;
 | 
				
			||||||
  if (plugins == nil) {
 | 
					  if (plugins == nil) {
 | 
				
			||||||
    plugins = [[NSMutableDictionary alloc] init];
 | 
					    plugins = [[NSMutableDictionary alloc] init];
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return plugins;
 | 
					  return plugins;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
+ (void) addFrameProcessorPlugin:(NSString*)name callback:(FrameProcessorPlugin)callback {
 | 
					+ (void) addFrameProcessorPlugin:(FrameProcessorPlugin*)plugin {
 | 
				
			||||||
  BOOL alreadyExists = [[FrameProcessorPluginRegistry frameProcessorPlugins] valueForKey:name] != nil;
 | 
					  BOOL alreadyExists = [[FrameProcessorPluginRegistry frameProcessorPlugins] valueForKey:plugin.name] != nil;
 | 
				
			||||||
  NSAssert(!alreadyExists, @"Tried to two Frame Processor Plugins with the same name! Either choose unique names, or remove the unused plugin.");
 | 
					  NSAssert(!alreadyExists, @"Tried to add a Frame Processor Plugin with a name that already exists! Either choose unique names, or remove the unused plugin. Name: %@", plugin.name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  [[FrameProcessorPluginRegistry frameProcessorPlugins] setValue:callback forKey:name];
 | 
					  [[FrameProcessorPluginRegistry frameProcessorPlugins] setValue:plugin forKey:plugin.name];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@end
 | 
					@end
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,6 +9,7 @@
 | 
				
			|||||||
#import <Foundation/Foundation.h>
 | 
					#import <Foundation/Foundation.h>
 | 
				
			||||||
#import "FrameProcessorRuntimeManager.h"
 | 
					#import "FrameProcessorRuntimeManager.h"
 | 
				
			||||||
#import "FrameProcessorPluginRegistry.h"
 | 
					#import "FrameProcessorPluginRegistry.h"
 | 
				
			||||||
 | 
					#import "FrameProcessorPlugin.h"
 | 
				
			||||||
#import "FrameHostObject.h"
 | 
					#import "FrameHostObject.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#import <memory>
 | 
					#import <memory>
 | 
				
			||||||
@@ -83,11 +84,11 @@ __attribute__((objc_runtime_name("_TtC12VisionCamera10CameraView")))
 | 
				
			|||||||
    auto pluginName = [pluginKey UTF8String];
 | 
					    auto pluginName = [pluginKey UTF8String];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    NSLog(@"FrameProcessorBindings: Installing Frame Processor plugin \"%s\"...", pluginName);
 | 
					    NSLog(@"FrameProcessorBindings: Installing Frame Processor plugin \"%s\"...", pluginName);
 | 
				
			||||||
    // Get the Plugin callback func
 | 
					    // Get the Plugin
 | 
				
			||||||
    FrameProcessorPlugin callback = [[FrameProcessorPluginRegistry frameProcessorPlugins] valueForKey:pluginKey];
 | 
					    FrameProcessorPlugin* plugin = [[FrameProcessorPluginRegistry frameProcessorPlugins] valueForKey:pluginKey];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Create the JSI host function
 | 
					    // Create the JSI host function
 | 
				
			||||||
    auto function = [callback, callInvoker](jsi::Runtime& runtime,
 | 
					    auto function = [plugin, callInvoker](jsi::Runtime& runtime,
 | 
				
			||||||
                                          const jsi::Value& thisValue,
 | 
					                                          const jsi::Value& thisValue,
 | 
				
			||||||
                                          const jsi::Value* arguments,
 | 
					                                          const jsi::Value* arguments,
 | 
				
			||||||
                                          size_t count) -> jsi::Value {
 | 
					                                          size_t count) -> jsi::Value {
 | 
				
			||||||
@@ -101,7 +102,7 @@ __attribute__((objc_runtime_name("_TtC12VisionCamera10CameraView")))
 | 
				
			|||||||
                                                 count - 1, // use smaller count
 | 
					                                                 count - 1, // use smaller count
 | 
				
			||||||
                                                 callInvoker);
 | 
					                                                 callInvoker);
 | 
				
			||||||
      // Call the FP Plugin, which might return something.
 | 
					      // Call the FP Plugin, which might return something.
 | 
				
			||||||
      id result = callback(frame->frame, args);
 | 
					      id result = [plugin callback:frame->frame withArguments:args];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Convert the return value (or null) to a JS Value and return it to JS
 | 
					      // Convert the return value (or null) to a JS Value and return it to JS
 | 
				
			||||||
      return convertObjCObjectToJSIValue(runtime, result);
 | 
					      return convertObjCObjectToJSIValue(runtime, result);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -110,6 +110,7 @@
 | 
				
			|||||||
		B86DC970260E2D5200FB17B2 /* AVAudioSession+trySetAllowHaptics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AVAudioSession+trySetAllowHaptics.swift"; sourceTree = "<group>"; };
 | 
							B86DC970260E2D5200FB17B2 /* AVAudioSession+trySetAllowHaptics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AVAudioSession+trySetAllowHaptics.swift"; sourceTree = "<group>"; };
 | 
				
			||||||
		B86DC973260E310600FB17B2 /* CameraView+AVAudioSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CameraView+AVAudioSession.swift"; sourceTree = "<group>"; };
 | 
							B86DC973260E310600FB17B2 /* CameraView+AVAudioSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CameraView+AVAudioSession.swift"; sourceTree = "<group>"; };
 | 
				
			||||||
		B86DC976260E315100FB17B2 /* CameraView+AVCaptureSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CameraView+AVCaptureSession.swift"; sourceTree = "<group>"; };
 | 
							B86DC976260E315100FB17B2 /* CameraView+AVCaptureSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CameraView+AVCaptureSession.swift"; sourceTree = "<group>"; };
 | 
				
			||||||
 | 
							B86F803429A90DBD00205E48 /* FrameProcessorPlugin.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FrameProcessorPlugin.m; sourceTree = "<group>"; };
 | 
				
			||||||
		B8805065266798AB00EAD7F2 /* JSConsoleHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSConsoleHelper.h; sourceTree = "<group>"; };
 | 
							B8805065266798AB00EAD7F2 /* JSConsoleHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSConsoleHelper.h; sourceTree = "<group>"; };
 | 
				
			||||||
		B8805066266798B600EAD7F2 /* JSConsoleHelper.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = JSConsoleHelper.mm; sourceTree = "<group>"; };
 | 
							B8805066266798B600EAD7F2 /* JSConsoleHelper.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = JSConsoleHelper.mm; sourceTree = "<group>"; };
 | 
				
			||||||
		B882720F26AEB1A100B14107 /* AVCaptureConnection+setInterfaceOrientation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AVCaptureConnection+setInterfaceOrientation.swift"; sourceTree = "<group>"; };
 | 
							B882720F26AEB1A100B14107 /* AVCaptureConnection+setInterfaceOrientation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AVCaptureConnection+setInterfaceOrientation.swift"; sourceTree = "<group>"; };
 | 
				
			||||||
@@ -285,6 +286,7 @@
 | 
				
			|||||||
				B80C0DFE260BDD97001699AB /* FrameProcessorPluginRegistry.h */,
 | 
									B80C0DFE260BDD97001699AB /* FrameProcessorPluginRegistry.h */,
 | 
				
			||||||
				B80C0DFF260BDDF7001699AB /* FrameProcessorPluginRegistry.mm */,
 | 
									B80C0DFF260BDDF7001699AB /* FrameProcessorPluginRegistry.mm */,
 | 
				
			||||||
				B88873E5263D46C7008B1D0E /* FrameProcessorPlugin.h */,
 | 
									B88873E5263D46C7008B1D0E /* FrameProcessorPlugin.h */,
 | 
				
			||||||
 | 
									B86F803429A90DBD00205E48 /* FrameProcessorPlugin.m */,
 | 
				
			||||||
			);
 | 
								);
 | 
				
			||||||
			path = "Frame Processor";
 | 
								path = "Frame Processor";
 | 
				
			||||||
			sourceTree = "<group>";
 | 
								sourceTree = "<group>";
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user