mirror of
https://github.com/TelegramMessenger/Telegram-iOS.git
synced 2026-07-05 19:28:46 +02:00
Various fixes
This commit is contained in:
parent
d25010c1cb
commit
37d1e2d93e
7 changed files with 69 additions and 33 deletions
|
|
@ -278,7 +278,6 @@ private final class CameraContext {
|
|||
self._positionPromise.set(targetPosition)
|
||||
self.modeChange = .position
|
||||
|
||||
|
||||
let preferWide = self.initialConfiguration.preferWide || isRoundVideo
|
||||
let preferLowerFramerate = self.initialConfiguration.preferLowerFramerate || isRoundVideo
|
||||
|
||||
|
|
@ -567,6 +566,11 @@ private final class CameraContext {
|
|||
return .finished(mainImage, additionalImage, CACurrentMediaTime())
|
||||
}
|
||||
} else {
|
||||
if case .failed = main {
|
||||
return .failed
|
||||
} else if case .failed = additional {
|
||||
return .failed
|
||||
}
|
||||
return .began
|
||||
}
|
||||
} |> distinctUntilChanged
|
||||
|
|
@ -585,6 +589,10 @@ private final class CameraContext {
|
|||
mainDeviceContext.device.setTorchMode(self._flashMode)
|
||||
}
|
||||
|
||||
let timestamp = CACurrentMediaTime() + 2.0
|
||||
self.lastSnapshotTimestamp = timestamp
|
||||
self.lastAdditionalSnapshotTimestamp = timestamp
|
||||
|
||||
let orientation = self.simplePreviewView?.videoPreviewLayer.connection?.videoOrientation ?? .portrait
|
||||
if self.initialConfiguration.isRoundVideo {
|
||||
return mainDeviceContext.output.startRecording(mode: .roundVideo, orientation: DeviceModel.current.isIpad ? orientation : .portrait, additionalOutput: self.additionalDeviceContext?.output)
|
||||
|
|
@ -790,6 +798,11 @@ public final class Camera {
|
|||
secondaryPreviewView.setSession(session.session, autoConnect: false)
|
||||
}
|
||||
|
||||
if #available(iOS 14.5, *), configuration.isRoundVideo {
|
||||
AVCaptureDevice.centerStageControlMode = .app
|
||||
AVCaptureDevice.isCenterStageEnabled = false
|
||||
}
|
||||
|
||||
self.queue.async {
|
||||
let context = CameraContext(queue: self.queue, session: session, configuration: configuration, metrics: self.metrics, previewView: previewView, secondaryPreviewView: secondaryPreviewView)
|
||||
self.contextRef = Unmanaged.passRetained(context)
|
||||
|
|
@ -803,6 +816,10 @@ public final class Camera {
|
|||
self.queue.async {
|
||||
contextRef?.release()
|
||||
}
|
||||
|
||||
if #available(iOS 14.5, *) {
|
||||
AVCaptureDevice.centerStageControlMode = .user
|
||||
}
|
||||
}
|
||||
|
||||
public func startCapture() {
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ final class CameraDevice {
|
|||
if device.isLowLightBoostSupported {
|
||||
device.automaticallyEnablesLowLightBoostWhenAvailable = true
|
||||
}
|
||||
|
||||
|
||||
if device.isExposureModeSupported(.continuousAutoExposure) {
|
||||
device.exposureMode = .continuousAutoExposure
|
||||
}
|
||||
|
|
@ -185,7 +185,7 @@ final class CameraDevice {
|
|||
private(set) var fps: Double = defaultFPS
|
||||
|
||||
func setFps(_ fps: Double) {
|
||||
guard let device = self.videoDevice, let targetFPS = device.actualFPS(Double(self.fps)) else {
|
||||
guard let device = self.videoDevice, let targetFPS = device.actualFPS(Double(fps)) else {
|
||||
return
|
||||
}
|
||||
self.fps = targetFPS.fps
|
||||
|
|
@ -305,7 +305,8 @@ final class CameraDevice {
|
|||
return
|
||||
}
|
||||
self.transaction(device) { device in
|
||||
device.videoZoomFactor = max(device.neutralZoomFactor, min(10.0, device.neutralZoomFactor + zoomLevel))
|
||||
let target = device.neutralZoomFactor + zoomLevel
|
||||
device.videoZoomFactor = self.clampedZoomFactor(target, for: device)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -314,7 +315,8 @@ final class CameraDevice {
|
|||
return
|
||||
}
|
||||
self.transaction(device) { device in
|
||||
device.videoZoomFactor = max(1.0, min(10.0, device.videoZoomFactor * zoomDelta))
|
||||
let target = device.videoZoomFactor * zoomDelta
|
||||
device.videoZoomFactor = self.clampedZoomFactor(target, for: device)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -323,7 +325,8 @@ final class CameraDevice {
|
|||
return
|
||||
}
|
||||
self.transaction(device) { device in
|
||||
device.ramp(toVideoZoomFactor: zoomLevel, withRate: Float(rate))
|
||||
let target = self.clampedZoomFactor(zoomLevel, for: device)
|
||||
device.ramp(toVideoZoomFactor: target, withRate: Float(rate))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -332,7 +335,14 @@ final class CameraDevice {
|
|||
return
|
||||
}
|
||||
self.transaction(device) { device in
|
||||
device.videoZoomFactor = neutral ? device.neutralZoomFactor : device.minAvailableVideoZoomFactor
|
||||
let target = neutral ? device.neutralZoomFactor : device.minAvailableVideoZoomFactor
|
||||
device.videoZoomFactor = self.clampedZoomFactor(target, for: device)
|
||||
}
|
||||
}
|
||||
|
||||
private func clampedZoomFactor(_ value: CGFloat, for device: AVCaptureDevice) -> CGFloat {
|
||||
let minimum = max(1.0, device.minAvailableVideoZoomFactor)
|
||||
let maximum = max(minimum, device.maxAvailableVideoZoomFactor)
|
||||
return min(maximum, max(minimum, value))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,11 +15,14 @@ class CameraInput {
|
|||
}
|
||||
|
||||
func invalidate(for session: CameraSession, switchAudio: Bool = true) {
|
||||
for input in session.session.inputs {
|
||||
if !switchAudio && input === self.audioInput {
|
||||
continue
|
||||
}
|
||||
session.session.removeInput(input)
|
||||
if let videoInput = self.videoInput, session.session.inputs.contains(where: { $0 === videoInput }) {
|
||||
session.session.removeInput(videoInput)
|
||||
}
|
||||
self.videoInput = nil
|
||||
|
||||
if switchAudio, let audioInput = self.audioInput, session.session.inputs.contains(where: { $0 === audioInput }) {
|
||||
session.session.removeInput(audioInput)
|
||||
self.audioInput = nil
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -192,9 +192,9 @@ final class CameraOutput: NSObject {
|
|||
}
|
||||
|
||||
if #available(iOS 13.0, *), session.hasMultiCam {
|
||||
if let device = device.videoDevice, let ports = input.videoInput?.ports(for: AVMediaType.video, sourceDeviceType: device.deviceType, sourceDevicePosition: device.position) {
|
||||
if let device = device.videoDevice, let ports = input.videoInput?.ports(for: AVMediaType.video, sourceDeviceType: device.deviceType, sourceDevicePosition: device.position), let firstPort = ports.first {
|
||||
if let previewView {
|
||||
let previewConnection = AVCaptureConnection(inputPort: ports.first!, videoPreviewLayer: previewView.videoPreviewLayer)
|
||||
let previewConnection = AVCaptureConnection(inputPort: firstPort, videoPreviewLayer: previewView.videoPreviewLayer)
|
||||
if session.session.canAddConnection(previewConnection) {
|
||||
session.session.addConnection(previewConnection)
|
||||
self.previewConnection = previewConnection
|
||||
|
|
@ -447,7 +447,7 @@ final class CameraOutput: NSObject {
|
|||
}
|
||||
|
||||
return Signal { subscriber in
|
||||
let timer = SwiftSignalKit.Timer(timeout: 0.1, repeat: true, completion: { [weak videoRecorder] in
|
||||
let timer = SwiftSignalKit.Timer(timeout: 0.09, repeat: true, completion: { [weak videoRecorder] in
|
||||
let recordingData = CameraRecordingData(duration: videoRecorder?.duration ?? 0.0, filePath: outputFilePath)
|
||||
subscriber.putNext(recordingData)
|
||||
}, queue: Queue.mainQueue())
|
||||
|
|
@ -473,11 +473,7 @@ final class CameraOutput: NSObject {
|
|||
}
|
||||
|
||||
var transitionImage: UIImage? {
|
||||
var result: UIImage?
|
||||
self.videoQueue.sync {
|
||||
result = self.videoRecorder?.transitionImage
|
||||
}
|
||||
return result
|
||||
return self.videoRecorder?.transitionImage
|
||||
}
|
||||
|
||||
private weak var masterOutput: CameraOutput?
|
||||
|
|
@ -705,7 +701,7 @@ extension CameraOutput: AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureA
|
|||
|
||||
func captureOutput(_ output: AVCaptureOutput, didDrop sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
|
||||
if #available(iOS 13.0, *) {
|
||||
Logger.shared.log("VideoRecorder", "Dropped sample buffer \(sampleBuffer.attachments)")
|
||||
Logger.shared.log("Camera", "Dropped sample buffer \(sampleBuffer.attachments)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -232,7 +232,9 @@ private final class VideoRecorderImpl {
|
|||
} else if self.orientation == .portraitUpsideDown {
|
||||
orientation = .left
|
||||
}
|
||||
self.transitionImage = UIImage(cgImage: cgImage, scale: 1.0, orientation: orientation)
|
||||
Queue.mainQueue().async {
|
||||
self.transitionImage = UIImage(cgImage: cgImage, scale: 1.0, orientation: orientation)
|
||||
}
|
||||
} else {
|
||||
self.savedTransitionImage = false
|
||||
}
|
||||
|
|
@ -375,21 +377,21 @@ private final class VideoRecorderImpl {
|
|||
dispatchPrecondition(condition: .onQueue(self.queue))
|
||||
let completion = self.completion
|
||||
if self.recordingStopSampleTime == .invalid {
|
||||
DispatchQueue.main.async {
|
||||
Queue.mainQueue().async {
|
||||
completion(false, nil, nil)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if let _ = self.error.with({ $0 }) {
|
||||
DispatchQueue.main.async {
|
||||
Queue.mainQueue().async {
|
||||
completion(false, nil, nil)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if !self.tryAppendingPendingAudioBuffers() {
|
||||
DispatchQueue.main.async {
|
||||
Queue.mainQueue().async {
|
||||
completion(false, nil, nil)
|
||||
}
|
||||
return
|
||||
|
|
@ -398,21 +400,21 @@ private final class VideoRecorderImpl {
|
|||
if self.assetWriter.status == .writing {
|
||||
self.assetWriter.finishWriting {
|
||||
if let _ = self.assetWriter.error {
|
||||
DispatchQueue.main.async {
|
||||
Queue.mainQueue().async {
|
||||
completion(false, nil, nil)
|
||||
}
|
||||
} else {
|
||||
DispatchQueue.main.async {
|
||||
Queue.mainQueue().async {
|
||||
completion(true, self.transitionImage, self.positionChangeTimestamps)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if let _ = self.assetWriter.error {
|
||||
DispatchQueue.main.async {
|
||||
Queue.mainQueue().async {
|
||||
completion(false, nil, nil)
|
||||
}
|
||||
} else {
|
||||
DispatchQueue.main.async {
|
||||
Queue.mainQueue().async {
|
||||
completion(false, nil, nil)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2751,6 +2751,8 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus
|
|||
return CGRectMake(0, 82, screenSize.width, screenSize.height - 82 - 83);
|
||||
else if (widescreenWidth == 926.0f)
|
||||
return CGRectMake(0, 82, screenSize.width, screenSize.height - 82 - 83);
|
||||
else if (widescreenWidth == 912.0f)
|
||||
return CGRectMake(0, 82, screenSize.width, screenSize.height - 82 - 83);
|
||||
else if (widescreenWidth == 896.0f)
|
||||
return CGRectMake(0, 77, screenSize.width, screenSize.height - 77 - 83);
|
||||
else if (widescreenWidth == 874.0f)
|
||||
|
|
@ -2784,6 +2786,8 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus
|
|||
return CGRectMake(0, 136, screenSize.width, screenSize.height - 136 - 223);
|
||||
else if (widescreenWidth == 926.0f)
|
||||
return CGRectMake(0, 121, screenSize.width, screenSize.height - 121 - 234);
|
||||
else if (widescreenWidth == 912.0f)
|
||||
return CGRectMake(0, 136, screenSize.width, screenSize.height - 136 - 216);
|
||||
else if (widescreenWidth == 896.0f)
|
||||
return CGRectMake(0, 121, screenSize.width, screenSize.height - 121 - 223);
|
||||
else if (widescreenWidth == 874.0f)
|
||||
|
|
|
|||
|
|
@ -575,14 +575,18 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent {
|
|||
|
||||
if !component.isPreviewing {
|
||||
if case .on = component.cameraState.flashMode, case .front = component.cameraState.position {
|
||||
let frontFlashPosition = CGPoint(x: component.previewFrame.midX, y: component.previewFrame.midY)
|
||||
let frontFlashSize = CGSize(
|
||||
width: max(abs(frontFlashPosition.x), abs(context.availableSize.width - frontFlashPosition.x)) * 2.0,
|
||||
height: max(abs(frontFlashPosition.y), abs(context.availableSize.height - frontFlashPosition.y)) * 2.0
|
||||
)
|
||||
let frontFlash = frontFlash.update(
|
||||
component: Image(image: state.image(.flashImage, theme: environment.theme), tintColor: component.cameraState.flashTint.color),
|
||||
availableSize: context.availableSize,
|
||||
component: Image(image: state.image(.flashImage, theme: environment.theme), tintColor: component.cameraState.flashTint.color, contentMode: .scaleAspectFill),
|
||||
availableSize: frontFlashSize,
|
||||
transition: .easeInOut(duration: 0.2)
|
||||
)
|
||||
let frontFlashFrame = CGRect(origin: CGPoint(), size: context.availableSize)
|
||||
context.add(frontFlash
|
||||
.position(frontFlashFrame.center)
|
||||
.position(frontFlashPosition)
|
||||
.scale(1.5 - component.cameraState.flashTintSize * 0.5)
|
||||
.appear(.default(alpha: true))
|
||||
.disappear(ComponentTransition.Disappear({ view, transition, completion in
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue