diff --git a/Sora/CameraVideoCapturer.swift b/Sora/CameraVideoCapturer.swift index cad7e266..3cec4064 100644 --- a/Sora/CameraVideoCapturer.swift +++ b/Sora/CameraVideoCapturer.swift @@ -54,26 +54,31 @@ public final class CameraVideoCapturer { /// 指定された設定に最も近い AVCaptureDevice.Format? を返します。 public static func format(width: Int32, height: Int32, for device: AVCaptureDevice, frameRate: Int? = nil) -> AVCaptureDevice.Format? { - let formats = RTCCameraVideoCapturer.supportedFormats(for: device) - var currentFormat: AVCaptureDevice.Format? - var currentDiff = INT_MAX - for format in formats { + func calcDiff(_ targetWidth: Int32, _ targetHeight: Int32, _ format: AVCaptureDevice.Format) -> Int32 { let dimension = CMVideoFormatDescriptionGetDimensions(format.formatDescription) - let diff = abs(width - dimension.width) + abs(height - dimension.height) - if diff < currentDiff { - currentFormat = format - currentDiff = diff - } + return abs(targetWidth - dimension.width) + abs(targetHeight - dimension.height) + } - // 解像度が一致し、フレームレートもサポートされている場合はその format を返す - let fpsRanges = format.videoSupportedFrameRateRanges - if frameRate != nil && width == dimension.width && height == dimension.height && - fpsRanges.contains(where: { Int($0.minFrameRate) <= frameRate! && frameRate! <= Int($0.maxFrameRate) }) { - return format - } + let supportedFormats = RTCCameraVideoCapturer.supportedFormats(for: device) + // 指定された解像度に近いフォーマットを絞り込む + guard let diff = supportedFormats.map({ calcDiff(width, height, $0) }).min() else { + return nil + } + let formats = supportedFormats.filter { calcDiff(width, height, $0) == diff } + guard !formats.isEmpty else { + return nil + } + + // この関数の引数に frameRate が指定された場合、フレームレートも考慮する + guard let frameRate else { + return formats.first } - return currentFormat + return formats.filter { + $0.videoSupportedFrameRateRanges.contains(where: { + Int($0.minFrameRate) <= frameRate && frameRate <= Int($0.maxFrameRate) + }) + }.first ?? formats.first } /// 指定された FPS 値をサポートしているレンジが存在すれば、その値を返します。