mirror of https://github.com/oxen-io/session-ios
				
				
				
			
			You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
	
	
		
			118 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Swift
		
	
		
		
			
		
	
	
			118 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Swift
		
	
| 
											4 years ago
										 | // | ||
|  | //  Copyright (c) 2020 Open Whisper Systems. All rights reserved. | ||
|  | // | ||
|  | 
 | ||
|  | import Foundation | ||
|  | 
 | ||
|  | class LocalVideoView: UIView { | ||
|  |     private let localVideoCapturePreview = RTCCameraPreviewView() | ||
|  | 
 | ||
|  |     var captureSession: AVCaptureSession? { | ||
|  |         set { localVideoCapturePreview.captureSession = newValue } | ||
|  |         get { localVideoCapturePreview.captureSession } | ||
|  |     } | ||
|  | 
 | ||
|  |     override var contentMode: UIView.ContentMode { | ||
|  |         didSet { localVideoCapturePreview.contentMode = contentMode } | ||
|  |     } | ||
|  | 
 | ||
|  |     override init(frame: CGRect) { | ||
|  |         super.init(frame: .zero) | ||
|  | 
 | ||
|  |         addSubview(localVideoCapturePreview) | ||
|  | 
 | ||
|  |         if Platform.isSimulator { | ||
|  |             backgroundColor = .green | ||
|  |         } | ||
|  | 
 | ||
|  |         NotificationCenter.default.addObserver( | ||
|  |             self, | ||
|  |             selector: #selector(updateLocalVideoOrientation), | ||
|  |             name: UIDevice.orientationDidChangeNotification, | ||
|  |             object: nil | ||
|  |         ) | ||
|  |     } | ||
|  | 
 | ||
|  |     required init?(coder: NSCoder) { | ||
|  |         fatalError("init(coder:) has not been implemented") | ||
|  |     } | ||
|  | 
 | ||
|  |     override var frame: CGRect { | ||
|  |         didSet { updateLocalVideoOrientation() } | ||
|  |     } | ||
|  | 
 | ||
|  |     @objc | ||
|  |     func updateLocalVideoOrientation() { | ||
|  |         defer { localVideoCapturePreview.frame = bounds } | ||
|  | 
 | ||
|  |         // iPad supports rotating this view controller directly, | ||
|  |         // so we don't need to do anything here. | ||
|  |         guard !UIDevice.current.isIPad else { return } | ||
|  | 
 | ||
|  |         // We lock this view to portrait only on phones, but the | ||
|  |         // local video capture will rotate with the device's | ||
|  |         // orientation (so the remote party will render your video | ||
|  |         // in the correct orientation). As such, we need to rotate | ||
|  |         // the local video preview layer so it *looks* like we're | ||
|  |         // also always capturing in portrait. | ||
|  | 
 | ||
|  |         switch UIDevice.current.orientation { | ||
|  |         case .portrait: | ||
|  |             localVideoCapturePreview.transform = .identity | ||
|  |         case .portraitUpsideDown: | ||
|  |             localVideoCapturePreview.transform = .init(rotationAngle: .pi) | ||
|  |         case .landscapeLeft: | ||
|  |             localVideoCapturePreview.transform = .init(rotationAngle: .halfPi) | ||
|  |         case .landscapeRight: | ||
|  |             localVideoCapturePreview.transform = .init(rotationAngle: .pi + .halfPi) | ||
|  |         case .faceUp, .faceDown, .unknown: | ||
|  |             break | ||
|  |         @unknown default: | ||
|  |             break | ||
|  |         } | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | extension RTCCameraPreviewView { | ||
|  |     var previewLayer: AVCaptureVideoPreviewLayer? { | ||
|  |         return layer as? AVCaptureVideoPreviewLayer | ||
|  |     } | ||
|  | 
 | ||
|  |     open override var contentMode: UIView.ContentMode { | ||
|  |         set { | ||
|  |             guard let previewLayer = previewLayer else { | ||
|  |                 return owsFailDebug("missing preview layer") | ||
|  |             } | ||
|  | 
 | ||
|  |             switch newValue { | ||
|  |             case .scaleAspectFill: | ||
|  |                 previewLayer.videoGravity = .resizeAspectFill | ||
|  |             case .scaleAspectFit: | ||
|  |                 previewLayer.videoGravity = .resizeAspect | ||
|  |             case .scaleToFill: | ||
|  |                 previewLayer.videoGravity = .resize | ||
|  |             default: | ||
|  |                 owsFailDebug("Unexpected contentMode") | ||
|  |             } | ||
|  |         } | ||
|  |         get { | ||
|  |             guard let previewLayer = previewLayer else { | ||
|  |                 owsFailDebug("missing preview layer") | ||
|  |                 return .scaleToFill | ||
|  |             } | ||
|  | 
 | ||
|  |             switch previewLayer.videoGravity { | ||
|  |             case .resizeAspectFill: | ||
|  |                 return .scaleAspectFill | ||
|  |             case .resizeAspect: | ||
|  |                 return .scaleAspectFit | ||
|  |             case .resize: | ||
|  |                 return .scaleToFill | ||
|  |             default: | ||
|  |                 owsFailDebug("Unexpected contentMode") | ||
|  |                 return .scaleToFill | ||
|  |             } | ||
|  |         } | ||
|  |     } | ||
|  | } |