• 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/frame_length_controller.h"
12 
13 #include <algorithm>
14 #include <iterator>
15 #include <utility>
16 
17 #include "rtc_base/checks.h"
18 
19 namespace webrtc {
20 
21 namespace {
22 constexpr int kPreventOveruseMarginBps = 5000;
23 
OverheadRateBps(size_t overhead_bytes_per_packet,int frame_length_ms)24 int OverheadRateBps(size_t overhead_bytes_per_packet, int frame_length_ms) {
25   return static_cast<int>(overhead_bytes_per_packet * 8 * 1000 /
26                           frame_length_ms);
27 }
28 }  // namespace
29 
Config(const std::set<int> & encoder_frame_lengths_ms,int initial_frame_length_ms,int min_encoder_bitrate_bps,float fl_increasing_packet_loss_fraction,float fl_decreasing_packet_loss_fraction,int fl_increase_overhead_offset,int fl_decrease_overhead_offset,std::map<FrameLengthChange,int> fl_changing_bandwidths_bps)30 FrameLengthController::Config::Config(
31     const std::set<int>& encoder_frame_lengths_ms,
32     int initial_frame_length_ms,
33     int min_encoder_bitrate_bps,
34     float fl_increasing_packet_loss_fraction,
35     float fl_decreasing_packet_loss_fraction,
36     int fl_increase_overhead_offset,
37     int fl_decrease_overhead_offset,
38     std::map<FrameLengthChange, int> fl_changing_bandwidths_bps)
39     : encoder_frame_lengths_ms(encoder_frame_lengths_ms),
40       initial_frame_length_ms(initial_frame_length_ms),
41       min_encoder_bitrate_bps(min_encoder_bitrate_bps),
42       fl_increasing_packet_loss_fraction(fl_increasing_packet_loss_fraction),
43       fl_decreasing_packet_loss_fraction(fl_decreasing_packet_loss_fraction),
44       fl_increase_overhead_offset(fl_increase_overhead_offset),
45       fl_decrease_overhead_offset(fl_decrease_overhead_offset),
46       fl_changing_bandwidths_bps(std::move(fl_changing_bandwidths_bps)) {}
47 
48 FrameLengthController::Config::Config(const Config& other) = default;
49 
50 FrameLengthController::Config::~Config() = default;
51 
FrameLengthController(const Config & config)52 FrameLengthController::FrameLengthController(const Config& config)
53     : config_(config) {
54   frame_length_ms_ = std::find(config_.encoder_frame_lengths_ms.begin(),
55                                config_.encoder_frame_lengths_ms.end(),
56                                config_.initial_frame_length_ms);
57   // |encoder_frame_lengths_ms| must contain |initial_frame_length_ms|.
58   RTC_DCHECK(frame_length_ms_ != config_.encoder_frame_lengths_ms.end());
59 }
60 
61 FrameLengthController::~FrameLengthController() = default;
62 
UpdateNetworkMetrics(const NetworkMetrics & network_metrics)63 void FrameLengthController::UpdateNetworkMetrics(
64     const NetworkMetrics& network_metrics) {
65   if (network_metrics.uplink_bandwidth_bps)
66     uplink_bandwidth_bps_ = network_metrics.uplink_bandwidth_bps;
67   if (network_metrics.uplink_packet_loss_fraction)
68     uplink_packet_loss_fraction_ = network_metrics.uplink_packet_loss_fraction;
69   if (network_metrics.overhead_bytes_per_packet)
70     overhead_bytes_per_packet_ = network_metrics.overhead_bytes_per_packet;
71 }
72 
MakeDecision(AudioEncoderRuntimeConfig * config)73 void FrameLengthController::MakeDecision(AudioEncoderRuntimeConfig* config) {
74   // Decision on |frame_length_ms| should not have been made.
75   RTC_DCHECK(!config->frame_length_ms);
76 
77   if (FrameLengthIncreasingDecision(*config)) {
78     prev_decision_increase_ = true;
79   } else if (FrameLengthDecreasingDecision(*config)) {
80     prev_decision_increase_ = false;
81   }
82   config->last_fl_change_increase = prev_decision_increase_;
83   config->frame_length_ms = *frame_length_ms_;
84 }
85 
FrameLengthChange(int from_frame_length_ms,int to_frame_length_ms)86 FrameLengthController::Config::FrameLengthChange::FrameLengthChange(
87     int from_frame_length_ms,
88     int to_frame_length_ms)
89     : from_frame_length_ms(from_frame_length_ms),
90       to_frame_length_ms(to_frame_length_ms) {}
91 
operator <(const FrameLengthChange & rhs) const92 bool FrameLengthController::Config::FrameLengthChange::operator<(
93     const FrameLengthChange& rhs) const {
94   return from_frame_length_ms < rhs.from_frame_length_ms ||
95          (from_frame_length_ms == rhs.from_frame_length_ms &&
96           to_frame_length_ms < rhs.to_frame_length_ms);
97 }
98 
FrameLengthIncreasingDecision(const AudioEncoderRuntimeConfig & config)99 bool FrameLengthController::FrameLengthIncreasingDecision(
100     const AudioEncoderRuntimeConfig& config) {
101   // Increase frame length if
102   // 1. |uplink_bandwidth_bps| is known to be smaller or equal than
103   //    |min_encoder_bitrate_bps| plus |prevent_overuse_margin_bps| plus the
104   //    current overhead rate OR all the following:
105   // 2. longer frame length is available AND
106   // 3. |uplink_bandwidth_bps| is known to be smaller than a threshold AND
107   // 4. |uplink_packet_loss_fraction| is known to be smaller than a threshold.
108 
109   // Find next frame length to which a criterion is defined to shift from
110   // current frame length.
111   auto longer_frame_length_ms = std::next(frame_length_ms_);
112   auto increase_threshold = config_.fl_changing_bandwidths_bps.end();
113   while (longer_frame_length_ms != config_.encoder_frame_lengths_ms.end()) {
114     increase_threshold = config_.fl_changing_bandwidths_bps.find(
115         Config::FrameLengthChange(*frame_length_ms_, *longer_frame_length_ms));
116     if (increase_threshold != config_.fl_changing_bandwidths_bps.end())
117       break;
118     longer_frame_length_ms = std::next(longer_frame_length_ms);
119   }
120 
121   if (increase_threshold == config_.fl_changing_bandwidths_bps.end())
122     return false;
123 
124   // Check that
125   // -(*overhead_bytes_per_packet_) <= offset <= (*overhead_bytes_per_packet_)
126   RTC_DCHECK(
127       !overhead_bytes_per_packet_ ||
128       (overhead_bytes_per_packet_ &&
129        static_cast<size_t>(std::max(0, -config_.fl_increase_overhead_offset)) <=
130            *overhead_bytes_per_packet_ &&
131        static_cast<size_t>(std::max(0, config_.fl_increase_overhead_offset)) <=
132            *overhead_bytes_per_packet_));
133 
134   if (uplink_bandwidth_bps_ && overhead_bytes_per_packet_ &&
135       *uplink_bandwidth_bps_ <=
136           config_.min_encoder_bitrate_bps + kPreventOveruseMarginBps +
137               OverheadRateBps(*overhead_bytes_per_packet_ +
138                                   config_.fl_increase_overhead_offset,
139                               *frame_length_ms_)) {
140     frame_length_ms_ = longer_frame_length_ms;
141     return true;
142   }
143 
144   if ((uplink_bandwidth_bps_ &&
145        *uplink_bandwidth_bps_ <= increase_threshold->second) &&
146       (uplink_packet_loss_fraction_ &&
147        *uplink_packet_loss_fraction_ <=
148            config_.fl_increasing_packet_loss_fraction)) {
149     frame_length_ms_ = longer_frame_length_ms;
150     return true;
151   }
152   return false;
153 }
154 
FrameLengthDecreasingDecision(const AudioEncoderRuntimeConfig & config)155 bool FrameLengthController::FrameLengthDecreasingDecision(
156     const AudioEncoderRuntimeConfig& config) {
157   // Decrease frame length if
158   // 1. shorter frame length is available AND
159   // 2. |uplink_bandwidth_bps| is known to be bigger than
160   // |min_encoder_bitrate_bps| plus |prevent_overuse_margin_bps| plus the
161   // overhead which would be produced with the shorter frame length AND
162   // one or more of the followings:
163   // 3. |uplink_bandwidth_bps| is known to be larger than a threshold,
164   // 4. |uplink_packet_loss_fraction| is known to be larger than a threshold,
165 
166   // Find next frame length to which a criterion is defined to shift from
167   // current frame length.
168   auto shorter_frame_length_ms = frame_length_ms_;
169   auto decrease_threshold = config_.fl_changing_bandwidths_bps.end();
170   while (shorter_frame_length_ms != config_.encoder_frame_lengths_ms.begin()) {
171     shorter_frame_length_ms = std::prev(shorter_frame_length_ms);
172     decrease_threshold = config_.fl_changing_bandwidths_bps.find(
173         Config::FrameLengthChange(*frame_length_ms_, *shorter_frame_length_ms));
174     if (decrease_threshold != config_.fl_changing_bandwidths_bps.end())
175       break;
176   }
177 
178   if (decrease_threshold == config_.fl_changing_bandwidths_bps.end())
179     return false;
180 
181   if (uplink_bandwidth_bps_ && overhead_bytes_per_packet_ &&
182       *uplink_bandwidth_bps_ <=
183           config_.min_encoder_bitrate_bps + kPreventOveruseMarginBps +
184               OverheadRateBps(*overhead_bytes_per_packet_ +
185                                   config_.fl_decrease_overhead_offset,
186                               *shorter_frame_length_ms)) {
187     return false;
188   }
189 
190   if ((uplink_bandwidth_bps_ &&
191        *uplink_bandwidth_bps_ >= decrease_threshold->second) ||
192       (uplink_packet_loss_fraction_ &&
193        *uplink_packet_loss_fraction_ >=
194            config_.fl_decreasing_packet_loss_fraction)) {
195     frame_length_ms_ = shorter_frame_length_ms;
196     return true;
197   }
198   return false;
199 }
200 
201 }  // namespace webrtc
202