Caps-iOS/CapCollector/Capture/CameraView.swift
2018-08-16 11:18:27 +02:00

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()
}
}