1/*
2 * Copyright (C) 2016 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24
25#include "config.h"
26#include "MediaTrackConstraints.h"
27
28#if ENABLE(MEDIA_STREAM)
29
30#include "MediaConstraints.h"
31
32namespace WebCore {
33
34enum class ConstraintSetType { Mandatory, Advanced };
35
36static void set(MediaTrackConstraintSetMap& map, ConstraintSetType setType, const char* typeAsString, MediaConstraintType type, const ConstrainLong& value)
37{
38 IntConstraint constraint(typeAsString, type);
39 WTF::switchOn(value,
40 [&] (int integer) {
41 if (setType == ConstraintSetType::Mandatory)
42 constraint.setIdeal(integer);
43 else
44 constraint.setExact(integer);
45 },
46 [&] (const ConstrainLongRange& range) {
47 if (range.min)
48 constraint.setMin(range.min.value());
49 if (range.max)
50 constraint.setMax(range.max.value());
51 if (range.exact)
52 constraint.setExact(range.exact.value());
53 if (range.ideal)
54 constraint.setIdeal(range.ideal.value());
55 }
56 );
57 map.set(type, WTFMove(constraint));
58}
59
60static void set(MediaTrackConstraintSetMap& map, ConstraintSetType setType, const char* typeAsString, MediaConstraintType type, const ConstrainDouble& value)
61{
62 DoubleConstraint constraint(typeAsString, type);
63 WTF::switchOn(value,
64 [&] (double number) {
65 if (setType == ConstraintSetType::Mandatory)
66 constraint.setIdeal(number);
67 else
68 constraint.setExact(number);
69 },
70 [&] (const ConstrainDoubleRange& range) {
71 if (range.min)
72 constraint.setMin(range.min.value());
73 if (range.max)
74 constraint.setMax(range.max.value());
75 if (range.exact)
76 constraint.setExact(range.exact.value());
77 if (range.ideal)
78 constraint.setIdeal(range.ideal.value());
79 }
80 );
81 map.set(type, WTFMove(constraint));
82}
83
84static void set(MediaTrackConstraintSetMap& map, ConstraintSetType setType, const char* typeAsString, MediaConstraintType type, const ConstrainBoolean& value)
85{
86 BooleanConstraint constraint(typeAsString, type);
87 WTF::switchOn(value,
88 [&] (bool boolean) {
89 if (setType == ConstraintSetType::Mandatory)
90 constraint.setIdeal(boolean);
91 else
92 constraint.setExact(boolean);
93 },
94 [&] (const ConstrainBooleanParameters& parameters) {
95 if (parameters.exact)
96 constraint.setExact(parameters.exact.value());
97 if (parameters.ideal)
98 constraint.setIdeal(parameters.ideal.value());
99 }
100 );
101 map.set(type, WTFMove(constraint));
102}
103
104static void set(MediaTrackConstraintSetMap& map, ConstraintSetType setType, const char* typeAsString, MediaConstraintType type, const ConstrainDOMString& value)
105{
106 StringConstraint constraint(typeAsString, type);
107 WTF::switchOn(value,
108 [&] (const String& string) {
109 if (setType == ConstraintSetType::Mandatory)
110 constraint.appendIdeal(string);
111 else
112 constraint.appendExact(string);
113 },
114 [&] (const Vector<String>& vector) {
115 if (setType == ConstraintSetType::Mandatory) {
116 for (auto& string : vector)
117 constraint.appendIdeal(string);
118 } else {
119 for (auto& string : vector)
120 constraint.appendExact(string);
121 }
122 },
123 [&] (const ConstrainDOMStringParameters& parameters) {
124 if (parameters.exact) {
125 WTF::switchOn(parameters.exact.value(),
126 [&] (const String& string) {
127 constraint.appendExact(string);
128 },
129 [&] (const Vector<String>& vector) {
130 for (auto& string : vector)
131 constraint.appendExact(string);
132 }
133 );
134 }
135 if (parameters.ideal) {
136 WTF::switchOn(parameters.ideal.value(),
137 [&] (const String& string) {
138 constraint.appendIdeal(string);
139 },
140 [&] (const Vector<String>& vector) {
141 for (auto& string : vector)
142 constraint.appendIdeal(string);
143 }
144 );
145 }
146 }
147 );
148 map.set(type, WTFMove(constraint));
149}
150
151template<typename T> static inline void set(MediaTrackConstraintSetMap& map, ConstraintSetType setType, const char* typeAsString, MediaConstraintType type, const Optional<T>& value)
152{
153 if (!value)
154 return;
155 set(map, setType, typeAsString, type, value.value());
156}
157
158static MediaTrackConstraintSetMap convertToInternalForm(ConstraintSetType setType, const MediaTrackConstraintSet& constraintSet)
159{
160 MediaTrackConstraintSetMap result;
161 set(result, setType, "width", MediaConstraintType::Width, constraintSet.width);
162 set(result, setType, "height", MediaConstraintType::Height, constraintSet.height);
163 set(result, setType, "aspectRatio", MediaConstraintType::AspectRatio, constraintSet.aspectRatio);
164 set(result, setType, "frameRate", MediaConstraintType::FrameRate, constraintSet.frameRate);
165 set(result, setType, "facingMode", MediaConstraintType::FacingMode, constraintSet.facingMode);
166 set(result, setType, "volume", MediaConstraintType::Volume, constraintSet.volume);
167 set(result, setType, "sampleRate", MediaConstraintType::SampleRate, constraintSet.sampleRate);
168 set(result, setType, "sampleSize", MediaConstraintType::SampleSize, constraintSet.sampleSize);
169 set(result, setType, "echoCancellation", MediaConstraintType::EchoCancellation, constraintSet.echoCancellation);
170 // FIXME: add latency
171 // FIXME: add channelCount
172 set(result, setType, "deviceId", MediaConstraintType::DeviceId, constraintSet.deviceId);
173 set(result, setType, "groupId", MediaConstraintType::GroupId, constraintSet.groupId);
174 set(result, setType, "displaySurface", MediaConstraintType::DisplaySurface, constraintSet.displaySurface);
175 set(result, setType, "logicalSurface", MediaConstraintType::LogicalSurface, constraintSet.logicalSurface);
176 return result;
177}
178
179static Vector<MediaTrackConstraintSetMap> convertAdvancedToInternalForm(const Vector<MediaTrackConstraintSet>& vector)
180{
181 Vector<MediaTrackConstraintSetMap> result;
182 result.reserveInitialCapacity(vector.size());
183 for (auto& set : vector)
184 result.uncheckedAppend(convertToInternalForm(ConstraintSetType::Advanced, set));
185 return result;
186}
187
188static Vector<MediaTrackConstraintSetMap> convertAdvancedToInternalForm(const Optional<Vector<MediaTrackConstraintSet>>& optionalVector)
189{
190 if (!optionalVector)
191 return { };
192 return convertAdvancedToInternalForm(optionalVector.value());
193}
194
195MediaConstraints createMediaConstraints(const MediaTrackConstraints& trackConstraints)
196{
197 MediaConstraints constraints;
198 constraints.mandatoryConstraints = convertToInternalForm(ConstraintSetType::Mandatory, trackConstraints);
199 constraints.advancedConstraints = convertAdvancedToInternalForm(trackConstraints.advanced);
200 constraints.isValid = true;
201 return constraints;
202}
203
204}
205
206#endif
207