blob: 55677869bedd7c3212400b87cfae3277acc34d30 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
kjellanderb24317b2016-02-10 07:54:43 -08002 * Copyright 2013 The WebRTC project authors. All Rights Reserved.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003 *
kjellanderb24317b2016-02-10 07:54:43 -08004 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00009 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "api/mediaconstraintsinterface.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000012
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020013#include "api/peerconnectioninterface.h"
14#include "rtc_base/stringencode.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000015
deadbeeffe0fd412017-01-13 11:47:56 -080016namespace {
17
18// Find the highest-priority instance of the T-valued constraint named by
19// |key| and return its value as |value|. |constraints| can be null.
20// If |mandatory_constraints| is non-null, it is incremented if the key appears
21// among the mandatory constraints.
22// Returns true if the key was found and has a valid value for type T.
23// If the key appears multiple times as an optional constraint, appearances
24// after the first are ignored.
25// Note: Because this uses FindFirst, repeated optional constraints whose
26// first instance has an unrecognized value are not handled precisely in
27// accordance with the specification.
28template <typename T>
29bool FindConstraint(const webrtc::MediaConstraintsInterface* constraints,
30 const std::string& key,
31 T* value,
32 size_t* mandatory_constraints) {
33 std::string string_value;
34 if (!FindConstraint(constraints, key, &string_value, mandatory_constraints)) {
35 return false;
36 }
37 return rtc::FromString(string_value, value);
38}
39
40// Specialization for std::string, since a string doesn't need conversion.
41template <>
42bool FindConstraint(const webrtc::MediaConstraintsInterface* constraints,
43 const std::string& key,
44 std::string* value,
45 size_t* mandatory_constraints) {
46 if (!constraints) {
47 return false;
48 }
49 if (constraints->GetMandatory().FindFirst(key, value)) {
50 if (mandatory_constraints) {
51 ++*mandatory_constraints;
52 }
53 return true;
54 }
55 if (constraints->GetOptional().FindFirst(key, value)) {
56 return true;
57 }
58 return false;
59}
60
61// Converts a constraint (mandatory takes precedence over optional) to an
Danil Chapovalov0bc58cf2018-06-21 13:32:56 +020062// absl::optional.
deadbeeffe0fd412017-01-13 11:47:56 -080063template <typename T>
64void ConstraintToOptional(const webrtc::MediaConstraintsInterface* constraints,
65 const std::string& key,
Danil Chapovalov0bc58cf2018-06-21 13:32:56 +020066 absl::optional<T>* value_out) {
deadbeeffe0fd412017-01-13 11:47:56 -080067 T value;
68 bool present = FindConstraint<T>(constraints, key, &value, nullptr);
69 if (present) {
Oskar Sundbom0e1d7982017-11-16 10:52:42 +010070 *value_out = value;
deadbeeffe0fd412017-01-13 11:47:56 -080071 }
72}
oprypin803dc292017-02-01 01:55:59 -080073} // namespace
deadbeeffe0fd412017-01-13 11:47:56 -080074
henrike@webrtc.org28e20752013-07-10 00:45:36 +000075namespace webrtc {
76
77const char MediaConstraintsInterface::kValueTrue[] = "true";
78const char MediaConstraintsInterface::kValueFalse[] = "false";
79
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +000080// Constraints declared as static members in mediastreaminterface.h
81// Specified by draft-alvestrand-constraints-resolution-00b
82const char MediaConstraintsInterface::kMinAspectRatio[] = "minAspectRatio";
83const char MediaConstraintsInterface::kMaxAspectRatio[] = "maxAspectRatio";
84const char MediaConstraintsInterface::kMaxWidth[] = "maxWidth";
85const char MediaConstraintsInterface::kMinWidth[] = "minWidth";
86const char MediaConstraintsInterface::kMaxHeight[] = "maxHeight";
87const char MediaConstraintsInterface::kMinHeight[] = "minHeight";
88const char MediaConstraintsInterface::kMaxFrameRate[] = "maxFrameRate";
89const char MediaConstraintsInterface::kMinFrameRate[] = "minFrameRate";
90
91// Audio constraints.
Yves Gerey665174f2018-06-19 15:03:05 +020092const char MediaConstraintsInterface::kEchoCancellation[] = "echoCancellation";
Tommi70c7fe12015-06-15 09:14:03 +020093const char MediaConstraintsInterface::kGoogEchoCancellation[] =
94 "googEchoCancellation";
Henrik Lundin441f6342015-06-09 16:03:13 +020095const char MediaConstraintsInterface::kExtendedFilterEchoCancellation[] =
96 "googEchoCancellation2";
Bjorn Volckerbf395c12015-03-25 22:45:56 +010097const char MediaConstraintsInterface::kDAEchoCancellation[] =
98 "googDAEchoCancellation";
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +000099const char MediaConstraintsInterface::kAutoGainControl[] =
100 "googAutoGainControl";
101const char MediaConstraintsInterface::kExperimentalAutoGainControl[] =
102 "googAutoGainControl2";
103const char MediaConstraintsInterface::kNoiseSuppression[] =
104 "googNoiseSuppression";
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +0000105const char MediaConstraintsInterface::kExperimentalNoiseSuppression[] =
106 "googNoiseSuppression2";
Yves Gerey665174f2018-06-19 15:03:05 +0200107const char MediaConstraintsInterface::kHighpassFilter[] = "googHighpassFilter";
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000108const char MediaConstraintsInterface::kTypingNoiseDetection[] =
109 "googTypingNoiseDetection";
110const char MediaConstraintsInterface::kAudioMirroring[] = "googAudioMirroring";
minyueba414282016-12-11 02:17:52 -0800111const char MediaConstraintsInterface::kAudioNetworkAdaptorConfig[] =
112 "googAudioNetworkAdaptorConfig";
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000113
114// Google-specific constraint keys for a local video source (getUserMedia).
115const char MediaConstraintsInterface::kNoiseReduction[] = "googNoiseReduction";
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000116
wu@webrtc.org14814912014-04-02 23:25:15 +0000117// Constraint keys for CreateOffer / CreateAnswer defined in W3C specification.
118const char MediaConstraintsInterface::kOfferToReceiveAudio[] =
119 "OfferToReceiveAudio";
120const char MediaConstraintsInterface::kOfferToReceiveVideo[] =
121 "OfferToReceiveVideo";
122const char MediaConstraintsInterface::kVoiceActivityDetection[] =
123 "VoiceActivityDetection";
Yves Gerey665174f2018-06-19 15:03:05 +0200124const char MediaConstraintsInterface::kIceRestart[] = "IceRestart";
wu@webrtc.org14814912014-04-02 23:25:15 +0000125// Google specific constraint for BUNDLE enable/disable.
Yves Gerey665174f2018-06-19 15:03:05 +0200126const char MediaConstraintsInterface::kUseRtpMux[] = "googUseRtpMUX";
wu@webrtc.org14814912014-04-02 23:25:15 +0000127
128// Below constraints should be used during PeerConnection construction.
129const char MediaConstraintsInterface::kEnableDtlsSrtp[] =
130 "DtlsSrtpKeyAgreement";
131const char MediaConstraintsInterface::kEnableRtpDataChannels[] =
132 "RtpDataChannels";
133// Google-specific constraint keys.
134const char MediaConstraintsInterface::kEnableDscp[] = "googDscp";
135const char MediaConstraintsInterface::kEnableIPv6[] = "googIPv6";
136const char MediaConstraintsInterface::kEnableVideoSuspendBelowMinBitrate[] =
137 "googSuspendBelowMinBitrate";
buildbot@webrtc.orgb4c7b092014-08-25 12:11:58 +0000138const char MediaConstraintsInterface::kCombinedAudioVideoBwe[] =
139 "googCombinedAudioVideoBwe";
henrike@webrtc.orgdce3feb2014-03-26 01:17:30 +0000140const char MediaConstraintsInterface::kScreencastMinBitrate[] =
141 "googScreencastMinBitrate";
henrike@webrtc.orgb0ecc1c2014-03-26 22:44:28 +0000142// TODO(ronghuawu): Remove once cpu overuse detection is stable.
143const char MediaConstraintsInterface::kCpuOveruseDetection[] =
144 "googCpuOveruseDetection";
buildbot@webrtc.org44a317a2014-06-17 07:49:15 +0000145const char MediaConstraintsInterface::kPayloadPadding[] = "googPayloadPadding";
146
Jonas Orelandfc1acd22018-08-24 10:58:37 +0200147const char MediaConstraintsInterface::kNumSimulcastLayers[] =
148 "googNumSimulcastLayers";
149
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000150// Set |value| to the value associated with the first appearance of |key|, or
151// return false if |key| is not found.
152bool MediaConstraintsInterface::Constraints::FindFirst(
Yves Gerey665174f2018-06-19 15:03:05 +0200153 const std::string& key,
154 std::string* value) const {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000155 for (Constraints::const_iterator iter = begin(); iter != end(); ++iter) {
156 if (iter->key == key) {
157 *value = iter->value;
158 return true;
159 }
160 }
161 return false;
162}
163
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000164bool FindConstraint(const MediaConstraintsInterface* constraints,
Yves Gerey665174f2018-06-19 15:03:05 +0200165 const std::string& key,
166 bool* value,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000167 size_t* mandatory_constraints) {
deadbeeffe0fd412017-01-13 11:47:56 -0800168 return ::FindConstraint<bool>(constraints, key, value, mandatory_constraints);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000169}
170
htaa2a49d92016-03-04 02:51:39 -0800171bool FindConstraint(const MediaConstraintsInterface* constraints,
172 const std::string& key,
173 int* value,
174 size_t* mandatory_constraints) {
deadbeeffe0fd412017-01-13 11:47:56 -0800175 return ::FindConstraint<int>(constraints, key, value, mandatory_constraints);
htaa2a49d92016-03-04 02:51:39 -0800176}
177
178void CopyConstraintsIntoRtcConfiguration(
179 const MediaConstraintsInterface* constraints,
180 PeerConnectionInterface::RTCConfiguration* configuration) {
181 // Copy info from constraints into configuration, if present.
182 if (!constraints) {
183 return;
184 }
185
nissec36b31b2016-04-11 23:25:29 -0700186 bool enable_ipv6;
htaa2a49d92016-03-04 02:51:39 -0800187 if (FindConstraint(constraints, MediaConstraintsInterface::kEnableIPv6,
nissec36b31b2016-04-11 23:25:29 -0700188 &enable_ipv6, nullptr)) {
189 configuration->disable_ipv6 = !enable_ipv6;
htaa2a49d92016-03-04 02:51:39 -0800190 }
nissec36b31b2016-04-11 23:25:29 -0700191 FindConstraint(constraints, MediaConstraintsInterface::kEnableDscp,
192 &configuration->media_config.enable_dscp, nullptr);
Yves Gerey665174f2018-06-19 15:03:05 +0200193 FindConstraint(constraints, MediaConstraintsInterface::kCpuOveruseDetection,
194 &configuration->media_config.video.enable_cpu_adaptation,
195 nullptr);
nissec36b31b2016-04-11 23:25:29 -0700196 FindConstraint(constraints, MediaConstraintsInterface::kEnableRtpDataChannels,
197 &configuration->enable_rtp_data_channel, nullptr);
htaa2a49d92016-03-04 02:51:39 -0800198 // Find Suspend Below Min Bitrate constraint.
nissec36b31b2016-04-11 23:25:29 -0700199 FindConstraint(constraints,
200 MediaConstraintsInterface::kEnableVideoSuspendBelowMinBitrate,
201 &configuration->media_config.video.suspend_below_min_bitrate,
202 nullptr);
deadbeeffe0fd412017-01-13 11:47:56 -0800203 ConstraintToOptional<int>(constraints,
204 MediaConstraintsInterface::kScreencastMinBitrate,
205 &configuration->screencast_min_bitrate);
206 ConstraintToOptional<bool>(constraints,
207 MediaConstraintsInterface::kCombinedAudioVideoBwe,
208 &configuration->combined_audio_video_bwe);
209 ConstraintToOptional<bool>(constraints,
210 MediaConstraintsInterface::kEnableDtlsSrtp,
211 &configuration->enable_dtls_srtp);
212}
213
214void CopyConstraintsIntoAudioOptions(
215 const MediaConstraintsInterface* constraints,
216 cricket::AudioOptions* options) {
217 if (!constraints) {
218 return;
219 }
220
221 ConstraintToOptional<bool>(constraints,
222 MediaConstraintsInterface::kGoogEchoCancellation,
223 &options->echo_cancellation);
224 ConstraintToOptional<bool>(
225 constraints, MediaConstraintsInterface::kExtendedFilterEchoCancellation,
226 &options->extended_filter_aec);
227 ConstraintToOptional<bool>(constraints,
228 MediaConstraintsInterface::kDAEchoCancellation,
229 &options->delay_agnostic_aec);
230 ConstraintToOptional<bool>(constraints,
231 MediaConstraintsInterface::kAutoGainControl,
232 &options->auto_gain_control);
233 ConstraintToOptional<bool>(
234 constraints, MediaConstraintsInterface::kExperimentalAutoGainControl,
235 &options->experimental_agc);
236 ConstraintToOptional<bool>(constraints,
237 MediaConstraintsInterface::kNoiseSuppression,
238 &options->noise_suppression);
239 ConstraintToOptional<bool>(
240 constraints, MediaConstraintsInterface::kExperimentalNoiseSuppression,
241 &options->experimental_ns);
deadbeeffe0fd412017-01-13 11:47:56 -0800242 ConstraintToOptional<bool>(constraints,
deadbeeffe0fd412017-01-13 11:47:56 -0800243 MediaConstraintsInterface::kHighpassFilter,
244 &options->highpass_filter);
245 ConstraintToOptional<bool>(constraints,
246 MediaConstraintsInterface::kTypingNoiseDetection,
247 &options->typing_detection);
248 ConstraintToOptional<bool>(constraints,
249 MediaConstraintsInterface::kAudioMirroring,
250 &options->stereo_swapping);
deadbeeffe0fd412017-01-13 11:47:56 -0800251 ConstraintToOptional<std::string>(
252 constraints, MediaConstraintsInterface::kAudioNetworkAdaptorConfig,
253 &options->audio_network_adaptor_config);
254 // When |kAudioNetworkAdaptorConfig| is defined, it both means that audio
255 // network adaptor is desired, and provides the config string.
256 if (options->audio_network_adaptor_config) {
Oskar Sundbom0e1d7982017-11-16 10:52:42 +0100257 options->audio_network_adaptor = true;
deadbeeffe0fd412017-01-13 11:47:56 -0800258 }
htaa2a49d92016-03-04 02:51:39 -0800259}
260
Niels Möllerf06f9232018-08-07 12:32:18 +0200261bool CopyConstraintsIntoOfferAnswerOptions(
262 const MediaConstraintsInterface* constraints,
263 PeerConnectionInterface::RTCOfferAnswerOptions* offer_answer_options) {
264 if (!constraints) {
265 return true;
266 }
267
268 bool value = false;
269 size_t mandatory_constraints_satisfied = 0;
270
271 if (FindConstraint(constraints,
272 MediaConstraintsInterface::kOfferToReceiveAudio, &value,
273 &mandatory_constraints_satisfied)) {
274 offer_answer_options->offer_to_receive_audio =
275 value ? PeerConnectionInterface::RTCOfferAnswerOptions::
276 kOfferToReceiveMediaTrue
277 : 0;
278 }
279
280 if (FindConstraint(constraints,
281 MediaConstraintsInterface::kOfferToReceiveVideo, &value,
282 &mandatory_constraints_satisfied)) {
283 offer_answer_options->offer_to_receive_video =
284 value ? PeerConnectionInterface::RTCOfferAnswerOptions::
285 kOfferToReceiveMediaTrue
286 : 0;
287 }
288 if (FindConstraint(constraints,
289 MediaConstraintsInterface::kVoiceActivityDetection, &value,
290 &mandatory_constraints_satisfied)) {
291 offer_answer_options->voice_activity_detection = value;
292 }
293 if (FindConstraint(constraints, MediaConstraintsInterface::kUseRtpMux, &value,
294 &mandatory_constraints_satisfied)) {
295 offer_answer_options->use_rtp_mux = value;
296 }
297 if (FindConstraint(constraints, MediaConstraintsInterface::kIceRestart,
298 &value, &mandatory_constraints_satisfied)) {
299 offer_answer_options->ice_restart = value;
300 }
301
Jonas Orelandfc1acd22018-08-24 10:58:37 +0200302 int layers;
303 if (FindConstraint(constraints,
304 MediaConstraintsInterface::kNumSimulcastLayers,
305 &layers, &mandatory_constraints_satisfied)) {
306 offer_answer_options->num_simulcast_layers = layers;
307 }
308
Niels Möllerf06f9232018-08-07 12:32:18 +0200309 return mandatory_constraints_satisfied == constraints->GetMandatory().size();
310}
311
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000312} // namespace webrtc