Change echo detector to scoped_refptr

The echo detector is currently stored as a unique_ptr, but when injecting an echo detector, a scoped_refptr makes more sense since the ownership will be shared.

Bug: webrtc:8732
Change-Id: I2180014acb84f1cd5c361864a444b7b6574520f5
Reviewed-on: https://webrtc-review.googlesource.com/83325
Commit-Queue: Ivo Creusen <ivoc@webrtc.org>
Reviewed-by: Gustaf Ullberg <gustaf@webrtc.org>
Reviewed-by: Henrik Lundin <henrik.lundin@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#23610}
diff --git a/modules/audio_processing/audio_processing_impl.cc b/modules/audio_processing/audio_processing_impl.cc
index 6d46490..0443c11 100644
--- a/modules/audio_processing/audio_processing_impl.cc
+++ b/modules/audio_processing/audio_processing_impl.cc
@@ -285,7 +285,7 @@
   ApmPrivateSubmodules(NonlinearBeamformer* beamformer,
                        std::unique_ptr<CustomProcessing> capture_post_processor,
                        std::unique_ptr<CustomProcessing> render_pre_processor,
-                       std::unique_ptr<EchoDetector> echo_detector)
+                       rtc::scoped_refptr<EchoDetector> echo_detector)
       : beamformer(beamformer),
         echo_detector(std::move(echo_detector)),
         capture_post_processor(std::move(capture_post_processor)),
@@ -295,7 +295,7 @@
   std::unique_ptr<AgcManagerDirect> agc_manager;
   std::unique_ptr<GainController2> gain_controller2;
   std::unique_ptr<LowCutFilter> low_cut_filter;
-  std::unique_ptr<EchoDetector> echo_detector;
+  rtc::scoped_refptr<EchoDetector> echo_detector;
   std::unique_ptr<EchoControl> echo_controller;
   std::unique_ptr<CustomProcessing> capture_post_processor;
   std::unique_ptr<CustomProcessing> render_pre_processor;
@@ -330,7 +330,7 @@
 }
 
 AudioProcessingBuilder& AudioProcessingBuilder::SetEchoDetector(
-    std::unique_ptr<EchoDetector> echo_detector) {
+    rtc::scoped_refptr<EchoDetector> echo_detector) {
   echo_detector_ = std::move(echo_detector);
   return *this;
 }
@@ -363,7 +363,7 @@
     std::unique_ptr<CustomProcessing> capture_post_processor,
     std::unique_ptr<CustomProcessing> render_pre_processor,
     std::unique_ptr<EchoControlFactory> echo_control_factory,
-    std::unique_ptr<EchoDetector> echo_detector,
+    rtc::scoped_refptr<EchoDetector> echo_detector,
     NonlinearBeamformer* beamformer)
     : data_dumper_(
           new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
@@ -422,7 +422,8 @@
 
     // If no echo detector is injected, use the ResidualEchoDetector.
     if (!private_submodules_->echo_detector) {
-      private_submodules_->echo_detector.reset(new ResidualEchoDetector());
+      private_submodules_->echo_detector =
+          new rtc::RefCountedObject<ResidualEchoDetector>();
     }
 
     // TODO(alessiob): Move the injected gain controller once injection is
diff --git a/modules/audio_processing/audio_processing_impl.h b/modules/audio_processing/audio_processing_impl.h
index 44b086b..7974982 100644
--- a/modules/audio_processing/audio_processing_impl.h
+++ b/modules/audio_processing/audio_processing_impl.h
@@ -44,7 +44,7 @@
                       std::unique_ptr<CustomProcessing> capture_post_processor,
                       std::unique_ptr<CustomProcessing> render_pre_processor,
                       std::unique_ptr<EchoControlFactory> echo_control_factory,
-                      std::unique_ptr<EchoDetector> echo_detector,
+                      rtc::scoped_refptr<EchoDetector> echo_detector,
                       NonlinearBeamformer* beamformer);
   ~AudioProcessingImpl() override;
   int Initialize() override;
diff --git a/modules/audio_processing/include/audio_processing.h b/modules/audio_processing/include/audio_processing.h
index 6162199..ee419df 100644
--- a/modules/audio_processing/include/audio_processing.h
+++ b/modules/audio_processing/include/audio_processing.h
@@ -678,7 +678,7 @@
       std::unique_ptr<NonlinearBeamformer> nonlinear_beamformer);
   // The AudioProcessingBuilder takes ownership of the echo_detector.
   AudioProcessingBuilder& SetEchoDetector(
-      std::unique_ptr<EchoDetector> echo_detector);
+      rtc::scoped_refptr<EchoDetector> echo_detector);
   // This creates an APM instance using the previously set components. Calling
   // the Create function resets the AudioProcessingBuilder to its initial state.
   AudioProcessing* Create();
@@ -689,7 +689,7 @@
   std::unique_ptr<CustomProcessing> capture_post_processing_;
   std::unique_ptr<CustomProcessing> render_pre_processing_;
   std::unique_ptr<NonlinearBeamformer> nonlinear_beamformer_;
-  std::unique_ptr<EchoDetector> echo_detector_;
+  rtc::scoped_refptr<EchoDetector> echo_detector_;
   RTC_DISALLOW_COPY_AND_ASSIGN(AudioProcessingBuilder);
 };
 
@@ -1135,7 +1135,7 @@
 };
 
 // Interface for an echo detector submodule.
-class EchoDetector {
+class EchoDetector : public rtc::RefCountInterface {
  public:
   // (Re-)Initializes the submodule.
   virtual void Initialize(int capture_sample_rate_hz,
@@ -1161,8 +1161,6 @@
 
   // Collect current metrics from the echo detector.
   virtual Metrics GetMetrics() const = 0;
-
-  virtual ~EchoDetector() {}
 };
 
 // The voice activity detection (VAD) component analyzes the stream to
diff --git a/modules/audio_processing/residual_echo_detector_unittest.cc b/modules/audio_processing/residual_echo_detector_unittest.cc
index 7bfa0d2..c6fb8e4 100644
--- a/modules/audio_processing/residual_echo_detector_unittest.cc
+++ b/modules/audio_processing/residual_echo_detector_unittest.cc
@@ -11,13 +11,15 @@
 #include <vector>
 
 #include "modules/audio_processing/residual_echo_detector.h"
+#include "rtc_base/refcountedobject.h"
 #include "test/gtest.h"
 
 namespace webrtc {
 
 TEST(ResidualEchoDetectorTests, Echo) {
-  ResidualEchoDetector echo_detector;
-  echo_detector.SetReliabilityForTest(1.0f);
+  rtc::scoped_refptr<ResidualEchoDetector> echo_detector =
+      new rtc::RefCountedObject<ResidualEchoDetector>();
+  echo_detector->SetReliabilityForTest(1.0f);
   std::vector<float> ones(160, 1.f);
   std::vector<float> zeros(160, 0.f);
 
@@ -26,24 +28,25 @@
   // frame interval.
   for (int i = 0; i < 1000; i++) {
     if (i % 20 == 0) {
-      echo_detector.AnalyzeRenderAudio(ones);
-      echo_detector.AnalyzeCaptureAudio(zeros);
+      echo_detector->AnalyzeRenderAudio(ones);
+      echo_detector->AnalyzeCaptureAudio(zeros);
     } else if (i % 20 == 10) {
-      echo_detector.AnalyzeRenderAudio(zeros);
-      echo_detector.AnalyzeCaptureAudio(ones);
+      echo_detector->AnalyzeRenderAudio(zeros);
+      echo_detector->AnalyzeCaptureAudio(ones);
     } else {
-      echo_detector.AnalyzeRenderAudio(zeros);
-      echo_detector.AnalyzeCaptureAudio(zeros);
+      echo_detector->AnalyzeRenderAudio(zeros);
+      echo_detector->AnalyzeCaptureAudio(zeros);
     }
   }
   // We expect to detect echo with near certain likelihood.
-  auto ed_metrics = echo_detector.GetMetrics();
+  auto ed_metrics = echo_detector->GetMetrics();
   EXPECT_NEAR(1.f, ed_metrics.echo_likelihood, 0.01f);
 }
 
 TEST(ResidualEchoDetectorTests, NoEcho) {
-  ResidualEchoDetector echo_detector;
-  echo_detector.SetReliabilityForTest(1.0f);
+  rtc::scoped_refptr<ResidualEchoDetector> echo_detector =
+      new rtc::RefCountedObject<ResidualEchoDetector>();
+  echo_detector->SetReliabilityForTest(1.0f);
   std::vector<float> ones(160, 1.f);
   std::vector<float> zeros(160, 0.f);
 
@@ -51,20 +54,21 @@
   // detected.
   for (int i = 0; i < 1000; i++) {
     if (i % 20 == 0) {
-      echo_detector.AnalyzeRenderAudio(ones);
+      echo_detector->AnalyzeRenderAudio(ones);
     } else {
-      echo_detector.AnalyzeRenderAudio(zeros);
+      echo_detector->AnalyzeRenderAudio(zeros);
     }
-    echo_detector.AnalyzeCaptureAudio(zeros);
+    echo_detector->AnalyzeCaptureAudio(zeros);
   }
   // We expect to not detect any echo.
-  auto ed_metrics = echo_detector.GetMetrics();
+  auto ed_metrics = echo_detector->GetMetrics();
   EXPECT_NEAR(0.f, ed_metrics.echo_likelihood, 0.01f);
 }
 
 TEST(ResidualEchoDetectorTests, EchoWithRenderClockDrift) {
-  ResidualEchoDetector echo_detector;
-  echo_detector.SetReliabilityForTest(1.0f);
+  rtc::scoped_refptr<ResidualEchoDetector> echo_detector =
+      new rtc::RefCountedObject<ResidualEchoDetector>();
+  echo_detector->SetReliabilityForTest(1.0f);
   std::vector<float> ones(160, 1.f);
   std::vector<float> zeros(160, 0.f);
 
@@ -74,18 +78,18 @@
   // the render side producing data slightly faster.
   for (int i = 0; i < 1000; i++) {
     if (i % 20 == 0) {
-      echo_detector.AnalyzeRenderAudio(ones);
-      echo_detector.AnalyzeCaptureAudio(zeros);
+      echo_detector->AnalyzeRenderAudio(ones);
+      echo_detector->AnalyzeCaptureAudio(zeros);
     } else if (i % 20 == 10) {
-      echo_detector.AnalyzeRenderAudio(zeros);
-      echo_detector.AnalyzeCaptureAudio(ones);
+      echo_detector->AnalyzeRenderAudio(zeros);
+      echo_detector->AnalyzeCaptureAudio(ones);
     } else {
-      echo_detector.AnalyzeRenderAudio(zeros);
-      echo_detector.AnalyzeCaptureAudio(zeros);
+      echo_detector->AnalyzeRenderAudio(zeros);
+      echo_detector->AnalyzeCaptureAudio(zeros);
     }
     if (i % 100 == 0) {
       // This is causing the simulated clock drift.
-      echo_detector.AnalyzeRenderAudio(zeros);
+      echo_detector->AnalyzeRenderAudio(zeros);
     }
   }
   // We expect to detect echo with high likelihood. Clock drift is harder to
@@ -94,13 +98,14 @@
   // A growing buffer can be caused by jitter or clock drift and it's not
   // possible to make this decision right away. For this reason we only expect
   // an echo likelihood of 75% in this test.
-  auto ed_metrics = echo_detector.GetMetrics();
+  auto ed_metrics = echo_detector->GetMetrics();
   EXPECT_GT(ed_metrics.echo_likelihood, 0.75f);
 }
 
 TEST(ResidualEchoDetectorTests, EchoWithCaptureClockDrift) {
-  ResidualEchoDetector echo_detector;
-  echo_detector.SetReliabilityForTest(1.0f);
+  rtc::scoped_refptr<ResidualEchoDetector> echo_detector =
+      new rtc::RefCountedObject<ResidualEchoDetector>();
+  echo_detector->SetReliabilityForTest(1.0f);
   std::vector<float> ones(160, 1.f);
   std::vector<float> zeros(160, 0.f);
 
@@ -110,22 +115,22 @@
   // the capture side producing data slightly faster.
   for (int i = 0; i < 1000; i++) {
     if (i % 20 == 0) {
-      echo_detector.AnalyzeRenderAudio(ones);
-      echo_detector.AnalyzeCaptureAudio(zeros);
+      echo_detector->AnalyzeRenderAudio(ones);
+      echo_detector->AnalyzeCaptureAudio(zeros);
     } else if (i % 20 == 10) {
-      echo_detector.AnalyzeRenderAudio(zeros);
-      echo_detector.AnalyzeCaptureAudio(ones);
+      echo_detector->AnalyzeRenderAudio(zeros);
+      echo_detector->AnalyzeCaptureAudio(ones);
     } else {
-      echo_detector.AnalyzeRenderAudio(zeros);
-      echo_detector.AnalyzeCaptureAudio(zeros);
+      echo_detector->AnalyzeRenderAudio(zeros);
+      echo_detector->AnalyzeCaptureAudio(zeros);
     }
     if (i % 100 == 0) {
       // This is causing the simulated clock drift.
-      echo_detector.AnalyzeCaptureAudio(zeros);
+      echo_detector->AnalyzeCaptureAudio(zeros);
     }
   }
   // We expect to detect echo with near certain likelihood.
-  auto ed_metrics = echo_detector.GetMetrics();
+  auto ed_metrics = echo_detector->GetMetrics();
   EXPECT_NEAR(1.f, ed_metrics.echo_likelihood, 0.01f);
 }
 
diff --git a/test/fuzzers/residual_echo_detector_fuzzer.cc b/test/fuzzers/residual_echo_detector_fuzzer.cc
index c3c8123..b0405ee 100644
--- a/test/fuzzers/residual_echo_detector_fuzzer.cc
+++ b/test/fuzzers/residual_echo_detector_fuzzer.cc
@@ -17,6 +17,7 @@
 
 #include "modules/audio_processing/residual_echo_detector.h"
 #include "rtc_base/checks.h"
+#include "rtc_base/refcountedobject.h"
 
 namespace webrtc {
 
@@ -42,10 +43,11 @@
   read_idx += 2;
   std::bitset<16> call_order(call_order_int);
 
-  ResidualEchoDetector echo_detector;
+  rtc::scoped_refptr<ResidualEchoDetector> echo_detector =
+      new rtc::RefCountedObject<ResidualEchoDetector>();
   std::vector<float> input(1);
   // Call AnalyzeCaptureAudio once to prevent the flushing of the buffer.
-  echo_detector.AnalyzeCaptureAudio(input);
+  echo_detector->AnalyzeCaptureAudio(input);
   for (size_t i = 0; i < 2 * kNrOfUpdates; ++i) {
     // Convert 4 input bytes to a float.
     RTC_DCHECK_LE(read_idx + sizeof(float), size);
@@ -56,9 +58,9 @@
       continue;
     }
     if (call_order[i]) {
-      echo_detector.AnalyzeRenderAudio(input);
+      echo_detector->AnalyzeRenderAudio(input);
     } else {
-      echo_detector.AnalyzeCaptureAudio(input);
+      echo_detector->AnalyzeCaptureAudio(input);
     }
   }
 }