summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_video_device.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_video_device.cc')
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_video_device.cc182
1 files changed, 173 insertions, 9 deletions
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_video_device.cc b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_video_device.cc
index c3dbb578e7a..37708d98373 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_video_device.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_video_device.cc
@@ -52,9 +52,9 @@ WebString ToWebString(media::VideoFacingMode facing_mode) {
}
}
-// Returns the fitness distance between the ideal value of |constraint| and the
-// closest value to it in the range [min, max].
-// Based on https://w3c.github.io/mediacapture-main/#dfn-fitness-distance.
+// Returns the fitness distance between the ideal value of |constraint| and
+// |value|. Based on
+// https://w3c.github.io/mediacapture-main/#dfn-fitness-distance.
template <typename NumericConstraint>
double NumericValueFitness(const NumericConstraint& constraint,
decltype(constraint.Min()) value) {
@@ -63,6 +63,29 @@ double NumericValueFitness(const NumericConstraint& constraint,
: 0.0;
}
+// Returns the fitness distance between the ideal value of |constraint| and the
+// closest value to it in the range [min, max].
+// If the ideal value is contained in the range, returns 1.
+// If there is no ideal value, returns 0;
+// Based on https://w3c.github.io/mediacapture-main/#dfn-fitness-distance.
+template <typename NumericConstraint>
+double NumericRangeFitness(
+ const NumericConstraint& constraint,
+ const media_constraints::NumericRangeSet<decltype(constraint.Min())>&
+ range) {
+ DCHECK(!range.IsEmpty());
+ if (!constraint.HasIdeal())
+ return 0.0;
+
+ auto ideal = constraint.Ideal();
+ if (range.Max().has_value() && ideal > *range.Max())
+ return NumericConstraintFitnessDistance(ideal, *range.Max());
+ else if (range.Min().has_value() && ideal < *range.Min())
+ return NumericConstraintFitnessDistance(ideal, *range.Min());
+
+ return 1.0;
+}
+
// Returns a custom distance between |native_value| and the ideal value and
// allowed range for a constrainable property. The ideal value is obtained from
// |constraint| and the allowed range is specified by |min| and |max|.
@@ -402,6 +425,112 @@ bool FacingModeSatisfiesConstraint(media::VideoFacingMode value,
return constraint.Matches(string_value);
}
+class PTZDeviceState {
+ public:
+ explicit PTZDeviceState(const MediaTrackConstraintSetPlatform& constraint_set)
+ : pan_set_(DoubleRangeSet::FromConstraint(constraint_set.pan)),
+ tilt_set_(DoubleRangeSet::FromConstraint(constraint_set.tilt)),
+ zoom_set_(DoubleRangeSet::FromConstraint(constraint_set.zoom)) {}
+
+ PTZDeviceState(const DoubleRangeSet& pan_set,
+ const DoubleRangeSet& tilt_set,
+ const DoubleRangeSet& zoom_set)
+ : pan_set_(pan_set), tilt_set_(tilt_set), zoom_set_(zoom_set) {}
+
+ PTZDeviceState(const PTZDeviceState& other) = default;
+ PTZDeviceState& operator=(const PTZDeviceState& other) = default;
+
+ PTZDeviceState Intersection(
+ const MediaTrackConstraintSetPlatform& constraint_set) const {
+ DoubleRangeSet pan_intersection = pan_set_.Intersection(
+ DoubleRangeSet::FromConstraint(constraint_set.pan));
+ DoubleRangeSet tilt_intersection = tilt_set_.Intersection(
+ DoubleRangeSet::FromConstraint(constraint_set.tilt));
+ DoubleRangeSet zoom_intersection = zoom_set_.Intersection(
+ DoubleRangeSet::FromConstraint(constraint_set.zoom));
+
+ return PTZDeviceState(pan_intersection, tilt_intersection,
+ zoom_intersection);
+ }
+
+ bool IsEmpty() const {
+ return pan_set_.IsEmpty() || tilt_set_.IsEmpty() || zoom_set_.IsEmpty();
+ }
+
+ double Fitness(const MediaTrackConstraintSetPlatform& basic_set) const {
+ return NumericRangeFitness(basic_set.pan, pan_set_) +
+ NumericRangeFitness(basic_set.tilt, tilt_set_) +
+ NumericRangeFitness(basic_set.zoom, zoom_set_);
+ }
+
+ const char* FailedConstraintName() const {
+ MediaTrackConstraintSetPlatform dummy;
+ if (!pan_set_.IsEmpty())
+ return dummy.pan.GetName();
+ if (!tilt_set_.IsEmpty())
+ return dummy.tilt.GetName();
+ if (!zoom_set_.IsEmpty())
+ return dummy.zoom.GetName();
+
+ // No failed constraint.
+ return nullptr;
+ }
+
+ base::Optional<double> SelectPan(
+ const MediaTrackConstraintSetPlatform& basic_set) const {
+ return SelectProperty(&PTZDeviceState::pan_set_, basic_set,
+ &MediaTrackConstraintSetPlatform::pan);
+ }
+
+ base::Optional<double> SelectTilt(
+ const MediaTrackConstraintSetPlatform& basic_set) const {
+ return SelectProperty(&PTZDeviceState::tilt_set_, basic_set,
+ &MediaTrackConstraintSetPlatform::tilt);
+ }
+
+ base::Optional<double> SelectZoom(
+ const MediaTrackConstraintSetPlatform& basic_set) const {
+ return SelectProperty(&PTZDeviceState::zoom_set_, basic_set,
+ &MediaTrackConstraintSetPlatform::zoom);
+ }
+
+ private:
+ // Select the target value of a property based on the ideal value in
+ // |basic_set| as follows:
+ // If an ideal value is provided, return the value in the range closest to
+ // ideal.
+ // If no ideal value is provided:
+ // * If minimum is provided, return minimum.
+ // * Otherwise, if maximum is provided, return maximum.
+ // * Otherwise, return nullopt.
+ base::Optional<double> SelectProperty(
+ DoubleRangeSet PTZDeviceState::*ptz_field,
+ const MediaTrackConstraintSetPlatform& basic_set,
+ DoubleConstraint MediaTrackConstraintSetPlatform::*basic_set_field)
+ const {
+ if (!(basic_set.*basic_set_field).HasIdeal()) {
+ return (this->*ptz_field).Min().has_value() ? (this->*ptz_field).Min()
+ : (this->*ptz_field).Max();
+ }
+
+ auto ideal = (basic_set.*basic_set_field).Ideal();
+ if ((this->*ptz_field).Min().has_value() &&
+ ideal < (this->*ptz_field).Min().value()) {
+ return (this->*ptz_field).Min();
+ }
+ if ((this->*ptz_field).Max().has_value() &&
+ ideal > (this->*ptz_field).Max().value()) {
+ return (this->*ptz_field).Max();
+ }
+
+ return ideal;
+ }
+
+ DoubleRangeSet pan_set_;
+ DoubleRangeSet tilt_set_;
+ DoubleRangeSet zoom_set_;
+};
+
// Returns true if |constraint_set| can be satisfied by |device|. Otherwise,
// returns false and, if |failed_constraint_name| is not null, updates
// |failed_constraint_name| with the name of a constraint that could not be
@@ -428,6 +557,21 @@ bool DeviceSatisfiesConstraintSet(
return false;
}
+ if (constraint_set.pan.IsPresent() && !device.pan_tilt_zoom_supported) {
+ UpdateFailedConstraintName(constraint_set.pan, failed_constraint_name);
+ return false;
+ }
+
+ if (constraint_set.tilt.IsPresent() && !device.pan_tilt_zoom_supported) {
+ UpdateFailedConstraintName(constraint_set.tilt, failed_constraint_name);
+ return false;
+ }
+
+ if (constraint_set.zoom.IsPresent() && !device.pan_tilt_zoom_supported) {
+ UpdateFailedConstraintName(constraint_set.zoom, failed_constraint_name);
+ return false;
+ }
+
return true;
}
@@ -464,11 +608,13 @@ double DeviceFitness(const DeviceInfo& device,
// The track settings for |candidate| that correspond to the returned fitness
// are returned in |track_settings|.
double CandidateFitness(const DeviceInfo& device,
+ const PTZDeviceState& ptz_state,
const CandidateFormat& candidate_format,
const base::Optional<bool>& noise_reduction,
const MediaTrackConstraintSetPlatform& constraint_set,
VideoTrackAdapterSettings* track_settings) {
return DeviceFitness(device, constraint_set) +
+ ptz_state.Fitness(constraint_set) +
candidate_format.Fitness(constraint_set, track_settings) +
OptionalBoolFitness(noise_reduction,
constraint_set.goog_noise_reduction);
@@ -524,11 +670,13 @@ VideoInputDeviceCapabilities::VideoInputDeviceCapabilities(
String device_id,
String group_id,
Vector<media::VideoCaptureFormat> formats,
- media::VideoFacingMode facing_mode)
+ media::VideoFacingMode facing_mode,
+ bool pan_tilt_zoom_supported)
: device_id(std::move(device_id)),
group_id(std::move(group_id)),
formats(std::move(formats)),
- facing_mode(facing_mode) {}
+ facing_mode(facing_mode),
+ pan_tilt_zoom_supported(pan_tilt_zoom_supported) {}
VideoInputDeviceCapabilities::VideoInputDeviceCapabilities(
VideoInputDeviceCapabilities&& other) = default;
@@ -600,7 +748,14 @@ VideoCaptureSettings SelectSettingsVideoDeviceCapture(
continue;
}
+ PTZDeviceState ptz_device_state(constraints.Basic());
+ if (ptz_device_state.IsEmpty()) {
+ failed_constraint_name = ptz_device_state.FailedConstraintName();
+ continue;
+ }
+
for (auto& format : device.formats) {
+ PTZDeviceState ptz_state_for_format = ptz_device_state;
CandidateFormat candidate_format(format);
if (!candidate_format.ApplyConstraintSet(constraints.Basic(),
&failed_constraint_name)) {
@@ -622,8 +777,11 @@ VideoCaptureSettings SelectSettingsVideoDeviceCapture(
// First criteria for valid candidates is satisfaction of advanced
// constraint sets.
for (const auto& advanced_set : constraints.Advanced()) {
+ PTZDeviceState ptz_advanced_state =
+ ptz_state_for_format.Intersection(advanced_set);
bool satisfies_advanced_set =
DeviceSatisfiesConstraintSet(device, advanced_set) &&
+ !ptz_advanced_state.IsEmpty() &&
OptionalBoolSatisfiesConstraint(
noise_reduction, advanced_set.goog_noise_reduction) &&
// This must be the last in the condition since it is the only
@@ -631,15 +789,18 @@ VideoCaptureSettings SelectSettingsVideoDeviceCapture(
// previous two are true.
candidate_format.ApplyConstraintSet(advanced_set);
+ if (satisfies_advanced_set)
+ ptz_state_for_format = ptz_advanced_state;
+
candidate_distance_vector.push_back(
satisfies_advanced_set ? 0 : HUGE_VAL);
}
VideoTrackAdapterSettings track_settings;
// Second criterion is fitness distance.
- candidate_distance_vector.push_back(
- CandidateFitness(device, candidate_format, noise_reduction,
- constraints.Basic(), &track_settings));
+ candidate_distance_vector.push_back(CandidateFitness(
+ device, ptz_state_for_format, candidate_format, noise_reduction,
+ constraints.Basic(), &track_settings));
// Third criterion is native fitness distance.
candidate_distance_vector.push_back(
@@ -660,7 +821,10 @@ VideoCaptureSettings SelectSettingsVideoDeviceCapture(
result = VideoCaptureSettings(
device.device_id.Utf8(), capture_params, noise_reduction,
track_settings, candidate_format.constrained_frame_rate().Min(),
- candidate_format.constrained_frame_rate().Max());
+ candidate_format.constrained_frame_rate().Max(),
+ ptz_state_for_format.SelectPan(constraints.Basic()),
+ ptz_state_for_format.SelectTilt(constraints.Basic()),
+ ptz_state_for_format.SelectZoom(constraints.Basic()));
}
}
}