diff --git a/submodules/Camera/Sources/Camera.swift b/submodules/Camera/Sources/Camera.swift index b09013873d..3de1bfe9f3 100644 --- a/submodules/Camera/Sources/Camera.swift +++ b/submodules/Camera/Sources/Camera.swift @@ -95,7 +95,7 @@ final class CameraDeviceContext { return 30.0 } switch DeviceModel.current { - case .iPhone14ProMax, .iPhone13ProMax: + case .iPhone15ProMax, .iPhone14ProMax, .iPhone13ProMax: return 60.0 default: return 30.0 diff --git a/submodules/Camera/Sources/CameraDevice.swift b/submodules/Camera/Sources/CameraDevice.swift index 203e3263b1..691f9c87bf 100644 --- a/submodules/Camera/Sources/CameraDevice.swift +++ b/submodules/Camera/Sources/CameraDevice.swift @@ -152,6 +152,10 @@ final class CameraDevice { if device.isLowLightBoostSupported { device.automaticallyEnablesLowLightBoostWhenAvailable = true } + + if device.isExposureModeSupported(.continuousAutoExposure) { + device.exposureMode = .continuousAutoExposure + } } } diff --git a/submodules/Camera/Sources/CameraMetrics.swift b/submodules/Camera/Sources/CameraMetrics.swift index f4bc7f8a7c..8bef2e9d07 100644 --- a/submodules/Camera/Sources/CameraMetrics.swift +++ b/submodules/Camera/Sources/CameraMetrics.swift @@ -7,6 +7,10 @@ public extension Camera { case iPhone14Plus case iPhone14Pro case iPhone14ProMax + case iPhone15 + case iPhone15Plus + case iPhone15Pro + case iPhone15ProMax case unknown init(model: DeviceModel) { @@ -21,6 +25,14 @@ public extension Camera { self = .iPhone14Pro case .iPhone14ProMax: self = .iPhone14ProMax + case .iPhone15: + self = .iPhone15 + case .iPhone15Plus: + self = .iPhone15Plus + case .iPhone15Pro: + self = .iPhone15Pro + case .iPhone15ProMax: + self = .iPhone15ProMax case .unknown: self = .unknown default: @@ -32,13 +44,9 @@ public extension Camera { switch self { case .singleCamera: return [1.0] - case .iPhone14: + case .iPhone14, .iPhone14Plus, .iPhone15, .iPhone15Plus: return [0.5, 1.0, 2.0] - case .iPhone14Plus: - return [0.5, 1.0, 2.0] - case .iPhone14Pro: - return [0.5, 1.0, 2.0, 3.0] - case .iPhone14ProMax: + case .iPhone14Pro, .iPhone14ProMax, .iPhone15Pro, .iPhone15ProMax: return [0.5, 1.0, 2.0, 3.0] case .unknown: return [1.0, 2.0] @@ -91,7 +99,11 @@ enum DeviceModel: CaseIterable, Equatable { .iPhone14, .iPhone14Plus, .iPhone14Pro, - .iPhone14ProMax + .iPhone14ProMax, + .iPhone15, + .iPhone15Plus, + .iPhone15Pro, + .iPhone15ProMax ] } @@ -154,6 +166,11 @@ enum DeviceModel: CaseIterable, Equatable { case iPhone14Pro case iPhone14ProMax + case iPhone15 + case iPhone15Plus + case iPhone15Pro + case iPhone15ProMax + case unknown(String) var modelId: [String] { @@ -248,6 +265,14 @@ enum DeviceModel: CaseIterable, Equatable { return ["iPhone15,2"] case .iPhone14ProMax: return ["iPhone15,3"] + case .iPhone15: + return ["iPhone15,4"] + case .iPhone15Plus: + return ["iPhone15,5"] + case .iPhone15Pro: + return ["iPhone16,1"] + case .iPhone15ProMax: + return ["iPhone16,2"] case let .unknown(modelId): return [modelId] } @@ -345,6 +370,14 @@ enum DeviceModel: CaseIterable, Equatable { return "iPhone 14 Pro" case .iPhone14ProMax: return "iPhone 14 Pro Max" + case .iPhone15: + return "iPhone 15" + case .iPhone15Plus: + return "iPhone 15 Plus" + case .iPhone15Pro: + return "iPhone 15 Pro" + case .iPhone15ProMax: + return "iPhone 15 Pro Max" case let .unknown(modelId): if modelId.hasPrefix("iPhone") { return "Unknown iPhone" diff --git a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/PGCamera.h b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/PGCamera.h index 16113759ff..9fa2410cae 100644 --- a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/PGCamera.h +++ b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/PGCamera.h @@ -48,7 +48,7 @@ typedef enum @class PGCameraDeviceAngleSampler; @class TGCameraPreviewView; -@interface PGCamera : NSObject +@interface PGCamera : NSObject @property (readonly, nonatomic) PGCameraCaptureSession *captureSession; @property (readonly, nonatomic) PGCameraDeviceAngleSampler *deviceAngleSampler; diff --git a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/PGCameraCaptureSession.h b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/PGCameraCaptureSession.h index ee08d0cb83..e8854fd941 100644 --- a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/PGCameraCaptureSession.h +++ b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/PGCameraCaptureSession.h @@ -9,10 +9,8 @@ @interface PGCameraCaptureSession : AVCaptureSession @property (nonatomic, readonly) AVCaptureDevice *videoDevice; -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" -@property (nonatomic, readonly) AVCaptureStillImageOutput *imageOutput; -#pragma clang diagnostic pop + +@property (nonatomic, readonly) AVCapturePhotoOutput *imageOutput; @property (nonatomic, readonly) AVCaptureVideoDataOutput *videoOutput; @property (nonatomic, readonly) AVCaptureAudioDataOutput *audioOutput; @property (nonatomic, readonly) AVCaptureMetadataOutput *metadataOutput; diff --git a/submodules/LegacyComponents/Sources/PGCamera.m b/submodules/LegacyComponents/Sources/PGCamera.m index 446282eb11..407f8f1cf7 100644 --- a/submodules/LegacyComponents/Sources/PGCamera.m +++ b/submodules/LegacyComponents/Sources/PGCamera.m @@ -16,7 +16,7 @@ NSString *const PGCameraTorchActiveKey = @"torchActive"; NSString *const PGCameraTorchAvailableKey = @"torchAvailable"; NSString *const PGCameraAdjustingFocusKey = @"adjustingFocus"; -@interface PGCamera () +@interface PGCamera () { dispatch_queue_t cameraProcessingQueue; dispatch_queue_t audioProcessingQueue; @@ -34,11 +34,16 @@ NSString *const PGCameraAdjustingFocusKey = @"adjustingFocus"; bool _capturing; bool _moment; - + TGCameraPreviewView *_previewView; + UIInterfaceOrientation _currentPhotoOrientation; + NSTimeInterval _captureStartTime; } + +@property (nonatomic, copy) void(^photoCaptureCompletionBlock)(UIImage *image, PGCameraShotMetadata *metadata); + @end @implementation PGCamera @@ -367,57 +372,57 @@ NSString *const PGCameraAdjustingFocusKey = @"adjustingFocus"; { bool videoMirrored = !self.disableResultMirroring ? _previewView.captureConnection.videoMirrored : false; - [[PGCameraCaptureSession cameraQueue] dispatch:^ + void (^takePhoto)(void) = ^ { - if (!self.captureSession.isRunning || self.captureSession.imageOutput.isCapturingStillImage || _invalidated) - return; - - void (^takePhoto)(void) = ^ + self.photoCaptureCompletionBlock = completion; + [[PGCameraCaptureSession cameraQueue] dispatch:^ { + if (!self.captureSession.isRunning || _invalidated) + return; + AVCaptureConnection *imageConnection = [self.captureSession.imageOutput connectionWithMediaType:AVMediaTypeVideo]; [imageConnection setVideoMirrored:videoMirrored]; UIInterfaceOrientation orientation = UIInterfaceOrientationPortrait; if (self.requestedCurrentInterfaceOrientation != nil) orientation = self.requestedCurrentInterfaceOrientation(NULL); - [imageConnection setVideoOrientation:[PGCamera _videoOrientationForInterfaceOrientation:orientation mirrored:false]]; - [self.captureSession.imageOutput captureStillImageAsynchronouslyFromConnection:self.captureSession.imageOutput.connections.firstObject completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) - { - if (imageDataSampleBuffer != NULL && error == nil) - { - NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer]; - UIImage *image = [[UIImage alloc] initWithData:imageData]; - - if (self.cameraMode == PGCameraModeSquarePhoto || self.cameraMode == PGCameraModeSquareVideo || self.cameraMode == PGCameraModeSquareSwing) - { - CGFloat shorterSide = MIN(image.size.width, image.size.height); - CGFloat longerSide = MAX(image.size.width, image.size.height); - - CGRect cropRect = CGRectMake(CGFloor((longerSide - shorterSide) / 2.0f), 0, shorterSide, shorterSide); - CGImageRef croppedCGImage = CGImageCreateWithImageInRect(image.CGImage, cropRect); - image = [UIImage imageWithCGImage:croppedCGImage scale:image.scale orientation:image.imageOrientation]; - CGImageRelease(croppedCGImage); - } - - PGCameraShotMetadata *metadata = [[PGCameraShotMetadata alloc] init]; - metadata.deviceAngle = [PGCameraShotMetadata relativeDeviceAngleFromAngle:_deviceAngleSampler.currentDeviceAngle orientation:orientation]; - - image = [self normalizeImageOrientation:image]; - - if (completion != nil) - completion(image, metadata); - } - }]; - }; - - NSTimeInterval delta = CFAbsoluteTimeGetCurrent() - _captureStartTime; - if (CFAbsoluteTimeGetCurrent() - _captureStartTime > 0.4) - takePhoto(); - else - TGDispatchAfter(0.4 - delta, [[PGCameraCaptureSession cameraQueue] _dispatch_queue], takePhoto); - }]; + _currentPhotoOrientation = orientation; + + AVCapturePhotoSettings *photoSettings = [AVCapturePhotoSettings photoSettings]; + [self.captureSession.imageOutput capturePhotoWithSettings:photoSettings delegate:self]; + }]; + }; + + NSTimeInterval delta = CFAbsoluteTimeGetCurrent() - _captureStartTime; + if (CFAbsoluteTimeGetCurrent() - _captureStartTime > 0.4) + takePhoto(); + else + TGDispatchAfter(0.4 - delta, [[PGCameraCaptureSession cameraQueue] _dispatch_queue], takePhoto); +} + +- (void)captureOutput:(AVCapturePhotoOutput *)output didFinishProcessingPhoto:(AVCapturePhoto *)photo error:(NSError *)error { + if (error) { + NSLog(@"Error capturing photo: %@", error); + return; + } + + NSData *photoData = [photo fileDataRepresentation]; + UIImage *capturedImage = [UIImage imageWithData:photoData]; + + PGCameraShotMetadata *metadata = [[PGCameraShotMetadata alloc] init]; + metadata.deviceAngle = [PGCameraShotMetadata relativeDeviceAngleFromAngle:_deviceAngleSampler.currentDeviceAngle orientation:_currentPhotoOrientation]; + + UIImage *image = [self normalizeImageOrientation:capturedImage]; + + TGDispatchOnMainThread(^ + { + if (self.photoCaptureCompletionBlock != nil) { + self.photoCaptureCompletionBlock(image, metadata); + self.photoCaptureCompletionBlock = nil; + } + }); } - (void)startVideoRecordingForMoment:(bool)moment completion:(void (^)(NSURL *, CGAffineTransform transform, CGSize dimensions, NSTimeInterval duration, bool success))completion diff --git a/submodules/LegacyComponents/Sources/PGCameraCaptureSession.m b/submodules/LegacyComponents/Sources/PGCameraCaptureSession.m index e071d81116..f34f96244a 100644 --- a/submodules/LegacyComponents/Sources/PGCameraCaptureSession.m +++ b/submodules/LegacyComponents/Sources/PGCameraCaptureSession.m @@ -130,8 +130,10 @@ const NSInteger PGCameraFrameRate = 30; [self setFrameRate:PGCameraFrameRate forDevice:_videoDevice]; } - AVCaptureStillImageOutput *imageOutput = [[AVCaptureStillImageOutput alloc] init]; - [imageOutput setOutputSettings:@{AVVideoCodecKey : AVVideoCodecJPEG}]; + AVCapturePhotoOutput *imageOutput = [[AVCapturePhotoOutput alloc] init]; + if (@available(iOS 13.0, *)) { + [imageOutput setMaxPhotoQualityPrioritization:AVCapturePhotoQualityPrioritizationBalanced]; + } if ([self canAddOutput:imageOutput]) { #if !TARGET_IPHONE_SIMULATOR