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.device.configureDeviceFormat(maxDimensions: self.preferredMaxDimensions, maxFramerate: self.preferredMaxFrameRate)
self.output.configureVideoStabilization() self.output.configureVideoStabilization()
self.device.resetZoom() self.device.resetZoom(neutral: self.exclusive || !self.additional)
} }
func invalidate() { func invalidate() {
@ -77,7 +77,11 @@ final class CameraDeviceContext {
} }
private var preferredMaxDimensions: CMVideoDimensions { 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 { 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 selectedDevice = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInDualCamera, .builtInWideAngleCamera, .builtInTelephotoCamera], mediaType: .video, position: position).devices.first
} }
} else { } 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 self.videoDevice = selectedDevice
@ -245,12 +252,12 @@ final class CameraDevice {
} }
} }
func resetZoom() { func resetZoom(neutral: Bool = true) {
guard let device = self.videoDevice else { guard let device = self.videoDevice else {
return return
} }
self.transaction(device) { device in 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) { public init(frame: CGRect, main: Bool) {
super.init(frame: frame) super.init(frame: frame)
self.videoPreviewLayer.videoGravity = .resizeAspectFill self.videoPreviewLayer.videoGravity = main ? .resizeAspectFill : .resizeAspect
self.placeholderView.contentMode = .scaleAspectFill self.placeholderView.contentMode = .scaleAspectFill
self.addSubview(self.placeholderView) 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 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)) 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) transition.setPosition(view: self.additionalPreviewContainerView, position: additionalPreviewFrame.center)
@ -1931,16 +1930,23 @@ public class CameraScreen: ViewController {
} }
} }
var mainPreviewInnerSize = previewFrame.size
let mainPreviewView: CameraSimplePreviewView let mainPreviewView: CameraSimplePreviewView
let additionalPreviewView: CameraSimplePreviewView let additionalPreviewView: CameraSimplePreviewView
if self.cameraPosition == .front && self.isDualCamEnabled { if self.cameraPosition == .front && self.isDualCamEnabled {
mainPreviewView = self.additionalPreviewView mainPreviewView = self.additionalPreviewView
additionalPreviewView = self.mainPreviewView additionalPreviewView = self.mainPreviewView
mainPreviewInnerSize = CGSize(width: floorToScreenPixels(mainPreviewInnerSize.height / 3.0 * 4.0), height: mainPreviewInnerSize.height)
} else { } else {
mainPreviewView = self.mainPreviewView mainPreviewView = self.mainPreviewView
additionalPreviewView = self.additionalPreviewView 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 { if mainPreviewView.superview != self.mainPreviewContainerView {
self.mainPreviewContainerView.insertSubview(mainPreviewView, at: 0) self.mainPreviewContainerView.insertSubview(mainPreviewView, at: 0)
} }
@ -1948,7 +1954,7 @@ public class CameraScreen: ViewController {
self.additionalPreviewContainerView.insertSubview(additionalPreviewView, at: 0) self.additionalPreviewContainerView.insertSubview(additionalPreviewView, at: 0)
} }
mainPreviewView.frame = CGRect(origin: .zero, size: previewFrame.size) mainPreviewView.frame = mainPreviewInnerFrame
additionalPreviewView.frame = additionalPreviewInnerFrame additionalPreviewView.frame = additionalPreviewInnerFrame
self.previewFrameLeftDimView.isHidden = !isTablet self.previewFrameLeftDimView.isHidden = !isTablet

View File

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