| Index: webrtc/modules/audio_processing/aec3/block_processor.cc
 | 
| diff --git a/webrtc/modules/audio_processing/aec3/block_processor.cc b/webrtc/modules/audio_processing/aec3/block_processor.cc
 | 
| index 5055b3f77deedcb7805989cf3f381f8f1a552ec3..79892345b10ff28d2d35bead2c538e76b9adc1aa 100644
 | 
| --- a/webrtc/modules/audio_processing/aec3/block_processor.cc
 | 
| +++ b/webrtc/modules/audio_processing/aec3/block_processor.cc
 | 
| @@ -20,6 +20,8 @@
 | 
|  namespace webrtc {
 | 
|  namespace {
 | 
|  
 | 
| +enum class BlockProcessorApiCall { kCapture, kRender };
 | 
| +
 | 
|  class BlockProcessorImpl final : public BlockProcessor {
 | 
|   public:
 | 
|    BlockProcessorImpl(int sample_rate_hz,
 | 
| @@ -33,24 +35,25 @@ class BlockProcessorImpl final : public BlockProcessor {
 | 
|                        bool capture_signal_saturation,
 | 
|                        std::vector<std::vector<float>>* capture_block) override;
 | 
|  
 | 
| -  bool BufferRender(std::vector<std::vector<float>>* block) override;
 | 
| +  void BufferRender(const std::vector<std::vector<float>>& block) override;
 | 
|  
 | 
|    void UpdateEchoLeakageStatus(bool leakage_detected) override;
 | 
|  
 | 
|   private:
 | 
|    static int instance_count_;
 | 
| +  bool no_capture_data_received_ = true;
 | 
| +  bool no_render_data_received_ = true;
 | 
|    std::unique_ptr<ApmDataDumper> data_dumper_;
 | 
|    const size_t sample_rate_hz_;
 | 
|    std::unique_ptr<RenderDelayBuffer> render_buffer_;
 | 
|    std::unique_ptr<RenderDelayController> delay_controller_;
 | 
|    std::unique_ptr<EchoRemover> echo_remover_;
 | 
|    BlockProcessorMetrics metrics_;
 | 
| +  bool render_buffer_overrun_occurred_ = false;
 | 
|    RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(BlockProcessorImpl);
 | 
|  };
 | 
|  
 | 
| -constexpr size_t kRenderBufferSize = 250;
 | 
|  int BlockProcessorImpl::instance_count_ = 0;
 | 
| -constexpr size_t kMaxApiJitter = 30;
 | 
|  
 | 
|  BlockProcessorImpl::BlockProcessorImpl(
 | 
|      int sample_rate_hz,
 | 
| @@ -75,40 +78,88 @@ void BlockProcessorImpl::ProcessCapture(
 | 
|    RTC_DCHECK(capture_block);
 | 
|    RTC_DCHECK_EQ(NumBandsForRate(sample_rate_hz_), capture_block->size());
 | 
|    RTC_DCHECK_EQ(kBlockSize, (*capture_block)[0].size());
 | 
| -
 | 
| -  const size_t delay = delay_controller_->GetDelay((*capture_block)[0]);
 | 
| -  const bool render_delay_change = delay != render_buffer_->Delay();
 | 
| -
 | 
| -  if (render_delay_change) {
 | 
| -    render_buffer_->SetDelay(delay);
 | 
| +  data_dumper_->DumpRaw("aec3_processblock_call_order",
 | 
| +                        static_cast<int>(BlockProcessorApiCall::kCapture));
 | 
| +  data_dumper_->DumpWav("aec3_processblock_capture_input", kBlockSize,
 | 
| +                        &(*capture_block)[0][0],
 | 
| +                        LowestBandRate(sample_rate_hz_), 1);
 | 
| +
 | 
| +  // Do not start processing until render data has been buffered as that will
 | 
| +  // cause the buffers to be wrongly aligned.
 | 
| +  no_capture_data_received_ = false;
 | 
| +  if (no_render_data_received_) {
 | 
| +    return;
 | 
|    }
 | 
|  
 | 
| -  if (render_buffer_->IsBlockAvailable()) {
 | 
| -    auto& render_block = render_buffer_->GetNext();
 | 
| -    echo_remover_->ProcessBlock(
 | 
| -        delay_controller_->AlignmentHeadroomSamples(),
 | 
| -        EchoPathVariability(echo_path_gain_change, render_delay_change),
 | 
| -        capture_signal_saturation, render_block, capture_block);
 | 
| -    metrics_.UpdateCapture(false);
 | 
| +  data_dumper_->DumpWav("aec3_processblock_capture_input2", kBlockSize,
 | 
| +                        &(*capture_block)[0][0],
 | 
| +                        LowestBandRate(sample_rate_hz_), 1);
 | 
| +
 | 
| +  bool render_buffer_underrun = false;
 | 
| +  if (render_buffer_overrun_occurred_) {
 | 
| +    // Reset the render buffers and the alignment functionality when there has
 | 
| +    // been a render buffer overrun as the buffer alignment may be noncausal.
 | 
| +    delay_controller_->Reset();
 | 
| +    render_buffer_->Reset();
 | 
|    } else {
 | 
| -    metrics_.UpdateCapture(true);
 | 
| +    // Update the render buffers with new render data, filling the buffers with
 | 
| +    // empty blocks when there is no render data available.
 | 
| +    render_buffer_underrun = !render_buffer_->UpdateBuffers();
 | 
| +
 | 
| +    // Compute and and apply the render delay required to achieve proper signal
 | 
| +    // alignment.
 | 
| +    const size_t old_delay = render_buffer_->Delay();
 | 
| +    const size_t new_delay = delay_controller_->GetDelay(
 | 
| +        render_buffer_->GetDownsampledRenderBuffer(), (*capture_block)[0]);
 | 
| +    render_buffer_->SetDelay(new_delay);
 | 
| +    const size_t achieved_delay = render_buffer_->Delay();
 | 
| +
 | 
| +    // Inform the delay controller of the actually set delay to allow it to
 | 
| +    // properly react to a non-feasible delay.
 | 
| +    delay_controller_->SetDelay(achieved_delay);
 | 
| +
 | 
| +    // Remove the echo from the capture signal.
 | 
| +    echo_remover_->ProcessCapture(
 | 
| +        delay_controller_->AlignmentHeadroomSamples(),
 | 
| +        EchoPathVariability(echo_path_gain_change,
 | 
| +                            old_delay != achieved_delay ||
 | 
| +                                old_delay != new_delay ||
 | 
| +                                render_buffer_overrun_occurred_),
 | 
| +        capture_signal_saturation, render_buffer_->GetRenderBuffer(),
 | 
| +        capture_block);
 | 
|    }
 | 
| +
 | 
| +  // Update the metrics.
 | 
| +  metrics_.UpdateCapture(render_buffer_underrun);
 | 
| +
 | 
| +  render_buffer_overrun_occurred_ = false;
 | 
|  }
 | 
|  
 | 
| -bool BlockProcessorImpl::BufferRender(std::vector<std::vector<float>>* block) {
 | 
| -  RTC_DCHECK(block);
 | 
| -  RTC_DCHECK_EQ(NumBandsForRate(sample_rate_hz_), block->size());
 | 
| -  RTC_DCHECK_EQ(kBlockSize, (*block)[0].size());
 | 
| -
 | 
| -  const bool delay_controller_overrun =
 | 
| -      !delay_controller_->AnalyzeRender((*block)[0]);
 | 
| -  const bool render_buffer_overrun = !render_buffer_->Insert(block);
 | 
| -  if (delay_controller_overrun || render_buffer_overrun) {
 | 
| -    metrics_.UpdateRender(true);
 | 
| -    return false;
 | 
| +void BlockProcessorImpl::BufferRender(
 | 
| +    const std::vector<std::vector<float>>& block) {
 | 
| +  RTC_DCHECK_EQ(NumBandsForRate(sample_rate_hz_), block.size());
 | 
| +  RTC_DCHECK_EQ(kBlockSize, block[0].size());
 | 
| +  data_dumper_->DumpRaw("aec3_processblock_call_order",
 | 
| +                        static_cast<int>(BlockProcessorApiCall::kRender));
 | 
| +  data_dumper_->DumpWav("aec3_processblock_render_input", kBlockSize,
 | 
| +                        &block[0][0], LowestBandRate(sample_rate_hz_), 1);
 | 
| +
 | 
| +  no_render_data_received_ = false;
 | 
| +
 | 
| +  // Do not start buffer render data until capture data has been received as
 | 
| +  // that data may give a false alignment.
 | 
| +  if (no_capture_data_received_) {
 | 
| +    return;
 | 
|    }
 | 
| -  metrics_.UpdateRender(false);
 | 
| -  return true;
 | 
| +
 | 
| +  data_dumper_->DumpWav("aec3_processblock_render_input2", kBlockSize,
 | 
| +                        &block[0][0], LowestBandRate(sample_rate_hz_), 1);
 | 
| +
 | 
| +  // Buffer the render data.
 | 
| +  render_buffer_overrun_occurred_ = !render_buffer_->Insert(block);
 | 
| +
 | 
| +  // Update the metrics.
 | 
| +  metrics_.UpdateRender(render_buffer_overrun_occurred_);
 | 
|  }
 | 
|  
 | 
|  void BlockProcessorImpl::UpdateEchoLeakageStatus(bool leakage_detected) {
 | 
| @@ -118,10 +169,10 @@ void BlockProcessorImpl::UpdateEchoLeakageStatus(bool leakage_detected) {
 | 
|  }  // namespace
 | 
|  
 | 
|  BlockProcessor* BlockProcessor::Create(int sample_rate_hz) {
 | 
| -  std::unique_ptr<RenderDelayBuffer> render_buffer(RenderDelayBuffer::Create(
 | 
| -      kRenderBufferSize, NumBandsForRate(sample_rate_hz), kMaxApiJitter));
 | 
| +  std::unique_ptr<RenderDelayBuffer> render_buffer(
 | 
| +      RenderDelayBuffer::Create(NumBandsForRate(sample_rate_hz)));
 | 
|    std::unique_ptr<RenderDelayController> delay_controller(
 | 
| -      RenderDelayController::Create(sample_rate_hz, *render_buffer));
 | 
| +      RenderDelayController::Create(sample_rate_hz));
 | 
|    std::unique_ptr<EchoRemover> echo_remover(
 | 
|        EchoRemover::Create(sample_rate_hz));
 | 
|    return Create(sample_rate_hz, std::move(render_buffer),
 | 
| @@ -132,7 +183,7 @@ BlockProcessor* BlockProcessor::Create(
 | 
|      int sample_rate_hz,
 | 
|      std::unique_ptr<RenderDelayBuffer> render_buffer) {
 | 
|    std::unique_ptr<RenderDelayController> delay_controller(
 | 
| -      RenderDelayController::Create(sample_rate_hz, *render_buffer));
 | 
| +      RenderDelayController::Create(sample_rate_hz));
 | 
|    std::unique_ptr<EchoRemover> echo_remover(
 | 
|        EchoRemover::Create(sample_rate_hz));
 | 
|    return Create(sample_rate_hz, std::move(render_buffer),
 | 
| 
 |