Removed the dependency in GainControlImpl on the ProcessingComponent class

BUG=webrtc:5353

Review URL: https://codereview.webrtc.org/1768943002

Cr-Commit-Position: refs/heads/master@{#11949}
diff --git a/webrtc/modules/audio_processing/gain_control_impl.cc b/webrtc/modules/audio_processing/gain_control_impl.cc
index 04a6c7b..936a286 100644
--- a/webrtc/modules/audio_processing/gain_control_impl.cc
+++ b/webrtc/modules/audio_processing/gain_control_impl.cc
@@ -10,8 +10,7 @@
 
 #include "webrtc/modules/audio_processing/gain_control_impl.h"
 
-#include <assert.h>
-
+#include "webrtc/base/optional.h"
 #include "webrtc/modules/audio_processing/audio_buffer.h"
 #include "webrtc/modules/audio_processing/agc/legacy/gain_control.h"
 
@@ -29,7 +28,7 @@
     case GainControl::kFixedDigital:
       return kAgcModeFixedDigital;
   }
-  assert(false);
+  RTC_DCHECK(false);
   return -1;
 }
 
@@ -42,11 +41,59 @@
 
 }  // namespace
 
+class GainControlImpl::GainController {
+ public:
+  explicit GainController() {
+    state_ = WebRtcAgc_Create();
+    RTC_CHECK(state_);
+  }
+
+  ~GainController() {
+    RTC_DCHECK(state_);
+    WebRtcAgc_Free(state_);
+  }
+
+  Handle* state() {
+    RTC_DCHECK(state_);
+    return state_;
+  }
+
+  void Initialize(int minimum_capture_level,
+                  int maximum_capture_level,
+                  Mode mode,
+                  int sample_rate_hz,
+                  int capture_level) {
+    RTC_DCHECK(state_);
+    int error =
+        WebRtcAgc_Init(state_, minimum_capture_level, maximum_capture_level,
+                       MapSetting(mode), sample_rate_hz);
+    RTC_DCHECK_EQ(0, error);
+
+    set_capture_level(capture_level);
+  }
+
+  void set_capture_level(int capture_level) {
+    capture_level_ = rtc::Optional<int>(capture_level);
+  }
+
+  int get_capture_level() {
+    RTC_DCHECK(capture_level_);
+    return *capture_level_;
+  }
+
+ private:
+  Handle* state_;
+  // TODO(peah): Remove the optional once the initialization is moved into the
+  // ctor.
+  rtc::Optional<int> capture_level_;
+
+  RTC_DISALLOW_COPY_AND_ASSIGN(GainController);
+};
+
 GainControlImpl::GainControlImpl(const AudioProcessing* apm,
                                  rtc::CriticalSection* crit_render,
                                  rtc::CriticalSection* crit_capture)
-    : ProcessingComponent(),
-      apm_(apm),
+    : apm_(apm),
       crit_render_(crit_render),
       crit_capture_(crit_capture),
       mode_(kAdaptiveAnalog),
@@ -68,20 +115,20 @@
 
 int GainControlImpl::ProcessRenderAudio(AudioBuffer* audio) {
   rtc::CritScope cs(crit_render_);
-  if (!is_component_enabled()) {
+  if (!enabled_) {
     return AudioProcessing::kNoError;
   }
 
-  assert(audio->num_frames_per_band() <= 160);
+  RTC_DCHECK_GE(160u, audio->num_frames_per_band());
 
   render_queue_buffer_.resize(0);
-  for (size_t i = 0; i < num_handles(); i++) {
-    Handle* my_handle = static_cast<Handle*>(handle(i));
-    int err =
-        WebRtcAgc_GetAddFarendError(my_handle, audio->num_frames_per_band());
+  for (auto& gain_controller : gain_controllers_) {
+    int err = WebRtcAgc_GetAddFarendError(gain_controller->state(),
+                                          audio->num_frames_per_band());
 
-    if (err != AudioProcessing::kNoError)
-      return GetHandleError(my_handle);
+    if (err != AudioProcessing::kNoError) {
+      return AudioProcessing::kUnspecifiedError;
+    }
 
     // Buffer the samples in the render queue.
     render_queue_buffer_.insert(
@@ -106,17 +153,17 @@
 void GainControlImpl::ReadQueuedRenderData() {
   rtc::CritScope cs(crit_capture_);
 
-  if (!is_component_enabled()) {
+  if (!enabled_) {
     return;
   }
 
   while (render_signal_queue_->Remove(&capture_queue_buffer_)) {
     size_t buffer_index = 0;
     const size_t num_frames_per_band =
-        capture_queue_buffer_.size() / num_handles();
-    for (size_t i = 0; i < num_handles(); i++) {
-      Handle* my_handle = static_cast<Handle*>(handle(i));
-      WebRtcAgc_AddFarend(my_handle, &capture_queue_buffer_[buffer_index],
+        capture_queue_buffer_.size() / num_handles_required();
+    for (auto& gain_controller : gain_controllers_) {
+      WebRtcAgc_AddFarend(gain_controller->state(),
+                          &capture_queue_buffer_[buffer_index],
                           num_frames_per_band);
 
       buffer_index += num_frames_per_band;
@@ -127,49 +174,42 @@
 int GainControlImpl::AnalyzeCaptureAudio(AudioBuffer* audio) {
   rtc::CritScope cs(crit_capture_);
 
-  if (!is_component_enabled()) {
+  if (!enabled_) {
     return AudioProcessing::kNoError;
   }
 
-  assert(audio->num_frames_per_band() <= 160);
-  assert(audio->num_channels() == num_handles());
-
-  int err = AudioProcessing::kNoError;
+  RTC_DCHECK_GE(160u, audio->num_frames_per_band());
+  RTC_DCHECK_EQ(audio->num_channels(), num_handles_required());
+  RTC_DCHECK_LE(num_handles_required(), gain_controllers_.size());
 
   if (mode_ == kAdaptiveAnalog) {
-    capture_levels_.assign(num_handles(), analog_capture_level_);
-    for (size_t i = 0; i < num_handles(); i++) {
-      Handle* my_handle = static_cast<Handle*>(handle(i));
-      err = WebRtcAgc_AddMic(
-          my_handle,
-          audio->split_bands(i),
-          audio->num_bands(),
-          audio->num_frames_per_band());
+    int capture_channel = 0;
+    for (auto& gain_controller : gain_controllers_) {
+      gain_controller->set_capture_level(analog_capture_level_);
+      int err = WebRtcAgc_AddMic(
+          gain_controller->state(), audio->split_bands(capture_channel),
+          audio->num_bands(), audio->num_frames_per_band());
 
       if (err != AudioProcessing::kNoError) {
-        return GetHandleError(my_handle);
+        return AudioProcessing::kUnspecifiedError;
       }
+      ++capture_channel;
     }
   } else if (mode_ == kAdaptiveDigital) {
-
-    for (size_t i = 0; i < num_handles(); i++) {
-      Handle* my_handle = static_cast<Handle*>(handle(i));
+    int capture_channel = 0;
+    for (auto& gain_controller : gain_controllers_) {
       int32_t capture_level_out = 0;
+      int err = WebRtcAgc_VirtualMic(
+          gain_controller->state(), audio->split_bands(capture_channel),
+          audio->num_bands(), audio->num_frames_per_band(),
+          analog_capture_level_, &capture_level_out);
 
-      err = WebRtcAgc_VirtualMic(
-          my_handle,
-          audio->split_bands(i),
-          audio->num_bands(),
-          audio->num_frames_per_band(),
-          analog_capture_level_,
-          &capture_level_out);
-
-      capture_levels_[i] = capture_level_out;
+      gain_controller->set_capture_level(capture_level_out);
 
       if (err != AudioProcessing::kNoError) {
-        return GetHandleError(my_handle);
+        return AudioProcessing::kUnspecifiedError;
       }
-
+      ++capture_channel;
     }
   }
 
@@ -179,7 +219,7 @@
 int GainControlImpl::ProcessCaptureAudio(AudioBuffer* audio) {
   rtc::CritScope cs(crit_capture_);
 
-  if (!is_component_enabled()) {
+  if (!enabled_) {
     return AudioProcessing::kNoError;
   }
 
@@ -187,46 +227,44 @@
     return AudioProcessing::kStreamParameterNotSetError;
   }
 
-  assert(audio->num_frames_per_band() <= 160);
-  assert(audio->num_channels() == num_handles());
+  RTC_DCHECK_GE(160u, audio->num_frames_per_band());
+  RTC_DCHECK_EQ(audio->num_channels(), num_handles_required());
 
   stream_is_saturated_ = false;
-  for (size_t i = 0; i < num_handles(); i++) {
-    Handle* my_handle = static_cast<Handle*>(handle(i));
+  int capture_channel = 0;
+  for (auto& gain_controller : gain_controllers_) {
     int32_t capture_level_out = 0;
     uint8_t saturation_warning = 0;
 
     // The call to stream_has_echo() is ok from a deadlock perspective
     // as the capture lock is allready held.
     int err = WebRtcAgc_Process(
-        my_handle,
-        audio->split_bands_const(i),
-        audio->num_bands(),
-        audio->num_frames_per_band(),
-        audio->split_bands(i),
-        capture_levels_[i],
-        &capture_level_out,
-        apm_->echo_cancellation()->stream_has_echo(),
-        &saturation_warning);
+        gain_controller->state(), audio->split_bands_const(capture_channel),
+        audio->num_bands(), audio->num_frames_per_band(),
+        audio->split_bands(capture_channel),
+        gain_controller->get_capture_level(), &capture_level_out,
+        apm_->echo_cancellation()->stream_has_echo(), &saturation_warning);
 
     if (err != AudioProcessing::kNoError) {
-      return GetHandleError(my_handle);
+      return AudioProcessing::kUnspecifiedError;
     }
 
-    capture_levels_[i] = capture_level_out;
+    gain_controller->set_capture_level(capture_level_out);
     if (saturation_warning == 1) {
       stream_is_saturated_ = true;
     }
+
+    ++capture_channel;
   }
 
   if (mode_ == kAdaptiveAnalog) {
     // Take the analog level to be the average across the handles.
     analog_capture_level_ = 0;
-    for (size_t i = 0; i < num_handles(); i++) {
-      analog_capture_level_ += capture_levels_[i];
+    for (auto& gain_controller : gain_controllers_) {
+      analog_capture_level_ += gain_controller->get_capture_level();
     }
 
-    analog_capture_level_ /= num_handles();
+    analog_capture_level_ /= num_handles_required();
   }
 
   was_analog_level_set_ = false;
@@ -257,12 +295,18 @@
 int GainControlImpl::Enable(bool enable) {
   rtc::CritScope cs_render(crit_render_);
   rtc::CritScope cs_capture(crit_capture_);
-  return EnableComponent(enable);
+  if (enable && !enabled_) {
+    enabled_ = enable;  // Must be set before Initialize() is called.
+    Initialize();
+  } else {
+    enabled_ = enable;
+  }
+  return AudioProcessing::kNoError;
 }
 
 bool GainControlImpl::is_enabled() const {
   rtc::CritScope cs(crit_capture_);
-  return is_component_enabled();
+  return enabled_;
 }
 
 int GainControlImpl::set_mode(Mode mode) {
@@ -273,7 +317,8 @@
   }
 
   mode_ = mode;
-  return Initialize();
+  Initialize();
+  return AudioProcessing::kNoError;
 }
 
 GainControl::Mode GainControlImpl::mode() const {
@@ -299,7 +344,8 @@
   minimum_capture_level_ = minimum;
   maximum_capture_level_ = maximum;
 
-  return Initialize();
+  Initialize();
+  return AudioProcessing::kNoError;
 }
 
 int GainControlImpl::analog_level_minimum() const {
@@ -318,12 +364,13 @@
 }
 
 int GainControlImpl::set_target_level_dbfs(int level) {
-  rtc::CritScope cs(crit_capture_);
   if (level > 31 || level < 0) {
     return AudioProcessing::kBadParameterError;
   }
-
-  target_level_dbfs_ = level;
+  {
+    rtc::CritScope cs(crit_capture_);
+    target_level_dbfs_ = level;
+  }
   return Configure();
 }
 
@@ -333,12 +380,13 @@
 }
 
 int GainControlImpl::set_compression_gain_db(int gain) {
-  rtc::CritScope cs(crit_capture_);
   if (gain < 0 || gain > 90) {
     return AudioProcessing::kBadParameterError;
   }
-
-  compression_gain_db_ = gain;
+  {
+    rtc::CritScope cs(crit_capture_);
+    compression_gain_db_ = gain;
+  }
   return Configure();
 }
 
@@ -348,8 +396,10 @@
 }
 
 int GainControlImpl::enable_limiter(bool enable) {
-  rtc::CritScope cs(crit_capture_);
-  limiter_enabled_ = enable;
+  {
+    rtc::CritScope cs(crit_capture_);
+    limiter_enabled_ = enable;
+  }
   return Configure();
 }
 
@@ -358,26 +408,32 @@
   return limiter_enabled_;
 }
 
-int GainControlImpl::Initialize() {
-  int err = ProcessingComponent::Initialize();
-  if (err != AudioProcessing::kNoError || !is_component_enabled()) {
-    return err;
+void GainControlImpl::Initialize() {
+  rtc::CritScope cs_render(crit_render_);
+  rtc::CritScope cs_capture(crit_capture_);
+  if (!enabled_) {
+    return;
   }
 
+  int sample_rate_hz = apm_->proc_sample_rate_hz();
+  gain_controllers_.resize(num_handles_required());
+  for (auto& gain_controller : gain_controllers_) {
+    if (!gain_controller) {
+      gain_controller.reset(new GainController());
+    }
+    gain_controller->Initialize(minimum_capture_level_, maximum_capture_level_,
+                                mode_, sample_rate_hz, analog_capture_level_);
+  }
+
+  Configure();
+
   AllocateRenderQueue();
-
-  rtc::CritScope cs_capture(crit_capture_);
-  const int n = num_handles();
-  RTC_CHECK_GE(n, 0) << "Bad number of handles: " << n;
-
-  capture_levels_.assign(n, analog_capture_level_);
-  return AudioProcessing::kNoError;
 }
 
 void GainControlImpl::AllocateRenderQueue() {
-  const size_t new_render_queue_element_max_size =
-      std::max<size_t>(static_cast<size_t>(1),
-                       kMaxAllowedValuesOfSamplesPerFrame * num_handles());
+  const size_t new_render_queue_element_max_size = std::max<size_t>(
+      static_cast<size_t>(1),
+      kMaxAllowedValuesOfSamplesPerFrame * num_handles_required());
 
   rtc::CritScope cs_render(crit_render_);
   rtc::CritScope cs_capture(crit_capture_);
@@ -398,26 +454,7 @@
   }
 }
 
-void* GainControlImpl::CreateHandle() const {
-  return WebRtcAgc_Create();
-}
-
-void GainControlImpl::DestroyHandle(void* handle) const {
-  WebRtcAgc_Free(static_cast<Handle*>(handle));
-}
-
-int GainControlImpl::InitializeHandle(void* handle) const {
-  rtc::CritScope cs_render(crit_render_);
-  rtc::CritScope cs_capture(crit_capture_);
-
-  return WebRtcAgc_Init(static_cast<Handle*>(handle),
-                          minimum_capture_level_,
-                          maximum_capture_level_,
-                          MapSetting(mode_),
-                          apm_->proc_sample_rate_hz());
-}
-
-int GainControlImpl::ConfigureHandle(void* handle) const {
+int GainControlImpl::Configure() {
   rtc::CritScope cs_render(crit_render_);
   rtc::CritScope cs_capture(crit_capture_);
   WebRtcAgcConfig config;
@@ -430,18 +467,19 @@
       static_cast<int16_t>(compression_gain_db_);
   config.limiterEnable = limiter_enabled_;
 
-  return WebRtcAgc_set_config(static_cast<Handle*>(handle), config);
+  int error = AudioProcessing::kNoError;
+  for (auto& gain_controller : gain_controllers_) {
+    const int handle_error =
+        WebRtcAgc_set_config(gain_controller->state(), config);
+    if (handle_error != AudioProcessing::kNoError) {
+      error = handle_error;
+    }
+  }
+  return error;
 }
 
 size_t GainControlImpl::num_handles_required() const {
   // Not locked as it only relies on APM public API which is threadsafe.
   return apm_->num_proc_channels();
 }
-
-int GainControlImpl::GetHandleError(void* handle) const {
-  // The AGC has no get_error() function.
-  // (Despite listing errors in its interface...)
-  assert(handle != NULL);
-  return AudioProcessing::kUnspecifiedError;
-}
 }  // namespace webrtc