Chromium Code Reviews| 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 |
| 53 } // namespace | 70 } // namespace |
| 54 | 71 |
| 55 void ApplyFixedAudioConstraints(RTCMediaConstraints* constraints) { | 72 // TODO(xians): Remove this method after the APM in WebRtc is deprecated. |
| 73 void MediaAudioConstraints::ApplyFixedAudioConstraints( | |
| 74 RTCMediaConstraints* constraints) { | |
| 56 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDefaultAudioConstraints); ++i) { | 75 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDefaultAudioConstraints); ++i) { |
| 57 bool already_set_value; | 76 bool already_set_value; |
| 58 if (!webrtc::FindConstraint(constraints, kDefaultAudioConstraints[i].key, | 77 if (!webrtc::FindConstraint(constraints, kDefaultAudioConstraints[i].key, |
| 59 &already_set_value, NULL)) { | 78 &already_set_value, NULL)) { |
| 60 constraints->AddOptional(kDefaultAudioConstraints[i].key, | 79 const std::string value = kDefaultAudioConstraints[i].value ? |
| 61 kDefaultAudioConstraints[i].value, false); | 80 webrtc::MediaConstraintsInterface::kValueTrue : |
| 81 webrtc::MediaConstraintsInterface::kValueFalse; | |
| 82 constraints->AddOptional(kDefaultAudioConstraints[i].key, value, false); | |
| 62 } else { | 83 } else { |
| 63 DVLOG(1) << "Constraint " << kDefaultAudioConstraints[i].key | 84 DVLOG(1) << "Constraint " << kDefaultAudioConstraints[i].key |
| 64 << " already set to " << already_set_value; | 85 << " already set to " << already_set_value; |
| 65 } | 86 } |
| 66 } | 87 } |
| 67 } | 88 } |
| 68 | 89 |
| 69 bool NeedsAudioProcessing(const blink::WebMediaConstraints& constraints, | 90 MediaAudioConstraints::MediaAudioConstraints( |
| 70 int effects) { | 91 const blink::WebMediaConstraints& constraints, int effects) |
| 71 RTCMediaConstraints native_constraints(constraints); | 92 : constraints_(constraints), |
| 72 ApplyFixedAudioConstraints(&native_constraints); | 93 effects_(effects), |
| 73 if (effects & media::AudioParameters::ECHO_CANCELLER) { | 94 turn_off_constraints_as_default_(false) { |
| 74 // If platform echo canceller is enabled, disable the software AEC. | 95 // The default audio processing constraints are turned off when |
| 75 native_constraints.AddOptional( | 96 // - gUM has a specific kMediaStreamSource, which is used by tab capture |
| 76 MediaConstraintsInterface::kEchoCancellation, | 97 // and screen capture. |
| 77 MediaConstraintsInterface::kValueFalse, true); | 98 // - |kEchoCancellation| is explicitly set to false. |
| 99 std::string value_str; | |
| 100 bool value_bool = false; | |
| 101 if ((GetConstraintValueAsString(constraints, kMediaStreamSource, | |
| 102 &value_str)) || | |
| 103 (GetConstraintValueAsBoolean(constraints_, kEchoCancellation, | |
| 104 &value_bool) && !value_bool)) { | |
| 105 turn_off_constraints_as_default_ = true; | |
|
tommi (sloooow) - chröme
2014/05/07 14:19:45
this applies only to the audio-processing-module,
no longer working on chromium
2014/05/07 15:45:00
how about simply default_constraint_value_?
tommi (sloooow) - chröme
2014/05/07 17:01:06
That name is technically not correct. See the fir
no longer working on chromium
2014/05/12 14:39:09
ah, right, I was trying to avoid the long name, ob
| |
| 78 } | 106 } |
| 107 } | |
| 108 | |
| 109 MediaAudioConstraints::~MediaAudioConstraints() {} | |
| 110 | |
| 111 // TODO(xians): Remove this method after the APM in WebRtc is deprecated. | |
| 112 bool MediaAudioConstraints::NeedsAudioProcessing() { | |
| 113 if (GetEchoCancellationProperty()) | |
| 114 return true; | |
| 115 | |
| 79 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDefaultAudioConstraints); ++i) { | 116 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDefaultAudioConstraints); ++i) { |
| 80 bool value = false; | 117 // |kMediaStreamAudioDucking| does not require audio processing. |
| 81 if (webrtc::FindConstraint(&native_constraints, | 118 // |kEchoCancellation| and |kGoogEchoCancellation| have been convered by |
| 82 kDefaultAudioConstraints[i].key, &value, NULL) && | 119 // GetEchoCancellationProperty(). |
| 83 value) { | 120 if (kDefaultAudioConstraints[i].key != kMediaStreamAudioDucking && |
| 121 kDefaultAudioConstraints[i].key != kEchoCancellation && | |
| 122 kDefaultAudioConstraints[i].key != kGoogEchoCancellation && | |
| 123 GetProperty(kDefaultAudioConstraints[i].key)) { | |
| 84 return true; | 124 return true; |
| 85 } | 125 } |
| 86 } | 126 } |
| 87 | 127 |
| 88 return false; | 128 return false; |
| 89 } | 129 } |
| 90 | 130 |
| 91 bool GetPropertyFromConstraints(const MediaConstraintsInterface* constraints, | 131 bool MediaAudioConstraints::GetProperty(const std::string& key) { |
| 92 const std::string& key) { | 132 // Return the value if the constraint is specified in |constraints|, |
| 133 // otherwise return the default value. | |
| 93 bool value = false; | 134 bool value = false; |
| 94 return webrtc::FindConstraint(constraints, key, &value, NULL) && value; | 135 if (!GetConstraintValueAsBoolean(constraints_, key, &value)) |
| 136 value = GetDefaultValueForConstraint(constraints_, key); | |
| 137 | |
| 138 return value; | |
| 139 } | |
| 140 | |
| 141 bool MediaAudioConstraints::GetEchoCancellationProperty() { | |
| 142 // If platform echo canceller is enabled, disable the software AEC. | |
| 143 if (effects_ & media::AudioParameters::ECHO_CANCELLER) | |
| 144 return false; | |
| 145 | |
| 146 // If |kEchoCancellation| is specified in the constraints, it will | |
| 147 // overwrite the value of |kGoogEchoCancellation|. | |
|
tommi (sloooow) - chröme
2014/05/07 14:19:45
nit: s/overwrite/override
no longer working on chromium
2014/05/07 15:45:00
Done.
| |
| 148 bool value = false; | |
| 149 if (GetConstraintValueAsBoolean(constraints_, kEchoCancellation, &value)) | |
| 150 return value; | |
| 151 | |
| 152 return GetProperty(kGoogEchoCancellation); | |
| 153 } | |
| 154 | |
| 155 bool MediaAudioConstraints::IsValid() { | |
| 156 blink::WebVector<blink::WebMediaConstraint> mandatory; | |
| 157 constraints_.getMandatoryConstraints(mandatory); | |
| 158 for (size_t i = 0; i < mandatory.size(); ++i) { | |
| 159 const std::string key = mandatory[i].m_name.utf8(); | |
| 160 if (key == kMediaStreamSource || key == kMediaStreamSourceId || | |
| 161 key == MediaStreamSource::kSourceId) { | |
| 162 // Ignore Chrome specific Tab capture and |kSourceId| constraints. | |
| 163 continue; | |
| 164 } | |
| 165 | |
| 166 bool valid = false; | |
| 167 for (size_t j = 0; j < ARRAYSIZE_UNSAFE(kDefaultAudioConstraints); ++j) { | |
| 168 if (key == kDefaultAudioConstraints[j].key) { | |
| 169 valid = true; | |
| 170 break; | |
| 171 } | |
| 172 } | |
| 173 | |
| 174 if (!valid) { | |
| 175 DLOG(ERROR) << "Invalid MediaStream constraint. Name: " << key; | |
| 176 return false; | |
| 177 } | |
| 178 } | |
| 179 | |
| 180 return true; | |
| 181 } | |
| 182 | |
|
tommi (sloooow) - chröme
2014/05/07 14:19:45
one empty line
no longer working on chromium
2014/05/07 15:45:00
Done.
| |
| 183 | |
| 184 bool MediaAudioConstraints::GetDefaultValueForConstraint( | |
| 185 const blink::WebMediaConstraints& constraints, const std::string& key) { | |
| 186 // |kMediaStreamAudioDucking| is not restricted by | |
| 187 // |turn_off_constraints_as_default_| since it does not require audio | |
| 188 // processing. | |
| 189 if (turn_off_constraints_as_default_ && key != kMediaStreamAudioDucking) | |
|
tommi (sloooow) - chröme
2014/05/07 14:19:45
I wonder if it's worth it now to factor the second
no longer working on chromium
2014/05/07 15:45:00
Done.
| |
| 190 return false; | |
| 191 | |
| 192 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDefaultAudioConstraints); ++i) { | |
| 193 if (kDefaultAudioConstraints[i].key == key) | |
| 194 return kDefaultAudioConstraints[i].value; | |
| 195 } | |
| 196 | |
| 197 return false; | |
| 95 } | 198 } |
| 96 | 199 |
| 97 void EnableEchoCancellation(AudioProcessing* audio_processing) { | 200 void EnableEchoCancellation(AudioProcessing* audio_processing) { |
| 98 #if defined(OS_ANDROID) || defined(OS_IOS) | 201 #if defined(OS_ANDROID) || defined(OS_IOS) |
| 99 const std::string group_name = | 202 const std::string group_name = |
| 100 base::FieldTrialList::FindFullName("ReplaceAECMWithAEC"); | 203 base::FieldTrialList::FindFullName("ReplaceAECMWithAEC"); |
| 101 if (group_name.empty() || (group_name != "Enabled")) { | 204 if (group_name.empty() || (group_name != "Enabled")) { |
|
tommi (sloooow) - chröme
2014/05/07 14:19:45
nit: no need for extra parenthesis
no longer working on chromium
2014/05/07 15:45:00
Done, though it is from a rebase.
| |
| 102 // Mobile devices are using AECM. | 205 // Mobile devices are using AECM. |
| 103 int err = audio_processing->echo_control_mobile()->set_routing_mode( | 206 int err = audio_processing->echo_control_mobile()->set_routing_mode( |
| 104 webrtc::EchoControlMobile::kSpeakerphone); | 207 webrtc::EchoControlMobile::kSpeakerphone); |
| 105 err |= audio_processing->echo_control_mobile()->Enable(true); | 208 err |= audio_processing->echo_control_mobile()->Enable(true); |
| 106 CHECK_EQ(err, 0); | 209 CHECK_EQ(err, 0); |
| 107 return; | 210 return; |
| 108 } | 211 } |
| 109 #endif | 212 #endif |
| 110 int err = audio_processing->echo_cancellation()->set_suppression_level( | 213 int err = audio_processing->echo_cancellation()->set_suppression_level( |
| 111 webrtc::EchoCancellation::kHighSuppression); | 214 webrtc::EchoCancellation::kHighSuppression); |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 212 } | 315 } |
| 213 | 316 |
| 214 int median = 0, std = 0; | 317 int median = 0, std = 0; |
| 215 if (!audio_processing->echo_cancellation()->GetDelayMetrics(&median, &std)) { | 318 if (!audio_processing->echo_cancellation()->GetDelayMetrics(&median, &std)) { |
| 216 stats->echo_delay_median_ms = median; | 319 stats->echo_delay_median_ms = median; |
| 217 stats->echo_delay_std_ms = std; | 320 stats->echo_delay_std_ms = std; |
| 218 } | 321 } |
| 219 } | 322 } |
| 220 | 323 |
| 221 } // namespace content | 324 } // namespace content |
| OLD | NEW |