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/path_service.h" | 9 #include "base/path_service.h" |
| 10 #include "base/strings/string_number_conversions.h" | |
| 10 #include "base/strings/utf_string_conversions.h" | 11 #include "base/strings/utf_string_conversions.h" |
| 11 #include "content/common/media/media_stream_options.h" | 12 #include "content/common/media/media_stream_options.h" |
| 13 #include "content/renderer/media/media_stream_constraints_util.h" | |
| 12 #include "content/renderer/media/rtc_media_constraints.h" | 14 #include "content/renderer/media/rtc_media_constraints.h" |
| 13 #include "media/audio/audio_parameters.h" | 15 #include "media/audio/audio_parameters.h" |
| 14 #include "third_party/WebKit/public/platform/WebMediaConstraints.h" | |
| 15 #include "third_party/libjingle/source/talk/app/webrtc/mediaconstraintsinterface .h" | |
| 16 #include "third_party/webrtc/modules/audio_processing/include/audio_processing.h " | 16 #include "third_party/webrtc/modules/audio_processing/include/audio_processing.h " |
| 17 #include "third_party/webrtc/modules/audio_processing/typing_detection.h" | 17 #include "third_party/webrtc/modules/audio_processing/typing_detection.h" |
| 18 | 18 |
| 19 namespace content { | 19 namespace content { |
| 20 | 20 |
| 21 const char MediaAudioConstraints::kEchoCancellation[] = "echoCancellation"; | |
| 22 const char MediaAudioConstraints::kGoogEchoCancellation[] = | |
| 23 "googEchoCancellation"; | |
| 24 const char MediaAudioConstraints::kGoogExperimentalEchoCancellation[] = | |
| 25 "googEchoCancellation2"; | |
| 26 const char MediaAudioConstraints::kGoogAutoGainControl[] = | |
| 27 "googAutoGainControl"; | |
| 28 const char MediaAudioConstraints::kGoogExperimentalAutoGainControl[] = | |
| 29 "googAutoGainControl2"; | |
| 30 const char MediaAudioConstraints::kGoogNoiseSuppression[] = | |
| 31 "googNoiseSuppression"; | |
| 32 const char MediaAudioConstraints::kGoogExperimentalNoiseSuppression[] = | |
| 33 "googNoiseSuppression2"; | |
| 34 const char MediaAudioConstraints::kGoogHighpassFilter[] = "googHighpassFilter"; | |
| 35 const char MediaAudioConstraints::kGoogTypingNoiseDetection[] = | |
| 36 "googTypingNoiseDetection"; | |
| 37 const char MediaAudioConstraints::kGoogAudioMirroring[] = "googAudioMirroring"; | |
| 38 | |
| 21 namespace { | 39 namespace { |
| 22 | 40 |
| 41 // Constraints keys for http://dev.w3.org/2011/webrtc/editor/getusermedia.html. | |
| 42 const char kSourceId[] = "sourceId"; | |
|
tommi (sloooow) - chröme
2014/05/03 10:26:28
Isn't this also defined elsewhere?
https://code.go
no longer working on chromium
2014/05/05 12:55:57
Discussed with Per and decided to move to media_st
tommi (sloooow) - chröme
2014/05/07 14:19:45
Makes sense. Thanks.
| |
| 43 | |
| 23 // Constant constraint keys which enables default audio constraints on | 44 // Constant constraint keys which enables default audio constraints on |
| 24 // mediastreams with audio. | 45 // mediastreams with audio. |
| 25 struct { | 46 struct { |
| 26 const char* key; | 47 const char* key; |
| 27 const char* value; | 48 bool value; |
| 28 } const kDefaultAudioConstraints[] = { | 49 } const kDefaultAudioConstraints[] = { |
| 29 { webrtc::MediaConstraintsInterface::kEchoCancellation, | 50 { MediaAudioConstraints::kEchoCancellation, true }, |
| 30 webrtc::MediaConstraintsInterface::kValueTrue }, | 51 { MediaAudioConstraints::kGoogEchoCancellation, true }, |
| 31 #if defined(OS_CHROMEOS) || defined(OS_MACOSX) | 52 #if defined(OS_CHROMEOS) || defined(OS_MACOSX) |
| 32 // Enable the extended filter mode AEC on platforms with known echo issues. | 53 // Enable the extended filter mode AEC on platforms with known echo issues. |
| 33 { webrtc::MediaConstraintsInterface::kExperimentalEchoCancellation, | 54 { MediaAudioConstraints::kGoogExperimentalEchoCancellation, true }, |
| 34 webrtc::MediaConstraintsInterface::kValueTrue }, | 55 #else |
| 56 { MediaAudioConstraints::kGoogExperimentalEchoCancellation, false }, | |
| 35 #endif | 57 #endif |
| 36 { webrtc::MediaConstraintsInterface::kAutoGainControl, | 58 { MediaAudioConstraints::kGoogAutoGainControl, true }, |
| 37 webrtc::MediaConstraintsInterface::kValueTrue }, | 59 { MediaAudioConstraints::kGoogExperimentalAutoGainControl, true }, |
| 38 { webrtc::MediaConstraintsInterface::kExperimentalAutoGainControl, | 60 { MediaAudioConstraints::kGoogNoiseSuppression, true }, |
| 39 webrtc::MediaConstraintsInterface::kValueTrue }, | 61 { MediaAudioConstraints::kGoogHighpassFilter, true }, |
| 40 { webrtc::MediaConstraintsInterface::kNoiseSuppression, | 62 { MediaAudioConstraints::kGoogTypingNoiseDetection, true }, |
| 41 webrtc::MediaConstraintsInterface::kValueTrue }, | 63 { MediaAudioConstraints::kGoogExperimentalNoiseSuppression, false }, |
| 42 { webrtc::MediaConstraintsInterface::kHighpassFilter, | |
| 43 webrtc::MediaConstraintsInterface::kValueTrue }, | |
| 44 { webrtc::MediaConstraintsInterface::kTypingNoiseDetection, | |
| 45 webrtc::MediaConstraintsInterface::kValueTrue }, | |
| 46 #if defined(OS_WIN) | 64 #if defined(OS_WIN) |
| 47 { content::kMediaStreamAudioDucking, | 65 { kMediaStreamAudioDucking, true }, |
| 48 webrtc::MediaConstraintsInterface::kValueTrue }, | 66 #else |
| 67 { kMediaStreamAudioDucking, false }, | |
| 49 #endif | 68 #endif |
| 50 }; | 69 }; |
| 51 | 70 |
| 71 bool GetDefaultValueForConstraint(const blink::WebMediaConstraints& constraints, | |
| 72 const std::string& key) { | |
| 73 // Audio constraints are false by default for gUM with a specific | |
| 74 // kMediaStreamSource, which is used by tab capture and screen capture. | |
| 75 std::string value; | |
| 76 if (GetConstraintValueAsString(constraints, kMediaStreamSource, &value)) | |
| 77 return false; | |
| 78 | |
| 79 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDefaultAudioConstraints); ++i) { | |
| 80 if (kDefaultAudioConstraints[i].key == key) | |
| 81 return kDefaultAudioConstraints[i].value; | |
| 82 } | |
| 83 | |
| 84 return false; | |
| 85 } | |
| 86 | |
| 52 } // namespace | 87 } // namespace |
| 53 | 88 |
| 54 void ApplyFixedAudioConstraints(RTCMediaConstraints* constraints) { | 89 // TODO(xians): Remove this method after the APM in WebRtc is deprecated. |
| 90 void MediaAudioConstraints::ApplyFixedAudioConstraints( | |
| 91 RTCMediaConstraints* constraints) { | |
| 55 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDefaultAudioConstraints); ++i) { | 92 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDefaultAudioConstraints); ++i) { |
| 56 bool already_set_value; | 93 bool already_set_value; |
| 57 if (!webrtc::FindConstraint(constraints, kDefaultAudioConstraints[i].key, | 94 if (!webrtc::FindConstraint(constraints, kDefaultAudioConstraints[i].key, |
| 58 &already_set_value, NULL)) { | 95 &already_set_value, NULL)) { |
| 59 constraints->AddOptional(kDefaultAudioConstraints[i].key, | 96 const std::string value = kDefaultAudioConstraints[i].value ? |
| 60 kDefaultAudioConstraints[i].value, false); | 97 webrtc::MediaConstraintsInterface::kValueTrue : |
| 98 webrtc::MediaConstraintsInterface::kValueFalse; | |
| 99 constraints->AddOptional(kDefaultAudioConstraints[i].key, value, false); | |
| 61 } else { | 100 } else { |
| 62 DVLOG(1) << "Constraint " << kDefaultAudioConstraints[i].key | 101 DVLOG(1) << "Constraint " << kDefaultAudioConstraints[i].key |
| 63 << " already set to " << already_set_value; | 102 << " already set to " << already_set_value; |
| 64 } | 103 } |
| 65 } | 104 } |
| 66 } | 105 } |
| 67 | 106 |
| 68 bool NeedsAudioProcessing(const blink::WebMediaConstraints& constraints, | 107 MediaAudioConstraints::MediaAudioConstraints( |
| 69 int effects) { | 108 const blink::WebMediaConstraints& constraints, int effects) |
| 70 RTCMediaConstraints native_constraints(constraints); | 109 : constraints_(constraints), effects_(effects) {} |
| 71 ApplyFixedAudioConstraints(&native_constraints); | 110 |
| 72 if (effects & media::AudioParameters::ECHO_CANCELLER) { | 111 MediaAudioConstraints::~MediaAudioConstraints() {} |
| 73 // If platform echo canceller is enabled, disable the software AEC. | 112 |
| 74 native_constraints.AddOptional( | 113 // TODO(xians): Remove this method after the APM in WebRtc is deprecated. |
| 75 MediaConstraintsInterface::kEchoCancellation, | 114 bool MediaAudioConstraints::NeedsAudioProcessing() { |
| 76 MediaConstraintsInterface::kValueFalse, true); | |
| 77 } | |
| 78 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDefaultAudioConstraints); ++i) { | 115 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDefaultAudioConstraints); ++i) { |
| 79 bool value = false; | 116 if (kDefaultAudioConstraints[i].key == kEchoCancellation) { |
| 80 if (webrtc::FindConstraint(&native_constraints, | 117 // Turn off the audio processing if |kEchoCancellation| is explicitly |
| 81 kDefaultAudioConstraints[i].key, &value, NULL) && | 118 // set the false. |
| 82 value) { | 119 if (!GetEchoCancellationProperty(kEchoCancellation)) |
| 83 return true; | 120 return false; |
| 121 } else if (kDefaultAudioConstraints[i].key == kGoogEchoCancellation) { | |
| 122 if (GetEchoCancellationProperty(kGoogEchoCancellation)) | |
| 123 return true; | |
| 124 } else { | |
| 125 // |kMediaStreamAudioDucking| does not require audio processing. | |
| 126 if (kDefaultAudioConstraints[i].key != kMediaStreamAudioDucking && | |
| 127 GetProperty(kDefaultAudioConstraints[i].key)) { | |
| 128 return true; | |
| 129 } | |
| 84 } | 130 } |
| 85 } | 131 } |
| 86 | 132 |
| 87 return false; | 133 return false; |
| 88 } | 134 } |
| 89 | 135 |
| 90 bool GetPropertyFromConstraints(const MediaConstraintsInterface* constraints, | 136 bool MediaAudioConstraints::GetProperty(const std::string& key) { |
| 91 const std::string& key) { | 137 // Return the value if the constraint is specified in |constraints|, |
| 138 // otherwise return the default value. | |
| 92 bool value = false; | 139 bool value = false; |
| 93 return webrtc::FindConstraint(constraints, key, &value, NULL) && value; | 140 if (!GetConstraintValueAsBoolean(constraints_, key, &value)) |
| 141 value = GetDefaultValueForConstraint(constraints_, key); | |
| 142 | |
| 143 return value; | |
| 144 } | |
| 145 | |
| 146 bool MediaAudioConstraints::GetEchoCancellationProperty( | |
| 147 const std::string& key) { | |
| 148 DCHECK(key == kEchoCancellation || key == kGoogEchoCancellation); | |
| 149 | |
| 150 if (key == kEchoCancellation) | |
| 151 return GetProperty(key); | |
| 152 | |
| 153 // If platform echo canceller is enabled, disable the software AEC. | |
| 154 if (effects_ & media::AudioParameters::ECHO_CANCELLER) | |
| 155 return false; | |
| 156 | |
| 157 // If |kEchoCancellation| is specified in the constraints, it will | |
| 158 // overwrite the value of |kGoogEchoCancellation|. | |
| 159 bool value = false; | |
| 160 if (GetConstraintValueAsBoolean(constraints_, kEchoCancellation, &value)) | |
| 161 return value; | |
| 162 | |
| 163 return GetProperty(key); | |
| 164 } | |
| 165 | |
| 166 bool MediaAudioConstraints::IsValid() { | |
| 167 blink::WebVector<blink::WebMediaConstraint> mandatory; | |
| 168 constraints_.getMandatoryConstraints(mandatory); | |
| 169 for (size_t i = 0; i < mandatory.size(); ++i) { | |
| 170 const std::string key = mandatory[i].m_name.utf8(); | |
| 171 if (key == kMediaStreamSource || key == kMediaStreamSourceId || | |
| 172 key == kSourceId) { | |
| 173 // Ignore Chrome specific Tab capture and |kSourceId| constraints. | |
| 174 continue; | |
| 175 } | |
| 176 | |
| 177 bool valid = false; | |
| 178 for (size_t j = 0; j < ARRAYSIZE_UNSAFE(kDefaultAudioConstraints); ++j) { | |
| 179 if (key == kDefaultAudioConstraints[j].key) { | |
| 180 valid = true; | |
| 181 break; | |
| 182 } | |
| 183 } | |
| 184 | |
| 185 if (!valid) { | |
| 186 DLOG(ERROR) << "Invalid MediaStream constraint. Name: " << key; | |
| 187 return false; | |
| 188 } | |
| 189 } | |
| 190 | |
| 191 return true; | |
| 94 } | 192 } |
| 95 | 193 |
| 96 void EnableEchoCancellation(AudioProcessing* audio_processing) { | 194 void EnableEchoCancellation(AudioProcessing* audio_processing) { |
| 97 #if defined(OS_ANDROID) | 195 #if defined(OS_ANDROID) |
| 98 // Mobile devices are using AECM. | 196 // Mobile devices are using AECM. |
| 99 int err = audio_processing->echo_control_mobile()->set_routing_mode( | 197 int err = audio_processing->echo_control_mobile()->set_routing_mode( |
| 100 webrtc::EchoControlMobile::kSpeakerphone); | 198 webrtc::EchoControlMobile::kSpeakerphone); |
| 101 err |= audio_processing->echo_control_mobile()->Enable(true); | 199 err |= audio_processing->echo_control_mobile()->Enable(true); |
| 102 CHECK_EQ(err, 0); | 200 CHECK_EQ(err, 0); |
| 103 #else | 201 #else |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 207 } | 305 } |
| 208 | 306 |
| 209 int median = 0, std = 0; | 307 int median = 0, std = 0; |
| 210 if (!audio_processing->echo_cancellation()->GetDelayMetrics(&median, &std)) { | 308 if (!audio_processing->echo_cancellation()->GetDelayMetrics(&median, &std)) { |
| 211 stats->echo_delay_median_ms = median; | 309 stats->echo_delay_median_ms = median; |
| 212 stats->echo_delay_std_ms = std; | 310 stats->echo_delay_std_ms = std; |
| 213 } | 311 } |
| 214 } | 312 } |
| 215 | 313 |
| 216 } // namespace content | 314 } // namespace content |
| OLD | NEW |