OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 #include "webrtc/modules/audio_processing/aec3/render_delay_controller.h" | 10 #include "webrtc/modules/audio_processing/aec3/render_delay_controller.h" |
11 | 11 |
12 #include <algorithm> | 12 #include <algorithm> |
13 #include <memory> | 13 #include <memory> |
14 #include <string> | 14 #include <string> |
15 #include <vector> | 15 #include <vector> |
16 | 16 |
17 #include "webrtc/base/atomicops.h" | 17 #include "webrtc/base/atomicops.h" |
18 #include "webrtc/base/constructormagic.h" | 18 #include "webrtc/base/constructormagic.h" |
19 #include "webrtc/modules/audio_processing/aec3/aec3_common.h" | 19 #include "webrtc/modules/audio_processing/aec3/aec3_common.h" |
20 #include "webrtc/modules/audio_processing/aec3/echo_path_delay_estimator.h" | 20 #include "webrtc/modules/audio_processing/aec3/echo_path_delay_estimator.h" |
21 #include "webrtc/modules/audio_processing/aec3/render_delay_controller_metrics.h " | 21 #include "webrtc/modules/audio_processing/aec3/render_delay_controller_metrics.h " |
22 | 22 |
23 namespace webrtc { | 23 namespace webrtc { |
24 | 24 |
25 namespace { | 25 namespace { |
26 | 26 |
27 class RenderBuffer { | |
28 public: | |
29 explicit RenderBuffer(size_t size) | |
30 : buffer_(size, std::vector<float>(kBlockSize, 0.f)) {} | |
31 ~RenderBuffer() = default; | |
32 | |
33 bool Insert(rtc::ArrayView<const float> v) { | |
34 if (size_ >= buffer_.size() - 1) { | |
35 return false; | |
36 } | |
37 | |
38 last_insert_index_ = (last_insert_index_ + 1) % buffer_.size(); | |
39 RTC_DCHECK_EQ(buffer_[last_insert_index_].size(), v.size()); | |
40 | |
41 buffer_[last_insert_index_].clear(); | |
42 buffer_[last_insert_index_].insert(buffer_[last_insert_index_].begin(), | |
43 v.begin(), v.end()); | |
44 ++size_; | |
45 return true; | |
46 } | |
47 rtc::ArrayView<const float> Get() { | |
48 RTC_DCHECK_LT(0, size_); | |
49 --size_; | |
50 return buffer_[(last_insert_index_ - size_ + buffer_.size()) % | |
51 buffer_.size()]; | |
52 } | |
53 | |
54 size_t Size() { return size_; } | |
55 | |
56 private: | |
57 std::vector<std::vector<float>> buffer_; | |
58 size_t size_ = 0; | |
59 int last_insert_index_ = 0; | |
60 }; | |
61 | |
62 class RenderDelayControllerImpl final : public RenderDelayController { | 27 class RenderDelayControllerImpl final : public RenderDelayController { |
63 public: | 28 public: |
64 RenderDelayControllerImpl(int sample_rate_hz, | 29 RenderDelayControllerImpl(int sample_rate_hz); |
65 const RenderDelayBuffer& render_delay_buffer); | |
66 ~RenderDelayControllerImpl() override; | 30 ~RenderDelayControllerImpl() override; |
67 size_t GetDelay(rtc::ArrayView<const float> capture) override; | 31 void Reset() override; |
68 bool AnalyzeRender(rtc::ArrayView<const float> render) override; | 32 void SetDelay(size_t render_delay) override; |
33 size_t GetDelay(const DownsampledRenderBuffer& render_buffer, | |
34 rtc::ArrayView<const float> capture) override; | |
69 rtc::Optional<size_t> AlignmentHeadroomSamples() const override { | 35 rtc::Optional<size_t> AlignmentHeadroomSamples() const override { |
70 return headroom_samples_; | 36 return headroom_samples_; |
71 } | 37 } |
72 | 38 |
73 private: | 39 private: |
74 static int instance_count_; | 40 static int instance_count_; |
75 std::unique_ptr<ApmDataDumper> data_dumper_; | 41 std::unique_ptr<ApmDataDumper> data_dumper_; |
76 const size_t max_delay_; | 42 size_t delay_ = 0; |
77 size_t delay_; | |
78 RenderBuffer render_buffer_; | |
79 EchoPathDelayEstimator delay_estimator_; | 43 EchoPathDelayEstimator delay_estimator_; |
80 size_t blocks_since_last_delay_estimate_ = 300000; | 44 size_t blocks_since_last_delay_estimate_ = 300000; |
81 int echo_path_delay_samples_ = 0; | 45 int echo_path_delay_samples_ = 0; |
82 size_t align_call_counter_ = 0; | 46 size_t align_call_counter_ = 0; |
83 rtc::Optional<size_t> headroom_samples_; | 47 rtc::Optional<size_t> headroom_samples_; |
84 RenderDelayControllerMetrics metrics_; | 48 RenderDelayControllerMetrics metrics_; |
85 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RenderDelayControllerImpl); | 49 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RenderDelayControllerImpl); |
86 }; | 50 }; |
87 | 51 |
88 size_t ComputeNewBufferDelay(size_t current_delay, | 52 size_t ComputeNewBufferDelay(size_t current_delay, |
89 size_t max_delay, | |
90 size_t echo_path_delay_samples) { | 53 size_t echo_path_delay_samples) { |
91 // The below division is not exact and the truncation is intended. | 54 // The below division is not exact and the truncation is intended. |
92 const int echo_path_delay_blocks = echo_path_delay_samples / kBlockSize; | 55 const int echo_path_delay_blocks = echo_path_delay_samples / kBlockSize; |
93 constexpr int kDelayHeadroomBlocks = 1; | 56 constexpr int kDelayHeadroomBlocks = 1; |
94 | 57 |
95 // Compute the buffer delay increase required to achieve the desired latency. | 58 // Compute the buffer delay increase required to achieve the desired latency. |
96 size_t new_delay = std::max(echo_path_delay_blocks - kDelayHeadroomBlocks, 0); | 59 size_t new_delay = std::max(echo_path_delay_blocks - kDelayHeadroomBlocks, 0); |
97 | 60 |
98 // Add hysteresis. | 61 // Add hysteresis. |
99 if (new_delay == current_delay + 1 || new_delay + 1 == current_delay) { | 62 if (new_delay == current_delay + 1 || new_delay + 1 == current_delay) { |
100 new_delay = current_delay; | 63 new_delay = current_delay; |
101 } | 64 } |
102 | 65 |
103 // Limit the delay to what is possible. | |
104 new_delay = std::min(new_delay, max_delay); | |
105 | |
106 return new_delay; | 66 return new_delay; |
107 } | 67 } |
108 | 68 |
109 int RenderDelayControllerImpl::instance_count_ = 0; | 69 int RenderDelayControllerImpl::instance_count_ = 0; |
110 | 70 |
111 RenderDelayControllerImpl::RenderDelayControllerImpl( | 71 RenderDelayControllerImpl::RenderDelayControllerImpl(int sample_rate_hz) |
112 int sample_rate_hz, | |
113 const RenderDelayBuffer& render_delay_buffer) | |
114 : data_dumper_( | 72 : data_dumper_( |
115 new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))), | 73 new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))), |
116 max_delay_(render_delay_buffer.MaxDelay()), | |
117 delay_(render_delay_buffer.Delay()), | |
118 render_buffer_(render_delay_buffer.MaxApiJitter() + 1), | |
119 delay_estimator_(data_dumper_.get()) { | 74 delay_estimator_(data_dumper_.get()) { |
120 RTC_DCHECK(ValidFullBandRate(sample_rate_hz)); | 75 RTC_DCHECK(ValidFullBandRate(sample_rate_hz)); |
121 } | 76 } |
122 | 77 |
123 RenderDelayControllerImpl::~RenderDelayControllerImpl() = default; | 78 RenderDelayControllerImpl::~RenderDelayControllerImpl() = default; |
124 | 79 |
80 void RenderDelayControllerImpl::Reset() { | |
81 delay_ = 0; | |
82 blocks_since_last_delay_estimate_ = 300000; | |
83 echo_path_delay_samples_ = 0; | |
84 align_call_counter_ = 0; | |
85 headroom_samples_ = rtc::Optional<size_t>(); | |
86 | |
87 delay_estimator_.Reset(); | |
88 } | |
89 | |
90 void RenderDelayControllerImpl::SetDelay(size_t render_delay) { | |
91 if (delay_ != render_delay) { | |
92 // If a the delay set does not match the actual delay, reset the delay | |
peah-webrtc
2017/03/30 05:36:56
The controller produces a delay in GetDelay, but i
| |
93 // controller. | |
94 Reset(); | |
95 delay_ = render_delay; | |
96 } | |
97 } | |
98 | |
125 size_t RenderDelayControllerImpl::GetDelay( | 99 size_t RenderDelayControllerImpl::GetDelay( |
100 const DownsampledRenderBuffer& render_buffer, | |
126 rtc::ArrayView<const float> capture) { | 101 rtc::ArrayView<const float> capture) { |
127 RTC_DCHECK_EQ(kBlockSize, capture.size()); | 102 RTC_DCHECK_EQ(kBlockSize, capture.size()); |
128 if (render_buffer_.Size() == 0) { | |
129 return delay_; | |
130 } | |
131 | 103 |
132 ++align_call_counter_; | 104 ++align_call_counter_; |
133 rtc::ArrayView<const float> render = render_buffer_.Get(); | |
134 rtc::Optional<size_t> echo_path_delay_samples = | 105 rtc::Optional<size_t> echo_path_delay_samples = |
135 delay_estimator_.EstimateDelay(render, capture); | 106 delay_estimator_.EstimateDelay(render_buffer, capture); |
136 if (echo_path_delay_samples) { | 107 if (echo_path_delay_samples) { |
137 echo_path_delay_samples_ = *echo_path_delay_samples; | 108 echo_path_delay_samples_ = *echo_path_delay_samples; |
138 | 109 |
139 // Compute and set new render delay buffer delay. | 110 // Compute and set new render delay buffer delay. |
140 const size_t new_delay = | 111 const size_t new_delay = |
141 ComputeNewBufferDelay(delay_, max_delay_, echo_path_delay_samples_); | 112 ComputeNewBufferDelay(delay_, echo_path_delay_samples_); |
142 if (new_delay != delay_ && align_call_counter_ > 250) { | 113 if (new_delay != delay_ && align_call_counter_ > 250) { |
143 delay_ = new_delay; | 114 delay_ = new_delay; |
144 } | 115 } |
145 | 116 |
146 // Update render delay buffer headroom. | 117 // Update render delay buffer headroom. |
147 blocks_since_last_delay_estimate_ = 0; | 118 blocks_since_last_delay_estimate_ = 0; |
148 const int headroom = echo_path_delay_samples_ - delay_ * kBlockSize; | 119 const int headroom = echo_path_delay_samples_ - delay_ * kBlockSize; |
149 RTC_DCHECK_LE(0, headroom); | 120 RTC_DCHECK_LE(0, headroom); |
150 headroom_samples_ = rtc::Optional<size_t>(headroom); | 121 headroom_samples_ = rtc::Optional<size_t>(headroom); |
151 } else if (++blocks_since_last_delay_estimate_ > 250 * 20) { | 122 } else if (++blocks_since_last_delay_estimate_ > 250 * 20) { |
152 headroom_samples_ = rtc::Optional<size_t>(); | 123 headroom_samples_ = rtc::Optional<size_t>(); |
153 } | 124 } |
154 | 125 |
155 metrics_.Update(echo_path_delay_samples, delay_); | 126 metrics_.Update(echo_path_delay_samples, delay_); |
156 | 127 |
157 data_dumper_->DumpRaw("aec3_render_delay_controller_delay", 1, | 128 data_dumper_->DumpRaw("aec3_render_delay_controller_delay", 1, |
158 &echo_path_delay_samples_); | 129 &echo_path_delay_samples_); |
159 data_dumper_->DumpRaw("aec3_render_delay_controller_buffer_delay", delay_); | 130 data_dumper_->DumpRaw("aec3_render_delay_controller_buffer_delay", delay_); |
160 | 131 |
161 return delay_; | 132 return delay_; |
162 } | 133 } |
163 | 134 |
164 bool RenderDelayControllerImpl::AnalyzeRender( | |
165 rtc::ArrayView<const float> render) { | |
166 return render_buffer_.Insert(render); | |
167 } | |
168 | |
169 } // namespace | 135 } // namespace |
170 | 136 |
171 RenderDelayController* RenderDelayController::Create( | 137 RenderDelayController* RenderDelayController::Create(int sample_rate_hz) { |
172 int sample_rate_hz, | 138 return new RenderDelayControllerImpl(sample_rate_hz); |
173 const RenderDelayBuffer& render_delay_buffer) { | |
174 return new RenderDelayControllerImpl(sample_rate_hz, render_delay_buffer); | |
175 } | 139 } |
176 | 140 |
177 } // namespace webrtc | 141 } // namespace webrtc |
OLD | NEW |