// // SCManagedCaptureDeviceDefaultZoomHandler.m // Snapchat // // Created by Yu-Kuan Lai on 4/12/17. // Copyright © 2017 Snapchat, Inc. All rights reserved. // #import "SCManagedCaptureDeviceDefaultZoomHandler_Private.h" #import "SCCaptureResource.h" #import "SCManagedCaptureDevice+SCManagedCapturer.h" #import "SCManagedCapturer.h" #import "SCManagedCapturerLogging.h" #import "SCManagedCapturerStateBuilder.h" #import "SCMetalUtils.h" #import #import #import #import @implementation SCManagedCaptureDeviceDefaultZoomHandler - (instancetype)initWithCaptureResource:(SCCaptureResource *)captureResource { self = [super init]; if (self) { _captureResource = captureResource; } return self; } - (void)setZoomFactor:(CGFloat)zoomFactor forDevice:(SCManagedCaptureDevice *)device immediately:(BOOL)immediately { [self _setZoomFactor:zoomFactor forManagedCaptureDevice:device]; } - (void)softwareZoomWithDevice:(SCManagedCaptureDevice *)device { SCTraceODPCompatibleStart(2); SCAssert([_captureResource.queuePerformer isCurrentPerformer] || [[SCQueuePerformer mainQueuePerformer] isCurrentPerformer], @""); SCAssert(device.softwareZoom, @"Only do software zoom for software zoom device"); SC_GUARD_ELSE_RETURN(!SCDeviceSupportsMetal()); float zoomFactor = device.zoomFactor; SCLogCapturerInfo(@"Adjusting software zoom factor to: %f", zoomFactor); AVCaptureVideoPreviewLayer *videoPreviewLayer = _captureResource.videoPreviewLayer; [[SCQueuePerformer mainQueuePerformer] perform:^{ [CATransaction begin]; [CATransaction setDisableActions:YES]; // I end up need to change its superlayer transform to get the zoom effect videoPreviewLayer.superlayer.affineTransform = CGAffineTransformMakeScale(zoomFactor, zoomFactor); [CATransaction commit]; }]; } - (void)_setZoomFactor:(CGFloat)zoomFactor forManagedCaptureDevice:(SCManagedCaptureDevice *)device { SCTraceODPCompatibleStart(2); [_captureResource.queuePerformer perform:^{ SCTraceStart(); if (device) { SCLogCapturerInfo(@"Set zoom factor: %f -> %f", _captureResource.state.zoomFactor, zoomFactor); [device setZoomFactor:zoomFactor]; BOOL zoomFactorChanged = NO; // If the device is our current device, send the notification, update the // state. if (device.isConnected && device == _captureResource.device) { if (device.softwareZoom) { [self softwareZoomWithDevice:device]; } _captureResource.state = [[[SCManagedCapturerStateBuilder withManagedCapturerState:_captureResource.state] setZoomFactor:zoomFactor] build]; zoomFactorChanged = YES; } SCManagedCapturerState *state = [_captureResource.state copy]; runOnMainThreadAsynchronously(^{ if (zoomFactorChanged) { [_captureResource.announcer managedCapturer:[SCManagedCapturer sharedInstance] didChangeState:state]; [_captureResource.announcer managedCapturer:[SCManagedCapturer sharedInstance] didChangeZoomFactor:state]; } }); } }]; } @end