Improve front camera fov in dual mode

This commit is contained in:
Ilya Laktyushin 2023-07-03 02:07:14 +02:00
parent 719b532480
commit f87c2ec00f
5 changed files with 44 additions and 18 deletions

View File

@ -65,7 +65,7 @@ final class CameraDeviceContext {
self.device.configureDeviceFormat(maxDimensions: self.preferredMaxDimensions, maxFramerate: self.preferredMaxFrameRate)
self.output.configureVideoStabilization()
self.device.resetZoom()
self.device.resetZoom(neutral: self.exclusive || !self.additional)
}
func invalidate() {
@ -77,7 +77,11 @@ final class CameraDeviceContext {
}
private var preferredMaxDimensions: CMVideoDimensions {
return CMVideoDimensions(width: 1920, height: 1080)
if self.additional {
return CMVideoDimensions(width: 1920, height: 1440)
} else {
return CMVideoDimensions(width: 1920, height: 1080)
}
}
private var preferredMaxFrameRate: Double {

View File

@ -44,7 +44,14 @@ final class CameraDevice {
selectedDevice = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInDualCamera, .builtInWideAngleCamera, .builtInTelephotoCamera], mediaType: .video, position: position).devices.first
}
} else {
selectedDevice = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInDualCamera, .builtInWideAngleCamera, .builtInTelephotoCamera], mediaType: .video, position: position).devices.first
if #available(iOS 11.1, *), dual, case .front = position {
if let trueDepthDevice = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInTrueDepthCamera], mediaType: .video, position: position).devices.first {
selectedDevice = trueDepthDevice
}
}
if selectedDevice == nil {
selectedDevice = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInDualCamera, .builtInWideAngleCamera, .builtInTelephotoCamera], mediaType: .video, position: position).devices.first
}
}
self.videoDevice = selectedDevice
@ -245,12 +252,12 @@ final class CameraDevice {
}
}
func resetZoom() {
func resetZoom(neutral: Bool = true) {
guard let device = self.videoDevice else {
return
}
self.transaction(device) { device in
device.videoZoomFactor = device.neutralZoomFactor
device.videoZoomFactor = neutral ? device.neutralZoomFactor : device.minAvailableVideoZoomFactor
}
}
}

View File

@ -48,7 +48,7 @@ public class CameraSimplePreviewView: UIView {
public init(frame: CGRect, main: Bool) {
super.init(frame: frame)
self.videoPreviewLayer.videoGravity = .resizeAspectFill
self.videoPreviewLayer.videoGravity = main ? .resizeAspectFill : .resizeAspect
self.placeholderView.contentMode = .scaleAspectFill
self.addSubview(self.placeholderView)

View File

@ -1912,8 +1912,7 @@ public class CameraScreen: ViewController {
}
let additionalPreviewInnerSize = previewFrame.size.aspectFilled(CGSize(width: circleSide, height: circleSide))
let additionalPreviewInnerFrame = CGRect(origin: CGPoint(x: 0.0, y: floorToScreenPixels((circleSide - additionalPreviewInnerSize.height) / 2.0)), size: additionalPreviewInnerSize)
let additionalPreviewFrame = CGRect(origin: CGPoint(x: origin.x - circleSide / 2.0, y: origin.y - circleSide / 2.0), size: CGSize(width: circleSide, height: circleSide))
transition.setPosition(view: self.additionalPreviewContainerView, position: additionalPreviewFrame.center)
@ -1931,16 +1930,23 @@ public class CameraScreen: ViewController {
}
}
var mainPreviewInnerSize = previewFrame.size
let mainPreviewView: CameraSimplePreviewView
let additionalPreviewView: CameraSimplePreviewView
if self.cameraPosition == .front && self.isDualCamEnabled {
mainPreviewView = self.additionalPreviewView
additionalPreviewView = self.mainPreviewView
mainPreviewInnerSize = CGSize(width: floorToScreenPixels(mainPreviewInnerSize.height / 3.0 * 4.0), height: mainPreviewInnerSize.height)
} else {
mainPreviewView = self.mainPreviewView
additionalPreviewView = self.additionalPreviewView
}
let mainPreviewInnerFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((previewSize.width - mainPreviewInnerSize.width) / 2.0), y: floorToScreenPixels((previewSize.height - mainPreviewInnerSize.height) / 2.0)), size: mainPreviewInnerSize)
let additionalPreviewInnerFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((circleSide - additionalPreviewInnerSize.width) / 2.0), y: floorToScreenPixels((circleSide - additionalPreviewInnerSize.height) / 2.0)), size: additionalPreviewInnerSize)
if mainPreviewView.superview != self.mainPreviewContainerView {
self.mainPreviewContainerView.insertSubview(mainPreviewView, at: 0)
}
@ -1948,7 +1954,7 @@ public class CameraScreen: ViewController {
self.additionalPreviewContainerView.insertSubview(additionalPreviewView, at: 0)
}
mainPreviewView.frame = CGRect(origin: .zero, size: previewFrame.size)
mainPreviewView.frame = mainPreviewInnerFrame
additionalPreviewView.frame = additionalPreviewInnerFrame
self.previewFrameLeftDimView.isHidden = !isTablet

View File

@ -514,7 +514,7 @@ final class VideoInputScalePass: RenderPass {
func update(values: MediaEditorValues) {
if let position = values.additionalVideoPosition, let scale = values.additionalVideoScale, let rotation = values.additionalVideoRotation {
self.additionalPosition = VideoInputScalePass.VideoPosition(position: position, size: CGSize(width: 1080.0 / 4.0, height: 1920.0 / 4.0), scale: scale, rotation: rotation)
self.additionalPosition = VideoInputScalePass.VideoPosition(position: position, size: CGSize(width: 1080.0 / 4.0, height: 1440.0 / 4.0), scale: scale, rotation: rotation)
}
if !values.additionalVideoPositionChanges.isEmpty {
self.videoPositionChanges = values.additionalVideoPositionChanges
@ -530,7 +530,7 @@ final class VideoInputScalePass: RenderPass {
private var additionalPosition = VideoPosition(
position: CGPoint(x: 1080 / 2.0, y: 1920.0 / 2.0),
size: CGSize(width: 1080.0, height: 1920.0),
size: CGSize(width: 1440.0, height: 1920.0),
scale: 0.5,
rotation: 0.0
)
@ -550,7 +550,6 @@ final class VideoInputScalePass: RenderPass {
let scale: CGFloat
let rotation: CGFloat
func mixed(with other: VideoPosition, fraction: CGFloat) -> VideoPosition {
let position = CGPoint(
x: self.position.x + (other.position.x - self.position.x) * fraction,
@ -589,6 +588,10 @@ final class VideoInputScalePass: RenderPass {
var foregroundTexture = additionalInput
var foregroundTextureRotation = self.additionalTextureRotation
var mainPosition = self.mainPosition
var additionalPosition = self.additionalPosition
var disappearingPosition = self.mainPosition
var transitionFraction = 1.0
if let additionalInput {
var previousChange: VideoPositionChange?
@ -606,8 +609,13 @@ final class VideoInputScalePass: RenderPass {
backgroundTexture = additionalInput
backgroundTextureRotation = self.additionalTextureRotation
mainPosition = VideoPosition(position: mainPosition.position, size: CGSize(width: 1440.0, height: 1920.0), scale: mainPosition.scale, rotation: mainPosition.rotation)
additionalPosition = VideoPosition(position: additionalPosition.position, size: CGSize(width: 1080.0 / 4.0, height: 1920.0 / 4.0), scale: additionalPosition.scale, rotation: additionalPosition.rotation)
foregroundTexture = mainInput
foregroundTextureRotation = self.mainTextureRotation
} else {
disappearingPosition = VideoPosition(position: mainPosition.position, size: CGSize(width: 1440.0, height: 1920.0), scale: mainPosition.scale, rotation: mainPosition.rotation)
}
if previousChange.timestamp > 0.0 && timestamp < previousChange.timestamp + transitionDuration {
transitionFraction = (timestamp - previousChange.timestamp) / transitionDuration
@ -615,22 +623,23 @@ final class VideoInputScalePass: RenderPass {
}
}
var backgroundVideoState = VideoState(texture: backgroundTexture, textureRotation: backgroundTextureRotation, position: self.mainPosition, roundness: 0.0, alpha: 1.0)
var backgroundVideoState = VideoState(texture: backgroundTexture, textureRotation: backgroundTextureRotation, position: mainPosition, roundness: 0.0, alpha: 1.0)
var foregroundVideoState: VideoState?
var disappearingVideoState: VideoState?
if let foregroundTexture {
var foregroundPosition = self.additionalPosition
var foregroundPosition = additionalPosition
var foregroundAlpha: Float = 1.0
if transitionFraction < 1.0 {
let springFraction = lookupSpringValue(transitionFraction)
let appearingPosition = VideoPosition(position: self.additionalPosition.position, size: self.additionalPosition.size, scale: 0.01, rotation: self.additionalPosition.rotation)
let appearingPosition = VideoPosition(position: additionalPosition.position, size: additionalPosition.size, scale: 0.01, rotation: self.additionalPosition.rotation)
let backgroundInitialPosition = VideoPosition(position: additionalPosition.position, size: CGSize(width: mainPosition.size.width / 4.0, height: mainPosition.size.height / 4.0), scale: additionalPosition.scale, rotation: additionalPosition.rotation)
foregroundPosition = appearingPosition.mixed(with: self.additionalPosition, fraction: springFraction)
foregroundPosition = appearingPosition.mixed(with: additionalPosition, fraction: springFraction)
disappearingVideoState = VideoState(texture: foregroundTexture, textureRotation: foregroundTextureRotation, position: self.mainPosition, roundness: 0.0, alpha: 1.0)
backgroundVideoState = VideoState(texture: backgroundTexture, textureRotation: backgroundTextureRotation, position: self.additionalPosition.mixed(with: self.mainPosition, fraction: springFraction), roundness: Float(1.0 - springFraction), alpha: 1.0)
disappearingVideoState = VideoState(texture: foregroundTexture, textureRotation: foregroundTextureRotation, position: disappearingPosition, roundness: 0.0, alpha: 1.0)
backgroundVideoState = VideoState(texture: backgroundTexture, textureRotation: backgroundTextureRotation, position: backgroundInitialPosition.mixed(with: mainPosition, fraction: springFraction), roundness: Float(1.0 - springFraction), alpha: 1.0)
foregroundAlpha = min(1.0, max(0.0, Float(transitionFraction) * 2.5))
}