From 0bc969da9578c2633c3076ca357a8b9fbc2bc2f5 Mon Sep 17 00:00:00 2001 From: Harold Thetiot Date: Sat, 26 Oct 2019 23:27:16 +0200 Subject: [PATCH 1/5] implement getUserMedia constraints video.(width|height|aspectRatio|frameRate).(ideal|exact) and add video.(aspectRatio|frameRate).(ideal|exact) support --- js/getUserMedia.js | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/js/getUserMedia.js b/js/getUserMedia.js index 00787570..4e2b8181 100644 --- a/js/getUserMedia.js +++ b/js/getUserMedia.js @@ -22,7 +22,6 @@ function isPositiveFloat(number) { return typeof number === 'number' && number >= 0; } - function getUserMedia(constraints) { // Detect callback usage to assist 5.0.1 to 5.0.2 migration @@ -239,7 +238,12 @@ function getUserMedia(constraints) { if (isPositiveInteger(constraints.video.width.max)) { newConstraints.video.width.max = constraints.video.width.max; } - // TODO exact, ideal + if (isPositiveInteger(constraints.video.width.exact)) { + newConstraints.video.width.exact = constraints.video.width.exact; + } + if (isPositiveInteger(constraints.video.width.ideal)) { + newConstraints.video.width.ideal = constraints.video.width.ideal; + } // Get requested width long as exact } else if (isPositiveInteger(constraints.video.width)) { @@ -257,7 +261,12 @@ function getUserMedia(constraints) { if (isPositiveInteger(constraints.video.height.max)) { newConstraints.video.height.max = constraints.video.height.max; } - // TODO exact, ideal + if (isPositiveInteger(constraints.video.height.exact)) { + newConstraints.video.height.exact = constraints.video.height.exact; + } + if (isPositiveInteger(constraints.video.height.ideal)) { + newConstraints.video.height.ideal = constraints.video.height.ideal; + } // Get requested height long as exact } else if (isPositiveInteger(constraints.video.height)) { @@ -275,7 +284,12 @@ function getUserMedia(constraints) { if (isPositiveFloat(constraints.video.frameRate.max)) { newConstraints.video.frameRate.max = parseFloat(constraints.video.frameRate.max, 10); } - // TODO exact, ideal + if (isPositiveInteger(constraints.video.frameRate.exact)) { + newConstraints.video.frameRate.exact = constraints.video.frameRate.exact; + } + if (isPositiveInteger(constraints.video.frameRate.ideal)) { + newConstraints.video.frameRate.ideal = constraints.video.frameRate.ideal; + } // Get requested frameRate double as exact } else if (isPositiveFloat(constraints.video.frameRate)) { @@ -285,8 +299,20 @@ function getUserMedia(constraints) { } // get aspectRatio (e.g 1.7777777777777777) - // TODO ConstrainDouble min, max - if (isPositiveFloat(constraints.video.aspectRatio)) { + if (typeof constraints.video.aspectRatio === 'object') { + if (isPositiveFloat(constraints.video.aspectRatio.min)) { + newConstraints.video.aspectRatio.min = parseFloat(constraints.video.aspectRatio.min, 10); + } + if (isPositiveFloat(constraints.video.aspectRatio.max)) { + newConstraints.video.aspectRatio.max = parseFloat(constraints.video.aspectRatio.max, 10); + } + if (isPositiveInteger(constraints.video.aspectRatio.exact)) { + newConstraints.video.aspectRatio.exact = constraints.video.aspectRatio.exact; + } + if (isPositiveInteger(constraints.video.aspectRatio.ideal)) { + newConstraints.video.aspectRatio.ideal = constraints.video.aspectRatio.ideal; + } + } else if (isPositiveFloat(constraints.video.aspectRatio)) { newConstraints.video.aspectRatio = { exact: parseFloat(constraints.video.aspectRatio, 10) }; From 6dad7d502f620ac54a86d7bdcc90d6372cfdc6ca Mon Sep 17 00:00:00 2001 From: Harold Thetiot Date: Sun, 27 Oct 2019 00:03:58 +0200 Subject: [PATCH 2/5] update PluginRTCVideoCaptureController aspectRatio and improve default constraints handling --- src/PluginRTCVideoCaptureController.swift | 138 +++++++++++++++------- 1 file changed, 93 insertions(+), 45 deletions(-) diff --git a/src/PluginRTCVideoCaptureController.swift b/src/PluginRTCVideoCaptureController.swift index f0da07d2..772af369 100644 --- a/src/PluginRTCVideoCaptureController.swift +++ b/src/PluginRTCVideoCaptureController.swift @@ -45,13 +45,19 @@ extension RTCMediaStreamTrack { class PluginRTCVideoCaptureController : NSObject { - private let DEFAULT_HEIGHT : Int = 480 - private let DEFAULT_WIDTH : Int = 640 + // Note: Default are low value on purpose private let DEFAULT_FPS : Int = 15 + private let DEFAULT_WIDTH : Int = 640 + private let DEFAULT_ASPECT_RATIO : Float32 = 4/3 + private let DEFAULT_WIDTHS_RATIO : NSDictionary = [ + "1.333333" : 640, + "1.222222": 352, + "1.777778" : 960 + ] var capturer: RTCCameraVideoCapturer - // Default to the front camera. + // Note: Default will be front camera. var device: AVCaptureDevice? var deviceFormat: AVCaptureDevice.Format? var deviceFrameRate: Int? @@ -170,14 +176,14 @@ class PluginRTCVideoCaptureController : NSObject { // and pick a default if neither are specified. var position = AVCaptureDevice.Position.front; let facingMode = self.getConstrainDOMStringValue(constraint: "facingMode"); - let facingModeRequired = self.isConstrainDOMStringRequired(constraint: "facingMode"); + let facingModeRequired = self.isConstrainDOMStringExact(constraint: "facingMode"); if (facingMode.count > 0) { if (facingMode == "environment") { position = AVCaptureDevice.Position.back } else if (facingMode == "user") { position = AVCaptureDevice.Position.front } else if (facingModeRequired) { - // TODO fail + NSLog("PluginRTCVideoCaptureController#findDevice facingMode fail exact requirement"); return nil; } @@ -192,8 +198,8 @@ class PluginRTCVideoCaptureController : NSObject { device = nil } - if (device == nil && self.isConstrainDOMStringRequired(constraint: "deviceId")) { - // TODO fail + if (device == nil && self.isConstrainDOMStringExact(constraint: "deviceId")) { + NSLog("PluginRTCVideoCaptureController#findDevice deviceId fail exact requirement"); return nil; } } @@ -210,7 +216,7 @@ class PluginRTCVideoCaptureController : NSObject { facingMode == "environment" && device?.position != AVCaptureDevice.Position.back || facingMode == "user" && device?.position != AVCaptureDevice.Position.front )) { - // TODO fail + NSLog("PluginRTCVideoCaptureController#findDevice facingMode fail exact requirement"); return nil; } @@ -220,23 +226,29 @@ class PluginRTCVideoCaptureController : NSObject { return nil; } - let frameRateRange: NSDictionary = getConstrainRangeValues(constraint: "frameRate", defaultValue: self.DEFAULT_FPS), - minFrameRate = frameRateRange.object(forKey: "min") as! Float64, - maxFrameRate = frameRateRange.object(forKey: "max") as! Float64 + let frameRateRange: NSDictionary = getConstraintDoubleValues(constraint: "frameRate", defaultValue: self.DEFAULT_FPS), + minFrameRate = frameRateRange.object(forKey: "min") as! Int, + maxFrameRate = frameRateRange.object(forKey: "max") as! Int if (minFrameRate > 0 || maxFrameRate > 0) { let formatFrameRateRange: AVFrameRateRange = deviceFormat!.videoSupportedFrameRateRanges[0] + // Fail if frameRate is exact and formatFrameRateRange is not capable if ( - (formatFrameRateRange.maxFrameRate <= maxFrameRate) && - formatFrameRateRange.minFrameRate >= minFrameRate && - isConstrainRangeRequired(constraint: "frameRate") + isConstrainRangeExact(constraint: "frameRate") && ( + Int(formatFrameRateRange.maxFrameRate) < maxFrameRate || + Int(formatFrameRateRange.minFrameRate) > minFrameRate + ) ) { - // TODO fail + NSLog("PluginRTCVideoCaptureController#findDevice frameRate fail exact requirement"); return nil; } - deviceFrameRate = Int(maxFrameRate > 0 ? maxFrameRate : minFrameRate) + // Compute deviceFrameRate knowing minFrameRate and maxFrameRate can be 0 + deviceFrameRate = max( + max(Int(formatFrameRateRange.minFrameRate), minFrameRate), + (maxFrameRate > 0 ? min(Int(formatFrameRateRange.maxFrameRate), maxFrameRate) : self.DEFAULT_FPS) + ) NSLog("PluginRTCVideoCaptureController#findDevice deviceFrameRate:%i", deviceFrameRate!); @@ -262,30 +274,34 @@ class PluginRTCVideoCaptureController : NSObject { } - fileprivate func findFormatForDevice(device: AVCaptureDevice) -> AVCaptureDevice.Format? { var selectedFormat: AVCaptureDevice.Format? = nil let formats: NSArray = RTCCameraVideoCapturer.supportedFormats(for: device) as NSArray - let widthRange: NSDictionary = getConstrainRangeValues(constraint: "width", defaultValue: self.DEFAULT_WIDTH), + let aspectRatioRange: NSDictionary = getConstraintLongValues(constraint: "aspectRatio", defaultValue: 0.0), + minAspectRatio = aspectRatioRange.object(forKey: "min") as! Float32, + maxAspectRatio = aspectRatioRange.object(forKey: "max") as! Float32, + defaultAspectRation = String(format: "%.6f", minAspectRatio > 0 ? minAspectRatio : DEFAULT_ASPECT_RATIO) + + let defaultWidth = DEFAULT_WIDTHS_RATIO.object(forKey: defaultAspectRation) != nil ? + DEFAULT_WIDTHS_RATIO.object(forKey: defaultAspectRation) as! Int : DEFAULT_WIDTH, + widthRange: NSDictionary = getConstraintDoubleValues(constraint: "width", defaultValue: defaultWidth), minWidth = widthRange.object(forKey: "min") as! Int32, maxWidth = widthRange.object(forKey: "max") as! Int32 + - let heightRange: NSDictionary = getConstrainRangeValues(constraint: "height", defaultValue: self.DEFAULT_HEIGHT), + let defaultHeight = Int(Float32(minWidth) / (minAspectRatio > 0 ? minAspectRatio : DEFAULT_ASPECT_RATIO)), + heightRange: NSDictionary = getConstraintDoubleValues(constraint: "height", defaultValue: defaultHeight), minHeight = heightRange.object(forKey: "min") as! Int32, maxHeight = heightRange.object(forKey: "max") as! Int32 - let frameRateRange: NSDictionary = getConstrainRangeValues(constraint: "frameRate", defaultValue: self.DEFAULT_FPS), + let frameRateRange: NSDictionary = getConstraintDoubleValues(constraint: "frameRate", defaultValue: DEFAULT_FPS), minFrameRate = frameRateRange.object(forKey: "min") as! Float64, maxFrameRate = frameRateRange.object(forKey: "max") as! Float64 - - let aspectRatioRange: NSDictionary = getConstrainRangeValues(constraint: "aspectRatio"), - minAspectRatio = aspectRatioRange.object(forKey: "min") as! Float32, - maxAspectRatio = aspectRatioRange.object(forKey: "max") as! Float32 - NSLog("PluginRTCVideoCaptureController#findFormatForDevice contraints width:%i/%i, height:%i%i, aspectRatio: %f%i, frameRateRanges:%f/%f", minWidth, maxWidth, minHeight, maxHeight, minAspectRatio, maxAspectRatio, minFrameRate, maxFrameRate); + NSLog("PluginRTCVideoCaptureController#findFormatForDevice contraints width:%i/%i, height:%i/%i, aspectRatio: %f/%f, frameRateRanges:%f/%f", minWidth, maxWidth, minHeight, maxHeight, minAspectRatio, maxAspectRatio, minFrameRate, maxFrameRate); for format: Any in formats { @@ -299,17 +315,12 @@ class PluginRTCVideoCaptureController : NSObject { let frameRateRanges: [AVFrameRateRange] = devFormat.videoSupportedFrameRateRanges let frameRates = frameRateRanges[0]; - NSLog("PluginRTCVideoCaptureController#findFormatForDevice format width:%i, height:%i, aspectRatio: %f, frameRateRanges:%f/%f", dimension.width, dimension.height, aspectRatio, frameRates.minFrameRate, frameRates.maxFrameRate); - // dimension.height and dimension.width Matches if ( - (maxHeight == 0 && minHeight == 0) || ( - (maxHeight == 0 || dimension.height >= maxHeight) && - (minHeight == 0 || dimension.height <= minHeight) && - (maxWidth == 0 || dimension.width >= maxWidth) && - (minWidth == 0 || dimension.width <= minWidth) - ) + ((maxHeight == 0 || dimension.height <= maxHeight) && (minHeight == 0 || dimension.height >= minHeight)) && + ((maxWidth == 0 || dimension.width <= maxWidth) && (minWidth == 0 || dimension.width >= minWidth)) ) { + //NSLog("dimension %i/%i", dimension.width, dimension.height); selectedFormat = devFormat } else { @@ -319,8 +330,8 @@ class PluginRTCVideoCaptureController : NSObject { if ( (minAspectRatio == 0 && maxAspectRatio == 0) || ( - (minAspectRatio == 0 || aspectRatio == minAspectRatio) && - (maxAspectRatio == 0 || aspectRatio == maxAspectRatio) + (minAspectRatio == 0 || checkDoubleIsEqual(fromFloat: aspectRatio, toFloat: minAspectRatio)) || + (maxAspectRatio == 0 || checkDoubleIsEqual(fromFloat: aspectRatio, toFloat: maxAspectRatio)) ) ) { selectedFormat = devFormat @@ -353,6 +364,8 @@ class PluginRTCVideoCaptureController : NSObject { if (pixelFormat == self.capturer.preferredOutputPixelFormat()) { selectedFormat = devFormat } + + NSLog("PluginRTCVideoCaptureController#findFormatForDevice format width:%i, height:%i, aspectRatio: %f, frameRateRanges:%f/%f", dimension.width, dimension.height, aspectRatio, frameRates.minFrameRate, frameRates.maxFrameRate); } if (selectedFormat != nil) { @@ -362,9 +375,11 @@ class PluginRTCVideoCaptureController : NSObject { let frameRateRanges: [AVFrameRateRange] = selectedFormat!.videoSupportedFrameRateRanges let frameRates = frameRateRanges[0]; - // TODO Apply frameRates via minFrameRate/maxFrameRate + // TODO check aspectRatio, width and height, using isConstrainRangeExact - NSLog("PluginRTCVideoCaptureController#findFormatForDevice width:%i, height:%i, aspectRatio: %f, frameRateRanges:%f/%f", dimension.width, dimension.height, aspectRatio, frameRates.minFrameRate, frameRates.maxFrameRate); + NSLog("PluginRTCVideoCaptureController#findFormatForDevice format selected width:%i, height:%i, aspectRatio: %f, frameRateRanges:%f/%f", dimension.width, dimension.height, aspectRatio, frameRates.minFrameRate, frameRates.maxFrameRate); + } else { + NSLog("PluginRTCVideoCaptureController#findFormatForDevice No device format matching constraints found"); } return selectedFormat @@ -418,7 +433,7 @@ class PluginRTCVideoCaptureController : NSObject { return finalValue; } - fileprivate func isConstrainDOMStringRequired(constraint: String) -> Bool { + fileprivate func isConstrainDOMStringExact(constraint: String) -> Bool { var isRequired: Bool = false; let constraints = self.constraints; let value = constraints.object(forKey: constraint); @@ -437,7 +452,40 @@ class PluginRTCVideoCaptureController : NSObject { return isRequired; } - fileprivate func getConstrainRangeValues(constraint: String, defaultValue: Int = 0) -> NSDictionary { + // Convert NSNumber to Float32 (e.g 1.7777777777777777 to 1.777778) + fileprivate func NSNumberToFloat32(number: NSNumber) -> Float32 { + return number.floatValue; + //return Float32(String(format: "%.7f", number.floatValue))!; + } + + // Handle (e.g Compare 1.7777777777777777 with 1.777778) + func checkDoubleIsEqual(fromFloat: Float32, toFloat : Float32, includingNumberOfFractionalDigits : Int = 6) -> Bool { + + let denominator : Float32 = pow(10.0, Float32(includingNumberOfFractionalDigits)) + let maximumDifference : Float32 = 1.0 / denominator + let realDifference : Float32 = abs(fromFloat - toFloat) + + if realDifference >= maximumDifference { + return false + } else { + return true + } + } + + fileprivate func getConstraintDoubleValues(constraint: String, defaultValue: Int) -> NSDictionary { + return getConstrainRangeValues(constraint: constraint, defaultValue: NSNumber(value: defaultValue)); + } + + fileprivate func getConstraintLongValues(constraint: String, defaultValue: Float) -> NSDictionary { + let finalValue = getConstrainRangeValues(constraint: constraint, defaultValue: NSNumber(value: defaultValue)); + + return [ + "min": NSNumberToFloat32(number: finalValue.object(forKey: "min") as! NSNumber), + "max": NSNumberToFloat32(number: finalValue.object(forKey: "max") as! NSNumber) + ]; + } + + fileprivate func getConstrainRangeValues(constraint: String, defaultValue: NSNumber) -> NSDictionary { let constraints = self.constraints; let finalValue: NSMutableDictionary = [:]; finalValue.setValue(defaultValue, forKey: "min") @@ -445,26 +493,26 @@ class PluginRTCVideoCaptureController : NSObject { let value = constraints.object(forKey: constraint); - if value is Int64 { + if value is NSNumber { finalValue.setValue(value, forKey: "min") finalValue.setValue(value, forKey: "max") } else if value is NSDictionary { let value = value as! NSDictionary; if (value.object(forKey: "exact") != nil) { - let value = value.object(forKey: "exact") as! Int64 + let value = value.object(forKey: "exact") as! NSNumber finalValue.setValue(value, forKey: "min") finalValue.setValue(value, forKey: "max") } else if (value.object(forKey: "ideal") != nil) { - let value = value.object(forKey: "ideal") as! Int64 + let value = value.object(forKey: "ideal") as! NSNumber finalValue.setValue(value, forKey: "min") finalValue.setValue(value, forKey: "max") } else { if (value.object(forKey: "min") != nil) { - let value = value.object(forKey: "min") as! Int64 + let value = value.object(forKey: "min") as! NSNumber finalValue.setValue(value, forKey: "min") } if (value.object(forKey: "max") != nil) { - let value = value.object(forKey: "max") as! Int64 + let value = value.object(forKey: "max") as! NSNumber finalValue.setValue(value, forKey: "max") } } @@ -473,7 +521,7 @@ class PluginRTCVideoCaptureController : NSObject { return finalValue; } - fileprivate func isConstrainRangeRequired(constraint: String) -> Bool { + fileprivate func isConstrainRangeExact(constraint: String) -> Bool { let constraints = self.constraints; var isRequired: Bool = false; let value = constraints.object(forKey: constraint); From c3fe0575a633ac3e2b33b88cc828d0216b644f2c Mon Sep 17 00:00:00 2001 From: Harold Thetiot Date: Sun, 27 Oct 2019 00:04:13 +0200 Subject: [PATCH 3/5] update dist/cordova-plugin-iosrtc.js build --- dist/cordova-plugin-iosrtc.js | 38 +++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/dist/cordova-plugin-iosrtc.js b/dist/cordova-plugin-iosrtc.js index 4125e529..dd6b5cfb 100644 --- a/dist/cordova-plugin-iosrtc.js +++ b/dist/cordova-plugin-iosrtc.js @@ -2351,7 +2351,6 @@ function isPositiveFloat(number) { return typeof number === 'number' && number >= 0; } - function getUserMedia(constraints) { // Detect callback usage to assist 5.0.1 to 5.0.2 migration @@ -2568,7 +2567,12 @@ function getUserMedia(constraints) { if (isPositiveInteger(constraints.video.width.max)) { newConstraints.video.width.max = constraints.video.width.max; } - // TODO exact, ideal + if (isPositiveInteger(constraints.video.width.exact)) { + newConstraints.video.width.exact = constraints.video.width.exact; + } + if (isPositiveInteger(constraints.video.width.ideal)) { + newConstraints.video.width.ideal = constraints.video.width.ideal; + } // Get requested width long as exact } else if (isPositiveInteger(constraints.video.width)) { @@ -2586,7 +2590,12 @@ function getUserMedia(constraints) { if (isPositiveInteger(constraints.video.height.max)) { newConstraints.video.height.max = constraints.video.height.max; } - // TODO exact, ideal + if (isPositiveInteger(constraints.video.height.exact)) { + newConstraints.video.height.exact = constraints.video.height.exact; + } + if (isPositiveInteger(constraints.video.height.ideal)) { + newConstraints.video.height.ideal = constraints.video.height.ideal; + } // Get requested height long as exact } else if (isPositiveInteger(constraints.video.height)) { @@ -2604,7 +2613,12 @@ function getUserMedia(constraints) { if (isPositiveFloat(constraints.video.frameRate.max)) { newConstraints.video.frameRate.max = parseFloat(constraints.video.frameRate.max, 10); } - // TODO exact, ideal + if (isPositiveInteger(constraints.video.frameRate.exact)) { + newConstraints.video.frameRate.exact = constraints.video.frameRate.exact; + } + if (isPositiveInteger(constraints.video.frameRate.ideal)) { + newConstraints.video.frameRate.ideal = constraints.video.frameRate.ideal; + } // Get requested frameRate double as exact } else if (isPositiveFloat(constraints.video.frameRate)) { @@ -2614,8 +2628,20 @@ function getUserMedia(constraints) { } // get aspectRatio (e.g 1.7777777777777777) - // TODO ConstrainDouble min, max - if (isPositiveFloat(constraints.video.aspectRatio)) { + if (typeof constraints.video.aspectRatio === 'object') { + if (isPositiveFloat(constraints.video.aspectRatio.min)) { + newConstraints.video.aspectRatio.min = parseFloat(constraints.video.aspectRatio.min, 10); + } + if (isPositiveFloat(constraints.video.aspectRatio.max)) { + newConstraints.video.aspectRatio.max = parseFloat(constraints.video.aspectRatio.max, 10); + } + if (isPositiveInteger(constraints.video.aspectRatio.exact)) { + newConstraints.video.aspectRatio.exact = constraints.video.aspectRatio.exact; + } + if (isPositiveInteger(constraints.video.aspectRatio.ideal)) { + newConstraints.video.aspectRatio.ideal = constraints.video.aspectRatio.ideal; + } + } else if (isPositiveFloat(constraints.video.aspectRatio)) { newConstraints.video.aspectRatio = { exact: parseFloat(constraints.video.aspectRatio, 10) }; From 573f83b92bb5b2790bb3d7f71fd6b76d13918546 Mon Sep 17 00:00:00 2001 From: Harold Thetiot Date: Mon, 28 Oct 2019 13:53:57 +0100 Subject: [PATCH 4/5] improve PluginRTCVideoCaptureController findFormatForDevice and getConstrainRangeValues to support height without with and handle partially ideal+min+max --- src/PluginRTCVideoCaptureController.swift | 93 ++++++++++++++++++----- 1 file changed, 72 insertions(+), 21 deletions(-) diff --git a/src/PluginRTCVideoCaptureController.swift b/src/PluginRTCVideoCaptureController.swift index 772af369..01b5a04c 100644 --- a/src/PluginRTCVideoCaptureController.swift +++ b/src/PluginRTCVideoCaptureController.swift @@ -278,29 +278,42 @@ class PluginRTCVideoCaptureController : NSObject { var selectedFormat: AVCaptureDevice.Format? = nil let formats: NSArray = RTCCameraVideoCapturer.supportedFormats(for: device) as NSArray + let selectedFormats : NSArray = []; - let aspectRatioRange: NSDictionary = getConstraintLongValues(constraint: "aspectRatio", defaultValue: 0.0), - minAspectRatio = aspectRatioRange.object(forKey: "min") as! Float32, - maxAspectRatio = aspectRatioRange.object(forKey: "max") as! Float32, - defaultAspectRation = String(format: "%.6f", minAspectRatio > 0 ? minAspectRatio : DEFAULT_ASPECT_RATIO) + var heightRange: NSDictionary = getConstraintDoubleValues(constraint: "height", defaultValue: 0), + minHeight = heightRange.object(forKey: "min") as! Int32, + maxHeight = heightRange.object(forKey: "max") as! Int32 - let defaultWidth = DEFAULT_WIDTHS_RATIO.object(forKey: defaultAspectRation) != nil ? - DEFAULT_WIDTHS_RATIO.object(forKey: defaultAspectRation) as! Int : DEFAULT_WIDTH, - widthRange: NSDictionary = getConstraintDoubleValues(constraint: "width", defaultValue: defaultWidth), + var widthRange: NSDictionary = getConstraintDoubleValues(constraint: "width", defaultValue: 0), minWidth = widthRange.object(forKey: "min") as! Int32, maxWidth = widthRange.object(forKey: "max") as! Int32 + let aspectRatioRange: NSDictionary = getConstraintLongValues(constraint: "aspectRatio", defaultValue: 0.0), + minAspectRatio = aspectRatioRange.object(forKey: "min") as! Float32, + maxAspectRatio = aspectRatioRange.object(forKey: "max") as! Float32 + + // Compute heightRange depending widthRange and aspectRatioRange + // We dont want to compute defaultHeight and defaultWidth if only height is provided + if (minWidth != 0 && maxWidth != 0 && minHeight == 0 && maxHeight == 0) { + + let defaultAspectRatio = String(format: "%.6f", minAspectRatio > 0 ? minAspectRatio : DEFAULT_ASPECT_RATIO); - let defaultHeight = Int(Float32(minWidth) / (minAspectRatio > 0 ? minAspectRatio : DEFAULT_ASPECT_RATIO)), - heightRange: NSDictionary = getConstraintDoubleValues(constraint: "height", defaultValue: defaultHeight), - minHeight = heightRange.object(forKey: "min") as! Int32, + let defaultWidth = DEFAULT_WIDTHS_RATIO.object(forKey: defaultAspectRatio) != nil ? + DEFAULT_WIDTHS_RATIO.object(forKey: defaultAspectRatio) as! Int : DEFAULT_WIDTH; + widthRange = getConstraintDoubleValues(constraint: "width", defaultValue: defaultWidth) + minWidth = widthRange.object(forKey: "min") as! Int32 + maxWidth = widthRange.object(forKey: "max") as! Int32 + + let defaultHeight = Int(Float32(minWidth) / (minAspectRatio > 0 ? minAspectRatio : DEFAULT_ASPECT_RATIO)); + heightRange = getConstraintDoubleValues(constraint: "height", defaultValue: defaultHeight) + minHeight = heightRange.object(forKey: "min") as! Int32 maxHeight = heightRange.object(forKey: "max") as! Int32 + } let frameRateRange: NSDictionary = getConstraintDoubleValues(constraint: "frameRate", defaultValue: DEFAULT_FPS), minFrameRate = frameRateRange.object(forKey: "min") as! Float64, maxFrameRate = frameRateRange.object(forKey: "max") as! Float64 - NSLog("PluginRTCVideoCaptureController#findFormatForDevice contraints width:%i/%i, height:%i/%i, aspectRatio: %f/%f, frameRateRanges:%f/%f", minWidth, maxWidth, minHeight, maxHeight, minAspectRatio, maxAspectRatio, minFrameRate, maxFrameRate); for format: Any in formats { @@ -366,7 +379,12 @@ class PluginRTCVideoCaptureController : NSObject { } NSLog("PluginRTCVideoCaptureController#findFormatForDevice format width:%i, height:%i, aspectRatio: %f, frameRateRanges:%f/%f", dimension.width, dimension.height, aspectRatio, frameRates.minFrameRate, frameRates.maxFrameRate); + + // Add to selectedFormats + selectedFormats.adding(selectedFormat!) } + + // TODO filter selectedFormats to get ideal match using getConstrainDoubleIdeal and getConstraintLongIdealValue if (selectedFormat != nil) { @@ -375,7 +393,7 @@ class PluginRTCVideoCaptureController : NSObject { let frameRateRanges: [AVFrameRateRange] = selectedFormat!.videoSupportedFrameRateRanges let frameRates = frameRateRanges[0]; - // TODO check aspectRatio, width and height, using isConstrainRangeExact + // TODO check aspectRatio, width and height, using getConstrainDoubleIdealValue NSLog("PluginRTCVideoCaptureController#findFormatForDevice format selected width:%i, height:%i, aspectRatio: %f, frameRateRanges:%f/%f", dimension.width, dimension.height, aspectRatio, frameRates.minFrameRate, frameRates.maxFrameRate); } else { @@ -434,12 +452,21 @@ class PluginRTCVideoCaptureController : NSObject { } fileprivate func isConstrainDOMStringExact(constraint: String) -> Bool { + return isConstrainExact(constraint: constraint); + } + + // If the constraint is required (constraintValue either contains one or more members named 'min', 'max', or 'exact', + // or is itself a bare value and bare values are to be treated as 'exact'), and the settings dictionary's value for + // the constraint does not satisfy the constraint, the fitness distance is positive infinity. + fileprivate func isConstrainExact(constraint: String) -> Bool { var isRequired: Bool = false; let constraints = self.constraints; let value = constraints.object(forKey: constraint); if value is String { isRequired = (value as! String).count > 0; + } else if value is NSNumber { + isRequired = (value as! NSNumber).floatValue > 0; } else if value is NSDictionary { let value = value as! NSDictionary; if (value.object(forKey: "exact") != nil) { @@ -452,6 +479,30 @@ class PluginRTCVideoCaptureController : NSObject { return isRequired; } + + fileprivate func getConstrainDoubleIdealValue(constraint: String) -> Int { + return getConstrainIdealValue(constraint: constraint) as! Int; + } + + fileprivate func getConstraintLongIdealValue(constraint: String) -> Float32 { + return getConstrainIdealValue(constraint: constraint).floatValue; + } + + fileprivate func getConstrainIdealValue(constraint: String) -> NSNumber { + var idealValue: NSNumber = -1; + let constraints = self.constraints; + let value = constraints.object(forKey: constraint); + + if value is NSDictionary { + let value = value as! NSDictionary; + if (value.object(forKey: "ideal") != nil) { + idealValue = value.object(forKey: "ideal") as! NSNumber; + } + } + + return idealValue; + } + // Convert NSNumber to Float32 (e.g 1.7777777777777777 to 1.777778) fileprivate func NSNumberToFloat32(number: NSNumber) -> Float32 { return number.floatValue; @@ -506,15 +557,15 @@ class PluginRTCVideoCaptureController : NSObject { let value = value.object(forKey: "ideal") as! NSNumber finalValue.setValue(value, forKey: "min") finalValue.setValue(value, forKey: "max") - } else { - if (value.object(forKey: "min") != nil) { - let value = value.object(forKey: "min") as! NSNumber - finalValue.setValue(value, forKey: "min") - } - if (value.object(forKey: "max") != nil) { - let value = value.object(forKey: "max") as! NSNumber - finalValue.setValue(value, forKey: "max") - } + } + // Note: We do not support (exact|ideal) + min/min at root, min/max will take over for now. + if (value.object(forKey: "min") != nil) { + let value = value.object(forKey: "min") as! NSNumber + finalValue.setValue(value, forKey: "min") + } + if (value.object(forKey: "max") != nil) { + let value = value.object(forKey: "max") as! NSNumber + finalValue.setValue(value, forKey: "max") } } From fb47df8559a6149f2b7addceae9c75e91ae4589f Mon Sep 17 00:00:00 2001 From: Harold Thetiot Date: Mon, 28 Oct 2019 13:55:28 +0100 Subject: [PATCH 5/5] fix indent --- src/PluginRTCVideoCaptureController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PluginRTCVideoCaptureController.swift b/src/PluginRTCVideoCaptureController.swift index 01b5a04c..eceea784 100644 --- a/src/PluginRTCVideoCaptureController.swift +++ b/src/PluginRTCVideoCaptureController.swift @@ -521,7 +521,7 @@ class PluginRTCVideoCaptureController : NSObject { } else { return true } - } + } fileprivate func getConstraintDoubleValues(constraint: String, defaultValue: Int) -> NSDictionary { return getConstrainRangeValues(constraint: constraint, defaultValue: NSNumber(value: defaultValue));