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 "modules/audio_coding/audio_network_adaptor/fec_controller_plr_based.h"
12
13 #include <string>
14 #include <utility>
15
16 #include "rtc_base/checks.h"
17 #include "system_wrappers/include/field_trial.h"
18
19 namespace webrtc {
20
21 namespace {
22 class NullSmoothingFilter final : public SmoothingFilter {
23 public:
AddSample(float sample)24 void AddSample(float sample) override { last_sample_ = sample; }
25
GetAverage()26 absl::optional<float> GetAverage() override { return last_sample_; }
27
SetTimeConstantMs(int time_constant_ms)28 bool SetTimeConstantMs(int time_constant_ms) override {
29 RTC_NOTREACHED();
30 return false;
31 }
32
33 private:
34 absl::optional<float> last_sample_;
35 };
36 } // namespace
37
Config(bool initial_fec_enabled,const ThresholdCurve & fec_enabling_threshold,const ThresholdCurve & fec_disabling_threshold,int time_constant_ms)38 FecControllerPlrBased::Config::Config(
39 bool initial_fec_enabled,
40 const ThresholdCurve& fec_enabling_threshold,
41 const ThresholdCurve& fec_disabling_threshold,
42 int time_constant_ms)
43 : initial_fec_enabled(initial_fec_enabled),
44 fec_enabling_threshold(fec_enabling_threshold),
45 fec_disabling_threshold(fec_disabling_threshold),
46 time_constant_ms(time_constant_ms) {}
47
FecControllerPlrBased(const Config & config,std::unique_ptr<SmoothingFilter> smoothing_filter)48 FecControllerPlrBased::FecControllerPlrBased(
49 const Config& config,
50 std::unique_ptr<SmoothingFilter> smoothing_filter)
51 : config_(config),
52 fec_enabled_(config.initial_fec_enabled),
53 packet_loss_smoother_(std::move(smoothing_filter)) {
54 RTC_DCHECK(config_.fec_disabling_threshold <= config_.fec_enabling_threshold);
55 }
56
FecControllerPlrBased(const Config & config)57 FecControllerPlrBased::FecControllerPlrBased(const Config& config)
58 : FecControllerPlrBased(
59 config,
60 webrtc::field_trial::FindFullName("UseTwccPlrForAna") == "Enabled"
61 ? std::unique_ptr<NullSmoothingFilter>(new NullSmoothingFilter())
62 : std::unique_ptr<SmoothingFilter>(
63 new SmoothingFilterImpl(config.time_constant_ms))) {}
64
65 FecControllerPlrBased::~FecControllerPlrBased() = default;
66
UpdateNetworkMetrics(const NetworkMetrics & network_metrics)67 void FecControllerPlrBased::UpdateNetworkMetrics(
68 const NetworkMetrics& network_metrics) {
69 if (network_metrics.uplink_bandwidth_bps)
70 uplink_bandwidth_bps_ = network_metrics.uplink_bandwidth_bps;
71 if (network_metrics.uplink_packet_loss_fraction) {
72 packet_loss_smoother_->AddSample(
73 *network_metrics.uplink_packet_loss_fraction);
74 }
75 }
76
MakeDecision(AudioEncoderRuntimeConfig * config)77 void FecControllerPlrBased::MakeDecision(AudioEncoderRuntimeConfig* config) {
78 RTC_DCHECK(!config->enable_fec);
79 RTC_DCHECK(!config->uplink_packet_loss_fraction);
80
81 const auto& packet_loss = packet_loss_smoother_->GetAverage();
82
83 fec_enabled_ = fec_enabled_ ? !FecDisablingDecision(packet_loss)
84 : FecEnablingDecision(packet_loss);
85
86 config->enable_fec = fec_enabled_;
87
88 config->uplink_packet_loss_fraction = packet_loss ? *packet_loss : 0.0;
89 }
90
FecEnablingDecision(const absl::optional<float> & packet_loss) const91 bool FecControllerPlrBased::FecEnablingDecision(
92 const absl::optional<float>& packet_loss) const {
93 if (!uplink_bandwidth_bps_ || !packet_loss) {
94 return false;
95 } else {
96 // Enable when above the curve or exactly on it.
97 return !config_.fec_enabling_threshold.IsBelowCurve(
98 {static_cast<float>(*uplink_bandwidth_bps_), *packet_loss});
99 }
100 }
101
FecDisablingDecision(const absl::optional<float> & packet_loss) const102 bool FecControllerPlrBased::FecDisablingDecision(
103 const absl::optional<float>& packet_loss) const {
104 if (!uplink_bandwidth_bps_ || !packet_loss) {
105 return false;
106 } else {
107 // Disable when below the curve.
108 return config_.fec_disabling_threshold.IsBelowCurve(
109 {static_cast<float>(*uplink_bandwidth_bps_), *packet_loss});
110 }
111 }
112
113 } // namespace webrtc
114