175 lines
6.3 KiB
Mathematica
175 lines
6.3 KiB
Mathematica
|
|
|
||
|
|
// Created by Tencent on 2023/06/09.
|
||
|
|
// Copyright © 2023 Tencent. All rights reserved.
|
||
|
|
|
||
|
|
#import "TUICameraManager.h"
|
||
|
|
|
||
|
|
@implementation TUICameraManager
|
||
|
|
|
||
|
|
#pragma mark - - Switch Camera
|
||
|
|
- (AVCaptureDeviceInput *)switchCamera:(AVCaptureSession *)session old:(AVCaptureDeviceInput *)oldinput new:(AVCaptureDeviceInput *)newinput {
|
||
|
|
[session beginConfiguration];
|
||
|
|
[session removeInput:oldinput];
|
||
|
|
if ([session canAddInput:newinput]) {
|
||
|
|
[session addInput:newinput];
|
||
|
|
[session commitConfiguration];
|
||
|
|
return newinput;
|
||
|
|
} else {
|
||
|
|
[session addInput:oldinput];
|
||
|
|
[session commitConfiguration];
|
||
|
|
return oldinput;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#pragma mark - - Zoom
|
||
|
|
- (id)zoom:(AVCaptureDevice *)device factor:(CGFloat)factor {
|
||
|
|
if (device.activeFormat.videoMaxZoomFactor > factor && factor >= 1.0) {
|
||
|
|
NSError *error;
|
||
|
|
if ([device lockForConfiguration:&error]) {
|
||
|
|
[device rampToVideoZoomFactor:factor withRate:4.0];
|
||
|
|
[device unlockForConfiguration];
|
||
|
|
}
|
||
|
|
return error;
|
||
|
|
}
|
||
|
|
return [self error:@"Unsupported zoom factor" code:2000];
|
||
|
|
}
|
||
|
|
|
||
|
|
#pragma mark - - Focus
|
||
|
|
- (id)focus:(AVCaptureDevice *)device point:(CGPoint)point {
|
||
|
|
BOOL supported = [device isFocusPointOfInterestSupported] && [device isFocusModeSupported:AVCaptureFocusModeAutoFocus];
|
||
|
|
if (supported) {
|
||
|
|
NSError *error;
|
||
|
|
if ([device lockForConfiguration:&error]) {
|
||
|
|
device.focusPointOfInterest = point;
|
||
|
|
device.focusMode = AVCaptureFocusModeAutoFocus;
|
||
|
|
[device unlockForConfiguration];
|
||
|
|
}
|
||
|
|
return error;
|
||
|
|
}
|
||
|
|
return [self error:@"Device does not support focus" code:2001];
|
||
|
|
}
|
||
|
|
|
||
|
|
#pragma mark - - Expose
|
||
|
|
static const NSString *CameraAdjustingExposureContext;
|
||
|
|
- (id)expose:(AVCaptureDevice *)device point:(CGPoint)point {
|
||
|
|
BOOL supported = [device isExposurePointOfInterestSupported] && [device isExposureModeSupported:AVCaptureExposureModeContinuousAutoExposure];
|
||
|
|
if (supported) {
|
||
|
|
NSError *error;
|
||
|
|
if ([device lockForConfiguration:&error]) {
|
||
|
|
device.exposurePointOfInterest = point;
|
||
|
|
device.exposureMode = AVCaptureExposureModeContinuousAutoExposure;
|
||
|
|
if ([device isExposureModeSupported:AVCaptureExposureModeLocked]) {
|
||
|
|
[device addObserver:self forKeyPath:@"adjustingExposure" options:NSKeyValueObservingOptionNew context:&CameraAdjustingExposureContext];
|
||
|
|
}
|
||
|
|
[device unlockForConfiguration];
|
||
|
|
}
|
||
|
|
return error;
|
||
|
|
}
|
||
|
|
return [self error:@"Device does not support exposure" code:2002];
|
||
|
|
}
|
||
|
|
|
||
|
|
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
|
||
|
|
if (context == &CameraAdjustingExposureContext) {
|
||
|
|
AVCaptureDevice *device = (AVCaptureDevice *)object;
|
||
|
|
if (!device.isAdjustingExposure && [device isExposureModeSupported:AVCaptureExposureModeLocked]) {
|
||
|
|
[object removeObserver:self forKeyPath:@"adjustingExposure" context:&CameraAdjustingExposureContext];
|
||
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||
|
|
NSError *error;
|
||
|
|
if ([device lockForConfiguration:&error]) {
|
||
|
|
device.exposureMode = AVCaptureExposureModeLocked;
|
||
|
|
[device unlockForConfiguration];
|
||
|
|
} else {
|
||
|
|
NSLog(@"%@", error);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#pragma mark - - Auto focus, exposure
|
||
|
|
- (id)resetFocusAndExposure:(AVCaptureDevice *)device {
|
||
|
|
AVCaptureFocusMode focusMode = AVCaptureFocusModeContinuousAutoFocus;
|
||
|
|
AVCaptureExposureMode exposureMode = AVCaptureExposureModeContinuousAutoExposure;
|
||
|
|
BOOL canResetFocus = [device isFocusPointOfInterestSupported] && [device isFocusModeSupported:focusMode];
|
||
|
|
BOOL canResetExposure = [device isExposurePointOfInterestSupported] && [device isExposureModeSupported:exposureMode];
|
||
|
|
CGPoint centerPoint = CGPointMake(0.5f, 0.5f);
|
||
|
|
NSError *error;
|
||
|
|
if ([device lockForConfiguration:&error]) {
|
||
|
|
if (canResetFocus) {
|
||
|
|
device.focusMode = focusMode;
|
||
|
|
device.focusPointOfInterest = centerPoint;
|
||
|
|
}
|
||
|
|
if (canResetExposure) {
|
||
|
|
device.exposureMode = exposureMode;
|
||
|
|
device.exposurePointOfInterest = centerPoint;
|
||
|
|
}
|
||
|
|
[device unlockForConfiguration];
|
||
|
|
}
|
||
|
|
return error;
|
||
|
|
}
|
||
|
|
|
||
|
|
#pragma mark - - Flash
|
||
|
|
- (AVCaptureFlashMode)flashMode:(AVCaptureDevice *)device {
|
||
|
|
return [device flashMode];
|
||
|
|
}
|
||
|
|
|
||
|
|
- (id)changeFlash:(AVCaptureDevice *)device mode:(AVCaptureFlashMode)mode {
|
||
|
|
if (![device hasFlash]) {
|
||
|
|
return [self error:@"Flash is not supported" code:2003];
|
||
|
|
}
|
||
|
|
if ([self torchMode:device] == AVCaptureTorchModeOn) {
|
||
|
|
[self setTorch:device model:AVCaptureTorchModeOff];
|
||
|
|
}
|
||
|
|
return [self setFlash:device mode:mode];
|
||
|
|
}
|
||
|
|
|
||
|
|
- (id)setFlash:(AVCaptureDevice *)device mode:(AVCaptureFlashMode)mode {
|
||
|
|
if ([device isFlashModeSupported:mode]) {
|
||
|
|
NSError *error;
|
||
|
|
if ([device lockForConfiguration:&error]) {
|
||
|
|
device.flashMode = mode;
|
||
|
|
[device unlockForConfiguration];
|
||
|
|
}
|
||
|
|
return error;
|
||
|
|
}
|
||
|
|
return [self error:@"Flash is not supported" code:2003];
|
||
|
|
}
|
||
|
|
|
||
|
|
#pragma mark - - Flashlight
|
||
|
|
- (AVCaptureTorchMode)torchMode:(AVCaptureDevice *)device {
|
||
|
|
return [device torchMode];
|
||
|
|
}
|
||
|
|
|
||
|
|
- (id)changeTorch:(AVCaptureDevice *)device model:(AVCaptureTorchMode)mode {
|
||
|
|
if (![device hasTorch]) {
|
||
|
|
return [self error:@"Flashlight not supported" code:2004];
|
||
|
|
}
|
||
|
|
if ([self flashMode:device] == AVCaptureFlashModeOn) {
|
||
|
|
[self setFlash:device mode:AVCaptureFlashModeOff];
|
||
|
|
}
|
||
|
|
return [self setTorch:device model:mode];
|
||
|
|
}
|
||
|
|
|
||
|
|
- (id)setTorch:(AVCaptureDevice *)device model:(AVCaptureTorchMode)mode {
|
||
|
|
if ([device isTorchModeSupported:mode]) {
|
||
|
|
NSError *error;
|
||
|
|
if ([device lockForConfiguration:&error]) {
|
||
|
|
device.torchMode = mode;
|
||
|
|
[device unlockForConfiguration];
|
||
|
|
}
|
||
|
|
return error;
|
||
|
|
}
|
||
|
|
return [self error:@"Flashlight not supported" code:2004];
|
||
|
|
}
|
||
|
|
|
||
|
|
#pragma mark -
|
||
|
|
- (NSError *)error:(NSString *)text code:(NSInteger)code {
|
||
|
|
NSDictionary *desc = @{NSLocalizedDescriptionKey : text};
|
||
|
|
NSError *error = [NSError errorWithDomain:@"com.tui.camera" code:code userInfo:desc];
|
||
|
|
return error;
|
||
|
|
}
|
||
|
|
|
||
|
|
@end
|