| 
									
										
										
										
											2023-10-13 18:33:20 +02:00
										 |  |  | // | 
					
						
							|  |  |  | //  AVCaptureOutput+mirror.swift | 
					
						
							|  |  |  | //  mrousavy | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //  Created by Marc Rousavy on 18.01.21. | 
					
						
							|  |  |  | //  Copyright © 2021 mrousavy. All rights reserved. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import AVFoundation | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | extension AVCaptureOutput { | 
					
						
							|  |  |  |   /**
 | 
					
						
							|  |  |  |    Mirrors the video output if possible. | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   func mirror() { | 
					
						
							| 
									
										
										
										
											2024-01-16 18:01:41 +01:00
										 |  |  |     for connection in connections { | 
					
						
							| 
									
										
										
										
											2023-10-13 18:33:20 +02:00
										 |  |  |       if connection.isVideoMirroringSupported { | 
					
						
							|  |  |  |         connection.automaticallyAdjustsVideoMirroring = false | 
					
						
							|  |  |  |         connection.isVideoMirrored = true | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /**
 | 
					
						
							|  |  |  |    Sets the target orientation of the video output. | 
					
						
							|  |  |  |    This does not always physically rotate image buffers. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    - For Preview, an orientation hint is used to rotate the layer/view itself. | 
					
						
							|  |  |  |    - For Photos, an EXIF tag is used. | 
					
						
							|  |  |  |    - For Videos, the buffers are physically rotated if available, since we use an AVCaptureVideoDataOutput instead of an AVCaptureMovieFileOutput. | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   func setOrientation(_ orientation: Orientation) { | 
					
						
							|  |  |  |     // Set orientation for each connection | 
					
						
							| 
									
										
										
										
											2024-01-16 18:01:41 +01:00
										 |  |  |     for connection in connections { | 
					
						
							| 
									
										
										
										
											2024-08-02 14:39:23 +01:00
										 |  |  |       connection.setOrientation(orientation) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | extension AVCaptureConnection { | 
					
						
							|  |  |  |   func setOrientation(_ orientation: Orientation) { | 
					
						
							|  |  |  |     #if swift(>=5.9) | 
					
						
							|  |  |  |       if #available(iOS 17.0, *) { | 
					
						
							|  |  |  |         // Camera Sensors are always in landscape rotation (90deg). | 
					
						
							|  |  |  |         // We are setting the target rotation here, so we need to rotate by landscape once. | 
					
						
							|  |  |  |         let cameraOrientation = orientation.rotateBy(orientation: .landscapeLeft) | 
					
						
							|  |  |  |         let degrees = cameraOrientation.toDegrees() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // TODO: Don't rotate the video output because it adds overhead. Instead just use EXIF flags for the .mp4 file if recording. | 
					
						
							|  |  |  |         //       Does that work when we flip the camera? | 
					
						
							|  |  |  |         if isVideoRotationAngleSupported(degrees) { | 
					
						
							|  |  |  |           videoRotationAngle = degrees | 
					
						
							| 
									
										
										
										
											2023-10-14 13:17:14 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2024-08-02 14:39:23 +01:00
										 |  |  |       } else { | 
					
						
							|  |  |  |         if isVideoOrientationSupported { | 
					
						
							|  |  |  |           videoOrientation = orientation.toAVCaptureVideoOrientation() | 
					
						
							| 
									
										
										
										
											2023-10-14 13:17:14 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2024-08-02 14:39:23 +01:00
										 |  |  |       } | 
					
						
							|  |  |  |     #else | 
					
						
							|  |  |  |       if isVideoOrientationSupported { | 
					
						
							|  |  |  |         videoOrientation = orientation.toAVCaptureVideoOrientation() | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     #endif | 
					
						
							| 
									
										
										
										
											2023-10-13 18:33:20 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | } |