Add files via upload
This commit is contained in:
parent
c69a609542
commit
53e8a5f244
|
@ -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
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue