EchoControl factory injectable in AudioProcessing.

This CL enables a factory method creating acoustic echo cancellers
that inherit EchoControl to be injected into the audio processing
module. AudioProcessing will call the factory method to create an
instance of the EchoControl subclass when needed. In the event of
sample rate changes, AudioProcessing will recreate the object using
the factory method.

Bug: webrtc:8346
Change-Id: I0c508b4d4cdb35569864cefaa0e3aea2555cc9b9
Reviewed-on: https://webrtc-review.googlesource.com/7742
Commit-Queue: Gustaf Ullberg <gustaf@webrtc.org>
Reviewed-by: Per Ã…hgren <peah@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20251}
diff --git a/modules/audio_processing/BUILD.gn b/modules/audio_processing/BUILD.gn
index dd2ded6..027e1ed 100644
--- a/modules/audio_processing/BUILD.gn
+++ b/modules/audio_processing/BUILD.gn
@@ -242,6 +242,7 @@
     "../../audio/utility:audio_frame_operations",
     "../../rtc_base:gtest_prod",
     "../../rtc_base:protobuf_utils",
+    "../../rtc_base:rtc_base",
     "../audio_coding:isac",
   ]
   public_deps = [
diff --git a/modules/audio_processing/audio_processing_impl.cc b/modules/audio_processing/audio_processing_impl.cc
index 68a24d2..c101066 100644
--- a/modules/audio_processing/audio_processing_impl.cc
+++ b/modules/audio_processing/audio_processing_impl.cc
@@ -309,24 +309,35 @@
 
 AudioProcessing* AudioProcessing::Create() {
   webrtc::Config config;
-  return Create(config, nullptr, nullptr);
+  return Create(config, nullptr, rtc::Callback1<EchoControl*, int>(), nullptr);
 }
 
 AudioProcessing* AudioProcessing::Create(const webrtc::Config& config) {
-  return Create(config, nullptr, nullptr);
+  return Create(config, nullptr, rtc::Callback1<EchoControl*, int>(), nullptr);
 }
 
 AudioProcessing* AudioProcessing::Create(const webrtc::Config& config,
                                          NonlinearBeamformer* beamformer) {
-  return Create(config, nullptr, beamformer);
+  return Create(config, nullptr, rtc::Callback1<EchoControl*, int>(),
+                beamformer);
 }
 
 AudioProcessing* AudioProcessing::Create(
     const webrtc::Config& config,
     std::unique_ptr<PostProcessing> capture_post_processor,
     NonlinearBeamformer* beamformer) {
+  return Create(config, std::move(capture_post_processor),
+                rtc::Callback1<EchoControl*, int>(), beamformer);
+}
+
+AudioProcessing* AudioProcessing::Create(
+    const webrtc::Config& config,
+    std::unique_ptr<PostProcessing> capture_post_processor,
+    rtc::Callback1<EchoControl*, int> echo_control_factory,
+    NonlinearBeamformer* beamformer) {
   AudioProcessingImpl* apm = new rtc::RefCountedObject<AudioProcessingImpl>(
-      config, std::move(capture_post_processor), beamformer);
+      config, std::move(capture_post_processor), echo_control_factory,
+      beamformer);
   if (apm->Initialize() != kNoError) {
     delete apm;
     apm = nullptr;
@@ -336,13 +347,18 @@
 }
 
 AudioProcessingImpl::AudioProcessingImpl(const webrtc::Config& config)
-    : AudioProcessingImpl(config, nullptr, nullptr) {}
+    : AudioProcessingImpl(config,
+                          nullptr,
+                          rtc::Callback1<EchoControl*, int>(),
+                          nullptr) {}
 
 AudioProcessingImpl::AudioProcessingImpl(
     const webrtc::Config& config,
     std::unique_ptr<PostProcessing> capture_post_processor,
+    rtc::Callback1<EchoControl*, int> echo_control_factory,
     NonlinearBeamformer* beamformer)
     : high_pass_filter_impl_(new HighPassFilterImpl(this)),
+      echo_control_factory_(echo_control_factory),
       submodule_states_(!!capture_post_processor),
       public_submodules_(new ApmPublicSubmodules()),
       private_submodules_(
@@ -679,6 +695,7 @@
   LOG(LS_INFO) << "Highpass filter activated: "
                << config_.high_pass_filter.enabled;
 
+  // TODO(gustaf): Do this outside of APM.
   config_ok = EchoCanceller3::Validate(config_.echo_canceller3);
   if (!config_ok) {
     LOG(LS_ERROR) << "AudioProcessing module config error" << std::endl
@@ -689,6 +706,7 @@
     config_.echo_canceller3 = AudioProcessing::Config::EchoCanceller3();
   }
 
+  // TODO(gustaf): Enable EchoCanceller3 by injection, not configuration.
   if (config.echo_canceller3.enabled !=
       capture_nonlocked_.echo_canceller3_enabled) {
     capture_nonlocked_.echo_canceller3_enabled =
@@ -1697,7 +1715,11 @@
 }
 
 void AudioProcessingImpl::InitializeEchoCanceller3() {
-  if (capture_nonlocked_.echo_canceller3_enabled) {
+  if (!echo_control_factory_.empty()) {
+    private_submodules_->echo_controller.reset(
+        echo_control_factory_(proc_sample_rate_hz()));
+  } else if (capture_nonlocked_.echo_canceller3_enabled) {
+    // TODO(gustaf): Remove once injection is used.
     private_submodules_->echo_controller.reset(new EchoCanceller3(
         config_.echo_canceller3, proc_sample_rate_hz(), true));
   } else {
diff --git a/modules/audio_processing/audio_processing_impl.h b/modules/audio_processing/audio_processing_impl.h
index 1e5695c..a5e16cb 100644
--- a/modules/audio_processing/audio_processing_impl.h
+++ b/modules/audio_processing/audio_processing_impl.h
@@ -43,6 +43,7 @@
   // beamformer.
   AudioProcessingImpl(const webrtc::Config& config,
                       std::unique_ptr<PostProcessing> capture_post_processor,
+                      rtc::Callback1<EchoControl*, int> echo_control_factory,
                       NonlinearBeamformer* beamformer);
   ~AudioProcessingImpl() override;
   int Initialize() override;
@@ -141,6 +142,9 @@
   // Submodule interface implementations.
   std::unique_ptr<HighPassFilter> high_pass_filter_impl_;
 
+  // EchoControl factory method.
+  rtc::Callback1<EchoControl*, int> echo_control_factory_;
+
   class ApmSubmoduleStates {
    public:
     explicit ApmSubmoduleStates(bool capture_post_processor_enabled);
diff --git a/modules/audio_processing/audio_processing_unittest.cc b/modules/audio_processing/audio_processing_unittest.cc
index 854d6a5..4540a6a 100644
--- a/modules/audio_processing/audio_processing_unittest.cc
+++ b/modules/audio_processing/audio_processing_unittest.cc
@@ -1316,8 +1316,8 @@
   config.Set<Beamforming>(new Beamforming(true, geometry));
   testing::NiceMock<MockNonlinearBeamformer>* beamformer =
       new testing::NiceMock<MockNonlinearBeamformer>(geometry, 1u);
-  std::unique_ptr<AudioProcessing> apm(
-      AudioProcessing::Create(config, nullptr, beamformer));
+  std::unique_ptr<AudioProcessing> apm(AudioProcessing::Create(
+      config, nullptr, rtc::Callback1<EchoControl*, int>(), beamformer));
   EXPECT_EQ(kNoErr, apm->gain_control()->Enable(true));
   ChannelBuffer<float> src_buf(kSamplesPerChannel, kNumInputChannels);
   ChannelBuffer<float> dest_buf(kSamplesPerChannel, kNumOutputChannels);
@@ -2915,15 +2915,16 @@
       new testing::NiceMock<test::MockPostProcessing>();
   auto mock_post_processor =
       std::unique_ptr<PostProcessing>(mock_post_processor_ptr);
-  rtc::scoped_refptr<AudioProcessing> apm = AudioProcessing::Create(
-      webrtc_config, std::move(mock_post_processor), nullptr);
+  rtc::scoped_refptr<AudioProcessing> apm =
+      AudioProcessing::Create(webrtc_config, std::move(mock_post_processor),
+                              rtc::Callback1<EchoControl*, int>(), nullptr);
 
   AudioFrame audio;
   audio.num_channels_ = 1;
   SetFrameSampleRate(&audio, AudioProcessing::NativeRate::kSampleRate16kHz);
 
   EXPECT_CALL(*mock_post_processor_ptr, Process(testing::_)).Times(1);
-  std::cout << apm->ProcessStream(&audio) << std::endl;
+  apm->ProcessStream(&audio);
 }
 
 }  // namespace webrtc
diff --git a/modules/audio_processing/include/audio_processing.h b/modules/audio_processing/include/audio_processing.h
index 54aed34..2cbea50 100644
--- a/modules/audio_processing/include/audio_processing.h
+++ b/modules/audio_processing/include/audio_processing.h
@@ -23,6 +23,7 @@
 #include "modules/audio_processing/beamformer/array_util.h"
 #include "modules/audio_processing/include/config.h"
 #include "rtc_base/arraysize.h"
+#include "rtc_base/callback.h"
 #include "rtc_base/deprecation.h"
 #include "rtc_base/platform_file.h"
 #include "rtc_base/refcount.h"
@@ -43,6 +44,7 @@
 
 class EchoCancellation;
 class EchoControlMobile;
+class EchoControl;
 class GainControl;
 class HighPassFilter;
 class LevelEstimator;
@@ -376,10 +378,15 @@
   RTC_DEPRECATED
   static AudioProcessing* Create(const webrtc::Config& config,
                                  NonlinearBeamformer* beamformer);
+  static AudioProcessing* Create(
+      const webrtc::Config& config,
+      std::unique_ptr<PostProcessing> capture_post_processor,
+      NonlinearBeamformer* beamformer);
   // Allows passing in optional user-defined processing modules.
   static AudioProcessing* Create(
       const webrtc::Config& config,
       std::unique_ptr<PostProcessing> capture_post_processor,
+      rtc::Callback1<EchoControl*, int> echo_control_factory,
       NonlinearBeamformer* beamformer);
   ~AudioProcessing() override {}