diff --git a/NextcloudTalk/Calls/CallViewController.xib b/NextcloudTalk/Calls/CallViewController.xib
index 613ad14bd..07528468c 100644
--- a/NextcloudTalk/Calls/CallViewController.xib
+++ b/NextcloudTalk/Calls/CallViewController.xib
@@ -339,7 +339,6 @@
-
diff --git a/NextcloudTalk/Calls/NCCameraController.swift b/NextcloudTalk/Calls/NCCameraController.swift
index 699806286..3b1054654 100644
--- a/NextcloudTalk/Calls/NCCameraController.swift
+++ b/NextcloudTalk/Calls/NCCameraController.swift
@@ -22,6 +22,7 @@ class NCCameraController: NSObject, AVCaptureVideoDataOutputSampleBufferDelegate
// State
private var backgroundBlurEnabled = NCUserDefaults.backgroundBlurEnabled()
private var usingFrontCamera = true
+ private var previousOrientationBeforeUpsideDown: UIDeviceOrientation?
private var deviceOrientation: UIDeviceOrientation = UIDevice.current.orientation
private var videoRotation: RTCVideoRotation = ._0
private var firstLocalViewFrameDrawn = false
@@ -92,26 +93,32 @@ class NCCameraController: NSObject, AVCaptureVideoDataOutputSampleBufferDelegate
}
func switchCamera() {
- var newInput: AVCaptureDeviceInput
+ DispatchQueue.global(qos: .userInitiated).async { [weak self] in
+ guard let self = self else { return }
+ var newInput: AVCaptureDeviceInput
- if self.usingFrontCamera {
- newInput = getBackCameraInput()
- } else {
- newInput = getFrontCameraInput()
- }
+ if self.usingFrontCamera {
+ newInput = getBackCameraInput()
+ } else {
+ newInput = getFrontCameraInput()
+ }
- if let firstInput = session?.inputs.first {
- session?.removeInput(firstInput)
- }
+ if let firstInput = session?.inputs.first {
+ session?.removeInput(firstInput)
+ }
- // Stop and restart the session to prevent a weird glitch when rotating our local view
- self.session?.stopRunning()
- self.session?.addInput(newInput)
+ // Stop and restart the session to prevent a weird glitch when rotating our local view
+ self.session?.stopRunning()
+ self.session?.addInput(newInput)
+
+ // We need to set the orientation again, because otherweise after switching the video is turned
+ self.session?.outputs.first?.connections.first?.videoOrientation = .portrait
+ self.session?.startRunning()
- // We need to set the orientation again, because otherweise after switching the video is turned
- self.session?.outputs.first?.connections.first?.videoOrientation = .portrait
- self.session?.startRunning()
- self.usingFrontCamera = !self.usingFrontCamera
+ // Toggle usingFrontCamera flag and update video rotation
+ self.usingFrontCamera.toggle()
+ self.updateVideoRotationBasedOnDeviceOrientation()
+ }
}
// See ARDCaptureController from the WebRTC project
@@ -326,12 +333,31 @@ class NCCameraController: NSObject, AVCaptureVideoDataOutputSampleBufferDelegate
// Correctly rotate the local image
if videoRotation == ._180 {
ciImage = ciImage.oriented(.down)
+
+ // Rotate the local image on iPhones to match the previous landscape orientation when in UpsideDown.
+ // Since the localView frame doesn't change when transitioning from landscape to UpsideDown.
+ if UIDevice.current.userInterfaceIdiom == .phone,
+ let previousLandscapeOrientation = previousOrientationBeforeUpsideDown {
+
+ if previousLandscapeOrientation == .landscapeLeft {
+ ciImage = usingFrontCamera ? ciImage.oriented(.left) : ciImage.oriented(.right)
+ } else if previousLandscapeOrientation == .landscapeRight {
+ ciImage = usingFrontCamera ? ciImage.oriented(.right) : ciImage.oriented(.left)
+ }
+ }
+
} else if videoRotation == ._90 {
ciImage = ciImage.oriented(.right)
} else if videoRotation == ._270 {
ciImage = ciImage.oriented(.left)
}
+ // Mirror local image when using front camera
+ if usingFrontCamera {
+ let mirrorTransform = CGAffineTransform(translationX: ciImage.extent.width, y: 0).scaledBy(x: -1, y: 1)
+ ciImage = ciImage.transformed(by: mirrorTransform)
+ }
+
// make sure the image is full screen
let drawSize = localView.drawableSize
let scaleX = drawSize.width / ciImage.extent.width
@@ -366,8 +392,19 @@ class NCCameraController: NSObject, AVCaptureVideoDataOutputSampleBufferDelegate
// MARK: - Notifications
func deviceOrientationDidChangeNotification() {
- self.deviceOrientation = UIDevice.current.orientation
- self.updateVideoRotationBasedOnDeviceOrientation()
+ let currentOrientation = UIDevice.current.orientation
+
+ // The app doesn't support UpsideDown orientation on iPhones, so the local view stays in landscape when
+ // transitioning from a landscape orientation to UpsideDown.
+ // We need to track the last landscape orientation to rotate the local view correctly.
+ if currentOrientation == .portraitUpsideDown, deviceOrientation.isLandscape {
+ previousOrientationBeforeUpsideDown = deviceOrientation
+ } else if currentOrientation != .portraitUpsideDown {
+ previousOrientationBeforeUpsideDown = nil
+ }
+
+ deviceOrientation = currentOrientation
+ updateVideoRotationBasedOnDeviceOrientation()
}
func updateVideoRotationBasedOnDeviceOrientation() {