1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// found in the LICENSE file. 4f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "content/renderer/media/media_stream_audio_processor_options.h" 6f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 7f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/files/file_path.h" 81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/logging.h" 10010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/metrics/field_trial.h" 11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/path_service.h" 12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/strings/string_number_conversions.h" 13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/strings/utf_string_conversions.h" 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/common/media/media_stream_options.h" 15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/renderer/media/media_stream_constraints_util.h" 16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/renderer/media/media_stream_source.h" 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/renderer/media/rtc_media_constraints.h" 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "media/audio/audio_parameters.h" 19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "third_party/webrtc/modules/audio_processing/include/audio_processing.h" 20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "third_party/webrtc/modules/audio_processing/typing_detection.h" 21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace content { 23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const char MediaAudioConstraints::kEchoCancellation[] = "echoCancellation"; 25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const char MediaAudioConstraints::kGoogEchoCancellation[] = 26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) "googEchoCancellation"; 27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const char MediaAudioConstraints::kGoogExperimentalEchoCancellation[] = 28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) "googEchoCancellation2"; 29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const char MediaAudioConstraints::kGoogAutoGainControl[] = 30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) "googAutoGainControl"; 31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const char MediaAudioConstraints::kGoogExperimentalAutoGainControl[] = 32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) "googAutoGainControl2"; 33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const char MediaAudioConstraints::kGoogNoiseSuppression[] = 34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) "googNoiseSuppression"; 35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const char MediaAudioConstraints::kGoogExperimentalNoiseSuppression[] = 36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) "googNoiseSuppression2"; 37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const char MediaAudioConstraints::kGoogHighpassFilter[] = "googHighpassFilter"; 38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const char MediaAudioConstraints::kGoogTypingNoiseDetection[] = 39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) "googTypingNoiseDetection"; 40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const char MediaAudioConstraints::kGoogAudioMirroring[] = "googAudioMirroring"; 41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace { 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Constant constraint keys which enables default audio constraints on 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// mediastreams with audio. 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)struct { 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const char* key; 48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool value; 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} const kDefaultAudioConstraints[] = { 50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) { MediaAudioConstraints::kEchoCancellation, true }, 51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) { MediaAudioConstraints::kGoogEchoCancellation, true }, 52116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if defined(OS_ANDROID) || defined(OS_IOS) 53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) { MediaAudioConstraints::kGoogExperimentalEchoCancellation, false }, 54116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#else 55116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Enable the extended filter mode AEC on all non-mobile platforms. 56116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch { MediaAudioConstraints::kGoogExperimentalEchoCancellation, true }, 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif 58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) { MediaAudioConstraints::kGoogAutoGainControl, true }, 59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) { MediaAudioConstraints::kGoogExperimentalAutoGainControl, true }, 60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) { MediaAudioConstraints::kGoogNoiseSuppression, true }, 61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) { MediaAudioConstraints::kGoogHighpassFilter, true }, 62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) { MediaAudioConstraints::kGoogTypingNoiseDetection, true }, 63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) { MediaAudioConstraints::kGoogExperimentalNoiseSuppression, false }, 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_WIN) 65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) { kMediaStreamAudioDucking, true }, 66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#else 67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) { kMediaStreamAudioDucking, false }, 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool IsAudioProcessingConstraint(const std::string& key) { 72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // |kMediaStreamAudioDucking| does not require audio processing. 73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return key != kMediaStreamAudioDucking; 74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// TODO(xians): Remove this method after the APM in WebRtc is deprecated. 79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void MediaAudioConstraints::ApplyFixedAudioConstraints( 80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) RTCMediaConstraints* constraints) { 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDefaultAudioConstraints); ++i) { 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool already_set_value; 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!webrtc::FindConstraint(constraints, kDefaultAudioConstraints[i].key, 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &already_set_value, NULL)) { 85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string value = kDefaultAudioConstraints[i].value ? 86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) webrtc::MediaConstraintsInterface::kValueTrue : 87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) webrtc::MediaConstraintsInterface::kValueFalse; 88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) constraints->AddOptional(kDefaultAudioConstraints[i].key, value, false); 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Constraint " << kDefaultAudioConstraints[i].key 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << " already set to " << already_set_value; 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)MediaAudioConstraints::MediaAudioConstraints( 97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const blink::WebMediaConstraints& constraints, int effects) 98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) : constraints_(constraints), 99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) effects_(effects), 100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) default_audio_processing_constraint_value_(true) { 101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // The default audio processing constraints are turned off when 102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // - gUM has a specific kMediaStreamSource, which is used by tab capture 103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // and screen capture. 104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // - |kEchoCancellation| is explicitly set to false. 105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string value_str; 106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool value_bool = false; 107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if ((GetConstraintValueAsString(constraints, kMediaStreamSource, 108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) &value_str)) || 109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) (GetConstraintValueAsBoolean(constraints_, kEchoCancellation, 110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) &value_bool) && !value_bool)) { 111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) default_audio_processing_constraint_value_ = false; 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)MediaAudioConstraints::~MediaAudioConstraints() {} 116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// TODO(xians): Remove this method after the APM in WebRtc is deprecated. 118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool MediaAudioConstraints::NeedsAudioProcessing() { 119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (GetEchoCancellationProperty()) 120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return true; 121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDefaultAudioConstraints); ++i) { 123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // |kEchoCancellation| and |kGoogEchoCancellation| have been convered by 124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // GetEchoCancellationProperty(). 125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (kDefaultAudioConstraints[i].key != kEchoCancellation && 126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) kDefaultAudioConstraints[i].key != kGoogEchoCancellation && 127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) IsAudioProcessingConstraint(kDefaultAudioConstraints[i].key) && 128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GetProperty(kDefaultAudioConstraints[i].key)) { 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool MediaAudioConstraints::GetProperty(const std::string& key) { 137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Return the value if the constraint is specified in |constraints|, 138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // otherwise return the default value. 139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bool value = false; 140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!GetConstraintValueAsBoolean(constraints_, key, &value)) 141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) value = GetDefaultValueForConstraint(constraints_, key); 142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return value; 144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool MediaAudioConstraints::GetEchoCancellationProperty() { 147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // If platform echo canceller is enabled, disable the software AEC. 148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (effects_ & media::AudioParameters::ECHO_CANCELLER) 149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return false; 150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // If |kEchoCancellation| is specified in the constraints, it will 152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // override the value of |kGoogEchoCancellation|. 153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool value = false; 154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (GetConstraintValueAsBoolean(constraints_, kEchoCancellation, &value)) 155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return value; 156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return GetProperty(kGoogEchoCancellation); 158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool MediaAudioConstraints::IsValid() { 161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) blink::WebVector<blink::WebMediaConstraint> mandatory; 162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) constraints_.getMandatoryConstraints(mandatory); 163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (size_t i = 0; i < mandatory.size(); ++i) { 164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string key = mandatory[i].m_name.utf8(); 165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (key == kMediaStreamSource || key == kMediaStreamSourceId || 166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) key == MediaStreamSource::kSourceId) { 167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Ignore Chrome specific Tab capture and |kSourceId| constraints. 168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) continue; 169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool valid = false; 172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (size_t j = 0; j < ARRAYSIZE_UNSAFE(kDefaultAudioConstraints); ++j) { 173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (key == kDefaultAudioConstraints[j].key) { 174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool value = false; 175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) valid = GetMandatoryConstraintValueAsBoolean(constraints_, key, &value); 176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!valid) { 181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DLOG(ERROR) << "Invalid MediaStream constraint. Name: " << key; 182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return false; 183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return true; 187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool MediaAudioConstraints::GetDefaultValueForConstraint( 190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const blink::WebMediaConstraints& constraints, const std::string& key) { 191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // |kMediaStreamAudioDucking| is not restricted by 192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // |default_audio_processing_constraint_value_| since it does not require 193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // audio processing. 194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!default_audio_processing_constraint_value_ && 195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) IsAudioProcessingConstraint(key)) 196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return false; 197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDefaultAudioConstraints); ++i) { 199cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (kDefaultAudioConstraints[i].key == key) 200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return kDefaultAudioConstraints[i].value; 201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 202cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return false; 204f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 205f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 206f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void EnableEchoCancellation(AudioProcessing* audio_processing) { 207010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#if defined(OS_ANDROID) || defined(OS_IOS) 208010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const std::string group_name = 209010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base::FieldTrialList::FindFullName("ReplaceAECMWithAEC"); 210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (group_name.empty() || group_name != "Enabled") { 211010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Mobile devices are using AECM. 212010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) int err = audio_processing->echo_control_mobile()->set_routing_mode( 213010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) webrtc::EchoControlMobile::kSpeakerphone); 214010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) err |= audio_processing->echo_control_mobile()->Enable(true); 215010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) CHECK_EQ(err, 0); 216010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return; 217010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 218010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#endif 2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int err = audio_processing->echo_cancellation()->set_suppression_level( 220f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) webrtc::EchoCancellation::kHighSuppression); 221f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 222f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Enable the metrics for AEC. 223f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) err |= audio_processing->echo_cancellation()->enable_metrics(true); 224f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) err |= audio_processing->echo_cancellation()->enable_delay_logging(true); 2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) err |= audio_processing->echo_cancellation()->Enable(true); 226f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) CHECK_EQ(err, 0); 227f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 228f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 229f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void EnableNoiseSuppression(AudioProcessing* audio_processing) { 230f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int err = audio_processing->noise_suppression()->set_level( 231f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) webrtc::NoiseSuppression::kHigh); 232f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) err |= audio_processing->noise_suppression()->Enable(true); 233f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) CHECK_EQ(err, 0); 234f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 235f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 236f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void EnableHighPassFilter(AudioProcessing* audio_processing) { 237f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) CHECK_EQ(audio_processing->high_pass_filter()->Enable(true), 0); 238f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 239f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 240a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void EnableTypingDetection(AudioProcessing* audio_processing, 241a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) webrtc::TypingDetection* typing_detector) { 242f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int err = audio_processing->voice_detection()->Enable(true); 243f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) err |= audio_processing->voice_detection()->set_likelihood( 244f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) webrtc::VoiceDetection::kVeryLowLikelihood); 245f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) CHECK_EQ(err, 0); 246a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 247a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Configure the update period to 1s (100 * 10ms) in the typing detector. 248a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) typing_detector->SetParameters(0, 0, 0, 0, 0, 100); 249f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 250f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void StartEchoCancellationDump(AudioProcessing* audio_processing, 252f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::File aec_dump_file) { 253f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK(aec_dump_file.IsValid()); 254e4256316f8b5e8d1ec0df1f7762771622a53fa63Ben Murdoch 255e4256316f8b5e8d1ec0df1f7762771622a53fa63Ben Murdoch FILE* stream = base::FileToFILE(aec_dump_file.Pass(), "w"); 256e4256316f8b5e8d1ec0df1f7762771622a53fa63Ben Murdoch if (!stream) { 257e4256316f8b5e8d1ec0df1f7762771622a53fa63Ben Murdoch LOG(ERROR) << "Failed to open AEC dump file"; 258e4256316f8b5e8d1ec0df1f7762771622a53fa63Ben Murdoch return; 259ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch } 260e4256316f8b5e8d1ec0df1f7762771622a53fa63Ben Murdoch 261e4256316f8b5e8d1ec0df1f7762771622a53fa63Ben Murdoch if (audio_processing->StartDebugRecording(stream)) 262e4256316f8b5e8d1ec0df1f7762771622a53fa63Ben Murdoch DLOG(ERROR) << "Fail to start AEC debug recording"; 263f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 264f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 265a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void StopEchoCancellationDump(AudioProcessing* audio_processing) { 266f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (audio_processing->StopDebugRecording()) 267f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DLOG(ERROR) << "Fail to stop AEC debug recording"; 268f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 269f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void EnableAutomaticGainControl(AudioProcessing* audio_processing) { 2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_ANDROID) || defined(OS_IOS) 2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const webrtc::GainControl::Mode mode = webrtc::GainControl::kFixedDigital; 2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#else 2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const webrtc::GainControl::Mode mode = webrtc::GainControl::kAdaptiveAnalog; 2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif 2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int err = audio_processing->gain_control()->set_mode(mode); 2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) err |= audio_processing->gain_control()->Enable(true); 2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CHECK_EQ(err, 0); 2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 281a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GetAecStats(AudioProcessing* audio_processing, 282a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) webrtc::AudioProcessorInterface::AudioProcessorStats* stats) { 283a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // These values can take on valid negative values, so use the lowest possible 284a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // level as default rather than -1. 285a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) stats->echo_return_loss = -100; 286a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) stats->echo_return_loss_enhancement = -100; 287a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 288a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // These values can also be negative, but in practice -1 is only used to 289a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // signal insufficient data, since the resolution is limited to multiples 290a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // of 4ms. 291a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) stats->echo_delay_median_ms = -1; 292a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) stats->echo_delay_std_ms = -1; 293a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 294a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // TODO(ajm): Re-enable this metric once we have a reliable implementation. 295a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) stats->aec_quality_min = -1.0f; 296a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 297a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!audio_processing->echo_cancellation()->are_metrics_enabled() || 298a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) !audio_processing->echo_cancellation()->is_delay_logging_enabled() || 299a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) !audio_processing->echo_cancellation()->is_enabled()) { 300a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 301a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 302a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 303a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // TODO(ajm): we may want to use VoECallReport::GetEchoMetricsSummary 304a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // here, but it appears to be unsuitable currently. Revisit after this is 305a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // investigated: http://b/issue?id=5666755 306a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) webrtc::EchoCancellation::Metrics echo_metrics; 307a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!audio_processing->echo_cancellation()->GetMetrics(&echo_metrics)) { 308a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) stats->echo_return_loss = echo_metrics.echo_return_loss.instant; 309a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) stats->echo_return_loss_enhancement = 310a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) echo_metrics.echo_return_loss_enhancement.instant; 311a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 312a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 313a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int median = 0, std = 0; 314a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!audio_processing->echo_cancellation()->GetDelayMetrics(&median, &std)) { 315a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) stats->echo_delay_median_ms = median; 316a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) stats->echo_delay_std_ms = std; 317a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 318a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 319a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 320f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} // namespace content 321