Jonny Banana
6 years ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 2721 additions and 0 deletions
-
233Resource/SCCaptureResource.h
-
66Resource/SCCaptureResource.m
-
377Tweaks/SCCameraTweaks.h
-
396Tweaks/SCCameraTweaks.m
-
47UI/AVCameraViewEnums.h
-
32UI/Lenses/LensButtonZ/SCFeatureLensButtonZ.h
-
33UI/Lenses/LensSideButton/SCFeatureLensSideButton.h
-
24UI/SCLongPressGestureRecognizer.h
-
88UI/SCLongPressGestureRecognizer.m
-
31VolumeButton/SCCameraVolumeButtonHandler.h
-
190VolumeButton/SCCameraVolumeButtonHandler.m
-
109Worker/SCCaptureWorker.h
-
1095Worker/SCCaptureWorker.m
@ -0,0 +1,233 @@ |
|||
// |
|||
// SCCaptureResource.h |
|||
// Snapchat |
|||
// |
|||
// Created by Lin Jia on 10/19/17. |
|||
// |
|||
// |
|||
|
|||
#import "SCManagedCapturerLensAPI.h" |
|||
#import "SCManagedCapturerListenerAnnouncer.h" |
|||
#import "SCSnapCreationTriggers.h" |
|||
|
|||
#import <SCCameraFoundation/SCManagedVideoDataSource.h> |
|||
|
|||
#import <FBKVOController/FBKVOController.h> |
|||
|
|||
#import <Foundation/Foundation.h> |
|||
|
|||
/* |
|||
In general, the function of SCCapturer is to use some resources (such as SCManagedCapturerListenerAnnouncer), to do |
|||
something (such as announce an event). |
|||
|
|||
SCCaptureResource abstract away the "resources" part of SCCapturer. It has no APIs itself, it is used to be the |
|||
resource which gets passed arround for capturer V2 state machine. |
|||
*/ |
|||
@class SCManagedDeviceCapacityAnalyzer; |
|||
|
|||
@class SCManagedCapturePreviewLayerController; |
|||
|
|||
@class ARSession; |
|||
|
|||
@class SCManagedVideoScanner; |
|||
|
|||
@class LSAGLView; |
|||
|
|||
@protocol SCManagedCapturerLSAComponentTrackerAPI; |
|||
|
|||
@class SCManagedStillImageCapturer; |
|||
|
|||
@class SCManagedVideoCapturer; |
|||
|
|||
@class SCQueuePerformer; |
|||
|
|||
@class SCManagedVideoFrameSampler; |
|||
|
|||
@class SCManagedDroppedFramesReporter; |
|||
|
|||
@class SCManagedVideoStreamReporter; |
|||
|
|||
@protocol SCManagedCapturerGLViewManagerAPI; |
|||
|
|||
@class SCCapturerToken; |
|||
|
|||
@class SCSingleFrameStreamCapturer; |
|||
|
|||
@class SCManagedFrontFlashController; |
|||
|
|||
@class SCManagedVideoCapturerHandler; |
|||
|
|||
@class SCManagedStillImageCapturerHandler; |
|||
|
|||
@class SCManagedDeviceCapacityAnalyzerHandler; |
|||
|
|||
@class SCManagedCaptureDeviceDefaultZoomHandler; |
|||
|
|||
@class SCManagedCaptureDeviceHandler; |
|||
|
|||
@class SCBlackCameraNoOutputDetector; |
|||
|
|||
@class SCCaptureSessionFixer; |
|||
|
|||
@protocol SCCaptureFaceDetector; |
|||
|
|||
@protocol SCManagedCapturerLensAPI; |
|||
|
|||
@protocol SCManagedCapturerARImageCaptureProvider; |
|||
|
|||
@class SCManagedCapturerARSessionHandler; |
|||
|
|||
@class SCManagedCaptureDeviceSubjectAreaHandler; |
|||
|
|||
@class SCManagedCaptureSession; |
|||
|
|||
@class SCBlackCameraDetector; |
|||
|
|||
@protocol SCLensProcessingCore; |
|||
|
|||
@protocol SCManagedCapturerLensAPI; |
|||
|
|||
@protocol SCManagedCapturePreviewLayerControllerDelegate; |
|||
|
|||
typedef enum : NSUInteger { |
|||
SCManagedCapturerStatusUnknown = 0, |
|||
SCManagedCapturerStatusReady, |
|||
SCManagedCapturerStatusRunning, |
|||
} SCManagedCapturerStatus; |
|||
|
|||
@protocol SCDeviceMotionProvider |
|||
|
|||
@property (nonatomic, readonly) BOOL isUnderDeviceMotion; |
|||
|
|||
@end |
|||
|
|||
@protocol SCFileInputDecider |
|||
|
|||
@property (nonatomic, readonly) BOOL shouldProcessFileInput; |
|||
@property (nonatomic, readonly) NSURL *fileURL; |
|||
|
|||
@end |
|||
|
|||
@interface SCCaptureResource : NSObject |
|||
|
|||
@property (nonatomic, readwrite, assign) SCManagedCapturerStatus status; |
|||
|
|||
@property (nonatomic, readwrite, strong) SCManagedCapturerState *state; |
|||
|
|||
@property (nonatomic, readwrite, strong) SCManagedCaptureDevice *device; |
|||
|
|||
@property (nonatomic, readwrite, strong) id<SCManagedCapturerLensAPI> lensProcessingCore; |
|||
|
|||
@property (nonatomic, readwrite, strong) id<SCManagedCapturerLensAPIProvider> lensAPIProvider; |
|||
|
|||
@property (nonatomic, readwrite, strong) ARSession *arSession NS_AVAILABLE_IOS(11_0); |
|||
|
|||
@property (nonatomic, readwrite, strong) SCManagedStillImageCapturer *arImageCapturer NS_AVAILABLE_IOS(11_0); |
|||
|
|||
@property (nonatomic, readwrite, strong) SCManagedCaptureSession *managedSession; |
|||
|
|||
@property (nonatomic, readwrite, strong) id<SCManagedVideoDataSource> videoDataSource; |
|||
|
|||
@property (nonatomic, readwrite, strong) SCManagedDeviceCapacityAnalyzer *deviceCapacityAnalyzer; |
|||
|
|||
@property (nonatomic, readwrite, strong) SCManagedVideoScanner *videoScanner; |
|||
|
|||
@property (nonatomic, readwrite, strong) SCManagedCapturerListenerAnnouncer *announcer; |
|||
|
|||
@property (nonatomic, readwrite, strong) AVCaptureVideoPreviewLayer *videoPreviewLayer; |
|||
|
|||
@property (nonatomic, readwrite, strong) id<SCManagedCapturerGLViewManagerAPI> videoPreviewGLViewManager; |
|||
|
|||
@property (nonatomic, readwrite, strong) SCManagedStillImageCapturer *stillImageCapturer; |
|||
|
|||
@property (nonatomic, readwrite, strong) SCManagedVideoCapturer *videoCapturer; |
|||
|
|||
@property (nonatomic, readwrite, strong) SCQueuePerformer *queuePerformer; |
|||
|
|||
@property (nonatomic, readwrite, strong) SCManagedVideoFrameSampler *videoFrameSampler; |
|||
|
|||
@property (nonatomic, readwrite, strong) SCManagedDroppedFramesReporter *droppedFramesReporter; |
|||
|
|||
@property (nonatomic, readwrite, strong) SCManagedVideoStreamReporter *videoStreamReporter; // INTERNAL USE ONLY |
|||
|
|||
@property (nonatomic, readwrite, strong) SCManagedFrontFlashController *frontFlashController; |
|||
|
|||
@property (nonatomic, readwrite, strong) SCManagedVideoCapturerHandler *videoCapturerHandler; |
|||
|
|||
@property (nonatomic, readwrite, strong) SCManagedStillImageCapturerHandler *stillImageCapturerHandler; |
|||
|
|||
@property (nonatomic, readwrite, strong) SCManagedDeviceCapacityAnalyzerHandler *deviceCapacityAnalyzerHandler; |
|||
|
|||
@property (nonatomic, readwrite, strong) SCManagedCaptureDeviceDefaultZoomHandler *deviceZoomHandler; |
|||
|
|||
@property (nonatomic, readwrite, strong) SCManagedCaptureDeviceHandler *captureDeviceHandler; |
|||
|
|||
@property (nonatomic, readwrite, strong) id<SCCaptureFaceDetector> captureFaceDetector; |
|||
|
|||
@property (nonatomic, readwrite, strong) FBKVOController *kvoController; |
|||
|
|||
@property (nonatomic, readwrite, strong) id<SCManagedCapturerLSAComponentTrackerAPI> lsaTrackingComponentHandler; |
|||
|
|||
@property (nonatomic, readwrite, strong) SCManagedCapturerARSessionHandler *arSessionHandler; |
|||
|
|||
@property (nonatomic, assign) SEL completeARSessionShutdown; |
|||
|
|||
@property (nonatomic, assign) SEL handleAVSessionStatusChange; |
|||
|
|||
@property (nonatomic, assign) BOOL videoRecording; |
|||
|
|||
@property (nonatomic, assign) NSInteger numRetriesFixAVCaptureSessionWithCurrentSession; |
|||
|
|||
@property (nonatomic, assign) BOOL appInBackground; |
|||
|
|||
@property (nonatomic, assign) NSUInteger streamingSequence; |
|||
|
|||
@property (nonatomic, assign) BOOL stillImageCapturing; |
|||
|
|||
@property (nonatomic, readwrite, strong) NSTimer *livenessTimer; |
|||
|
|||
@property (nonatomic, readwrite, strong) NSMutableSet<SCCapturerToken *> *tokenSet; |
|||
|
|||
@property (nonatomic, readwrite, strong) SCSingleFrameStreamCapturer *frameCap; |
|||
|
|||
@property (nonatomic, readwrite, strong) id<SCManagedSampleBufferDisplayController> sampleBufferDisplayController; |
|||
|
|||
@property (nonatomic, readwrite, strong) SCSnapCreationTriggers *snapCreationTriggers; |
|||
|
|||
// Different from most properties above, following are main thread properties. |
|||
@property (nonatomic, assign) BOOL allowsZoom; |
|||
|
|||
@property (nonatomic, assign) NSUInteger numRetriesFixInconsistencyWithCurrentSession; |
|||
|
|||
@property (nonatomic, readwrite, strong) NSMutableDictionary *debugInfoDict; |
|||
|
|||
@property (nonatomic, assign) BOOL notificationRegistered; |
|||
|
|||
@property (nonatomic, readwrite, strong) SCManagedCaptureDeviceSubjectAreaHandler *deviceSubjectAreaHandler; |
|||
|
|||
@property (nonatomic, assign) SEL sessionRuntimeError; |
|||
|
|||
@property (nonatomic, assign) SEL livenessConsistency; |
|||
|
|||
// TODO: these properties will be refactored into SCCaptureSessionFixer class |
|||
// The refactor will be in a separate PR |
|||
// Timestamp when _fixAVSessionIfNecessary is called |
|||
@property (nonatomic, assign) NSTimeInterval lastFixSessionTimestamp; |
|||
// Timestamp when session runtime error is handled |
|||
@property (nonatomic, assign) NSTimeInterval lastSessionRuntimeErrorTime; |
|||
// Wether we schedule fix of creating session already |
|||
@property (nonatomic, assign) BOOL isRecreateSessionFixScheduled; |
|||
|
|||
@property (nonatomic, readwrite, strong) SCCaptureSessionFixer *captureSessionFixer; |
|||
|
|||
@property (nonatomic, readwrite, strong) SCBlackCameraDetector *blackCameraDetector; |
|||
|
|||
@property (nonatomic, readwrite, strong) id<SCDeviceMotionProvider> deviceMotionProvider; |
|||
|
|||
@property (nonatomic, readwrite, strong) id<SCManagedCapturerARImageCaptureProvider> arImageCaptureProvider; |
|||
|
|||
@property (nonatomic, readwrite, strong) id<SCFileInputDecider> fileInputDecider; |
|||
|
|||
@property (nonatomic, readwrite, strong) |
|||
id<SCManagedCapturePreviewLayerControllerDelegate> previewLayerControllerDelegate; |
|||
@end |
@ -0,0 +1,66 @@ |
|||
// |
|||
// SCCaptureResource.m |
|||
// Snapchat |
|||
// |
|||
// Created by Lin Jia on 10/19/17. |
|||
// |
|||
// |
|||
|
|||
#import "SCCaptureResource.h" |
|||
|
|||
#import "SCBlackCameraDetector.h" |
|||
#import "SCManagedCapturerState.h" |
|||
#import "SCManagedFrontFlashController.h" |
|||
#import "SCManagedVideoCapturer.h" |
|||
|
|||
#import <SCFoundation/SCAssertWrapper.h> |
|||
#import <SCFoundation/SCQueuePerformer.h> |
|||
#import <SCFoundation/SCTraceODPCompatible.h> |
|||
|
|||
#import <FBKVOController/FBKVOController.h> |
|||
|
|||
@interface SCCaptureResource () { |
|||
FBKVOController *_previewHiddenKVO; |
|||
} |
|||
|
|||
@end |
|||
|
|||
@implementation SCCaptureResource |
|||
|
|||
- (SCManagedFrontFlashController *)frontFlashController |
|||
{ |
|||
SCTraceODPCompatibleStart(2); |
|||
SCAssert([self.queuePerformer isCurrentPerformer], @""); |
|||
if (!_frontFlashController) { |
|||
_frontFlashController = [[SCManagedFrontFlashController alloc] init]; |
|||
} |
|||
return _frontFlashController; |
|||
} |
|||
|
|||
- (void)setVideoPreviewLayer:(AVCaptureVideoPreviewLayer *)layer |
|||
{ |
|||
SC_GUARD_ELSE_RETURN(layer != _videoPreviewLayer); |
|||
|
|||
if (_videoPreviewLayer) { |
|||
[_previewHiddenKVO unobserve:_videoPreviewLayer]; |
|||
} |
|||
_videoPreviewLayer = layer; |
|||
|
|||
SC_GUARD_ELSE_RETURN(_videoPreviewLayer); |
|||
|
|||
if (!_previewHiddenKVO) { |
|||
_previewHiddenKVO = [[FBKVOController alloc] initWithObserver:self]; |
|||
} |
|||
|
|||
[_previewHiddenKVO observe:_videoPreviewLayer |
|||
keyPath:@keypath(_videoPreviewLayer.hidden) |
|||
options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld |
|||
block:^(id observer, id object, NSDictionary *change) { |
|||
BOOL oldValue = [change[NSKeyValueChangeOldKey] boolValue]; |
|||
BOOL newValue = [change[NSKeyValueChangeNewKey] boolValue]; |
|||
if (oldValue != newValue) { |
|||
[_blackCameraDetector capturePreviewDidBecomeVisible:!newValue]; |
|||
} |
|||
}]; |
|||
} |
|||
@end |
@ -0,0 +1,377 @@ |
|||
// |
|||
// SCCameraTweaks.h |
|||
// Snapchat |
|||
// |
|||
// Created by Liu Liu on 9/16/15. |
|||
// Copyright © 2015 Snapchat, Inc. All rights reserved. |
|||
// |
|||
|
|||
#import <SCBase/SCMacros.h> |
|||
#import <SCCameraFoundation/SCManagedCaptureDevicePosition.h> |
|||
#import <SCTweakAdditions/SCTweakDefines.h> |
|||
|
|||
#import <Tweaks/FBTweakInline.h> |
|||
|
|||
#import <CoreGraphics/CoreGraphics.h> |
|||
#import <Foundation/Foundation.h> |
|||
|
|||
// Core Camera |
|||
|
|||
typedef NS_ENUM(NSUInteger, SCManagedCaptureDeviceZoomHandlerType) { |
|||
SCManagedCaptureDeviceDefaultZoom, |
|||
SCManagedCaptureDeviceSavitzkyGolayFilter, |
|||
SCManagedCaptureDeviceLinearInterpolation, |
|||
}; |
|||
|
|||
typedef NS_ENUM(NSUInteger, SCCameraTweaksStrategyType) { |
|||
SCCameraTweaksStrategyFollowABTest = 0, |
|||
SCCameraTweaksStrategyOverrideToYes, |
|||
SCCameraTweaksStrategyOverrideToNo |
|||
}; |
|||
|
|||
typedef NS_ENUM(NSUInteger, SCCameraHandsFreeModeType) { |
|||
SCCameraHandsFreeModeTypeABTest = 0, |
|||
SCCameraHandsFreeModeTypeDisabled, |
|||
SCCameraHandsFreeModeTypeMainOnly, |
|||
SCCameraHandsFreeModeTypeChatMoveCaptureButton, |
|||
SCCameraHandsFreeModeTypeMainAndChat, |
|||
SCCameraHandsFreeModeTypeLeftOfCapture, |
|||
}; |
|||
|
|||
/// Face detection and focus strategy in Tweak. There are less options in internal Tweaks than the A/B testing |
|||
/// strategies. |
|||
typedef NS_ENUM(NSUInteger, SCCameraFaceFocusModeStrategyType) { |
|||
SCCameraFaceFocusModeStrategyTypeABTest = 0, |
|||
SCCameraFaceFocusModeStrategyTypeDisabled, // Disabled for both cameras. |
|||
SCCameraFaceFocusModeStrategyTypeOffByDefault, // Enabled for both cameras, but is off by default. |
|||
SCCameraFaceFocusModeStrategyTypeOnByDefault, // Enabled for both cameras, but is off by default. |
|||
}; |
|||
|
|||
typedef NS_ENUM(NSUInteger, SCCameraFaceFocusDetectionMethodType) { |
|||
SCCameraFaceFocusDetectionMethodTypeABTest = 0, |
|||
SCCameraFaceFocusDetectionMethodTypeCIDetector, // Use SCCaptureCoreImageFaceDetector |
|||
SCCameraFaceFocusDetectionMethodTypeAVMetadata, // Use SCCaptureMetadataOutputDetector |
|||
}; |
|||
|
|||
SC_EXTERN_C_BEGIN |
|||
|
|||
extern SCManagedCaptureDeviceZoomHandlerType SCCameraTweaksDeviceZoomHandlerStrategy(void); |
|||
|
|||
extern BOOL SCCameraTweaksBlackCameraRecoveryEnabled(void); |
|||
|
|||
extern BOOL SCCameraTweaksMicPermissionEnabled(void); |
|||
|
|||
extern BOOL SCCameraTweaksEnableCaptureKeepRecordedVideo(void); |
|||
|
|||
extern BOOL SCCameraTweaksEnableHandsFreeXToCancel(void); |
|||
extern SCCameraHandsFreeModeType SCCameraTweaksHandsFreeMode(void); |
|||
|
|||
BOOL SCCameraTweaksEnableShortPreviewTransitionAnimationDuration(void); |
|||
|
|||
extern BOOL SCCameraTweaksEnablePreviewPresenterFastPreview(void); |
|||
|
|||
extern BOOL SCCameraTweaksEnableCaptureSharePerformer(void); |
|||
|
|||
extern BOOL SCCameraTweaksEnableFaceDetectionFocus(SCManagedCaptureDevicePosition captureDevicePosition); |
|||
|
|||
extern BOOL SCCameraTweaksTurnOnFaceDetectionFocusByDefault(SCManagedCaptureDevicePosition captureDevicePosition); |
|||
|
|||
extern SCCameraFaceFocusDetectionMethodType SCCameraFaceFocusDetectionMethod(void); |
|||
|
|||
extern CGFloat SCCameraFaceFocusMinFaceSize(void); |
|||
|
|||
extern BOOL SCCameraTweaksSessionLightWeightFixEnabled(void); |
|||
|
|||
SC_EXTERN_C_END |
|||
|
|||
static inline BOOL SCCameraTweaksEnableVideoStabilization(void) |
|||
{ |
|||
return FBTweakValue(@"Camera", @"Core Camera", @"Enable video stabilization", NO); |
|||
} |
|||
|
|||
static inline BOOL SCCameraTweaksEnableForceTouchToToggleCamera(void) |
|||
{ |
|||
return FBTweakValue(@"Camera", @"Recording", @"Force Touch to Toggle", NO); |
|||
} |
|||
|
|||
static inline BOOL SCCameraTweaksEnableStayOnCameraAfterPostingStory(void) |
|||
{ |
|||
return FBTweakValue(@"Camera", @"Story", @"Stay on camera after posting", NO); |
|||
} |
|||
|
|||
static inline BOOL SCCameraTweaksEnableKeepLastFrameOnCamera(void) |
|||
{ |
|||
return FBTweakValue(@"Camera", @"Core Camera", @"Keep last frame on camera", YES); |
|||
} |
|||
|
|||
static inline BOOL SCCameraTweaksSmoothAutoFocusWhileRecording(void) |
|||
{ |
|||
return FBTweakValue(@"Camera", @"Core Camera", @"Smooth autofocus while recording", YES); |
|||
} |
|||
|
|||
static inline NSInteger SCCameraExposureAdjustmentMode(void) |
|||
{ |
|||
return [FBTweakValue( |
|||
@"Camera", @"Core Camera", @"Adjust Exposure", (id) @0, |
|||
(@{ @0 : @"NO", |
|||
@1 : @"Dynamic enhancement", |
|||
@2 : @"Night vision", |
|||
@3 : @"Inverted night vision" })) integerValue]; |
|||
} |
|||
|
|||
static inline BOOL SCCameraTweaksRotateToggleCameraButton(void) |
|||
{ |
|||
return SCTweakValueWithHalt(@"Camera", @"Core Camera", @"Rotate Toggle-Camera Button", NO); |
|||
} |
|||
|
|||
static inline CGFloat SCCameraTweaksRotateToggleCameraButtonTime(void) |
|||
{ |
|||
return FBTweakValue(@"Camera", @"Core Camera", @"Toggle-Camera Button Rotation Time", 0.3); |
|||
} |
|||
|
|||
static inline BOOL SCCameraTweaksDefaultPortrait(void) |
|||
{ |
|||
return FBTweakValue(@"Camera", @"Core Camera", @"Default to Portrait Orientation", YES); |
|||
} |
|||
|
|||
// For test purpose |
|||
static inline BOOL SCCameraTweaksTranscodingAlwaysFails(void) |
|||
{ |
|||
return FBTweakValue(@"Camera", @"Core Camera", @"Transcoding always fails", NO); |
|||
} |
|||
|
|||
// This tweak disables the video masking behavior of the snap overlays; |
|||
// Intended to be used by curators who are on-site snapping special events. |
|||
// Ping news-dev@snapchat.com for any questions/comments |
|||
static inline BOOL SCCameraTweaksDisableOverlayVideoMask(void) |
|||
{ |
|||
return FBTweakValue(@"Camera", @"Creative Tools", @"Disable Overlay Video Masking", NO); |
|||
} |
|||
|
|||
static inline NSInteger SCCameraTweaksDelayTurnOnFilters(void) |
|||
{ |
|||
return [FBTweakValue(@"Camera", @"Core Camera", @"Delay turn on filter", (id) @0, |
|||
(@{ @0 : @"Respect A/B testing", |
|||
@1 : @"Override to YES", |
|||
@2 : @"Override to NO" })) integerValue]; |
|||
} |
|||
|
|||
static inline BOOL SCCameraTweaksEnableExposurePointObservation(void) |
|||
{ |
|||
return FBTweakValue(@"Camera", @"Core Camera - Face Focus", @"Observe Exposure Point", NO); |
|||
} |
|||
|
|||
static inline BOOL SCCameraTweaksEnableFocusPointObservation(void) |
|||
{ |
|||
return FBTweakValue(@"Camera", @"Core Camera - Face Focus", @"Observe Focus Point", NO); |
|||
} |
|||
|
|||
static inline CGFloat SCCameraTweaksSmoothZoomThresholdTime() |
|||
{ |
|||
return FBTweakValue(@"Camera", @"Zoom Strategy - Linear Interpolation", @"Threshold time", 0.3); |
|||
} |
|||
|
|||
static inline CGFloat SCCameraTweaksSmoothZoomThresholdFactor() |
|||
{ |
|||
return FBTweakValue(@"Camera", @"Zoom Strategy - Linear Interpolation", @"Threshold factor diff", 0.25); |
|||
} |
|||
|
|||
static inline CGFloat SCCameraTweaksSmoothZoomIntermediateFramesPerSecond() |
|||
{ |
|||
return FBTweakValue(@"Camera", @"Zoom Strategy - Linear Interpolation", @"Intermediate fps", 60); |
|||
} |
|||
|
|||
static inline CGFloat SCCameraTweaksSmoothZoomDelayTolerantTime() |
|||
{ |
|||
return FBTweakValue(@"Camera", @"Zoom Strategy - Linear Interpolation", @"Delay tolerant time", 0.15); |
|||
} |
|||
|
|||
static inline CGFloat SCCameraTweaksSmoothZoomMinStepLength() |
|||
{ |
|||
return FBTweakValue(@"Camera", @"Zoom Strategy - Linear Interpolation", @"Min step length", 0.05); |
|||
} |
|||
|
|||
static inline CGFloat SCCameraTweaksExposureDeadline() |
|||
{ |
|||
return FBTweakValue(@"Camera", @"Adjust Exposure", @"Exposure Deadline", 0.2); |
|||
} |
|||
|
|||
static inline BOOL SCCameraTweaksKillFrontCamera(void) |
|||
{ |
|||
return SCTweakValueWithHalt(@"Camera", @"Debugging", @"Kill Front Camera", NO); |
|||
} |
|||
|
|||
static inline BOOL SCCameraTweaksKillBackCamera(void) |
|||
{ |
|||
return SCTweakValueWithHalt(@"Camera", @"Debugging", @"Kill Back Camera", NO); |
|||
} |
|||
|
|||
#if TARGET_IPHONE_SIMULATOR |
|||
|
|||
static inline BOOL SCCameraTweaksUseRealMockImage(void) |
|||
{ |
|||
return FBTweakValue(@"Camera", @"Debugging", @"Use real mock image on simulator", YES); |
|||
} |
|||
|
|||
#endif |
|||
|
|||
static inline CGFloat SCCameraTweaksShortPreviewTransitionAnimationDuration() |
|||
{ |
|||
return FBTweakValue(@"Camera", @"Preview Transition", @"Short Animation Duration", 0.35); |
|||
} |
|||
|
|||
static inline SCCameraTweaksStrategyType SCCameraTweaksPreviewTransitionAnimationDurationStrategy() |
|||
{ |
|||
NSNumber *strategy = SCTweakValueWithHalt(@"Camera", @"Preview Transition", @"Enable Short Animation Duration", |
|||
(id) @(SCCameraTweaksStrategyFollowABTest), (@{ |
|||
@(SCCameraTweaksStrategyFollowABTest) : @"Respect A/B testing", |
|||
@(SCCameraTweaksStrategyOverrideToYes) : @"Override to YES", |
|||
@(SCCameraTweaksStrategyOverrideToNo) : @"Override to NO" |
|||
})); |
|||
return (SCCameraTweaksStrategyType)[strategy unsignedIntegerValue]; |
|||
} |
|||
|
|||
static inline CGFloat SCCameraTweaksEnablePortraitModeButton(void) |
|||
{ |
|||
return FBTweakValue(@"Camera", @"Core Camera - Portrait Mode", @"Enable Button", NO); |
|||
} |
|||
|
|||
static inline CGFloat SCCameraTweaksDepthBlurForegroundThreshold(void) |
|||
{ |
|||
return FBTweakValue(@"Camera", @"Core Camera - Portrait Mode", @"Foreground Blur Threshold", 0.3); |
|||
} |
|||
|
|||
static inline CGFloat SCCameraTweaksDepthBlurBackgroundThreshold(void) |
|||
{ |
|||
return FBTweakValue(@"Camera", @"Core Camera - Portrait Mode", @"Background Blur Threshold", 0.1); |
|||
} |
|||
|
|||
static inline CGFloat SCCameraTweaksBlurSigma(void) |
|||
{ |
|||
return FBTweakValue(@"Camera", @"Core Camera - Portrait Mode", @"Blur Sigma", 4.0); |
|||
} |
|||
|
|||
static inline BOOL SCCameraTweaksEnableFilterInputFocusRect(void) |
|||
{ |
|||
return FBTweakValue(@"Camera", @"Core Camera - Portrait Mode", @"Filter Input Focus Rect", NO); |
|||
} |
|||
|
|||
static inline BOOL SCCameraTweaksEnablePortraitModeTapToFocus(void) |
|||
{ |
|||
return FBTweakValue(@"Camera", @"Core Camera - Portrait Mode", @"Tap to Focus", NO); |
|||
} |
|||
|
|||
static inline BOOL SCCameraTweaksEnablePortraitModeAutofocus(void) |
|||
{ |
|||
return FBTweakValue(@"Camera", @"Core Camera - Portrait Mode", @"Autofocus", NO); |
|||
} |
|||
|
|||
static inline BOOL SCCameraTweaksDepthToGrayscaleOverride(void) |
|||
{ |
|||
return FBTweakValue(@"Camera", @"Core Camera - Portrait Mode", @"Depth to Grayscale Override", NO); |
|||
} |
|||
|
|||
static inline SCCameraTweaksStrategyType SCCameraTweaksEnableHandsFreeXToCancelStrategy(void) |
|||
{ |
|||
NSNumber *strategy = SCTweakValueWithHalt(@"Camera", @"Hands-Free Recording", @"X to Cancel", |
|||
(id) @(SCCameraTweaksStrategyFollowABTest), (@{ |
|||
@(SCCameraTweaksStrategyFollowABTest) : @"Respect A/B testing", |
|||
@(SCCameraTweaksStrategyOverrideToYes) : @"Override to YES", |
|||
@(SCCameraTweaksStrategyOverrideToNo) : @"Override to NO" |
|||
})); |
|||
return (SCCameraTweaksStrategyType)[strategy unsignedIntegerValue]; |
|||
} |
|||
|
|||
static inline SCCameraHandsFreeModeType SCCameraTweaksHandsFreeModeType() |
|||
{ |
|||
NSNumber *strategy = SCTweakValueWithHalt( |
|||
@"Camera", @"Hands-Free Recording", @"Enabled", (id) @(SCCameraHandsFreeModeTypeABTest), (@{ |
|||
@(SCCameraHandsFreeModeTypeABTest) : @"Respect A/B testing", |
|||
@(SCCameraHandsFreeModeTypeDisabled) : @"Disable", |
|||
@(SCCameraHandsFreeModeTypeMainOnly) : @"Main Camera only", |
|||
@(SCCameraHandsFreeModeTypeChatMoveCaptureButton) : @"Main Camera + move Chat capture button", |
|||
@(SCCameraHandsFreeModeTypeMainAndChat) : @"Main + Chat Cameras", |
|||
@(SCCameraHandsFreeModeTypeLeftOfCapture) : @"Left of Main + Chat Cameras" |
|||
})); |
|||
return (SCCameraHandsFreeModeType)[strategy unsignedIntegerValue]; |
|||
} |
|||
|
|||
static inline SCCameraTweaksStrategyType SCCameraTweaksPreviewPresenterFastPreviewStrategy(void) |
|||
{ |
|||
NSNumber *strategy = SCTweakValueWithHalt(@"Camera", @"Preview Presenter", @"Fast Preview", |
|||
(id) @(SCCameraTweaksStrategyFollowABTest), (@{ |
|||
@(SCCameraTweaksStrategyFollowABTest) : @"Respect A/B testing", |
|||
@(SCCameraTweaksStrategyOverrideToYes) : @"Override to YES", |
|||
@(SCCameraTweaksStrategyOverrideToNo) : @"Override to NO" |
|||
})); |
|||
return (SCCameraTweaksStrategyType)[strategy unsignedIntegerValue]; |
|||
} |
|||
|
|||
static inline NSInteger SCCameraTweaksEnableCaptureKeepRecordedVideoStrategy(void) |
|||
{ |
|||
NSNumber *strategy = |
|||
SCTweakValueWithHalt(@"Camera", @"Core Camera - Capture Keep Recorded Video", |
|||
@"Enable Capture Keep Recorded Video", (id) @(SCCameraTweaksStrategyFollowABTest), (@{ |
|||
@(SCCameraTweaksStrategyFollowABTest) : @"Respect A/B testing", |
|||
@(SCCameraTweaksStrategyOverrideToYes) : @"Override to YES", |
|||
@(SCCameraTweaksStrategyOverrideToNo) : @"Override to NO" |
|||
})); |
|||
return (SCCameraTweaksStrategyType)[strategy unsignedIntegerValue]; |
|||
} |
|||
|
|||
static inline NSInteger SCCameraTweaksEnableCaptureSharePerformerStrategy(void) |
|||
{ |
|||
NSNumber *strategy = |
|||
SCTweakValueWithHalt(@"Camera", @"Core Camera - Capture Share Performer", @"Enable Capture Share Performer", |
|||
(id) @(SCCameraTweaksStrategyFollowABTest), (@{ |
|||
@(SCCameraTweaksStrategyFollowABTest) : @"Respect A/B testing", |
|||
@(SCCameraTweaksStrategyOverrideToYes) : @"Override to YES", |
|||
@(SCCameraTweaksStrategyOverrideToNo) : @"Override to NO" |
|||
})); |
|||
return (SCCameraTweaksStrategyType)[strategy unsignedIntegerValue]; |
|||
} |
|||
|
|||
static inline SCCameraFaceFocusModeStrategyType SCCameraTweaksFaceFocusStrategy() |
|||
{ |
|||
NSNumber *strategy = |
|||
SCTweakValueWithHalt(@"Camera", @"Core Camera - Face Focus", @"Enable Face Focus", |
|||
(id) @(SCCameraFaceFocusModeStrategyTypeABTest), (@{ |
|||
@(SCCameraFaceFocusModeStrategyTypeABTest) : @"Respect A/B testing", |
|||
@(SCCameraFaceFocusModeStrategyTypeDisabled) : @"Disabled", |
|||
@(SCCameraFaceFocusModeStrategyTypeOffByDefault) : @"Enabled, off by default", |
|||
@(SCCameraFaceFocusModeStrategyTypeOnByDefault) : @"Enabled, on by default", |
|||
})); |
|||
return (SCCameraFaceFocusModeStrategyType)[strategy unsignedIntegerValue]; |
|||
} |
|||
|
|||
static inline SCCameraFaceFocusDetectionMethodType SCCameraTweaksFaceFocusDetectionMethodType() |
|||
{ |
|||
NSNumber *strategy = |
|||
SCTweakValueWithHalt(@"Camera", @"Core Camera - Face Focus", @"Detection Method", |
|||
(id) @(SCCameraFaceFocusDetectionMethodTypeABTest), (@{ |
|||
@(SCCameraFaceFocusDetectionMethodTypeABTest) : @"Respect A/B testing", |
|||
@(SCCameraFaceFocusDetectionMethodTypeCIDetector) : @"CIDetector", |
|||
@(SCCameraFaceFocusDetectionMethodTypeAVMetadata) : @"AVMetadata", |
|||
})); |
|||
return (SCCameraFaceFocusDetectionMethodType)[strategy unsignedIntegerValue]; |
|||
} |
|||
|
|||
static inline int SCCameraTweaksFaceFocusDetectionFrequency() |
|||
{ |
|||
return FBTweakValue(@"Camera", @"Core Camera - Face Focus", @"Detection Frequency", 3, 1, 30); |
|||
} |
|||
|
|||
static inline BOOL SCCameraTweaksFaceFocusMinFaceSizeRespectABTesting() |
|||
{ |
|||
return SCTweakValueWithHalt(@"Camera", @"Core Camera - Face Focus", @"Min Face Size Respect AB", YES); |
|||
} |
|||
|
|||
static inline CGFloat SCCameraTweaksFaceFocusMinFaceSizeValue() |
|||
{ |
|||
return FBTweakValue(@"Camera", @"Core Camera - Face Focus", @"Min Face Size", 0.25, 0.01, 0.5); |
|||
} |
|||
|
|||
static inline BOOL SCCameraTweaksEnableDualCamera(void) |
|||
{ |
|||
return SCTweakValueWithHalt(@"Camera", @"Core Camera - Dual Camera", @"Enable Dual Camera", NO); |
|||
} |
@ -0,0 +1,396 @@ |
|||
// |
|||
// SCCameraTweaks.m |
|||
// Snapchat |
|||
// |
|||
// Created by Liu Liu on 10/4/16. |
|||
// Copyright © 2016 Snapchat, Inc. All rights reserved. |
|||
// |
|||
|
|||
#import "SCCameraTweaks.h" |
|||
|
|||
#import "SCManagedCapturePreviewLayerController.h" |
|||
|
|||
#import <SCFoundation/SCDeviceName.h> |
|||
#import <SCFoundation/SCZeroDependencyExperiments.h> |
|||
#import <SCTweakAdditions/SCTweakDefines.h> |
|||
|
|||
SCManagedCaptureDeviceZoomHandlerType SCCameraTweaksDeviceZoomHandlerStrategy(void) |
|||
{ |
|||
|
|||
NSNumber *strategyNumber = SCTweakValueWithHalt( |
|||
@"Camera", @"Core Camera", @"Zoom Strategy", |
|||
@(SCIsMasterBuild() ? SCManagedCaptureDeviceLinearInterpolation : SCManagedCaptureDeviceDefaultZoom), (@{ |
|||
@(SCManagedCaptureDeviceDefaultZoom) : @"Default", |
|||
@(SCManagedCaptureDeviceSavitzkyGolayFilter) : @"Savitzky-Golay Filter", |
|||
@(SCManagedCaptureDeviceLinearInterpolation) : @"Linear Interpolation" |
|||
})); |
|||
return (SCManagedCaptureDeviceZoomHandlerType)[strategyNumber integerValue]; |
|||
} |
|||
|
|||
BOOL SCCameraTweaksEnableFaceDetectionFocus(SCManagedCaptureDevicePosition captureDevicePosition) |
|||
{ |
|||
SC_GUARD_ELSE_RETURN_VALUE([SCDeviceName isIphone], NO); |
|||
SC_GUARD_ELSE_RETURN_VALUE(captureDevicePosition != SCManagedCaptureDevicePositionBackDualCamera, NO); |
|||
|
|||
BOOL isFrontCamera = (captureDevicePosition == SCManagedCaptureDevicePositionFront); |
|||
BOOL isEnabled = NO; |
|||
SCCameraFaceFocusModeStrategyType option = SCCameraTweaksFaceFocusStrategy(); |
|||
switch (option) { |
|||
case SCCameraFaceFocusModeStrategyTypeABTest: |
|||
if (isFrontCamera) { |
|||
isEnabled = SCExperimentWithFaceDetectionFocusFrontCameraEnabled(); |
|||
} else { |
|||
isEnabled = SCExperimentWithFaceDetectionFocusBackCameraEnabled(); |
|||
} |
|||
break; |
|||
case SCCameraFaceFocusModeStrategyTypeDisabled: |
|||
isEnabled = NO; |
|||
break; |
|||
case SCCameraFaceFocusModeStrategyTypeOffByDefault: |
|||
case SCCameraFaceFocusModeStrategyTypeOnByDefault: |
|||
isEnabled = YES; |
|||
break; |
|||
} |
|||
return isEnabled; |
|||
} |
|||
|
|||
BOOL SCCameraTweaksTurnOnFaceDetectionFocusByDefault(SCManagedCaptureDevicePosition captureDevicePosition) |
|||
{ |
|||
SC_GUARD_ELSE_RETURN_VALUE([SCDeviceName isIphone], NO); |
|||
SC_GUARD_ELSE_RETURN_VALUE(captureDevicePosition != SCManagedCaptureDevicePositionBackDualCamera, NO); |
|||
|
|||
BOOL isFrontCamera = (captureDevicePosition == SCManagedCaptureDevicePositionFront); |
|||
BOOL isOnByDefault = NO; |
|||
SCCameraFaceFocusModeStrategyType option = SCCameraTweaksFaceFocusStrategy(); |
|||
switch (option) { |
|||
case SCCameraFaceFocusModeStrategyTypeABTest: |
|||
if (isFrontCamera) { |
|||
isOnByDefault = SCExperimentWithFaceDetectionFocusFrontCameraOnByDefault(); |
|||
} else { |
|||
isOnByDefault = SCExperimentWithFaceDetectionFocusBackCameraOnByDefault(); |
|||
} |
|||
break; |
|||
case SCCameraFaceFocusModeStrategyTypeDisabled: |
|||
case SCCameraFaceFocusModeStrategyTypeOffByDefault: |
|||
isOnByDefault = NO; |
|||
break; |
|||
case SCCameraFaceFocusModeStrategyTypeOnByDefault: |
|||
isOnByDefault = YES; |
|||
break; |
|||
} |
|||
return isOnByDefault; |
|||
} |
|||
|
|||
SCCameraFaceFocusDetectionMethodType SCCameraFaceFocusDetectionMethod() |
|||
{ |
|||
static SCCameraFaceFocusDetectionMethodType detectionMethodType; |
|||
static dispatch_once_t onceToken; |
|||
dispatch_once(&onceToken, ^{ |
|||
SCCameraFaceFocusDetectionMethodType option = SCCameraTweaksFaceFocusDetectionMethodType(); |
|||
switch (option) { |
|||
case SCCameraFaceFocusDetectionMethodTypeABTest: { |
|||
// Check the validity of AB value. |
|||
NSUInteger experimentValue = SCExperimentWithFaceDetectionFocusDetectionMethod(); |
|||
if (experimentValue >= SCCameraFaceFocusDetectionMethodTypeCIDetector && |
|||
experimentValue <= SCCameraFaceFocusDetectionMethodTypeAVMetadata) { |
|||
detectionMethodType = experimentValue; |
|||
} else { |
|||
// Use CIDetector by default. |
|||
detectionMethodType = SCCameraFaceFocusDetectionMethodTypeCIDetector; |
|||
} |
|||
} break; |
|||
case SCCameraFaceFocusDetectionMethodTypeAVMetadata: |
|||
detectionMethodType = SCCameraFaceFocusDetectionMethodTypeAVMetadata; |
|||
break; |
|||
case SCCameraFaceFocusDetectionMethodTypeCIDetector: |
|||
detectionMethodType = SCCameraFaceFocusDetectionMethodTypeCIDetector; |
|||
break; |
|||
} |
|||
}); |
|||
return detectionMethodType; |
|||
} |
|||
|
|||
CGFloat SCCameraFaceFocusMinFaceSize(void) |
|||
{ |
|||
static CGFloat minFaceSize; |
|||
static dispatch_once_t onceToken; |
|||
dispatch_once(&onceToken, ^{ |
|||
if (SCCameraTweaksFaceFocusMinFaceSizeRespectABTesting()) { |
|||
minFaceSize = (CGFloat)SCExperimentWithFaceDetectionMinFaceSize(); |
|||
} else { |
|||
minFaceSize = SCCameraTweaksFaceFocusMinFaceSizeValue(); |
|||
} |
|||
if (minFaceSize < 0.01 || minFaceSize > 0.5) { |
|||
minFaceSize = 0.25; // Default value is 0.25 |
|||
} |
|||
}); |
|||
return minFaceSize; |
|||
} |
|||
|
|||
BOOL SCCameraTweaksEnableCaptureKeepRecordedVideo(void) |
|||
{ |
|||
static BOOL enableCaptureKeepRecordedVideo; |
|||
static dispatch_once_t onceToken; |
|||
dispatch_once(&onceToken, ^{ |
|||
switch (SCCameraTweaksEnableCaptureKeepRecordedVideoStrategy()) { |
|||
case SCCameraTweaksStrategyOverrideToYes: { |
|||
enableCaptureKeepRecordedVideo = YES; |
|||
break; |
|||
} |
|||
case SCCameraTweaksStrategyOverrideToNo: { |
|||
enableCaptureKeepRecordedVideo = NO; |
|||
break; |
|||
} |
|||
case SCCameraTweaksStrategyFollowABTest: { |
|||
enableCaptureKeepRecordedVideo = SCExperimentWithCaptureKeepRecordedVideo(); |
|||
break; |
|||
} |
|||
default: { |
|||
enableCaptureKeepRecordedVideo = NO; |
|||
break; |
|||
} |
|||
} |
|||
}); |
|||
return enableCaptureKeepRecordedVideo; |
|||
} |
|||
|
|||
static inline SCCameraTweaksStrategyType SCCameraTweaksBlackCameraRecoveryStrategy(void) |
|||
{ |
|||
NSNumber *strategy = SCTweakValueWithHalt(@"Camera", @"Core Camera", @"Black Camera Recovery", |
|||
(id) @(SCCameraTweaksStrategyFollowABTest), (@{ |
|||
@(SCCameraTweaksStrategyFollowABTest) : @"Respect A/B testing", |
|||
@(SCCameraTweaksStrategyOverrideToYes) : @"Override to YES", |
|||
@(SCCameraTweaksStrategyOverrideToNo) : @"Override to NO" |
|||
})); |
|||
return (SCCameraTweaksStrategyType)[strategy unsignedIntegerValue]; |
|||
} |
|||
|
|||
BOOL SCCameraTweaksBlackCameraRecoveryEnabled(void) |
|||
{ |
|||
static BOOL enabled; |
|||
static dispatch_once_t onceToken; |
|||
dispatch_once(&onceToken, ^{ |
|||
switch (SCCameraTweaksBlackCameraRecoveryStrategy()) { |
|||
case SCCameraTweaksStrategyOverrideToYes: |
|||
enabled = YES; |
|||
break; |
|||
case SCCameraTweaksStrategyOverrideToNo: |
|||
enabled = NO; |
|||
break; |
|||
case SCCameraTweaksStrategyFollowABTest: |
|||
enabled = SCExperimentWithBlackCameraRecovery(); |
|||
break; |
|||
default: |
|||
enabled = NO; |
|||
break; |
|||
} |
|||
}); |
|||
return enabled; |
|||
} |
|||
|
|||
static inline SCCameraTweaksStrategyType SCCameraTweaksMicrophoneNotificationStrategy(void) |
|||
{ |
|||
NSNumber *strategy = SCTweakValueWithHalt(@"Camera", @"Core Camera", @"Mic Notification", |
|||
(id) @(SCCameraTweaksStrategyFollowABTest), (@{ |
|||
@(SCCameraTweaksStrategyFollowABTest) : @"Respect A/B testing", |
|||
@(SCCameraTweaksStrategyOverrideToYes) : @"Override to YES", |
|||
@(SCCameraTweaksStrategyOverrideToNo) : @"Override to NO" |
|||
})); |
|||
return (SCCameraTweaksStrategyType)[strategy unsignedIntegerValue]; |
|||
} |
|||
|
|||
BOOL SCCameraTweaksMicPermissionEnabled(void) |
|||
{ |
|||
static BOOL enabled; |
|||
static dispatch_once_t onceToken; |
|||
dispatch_once(&onceToken, ^{ |
|||
switch (SCCameraTweaksMicrophoneNotificationStrategy()) { |
|||
case SCCameraTweaksStrategyOverrideToYes: |
|||
enabled = YES; |
|||
break; |
|||
case SCCameraTweaksStrategyOverrideToNo: |
|||
enabled = NO; |
|||
break; |
|||
case SCCameraTweaksStrategyFollowABTest: |
|||
enabled = SCExperimentWithMicrophonePermissionNotificationEnabled(); |
|||
break; |
|||
default: |
|||
enabled = NO; |
|||
break; |
|||
} |
|||
}); |
|||
return enabled; |
|||
} |
|||
|
|||
SCCameraHandsFreeModeType SCCameraTweaksHandsFreeMode(void) |
|||
{ |
|||
static SCCameraHandsFreeModeType handsFreeModeType; |
|||
static dispatch_once_t onceToken; |
|||
dispatch_once(&onceToken, ^{ |
|||
SCCameraHandsFreeModeType option = SCCameraTweaksHandsFreeModeType(); |
|||
switch (option) { |
|||
case SCCameraHandsFreeModeTypeDisabled: |
|||
handsFreeModeType = SCCameraHandsFreeModeTypeDisabled; |
|||
break; |
|||
case SCCameraHandsFreeModeTypeMainOnly: |
|||
handsFreeModeType = SCCameraHandsFreeModeTypeMainOnly; |
|||
break; |
|||
case SCCameraHandsFreeModeTypeChatMoveCaptureButton: |
|||
handsFreeModeType = SCCameraHandsFreeModeTypeChatMoveCaptureButton; |
|||
break; |
|||
case SCCameraHandsFreeModeTypeMainAndChat: |
|||
handsFreeModeType = SCCameraHandsFreeModeTypeMainAndChat; |
|||
break; |
|||
case SCCameraHandsFreeModeTypeLeftOfCapture: |
|||
handsFreeModeType = SCCameraHandsFreeModeTypeLeftOfCapture; |
|||
break; |
|||
case SCCameraHandsFreeModeTypeABTest: |
|||
default: |
|||
handsFreeModeType = SCExperimentWithHandsFreeMode(); |
|||
break; |
|||
} |
|||
}); |
|||
return handsFreeModeType; |
|||
} |
|||
|
|||
BOOL SCCameraTweaksEnableHandsFreeXToCancel(void) |
|||
{ |
|||
static BOOL enableHandsFreeXToCancel; |
|||
static dispatch_once_t onceToken; |
|||
dispatch_once(&onceToken, ^{ |
|||
switch (SCCameraTweaksEnableHandsFreeXToCancelStrategy()) { |
|||
case SCCameraTweaksStrategyOverrideToYes: { |
|||
enableHandsFreeXToCancel = YES; |
|||
break; |
|||
} |
|||
case SCCameraTweaksStrategyOverrideToNo: { |
|||
enableHandsFreeXToCancel = NO; |
|||
break; |
|||
} |
|||
case SCCameraTweaksStrategyFollowABTest: { |
|||
enableHandsFreeXToCancel = SCExperimentWithHandsFreeXToCancel(); |
|||
break; |
|||
} |
|||
default: { |
|||
enableHandsFreeXToCancel = NO; |
|||
break; |
|||
} |
|||
} |
|||
}); |
|||
return enableHandsFreeXToCancel; |
|||
} |
|||
|
|||
BOOL SCCameraTweaksEnableShortPreviewTransitionAnimationDuration(void) |
|||
{ |
|||
static BOOL enableShortPreviewTransitionAnimationDuration; |
|||
static dispatch_once_t onceToken; |
|||
dispatch_once(&onceToken, ^{ |
|||
switch (SCCameraTweaksPreviewTransitionAnimationDurationStrategy()) { |
|||
case SCCameraTweaksStrategyOverrideToYes: { |
|||
enableShortPreviewTransitionAnimationDuration = YES; |
|||
break; |
|||
} |
|||
case SCCameraTweaksStrategyOverrideToNo: { |
|||
enableShortPreviewTransitionAnimationDuration = NO; |
|||
break; |
|||
} |
|||
case SCCameraTweaksStrategyFollowABTest: { |
|||
enableShortPreviewTransitionAnimationDuration = SCExperimentWithShortPreviewTransitionAnimationDuration(); |
|||
break; |
|||
} |
|||
default: { |
|||
enableShortPreviewTransitionAnimationDuration = YES; |
|||
break; |
|||
} |
|||
} |
|||
}); |
|||
return enableShortPreviewTransitionAnimationDuration; |
|||
} |
|||
|
|||
BOOL SCCameraTweaksEnablePreviewPresenterFastPreview(void) |
|||
{ |
|||
static BOOL enablePreviewPresenterFastPreview; |
|||
static dispatch_once_t onceToken; |
|||
dispatch_once(&onceToken, ^{ |
|||
switch (SCCameraTweaksPreviewPresenterFastPreviewStrategy()) { |
|||
case SCCameraTweaksStrategyOverrideToYes: { |
|||
enablePreviewPresenterFastPreview = YES; |
|||
break; |
|||
} |
|||
case SCCameraTweaksStrategyOverrideToNo: { |
|||
enablePreviewPresenterFastPreview = NO; |
|||
break; |
|||
} |
|||
case SCCameraTweaksStrategyFollowABTest: { |
|||
enablePreviewPresenterFastPreview = SCExperimentWithPreviewPresenterFastPreview(); |
|||
break; |
|||
} |
|||
default: { |
|||
enablePreviewPresenterFastPreview = NO; |
|||
break; |
|||
} |
|||
} |
|||
}); |
|||
return enablePreviewPresenterFastPreview; |
|||
} |
|||
|
|||
BOOL SCCameraTweaksEnableCaptureSharePerformer(void) |
|||
{ |
|||
static BOOL enableCaptureSharePerformer; |
|||
static dispatch_once_t onceToken; |
|||
dispatch_once(&onceToken, ^{ |
|||
switch (SCCameraTweaksEnableCaptureSharePerformerStrategy()) { |
|||
case SCCameraTweaksStrategyOverrideToYes: { |
|||
enableCaptureSharePerformer = YES; |
|||
break; |
|||
} |
|||
case SCCameraTweaksStrategyOverrideToNo: { |
|||
enableCaptureSharePerformer = NO; |
|||
break; |
|||
} |
|||
case SCCameraTweaksStrategyFollowABTest: { |
|||
enableCaptureSharePerformer = SCExperimentWithCaptureSharePerformer(); |
|||
break; |
|||
} |
|||
default: { |
|||
enableCaptureSharePerformer = NO; |
|||
break; |
|||
} |
|||
} |
|||
}); |
|||
return enableCaptureSharePerformer; |
|||
} |
|||
|
|||
static inline SCCameraTweaksStrategyType SCCameraTweaksSessionLightWeightFixStrategy(void) |
|||
{ |
|||
NSNumber *strategy = SCTweakValueWithHalt(@"Camera", @"Core Camera", @"Light-weight Session Fix", |
|||
(id) @(SCCameraTweaksStrategyFollowABTest), (@{ |
|||
@(SCCameraTweaksStrategyFollowABTest) : @"Respect A/B testing", |
|||
@(SCCameraTweaksStrategyOverrideToYes) : @"Override to YES", |
|||
@(SCCameraTweaksStrategyOverrideToNo) : @"Override to NO" |
|||
})); |
|||
return (SCCameraTweaksStrategyType)[strategy unsignedIntegerValue]; |
|||
} |
|||
|
|||
BOOL SCCameraTweaksSessionLightWeightFixEnabled(void) |
|||
{ |
|||
static BOOL enabled; |
|||
static dispatch_once_t onceToken; |
|||
dispatch_once(&onceToken, ^{ |
|||
switch (SCCameraTweaksSessionLightWeightFixStrategy()) { |
|||
case SCCameraTweaksStrategyOverrideToYes: |
|||
enabled = YES; |
|||
break; |
|||
case SCCameraTweaksStrategyOverrideToNo: |
|||
enabled = NO; |
|||
break; |
|||
case SCCameraTweaksStrategyFollowABTest: |
|||
enabled = SCExperimentWithSessionLightWeightFix(); |
|||
break; |
|||
default: |
|||
enabled = NO; |
|||
break; |
|||
} |
|||
}); |
|||
return enabled; |
|||
} |
@ -0,0 +1,47 @@ |
|||
// |
|||
// AVCameraViewEnums.h |
|||
// SCCamera |
|||
// |
|||
// Copyright © 2016 Snapchat, Inc. All rights reserved. |
|||
// |
|||
|
|||
#import <Foundation/Foundation.h> |
|||
|
|||
/** |
|||
The context specifies the way in which the camera is presented to the user. |
|||
The controller can be configured a variety of ways depending on the context. |
|||
*/ |
|||
typedef NS_ENUM(NSUInteger, AVCameraViewControllerContext) { |
|||
AVCameraViewControllerContextMainVC = 1, |
|||
AVCameraViewControllerContextReply, |
|||
AVCameraViewControllerContextDefault = AVCameraViewControllerContextReply, |
|||
AVCameraViewControllerContextSnapAds, |
|||
AVCameraViewControllerContextAddToStory, |
|||
}; |
|||
|
|||
typedef NS_ENUM(NSInteger, AVCameraViewType) { |
|||
AVCameraViewNoReply = 0, |
|||
AVCameraViewReplyLeft, |
|||
AVCameraViewReplyRight, |
|||
AVCameraViewChat, |
|||
AVCameraViewReplyHydra, |
|||
AVCameraViewSnapAds, |
|||
AVCameraViewGalleryMadeWithLenses, |
|||
AVCameraViewSnapConnectSnapKit, |
|||
AVCameraViewSnappable |
|||
}; |
|||
|
|||
typedef NS_ENUM(NSUInteger, AVCameraViewControllerRecordingState) { |
|||
AVCameraViewControllerRecordingStateDefault, // No capture activity |
|||
AVCameraViewControllerRecordingStatePrepareRecording, // Preparing for recording with delay |
|||
AVCameraViewControllerRecordingStateInitiatedRecording, // Actively recording |
|||
AVCameraViewControllerRecordingStateTakingPicture, // Taking a still image |
|||
AVCameraViewControllerRecordingStatePictureTaken, // Picture is taken |
|||
AVCameraViewControllerRecordingStatePreview, // Preparing to present preview |
|||
}; |
|||
|
|||
typedef NS_ENUM(NSUInteger, SCCameraRecordingMethod) { |
|||
SCCameraRecordingMethodCameraButton, |
|||
SCCameraRecordingMethodVolumeButton, |
|||
SCCameraRecordingMethodLensInitiated |
|||
}; |
@ -0,0 +1,32 @@ |
|||
// |
|||
// SCFeatureLensButtonZ.h |
|||
// SCCamera |
|||
// |
|||
// Created by Anton Udovychenko on 4/24/18. |
|||
// |
|||
|
|||
#import "AVCameraViewEnums.h" |
|||
#import "SCFeature.h" |
|||
|
|||
#import <Foundation/Foundation.h> |
|||
|
|||
@protocol SCFeatureLensButtonZ; |
|||
@class SCGrowingButton, SCLens; |
|||
|
|||
NS_ASSUME_NONNULL_BEGIN |
|||
|
|||
@protocol SCFeatureLensButtonZDelegate <NSObject> |
|||
- (void)featureLensZButton:(id<SCFeatureLensButtonZ>)featureLensZButton |
|||
didPressLensButton:(SCGrowingButton *)lensButton; |
|||
- (nullable NSArray<SCLens *> *)allLenses; |
|||
@end |
|||
|
|||
@protocol SCFeatureLensButtonZ <SCFeature> |
|||
|
|||
@property (nonatomic, weak) id<SCFeatureLensButtonZDelegate> delegate; |
|||
|
|||
- (void)setLensButtonActive:(BOOL)active; |
|||
|
|||
@end |
|||
|
|||
NS_ASSUME_NONNULL_END |
@ -0,0 +1,33 @@ |
|||
// |
|||
// SCFeatureLensSideButton.h |
|||
// SCCamera |
|||
// |
|||
// Created by Anton Udovychenko on 4/12/18. |
|||
// |
|||
|
|||
#import "AVCameraViewEnums.h" |
|||
#import "SCFeature.h" |
|||
|
|||
#import <Foundation/Foundation.h> |
|||
|
|||
@protocol SCFeatureLensSideButton; |
|||
@class SCGrowingButton, SCLens; |
|||
|
|||
NS_ASSUME_NONNULL_BEGIN |
|||
|
|||
@protocol SCFeatureLensSideButtonDelegate <NSObject> |
|||
- (void)featureLensSideButton:(id<SCFeatureLensSideButton>)featureLensSideButton |
|||
didPressLensButton:(SCGrowingButton *)lensButton; |
|||
- (nullable SCLens *)firstApplicableLens; |
|||
@end |
|||
|
|||
@protocol SCFeatureLensSideButton <SCFeature> |
|||
|
|||
@property (nonatomic, weak) id<SCFeatureLensSideButtonDelegate> delegate; |
|||
|
|||
- (void)updateLensButtonVisibility:(CGFloat)visibilityPercentage; |
|||
- (void)showLensButtonIfNeeded; |
|||
|
|||
@end |
|||
|
|||
NS_ASSUME_NONNULL_END |
@ -0,0 +1,24 @@ |
|||
// |
|||
// SCLongPressGestureRecognizer.h |
|||
// SCCamera |
|||
// |
|||
// Created by Pavlo Antonenko on 4/28/15. |
|||
// Copyright (c) 2015 Snapchat, Inc. All rights reserved. |
|||
// |
|||
|
|||
#import <UIKit/UIKit.h> |
|||
|
|||
// gesture recognizer cancels, if user moved finger more then defined value, even if long press started, unlike |
|||
// UILongPressGestureRecognizer. But if user haven't moved finger for defined time, unlimited movement is allowed. |
|||
@interface SCLongPressGestureRecognizer : UILongPressGestureRecognizer |
|||
|
|||
@property (nonatomic, assign) CGFloat allowableMovementAfterBegan; |
|||
@property (nonatomic, assign) CGFloat timeBeforeUnlimitedMovementAllowed; |
|||
@property (nonatomic, assign, readonly) CGFloat forceOfAllTouches; |
|||
@property (nonatomic, assign, readonly) CGFloat maximumPossibleForceOfAllTouches; |
|||
@property (nonatomic, strong) NSDictionary *userInfo; |
|||
@property (nonatomic, assign) BOOL failedByMovement; |
|||
|
|||
- (BOOL)isUnlimitedMovementAllowed; |
|||
|
|||
@end |
@ -0,0 +1,88 @@ |
|||
// |
|||
// SCLongPressGestureRecognizer.m |
|||
// SCCamera |
|||
// |
|||
// Created by Pavlo Antonenko on 4/28/15. |
|||
// Copyright (c) 2015 Snapchat, Inc. All rights reserved. |
|||
// |
|||
|
|||
#import "SCLongPressGestureRecognizer.h" |
|||
|
|||
#import <SCFoundation/SCLog.h> |
|||
|
|||
#import <UIKit/UIGestureRecognizerSubclass.h> |
|||
|
|||
@implementation SCLongPressGestureRecognizer { |
|||
CGPoint _initialPoint; |
|||
CGFloat _initialTime; |
|||
} |
|||
|
|||
- (instancetype)initWithTarget:(id)target action:(SEL)action |
|||
{ |
|||
self = [super initWithTarget:target action:action]; |
|||
if (self) { |
|||
_allowableMovementAfterBegan = FLT_MAX; |
|||
_timeBeforeUnlimitedMovementAllowed = 0.0; |
|||
} |
|||
return self; |
|||
} |
|||
|
|||
- (void)reset |
|||
{ |
|||
[super reset]; |
|||
_initialPoint = CGPointZero; |
|||
_initialTime = 0; |
|||
_forceOfAllTouches = 1.0; |
|||
_maximumPossibleForceOfAllTouches = 1.0; |
|||
self.failedByMovement = NO; |
|||
} |
|||
|
|||
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event |
|||
{ |
|||
[super touchesBegan:touches withEvent:event]; |
|||
_initialPoint = [self locationInView:self.view]; |
|||
_initialTime = CACurrentMediaTime(); |
|||
_forceOfAllTouches = 1.0; |
|||
for (UITouch *touch in touches) { |
|||
_maximumPossibleForceOfAllTouches = MAX(touch.maximumPossibleForce, _maximumPossibleForceOfAllTouches); |
|||
_forceOfAllTouches = MAX(touch.force, _forceOfAllTouches); |
|||
} |
|||
} |
|||
|
|||
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event |
|||
{ |
|||
[super touchesMoved:touches withEvent:event]; |
|||
|
|||
_forceOfAllTouches = 1.0; |
|||
for (UITouch *touch in touches) { |
|||
_maximumPossibleForceOfAllTouches = MAX(touch.maximumPossibleForce, _maximumPossibleForceOfAllTouches); |
|||
_forceOfAllTouches = MAX(touch.force, _forceOfAllTouches); |
|||
} |
|||
|
|||
if (!CGPointEqualToPoint(_initialPoint, CGPointZero)) { |
|||
CGPoint currentPoint = [self locationInView:self.view]; |
|||
|
|||
CGFloat distance = hypot(_initialPoint.x - currentPoint.x, _initialPoint.y - currentPoint.y); |
|||
CGFloat timeDifference = CACurrentMediaTime() - _initialTime; |
|||
|
|||
if (distance > self.allowableMovementAfterBegan && timeDifference < self.timeBeforeUnlimitedMovementAllowed) { |
|||
SCLogGeneralInfo(@"Long press moved %.2f > %.2f after %.3f < %.3f seconds, and is cancelled", distance, |
|||
self.allowableMovementAfterBegan, timeDifference, self.timeBeforeUnlimitedMovementAllowed); |
|||
self.state = UIGestureRecognizerStateFailed; |
|||
self.failedByMovement = YES; |
|||
} |
|||
} |
|||
} |
|||
|
|||
- (void)setEnabled:(BOOL)enabled |
|||
{ |
|||
SCLogGeneralInfo(@"Setting enabled: %d for %@", enabled, self); |
|||
[super setEnabled:enabled]; |
|||
} |
|||
|
|||
- (BOOL)isUnlimitedMovementAllowed |
|||
{ |
|||
return CACurrentMediaTime() - _initialTime > self.timeBeforeUnlimitedMovementAllowed; |
|||
} |
|||
|
|||
@end |
@ -0,0 +1,31 @@ |
|||
// |
|||
// SCCameraVolumeButtonHandler.h |
|||
// Snapchat |
|||
// |
|||
// Created by Xiaomu Wu on 2/27/15. |
|||
// Copyright (c) 2015 Snapchat, Inc. All rights reserved. |
|||
// |
|||
|
|||
#import <Foundation/Foundation.h> |
|||
|
|||
@class SCCameraVolumeButtonHandler; |
|||
|
|||
@protocol SCCameraVolumeButtonHandlerDelegate <NSObject> |
|||
|
|||
- (void)volumeButtonHandlerDidBeginPressingVolumeButton:(SCCameraVolumeButtonHandler *)handler; |
|||
- (void)volumeButtonHandlerDidEndPressingVolumeButton:(SCCameraVolumeButtonHandler *)handler; |
|||
|
|||
@end |
|||
|
|||
@interface SCCameraVolumeButtonHandler : NSObject |
|||
|
|||
@property (nonatomic, weak) id<SCCameraVolumeButtonHandlerDelegate> delegate; |
|||
|
|||
- (void)startHandlingVolumeButtonEvents; |
|||
- (void)stopHandlingVolumeButtonEvents; |
|||
- (void)stopHandlingVolumeButtonEventsWhenPressingEnds; |
|||
- (BOOL)isHandlingVolumeButtonEvents; |
|||
|
|||
- (BOOL)isPressingVolumeButton; |
|||
|
|||
@end |
@ -0,0 +1,190 @@ |
|||
// |
|||
// SCCameraVolumeButtonHandler.m |
|||
// Snapchat |
|||
// |
|||
// Created by Xiaomu Wu on 2/27/15. |
|||
// Copyright (c) 2015 Snapchat, Inc. All rights reserved. |
|||
// |
|||
|
|||
#import "SCCameraVolumeButtonHandler.h" |
|||
|
|||
#import <SCFoundation/SCLog.h> |
|||
#import <SCFoundation/UIApplication+SCSecretFeature2.h> |
|||
|
|||
@implementation SCCameraVolumeButtonHandler { |
|||
NSString *_secretFeatureToken; |
|||
BOOL _pressingButton1; // volume down button |
|||
BOOL _pressingButton2; // volume up button |
|||
BOOL _stopsHandlingWhenPressingEnds; |
|||
} |
|||
|
|||
#pragma mark - NSObject |
|||
|
|||
- (instancetype)init |
|||
{ |
|||
self = [super init]; |
|||
if (self) { |
|||
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; |
|||
UIApplication *application = [UIApplication sharedApplication]; |
|||
[notificationCenter addObserver:self |
|||
selector:@selector(_handleButton1Down:) |
|||
name:[application sc_eventNotificationName1] |
|||
object:nil]; |
|||
[notificationCenter addObserver:self |
|||
selector:@selector(_handleButton1Up:) |
|||
name:[application sc_eventNotificationName2] |
|||
object:nil]; |
|||
[notificationCenter addObserver:self |
|||
selector:@selector(_handleButton2Down:) |
|||
name:[application sc_eventNotificationName3] |
|||
object:nil]; |
|||
[notificationCenter addObserver:self |
|||
selector:@selector(_handleButton2Up:) |
|||
name:[application sc_eventNotificationName4] |
|||
object:nil]; |
|||
} |
|||
return self; |
|||
} |
|||
|
|||
- (void)dealloc |
|||
{ |
|||
if (_secretFeatureToken) { |
|||
[[UIApplication sharedApplication] sc_disableSecretFeature2:_secretFeatureToken]; |
|||
} |
|||
} |
|||
|
|||
#pragma mark - Public |
|||
|
|||
- (void)startHandlingVolumeButtonEvents |
|||
{ |
|||
_stopsHandlingWhenPressingEnds = NO; |
|||
[self _resetPressingButtons]; |
|||
if ([self isHandlingVolumeButtonEvents]) { |
|||
return; |
|||
} |
|||
SCLogGeneralInfo(@"[Volume Buttons] Start handling volume button events"); |
|||
_secretFeatureToken = [[[UIApplication sharedApplication] sc_enableSecretFeature2] copy]; |
|||
} |
|||
|
|||
- (void)stopHandlingVolumeButtonEvents |
|||
{ |
|||
if (![self isHandlingVolumeButtonEvents]) { |
|||
return; |
|||
} |
|||
SCLogGeneralInfo(@"[Volume Buttons] Stop handling volume button events"); |
|||
[[UIApplication sharedApplication] sc_disableSecretFeature2:_secretFeatureToken]; |
|||
_secretFeatureToken = nil; |
|||
_stopsHandlingWhenPressingEnds = NO; |
|||
} |
|||
|
|||
- (void)stopHandlingVolumeButtonEventsWhenPressingEnds |
|||
{ |
|||
if (![self isHandlingVolumeButtonEvents]) { |
|||
return; |
|||
} |
|||
if (![self isPressingVolumeButton]) { |
|||
return; |
|||
} |
|||
SCLogGeneralInfo(@"[Volume Buttons] Stop handling volume button events when pressing ends"); |
|||
_stopsHandlingWhenPressingEnds = YES; |
|||
} |
|||
|
|||
- (BOOL)isHandlingVolumeButtonEvents |
|||
{ |
|||
return (_secretFeatureToken != nil); |
|||
} |
|||
|
|||
- (BOOL)isPressingVolumeButton |
|||
{ |
|||
return _pressingButton1 || _pressingButton2; |
|||
} |
|||
|
|||
- (void)_resetPressingButtons |
|||
{ |
|||
_pressingButton1 = NO; |
|||
_pressingButton2 = NO; |
|||
} |
|||
|
|||
#pragma mark - Private |
|||
|
|||
- (void)_handleButton1Down:(NSNotification *)notification |
|||
{ |
|||
if (![self isHandlingVolumeButtonEvents]) { |
|||
SCLogGeneralInfo(@"[Volume Buttons] Volume button 1 down, not handled"); |
|||
return; |
|||
} |
|||
if (_pressingButton1) { |
|||
SCLogGeneralInfo(@"[Volume Buttons] Volume button 1 down, already down"); |
|||
return; |
|||
} |
|||
SCLogGeneralInfo(@"[Volume Buttons] Volume button 1 down"); |
|||
[self _changePressingButton:^{ |
|||
_pressingButton1 = YES; |
|||
}]; |
|||
} |
|||
|
|||
- (void)_handleButton1Up:(NSNotification *)notification |
|||
{ |
|||
if (![self isHandlingVolumeButtonEvents]) { |
|||
SCLogGeneralInfo(@"[Volume Buttons] Volume button 1 up, not handled"); |
|||
return; |
|||
} |
|||
if (!_pressingButton1) { |
|||
SCLogGeneralInfo(@"[Volume Buttons] Volume button 1 up, already up"); |
|||
return; |
|||
} |
|||
SCLogGeneralInfo(@"[Volume Buttons] Volume button 1 up"); |
|||
[self _changePressingButton:^{ |
|||
_pressingButton1 = NO; |
|||
}]; |
|||
} |
|||
|
|||
- (void)_handleButton2Down:(NSNotification *)notification |
|||
{ |
|||
if (![self isHandlingVolumeButtonEvents]) { |
|||
SCLogGeneralInfo(@"[Volume Buttons] Volume button 2 down, not handled"); |
|||
return; |
|||
} |
|||
if (_pressingButton2) { |
|||
SCLogGeneralInfo(@"[Volume Buttons] Volume button 2 down, already down"); |
|||
return; |
|||
} |
|||
SCLogGeneralInfo(@"[Volume Buttons] Volume button 2 down"); |
|||
[self _changePressingButton:^{ |
|||
_pressingButton2 = YES; |
|||
}]; |
|||
} |
|||
|
|||
- (void)_handleButton2Up:(NSNotification *)notification |
|||
{ |
|||
if (![self isHandlingVolumeButtonEvents]) { |
|||
SCLogGeneralInfo(@"[Volume Buttons] Volume button 2 up, not handled"); |
|||
return; |
|||
} |
|||
if (!_pressingButton2) { |
|||
SCLogGeneralInfo(@"[Volume Buttons] Volume button 2 up, already up"); |
|||
return; |
|||
} |
|||
SCLogGeneralInfo(@"[Volume Buttons] Volume button 2 up"); |
|||
[self _changePressingButton:^{ |
|||
_pressingButton2 = NO; |
|||
}]; |
|||
} |
|||
|
|||
- (void)_changePressingButton:(void (^)(void))change |
|||
{ |
|||
BOOL oldPressingVolumeButton = [self isPressingVolumeButton]; |
|||
change(); |
|||
BOOL newPressingVolumeButton = [self isPressingVolumeButton]; |
|||
|
|||
if (!oldPressingVolumeButton && newPressingVolumeButton) { |
|||
[_delegate volumeButtonHandlerDidBeginPressingVolumeButton:self]; |
|||
} else if (oldPressingVolumeButton && !newPressingVolumeButton) { |
|||
[_delegate volumeButtonHandlerDidEndPressingVolumeButton:self]; |
|||
if (_stopsHandlingWhenPressingEnds) { |
|||
[self stopHandlingVolumeButtonEvents]; |
|||
} |
|||
} |
|||
} |
|||
|
|||
@end |
@ -0,0 +1,109 @@ |
|||
// |
|||
// SCCaptureWorker.h |
|||
// Snapchat |
|||
// |
|||
// Created by Lin Jia on 10/19/17. |
|||
// |
|||
// |
|||
|
|||
#import "SCCaptureResource.h" |
|||
|
|||
#import <SCFoundation/SCQueuePerformer.h> |
|||
|
|||
#import <Foundation/Foundation.h> |
|||
|
|||
/* |
|||
In general, the function of SCCapturer is to use some resources (such as SCManagedCapturerListenerAnnouncer), to do |
|||
something (such as announce an event). |
|||
|
|||
SCCaptureWorker abstract away the "do something" part of SCCapturer. It has very little internal states/resources. |
|||
|
|||
SCCaptureWorker is introduced to be shared between CaptureV1 and CaptureV2, to minimize duplication code. |
|||
|
|||
*/ |
|||
|
|||
@interface SCCaptureWorker : NSObject |
|||
|
|||
+ (SCCaptureResource *)generateCaptureResource; |
|||
|
|||
+ (void)setupWithCaptureResource:(SCCaptureResource *)captureResource |
|||
devicePosition:(SCManagedCaptureDevicePosition)devicePosition; |
|||
|
|||
+ (void)setupCapturePreviewLayerController; |
|||
|
|||
+ (void)startRunningWithCaptureResource:(SCCaptureResource *)captureResource |
|||
token:(SCCapturerToken *)token |
|||
completionHandler:(dispatch_block_t)completionHandler; |
|||
|
|||
+ (BOOL)stopRunningWithCaptureResource:(SCCaptureResource *)captureResource |
|||
token:(SCCapturerToken *)token |
|||
completionHandler:(sc_managed_capturer_stop_running_completion_handler_t)completionHandler; |
|||
|
|||
+ (void)setupVideoPreviewLayer:(SCCaptureResource *)resource; |
|||
|
|||
+ (void)makeVideoPreviewLayer:(SCCaptureResource *)resource; |
|||
|
|||
+ (void)redoVideoPreviewLayer:(SCCaptureResource *)resource; |
|||
|
|||
+ (void)startStreaming:(SCCaptureResource *)resource; |
|||
|
|||
+ (void)setupLivenessConsistencyTimerIfForeground:(SCCaptureResource *)resource; |
|||
|
|||
+ (void)destroyLivenessConsistencyTimer:(SCCaptureResource *)resource; |
|||
|
|||
+ (void)softwareZoomWithDevice:(SCManagedCaptureDevice *)device resource:(SCCaptureResource *)resource; |
|||
|
|||
+ (void)captureStillImageWithCaptureResource:(SCCaptureResource *)captureResource |
|||
aspectRatio:(CGFloat)aspectRatio |
|||
captureSessionID:(NSString *)captureSessionID |
|||
shouldCaptureFromVideo:(BOOL)shouldCaptureFromVideo |
|||
completionHandler: |
|||
(sc_managed_capturer_capture_still_image_completion_handler_t)completionHandler |
|||
context:(NSString *)context; |
|||
|
|||
+ (void)startRecordingWithCaptureResource:(SCCaptureResource *)captureResource |
|||
outputSettings:(SCManagedVideoCapturerOutputSettings *)outputSettings |
|||
audioConfiguration:(SCAudioConfiguration *)configuration |
|||
maxDuration:(NSTimeInterval)maxDuration |
|||
fileURL:(NSURL *)fileURL |
|||
captureSessionID:(NSString *)captureSessionID |
|||
completionHandler:(sc_managed_capturer_start_recording_completion_handler_t)completionHandler; |
|||
|
|||
+ (void)stopRecordingWithCaptureResource:(SCCaptureResource *)captureResource; |
|||
|
|||
+ (void)cancelRecordingWithCaptureResource:(SCCaptureResource *)captureResource; |
|||
|
|||
+ (SCVideoCaptureSessionInfo)activeSession:(SCCaptureResource *)resource; |
|||
|
|||
+ (BOOL)canRunARSession:(SCCaptureResource *)resource; |
|||
|
|||
+ (void)turnARSessionOn:(SCCaptureResource *)resource; |
|||
|
|||
+ (void)turnARSessionOff:(SCCaptureResource *)resource; |
|||
|
|||
+ (void)clearARKitData:(SCCaptureResource *)resource; |
|||
|
|||
+ (void)updateLensesFieldOfViewTracking:(SCCaptureResource *)captureResource; |
|||
|
|||
+ (CMTime)firstWrittenAudioBufferDelay:(SCCaptureResource *)resource; |
|||
|
|||
+ (BOOL)audioQueueStarted:(SCCaptureResource *)resource; |
|||
|
|||
+ (BOOL)isLensApplied:(SCCaptureResource *)resource; |
|||
|
|||
+ (BOOL)isVideoMirrored:(SCCaptureResource *)resource; |
|||
|
|||
+ (BOOL)shouldCaptureImageFromVideoWithResource:(SCCaptureResource *)resource; |
|||
|
|||
+ (void)setPortraitModePointOfInterestAsynchronously:(CGPoint)pointOfInterest |
|||
completionHandler:(dispatch_block_t)completionHandler |
|||
resource:(SCCaptureResource *)resource; |
|||
|
|||
+ (void)prepareForRecordingWithAudioConfiguration:(SCAudioConfiguration *)configuration |
|||
resource:(SCCaptureResource *)resource; |
|||
|
|||
+ (void)stopScanWithCompletionHandler:(dispatch_block_t)completionHandler resource:(SCCaptureResource *)resource; |
|||
|
|||
+ (void)startScanWithScanConfiguration:(SCScanConfiguration *)configuration resource:(SCCaptureResource *)resource; |
|||
|
|||
@end |
1095
Worker/SCCaptureWorker.m
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
Write
Preview
Loading…
Cancel
Save
Reference in new issue