Chromium Code Reviews| 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 |