2014 snapchat source code
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
// // SCManagedCaptureDeviceLinearInterpolationZoomHandler.m // Snapchat // // Created by Joe Qiao on 03/01/2018. //
#import "SCManagedCaptureDeviceLinearInterpolationZoomHandler.h"
#import "SCCameraTweaks.h" #import "SCManagedCaptureDeviceDefaultZoomHandler_Private.h" #import "SCManagedCapturerLogging.h"
#import <SCFoundation/SCAssertWrapper.h> #import <SCFoundation/SCMathUtils.h>
@interface SCManagedCaptureDeviceLinearInterpolationZoomHandler ()
@property (nonatomic, strong) CADisplayLink *displayLink; @property (nonatomic, assign) double timestamp; @property (nonatomic, assign) float targetFactor; @property (nonatomic, assign) float intermediateFactor; @property (nonatomic, assign) int trend; @property (nonatomic, assign) float stepLength;
@end
@implementation SCManagedCaptureDeviceLinearInterpolationZoomHandler
- (instancetype)initWithCaptureResource:(SCCaptureResource *)captureResource { self = [super initWithCaptureResource:captureResource]; if (self) { _timestamp = -1.0; _targetFactor = 1.0; _intermediateFactor = _targetFactor; _trend = 1; _stepLength = 0.0; }
return self; }
- (void)dealloc { [self _invalidate]; }
- (void)setZoomFactor:(CGFloat)zoomFactor forDevice:(SCManagedCaptureDevice *)device immediately:(BOOL)immediately { if (self.currentDevice != device) { if (_displayLink) { // if device changed, interupt smoothing process // and reset to target zoom factor immediately [self _resetToZoomFactor:_targetFactor]; } self.currentDevice = device; immediately = YES; }
if (immediately) { [self _resetToZoomFactor:zoomFactor]; } else { [self _addTargetZoomFactor:zoomFactor]; } }
#pragma mark - Configurable // smoothen if the update time interval is greater than the threshold - (double)_thresholdTimeIntervalToSmoothen { return SCCameraTweaksSmoothZoomThresholdTime(); }
- (double)_thresholdFactorDiffToSmoothen { return SCCameraTweaksSmoothZoomThresholdFactor(); }
- (int)_intermediateFactorFramesPerSecond { return SCCameraTweaksSmoothZoomIntermediateFramesPerSecond(); }
- (double)_delayTolerantTime { return SCCameraTweaksSmoothZoomDelayTolerantTime(); }
// minimum step length between two intermediate factors, // the greater the better as long as could provide a 'smooth experience' during smoothing process - (float)_minimumStepLength { return SCCameraTweaksSmoothZoomMinStepLength(); }
#pragma mark - Private methods - (void)_addTargetZoomFactor:(float)factor { SCAssertMainThread();
SCLogCapturerInfo(@"Smooth Zoom - [1] t=%f zf=%f", CACurrentMediaTime(), factor); if (SCFloatEqual(factor, _targetFactor)) { return; } _targetFactor = factor;
float diff = _targetFactor - _intermediateFactor; if ([self _isDuringSmoothingProcess]) { // during smoothing, only update data [self _updateDataWithDiff:diff]; } else { double curTimestamp = CACurrentMediaTime(); if (!SCFloatEqual(_timestamp, -1.0) && (curTimestamp - _timestamp) > [self _thresholdTimeIntervalToSmoothen] && ABS(diff) > [self _thresholdFactorDiffToSmoothen]) { // need smoothing [self _updateDataWithDiff:diff]; if ([self _nextStep]) { // use timer to interpolate intermediate factors to avoid sharp jump _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(_nextStep)]; _displayLink.preferredFramesPerSecond = [self _intermediateFactorFramesPerSecond]; [_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; } } else { _timestamp = curTimestamp; _intermediateFactor = factor;
SCLogCapturerInfo(@"Smooth Zoom - [2] t=%f zf=%f", CACurrentMediaTime(), _intermediateFactor); [self _setZoomFactor:_intermediateFactor forManagedCaptureDevice:self.currentDevice]; } } }
- (void)_resetToZoomFactor:(float)factor { [self _invalidate];
_timestamp = -1.0; _targetFactor = factor; _intermediateFactor = _targetFactor;
[self _setZoomFactor:_intermediateFactor forManagedCaptureDevice:self.currentDevice]; }
- (BOOL)_nextStep { _timestamp = CACurrentMediaTime(); _intermediateFactor += (_trend * _stepLength);
BOOL hasNext = YES; if (_trend < 0.0) { _intermediateFactor = MAX(_intermediateFactor, _targetFactor); } else { _intermediateFactor = MIN(_intermediateFactor, _targetFactor); }
SCLogCapturerInfo(@"Smooth Zoom - [3] t=%f zf=%f", CACurrentMediaTime(), _intermediateFactor); [self _setZoomFactor:_intermediateFactor forManagedCaptureDevice:self.currentDevice];
if (SCFloatEqual(_intermediateFactor, _targetFactor)) { // finish smoothening [self _invalidate]; hasNext = NO; }
return hasNext; }
- (void)_invalidate { [_displayLink invalidate]; _displayLink = nil; _trend = 1; _stepLength = 0.0; }
- (void)_updateDataWithDiff:(CGFloat)diff { _trend = diff < 0.0 ? -1 : 1; _stepLength = MAX(_stepLength, MAX([self _minimumStepLength], ABS(diff) / ([self _delayTolerantTime] * [self _intermediateFactorFramesPerSecond]))); }
- (BOOL)_isDuringSmoothingProcess { return (_displayLink ? YES : NO); }
@end
|