@@ -14,17 +14,13 @@ class VideoRecorder: NSObject {
14
14
// MARK: - Private properties
15
15
private var currentDeviceOrientation = UIDeviceOrientation . portrait
16
16
private var cameraAvailable : Bool
17
- private var captureVideoPreviewLayer : AVCaptureVideoPreviewLayer ?
18
-
19
- private var defaultAVCaptureVideoOrientation = AVCaptureVideoOrientation . portrait
17
+ private var captureVideoPreviewLayer : AVCaptureVideoPreviewLayer !
20
18
21
19
private var captureSession : AVCaptureSession !
22
20
private var captureSessionLoaded = false
23
21
24
- private var parentView : UIView
25
-
26
22
private let dataOutputQueue = DispatchQueue ( label: " DataOutputQueue " )
27
- private var isAssetWriterSessionStarted = false
23
+ private var isRecordingSessionStarted = false
28
24
29
25
private var assetVideoWriterInput : AVAssetWriterInput !
30
26
private var assetAudioWriterInput : AVAssetWriterInput !
@@ -44,10 +40,11 @@ class VideoRecorder: NSObject {
44
40
private let videoFileURL =
45
41
FileManager . default. temporaryDirectory. appendingPathComponent ( " recorded_video.mp4 " )
46
42
47
- // MARK: - Initiallization
48
- init ( withParent parent: UIView ) {
43
+ // MARK: - Initialization
44
+ init ( withParent parent: VideoPreviewView ) {
49
45
cameraAvailable = UIImagePickerController . isSourceTypeAvailable ( . camera)
50
- parentView = parent
46
+ captureVideoPreviewLayer = parent. videoPreviewLayer
47
+
51
48
super. init ( )
52
49
}
53
50
}
@@ -82,9 +79,7 @@ extension VideoRecorder {
82
79
83
80
captureSession. stopRunning ( )
84
81
85
- captureVideoPreviewLayer? . removeFromSuperlayer ( )
86
- captureVideoPreviewLayer = nil
87
-
82
+ captureVideoPreviewLayer. session = nil
88
83
captureSessionLoaded = false
89
84
90
85
stopRecord ( )
@@ -119,7 +114,7 @@ private extension VideoRecorder {
119
114
120
115
captureSession. commitConfiguration ( )
121
116
122
- addVideoPreviewLayer ( )
117
+ assignVideoPreviewLayerSession ( )
123
118
124
119
captureSessionLoaded = true
125
120
captureSession. startRunning ( )
@@ -207,19 +202,13 @@ private extension VideoRecorder {
207
202
if captureSession. canAddOutput ( captureVideoDataOutput) {
208
203
captureSession. addOutput ( captureVideoDataOutput)
209
204
}
205
+
210
206
captureVideoDataOutput. connection ( with: . video) ? . isEnabled = true
207
+ captureVideoDataOutput. setSampleBufferDelegate ( self , queue: dataOutputQueue)
211
208
212
- // set default video orientation
213
- if ( captureVideoDataOutput. connection ( with: . video) ? . isVideoOrientationSupported) ! {
214
- captureVideoDataOutput. connection ( with: . video) ? . videoOrientation = defaultAVCaptureVideoOrientation
209
+ if let connection = captureVideoDataOutput. connection ( with: . video) , connection. isVideoOrientationSupported {
210
+ connection. videoOrientation = . portrait
215
211
}
216
-
217
- // create a serial dispatch queue used for the sample buffer delegate as well as when
218
- // a still image is captured a serial dispatch queue must be used to guarantee that
219
- // video frames will be delivered in order see the header doc for
220
- // setSampleBufferDelegate:queue: for more information
221
- //let dataOutputQueue = DispatchQueue(label: "VideoDataOutputQueue")
222
- captureVideoDataOutput. setSampleBufferDelegate ( self , queue: dataOutputQueue)
223
212
}
224
213
225
214
func addCaptureAudioDataOutput( ) {
@@ -228,23 +217,35 @@ private extension VideoRecorder {
228
217
if captureSession. canAddOutput ( captureAudioDataOutput) {
229
218
captureSession. addOutput ( captureAudioDataOutput)
230
219
}
231
- captureAudioDataOutput. connection ( with: . audio) ? . isEnabled = true
232
220
233
- //let dataOutputQueue = DispatchQueue(label: "AudioDataOutputQueue")
221
+ captureAudioDataOutput . connection ( with : . audio ) ? . isEnabled = true
234
222
captureAudioDataOutput. setSampleBufferDelegate ( self , queue: dataOutputQueue)
235
223
}
236
224
237
- func addVideoPreviewLayer( ) {
238
- captureVideoPreviewLayer = AVCaptureVideoPreviewLayer ( session: captureSession)
239
-
240
- if ( captureVideoPreviewLayer? . connection? . isVideoOrientationSupported) ! {
241
- captureVideoPreviewLayer? . connection? . videoOrientation = defaultAVCaptureVideoOrientation
225
+ func assignVideoPreviewLayerSession( ) {
226
+ captureVideoPreviewLayer. session = captureSession
227
+ }
228
+ }
229
+
230
+ // MARK: - Handle device rotation
231
+ extension VideoRecorder {
232
+ func viewWillLayoutSubviews( ) {
233
+ guard let connection = captureVideoPreviewLayer. connection, connection. isVideoOrientationSupported else {
234
+ return
235
+ }
236
+
237
+ switch ( UIDevice . current. orientation) {
238
+ case . portrait:
239
+ connection. videoOrientation = . portrait
240
+ case . portraitUpsideDown:
241
+ connection. videoOrientation = . portraitUpsideDown
242
+ case . landscapeLeft:
243
+ connection. videoOrientation = . landscapeRight
244
+ case . landscapeRight:
245
+ connection. videoOrientation = . landscapeLeft
246
+ default :
247
+ break
242
248
}
243
-
244
- captureVideoPreviewLayer? . frame = parentView. frame
245
-
246
- captureVideoPreviewLayer? . videoGravity = . resizeAspectFill
247
- parentView. layer. addSublayer ( captureVideoPreviewLayer!)
248
249
}
249
250
}
250
251
@@ -317,7 +318,7 @@ extension VideoRecorder {
317
318
assetWriterInputPixelBufferAdaptor = nil
318
319
assetVideoWriterInput = nil
319
320
assetAudioWriterInput = nil
320
- isAssetWriterSessionStarted = false
321
+ isRecordingSessionStarted = false
321
322
}
322
323
}
323
324
@@ -335,9 +336,9 @@ extension VideoRecorder: AVCaptureVideoDataOutputSampleBufferDelegate, AVCapture
335
336
let isRecording = assetWriter != nil && assetWriter. status == . writing
336
337
337
338
if isRecording {
338
- if ( !isAssetWriterSessionStarted ) {
339
+ if ( !isRecordingSessionStarted ) {
339
340
assetWriter. startSession ( atSourceTime: sourceSampleTimeStamp)
340
- isAssetWriterSessionStarted = true
341
+ isRecordingSessionStarted = true
341
342
}
342
343
}
343
344
0 commit comments