@@ -17,7 +17,7 @@ class CameraController: NSObject {
1717 var frontCamera : AVCaptureDevice ?
1818 var frontCameraInput : AVCaptureDeviceInput ?
1919
20- var dataOutput : AVCaptureVideoDataOutput ?
20+ var videoOutput : AVCaptureMovieFileOutput ?
2121 var photoOutput : AVCapturePhotoOutput ?
2222
2323 var rearCamera : AVCaptureDevice ?
@@ -27,6 +27,7 @@ class CameraController: NSObject {
2727
2828 var flashMode = AVCaptureDevice . FlashMode. off
2929 var photoCaptureCompletionBlock : ( ( UIImage ? , Error ? ) -> Void ) ?
30+ var videoCaptureCompletionBlock : ( ( URL ? , Error ? ) -> Void ) ?
3031
3132 var sampleBufferCaptureCompletionBlock : ( ( UIImage ? , Error ? ) -> Void ) ?
3233
@@ -42,6 +43,7 @@ extension CameraController {
4243 func prepare( cameraPosition: String , disableAudio: Bool , completionHandler: @escaping ( Error ? ) -> Void ) {
4344 func createCaptureSession( ) {
4445 self . captureSession = AVCaptureSession ( )
46+ self . captureSession? . beginConfiguration ( )
4547 }
4648
4749 func configureCaptureDevices( ) throws {
@@ -110,25 +112,18 @@ extension CameraController {
110112 self . photoOutput!. setPreparedPhotoSettingsArray ( [ AVCapturePhotoSettings ( format: [ AVVideoCodecKey: AVVideoCodecType . jpeg] ) ] , completionHandler: nil )
111113 self . photoOutput? . isHighResolutionCaptureEnabled = self . highResolutionOutput
112114 if captureSession. canAddOutput ( self . photoOutput!) { captureSession. addOutput ( self . photoOutput!) }
113- captureSession. startRunning ( )
114115 }
115116
116- func configureDataOutput ( ) throws {
117+ func configureVideoOutput ( ) throws {
117118 guard let captureSession = self . captureSession else { throw CameraControllerError . captureSessionIsMissing }
118119
119- self . dataOutput = AVCaptureVideoDataOutput ( )
120- self . dataOutput? . videoSettings = [
121- ( kCVPixelBufferPixelFormatTypeKey as String ) : NSNumber ( value: kCVPixelFormatType_32BGRA as UInt32 )
122- ]
123- self . dataOutput? . alwaysDiscardsLateVideoFrames = true
124- if captureSession. canAddOutput ( self . dataOutput!) {
125- captureSession. addOutput ( self . dataOutput!)
126- }
127-
128- captureSession. commitConfiguration ( )
120+ self . videoOutput = AVCaptureMovieFileOutput ( )
129121
130- let queue = DispatchQueue ( label: " DataOutput " , attributes: [ ] )
131- self . dataOutput? . setSampleBufferDelegate ( self , queue: queue)
122+ if captureSession. canAddOutput ( self . videoOutput!) {
123+ captureSession. addOutput ( self . videoOutput!)
124+ } else {
125+ throw CameraControllerError . invalidOperation
126+ }
132127 }
133128
134129 DispatchQueue ( label: " prepare " ) . async {
@@ -138,7 +133,9 @@ extension CameraController {
138133 try configureDeviceInputs ( )
139134 try configurePhotoOutput ( )
140135 try configureDataOutput ( )
141- // try configureVideoOutput()
136+ try configureVideoOutput ( )
137+ self . captureSession? . commitConfiguration ( )
138+ self . captureSession? . startRunning ( )
142139 } catch {
143140 DispatchQueue . main. async {
144141 completionHandler ( error)
@@ -153,6 +150,21 @@ extension CameraController {
153150 }
154151 }
155152
153+ func resume( completionHandler: @escaping ( Error ? ) -> Void ) {
154+ guard let captureSession = self . captureSession else {
155+ completionHandler ( CameraControllerError . captureSessionIsMissing)
156+ return
157+ }
158+ DispatchQueue ( label: " prepare " ) . async {
159+ if ( !captureSession. isRunning) {
160+ captureSession. startRunning ( )
161+ }
162+ DispatchQueue . main. async {
163+ completionHandler ( nil )
164+ }
165+ }
166+ }
167+
156168 func displayPreview( on view: UIView ) throws {
157169 guard let captureSession = self . captureSession, captureSession. isRunning else { throw CameraControllerError . captureSessionIsMissing }
158170
@@ -204,7 +216,8 @@ extension CameraController {
204216 }
205217
206218 previewLayer? . connection? . videoOrientation = videoOrientation
207- dataOutput? . connections. forEach { $0. videoOrientation = videoOrientation }
219+ //Orientation is not supported for video connections
220+ //videoOutput?.connections.forEach { $0.videoOrientation = videoOrientation }
208221 photoOutput? . connections. forEach { $0. videoOrientation = videoOrientation }
209222 }
210223
@@ -396,9 +409,9 @@ extension CameraController {
396409
397410 }
398411
399- func captureVideo( completion: @escaping ( URL ? , Error ? ) -> Void ) {
412+ func captureVideo( mirror : Bool = false , completion: @escaping ( URL ? , Error ? ) -> Void ) {
400413 guard let captureSession = self . captureSession, captureSession. isRunning else {
401- completion ( nil , CameraControllerError . captureSessionIsMissing)
414+ completion ( CameraControllerError . captureSessionIsMissing)
402415 return
403416 }
404417 let path = FileManager . default. urls ( for: . cachesDirectory, in: . userDomainMask) [ 0 ]
@@ -409,16 +422,27 @@ extension CameraController {
409422
410423 let fileUrl = path. appendingPathComponent ( fileName)
411424 try ? FileManager . default. removeItem ( at: fileUrl)
412- /*videoOutput!.startRecording(to: fileUrl, recordingDelegate: self)
413- self.videoRecordCompletionBlock = completion*/
425+
426+ if mirror {
427+ if let connection = videoOutput? . connection ( with: AVMediaType . video) , connection. isVideoOrientationSupported {
428+ connection. isVideoMirrored = true
429+ } else {
430+ completion ( CameraControllerError . invalidOperation)
431+ return
432+ }
433+ }
434+
435+ videoOutput!. startRecording ( to: fileUrl, recordingDelegate: self )
436+ completion ( nil )
414437 }
415438
416- func stopRecording( completion: @escaping ( Error ? ) -> Void ) {
439+ func stopRecording( completion: @escaping ( URL ? , Error ? ) -> Void ) {
417440 guard let captureSession = self . captureSession, captureSession. isRunning else {
418- completion ( CameraControllerError . captureSessionIsMissing)
441+ completion ( nil , CameraControllerError . captureSessionIsMissing)
419442 return
420443 }
421- // self.videoOutput?.stopRecording()
444+ self . videoCaptureCompletionBlock = completion
445+ self . videoOutput? . stopRecording ( )
422446 }
423447}
424448
@@ -495,48 +519,6 @@ extension CameraController: AVCapturePhotoCaptureDelegate {
495519 }
496520}
497521
498- extension CameraController : AVCaptureVideoDataOutputSampleBufferDelegate {
499- func captureOutput( _ output: AVCaptureOutput , didOutput sampleBuffer: CMSampleBuffer , from connection: AVCaptureConnection ) {
500- guard let completion = sampleBufferCaptureCompletionBlock else { return }
501-
502- guard let imageBuffer = CMSampleBufferGetImageBuffer ( sampleBuffer) else {
503- completion ( nil , CameraControllerError . unknown)
504- return
505- }
506-
507- CVPixelBufferLockBaseAddress ( imageBuffer, . readOnly)
508- defer { CVPixelBufferUnlockBaseAddress ( imageBuffer, . readOnly) }
509-
510- let baseAddress = CVPixelBufferGetBaseAddress ( imageBuffer)
511- let bytesPerRow = CVPixelBufferGetBytesPerRow ( imageBuffer)
512- let width = CVPixelBufferGetWidth ( imageBuffer)
513- let height = CVPixelBufferGetHeight ( imageBuffer)
514- let colorSpace = CGColorSpaceCreateDeviceRGB ( )
515- let bitmapInfo : UInt32 = CGBitmapInfo . byteOrder32Little. rawValue |
516- CGImageAlphaInfo . premultipliedFirst. rawValue
517-
518- let context = CGContext (
519- data: baseAddress,
520- width: width,
521- height: height,
522- bitsPerComponent: 8 ,
523- bytesPerRow: bytesPerRow,
524- space: colorSpace,
525- bitmapInfo: bitmapInfo
526- )
527-
528- guard let cgImage = context? . makeImage ( ) else {
529- completion ( nil , CameraControllerError . unknown)
530- return
531- }
532-
533- let image = UIImage ( cgImage: cgImage)
534- completion ( image. fixedOrientation ( ) , nil )
535-
536- sampleBufferCaptureCompletionBlock = nil
537- }
538- }
539-
540522enum CameraControllerError : Swift . Error {
541523 case captureSessionAlreadyRunning
542524 case captureSessionIsMissing
@@ -639,10 +621,10 @@ extension UIImage {
639621
640622extension CameraController : AVCaptureFileOutputRecordingDelegate {
641623 func fileOutput( _ output: AVCaptureFileOutput , didFinishRecordingTo outputFileURL: URL , from connections: [ AVCaptureConnection ] , error: Error ? ) {
642- /* if error == nil {
643- self.videoRecordCompletionBlock ?(outputFileURL, nil)
644- } else {
645- self.videoRecordCompletionBlock ?(nil, error)
646- }*/
624+ if error == nil {
625+ self . videoCaptureCompletionBlock ? ( outputFileURL, nil )
626+ } else {
627+ self . videoCaptureCompletionBlock ? ( nil , error)
628+ }
647629 }
648630}
0 commit comments