@arfuhad/react-native-smart-camera 0.1.0

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.
Files changed (95) hide show
  1. package/ARCHITECTURE.md +341 -0
  2. package/README.md +154 -0
  3. package/android/build.gradle +89 -0
  4. package/android/src/main/AndroidManifest.xml +2 -0
  5. package/android/src/main/java/expo/modules/smartcamera/ImageLoader.kt +106 -0
  6. package/android/src/main/java/expo/modules/smartcamera/MLKitFaceDetector.kt +273 -0
  7. package/android/src/main/java/expo/modules/smartcamera/SmartCameraModule.kt +205 -0
  8. package/android/src/main/java/expo/modules/smartcamera/SmartCameraView.kt +153 -0
  9. package/android/src/main/java/expo/modules/smartcamera/WebRTCFrameBridge.kt +184 -0
  10. package/app.plugin.js +17 -0
  11. package/build/SmartCamera.d.ts +17 -0
  12. package/build/SmartCamera.d.ts.map +1 -0
  13. package/build/SmartCamera.js +270 -0
  14. package/build/SmartCamera.js.map +1 -0
  15. package/build/SmartCameraModule.d.ts +112 -0
  16. package/build/SmartCameraModule.d.ts.map +1 -0
  17. package/build/SmartCameraModule.js +121 -0
  18. package/build/SmartCameraModule.js.map +1 -0
  19. package/build/SmartCameraView.d.ts +8 -0
  20. package/build/SmartCameraView.d.ts.map +1 -0
  21. package/build/SmartCameraView.js +7 -0
  22. package/build/SmartCameraView.js.map +1 -0
  23. package/build/detection/blinkProcessor.d.ts +23 -0
  24. package/build/detection/blinkProcessor.d.ts.map +1 -0
  25. package/build/detection/blinkProcessor.js +90 -0
  26. package/build/detection/blinkProcessor.js.map +1 -0
  27. package/build/detection/faceDetector.d.ts +16 -0
  28. package/build/detection/faceDetector.d.ts.map +1 -0
  29. package/build/detection/faceDetector.js +46 -0
  30. package/build/detection/faceDetector.js.map +1 -0
  31. package/build/detection/index.d.ts +4 -0
  32. package/build/detection/index.d.ts.map +1 -0
  33. package/build/detection/index.js +4 -0
  34. package/build/detection/index.js.map +1 -0
  35. package/build/detection/staticImageDetector.d.ts +25 -0
  36. package/build/detection/staticImageDetector.d.ts.map +1 -0
  37. package/build/detection/staticImageDetector.js +48 -0
  38. package/build/detection/staticImageDetector.js.map +1 -0
  39. package/build/hooks/index.d.ts +5 -0
  40. package/build/hooks/index.d.ts.map +1 -0
  41. package/build/hooks/index.js +5 -0
  42. package/build/hooks/index.js.map +1 -0
  43. package/build/hooks/useBlinkDetection.d.ts +39 -0
  44. package/build/hooks/useBlinkDetection.d.ts.map +1 -0
  45. package/build/hooks/useBlinkDetection.js +67 -0
  46. package/build/hooks/useBlinkDetection.js.map +1 -0
  47. package/build/hooks/useFaceDetection.d.ts +46 -0
  48. package/build/hooks/useFaceDetection.d.ts.map +1 -0
  49. package/build/hooks/useFaceDetection.js +80 -0
  50. package/build/hooks/useFaceDetection.js.map +1 -0
  51. package/build/hooks/useSmartCamera.d.ts +31 -0
  52. package/build/hooks/useSmartCamera.d.ts.map +1 -0
  53. package/build/hooks/useSmartCamera.js +75 -0
  54. package/build/hooks/useSmartCamera.js.map +1 -0
  55. package/build/hooks/useSmartCameraWebRTC.d.ts +58 -0
  56. package/build/hooks/useSmartCameraWebRTC.d.ts.map +1 -0
  57. package/build/hooks/useSmartCameraWebRTC.js +160 -0
  58. package/build/hooks/useSmartCameraWebRTC.js.map +1 -0
  59. package/build/index.d.ts +14 -0
  60. package/build/index.d.ts.map +1 -0
  61. package/build/index.js +20 -0
  62. package/build/index.js.map +1 -0
  63. package/build/types.d.ts +478 -0
  64. package/build/types.d.ts.map +1 -0
  65. package/build/types.js +2 -0
  66. package/build/types.js.map +1 -0
  67. package/build/utils/index.d.ts +98 -0
  68. package/build/utils/index.d.ts.map +1 -0
  69. package/build/utils/index.js +276 -0
  70. package/build/utils/index.js.map +1 -0
  71. package/build/webrtc/WebRTCBridge.d.ts +55 -0
  72. package/build/webrtc/WebRTCBridge.d.ts.map +1 -0
  73. package/build/webrtc/WebRTCBridge.js +113 -0
  74. package/build/webrtc/WebRTCBridge.js.map +1 -0
  75. package/build/webrtc/index.d.ts +3 -0
  76. package/build/webrtc/index.d.ts.map +1 -0
  77. package/build/webrtc/index.js +2 -0
  78. package/build/webrtc/index.js.map +1 -0
  79. package/build/webrtc/types.d.ts +64 -0
  80. package/build/webrtc/types.d.ts.map +1 -0
  81. package/build/webrtc/types.js +5 -0
  82. package/build/webrtc/types.js.map +1 -0
  83. package/expo-module.config.json +9 -0
  84. package/ios/MLKitFaceDetector.swift +310 -0
  85. package/ios/SmartCamera.podspec +33 -0
  86. package/ios/SmartCameraModule.swift +225 -0
  87. package/ios/SmartCameraView.swift +146 -0
  88. package/ios/WebRTCFrameBridge.swift +150 -0
  89. package/package.json +91 -0
  90. package/plugin/build/index.d.ts +28 -0
  91. package/plugin/build/index.js +33 -0
  92. package/plugin/build/withSmartCameraAndroid.d.ts +9 -0
  93. package/plugin/build/withSmartCameraAndroid.js +108 -0
  94. package/plugin/build/withSmartCameraIOS.d.ts +11 -0
  95. package/plugin/build/withSmartCameraIOS.js +92 -0
@@ -0,0 +1,276 @@
1
+ /**
2
+ * SmartCamera utility functions
3
+ */
4
+ // ============================================================================
5
+ // FPS Limiter
6
+ // ============================================================================
7
+ /**
8
+ * Creates an FPS limiter for frame processing
9
+ *
10
+ * @param targetFps - Target frames per second
11
+ * @returns Object with shouldProcess function
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * const limiter = createFpsLimiter(15);
16
+ *
17
+ * const frameProcessor = useFrameProcessor((frame) => {
18
+ * if (!limiter.shouldProcess()) return;
19
+ * // Process frame...
20
+ * }, []);
21
+ * ```
22
+ */
23
+ export function createFpsLimiter(targetFps) {
24
+ const frameInterval = 1000 / targetFps;
25
+ let lastFrameTime = 0;
26
+ return {
27
+ shouldProcess: () => {
28
+ const now = Date.now();
29
+ if (now - lastFrameTime >= frameInterval) {
30
+ lastFrameTime = now;
31
+ return true;
32
+ }
33
+ return false;
34
+ },
35
+ reset: () => {
36
+ lastFrameTime = 0;
37
+ },
38
+ setTargetFps: (fps) => {
39
+ // Note: This creates a new interval but doesn't update the closure
40
+ // Consider using a ref if dynamic FPS changes are needed
41
+ },
42
+ };
43
+ }
44
+ // ============================================================================
45
+ // Debounce
46
+ // ============================================================================
47
+ /**
48
+ * Creates a debounced function
49
+ *
50
+ * @param fn - Function to debounce
51
+ * @param delay - Delay in milliseconds
52
+ * @returns Debounced function
53
+ */
54
+ export function debounce(fn, delay) {
55
+ let timeoutId = null;
56
+ return (...args) => {
57
+ if (timeoutId) {
58
+ clearTimeout(timeoutId);
59
+ }
60
+ timeoutId = setTimeout(() => {
61
+ fn(...args);
62
+ timeoutId = null;
63
+ }, delay);
64
+ };
65
+ }
66
+ // ============================================================================
67
+ // Throttle
68
+ // ============================================================================
69
+ /**
70
+ * Creates a throttled function
71
+ *
72
+ * @param fn - Function to throttle
73
+ * @param limit - Minimum time between calls in milliseconds
74
+ * @returns Throttled function
75
+ */
76
+ export function throttle(fn, limit) {
77
+ let lastCall = 0;
78
+ return (...args) => {
79
+ const now = Date.now();
80
+ if (now - lastCall >= limit) {
81
+ lastCall = now;
82
+ fn(...args);
83
+ }
84
+ };
85
+ }
86
+ /**
87
+ * Creates an object pool for reducing garbage collection
88
+ *
89
+ * @param factory - Factory function to create new objects
90
+ * @param initialSize - Initial pool size
91
+ * @param maxSize - Maximum pool size
92
+ */
93
+ export function createObjectPool(factory, initialSize = 10, maxSize = 100) {
94
+ const pool = [];
95
+ // Pre-populate pool
96
+ for (let i = 0; i < initialSize; i++) {
97
+ pool.push({ data: factory(), inUse: false });
98
+ }
99
+ return {
100
+ acquire: () => {
101
+ // Find an available object
102
+ const available = pool.find((obj) => !obj.inUse);
103
+ if (available) {
104
+ available.inUse = true;
105
+ return available.data;
106
+ }
107
+ // Create new if pool not at max
108
+ if (pool.length < maxSize) {
109
+ const newObj = { data: factory(), inUse: true };
110
+ pool.push(newObj);
111
+ return newObj.data;
112
+ }
113
+ // Pool exhausted, create temporary object
114
+ return factory();
115
+ },
116
+ release: (obj) => {
117
+ const pooledObj = pool.find((p) => p.data === obj);
118
+ if (pooledObj) {
119
+ pooledObj.inUse = false;
120
+ }
121
+ },
122
+ clear: () => {
123
+ pool.length = 0;
124
+ },
125
+ getStats: () => ({
126
+ size: pool.length,
127
+ inUse: pool.filter((p) => p.inUse).length,
128
+ available: pool.filter((p) => !p.inUse).length,
129
+ }),
130
+ };
131
+ }
132
+ /**
133
+ * Creates a SmartCameraError from an unknown error
134
+ *
135
+ * @param error - The original error
136
+ * @param defaultCode - Default error code if not determinable
137
+ * @returns SmartCameraError
138
+ */
139
+ export function createSmartCameraError(error, defaultCode = 'UNKNOWN_ERROR') {
140
+ if (error instanceof Error) {
141
+ // Check for specific error types
142
+ const message = error.message.toLowerCase();
143
+ let code = defaultCode;
144
+ if (message.includes('permission')) {
145
+ code = 'PERMISSION_DENIED';
146
+ }
147
+ else if (message.includes('camera') && message.includes('unavailable')) {
148
+ code = 'CAMERA_UNAVAILABLE';
149
+ }
150
+ else if (message.includes('webrtc')) {
151
+ code = 'WEBRTC_ERROR';
152
+ }
153
+ else if (message.includes('mlkit') || message.includes('face detection')) {
154
+ code = 'ML_KIT_ERROR';
155
+ }
156
+ else if (message.includes('frame processor')) {
157
+ code = 'FRAME_PROCESSOR_ERROR';
158
+ }
159
+ return {
160
+ code,
161
+ message: error.message,
162
+ nativeError: error,
163
+ };
164
+ }
165
+ return {
166
+ code: defaultCode,
167
+ message: String(error),
168
+ };
169
+ }
170
+ /**
171
+ * Safely execute a function and return a SmartCameraError on failure
172
+ */
173
+ export async function safeExecute(fn, errorCode = 'UNKNOWN_ERROR') {
174
+ try {
175
+ const data = await fn();
176
+ return { data, error: null };
177
+ }
178
+ catch (error) {
179
+ return { data: null, error: createSmartCameraError(error, errorCode) };
180
+ }
181
+ }
182
+ // ============================================================================
183
+ // Validation Utilities
184
+ // ============================================================================
185
+ /**
186
+ * Validates face detection options
187
+ */
188
+ export function validateFaceDetectionOptions(options) {
189
+ const errors = [];
190
+ if (options.minFaceSize !== undefined) {
191
+ const minFaceSize = options.minFaceSize;
192
+ if (typeof minFaceSize !== 'number' || minFaceSize < 0 || minFaceSize > 1) {
193
+ errors.push('minFaceSize must be a number between 0 and 1');
194
+ }
195
+ }
196
+ if (options.performanceMode !== undefined) {
197
+ const mode = options.performanceMode;
198
+ if (mode !== 'fast' && mode !== 'accurate') {
199
+ errors.push('performanceMode must be "fast" or "accurate"');
200
+ }
201
+ }
202
+ if (options.landmarkMode !== undefined) {
203
+ const mode = options.landmarkMode;
204
+ if (mode !== 'none' && mode !== 'all') {
205
+ errors.push('landmarkMode must be "none" or "all"');
206
+ }
207
+ }
208
+ if (options.contourMode !== undefined) {
209
+ const mode = options.contourMode;
210
+ if (mode !== 'none' && mode !== 'all') {
211
+ errors.push('contourMode must be "none" or "all"');
212
+ }
213
+ }
214
+ if (options.classificationMode !== undefined) {
215
+ const mode = options.classificationMode;
216
+ if (mode !== 'none' && mode !== 'all') {
217
+ errors.push('classificationMode must be "none" or "all"');
218
+ }
219
+ }
220
+ // Warn about contourMode + trackingEnabled combination
221
+ if (options.contourMode === 'all' && options.trackingEnabled === true) {
222
+ errors.push('Warning: Using contourMode="all" with trackingEnabled=true is not recommended. ' +
223
+ 'Contour detection only works on the most prominent face, making tracking less useful.');
224
+ }
225
+ return errors;
226
+ }
227
+ /**
228
+ * Creates a performance monitor for frame processing
229
+ */
230
+ export function createPerformanceMonitor(windowSize = 30) {
231
+ const processingTimes = [];
232
+ let frameCount = 0;
233
+ let droppedFrames = 0;
234
+ let lastFrameTime = 0;
235
+ const targetFrameTime = 1000 / 30; // 30 FPS target
236
+ return {
237
+ startFrame: () => {
238
+ return Date.now();
239
+ },
240
+ endFrame: (startTime) => {
241
+ const processingTime = Date.now() - startTime;
242
+ processingTimes.push(processingTime);
243
+ // Keep only last N samples
244
+ if (processingTimes.length > windowSize) {
245
+ processingTimes.shift();
246
+ }
247
+ frameCount++;
248
+ // Check for dropped frames
249
+ const now = Date.now();
250
+ if (lastFrameTime > 0) {
251
+ const frameGap = now - lastFrameTime;
252
+ if (frameGap > targetFrameTime * 2) {
253
+ droppedFrames += Math.floor(frameGap / targetFrameTime) - 1;
254
+ }
255
+ }
256
+ lastFrameTime = now;
257
+ },
258
+ getMetrics: () => {
259
+ const times = processingTimes.length > 0 ? processingTimes : [0];
260
+ return {
261
+ frameCount,
262
+ averageProcessingTime: times.reduce((a, b) => a + b, 0) / times.length,
263
+ minProcessingTime: Math.min(...times),
264
+ maxProcessingTime: Math.max(...times),
265
+ droppedFrames,
266
+ };
267
+ },
268
+ reset: () => {
269
+ processingTimes.length = 0;
270
+ frameCount = 0;
271
+ droppedFrames = 0;
272
+ lastFrameTime = 0;
273
+ },
274
+ };
275
+ }
276
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,+EAA+E;AAC/E,cAAc;AACd,+EAA+E;AAE/E;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,gBAAgB,CAAC,SAAiB;IAChD,MAAM,aAAa,GAAG,IAAI,GAAG,SAAS,CAAC;IACvC,IAAI,aAAa,GAAG,CAAC,CAAC;IAEtB,OAAO;QACL,aAAa,EAAE,GAAY,EAAE;YAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACvB,IAAI,GAAG,GAAG,aAAa,IAAI,aAAa,EAAE,CAAC;gBACzC,aAAa,GAAG,GAAG,CAAC;gBACpB,OAAO,IAAI,CAAC;YACd,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QACD,KAAK,EAAE,GAAG,EAAE;YACV,aAAa,GAAG,CAAC,CAAC;QACpB,CAAC;QACD,YAAY,EAAE,CAAC,GAAW,EAAE,EAAE;YAC5B,mEAAmE;YACnE,yDAAyD;QAC3D,CAAC;KACF,CAAC;AACJ,CAAC;AAED,+EAA+E;AAC/E,WAAW;AACX,+EAA+E;AAE/E;;;;;;GAMG;AACH,MAAM,UAAU,QAAQ,CACtB,EAAK,EACL,KAAa;IAEb,IAAI,SAAS,GAAyC,IAAI,CAAC;IAE3D,OAAO,CAAC,GAAG,IAAmB,EAAE,EAAE;QAChC,IAAI,SAAS,EAAE,CAAC;YACd,YAAY,CAAC,SAAS,CAAC,CAAC;QAC1B,CAAC;QACD,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE;YAC1B,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;YACZ,SAAS,GAAG,IAAI,CAAC;QACnB,CAAC,EAAE,KAAK,CAAC,CAAC;IACZ,CAAC,CAAC;AACJ,CAAC;AAED,+EAA+E;AAC/E,WAAW;AACX,+EAA+E;AAE/E;;;;;;GAMG;AACH,MAAM,UAAU,QAAQ,CACtB,EAAK,EACL,KAAa;IAEb,IAAI,QAAQ,GAAG,CAAC,CAAC;IAEjB,OAAO,CAAC,GAAG,IAAmB,EAAE,EAAE;QAChC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,IAAI,GAAG,GAAG,QAAQ,IAAI,KAAK,EAAE,CAAC;YAC5B,QAAQ,GAAG,GAAG,CAAC;YACf,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;QACd,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAWD;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAC9B,OAAgB,EAChB,cAAsB,EAAE,EACxB,UAAkB,GAAG;IAErB,MAAM,IAAI,GAAsB,EAAE,CAAC;IAEnC,oBAAoB;IACpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/C,CAAC;IAED,OAAO;QACL,OAAO,EAAE,GAAM,EAAE;YACf,2BAA2B;YAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACjD,IAAI,SAAS,EAAE,CAAC;gBACd,SAAS,CAAC,KAAK,GAAG,IAAI,CAAC;gBACvB,OAAO,SAAS,CAAC,IAAI,CAAC;YACxB,CAAC;YAED,gCAAgC;YAChC,IAAI,IAAI,CAAC,MAAM,GAAG,OAAO,EAAE,CAAC;gBAC1B,MAAM,MAAM,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;gBAChD,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBAClB,OAAO,MAAM,CAAC,IAAI,CAAC;YACrB,CAAC;YAED,0CAA0C;YAC1C,OAAO,OAAO,EAAE,CAAC;QACnB,CAAC;QAED,OAAO,EAAE,CAAC,GAAM,EAAQ,EAAE;YACxB,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC;YACnD,IAAI,SAAS,EAAE,CAAC;gBACd,SAAS,CAAC,KAAK,GAAG,KAAK,CAAC;YAC1B,CAAC;QACH,CAAC;QAED,KAAK,EAAE,GAAS,EAAE;YAChB,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QAClB,CAAC;QAED,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC;YACf,IAAI,EAAE,IAAI,CAAC,MAAM;YACjB,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM;YACzC,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM;SAC/C,CAAC;KACH,CAAC;AACJ,CAAC;AAQD;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CACpC,KAAc,EACd,cAAoC,eAAe;IAEnD,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,iCAAiC;QACjC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;QAE5C,IAAI,IAAI,GAAyB,WAAW,CAAC;QAC7C,IAAI,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;YACnC,IAAI,GAAG,mBAAmB,CAAC;QAC7B,CAAC;aAAM,IAAI,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;YACzE,IAAI,GAAG,oBAAoB,CAAC;QAC9B,CAAC;aAAM,IAAI,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YACtC,IAAI,GAAG,cAAc,CAAC;QACxB,CAAC;aAAM,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC;YAC3E,IAAI,GAAG,cAAc,CAAC;QACxB,CAAC;aAAM,IAAI,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC;YAC/C,IAAI,GAAG,uBAAuB,CAAC;QACjC,CAAC;QAED,OAAO;YACL,IAAI;YACJ,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,WAAW,EAAE,KAAK;SACnB,CAAC;IACJ,CAAC;IAED,OAAO;QACL,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC;KACvB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,EAAoB,EACpB,YAAkC,eAAe;IAEjD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,EAAE,EAAE,CAAC;QACxB,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAC/B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,sBAAsB,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE,CAAC;IACzE,CAAC;AACH,CAAC;AAED,+EAA+E;AAC/E,uBAAuB;AACvB,+EAA+E;AAE/E;;GAEG;AACH,MAAM,UAAU,4BAA4B,CAAC,OAAgC;IAC3E,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,IAAI,OAAO,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;QACtC,MAAM,WAAW,GAAG,OAAO,CAAC,WAAqB,CAAC;QAClD,IAAI,OAAO,WAAW,KAAK,QAAQ,IAAI,WAAW,GAAG,CAAC,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;YAC1E,MAAM,CAAC,IAAI,CAAC,8CAA8C,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC;IAED,IAAI,OAAO,CAAC,eAAe,KAAK,SAAS,EAAE,CAAC;QAC1C,MAAM,IAAI,GAAG,OAAO,CAAC,eAAyB,CAAC;QAC/C,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;YAC3C,MAAM,CAAC,IAAI,CAAC,8CAA8C,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC;IAED,IAAI,OAAO,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;QACvC,MAAM,IAAI,GAAG,OAAO,CAAC,YAAsB,CAAC;QAC5C,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;YACtC,MAAM,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;IAED,IAAI,OAAO,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,OAAO,CAAC,WAAqB,CAAC;QAC3C,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;YACtC,MAAM,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;IAED,IAAI,OAAO,CAAC,kBAAkB,KAAK,SAAS,EAAE,CAAC;QAC7C,MAAM,IAAI,GAAG,OAAO,CAAC,kBAA4B,CAAC;QAClD,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;YACtC,MAAM,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IAED,uDAAuD;IACvD,IAAI,OAAO,CAAC,WAAW,KAAK,KAAK,IAAI,OAAO,CAAC,eAAe,KAAK,IAAI,EAAE,CAAC;QACtE,MAAM,CAAC,IAAI,CACT,iFAAiF;YACjF,uFAAuF,CACxF,CAAC;IACJ,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAcD;;GAEG;AACH,MAAM,UAAU,wBAAwB,CAAC,aAAqB,EAAE;IAC9D,MAAM,eAAe,GAAa,EAAE,CAAC;IACrC,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,aAAa,GAAG,CAAC,CAAC;IACtB,IAAI,aAAa,GAAG,CAAC,CAAC;IACtB,MAAM,eAAe,GAAG,IAAI,GAAG,EAAE,CAAC,CAAC,gBAAgB;IAEnD,OAAO;QACL,UAAU,EAAE,GAAW,EAAE;YACvB,OAAO,IAAI,CAAC,GAAG,EAAE,CAAC;QACpB,CAAC;QAED,QAAQ,EAAE,CAAC,SAAiB,EAAQ,EAAE;YACpC,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;YAC9C,eAAe,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAErC,2BAA2B;YAC3B,IAAI,eAAe,CAAC,MAAM,GAAG,UAAU,EAAE,CAAC;gBACxC,eAAe,CAAC,KAAK,EAAE,CAAC;YAC1B,CAAC;YAED,UAAU,EAAE,CAAC;YAEb,2BAA2B;YAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACvB,IAAI,aAAa,GAAG,CAAC,EAAE,CAAC;gBACtB,MAAM,QAAQ,GAAG,GAAG,GAAG,aAAa,CAAC;gBACrC,IAAI,QAAQ,GAAG,eAAe,GAAG,CAAC,EAAE,CAAC;oBACnC,aAAa,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;gBAC9D,CAAC;YACH,CAAC;YACD,aAAa,GAAG,GAAG,CAAC;QACtB,CAAC;QAED,UAAU,EAAE,GAAuB,EAAE;YACnC,MAAM,KAAK,GAAG,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACjE,OAAO;gBACL,UAAU;gBACV,qBAAqB,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM;gBACtE,iBAAiB,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;gBACrC,iBAAiB,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;gBACrC,aAAa;aACd,CAAC;QACJ,CAAC;QAED,KAAK,EAAE,GAAS,EAAE;YAChB,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC;YAC3B,UAAU,GAAG,CAAC,CAAC;YACf,aAAa,GAAG,CAAC,CAAC;YAClB,aAAa,GAAG,CAAC,CAAC;QACpB,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["/**\n * SmartCamera utility functions\n */\n\n// ============================================================================\n// FPS Limiter\n// ============================================================================\n\n/**\n * Creates an FPS limiter for frame processing\n * \n * @param targetFps - Target frames per second\n * @returns Object with shouldProcess function\n * \n * @example\n * ```ts\n * const limiter = createFpsLimiter(15);\n * \n * const frameProcessor = useFrameProcessor((frame) => {\n * if (!limiter.shouldProcess()) return;\n * // Process frame...\n * }, []);\n * ```\n */\nexport function createFpsLimiter(targetFps: number) {\n const frameInterval = 1000 / targetFps;\n let lastFrameTime = 0;\n\n return {\n shouldProcess: (): boolean => {\n const now = Date.now();\n if (now - lastFrameTime >= frameInterval) {\n lastFrameTime = now;\n return true;\n }\n return false;\n },\n reset: () => {\n lastFrameTime = 0;\n },\n setTargetFps: (fps: number) => {\n // Note: This creates a new interval but doesn't update the closure\n // Consider using a ref if dynamic FPS changes are needed\n },\n };\n}\n\n// ============================================================================\n// Debounce\n// ============================================================================\n\n/**\n * Creates a debounced function\n * \n * @param fn - Function to debounce\n * @param delay - Delay in milliseconds\n * @returns Debounced function\n */\nexport function debounce<T extends (...args: unknown[]) => unknown>(\n fn: T,\n delay: number\n): (...args: Parameters<T>) => void {\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n return (...args: Parameters<T>) => {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n timeoutId = setTimeout(() => {\n fn(...args);\n timeoutId = null;\n }, delay);\n };\n}\n\n// ============================================================================\n// Throttle\n// ============================================================================\n\n/**\n * Creates a throttled function\n * \n * @param fn - Function to throttle\n * @param limit - Minimum time between calls in milliseconds\n * @returns Throttled function\n */\nexport function throttle<T extends (...args: unknown[]) => unknown>(\n fn: T,\n limit: number\n): (...args: Parameters<T>) => void {\n let lastCall = 0;\n\n return (...args: Parameters<T>) => {\n const now = Date.now();\n if (now - lastCall >= limit) {\n lastCall = now;\n fn(...args);\n }\n };\n}\n\n// ============================================================================\n// Memory Pool for Face Objects\n// ============================================================================\n\ninterface PooledObject<T> {\n data: T;\n inUse: boolean;\n}\n\n/**\n * Creates an object pool for reducing garbage collection\n * \n * @param factory - Factory function to create new objects\n * @param initialSize - Initial pool size\n * @param maxSize - Maximum pool size\n */\nexport function createObjectPool<T>(\n factory: () => T,\n initialSize: number = 10,\n maxSize: number = 100\n) {\n const pool: PooledObject<T>[] = [];\n\n // Pre-populate pool\n for (let i = 0; i < initialSize; i++) {\n pool.push({ data: factory(), inUse: false });\n }\n\n return {\n acquire: (): T => {\n // Find an available object\n const available = pool.find((obj) => !obj.inUse);\n if (available) {\n available.inUse = true;\n return available.data;\n }\n\n // Create new if pool not at max\n if (pool.length < maxSize) {\n const newObj = { data: factory(), inUse: true };\n pool.push(newObj);\n return newObj.data;\n }\n\n // Pool exhausted, create temporary object\n return factory();\n },\n\n release: (obj: T): void => {\n const pooledObj = pool.find((p) => p.data === obj);\n if (pooledObj) {\n pooledObj.inUse = false;\n }\n },\n\n clear: (): void => {\n pool.length = 0;\n },\n\n getStats: () => ({\n size: pool.length,\n inUse: pool.filter((p) => p.inUse).length,\n available: pool.filter((p) => !p.inUse).length,\n }),\n };\n}\n\n// ============================================================================\n// Error Utilities\n// ============================================================================\n\nimport type { SmartCameraError, SmartCameraErrorCode } from '../types';\n\n/**\n * Creates a SmartCameraError from an unknown error\n * \n * @param error - The original error\n * @param defaultCode - Default error code if not determinable\n * @returns SmartCameraError\n */\nexport function createSmartCameraError(\n error: unknown,\n defaultCode: SmartCameraErrorCode = 'UNKNOWN_ERROR'\n): SmartCameraError {\n if (error instanceof Error) {\n // Check for specific error types\n const message = error.message.toLowerCase();\n\n let code: SmartCameraErrorCode = defaultCode;\n if (message.includes('permission')) {\n code = 'PERMISSION_DENIED';\n } else if (message.includes('camera') && message.includes('unavailable')) {\n code = 'CAMERA_UNAVAILABLE';\n } else if (message.includes('webrtc')) {\n code = 'WEBRTC_ERROR';\n } else if (message.includes('mlkit') || message.includes('face detection')) {\n code = 'ML_KIT_ERROR';\n } else if (message.includes('frame processor')) {\n code = 'FRAME_PROCESSOR_ERROR';\n }\n\n return {\n code,\n message: error.message,\n nativeError: error,\n };\n }\n\n return {\n code: defaultCode,\n message: String(error),\n };\n}\n\n/**\n * Safely execute a function and return a SmartCameraError on failure\n */\nexport async function safeExecute<T>(\n fn: () => Promise<T>,\n errorCode: SmartCameraErrorCode = 'UNKNOWN_ERROR'\n): Promise<{ data: T; error: null } | { data: null; error: SmartCameraError }> {\n try {\n const data = await fn();\n return { data, error: null };\n } catch (error) {\n return { data: null, error: createSmartCameraError(error, errorCode) };\n }\n}\n\n// ============================================================================\n// Validation Utilities\n// ============================================================================\n\n/**\n * Validates face detection options\n */\nexport function validateFaceDetectionOptions(options: Record<string, unknown>): string[] {\n const errors: string[] = [];\n\n if (options.minFaceSize !== undefined) {\n const minFaceSize = options.minFaceSize as number;\n if (typeof minFaceSize !== 'number' || minFaceSize < 0 || minFaceSize > 1) {\n errors.push('minFaceSize must be a number between 0 and 1');\n }\n }\n\n if (options.performanceMode !== undefined) {\n const mode = options.performanceMode as string;\n if (mode !== 'fast' && mode !== 'accurate') {\n errors.push('performanceMode must be \"fast\" or \"accurate\"');\n }\n }\n\n if (options.landmarkMode !== undefined) {\n const mode = options.landmarkMode as string;\n if (mode !== 'none' && mode !== 'all') {\n errors.push('landmarkMode must be \"none\" or \"all\"');\n }\n }\n\n if (options.contourMode !== undefined) {\n const mode = options.contourMode as string;\n if (mode !== 'none' && mode !== 'all') {\n errors.push('contourMode must be \"none\" or \"all\"');\n }\n }\n\n if (options.classificationMode !== undefined) {\n const mode = options.classificationMode as string;\n if (mode !== 'none' && mode !== 'all') {\n errors.push('classificationMode must be \"none\" or \"all\"');\n }\n }\n\n // Warn about contourMode + trackingEnabled combination\n if (options.contourMode === 'all' && options.trackingEnabled === true) {\n errors.push(\n 'Warning: Using contourMode=\"all\" with trackingEnabled=true is not recommended. ' +\n 'Contour detection only works on the most prominent face, making tracking less useful.'\n );\n }\n\n return errors;\n}\n\n// ============================================================================\n// Performance Monitoring\n// ============================================================================\n\ninterface PerformanceMetrics {\n frameCount: number;\n averageProcessingTime: number;\n minProcessingTime: number;\n maxProcessingTime: number;\n droppedFrames: number;\n}\n\n/**\n * Creates a performance monitor for frame processing\n */\nexport function createPerformanceMonitor(windowSize: number = 30) {\n const processingTimes: number[] = [];\n let frameCount = 0;\n let droppedFrames = 0;\n let lastFrameTime = 0;\n const targetFrameTime = 1000 / 30; // 30 FPS target\n\n return {\n startFrame: (): number => {\n return Date.now();\n },\n\n endFrame: (startTime: number): void => {\n const processingTime = Date.now() - startTime;\n processingTimes.push(processingTime);\n \n // Keep only last N samples\n if (processingTimes.length > windowSize) {\n processingTimes.shift();\n }\n\n frameCount++;\n\n // Check for dropped frames\n const now = Date.now();\n if (lastFrameTime > 0) {\n const frameGap = now - lastFrameTime;\n if (frameGap > targetFrameTime * 2) {\n droppedFrames += Math.floor(frameGap / targetFrameTime) - 1;\n }\n }\n lastFrameTime = now;\n },\n\n getMetrics: (): PerformanceMetrics => {\n const times = processingTimes.length > 0 ? processingTimes : [0];\n return {\n frameCount,\n averageProcessingTime: times.reduce((a, b) => a + b, 0) / times.length,\n minProcessingTime: Math.min(...times),\n maxProcessingTime: Math.max(...times),\n droppedFrames,\n };\n },\n\n reset: (): void => {\n processingTimes.length = 0;\n frameCount = 0;\n droppedFrames = 0;\n lastFrameTime = 0;\n },\n };\n}\n\n"]}
@@ -0,0 +1,55 @@
1
+ import type { WebRTCVideoSourceConfig, WebRTCStreamStats, WebRTCQualitySettings } from './types';
2
+ /**
3
+ * WebRTC Bridge for SmartCamera
4
+ *
5
+ * This class provides a bridge between VisionCamera frames and WebRTC,
6
+ * allowing camera frames to be streamed via WebRTC peer connections.
7
+ */
8
+ export declare class WebRTCBridge {
9
+ private isInitialized;
10
+ private isStreaming;
11
+ private config;
12
+ /**
13
+ * Initialize the WebRTC bridge
14
+ *
15
+ * This must be called before starting streaming.
16
+ */
17
+ initialize(): Promise<void>;
18
+ /**
19
+ * Start streaming camera frames via WebRTC
20
+ *
21
+ * @param config - Video source configuration
22
+ */
23
+ startStreaming(config: WebRTCVideoSourceConfig): Promise<void>;
24
+ /**
25
+ * Stop streaming
26
+ */
27
+ stopStreaming(): Promise<void>;
28
+ /**
29
+ * Check if currently streaming
30
+ */
31
+ getIsStreaming(): boolean;
32
+ /**
33
+ * Get current configuration
34
+ */
35
+ getConfig(): WebRTCVideoSourceConfig | null;
36
+ /**
37
+ * Update quality settings (if supported)
38
+ *
39
+ * @param settings - Quality settings to apply
40
+ */
41
+ updateQuality(settings: WebRTCQualitySettings): Promise<void>;
42
+ /**
43
+ * Get current stream statistics
44
+ */
45
+ getStats(): Promise<WebRTCStreamStats | null>;
46
+ /**
47
+ * Cleanup and release resources
48
+ */
49
+ destroy(): Promise<void>;
50
+ }
51
+ /**
52
+ * Get the shared WebRTC bridge instance
53
+ */
54
+ export declare function getWebRTCBridge(): WebRTCBridge;
55
+ //# sourceMappingURL=WebRTCBridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WebRTCBridge.d.ts","sourceRoot":"","sources":["../../src/webrtc/WebRTCBridge.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,uBAAuB,EACvB,iBAAiB,EACjB,qBAAqB,EACtB,MAAM,SAAS,CAAC;AAEjB;;;;;GAKG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,MAAM,CAAwC;IAEtD;;;;OAIG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IASjC;;;;OAIG;IACG,cAAc,CAAC,MAAM,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBpE;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAUpC;;OAEG;IACH,cAAc,IAAI,OAAO;IAIzB;;OAEG;IACH,SAAS,IAAI,uBAAuB,GAAG,IAAI;IAI3C;;;;OAIG;IACG,aAAa,CAAC,QAAQ,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IAKnE;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAgBnD;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAI/B;AAKD;;GAEG;AACH,wBAAgB,eAAe,IAAI,YAAY,CAK9C"}
@@ -0,0 +1,113 @@
1
+ import SmartCameraModule from '../SmartCameraModule';
2
+ /**
3
+ * WebRTC Bridge for SmartCamera
4
+ *
5
+ * This class provides a bridge between VisionCamera frames and WebRTC,
6
+ * allowing camera frames to be streamed via WebRTC peer connections.
7
+ */
8
+ export class WebRTCBridge {
9
+ isInitialized = false;
10
+ isStreaming = false;
11
+ config = null;
12
+ /**
13
+ * Initialize the WebRTC bridge
14
+ *
15
+ * This must be called before starting streaming.
16
+ */
17
+ async initialize() {
18
+ if (this.isInitialized) {
19
+ return;
20
+ }
21
+ await SmartCameraModule.initializeWebRTC();
22
+ this.isInitialized = true;
23
+ }
24
+ /**
25
+ * Start streaming camera frames via WebRTC
26
+ *
27
+ * @param config - Video source configuration
28
+ */
29
+ async startStreaming(config) {
30
+ if (!this.isInitialized) {
31
+ await this.initialize();
32
+ }
33
+ if (this.isStreaming) {
34
+ console.warn('[WebRTCBridge] Already streaming, stopping first');
35
+ await this.stopStreaming();
36
+ }
37
+ this.config = config;
38
+ await SmartCameraModule.startWebRTCStream({
39
+ width: config.width,
40
+ height: config.height,
41
+ frameRate: config.frameRate,
42
+ });
43
+ this.isStreaming = true;
44
+ }
45
+ /**
46
+ * Stop streaming
47
+ */
48
+ async stopStreaming() {
49
+ if (!this.isStreaming) {
50
+ return;
51
+ }
52
+ await SmartCameraModule.stopWebRTCStream();
53
+ this.isStreaming = false;
54
+ this.config = null;
55
+ }
56
+ /**
57
+ * Check if currently streaming
58
+ */
59
+ getIsStreaming() {
60
+ return this.isStreaming;
61
+ }
62
+ /**
63
+ * Get current configuration
64
+ */
65
+ getConfig() {
66
+ return this.config;
67
+ }
68
+ /**
69
+ * Update quality settings (if supported)
70
+ *
71
+ * @param settings - Quality settings to apply
72
+ */
73
+ async updateQuality(settings) {
74
+ // This would call a native method to adjust encoder settings
75
+ console.log('[WebRTCBridge] Updating quality:', settings);
76
+ }
77
+ /**
78
+ * Get current stream statistics
79
+ */
80
+ async getStats() {
81
+ if (!this.isStreaming) {
82
+ return null;
83
+ }
84
+ // This would call a native method to get stats
85
+ // For now, return placeholder
86
+ return {
87
+ frameRate: this.config?.frameRate ?? 0,
88
+ framesSent: 0,
89
+ framesDropped: 0,
90
+ bytesSent: 0,
91
+ bitrate: 0,
92
+ };
93
+ }
94
+ /**
95
+ * Cleanup and release resources
96
+ */
97
+ async destroy() {
98
+ await this.stopStreaming();
99
+ this.isInitialized = false;
100
+ }
101
+ }
102
+ // Singleton instance for convenience
103
+ let bridgeInstance = null;
104
+ /**
105
+ * Get the shared WebRTC bridge instance
106
+ */
107
+ export function getWebRTCBridge() {
108
+ if (!bridgeInstance) {
109
+ bridgeInstance = new WebRTCBridge();
110
+ }
111
+ return bridgeInstance;
112
+ }
113
+ //# sourceMappingURL=WebRTCBridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WebRTCBridge.js","sourceRoot":"","sources":["../../src/webrtc/WebRTCBridge.ts"],"names":[],"mappings":"AAAA,OAAO,iBAAiB,MAAM,sBAAsB,CAAC;AAOrD;;;;;GAKG;AACH,MAAM,OAAO,YAAY;IACf,aAAa,GAAG,KAAK,CAAC;IACtB,WAAW,GAAG,KAAK,CAAC;IACpB,MAAM,GAAmC,IAAI,CAAC;IAEtD;;;;OAIG;IACH,KAAK,CAAC,UAAU;QACd,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,OAAO;QACT,CAAC;QAED,MAAM,iBAAiB,CAAC,gBAAgB,EAAE,CAAC;QAC3C,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;IAC5B,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,cAAc,CAAC,MAA+B;QAClD,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;YACxB,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;QAC1B,CAAC;QAED,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,OAAO,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC;YACjE,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;QAC7B,CAAC;QAED,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,MAAM,iBAAiB,CAAC,iBAAiB,CAAC;YACxC,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,SAAS,EAAE,MAAM,CAAC,SAAS;SAC5B,CAAC,CAAC;QACH,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;IAC1B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,aAAa;QACjB,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,OAAO;QACT,CAAC;QAED,MAAM,iBAAiB,CAAC,gBAAgB,EAAE,CAAC;QAC3C,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;QACzB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;IACrB,CAAC;IAED;;OAEG;IACH,cAAc;QACZ,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED;;OAEG;IACH,SAAS;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,aAAa,CAAC,QAA+B;QACjD,6DAA6D;QAC7D,OAAO,CAAC,GAAG,CAAC,kCAAkC,EAAE,QAAQ,CAAC,CAAC;IAC5D,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,QAAQ;QACZ,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,+CAA+C;QAC/C,8BAA8B;QAC9B,OAAO;YACL,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,SAAS,IAAI,CAAC;YACtC,UAAU,EAAE,CAAC;YACb,aAAa,EAAE,CAAC;YAChB,SAAS,EAAE,CAAC;YACZ,OAAO,EAAE,CAAC;SACX,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO;QACX,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;QAC3B,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;IAC7B,CAAC;CACF;AAED,qCAAqC;AACrC,IAAI,cAAc,GAAwB,IAAI,CAAC;AAE/C;;GAEG;AACH,MAAM,UAAU,eAAe;IAC7B,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,cAAc,GAAG,IAAI,YAAY,EAAE,CAAC;IACtC,CAAC;IACD,OAAO,cAAc,CAAC;AACxB,CAAC","sourcesContent":["import SmartCameraModule from '../SmartCameraModule';\nimport type {\n WebRTCVideoSourceConfig,\n WebRTCStreamStats,\n WebRTCQualitySettings,\n} from './types';\n\n/**\n * WebRTC Bridge for SmartCamera\n * \n * This class provides a bridge between VisionCamera frames and WebRTC,\n * allowing camera frames to be streamed via WebRTC peer connections.\n */\nexport class WebRTCBridge {\n private isInitialized = false;\n private isStreaming = false;\n private config: WebRTCVideoSourceConfig | null = null;\n\n /**\n * Initialize the WebRTC bridge\n * \n * This must be called before starting streaming.\n */\n async initialize(): Promise<void> {\n if (this.isInitialized) {\n return;\n }\n\n await SmartCameraModule.initializeWebRTC();\n this.isInitialized = true;\n }\n\n /**\n * Start streaming camera frames via WebRTC\n * \n * @param config - Video source configuration\n */\n async startStreaming(config: WebRTCVideoSourceConfig): Promise<void> {\n if (!this.isInitialized) {\n await this.initialize();\n }\n\n if (this.isStreaming) {\n console.warn('[WebRTCBridge] Already streaming, stopping first');\n await this.stopStreaming();\n }\n\n this.config = config;\n await SmartCameraModule.startWebRTCStream({\n width: config.width,\n height: config.height,\n frameRate: config.frameRate,\n });\n this.isStreaming = true;\n }\n\n /**\n * Stop streaming\n */\n async stopStreaming(): Promise<void> {\n if (!this.isStreaming) {\n return;\n }\n\n await SmartCameraModule.stopWebRTCStream();\n this.isStreaming = false;\n this.config = null;\n }\n\n /**\n * Check if currently streaming\n */\n getIsStreaming(): boolean {\n return this.isStreaming;\n }\n\n /**\n * Get current configuration\n */\n getConfig(): WebRTCVideoSourceConfig | null {\n return this.config;\n }\n\n /**\n * Update quality settings (if supported)\n * \n * @param settings - Quality settings to apply\n */\n async updateQuality(settings: WebRTCQualitySettings): Promise<void> {\n // This would call a native method to adjust encoder settings\n console.log('[WebRTCBridge] Updating quality:', settings);\n }\n\n /**\n * Get current stream statistics\n */\n async getStats(): Promise<WebRTCStreamStats | null> {\n if (!this.isStreaming) {\n return null;\n }\n\n // This would call a native method to get stats\n // For now, return placeholder\n return {\n frameRate: this.config?.frameRate ?? 0,\n framesSent: 0,\n framesDropped: 0,\n bytesSent: 0,\n bitrate: 0,\n };\n }\n\n /**\n * Cleanup and release resources\n */\n async destroy(): Promise<void> {\n await this.stopStreaming();\n this.isInitialized = false;\n }\n}\n\n// Singleton instance for convenience\nlet bridgeInstance: WebRTCBridge | null = null;\n\n/**\n * Get the shared WebRTC bridge instance\n */\nexport function getWebRTCBridge(): WebRTCBridge {\n if (!bridgeInstance) {\n bridgeInstance = new WebRTCBridge();\n }\n return bridgeInstance;\n}\n\n"]}
@@ -0,0 +1,3 @@
1
+ export { WebRTCBridge, getWebRTCBridge } from './WebRTCBridge';
2
+ export type { VideoFrameFormat, WebRTCVideoSourceConfig, WebRTCConnectionState, WebRTCStreamStats, WebRTCQualitySettings, WebRTCStreamEvent, } from './types';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/webrtc/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC/D,YAAY,EACV,gBAAgB,EAChB,uBAAuB,EACvB,qBAAqB,EACrB,iBAAiB,EACjB,qBAAqB,EACrB,iBAAiB,GAClB,MAAM,SAAS,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { WebRTCBridge, getWebRTCBridge } from './WebRTCBridge';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/webrtc/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC","sourcesContent":["export { WebRTCBridge, getWebRTCBridge } from './WebRTCBridge';\nexport type {\n VideoFrameFormat,\n WebRTCVideoSourceConfig,\n WebRTCConnectionState,\n WebRTCStreamStats,\n WebRTCQualitySettings,\n WebRTCStreamEvent,\n} from './types';\n"]}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * WebRTC-related types for the SmartCamera module
3
+ */
4
+ /**
5
+ * Video frame format for WebRTC
6
+ */
7
+ export type VideoFrameFormat = 'I420' | 'NV12' | 'NV21' | 'BGRA';
8
+ /**
9
+ * Configuration for the WebRTC video source
10
+ */
11
+ export interface WebRTCVideoSourceConfig {
12
+ /** Frame width in pixels */
13
+ width: number;
14
+ /** Frame height in pixels */
15
+ height: number;
16
+ /** Target frame rate */
17
+ frameRate: number;
18
+ /** Video frame format. Default: 'I420' */
19
+ format?: VideoFrameFormat;
20
+ }
21
+ /**
22
+ * WebRTC connection state
23
+ */
24
+ export type WebRTCConnectionState = 'new' | 'connecting' | 'connected' | 'disconnected' | 'failed' | 'closed';
25
+ /**
26
+ * WebRTC stream statistics
27
+ */
28
+ export interface WebRTCStreamStats {
29
+ /** Current frame rate */
30
+ frameRate: number;
31
+ /** Frames sent */
32
+ framesSent: number;
33
+ /** Frames dropped */
34
+ framesDropped: number;
35
+ /** Bytes sent */
36
+ bytesSent: number;
37
+ /** Current bitrate in bps */
38
+ bitrate: number;
39
+ /** Round-trip time in ms */
40
+ rtt?: number;
41
+ }
42
+ /**
43
+ * WebRTC stream quality settings
44
+ */
45
+ export interface WebRTCQualitySettings {
46
+ /** Maximum bitrate in bps */
47
+ maxBitrate?: number;
48
+ /** Minimum bitrate in bps */
49
+ minBitrate?: number;
50
+ /** Target frame rate */
51
+ targetFrameRate?: number;
52
+ /** Resolution scale (0.0 - 1.0) */
53
+ resolutionScale?: number;
54
+ }
55
+ /**
56
+ * Event emitted when WebRTC stream state changes
57
+ */
58
+ export interface WebRTCStreamEvent {
59
+ type: 'started' | 'stopped' | 'error' | 'stats';
60
+ timestamp: number;
61
+ error?: Error;
62
+ stats?: WebRTCStreamStats;
63
+ }
64
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/webrtc/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAEjE;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAC;IAEd,6BAA6B;IAC7B,MAAM,EAAE,MAAM,CAAC;IAEf,wBAAwB;IACxB,SAAS,EAAE,MAAM,CAAC;IAElB,0CAA0C;IAC1C,MAAM,CAAC,EAAE,gBAAgB,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAC7B,KAAK,GACL,YAAY,GACZ,WAAW,GACX,cAAc,GACd,QAAQ,GACR,QAAQ,CAAC;AAEb;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAC;IAElB,kBAAkB;IAClB,UAAU,EAAE,MAAM,CAAC;IAEnB,qBAAqB;IACrB,aAAa,EAAE,MAAM,CAAC;IAEtB,iBAAiB;IACjB,SAAS,EAAE,MAAM,CAAC;IAElB,6BAA6B;IAC7B,OAAO,EAAE,MAAM,CAAC;IAEhB,4BAA4B;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,6BAA6B;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,6BAA6B;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,wBAAwB;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,mCAAmC;IACnC,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,KAAK,CAAC,EAAE,iBAAiB,CAAC;CAC3B"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * WebRTC-related types for the SmartCamera module
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/webrtc/types.ts"],"names":[],"mappings":"AAAA;;GAEG","sourcesContent":["/**\n * WebRTC-related types for the SmartCamera module\n */\n\n/**\n * Video frame format for WebRTC\n */\nexport type VideoFrameFormat = 'I420' | 'NV12' | 'NV21' | 'BGRA';\n\n/**\n * Configuration for the WebRTC video source\n */\nexport interface WebRTCVideoSourceConfig {\n /** Frame width in pixels */\n width: number;\n \n /** Frame height in pixels */\n height: number;\n \n /** Target frame rate */\n frameRate: number;\n \n /** Video frame format. Default: 'I420' */\n format?: VideoFrameFormat;\n}\n\n/**\n * WebRTC connection state\n */\nexport type WebRTCConnectionState =\n | 'new'\n | 'connecting'\n | 'connected'\n | 'disconnected'\n | 'failed'\n | 'closed';\n\n/**\n * WebRTC stream statistics\n */\nexport interface WebRTCStreamStats {\n /** Current frame rate */\n frameRate: number;\n \n /** Frames sent */\n framesSent: number;\n \n /** Frames dropped */\n framesDropped: number;\n \n /** Bytes sent */\n bytesSent: number;\n \n /** Current bitrate in bps */\n bitrate: number;\n \n /** Round-trip time in ms */\n rtt?: number;\n}\n\n/**\n * WebRTC stream quality settings\n */\nexport interface WebRTCQualitySettings {\n /** Maximum bitrate in bps */\n maxBitrate?: number;\n \n /** Minimum bitrate in bps */\n minBitrate?: number;\n \n /** Target frame rate */\n targetFrameRate?: number;\n \n /** Resolution scale (0.0 - 1.0) */\n resolutionScale?: number;\n}\n\n/**\n * Event emitted when WebRTC stream state changes\n */\nexport interface WebRTCStreamEvent {\n type: 'started' | 'stopped' | 'error' | 'stats';\n timestamp: number;\n error?: Error;\n stats?: WebRTCStreamStats;\n}\n\n"]}
@@ -0,0 +1,9 @@
1
+ {
2
+ "platforms": ["ios", "android"],
3
+ "ios": {
4
+ "modules": ["SmartCameraModule"]
5
+ },
6
+ "android": {
7
+ "modules": ["expo.modules.smartcamera.SmartCameraModule"]
8
+ }
9
+ }