react-native-vision-camera-spoof-detector 1.1.0 โ 1.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.npmignore +16 -0
- package/README.md +103 -186
- package/android/CMakeLists.txt +29 -0
- package/android/build.gradle +26 -10
- package/android/fix-prefab.gradle +4 -0
- package/android/src/main/AndroidManifest.xml +1 -1
- package/android/src/main/cpp/CMakeLists.txt +18 -86
- package/android/src/main/cpp/FaceAntiSpoofJSI.cpp +80 -6
- package/android/src/main/cpp/cpp-adapter.cpp +9 -0
- package/android/src/main/java/com/faceantispoof/FaceAntiSpoofModule.kt +55 -103
- package/android/src/main/java/com/faceantispoof/FaceAntiSpoofPackage.kt +15 -8
- package/android/src/main/java/com/margelo/nitro/camera/spoofdetector/HybridSpoofDetectorFactory.kt +15 -0
- package/android/src/main/java/com/margelo/nitro/camera/spoofdetector/HybridSpoofDetectorOutput.kt +111 -0
- package/index.js +22 -43
- package/nitro.json +20 -0
- package/nitrogen/generated/.gitattributes +1 -0
- package/nitrogen/generated/android/VisionCameraSpoofDetector+autolinking.cmake +81 -0
- package/nitrogen/generated/android/VisionCameraSpoofDetector+autolinking.gradle +27 -0
- package/nitrogen/generated/android/VisionCameraSpoofDetectorOnLoad.cpp +58 -0
- package/nitrogen/generated/android/VisionCameraSpoofDetectorOnLoad.hpp +34 -0
- package/nitrogen/generated/android/c++/JAntiSpoofingResult.hpp +77 -0
- package/nitrogen/generated/android/c++/JFunc_void_AntiSpoofingResult.hpp +78 -0
- package/nitrogen/generated/android/c++/JFunc_void_std__exception_ptr.hpp +76 -0
- package/nitrogen/generated/android/c++/JHybridSpoofDetectorFactorySpec.cpp +75 -0
- package/nitrogen/generated/android/c++/JHybridSpoofDetectorFactorySpec.hpp +63 -0
- package/nitrogen/generated/android/c++/JSize.hpp +61 -0
- package/nitrogen/generated/android/c++/JSpoofDetectorOutputOptions.hpp +91 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/camera/spoofdetector/AntiSpoofingResult.kt +76 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/camera/spoofdetector/Func_void_AntiSpoofingResult.kt +78 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/camera/spoofdetector/Func_void_std__exception_ptr.kt +78 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/camera/spoofdetector/HybridSpoofDetectorFactorySpec.kt +57 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/camera/spoofdetector/Size.kt +56 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/camera/spoofdetector/SpoofDetectorOutputOptions.kt +65 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/camera/spoofdetector/VisionCameraSpoofDetectorOnLoad.kt +35 -0
- package/nitrogen/generated/shared/c++/AntiSpoofingResult.hpp +103 -0
- package/nitrogen/generated/shared/c++/HybridSpoofDetectorFactorySpec.cpp +21 -0
- package/nitrogen/generated/shared/c++/HybridSpoofDetectorFactorySpec.hpp +67 -0
- package/nitrogen/generated/shared/c++/Size.hpp +87 -0
- package/nitrogen/generated/shared/c++/SpoofDetectorOutputOptions.hpp +98 -0
- package/package.json +10 -8
- package/src/specs/SpoofDetectorFactory.nitro.ts +23 -0
- package/android/src/main/assets/spoof_model_scale_2_7.tflite +0 -0
- package/android/src/main/assets/spoof_model_scale_4_0.tflite +0 -0
- /package/{android/src/main โ lib}/assets/FaceAntiSpoofing.tflite +0 -0
package/.npmignore
ADDED
package/README.md
CHANGED
|
@@ -19,13 +19,11 @@ High-performance face anti-spoofing and liveness detection module for React Nati
|
|
|
19
19
|
|
|
20
20
|
## ๐ Requirements
|
|
21
21
|
|
|
22
|
-
- React Native >= 0.
|
|
23
|
-
- React Native Vision Camera `^
|
|
24
|
-
- `react-native-reanimated` `^3.0.0`
|
|
25
|
-
- `react-native-worklets` `^0.12.0`
|
|
22
|
+
- React Native >= 0.76.0
|
|
23
|
+
- React Native Vision Camera `^5.0.0`
|
|
26
24
|
- `react-native-vision-camera-worklets` `^5.0.0`
|
|
27
25
|
- iOS 11.0 or later
|
|
28
|
-
- react-native-vision-camera-face-detector (
|
|
26
|
+
- `react-native-vision-camera-face-detector` (required for the face-gated example below)
|
|
29
27
|
|
|
30
28
|
## ๐ฆ Installation
|
|
31
29
|
|
|
@@ -40,9 +38,9 @@ yarn add react-native-vision-camera-spoof-detector
|
|
|
40
38
|
### Step 2: Install peer dependencies
|
|
41
39
|
|
|
42
40
|
```bash
|
|
43
|
-
npm install react-native-vision-camera react-native-reanimated react-native-worklets react-native-vision-camera-worklets
|
|
41
|
+
npm install react-native-vision-camera react-native-reanimated react-native-worklets react-native-vision-camera-worklets react-native-vision-camera-face-detector
|
|
44
42
|
# or
|
|
45
|
-
yarn add react-native-vision-camera react-native-reanimated react-native-worklets react-native-vision-camera-worklets
|
|
43
|
+
yarn add react-native-vision-camera react-native-reanimated react-native-worklets react-native-vision-camera-worklets react-native-vision-camera-face-detector
|
|
46
44
|
```
|
|
47
45
|
|
|
48
46
|
### Step 3: Configure iOS
|
|
@@ -82,213 +80,144 @@ react-native link react-native-vision-camera-spoof-detector
|
|
|
82
80
|
|
|
83
81
|
## ๐ Quick Start
|
|
84
82
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
### Simple Usage
|
|
83
|
+
Vision Camera 5 uses camera outputs for this package. The anti-spoof output can be combined with the face detector output and enabled only while a face is visible.
|
|
88
84
|
|
|
89
85
|
```javascript
|
|
90
86
|
import React, { useEffect, useState } from 'react';
|
|
91
|
-
import { StyleSheet, Text, View } from 'react-native';
|
|
92
|
-
import {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
87
|
+
import { StyleSheet, Text, useWindowDimensions, View } from 'react-native';
|
|
88
|
+
import {
|
|
89
|
+
Camera,
|
|
90
|
+
useCameraDevice,
|
|
91
|
+
useCameraPermission,
|
|
92
|
+
} from 'react-native-vision-camera';
|
|
93
|
+
import { useFaceDetectorOutput } from 'react-native-vision-camera-face-detector';
|
|
94
|
+
import { useFaceAntiSpoofFrameOutput } from 'react-native-vision-camera-spoof-detector';
|
|
95
|
+
|
|
96
|
+
const CameraScreen = () => {
|
|
97
|
+
const device = useCameraDevice('front');
|
|
99
98
|
const { hasPermission, requestPermission } = useCameraPermission();
|
|
99
|
+
const { width: windowWidth, height: windowHeight } = useWindowDimensions();
|
|
100
|
+
const [faces, setFaces] = useState([]);
|
|
101
|
+
const [detectionError, setDetectionError] = useState(null);
|
|
100
102
|
const [spoofResult, setSpoofResult] = useState(null);
|
|
101
103
|
|
|
102
104
|
useEffect(() => {
|
|
103
105
|
if (!hasPermission) requestPermission();
|
|
104
106
|
}, [hasPermission, requestPermission]);
|
|
105
107
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
108
|
+
const faceDetectorOutput = useFaceDetectorOutput({
|
|
109
|
+
cameraFacing: 'front',
|
|
110
|
+
autoMode: true,
|
|
111
|
+
windowWidth,
|
|
112
|
+
windowHeight,
|
|
113
|
+
performanceMode: 'fast',
|
|
114
|
+
trackingEnabled: true,
|
|
115
|
+
onFacesDetected(detectedFaces) {
|
|
116
|
+
setDetectionError(null);
|
|
117
|
+
setFaces(detectedFaces);
|
|
118
|
+
if (detectedFaces.length === 0) setSpoofResult(null);
|
|
119
|
+
},
|
|
120
|
+
onError(error) {
|
|
121
|
+
setDetectionError(error.message);
|
|
122
|
+
},
|
|
123
|
+
});
|
|
111
124
|
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}
|
|
118
|
-
}, []);
|
|
125
|
+
const antiSpoofOutput = useFaceAntiSpoofFrameOutput({
|
|
126
|
+
onResult(result) {
|
|
127
|
+
setSpoofResult(result);
|
|
128
|
+
},
|
|
129
|
+
});
|
|
119
130
|
|
|
120
|
-
|
|
131
|
+
const outputs = faces.length > 0
|
|
132
|
+
? [faceDetectorOutput, antiSpoofOutput]
|
|
133
|
+
: [faceDetectorOutput];
|
|
134
|
+
|
|
135
|
+
if (!hasPermission) return <Message text="Camera permission is required." />;
|
|
136
|
+
if (!device) return <Message text="No front camera is available." />;
|
|
121
137
|
|
|
122
138
|
return (
|
|
123
139
|
<View style={styles.container}>
|
|
124
140
|
<Camera
|
|
125
141
|
style={StyleSheet.absoluteFill}
|
|
126
142
|
device={device}
|
|
127
|
-
isActive
|
|
128
|
-
|
|
129
|
-
frameProcessorFps={5}
|
|
143
|
+
isActive
|
|
144
|
+
outputs={outputs}
|
|
130
145
|
/>
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
</
|
|
143
|
-
|
|
146
|
+
|
|
147
|
+
<View style={styles.statusContainer}>
|
|
148
|
+
<Text style={styles.statusText}>
|
|
149
|
+
{detectionError ?? `${faces.length} face${faces.length === 1 ? '' : 's'} detected`}
|
|
150
|
+
</Text>
|
|
151
|
+
<Text style={styles.statusText}>
|
|
152
|
+
{faces.length === 0
|
|
153
|
+
? 'Waiting for face...'
|
|
154
|
+
: spoofResult
|
|
155
|
+
? JSON.stringify(spoofResult)
|
|
156
|
+
: 'Anti-spoof processing...'}
|
|
157
|
+
</Text>
|
|
158
|
+
</View>
|
|
144
159
|
</View>
|
|
145
160
|
);
|
|
146
|
-
}
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
const Message = ({ text }) => (
|
|
164
|
+
<View style={styles.messageContainer}>
|
|
165
|
+
<Text style={styles.messageText}>{text}</Text>
|
|
166
|
+
</View>
|
|
167
|
+
);
|
|
147
168
|
|
|
148
169
|
const styles = StyleSheet.create({
|
|
149
170
|
container: { flex: 1 },
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
bottom: 50,
|
|
153
|
-
left: 0,
|
|
154
|
-
right: 0,
|
|
171
|
+
messageContainer: {
|
|
172
|
+
flex: 1,
|
|
155
173
|
alignItems: 'center',
|
|
156
|
-
|
|
157
|
-
|
|
174
|
+
justifyContent: 'center',
|
|
175
|
+
paddingHorizontal: 24,
|
|
158
176
|
},
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
177
|
+
messageText: { fontSize: 16, textAlign: 'center' },
|
|
178
|
+
statusContainer: {
|
|
179
|
+
position: 'absolute',
|
|
180
|
+
top: 56,
|
|
181
|
+
alignSelf: 'center',
|
|
182
|
+
paddingHorizontal: 14,
|
|
183
|
+
paddingVertical: 8,
|
|
184
|
+
borderRadius: 16,
|
|
185
|
+
backgroundColor: 'rgba(0, 0, 0, 0.65)',
|
|
163
186
|
},
|
|
187
|
+
statusText: { color: '#ffffff', fontSize: 14, marginVertical: 2 },
|
|
164
188
|
});
|
|
189
|
+
|
|
190
|
+
export default CameraScreen;
|
|
165
191
|
```
|
|
166
192
|
|
|
167
|
-
|
|
193
|
+
The anti-spoof output callback receives a result after native inference. No manual `runOnJS`, frame processor, or explicit initialization call is required for this output API. The output may be omitted until a face is detected, as shown above.
|
|
168
194
|
|
|
169
|
-
|
|
170
|
-
import { useCallback, useMemo, useEffect, useRef } from 'react';
|
|
171
|
-
import { scheduleOnRN } from 'react-native-worklets';
|
|
172
|
-
import { useFrameProcessor } from 'react-native-vision-camera';
|
|
173
|
-
import { useFaceDetector } from 'react-native-vision-camera-face-detector';
|
|
174
|
-
import {
|
|
175
|
-
faceAntiSpoofFrameProcessor,
|
|
176
|
-
initializeFaceAntiSpoof,
|
|
177
|
-
isFaceAntiSpoofAvailable,
|
|
178
|
-
} from 'react-native-vision-camera-spoof-detector';
|
|
179
|
-
|
|
180
|
-
const useFaceDetectionFrameProcessor = ({
|
|
181
|
-
onStableFaceDetected = () => { },
|
|
182
|
-
onFacesUpdate = () => { },
|
|
183
|
-
onLivenessUpdate = () => { },
|
|
184
|
-
onAntiSpoofUpdate = () => { },
|
|
185
|
-
showCodeScanner = false,
|
|
186
|
-
isLoading = false,
|
|
187
|
-
isActive = true,
|
|
188
|
-
livenessLevel = 0,
|
|
189
|
-
antispooflevel = 0.35,
|
|
190
|
-
}) => {
|
|
191
|
-
const { detectFaces } = useFaceDetector({
|
|
192
|
-
performanceMode: 'fast',
|
|
193
|
-
landmarkMode: 'none',
|
|
194
|
-
contourMode: 'none',
|
|
195
|
-
classificationMode: livenessLevel === 1 ? 'all' : 'none',
|
|
196
|
-
minFaceSize: 0.2,
|
|
197
|
-
});
|
|
195
|
+
## ๐ API Reference
|
|
198
196
|
|
|
199
|
-
|
|
200
|
-
const antiSpoofInitialized = useRef(false);
|
|
201
|
-
|
|
202
|
-
const initializeAntiSpoof = useCallback(async () => {
|
|
203
|
-
if (antiSpoofInitialized.current) return true;
|
|
204
|
-
try {
|
|
205
|
-
const available = isFaceAntiSpoofAvailable?.();
|
|
206
|
-
if (!available) return false;
|
|
207
|
-
await initializeFaceAntiSpoof();
|
|
208
|
-
antiSpoofInitialized.current = true;
|
|
209
|
-
return true;
|
|
210
|
-
} catch (err) {
|
|
211
|
-
console.error('Anti-spoof initialization error:', err);
|
|
212
|
-
return false;
|
|
213
|
-
}
|
|
214
|
-
}, []);
|
|
197
|
+
### `useFaceAntiSpoofFrameOutput(options?)`
|
|
215
198
|
|
|
216
|
-
|
|
217
|
-
initializeAntiSpoof();
|
|
218
|
-
}, [initializeAntiSpoof]);
|
|
219
|
-
|
|
220
|
-
// Shared state for face tracking
|
|
221
|
-
const sharedState = useMemo(
|
|
222
|
-
() =>
|
|
223
|
-
Worklets.createSharedValue({
|
|
224
|
-
flags: {
|
|
225
|
-
captured: false,
|
|
226
|
-
showCodeScanner: showCodeScanner,
|
|
227
|
-
isActive: isActive,
|
|
228
|
-
hasSingleFace: false,
|
|
229
|
-
isFaceCentered: false,
|
|
230
|
-
},
|
|
231
|
-
antiSpoof: {
|
|
232
|
-
isLive: false,
|
|
233
|
-
confidence: 0,
|
|
234
|
-
consecutiveLiveFrames: 0,
|
|
235
|
-
},
|
|
236
|
-
}),
|
|
237
|
-
[]
|
|
238
|
-
);
|
|
199
|
+
Creates a Vision Camera 5 camera output for native anti-spoofing inference.
|
|
239
200
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
if (detected.length === 1 && !sharedState.value.flags.captured) {
|
|
253
|
-
const antiSpoofResult = faceAntiSpoofFrameProcessor?.(frame);
|
|
254
|
-
|
|
255
|
-
if (antiSpoofResult?.isLive) {
|
|
256
|
-
sharedState.value.antiSpoof.isLive = true;
|
|
257
|
-
sharedState.value.antiSpoof.confidence = antiSpoofResult.combinedScore;
|
|
258
|
-
onAntiSpoofUpdate?.({
|
|
259
|
-
isLive: true,
|
|
260
|
-
confidence: antiSpoofResult.combinedScore,
|
|
261
|
-
});
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
onFacesUpdate?.({ count: 1, progress: 50 });
|
|
265
|
-
} else {
|
|
266
|
-
onFacesUpdate?.({ count: detected.length, progress: 0 });
|
|
267
|
-
}
|
|
268
|
-
} catch (err) {
|
|
269
|
-
console.error('Frame processing error:', err);
|
|
270
|
-
} finally {
|
|
271
|
-
frame.release?.();
|
|
272
|
-
}
|
|
273
|
-
},
|
|
274
|
-
[detectFaces, isLoading]
|
|
275
|
-
);
|
|
201
|
+
```javascript
|
|
202
|
+
const antiSpoofOutput = useFaceAntiSpoofFrameOutput({
|
|
203
|
+
onResult(result) {
|
|
204
|
+
console.log(result);
|
|
205
|
+
},
|
|
206
|
+
onError(error) {
|
|
207
|
+
console.error(error);
|
|
208
|
+
},
|
|
209
|
+
});
|
|
210
|
+
```
|
|
276
211
|
|
|
277
|
-
|
|
278
|
-
frameProcessor,
|
|
279
|
-
sharedState,
|
|
280
|
-
initializeAntiSpoof,
|
|
281
|
-
};
|
|
282
|
-
};
|
|
212
|
+
Pass the returned output in the `Camera` component's `outputs` array. The callback runs on the React Native runtime after native inference.
|
|
283
213
|
|
|
284
|
-
|
|
285
|
-
```
|
|
214
|
+
**Options**: `onResult(result)` and optional `onError(error)`.
|
|
286
215
|
|
|
287
|
-
|
|
216
|
+
---
|
|
288
217
|
|
|
289
218
|
### `initializeFaceAntiSpoof()`
|
|
290
219
|
|
|
291
|
-
Initializes the
|
|
220
|
+
Initializes the native module when an application needs an explicit startup check or model-loading diagnostics. It is not required when using `useFaceAntiSpoofFrameOutput()`.
|
|
292
221
|
|
|
293
222
|
```javascript
|
|
294
223
|
const success = await initializeFaceAntiSpoof();
|
|
@@ -310,18 +239,6 @@ const available = isFaceAntiSpoofAvailable();
|
|
|
310
239
|
|
|
311
240
|
---
|
|
312
241
|
|
|
313
|
-
### `faceAntiSpoofFrameProcessor(frame)`
|
|
314
|
-
|
|
315
|
-
Process frame and get anti-spoofing result.
|
|
316
|
-
|
|
317
|
-
```javascript
|
|
318
|
-
const result = faceAntiSpoofFrameProcessor(frame);
|
|
319
|
-
```
|
|
320
|
-
|
|
321
|
-
**Parameters**: `frame` (Vision Camera Frame)
|
|
322
|
-
|
|
323
|
-
**Returns**: `FaceAntiSpoofingResult | null`. On iOS, inference runs off the frame callback and the returned object can be the latest completed result.
|
|
324
|
-
|
|
325
242
|
### `FaceAntiSpoofingResult`
|
|
326
243
|
|
|
327
244
|
```typescript
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
project(VisionCameraSpoofDetector)
|
|
2
|
+
cmake_minimum_required(VERSION 3.9.0)
|
|
3
|
+
|
|
4
|
+
set(PACKAGE_NAME VisionCameraSpoofDetector)
|
|
5
|
+
set(CMAKE_SUPPRESS_REGENERATION ON)
|
|
6
|
+
set(CMAKE_VERBOSE_MAKEFILE ON)
|
|
7
|
+
set(CMAKE_CXX_STANDARD 20)
|
|
8
|
+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
9
|
+
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
|
10
|
+
set(CMAKE_ANDROID_STL_TYPE c++_shared)
|
|
11
|
+
|
|
12
|
+
add_library(${PACKAGE_NAME} SHARED
|
|
13
|
+
src/main/cpp/cpp-adapter.cpp
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
# Nitrogen-generated specs: this path is valid because the project root is android/
|
|
17
|
+
include(${CMAKE_SOURCE_DIR}/../nitrogen/generated/android/VisionCameraSpoofDetector+autolinking.cmake)
|
|
18
|
+
|
|
19
|
+
find_library(LOG_LIB log)
|
|
20
|
+
find_package(react-native-vision-camera REQUIRED)
|
|
21
|
+
|
|
22
|
+
target_link_options(${PACKAGE_NAME} PRIVATE "-Wl,-z,max-page-size=16384")
|
|
23
|
+
|
|
24
|
+
target_link_libraries(
|
|
25
|
+
${PACKAGE_NAME}
|
|
26
|
+
${LOG_LIB}
|
|
27
|
+
android
|
|
28
|
+
react-native-vision-camera::VisionCamera
|
|
29
|
+
)
|
package/android/build.gradle
CHANGED
|
@@ -19,8 +19,15 @@ buildscript {
|
|
|
19
19
|
|
|
20
20
|
apply plugin: 'com.android.library'
|
|
21
21
|
apply plugin: 'kotlin-android'
|
|
22
|
+
apply from: '../nitrogen/generated/android/VisionCameraSpoofDetector+autolinking.gradle'
|
|
23
|
+
|
|
24
|
+
def reactNativeArchitectures() {
|
|
25
|
+
def value = rootProject.getProperties().get("reactNativeArchitectures")
|
|
26
|
+
return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
|
|
27
|
+
}
|
|
22
28
|
|
|
23
29
|
android {
|
|
30
|
+
namespace "com.margelo.nitro.camera.spoofdetector"
|
|
24
31
|
compileSdkVersion rootProject.ext.compileSdkVersion
|
|
25
32
|
|
|
26
33
|
defaultConfig {
|
|
@@ -35,7 +42,9 @@ android {
|
|
|
35
42
|
// Needed for JSI / C++ build
|
|
36
43
|
externalNativeBuild {
|
|
37
44
|
cmake {
|
|
38
|
-
cppFlags "-
|
|
45
|
+
cppFlags "-frtti -fexceptions -Wall -Wextra -fstack-protector-all"
|
|
46
|
+
arguments "-DANDROID_STL=c++_shared", "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON"
|
|
47
|
+
abiFilters (*reactNativeArchitectures())
|
|
39
48
|
}
|
|
40
49
|
}
|
|
41
50
|
}
|
|
@@ -61,7 +70,7 @@ android {
|
|
|
61
70
|
|
|
62
71
|
sourceSets {
|
|
63
72
|
main {
|
|
64
|
-
assets.srcDirs = ['
|
|
73
|
+
assets.srcDirs = ['../lib/assets']
|
|
65
74
|
}
|
|
66
75
|
}
|
|
67
76
|
|
|
@@ -91,10 +100,14 @@ android {
|
|
|
91
100
|
|
|
92
101
|
externalNativeBuild {
|
|
93
102
|
cmake {
|
|
94
|
-
path "
|
|
95
|
-
version "3.22.1"
|
|
103
|
+
path "CMakeLists.txt"
|
|
104
|
+
version "3.22.1"
|
|
96
105
|
}
|
|
97
106
|
}
|
|
107
|
+
|
|
108
|
+
buildFeatures {
|
|
109
|
+
prefab true
|
|
110
|
+
}
|
|
98
111
|
}
|
|
99
112
|
|
|
100
113
|
def isNewArchitectureEnabled() {
|
|
@@ -109,8 +122,10 @@ repositories {
|
|
|
109
122
|
}
|
|
110
123
|
|
|
111
124
|
dependencies {
|
|
112
|
-
|
|
113
|
-
|
|
125
|
+
implementation "androidx.camera:camera-core:1.7.0-alpha03"
|
|
126
|
+
|
|
127
|
+
// React Native and VisionCamera provide their native Prefab libraries.
|
|
128
|
+
compileOnly "com.facebook.react:react-android"
|
|
114
129
|
|
|
115
130
|
// Kotlin
|
|
116
131
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
|
|
@@ -130,8 +145,9 @@ dependencies {
|
|
|
130
145
|
// AndroidX - EXIF Support for image orientation
|
|
131
146
|
implementation "androidx.exifinterface:exifinterface:1.3.6"
|
|
132
147
|
|
|
133
|
-
// VisionCamera 5
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
148
|
+
// VisionCamera 5 and Nitro provide these native libraries to the consuming app.
|
|
149
|
+
compileOnly project(':react-native-vision-camera')
|
|
150
|
+
compileOnly project(':react-native-vision-camera-worklets')
|
|
151
|
+
compileOnly project(':react-native-worklets')
|
|
152
|
+
compileOnly project(':react-native-nitro-modules')
|
|
137
153
|
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
// This package does not need the forced prefab reconfigure workaround.
|
|
2
|
+
// Leaving the task outputs as a normal Gradle up-to-date state prevents the
|
|
3
|
+
// infinite CMake regeneration loop that was triggering
|
|
4
|
+
// "ninja: error: manifest 'build.ninja' still dirty after 100 tries".
|
|
@@ -1,101 +1,33 @@
|
|
|
1
|
-
cmake_minimum_required(VERSION 3.4.1)
|
|
2
|
-
|
|
3
|
-
project(fastyuv)
|
|
4
|
-
|
|
5
|
-
set(SOURCE_FILES
|
|
6
|
-
FastYuvJni.cpp
|
|
7
|
-
fast_yuv.cpp
|
|
8
|
-
)
|
|
9
|
-
|
|
10
|
-
add_library(fastyuv SHARED ${SOURCE_FILES})
|
|
11
|
-
|
|
12
|
-
# Enable NEON SIMD optimizations for ARM architectures
|
|
13
|
-
if(CMAKE_SYSTEM_PROCESSOR MATCHES "armv7" OR CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64")
|
|
14
|
-
# ARM NEON optimization flags
|
|
15
|
-
target_compile_options(fastyuv PRIVATE
|
|
16
|
-
-fPIC
|
|
17
|
-
-O3
|
|
18
|
-
)
|
|
19
|
-
|
|
20
|
-
# ARM-specific NEON enablement (clang doesn't support -march=native for cross-compilation)
|
|
21
|
-
if(CMAKE_SYSTEM_PROCESSOR MATCHES "armv7")
|
|
22
|
-
# ARMv7 with NEON (32-bit ARM)
|
|
23
|
-
target_compile_options(fastyuv PRIVATE -march=armv7-a -mfpu=neon -mfloat-abi=softfp)
|
|
24
|
-
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64")
|
|
25
|
-
# ARMv8 with full SIMD support (64-bit ARM)
|
|
26
|
-
target_compile_options(fastyuv PRIVATE -march=armv8-a)
|
|
27
|
-
endif()
|
|
28
|
-
endif()
|
|
29
|
-
|
|
30
|
-
# Always add libyuv include dir so headers like libyuv/convert.h are found.
|
|
31
|
-
target_include_directories(fastyuv PRIVATE ${CMAKE_SOURCE_DIR}/libyuv/include)
|
|
32
|
-
|
|
33
|
-
# Prefer using libyuv subproject if available.
|
|
34
|
-
if (EXISTS ${CMAKE_SOURCE_DIR}/libyuv/CMakeLists.txt)
|
|
35
|
-
add_subdirectory(libyuv)
|
|
36
|
-
# Link against the libyuv target produced by that CMake. The lib creates
|
|
37
|
-
# targets named 'yuv' (static) and 'yuv_shared' (shared) whose output
|
|
38
|
-
# library name is 'libyuv'. Prefer the shared target when available.
|
|
39
|
-
if (TARGET yuv_shared)
|
|
40
|
-
target_link_libraries(fastyuv PRIVATE yuv_shared)
|
|
41
|
-
elseif (TARGET yuv)
|
|
42
|
-
target_link_libraries(fastyuv PRIVATE yuv)
|
|
43
|
-
endif()
|
|
44
|
-
endif()
|
|
45
|
-
|
|
46
|
-
# ๆฏๆ Android 15+ ็ 16KB ้กต้ขๅคงๅฐ
|
|
47
|
-
# https://developer.android.com/guide/practices/page-sizes
|
|
48
|
-
target_link_options(fastyuv PRIVATE "-Wl,-z,max-page-size=16384")
|
|
49
|
-
|
|
50
|
-
# Android log
|
|
51
|
-
find_library(log-lib log)
|
|
52
|
-
target_link_libraries(fastyuv PRIVATE ${log-lib})
|
|
53
1
|
cmake_minimum_required(VERSION 3.18)
|
|
54
|
-
project(
|
|
2
|
+
project(VisionCameraSpoofDetector)
|
|
55
3
|
|
|
56
4
|
set(CMAKE_CXX_STANDARD 17)
|
|
57
5
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
6
|
+
set(CMAKE_SUPPRESS_REGENERATION ON)
|
|
58
7
|
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
|
8
|
+
set(CMAKE_ANDROID_STL_TYPE c++_shared)
|
|
59
9
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
get_filename_component(PARENT_1 "${CMAKE_SOURCE_ABS}/.." ABSOLUTE) # main
|
|
63
|
-
get_filename_component(PARENT_2 "${PARENT_1}/.." ABSOLUTE) # src
|
|
64
|
-
get_filename_component(PARENT_3 "${PARENT_2}/.." ABSOLUTE) # android
|
|
65
|
-
get_filename_component(PARENT_4 "${PARENT_3}/.." ABSOLUTE) # react-native-vision-camera-spoof-detector
|
|
66
|
-
get_filename_component(NODE_MODULES_ABS "${PARENT_4}/.." ABSOLUTE) # node_modules
|
|
67
|
-
|
|
68
|
-
set(REACT_NATIVE_DIR "${NODE_MODULES_ABS}/react-native")
|
|
69
|
-
set(REACT_COMMON_DIR "${REACT_NATIVE_DIR}/ReactCommon")
|
|
70
|
-
|
|
71
|
-
message(STATUS "NODE_MODULES_ABS: ${NODE_MODULES_ABS}")
|
|
72
|
-
message(STATUS "REACT_NATIVE_DIR: ${REACT_NATIVE_DIR}")
|
|
73
|
-
message(STATUS "REACT_COMMON_DIR: ${REACT_COMMON_DIR}")
|
|
10
|
+
set(PACKAGE_NAME VisionCameraSpoofDetector)
|
|
11
|
+
set(CMAKE_VERBOSE_MAKEFILE ON)
|
|
74
12
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
add_library(faceantispoof SHARED FaceAntiSpoofJSI.cpp ${JSI_CPP})
|
|
79
|
-
|
|
80
|
-
target_include_directories(faceantispoof PRIVATE
|
|
81
|
-
"${REACT_COMMON_DIR}/jsi"
|
|
82
|
-
"${REACT_COMMON_DIR}/cxxreact"
|
|
83
|
-
"${REACT_COMMON_DIR}/callinvoker/ReactCommon"
|
|
84
|
-
"${REACT_COMMON_DIR}/runtimeexecutor/ReactCommon"
|
|
85
|
-
"${REACT_COMMON_DIR}"
|
|
13
|
+
add_library(${PACKAGE_NAME} SHARED
|
|
14
|
+
cpp-adapter.cpp
|
|
86
15
|
)
|
|
87
16
|
|
|
88
|
-
|
|
17
|
+
# Nitrogen-generated hybrid bindings
|
|
18
|
+
include(${CMAKE_SOURCE_DIR}/../../../../nitrogen/generated/android/VisionCameraSpoofDetector+autolinking.cmake)
|
|
19
|
+
|
|
20
|
+
find_library(LOG_LIB log)
|
|
21
|
+
find_package(react-native-vision-camera REQUIRED)
|
|
89
22
|
|
|
90
|
-
#
|
|
91
|
-
target_link_options(
|
|
23
|
+
# Android 15+ 16KB page support
|
|
24
|
+
target_link_options(${PACKAGE_NAME} PRIVATE "-Wl,-z,max-page-size=16384")
|
|
92
25
|
|
|
93
26
|
target_link_libraries(
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
m
|
|
27
|
+
${PACKAGE_NAME}
|
|
28
|
+
${LOG_LIB}
|
|
29
|
+
android
|
|
30
|
+
react-native-vision-camera::VisionCamera
|
|
99
31
|
)
|
|
100
32
|
|
|
101
33
|
|