OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/renderer/media/media_stream_audio_processor_options.h" | 5 #include "content/renderer/media/media_stream_audio_processor_options.h" |
6 | 6 |
7 #include "base/files/file_path.h" | 7 #include "base/files/file_path.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/metrics/field_trial.h" | 9 #include "base/metrics/field_trial.h" |
10 #include "base/path_service.h" | 10 #include "base/path_service.h" |
| 11 #include "base/strings/string_number_conversions.h" |
11 #include "base/strings/utf_string_conversions.h" | 12 #include "base/strings/utf_string_conversions.h" |
12 #include "content/common/media/media_stream_options.h" | 13 #include "content/common/media/media_stream_options.h" |
| 14 #include "content/renderer/media/media_stream_constraints_util.h" |
| 15 #include "content/renderer/media/media_stream_source.h" |
13 #include "content/renderer/media/rtc_media_constraints.h" | 16 #include "content/renderer/media/rtc_media_constraints.h" |
14 #include "media/audio/audio_parameters.h" | 17 #include "media/audio/audio_parameters.h" |
15 #include "third_party/WebKit/public/platform/WebMediaConstraints.h" | |
16 #include "third_party/libjingle/source/talk/app/webrtc/mediaconstraintsinterface
.h" | |
17 #include "third_party/webrtc/modules/audio_processing/include/audio_processing.h
" | 18 #include "third_party/webrtc/modules/audio_processing/include/audio_processing.h
" |
18 #include "third_party/webrtc/modules/audio_processing/typing_detection.h" | 19 #include "third_party/webrtc/modules/audio_processing/typing_detection.h" |
19 | 20 |
20 namespace content { | 21 namespace content { |
21 | 22 |
| 23 const char MediaAudioConstraints::kEchoCancellation[] = "echoCancellation"; |
| 24 const char MediaAudioConstraints::kGoogEchoCancellation[] = |
| 25 "googEchoCancellation"; |
| 26 const char MediaAudioConstraints::kGoogExperimentalEchoCancellation[] = |
| 27 "googEchoCancellation2"; |
| 28 const char MediaAudioConstraints::kGoogAutoGainControl[] = |
| 29 "googAutoGainControl"; |
| 30 const char MediaAudioConstraints::kGoogExperimentalAutoGainControl[] = |
| 31 "googAutoGainControl2"; |
| 32 const char MediaAudioConstraints::kGoogNoiseSuppression[] = |
| 33 "googNoiseSuppression"; |
| 34 const char MediaAudioConstraints::kGoogExperimentalNoiseSuppression[] = |
| 35 "googNoiseSuppression2"; |
| 36 const char MediaAudioConstraints::kGoogHighpassFilter[] = "googHighpassFilter"; |
| 37 const char MediaAudioConstraints::kGoogTypingNoiseDetection[] = |
| 38 "googTypingNoiseDetection"; |
| 39 const char MediaAudioConstraints::kGoogAudioMirroring[] = "googAudioMirroring"; |
| 40 |
22 namespace { | 41 namespace { |
23 | 42 |
24 // Constant constraint keys which enables default audio constraints on | 43 // Constant constraint keys which enables default audio constraints on |
25 // mediastreams with audio. | 44 // mediastreams with audio. |
26 struct { | 45 struct { |
27 const char* key; | 46 const char* key; |
28 const char* value; | 47 bool value; |
29 } const kDefaultAudioConstraints[] = { | 48 } const kDefaultAudioConstraints[] = { |
30 { webrtc::MediaConstraintsInterface::kEchoCancellation, | 49 { MediaAudioConstraints::kEchoCancellation, true }, |
31 webrtc::MediaConstraintsInterface::kValueTrue }, | 50 { MediaAudioConstraints::kGoogEchoCancellation, true }, |
32 #if defined(OS_CHROMEOS) || defined(OS_MACOSX) | 51 #if defined(OS_CHROMEOS) || defined(OS_MACOSX) |
33 // Enable the extended filter mode AEC on platforms with known echo issues. | 52 // Enable the extended filter mode AEC on platforms with known echo issues. |
34 { webrtc::MediaConstraintsInterface::kExperimentalEchoCancellation, | 53 { MediaAudioConstraints::kGoogExperimentalEchoCancellation, true }, |
35 webrtc::MediaConstraintsInterface::kValueTrue }, | 54 #else |
| 55 { MediaAudioConstraints::kGoogExperimentalEchoCancellation, false }, |
36 #endif | 56 #endif |
37 { webrtc::MediaConstraintsInterface::kAutoGainControl, | 57 { MediaAudioConstraints::kGoogAutoGainControl, true }, |
38 webrtc::MediaConstraintsInterface::kValueTrue }, | 58 { MediaAudioConstraints::kGoogExperimentalAutoGainControl, true }, |
39 { webrtc::MediaConstraintsInterface::kExperimentalAutoGainControl, | 59 { MediaAudioConstraints::kGoogNoiseSuppression, true }, |
40 webrtc::MediaConstraintsInterface::kValueTrue }, | 60 { MediaAudioConstraints::kGoogHighpassFilter, true }, |
41 { webrtc::MediaConstraintsInterface::kNoiseSuppression, | 61 { MediaAudioConstraints::kGoogTypingNoiseDetection, true }, |
42 webrtc::MediaConstraintsInterface::kValueTrue }, | 62 { MediaAudioConstraints::kGoogExperimentalNoiseSuppression, false }, |
43 { webrtc::MediaConstraintsInterface::kHighpassFilter, | |
44 webrtc::MediaConstraintsInterface::kValueTrue }, | |
45 { webrtc::MediaConstraintsInterface::kTypingNoiseDetection, | |
46 webrtc::MediaConstraintsInterface::kValueTrue }, | |
47 #if defined(OS_WIN) | 63 #if defined(OS_WIN) |
48 { content::kMediaStreamAudioDucking, | 64 { kMediaStreamAudioDucking, true }, |
49 webrtc::MediaConstraintsInterface::kValueTrue }, | 65 #else |
| 66 { kMediaStreamAudioDucking, false }, |
50 #endif | 67 #endif |
51 }; | 68 }; |
52 | 69 |
| 70 bool IsAudioProcessingConstraint(const std::string& key) { |
| 71 // |kMediaStreamAudioDucking| does not require audio processing. |
| 72 return key != kMediaStreamAudioDucking; |
| 73 } |
| 74 |
53 } // namespace | 75 } // namespace |
54 | 76 |
55 void ApplyFixedAudioConstraints(RTCMediaConstraints* constraints) { | 77 // TODO(xians): Remove this method after the APM in WebRtc is deprecated. |
| 78 void MediaAudioConstraints::ApplyFixedAudioConstraints( |
| 79 RTCMediaConstraints* constraints) { |
56 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDefaultAudioConstraints); ++i) { | 80 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDefaultAudioConstraints); ++i) { |
57 bool already_set_value; | 81 bool already_set_value; |
58 if (!webrtc::FindConstraint(constraints, kDefaultAudioConstraints[i].key, | 82 if (!webrtc::FindConstraint(constraints, kDefaultAudioConstraints[i].key, |
59 &already_set_value, NULL)) { | 83 &already_set_value, NULL)) { |
60 constraints->AddOptional(kDefaultAudioConstraints[i].key, | 84 const std::string value = kDefaultAudioConstraints[i].value ? |
61 kDefaultAudioConstraints[i].value, false); | 85 webrtc::MediaConstraintsInterface::kValueTrue : |
| 86 webrtc::MediaConstraintsInterface::kValueFalse; |
| 87 constraints->AddOptional(kDefaultAudioConstraints[i].key, value, false); |
62 } else { | 88 } else { |
63 DVLOG(1) << "Constraint " << kDefaultAudioConstraints[i].key | 89 DVLOG(1) << "Constraint " << kDefaultAudioConstraints[i].key |
64 << " already set to " << already_set_value; | 90 << " already set to " << already_set_value; |
65 } | 91 } |
66 } | 92 } |
67 } | 93 } |
68 | 94 |
69 bool NeedsAudioProcessing(const blink::WebMediaConstraints& constraints, | 95 MediaAudioConstraints::MediaAudioConstraints( |
70 int effects) { | 96 const blink::WebMediaConstraints& constraints, int effects) |
71 RTCMediaConstraints native_constraints(constraints); | 97 : constraints_(constraints), |
72 ApplyFixedAudioConstraints(&native_constraints); | 98 effects_(effects), |
73 if (effects & media::AudioParameters::ECHO_CANCELLER) { | 99 default_audio_processing_constraint_value_(true) { |
74 // If platform echo canceller is enabled, disable the software AEC. | 100 // The default audio processing constraints are turned off when |
75 native_constraints.AddOptional( | 101 // - gUM has a specific kMediaStreamSource, which is used by tab capture |
76 MediaConstraintsInterface::kEchoCancellation, | 102 // and screen capture. |
77 MediaConstraintsInterface::kValueFalse, true); | 103 // - |kEchoCancellation| is explicitly set to false. |
| 104 std::string value_str; |
| 105 bool value_bool = false; |
| 106 if ((GetConstraintValueAsString(constraints, kMediaStreamSource, |
| 107 &value_str)) || |
| 108 (GetConstraintValueAsBoolean(constraints_, kEchoCancellation, |
| 109 &value_bool) && !value_bool)) { |
| 110 default_audio_processing_constraint_value_ = false; |
78 } | 111 } |
| 112 } |
| 113 |
| 114 MediaAudioConstraints::~MediaAudioConstraints() {} |
| 115 |
| 116 // TODO(xians): Remove this method after the APM in WebRtc is deprecated. |
| 117 bool MediaAudioConstraints::NeedsAudioProcessing() { |
| 118 if (GetEchoCancellationProperty()) |
| 119 return true; |
| 120 |
79 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDefaultAudioConstraints); ++i) { | 121 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDefaultAudioConstraints); ++i) { |
80 bool value = false; | 122 // |kEchoCancellation| and |kGoogEchoCancellation| have been convered by |
81 if (webrtc::FindConstraint(&native_constraints, | 123 // GetEchoCancellationProperty(). |
82 kDefaultAudioConstraints[i].key, &value, NULL) && | 124 if (kDefaultAudioConstraints[i].key != kEchoCancellation && |
83 value) { | 125 kDefaultAudioConstraints[i].key != kGoogEchoCancellation && |
| 126 IsAudioProcessingConstraint(kDefaultAudioConstraints[i].key) && |
| 127 GetProperty(kDefaultAudioConstraints[i].key)) { |
84 return true; | 128 return true; |
85 } | 129 } |
86 } | 130 } |
87 | 131 |
88 return false; | 132 return false; |
89 } | 133 } |
90 | 134 |
91 bool GetPropertyFromConstraints(const MediaConstraintsInterface* constraints, | 135 bool MediaAudioConstraints::GetProperty(const std::string& key) { |
92 const std::string& key) { | 136 // Return the value if the constraint is specified in |constraints|, |
| 137 // otherwise return the default value. |
93 bool value = false; | 138 bool value = false; |
94 return webrtc::FindConstraint(constraints, key, &value, NULL) && value; | 139 if (!GetConstraintValueAsBoolean(constraints_, key, &value)) |
| 140 value = GetDefaultValueForConstraint(constraints_, key); |
| 141 |
| 142 return value; |
| 143 } |
| 144 |
| 145 bool MediaAudioConstraints::GetEchoCancellationProperty() { |
| 146 // If platform echo canceller is enabled, disable the software AEC. |
| 147 if (effects_ & media::AudioParameters::ECHO_CANCELLER) |
| 148 return false; |
| 149 |
| 150 // If |kEchoCancellation| is specified in the constraints, it will |
| 151 // override the value of |kGoogEchoCancellation|. |
| 152 bool value = false; |
| 153 if (GetConstraintValueAsBoolean(constraints_, kEchoCancellation, &value)) |
| 154 return value; |
| 155 |
| 156 return GetProperty(kGoogEchoCancellation); |
| 157 } |
| 158 |
| 159 bool MediaAudioConstraints::IsValid() { |
| 160 blink::WebVector<blink::WebMediaConstraint> mandatory; |
| 161 constraints_.getMandatoryConstraints(mandatory); |
| 162 for (size_t i = 0; i < mandatory.size(); ++i) { |
| 163 const std::string key = mandatory[i].m_name.utf8(); |
| 164 if (key == kMediaStreamSource || key == kMediaStreamSourceId || |
| 165 key == MediaStreamSource::kSourceId) { |
| 166 // Ignore Chrome specific Tab capture and |kSourceId| constraints. |
| 167 continue; |
| 168 } |
| 169 |
| 170 bool valid = false; |
| 171 for (size_t j = 0; j < ARRAYSIZE_UNSAFE(kDefaultAudioConstraints); ++j) { |
| 172 if (key == kDefaultAudioConstraints[j].key) { |
| 173 bool value = false; |
| 174 valid = GetMandatoryConstraintValueAsBoolean(constraints_, key, &value); |
| 175 break; |
| 176 } |
| 177 } |
| 178 |
| 179 if (!valid) { |
| 180 DLOG(ERROR) << "Invalid MediaStream constraint. Name: " << key; |
| 181 return false; |
| 182 } |
| 183 } |
| 184 |
| 185 return true; |
| 186 } |
| 187 |
| 188 bool MediaAudioConstraints::GetDefaultValueForConstraint( |
| 189 const blink::WebMediaConstraints& constraints, const std::string& key) { |
| 190 // |kMediaStreamAudioDucking| is not restricted by |
| 191 // |default_audio_processing_constraint_value_| since it does not require |
| 192 // audio processing. |
| 193 if (!default_audio_processing_constraint_value_ && |
| 194 IsAudioProcessingConstraint(key)) |
| 195 return false; |
| 196 |
| 197 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDefaultAudioConstraints); ++i) { |
| 198 if (kDefaultAudioConstraints[i].key == key) |
| 199 return kDefaultAudioConstraints[i].value; |
| 200 } |
| 201 |
| 202 return false; |
95 } | 203 } |
96 | 204 |
97 void EnableEchoCancellation(AudioProcessing* audio_processing) { | 205 void EnableEchoCancellation(AudioProcessing* audio_processing) { |
98 #if defined(OS_ANDROID) || defined(OS_IOS) | 206 #if defined(OS_ANDROID) || defined(OS_IOS) |
99 const std::string group_name = | 207 const std::string group_name = |
100 base::FieldTrialList::FindFullName("ReplaceAECMWithAEC"); | 208 base::FieldTrialList::FindFullName("ReplaceAECMWithAEC"); |
101 if (group_name.empty() || (group_name != "Enabled")) { | 209 if (group_name.empty() || group_name != "Enabled") { |
102 // Mobile devices are using AECM. | 210 // Mobile devices are using AECM. |
103 int err = audio_processing->echo_control_mobile()->set_routing_mode( | 211 int err = audio_processing->echo_control_mobile()->set_routing_mode( |
104 webrtc::EchoControlMobile::kSpeakerphone); | 212 webrtc::EchoControlMobile::kSpeakerphone); |
105 err |= audio_processing->echo_control_mobile()->Enable(true); | 213 err |= audio_processing->echo_control_mobile()->Enable(true); |
106 CHECK_EQ(err, 0); | 214 CHECK_EQ(err, 0); |
107 return; | 215 return; |
108 } | 216 } |
109 #endif | 217 #endif |
110 int err = audio_processing->echo_cancellation()->set_suppression_level( | 218 int err = audio_processing->echo_cancellation()->set_suppression_level( |
111 webrtc::EchoCancellation::kHighSuppression); | 219 webrtc::EchoCancellation::kHighSuppression); |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
212 } | 320 } |
213 | 321 |
214 int median = 0, std = 0; | 322 int median = 0, std = 0; |
215 if (!audio_processing->echo_cancellation()->GetDelayMetrics(&median, &std)) { | 323 if (!audio_processing->echo_cancellation()->GetDelayMetrics(&median, &std)) { |
216 stats->echo_delay_median_ms = median; | 324 stats->echo_delay_median_ms = median; |
217 stats->echo_delay_std_ms = std; | 325 stats->echo_delay_std_ms = std; |
218 } | 326 } |
219 } | 327 } |
220 | 328 |
221 } // namespace content | 329 } // namespace content |
OLD | NEW |