Line data Source code
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 <limits>
14 : #include <utility>
15 :
16 : #include "webrtc/base/checks.h"
17 :
18 : namespace webrtc {
19 :
20 0 : FecController::Config::Threshold::Threshold(int low_bandwidth_bps,
21 : float low_bandwidth_packet_loss,
22 : int high_bandwidth_bps,
23 0 : float high_bandwidth_packet_loss)
24 : : low_bandwidth_bps(low_bandwidth_bps),
25 : low_bandwidth_packet_loss(low_bandwidth_packet_loss),
26 : high_bandwidth_bps(high_bandwidth_bps),
27 0 : high_bandwidth_packet_loss(high_bandwidth_packet_loss) {}
28 :
29 0 : FecController::Config::Config(bool initial_fec_enabled,
30 : const Threshold& fec_enabling_threshold,
31 : const Threshold& fec_disabling_threshold,
32 : int time_constant_ms,
33 0 : const Clock* clock)
34 : : initial_fec_enabled(initial_fec_enabled),
35 : fec_enabling_threshold(fec_enabling_threshold),
36 : fec_disabling_threshold(fec_disabling_threshold),
37 : time_constant_ms(time_constant_ms),
38 0 : clock(clock) {}
39 :
40 0 : FecController::FecController(const Config& config)
41 : : config_(config),
42 0 : fec_enabled_(config.initial_fec_enabled),
43 : packet_loss_smoothed_(
44 0 : new SmoothingFilterImpl(config_.time_constant_ms, config_.clock)),
45 : fec_enabling_threshold_info_(config_.fec_enabling_threshold),
46 0 : fec_disabling_threshold_info_(config_.fec_disabling_threshold) {
47 0 : RTC_DCHECK_LE(fec_enabling_threshold_info_.slope, 0);
48 0 : RTC_DCHECK_LE(fec_enabling_threshold_info_.slope, 0);
49 0 : RTC_DCHECK_LE(
50 : GetPacketLossThreshold(config_.fec_enabling_threshold.low_bandwidth_bps,
51 : config_.fec_disabling_threshold,
52 : fec_disabling_threshold_info_),
53 0 : config_.fec_enabling_threshold.low_bandwidth_packet_loss);
54 0 : RTC_DCHECK_LE(
55 : GetPacketLossThreshold(config_.fec_enabling_threshold.high_bandwidth_bps,
56 : config_.fec_disabling_threshold,
57 : fec_disabling_threshold_info_),
58 0 : config_.fec_enabling_threshold.high_bandwidth_packet_loss);
59 0 : }
60 :
61 0 : FecController::FecController(const Config& config,
62 0 : std::unique_ptr<SmoothingFilter> smoothing_filter)
63 0 : : FecController(config) {
64 0 : packet_loss_smoothed_ = std::move(smoothing_filter);
65 0 : }
66 :
67 : FecController::~FecController() = default;
68 :
69 0 : void FecController::MakeDecision(
70 : const NetworkMetrics& metrics,
71 : AudioNetworkAdaptor::EncoderRuntimeConfig* config) {
72 0 : RTC_DCHECK(!config->enable_fec);
73 0 : RTC_DCHECK(!config->uplink_packet_loss_fraction);
74 :
75 0 : if (metrics.uplink_packet_loss_fraction)
76 0 : packet_loss_smoothed_->AddSample(*metrics.uplink_packet_loss_fraction);
77 :
78 0 : const auto& packet_loss = packet_loss_smoothed_->GetAverage();
79 :
80 0 : fec_enabled_ = fec_enabled_ ? !FecDisablingDecision(metrics, packet_loss)
81 : : FecEnablingDecision(metrics, packet_loss);
82 :
83 0 : config->enable_fec = rtc::Optional<bool>(fec_enabled_);
84 :
85 0 : auto packet_loss_fraction = packet_loss_smoothed_->GetAverage();
86 0 : config->uplink_packet_loss_fraction = rtc::Optional<float>(
87 0 : packet_loss_fraction ? *packet_loss_fraction : 0.0);
88 0 : }
89 :
90 0 : FecController::ThresholdInfo::ThresholdInfo(
91 0 : const Config::Threshold& threshold) {
92 : int bandwidth_diff_bps =
93 0 : threshold.high_bandwidth_bps - threshold.low_bandwidth_bps;
94 0 : float packet_loss_diff = threshold.high_bandwidth_packet_loss -
95 0 : threshold.low_bandwidth_packet_loss;
96 0 : slope = bandwidth_diff_bps == 0 ? 0.0 : packet_loss_diff / bandwidth_diff_bps;
97 0 : offset =
98 0 : threshold.low_bandwidth_packet_loss - slope * threshold.low_bandwidth_bps;
99 0 : }
100 :
101 0 : float FecController::GetPacketLossThreshold(
102 : int bandwidth_bps,
103 : const Config::Threshold& threshold,
104 : const ThresholdInfo& threshold_info) const {
105 0 : if (bandwidth_bps < threshold.low_bandwidth_bps)
106 0 : return std::numeric_limits<float>::max();
107 0 : if (bandwidth_bps >= threshold.high_bandwidth_bps)
108 0 : return threshold.high_bandwidth_packet_loss;
109 0 : return threshold_info.offset + threshold_info.slope * bandwidth_bps;
110 : }
111 :
112 0 : bool FecController::FecEnablingDecision(
113 : const NetworkMetrics& metrics,
114 : const rtc::Optional<float>& packet_loss) const {
115 0 : if (!metrics.uplink_bandwidth_bps)
116 0 : return false;
117 0 : if (!packet_loss)
118 0 : return false;
119 0 : return *packet_loss >= GetPacketLossThreshold(*metrics.uplink_bandwidth_bps,
120 : config_.fec_enabling_threshold,
121 0 : fec_enabling_threshold_info_);
122 : }
123 :
124 0 : bool FecController::FecDisablingDecision(
125 : const NetworkMetrics& metrics,
126 : const rtc::Optional<float>& packet_loss) const {
127 0 : if (!metrics.uplink_bandwidth_bps)
128 0 : return false;
129 0 : if (!packet_loss)
130 0 : return false;
131 0 : return *packet_loss <= GetPacketLossThreshold(*metrics.uplink_bandwidth_bps,
132 : config_.fec_disabling_threshold,
133 0 : fec_disabling_threshold_info_);
134 : }
135 :
136 : } // namespace webrtc
|