-
Notifications
You must be signed in to change notification settings - Fork 92
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #51 from dokun1/minorRefactoring
Minor refactoring
- Loading branch information
Showing
42 changed files
with
2,073 additions
and
1,793 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,5 @@ | ||
disabled_rules: | ||
- line_length | ||
file_length: | ||
warning: 600 | ||
error: 1000 |
Large diffs are not rendered by default.
Oops, something went wrong.
68 changes: 68 additions & 0 deletions
68
Lumina/Lumina/Camera/Extensions/CameraActionsExtension.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
// | ||
// CameraActionsExtension.swift | ||
// Lumina | ||
// | ||
// Created by David Okun on 11/20/17. | ||
// Copyright © 2017 David Okun. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
import AVFoundation | ||
|
||
extension LuminaCamera { | ||
func getPreviewLayer() -> AVCaptureVideoPreviewLayer? { | ||
let previewLayer = AVCaptureVideoPreviewLayer(session: self.session) | ||
previewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill | ||
return previewLayer | ||
} | ||
|
||
func captureStillImage() { | ||
var settings = AVCapturePhotoSettings() | ||
if #available(iOS 11.0, *) { | ||
if self.photoOutput.availablePhotoCodecTypes.contains(.hevc) { | ||
settings = AVCapturePhotoSettings(format: [AVVideoCodecKey: AVVideoCodecType.hevc]) | ||
} | ||
} | ||
settings.isAutoStillImageStabilizationEnabled = true | ||
settings.flashMode = self.torchState ? .on : .off | ||
if self.captureLivePhotos { | ||
let fileName = NSTemporaryDirectory().appending("livePhoto" + Date().iso8601 + ".mov") | ||
settings.livePhotoMovieFileURL = URL(fileURLWithPath: fileName) | ||
} | ||
if self.captureHighResolutionImages { | ||
settings.isHighResolutionPhotoEnabled = true | ||
} | ||
if #available(iOS 11.0, *) { | ||
if self.captureDepthData && self.photoOutput.isDepthDataDeliverySupported { | ||
settings.isDepthDataDeliveryEnabled = true | ||
} | ||
} | ||
self.photoOutput.capturePhoto(with: settings, delegate: self) | ||
} | ||
|
||
func startVideoRecording() { | ||
if self.resolution == .photo { | ||
return // TODO: make this function throw an error | ||
} | ||
recordingVideo = true | ||
sessionQueue.async { | ||
if let connection = self.videoFileOutput.connection(with: AVMediaType.video), let videoConnection = self.videoDataOutput.connection(with: AVMediaType.video) { | ||
connection.videoOrientation = videoConnection.videoOrientation | ||
connection.isVideoMirrored = self.position == .front ? true : false | ||
if connection.isVideoStabilizationSupported { | ||
connection.preferredVideoStabilizationMode = .cinematic | ||
} | ||
self.session.commitConfiguration() | ||
} | ||
let fileName = NSTemporaryDirectory().appending(Date().iso8601 + ".mov") | ||
self.videoFileOutput.startRecording(to: URL(fileURLWithPath: fileName), recordingDelegate: self) | ||
} | ||
} | ||
|
||
func stopVideoRecording() { | ||
recordingVideo = false | ||
sessionQueue.async { | ||
self.videoFileOutput.stopRecording() | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// | ||
// CameraUtilExtension.swift | ||
// Lumina | ||
// | ||
// Created by David Okun on 11/20/17. | ||
// Copyright © 2017 David Okun. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
extension Formatter { | ||
static let iso8601: DateFormatter = { | ||
let formatter = DateFormatter() | ||
formatter.calendar = Calendar(identifier: .iso8601) | ||
formatter.locale = Locale(identifier: "en_US_POSIX") | ||
formatter.timeZone = TimeZone(secondsFromGMT: 0) | ||
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX" | ||
return formatter | ||
}() | ||
} | ||
extension Date { | ||
var iso8601: String { | ||
return Formatter.iso8601.string(from: self) | ||
} | ||
} |
122 changes: 122 additions & 0 deletions
122
Lumina/Lumina/Camera/Extensions/CaptureDeviceHandlerExtension.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
// | ||
// CaptureDeviceHandlerExtension.swift | ||
// Lumina | ||
// | ||
// Created by David Okun on 11/20/17. | ||
// Copyright © 2017 David Okun. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
import AVFoundation | ||
|
||
extension LuminaCamera { | ||
func getNewVideoInputDevice() -> AVCaptureDeviceInput? { | ||
do { | ||
guard let device = getDevice(with: self.position == .front ? AVCaptureDevice.Position.front : AVCaptureDevice.Position.back) else { | ||
print("could not find valid AVCaptureDevice") | ||
return nil | ||
} | ||
let input = try AVCaptureDeviceInput(device: device) | ||
return input | ||
} catch { | ||
return nil | ||
} | ||
} | ||
|
||
func getNewAudioInputDevice() -> AVCaptureDeviceInput? { | ||
do { | ||
guard let device = AVCaptureDevice.default(for: AVMediaType.audio) else { | ||
return nil | ||
} | ||
let deviceInput = try AVCaptureDeviceInput(device: device) | ||
return deviceInput | ||
} catch { | ||
return nil | ||
} | ||
} | ||
|
||
func purgeAudioDevices() { | ||
for oldInput in self.session.inputs where oldInput == self.audioInput { | ||
self.session.removeInput(oldInput) | ||
} | ||
} | ||
|
||
func purgeVideoDevices() { | ||
for oldInput in self.session.inputs where oldInput == self.videoInput { | ||
self.session.removeInput(oldInput) | ||
} | ||
for oldOutput in self.session.outputs { | ||
if oldOutput == self.videoDataOutput || oldOutput == self.photoOutput || oldOutput == self.metadataOutput || oldOutput == self.videoFileOutput { | ||
self.session.removeOutput(oldOutput) | ||
} | ||
if let dataOutput = oldOutput as? AVCaptureVideoDataOutput { | ||
self.session.removeOutput(dataOutput) | ||
} | ||
if #available(iOS 11.0, *) { | ||
if let depthOutput = oldOutput as? AVCaptureDepthDataOutput { | ||
self.session.removeOutput(depthOutput) | ||
} | ||
} | ||
} | ||
} | ||
|
||
func getDevice(with position: AVCaptureDevice.Position) -> AVCaptureDevice? { | ||
#if swift(>=4.0.2) | ||
if #available(iOS 11.1, *), position == .front { | ||
if let device = AVCaptureDevice.default(.builtInTrueDepthCamera, for: .video, position: .front) { | ||
return device | ||
} | ||
} | ||
#endif | ||
if #available(iOS 10.2, *), let device = AVCaptureDevice.default(.builtInDualCamera, for: .video, position: position) { | ||
return device | ||
} else if let device = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: position) { | ||
return device | ||
} | ||
return nil | ||
} | ||
|
||
func configureFrameRate() { | ||
guard let device = self.currentCaptureDevice else { | ||
return | ||
} | ||
for vFormat in device.formats { | ||
let dimensions = CMVideoFormatDescriptionGetDimensions(vFormat.formatDescription) | ||
let ranges = vFormat.videoSupportedFrameRateRanges as [AVFrameRateRange] | ||
guard let frameRate = ranges.first else { | ||
continue | ||
} | ||
if frameRate.maxFrameRate >= Float64(self.frameRate) && | ||
frameRate.minFrameRate <= Float64(self.frameRate) && | ||
self.resolution.getDimensions().width == dimensions.width && | ||
self.resolution.getDimensions().height == dimensions.height && | ||
CMFormatDescriptionGetMediaSubType(vFormat.formatDescription) == 875704422 { // meant for full range 420f | ||
do { | ||
try device.lockForConfiguration() | ||
device.activeFormat = vFormat as AVCaptureDevice.Format | ||
device.activeVideoMinFrameDuration = CMTimeMake(1, Int32(self.frameRate)) | ||
device.activeVideoMaxFrameDuration = CMTimeMake(1, Int32(self.frameRate)) | ||
device.unlockForConfiguration() | ||
break | ||
} catch { | ||
continue | ||
} | ||
} | ||
} | ||
} | ||
|
||
func updateZoom() { | ||
guard let input = self.videoInput else { | ||
return | ||
} | ||
let device = input.device | ||
do { | ||
try device.lockForConfiguration() | ||
let newZoomScale = min(maxZoomScale, max(Float(1.0), min(currentZoomScale, Float(device.activeFormat.videoMaxZoomFactor)))) | ||
device.videoZoomFactor = CGFloat(newZoomScale) | ||
device.unlockForConfiguration() | ||
} catch { | ||
device.unlockForConfiguration() | ||
} | ||
} | ||
} |
35 changes: 35 additions & 0 deletions
35
Lumina/Lumina/Camera/Extensions/CapturePhotoExtension.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// | ||
// CapturePhotoExtension.swift | ||
// Lumina | ||
// | ||
// Created by David Okun on 11/20/17. | ||
// Copyright © 2017 David Okun. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
import AVFoundation | ||
|
||
@available (iOS 11.0, *) | ||
extension AVCapturePhoto { | ||
func normalizedImage(forCameraPosition position: CameraPosition) -> UIImage? { | ||
guard let cgImage = self.cgImageRepresentation() else { | ||
return nil | ||
} | ||
return UIImage(cgImage: cgImage.takeUnretainedValue(), scale: 1.0, orientation: getImageOrientation(forCamera: position)) | ||
} | ||
|
||
private func getImageOrientation(forCamera: CameraPosition) -> UIImageOrientation { | ||
switch UIApplication.shared.statusBarOrientation { | ||
case .landscapeLeft: | ||
return forCamera == .back ? .down : .upMirrored | ||
case .landscapeRight: | ||
return forCamera == .back ? .up : .downMirrored | ||
case .portraitUpsideDown: | ||
return forCamera == .back ? .left : .rightMirrored | ||
case .portrait: | ||
return forCamera == .back ? .right : .leftMirrored | ||
case .unknown: | ||
return forCamera == .back ? .right : .leftMirrored | ||
} | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
Lumina/Lumina/Camera/Extensions/Delegates/DepthDataExtension.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
// | ||
// DepthDataExtension.swift | ||
// Lumina | ||
// | ||
// Created by David Okun on 11/20/17. | ||
// Copyright © 2017 David Okun. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
import AVFoundation | ||
|
||
@available(iOS 11.0, *) | ||
extension LuminaCamera: AVCaptureDepthDataOutputDelegate { | ||
func depthDataOutput(_ output: AVCaptureDepthDataOutput, didOutput depthData: AVDepthData, timestamp: CMTime, connection: AVCaptureConnection) { | ||
DispatchQueue.main.async { | ||
self.delegate?.depthDataCaptured(camera: self, depthData: depthData) | ||
} | ||
} | ||
|
||
func depthDataOutput(_ output: AVCaptureDepthDataOutput, didDrop depthData: AVDepthData, timestamp: CMTime, connection: AVCaptureConnection, reason: AVCaptureOutput.DataDroppedReason) { | ||
// place to handle dropped AVDepthData if we need it | ||
} | ||
} |
51 changes: 51 additions & 0 deletions
51
Lumina/Lumina/Camera/Extensions/Delegates/FileRecordingExtension.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
// | ||
// LuminaCamera+FileOutputRecordingDelegate.swift | ||
// Lumina | ||
// | ||
// Created by David Okun on 11/20/17. | ||
// Copyright © 2017 David Okun. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
import AVFoundation | ||
|
||
extension LuminaCamera: AVCaptureFileOutputRecordingDelegate { | ||
func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) { | ||
DispatchQueue.main.async { | ||
if error == nil, let delegate = self.delegate { | ||
delegate.videoRecordingCaptured(camera: self, videoURL: outputFileURL) | ||
} | ||
} | ||
} | ||
|
||
func photoOutput(_ output: AVCapturePhotoOutput, willBeginCaptureFor resolvedSettings: AVCaptureResolvedPhotoSettings) { | ||
if self.captureLivePhotos { | ||
self.delegate?.cameraBeganTakingLivePhoto(camera: self) | ||
} | ||
} | ||
|
||
func photoOutput(_ output: AVCapturePhotoOutput, didFinishRecordingLivePhotoMovieForEventualFileAt outputFileURL: URL, resolvedSettings: AVCaptureResolvedPhotoSettings) { | ||
if self.captureLivePhotos { | ||
self.delegate?.cameraFinishedTakingLivePhoto(camera: self) | ||
} | ||
} | ||
|
||
//swiftlint:disable function_parameter_count | ||
func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingLivePhotoToMovieFileAt outputFileURL: URL, duration: CMTime, photoDisplayTime: CMTime, resolvedSettings: AVCaptureResolvedPhotoSettings, error: Error?) { | ||
photoCollectionQueue.sync { | ||
if self.currentPhotoCollection == nil { | ||
var collection = LuminaPhotoCapture() | ||
collection.camera = self | ||
collection.livePhotoURL = outputFileURL | ||
self.currentPhotoCollection = collection | ||
} else { | ||
guard var collection = self.currentPhotoCollection else { | ||
return | ||
} | ||
collection.camera = self | ||
collection.livePhotoURL = outputFileURL | ||
self.currentPhotoCollection = collection | ||
} | ||
} | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
Lumina/Lumina/Camera/Extensions/Delegates/MetadataOutputDelegateExtension.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// | ||
// MetadataOutputDelegateExtension.swift | ||
// Lumina | ||
// | ||
// Created by David Okun on 11/20/17. | ||
// Copyright © 2017 David Okun. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
import AVFoundation | ||
|
||
extension LuminaCamera: AVCaptureMetadataOutputObjectsDelegate { | ||
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) { | ||
guard case self.trackMetadata = true else { | ||
return | ||
} | ||
DispatchQueue.main.async { | ||
self.delegate?.detected(camera: self, metadata: metadataObjects) | ||
} | ||
} | ||
} |
Oops, something went wrong.