OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright (c) 2016 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 | |
11 #include "webrtc/modules/audio_coding/audio_network_adaptor/fec_controller.h" | |
12 | |
13 #include <algorithm> | |
14 #include <utility> | |
15 | |
16 #include "webrtc/base/checks.h" | |
17 | |
18 namespace webrtc { | |
19 | |
20 namespace { | |
21 | |
22 // Return if two line segments: (l1_x1, l1_y1) - (l1_x2, l1_y2) and | |
23 // (l2_x1, l2_y1) - (l2_x2, l2_y2) intersect. | |
24 bool Insersect(int l1_x1, | |
25 float l1_y1, | |
26 int l1_x2, | |
27 float l1_y2, | |
28 int l2_x1, | |
29 float l2_y1, | |
30 int l2_x2, | |
31 float l2_y2) { | |
32 // Solving alpha and beta for | |
33 // l1_x1 * alpha + l1_x2 * (1 - alpha) = l2_x1 * beta + l2_x2 * (1 - beta) | |
34 // l1_y1 * alpha + l1_y2 * (1 - alpha) = l2_y1 * beta + l2_y2 * (1 - beta) | |
35 // This leads to | |
36 int h1 = l1_x1 - l1_x2; | |
37 int h2 = l2_x2 - l2_x1; | |
38 float h3 = l1_y1 - l1_y2; | |
39 float h4 = l2_y2 - l2_y1; | |
40 int b1 = l2_x2 - l1_x2; | |
41 float b2 = l2_y2 - l1_y2; | |
42 float denom = h1 * h4 - h2 * h3; | |
43 printf("%f\n", denom); | |
minyue-webrtc
2016/09/20 12:01:01
remove
| |
44 if (denom == 0.0) | |
45 return false; | |
46 float alpha = (h4 * b1 - h2 * b2) / denom; | |
47 float beta = (-h3 * b1 + h1 * b2) / denom; | |
48 printf("%f, %f\n", alpha, beta); | |
minyue-webrtc
2016/09/20 12:01:01
remove
| |
49 return alpha >= 0 && alpha <= 1 && beta >= 0 && beta <= 1; | |
50 } | |
51 | |
52 } // namespace | |
53 | |
54 FecController::Config::Threshold::Threshold(int low_bandwidth_bps, | |
55 float low_bandwidth_packet_loss, | |
56 int high_bandwidth_bps, | |
57 float high_bandwidth_packet_loss) | |
58 : low_bandwidth_bps(low_bandwidth_bps), | |
59 low_bandwidth_packet_loss(low_bandwidth_packet_loss), | |
60 high_bandwidth_bps(high_bandwidth_bps), | |
61 high_bandwidth_packet_loss(high_bandwidth_packet_loss) {} | |
62 | |
63 FecController::Config::Config(bool initial_fec_enabled, | |
64 const Threshold& fec_enabling_threshold, | |
65 const Threshold& fec_disabling_threshold, | |
66 int time_constant_ms, | |
67 Clock* clock) | |
68 : initial_fec_enabled(initial_fec_enabled), | |
69 fec_enabling_threshold(fec_enabling_threshold), | |
70 fec_disabling_threshold(fec_disabling_threshold), | |
71 time_constant_ms(time_constant_ms), | |
72 clock(clock) {} | |
73 | |
74 FecController::FecController(const Config& config) | |
75 : config_(config), | |
76 fec_enabled_(config.initial_fec_enabled), | |
77 packet_loss_smoothed_( | |
78 new SmoothingFilterImpl(config_.time_constant_ms, config_.clock)), | |
79 fec_enabling_threshold_info_(config_.fec_enabling_threshold), | |
80 fec_disabling_threshold_info_(config_.fec_disabling_threshold) { | |
81 RTC_DCHECK_LE(fec_enabling_threshold_info_.slope, 0); | |
82 RTC_DCHECK_LE(fec_enabling_threshold_info_.slope, 0); | |
83 RTC_DCHECK_GE(config_.fec_enabling_threshold.low_bandwidth_bps, | |
84 config_.fec_disabling_threshold.low_bandwidth_bps); | |
85 RTC_DCHECK_GE(config_.fec_enabling_threshold.high_bandwidth_packet_loss, | |
86 config_.fec_disabling_threshold.high_bandwidth_packet_loss); | |
87 // Ensure that the two middle parts of the curves do not intersect. | |
hlundin-webrtc
2016/09/20 12:40:37
Please, simplify this as we discussed offline. (To
minyue-webrtc
2016/09/20 16:16:12
thanks the inspiration! FecDisablingDecision and F
| |
88 RTC_DCHECK( | |
89 !Insersect(config_.fec_enabling_threshold.low_bandwidth_bps, | |
90 config_.fec_enabling_threshold.low_bandwidth_packet_loss, | |
91 config_.fec_enabling_threshold.high_bandwidth_bps, | |
92 config_.fec_enabling_threshold.high_bandwidth_packet_loss, | |
93 config_.fec_disabling_threshold.low_bandwidth_bps, | |
94 config_.fec_disabling_threshold.low_bandwidth_packet_loss, | |
95 config_.fec_disabling_threshold.high_bandwidth_bps, | |
96 config_.fec_disabling_threshold.high_bandwidth_packet_loss)); | |
97 // Ensure that the middle part of the FEC disabling curve do not intersect | |
98 // with the vertical part of the FEC enabling curve. | |
99 RTC_DCHECK(!Insersect( | |
100 config_.fec_enabling_threshold.low_bandwidth_bps, | |
101 config_.fec_enabling_threshold.low_bandwidth_packet_loss, | |
102 config_.fec_enabling_threshold.low_bandwidth_bps, | |
103 std::max(config_.fec_enabling_threshold.low_bandwidth_packet_loss, | |
104 config_.fec_disabling_threshold.low_bandwidth_packet_loss), | |
105 config_.fec_disabling_threshold.low_bandwidth_bps, | |
106 config_.fec_disabling_threshold.low_bandwidth_packet_loss, | |
107 config_.fec_disabling_threshold.high_bandwidth_bps, | |
108 config_.fec_disabling_threshold.high_bandwidth_packet_loss)); | |
109 // Ensure that the middle part of the FEC disabling curve do not intersect | |
110 // with the horizontal part of the FEC enabling curve. | |
111 RTC_DCHECK( | |
112 !Insersect(std::max(config_.fec_enabling_threshold.high_bandwidth_bps, | |
113 config_.fec_disabling_threshold.high_bandwidth_bps), | |
114 config_.fec_enabling_threshold.high_bandwidth_packet_loss, | |
115 config_.fec_enabling_threshold.high_bandwidth_bps, | |
116 config_.fec_enabling_threshold.high_bandwidth_packet_loss, | |
117 config_.fec_disabling_threshold.low_bandwidth_bps, | |
118 config_.fec_disabling_threshold.low_bandwidth_packet_loss, | |
119 config_.fec_disabling_threshold.high_bandwidth_bps, | |
120 config_.fec_disabling_threshold.high_bandwidth_packet_loss)); | |
121 } | |
122 | |
123 FecController::FecController(const Config& config, | |
124 std::unique_ptr<SmoothingFilter> smoothing_filter) | |
125 : FecController(config) { | |
126 packet_loss_smoothed_ = std::move(smoothing_filter); | |
127 } | |
128 | |
129 FecController::~FecController() = default; | |
130 | |
131 void FecController::MakeDecision( | |
132 const NetworkMetrics& metrics, | |
133 AudioNetworkAdaptor::EncoderRuntimeConfig* config) { | |
134 RTC_DCHECK(!config->enable_fec); | |
135 RTC_DCHECK(!config->uplink_packet_loss_fraction); | |
136 | |
137 if (metrics.uplink_packet_loss_fraction) | |
138 packet_loss_smoothed_->AddSample(*metrics.uplink_packet_loss_fraction); | |
139 | |
140 fec_enabled_ = fec_enabled_ ? !FecDisablingDecision(metrics) | |
141 : FecEnablingDecision(metrics); | |
142 | |
143 config->enable_fec = rtc::Optional<bool>(fec_enabled_); | |
144 | |
145 if (fec_enabled_) { | |
146 auto packet_loss_fraction = packet_loss_smoothed_->GetAverage(); | |
147 config->uplink_packet_loss_fraction = rtc::Optional<float>( | |
148 packet_loss_fraction ? *packet_loss_fraction : 0.0); | |
149 } else { | |
150 config->uplink_packet_loss_fraction = rtc::Optional<float>(0.0); | |
151 } | |
152 } | |
153 | |
154 FecController::ThresholdInfo::ThresholdInfo( | |
155 const Config::Threshold& threshold) { | |
156 int bandwidth_diff_bps = | |
157 threshold.high_bandwidth_bps - threshold.low_bandwidth_bps; | |
158 float packet_loss_diff = threshold.high_bandwidth_packet_loss - | |
159 threshold.low_bandwidth_packet_loss; | |
160 slope = bandwidth_diff_bps == 0 ? 0.0 : packet_loss_diff / bandwidth_diff_bps; | |
161 offset = | |
162 threshold.low_bandwidth_packet_loss - slope * threshold.low_bandwidth_bps; | |
163 } | |
164 | |
165 float FecController::GetPacketLossThreshold( | |
166 int bandwidth_bps, | |
167 const FecController::ThresholdInfo& threshold_info) const { | |
168 return threshold_info.offset + threshold_info.slope * bandwidth_bps; | |
169 } | |
170 | |
171 bool FecController::FecEnablingDecision(const NetworkMetrics& metrics) const { | |
172 if (!metrics.uplink_bandwidth_bps) | |
173 return false; | |
174 | |
175 auto packet_loss = packet_loss_smoothed_->GetAverage(); | |
176 if (!packet_loss) | |
177 return false; | |
178 | |
179 if (*metrics.uplink_bandwidth_bps >= | |
180 config_.fec_enabling_threshold.high_bandwidth_bps && | |
181 *packet_loss >= config_.fec_enabling_threshold.high_bandwidth_packet_loss) | |
182 return true; | |
183 | |
184 if (*metrics.uplink_bandwidth_bps < | |
185 config_.fec_enabling_threshold.high_bandwidth_bps && | |
186 *metrics.uplink_bandwidth_bps >= | |
187 config_.fec_enabling_threshold.low_bandwidth_bps && | |
188 *packet_loss >= GetPacketLossThreshold(*metrics.uplink_bandwidth_bps, | |
189 fec_enabling_threshold_info_)) | |
190 return true; | |
191 | |
192 return false; | |
193 } | |
194 | |
195 bool FecController::FecDisablingDecision(const NetworkMetrics& metrics) const { | |
196 if (!metrics.uplink_bandwidth_bps) | |
197 return false; | |
198 | |
199 auto packet_loss = packet_loss_smoothed_->GetAverage(); | |
200 if (!packet_loss) | |
201 return false; | |
202 | |
203 if (*metrics.uplink_bandwidth_bps <= | |
204 config_.fec_disabling_threshold.low_bandwidth_bps) | |
205 return true; | |
206 | |
207 if (*metrics.uplink_bandwidth_bps >= | |
208 config_.fec_disabling_threshold.high_bandwidth_bps && | |
209 *packet_loss <= | |
210 config_.fec_disabling_threshold.high_bandwidth_packet_loss) | |
211 return true; | |
212 | |
213 if (*metrics.uplink_bandwidth_bps > | |
214 config_.fec_disabling_threshold.low_bandwidth_bps && | |
215 *metrics.uplink_bandwidth_bps < | |
216 config_.fec_disabling_threshold.high_bandwidth_bps && | |
217 *packet_loss <= GetPacketLossThreshold(*metrics.uplink_bandwidth_bps, | |
218 fec_disabling_threshold_info_)) | |
219 return true; | |
220 | |
221 return false; | |
222 } | |
223 | |
224 } // namespace webrtc | |
OLD | NEW |