serve-sim 0.1.25 → 0.1.26
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/README.md +1 -1
- package/Sources/SimCameraHelper/build.sh +1 -1
- package/Sources/SimCameraHelper/main.m +28 -17
- package/Sources/SimCameraInjector/SimCamFakes.h +86 -0
- package/Sources/SimCameraInjector/SimCamFakes.m +635 -0
- package/Sources/SimCameraInjector/SimCamFrameSource.h +26 -0
- package/Sources/SimCameraInjector/SimCamFrameSource.m +546 -0
- package/Sources/SimCameraInjector/SimCamLog.h +5 -0
- package/Sources/SimCameraInjector/SimCamLog.m +9 -0
- package/Sources/SimCameraInjector/SimCamSwizzles.h +3 -0
- package/Sources/SimCameraInjector/SimCamSwizzles.m +1014 -0
- package/Sources/SimCameraInjector/SimCameraInjector.m +9 -1150
- package/Sources/SimCameraInjector/build.sh +6 -1
- package/bin/serve-sim-bin +0 -0
- package/dist/middleware.js +18 -18
- package/dist/serve-sim.js +31 -31
- package/dist/simcam/libSimCameraInjector.dylib +0 -0
- package/dist/simcam/serve-sim-camera-helper +0 -0
- package/package.json +3 -1
- package/src/middleware.ts +39 -23
|
@@ -0,0 +1,635 @@
|
|
|
1
|
+
#import "SimCamFakes.h"
|
|
2
|
+
#import "SimCamLog.h"
|
|
3
|
+
|
|
4
|
+
#import <CoreImage/CoreImage.h>
|
|
5
|
+
#import <CoreMedia/CoreMedia.h>
|
|
6
|
+
#import <CoreVideo/CoreVideo.h>
|
|
7
|
+
#import <UIKit/UIKit.h>
|
|
8
|
+
#import <objc/runtime.h>
|
|
9
|
+
#import <objc/message.h>
|
|
10
|
+
#include <stdatomic.h>
|
|
11
|
+
#include <string.h>
|
|
12
|
+
|
|
13
|
+
#pragma mark - Mirror mode
|
|
14
|
+
|
|
15
|
+
static SimCamMirrorMode gMirrorMode = SimCamMirrorAuto;
|
|
16
|
+
|
|
17
|
+
SimCamMirrorMode SimCamGetMirrorMode(void) { return gMirrorMode; }
|
|
18
|
+
void SimCamSetMirrorMode(SimCamMirrorMode m) { gMirrorMode = m; }
|
|
19
|
+
|
|
20
|
+
BOOL SimCamShouldMirror(AVCaptureDevicePosition p) {
|
|
21
|
+
if (gMirrorMode == SimCamMirrorForceOn) return YES;
|
|
22
|
+
if (gMirrorMode == SimCamMirrorForceOff) return NO;
|
|
23
|
+
return p == AVCaptureDevicePositionFront;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
void SimCamReadMirrorModeFromEnv(void) {
|
|
27
|
+
const char *m = getenv("SIMCAM_MIRROR_MODE");
|
|
28
|
+
if (!m) return;
|
|
29
|
+
if (!strcasecmp(m, "on") || !strcmp(m, "1") || !strcasecmp(m, "true")) {
|
|
30
|
+
gMirrorMode = SimCamMirrorForceOn;
|
|
31
|
+
simcam_log(@"mirror mode forced ON");
|
|
32
|
+
} else if (!strcasecmp(m, "off") || !strcmp(m, "0") || !strcasecmp(m, "false")) {
|
|
33
|
+
gMirrorMode = SimCamMirrorForceOff;
|
|
34
|
+
simcam_log(@"mirror mode forced OFF");
|
|
35
|
+
} else if (!strcasecmp(m, "auto")) {
|
|
36
|
+
gMirrorMode = SimCamMirrorAuto;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
#pragma mark - Position tag tracking
|
|
41
|
+
|
|
42
|
+
static char kSimCamPositionKey;
|
|
43
|
+
|
|
44
|
+
AVCaptureDevicePosition SimCamPositionOf(id obj) {
|
|
45
|
+
if (!obj) return AVCaptureDevicePositionFront;
|
|
46
|
+
NSNumber *n = objc_getAssociatedObject(obj, &kSimCamPositionKey);
|
|
47
|
+
return n ? (AVCaptureDevicePosition)n.intValue : AVCaptureDevicePositionFront;
|
|
48
|
+
}
|
|
49
|
+
void SimCamSetPosition(id obj, AVCaptureDevicePosition p) {
|
|
50
|
+
objc_setAssociatedObject(obj, &kSimCamPositionKey, @(p), OBJC_ASSOCIATION_RETAIN);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
#pragma mark - Camera-in-use sticky flag
|
|
54
|
+
|
|
55
|
+
static atomic_int gSimCamCameraInUse = 0;
|
|
56
|
+
static char kSimCamSessionUsingFakeCameraKey;
|
|
57
|
+
|
|
58
|
+
BOOL SimCamCameraIsInUse(void) {
|
|
59
|
+
return atomic_load_explicit(&gSimCamCameraInUse, memory_order_relaxed) > 0;
|
|
60
|
+
}
|
|
61
|
+
void SimCamMarkCameraInUse(void) {
|
|
62
|
+
atomic_store_explicit(&gSimCamCameraInUse, 1, memory_order_relaxed);
|
|
63
|
+
}
|
|
64
|
+
void SimCamMarkSessionUsingFakeCamera(id session, BOOL usingFakeCamera) {
|
|
65
|
+
if (!session) return;
|
|
66
|
+
objc_setAssociatedObject(session,
|
|
67
|
+
&kSimCamSessionUsingFakeCameraKey,
|
|
68
|
+
usingFakeCamera ? @YES : nil,
|
|
69
|
+
OBJC_ASSOCIATION_RETAIN);
|
|
70
|
+
}
|
|
71
|
+
static BOOL SimCamSessionUsesFakeCamera(id session) {
|
|
72
|
+
if (!session) return NO;
|
|
73
|
+
if (![session isKindOfClass:[AVCaptureSession class]]) return NO;
|
|
74
|
+
return [objc_getAssociatedObject(session, &kSimCamSessionUsingFakeCameraKey) boolValue];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
#pragma mark - AVF runtime-error notification suppression
|
|
78
|
+
|
|
79
|
+
BOOL SimCamShouldSwallowAVFRuntimeError(NSNotificationName name, id object) {
|
|
80
|
+
if (!name) return NO;
|
|
81
|
+
if (![name isEqualToString:AVCaptureSessionRuntimeErrorNotification]) return NO;
|
|
82
|
+
return SimCamSessionUsesFakeCamera(object);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
void SimCamLogSwallowedRuntimeError(NSString *via, id object, NSDictionary *userInfo) {
|
|
86
|
+
NSError *err = userInfo[AVCaptureSessionErrorKey];
|
|
87
|
+
simcam_log(@"SWALLOW AVCaptureSessionRuntimeError via %@ object=%@ code=%ld domain=%@ desc=%@ underlying=%@",
|
|
88
|
+
via,
|
|
89
|
+
object ? NSStringFromClass([object class]) : @"<nil>",
|
|
90
|
+
(long)err.code,
|
|
91
|
+
err.domain ?: @"<nil>",
|
|
92
|
+
err.localizedDescription ?: @"<nil>",
|
|
93
|
+
err.userInfo[NSUnderlyingErrorKey] ?: @"<nil>");
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
#pragma mark - Weak delegate ref
|
|
97
|
+
|
|
98
|
+
@implementation SimCamWeakRef
|
|
99
|
+
@end
|
|
100
|
+
|
|
101
|
+
#pragma mark - SimCamFakeFrameRateRange
|
|
102
|
+
|
|
103
|
+
@interface SimCamFakeFrameRateRange : AVFrameRateRange
|
|
104
|
+
@end
|
|
105
|
+
@implementation SimCamFakeFrameRateRange
|
|
106
|
+
- (Float64)minFrameRate { return 1.0; }
|
|
107
|
+
- (Float64)maxFrameRate { return 60.0; }
|
|
108
|
+
- (CMTime)minFrameDuration { return CMTimeMake(1, 60); }
|
|
109
|
+
- (CMTime)maxFrameDuration { return CMTimeMake(1, 1); }
|
|
110
|
+
@end
|
|
111
|
+
|
|
112
|
+
#pragma mark - SimCamFakeFormat
|
|
113
|
+
|
|
114
|
+
@implementation SimCamFakeFormat {
|
|
115
|
+
CMVideoFormatDescriptionRef _fd;
|
|
116
|
+
NSArray<AVFrameRateRange *> *_ranges;
|
|
117
|
+
}
|
|
118
|
+
- (CMFormatDescriptionRef)formatDescription {
|
|
119
|
+
if (!_fd) {
|
|
120
|
+
CMVideoFormatDescriptionCreate(kCFAllocatorDefault,
|
|
121
|
+
kCVPixelFormatType_32BGRA, 1280, 720, NULL, &_fd);
|
|
122
|
+
}
|
|
123
|
+
return _fd;
|
|
124
|
+
}
|
|
125
|
+
- (NSArray<AVFrameRateRange *> *)videoSupportedFrameRateRanges {
|
|
126
|
+
if (!_ranges) {
|
|
127
|
+
AVFrameRateRange *r = (AVFrameRateRange *)class_createInstance(
|
|
128
|
+
[SimCamFakeFrameRateRange class], 0);
|
|
129
|
+
_ranges = r ? @[r] : @[];
|
|
130
|
+
}
|
|
131
|
+
return _ranges;
|
|
132
|
+
}
|
|
133
|
+
- (NSString *)mediaType { return AVMediaTypeVideo; }
|
|
134
|
+
- (FourCharCode)mediaSubType { return kCVPixelFormatType_32BGRA; }
|
|
135
|
+
- (CMVideoDimensions)highResolutionStillImageDimensions {
|
|
136
|
+
return (CMVideoDimensions){ 1280, 720 };
|
|
137
|
+
}
|
|
138
|
+
- (NSArray<NSValue *> *)supportedMaxPhotoDimensions {
|
|
139
|
+
CMVideoDimensions dims = { 1920, 1080 };
|
|
140
|
+
return @[ [NSValue valueWithBytes:&dims objCType:@encode(CMVideoDimensions)] ];
|
|
141
|
+
}
|
|
142
|
+
- (BOOL)isHighestPhotoQualitySupported { return YES; }
|
|
143
|
+
- (BOOL)isVideoBinned { return NO; }
|
|
144
|
+
- (BOOL)isVideoStabilizationModeSupported:(AVCaptureVideoStabilizationMode)m { return NO; }
|
|
145
|
+
- (CGFloat)videoMaxZoomFactor { return 16.0; }
|
|
146
|
+
- (CGFloat)videoZoomFactorUpscaleThreshold { return 1.0; }
|
|
147
|
+
- (AVCaptureAutoFocusSystem)autoFocusSystem { return AVCaptureAutoFocusSystemNone; }
|
|
148
|
+
- (BOOL)isMultiCamSupported { return NO; }
|
|
149
|
+
- (NSArray *)supportedColorSpaces { return @[]; }
|
|
150
|
+
- (NSArray *)supportedDepthDataFormats { return @[]; }
|
|
151
|
+
- (BOOL)isPortraitEffectSupported { return NO; }
|
|
152
|
+
- (float)minISO { return 25.0f; }
|
|
153
|
+
- (float)maxISO { return 6400.0f; }
|
|
154
|
+
- (CMTime)minExposureDuration { return CMTimeMake(1, 8000); }
|
|
155
|
+
- (CMTime)maxExposureDuration { return CMTimeMake(1, 30); }
|
|
156
|
+
- (id)figCaptureSourceVideoFormat { return nil; }
|
|
157
|
+
- (void)dealloc { if (_fd) CFRelease(_fd); }
|
|
158
|
+
@end
|
|
159
|
+
|
|
160
|
+
AVCaptureDeviceFormat *SimCamSharedFakeFormat(void) {
|
|
161
|
+
static AVCaptureDeviceFormat *f = nil;
|
|
162
|
+
static dispatch_once_t once;
|
|
163
|
+
dispatch_once(&once, ^{
|
|
164
|
+
f = (AVCaptureDeviceFormat *)class_createInstance([SimCamFakeFormat class], 0);
|
|
165
|
+
});
|
|
166
|
+
return f;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
#pragma mark - SimCamFakeDevice
|
|
170
|
+
|
|
171
|
+
static char kFakePositionKey;
|
|
172
|
+
|
|
173
|
+
@implementation SimCamFakeDevice
|
|
174
|
+
- (AVCaptureDevicePosition)position {
|
|
175
|
+
NSNumber *n = objc_getAssociatedObject(self, &kFakePositionKey);
|
|
176
|
+
return n ? (AVCaptureDevicePosition)n.intValue : AVCaptureDevicePositionFront;
|
|
177
|
+
}
|
|
178
|
+
- (NSString *)uniqueID {
|
|
179
|
+
return self.position == AVCaptureDevicePositionBack
|
|
180
|
+
? @"sim-cam-fake-back-0" : @"sim-cam-fake-front-0";
|
|
181
|
+
}
|
|
182
|
+
- (NSString *)modelID { return @"SimCamFakeCamera"; }
|
|
183
|
+
- (NSString *)localizedName {
|
|
184
|
+
return self.position == AVCaptureDevicePositionBack
|
|
185
|
+
? @"Simulated Camera Back (serve-sim)"
|
|
186
|
+
: @"Simulated Camera Front (serve-sim)";
|
|
187
|
+
}
|
|
188
|
+
- (NSString *)manufacturer { return @"serve-sim"; }
|
|
189
|
+
- (BOOL)hasMediaType:(AVMediaType)mediaType { return [mediaType isEqualToString:AVMediaTypeVideo]; }
|
|
190
|
+
- (BOOL)supportsAVCaptureSessionPreset:(AVCaptureSessionPreset)preset { return YES; }
|
|
191
|
+
- (AVCaptureDeviceType)deviceType { return AVCaptureDeviceTypeBuiltInWideAngleCamera; }
|
|
192
|
+
- (NSArray<AVCaptureDeviceFormat *> *)formats {
|
|
193
|
+
AVCaptureDeviceFormat *f = SimCamSharedFakeFormat();
|
|
194
|
+
return f ? @[f] : @[];
|
|
195
|
+
}
|
|
196
|
+
- (BOOL)isConnected { return YES; }
|
|
197
|
+
- (BOOL)isSuspended { return NO; }
|
|
198
|
+
- (BOOL)lockForConfiguration:(NSError **)e { return YES; }
|
|
199
|
+
- (void)unlockForConfiguration { }
|
|
200
|
+
- (AVCaptureDeviceFormat *)activeFormat { return SimCamSharedFakeFormat(); }
|
|
201
|
+
- (CMTime)activeVideoMinFrameDuration { return CMTimeMake(1, 30); }
|
|
202
|
+
- (CMTime)activeVideoMaxFrameDuration { return CMTimeMake(1, 30); }
|
|
203
|
+
- (CGFloat)videoZoomFactor { return 1.0; }
|
|
204
|
+
- (void)setVideoZoomFactor:(CGFloat)v { (void)v; }
|
|
205
|
+
- (void)rampToVideoZoomFactor:(CGFloat)f withRate:(float)r { (void)f; (void)r; }
|
|
206
|
+
- (void)cancelVideoZoomRamp { }
|
|
207
|
+
- (BOOL)isRampingVideoZoom { return NO; }
|
|
208
|
+
- (CGFloat)minAvailableVideoZoomFactor { return 1.0; }
|
|
209
|
+
- (CGFloat)maxAvailableVideoZoomFactor { return 16.0; }
|
|
210
|
+
- (CGFloat)dualCameraSwitchOverVideoZoomFactor { return 2.0; }
|
|
211
|
+
- (NSArray<NSNumber *> *)virtualDeviceSwitchOverVideoZoomFactors { return @[]; }
|
|
212
|
+
- (NSArray *)constituentDevices { return @[]; }
|
|
213
|
+
- (BOOL)isVirtualDevice { return NO; }
|
|
214
|
+
- (BOOL)hasTorch { return NO; }
|
|
215
|
+
- (BOOL)hasFlash { return NO; }
|
|
216
|
+
- (BOOL)isTorchAvailable { return NO; }
|
|
217
|
+
- (BOOL)isTorchActive { return NO; }
|
|
218
|
+
- (AVCaptureTorchMode)torchMode { return AVCaptureTorchModeOff; }
|
|
219
|
+
- (void)setTorchMode:(AVCaptureTorchMode)m { (void)m; }
|
|
220
|
+
- (BOOL)isTorchModeSupported:(AVCaptureTorchMode)m { (void)m; return NO; }
|
|
221
|
+
- (BOOL)setTorchModeOnWithLevel:(float)l error:(NSError **)e { (void)l; if (e) *e = nil; return YES; }
|
|
222
|
+
- (AVCaptureFocusMode)focusMode { return AVCaptureFocusModeContinuousAutoFocus; }
|
|
223
|
+
- (void)setFocusMode:(AVCaptureFocusMode)m { (void)m; }
|
|
224
|
+
- (BOOL)isFocusModeSupported:(AVCaptureFocusMode)m { (void)m; return YES; }
|
|
225
|
+
- (CGPoint)focusPointOfInterest { return CGPointMake(0.5, 0.5); }
|
|
226
|
+
- (void)setFocusPointOfInterest:(CGPoint)p { (void)p; }
|
|
227
|
+
- (BOOL)isFocusPointOfInterestSupported { return YES; }
|
|
228
|
+
- (BOOL)isAdjustingFocus { return NO; }
|
|
229
|
+
- (BOOL)isSmoothAutoFocusEnabled { return NO; }
|
|
230
|
+
- (void)setSmoothAutoFocusEnabled:(BOOL)b { (void)b; }
|
|
231
|
+
- (BOOL)isSmoothAutoFocusSupported { return NO; }
|
|
232
|
+
- (AVCaptureAutoFocusRangeRestriction)autoFocusRangeRestriction { return AVCaptureAutoFocusRangeRestrictionNone; }
|
|
233
|
+
- (void)setAutoFocusRangeRestriction:(AVCaptureAutoFocusRangeRestriction)r { (void)r; }
|
|
234
|
+
- (BOOL)isAutoFocusRangeRestrictionSupported { return NO; }
|
|
235
|
+
- (AVCaptureExposureMode)exposureMode { return AVCaptureExposureModeContinuousAutoExposure; }
|
|
236
|
+
- (void)setExposureMode:(AVCaptureExposureMode)m { (void)m; }
|
|
237
|
+
- (BOOL)isExposureModeSupported:(AVCaptureExposureMode)m { (void)m; return YES; }
|
|
238
|
+
- (CGPoint)exposurePointOfInterest { return CGPointMake(0.5, 0.5); }
|
|
239
|
+
- (void)setExposurePointOfInterest:(CGPoint)p { (void)p; }
|
|
240
|
+
- (BOOL)isExposurePointOfInterestSupported { return YES; }
|
|
241
|
+
- (BOOL)isAdjustingExposure { return NO; }
|
|
242
|
+
- (float)exposureTargetBias { return 0.0f; }
|
|
243
|
+
- (float)minExposureTargetBias { return -8.0f; }
|
|
244
|
+
- (float)maxExposureTargetBias { return 8.0f; }
|
|
245
|
+
- (CMTime)exposureDuration { return CMTimeMake(1, 30); }
|
|
246
|
+
- (float)ISO { return 100.0f; }
|
|
247
|
+
- (float)minISO { return 25.0f; }
|
|
248
|
+
- (float)maxISO { return 6400.0f; }
|
|
249
|
+
- (CMTime)activeMinExposureDuration { return CMTimeMake(1, 8000); }
|
|
250
|
+
- (CMTime)activeMaxExposureDuration { return CMTimeMake(1, 30); }
|
|
251
|
+
- (AVCaptureWhiteBalanceMode)whiteBalanceMode { return AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance; }
|
|
252
|
+
- (void)setWhiteBalanceMode:(AVCaptureWhiteBalanceMode)m { (void)m; }
|
|
253
|
+
- (BOOL)isWhiteBalanceModeSupported:(AVCaptureWhiteBalanceMode)m { (void)m; return YES; }
|
|
254
|
+
- (BOOL)isAdjustingWhiteBalance { return NO; }
|
|
255
|
+
- (BOOL)isFlashAvailable { return NO; }
|
|
256
|
+
- (BOOL)videoHDREnabled { return NO; }
|
|
257
|
+
- (void)setVideoHDREnabled:(BOOL)b { (void)b; }
|
|
258
|
+
- (BOOL)automaticallyAdjustsVideoHDREnabled { return NO; }
|
|
259
|
+
- (void)setAutomaticallyAdjustsVideoHDREnabled:(BOOL)b { (void)b; }
|
|
260
|
+
- (BOOL)isLowLightBoostSupported { return NO; }
|
|
261
|
+
- (BOOL)isLowLightBoostEnabled { return NO; }
|
|
262
|
+
- (BOOL)automaticallyEnablesLowLightBoostWhenAvailable { return NO; }
|
|
263
|
+
- (void)setAutomaticallyEnablesLowLightBoostWhenAvailable:(BOOL)b { (void)b; }
|
|
264
|
+
- (NSArray *)linkedDevices { return @[]; }
|
|
265
|
+
@end
|
|
266
|
+
|
|
267
|
+
AVCaptureDevice *SimCamFakeDeviceForPosition(AVCaptureDevicePosition p) {
|
|
268
|
+
static AVCaptureDevice *front = nil;
|
|
269
|
+
static AVCaptureDevice *back = nil;
|
|
270
|
+
static dispatch_once_t once;
|
|
271
|
+
dispatch_once(&once, ^{
|
|
272
|
+
front = (AVCaptureDevice *)class_createInstance([SimCamFakeDevice class], 0);
|
|
273
|
+
objc_setAssociatedObject(front, &kFakePositionKey,
|
|
274
|
+
@(AVCaptureDevicePositionFront), OBJC_ASSOCIATION_RETAIN);
|
|
275
|
+
back = (AVCaptureDevice *)class_createInstance([SimCamFakeDevice class], 0);
|
|
276
|
+
objc_setAssociatedObject(back, &kFakePositionKey,
|
|
277
|
+
@(AVCaptureDevicePositionBack), OBJC_ASSOCIATION_RETAIN);
|
|
278
|
+
});
|
|
279
|
+
return p == AVCaptureDevicePositionBack ? back : front;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
#pragma mark - SimCamFakeConnection
|
|
283
|
+
|
|
284
|
+
@interface AVCaptureConnection (SimCamPrivate)
|
|
285
|
+
- (BOOL)sourcesFromExternalCamera;
|
|
286
|
+
- (AVCaptureVideoOrientation)_videoOrientation;
|
|
287
|
+
@end
|
|
288
|
+
|
|
289
|
+
@implementation SimCamFakeConnection {
|
|
290
|
+
__weak AVCaptureOutput *_outputRef;
|
|
291
|
+
AVCaptureDevicePosition _position;
|
|
292
|
+
AVCaptureVideoOrientation _orientation;
|
|
293
|
+
BOOL _videoMirrored;
|
|
294
|
+
BOOL _automaticallyAdjustsVideoMirroring;
|
|
295
|
+
BOOL _enabled;
|
|
296
|
+
}
|
|
297
|
+
+ (instancetype)allocWithZone:(NSZone *)zone {
|
|
298
|
+
return class_createInstance([SimCamFakeConnection class], 0);
|
|
299
|
+
}
|
|
300
|
+
+ (instancetype)connectionForOutput:(AVCaptureOutput *)output
|
|
301
|
+
position:(AVCaptureDevicePosition)pos {
|
|
302
|
+
SimCamFakeConnection *c = [self alloc];
|
|
303
|
+
if (c) {
|
|
304
|
+
c->_outputRef = output;
|
|
305
|
+
c->_position = pos;
|
|
306
|
+
c->_orientation = AVCaptureVideoOrientationPortrait;
|
|
307
|
+
c->_automaticallyAdjustsVideoMirroring = YES;
|
|
308
|
+
c->_videoMirrored = SimCamShouldMirror(pos);
|
|
309
|
+
c->_enabled = YES;
|
|
310
|
+
}
|
|
311
|
+
return c;
|
|
312
|
+
}
|
|
313
|
+
- (AVCaptureOutput *)output { return _outputRef; }
|
|
314
|
+
- (NSArray *)inputPorts { return @[]; }
|
|
315
|
+
- (AVCaptureInput *)input { return nil; }
|
|
316
|
+
- (AVCaptureVideoPreviewLayer *)videoPreviewLayer { return nil; }
|
|
317
|
+
- (BOOL)isEnabled { return _enabled; }
|
|
318
|
+
- (void)setEnabled:(BOOL)e { _enabled = e; }
|
|
319
|
+
- (BOOL)isActive { return YES; }
|
|
320
|
+
- (NSArray *)audioChannels { return @[]; }
|
|
321
|
+
- (AVMediaType)mediaType { return AVMediaTypeVideo; }
|
|
322
|
+
|
|
323
|
+
- (AVCaptureDevice *)sourceDevice { return SimCamFakeDeviceForPosition(_position); }
|
|
324
|
+
- (AVCaptureDeviceType)sourceDeviceType { return AVCaptureDeviceTypeBuiltInWideAngleCamera; }
|
|
325
|
+
- (AVCaptureDevicePosition)sourceDevicePosition { return _position; }
|
|
326
|
+
- (AVCaptureSession *)originatingSession { return nil; }
|
|
327
|
+
|
|
328
|
+
- (AVCaptureDeviceInput *)deviceInput {
|
|
329
|
+
return SimCamFakeInputForPosition(_position);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
- (BOOL)isVideoOrientationSupported { return YES; }
|
|
333
|
+
- (AVCaptureVideoOrientation)videoOrientation { return _orientation; }
|
|
334
|
+
- (void)setVideoOrientation:(AVCaptureVideoOrientation)o { _orientation = o; }
|
|
335
|
+
|
|
336
|
+
- (BOOL)isVideoRotationAngleSupported:(CGFloat)angle { (void)angle; return YES; }
|
|
337
|
+
- (CGFloat)videoRotationAngle {
|
|
338
|
+
switch (_orientation) {
|
|
339
|
+
case AVCaptureVideoOrientationPortrait: return 90.0;
|
|
340
|
+
case AVCaptureVideoOrientationPortraitUpsideDown: return 270.0;
|
|
341
|
+
case AVCaptureVideoOrientationLandscapeRight: return 0.0;
|
|
342
|
+
case AVCaptureVideoOrientationLandscapeLeft: return 180.0;
|
|
343
|
+
default: return 90.0;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
- (void)setVideoRotationAngle:(CGFloat)angle {
|
|
347
|
+
long a = ((long)angle % 360 + 360) % 360;
|
|
348
|
+
if (a == 0) _orientation = AVCaptureVideoOrientationLandscapeRight;
|
|
349
|
+
else if (a == 90) _orientation = AVCaptureVideoOrientationPortrait;
|
|
350
|
+
else if (a == 180) _orientation = AVCaptureVideoOrientationLandscapeLeft;
|
|
351
|
+
else if (a == 270) _orientation = AVCaptureVideoOrientationPortraitUpsideDown;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
- (BOOL)isVideoMirroringSupported { return YES; }
|
|
355
|
+
- (BOOL)isVideoMirrored {
|
|
356
|
+
if (_automaticallyAdjustsVideoMirroring) return SimCamShouldMirror(_position);
|
|
357
|
+
return _videoMirrored;
|
|
358
|
+
}
|
|
359
|
+
- (void)setVideoMirrored:(BOOL)m {
|
|
360
|
+
_videoMirrored = m;
|
|
361
|
+
_automaticallyAdjustsVideoMirroring = NO;
|
|
362
|
+
}
|
|
363
|
+
- (BOOL)automaticallyAdjustsVideoMirroring { return _automaticallyAdjustsVideoMirroring; }
|
|
364
|
+
- (void)setAutomaticallyAdjustsVideoMirroring:(BOOL)b {
|
|
365
|
+
_automaticallyAdjustsVideoMirroring = b;
|
|
366
|
+
if (b) _videoMirrored = SimCamShouldMirror(_position);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
- (BOOL)isVideoMinFrameDurationSupported { return NO; }
|
|
370
|
+
- (BOOL)isVideoMaxFrameDurationSupported { return NO; }
|
|
371
|
+
- (CMTime)videoMinFrameDuration { return kCMTimeInvalid; }
|
|
372
|
+
- (CMTime)videoMaxFrameDuration { return kCMTimeInvalid; }
|
|
373
|
+
- (void)setVideoMinFrameDuration:(CMTime)d { (void)d; }
|
|
374
|
+
- (void)setVideoMaxFrameDuration:(CMTime)d { (void)d; }
|
|
375
|
+
|
|
376
|
+
- (BOOL)isVideoStabilizationSupported { return NO; }
|
|
377
|
+
- (AVCaptureVideoStabilizationMode)preferredVideoStabilizationMode { return AVCaptureVideoStabilizationModeOff; }
|
|
378
|
+
- (void)setPreferredVideoStabilizationMode:(AVCaptureVideoStabilizationMode)m { (void)m; }
|
|
379
|
+
- (AVCaptureVideoStabilizationMode)activeVideoStabilizationMode { return AVCaptureVideoStabilizationModeOff; }
|
|
380
|
+
- (BOOL)isVideoStabilizationEnabled { return NO; }
|
|
381
|
+
- (BOOL)enablesVideoStabilizationWhenAvailable { return NO; }
|
|
382
|
+
- (void)setEnablesVideoStabilizationWhenAvailable:(BOOL)b { (void)b; }
|
|
383
|
+
|
|
384
|
+
- (BOOL)isCameraIntrinsicMatrixDeliverySupported { return NO; }
|
|
385
|
+
- (BOOL)isCameraIntrinsicMatrixDeliveryEnabled { return NO; }
|
|
386
|
+
- (void)setCameraIntrinsicMatrixDeliveryEnabled:(BOOL)b { (void)b; }
|
|
387
|
+
|
|
388
|
+
- (BOOL)isVideoFieldModeSupported { return NO; }
|
|
389
|
+
- (CGFloat)videoMaxScaleAndCropFactor { return 1.0; }
|
|
390
|
+
- (CGFloat)videoScaleAndCropFactor { return 1.0; }
|
|
391
|
+
- (void)setVideoScaleAndCropFactor:(CGFloat)v { (void)v; }
|
|
392
|
+
|
|
393
|
+
- (AVCaptureVideoOrientation)_videoOrientation { return _orientation; }
|
|
394
|
+
- (BOOL)sourcesFromExternalCamera { return NO; }
|
|
395
|
+
@end
|
|
396
|
+
|
|
397
|
+
static char kSimCamOutputConnectionKey;
|
|
398
|
+
|
|
399
|
+
AVCaptureConnection *SimCamFakeConnectionForOutput(AVCaptureOutput *out) {
|
|
400
|
+
if (!out) return nil;
|
|
401
|
+
AVCaptureConnection *conn = objc_getAssociatedObject(out, &kSimCamOutputConnectionKey);
|
|
402
|
+
if (!conn) {
|
|
403
|
+
conn = (AVCaptureConnection *)[SimCamFakeConnection
|
|
404
|
+
connectionForOutput:out
|
|
405
|
+
position:SimCamPositionOf(out)];
|
|
406
|
+
if (conn) {
|
|
407
|
+
objc_setAssociatedObject(out, &kSimCamOutputConnectionKey, conn,
|
|
408
|
+
OBJC_ASSOCIATION_RETAIN);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
return conn;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
#pragma mark - SimCamFakeInput marking
|
|
415
|
+
|
|
416
|
+
static char kSimCamFakeInputKey;
|
|
417
|
+
static char kSimCamFakeInputDeviceKey;
|
|
418
|
+
|
|
419
|
+
void SimCamMarkFakeInput(id input, AVCaptureDevice *fakeDevice) {
|
|
420
|
+
if (!input) return;
|
|
421
|
+
objc_setAssociatedObject(input, &kSimCamFakeInputKey, @YES, OBJC_ASSOCIATION_RETAIN);
|
|
422
|
+
if (fakeDevice) {
|
|
423
|
+
objc_setAssociatedObject(input, &kSimCamFakeInputDeviceKey, fakeDevice, OBJC_ASSOCIATION_RETAIN);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
BOOL SimCamIsFakeInput(id input) {
|
|
427
|
+
if (!input) return NO;
|
|
428
|
+
return [objc_getAssociatedObject(input, &kSimCamFakeInputKey) boolValue];
|
|
429
|
+
}
|
|
430
|
+
AVCaptureDevice *SimCamFakeInputDevice(id input) {
|
|
431
|
+
if (!input) return nil;
|
|
432
|
+
return objc_getAssociatedObject(input, &kSimCamFakeInputDeviceKey);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
AVCaptureDeviceInput *SimCamFakeInputForPosition(AVCaptureDevicePosition p) {
|
|
436
|
+
static AVCaptureDeviceInput *front = nil;
|
|
437
|
+
static AVCaptureDeviceInput *back = nil;
|
|
438
|
+
static dispatch_once_t once;
|
|
439
|
+
dispatch_once(&once, ^{
|
|
440
|
+
front = (AVCaptureDeviceInput *)class_createInstance([AVCaptureDeviceInput class], 0);
|
|
441
|
+
SimCamMarkFakeInput(front, SimCamFakeDeviceForPosition(AVCaptureDevicePositionFront));
|
|
442
|
+
SimCamSetPosition(front, AVCaptureDevicePositionFront);
|
|
443
|
+
|
|
444
|
+
back = (AVCaptureDeviceInput *)class_createInstance([AVCaptureDeviceInput class], 0);
|
|
445
|
+
SimCamMarkFakeInput(back, SimCamFakeDeviceForPosition(AVCaptureDevicePositionBack));
|
|
446
|
+
SimCamSetPosition(back, AVCaptureDevicePositionBack);
|
|
447
|
+
});
|
|
448
|
+
return p == AVCaptureDevicePositionBack ? back : front;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
#pragma mark - SimCamFakeResolvedPhotoSettings
|
|
452
|
+
|
|
453
|
+
@interface SimCamFakeResolvedPhotoSettings (SimCamFactory)
|
|
454
|
+
+ (instancetype)settingsWithDimensions:(CMVideoDimensions)dims;
|
|
455
|
+
@end
|
|
456
|
+
|
|
457
|
+
@implementation SimCamFakeResolvedPhotoSettings {
|
|
458
|
+
CMVideoDimensions _photoDims;
|
|
459
|
+
}
|
|
460
|
+
+ (instancetype)allocWithZone:(NSZone *)zone {
|
|
461
|
+
return class_createInstance([SimCamFakeResolvedPhotoSettings class], 0);
|
|
462
|
+
}
|
|
463
|
+
+ (instancetype)settingsWithDimensions:(CMVideoDimensions)dims {
|
|
464
|
+
SimCamFakeResolvedPhotoSettings *s = [self alloc];
|
|
465
|
+
if (s) s->_photoDims = dims;
|
|
466
|
+
return s;
|
|
467
|
+
}
|
|
468
|
+
- (CMVideoDimensions)photoDimensions { return _photoDims; }
|
|
469
|
+
- (CMVideoDimensions)rawPhotoDimensions { return (CMVideoDimensions){0, 0}; }
|
|
470
|
+
- (CMVideoDimensions)previewDimensions { return _photoDims; }
|
|
471
|
+
- (CMVideoDimensions)embeddedThumbnailDimensions { return (CMVideoDimensions){0, 0}; }
|
|
472
|
+
- (CMVideoDimensions)portraitEffectsMatteDimensions { return (CMVideoDimensions){0, 0}; }
|
|
473
|
+
- (CMVideoDimensions)rawEmbeddedThumbnailDimensions { return (CMVideoDimensions){0, 0}; }
|
|
474
|
+
- (int64_t)uniqueID { return 1; }
|
|
475
|
+
- (BOOL)isFlashEnabled { return NO; }
|
|
476
|
+
- (BOOL)isRedEyeReductionEnabled { return NO; }
|
|
477
|
+
- (BOOL)isContentAwareDistortionCorrectionEnabled { return NO; }
|
|
478
|
+
- (BOOL)isStillImageStabilizationEnabled { return NO; }
|
|
479
|
+
- (BOOL)isVirtualDeviceFusionEnabled { return NO; }
|
|
480
|
+
- (BOOL)isAutoVirtualDeviceFusionEnabled { return NO; }
|
|
481
|
+
- (BOOL)isDualCameraFusionEnabled { return NO; }
|
|
482
|
+
- (BOOL)isAutoDualCameraFusionEnabled { return NO; }
|
|
483
|
+
- (BOOL)isDepthDataDeliveryEnabled { return NO; }
|
|
484
|
+
- (BOOL)isPortraitEffectsMatteDeliveryEnabled { return NO; }
|
|
485
|
+
- (BOOL)isCameraCalibrationDataDeliveryEnabled { return NO; }
|
|
486
|
+
- (NSArray *)enabledSemanticSegmentationMatteTypes { return @[]; }
|
|
487
|
+
- (CMTimeRange)photoProcessingTimeRange {
|
|
488
|
+
return CMTimeRangeMake(kCMTimeZero, kCMTimeZero);
|
|
489
|
+
}
|
|
490
|
+
- (CMTime)expectedPhotoCaptureDuration { return kCMTimeInvalid; }
|
|
491
|
+
- (NSURL *)deferredPhotoProxyDataFileURL { return nil; }
|
|
492
|
+
- (NSDictionary *)dimensionsRepresentation { return @{}; }
|
|
493
|
+
@end
|
|
494
|
+
|
|
495
|
+
#pragma mark - SimCamFakePhoto
|
|
496
|
+
|
|
497
|
+
@implementation SimCamFakePhoto {
|
|
498
|
+
NSData *_jpegData;
|
|
499
|
+
CGImageRef _cgImage;
|
|
500
|
+
NSDictionary *_metadata;
|
|
501
|
+
AVCaptureResolvedPhotoSettings *_resolvedSettings;
|
|
502
|
+
}
|
|
503
|
+
+ (instancetype)allocWithZone:(NSZone *)zone {
|
|
504
|
+
return class_createInstance([SimCamFakePhoto class], 0);
|
|
505
|
+
}
|
|
506
|
+
+ (instancetype)photoFromImage:(CGImageRef)cgImage
|
|
507
|
+
jpegQuality:(CGFloat)q
|
|
508
|
+
mirrored:(BOOL)mirrored {
|
|
509
|
+
if (!cgImage) return nil;
|
|
510
|
+
SimCamFakePhoto *p = [SimCamFakePhoto alloc];
|
|
511
|
+
if (p) {
|
|
512
|
+
p->_cgImage = CGImageRetain(cgImage);
|
|
513
|
+
UIImage *ui = [UIImage imageWithCGImage:cgImage];
|
|
514
|
+
p->_jpegData = UIImageJPEGRepresentation(ui, q);
|
|
515
|
+
UInt32 exifOrient = mirrored ? 2u : 1u;
|
|
516
|
+
p->_metadata = @{
|
|
517
|
+
(NSString *)kCGImagePropertyOrientation: @(exifOrient),
|
|
518
|
+
};
|
|
519
|
+
CMVideoDimensions dims = {
|
|
520
|
+
(int32_t)CGImageGetWidth(cgImage),
|
|
521
|
+
(int32_t)CGImageGetHeight(cgImage),
|
|
522
|
+
};
|
|
523
|
+
p->_resolvedSettings = (AVCaptureResolvedPhotoSettings *)
|
|
524
|
+
[SimCamFakeResolvedPhotoSettings settingsWithDimensions:dims];
|
|
525
|
+
}
|
|
526
|
+
return p;
|
|
527
|
+
}
|
|
528
|
+
- (NSData *)fileDataRepresentation { return _jpegData; }
|
|
529
|
+
- (NSData *)fileDataRepresentationWithCustomizer:(id)c { return _jpegData; }
|
|
530
|
+
- (NSData *)fileDataRepresentationWithReplacementMetadata:(NSDictionary *)m
|
|
531
|
+
replacementEmbeddedThumbnailPhotoFormat:(NSDictionary *)t
|
|
532
|
+
replacementEmbeddedThumbnailPixelBuffer:(CVPixelBufferRef)pb
|
|
533
|
+
replacementDepthData:(id)d { return _jpegData; }
|
|
534
|
+
- (CGImageRef)CGImageRepresentation { return _cgImage; }
|
|
535
|
+
- (CGImageRef)previewCGImageRepresentation { return _cgImage; }
|
|
536
|
+
- (NSDictionary *)metadata { return _metadata; }
|
|
537
|
+
- (CVPixelBufferRef)pixelBuffer { return NULL; }
|
|
538
|
+
- (CVPixelBufferRef)previewPixelBuffer { return NULL; }
|
|
539
|
+
- (AVDepthData *)depthData { return nil; }
|
|
540
|
+
- (AVCameraCalibrationData *)cameraCalibrationData { return nil; }
|
|
541
|
+
- (NSData *)bracketSettings { return nil; }
|
|
542
|
+
- (AVCaptureBracketedStillImageSettings *)bracketedSettings { return nil; }
|
|
543
|
+
- (NSData *)embeddedThumbnailPhotoFormat { return nil; }
|
|
544
|
+
- (NSInteger)photoCount { return 1; }
|
|
545
|
+
- (NSInteger)sequenceCount { return 1; }
|
|
546
|
+
- (CMTime)timestamp { return CMTimeMake(0, 30); }
|
|
547
|
+
- (BOOL)isRawPhoto { return NO; }
|
|
548
|
+
- (AVCaptureResolvedPhotoSettings *)resolvedSettings { return _resolvedSettings; }
|
|
549
|
+
- (NSString *)sourceDeviceType { return AVCaptureDeviceTypeBuiltInWideAngleCamera; }
|
|
550
|
+
- (NSArray *)availableRawEmbeddedThumbnailPhotoCodecTypes { return @[]; }
|
|
551
|
+
- (NSArray *)availableEmbeddedThumbnailPhotoCodecTypes { return @[]; }
|
|
552
|
+
- (void)dealloc { if (_cgImage) CGImageRelease(_cgImage); }
|
|
553
|
+
@end
|
|
554
|
+
|
|
555
|
+
#pragma mark - CoreMotion fakes
|
|
556
|
+
|
|
557
|
+
@implementation SimCamAttitude
|
|
558
|
+
- (double)pitch { return 0.0; }
|
|
559
|
+
- (double)roll { return 0.0; }
|
|
560
|
+
- (double)yaw { return 0.0; }
|
|
561
|
+
- (CMRotationMatrix)rotationMatrix {
|
|
562
|
+
return (CMRotationMatrix){ 1, 0, 0, 0, 1, 0, 0, 0, 1 };
|
|
563
|
+
}
|
|
564
|
+
- (CMQuaternion)quaternion { return (CMQuaternion){ 0, 0, 0, 1 }; }
|
|
565
|
+
- (void)multiplyByInverseOfAttitude:(CMAttitude *)attitude { (void)attitude; }
|
|
566
|
+
@end
|
|
567
|
+
|
|
568
|
+
@implementation SimCamAccelerometerData
|
|
569
|
+
- (CMAcceleration)acceleration { return (CMAcceleration){ 0.0, -1.0, 0.0 }; }
|
|
570
|
+
- (NSTimeInterval)timestamp { return [NSProcessInfo processInfo].systemUptime; }
|
|
571
|
+
@end
|
|
572
|
+
|
|
573
|
+
@implementation SimCamGyroData
|
|
574
|
+
- (CMRotationRate)rotationRate { return (CMRotationRate){ 0.0, 0.0, 0.0 }; }
|
|
575
|
+
- (NSTimeInterval)timestamp { return [NSProcessInfo processInfo].systemUptime; }
|
|
576
|
+
@end
|
|
577
|
+
|
|
578
|
+
@implementation SimCamMagnetometerData
|
|
579
|
+
- (CMMagneticField)magneticField { return (CMMagneticField){ 0.0, 0.0, 0.0 }; }
|
|
580
|
+
- (NSTimeInterval)timestamp { return [NSProcessInfo processInfo].systemUptime; }
|
|
581
|
+
@end
|
|
582
|
+
|
|
583
|
+
@implementation SimCamDeviceMotion
|
|
584
|
+
- (CMAttitude *)attitude { return SimCamSharedAttitude(); }
|
|
585
|
+
- (CMAcceleration)gravity { return (CMAcceleration){ 0.0, -1.0, 0.0 }; }
|
|
586
|
+
- (CMAcceleration)userAcceleration { return (CMAcceleration){ 0.0, 0.0, 0.0 }; }
|
|
587
|
+
- (CMRotationRate)rotationRate { return (CMRotationRate){ 0.0, 0.0, 0.0 }; }
|
|
588
|
+
- (CMCalibratedMagneticField)magneticField {
|
|
589
|
+
return (CMCalibratedMagneticField){ { 0.0, 0.0, 0.0 },
|
|
590
|
+
CMMagneticFieldCalibrationAccuracyUncalibrated };
|
|
591
|
+
}
|
|
592
|
+
- (double)heading { return 0.0; }
|
|
593
|
+
- (NSTimeInterval)timestamp { return [NSProcessInfo processInfo].systemUptime; }
|
|
594
|
+
@end
|
|
595
|
+
|
|
596
|
+
CMAttitude *SimCamSharedAttitude(void) {
|
|
597
|
+
static CMAttitude *att = nil;
|
|
598
|
+
static dispatch_once_t once;
|
|
599
|
+
dispatch_once(&once, ^{
|
|
600
|
+
att = (CMAttitude *)class_createInstance([SimCamAttitude class], 0);
|
|
601
|
+
});
|
|
602
|
+
return att;
|
|
603
|
+
}
|
|
604
|
+
CMAccelerometerData *SimCamSharedAccelerometerData(void) {
|
|
605
|
+
static CMAccelerometerData *d = nil;
|
|
606
|
+
static dispatch_once_t once;
|
|
607
|
+
dispatch_once(&once, ^{
|
|
608
|
+
d = (CMAccelerometerData *)class_createInstance([SimCamAccelerometerData class], 0);
|
|
609
|
+
});
|
|
610
|
+
return d;
|
|
611
|
+
}
|
|
612
|
+
CMGyroData *SimCamSharedGyroData(void) {
|
|
613
|
+
static CMGyroData *d = nil;
|
|
614
|
+
static dispatch_once_t once;
|
|
615
|
+
dispatch_once(&once, ^{
|
|
616
|
+
d = (CMGyroData *)class_createInstance([SimCamGyroData class], 0);
|
|
617
|
+
});
|
|
618
|
+
return d;
|
|
619
|
+
}
|
|
620
|
+
CMMagnetometerData *SimCamSharedMagnetometerData(void) {
|
|
621
|
+
static CMMagnetometerData *d = nil;
|
|
622
|
+
static dispatch_once_t once;
|
|
623
|
+
dispatch_once(&once, ^{
|
|
624
|
+
d = (CMMagnetometerData *)class_createInstance([SimCamMagnetometerData class], 0);
|
|
625
|
+
});
|
|
626
|
+
return d;
|
|
627
|
+
}
|
|
628
|
+
CMDeviceMotion *SimCamSharedDeviceMotion(void) {
|
|
629
|
+
static CMDeviceMotion *d = nil;
|
|
630
|
+
static dispatch_once_t once;
|
|
631
|
+
dispatch_once(&once, ^{
|
|
632
|
+
d = (CMDeviceMotion *)class_createInstance([SimCamDeviceMotion class], 0);
|
|
633
|
+
});
|
|
634
|
+
return d;
|
|
635
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#import <AVFoundation/AVFoundation.h>
|
|
4
|
+
|
|
5
|
+
@interface SimCamRegistry : NSObject
|
|
6
|
+
+ (instancetype)shared;
|
|
7
|
+
|
|
8
|
+
- (void)addOutput:(AVCaptureVideoDataOutput *)out
|
|
9
|
+
delegate:(id<AVCaptureVideoDataOutputSampleBufferDelegate>)delegate
|
|
10
|
+
queue:(dispatch_queue_t)queue;
|
|
11
|
+
- (void)removeOutput:(AVCaptureVideoDataOutput *)out;
|
|
12
|
+
- (void)addPreviewLayer:(AVCaptureVideoPreviewLayer *)layer;
|
|
13
|
+
- (void)reapplyMirrorToLayers;
|
|
14
|
+
|
|
15
|
+
- (CVPixelBufferRef)currentPixelBuffer CF_RETURNS_RETAINED;
|
|
16
|
+
|
|
17
|
+
- (NSData *)currentSnapshotJPEGAtQuality:(CGFloat)q;
|
|
18
|
+
|
|
19
|
+
- (void)startPumpingIfNeeded;
|
|
20
|
+
- (void)stopPumping;
|
|
21
|
+
@end
|
|
22
|
+
|
|
23
|
+
void SimCamFrameSourceLoadImage(void);
|
|
24
|
+
void SimCamFrameSourceOpenShmIfRequested(void);
|
|
25
|
+
|
|
26
|
+
BOOL SimCamFrameSourceIsShmAttached(void);
|