// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. import WebRTC import Foundation import SessionUtilitiesKit import SignalCoreKit #if targetEnvironment(simulator) // Note: 'RTCMTLVideoView' doesn't seem to work on the simulator so use 'RTCEAGLVideoView' instead typealias TargetView = RTCEAGLVideoView #else typealias TargetView = RTCMTLVideoView #endif // MARK: RemoteVideoView class RemoteVideoView: TargetView { override func renderFrame(_ frame: RTCVideoFrame?) { super.renderFrame(frame) guard let frame = frame else { return } if UIDevice.current.isIPad { DispatchMainThreadSafe { #if targetEnvironment(simulator) self.contentMode = .scaleAspectFit #else self.videoContentMode = .scaleAspectFit #endif } return } Threading.dispatchMainThreadSafe { let frameRatio = Double(frame.height) / Double(frame.width) let frameRotation = frame.rotation let deviceRotation = UIDevice.current.orientation var rotationOverride: RTCVideoRotation? = nil switch deviceRotation { case .portrait, .portraitUpsideDown: // We don't have to do anything, the renderer will automatically make sure it's right-side-up. break case .landscapeLeft: switch frameRotation { case RTCVideoRotation._0: rotationOverride = RTCVideoRotation._90 // Landscape left case RTCVideoRotation._90: rotationOverride = RTCVideoRotation._180 // Portrait case RTCVideoRotation._180: rotationOverride = RTCVideoRotation._270 // Landscape right case RTCVideoRotation._270: rotationOverride = RTCVideoRotation._0 // Portrait upside-down default: break } case .landscapeRight: switch frameRotation { case RTCVideoRotation._0: rotationOverride = RTCVideoRotation._270 // Landscape left case RTCVideoRotation._90: rotationOverride = RTCVideoRotation._0 // Portrait case RTCVideoRotation._180: rotationOverride = RTCVideoRotation._90 // Landscape right case RTCVideoRotation._270: rotationOverride = RTCVideoRotation._180 // Portrait upside-down default: break } default: // Do nothing if we're face down, up, etc. // Assume we're already setup for the correct orientation. break } #if targetEnvironment(simulator) #else if let rotationOverride = rotationOverride { self.rotationOverride = NSNumber(value: rotationOverride.rawValue) if [ RTCVideoRotation._0, RTCVideoRotation._180 ].contains(rotationOverride) { self.videoContentMode = .scaleAspectFill } else { self.videoContentMode = .scaleAspectFit } } else { self.rotationOverride = nil if [ RTCVideoRotation._0, RTCVideoRotation._180 ].contains(frameRotation) { self.videoContentMode = .scaleAspectFill } else { self.videoContentMode = .scaleAspectFit } } // if not a mobile ratio, always use .scaleAspectFit if frameRatio < 1.5 { self.videoContentMode = .scaleAspectFit } #endif } } } // MARK: LocalVideoView class LocalVideoView: TargetView { override func renderFrame(_ frame: RTCVideoFrame?) { super.renderFrame(frame) Threading.dispatchMainThreadSafe { // This is a workaround for a weird issue that // sometimes the rotationOverride is not working // if it is only set once on initialization self.rotationOverride = NSNumber(value: RTCVideoRotation._0.rawValue) #if targetEnvironment(simulator) #else self.videoContentMode = .scaleAspectFill #endif } } }