Title: [206445] trunk/Source/WebCore
Revision
206445
Author
eric.carl...@apple.com
Date
2016-09-27 10:58:44 -0700 (Tue, 27 Sep 2016)

Log Message

[MediaStream] Restructure MediaConstraints classes
https://bugs.webkit.org/show_bug.cgi?id=162571

Reviewed by Jer Noble.

No new tests, no functional changes.

* Modules/mediastream/MediaConstraintsImpl.cpp:
(WebCore::MediaConstraintsImpl::initialize): Deleted, no longer used.
* Modules/mediastream/MediaConstraintsImpl.h:

* bindings/js/JSMediaDevicesCustom.cpp:
(WebCore::createStringConstraint): Return Optional<> instead of RefPtr<>.
(WebCore::createBooleanConstraint): Ditto.
(WebCore::createDoubleConstraint): Ditto.
(WebCore::createIntConstraint): Ditto.
(WebCore::parseMediaTrackConstraintSetForKey): Deal with above change.

* platform/mediastream/CaptureDeviceManager.cpp:
(CaptureDeviceManager::verifyConstraintsForMediaType): Use constraints.mandatoryConstraints.filter
  instead of direct enumeration.
(CaptureDeviceManager::sessionSupportsConstraint): Use downcast<>.
(CaptureDeviceManager::isSupportedFrameRate): Ditto.

* platform/mediastream/MediaConstraints.cpp:
(WebCore::StringConstraint::find): Lose the ConstraintType parameter.
(WebCore::StringConstraint::merge): Use downcast<>.
(WebCore::FlattenedConstraint::set): Use ConstraintHolder.
(WebCore::FlattenedConstraint::merge): Ditto.
(WebCore::MediaTrackConstraintSetMap::forEach): New.
(WebCore::MediaTrackConstraintSetMap::filter): Ditto.
(WebCore::MediaTrackConstraintSetMap::isEmpty): Ditto.
(WebCore::MediaTrackConstraintSetMap::set): Ditto.
(WebCore::MediaConstraint::copy): Deleted.
(WebCore::IntConstraint::copy): Deleted.
(WebCore::DoubleConstraint::copy): Deleted.
(WebCore::BooleanConstraint::copy): Deleted.
(WebCore::StringConstraint::copy): Deleted.
* platform/mediastream/MediaConstraints.h:
(WebCore::MediaConstraint::MediaConstraint):
(WebCore::MediaConstraint::isEmpty):
(WebCore::MediaConstraint::isMandatory):
(WebCore::MediaConstraint::merge):
(WebCore::MediaConstraint::isInt):
(WebCore::MediaConstraint::isDouble):
(WebCore::MediaConstraint::isBoolean):
(WebCore::MediaConstraint::isString):
(WebCore::MediaConstraint::dataType):
(WebCore::MediaConstraint::constraintType):
(WebCore::NumericConstraint::getMin):
(WebCore::NumericConstraint::getMax):
(WebCore::NumericConstraint::getExact):
(WebCore::NumericConstraint::getIdeal):
(WebCore::NumericConstraint::fitnessDistance):
(WebCore::NumericConstraint::validForRange):
(WebCore::NumericConstraint::find):
(WebCore::NumericConstraint::NumericConstraint):
(WebCore::NumericConstraint::innerMerge):
(WebCore::FlattenedConstraint::isEmpty):
(WebCore::FlattenedConstraint::iterator::iterator):
(WebCore::FlattenedConstraint::iterator::operator*):
(WebCore::FlattenedConstraint::iterator::operator++):
(WebCore::FlattenedConstraint::iterator::operator==):
(WebCore::FlattenedConstraint::iterator::operator!=):
(WebCore::FlattenedConstraint::begin):
(WebCore::FlattenedConstraint::end):
(WebCore::FlattenedConstraint::ConstraintHolder::create):
(WebCore::FlattenedConstraint::ConstraintHolder::~ConstraintHolder):
(WebCore::FlattenedConstraint::ConstraintHolder::constraint):
(WebCore::FlattenedConstraint::ConstraintHolder::dataType):
(WebCore::FlattenedConstraint::ConstraintHolder::constraintType):
(WebCore::FlattenedConstraint::ConstraintHolder::ConstraintHolder):
(WebCore::MediaConstraint::getMin): Deleted.
(WebCore::MediaConstraint::getMax): Deleted.
(WebCore::MediaConstraint::getExact): Deleted.
(WebCore::MediaConstraint::getIdeal): Deleted.
(WebCore::MediaConstraint::validForRange): Deleted.
(WebCore::MediaConstraint::find): Deleted.
(WebCore::MediaConstraint::fitnessDistance): Deleted.
(WebCore::MediaConstraint::type): Deleted.

* platform/mediastream/RealtimeMediaSource.cpp:
(WebCore::RealtimeMediaSource::fitnessDistance): Use downcast<>.
(WebCore::applyNumericConstraint):
(WebCore::RealtimeMediaSource::applyConstraint): Ditto.
(WebCore::RealtimeMediaSource::selectSettings): Ditto. Use constraints.mandatoryConstraints.filter
  instead of direct enumeration.
(WebCore::RealtimeMediaSource::applyConstraints):
(WebCore::RealtimeMediaSource::setSampleRate): Sample rate is an int, not a double.
(WebCore::RealtimeMediaSource::setSampleSize): Sample size is also an int.
* platform/mediastream/RealtimeMediaSource.h:

* platform/mediastream/mac/AVCaptureDeviceManager.mm:
(WebCore::AVCaptureDeviceManager::sessionSupportsConstraint): Use downcast<>.

* platform/mock/MediaConstraintsMock.cpp:
(WebCore::isIntMediaConstraintSatisfiable): Use downcast<>.
(WebCore::isDoubleMediaConstraintSatisfiable): Ditto.
(WebCore::isBooleanMediaConstraintSatisfiable): Ditto.
(WebCore::isStringMediaConstraintSatisfiable):
(WebCore::isSatisfiable):
(WebCore::MediaConstraintsMock::verifyConstraints): Use constraints.mandatoryConstraints.filter
  instead of direct enumeration.
* platform/mock/MediaConstraintsMock.h:

* platform/mock/MockRealtimeAudioSource.h:
* platform/mock/MockRealtimeMediaSourceCenter.cpp:
(WebCore::MockRealtimeMediaSourceCenter::createMediaStream):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (206444 => 206445)


--- trunk/Source/WebCore/ChangeLog	2016-09-27 17:54:49 UTC (rev 206444)
+++ trunk/Source/WebCore/ChangeLog	2016-09-27 17:58:44 UTC (rev 206445)
@@ -1,3 +1,114 @@
+2016-09-27  Eric Carlson  <eric.carl...@apple.com>
+
+        [MediaStream] Restructure MediaConstraints classes
+        https://bugs.webkit.org/show_bug.cgi?id=162571
+
+        Reviewed by Jer Noble.
+
+        No new tests, no functional changes.
+
+        * Modules/mediastream/MediaConstraintsImpl.cpp:
+        (WebCore::MediaConstraintsImpl::initialize): Deleted, no longer used.
+        * Modules/mediastream/MediaConstraintsImpl.h:
+
+        * bindings/js/JSMediaDevicesCustom.cpp:
+        (WebCore::createStringConstraint): Return Optional<> instead of RefPtr<>.
+        (WebCore::createBooleanConstraint): Ditto.
+        (WebCore::createDoubleConstraint): Ditto.
+        (WebCore::createIntConstraint): Ditto.
+        (WebCore::parseMediaTrackConstraintSetForKey): Deal with above change.
+
+        * platform/mediastream/CaptureDeviceManager.cpp:
+        (CaptureDeviceManager::verifyConstraintsForMediaType): Use constraints.mandatoryConstraints.filter
+          instead of direct enumeration.
+        (CaptureDeviceManager::sessionSupportsConstraint): Use downcast<>.
+        (CaptureDeviceManager::isSupportedFrameRate): Ditto.
+
+        * platform/mediastream/MediaConstraints.cpp:
+        (WebCore::StringConstraint::find): Lose the ConstraintType parameter.
+        (WebCore::StringConstraint::merge): Use downcast<>.
+        (WebCore::FlattenedConstraint::set): Use ConstraintHolder.
+        (WebCore::FlattenedConstraint::merge): Ditto.
+        (WebCore::MediaTrackConstraintSetMap::forEach): New.
+        (WebCore::MediaTrackConstraintSetMap::filter): Ditto.
+        (WebCore::MediaTrackConstraintSetMap::isEmpty): Ditto.
+        (WebCore::MediaTrackConstraintSetMap::set): Ditto.
+        (WebCore::MediaConstraint::copy): Deleted.
+        (WebCore::IntConstraint::copy): Deleted.
+        (WebCore::DoubleConstraint::copy): Deleted.
+        (WebCore::BooleanConstraint::copy): Deleted.
+        (WebCore::StringConstraint::copy): Deleted.
+        * platform/mediastream/MediaConstraints.h:
+        (WebCore::MediaConstraint::MediaConstraint):
+        (WebCore::MediaConstraint::isEmpty):
+        (WebCore::MediaConstraint::isMandatory):
+        (WebCore::MediaConstraint::merge):
+        (WebCore::MediaConstraint::isInt):
+        (WebCore::MediaConstraint::isDouble):
+        (WebCore::MediaConstraint::isBoolean):
+        (WebCore::MediaConstraint::isString):
+        (WebCore::MediaConstraint::dataType):
+        (WebCore::MediaConstraint::constraintType):
+        (WebCore::NumericConstraint::getMin):
+        (WebCore::NumericConstraint::getMax):
+        (WebCore::NumericConstraint::getExact):
+        (WebCore::NumericConstraint::getIdeal):
+        (WebCore::NumericConstraint::fitnessDistance):
+        (WebCore::NumericConstraint::validForRange):
+        (WebCore::NumericConstraint::find):
+        (WebCore::NumericConstraint::NumericConstraint):
+        (WebCore::NumericConstraint::innerMerge):
+        (WebCore::FlattenedConstraint::isEmpty):
+        (WebCore::FlattenedConstraint::iterator::iterator):
+        (WebCore::FlattenedConstraint::iterator::operator*):
+        (WebCore::FlattenedConstraint::iterator::operator++):
+        (WebCore::FlattenedConstraint::iterator::operator==):
+        (WebCore::FlattenedConstraint::iterator::operator!=):
+        (WebCore::FlattenedConstraint::begin):
+        (WebCore::FlattenedConstraint::end):
+        (WebCore::FlattenedConstraint::ConstraintHolder::create):
+        (WebCore::FlattenedConstraint::ConstraintHolder::~ConstraintHolder):
+        (WebCore::FlattenedConstraint::ConstraintHolder::constraint):
+        (WebCore::FlattenedConstraint::ConstraintHolder::dataType):
+        (WebCore::FlattenedConstraint::ConstraintHolder::constraintType):
+        (WebCore::FlattenedConstraint::ConstraintHolder::ConstraintHolder):
+        (WebCore::MediaConstraint::getMin): Deleted.
+        (WebCore::MediaConstraint::getMax): Deleted.
+        (WebCore::MediaConstraint::getExact): Deleted.
+        (WebCore::MediaConstraint::getIdeal): Deleted.
+        (WebCore::MediaConstraint::validForRange): Deleted.
+        (WebCore::MediaConstraint::find): Deleted.
+        (WebCore::MediaConstraint::fitnessDistance): Deleted.
+        (WebCore::MediaConstraint::type): Deleted.
+
+        * platform/mediastream/RealtimeMediaSource.cpp:
+        (WebCore::RealtimeMediaSource::fitnessDistance): Use downcast<>.
+        (WebCore::applyNumericConstraint):
+        (WebCore::RealtimeMediaSource::applyConstraint): Ditto.
+        (WebCore::RealtimeMediaSource::selectSettings): Ditto. Use constraints.mandatoryConstraints.filter
+          instead of direct enumeration.
+        (WebCore::RealtimeMediaSource::applyConstraints):
+        (WebCore::RealtimeMediaSource::setSampleRate): Sample rate is an int, not a double.
+        (WebCore::RealtimeMediaSource::setSampleSize): Sample size is also an int.
+        * platform/mediastream/RealtimeMediaSource.h:
+
+        * platform/mediastream/mac/AVCaptureDeviceManager.mm:
+        (WebCore::AVCaptureDeviceManager::sessionSupportsConstraint): Use downcast<>.
+
+        * platform/mock/MediaConstraintsMock.cpp:
+        (WebCore::isIntMediaConstraintSatisfiable): Use downcast<>.
+        (WebCore::isDoubleMediaConstraintSatisfiable): Ditto.
+        (WebCore::isBooleanMediaConstraintSatisfiable): Ditto.
+        (WebCore::isStringMediaConstraintSatisfiable):
+        (WebCore::isSatisfiable):
+        (WebCore::MediaConstraintsMock::verifyConstraints): Use constraints.mandatoryConstraints.filter
+          instead of direct enumeration.
+        * platform/mock/MediaConstraintsMock.h:
+
+        * platform/mock/MockRealtimeAudioSource.h:
+        * platform/mock/MockRealtimeMediaSourceCenter.cpp:
+        (WebCore::MockRealtimeMediaSourceCenter::createMediaStream):
+
 2016-09-27  Wenson Hsieh  <wenson_hs...@apple.com>
 
         Some Now Playing behavior is broken after r206315

Modified: trunk/Source/WebCore/Modules/mediastream/MediaConstraintsImpl.cpp (206444 => 206445)


--- trunk/Source/WebCore/Modules/mediastream/MediaConstraintsImpl.cpp	2016-09-27 17:54:49 UTC (rev 206444)
+++ trunk/Source/WebCore/Modules/mediastream/MediaConstraintsImpl.cpp	2016-09-27 17:58:44 UTC (rev 206445)
@@ -46,13 +46,6 @@
     return adoptRef(*new MediaConstraintsImpl());
 }
 
-// FIXME: Remove after https://bugs.webkit.org/show_bug.cgi?id=160579
-void MediaConstraintsImpl::initialize(const Dictionary& constraints)
-{
-    if (constraints.isUndefinedOrNull())
-        return;
-}
-
 Ref<MediaConstraintsImpl> MediaConstraintsImpl::create(MediaTrackConstraintSetMap&& mandatoryConstraints, Vector<MediaTrackConstraintSetMap>&& advancedConstraints, bool isValid)
 {
     return adoptRef(*new MediaConstraintsImpl(WTFMove(mandatoryConstraints), WTFMove(advancedConstraints), isValid));

Modified: trunk/Source/WebCore/Modules/mediastream/MediaConstraintsImpl.h (206444 => 206445)


--- trunk/Source/WebCore/Modules/mediastream/MediaConstraintsImpl.h	2016-09-27 17:54:49 UTC (rev 206444)
+++ trunk/Source/WebCore/Modules/mediastream/MediaConstraintsImpl.h	2016-09-27 17:58:44 UTC (rev 206445)
@@ -48,7 +48,6 @@
     static Ref<MediaConstraintsImpl> create(MediaTrackConstraintSetMap&& mandatoryConstraints, Vector<MediaTrackConstraintSetMap>&& advancedConstraints, bool isValid);
 
     virtual ~MediaConstraintsImpl();
-    void initialize(const Dictionary&);
 
     const MediaTrackConstraintSetMap& mandatoryConstraints() const final { return m_mandatoryConstraints; }
     const Vector<MediaTrackConstraintSetMap>& advancedConstraints() const final { return m_advancedConstraints; }

Modified: trunk/Source/WebCore/bindings/js/JSMediaDevicesCustom.cpp (206444 => 206445)


--- trunk/Source/WebCore/bindings/js/JSMediaDevicesCustom.cpp	2016-09-27 17:54:49 UTC (rev 206444)
+++ trunk/Source/WebCore/bindings/js/JSMediaDevicesCustom.cpp	2016-09-27 17:58:44 UTC (rev 206445)
@@ -58,9 +58,9 @@
     }
 }
 
-static RefPtr<StringConstraint> createStringConstraint(const Dictionary& mediaTrackConstraintSet, const String& name, MediaConstraintType type, ConstraintSetType constraintSetType)
+static Optional<StringConstraint> createStringConstraint(const Dictionary& mediaTrackConstraintSet, const String& name, MediaConstraintType type, ConstraintSetType constraintSetType)
 {
-    auto constraint = StringConstraint::create(name, type);
+    auto constraint = StringConstraint(name, type);
 
     // Dictionary constraint value.
     Dictionary dictionaryValue;
@@ -71,7 +71,7 @@
         else {
             String exactStringValue;
             if (dictionaryValue.get("exact", exactStringValue))
-                constraint->setExact(exactStringValue);
+                constraint.setExact(exactStringValue);
         }
 
         ArrayValue idealArrayValue;
@@ -80,12 +80,12 @@
         else {
             String idealStringValue;
             if (!dictionaryValue.get("ideal", idealStringValue))
-                constraint->setIdeal(idealStringValue);
+                constraint.setIdeal(idealStringValue);
         }
 
-        if (constraint->isEmpty()) {
+        if (constraint.isEmpty()) {
             LOG(Media, "createStringConstraint() - ignoring string constraint '%s' with dictionary value since it has no valid or supported key/value pairs.", name.utf8().data());
-            return nullptr;
+            return Nullopt;
         }
         
         return WTFMove(constraint);
@@ -96,9 +96,9 @@
     if (mediaTrackConstraintSet.get(name, arrayValue) && !arrayValue.isUndefinedOrNull()) {
         initializeStringConstraintWithList(constraint, &StringConstraint::appendIdeal, arrayValue);
 
-        if (constraint->isEmpty()) {
+        if (constraint.isEmpty()) {
             LOG(Media, "createStringConstraint() - ignoring string constraint '%s' with array value since it is empty.", name.utf8().data());
-            return nullptr;
+            return Nullopt;
         }
 
         return WTFMove(constraint);
@@ -108,9 +108,9 @@
     String value;
     if (mediaTrackConstraintSet.get(name, value)) {
         if (constraintSetType == ConstraintSetType::Mandatory)
-            constraint->setIdeal(value);
+            constraint.setIdeal(value);
         else
-            constraint->setExact(value);
+            constraint.setExact(value);
         
         return WTFMove(constraint);
     }
@@ -117,12 +117,12 @@
 
     // Invalid constraint value.
     LOG(Media, "createStringConstraint() - ignoring string constraint '%s' since it has neither a dictionary nor sequence nor scalar value.", name.utf8().data());
-    return nullptr;
+    return Nullopt;
 }
 
-static RefPtr<BooleanConstraint> createBooleanConstraint(const Dictionary& mediaTrackConstraintSet, const String& name, MediaConstraintType type, ConstraintSetType constraintSetType)
+static Optional<BooleanConstraint> createBooleanConstraint(const Dictionary& mediaTrackConstraintSet, const String& name, MediaConstraintType type, ConstraintSetType constraintSetType)
 {
-    auto constraint = BooleanConstraint::create(name, type);
+    auto constraint = BooleanConstraint(name, type);
 
     // Dictionary constraint value.
     Dictionary dictionaryValue;
@@ -129,15 +129,15 @@
     if (mediaTrackConstraintSet.get(name, dictionaryValue) && !dictionaryValue.isUndefinedOrNull()) {
         bool exactValue;
         if (dictionaryValue.get("exact", exactValue))
-            constraint->setExact(exactValue);
+            constraint.setExact(exactValue);
 
         bool idealValue;
         if (dictionaryValue.get("ideal", idealValue))
-            constraint->setIdeal(idealValue);
+            constraint.setIdeal(idealValue);
 
-        if (constraint->isEmpty()) {
+        if (constraint.isEmpty()) {
             LOG(Media, "createBooleanConstraint() - ignoring boolean constraint '%s' with dictionary value since it has no valid or supported key/value pairs.", name.utf8().data());
-            return nullptr;
+            return Nullopt;
         }
 
         return WTFMove(constraint);
@@ -147,9 +147,9 @@
     bool value;
     if (mediaTrackConstraintSet.get(name, value)) {
         if (constraintSetType == ConstraintSetType::Mandatory)
-            constraint->setIdeal(value);
+            constraint.setIdeal(value);
         else
-            constraint->setExact(value);
+            constraint.setExact(value);
         
         return WTFMove(constraint);
     }
@@ -156,12 +156,12 @@
 
     // Invalid constraint value.
     LOG(Media, "createBooleanConstraint() - ignoring boolean constraint '%s' since it has neither a dictionary nor scalar value.", name.utf8().data());
-    return nullptr;
+    return Nullopt;
 }
 
-static RefPtr<DoubleConstraint> createDoubleConstraint(const Dictionary& mediaTrackConstraintSet, const String& name, MediaConstraintType type, ConstraintSetType constraintSetType)
+static Optional<DoubleConstraint> createDoubleConstraint(const Dictionary& mediaTrackConstraintSet, const String& name, MediaConstraintType type, ConstraintSetType constraintSetType)
 {
-    auto constraint = DoubleConstraint::create(name, type);
+    auto constraint = DoubleConstraint(name, type);
 
     // Dictionary constraint value.
     Dictionary dictionaryValue;
@@ -168,23 +168,23 @@
     if (mediaTrackConstraintSet.get(name, dictionaryValue) && !dictionaryValue.isUndefinedOrNull()) {
         double minValue;
         if (dictionaryValue.get("min", minValue))
-            constraint->setMin(minValue);
+            constraint.setMin(minValue);
 
         double maxValue;
         if (dictionaryValue.get("max", maxValue))
-            constraint->setMax(maxValue);
+            constraint.setMax(maxValue);
 
         double exactValue;
         if (dictionaryValue.get("exact", exactValue))
-            constraint->setExact(exactValue);
+            constraint.setExact(exactValue);
 
         double idealValue;
         if (dictionaryValue.get("ideal", idealValue))
-            constraint->setIdeal(idealValue);
+            constraint.setIdeal(idealValue);
 
-        if (constraint->isEmpty()) {
+        if (constraint.isEmpty()) {
             LOG(Media, "createDoubleConstraint() - ignoring double constraint '%s' with dictionary value since it has no valid or supported key/value pairs.", name.utf8().data());
-            return nullptr;
+            return Nullopt;
         }
 
         return WTFMove(constraint);
@@ -194,9 +194,9 @@
     double value;
     if (mediaTrackConstraintSet.get(name, value)) {
         if (constraintSetType == ConstraintSetType::Mandatory)
-            constraint->setIdeal(value);
+            constraint.setIdeal(value);
         else
-            constraint->setExact(value);
+            constraint.setExact(value);
         
         return WTFMove(constraint);
     }
@@ -203,12 +203,12 @@
 
     // Invalid constraint value.
     LOG(Media, "createDoubleConstraint() - ignoring double constraint '%s' since it has neither a dictionary nor scalar value.", name.utf8().data());
-    return nullptr;
+    return Nullopt;
 }
 
-static RefPtr<IntConstraint> createIntConstraint(const Dictionary& mediaTrackConstraintSet, const String& name, MediaConstraintType type, ConstraintSetType constraintSetType)
+static Optional<IntConstraint> createIntConstraint(const Dictionary& mediaTrackConstraintSet, const String& name, MediaConstraintType type, ConstraintSetType constraintSetType)
 {
-    auto constraint = IntConstraint::create(name, type);
+    auto constraint = IntConstraint(name, type);
 
     // Dictionary constraint value.
     Dictionary dictionaryValue;
@@ -215,23 +215,23 @@
     if (mediaTrackConstraintSet.get(name, dictionaryValue) && !dictionaryValue.isUndefinedOrNull()) {
         int minValue;
         if (dictionaryValue.get("min", minValue))
-            constraint->setMin(minValue);
+            constraint.setMin(minValue);
 
         int maxValue;
         if (dictionaryValue.get("max", maxValue))
-            constraint->setMax(maxValue);
+            constraint.setMax(maxValue);
 
         int exactValue;
         if (dictionaryValue.get("exact", exactValue))
-            constraint->setExact(exactValue);
+            constraint.setExact(exactValue);
 
         int idealValue;
         if (dictionaryValue.get("ideal", idealValue))
-            constraint->setIdeal(idealValue);
+            constraint.setIdeal(idealValue);
 
-        if (constraint->isEmpty()) {
+        if (constraint.isEmpty()) {
             LOG(Media, "createIntConstraint() - ignoring long constraint '%s' with dictionary value since it has no valid or supported key/value pairs.", name.utf8().data());
-            return nullptr;
+            return Nullopt;
         }
 
         return WTFMove(constraint);
@@ -241,9 +241,9 @@
     int value;
     if (mediaTrackConstraintSet.get(name, value)) {
         if (constraintSetType == ConstraintSetType::Mandatory)
-            constraint->setIdeal(value);
+            constraint.setIdeal(value);
         else
-            constraint->setExact(value);
+            constraint.setExact(value);
         
         return WTFMove(constraint);
     }
@@ -250,45 +250,54 @@
 
     // Invalid constraint value.
     LOG(Media, "createIntConstraint() - ignoring long constraint '%s' since it has neither a dictionary nor scalar value.", name.utf8().data());
-    return nullptr;
+    return Nullopt;
 }
 
 static void parseMediaTrackConstraintSetForKey(const Dictionary& mediaTrackConstraintSet, const String& name, MediaTrackConstraintSetMap& map, ConstraintSetType constraintSetType)
 {
     MediaConstraintType constraintType = RealtimeMediaSourceSupportedConstraints::constraintFromName(name);
-
-    RefPtr<MediaConstraint> mediaConstraint;
     switch (constraintType) {
     case MediaConstraintType::Width:
+        map.set(constraintType, createIntConstraint(mediaTrackConstraintSet, name, constraintType, constraintSetType));
+        break;
     case MediaConstraintType::Height:
+        map.set(constraintType, createIntConstraint(mediaTrackConstraintSet, name, constraintType, constraintSetType));
+        break;
     case MediaConstraintType::SampleRate:
+        map.set(constraintType, createIntConstraint(mediaTrackConstraintSet, name, constraintType, constraintSetType));
+        break;
     case MediaConstraintType::SampleSize:
-        mediaConstraint = createIntConstraint(mediaTrackConstraintSet, name, constraintType, constraintSetType);
+        map.set(constraintType, createIntConstraint(mediaTrackConstraintSet, name, constraintType, constraintSetType));
         break;
 
     case MediaConstraintType::AspectRatio:
+        map.set(constraintType, createDoubleConstraint(mediaTrackConstraintSet, name, constraintType, constraintSetType));
+        break;
     case MediaConstraintType::FrameRate:
+        map.set(constraintType, createDoubleConstraint(mediaTrackConstraintSet, name, constraintType, constraintSetType));
+        break;
     case MediaConstraintType::Volume:
-        mediaConstraint = createDoubleConstraint(mediaTrackConstraintSet, name, constraintType, constraintSetType);
+        map.set(constraintType, createDoubleConstraint(mediaTrackConstraintSet, name, constraintType, constraintSetType));
         break;
 
     case MediaConstraintType::EchoCancellation:
-        mediaConstraint = createBooleanConstraint(mediaTrackConstraintSet, name, constraintType, constraintSetType);
+        map.set(constraintType, createBooleanConstraint(mediaTrackConstraintSet, name, constraintType, constraintSetType));
         break;
 
     case MediaConstraintType::FacingMode:
+        map.set(constraintType, createStringConstraint(mediaTrackConstraintSet, name, constraintType, constraintSetType));
+        break;
     case MediaConstraintType::DeviceId:
+        map.set(constraintType, createStringConstraint(mediaTrackConstraintSet, name, constraintType, constraintSetType));
+        break;
     case MediaConstraintType::GroupId:
-        mediaConstraint = createStringConstraint(mediaTrackConstraintSet, name, constraintType, constraintSetType);
+        map.set(constraintType, createStringConstraint(mediaTrackConstraintSet, name, constraintType, constraintSetType));
         break;
 
     case MediaConstraintType::Unknown:
-        LOG(Media, "parseMediaTrackConstraintSetForKey() - found unsupported constraint '%s'.", name.utf8().data());
-        mediaConstraint = UnknownConstraint::create(name, constraintType);
-        break;
+        LOG(Media, "parseMediaTrackConstraintSetForKey() - ignoring unsupported constraint '%s'.", name.utf8().data());
+        return;
     }
-    
-    map.add(name, WTFMove(mediaConstraint));
 }
 
 static void parseAdvancedConstraints(const Dictionary& mediaTrackConstraints, Vector<MediaTrackConstraintSetMap>& advancedConstraints)

Modified: trunk/Source/WebCore/platform/mediastream/CaptureDeviceManager.cpp (206444 => 206445)


--- trunk/Source/WebCore/platform/mediastream/CaptureDeviceManager.cpp	2016-09-27 17:54:49 UTC (rev 206444)
+++ trunk/Source/WebCore/platform/mediastream/CaptureDeviceManager.cpp	2016-09-27 17:58:44 UTC (rev 206445)
@@ -72,16 +72,18 @@
 
 bool CaptureDeviceManager::verifyConstraintsForMediaType(RealtimeMediaSource::Type type, const MediaConstraints& constraints, const CaptureSessionInfo* session, String& invalidConstraint)
 {
-    auto& mandatoryConstraints = constraints.mandatoryConstraints();
-    for (auto& nameConstraintPair : mandatoryConstraints) {
-        if (sessionSupportsConstraint(session, type, *nameConstraintPair.value))
-            continue;
+    invalidConstraint = emptyString();
+    constraints.mandatoryConstraints().filter([&](const MediaConstraint& constraint) {
+        if (!sessionSupportsConstraint(session, type, constraint)) {
+            invalidConstraint = constraint.name();
+            return true;
+        }
 
-        invalidConstraint = nameConstraintPair.key;
         return false;
-    }
+    });
 
-    return true;
+    return invalidConstraint.isEmpty();
+
 }
 
 Vector<RefPtr<RealtimeMediaSource>> CaptureDeviceManager::bestSourcesForTypeAndConstraints(RealtimeMediaSource::Type type, MediaConstraints& constraints)
@@ -153,7 +155,7 @@
 bool CaptureDeviceManager::sessionSupportsConstraint(const CaptureSessionInfo*, RealtimeMediaSource::Type type, const MediaConstraint& constraint)
 {
     const RealtimeMediaSourceSupportedConstraints& supportedConstraints = RealtimeMediaSourceCenter::singleton().supportedConstraints();
-    MediaConstraintType constraintType = constraint.type();
+    MediaConstraintType constraintType = constraint.constraintType();
     if (!supportedConstraints.supportsConstraint(constraintType))
         return false;
 
@@ -176,7 +178,7 @@
 
         // FIXME: https://bugs.webkit.org/show_bug.cgi?id=160793. Handle sequence of facingMode constraints.
         Vector<String> exactFacingMode;
-        if (!constraint.getExact(exactFacingMode))
+        if (!downcast<const StringConstraint>(constraint).getExact(exactFacingMode))
             return false;
 
         return bestDeviceForFacingMode(facingModeFromString(exactFacingMode[0]));
@@ -192,15 +194,15 @@
     bool isSupported = true;
 
     int min = 0;
-    if (constraint.getMin(min))
+    if (downcast<const IntConstraint>(constraint).getMin(min))
         isSupported &= min > 60;
 
     int max = 60;
-    if (constraint.getMax(max))
+    if (downcast<const IntConstraint>(constraint).getMax(max))
         isSupported &= max < min;
 
     int exact;
-    if (constraint.getExact(exact))
+    if (downcast<const IntConstraint>(constraint).getExact(exact))
         isSupported &= (exact < min || exact > max);
 
     return isSupported;

Modified: trunk/Source/WebCore/platform/mediastream/MediaConstraints.cpp (206444 => 206445)


--- trunk/Source/WebCore/platform/mediastream/MediaConstraints.cpp	2016-09-27 17:54:49 UTC (rev 206444)
+++ trunk/Source/WebCore/platform/mediastream/MediaConstraints.cpp	2016-09-27 17:58:44 UTC (rev 206445)
@@ -34,82 +34,10 @@
 #if ENABLE(MEDIA_STREAM)
 #include "RealtimeMediaSourceCenter.h"
 #include "RealtimeMediaSourceSupportedConstraints.h"
+#include <wtf/StdLibExtras.h>
 
 namespace WebCore {
 
-Ref<MediaConstraint> MediaConstraint::create(const String& name)
-{
-    MediaConstraintType constraintType = RealtimeMediaSourceSupportedConstraints::constraintFromName(name);
-
-    switch (constraintType) {
-    case MediaConstraintType::Width:
-    case MediaConstraintType::Height:
-    case MediaConstraintType::SampleRate:
-    case MediaConstraintType::SampleSize:
-        return IntConstraint::create(name, constraintType);
-    case MediaConstraintType::AspectRatio:
-    case MediaConstraintType::FrameRate:
-    case MediaConstraintType::Volume:
-        return DoubleConstraint::create(name, constraintType);
-    case MediaConstraintType::EchoCancellation:
-        return BooleanConstraint::create(name, constraintType);
-    case MediaConstraintType::FacingMode:
-    case MediaConstraintType::DeviceId:
-    case MediaConstraintType::GroupId:
-        return StringConstraint::create(name, constraintType);
-    case MediaConstraintType::Unknown:
-        return UnknownConstraint::create(name, constraintType);
-    }
-
-    ASSERT_NOT_REACHED();
-    return MediaConstraint::create(String());
-}
-
-Ref<MediaConstraint> MediaConstraint::copy() const
-{
-    return MediaConstraint::create(name());
-}
-
-Ref<MediaConstraint> IntConstraint::copy() const
-{
-    auto copy = IntConstraint::create(name(), type());
-    copy->m_min = m_min;
-    copy->m_max = m_max;
-    copy->m_exact = m_exact;
-    copy->m_ideal = m_ideal;
-
-    return copy.leakRef();
-}
-
-Ref<MediaConstraint> DoubleConstraint::copy() const
-{
-    auto copy = DoubleConstraint::create(name(), type());
-    copy->m_min = m_min;
-    copy->m_max = m_max;
-    copy->m_exact = m_exact;
-    copy->m_ideal = m_ideal;
-    
-    return copy.leakRef();
-}
-
-Ref<MediaConstraint> BooleanConstraint::copy() const
-{
-    auto copy = BooleanConstraint::create(name(), type());
-    copy->m_exact = m_exact;
-    copy->m_ideal = m_ideal;
-
-    return copy.leakRef();
-}
-
-Ref<MediaConstraint> StringConstraint::copy() const
-{
-    auto copy = StringConstraint::create(name(), type());
-    copy->m_exact = m_exact;
-    copy->m_ideal = m_ideal;
-
-    return copy.leakRef();
-}
-
 bool BooleanConstraint::getExact(bool& exact) const
 {
     if (!m_exact)
@@ -169,15 +97,15 @@
     return true;
 }
 
-const String& StringConstraint::find(std::function<bool(ConstraintType, const String&)> filter) const
+const String& StringConstraint::find(std::function<bool(const String&)> filter) const
 {
     for (auto& constraint : m_exact) {
-        if (filter(ConstraintType::ExactConstraint, constraint))
+        if (filter(constraint))
             return constraint;
     }
 
     for (auto& constraint : m_ideal) {
-        if (filter(ConstraintType::IdealConstraint, constraint))
+        if (filter(constraint))
             return constraint;
     }
     
@@ -222,11 +150,14 @@
 
 void StringConstraint::merge(const MediaConstraint& other)
 {
+    ASSERT(other.isString());
+    const StringConstraint& typedOther = downcast<StringConstraint>(other);
+
     if (other.isEmpty())
         return;
 
     Vector<String> values;
-    if (other.getExact(values)) {
+    if (typedOther.getExact(values)) {
         if (m_exact.isEmpty())
             m_exact = values;
         else {
@@ -237,7 +168,7 @@
         }
     }
 
-    if (other.getIdeal(values)) {
+    if (typedOther.getIdeal(values)) {
         if (m_ideal.isEmpty())
             m_ideal = values;
         else {
@@ -251,28 +182,235 @@
 
 void FlattenedConstraint::set(const MediaConstraint& constraint)
 {
-    for (auto existingConstraint : m_constraints) {
-        if (existingConstraint->type() == constraint.type()) {
-            existingConstraint = constraint.copy();
+    for (auto& variant : m_variants) {
+        if (variant.constraintType() == constraint.constraintType())
             return;
-        }
     }
 
-    m_constraints.append(constraint.copy());
+    append(constraint);
 }
 
 void FlattenedConstraint::merge(const MediaConstraint& constraint)
 {
-    for (auto existingConstraint : m_constraints) {
-        if (existingConstraint->type() == constraint.type()) {
-            existingConstraint->merge(constraint);
+    for (auto& variant : *this) {
+        if (variant.constraintType() != constraint.constraintType())
+            continue;
+
+        switch (variant.dataType()) {
+        case MediaConstraint::DataType::Integer:
+            ASSERT(constraint.isInt());
+            downcast<const IntConstraint>(variant).merge(downcast<const IntConstraint>(constraint));
             return;
+        case MediaConstraint::DataType::Double:
+            ASSERT(constraint.isDouble());
+            downcast<const DoubleConstraint>(variant).merge(downcast<const DoubleConstraint>(constraint));
+            return;
+        case MediaConstraint::DataType::Boolean:
+            ASSERT(constraint.isBoolean());
+            downcast<const BooleanConstraint>(variant).merge(downcast<const BooleanConstraint>(constraint));
+            return;
+        case MediaConstraint::DataType::String:
+            ASSERT(constraint.isString());
+            downcast<const StringConstraint>(variant).merge(downcast<const StringConstraint>(constraint));
+            return;
+        case MediaConstraint::DataType::None:
+            ASSERT_NOT_REACHED();
+            return;
         }
     }
 
-    m_constraints.append(constraint.copy());
+    append(constraint);
 }
 
+void FlattenedConstraint::append(const MediaConstraint& constraint)
+{
+#ifndef NDEBUG
+    ++m_generation;
+#endif
+
+    m_variants.append(ConstraintHolder::create(constraint));
+
 }
 
+void MediaTrackConstraintSetMap::forEach(std::function<void(const MediaConstraint&)> callback) const
+{
+    if (m_width && !m_width->isEmpty())
+        callback(*m_width);
+    if (m_height && !m_height->isEmpty())
+        callback(*m_height);
+    if (m_sampleRate && !m_sampleRate->isEmpty())
+        callback(*m_sampleRate);
+    if (m_sampleSize && !m_sampleSize->isEmpty())
+        callback(*m_sampleSize);
+
+    if (m_aspectRatio && !m_aspectRatio->isEmpty())
+        callback(*m_aspectRatio);
+    if (m_frameRate && !m_frameRate->isEmpty())
+        callback(*m_frameRate);
+    if (m_volume && !m_volume->isEmpty())
+        callback(*m_volume);
+
+    if (m_echoCancellation && !m_echoCancellation->isEmpty())
+        callback(*m_echoCancellation);
+
+    if (m_facingMode && !m_facingMode->isEmpty())
+        callback(*m_facingMode);
+    if (m_deviceId && !m_deviceId->isEmpty())
+        callback(*m_deviceId);
+    if (m_groupId && !m_groupId->isEmpty())
+        callback(*m_groupId);
+}
+
+void MediaTrackConstraintSetMap::filter(std::function<bool(const MediaConstraint&)> callback) const
+{
+    if (m_width && !m_width->isEmpty() && callback(*m_width))
+        return;
+    if (m_height && !m_height->isEmpty() && callback(*m_height))
+        return;
+    if (m_sampleRate && !m_sampleRate->isEmpty() && callback(*m_sampleRate))
+        return;
+    if (m_sampleSize && !m_sampleSize->isEmpty() && callback(*m_sampleSize))
+        return;
+
+    if (m_aspectRatio && !m_aspectRatio->isEmpty() && callback(*m_aspectRatio))
+        return;
+    if (m_frameRate && !m_frameRate->isEmpty() && callback(*m_frameRate))
+        return;
+    if (m_volume && !m_volume->isEmpty() && callback(*m_volume))
+        return;
+
+    if (m_echoCancellation && !m_echoCancellation->isEmpty() && callback(*m_echoCancellation))
+        return;
+
+    if (m_facingMode && !m_facingMode->isEmpty() && callback(*m_facingMode))
+        return;
+    if (m_deviceId && !m_deviceId->isEmpty() && callback(*m_deviceId))
+        return;
+    if (m_groupId && !m_groupId->isEmpty() && callback(*m_groupId))
+        return;
+}
+
+bool MediaTrackConstraintSetMap::isEmpty() const
+{
+    return (!m_width || m_width->isEmpty())
+        && (!m_height || m_height->isEmpty())
+        && (!m_sampleRate || m_sampleRate->isEmpty())
+        && (!m_sampleSize || m_sampleSize->isEmpty())
+        && (!m_aspectRatio || m_aspectRatio->isEmpty())
+        && (!m_frameRate || m_frameRate->isEmpty())
+        && (!m_volume || m_volume->isEmpty())
+        && (!m_echoCancellation || m_echoCancellation->isEmpty())
+        && (!m_facingMode || m_facingMode->isEmpty())
+        && (!m_deviceId || m_deviceId->isEmpty())
+        && (!m_groupId || m_groupId->isEmpty());
+}
+
+void MediaTrackConstraintSetMap::set(MediaConstraintType constraintType, Optional<IntConstraint>&& constraint)
+{
+    switch (constraintType) {
+    case MediaConstraintType::Width:
+        m_width = WTFMove(constraint);
+        break;
+    case MediaConstraintType::Height:
+        m_height = WTFMove(constraint);
+        break;
+    case MediaConstraintType::SampleRate:
+        m_sampleRate = WTFMove(constraint);
+        break;
+    case MediaConstraintType::SampleSize:
+        m_sampleSize = WTFMove(constraint);
+        break;
+
+    case MediaConstraintType::AspectRatio:
+    case MediaConstraintType::FrameRate:
+    case MediaConstraintType::Volume:
+    case MediaConstraintType::EchoCancellation:
+    case MediaConstraintType::FacingMode:
+    case MediaConstraintType::DeviceId:
+    case MediaConstraintType::GroupId:
+    case MediaConstraintType::Unknown:
+        ASSERT_NOT_REACHED();
+        break;
+    }
+}
+
+void MediaTrackConstraintSetMap::set(MediaConstraintType constraintType, Optional<DoubleConstraint>&& constraint)
+{
+    switch (constraintType) {
+    case MediaConstraintType::AspectRatio:
+        m_aspectRatio = WTFMove(constraint);
+        break;
+    case MediaConstraintType::FrameRate:
+        m_frameRate = WTFMove(constraint);
+        break;
+    case MediaConstraintType::Volume:
+        m_volume = WTFMove(constraint);
+        break;
+
+    case MediaConstraintType::Width:
+    case MediaConstraintType::Height:
+    case MediaConstraintType::SampleRate:
+    case MediaConstraintType::SampleSize:
+    case MediaConstraintType::EchoCancellation:
+    case MediaConstraintType::FacingMode:
+    case MediaConstraintType::DeviceId:
+    case MediaConstraintType::GroupId:
+    case MediaConstraintType::Unknown:
+        ASSERT_NOT_REACHED();
+        break;
+    }
+}
+
+void MediaTrackConstraintSetMap::set(MediaConstraintType constraintType, Optional<BooleanConstraint>&& constraint)
+{
+    switch (constraintType) {
+    case MediaConstraintType::EchoCancellation:
+        m_echoCancellation = WTFMove(constraint);
+        break;
+
+    case MediaConstraintType::Width:
+    case MediaConstraintType::Height:
+    case MediaConstraintType::SampleRate:
+    case MediaConstraintType::SampleSize:
+    case MediaConstraintType::AspectRatio:
+    case MediaConstraintType::FrameRate:
+    case MediaConstraintType::Volume:
+    case MediaConstraintType::FacingMode:
+    case MediaConstraintType::DeviceId:
+    case MediaConstraintType::GroupId:
+    case MediaConstraintType::Unknown:
+        ASSERT_NOT_REACHED();
+        break;
+    }
+}
+
+void MediaTrackConstraintSetMap::set(MediaConstraintType constraintType, Optional<StringConstraint>&& constraint)
+{
+    switch (constraintType) {
+    case MediaConstraintType::FacingMode:
+        m_facingMode = WTFMove(constraint);
+        break;
+    case MediaConstraintType::DeviceId:
+        m_deviceId = WTFMove(constraint);
+        break;
+    case MediaConstraintType::GroupId:
+        m_groupId = WTFMove(constraint);
+        break;
+
+    case MediaConstraintType::Width:
+    case MediaConstraintType::Height:
+    case MediaConstraintType::SampleRate:
+    case MediaConstraintType::SampleSize:
+    case MediaConstraintType::AspectRatio:
+    case MediaConstraintType::FrameRate:
+    case MediaConstraintType::Volume:
+    case MediaConstraintType::EchoCancellation:
+    case MediaConstraintType::Unknown:
+        ASSERT_NOT_REACHED();
+        break;
+    }
+}
+
+}
+
 #endif // ENABLE(MEDIA_STREAM)

Modified: trunk/Source/WebCore/platform/mediastream/MediaConstraints.h (206444 => 206445)


--- trunk/Source/WebCore/platform/mediastream/MediaConstraints.h	2016-09-27 17:54:49 UTC (rev 206444)
+++ trunk/Source/WebCore/platform/mediastream/MediaConstraints.h	2016-09-27 17:58:44 UTC (rev 206445)
@@ -38,83 +38,56 @@
 #include <cstdlib>
 #include <wtf/HashMap.h>
 #include <wtf/RefCounted.h>
+#include <wtf/Variant.h>
 #include <wtf/text/StringHash.h>
 #include <wtf/text/WTFString.h>
 
 namespace WebCore {
 
-class MediaConstraint : public RefCounted<MediaConstraint> {
+class MediaConstraint {
 public:
-    static Ref<MediaConstraint> create(const String&);
+    enum class DataType { None, Integer, Double, Boolean, String };
 
-    enum class ConstraintType { ExactConstraint, IdealConstraint, MinConstraint, MaxConstraint };
-
     virtual ~MediaConstraint() { };
 
-    virtual Ref<MediaConstraint> copy() const;
-    virtual bool isEmpty() const = 0;
-    virtual bool isMandatory() const = 0;
+    virtual bool isEmpty() const { return true; }
+    virtual bool isMandatory() const { return false; }
+    virtual void merge(const MediaConstraint&) { }
 
-    virtual bool getMin(int&) const { ASSERT_NOT_REACHED(); return false; }
-    virtual bool getMax(int&) const { ASSERT_NOT_REACHED(); return false; }
-    virtual bool getExact(int&) const { ASSERT_NOT_REACHED(); return false; }
-    virtual bool getIdeal(int&) const { ASSERT_NOT_REACHED(); return false; }
-    virtual bool validForRange(int, int) const { ASSERT_NOT_REACHED(); return false; }
-    virtual int find(std::function<bool(ConstraintType, int)>) const { ASSERT_NOT_REACHED(); return 0; }
-    virtual double fitnessDistance(int, int) const { ASSERT_NOT_REACHED(); return 0; }
+    bool isInt() const { return m_dataType == DataType::Integer; }
+    bool isDouble() const { return m_dataType == DataType::Double; }
+    bool isBoolean() const { return m_dataType == DataType::Boolean; }
+    bool isString() const { return m_dataType == DataType::String; }
 
-    virtual bool getMin(double&) const { ASSERT_NOT_REACHED(); return false; }
-    virtual bool getMax(double&) const { ASSERT_NOT_REACHED(); return false; }
-    virtual bool getExact(double&) const { ASSERT_NOT_REACHED(); return false; }
-    virtual bool getIdeal(double&) const { ASSERT_NOT_REACHED(); return false; }
-    virtual bool validForRange(double, double) const { ASSERT_NOT_REACHED(); return false; }
-    virtual double find(std::function<bool(ConstraintType, double)>) const { ASSERT_NOT_REACHED(); return 0; }
-    virtual double fitnessDistance(double, double) const { ASSERT_NOT_REACHED(); return 0; }
-
-    virtual bool getMin(bool&) const { ASSERT_NOT_REACHED(); return false; }
-    virtual bool getMax(bool&) const { ASSERT_NOT_REACHED(); return false; }
-    virtual bool getExact(bool&) const { ASSERT_NOT_REACHED(); return false; }
-    virtual bool getIdeal(bool&) const { ASSERT_NOT_REACHED(); return false; }
-    virtual double fitnessDistance(bool) const { ASSERT_NOT_REACHED(); return 0; }
-
-    virtual bool getMin(Vector<String>&) const { ASSERT_NOT_REACHED(); return false; }
-    virtual bool getMax(Vector<String>&) const { ASSERT_NOT_REACHED(); return false; }
-    virtual bool getExact(Vector<String>&) const { ASSERT_NOT_REACHED(); return false; }
-    virtual bool getIdeal(Vector<String>&) const { ASSERT_NOT_REACHED(); return false; }
-    virtual const String& find(std::function<bool(ConstraintType, const String&)>) const { ASSERT_NOT_REACHED(); return emptyString(); }
-
-    virtual double fitnessDistance(const String&) const { ASSERT_NOT_REACHED(); return 0; }
-    virtual double fitnessDistance(const Vector<String>&) const { ASSERT_NOT_REACHED(); return 0; }
-
-    virtual void merge(const MediaConstraint&) { ASSERT_NOT_REACHED(); }
-
-    MediaConstraintType type() const { return m_type; }
+    DataType dataType() const { return m_dataType; }
+    MediaConstraintType constraintType() const { return m_constraintType; }
     const String& name() const { return m_name; }
 
 protected:
-    explicit MediaConstraint(const String& name, MediaConstraintType type)
+    explicit MediaConstraint(const AtomicString& name, MediaConstraintType constraintType, DataType dataType)
         : m_name(name)
-        , m_type(type)
+        , m_constraintType(constraintType)
+        , m_dataType(dataType)
     {
     }
 
+
 private:
-    String m_name;
-    MediaConstraintType m_type;
+    AtomicString m_name;
+    MediaConstraintType m_constraintType;
+    DataType m_dataType;
 };
 
 template<class ValueType>
 class NumericConstraint : public MediaConstraint {
 public:
-    bool isEmpty() const override { return !m_min && !m_max && !m_exact && !m_ideal; }
-    bool isMandatory() const override { return m_min || m_max || m_exact; }
-
     void setMin(ValueType value) { m_min = value; }
     void setMax(ValueType value) { m_max = value; }
     void setExact(ValueType value) { m_exact = value; }
     void setIdeal(ValueType value) { m_ideal = value; }
 
-    bool getMin(ValueType& min) const final {
+    bool getMin(ValueType& min) const
+    {
         if (!m_min)
             return false;
 
@@ -122,7 +95,8 @@
         return true;
     }
 
-    bool getMax(ValueType& max) const final {
+    bool getMax(ValueType& max) const
+    {
         if (!m_max)
             return false;
 
@@ -130,7 +104,8 @@
         return true;
     }
 
-    bool getExact(ValueType& exact) const final {
+    bool getExact(ValueType& exact) const
+    {
         if (!m_exact)
             return false;
 
@@ -138,7 +113,8 @@
         return true;
     }
 
-    bool getIdeal(ValueType& ideal) const final {
+    bool getIdeal(ValueType& ideal) const
+    {
         if (!m_ideal)
             return false;
 
@@ -154,7 +130,8 @@
         return std::abs(a - b) <= epsilon;
     }
 
-    double fitnessDistance(ValueType rangeMin, ValueType rangeMax) const final {
+    double fitnessDistance(ValueType rangeMin, ValueType rangeMax) const
+    {
         // https://w3c.github.io/mediacapture-main/#dfn-applyconstraints
         // 1. If the constraint is not supported by the browser, the fitness distance is 0.
         if (isEmpty())
@@ -189,32 +166,8 @@
         return static_cast<double>(std::abs(ideal - m_ideal.value())) / std::max(std::abs(ideal), std::abs(m_ideal.value()));
     }
 
-    void merge(const MediaConstraint& other) final {
-        if (other.isEmpty())
-            return;
-
-        ValueType value;
-        if (other.getExact(value))
-            m_exact = value;
-
-        if (other.getMin(value))
-            m_min = value;
-
-        if (other.getMax(value))
-            m_max = value;
-
-        // https://w3c.github.io/mediacapture-main/#constrainable-interface
-        // When processing advanced constraints:
-        //   ... the User Agent must attempt to apply, individually, any 'ideal' constraints or
-        //   a constraint given as a bare value for the property. Of these properties, it must
-        //   satisfy the largest number that it can, in any order.
-        if (other.getIdeal(value)) {
-            if (!m_ideal || value > m_ideal.value())
-                m_ideal = value;
-        }
-    }
-
-    bool validForRange(ValueType rangeMin, ValueType rangeMax) const final {
+    bool validForRange(ValueType rangeMin, ValueType rangeMax) const
+    {
         if (isEmpty())
             return false;
 
@@ -242,29 +195,58 @@
         return true;
     }
 
-    ValueType find(std::function<bool(ConstraintType, ValueType)> function) const final {
-        if (m_min && function(ConstraintType::MinConstraint, m_min.value()))
+    ValueType find(std::function<bool(ValueType)> function) const
+    {
+        if (m_min && function(m_min.value()))
             return m_min.value();
 
-        if (m_max && function(ConstraintType::MaxConstraint, m_max.value()))
+        if (m_max && function(m_max.value()))
             return m_max.value();
 
-        if (m_exact && function(ConstraintType::ExactConstraint, m_exact.value()))
+        if (m_exact && function(m_exact.value()))
             return m_exact.value();
 
-        if (m_ideal && function(ConstraintType::IdealConstraint, m_ideal.value()))
+        if (m_ideal && function(m_ideal.value()))
             return m_ideal.value();
 
         return 0;
     }
-    
 
+    bool isEmpty() const override { return !m_min && !m_max && !m_exact && !m_ideal; }
+    bool isMandatory() const override { return m_min || m_max || m_exact; }
+
 protected:
-    explicit NumericConstraint(const String& name, MediaConstraintType type)
-        : MediaConstraint(name, type)
+    explicit NumericConstraint(const AtomicString& name, MediaConstraintType type, DataType dataType)
+        : MediaConstraint(name, type, dataType)
     {
     }
 
+    void innerMerge(const NumericConstraint& other)
+    {
+        if (other.isEmpty())
+            return;
+
+        ValueType value;
+        if (other.getExact(value))
+            m_exact = value;
+
+        if (other.getMin(value))
+            m_min = value;
+
+        if (other.getMax(value))
+            m_max = value;
+
+        // https://w3c.github.io/mediacapture-main/#constrainable-interface
+        // When processing advanced constraints:
+        //   ... the User Agent must attempt to apply, individually, any 'ideal' constraints or
+        //   a constraint given as a bare value for the property. Of these properties, it must
+        //   satisfy the largest number that it can, in any order.
+        if (other.getIdeal(value)) {
+            if (!m_ideal || value > m_ideal.value())
+                m_ideal = value;
+        }
+    }
+
     Optional<ValueType> m_min;
     Optional<ValueType> m_max;
     Optional<ValueType> m_exact;
@@ -273,46 +255,45 @@
 
 class IntConstraint final : public NumericConstraint<int> {
 public:
-    static Ref<IntConstraint> create(const String& name, MediaConstraintType type) { return adoptRef(*new IntConstraint(name, type)); }
-
-    Ref<MediaConstraint> copy() const final;
-
-private:
-    explicit IntConstraint(const String& name, MediaConstraintType type)
-        : NumericConstraint<int>(name, type)
+    explicit IntConstraint(const AtomicString& name, MediaConstraintType type)
+        : NumericConstraint<int>(name, type, DataType::Integer)
     {
     }
+
+    void merge(const MediaConstraint& other) final {
+        ASSERT(other.isInt());
+        NumericConstraint::innerMerge(downcast<const IntConstraint>(other));
+    }
 };
 
 class DoubleConstraint final : public NumericConstraint<double> {
 public:
-    static Ref<DoubleConstraint> create(const String& name, MediaConstraintType type) { return adoptRef(*new DoubleConstraint(name, type)); }
-
-    Ref<MediaConstraint> copy() const final;
-
-private:
-    explicit DoubleConstraint(const String& name, MediaConstraintType type)
-        : NumericConstraint<double>(name, type)
+    explicit DoubleConstraint(const AtomicString& name, MediaConstraintType type)
+        : NumericConstraint<double>(name, type, DataType::Double)
     {
     }
+
+    void merge(const MediaConstraint& other) final {
+        ASSERT(other.isDouble());
+        NumericConstraint::innerMerge(downcast<DoubleConstraint>(other));
+    }
 };
 
 class BooleanConstraint final : public MediaConstraint {
 public:
-    static Ref<BooleanConstraint> create(const String& name, MediaConstraintType type) { return adoptRef(*new BooleanConstraint(name, type)); }
+    explicit BooleanConstraint(const AtomicString& name, MediaConstraintType type)
+        : MediaConstraint(name, type, DataType::Boolean)
+    {
+    }
 
-    Ref<MediaConstraint> copy() const final;
-
     void setExact(bool value) { m_exact = value; }
     void setIdeal(bool value) { m_ideal = value; }
 
-    bool getExact(bool&) const final;
-    bool getIdeal(bool&) const final;
+    bool getExact(bool&) const;
+    bool getIdeal(bool&) const;
 
-    bool isEmpty() const final { return !m_exact && !m_ideal; };
-    bool isMandatory() const final { return bool(m_exact); }
-
-    double fitnessDistance(bool value) const final {
+    double fitnessDistance(bool value) const
+    {
         // https://w3c.github.io/mediacapture-main/#dfn-applyconstraints
         // 1. If the constraint is not supported by the browser, the fitness distance is 0.
         if (isEmpty())
@@ -335,25 +316,26 @@
     }
 
     void merge(const MediaConstraint& other) final {
-        if (other.isEmpty())
+        ASSERT(other.isBoolean());
+        const BooleanConstraint& typedOther = downcast<BooleanConstraint>(other);
+
+        if (typedOther.isEmpty())
             return;
 
         bool value;
-        if (other.getExact(value))
+        if (typedOther.getExact(value))
             m_exact = value;
 
-        if (other.getIdeal(value)) {
+        if (typedOther.getIdeal(value)) {
             if (!m_ideal || (value && !m_ideal.value()))
                 m_ideal = value;
         }
     }
 
+    bool isEmpty() const final { return !m_exact && !m_ideal; };
+    bool isMandatory() const final { return bool(m_exact); }
+
 private:
-    explicit BooleanConstraint(const String& name, MediaConstraintType type)
-        : MediaConstraint(name, type)
-    {
-    }
-
     Optional<bool> m_exact;
     Optional<bool> m_ideal;
 };
@@ -360,33 +342,29 @@
 
 class StringConstraint final : public MediaConstraint {
 public:
-    static Ref<StringConstraint> create(const String& name, MediaConstraintType type) { return adoptRef(*new StringConstraint(name, type)); }
+    explicit StringConstraint(const AtomicString& name, MediaConstraintType type)
+        : MediaConstraint(name, type, DataType::String)
+    {
+    }
 
-    Ref<MediaConstraint> copy() const final;
-
     void setExact(const String&);
     void appendExact(const String&);
     void setIdeal(const String&);
     void appendIdeal(const String&);
 
-    bool getExact(Vector<String>&) const final;
-    bool getIdeal(Vector<String>&) const final;
+    bool getExact(Vector<String>&) const;
+    bool getIdeal(Vector<String>&) const;
 
+    double fitnessDistance(const String&) const;
+    double fitnessDistance(const Vector<String>&) const;
+
+    const String& find(std::function<bool(const String&)>) const;
+    void merge(const MediaConstraint&) final;
+
     bool isEmpty() const final { return m_exact.isEmpty() && m_ideal.isEmpty(); }
     bool isMandatory() const final { return !m_exact.isEmpty(); }
 
-    double fitnessDistance(const String&) const final;
-    double fitnessDistance(const Vector<String>&) const final;
-
-    const String& find(std::function<bool(ConstraintType, const String&)>) const final;
-    void merge(const MediaConstraint&) final;
-
 private:
-    explicit StringConstraint(const String& name, MediaConstraintType type)
-        : MediaConstraint(name, type)
-    {
-    }
-
     Vector<String> m_exact;
     Vector<String> m_ideal;
 };
@@ -393,34 +371,161 @@
 
 class UnknownConstraint final : public MediaConstraint {
 public:
-    static Ref<UnknownConstraint> create(const String& name, MediaConstraintType type) { return adoptRef(*new UnknownConstraint(name, type)); }
+    explicit UnknownConstraint(const AtomicString& name, MediaConstraintType type)
+        : MediaConstraint(name, type, DataType::None)
+    {
+    }
 
+private:
     bool isEmpty() const final { return true; }
     bool isMandatory() const final { return false; }
+    void merge(const MediaConstraint&) final { }
+};
 
+class MediaTrackConstraintSetMap {
+public:
+    void forEach(std::function<void(const MediaConstraint&)>) const;
+    void filter(std::function<bool(const MediaConstraint&)>) const;
+    bool isEmpty() const;
+
+    void set(MediaConstraintType, Optional<IntConstraint>&&);
+    void set(MediaConstraintType, Optional<DoubleConstraint>&&);
+    void set(MediaConstraintType, Optional<BooleanConstraint>&&);
+    void set(MediaConstraintType, Optional<StringConstraint>&&);
+
 private:
-    explicit UnknownConstraint(const String& name, MediaConstraintType type)
-        : MediaConstraint(name, type)
-    {
-    }
+    Optional<IntConstraint> m_width;
+    Optional<IntConstraint> m_height;
+    Optional<IntConstraint> m_sampleRate;
+    Optional<IntConstraint> m_sampleSize;
+
+    Optional<DoubleConstraint> m_aspectRatio;
+    Optional<DoubleConstraint> m_frameRate;
+    Optional<DoubleConstraint> m_volume;
+
+    Optional<BooleanConstraint> m_echoCancellation;
+
+    Optional<StringConstraint> m_facingMode;
+    Optional<StringConstraint> m_deviceId;
+    Optional<StringConstraint> m_groupId;
 };
 
-using MediaTrackConstraintSetMap = HashMap<String, RefPtr<MediaConstraint>>;
-
 class FlattenedConstraint {
 public:
-    typedef Vector<RefPtr<MediaConstraint>>::const_iterator const_iterator;
 
     void set(const MediaConstraint&);
     void merge(const MediaConstraint&);
-    bool isEmpty() const { return m_constraints.isEmpty(); }
+    void append(const MediaConstraint&);
+    bool isEmpty() const { return m_variants.isEmpty(); }
 
-    const_iterator begin() const { return m_constraints.begin(); }
-    const_iterator end() const { return m_constraints.end(); }
+    class iterator {
+    public:
+        iterator(const FlattenedConstraint* constraint, size_t index)
+            : m_constraint(constraint)
+            , m_index(index)
+#ifndef NDEBUG
+            , m_generation(constraint->m_generation)
+#endif
+        {
+        }
 
+        MediaConstraint& operator*() const
+        {
+            return m_constraint->m_variants.at(m_index).constraint();
+        }
+
+        iterator& operator++()
+        {
+#ifndef NDEBUG
+            ASSERT(m_generation == m_constraint->m_generation);
+#endif
+            m_index++;
+            return *this;
+        }
+
+        bool operator==(const iterator& other) const { return m_index == other.m_index; }
+        bool operator!=(const iterator& other) const { return !(*this == other); }
+
+    private:
+        const FlattenedConstraint* m_constraint { nullptr };
+        size_t m_index { 0 };
+#ifndef NDEBUG
+        int m_generation { 0 };
+#endif
+    };
+
+    const iterator begin() const { return iterator(this, 0); }
+    const iterator end() const { return iterator(this, m_variants.size()); }
+
 private:
+    class ConstraintHolder {
+    public:
+        static ConstraintHolder& create(const MediaConstraint& value) { return *new ConstraintHolder(value); }
 
-    Vector<RefPtr<MediaConstraint>> m_constraints;
+        ~ConstraintHolder()
+        {
+            switch (dataType()) {
+            case MediaConstraint::DataType::Integer:
+                delete m_value.asInteger;
+                break;
+            case MediaConstraint::DataType::Double:
+                delete m_value.asDouble;
+                break;
+            case MediaConstraint::DataType::Boolean:
+                delete m_value.asBoolean;
+                break;
+            case MediaConstraint::DataType::String:
+                delete m_value.asString;
+                break;
+            case MediaConstraint::DataType::None:
+                ASSERT_NOT_REACHED();
+                break;
+            }
+
+#ifndef NDEBUG
+            m_value.asRaw = reinterpret_cast<MediaConstraint*>(0xbbadbeef);
+#endif
+        }
+
+        MediaConstraint& constraint() const { return *m_value.asRaw; }
+        MediaConstraint::DataType dataType() const { return constraint().dataType(); }
+        MediaConstraintType constraintType() const { return constraint().constraintType(); }
+
+    private:
+        explicit ConstraintHolder(const MediaConstraint& value)
+        {
+            switch (value.dataType()) {
+            case MediaConstraint::DataType::Integer:
+                m_value.asInteger = new IntConstraint(downcast<const IntConstraint>(value));
+                break;
+            case MediaConstraint::DataType::Double:
+                m_value.asDouble = new DoubleConstraint(downcast<DoubleConstraint>(value));
+                break;
+            case MediaConstraint::DataType::Boolean:
+                m_value.asBoolean = new BooleanConstraint(downcast<BooleanConstraint>(value));
+                break;
+            case MediaConstraint::DataType::String:
+                m_value.asString = new StringConstraint(downcast<StringConstraint>(value));
+                break;
+            case MediaConstraint::DataType::None:
+                ASSERT_NOT_REACHED();
+                break;
+            }
+        }
+        
+        union {
+            MediaConstraint* asRaw;
+            IntConstraint* asInteger;
+            DoubleConstraint* asDouble;
+            BooleanConstraint* asBoolean;
+            StringConstraint* asString;
+        } m_value;
+    };
+
+    Vector<ConstraintHolder> m_variants;
+#ifndef NDEBUG
+    int m_generation { 0 };
+#endif
 };
 
 class MediaConstraints : public RefCounted<MediaConstraints> {
@@ -437,6 +542,16 @@
 
 } // namespace WebCore
 
+#define SPECIALIZE_TYPE_TRAITS_MEDIACONSTRAINT(ConstraintType, predicate) \
+SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::ConstraintType) \
+static bool isType(const WebCore::MediaConstraint& constraint) { return constraint.predicate; } \
+SPECIALIZE_TYPE_TRAITS_END()
+
+SPECIALIZE_TYPE_TRAITS_MEDIACONSTRAINT(IntConstraint, isInt())
+SPECIALIZE_TYPE_TRAITS_MEDIACONSTRAINT(DoubleConstraint, isDouble())
+SPECIALIZE_TYPE_TRAITS_MEDIACONSTRAINT(StringConstraint, isString())
+SPECIALIZE_TYPE_TRAITS_MEDIACONSTRAINT(BooleanConstraint, isBoolean())
+
 #endif // ENABLE(MEDIA_STREAM)
 
 #endif // MediaConstraints_h

Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp (206444 => 206445)


--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp	2016-09-27 17:54:49 UTC (rev 206444)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp	2016-09-27 17:58:44 UTC (rev 206445)
@@ -150,75 +150,84 @@
     stop(callingObserver);
 }
 
+#if 1
 double RealtimeMediaSource::fitnessDistance(const MediaConstraint& constraint)
 {
     RealtimeMediaSourceCapabilities& capabilities = *this->capabilities();
 
-    switch (constraint.type()) {
+    switch (constraint.constraintType()) {
     case MediaConstraintType::Width: {
+        ASSERT(constraint.isInt());
         if (!capabilities.supportsWidth())
             return 0;
 
         auto range = capabilities.width();
-        return constraint.fitnessDistance(range.rangeMin().asInt, range.rangeMax().asInt);
+        return downcast<IntConstraint>(constraint).fitnessDistance(range.rangeMin().asInt, range.rangeMax().asInt);
         break;
     }
 
     case MediaConstraintType::Height: {
+        ASSERT(constraint.isInt());
         if (!capabilities.supportsHeight())
             return 0;
 
         auto range = capabilities.height();
-        return constraint.fitnessDistance(range.rangeMin().asInt, range.rangeMax().asInt);
+        return downcast<IntConstraint>(constraint).fitnessDistance(range.rangeMin().asInt, range.rangeMax().asInt);
         break;
     }
 
     case MediaConstraintType::FrameRate: {
+        ASSERT(constraint.isDouble());
         if (!capabilities.supportsFrameRate())
             return 0;
 
         auto range = capabilities.frameRate();
-        return constraint.fitnessDistance(range.rangeMin().asDouble, range.rangeMax().asDouble);
+        return downcast<DoubleConstraint>(constraint).fitnessDistance(range.rangeMin().asDouble, range.rangeMax().asDouble);
         break;
     }
 
     case MediaConstraintType::AspectRatio: {
+        ASSERT(constraint.isDouble());
         if (!capabilities.supportsAspectRatio())
             return 0;
 
         auto range = capabilities.aspectRatio();
-        return constraint.fitnessDistance(range.rangeMin().asDouble, range.rangeMax().asDouble);
+        return downcast<DoubleConstraint>(constraint).fitnessDistance(range.rangeMin().asDouble, range.rangeMax().asDouble);
         break;
     }
 
     case MediaConstraintType::Volume: {
+        ASSERT(constraint.isDouble());
         if (!capabilities.supportsVolume())
             return 0;
 
         auto range = capabilities.volume();
-        return constraint.fitnessDistance(range.rangeMin().asDouble, range.rangeMax().asDouble);
+        return downcast<DoubleConstraint>(constraint).fitnessDistance(range.rangeMin().asDouble, range.rangeMax().asDouble);
         break;
     }
 
     case MediaConstraintType::SampleRate: {
+        ASSERT(constraint.isInt());
         if (!capabilities.supportsSampleRate())
             return 0;
 
         auto range = capabilities.sampleRate();
-        return constraint.fitnessDistance(range.rangeMin().asDouble, range.rangeMax().asDouble);
+        return downcast<IntConstraint>(constraint).fitnessDistance(range.rangeMin().asInt, range.rangeMax().asInt);
         break;
     }
 
     case MediaConstraintType::SampleSize: {
+        ASSERT(constraint.isInt());
         if (!capabilities.supportsSampleSize())
             return 0;
 
         auto range = capabilities.sampleSize();
-        return constraint.fitnessDistance(range.rangeMin().asDouble, range.rangeMax().asDouble);
+        return downcast<IntConstraint>(constraint).fitnessDistance(range.rangeMin().asInt, range.rangeMax().asInt);
         break;
     }
 
     case MediaConstraintType::FacingMode: {
+        ASSERT(constraint.isString());
         if (!capabilities.supportsFacingMode())
             return 0;
 
@@ -227,32 +236,35 @@
         supportedModes.reserveInitialCapacity(modes.size());
         for (auto& mode : modes)
             supportedModes.append(RealtimeMediaSourceSettings::facingMode(mode));
-        return constraint.fitnessDistance(supportedModes);
+        return downcast<StringConstraint>(constraint).fitnessDistance(supportedModes);
         break;
     }
 
     case MediaConstraintType::EchoCancellation: {
+        ASSERT(constraint.isBoolean());
         if (!capabilities.supportsEchoCancellation())
             return 0;
 
         bool echoCancellationReadWrite = capabilities.echoCancellation() == RealtimeMediaSourceCapabilities::EchoCancellation::ReadWrite;
-        return constraint.fitnessDistance(echoCancellationReadWrite);
+        return downcast<BooleanConstraint>(constraint).fitnessDistance(echoCancellationReadWrite);
         break;
     }
 
     case MediaConstraintType::DeviceId: {
+        ASSERT(constraint.isString());
         if (!capabilities.supportsDeviceId())
             return 0;
 
-        return constraint.fitnessDistance(m_id);
+        return downcast<StringConstraint>(constraint).fitnessDistance(m_id);
         break;
     }
 
     case MediaConstraintType::GroupId: {
+        ASSERT(constraint.isString());
         if (!capabilities.supportsDeviceId())
             return 0;
 
-        return constraint.fitnessDistance(settings().groupId());
+        return downcast<StringConstraint>(constraint).fitnessDistance(settings().groupId());
         break;
     }
 
@@ -263,9 +275,10 @@
 
     return 0;
 }
+#endif
 
 template <typename ValueType>
-static void applyNumericConstraint(const MediaConstraint& constraint, ValueType current, ValueType capabilityMin, ValueType capabilityMax, RealtimeMediaSource* source, void (RealtimeMediaSource::*function)(ValueType))
+static void applyNumericConstraint(const NumericConstraint<ValueType>& constraint, ValueType current, ValueType capabilityMin, ValueType capabilityMax, RealtimeMediaSource* source, void (RealtimeMediaSource::*applier)(ValueType))
 {
     ValueType value;
     ValueType min = capabilityMin;
@@ -273,7 +286,7 @@
 
     if (constraint.getExact(value)) {
         ASSERT(constraint.validForRange(capabilityMin, capabilityMax));
-        (source->*function)(value);
+        (source->*applier)(value);
         return;
     }
 
@@ -302,91 +315,102 @@
     }
 
     if (value != current)
-        (source->*function)(value);
+        (source->*applier)(value);
 }
 
 void RealtimeMediaSource::applyConstraint(const MediaConstraint& constraint)
 {
     RealtimeMediaSourceCapabilities& capabilities = *this->capabilities();
-    switch (constraint.type()) {
+    switch (constraint.constraintType()) {
     case MediaConstraintType::Width: {
+        ASSERT(constraint.isInt());
         if (!capabilities.supportsWidth())
             return;
 
         auto range = capabilities.width();
-        applyNumericConstraint(constraint, size().width(), range.rangeMin().asInt, range.rangeMax().asInt, this, &RealtimeMediaSource::setWidth);
+        applyNumericConstraint(downcast<IntConstraint>(constraint), size().width(), range.rangeMin().asInt, range.rangeMax().asInt, this, &RealtimeMediaSource::setWidth);
         break;
     }
 
     case MediaConstraintType::Height: {
+        ASSERT(constraint.isInt());
         if (!capabilities.supportsHeight())
             return;
 
         auto range = capabilities.height();
-        applyNumericConstraint(constraint, size().height(), range.rangeMin().asInt, range.rangeMax().asInt, this, &RealtimeMediaSource::setHeight);
+        applyNumericConstraint(downcast<IntConstraint>(constraint), size().height(), range.rangeMin().asInt, range.rangeMax().asInt, this, &RealtimeMediaSource::setHeight);
         break;
     }
 
     case MediaConstraintType::FrameRate: {
+        ASSERT(constraint.isDouble());
         if (!capabilities.supportsFrameRate())
             return;
 
         auto range = capabilities.frameRate();
-        applyNumericConstraint(constraint, frameRate(), range.rangeMin().asDouble, range.rangeMax().asDouble, this, &RealtimeMediaSource::setFrameRate);
+        applyNumericConstraint(downcast<DoubleConstraint>(constraint), frameRate(), range.rangeMin().asDouble, range.rangeMax().asDouble, this, &RealtimeMediaSource::setFrameRate);
         break;
     }
 
     case MediaConstraintType::AspectRatio: {
+        ASSERT(constraint.isDouble());
         if (!capabilities.supportsAspectRatio())
             return;
 
         auto range = capabilities.aspectRatio();
-        applyNumericConstraint(constraint, aspectRatio(), range.rangeMin().asDouble, range.rangeMax().asDouble, this, &RealtimeMediaSource::setAspectRatio);
+        applyNumericConstraint(downcast<DoubleConstraint>(constraint), aspectRatio(), range.rangeMin().asDouble, range.rangeMax().asDouble, this, &RealtimeMediaSource::setAspectRatio);
         break;
     }
 
     case MediaConstraintType::Volume: {
+        ASSERT(constraint.isDouble());
         if (!capabilities.supportsVolume())
             return;
 
         auto range = capabilities.volume();
-        applyNumericConstraint(constraint, volume(), range.rangeMin().asDouble, range.rangeMax().asDouble, this, &RealtimeMediaSource::setVolume);
+        applyNumericConstraint(downcast<DoubleConstraint>(constraint), volume(), range.rangeMin().asDouble, range.rangeMax().asDouble, this, &RealtimeMediaSource::setVolume);
         break;
     }
 
     case MediaConstraintType::SampleRate: {
+        ASSERT(constraint.isInt());
         if (!capabilities.supportsSampleRate())
             return;
 
         auto range = capabilities.sampleRate();
-        applyNumericConstraint(constraint, sampleRate(), range.rangeMin().asDouble, range.rangeMax().asDouble, this, &RealtimeMediaSource::setSampleRate);
+        applyNumericConstraint(downcast<IntConstraint>(constraint), sampleRate(), range.rangeMin().asInt, range.rangeMax().asInt, this, &RealtimeMediaSource::setSampleRate);
         break;
     }
 
     case MediaConstraintType::SampleSize: {
+        ASSERT(constraint.isInt());
         if (!capabilities.supportsSampleSize())
             return;
 
         auto range = capabilities.sampleSize();
-        applyNumericConstraint(constraint, sampleSize(), range.rangeMin().asDouble, range.rangeMax().asDouble, this, &RealtimeMediaSource::setSampleSize);
+        applyNumericConstraint(downcast<IntConstraint>(constraint), sampleSize(), range.rangeMin().asInt, range.rangeMax().asInt, this, &RealtimeMediaSource::setSampleSize);
         break;
     }
 
-    case MediaConstraintType::EchoCancellation:
+    case MediaConstraintType::EchoCancellation: {
+        ASSERT(constraint.isBoolean());
         if (!capabilities.supportsEchoCancellation())
             return;
 
         bool setting;
-        if (constraint.getExact(setting) || constraint.getIdeal(setting))
+        const BooleanConstraint& boolConstraint = downcast<BooleanConstraint>(constraint);
+        if (boolConstraint.getExact(setting) || boolConstraint.getIdeal(setting))
             setEchoCancellation(setting);
         break;
+    }
 
     case MediaConstraintType::FacingMode: {
+        ASSERT(constraint.isString());
         if (!capabilities.supportsFacingMode())
             return;
 
         auto& supportedModes = capabilities.facingMode();
-        std::function<bool(MediaConstraint::ConstraintType, const String&)> filter = [supportedModes](MediaConstraint::ConstraintType, const String& modeString) {
+        auto filter = [supportedModes](const String& modeString) {
             auto mode = RealtimeMediaSourceSettings::videoFacingModeEnum(modeString);
             for (auto& supportedMode : supportedModes) {
                 if (mode == supportedMode)
@@ -395,7 +419,7 @@
             return false;
         };
 
-        auto modeString = constraint.find(filter);
+        auto modeString = downcast<StringConstraint>(constraint).find(filter);
         if (!modeString.isEmpty())
             setFacingMode(RealtimeMediaSourceSettings::videoFacingModeEnum(modeString));
         break;
@@ -403,6 +427,7 @@
 
     case MediaConstraintType::DeviceId:
     case MediaConstraintType::GroupId:
+        ASSERT(constraint.isString());
         // There is nothing to do here, neither can be changed.
         break;
 
@@ -431,17 +456,21 @@
     // 3. For every possible settings dictionary of copy compute its fitness distance, treating bare values of
     //    properties as ideal values. Let candidates be the set of settings dictionaries for which the fitness
     //    distance is finite.
-    auto& mandatoryConstraints = constraints.mandatoryConstraints();
-    for (auto& nameConstraintPair : mandatoryConstraints) {
-        const auto& constraint = nameConstraintPair.value;
-        if (fitnessDistance(*constraint) == std::numeric_limits<double>::infinity()) {
-            failedConstraint = constraint->name();
-            return false;
+
+    failedConstraint = emptyString();
+    constraints.mandatoryConstraints().filter([&](const MediaConstraint& constraint) {
+        if (fitnessDistance(constraint) == std::numeric_limits<double>::infinity()) {
+            failedConstraint = constraint.name();
+            return true;
         }
 
-        candidates.set(*constraint);
-    }
+        candidates.set(constraint);
+        return false;
+    });
 
+    if (!failedConstraint.isEmpty())
+        return false;
+
     // 4. If candidates is empty, return undefined as the result of the SelectSettings() algorithm.
     if (candidates.isEmpty())
         return true;
@@ -453,15 +482,17 @@
     //     values of properties as exact.
     Vector<std::pair<double, MediaTrackConstraintSetMap>> supportedConstraints;
     double minimumDistance = std::numeric_limits<double>::infinity();
+
     for (const auto& advancedConstraint : constraints.advancedConstraints()) {
         double constraintDistance = 0;
         bool supported = false;
-        for (auto& nameConstraintPair : advancedConstraint) {
-            double distance = fitnessDistance(*nameConstraintPair.value);
+
+        advancedConstraint.forEach([&](const MediaConstraint& constraint) {
+            double distance = fitnessDistance(constraint);
             constraintDistance += distance;
             if (distance != std::numeric_limits<double>::infinity())
                 supported = true;
-        }
+        });
 
         if (constraintDistance < minimumDistance)
             minimumDistance = constraintDistance;
@@ -476,14 +507,15 @@
     // 6. Select one settings dictionary from candidates, and return it as the result of the SelectSettings() algorithm.
     //    The UA should use the one with the smallest fitness distance, as calculated in step 3.
     if (minimumDistance != std::numeric_limits<double>::infinity()) {
-        supportedConstraints.removeAllMatching( [&] (std::pair<double, MediaTrackConstraintSetMap> pair) -> bool {
+        supportedConstraints.removeAllMatching([&](std::pair<double, MediaTrackConstraintSetMap> pair) -> bool {
             return pair.first > minimumDistance;
         });
 
         if (!supportedConstraints.isEmpty()) {
             auto& advancedConstraint = supportedConstraints[0].second;
-            for (auto& nameConstraintPair : advancedConstraint)
-                candidates.merge(*nameConstraintPair.value);
+            advancedConstraint.forEach([&](const MediaConstraint& constraint) {
+                candidates.merge(constraint);
+            });
         }
     }
 
@@ -490,13 +522,11 @@
     return true;
 }
 
-
 void RealtimeMediaSource::applyConstraints(const MediaConstraints& constraints, SuccessHandler successHandler, FailureHandler failureHandler)
 {
     ASSERT(constraints.isValid());
 
     FlattenedConstraint candidates;
-
     String failedConstraint;
     if (!selectSettings(constraints, candidates, failedConstraint)) {
         failureHandler(failedConstraint, "Constraint not supported");
@@ -503,8 +533,8 @@
         return;
     }
 
-    for (auto constraint : candidates)
-        applyConstraint(*constraint);
+    for (auto& variant : candidates)
+        applyConstraint(variant);
 
     successHandler();
 }
@@ -578,7 +608,7 @@
     settingsDidChange();
 }
 
-void RealtimeMediaSource::setSampleRate(double rate)
+void RealtimeMediaSource::setSampleRate(int rate)
 {
     if (m_sampleRate == rate || !applySampleRate(rate))
         return;
@@ -587,7 +617,7 @@
     settingsDidChange();
 }
 
-void RealtimeMediaSource::setSampleSize(double size)
+void RealtimeMediaSource::setSampleSize(int size)
 {
     if (m_sampleSize == size || !applySampleSize(size))
         return;

Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h (206444 => 206445)


--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h	2016-09-27 17:54:49 UTC (rev 206444)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h	2016-09-27 17:58:44 UTC (rev 206445)
@@ -148,13 +148,13 @@
     void setVolume(double);
     virtual bool applyVolume(double) { return false; }
 
-    double sampleRate() const { return m_sampleRate; }
-    void setSampleRate(double);
-    virtual bool applySampleRate(double) { return false; }
+    int sampleRate() const { return m_sampleRate; }
+    void setSampleRate(int);
+    virtual bool applySampleRate(int) { return false; }
 
-    double sampleSize() const { return m_sampleSize; }
-    void setSampleSize(double);
-    virtual bool applySampleSize(double) { return false; }
+    int sampleSize() const { return m_sampleSize; }
+    void setSampleSize(int);
+    virtual bool applySampleSize(int) { return false; }
 
     bool echoCancellation() const { return m_echoCancellation; }
     void setEchoCancellation(bool);
@@ -170,7 +170,6 @@
 private:
     WeakPtr<RealtimeMediaSource> createWeakPtr() { return m_weakPtrFactory.createWeakPtr(); }
 
-    bool supportsConstraints(const MediaTrackConstraintSetMap&);
     bool selectSettings(const MediaConstraints&, FlattenedConstraint&, String&);
     double fitnessDistance(const MediaConstraint&);
     void applyConstraint(const MediaConstraint&);

Modified: trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.mm (206444 => 206445)


--- trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.mm	2016-09-27 17:54:49 UTC (rev 206444)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.mm	2016-09-27 17:58:44 UTC (rev 206445)
@@ -267,7 +267,7 @@
 bool AVCaptureDeviceManager::sessionSupportsConstraint(const CaptureSessionInfo* session, RealtimeMediaSource::Type type, const MediaConstraint& constraint)
 {
     const RealtimeMediaSourceSupportedConstraints& supportedConstraints = RealtimeMediaSourceCenter::singleton().supportedConstraints();
-    MediaConstraintType constraintType = constraint.type();
+    MediaConstraintType constraintType = constraint.constraintType();
     if (!supportedConstraints.supportsConstraint(constraintType))
         return false;
 
@@ -279,7 +279,7 @@
         if (constraintType == MediaConstraintType::Width) {
             // FIXME: https://bugs.webkit.org/show_bug.cgi?id=160578. Support min, max constraints.
             int exact;
-            if (!constraint.getExact(exact))
+            if (!downcast<const IntConstraint>(constraint).getExact(exact))
                 return false;
 
             return !session->bestSessionPresetForVideoDimensions(exact, 0).isEmpty();
@@ -288,7 +288,7 @@
         if (constraintType == MediaConstraintType::Height) {
             // FIXME: https://bugs.webkit.org/show_bug.cgi?id=160578. Support min, max constraints.
             int exact;
-            if (!constraint.getExact(exact))
+            if (!downcast<const IntConstraint>(constraint).getExact(exact))
                 return false;
 
             return !session->bestSessionPresetForVideoDimensions(0, exact).isEmpty();

Modified: trunk/Source/WebCore/platform/mock/MediaConstraintsMock.cpp (206444 => 206445)


--- trunk/Source/WebCore/platform/mock/MediaConstraintsMock.cpp	2016-09-27 17:54:49 UTC (rev 206444)
+++ trunk/Source/WebCore/platform/mock/MediaConstraintsMock.cpp	2016-09-27 17:58:44 UTC (rev 206445)
@@ -43,15 +43,15 @@
     int floor = 0;
 
     int min = floor;
-    if (constraint.getMin(min) && min > ceiling)
+    if (downcast<const IntConstraint>(constraint).getMin(min) && min > ceiling)
         return false;
 
     int max = ceiling;
-    if (constraint.getMax(max) && max < min)
+    if (downcast<const IntConstraint>(constraint).getMax(max) && max < min)
         return false;
 
     int exact;
-    if (constraint.getExact(exact) && (exact < min || exact > max))
+    if (downcast<const IntConstraint>(constraint).getExact(exact) && (exact < min || exact > max))
         return false;
 
     return true;
@@ -63,15 +63,15 @@
     double floor = 0;
 
     double min = floor;
-    if (constraint.getMin(min) && min > ceiling)
+    if (downcast<const DoubleConstraint>(constraint).getMin(min) && min > ceiling)
         return false;
 
     double max = ceiling;
-    if (constraint.getMax(max) && max < min)
+    if (downcast<const DoubleConstraint>(constraint).getMax(max) && max < min)
         return false;
 
     double exact;
-    if (constraint.getExact(exact) && (exact < min || exact > max))
+    if (downcast<const DoubleConstraint>(constraint).getExact(exact) && (exact < min || exact > max))
         return false;
 
     return true;
@@ -80,7 +80,7 @@
 static bool isBooleanMediaConstraintSatisfiable(const MediaConstraint& constraint)
 {
     bool exact;
-    if (constraint.getExact(exact))
+    if (downcast<const BooleanConstraint>(constraint).getExact(exact))
         return exact;
 
     return true;
@@ -89,7 +89,7 @@
 static bool isStringMediaConstraintSatisfiable(const MediaConstraint& constraint)
 {
     Vector<String> exact;
-    if (constraint.getExact(exact)) {
+    if (downcast<const StringConstraint>(constraint).getExact(exact)) {
         for (auto& constraintValue : exact) {
             if (constraintValue.find("invalid") != notFound)
                 return false;
@@ -101,7 +101,7 @@
 
 static bool isSatisfiable(RealtimeMediaSource::Type type, const MediaConstraint& constraint)
 {
-    MediaConstraintType constraintType = constraint.type();
+    MediaConstraintType constraintType = constraint.constraintType();
 
     if (type == RealtimeMediaSource::Audio) {
         if (constraintType == MediaConstraintType::SampleRate || constraintType == MediaConstraintType::SampleSize)
@@ -124,15 +124,20 @@
     return false;
 }
 
-const String& MediaConstraintsMock::verifyConstraints(RealtimeMediaSource::Type type, const MediaConstraints& constraints)
+const String MediaConstraintsMock::verifyConstraints(RealtimeMediaSource::Type type, const MediaConstraints& constraints)
 {
-    auto& mandatoryConstraints = constraints.mandatoryConstraints();
-    for (auto& nameConstraintPair : mandatoryConstraints) {
-        if (!isSatisfiable(type, *nameConstraintPair.value))
-            return nameConstraintPair.key;
-    }
+    String invalidConstraint = emptyString();
+    constraints.mandatoryConstraints().filter([&](const MediaConstraint& constraint) {
+        if (!isSatisfiable(type, constraint)) {
+            invalidConstraint = constraint.name();
+            return true;
+        }
 
-    return emptyString();
+        return false;
+    });
+
+    return invalidConstraint;
+
 }
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/platform/mock/MediaConstraintsMock.h (206444 => 206445)


--- trunk/Source/WebCore/platform/mock/MediaConstraintsMock.h	2016-09-27 17:54:49 UTC (rev 206444)
+++ trunk/Source/WebCore/platform/mock/MediaConstraintsMock.h	2016-09-27 17:58:44 UTC (rev 206445)
@@ -39,7 +39,7 @@
 
 class MediaConstraintsMock {
 public:
-    static const String& verifyConstraints(RealtimeMediaSource::Type, const MediaConstraints&);
+    static const String verifyConstraints(RealtimeMediaSource::Type, const MediaConstraints&);
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/platform/mock/MockRealtimeAudioSource.h (206444 => 206445)


--- trunk/Source/WebCore/platform/mock/MockRealtimeAudioSource.h	2016-09-27 17:54:49 UTC (rev 206444)
+++ trunk/Source/WebCore/platform/mock/MockRealtimeAudioSource.h	2016-09-27 17:58:44 UTC (rev 206445)
@@ -53,8 +53,8 @@
 private:
 
     bool applyVolume(double) override { return true; }
-    bool applySampleRate(double) override { return true; }
-    bool applySampleSize(double) override { return true; }
+    bool applySampleRate(int) override { return true; }
+    bool applySampleSize(int) override { return true; }
     bool applyEchoCancellation(bool) override { return true; }
 
     void updateSettings(RealtimeMediaSourceSettings&) override;

Modified: trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp (206444 => 206445)


--- trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp	2016-09-27 17:54:49 UTC (rev 206444)
+++ trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp	2016-09-27 17:58:44 UTC (rev 206445)
@@ -109,7 +109,7 @@
     Vector<RefPtr<RealtimeMediaSource>> videoSources;
 
     if (audioConstraints.isValid()) {
-        const String& invalidQuery = MediaConstraintsMock::verifyConstraints(RealtimeMediaSource::Audio, audioConstraints);
+        const String invalidQuery = MediaConstraintsMock::verifyConstraints(RealtimeMediaSource::Audio, audioConstraints);
         if (!invalidQuery.isEmpty()) {
             client->failedToCreateStreamWithConstraintsError(invalidQuery);
             return;
@@ -120,7 +120,7 @@
     }
 
     if (videoConstraints.isValid()) {
-        const String& invalidQuery = MediaConstraintsMock::verifyConstraints(RealtimeMediaSource::Video, videoConstraints);
+        const String invalidQuery = MediaConstraintsMock::verifyConstraints(RealtimeMediaSource::Video, videoConstraints);
         if (!invalidQuery.isEmpty()) {
             client->failedToCreateStreamWithConstraintsError(invalidQuery);
             return;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to