react-native-vision-camera/package/ios/Core/CameraSession+Focus.swift

83 lines
2.4 KiB
Swift
Raw Normal View History

//
// CameraSession+Focus.swift
// VisionCamera
//
// Created by Marc Rousavy on 11.10.23.
// Copyright © 2023 mrousavy. All rights reserved.
//
import AVFoundation
import Foundation
extension CameraSession {
/**
Focuses the Camera to the specified point. The point must be in the Camera coordinate system, so {0...1} on both axis.
*/
func focus(point: CGPoint) throws {
guard let device = videoDeviceInput?.device else {
throw CameraError.session(SessionError.cameraNotReady)
}
if !device.isFocusPointOfInterestSupported {
throw CameraError.device(DeviceError.focusNotSupported)
}
do {
try device.lockForConfiguration()
defer {
device.unlockForConfiguration()
}
// Set Focus
if device.isFocusPointOfInterestSupported {
device.focusPointOfInterest = point
device.focusMode = .autoFocus
}
// Set Exposure
if device.isExposurePointOfInterestSupported {
device.exposurePointOfInterest = point
device.exposureMode = .autoExpose
}
// Remove any existing listeners
NotificationCenter.default.removeObserver(self,
name: NSNotification.Name.AVCaptureDeviceSubjectAreaDidChange,
object: nil)
// Listen for focus completion
device.isSubjectAreaChangeMonitoringEnabled = true
NotificationCenter.default.addObserver(self,
selector: #selector(subjectAreaDidChange),
name: NSNotification.Name.AVCaptureDeviceSubjectAreaDidChange,
object: nil)
} catch {
throw CameraError.device(DeviceError.configureError)
}
}
@objc
func subjectAreaDidChange(notification _: NSNotification) {
guard let device = videoDeviceInput?.device else {
return
}
try? device.lockForConfiguration()
defer {
device.unlockForConfiguration()
}
// Reset Focus to continuous/auto
if device.isFocusPointOfInterestSupported {
device.focusMode = .continuousAutoFocus
}
// Reset Exposure to continuous/auto
if device.isExposurePointOfInterestSupported {
device.exposureMode = .continuousAutoExposure
}
// Disable listeners
device.isSubjectAreaChangeMonitoringEnabled = false
}
}