1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright 2013 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker #include "sdk/media_constraints.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker #include "absl/types/optional.h"
14*d9f75844SAndroid Build Coastguard Worker #include "api/peer_connection_interface.h"
15*d9f75844SAndroid Build Coastguard Worker
16*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
17*d9f75844SAndroid Build Coastguard Worker namespace {
18*d9f75844SAndroid Build Coastguard Worker
19*d9f75844SAndroid Build Coastguard Worker // Find the highest-priority instance of the T-valued constraint named by
20*d9f75844SAndroid Build Coastguard Worker // `key` and return its value as `value`. `constraints` can be null.
21*d9f75844SAndroid Build Coastguard Worker // If `mandatory_constraints` is non-null, it is incremented if the key appears
22*d9f75844SAndroid Build Coastguard Worker // among the mandatory constraints.
23*d9f75844SAndroid Build Coastguard Worker // Returns true if the key was found and has a valid value for type T.
24*d9f75844SAndroid Build Coastguard Worker // If the key appears multiple times as an optional constraint, appearances
25*d9f75844SAndroid Build Coastguard Worker // after the first are ignored.
26*d9f75844SAndroid Build Coastguard Worker // Note: Because this uses FindFirst, repeated optional constraints whose
27*d9f75844SAndroid Build Coastguard Worker // first instance has an unrecognized value are not handled precisely in
28*d9f75844SAndroid Build Coastguard Worker // accordance with the specification.
29*d9f75844SAndroid Build Coastguard Worker template <typename T>
FindConstraint(const MediaConstraints * constraints,const std::string & key,T * value,size_t * mandatory_constraints)30*d9f75844SAndroid Build Coastguard Worker bool FindConstraint(const MediaConstraints* constraints,
31*d9f75844SAndroid Build Coastguard Worker const std::string& key,
32*d9f75844SAndroid Build Coastguard Worker T* value,
33*d9f75844SAndroid Build Coastguard Worker size_t* mandatory_constraints) {
34*d9f75844SAndroid Build Coastguard Worker std::string string_value;
35*d9f75844SAndroid Build Coastguard Worker if (!FindConstraint(constraints, key, &string_value, mandatory_constraints)) {
36*d9f75844SAndroid Build Coastguard Worker return false;
37*d9f75844SAndroid Build Coastguard Worker }
38*d9f75844SAndroid Build Coastguard Worker return rtc::FromString(string_value, value);
39*d9f75844SAndroid Build Coastguard Worker }
40*d9f75844SAndroid Build Coastguard Worker
41*d9f75844SAndroid Build Coastguard Worker // Specialization for std::string, since a string doesn't need conversion.
42*d9f75844SAndroid Build Coastguard Worker template <>
FindConstraint(const MediaConstraints * constraints,const std::string & key,std::string * value,size_t * mandatory_constraints)43*d9f75844SAndroid Build Coastguard Worker bool FindConstraint(const MediaConstraints* constraints,
44*d9f75844SAndroid Build Coastguard Worker const std::string& key,
45*d9f75844SAndroid Build Coastguard Worker std::string* value,
46*d9f75844SAndroid Build Coastguard Worker size_t* mandatory_constraints) {
47*d9f75844SAndroid Build Coastguard Worker if (!constraints) {
48*d9f75844SAndroid Build Coastguard Worker return false;
49*d9f75844SAndroid Build Coastguard Worker }
50*d9f75844SAndroid Build Coastguard Worker if (constraints->GetMandatory().FindFirst(key, value)) {
51*d9f75844SAndroid Build Coastguard Worker if (mandatory_constraints) {
52*d9f75844SAndroid Build Coastguard Worker ++*mandatory_constraints;
53*d9f75844SAndroid Build Coastguard Worker }
54*d9f75844SAndroid Build Coastguard Worker return true;
55*d9f75844SAndroid Build Coastguard Worker }
56*d9f75844SAndroid Build Coastguard Worker if (constraints->GetOptional().FindFirst(key, value)) {
57*d9f75844SAndroid Build Coastguard Worker return true;
58*d9f75844SAndroid Build Coastguard Worker }
59*d9f75844SAndroid Build Coastguard Worker return false;
60*d9f75844SAndroid Build Coastguard Worker }
61*d9f75844SAndroid Build Coastguard Worker
FindConstraint(const MediaConstraints * constraints,const std::string & key,bool * value,size_t * mandatory_constraints)62*d9f75844SAndroid Build Coastguard Worker bool FindConstraint(const MediaConstraints* constraints,
63*d9f75844SAndroid Build Coastguard Worker const std::string& key,
64*d9f75844SAndroid Build Coastguard Worker bool* value,
65*d9f75844SAndroid Build Coastguard Worker size_t* mandatory_constraints) {
66*d9f75844SAndroid Build Coastguard Worker return FindConstraint<bool>(constraints, key, value, mandatory_constraints);
67*d9f75844SAndroid Build Coastguard Worker }
68*d9f75844SAndroid Build Coastguard Worker
FindConstraint(const MediaConstraints * constraints,const std::string & key,int * value,size_t * mandatory_constraints)69*d9f75844SAndroid Build Coastguard Worker bool FindConstraint(const MediaConstraints* constraints,
70*d9f75844SAndroid Build Coastguard Worker const std::string& key,
71*d9f75844SAndroid Build Coastguard Worker int* value,
72*d9f75844SAndroid Build Coastguard Worker size_t* mandatory_constraints) {
73*d9f75844SAndroid Build Coastguard Worker return FindConstraint<int>(constraints, key, value, mandatory_constraints);
74*d9f75844SAndroid Build Coastguard Worker }
75*d9f75844SAndroid Build Coastguard Worker
76*d9f75844SAndroid Build Coastguard Worker // Converts a constraint (mandatory takes precedence over optional) to an
77*d9f75844SAndroid Build Coastguard Worker // absl::optional.
78*d9f75844SAndroid Build Coastguard Worker template <typename T>
ConstraintToOptional(const MediaConstraints * constraints,const std::string & key,absl::optional<T> * value_out)79*d9f75844SAndroid Build Coastguard Worker void ConstraintToOptional(const MediaConstraints* constraints,
80*d9f75844SAndroid Build Coastguard Worker const std::string& key,
81*d9f75844SAndroid Build Coastguard Worker absl::optional<T>* value_out) {
82*d9f75844SAndroid Build Coastguard Worker T value;
83*d9f75844SAndroid Build Coastguard Worker bool present = FindConstraint<T>(constraints, key, &value, nullptr);
84*d9f75844SAndroid Build Coastguard Worker if (present) {
85*d9f75844SAndroid Build Coastguard Worker *value_out = value;
86*d9f75844SAndroid Build Coastguard Worker }
87*d9f75844SAndroid Build Coastguard Worker }
88*d9f75844SAndroid Build Coastguard Worker } // namespace
89*d9f75844SAndroid Build Coastguard Worker
90*d9f75844SAndroid Build Coastguard Worker const char MediaConstraints::kValueTrue[] = "true";
91*d9f75844SAndroid Build Coastguard Worker const char MediaConstraints::kValueFalse[] = "false";
92*d9f75844SAndroid Build Coastguard Worker
93*d9f75844SAndroid Build Coastguard Worker // Constraints declared as static members in mediastreaminterface.h
94*d9f75844SAndroid Build Coastguard Worker
95*d9f75844SAndroid Build Coastguard Worker // Audio constraints.
96*d9f75844SAndroid Build Coastguard Worker const char MediaConstraints::kGoogEchoCancellation[] = "googEchoCancellation";
97*d9f75844SAndroid Build Coastguard Worker const char MediaConstraints::kAutoGainControl[] = "googAutoGainControl";
98*d9f75844SAndroid Build Coastguard Worker const char MediaConstraints::kNoiseSuppression[] = "googNoiseSuppression";
99*d9f75844SAndroid Build Coastguard Worker const char MediaConstraints::kHighpassFilter[] = "googHighpassFilter";
100*d9f75844SAndroid Build Coastguard Worker const char MediaConstraints::kAudioMirroring[] = "googAudioMirroring";
101*d9f75844SAndroid Build Coastguard Worker const char MediaConstraints::kAudioNetworkAdaptorConfig[] =
102*d9f75844SAndroid Build Coastguard Worker "googAudioNetworkAdaptorConfig";
103*d9f75844SAndroid Build Coastguard Worker const char MediaConstraints::kInitAudioRecordingOnSend[] =
104*d9f75844SAndroid Build Coastguard Worker "InitAudioRecordingOnSend";
105*d9f75844SAndroid Build Coastguard Worker
106*d9f75844SAndroid Build Coastguard Worker // Constraint keys for CreateOffer / CreateAnswer defined in W3C specification.
107*d9f75844SAndroid Build Coastguard Worker const char MediaConstraints::kOfferToReceiveAudio[] = "OfferToReceiveAudio";
108*d9f75844SAndroid Build Coastguard Worker const char MediaConstraints::kOfferToReceiveVideo[] = "OfferToReceiveVideo";
109*d9f75844SAndroid Build Coastguard Worker const char MediaConstraints::kVoiceActivityDetection[] =
110*d9f75844SAndroid Build Coastguard Worker "VoiceActivityDetection";
111*d9f75844SAndroid Build Coastguard Worker const char MediaConstraints::kIceRestart[] = "IceRestart";
112*d9f75844SAndroid Build Coastguard Worker // Google specific constraint for BUNDLE enable/disable.
113*d9f75844SAndroid Build Coastguard Worker const char MediaConstraints::kUseRtpMux[] = "googUseRtpMUX";
114*d9f75844SAndroid Build Coastguard Worker
115*d9f75844SAndroid Build Coastguard Worker // Below constraints should be used during PeerConnection construction.
116*d9f75844SAndroid Build Coastguard Worker // Google-specific constraint keys.
117*d9f75844SAndroid Build Coastguard Worker const char MediaConstraints::kEnableDscp[] = "googDscp";
118*d9f75844SAndroid Build Coastguard Worker const char MediaConstraints::kEnableVideoSuspendBelowMinBitrate[] =
119*d9f75844SAndroid Build Coastguard Worker "googSuspendBelowMinBitrate";
120*d9f75844SAndroid Build Coastguard Worker const char MediaConstraints::kCombinedAudioVideoBwe[] =
121*d9f75844SAndroid Build Coastguard Worker "googCombinedAudioVideoBwe";
122*d9f75844SAndroid Build Coastguard Worker const char MediaConstraints::kScreencastMinBitrate[] =
123*d9f75844SAndroid Build Coastguard Worker "googScreencastMinBitrate";
124*d9f75844SAndroid Build Coastguard Worker // TODO(ronghuawu): Remove once cpu overuse detection is stable.
125*d9f75844SAndroid Build Coastguard Worker const char MediaConstraints::kCpuOveruseDetection[] = "googCpuOveruseDetection";
126*d9f75844SAndroid Build Coastguard Worker
127*d9f75844SAndroid Build Coastguard Worker const char MediaConstraints::kRawPacketizationForVideoEnabled[] =
128*d9f75844SAndroid Build Coastguard Worker "googRawPacketizationForVideoEnabled";
129*d9f75844SAndroid Build Coastguard Worker
130*d9f75844SAndroid Build Coastguard Worker const char MediaConstraints::kNumSimulcastLayers[] = "googNumSimulcastLayers";
131*d9f75844SAndroid Build Coastguard Worker
132*d9f75844SAndroid Build Coastguard Worker // Set `value` to the value associated with the first appearance of `key`, or
133*d9f75844SAndroid Build Coastguard Worker // return false if `key` is not found.
FindFirst(const std::string & key,std::string * value) const134*d9f75844SAndroid Build Coastguard Worker bool MediaConstraints::Constraints::FindFirst(const std::string& key,
135*d9f75844SAndroid Build Coastguard Worker std::string* value) const {
136*d9f75844SAndroid Build Coastguard Worker for (Constraints::const_iterator iter = begin(); iter != end(); ++iter) {
137*d9f75844SAndroid Build Coastguard Worker if (iter->key == key) {
138*d9f75844SAndroid Build Coastguard Worker *value = iter->value;
139*d9f75844SAndroid Build Coastguard Worker return true;
140*d9f75844SAndroid Build Coastguard Worker }
141*d9f75844SAndroid Build Coastguard Worker }
142*d9f75844SAndroid Build Coastguard Worker return false;
143*d9f75844SAndroid Build Coastguard Worker }
144*d9f75844SAndroid Build Coastguard Worker
CopyConstraintsIntoRtcConfiguration(const MediaConstraints * constraints,PeerConnectionInterface::RTCConfiguration * configuration)145*d9f75844SAndroid Build Coastguard Worker void CopyConstraintsIntoRtcConfiguration(
146*d9f75844SAndroid Build Coastguard Worker const MediaConstraints* constraints,
147*d9f75844SAndroid Build Coastguard Worker PeerConnectionInterface::RTCConfiguration* configuration) {
148*d9f75844SAndroid Build Coastguard Worker // Copy info from constraints into configuration, if present.
149*d9f75844SAndroid Build Coastguard Worker if (!constraints) {
150*d9f75844SAndroid Build Coastguard Worker return;
151*d9f75844SAndroid Build Coastguard Worker }
152*d9f75844SAndroid Build Coastguard Worker
153*d9f75844SAndroid Build Coastguard Worker FindConstraint(constraints, MediaConstraints::kEnableDscp,
154*d9f75844SAndroid Build Coastguard Worker &configuration->media_config.enable_dscp, nullptr);
155*d9f75844SAndroid Build Coastguard Worker FindConstraint(constraints, MediaConstraints::kCpuOveruseDetection,
156*d9f75844SAndroid Build Coastguard Worker &configuration->media_config.video.enable_cpu_adaptation,
157*d9f75844SAndroid Build Coastguard Worker nullptr);
158*d9f75844SAndroid Build Coastguard Worker // Find Suspend Below Min Bitrate constraint.
159*d9f75844SAndroid Build Coastguard Worker FindConstraint(
160*d9f75844SAndroid Build Coastguard Worker constraints, MediaConstraints::kEnableVideoSuspendBelowMinBitrate,
161*d9f75844SAndroid Build Coastguard Worker &configuration->media_config.video.suspend_below_min_bitrate, nullptr);
162*d9f75844SAndroid Build Coastguard Worker ConstraintToOptional<int>(constraints,
163*d9f75844SAndroid Build Coastguard Worker MediaConstraints::kScreencastMinBitrate,
164*d9f75844SAndroid Build Coastguard Worker &configuration->screencast_min_bitrate);
165*d9f75844SAndroid Build Coastguard Worker ConstraintToOptional<bool>(constraints,
166*d9f75844SAndroid Build Coastguard Worker MediaConstraints::kCombinedAudioVideoBwe,
167*d9f75844SAndroid Build Coastguard Worker &configuration->combined_audio_video_bwe);
168*d9f75844SAndroid Build Coastguard Worker }
169*d9f75844SAndroid Build Coastguard Worker
CopyConstraintsIntoAudioOptions(const MediaConstraints * constraints,cricket::AudioOptions * options)170*d9f75844SAndroid Build Coastguard Worker void CopyConstraintsIntoAudioOptions(const MediaConstraints* constraints,
171*d9f75844SAndroid Build Coastguard Worker cricket::AudioOptions* options) {
172*d9f75844SAndroid Build Coastguard Worker if (!constraints) {
173*d9f75844SAndroid Build Coastguard Worker return;
174*d9f75844SAndroid Build Coastguard Worker }
175*d9f75844SAndroid Build Coastguard Worker
176*d9f75844SAndroid Build Coastguard Worker ConstraintToOptional<bool>(constraints,
177*d9f75844SAndroid Build Coastguard Worker MediaConstraints::kGoogEchoCancellation,
178*d9f75844SAndroid Build Coastguard Worker &options->echo_cancellation);
179*d9f75844SAndroid Build Coastguard Worker ConstraintToOptional<bool>(constraints, MediaConstraints::kAutoGainControl,
180*d9f75844SAndroid Build Coastguard Worker &options->auto_gain_control);
181*d9f75844SAndroid Build Coastguard Worker ConstraintToOptional<bool>(constraints, MediaConstraints::kNoiseSuppression,
182*d9f75844SAndroid Build Coastguard Worker &options->noise_suppression);
183*d9f75844SAndroid Build Coastguard Worker ConstraintToOptional<bool>(constraints, MediaConstraints::kHighpassFilter,
184*d9f75844SAndroid Build Coastguard Worker &options->highpass_filter);
185*d9f75844SAndroid Build Coastguard Worker ConstraintToOptional<bool>(constraints, MediaConstraints::kAudioMirroring,
186*d9f75844SAndroid Build Coastguard Worker &options->stereo_swapping);
187*d9f75844SAndroid Build Coastguard Worker ConstraintToOptional<std::string>(
188*d9f75844SAndroid Build Coastguard Worker constraints, MediaConstraints::kAudioNetworkAdaptorConfig,
189*d9f75844SAndroid Build Coastguard Worker &options->audio_network_adaptor_config);
190*d9f75844SAndroid Build Coastguard Worker // When `kAudioNetworkAdaptorConfig` is defined, it both means that audio
191*d9f75844SAndroid Build Coastguard Worker // network adaptor is desired, and provides the config string.
192*d9f75844SAndroid Build Coastguard Worker if (options->audio_network_adaptor_config) {
193*d9f75844SAndroid Build Coastguard Worker options->audio_network_adaptor = true;
194*d9f75844SAndroid Build Coastguard Worker }
195*d9f75844SAndroid Build Coastguard Worker ConstraintToOptional<bool>(constraints,
196*d9f75844SAndroid Build Coastguard Worker MediaConstraints::kInitAudioRecordingOnSend,
197*d9f75844SAndroid Build Coastguard Worker &options->init_recording_on_send);
198*d9f75844SAndroid Build Coastguard Worker }
199*d9f75844SAndroid Build Coastguard Worker
CopyConstraintsIntoOfferAnswerOptions(const MediaConstraints * constraints,PeerConnectionInterface::RTCOfferAnswerOptions * offer_answer_options)200*d9f75844SAndroid Build Coastguard Worker bool CopyConstraintsIntoOfferAnswerOptions(
201*d9f75844SAndroid Build Coastguard Worker const MediaConstraints* constraints,
202*d9f75844SAndroid Build Coastguard Worker PeerConnectionInterface::RTCOfferAnswerOptions* offer_answer_options) {
203*d9f75844SAndroid Build Coastguard Worker if (!constraints) {
204*d9f75844SAndroid Build Coastguard Worker return true;
205*d9f75844SAndroid Build Coastguard Worker }
206*d9f75844SAndroid Build Coastguard Worker
207*d9f75844SAndroid Build Coastguard Worker bool value = false;
208*d9f75844SAndroid Build Coastguard Worker size_t mandatory_constraints_satisfied = 0;
209*d9f75844SAndroid Build Coastguard Worker
210*d9f75844SAndroid Build Coastguard Worker if (FindConstraint(constraints, MediaConstraints::kOfferToReceiveAudio,
211*d9f75844SAndroid Build Coastguard Worker &value, &mandatory_constraints_satisfied)) {
212*d9f75844SAndroid Build Coastguard Worker offer_answer_options->offer_to_receive_audio =
213*d9f75844SAndroid Build Coastguard Worker value ? PeerConnectionInterface::RTCOfferAnswerOptions::
214*d9f75844SAndroid Build Coastguard Worker kOfferToReceiveMediaTrue
215*d9f75844SAndroid Build Coastguard Worker : 0;
216*d9f75844SAndroid Build Coastguard Worker }
217*d9f75844SAndroid Build Coastguard Worker
218*d9f75844SAndroid Build Coastguard Worker if (FindConstraint(constraints, MediaConstraints::kOfferToReceiveVideo,
219*d9f75844SAndroid Build Coastguard Worker &value, &mandatory_constraints_satisfied)) {
220*d9f75844SAndroid Build Coastguard Worker offer_answer_options->offer_to_receive_video =
221*d9f75844SAndroid Build Coastguard Worker value ? PeerConnectionInterface::RTCOfferAnswerOptions::
222*d9f75844SAndroid Build Coastguard Worker kOfferToReceiveMediaTrue
223*d9f75844SAndroid Build Coastguard Worker : 0;
224*d9f75844SAndroid Build Coastguard Worker }
225*d9f75844SAndroid Build Coastguard Worker if (FindConstraint(constraints, MediaConstraints::kVoiceActivityDetection,
226*d9f75844SAndroid Build Coastguard Worker &value, &mandatory_constraints_satisfied)) {
227*d9f75844SAndroid Build Coastguard Worker offer_answer_options->voice_activity_detection = value;
228*d9f75844SAndroid Build Coastguard Worker }
229*d9f75844SAndroid Build Coastguard Worker if (FindConstraint(constraints, MediaConstraints::kUseRtpMux, &value,
230*d9f75844SAndroid Build Coastguard Worker &mandatory_constraints_satisfied)) {
231*d9f75844SAndroid Build Coastguard Worker offer_answer_options->use_rtp_mux = value;
232*d9f75844SAndroid Build Coastguard Worker }
233*d9f75844SAndroid Build Coastguard Worker if (FindConstraint(constraints, MediaConstraints::kIceRestart, &value,
234*d9f75844SAndroid Build Coastguard Worker &mandatory_constraints_satisfied)) {
235*d9f75844SAndroid Build Coastguard Worker offer_answer_options->ice_restart = value;
236*d9f75844SAndroid Build Coastguard Worker }
237*d9f75844SAndroid Build Coastguard Worker
238*d9f75844SAndroid Build Coastguard Worker if (FindConstraint(constraints,
239*d9f75844SAndroid Build Coastguard Worker MediaConstraints::kRawPacketizationForVideoEnabled, &value,
240*d9f75844SAndroid Build Coastguard Worker &mandatory_constraints_satisfied)) {
241*d9f75844SAndroid Build Coastguard Worker offer_answer_options->raw_packetization_for_video = value;
242*d9f75844SAndroid Build Coastguard Worker }
243*d9f75844SAndroid Build Coastguard Worker
244*d9f75844SAndroid Build Coastguard Worker int layers;
245*d9f75844SAndroid Build Coastguard Worker if (FindConstraint(constraints, MediaConstraints::kNumSimulcastLayers,
246*d9f75844SAndroid Build Coastguard Worker &layers, &mandatory_constraints_satisfied)) {
247*d9f75844SAndroid Build Coastguard Worker offer_answer_options->num_simulcast_layers = layers;
248*d9f75844SAndroid Build Coastguard Worker }
249*d9f75844SAndroid Build Coastguard Worker
250*d9f75844SAndroid Build Coastguard Worker return mandatory_constraints_satisfied == constraints->GetMandatory().size();
251*d9f75844SAndroid Build Coastguard Worker }
252*d9f75844SAndroid Build Coastguard Worker
253*d9f75844SAndroid Build Coastguard Worker } // namespace webrtc
254