OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 * | 9 * |
10 */ | 10 */ |
11 | 11 |
12 #include "webrtc/call/bitrate_allocator.h" | 12 #include "webrtc/call/bitrate_allocator.h" |
13 | 13 |
14 #include <algorithm> | 14 #include <algorithm> |
15 #include <utility> | 15 #include <utility> |
16 | 16 |
17 #include "webrtc/base/checks.h" | 17 #include "webrtc/base/checks.h" |
18 #include "webrtc/modules/bitrate_controller/include/bitrate_controller.h" | 18 #include "webrtc/modules/bitrate_controller/include/bitrate_controller.h" |
19 | 19 |
20 namespace webrtc { | 20 namespace webrtc { |
21 | 21 |
22 // Allow packets to be transmitted in up to 2 times max video bitrate if the | 22 // Allow packets to be transmitted in up to 2 times max video bitrate if the |
23 // bandwidth estimate allows it. | 23 // bandwidth estimate allows it. |
24 const int kTransmissionMaxBitrateMultiplier = 2; | 24 const int kTransmissionMaxBitrateMultiplier = 2; |
25 const int kDefaultBitrateBps = 300000; | 25 const int kDefaultBitrateBps = 300000; |
26 | 26 |
27 BitrateAllocator::BitrateAllocator() | 27 BitrateAllocator::BitrateAllocator(LimitObserver* limit_observer) |
28 : bitrate_observer_configs_(), | 28 : limit_observer_(limit_observer), |
29 bitrate_observer_configs_(), | |
29 enforce_min_bitrate_(true), | 30 enforce_min_bitrate_(true), |
30 last_bitrate_bps_(kDefaultBitrateBps), | 31 last_bitrate_bps_(kDefaultBitrateBps), |
31 last_non_zero_bitrate_bps_(kDefaultBitrateBps), | 32 last_non_zero_bitrate_bps_(kDefaultBitrateBps), |
32 last_fraction_loss_(0), | 33 last_fraction_loss_(0), |
33 last_rtt_(0) {} | 34 last_rtt_(0) {} |
34 | 35 |
35 uint32_t BitrateAllocator::OnNetworkChanged(uint32_t bitrate, | 36 void BitrateAllocator::OnNetworkChanged(uint32_t bitrate, |
36 uint8_t fraction_loss, | 37 uint8_t fraction_loss, |
37 int64_t rtt) { | 38 int64_t rtt) { |
38 rtc::CritScope lock(&crit_sect_); | 39 rtc::CritScope lock(&crit_sect_); |
39 last_bitrate_bps_ = bitrate; | 40 last_bitrate_bps_ = bitrate; |
40 last_non_zero_bitrate_bps_ = | 41 last_non_zero_bitrate_bps_ = |
41 bitrate > 0 ? bitrate : last_non_zero_bitrate_bps_; | 42 bitrate > 0 ? bitrate : last_non_zero_bitrate_bps_; |
42 last_fraction_loss_ = fraction_loss; | 43 last_fraction_loss_ = fraction_loss; |
43 last_rtt_ = rtt; | 44 last_rtt_ = rtt; |
44 | 45 |
45 uint32_t allocated_bitrate_bps = 0; | |
46 ObserverAllocation allocation = AllocateBitrates(bitrate); | 46 ObserverAllocation allocation = AllocateBitrates(bitrate); |
47 for (const auto& kv : allocation) { | 47 for (const auto& kv : allocation) { |
48 kv.first->OnBitrateUpdated(kv.second, last_fraction_loss_, last_rtt_); | 48 kv.first->OnBitrateUpdated(kv.second, last_fraction_loss_, last_rtt_); |
49 allocated_bitrate_bps += kv.second; | |
50 } | 49 } |
51 return allocated_bitrate_bps; | |
52 } | 50 } |
53 | 51 |
54 int BitrateAllocator::AddObserver(BitrateAllocatorObserver* observer, | 52 int BitrateAllocator::AddObserver(BitrateAllocatorObserver* observer, |
55 uint32_t min_bitrate_bps, | 53 uint32_t min_bitrate_bps, |
56 uint32_t max_bitrate_bps, | 54 uint32_t max_bitrate_bps, |
55 uint32_t pad_up_bitrate_bps, | |
57 bool enforce_min_bitrate) { | 56 bool enforce_min_bitrate) { |
58 rtc::CritScope lock(&crit_sect_); | 57 rtc::CritScope lock(&crit_sect_); |
59 // TODO(mflodman): Enforce this per observer. | 58 // TODO(mflodman): Enforce this per observer. |
60 EnforceMinBitrate(enforce_min_bitrate); | 59 EnforceMinBitrate(enforce_min_bitrate); |
61 | 60 |
62 auto it = FindObserverConfig(observer); | 61 auto it = FindObserverConfig(observer); |
63 | 62 |
64 // Allow the max bitrate to be exceeded for FEC and retransmissions. | 63 // Allow the max bitrate to be exceeded for FEC and retransmissions. |
65 // TODO(holmer): We have to get rid of this hack as it makes it difficult to | 64 // TODO(holmer): We have to get rid of this hack as it makes it difficult to |
66 // properly allocate bitrate. The allocator should instead distribute any | 65 // properly allocate bitrate. The allocator should instead distribute any |
67 // extra bitrate after all streams have maxed out. | 66 // extra bitrate after all streams have maxed out. |
68 max_bitrate_bps *= kTransmissionMaxBitrateMultiplier; | 67 max_bitrate_bps *= kTransmissionMaxBitrateMultiplier; |
69 if (it != bitrate_observer_configs_.end()) { | 68 if (it != bitrate_observer_configs_.end()) { |
70 // Update current configuration. | 69 // Update current configuration. |
71 it->min_bitrate_bps = min_bitrate_bps; | 70 it->min_bitrate_bps = min_bitrate_bps; |
72 it->max_bitrate_bps = max_bitrate_bps; | 71 it->max_bitrate_bps = max_bitrate_bps; |
72 it->pad_up_bitrate_bps = pad_up_bitrate_bps; | |
73 } else { | 73 } else { |
74 // Add new settings. | 74 // Add new settings. |
75 bitrate_observer_configs_.push_back(ObserverConfig( | 75 bitrate_observer_configs_.push_back( |
76 observer, min_bitrate_bps, max_bitrate_bps, enforce_min_bitrate)); | 76 ObserverConfig(observer, min_bitrate_bps, max_bitrate_bps, |
77 pad_up_bitrate_bps, enforce_min_bitrate)); | |
77 } | 78 } |
78 | 79 |
79 int new_observer_bitrate_bps = 0; | 80 int new_observer_bitrate_bps = 0; |
80 if (last_bitrate_bps_ > 0) { // We have a bitrate to allocate. | 81 if (last_bitrate_bps_ > 0) { // We have a bitrate to allocate. |
81 ObserverAllocation allocation = AllocateBitrates(last_bitrate_bps_); | 82 ObserverAllocation allocation = AllocateBitrates(last_bitrate_bps_); |
82 for (auto& kv : allocation) { | 83 for (auto& kv : allocation) { |
83 // Update all observers with the new allocation. | 84 // Update all observers with the new allocation. |
84 kv.first->OnBitrateUpdated(kv.second, last_fraction_loss_, last_rtt_); | 85 kv.first->OnBitrateUpdated(kv.second, last_fraction_loss_, last_rtt_); |
85 if (kv.first == observer) | 86 if (kv.first == observer) |
86 new_observer_bitrate_bps = kv.second; | 87 new_observer_bitrate_bps = kv.second; |
87 } | 88 } |
88 } else { | 89 } else { |
89 // Currently, an encoder is not allowed to produce frames. | 90 // Currently, an encoder is not allowed to produce frames. |
90 // But we still have to return the initial config bitrate + let the | 91 // But we still have to return the initial config bitrate + let the |
91 // observer know that it can not produce frames. | 92 // observer know that it can not produce frames. |
92 ObserverAllocation allocation = | 93 ObserverAllocation allocation = |
93 AllocateBitrates(last_non_zero_bitrate_bps_); | 94 AllocateBitrates(last_non_zero_bitrate_bps_); |
94 observer->OnBitrateUpdated(0, last_fraction_loss_, last_rtt_); | 95 observer->OnBitrateUpdated(0, last_fraction_loss_, last_rtt_); |
95 new_observer_bitrate_bps = allocation[observer]; | 96 new_observer_bitrate_bps = allocation[observer]; |
96 } | 97 } |
98 | |
99 UpdateAllocationLimits(); | |
100 | |
97 return new_observer_bitrate_bps; | 101 return new_observer_bitrate_bps; |
98 } | 102 } |
99 | 103 |
104 void BitrateAllocator::NotifyObserverInactive( | |
mflodman
2016/06/08 10:18:31
Can we in this case just remove the observer inste
perkj_webrtc
2016/06/08 15:35:27
Seems like that is what stefan suggests too.
| |
105 BitrateAllocatorObserver* observer, | |
106 bool inactive) { | |
107 rtc::CritScope lock(&crit_sect_); | |
108 auto iter = std::find_if( | |
109 bitrate_observer_configs_.begin(), bitrate_observer_configs_.end(), | |
110 [observer](const ObserverConfig& c) { return c.observer == observer; }); | |
111 RTC_DCHECK(iter != bitrate_observer_configs_.end()); | |
112 iter->active = !inactive; | |
113 | |
114 UpdateAllocationLimits(); | |
115 } | |
116 | |
117 void BitrateAllocator::UpdateAllocationLimits() { | |
118 uint32_t total_requested_padding_bitrate = 0; | |
119 uint32_t total_requested_min_bitrate = 0; | |
120 | |
121 for (const auto& config : bitrate_observer_configs_) { | |
122 if (enforce_min_bitrate_) { | |
123 total_requested_min_bitrate += config.min_bitrate_bps; | |
124 } | |
125 if (config.active) | |
126 total_requested_padding_bitrate += config.pad_up_bitrate_bps; | |
127 } | |
128 crit_sect_.Leave(); | |
stefan-webrtc
2016/06/08 09:25:13
I don't like this... Can we make sure we can OnAll
perkj_webrtc
2016/06/08 15:35:27
Yes, but with code duplication. Do you have a sugg
| |
129 limit_observer_->OnAllocationLimitsChanged(total_requested_min_bitrate, | |
130 total_requested_padding_bitrate); | |
131 crit_sect_.Enter(); | |
132 } | |
133 | |
100 void BitrateAllocator::RemoveObserver(BitrateAllocatorObserver* observer) { | 134 void BitrateAllocator::RemoveObserver(BitrateAllocatorObserver* observer) { |
101 rtc::CritScope lock(&crit_sect_); | 135 rtc::CritScope lock(&crit_sect_); |
102 auto it = FindObserverConfig(observer); | 136 auto it = FindObserverConfig(observer); |
103 if (it != bitrate_observer_configs_.end()) { | 137 if (it != bitrate_observer_configs_.end()) { |
104 bitrate_observer_configs_.erase(it); | 138 bitrate_observer_configs_.erase(it); |
105 } | 139 } |
140 UpdateAllocationLimits(); | |
106 } | 141 } |
107 | 142 |
108 void BitrateAllocator::EnforceMinBitrate(bool enforce_min_bitrate) { | 143 void BitrateAllocator::EnforceMinBitrate(bool enforce_min_bitrate) { |
109 enforce_min_bitrate_ = enforce_min_bitrate; | 144 enforce_min_bitrate_ = enforce_min_bitrate; |
110 } | 145 } |
111 | 146 |
112 BitrateAllocator::ObserverConfigList::iterator | 147 BitrateAllocator::ObserverConfigList::iterator |
113 BitrateAllocator::FindObserverConfig( | 148 BitrateAllocator::FindObserverConfig( |
114 const BitrateAllocatorObserver* observer) { | 149 const BitrateAllocatorObserver* observer) { |
115 for (auto it = bitrate_observer_configs_.begin(); | 150 for (auto it = bitrate_observer_configs_.begin(); |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
198 for (const auto& observer_config : bitrate_observer_configs_) { | 233 for (const auto& observer_config : bitrate_observer_configs_) { |
199 uint32_t allocated_bitrate = | 234 uint32_t allocated_bitrate = |
200 std::min(remainder, observer_config.min_bitrate_bps); | 235 std::min(remainder, observer_config.min_bitrate_bps); |
201 allocation[observer_config.observer] = allocated_bitrate; | 236 allocation[observer_config.observer] = allocated_bitrate; |
202 remainder -= allocated_bitrate; | 237 remainder -= allocated_bitrate; |
203 } | 238 } |
204 } | 239 } |
205 return allocation; | 240 return allocation; |
206 } | 241 } |
207 } // namespace webrtc | 242 } // namespace webrtc |
OLD | NEW |