Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1642)

Side by Side Diff: webrtc/modules/audio_coding/audio_network_adaptor/fec_controller.cc

Issue 2337103006: Adding FecController to audio network adaptor. (Closed)
Patch Set: On Henrik's comments Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698