summaryrefslogtreecommitdiff
path: root/Source/WebCore/platform/mediastream/MediaConstraints.h
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/platform/mediastream/MediaConstraints.h
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/WebCore/platform/mediastream/MediaConstraints.h')
-rw-r--r--Source/WebCore/platform/mediastream/MediaConstraints.h790
1 files changed, 775 insertions, 15 deletions
diff --git a/Source/WebCore/platform/mediastream/MediaConstraints.h b/Source/WebCore/platform/mediastream/MediaConstraints.h
index 5141c228d..899837457 100644
--- a/Source/WebCore/platform/mediastream/MediaConstraints.h
+++ b/Source/WebCore/platform/mediastream/MediaConstraints.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2012 Google Inc. All rights reserved.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -28,36 +29,787 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef MediaConstraints_h
-#define MediaConstraints_h
+#pragma once
#if ENABLE(MEDIA_STREAM)
-#include <wtf/RefCounted.h>
-#include <wtf/text/WTFString.h>
+#include "RealtimeMediaSourceSupportedConstraints.h"
+#include <cstdlib>
namespace WebCore {
-struct MediaConstraint {
- MediaConstraint(String name, String value)
+class MediaConstraint {
+public:
+ enum class DataType { None, Integer, Double, Boolean, String };
+
+ 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; }
+
+ DataType dataType() const { return m_dataType; }
+ MediaConstraintType constraintType() const { return m_constraintType; }
+ const String& name() const { return m_name; }
+
+ template <class Encoder> void encode(Encoder& encoder) const
+ {
+ encoder.encodeEnum(m_constraintType);
+ encoder << m_name;
+ encoder.encodeEnum(m_dataType);
+ }
+
+ template <class Decoder> static bool decode(Decoder& decoder, MediaConstraint& constraint)
+ {
+ if (!decoder.decodeEnum(constraint.m_constraintType))
+ return false;
+
+ if (!decoder.decode(constraint.m_name))
+ return false;
+
+ if (!decoder.decodeEnum(constraint.m_dataType))
+ return false;
+
+ return true;
+ }
+
+protected:
+ MediaConstraint(const String& name, MediaConstraintType constraintType, DataType dataType)
: m_name(name)
- , m_value(value)
+ , m_constraintType(constraintType)
+ , m_dataType(dataType)
{
}
+ MediaConstraint() = default;
+ ~MediaConstraint() = default;
+
+private:
String m_name;
- String m_value;
+ MediaConstraintType m_constraintType { MediaConstraintType::Unknown };
+ DataType m_dataType { DataType::None };
+};
+
+template<class ValueType>
+class NumericConstraint : public MediaConstraint {
+public:
+ 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
+ {
+ if (!m_min)
+ return false;
+
+ min = m_min.value();
+ return true;
+ }
+
+ bool getMax(ValueType& max) const
+ {
+ if (!m_max)
+ return false;
+
+ max = m_max.value();
+ return true;
+ }
+
+ bool getExact(ValueType& exact) const
+ {
+ if (!m_exact)
+ return false;
+
+ exact = m_exact.value();
+ return true;
+ }
+
+ bool getIdeal(ValueType& ideal) const
+ {
+ if (!m_ideal)
+ return false;
+
+ ideal = m_ideal.value();
+ return true;
+ }
+
+ bool nearlyEqual(double a, double b) const
+ {
+ // Don't require strict equality when comparing constraints, or many floating point constraint values,
+ // e.g. "aspectRatio: 1.333", will never match.
+ const double epsilon = 0.00001;
+ return std::abs(a - b) <= epsilon;
+ }
+
+ 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())
+ return 0;
+
+ // 2. If the constraint is required ('min', 'max', or 'exact'), and the settings
+ // dictionary's value for the constraint does not satisfy the constraint, the
+ // fitness distance is positive infinity.
+ bool valid = validForRange(rangeMin, rangeMax);
+ if (m_exact) {
+ if (valid && m_min && m_exact.value() < m_min.value())
+ valid = false;
+ if (valid && m_max && m_exact.value() > m_max.value())
+ valid = false;
+ if (!valid)
+ return std::numeric_limits<double>::infinity();
+ }
+
+ if (m_min) {
+ if (valid && m_max && m_min.value() > m_max.value())
+ valid = false;
+ if (!valid)
+ return std::numeric_limits<double>::infinity();
+ }
+
+ if (m_max) {
+ if (valid && m_min && m_max.value() < m_min.value())
+ valid = false;
+ if (!valid)
+ return std::numeric_limits<double>::infinity();
+ }
+
+ // 3. If no ideal value is specified, the fitness distance is 0.
+ if (!m_ideal)
+ return 0;
+
+ // 4. For all positive numeric non-required constraints (such as height, width, frameRate,
+ // aspectRatio, sampleRate and sampleSize), the fitness distance is the result of the formula
+ //
+ // (actual == ideal) ? 0 : |actual - ideal| / max(|actual|,|ideal|)
+ ValueType ideal = m_ideal.value();
+ if (ideal >= rangeMin && ideal <= rangeMax)
+ return 0;
+
+ ideal = ideal > std::max(rangeMin, rangeMax) ? rangeMax : rangeMin;
+ return static_cast<double>(std::abs(ideal - m_ideal.value())) / std::max(std::abs(ideal), std::abs(m_ideal.value()));
+ }
+
+ bool validForRange(ValueType rangeMin, ValueType rangeMax) const
+ {
+ if (isEmpty())
+ return false;
+
+ if (m_exact) {
+ const ValueType exact = m_exact.value();
+ if (exact < rangeMin && !nearlyEqual(exact, rangeMin))
+ return false;
+ if (exact > rangeMax && !nearlyEqual(exact, rangeMax))
+ return false;
+ }
+
+ if (m_min) {
+ const ValueType constraintMin = m_min.value();
+ if (constraintMin > rangeMax && !nearlyEqual(constraintMin, rangeMax))
+ return false;
+ }
+
+ if (m_max) {
+ const ValueType constraintMax = m_max.value();
+ if (constraintMax < rangeMin && !nearlyEqual(constraintMax, rangeMin))
+ return false;
+ }
+
+ return true;
+ }
+
+ ValueType find(std::function<bool(ValueType)> function) const
+ {
+ if (m_min && function(m_min.value()))
+ return m_min.value();
+
+ if (m_max && function(m_max.value()))
+ return m_max.value();
+
+ if (m_exact && function(m_exact.value()))
+ return m_exact.value();
+
+ if (m_ideal && function(m_ideal.value()))
+ return m_ideal.value();
+
+ return 0;
+ }
+
+ ValueType valueForCapabilityRange(ValueType current, ValueType capabilityMin, ValueType capabilityMax) const
+ {
+ ValueType value;
+ ValueType min = capabilityMin;
+ ValueType max = capabilityMax;
+
+ if (m_exact) {
+ ASSERT(validForRange(capabilityMin, capabilityMax));
+ return m_exact.value();
+ }
+
+ if (m_min) {
+ value = m_min.value();
+ ASSERT(validForRange(value, capabilityMax));
+ if (value > min)
+ min = value;
+
+ // If there is no ideal, don't change if minimum is smaller than current.
+ if (!m_ideal && value < current)
+ value = current;
+ }
+
+ if (m_max) {
+ value = m_max.value();
+ ASSERT(validForRange(capabilityMin, value));
+ if (value < max)
+ max = value;
+ }
+
+ if (m_ideal)
+ value = std::max(min, std::min(max, m_ideal.value()));
+
+ return value;
+ }
+
+ bool isEmpty() const { return !m_min && !m_max && !m_exact && !m_ideal; }
+ bool isMandatory() const { return m_min || m_max || m_exact; }
+
+ template <class Encoder> void encode(Encoder& encoder) const
+ {
+ MediaConstraint::encode(encoder);
+
+ encoder << m_min;
+ encoder << m_max;
+ encoder << m_exact;
+ encoder << m_ideal;
+ }
+
+ template <class Decoder> static bool decode(Decoder& decoder, NumericConstraint& constraint)
+ {
+ if (!MediaConstraint::decode(decoder, constraint))
+ return false;
+
+ if (!decoder.decode(constraint.m_min))
+ return false;
+ if (!decoder.decode(constraint.m_max))
+ return false;
+ if (!decoder.decode(constraint.m_exact))
+ return false;
+ if (!decoder.decode(constraint.m_ideal))
+ return false;
+
+ return true;
+ }
+
+protected:
+ NumericConstraint(const String& name, MediaConstraintType type, DataType dataType)
+ : MediaConstraint(name, type, dataType)
+ {
+ }
+
+ NumericConstraint() = default;
+
+ 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;
+ }
+ }
+
+ std::optional<ValueType> m_min;
+ std::optional<ValueType> m_max;
+ std::optional<ValueType> m_exact;
+ std::optional<ValueType> m_ideal;
+};
+
+class IntConstraint final : public NumericConstraint<int> {
+public:
+ IntConstraint(const String& name, MediaConstraintType type)
+ : NumericConstraint<int>(name, type, DataType::Integer)
+ {
+ }
+
+ IntConstraint() = default;
+
+ void merge(const MediaConstraint& other)
+ {
+ ASSERT(other.isInt());
+ NumericConstraint::innerMerge(downcast<const IntConstraint>(other));
+ }
+};
+
+class DoubleConstraint final : public NumericConstraint<double> {
+public:
+ DoubleConstraint(const String& name, MediaConstraintType type)
+ : NumericConstraint<double>(name, type, DataType::Double)
+ {
+ }
+
+ DoubleConstraint() = default;
+
+ void merge(const MediaConstraint& other)
+ {
+ ASSERT(other.isDouble());
+ NumericConstraint::innerMerge(downcast<DoubleConstraint>(other));
+ }
+};
+
+class BooleanConstraint final : public MediaConstraint {
+public:
+ BooleanConstraint(const String& name, MediaConstraintType type)
+ : MediaConstraint(name, type, DataType::Boolean)
+ {
+ }
+
+ BooleanConstraint() = default;
+
+ void setExact(bool value) { m_exact = value; }
+ void setIdeal(bool value) { m_ideal = value; }
+
+ bool getExact(bool& exact) const
+ {
+ if (!m_exact)
+ return false;
+
+ exact = m_exact.value();
+ return true;
+ }
+
+ bool getIdeal(bool& ideal) const
+ {
+ if (!m_ideal)
+ return false;
+
+ ideal = m_ideal.value();
+ return true;
+ }
+
+ 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())
+ return 0;
+
+ // 2. If the constraint is required ('min', 'max', or 'exact'), and the settings
+ // dictionary's value for the constraint does not satisfy the constraint, the
+ // fitness distance is positive infinity.
+ if (m_exact && value != m_exact.value())
+ return std::numeric_limits<double>::infinity();
+
+ // 3. If no ideal value is specified, the fitness distance is 0.
+ if (!m_ideal || m_ideal.value() == value)
+ return 0;
+
+ // 5. For all string and enum non-required constraints (deviceId, groupId, facingMode,
+ // echoCancellation), the fitness distance is the result of the formula
+ // (actual == ideal) ? 0 : 1
+ return 1;
+ }
+
+ void merge(const MediaConstraint& other)
+ {
+ ASSERT(other.isBoolean());
+ const BooleanConstraint& typedOther = downcast<BooleanConstraint>(other);
+
+ if (typedOther.isEmpty())
+ return;
+
+ bool value;
+ if (typedOther.getExact(value))
+ m_exact = value;
+
+ if (typedOther.getIdeal(value)) {
+ if (!m_ideal || (value && !m_ideal.value()))
+ m_ideal = value;
+ }
+ }
+
+ bool isEmpty() const { return !m_exact && !m_ideal; };
+ bool isMandatory() const { return bool(m_exact); }
+
+ template <class Encoder> void encode(Encoder& encoder) const
+ {
+ MediaConstraint::encode(encoder);
+ encoder << m_exact;
+ encoder << m_ideal;
+ }
+
+ template <class Decoder> static bool decode(Decoder& decoder, BooleanConstraint& constraint)
+ {
+ if (!MediaConstraint::decode(decoder, constraint))
+ return false;
+
+ if (!decoder.decode(constraint.m_exact))
+ return false;
+ if (!decoder.decode(constraint.m_ideal))
+ return false;
+
+ return true;
+ }
+
+private:
+ std::optional<bool> m_exact;
+ std::optional<bool> m_ideal;
+};
+
+class StringConstraint : public MediaConstraint {
+public:
+ StringConstraint(const String& name, MediaConstraintType type)
+ : MediaConstraint(name, type, DataType::String)
+ {
+ }
+
+ StringConstraint() = default;
+
+ void setExact(const String& value)
+ {
+ m_exact.clear();
+ m_exact.append(value);
+ }
+
+ void appendExact(const String& value)
+ {
+ m_exact.append(value);
+ }
+
+ void setIdeal(const String& value)
+ {
+ m_ideal.clear();
+ m_ideal.append(value);
+ }
+
+ void appendIdeal(const String& value)
+ {
+ m_ideal.append(value);
+ }
+
+ bool getExact(Vector<String>& exact) const
+ {
+ if (!m_exact.isEmpty())
+ return false;
+
+ exact = m_exact;
+ return true;
+ }
+
+ bool getIdeal(Vector<String>& ideal) const
+ {
+ if (!m_ideal.isEmpty())
+ return false;
+
+ ideal = m_ideal;
+ return true;
+ }
+
+ double fitnessDistance(const String&) const;
+ double fitnessDistance(const Vector<String>&) const;
+
+ const String& find(std::function<bool(const String&)>) const;
+
+ bool isEmpty() const { return m_exact.isEmpty() && m_ideal.isEmpty(); }
+ bool isMandatory() const { return !m_exact.isEmpty(); }
+ WEBCORE_EXPORT void merge(const MediaConstraint&);
+
+ template <class Encoder> void encode(Encoder& encoder) const
+ {
+ MediaConstraint::encode(encoder);
+
+ encoder << m_exact;
+ encoder << m_ideal;
+ }
+
+ template <class Decoder> static bool decode(Decoder& decoder, StringConstraint& constraint)
+ {
+ if (!MediaConstraint::decode(decoder, constraint))
+ return false;
+
+ if (!decoder.decode(constraint.m_exact))
+ return false;
+ if (!decoder.decode(constraint.m_ideal))
+ return false;
+
+ return true;
+ }
+
+private:
+ Vector<String> m_exact;
+ Vector<String> m_ideal;
+};
+
+class UnknownConstraint final : public MediaConstraint {
+public:
+ UnknownConstraint(const String& name, MediaConstraintType type)
+ : MediaConstraint(name, type, DataType::None)
+ {
+ }
+
+private:
+ bool isEmpty() const { return true; }
+ bool isMandatory() const { return false; }
+ void merge(const MediaConstraint&) { }
+};
+
+class MediaTrackConstraintSetMap {
+public:
+ WEBCORE_EXPORT void forEach(std::function<void(const MediaConstraint&)>) const;
+ void filter(std::function<bool(const MediaConstraint&)>) const;
+ bool isEmpty() const;
+ WEBCORE_EXPORT size_t size() const;
+
+ WEBCORE_EXPORT void set(MediaConstraintType, std::optional<IntConstraint>&&);
+ WEBCORE_EXPORT void set(MediaConstraintType, std::optional<DoubleConstraint>&&);
+ WEBCORE_EXPORT void set(MediaConstraintType, std::optional<BooleanConstraint>&&);
+ WEBCORE_EXPORT void set(MediaConstraintType, std::optional<StringConstraint>&&);
+
+ std::optional<IntConstraint> width() const { return m_width; }
+ std::optional<IntConstraint> height() const { return m_height; }
+ std::optional<IntConstraint> sampleRate() const { return m_sampleRate; }
+ std::optional<IntConstraint> sampleSize() const { return m_sampleSize; }
+
+ std::optional<DoubleConstraint> aspectRatio() const { return m_aspectRatio; }
+ std::optional<DoubleConstraint> frameRate() const { return m_frameRate; }
+ std::optional<DoubleConstraint> volume() const { return m_volume; }
+
+ std::optional<BooleanConstraint> echoCancellation() const { return m_echoCancellation; }
+
+ std::optional<StringConstraint> facingMode() const { return m_facingMode; }
+ std::optional<StringConstraint> deviceId() const { return m_deviceId; }
+ std::optional<StringConstraint> groupId() const { return m_groupId; }
+
+ template <class Encoder> void encode(Encoder& encoder) const
+ {
+ encoder << m_width;
+ encoder << m_height;
+ encoder << m_sampleRate;
+ encoder << m_sampleSize;
+
+ encoder << m_aspectRatio;
+ encoder << m_frameRate;
+ encoder << m_volume;
+
+ encoder << m_echoCancellation;
+
+ encoder << m_facingMode;
+ encoder << m_deviceId;
+ encoder << m_groupId;
+ }
+
+ template <class Decoder> static bool decode(Decoder& decoder, MediaTrackConstraintSetMap& map)
+ {
+ if (!decoder.decode(map.m_width))
+ return false;
+ if (!decoder.decode(map.m_height))
+ return false;
+ if (!decoder.decode(map.m_sampleRate))
+ return false;
+ if (!decoder.decode(map.m_sampleSize))
+ return false;
+
+ if (!decoder.decode(map.m_aspectRatio))
+ return false;
+ if (!decoder.decode(map.m_frameRate))
+ return false;
+ if (!decoder.decode(map.m_volume))
+ return false;
+
+ if (!decoder.decode(map.m_echoCancellation))
+ return false;
+
+ if (!decoder.decode(map.m_facingMode))
+ return false;
+ if (!decoder.decode(map.m_deviceId))
+ return false;
+ if (!decoder.decode(map.m_groupId))
+ return false;
+
+ return true;
+ }
+
+private:
+ std::optional<IntConstraint> m_width;
+ std::optional<IntConstraint> m_height;
+ std::optional<IntConstraint> m_sampleRate;
+ std::optional<IntConstraint> m_sampleSize;
+
+ std::optional<DoubleConstraint> m_aspectRatio;
+ std::optional<DoubleConstraint> m_frameRate;
+ std::optional<DoubleConstraint> m_volume;
+
+ std::optional<BooleanConstraint> m_echoCancellation;
+
+ std::optional<StringConstraint> m_facingMode;
+ std::optional<StringConstraint> m_deviceId;
+ std::optional<StringConstraint> m_groupId;
+};
+
+class FlattenedConstraint {
+public:
+
+ void set(const MediaConstraint&);
+ void merge(const MediaConstraint&);
+ void append(const MediaConstraint&);
+ const MediaConstraint* find(MediaConstraintType) const;
+ bool isEmpty() const { return m_variants.isEmpty(); }
+
+ 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 ConstraintHolder(value); }
+
+ ~ConstraintHolder()
+ {
+ if (m_value.asRaw) {
+ 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
+ }
+
+ ConstraintHolder(ConstraintHolder&& other)
+ {
+ switch (other.dataType()) {
+ case MediaConstraint::DataType::Integer:
+ m_value.asInteger = std::exchange(other.m_value.asInteger, nullptr);
+ break;
+ case MediaConstraint::DataType::Double:
+ m_value.asDouble = std::exchange(other.m_value.asDouble, nullptr);
+ break;
+ case MediaConstraint::DataType::Boolean:
+ m_value.asBoolean = std::exchange(other.m_value.asBoolean, nullptr);
+ break;
+ case MediaConstraint::DataType::String:
+ m_value.asString = std::exchange(other.m_value.asString, nullptr);
+ break;
+ case MediaConstraint::DataType::None:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+ }
+
+ 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> {
public:
virtual ~MediaConstraints() { }
- virtual void getMandatoryConstraints(Vector<MediaConstraint>&) const = 0;
- virtual void getOptionalConstraints(Vector<MediaConstraint>&) const = 0;
-
- virtual bool getMandatoryConstraintValue(const String& name, String& value) const = 0;
- virtual bool getOptionalConstraintValue(const String& name, String& value) const = 0;
+ virtual const MediaTrackConstraintSetMap& mandatoryConstraints() const = 0;
+ virtual const Vector<MediaTrackConstraintSetMap>& advancedConstraints() const = 0;
+ virtual bool isValid() const = 0;
protected:
MediaConstraints() { }
@@ -65,6 +817,14 @@ protected:
} // namespace WebCore
-#endif // ENABLE(MEDIA_STREAM)
+#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 // MediaConstraints_h
+#endif // ENABLE(MEDIA_STREAM)