• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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