198 lines
5.5 KiB
Swift
198 lines
5.5 KiB
Swift
//
|
|
// CameraView.swift
|
|
// CapFinder
|
|
//
|
|
// Created by User on 07.02.18.
|
|
// Copyright © 2018 User. All rights reserved.
|
|
//
|
|
|
|
import UIKit
|
|
import AVFoundation
|
|
|
|
class CameraView: UIView {
|
|
|
|
// MARK: UIView overrides
|
|
|
|
/**
|
|
Override for AVCapture
|
|
*/
|
|
override class var layerClass: AnyClass {
|
|
return AVCaptureVideoPreviewLayer.self
|
|
}
|
|
|
|
// MARK: Enums
|
|
|
|
private enum SessionSetupResult {
|
|
case success
|
|
case notAuthorized
|
|
case configurationFailed
|
|
}
|
|
|
|
// MARK: Variables
|
|
|
|
var delegate: PhotoCaptureHandlerDelegate? {
|
|
get {
|
|
return photoCaptureProcessor.delegate
|
|
}
|
|
set {
|
|
photoCaptureProcessor.delegate = newValue
|
|
}
|
|
}
|
|
|
|
private let session = AVCaptureSession()
|
|
|
|
private var isSessionRunning = false
|
|
|
|
/// Communicate with the session and other session objects on this queue.
|
|
private let sessionQueue = DispatchQueue(label: "session queue")
|
|
|
|
private var setupResult: SessionSetupResult = .success
|
|
|
|
var videoDeviceInput: AVCaptureDeviceInput!
|
|
|
|
private let photoOutput = AVCapturePhotoOutput()
|
|
|
|
private let photoCaptureProcessor = PhotoCaptureHandler()
|
|
|
|
var videoPreviewLayer: AVCaptureVideoPreviewLayer {
|
|
return layer as! AVCaptureVideoPreviewLayer
|
|
}
|
|
|
|
// MARK: Life cycle
|
|
|
|
func configure() {
|
|
videoPreviewLayer.session = session
|
|
|
|
checkPermission()
|
|
|
|
// Setup the capture session.
|
|
sessionQueue.async {
|
|
self.configureSession()
|
|
}
|
|
}
|
|
|
|
func launch(completionHandler: @escaping (Bool, String?) -> ()) {
|
|
sessionQueue.async {
|
|
switch self.setupResult {
|
|
case .success:
|
|
// Only setup observers and start the session running if setup succeeded.
|
|
self.session.startRunning()
|
|
self.isSessionRunning = self.session.isRunning
|
|
|
|
case .notAuthorized:
|
|
DispatchQueue.main.async {
|
|
completionHandler(false, "No camera access")
|
|
}
|
|
|
|
case .configurationFailed:
|
|
DispatchQueue.main.async {
|
|
completionHandler(false, "Camera error")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func complete() {
|
|
sessionQueue.async {
|
|
if self.setupResult == .success {
|
|
self.session.stopRunning()
|
|
self.isSessionRunning = self.session.isRunning
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: Photo Capture
|
|
|
|
func capture() {
|
|
sessionQueue.async {
|
|
self.photoOutput.capturePhoto(
|
|
with: self.photoCaptureProcessor.photoSettings,
|
|
delegate: self.photoCaptureProcessor)
|
|
}
|
|
}
|
|
|
|
// MARK: Camera permissions
|
|
|
|
private func checkPermission() {
|
|
switch AVCaptureDevice.authorizationStatus(for: .video) {
|
|
case .authorized: break
|
|
case .notDetermined:
|
|
sessionQueue.suspend()
|
|
AVCaptureDevice.requestAccess(for: .video, completionHandler: { granted in
|
|
if !granted {
|
|
self.setupResult = .notAuthorized
|
|
}
|
|
self.sessionQueue.resume()
|
|
})
|
|
|
|
default:
|
|
// The user has previously denied access.
|
|
setupResult = .notAuthorized
|
|
}
|
|
}
|
|
|
|
// Call this on the session queue.
|
|
private func configureSession() {
|
|
if setupResult != .success {
|
|
return
|
|
}
|
|
|
|
session.beginConfiguration()
|
|
|
|
/*
|
|
We do not create an AVCaptureMovieFileOutput when setting up the session because the
|
|
AVCaptureMovieFileOutput does not support movie recording with AVCaptureSession.Preset.Photo.
|
|
*/
|
|
session.sessionPreset = .photo
|
|
|
|
// Add video input.
|
|
do {
|
|
guard let backCameraDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back) else {
|
|
print("No camera on device")
|
|
setupResult = .configurationFailed
|
|
session.commitConfiguration()
|
|
return
|
|
}
|
|
|
|
let videoDeviceInput = try AVCaptureDeviceInput(device: backCameraDevice)
|
|
|
|
if session.canAddInput(videoDeviceInput) {
|
|
session.addInput(videoDeviceInput)
|
|
self.videoDeviceInput = videoDeviceInput
|
|
|
|
DispatchQueue.main.async {
|
|
self.videoPreviewLayer.connection?.videoOrientation = .portrait
|
|
}
|
|
} else {
|
|
print("Could not add video device input to the session")
|
|
setupResult = .configurationFailed
|
|
session.commitConfiguration()
|
|
return
|
|
}
|
|
} catch {
|
|
print("Could not create video device input: \(error)")
|
|
setupResult = .configurationFailed
|
|
session.commitConfiguration()
|
|
return
|
|
}
|
|
|
|
// Add photo output.
|
|
if session.canAddOutput(photoOutput) {
|
|
session.addOutput(photoOutput)
|
|
|
|
photoOutput.isHighResolutionCaptureEnabled = true
|
|
photoOutput.isDepthDataDeliveryEnabled = false
|
|
photoOutput.isDualCameraDualPhotoDeliveryEnabled = false
|
|
photoOutput.isLivePhotoCaptureEnabled = false
|
|
} else {
|
|
print("Could not add photo output to the session")
|
|
setupResult = .configurationFailed
|
|
session.commitConfiguration()
|
|
return
|
|
}
|
|
|
|
session.commitConfiguration()
|
|
}
|
|
}
|
|
|