blob: 0aec528cde170c1e11ab983708c0a3894c5321d5 [file] [log] [blame]
stefan@webrtc.org792f1a12015-03-04 12:24:26 +00001/*
2 * Copyright (c) 2015 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
12#include "webrtc/modules/bitrate_controller/include/bitrate_allocator.h"
13
14#include <algorithm>
15#include <utility>
16
17#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
18
19namespace webrtc {
20
Stefan Holmere5904162015-03-26 11:11:06 +010021// Allow packets to be transmitted in up to 2 times max video bitrate if the
22// bandwidth estimate allows it.
23const int kTransmissionMaxBitrateMultiplier = 2;
24const int kDefaultBitrateBps = 300000;
25
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000026BitrateAllocator::BitrateAllocator()
27 : crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
28 bitrate_observers_(),
Stefan Holmere5904162015-03-26 11:11:06 +010029 enforce_min_bitrate_(true),
30 last_bitrate_bps_(kDefaultBitrateBps),
31 last_fraction_loss_(0),
32 last_rtt_(0) {
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000033}
34
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000035
36void BitrateAllocator::OnNetworkChanged(uint32_t bitrate,
37 uint8_t fraction_loss,
38 int64_t rtt) {
39 CriticalSectionScoped lock(crit_sect_.get());
Stefan Holmere5904162015-03-26 11:11:06 +010040 last_bitrate_bps_ = bitrate;
41 last_fraction_loss_ = fraction_loss;
42 last_rtt_ = rtt;
43 ObserverBitrateMap allocation = AllocateBitrates();
44 for (const auto& kv : allocation)
45 kv.first->OnNetworkChanged(kv.second, last_fraction_loss_, last_rtt_);
46}
47
48BitrateAllocator::ObserverBitrateMap BitrateAllocator::AllocateBitrates() {
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000049 if (bitrate_observers_.empty())
Stefan Holmere5904162015-03-26 11:11:06 +010050 return ObserverBitrateMap();
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000051
52 uint32_t sum_min_bitrates = 0;
Stefan Holmere5904162015-03-26 11:11:06 +010053 for (const auto& observer : bitrate_observers_)
Peter Boström8e4e8b02015-09-15 15:08:03 +020054 sum_min_bitrates += observer.second.min_bitrate;
Stefan Holmere5904162015-03-26 11:11:06 +010055 if (last_bitrate_bps_ <= sum_min_bitrates)
56 return LowRateAllocation(last_bitrate_bps_);
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000057 else
Stefan Holmere5904162015-03-26 11:11:06 +010058 return NormalRateAllocation(last_bitrate_bps_, sum_min_bitrates);
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000059}
60
61int BitrateAllocator::AddBitrateObserver(BitrateObserver* observer,
Stefan Holmere5904162015-03-26 11:11:06 +010062 uint32_t min_bitrate_bps,
Peter Boström8e4e8b02015-09-15 15:08:03 +020063 uint32_t max_bitrate_bps) {
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000064 CriticalSectionScoped lock(crit_sect_.get());
65
66 BitrateObserverConfList::iterator it =
67 FindObserverConfigurationPair(observer);
68
Stefan Holmere5904162015-03-26 11:11:06 +010069 // Allow the max bitrate to be exceeded for FEC and retransmissions.
70 // TODO(holmer): We have to get rid of this hack as it makes it difficult to
71 // properly allocate bitrate. The allocator should instead distribute any
72 // extra bitrate after all streams have maxed out.
73 max_bitrate_bps *= kTransmissionMaxBitrateMultiplier;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000074 if (it != bitrate_observers_.end()) {
75 // Update current configuration.
Peter Boström8e4e8b02015-09-15 15:08:03 +020076 it->second.min_bitrate = min_bitrate_bps;
77 it->second.max_bitrate = max_bitrate_bps;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000078 } else {
79 // Add new settings.
80 bitrate_observers_.push_back(BitrateObserverConfiguration(
Peter Boström8e4e8b02015-09-15 15:08:03 +020081 observer, BitrateConfiguration(min_bitrate_bps, max_bitrate_bps)));
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000082 bitrate_observers_modified_ = true;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000083 }
Stefan Holmere5904162015-03-26 11:11:06 +010084
Stefan Holmere5904162015-03-26 11:11:06 +010085 ObserverBitrateMap allocation = AllocateBitrates();
Peter Boström8e4e8b02015-09-15 15:08:03 +020086 int new_observer_bitrate_bps = 0;
Stefan Holmere5904162015-03-26 11:11:06 +010087 for (auto& kv : allocation) {
88 kv.first->OnNetworkChanged(kv.second, last_fraction_loss_, last_rtt_);
89 if (kv.first == observer)
Peter Boström8e4e8b02015-09-15 15:08:03 +020090 new_observer_bitrate_bps = kv.second;
Stefan Holmere5904162015-03-26 11:11:06 +010091 }
Peter Boström8e4e8b02015-09-15 15:08:03 +020092 return new_observer_bitrate_bps;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000093}
94
95void BitrateAllocator::RemoveBitrateObserver(BitrateObserver* observer) {
96 CriticalSectionScoped lock(crit_sect_.get());
97 BitrateObserverConfList::iterator it =
98 FindObserverConfigurationPair(observer);
99 if (it != bitrate_observers_.end()) {
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000100 bitrate_observers_.erase(it);
101 bitrate_observers_modified_ = true;
102 }
103}
104
105void BitrateAllocator::GetMinMaxBitrateSumBps(int* min_bitrate_sum_bps,
106 int* max_bitrate_sum_bps) const {
107 *min_bitrate_sum_bps = 0;
108 *max_bitrate_sum_bps = 0;
109
110 CriticalSectionScoped lock(crit_sect_.get());
Stefan Holmere5904162015-03-26 11:11:06 +0100111 for (const auto& observer : bitrate_observers_) {
Peter Boström8e4e8b02015-09-15 15:08:03 +0200112 *min_bitrate_sum_bps += observer.second.min_bitrate;
113 *max_bitrate_sum_bps += observer.second.max_bitrate;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000114 }
115}
116
117BitrateAllocator::BitrateObserverConfList::iterator
118BitrateAllocator::FindObserverConfigurationPair(
119 const BitrateObserver* observer) {
Stefan Holmere5904162015-03-26 11:11:06 +0100120 for (auto it = bitrate_observers_.begin(); it != bitrate_observers_.end();
121 ++it) {
122 if (it->first == observer)
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000123 return it;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000124 }
125 return bitrate_observers_.end();
126}
127
128void BitrateAllocator::EnforceMinBitrate(bool enforce_min_bitrate) {
129 CriticalSectionScoped lock(crit_sect_.get());
130 enforce_min_bitrate_ = enforce_min_bitrate;
131}
132
Stefan Holmere5904162015-03-26 11:11:06 +0100133BitrateAllocator::ObserverBitrateMap BitrateAllocator::NormalRateAllocation(
134 uint32_t bitrate,
135 uint32_t sum_min_bitrates) {
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000136 uint32_t number_of_observers = bitrate_observers_.size();
137 uint32_t bitrate_per_observer =
138 (bitrate - sum_min_bitrates) / number_of_observers;
139 // Use map to sort list based on max bitrate.
140 ObserverSortingMap list_max_bitrates;
Stefan Holmere5904162015-03-26 11:11:06 +0100141 for (const auto& observer : bitrate_observers_) {
142 list_max_bitrates.insert(std::pair<uint32_t, ObserverConfiguration>(
Peter Boström8e4e8b02015-09-15 15:08:03 +0200143 observer.second.max_bitrate,
144 ObserverConfiguration(observer.first, observer.second.min_bitrate)));
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000145 }
Stefan Holmere5904162015-03-26 11:11:06 +0100146 ObserverBitrateMap allocation;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000147 ObserverSortingMap::iterator max_it = list_max_bitrates.begin();
148 while (max_it != list_max_bitrates.end()) {
149 number_of_observers--;
150 uint32_t observer_allowance =
Peter Boström8e4e8b02015-09-15 15:08:03 +0200151 max_it->second.min_bitrate + bitrate_per_observer;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000152 if (max_it->first < observer_allowance) {
153 // We have more than enough for this observer.
154 // Carry the remainder forward.
155 uint32_t remainder = observer_allowance - max_it->first;
156 if (number_of_observers != 0) {
157 bitrate_per_observer += remainder / number_of_observers;
158 }
Peter Boström8e4e8b02015-09-15 15:08:03 +0200159 allocation[max_it->second.observer] = max_it->first;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000160 } else {
Peter Boström8e4e8b02015-09-15 15:08:03 +0200161 allocation[max_it->second.observer] = observer_allowance;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000162 }
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000163 list_max_bitrates.erase(max_it);
164 // Prepare next iteration.
165 max_it = list_max_bitrates.begin();
166 }
Stefan Holmere5904162015-03-26 11:11:06 +0100167 return allocation;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000168}
169
Stefan Holmere5904162015-03-26 11:11:06 +0100170BitrateAllocator::ObserverBitrateMap BitrateAllocator::LowRateAllocation(
171 uint32_t bitrate) {
172 ObserverBitrateMap allocation;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000173 if (enforce_min_bitrate_) {
174 // Min bitrate to all observers.
Stefan Holmere5904162015-03-26 11:11:06 +0100175 for (const auto& observer : bitrate_observers_)
Peter Boström8e4e8b02015-09-15 15:08:03 +0200176 allocation[observer.first] = observer.second.min_bitrate;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000177 } else {
Peter Boström8e4e8b02015-09-15 15:08:03 +0200178 // Allocate up to |min_bitrate| to one observer at a time, until
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000179 // |bitrate| is depleted.
180 uint32_t remainder = bitrate;
Stefan Holmere5904162015-03-26 11:11:06 +0100181 for (const auto& observer : bitrate_observers_) {
182 uint32_t allocated_bitrate =
Peter Boström8e4e8b02015-09-15 15:08:03 +0200183 std::min(remainder, observer.second.min_bitrate);
Stefan Holmere5904162015-03-26 11:11:06 +0100184 allocation[observer.first] = allocated_bitrate;
185 remainder -= allocated_bitrate;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000186 }
187 }
Stefan Holmere5904162015-03-26 11:11:06 +0100188 return allocation;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000189}
190} // namespace webrtc