render_delay_controller.cc (6692B)
1 /* 2 * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 #include "modules/audio_processing/aec3/render_delay_controller.h" 11 12 #include <atomic> 13 #include <cstddef> 14 #include <memory> 15 #include <optional> 16 17 #include "api/audio/echo_canceller3_config.h" 18 #include "modules/audio_processing/aec3/aec3_common.h" 19 #include "modules/audio_processing/aec3/block.h" 20 #include "modules/audio_processing/aec3/clockdrift_detector.h" 21 #include "modules/audio_processing/aec3/delay_estimate.h" 22 #include "modules/audio_processing/aec3/downsampled_render_buffer.h" 23 #include "modules/audio_processing/aec3/echo_path_delay_estimator.h" 24 #include "modules/audio_processing/aec3/render_delay_controller_metrics.h" 25 #include "modules/audio_processing/logging/apm_data_dumper.h" 26 #include "rtc_base/checks.h" 27 28 namespace webrtc { 29 30 namespace { 31 32 class RenderDelayControllerImpl final : public RenderDelayController { 33 public: 34 RenderDelayControllerImpl(const EchoCanceller3Config& config, 35 int sample_rate_hz, 36 size_t num_capture_channels); 37 38 RenderDelayControllerImpl() = delete; 39 RenderDelayControllerImpl(const RenderDelayControllerImpl&) = delete; 40 RenderDelayControllerImpl& operator=(const RenderDelayControllerImpl&) = 41 delete; 42 43 ~RenderDelayControllerImpl() override; 44 void Reset(bool reset_delay_confidence) override; 45 void LogRenderCall() override; 46 std::optional<DelayEstimate> GetDelay( 47 const DownsampledRenderBuffer& render_buffer, 48 size_t render_delay_buffer_delay, 49 const Block& capture) override; 50 bool HasClockdrift() const override; 51 52 private: 53 static std::atomic<int> instance_count_; 54 std::unique_ptr<ApmDataDumper> data_dumper_; 55 const int hysteresis_limit_blocks_; 56 std::optional<DelayEstimate> delay_; 57 EchoPathDelayEstimator delay_estimator_; 58 RenderDelayControllerMetrics metrics_; 59 std::optional<DelayEstimate> delay_samples_; 60 size_t capture_call_counter_ = 0; 61 int delay_change_counter_ = 0; 62 DelayEstimate::Quality last_delay_estimate_quality_; 63 }; 64 65 DelayEstimate ComputeBufferDelay( 66 const std::optional<DelayEstimate>& current_delay, 67 int hysteresis_limit_blocks, 68 DelayEstimate estimated_delay) { 69 // Compute the buffer delay increase required to achieve the desired latency. 70 size_t new_delay_blocks = estimated_delay.delay >> kBlockSizeLog2; 71 // Add hysteresis. 72 if (current_delay) { 73 size_t current_delay_blocks = current_delay->delay; 74 if (new_delay_blocks > current_delay_blocks && 75 new_delay_blocks <= current_delay_blocks + hysteresis_limit_blocks) { 76 new_delay_blocks = current_delay_blocks; 77 } 78 } 79 DelayEstimate new_delay = estimated_delay; 80 new_delay.delay = new_delay_blocks; 81 return new_delay; 82 } 83 84 std::atomic<int> RenderDelayControllerImpl::instance_count_(0); 85 86 RenderDelayControllerImpl::RenderDelayControllerImpl( 87 const EchoCanceller3Config& config, 88 int sample_rate_hz, 89 size_t num_capture_channels) 90 : data_dumper_(new ApmDataDumper(instance_count_.fetch_add(1) + 1)), 91 hysteresis_limit_blocks_( 92 static_cast<int>(config.delay.hysteresis_limit_blocks)), 93 delay_estimator_(data_dumper_.get(), config, num_capture_channels), 94 last_delay_estimate_quality_(DelayEstimate::Quality::kCoarse) { 95 RTC_DCHECK(ValidFullBandRate(sample_rate_hz)); 96 delay_estimator_.LogDelayEstimationProperties(sample_rate_hz, 0); 97 } 98 99 RenderDelayControllerImpl::~RenderDelayControllerImpl() = default; 100 101 void RenderDelayControllerImpl::Reset(bool reset_delay_confidence) { 102 delay_ = std::nullopt; 103 delay_samples_ = std::nullopt; 104 delay_estimator_.Reset(reset_delay_confidence); 105 delay_change_counter_ = 0; 106 if (reset_delay_confidence) { 107 last_delay_estimate_quality_ = DelayEstimate::Quality::kCoarse; 108 } 109 } 110 111 void RenderDelayControllerImpl::LogRenderCall() {} 112 113 std::optional<DelayEstimate> RenderDelayControllerImpl::GetDelay( 114 const DownsampledRenderBuffer& render_buffer, 115 size_t /* render_delay_buffer_delay */, 116 const Block& capture) { 117 ++capture_call_counter_; 118 119 auto delay_samples = delay_estimator_.EstimateDelay(render_buffer, capture); 120 121 if (delay_samples) { 122 if (!delay_samples_ || delay_samples->delay != delay_samples_->delay) { 123 delay_change_counter_ = 0; 124 } 125 if (delay_samples_) { 126 delay_samples_->blocks_since_last_change = 127 delay_samples_->delay == delay_samples->delay 128 ? delay_samples_->blocks_since_last_change + 1 129 : 0; 130 delay_samples_->blocks_since_last_update = 0; 131 delay_samples_->delay = delay_samples->delay; 132 delay_samples_->quality = delay_samples->quality; 133 } else { 134 delay_samples_ = delay_samples; 135 } 136 } else { 137 if (delay_samples_) { 138 ++delay_samples_->blocks_since_last_change; 139 ++delay_samples_->blocks_since_last_update; 140 } 141 } 142 143 if (delay_change_counter_ < 2 * kNumBlocksPerSecond) { 144 ++delay_change_counter_; 145 } 146 147 if (delay_samples_) { 148 // Compute the render delay buffer delay. 149 const bool use_hysteresis = 150 last_delay_estimate_quality_ == DelayEstimate::Quality::kRefined && 151 delay_samples_->quality == DelayEstimate::Quality::kRefined; 152 delay_ = ComputeBufferDelay( 153 delay_, use_hysteresis ? hysteresis_limit_blocks_ : 0, *delay_samples_); 154 last_delay_estimate_quality_ = delay_samples_->quality; 155 } 156 157 metrics_.Update(delay_samples_ ? std::optional<size_t>(delay_samples_->delay) 158 : std::nullopt, 159 delay_ ? std::optional<size_t>(delay_->delay) : std::nullopt, 160 delay_estimator_.Clockdrift()); 161 162 data_dumper_->DumpRaw("aec3_render_delay_controller_delay", 163 delay_samples ? delay_samples->delay : 0); 164 data_dumper_->DumpRaw("aec3_render_delay_controller_buffer_delay", 165 delay_ ? delay_->delay : 0); 166 167 return delay_; 168 } 169 170 bool RenderDelayControllerImpl::HasClockdrift() const { 171 return delay_estimator_.Clockdrift() != ClockdriftDetector::Level::kNone; 172 } 173 174 } // namespace 175 176 RenderDelayController* RenderDelayController::Create( 177 const EchoCanceller3Config& config, 178 int sample_rate_hz, 179 size_t num_capture_channels) { 180 return new RenderDelayControllerImpl(config, sample_rate_hz, 181 num_capture_channels); 182 } 183 184 } // namespace webrtc