Skip to content

Commit

Permalink
Cherry-pick various fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
laktyushin committed Jan 22, 2024
1 parent 1fb7544 commit 7d8de2a
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 85 deletions.
16 changes: 11 additions & 5 deletions submodules/Camera/Sources/Camera.swift
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,10 @@ private final class CameraContext {
var secondaryPreviewView: CameraSimplePreviewView?

private var lastSnapshotTimestamp: Double = CACurrentMediaTime()
private var savedSnapshot = false
private var lastAdditionalSnapshotTimestamp: Double = CACurrentMediaTime()
private var savedAdditionalSnapshot = false

private func savePreviewSnapshot(pixelBuffer: CVPixelBuffer, front: Bool) {
Queue.concurrentDefaultQueue().async {
var ciImage = CIImage(cvImageBuffer: pixelBuffer)
Expand All @@ -141,7 +144,7 @@ private final class CameraContext {
transform = CGAffineTransformTranslate(transform, 0.0, -size.height)
ciImage = ciImage.transformed(by: transform)
}
ciImage = ciImage.clampedToExtent().applyingGaussianBlur(sigma: 100.0).cropped(to: CGRect(origin: .zero, size: size))
ciImage = ciImage.clampedToExtent().applyingGaussianBlur(sigma: Camera.isDualCameraSupported ? 100.0 : 40.0).cropped(to: CGRect(origin: .zero, size: size))
if let cgImage = self.ciContext.createCGImage(ciImage, from: ciImage.extent) {
let uiImage = UIImage(cgImage: cgImage, scale: 1.0, orientation: .right)
if front {
Expand Down Expand Up @@ -330,27 +333,29 @@ private final class CameraContext {
return
}
let timestamp = CACurrentMediaTime()
if timestamp > self.lastSnapshotTimestamp + 2.5, !mainDeviceContext.output.isRecording {
if timestamp > self.lastSnapshotTimestamp + 2.5, !mainDeviceContext.output.isRecording || !self.savedSnapshot {
var front = false
if #available(iOS 13.0, *) {
front = connection.inputPorts.first?.sourceDevicePosition == .front
}
self.savePreviewSnapshot(pixelBuffer: pixelBuffer, front: front)
self.lastSnapshotTimestamp = timestamp
self.savedSnapshot = true
}
}
self.additionalDeviceContext?.output.processSampleBuffer = { [weak self] sampleBuffer, pixelBuffer, connection in
guard let self, let additionalDeviceContext = self.additionalDeviceContext else {
return
}
let timestamp = CACurrentMediaTime()
if timestamp > self.lastAdditionalSnapshotTimestamp + 2.5, !additionalDeviceContext.output.isRecording {
if timestamp > self.lastAdditionalSnapshotTimestamp + 2.5, !additionalDeviceContext.output.isRecording || !self.savedAdditionalSnapshot {
var front = false
if #available(iOS 13.0, *) {
front = connection.inputPorts.first?.sourceDevicePosition == .front
}
self.savePreviewSnapshot(pixelBuffer: pixelBuffer, front: front)
self.lastAdditionalSnapshotTimestamp = timestamp
self.savedAdditionalSnapshot = true
}
}
} else {
Expand All @@ -370,13 +375,14 @@ private final class CameraContext {
return
}
let timestamp = CACurrentMediaTime()
if timestamp > self.lastSnapshotTimestamp + 2.5, !mainDeviceContext.output.isRecording {
if timestamp > self.lastSnapshotTimestamp + 2.5, !mainDeviceContext.output.isRecording || !self.savedSnapshot {
var front = false
if #available(iOS 13.0, *) {
front = connection.inputPorts.first?.sourceDevicePosition == .front
}
self.savePreviewSnapshot(pixelBuffer: pixelBuffer, front: front)
self.lastSnapshotTimestamp = timestamp
self.savedSnapshot = true
}
}
if self.initialConfiguration.reportAudioLevel {
Expand Down Expand Up @@ -557,7 +563,7 @@ private final class CameraContext {

let orientation = self.simplePreviewView?.videoPreviewLayer.connection?.videoOrientation ?? .portrait
if self.initialConfiguration.isRoundVideo {
return mainDeviceContext.output.startRecording(mode: .roundVideo, orientation: .portrait, additionalOutput: self.additionalDeviceContext?.output)
return mainDeviceContext.output.startRecording(mode: .roundVideo, orientation: DeviceModel.current.isIpad ? orientation : .portrait, additionalOutput: self.additionalDeviceContext?.output)
} else {
if let additionalDeviceContext = self.additionalDeviceContext {
return combineLatest(
Expand Down
5 changes: 4 additions & 1 deletion submodules/Camera/Sources/CameraOutput.swift
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ final class CameraOutput: NSObject {

private var photoCaptureRequests: [Int64: PhotoCaptureContext] = [:]
private var videoRecorder: VideoRecorder?

private var captureOrientation: AVCaptureVideoOrientation = .portrait

var processSampleBuffer: ((CMSampleBuffer, CVImageBuffer, AVCaptureConnection) -> Void)?
var processAudioBuffer: ((CMSampleBuffer) -> Void)?
Expand Down Expand Up @@ -305,6 +307,7 @@ final class CameraOutput: NSObject {

self.currentMode = mode
self.lastSampleTimestamp = nil
self.captureOrientation = orientation

var orientation = orientation
let dimensions: CGSize
Expand Down Expand Up @@ -538,7 +541,7 @@ final class CameraOutput: NSObject {
if !filter.isPrepared {
filter.prepare(with: newFormatDescription, outputRetainedBufferCountHint: 3)
}
guard let newPixelBuffer = filter.render(pixelBuffer: videoPixelBuffer, additional: additional, transitionFactor: transitionFactor) else {
guard let newPixelBuffer = filter.render(pixelBuffer: videoPixelBuffer, additional: additional, captureOrientation: self.captureOrientation, transitionFactor: transitionFactor) else {
self.semaphore.signal()
return nil
}
Expand Down
30 changes: 26 additions & 4 deletions submodules/Camera/Sources/CameraRoundVideoFilter.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Foundation
import UIKit
import AVFoundation
import CoreImage
import CoreMedia
import CoreVideo
Expand Down Expand Up @@ -157,13 +158,29 @@ final class CameraRoundVideoFilter {
private var lastMainSourceImage: CIImage?
private var lastAdditionalSourceImage: CIImage?

func render(pixelBuffer: CVPixelBuffer, additional: Bool, transitionFactor: CGFloat) -> CVPixelBuffer? {
func render(pixelBuffer: CVPixelBuffer, additional: Bool, captureOrientation: AVCaptureVideoOrientation, transitionFactor: CGFloat) -> CVPixelBuffer? {
guard let resizeFilter = self.resizeFilter, let overlayFilter = self.overlayFilter, let compositeFilter = self.compositeFilter, let borderFilter = self.borderFilter, self.isPrepared else {
return nil
}

var sourceImage = CIImage(cvImageBuffer: pixelBuffer, options: [.colorSpace: self.colorSpace])
sourceImage = sourceImage.oriented(additional ? .leftMirrored : .right)
var sourceOrientation: CGImagePropertyOrientation
var sourceIsLandscape = false
switch captureOrientation {
case .portrait:
sourceOrientation = additional ? .leftMirrored : .right
case .landscapeLeft:
sourceOrientation = additional ? .upMirrored : .down
sourceIsLandscape = true
case .landscapeRight:
sourceOrientation = additional ? .downMirrored : .up
sourceIsLandscape = true
case .portraitUpsideDown:
sourceOrientation = additional ? .rightMirrored : .left
@unknown default:
sourceOrientation = additional ? .leftMirrored : .right
}
sourceImage = sourceImage.oriented(sourceOrientation)
let scale = CGFloat(videoMessageDimensions.width) / min(sourceImage.extent.width, sourceImage.extent.height)

if !self.simple {
Expand All @@ -179,8 +196,13 @@ final class CameraRoundVideoFilter {
sourceImage = sourceImage.transformed(by: CGAffineTransformMakeScale(scale, scale), highQualityDownsample: true)
}

sourceImage = sourceImage.transformed(by: CGAffineTransformMakeTranslation(0.0, -(sourceImage.extent.height - sourceImage.extent.width) / 2.0))
sourceImage = sourceImage.cropped(to: CGRect(x: 0.0, y: 0.0, width: sourceImage.extent.width, height: sourceImage.extent.width))
if sourceIsLandscape {
sourceImage = sourceImage.transformed(by: CGAffineTransformMakeTranslation(-(sourceImage.extent.width - sourceImage.extent.height) / 2.0, 0.0))
sourceImage = sourceImage.cropped(to: CGRect(x: 0.0, y: 0.0, width: sourceImage.extent.height, height: sourceImage.extent.height))
} else {
sourceImage = sourceImage.transformed(by: CGAffineTransformMakeTranslation(0.0, -(sourceImage.extent.height - sourceImage.extent.width) / 2.0))
sourceImage = sourceImage.cropped(to: CGRect(x: 0.0, y: 0.0, width: sourceImage.extent.width, height: sourceImage.extent.width))
}

if additional {
self.lastAdditionalSourceImage = sourceImage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ swift_library(
"//submodules/DeviceAccess",
"//submodules/TelegramUI/Components/MediaEditor",
"//submodules/LegacyMediaPickerUI",
"//submodules/TelegramAudio",
],
visibility = [
"//visibility:public",
Expand Down
Loading

0 comments on commit 7d8de2a

Please sign in to comment.