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