diff --git a/Source/Helpers/Extensions/AVCaptureDevice+Extensions.swift b/Source/Helpers/Extensions/AVCaptureDevice+Extensions.swift index 35eebaada..3f3ef1a4b 100644 --- a/Source/Helpers/Extensions/AVCaptureDevice+Extensions.swift +++ b/Source/Helpers/Extensions/AVCaptureDevice+Extensions.swift @@ -33,3 +33,22 @@ extension AVCaptureDevice { } } } + +internal extension AVCaptureDevice { + class var audioCaptureDevice: AVCaptureDevice? { + let availableMicrophoneAudioDevices = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInMicrophone], mediaType: .audio, position: .unspecified).devices + return availableMicrophoneAudioDevices.first + } + + /// Best available device for selected position. + class func deviceForPosition(_ p: AVCaptureDevice.Position) -> AVCaptureDevice? { + let devicesSession = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInTrueDepthCamera, .builtInDualCamera, .builtInWideAngleCamera], mediaType: .video, position: p) + let devices = devicesSession.devices + guard !devices.isEmpty else { + print("Don't have supported cameras for this position: \(p.rawValue)") + return nil + } + + return devices.first + } +} diff --git a/Source/Helpers/Extensions/AVFoundation+Extensions.swift b/Source/Helpers/Extensions/AVFoundation+Extensions.swift index 670afd105..23cc8ba76 100644 --- a/Source/Helpers/Extensions/AVFoundation+Extensions.swift +++ b/Source/Helpers/Extensions/AVFoundation+Extensions.swift @@ -12,14 +12,16 @@ import AVFoundation // MARK: - Global functions -func deviceForPosition(_ p: AVCaptureDevice.Position) -> AVCaptureDevice? { - for device in AVCaptureDevice.devices(for: AVMediaType.video) where device.position == p { - return device + +internal func flippedDeviceInputForInput(_ input: AVCaptureDeviceInput) -> AVCaptureDeviceInput? { + let position: AVCaptureDevice.Position = (input.device.position == .front) ? .back : .front + guard let aDevice = AVCaptureDevice.deviceForPosition(position) else { + return nil } - return nil + return try? AVCaptureDeviceInput(device: aDevice) } -func thumbnailFromVideoPath(_ path: URL) -> UIImage { +internal func thumbnailFromVideoPath(_ path: URL) -> UIImage { let asset = AVURLAsset(url: path, options: nil) let gen = AVAssetImageGenerator(asset: asset) gen.appliesPreferredTrackTransform = true @@ -34,7 +36,7 @@ func thumbnailFromVideoPath(_ path: URL) -> UIImage { return UIImage() } -func setFocusPointOnDevice(device: AVCaptureDevice, point: CGPoint) { +internal func setFocusPointOnDevice(device: AVCaptureDevice, point: CGPoint) { do { try device.lockForConfiguration() if device.isFocusModeSupported(AVCaptureDevice.FocusMode.autoFocus) { @@ -51,7 +53,7 @@ func setFocusPointOnDevice(device: AVCaptureDevice, point: CGPoint) { } } -func setFocusPointOnCurrentDevice(_ point: CGPoint) { +internal func setFocusPointOnCurrentDevice(_ point: CGPoint) { if let device = AVCaptureDevice.default(for: AVMediaType.video) { do { try device.lockForConfiguration() @@ -69,13 +71,3 @@ func setFocusPointOnCurrentDevice(_ point: CGPoint) { device.unlockForConfiguration() } } - -func toggledPositionForDevice(_ device: AVCaptureDevice) -> AVCaptureDevice.Position { - return (device.position == .front) ? .back : .front -} - -func flippedDeviceInputForInput(_ input: AVCaptureDeviceInput) -> AVCaptureDeviceInput? { - let p = toggledPositionForDevice(input.device) - let aDevice = deviceForPosition(p) - return try? AVCaptureDeviceInput(device: aDevice!) -} diff --git a/Source/Pages/Photo/YPPhotoCaptureHelper.swift b/Source/Pages/Photo/YPPhotoCaptureHelper.swift index af8f5e909..705ffc5ca 100644 --- a/Source/Pages/Photo/YPPhotoCaptureHelper.swift +++ b/Source/Pages/Photo/YPPhotoCaptureHelper.swift @@ -172,7 +172,7 @@ private extension YPPhotoCaptureHelper { session.beginConfiguration() session.sessionPreset = .photo let cameraPosition: AVCaptureDevice.Position = YPConfig.usesFrontCamera ? .front : .back - let aDevice = deviceForPosition(cameraPosition) + let aDevice = AVCaptureDevice.deviceForPosition(cameraPosition) if let d = aDevice { deviceInput = try? AVCaptureDeviceInput(device: d) } diff --git a/Source/Pages/Video/YPVideoCaptureHelper.swift b/Source/Pages/Video/YPVideoCaptureHelper.swift index e897d0d59..dfb847c07 100644 --- a/Source/Pages/Video/YPVideoCaptureHelper.swift +++ b/Source/Pages/Video/YPVideoCaptureHelper.swift @@ -52,21 +52,24 @@ class YPVideoCaptureHelper: NSObject { // MARK: - Start Camera public func startCamera(completion: @escaping (() -> Void)) { - if !session.isRunning { - sessionQueue.async { [weak self] in - // Re-apply session preset - self?.session.sessionPreset = .photo - let status = AVCaptureDevice.authorizationStatus(for: AVMediaType.video) - switch status { - case .notDetermined, .restricted, .denied: - self?.session.stopRunning() - case .authorized: - self?.session.startRunning() - completion() - self?.tryToSetupPreview() - @unknown default: - ypLog("unknown default reached. Check code.") - } + guard !session.isRunning else { + print("Session is already running. Returning.") + return + } + + sessionQueue.async { [weak self] in + // Re-apply session preset + self?.session.sessionPreset = .photo + let status = AVCaptureDevice.authorizationStatus(for: AVMediaType.video) + switch status { + case .notDetermined, .restricted, .denied: + self?.session.stopRunning() + case .authorized: + self?.session.startRunning() + completion() + self?.tryToSetupPreview() + @unknown default: + ypLog("unknown default reached. Check code.") } } } @@ -92,14 +95,14 @@ class YPVideoCaptureHelper: NSObject { } // Re Add audio recording - for device in AVCaptureDevice.devices(for: .audio) { - if let audioInput = try? AVCaptureDeviceInput(device: device) { - if strongSelf.session.canAddInput(audioInput) { - strongSelf.session.addInput(audioInput) - } - } + if let audioDevice = AVCaptureDevice.audioCaptureDevice, + let audioInput = try? AVCaptureDeviceInput(device: audioDevice), + strongSelf.session.canAddInput(audioInput) { + strongSelf.session.addInput(audioInput) } + strongSelf.session.commitConfiguration() + DispatchQueue.main.async { completion() } @@ -151,10 +154,12 @@ class YPVideoCaptureHelper: NSObject { // MARK: - Stop Camera public func stopCamera() { - if session.isRunning { - sessionQueue.async { [weak self] in - self?.session.stopRunning() - } + guard session.isRunning else { + return + } + + sessionQueue.async { [weak self] in + self?.session.stopRunning() } } @@ -205,7 +210,7 @@ class YPVideoCaptureHelper: NSObject { private func setupCaptureSession() { session.beginConfiguration() let cameraPosition: AVCaptureDevice.Position = YPConfig.usesFrontCamera ? .front : .back - let aDevice = deviceForPosition(cameraPosition) + let aDevice = AVCaptureDevice.deviceForPosition(cameraPosition) if let d = aDevice { videoInput = try? AVCaptureDeviceInput(device: d) @@ -217,14 +222,12 @@ class YPVideoCaptureHelper: NSObject { } // Add audio recording - for device in AVCaptureDevice.devices(for: .audio) { - if let audioInput = try? AVCaptureDeviceInput(device: device) { - if session.canAddInput(audioInput) { - session.addInput(audioInput) - } - } + if let audioDevice = AVCaptureDevice.audioCaptureDevice, + let audioInput = try? AVCaptureDeviceInput(device: audioDevice), + session.canAddInput(audioInput) { + session.addInput(audioInput) } - + let timeScale: Int32 = 30 // FPS let maxDuration = CMTimeMakeWithSeconds(self.videoRecordingTimeLimit, preferredTimescale: timeScale)