Send runtime settings to the Audio Processing Module (APM)

This CL includes the following changes:
- APM runtime setting (ID + float payload) and unit tests
- Swap queue of APM runtime settings used in AudioProcessingImpl
- runtime settings handler that forwards the settings to APM
  sub-modules when a message is retrieved from the queue
- Unit test placeholder to check that the pre-gain update message
  is correctly delivered

Bug: webrtc:9138
Change-Id: Id22704af15fde2b87a4431f5ce64ad1aeafc5280
Reviewed-on: https://webrtc-review.googlesource.com/69320
Reviewed-by: Per Ã…hgren <peah@webrtc.org>
Reviewed-by: Alex Loiko <aleloi@webrtc.org>
Commit-Queue: Alessio Bazzica <alessiob@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22873}
diff --git a/modules/audio_processing/audio_processing_impl.cc b/modules/audio_processing/audio_processing_impl.cc
index 2e36895..f25c430 100644
--- a/modules/audio_processing/audio_processing_impl.cc
+++ b/modules/audio_processing/audio_processing_impl.cc
@@ -379,6 +379,8 @@
     NonlinearBeamformer* beamformer)
     : data_dumper_(
           new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
+      runtime_settings_(new SwapQueue<RuntimeSetting>(100)),
+      runtime_settings_enqueuer_(runtime_settings_.get()),
       high_pass_filter_impl_(new HighPassFilterImpl(this)),
       echo_control_factory_(std::move(echo_control_factory)),
       submodule_states_(!!capture_post_processor, !!render_pre_processor),
@@ -795,6 +797,32 @@
   }
 }
 
+void AudioProcessingImpl::SetRuntimeSetting(RuntimeSetting setting) {
+  RTC_DCHECK(setting.type() != RuntimeSetting::Type::kNotSpecified);
+  runtime_settings_enqueuer_.Enqueue(setting);
+}
+
+AudioProcessingImpl::RuntimeSettingEnqueuer::RuntimeSettingEnqueuer(
+    SwapQueue<RuntimeSetting>* runtime_settings)
+    : runtime_settings_(runtime_settings) {
+  RTC_DCHECK(runtime_settings_);
+}
+
+AudioProcessingImpl::RuntimeSettingEnqueuer::~RuntimeSettingEnqueuer() =
+    default;
+
+void AudioProcessingImpl::RuntimeSettingEnqueuer::Enqueue(
+    RuntimeSetting setting) {
+  size_t remaining_attempts = 10;
+  while (!runtime_settings_->Insert(&setting) && remaining_attempts-- > 0) {
+    RuntimeSetting setting_to_discard;
+    if (runtime_settings_->Remove(&setting_to_discard))
+      RTC_LOG(LS_ERROR)
+          << "The runtime settings queue is full. Oldest setting discarded.";
+  }
+  if (remaining_attempts == 0)
+    RTC_LOG(LS_ERROR) << "Cannot enqueue a new runtime setting.";
+}
 
 int AudioProcessingImpl::ProcessStream(const float* const* src,
                                        size_t samples_per_channel,
@@ -877,6 +905,22 @@
   return kNoError;
 }
 
+void AudioProcessingImpl::HandleRuntimeSettings() {
+  RuntimeSetting setting;
+  while (runtime_settings_->Remove(&setting)) {
+    RTC_DCHECK(setting.type() != RuntimeSetting::Type::kNotSpecified);
+    switch (setting.type()) {
+      case RuntimeSetting::Type::kCapturePreGain:
+        // TODO(bugs.chromium.org/9138): Notify
+        // pre-gain when the sub-module is implemented.
+        break;
+      default:
+        RTC_NOTREACHED();
+        break;
+    }
+  }
+}
+
 void AudioProcessingImpl::QueueBandedRenderAudio(AudioBuffer* audio) {
   EchoCancellationImpl::PackRenderAudioBuffer(audio, num_output_channels(),
                                               num_reverse_channels(),
@@ -1131,6 +1175,8 @@
 }
 
 int AudioProcessingImpl::ProcessCaptureStreamLocked() {
+  HandleRuntimeSettings();
+
   // Ensure that not both the AEC and AECM are active at the same time.
   // TODO(peah): Simplify once the public API Enable functions for these
   // are moved to APM.