Skip to content

Commit c0aad3b

Browse files
committed
ProverSwype: Start to handle rotation. The recording video screen is done.
1 parent ef71d32 commit c0aad3b

File tree

7 files changed

+78
-49
lines changed

7 files changed

+78
-49
lines changed

client/iOS/swype/ProverSwipe.xcodeproj/project.pbxproj

+5-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
/* Begin PBXBuildFile section */
1010
1A1EAB5420D3E15200C8A3C9 /* AccountTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A1EAB5320D3E15200C8A3C9 /* AccountTests.swift */; };
11+
1A4FE43620E621BC004433F0 /* VideoPreviewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A4FE43520E621BC004433F0 /* VideoPreviewView.swift */; };
1112
1A58439A20C96B6D00C8FA14 /* Keychain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A58439920C96B6D00C8FA14 /* Keychain.swift */; };
1213
1A8A317720D15A1F00BB7E97 /* keccak.c in Sources */ = {isa = PBXBuildFile; fileRef = 1A8A314D20D15A1F00BB7E97 /* keccak.c */; };
1314
1A8A317820D15A1F00BB7E97 /* HashManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A8A314F20D15A1F00BB7E97 /* HashManager.swift */; };
@@ -226,6 +227,7 @@
226227
1A1EAB5120D3E15200C8A3C9 /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
227228
1A1EAB5320D3E15200C8A3C9 /* AccountTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountTests.swift; sourceTree = "<group>"; };
228229
1A1EAB5520D3E15200C8A3C9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
230+
1A4FE43520E621BC004433F0 /* VideoPreviewView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPreviewView.swift; sourceTree = "<group>"; };
229231
1A58439920C96B6D00C8FA14 /* Keychain.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Keychain.swift; sourceTree = "<group>"; };
230232
1A8A314D20D15A1F00BB7E97 /* keccak.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = keccak.c; sourceTree = "<group>"; };
231233
1A8A314E20D15A1F00BB7E97 /* keccak.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = keccak.h; sourceTree = "<group>"; };
@@ -800,9 +802,9 @@
800802
children = (
801803
9A2EA9DE2074EB9300910CFB /* CPP */,
802804
9A2EA9DA2074EB7E00910CFB /* Wrapper */,
803-
9AF02BA520B59B9A00C5BC3A /* VideoProcessor.swift */,
804805
9A2EA9FA2074EC1D00910CFB /* SwypeDetector.swift */,
805806
9AF364A220BBF21400A6A968 /* SwypeDetectionProtocols.swift */,
807+
9AF02BA520B59B9A00C5BC3A /* VideoProcessor.swift */,
806808
9A89F3CB207CA06D00E31F57 /* VideoRecorder.swift */,
807809
);
808810
path = Detection;
@@ -850,6 +852,7 @@
850852
9AA2DC1720B577FF001F6376 /* SwypeScreenState.swift */,
851853
9A2EAA252074F5F100910CFB /* SwypeViewController.swift */,
852854
9A7B96DB20B54ADD00ED4799 /* TargetView.swift */,
855+
1A4FE43520E621BC004433F0 /* VideoPreviewView.swift */,
853856
9A8FDDCD20BED3780080FB30 /* VideoSaver.swift */,
854857
);
855858
path = Swype;
@@ -1446,6 +1449,7 @@
14461449
1A8A317720D15A1F00BB7E97 /* keccak.c in Sources */,
14471450
9A9DB78320737D7000E29A07 /* UIImage+extension.swift in Sources */,
14481451
9A19C11220B04A45005FCD04 /* UIImageView+extension.swift in Sources */,
1452+
1A4FE43620E621BC004433F0 /* VideoPreviewView.swift in Sources */,
14491453
9A63764020B2AF3600F07704 /* UILabel+extension.swift in Sources */,
14501454
1A8A317F20D15A1F00BB7E97 /* Base32.swift in Sources */,
14511455
1AACAB3020D1AD420018AAFA /* ServerExceptions.swift in Sources */,

client/iOS/swype/ProverSwipe/Detection/VideoProcessor.swift

+7-3
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ class VideoProcessor {
1616
private weak var delegate: VideoProcessorDelegate!
1717
private weak var coordinateDelegate: SwypeDetectorCoordinateDelegate!
1818

19-
init(preview: UIView,
19+
init(videoPreviewView: VideoPreviewView,
2020
coordinateDelegate: SwypeDetectorCoordinateDelegate,
2121
delegate: VideoProcessorDelegate) {
2222

23-
videoRecorder = VideoRecorder(withParent: preview)
23+
videoRecorder = VideoRecorder(withParent: videoPreviewView)
2424
videoRecorder.delegate = self
2525

2626
self.coordinateDelegate = coordinateDelegate
@@ -32,7 +32,11 @@ class VideoProcessor {
3232

3333
// MARK: - Public methods (Detector)
3434
extension VideoProcessor {
35-
35+
36+
func viewWillLayoutSubviews() {
37+
videoRecorder.viewWillLayoutSubviews()
38+
}
39+
3640
func setSwype(code: [Int]) {
3741
swypeDetector.setSwype(code: code)
3842
}

client/iOS/swype/ProverSwipe/Detection/VideoRecorder.swift

+39-38
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,13 @@ class VideoRecorder: NSObject {
1414
// MARK: - Private properties
1515
private var currentDeviceOrientation = UIDeviceOrientation.portrait
1616
private var cameraAvailable: Bool
17-
private var captureVideoPreviewLayer: AVCaptureVideoPreviewLayer?
18-
19-
private var defaultAVCaptureVideoOrientation = AVCaptureVideoOrientation.portrait
17+
private var captureVideoPreviewLayer: AVCaptureVideoPreviewLayer!
2018

2119
private var captureSession: AVCaptureSession!
2220
private var captureSessionLoaded = false
2321

24-
private var parentView: UIView
25-
2622
private let dataOutputQueue = DispatchQueue(label: "DataOutputQueue")
27-
private var isAssetWriterSessionStarted = false
23+
private var isRecordingSessionStarted = false
2824

2925
private var assetVideoWriterInput: AVAssetWriterInput!
3026
private var assetAudioWriterInput: AVAssetWriterInput!
@@ -44,10 +40,11 @@ class VideoRecorder: NSObject {
4440
private let videoFileURL =
4541
FileManager.default.temporaryDirectory.appendingPathComponent("recorded_video.mp4")
4642

47-
// MARK: - Initiallization
48-
init(withParent parent: UIView) {
43+
// MARK: - Initialization
44+
init(withParent parent: VideoPreviewView) {
4945
cameraAvailable = UIImagePickerController.isSourceTypeAvailable(.camera)
50-
parentView = parent
46+
captureVideoPreviewLayer = parent.videoPreviewLayer
47+
5148
super.init()
5249
}
5350
}
@@ -82,9 +79,7 @@ extension VideoRecorder {
8279

8380
captureSession.stopRunning()
8481

85-
captureVideoPreviewLayer?.removeFromSuperlayer()
86-
captureVideoPreviewLayer = nil
87-
82+
captureVideoPreviewLayer.session = nil
8883
captureSessionLoaded = false
8984

9085
stopRecord()
@@ -119,7 +114,7 @@ private extension VideoRecorder {
119114

120115
captureSession.commitConfiguration()
121116

122-
addVideoPreviewLayer()
117+
assignVideoPreviewLayerSession()
123118

124119
captureSessionLoaded = true
125120
captureSession.startRunning()
@@ -207,19 +202,13 @@ private extension VideoRecorder {
207202
if captureSession.canAddOutput(captureVideoDataOutput) {
208203
captureSession.addOutput(captureVideoDataOutput)
209204
}
205+
210206
captureVideoDataOutput.connection(with: .video)?.isEnabled = true
207+
captureVideoDataOutput.setSampleBufferDelegate(self, queue: dataOutputQueue)
211208

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
215211
}
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)
223212
}
224213

225214
func addCaptureAudioDataOutput() {
@@ -228,23 +217,35 @@ private extension VideoRecorder {
228217
if captureSession.canAddOutput(captureAudioDataOutput) {
229218
captureSession.addOutput(captureAudioDataOutput)
230219
}
231-
captureAudioDataOutput.connection(with: .audio)?.isEnabled = true
232220

233-
//let dataOutputQueue = DispatchQueue(label: "AudioDataOutputQueue")
221+
captureAudioDataOutput.connection(with: .audio)?.isEnabled = true
234222
captureAudioDataOutput.setSampleBufferDelegate(self, queue: dataOutputQueue)
235223
}
236224

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
242248
}
243-
244-
captureVideoPreviewLayer?.frame = parentView.frame
245-
246-
captureVideoPreviewLayer?.videoGravity = .resizeAspectFill
247-
parentView.layer.addSublayer(captureVideoPreviewLayer!)
248249
}
249250
}
250251

@@ -317,7 +318,7 @@ extension VideoRecorder {
317318
assetWriterInputPixelBufferAdaptor = nil
318319
assetVideoWriterInput = nil
319320
assetAudioWriterInput = nil
320-
isAssetWriterSessionStarted = false
321+
isRecordingSessionStarted = false
321322
}
322323
}
323324

@@ -335,9 +336,9 @@ extension VideoRecorder: AVCaptureVideoDataOutputSampleBufferDelegate, AVCapture
335336
let isRecording = assetWriter != nil && assetWriter.status == .writing
336337

337338
if isRecording {
338-
if (!isAssetWriterSessionStarted) {
339+
if (!isRecordingSessionStarted) {
339340
assetWriter.startSession(atSourceTime: sourceSampleTimeStamp)
340-
isAssetWriterSessionStarted = true
341+
isRecordingSessionStarted = true
341342
}
342343
}
343344

client/iOS/swype/ProverSwipe/Info.plist

+5-2
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@
2929
<string>Access to camera is required</string>
3030
<key>NSMicrophoneUsageDescription</key>
3131
<string>Access to microphone is required</string>
32-
<key>NSPhotoLibraryUsageDescription</key>
33-
<string>Access to the Photo Library is required</string>
3432
<key>NSPhotoLibraryAddUsageDescription</key>
3533
<string>Access to the Photo Library Additions is required</string>
34+
<key>NSPhotoLibraryUsageDescription</key>
35+
<string>Access to the Photo Library is required</string>
3636
<key>UIFileSharingEnabled</key>
3737
<true/>
3838
<key>UILaunchStoryboardName</key>
@@ -46,6 +46,9 @@
4646
<key>UISupportedInterfaceOrientations</key>
4747
<array>
4848
<string>UIInterfaceOrientationPortrait</string>
49+
<string>UIInterfaceOrientationPortraitUpsideDown</string>
50+
<string>UIInterfaceOrientationLandscapeLeft</string>
51+
<string>UIInterfaceOrientationLandscapeRight</string>
4952
</array>
5053
<key>UISupportedInterfaceOrientations~ipad</key>
5154
<array>

client/iOS/swype/ProverSwipe/Screeens/Base.lproj/Main.storyboard

+2-2
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,7 @@
526526
<rect key="frame" x="0.0" y="0.0" width="414" height="736"/>
527527
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
528528
<subviews>
529-
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="gOj-HD-XuC">
529+
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="gOj-HD-XuC" customClass="VideoPreviewView" customModule="ProverSwipe" customModuleProvider="target">
530530
<rect key="frame" x="0.0" y="0.0" width="414" height="736"/>
531531
<color key="backgroundColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
532532
</imageView>
@@ -650,10 +650,10 @@
650650
<connections>
651651
<outlet property="balanceLabel" destination="cAl-Mi-600" id="Ueg-9r-C00"/>
652652
<outlet property="infoView" destination="oM7-at-dh9" id="Irp-KZ-wcc"/>
653-
<outlet property="preview" destination="gOj-HD-XuC" id="P3Q-dG-N0C"/>
654653
<outlet property="progressSwype" destination="Jhf-Mm-OSy" id="quf-zd-i4k"/>
655654
<outlet property="recordButton" destination="SHN-i0-ZdJ" id="G7a-OX-qbt"/>
656655
<outlet property="targetView" destination="T7K-8V-I5z" id="4Xh-26-Hzl"/>
656+
<outlet property="videoPreviewView" destination="gOj-HD-XuC" id="P3Q-dG-N0C"/>
657657
<segue destination="4ZJ-jn-pTM" kind="show" identifier="showWalletSegue" id="36F-PT-BIZ"/>
658658
</connections>
659659
</viewController>

client/iOS/swype/ProverSwipe/Screeens/Swype/SwypeViewController.swift

+8-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class SwypeViewController: UIViewController, UpdateBalanceBehaviour {
1111

1212
@IBOutlet weak var progressSwype: UIPageControl!
1313

14-
@IBOutlet weak var preview: UIImageView!
14+
@IBOutlet weak var videoPreviewView: VideoPreviewView!
1515
@IBOutlet weak var recordButton: UIButton!
1616

1717
@IBOutlet weak var balanceLabel: UILabel!
@@ -78,7 +78,12 @@ class SwypeViewController: UIViewController, UpdateBalanceBehaviour {
7878
print("[SwypeViewController] viewDidDisappear")
7979
videoProcessor.stopCapture()
8080
}
81-
81+
82+
override func viewWillLayoutSubviews() {
83+
super.viewWillLayoutSubviews()
84+
videoProcessor.viewWillLayoutSubviews()
85+
}
86+
8287
// MARK: - Segue
8388
enum Segue: String {
8489
case showWalletSegue
@@ -177,7 +182,7 @@ private extension SwypeViewController {
177182

178183
func configDependencies() {
179184

180-
videoProcessor = VideoProcessor(preview: preview,
185+
videoProcessor = VideoProcessor(videoPreviewView: videoPreviewView,
181186
coordinateDelegate: targetView,
182187
delegate: self)
183188

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import UIKit
2+
3+
class VideoPreviewView: UIImageView {
4+
override class var layerClass: AnyClass {
5+
return AVCaptureVideoPreviewLayer.self
6+
}
7+
8+
/// Convenience wrapper to get layer as its statically known type.
9+
var videoPreviewLayer: AVCaptureVideoPreviewLayer {
10+
return layer as! AVCaptureVideoPreviewLayer
11+
}
12+
}

0 commit comments

Comments
 (0)