mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Camera fixes
This commit is contained in:
parent
0a2532b802
commit
df13a48bf7
@ -95,7 +95,7 @@ final class CameraDeviceContext {
|
|||||||
return 30.0
|
return 30.0
|
||||||
}
|
}
|
||||||
switch DeviceModel.current {
|
switch DeviceModel.current {
|
||||||
case .iPhone14ProMax, .iPhone13ProMax:
|
case .iPhone15ProMax, .iPhone14ProMax, .iPhone13ProMax:
|
||||||
return 60.0
|
return 60.0
|
||||||
default:
|
default:
|
||||||
return 30.0
|
return 30.0
|
||||||
|
@ -152,6 +152,10 @@ final class CameraDevice {
|
|||||||
if device.isLowLightBoostSupported {
|
if device.isLowLightBoostSupported {
|
||||||
device.automaticallyEnablesLowLightBoostWhenAvailable = true
|
device.automaticallyEnablesLowLightBoostWhenAvailable = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if device.isExposureModeSupported(.continuousAutoExposure) {
|
||||||
|
device.exposureMode = .continuousAutoExposure
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,10 @@ public extension Camera {
|
|||||||
case iPhone14Plus
|
case iPhone14Plus
|
||||||
case iPhone14Pro
|
case iPhone14Pro
|
||||||
case iPhone14ProMax
|
case iPhone14ProMax
|
||||||
|
case iPhone15
|
||||||
|
case iPhone15Plus
|
||||||
|
case iPhone15Pro
|
||||||
|
case iPhone15ProMax
|
||||||
case unknown
|
case unknown
|
||||||
|
|
||||||
init(model: DeviceModel) {
|
init(model: DeviceModel) {
|
||||||
@ -21,6 +25,14 @@ public extension Camera {
|
|||||||
self = .iPhone14Pro
|
self = .iPhone14Pro
|
||||||
case .iPhone14ProMax:
|
case .iPhone14ProMax:
|
||||||
self = .iPhone14ProMax
|
self = .iPhone14ProMax
|
||||||
|
case .iPhone15:
|
||||||
|
self = .iPhone15
|
||||||
|
case .iPhone15Plus:
|
||||||
|
self = .iPhone15Plus
|
||||||
|
case .iPhone15Pro:
|
||||||
|
self = .iPhone15Pro
|
||||||
|
case .iPhone15ProMax:
|
||||||
|
self = .iPhone15ProMax
|
||||||
case .unknown:
|
case .unknown:
|
||||||
self = .unknown
|
self = .unknown
|
||||||
default:
|
default:
|
||||||
@ -32,13 +44,9 @@ public extension Camera {
|
|||||||
switch self {
|
switch self {
|
||||||
case .singleCamera:
|
case .singleCamera:
|
||||||
return [1.0]
|
return [1.0]
|
||||||
case .iPhone14:
|
case .iPhone14, .iPhone14Plus, .iPhone15, .iPhone15Plus:
|
||||||
return [0.5, 1.0, 2.0]
|
return [0.5, 1.0, 2.0]
|
||||||
case .iPhone14Plus:
|
case .iPhone14Pro, .iPhone14ProMax, .iPhone15Pro, .iPhone15ProMax:
|
||||||
return [0.5, 1.0, 2.0]
|
|
||||||
case .iPhone14Pro:
|
|
||||||
return [0.5, 1.0, 2.0, 3.0]
|
|
||||||
case .iPhone14ProMax:
|
|
||||||
return [0.5, 1.0, 2.0, 3.0]
|
return [0.5, 1.0, 2.0, 3.0]
|
||||||
case .unknown:
|
case .unknown:
|
||||||
return [1.0, 2.0]
|
return [1.0, 2.0]
|
||||||
@ -91,7 +99,11 @@ enum DeviceModel: CaseIterable, Equatable {
|
|||||||
.iPhone14,
|
.iPhone14,
|
||||||
.iPhone14Plus,
|
.iPhone14Plus,
|
||||||
.iPhone14Pro,
|
.iPhone14Pro,
|
||||||
.iPhone14ProMax
|
.iPhone14ProMax,
|
||||||
|
.iPhone15,
|
||||||
|
.iPhone15Plus,
|
||||||
|
.iPhone15Pro,
|
||||||
|
.iPhone15ProMax
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,6 +166,11 @@ enum DeviceModel: CaseIterable, Equatable {
|
|||||||
case iPhone14Pro
|
case iPhone14Pro
|
||||||
case iPhone14ProMax
|
case iPhone14ProMax
|
||||||
|
|
||||||
|
case iPhone15
|
||||||
|
case iPhone15Plus
|
||||||
|
case iPhone15Pro
|
||||||
|
case iPhone15ProMax
|
||||||
|
|
||||||
case unknown(String)
|
case unknown(String)
|
||||||
|
|
||||||
var modelId: [String] {
|
var modelId: [String] {
|
||||||
@ -248,6 +265,14 @@ enum DeviceModel: CaseIterable, Equatable {
|
|||||||
return ["iPhone15,2"]
|
return ["iPhone15,2"]
|
||||||
case .iPhone14ProMax:
|
case .iPhone14ProMax:
|
||||||
return ["iPhone15,3"]
|
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):
|
case let .unknown(modelId):
|
||||||
return [modelId]
|
return [modelId]
|
||||||
}
|
}
|
||||||
@ -345,6 +370,14 @@ enum DeviceModel: CaseIterable, Equatable {
|
|||||||
return "iPhone 14 Pro"
|
return "iPhone 14 Pro"
|
||||||
case .iPhone14ProMax:
|
case .iPhone14ProMax:
|
||||||
return "iPhone 14 Pro Max"
|
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):
|
case let .unknown(modelId):
|
||||||
if modelId.hasPrefix("iPhone") {
|
if modelId.hasPrefix("iPhone") {
|
||||||
return "Unknown iPhone"
|
return "Unknown iPhone"
|
||||||
|
@ -48,7 +48,7 @@ typedef enum
|
|||||||
@class PGCameraDeviceAngleSampler;
|
@class PGCameraDeviceAngleSampler;
|
||||||
@class TGCameraPreviewView;
|
@class TGCameraPreviewView;
|
||||||
|
|
||||||
@interface PGCamera : NSObject
|
@interface PGCamera : NSObject <AVCapturePhotoCaptureDelegate>
|
||||||
|
|
||||||
@property (readonly, nonatomic) PGCameraCaptureSession *captureSession;
|
@property (readonly, nonatomic) PGCameraCaptureSession *captureSession;
|
||||||
@property (readonly, nonatomic) PGCameraDeviceAngleSampler *deviceAngleSampler;
|
@property (readonly, nonatomic) PGCameraDeviceAngleSampler *deviceAngleSampler;
|
||||||
|
@ -9,10 +9,8 @@
|
|||||||
@interface PGCameraCaptureSession : AVCaptureSession
|
@interface PGCameraCaptureSession : AVCaptureSession
|
||||||
|
|
||||||
@property (nonatomic, readonly) AVCaptureDevice *videoDevice;
|
@property (nonatomic, readonly) AVCaptureDevice *videoDevice;
|
||||||
#pragma clang diagnostic push
|
|
||||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
@property (nonatomic, readonly) AVCapturePhotoOutput *imageOutput;
|
||||||
@property (nonatomic, readonly) AVCaptureStillImageOutput *imageOutput;
|
|
||||||
#pragma clang diagnostic pop
|
|
||||||
@property (nonatomic, readonly) AVCaptureVideoDataOutput *videoOutput;
|
@property (nonatomic, readonly) AVCaptureVideoDataOutput *videoOutput;
|
||||||
@property (nonatomic, readonly) AVCaptureAudioDataOutput *audioOutput;
|
@property (nonatomic, readonly) AVCaptureAudioDataOutput *audioOutput;
|
||||||
@property (nonatomic, readonly) AVCaptureMetadataOutput *metadataOutput;
|
@property (nonatomic, readonly) AVCaptureMetadataOutput *metadataOutput;
|
||||||
|
@ -16,7 +16,7 @@ NSString *const PGCameraTorchActiveKey = @"torchActive";
|
|||||||
NSString *const PGCameraTorchAvailableKey = @"torchAvailable";
|
NSString *const PGCameraTorchAvailableKey = @"torchAvailable";
|
||||||
NSString *const PGCameraAdjustingFocusKey = @"adjustingFocus";
|
NSString *const PGCameraAdjustingFocusKey = @"adjustingFocus";
|
||||||
|
|
||||||
@interface PGCamera ()
|
@interface PGCamera ()
|
||||||
{
|
{
|
||||||
dispatch_queue_t cameraProcessingQueue;
|
dispatch_queue_t cameraProcessingQueue;
|
||||||
dispatch_queue_t audioProcessingQueue;
|
dispatch_queue_t audioProcessingQueue;
|
||||||
@ -34,11 +34,16 @@ NSString *const PGCameraAdjustingFocusKey = @"adjustingFocus";
|
|||||||
|
|
||||||
bool _capturing;
|
bool _capturing;
|
||||||
bool _moment;
|
bool _moment;
|
||||||
|
|
||||||
TGCameraPreviewView *_previewView;
|
TGCameraPreviewView *_previewView;
|
||||||
|
|
||||||
|
UIInterfaceOrientation _currentPhotoOrientation;
|
||||||
|
|
||||||
NSTimeInterval _captureStartTime;
|
NSTimeInterval _captureStartTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@property (nonatomic, copy) void(^photoCaptureCompletionBlock)(UIImage *image, PGCameraShotMetadata *metadata);
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation PGCamera
|
@implementation PGCamera
|
||||||
@ -367,57 +372,57 @@ NSString *const PGCameraAdjustingFocusKey = @"adjustingFocus";
|
|||||||
{
|
{
|
||||||
bool videoMirrored = !self.disableResultMirroring ? _previewView.captureConnection.videoMirrored : false;
|
bool videoMirrored = !self.disableResultMirroring ? _previewView.captureConnection.videoMirrored : false;
|
||||||
|
|
||||||
[[PGCameraCaptureSession cameraQueue] dispatch:^
|
void (^takePhoto)(void) = ^
|
||||||
{
|
{
|
||||||
if (!self.captureSession.isRunning || self.captureSession.imageOutput.isCapturingStillImage || _invalidated)
|
self.photoCaptureCompletionBlock = completion;
|
||||||
return;
|
[[PGCameraCaptureSession cameraQueue] dispatch:^
|
||||||
|
|
||||||
void (^takePhoto)(void) = ^
|
|
||||||
{
|
{
|
||||||
|
if (!self.captureSession.isRunning || _invalidated)
|
||||||
|
return;
|
||||||
|
|
||||||
AVCaptureConnection *imageConnection = [self.captureSession.imageOutput connectionWithMediaType:AVMediaTypeVideo];
|
AVCaptureConnection *imageConnection = [self.captureSession.imageOutput connectionWithMediaType:AVMediaTypeVideo];
|
||||||
[imageConnection setVideoMirrored:videoMirrored];
|
[imageConnection setVideoMirrored:videoMirrored];
|
||||||
|
|
||||||
UIInterfaceOrientation orientation = UIInterfaceOrientationPortrait;
|
UIInterfaceOrientation orientation = UIInterfaceOrientationPortrait;
|
||||||
if (self.requestedCurrentInterfaceOrientation != nil)
|
if (self.requestedCurrentInterfaceOrientation != nil)
|
||||||
orientation = self.requestedCurrentInterfaceOrientation(NULL);
|
orientation = self.requestedCurrentInterfaceOrientation(NULL);
|
||||||
|
|
||||||
[imageConnection setVideoOrientation:[PGCamera _videoOrientationForInterfaceOrientation:orientation mirrored:false]];
|
[imageConnection setVideoOrientation:[PGCamera _videoOrientationForInterfaceOrientation:orientation mirrored:false]];
|
||||||
|
|
||||||
[self.captureSession.imageOutput captureStillImageAsynchronouslyFromConnection:self.captureSession.imageOutput.connections.firstObject completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error)
|
_currentPhotoOrientation = orientation;
|
||||||
{
|
|
||||||
if (imageDataSampleBuffer != NULL && error == nil)
|
AVCapturePhotoSettings *photoSettings = [AVCapturePhotoSettings photoSettings];
|
||||||
{
|
[self.captureSession.imageOutput capturePhotoWithSettings:photoSettings delegate:self];
|
||||||
NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
|
}];
|
||||||
UIImage *image = [[UIImage alloc] initWithData:imageData];
|
};
|
||||||
|
|
||||||
if (self.cameraMode == PGCameraModeSquarePhoto || self.cameraMode == PGCameraModeSquareVideo || self.cameraMode == PGCameraModeSquareSwing)
|
NSTimeInterval delta = CFAbsoluteTimeGetCurrent() - _captureStartTime;
|
||||||
{
|
if (CFAbsoluteTimeGetCurrent() - _captureStartTime > 0.4)
|
||||||
CGFloat shorterSide = MIN(image.size.width, image.size.height);
|
takePhoto();
|
||||||
CGFloat longerSide = MAX(image.size.width, image.size.height);
|
else
|
||||||
|
TGDispatchAfter(0.4 - delta, [[PGCameraCaptureSession cameraQueue] _dispatch_queue], takePhoto);
|
||||||
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];
|
- (void)captureOutput:(AVCapturePhotoOutput *)output didFinishProcessingPhoto:(AVCapturePhoto *)photo error:(NSError *)error {
|
||||||
CGImageRelease(croppedCGImage);
|
if (error) {
|
||||||
}
|
NSLog(@"Error capturing photo: %@", error);
|
||||||
|
return;
|
||||||
PGCameraShotMetadata *metadata = [[PGCameraShotMetadata alloc] init];
|
}
|
||||||
metadata.deviceAngle = [PGCameraShotMetadata relativeDeviceAngleFromAngle:_deviceAngleSampler.currentDeviceAngle orientation:orientation];
|
|
||||||
|
NSData *photoData = [photo fileDataRepresentation];
|
||||||
image = [self normalizeImageOrientation:image];
|
UIImage *capturedImage = [UIImage imageWithData:photoData];
|
||||||
|
|
||||||
if (completion != nil)
|
PGCameraShotMetadata *metadata = [[PGCameraShotMetadata alloc] init];
|
||||||
completion(image, metadata);
|
metadata.deviceAngle = [PGCameraShotMetadata relativeDeviceAngleFromAngle:_deviceAngleSampler.currentDeviceAngle orientation:_currentPhotoOrientation];
|
||||||
}
|
|
||||||
}];
|
UIImage *image = [self normalizeImageOrientation:capturedImage];
|
||||||
};
|
|
||||||
|
TGDispatchOnMainThread(^
|
||||||
NSTimeInterval delta = CFAbsoluteTimeGetCurrent() - _captureStartTime;
|
{
|
||||||
if (CFAbsoluteTimeGetCurrent() - _captureStartTime > 0.4)
|
if (self.photoCaptureCompletionBlock != nil) {
|
||||||
takePhoto();
|
self.photoCaptureCompletionBlock(image, metadata);
|
||||||
else
|
self.photoCaptureCompletionBlock = nil;
|
||||||
TGDispatchAfter(0.4 - delta, [[PGCameraCaptureSession cameraQueue] _dispatch_queue], takePhoto);
|
}
|
||||||
}];
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)startVideoRecordingForMoment:(bool)moment completion:(void (^)(NSURL *, CGAffineTransform transform, CGSize dimensions, NSTimeInterval duration, bool success))completion
|
- (void)startVideoRecordingForMoment:(bool)moment completion:(void (^)(NSURL *, CGAffineTransform transform, CGSize dimensions, NSTimeInterval duration, bool success))completion
|
||||||
|
@ -130,8 +130,10 @@ const NSInteger PGCameraFrameRate = 30;
|
|||||||
[self setFrameRate:PGCameraFrameRate forDevice:_videoDevice];
|
[self setFrameRate:PGCameraFrameRate forDevice:_videoDevice];
|
||||||
}
|
}
|
||||||
|
|
||||||
AVCaptureStillImageOutput *imageOutput = [[AVCaptureStillImageOutput alloc] init];
|
AVCapturePhotoOutput *imageOutput = [[AVCapturePhotoOutput alloc] init];
|
||||||
[imageOutput setOutputSettings:@{AVVideoCodecKey : AVVideoCodecJPEG}];
|
if (@available(iOS 13.0, *)) {
|
||||||
|
[imageOutput setMaxPhotoQualityPrioritization:AVCapturePhotoQualityPrioritizationBalanced];
|
||||||
|
}
|
||||||
if ([self canAddOutput:imageOutput])
|
if ([self canAddOutput:imageOutput])
|
||||||
{
|
{
|
||||||
#if !TARGET_IPHONE_SIMULATOR
|
#if !TARGET_IPHONE_SIMULATOR
|
||||||
|
Loading…
x
Reference in New Issue
Block a user