blob: 4c8d2a0c441bb20f41d7dd7ac30eb4a2110a85d2 [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
mflodman0e7e2592015-11-12 21:02:42 -080012#include "webrtc/call/bitrate_allocator.h"
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000013
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()
tommi63cb4342016-01-20 02:32:54 -080027 : bitrate_observers_(),
sprang2f48d942015-11-05 04:25:49 -080028 bitrate_observers_modified_(false),
Stefan Holmere5904162015-03-26 11:11:06 +010029 enforce_min_bitrate_(true),
30 last_bitrate_bps_(kDefaultBitrateBps),
31 last_fraction_loss_(0),
sprang2f48d942015-11-05 04:25:49 -080032 last_rtt_(0) {}
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000033
sprang2f48d942015-11-05 04:25:49 -080034uint32_t BitrateAllocator::OnNetworkChanged(uint32_t bitrate,
35 uint8_t fraction_loss,
36 int64_t rtt) {
tommi63cb4342016-01-20 02:32:54 -080037 rtc::CritScope lock(&crit_sect_);
Stefan Holmere5904162015-03-26 11:11:06 +010038 last_bitrate_bps_ = bitrate;
39 last_fraction_loss_ = fraction_loss;
40 last_rtt_ = rtt;
sprang2f48d942015-11-05 04:25:49 -080041 uint32_t allocated_bitrate_bps = 0;
Stefan Holmere5904162015-03-26 11:11:06 +010042 ObserverBitrateMap allocation = AllocateBitrates();
sprang2f48d942015-11-05 04:25:49 -080043 for (const auto& kv : allocation) {
mflodman86aabb22016-03-11 15:44:32 +010044 kv.first->OnBitrateUpdated(kv.second, last_fraction_loss_, last_rtt_);
sprang2f48d942015-11-05 04:25:49 -080045 allocated_bitrate_bps += kv.second;
46 }
47 return allocated_bitrate_bps;
Stefan Holmere5904162015-03-26 11:11:06 +010048}
49
50BitrateAllocator::ObserverBitrateMap BitrateAllocator::AllocateBitrates() {
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000051 if (bitrate_observers_.empty())
Stefan Holmere5904162015-03-26 11:11:06 +010052 return ObserverBitrateMap();
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000053
54 uint32_t sum_min_bitrates = 0;
Stefan Holmere5904162015-03-26 11:11:06 +010055 for (const auto& observer : bitrate_observers_)
Peter Boström8e4e8b02015-09-15 15:08:03 +020056 sum_min_bitrates += observer.second.min_bitrate;
Per28a44562016-05-04 17:12:51 +020057 if (last_bitrate_bps_ == 0)
58 return ZeroRateAllocation();
59 else if (last_bitrate_bps_ <= sum_min_bitrates)
Stefan Holmere5904162015-03-26 11:11:06 +010060 return LowRateAllocation(last_bitrate_bps_);
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000061 else
Stefan Holmere5904162015-03-26 11:11:06 +010062 return NormalRateAllocation(last_bitrate_bps_, sum_min_bitrates);
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000063}
64
mflodman86aabb22016-03-11 15:44:32 +010065int BitrateAllocator::AddObserver(BitrateAllocatorObserver* observer,
66 uint32_t min_bitrate_bps,
67 uint32_t max_bitrate_bps) {
tommi63cb4342016-01-20 02:32:54 -080068 rtc::CritScope lock(&crit_sect_);
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000069
70 BitrateObserverConfList::iterator it =
71 FindObserverConfigurationPair(observer);
72
Stefan Holmere5904162015-03-26 11:11:06 +010073 // Allow the max bitrate to be exceeded for FEC and retransmissions.
74 // TODO(holmer): We have to get rid of this hack as it makes it difficult to
75 // properly allocate bitrate. The allocator should instead distribute any
76 // extra bitrate after all streams have maxed out.
77 max_bitrate_bps *= kTransmissionMaxBitrateMultiplier;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000078 if (it != bitrate_observers_.end()) {
79 // Update current configuration.
Peter Boström8e4e8b02015-09-15 15:08:03 +020080 it->second.min_bitrate = min_bitrate_bps;
81 it->second.max_bitrate = max_bitrate_bps;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000082 } else {
83 // Add new settings.
84 bitrate_observers_.push_back(BitrateObserverConfiguration(
Peter Boström8e4e8b02015-09-15 15:08:03 +020085 observer, BitrateConfiguration(min_bitrate_bps, max_bitrate_bps)));
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000086 bitrate_observers_modified_ = true;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000087 }
Stefan Holmere5904162015-03-26 11:11:06 +010088
Stefan Holmere5904162015-03-26 11:11:06 +010089 ObserverBitrateMap allocation = AllocateBitrates();
Peter Boström8e4e8b02015-09-15 15:08:03 +020090 int new_observer_bitrate_bps = 0;
Stefan Holmere5904162015-03-26 11:11:06 +010091 for (auto& kv : allocation) {
mflodman86aabb22016-03-11 15:44:32 +010092 kv.first->OnBitrateUpdated(kv.second, last_fraction_loss_, last_rtt_);
Stefan Holmere5904162015-03-26 11:11:06 +010093 if (kv.first == observer)
Peter Boström8e4e8b02015-09-15 15:08:03 +020094 new_observer_bitrate_bps = kv.second;
Stefan Holmere5904162015-03-26 11:11:06 +010095 }
Peter Boström8e4e8b02015-09-15 15:08:03 +020096 return new_observer_bitrate_bps;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000097}
98
mflodman86aabb22016-03-11 15:44:32 +010099void BitrateAllocator::RemoveObserver(BitrateAllocatorObserver* observer) {
tommi63cb4342016-01-20 02:32:54 -0800100 rtc::CritScope lock(&crit_sect_);
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000101 BitrateObserverConfList::iterator it =
102 FindObserverConfigurationPair(observer);
103 if (it != bitrate_observers_.end()) {
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000104 bitrate_observers_.erase(it);
105 bitrate_observers_modified_ = true;
106 }
107}
108
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000109BitrateAllocator::BitrateObserverConfList::iterator
110BitrateAllocator::FindObserverConfigurationPair(
mflodman86aabb22016-03-11 15:44:32 +0100111 const BitrateAllocatorObserver* observer) {
Stefan Holmere5904162015-03-26 11:11:06 +0100112 for (auto it = bitrate_observers_.begin(); it != bitrate_observers_.end();
113 ++it) {
114 if (it->first == observer)
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000115 return it;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000116 }
117 return bitrate_observers_.end();
118}
119
120void BitrateAllocator::EnforceMinBitrate(bool enforce_min_bitrate) {
tommi63cb4342016-01-20 02:32:54 -0800121 rtc::CritScope lock(&crit_sect_);
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000122 enforce_min_bitrate_ = enforce_min_bitrate;
123}
124
Stefan Holmere5904162015-03-26 11:11:06 +0100125BitrateAllocator::ObserverBitrateMap BitrateAllocator::NormalRateAllocation(
126 uint32_t bitrate,
127 uint32_t sum_min_bitrates) {
mflodman0e7e2592015-11-12 21:02:42 -0800128 uint32_t number_of_observers =
129 static_cast<uint32_t>(bitrate_observers_.size());
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000130 uint32_t bitrate_per_observer =
131 (bitrate - sum_min_bitrates) / number_of_observers;
132 // Use map to sort list based on max bitrate.
133 ObserverSortingMap list_max_bitrates;
Stefan Holmere5904162015-03-26 11:11:06 +0100134 for (const auto& observer : bitrate_observers_) {
135 list_max_bitrates.insert(std::pair<uint32_t, ObserverConfiguration>(
Peter Boström8e4e8b02015-09-15 15:08:03 +0200136 observer.second.max_bitrate,
137 ObserverConfiguration(observer.first, observer.second.min_bitrate)));
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000138 }
Stefan Holmere5904162015-03-26 11:11:06 +0100139 ObserverBitrateMap allocation;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000140 ObserverSortingMap::iterator max_it = list_max_bitrates.begin();
141 while (max_it != list_max_bitrates.end()) {
142 number_of_observers--;
143 uint32_t observer_allowance =
Peter Boström8e4e8b02015-09-15 15:08:03 +0200144 max_it->second.min_bitrate + bitrate_per_observer;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000145 if (max_it->first < observer_allowance) {
146 // We have more than enough for this observer.
147 // Carry the remainder forward.
148 uint32_t remainder = observer_allowance - max_it->first;
149 if (number_of_observers != 0) {
150 bitrate_per_observer += remainder / number_of_observers;
151 }
Peter Boström8e4e8b02015-09-15 15:08:03 +0200152 allocation[max_it->second.observer] = max_it->first;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000153 } else {
Peter Boström8e4e8b02015-09-15 15:08:03 +0200154 allocation[max_it->second.observer] = observer_allowance;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000155 }
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000156 list_max_bitrates.erase(max_it);
157 // Prepare next iteration.
158 max_it = list_max_bitrates.begin();
159 }
Stefan Holmere5904162015-03-26 11:11:06 +0100160 return allocation;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000161}
162
Per28a44562016-05-04 17:12:51 +0200163BitrateAllocator::ObserverBitrateMap BitrateAllocator::ZeroRateAllocation() {
164 ObserverBitrateMap allocation;
165 // Zero bitrate to all observers.
166 for (const auto& observer : bitrate_observers_)
167 allocation[observer.first] = 0;
168 return allocation;
169}
170
Stefan Holmere5904162015-03-26 11:11:06 +0100171BitrateAllocator::ObserverBitrateMap BitrateAllocator::LowRateAllocation(
172 uint32_t bitrate) {
173 ObserverBitrateMap allocation;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000174 if (enforce_min_bitrate_) {
175 // Min bitrate to all observers.
Stefan Holmere5904162015-03-26 11:11:06 +0100176 for (const auto& observer : bitrate_observers_)
Peter Boström8e4e8b02015-09-15 15:08:03 +0200177 allocation[observer.first] = observer.second.min_bitrate;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000178 } else {
Peter Boström8e4e8b02015-09-15 15:08:03 +0200179 // Allocate up to |min_bitrate| to one observer at a time, until
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000180 // |bitrate| is depleted.
181 uint32_t remainder = bitrate;
Stefan Holmere5904162015-03-26 11:11:06 +0100182 for (const auto& observer : bitrate_observers_) {
183 uint32_t allocated_bitrate =
Peter Boström8e4e8b02015-09-15 15:08:03 +0200184 std::min(remainder, observer.second.min_bitrate);
Stefan Holmere5904162015-03-26 11:11:06 +0100185 allocation[observer.first] = allocated_bitrate;
186 remainder -= allocated_bitrate;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000187 }
188 }
Stefan Holmere5904162015-03-26 11:11:06 +0100189 return allocation;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000190}
191} // namespace webrtc