blob: e16fc19590c68c2eee32815a60be592b1bea33f9 [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
Steve Anton10542f22019-01-11 09:11:00 -080011#include "api/media_constraints_interface.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000012
Yves Gerey988cc082018-10-23 12:03:01 +020013#include "absl/types/optional.h"
Steve Anton10542f22019-01-11 09:11:00 -080014#include "api/peer_connection_interface.h"
15#include "media/base/media_config.h"
16#include "rtc_base/string_encode.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000017
deadbeeffe0fd412017-01-13 11:47:56 -080018namespace {
19
20// Find the highest-priority instance of the T-valued constraint named by
21// |key| and return its value as |value|. |constraints| can be null.
22// If |mandatory_constraints| is non-null, it is incremented if the key appears
23// among the mandatory constraints.
24// Returns true if the key was found and has a valid value for type T.
25// If the key appears multiple times as an optional constraint, appearances
26// after the first are ignored.
27// Note: Because this uses FindFirst, repeated optional constraints whose
28// first instance has an unrecognized value are not handled precisely in
29// accordance with the specification.
30template <typename T>
31bool FindConstraint(const webrtc::MediaConstraintsInterface* constraints,
32 const std::string& key,
33 T* value,
34 size_t* mandatory_constraints) {
35 std::string string_value;
36 if (!FindConstraint(constraints, key, &string_value, mandatory_constraints)) {
37 return false;
38 }
39 return rtc::FromString(string_value, value);
40}
41
42// Specialization for std::string, since a string doesn't need conversion.
43template <>
44bool FindConstraint(const webrtc::MediaConstraintsInterface* constraints,
45 const std::string& key,
46 std::string* value,
47 size_t* mandatory_constraints) {
48 if (!constraints) {
49 return false;
50 }
51 if (constraints->GetMandatory().FindFirst(key, value)) {
52 if (mandatory_constraints) {
53 ++*mandatory_constraints;
54 }
55 return true;
56 }
57 if (constraints->GetOptional().FindFirst(key, value)) {
58 return true;
59 }
60 return false;
61}
62
63// Converts a constraint (mandatory takes precedence over optional) to an
Danil Chapovalov0bc58cf2018-06-21 13:32:56 +020064// absl::optional.
deadbeeffe0fd412017-01-13 11:47:56 -080065template <typename T>
66void ConstraintToOptional(const webrtc::MediaConstraintsInterface* constraints,
67 const std::string& key,
Danil Chapovalov0bc58cf2018-06-21 13:32:56 +020068 absl::optional<T>* value_out) {
deadbeeffe0fd412017-01-13 11:47:56 -080069 T value;
70 bool present = FindConstraint<T>(constraints, key, &value, nullptr);
71 if (present) {
Oskar Sundbom0e1d7982017-11-16 10:52:42 +010072 *value_out = value;
deadbeeffe0fd412017-01-13 11:47:56 -080073 }
74}
oprypin803dc292017-02-01 01:55:59 -080075} // namespace
deadbeeffe0fd412017-01-13 11:47:56 -080076
henrike@webrtc.org28e20752013-07-10 00:45:36 +000077namespace webrtc {
78
79const char MediaConstraintsInterface::kValueTrue[] = "true";
80const char MediaConstraintsInterface::kValueFalse[] = "false";
81
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +000082// Constraints declared as static members in mediastreaminterface.h
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +000083
84// Audio constraints.
Tommi70c7fe12015-06-15 09:14:03 +020085const char MediaConstraintsInterface::kGoogEchoCancellation[] =
86 "googEchoCancellation";
Henrik Lundin441f6342015-06-09 16:03:13 +020087const char MediaConstraintsInterface::kExtendedFilterEchoCancellation[] =
88 "googEchoCancellation2";
Bjorn Volckerbf395c12015-03-25 22:45:56 +010089const char MediaConstraintsInterface::kDAEchoCancellation[] =
90 "googDAEchoCancellation";
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +000091const char MediaConstraintsInterface::kAutoGainControl[] =
92 "googAutoGainControl";
93const char MediaConstraintsInterface::kExperimentalAutoGainControl[] =
94 "googAutoGainControl2";
95const char MediaConstraintsInterface::kNoiseSuppression[] =
96 "googNoiseSuppression";
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +000097const char MediaConstraintsInterface::kExperimentalNoiseSuppression[] =
98 "googNoiseSuppression2";
Yves Gerey665174f2018-06-19 15:03:05 +020099const char MediaConstraintsInterface::kHighpassFilter[] = "googHighpassFilter";
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000100const char MediaConstraintsInterface::kTypingNoiseDetection[] =
101 "googTypingNoiseDetection";
102const char MediaConstraintsInterface::kAudioMirroring[] = "googAudioMirroring";
minyueba414282016-12-11 02:17:52 -0800103const char MediaConstraintsInterface::kAudioNetworkAdaptorConfig[] =
104 "googAudioNetworkAdaptorConfig";
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000105
wu@webrtc.org14814912014-04-02 23:25:15 +0000106// Constraint keys for CreateOffer / CreateAnswer defined in W3C specification.
107const char MediaConstraintsInterface::kOfferToReceiveAudio[] =
108 "OfferToReceiveAudio";
109const char MediaConstraintsInterface::kOfferToReceiveVideo[] =
110 "OfferToReceiveVideo";
111const char MediaConstraintsInterface::kVoiceActivityDetection[] =
112 "VoiceActivityDetection";
Yves Gerey665174f2018-06-19 15:03:05 +0200113const char MediaConstraintsInterface::kIceRestart[] = "IceRestart";
wu@webrtc.org14814912014-04-02 23:25:15 +0000114// Google specific constraint for BUNDLE enable/disable.
Yves Gerey665174f2018-06-19 15:03:05 +0200115const char MediaConstraintsInterface::kUseRtpMux[] = "googUseRtpMUX";
wu@webrtc.org14814912014-04-02 23:25:15 +0000116
117// Below constraints should be used during PeerConnection construction.
118const char MediaConstraintsInterface::kEnableDtlsSrtp[] =
119 "DtlsSrtpKeyAgreement";
120const char MediaConstraintsInterface::kEnableRtpDataChannels[] =
121 "RtpDataChannels";
122// Google-specific constraint keys.
123const char MediaConstraintsInterface::kEnableDscp[] = "googDscp";
124const char MediaConstraintsInterface::kEnableIPv6[] = "googIPv6";
125const char MediaConstraintsInterface::kEnableVideoSuspendBelowMinBitrate[] =
126 "googSuspendBelowMinBitrate";
buildbot@webrtc.orgb4c7b092014-08-25 12:11:58 +0000127const char MediaConstraintsInterface::kCombinedAudioVideoBwe[] =
128 "googCombinedAudioVideoBwe";
henrike@webrtc.orgdce3feb2014-03-26 01:17:30 +0000129const char MediaConstraintsInterface::kScreencastMinBitrate[] =
130 "googScreencastMinBitrate";
henrike@webrtc.orgb0ecc1c2014-03-26 22:44:28 +0000131// TODO(ronghuawu): Remove once cpu overuse detection is stable.
132const char MediaConstraintsInterface::kCpuOveruseDetection[] =
133 "googCpuOveruseDetection";
buildbot@webrtc.org44a317a2014-06-17 07:49:15 +0000134
Jonas Orelandfc1acd22018-08-24 10:58:37 +0200135const char MediaConstraintsInterface::kNumSimulcastLayers[] =
136 "googNumSimulcastLayers";
137
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000138// Set |value| to the value associated with the first appearance of |key|, or
139// return false if |key| is not found.
140bool MediaConstraintsInterface::Constraints::FindFirst(
Yves Gerey665174f2018-06-19 15:03:05 +0200141 const std::string& key,
142 std::string* value) const {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000143 for (Constraints::const_iterator iter = begin(); iter != end(); ++iter) {
144 if (iter->key == key) {
145 *value = iter->value;
146 return true;
147 }
148 }
149 return false;
150}
151
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000152bool FindConstraint(const MediaConstraintsInterface* constraints,
Yves Gerey665174f2018-06-19 15:03:05 +0200153 const std::string& key,
154 bool* value,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000155 size_t* mandatory_constraints) {
deadbeeffe0fd412017-01-13 11:47:56 -0800156 return ::FindConstraint<bool>(constraints, key, value, mandatory_constraints);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000157}
158
htaa2a49d92016-03-04 02:51:39 -0800159bool FindConstraint(const MediaConstraintsInterface* constraints,
160 const std::string& key,
161 int* value,
162 size_t* mandatory_constraints) {
deadbeeffe0fd412017-01-13 11:47:56 -0800163 return ::FindConstraint<int>(constraints, key, value, mandatory_constraints);
htaa2a49d92016-03-04 02:51:39 -0800164}
165
166void CopyConstraintsIntoRtcConfiguration(
167 const MediaConstraintsInterface* constraints,
168 PeerConnectionInterface::RTCConfiguration* configuration) {
169 // Copy info from constraints into configuration, if present.
170 if (!constraints) {
171 return;
172 }
173
nissec36b31b2016-04-11 23:25:29 -0700174 bool enable_ipv6;
htaa2a49d92016-03-04 02:51:39 -0800175 if (FindConstraint(constraints, MediaConstraintsInterface::kEnableIPv6,
nissec36b31b2016-04-11 23:25:29 -0700176 &enable_ipv6, nullptr)) {
177 configuration->disable_ipv6 = !enable_ipv6;
htaa2a49d92016-03-04 02:51:39 -0800178 }
nissec36b31b2016-04-11 23:25:29 -0700179 FindConstraint(constraints, MediaConstraintsInterface::kEnableDscp,
180 &configuration->media_config.enable_dscp, nullptr);
Yves Gerey665174f2018-06-19 15:03:05 +0200181 FindConstraint(constraints, MediaConstraintsInterface::kCpuOveruseDetection,
182 &configuration->media_config.video.enable_cpu_adaptation,
183 nullptr);
nissec36b31b2016-04-11 23:25:29 -0700184 FindConstraint(constraints, MediaConstraintsInterface::kEnableRtpDataChannels,
185 &configuration->enable_rtp_data_channel, nullptr);
htaa2a49d92016-03-04 02:51:39 -0800186 // Find Suspend Below Min Bitrate constraint.
nissec36b31b2016-04-11 23:25:29 -0700187 FindConstraint(constraints,
188 MediaConstraintsInterface::kEnableVideoSuspendBelowMinBitrate,
189 &configuration->media_config.video.suspend_below_min_bitrate,
190 nullptr);
deadbeeffe0fd412017-01-13 11:47:56 -0800191 ConstraintToOptional<int>(constraints,
192 MediaConstraintsInterface::kScreencastMinBitrate,
193 &configuration->screencast_min_bitrate);
194 ConstraintToOptional<bool>(constraints,
195 MediaConstraintsInterface::kCombinedAudioVideoBwe,
196 &configuration->combined_audio_video_bwe);
197 ConstraintToOptional<bool>(constraints,
198 MediaConstraintsInterface::kEnableDtlsSrtp,
199 &configuration->enable_dtls_srtp);
200}
201
202void CopyConstraintsIntoAudioOptions(
203 const MediaConstraintsInterface* constraints,
204 cricket::AudioOptions* options) {
205 if (!constraints) {
206 return;
207 }
208
209 ConstraintToOptional<bool>(constraints,
210 MediaConstraintsInterface::kGoogEchoCancellation,
211 &options->echo_cancellation);
212 ConstraintToOptional<bool>(
213 constraints, MediaConstraintsInterface::kExtendedFilterEchoCancellation,
214 &options->extended_filter_aec);
215 ConstraintToOptional<bool>(constraints,
216 MediaConstraintsInterface::kDAEchoCancellation,
217 &options->delay_agnostic_aec);
218 ConstraintToOptional<bool>(constraints,
219 MediaConstraintsInterface::kAutoGainControl,
220 &options->auto_gain_control);
221 ConstraintToOptional<bool>(
222 constraints, MediaConstraintsInterface::kExperimentalAutoGainControl,
223 &options->experimental_agc);
224 ConstraintToOptional<bool>(constraints,
225 MediaConstraintsInterface::kNoiseSuppression,
226 &options->noise_suppression);
227 ConstraintToOptional<bool>(
228 constraints, MediaConstraintsInterface::kExperimentalNoiseSuppression,
229 &options->experimental_ns);
deadbeeffe0fd412017-01-13 11:47:56 -0800230 ConstraintToOptional<bool>(constraints,
deadbeeffe0fd412017-01-13 11:47:56 -0800231 MediaConstraintsInterface::kHighpassFilter,
232 &options->highpass_filter);
233 ConstraintToOptional<bool>(constraints,
234 MediaConstraintsInterface::kTypingNoiseDetection,
235 &options->typing_detection);
236 ConstraintToOptional<bool>(constraints,
237 MediaConstraintsInterface::kAudioMirroring,
238 &options->stereo_swapping);
deadbeeffe0fd412017-01-13 11:47:56 -0800239 ConstraintToOptional<std::string>(
240 constraints, MediaConstraintsInterface::kAudioNetworkAdaptorConfig,
241 &options->audio_network_adaptor_config);
242 // When |kAudioNetworkAdaptorConfig| is defined, it both means that audio
243 // network adaptor is desired, and provides the config string.
244 if (options->audio_network_adaptor_config) {
Oskar Sundbom0e1d7982017-11-16 10:52:42 +0100245 options->audio_network_adaptor = true;
deadbeeffe0fd412017-01-13 11:47:56 -0800246 }
htaa2a49d92016-03-04 02:51:39 -0800247}
248
Niels Möllerf06f9232018-08-07 12:32:18 +0200249bool CopyConstraintsIntoOfferAnswerOptions(
250 const MediaConstraintsInterface* constraints,
251 PeerConnectionInterface::RTCOfferAnswerOptions* offer_answer_options) {
252 if (!constraints) {
253 return true;
254 }
255
256 bool value = false;
257 size_t mandatory_constraints_satisfied = 0;
258
259 if (FindConstraint(constraints,
260 MediaConstraintsInterface::kOfferToReceiveAudio, &value,
261 &mandatory_constraints_satisfied)) {
262 offer_answer_options->offer_to_receive_audio =
263 value ? PeerConnectionInterface::RTCOfferAnswerOptions::
264 kOfferToReceiveMediaTrue
265 : 0;
266 }
267
268 if (FindConstraint(constraints,
269 MediaConstraintsInterface::kOfferToReceiveVideo, &value,
270 &mandatory_constraints_satisfied)) {
271 offer_answer_options->offer_to_receive_video =
272 value ? PeerConnectionInterface::RTCOfferAnswerOptions::
273 kOfferToReceiveMediaTrue
274 : 0;
275 }
276 if (FindConstraint(constraints,
277 MediaConstraintsInterface::kVoiceActivityDetection, &value,
278 &mandatory_constraints_satisfied)) {
279 offer_answer_options->voice_activity_detection = value;
280 }
281 if (FindConstraint(constraints, MediaConstraintsInterface::kUseRtpMux, &value,
282 &mandatory_constraints_satisfied)) {
283 offer_answer_options->use_rtp_mux = value;
284 }
285 if (FindConstraint(constraints, MediaConstraintsInterface::kIceRestart,
286 &value, &mandatory_constraints_satisfied)) {
287 offer_answer_options->ice_restart = value;
288 }
289
Jonas Orelandfc1acd22018-08-24 10:58:37 +0200290 int layers;
291 if (FindConstraint(constraints,
292 MediaConstraintsInterface::kNumSimulcastLayers,
293 &layers, &mandatory_constraints_satisfied)) {
294 offer_answer_options->num_simulcast_layers = layers;
295 }
296
Niels Möllerf06f9232018-08-07 12:32:18 +0200297 return mandatory_constraints_satisfied == constraints->GetMandatory().size();
298}
299
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000300} // namespace webrtc