@@ -90,6 +90,14 @@ public class CameraCapturer: VideoCapturer, @unchecked Sendable {
9090 capturer. captureSession
9191 }
9292
93+ private var isMultiCamSession : Bool {
94+ #if os(iOS) || os(tvOS)
95+ captureSession is AVCaptureMultiCamSession
96+ #else
97+ false
98+ #endif
99+ }
100+
93101 // RTCCameraVideoCapturer used internally for now
94102 private lazy var capturer : LKRTCCameraVideoCapturer = . init( delegate: adapter)
95103
@@ -154,21 +162,17 @@ public class CameraCapturer: VideoCapturer, @unchecked Sendable {
154162 var device : AVCaptureDevice ? = options. device
155163
156164 if device == nil {
157- #if os(iOS) || os(tvOS)
158165 var devices : [ AVCaptureDevice ]
159- if AVCaptureMultiCamSession . isMultiCamSupported {
166+ if isMultiCamSession {
160167 // Get the list of devices already on the shared multi-cam session.
161168 let existingDevices = captureSession. inputs. compactMap { $0 as? AVCaptureDeviceInput } . map ( \. device)
162- log ( " Existing multicam devices: \( existingDevices) " )
169+ log ( " Existing multiCam devices: \( existingDevices) " )
163170 // Compute other multi-cam compatible devices.
164171 devices = try await DeviceManager . shared. multiCamCompatibleDevices ( for: Set ( existingDevices) )
165- log ( " Compabible multicam devices: \( devices) " )
172+ log ( " Compatible multiCam devices: \( devices) " )
166173 } else {
167174 devices = try await CameraCapturer . captureDevices ( )
168175 }
169- #else
170- var devices = try await CameraCapturer . captureDevices ( )
171- #endif
172176
173177 #if !os(visionOS)
174178 // Filter by deviceType if specified in options.
@@ -217,26 +221,27 @@ public class CameraCapturer: VideoCapturer, @unchecked Sendable {
217221
218222 let any : ( FormatTuple ) -> Bool = { _ in true }
219223 let matchesFps : ( FormatTuple ) -> Bool = { $0. format. fpsRange ( ) . contains ( targetFps) }
220- let supportsMulticam : ( FormatTuple ) -> Bool = { $0. format. filterForMulticamSupport }
224+ let matchesAspectRatio : ( FormatTuple ) -> Bool = {
225+ let sourceRatio = Double ( $0. dimensions. width) / Double( $0. dimensions. height)
226+ let targetRatio = Double ( targetDimensions. width) / Double( targetDimensions. height)
227+ return abs ( sourceRatio - targetRatio) / targetRatio < CGFloat . aspectRatioTolerance
228+ }
229+ let supportsMultiCam : ( FormatTuple ) -> Bool = { $0. format. filterForMultiCamSupport }
221230 let byManhattanDistance : ( FormatTuple , FormatTuple ) -> Bool = { manhattanDistance ( $0) < manhattanDistance ( $1) }
222231
223- #if os(iOS) || os(tvOS)
224- let isMulticamActive = AVCaptureMultiCamSession . isMultiCamSupported && !captureSession. inputs. isEmpty
225- let criteria : [ ( name: String , filter: ( FormatTuple ) -> Bool ) ] = isMulticamActive ? [
226- ( name: " fps, multicam " , filter: { matchesFps ( $0) && supportsMulticam ( $0) } ) ,
227- ( name: " multicam " , filter: supportsMulticam) ,
228- ( name: " fps " , filter: matchesFps) ,
229- ( name: " (fallback) " , filter: any) ,
230- ] : [
231- ( name: " fps " , filter: matchesFps) ,
232- ( name: " (fallback) " , filter: any) ,
233- ]
234- #else
235- let criteria : [ ( name: String , filter: ( FormatTuple ) -> Bool ) ] = [
232+ var criteria : [ ( name: String , filter: ( FormatTuple ) -> Bool ) ] = isMultiCamSession ? [
233+ ( name: " multiCam, aspectRatio, fps " , filter: { supportsMultiCam ( $0) && matchesAspectRatio ( $0) && matchesFps ( $0) } ) ,
234+ ( name: " multiCam, aspectRatio " , filter: { supportsMultiCam ( $0) && matchesAspectRatio ( $0) } ) ,
235+ ( name: " multiCam, fps " , filter: { supportsMultiCam ( $0) && matchesFps ( $0) } ) ,
236+ ( name: " multiCam " , filter: supportsMultiCam) ,
237+ ] : [ ]
238+
239+ criteria. append ( contentsOf: [
240+ ( name: " aspectRatio, fps " , filter: { matchesAspectRatio ( $0) && matchesFps ( $0) } ) ,
241+ ( name: " aspectRatio " , filter: matchesAspectRatio) ,
236242 ( name: " fps " , filter: matchesFps) ,
237243 ( name: " (fallback) " , filter: any) ,
238- ]
239- #endif
244+ ] )
240245
241246 for (name, filter) in criteria {
242247 if let foundFormat = sortedFormats. sorted ( by: byManhattanDistance) . first ( where: filter) {
@@ -384,7 +389,7 @@ extension AVCaptureDevice.Format {
384389
385390 // Used for filtering.
386391 // Only include multi-cam supported devices if in multi-cam mode. Otherwise, always include the devices.
387- var filterForMulticamSupport : Bool {
392+ var filterForMultiCamSupport : Bool {
388393 #if os(iOS) || os(tvOS)
389394 return AVCaptureMultiCamSession . isMultiCamSupported ? isMultiCamSupported : true
390395 #else
0 commit comments