Break out allocation from BitrateController into a BitrateAllocator.
This also refactors some of the padding and allocation code in ViEEncoder, and makes ChannelGroup a simple forwarder from BitrateController to BitrateAllocator. This CL is part of a bigger picture, see https://review.webrtc.org/35319004/ for details. BUG=4323 R=mflodman@webrtc.org, pbos@webrtc.org, sprang@webrtc.org Review URL: https://webrtc-codereview.appspot.com/44399004 Cr-Commit-Position: refs/heads/master@{#8595} git-svn-id: http://webrtc.googlecode.com/svn/trunk@8595 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
61c22aca5f
commit
792f1a14e2
@ -10,8 +10,10 @@ import("../../build/webrtc.gni")
|
|||||||
|
|
||||||
source_set("bitrate_controller") {
|
source_set("bitrate_controller") {
|
||||||
sources = [
|
sources = [
|
||||||
|
"bitrate_allocator.cc",
|
||||||
"bitrate_controller_impl.cc",
|
"bitrate_controller_impl.cc",
|
||||||
"bitrate_controller_impl.h",
|
"bitrate_controller_impl.h",
|
||||||
|
"include/bitrate_allocator.h",
|
||||||
"include/bitrate_controller.h",
|
"include/bitrate_controller.h",
|
||||||
"remb_suppressor.cc",
|
"remb_suppressor.cc",
|
||||||
"remb_suppressor.h",
|
"remb_suppressor.h",
|
||||||
|
205
webrtc/modules/bitrate_controller/bitrate_allocator.cc
Normal file
205
webrtc/modules/bitrate_controller/bitrate_allocator.cc
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license
|
||||||
|
* that can be found in the LICENSE file in the root of the source
|
||||||
|
* tree. An additional intellectual property rights grant can be found
|
||||||
|
* in the file PATENTS. All contributing project authors may
|
||||||
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "webrtc/modules/bitrate_controller/include/bitrate_allocator.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
|
||||||
|
BitrateAllocator::BitrateAllocator()
|
||||||
|
: crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
|
||||||
|
bitrate_observers_(),
|
||||||
|
enforce_min_bitrate_(true) {
|
||||||
|
}
|
||||||
|
|
||||||
|
BitrateAllocator::~BitrateAllocator() {
|
||||||
|
for (auto& kv : bitrate_observers_)
|
||||||
|
delete kv.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BitrateAllocator::OnNetworkChanged(uint32_t bitrate,
|
||||||
|
uint8_t fraction_loss,
|
||||||
|
int64_t rtt) {
|
||||||
|
CriticalSectionScoped lock(crit_sect_.get());
|
||||||
|
// Sanity check.
|
||||||
|
if (bitrate_observers_.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint32_t sum_min_bitrates = 0;
|
||||||
|
BitrateObserverConfList::iterator it;
|
||||||
|
for (auto& kv : bitrate_observers_)
|
||||||
|
sum_min_bitrates += kv.second->min_bitrate_;
|
||||||
|
if (bitrate <= sum_min_bitrates)
|
||||||
|
return LowRateAllocation(bitrate, fraction_loss, rtt, sum_min_bitrates);
|
||||||
|
else
|
||||||
|
return NormalRateAllocation(bitrate, fraction_loss, rtt, sum_min_bitrates);
|
||||||
|
}
|
||||||
|
|
||||||
|
int BitrateAllocator::AddBitrateObserver(BitrateObserver* observer,
|
||||||
|
uint32_t start_bitrate,
|
||||||
|
uint32_t min_bitrate,
|
||||||
|
uint32_t max_bitrate) {
|
||||||
|
CriticalSectionScoped lock(crit_sect_.get());
|
||||||
|
|
||||||
|
BitrateObserverConfList::iterator it =
|
||||||
|
FindObserverConfigurationPair(observer);
|
||||||
|
|
||||||
|
int new_bwe_candidate_bps = -1;
|
||||||
|
if (it != bitrate_observers_.end()) {
|
||||||
|
// Update current configuration.
|
||||||
|
it->second->start_bitrate_ = start_bitrate;
|
||||||
|
it->second->min_bitrate_ = min_bitrate;
|
||||||
|
it->second->max_bitrate_ = max_bitrate;
|
||||||
|
// Set the send-side bandwidth to the max of the sum of start bitrates and
|
||||||
|
// the current estimate, so that if the user wants to immediately use more
|
||||||
|
// bandwidth, that can be enforced.
|
||||||
|
new_bwe_candidate_bps = 0;
|
||||||
|
for (auto& kv : bitrate_observers_)
|
||||||
|
new_bwe_candidate_bps += kv.second->start_bitrate_;
|
||||||
|
} else {
|
||||||
|
// Add new settings.
|
||||||
|
bitrate_observers_.push_back(BitrateObserverConfiguration(
|
||||||
|
observer,
|
||||||
|
new BitrateConfiguration(start_bitrate, min_bitrate, max_bitrate)));
|
||||||
|
bitrate_observers_modified_ = true;
|
||||||
|
|
||||||
|
// TODO(andresp): This is a ugly way to set start bitrate.
|
||||||
|
//
|
||||||
|
// Only change start bitrate if we have exactly one observer. By definition
|
||||||
|
// you can only have one start bitrate, once we have our first estimate we
|
||||||
|
// will adapt from there.
|
||||||
|
if (bitrate_observers_.size() == 1)
|
||||||
|
new_bwe_candidate_bps = start_bitrate;
|
||||||
|
}
|
||||||
|
return new_bwe_candidate_bps;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BitrateAllocator::RemoveBitrateObserver(BitrateObserver* observer) {
|
||||||
|
CriticalSectionScoped lock(crit_sect_.get());
|
||||||
|
BitrateObserverConfList::iterator it =
|
||||||
|
FindObserverConfigurationPair(observer);
|
||||||
|
if (it != bitrate_observers_.end()) {
|
||||||
|
delete it->second;
|
||||||
|
bitrate_observers_.erase(it);
|
||||||
|
bitrate_observers_modified_ = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BitrateAllocator::GetMinMaxBitrateSumBps(int* min_bitrate_sum_bps,
|
||||||
|
int* max_bitrate_sum_bps) const {
|
||||||
|
*min_bitrate_sum_bps = 0;
|
||||||
|
*max_bitrate_sum_bps = 0;
|
||||||
|
|
||||||
|
CriticalSectionScoped lock(crit_sect_.get());
|
||||||
|
BitrateObserverConfList::const_iterator it;
|
||||||
|
for (it = bitrate_observers_.begin(); it != bitrate_observers_.end(); ++it) {
|
||||||
|
*min_bitrate_sum_bps += it->second->min_bitrate_;
|
||||||
|
*max_bitrate_sum_bps += it->second->max_bitrate_;
|
||||||
|
}
|
||||||
|
if (*max_bitrate_sum_bps == 0) {
|
||||||
|
// No max configured use 1Gbit/s.
|
||||||
|
*max_bitrate_sum_bps = 1000000000;
|
||||||
|
}
|
||||||
|
// TODO(holmer): Enforcing a min bitrate should be per stream, allowing some
|
||||||
|
// streams to auto-mute while others keep sending.
|
||||||
|
if (!enforce_min_bitrate_) {
|
||||||
|
// If not enforcing min bitrate, allow the bandwidth estimation to
|
||||||
|
// go as low as 10 kbps.
|
||||||
|
*min_bitrate_sum_bps = std::min(*min_bitrate_sum_bps, 10000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BitrateAllocator::BitrateObserverConfList::iterator
|
||||||
|
BitrateAllocator::FindObserverConfigurationPair(
|
||||||
|
const BitrateObserver* observer) {
|
||||||
|
BitrateObserverConfList::iterator it = bitrate_observers_.begin();
|
||||||
|
for (; it != bitrate_observers_.end(); ++it) {
|
||||||
|
if (it->first == observer) {
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bitrate_observers_.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BitrateAllocator::EnforceMinBitrate(bool enforce_min_bitrate) {
|
||||||
|
CriticalSectionScoped lock(crit_sect_.get());
|
||||||
|
enforce_min_bitrate_ = enforce_min_bitrate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BitrateAllocator::NormalRateAllocation(uint32_t bitrate,
|
||||||
|
uint8_t fraction_loss,
|
||||||
|
int64_t rtt,
|
||||||
|
uint32_t sum_min_bitrates) {
|
||||||
|
uint32_t number_of_observers = bitrate_observers_.size();
|
||||||
|
uint32_t bitrate_per_observer =
|
||||||
|
(bitrate - sum_min_bitrates) / number_of_observers;
|
||||||
|
// Use map to sort list based on max bitrate.
|
||||||
|
ObserverSortingMap list_max_bitrates;
|
||||||
|
BitrateObserverConfList::iterator it;
|
||||||
|
for (it = bitrate_observers_.begin(); it != bitrate_observers_.end(); ++it) {
|
||||||
|
list_max_bitrates.insert(std::pair<uint32_t, ObserverConfiguration*>(
|
||||||
|
it->second->max_bitrate_,
|
||||||
|
new ObserverConfiguration(it->first, it->second->min_bitrate_)));
|
||||||
|
}
|
||||||
|
ObserverSortingMap::iterator max_it = list_max_bitrates.begin();
|
||||||
|
while (max_it != list_max_bitrates.end()) {
|
||||||
|
number_of_observers--;
|
||||||
|
uint32_t observer_allowance =
|
||||||
|
max_it->second->min_bitrate_ + bitrate_per_observer;
|
||||||
|
if (max_it->first < observer_allowance) {
|
||||||
|
// We have more than enough for this observer.
|
||||||
|
// Carry the remainder forward.
|
||||||
|
uint32_t remainder = observer_allowance - max_it->first;
|
||||||
|
if (number_of_observers != 0) {
|
||||||
|
bitrate_per_observer += remainder / number_of_observers;
|
||||||
|
}
|
||||||
|
max_it->second->observer_->OnNetworkChanged(max_it->first, fraction_loss,
|
||||||
|
rtt);
|
||||||
|
} else {
|
||||||
|
max_it->second->observer_->OnNetworkChanged(observer_allowance,
|
||||||
|
fraction_loss, rtt);
|
||||||
|
}
|
||||||
|
delete max_it->second;
|
||||||
|
list_max_bitrates.erase(max_it);
|
||||||
|
// Prepare next iteration.
|
||||||
|
max_it = list_max_bitrates.begin();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BitrateAllocator::LowRateAllocation(uint32_t bitrate,
|
||||||
|
uint8_t fraction_loss,
|
||||||
|
int64_t rtt,
|
||||||
|
uint32_t sum_min_bitrates) {
|
||||||
|
if (enforce_min_bitrate_) {
|
||||||
|
// Min bitrate to all observers.
|
||||||
|
BitrateObserverConfList::iterator it;
|
||||||
|
for (it = bitrate_observers_.begin(); it != bitrate_observers_.end();
|
||||||
|
++it) {
|
||||||
|
it->first->OnNetworkChanged(it->second->min_bitrate_, fraction_loss, rtt);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Allocate up to |min_bitrate_| to one observer at a time, until
|
||||||
|
// |bitrate| is depleted.
|
||||||
|
uint32_t remainder = bitrate;
|
||||||
|
BitrateObserverConfList::iterator it;
|
||||||
|
for (it = bitrate_observers_.begin(); it != bitrate_observers_.end();
|
||||||
|
++it) {
|
||||||
|
uint32_t allocation = std::min(remainder, it->second->min_bitrate_);
|
||||||
|
it->first->OnNetworkChanged(allocation, fraction_loss, rtt);
|
||||||
|
remainder -= allocation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace webrtc
|
184
webrtc/modules/bitrate_controller/bitrate_allocator_unittest.cc
Normal file
184
webrtc/modules/bitrate_controller/bitrate_allocator_unittest.cc
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license
|
||||||
|
* that can be found in the LICENSE file in the root of the source
|
||||||
|
* tree. An additional intellectual property rights grant can be found
|
||||||
|
* in the file PATENTS. All contributing project authors may
|
||||||
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "testing/gtest/include/gtest/gtest.h"
|
||||||
|
#include "webrtc/modules/bitrate_controller/include/bitrate_allocator.h"
|
||||||
|
#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
|
||||||
|
class TestBitrateObserver : public BitrateObserver {
|
||||||
|
public:
|
||||||
|
TestBitrateObserver()
|
||||||
|
: last_bitrate_(0), last_fraction_loss_(0), last_rtt_(0) {}
|
||||||
|
|
||||||
|
virtual void OnNetworkChanged(uint32_t bitrate,
|
||||||
|
uint8_t fraction_loss,
|
||||||
|
int64_t rtt) {
|
||||||
|
last_bitrate_ = bitrate;
|
||||||
|
last_fraction_loss_ = fraction_loss;
|
||||||
|
last_rtt_ = rtt;
|
||||||
|
}
|
||||||
|
uint32_t last_bitrate_;
|
||||||
|
uint8_t last_fraction_loss_;
|
||||||
|
int64_t last_rtt_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BitrateAllocatorTest : public ::testing::Test {
|
||||||
|
protected:
|
||||||
|
BitrateAllocatorTest() : allocator_(new BitrateAllocator()) {}
|
||||||
|
~BitrateAllocatorTest() {}
|
||||||
|
|
||||||
|
rtc::scoped_ptr<BitrateAllocator> allocator_;
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(BitrateAllocatorTest, UpdatingBitrateObserver) {
|
||||||
|
TestBitrateObserver bitrate_observer;
|
||||||
|
allocator_->AddBitrateObserver(&bitrate_observer, 200000, 100000, 1500000);
|
||||||
|
allocator_->OnNetworkChanged(200000, 0, 0);
|
||||||
|
EXPECT_EQ(200000u, bitrate_observer.last_bitrate_);
|
||||||
|
|
||||||
|
allocator_->AddBitrateObserver(&bitrate_observer, 1500000, 100000, 1500000);
|
||||||
|
allocator_->OnNetworkChanged(1500000, 0, 0);
|
||||||
|
EXPECT_EQ(1500000u, bitrate_observer.last_bitrate_);
|
||||||
|
|
||||||
|
allocator_->AddBitrateObserver(&bitrate_observer, 500000, 100000, 1500000);
|
||||||
|
allocator_->OnNetworkChanged(1500000, 0, 0);
|
||||||
|
EXPECT_EQ(1500000u, bitrate_observer.last_bitrate_);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(BitrateAllocatorTest, TwoBitrateObserversOneRtcpObserver) {
|
||||||
|
TestBitrateObserver bitrate_observer_1;
|
||||||
|
TestBitrateObserver bitrate_observer_2;
|
||||||
|
allocator_->AddBitrateObserver(&bitrate_observer_1, 200000, 100000, 300000);
|
||||||
|
allocator_->AddBitrateObserver(&bitrate_observer_2, 200000, 200000, 300000);
|
||||||
|
|
||||||
|
// Test too low start bitrate, hence lower than sum of min. Min bitrates will
|
||||||
|
// be allocated to all observers.
|
||||||
|
allocator_->OnNetworkChanged(200000, 0, 50);
|
||||||
|
EXPECT_EQ(100000u, bitrate_observer_1.last_bitrate_);
|
||||||
|
EXPECT_EQ(0, bitrate_observer_1.last_fraction_loss_);
|
||||||
|
EXPECT_EQ(50, bitrate_observer_1.last_rtt_);
|
||||||
|
EXPECT_EQ(200000u, bitrate_observer_2.last_bitrate_);
|
||||||
|
EXPECT_EQ(0, bitrate_observer_2.last_fraction_loss_);
|
||||||
|
EXPECT_EQ(50, bitrate_observer_2.last_rtt_);
|
||||||
|
|
||||||
|
// Test a bitrate which should be distributed equally.
|
||||||
|
allocator_->OnNetworkChanged(500000, 0, 50);
|
||||||
|
const uint32_t kBitrateToShare = 500000 - 200000 - 100000;
|
||||||
|
EXPECT_EQ(100000u + kBitrateToShare / 2, bitrate_observer_1.last_bitrate_);
|
||||||
|
EXPECT_EQ(200000u + kBitrateToShare / 2, bitrate_observer_2.last_bitrate_);
|
||||||
|
|
||||||
|
// Limited by max bitrates.
|
||||||
|
allocator_->OnNetworkChanged(800000, 0, 50);
|
||||||
|
EXPECT_EQ(300000u, bitrate_observer_1.last_bitrate_);
|
||||||
|
EXPECT_EQ(300000u, bitrate_observer_2.last_bitrate_);
|
||||||
|
}
|
||||||
|
|
||||||
|
class BitrateAllocatorTestNoEnforceMin : public ::testing::Test {
|
||||||
|
protected:
|
||||||
|
BitrateAllocatorTestNoEnforceMin() : allocator_(new BitrateAllocator()) {
|
||||||
|
allocator_->EnforceMinBitrate(false);
|
||||||
|
}
|
||||||
|
~BitrateAllocatorTestNoEnforceMin() {}
|
||||||
|
|
||||||
|
rtc::scoped_ptr<BitrateAllocator> allocator_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// The following three tests verify that the EnforceMinBitrate() method works
|
||||||
|
// as intended.
|
||||||
|
TEST_F(BitrateAllocatorTestNoEnforceMin, OneBitrateObserver) {
|
||||||
|
TestBitrateObserver bitrate_observer_1;
|
||||||
|
allocator_->AddBitrateObserver(&bitrate_observer_1, 200000, 100000, 400000);
|
||||||
|
|
||||||
|
// High REMB.
|
||||||
|
allocator_->OnNetworkChanged(150000, 0, 0);
|
||||||
|
EXPECT_EQ(150000u, bitrate_observer_1.last_bitrate_);
|
||||||
|
|
||||||
|
// Low REMB.
|
||||||
|
allocator_->OnNetworkChanged(10000, 0, 0);
|
||||||
|
EXPECT_EQ(10000u, bitrate_observer_1.last_bitrate_);
|
||||||
|
|
||||||
|
allocator_->RemoveBitrateObserver(&bitrate_observer_1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(BitrateAllocatorTestNoEnforceMin, ThreeBitrateObservers) {
|
||||||
|
TestBitrateObserver bitrate_observer_1;
|
||||||
|
TestBitrateObserver bitrate_observer_2;
|
||||||
|
TestBitrateObserver bitrate_observer_3;
|
||||||
|
// Set up the observers with min bitrates at 100000, 200000, and 300000.
|
||||||
|
// Note: The start bitrate of bitrate_observer_1 (700000) is used as the
|
||||||
|
// overall start bitrate.
|
||||||
|
allocator_->AddBitrateObserver(&bitrate_observer_1, 700000, 100000, 400000);
|
||||||
|
allocator_->AddBitrateObserver(&bitrate_observer_2, 200000, 200000, 400000);
|
||||||
|
allocator_->AddBitrateObserver(&bitrate_observer_3, 200000, 300000, 400000);
|
||||||
|
|
||||||
|
// High REMB. Make sure the controllers get a fair share of the surplus
|
||||||
|
// (i.e., what is left after each controller gets its min rate).
|
||||||
|
allocator_->OnNetworkChanged(690000, 0, 0);
|
||||||
|
// Verify that each observer gets its min rate (sum of min rates is 600000),
|
||||||
|
// and that the remaining 90000 is divided equally among the three.
|
||||||
|
const uint32_t kBitrateToShare = 690000u - 100000u - 200000u - 300000u;
|
||||||
|
EXPECT_EQ(100000u + kBitrateToShare / 3, bitrate_observer_1.last_bitrate_);
|
||||||
|
EXPECT_EQ(200000u + kBitrateToShare / 3, bitrate_observer_2.last_bitrate_);
|
||||||
|
EXPECT_EQ(300000u + kBitrateToShare / 3, bitrate_observer_3.last_bitrate_);
|
||||||
|
|
||||||
|
// High REMB, but below the sum of min bitrates.
|
||||||
|
allocator_->OnNetworkChanged(500000, 0, 0);
|
||||||
|
// Verify that the first and second observers get their min bitrates, and the
|
||||||
|
// third gets the remainder.
|
||||||
|
EXPECT_EQ(100000u, bitrate_observer_1.last_bitrate_); // Min bitrate.
|
||||||
|
EXPECT_EQ(200000u, bitrate_observer_2.last_bitrate_); // Min bitrate.
|
||||||
|
EXPECT_EQ(200000u, bitrate_observer_3.last_bitrate_); // Remainder.
|
||||||
|
|
||||||
|
// Low REMB.
|
||||||
|
allocator_->OnNetworkChanged(10000, 0, 0);
|
||||||
|
// Verify that the first observer gets all the rate, and the rest get zero.
|
||||||
|
EXPECT_EQ(10000u, bitrate_observer_1.last_bitrate_);
|
||||||
|
EXPECT_EQ(0u, bitrate_observer_2.last_bitrate_);
|
||||||
|
EXPECT_EQ(0u, bitrate_observer_3.last_bitrate_);
|
||||||
|
|
||||||
|
allocator_->RemoveBitrateObserver(&bitrate_observer_1);
|
||||||
|
allocator_->RemoveBitrateObserver(&bitrate_observer_2);
|
||||||
|
allocator_->RemoveBitrateObserver(&bitrate_observer_3);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(BitrateAllocatorTestNoEnforceMin, Honors10KbpsLimit) {
|
||||||
|
TestBitrateObserver bitrate_observer;
|
||||||
|
allocator_->AddBitrateObserver(&bitrate_observer, 700000, 30000, 400000);
|
||||||
|
|
||||||
|
int min_bitrate = 0;
|
||||||
|
int max_bitrate = 0;
|
||||||
|
allocator_->GetMinMaxBitrateSumBps(&min_bitrate, &max_bitrate);
|
||||||
|
EXPECT_EQ(10000, min_bitrate);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(BitrateAllocatorTest, ThreeBitrateObserversLowRembEnforceMin) {
|
||||||
|
TestBitrateObserver bitrate_observer_1;
|
||||||
|
TestBitrateObserver bitrate_observer_2;
|
||||||
|
TestBitrateObserver bitrate_observer_3;
|
||||||
|
allocator_->AddBitrateObserver(&bitrate_observer_1, 200000, 100000, 300000);
|
||||||
|
allocator_->AddBitrateObserver(&bitrate_observer_2, 200000, 200000, 300000);
|
||||||
|
allocator_->AddBitrateObserver(&bitrate_observer_3, 200000, 300000, 300000);
|
||||||
|
|
||||||
|
// Low REMB. Verify that all observers still get their respective min bitrate.
|
||||||
|
allocator_->OnNetworkChanged(1000, 0, 0);
|
||||||
|
EXPECT_EQ(100000u, bitrate_observer_1.last_bitrate_); // Min cap.
|
||||||
|
EXPECT_EQ(200000u, bitrate_observer_2.last_bitrate_); // Min cap.
|
||||||
|
EXPECT_EQ(300000u, bitrate_observer_3.last_bitrate_); // Min cap.
|
||||||
|
|
||||||
|
allocator_->RemoveBitrateObserver(&bitrate_observer_1);
|
||||||
|
allocator_->RemoveBitrateObserver(&bitrate_observer_2);
|
||||||
|
allocator_->RemoveBitrateObserver(&bitrate_observer_3);
|
||||||
|
}
|
||||||
|
} // namespace webrtc
|
@ -15,9 +15,11 @@
|
|||||||
'<(webrtc_root)/system_wrappers/system_wrappers.gyp:system_wrappers',
|
'<(webrtc_root)/system_wrappers/system_wrappers.gyp:system_wrappers',
|
||||||
],
|
],
|
||||||
'sources': [
|
'sources': [
|
||||||
|
'bitrate_allocator.cc',
|
||||||
'bitrate_controller_impl.cc',
|
'bitrate_controller_impl.cc',
|
||||||
'bitrate_controller_impl.h',
|
'bitrate_controller_impl.h',
|
||||||
'include/bitrate_controller.h',
|
'include/bitrate_controller.h',
|
||||||
|
'include/bitrate_allocator.h',
|
||||||
'remb_suppressor.cc',
|
'remb_suppressor.cc',
|
||||||
'remb_suppressor.h',
|
'remb_suppressor.h',
|
||||||
'send_side_bandwidth_estimation.cc',
|
'send_side_bandwidth_estimation.cc',
|
||||||
|
@ -79,35 +79,26 @@ class BitrateControllerImpl::RtcpBandwidthObserverImpl
|
|||||||
|
|
||||||
BitrateController* BitrateController::CreateBitrateController(
|
BitrateController* BitrateController::CreateBitrateController(
|
||||||
Clock* clock,
|
Clock* clock,
|
||||||
bool enforce_min_bitrate) {
|
BitrateObserver* observer) {
|
||||||
return new BitrateControllerImpl(clock, enforce_min_bitrate);
|
return new BitrateControllerImpl(clock, observer);
|
||||||
}
|
}
|
||||||
|
|
||||||
BitrateControllerImpl::BitrateControllerImpl(Clock* clock,
|
BitrateControllerImpl::BitrateControllerImpl(Clock* clock,
|
||||||
bool enforce_min_bitrate)
|
BitrateObserver* observer)
|
||||||
: clock_(clock),
|
: clock_(clock),
|
||||||
|
observer_(observer),
|
||||||
last_bitrate_update_ms_(clock_->TimeInMilliseconds()),
|
last_bitrate_update_ms_(clock_->TimeInMilliseconds()),
|
||||||
critsect_(CriticalSectionWrapper::CreateCriticalSection()),
|
critsect_(CriticalSectionWrapper::CreateCriticalSection()),
|
||||||
bandwidth_estimation_(),
|
bandwidth_estimation_(),
|
||||||
bitrate_observers_(),
|
|
||||||
enforce_min_bitrate_(enforce_min_bitrate),
|
|
||||||
reserved_bitrate_bps_(0),
|
reserved_bitrate_bps_(0),
|
||||||
last_bitrate_bps_(0),
|
last_bitrate_bps_(0),
|
||||||
last_fraction_loss_(0),
|
last_fraction_loss_(0),
|
||||||
last_rtt_ms_(0),
|
last_rtt_ms_(0),
|
||||||
last_enforce_min_bitrate_(!enforce_min_bitrate_),
|
|
||||||
bitrate_observers_modified_(false),
|
|
||||||
last_reserved_bitrate_bps_(0),
|
last_reserved_bitrate_bps_(0),
|
||||||
remb_suppressor_(new RembSuppressor(clock)) {
|
remb_suppressor_(new RembSuppressor(clock)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
BitrateControllerImpl::~BitrateControllerImpl() {
|
BitrateControllerImpl::~BitrateControllerImpl() {
|
||||||
BitrateObserverConfList::iterator it = bitrate_observers_.begin();
|
|
||||||
while (it != bitrate_observers_.end()) {
|
|
||||||
delete it->second;
|
|
||||||
bitrate_observers_.erase(it);
|
|
||||||
it = bitrate_observers_.begin();
|
|
||||||
}
|
|
||||||
delete critsect_;
|
delete critsect_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,117 +106,33 @@ RtcpBandwidthObserver* BitrateControllerImpl::CreateRtcpBandwidthObserver() {
|
|||||||
return new RtcpBandwidthObserverImpl(this);
|
return new RtcpBandwidthObserverImpl(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
BitrateControllerImpl::BitrateObserverConfList::iterator
|
void BitrateControllerImpl::SetStartBitrate(int start_bitrate_bps) {
|
||||||
BitrateControllerImpl::FindObserverConfigurationPair(const BitrateObserver*
|
|
||||||
observer) {
|
|
||||||
BitrateObserverConfList::iterator it = bitrate_observers_.begin();
|
|
||||||
for (; it != bitrate_observers_.end(); ++it) {
|
|
||||||
if (it->first == observer) {
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return bitrate_observers_.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
void BitrateControllerImpl::SetBitrateObserver(
|
|
||||||
BitrateObserver* observer,
|
|
||||||
uint32_t start_bitrate,
|
|
||||||
uint32_t min_bitrate,
|
|
||||||
uint32_t max_bitrate) {
|
|
||||||
CriticalSectionScoped cs(critsect_);
|
CriticalSectionScoped cs(critsect_);
|
||||||
|
bandwidth_estimation_.SetSendBitrate(start_bitrate_bps);
|
||||||
BitrateObserverConfList::iterator it = FindObserverConfigurationPair(
|
|
||||||
observer);
|
|
||||||
|
|
||||||
if (it != bitrate_observers_.end()) {
|
|
||||||
// Update current configuration.
|
|
||||||
it->second->start_bitrate_ = start_bitrate;
|
|
||||||
it->second->min_bitrate_ = min_bitrate;
|
|
||||||
it->second->max_bitrate_ = max_bitrate;
|
|
||||||
// Set the send-side bandwidth to the max of the sum of start bitrates and
|
|
||||||
// the current estimate, so that if the user wants to immediately use more
|
|
||||||
// bandwidth, that can be enforced.
|
|
||||||
uint32_t sum_start_bitrate = 0;
|
|
||||||
BitrateObserverConfList::iterator it;
|
|
||||||
for (it = bitrate_observers_.begin(); it != bitrate_observers_.end();
|
|
||||||
++it) {
|
|
||||||
sum_start_bitrate += it->second->start_bitrate_;
|
|
||||||
}
|
|
||||||
uint32_t current_estimate;
|
|
||||||
uint8_t loss;
|
|
||||||
int64_t rtt;
|
|
||||||
bandwidth_estimation_.CurrentEstimate(¤t_estimate, &loss, &rtt);
|
|
||||||
bandwidth_estimation_.SetSendBitrate(std::max(sum_start_bitrate,
|
|
||||||
current_estimate));
|
|
||||||
} else {
|
|
||||||
// Add new settings.
|
|
||||||
bitrate_observers_.push_back(BitrateObserverConfiguration(observer,
|
|
||||||
new BitrateConfiguration(start_bitrate, min_bitrate, max_bitrate)));
|
|
||||||
bitrate_observers_modified_ = true;
|
|
||||||
|
|
||||||
// TODO(andresp): This is a ugly way to set start bitrate.
|
|
||||||
//
|
|
||||||
// Only change start bitrate if we have exactly one observer. By definition
|
|
||||||
// you can only have one start bitrate, once we have our first estimate we
|
|
||||||
// will adapt from there.
|
|
||||||
if (bitrate_observers_.size() == 1) {
|
|
||||||
bandwidth_estimation_.SetSendBitrate(start_bitrate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateMinMaxBitrate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BitrateControllerImpl::UpdateMinMaxBitrate() {
|
void BitrateControllerImpl::SetMinMaxBitrate(int min_bitrate_bps,
|
||||||
uint32_t sum_min_bitrate = 0;
|
int max_bitrate_bps) {
|
||||||
uint32_t sum_max_bitrate = 0;
|
|
||||||
BitrateObserverConfList::iterator it;
|
|
||||||
for (it = bitrate_observers_.begin(); it != bitrate_observers_.end(); ++it) {
|
|
||||||
sum_min_bitrate += it->second->min_bitrate_;
|
|
||||||
sum_max_bitrate += it->second->max_bitrate_;
|
|
||||||
}
|
|
||||||
if (sum_max_bitrate == 0) {
|
|
||||||
// No max configured use 1Gbit/s.
|
|
||||||
sum_max_bitrate = 1000000000;
|
|
||||||
}
|
|
||||||
if (enforce_min_bitrate_ == false) {
|
|
||||||
// If not enforcing min bitrate, allow the bandwidth estimation to
|
|
||||||
// go as low as 10 kbps.
|
|
||||||
sum_min_bitrate = std::min(sum_min_bitrate, 10000u);
|
|
||||||
}
|
|
||||||
bandwidth_estimation_.SetMinMaxBitrate(sum_min_bitrate,
|
|
||||||
sum_max_bitrate);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BitrateControllerImpl::RemoveBitrateObserver(BitrateObserver* observer) {
|
|
||||||
CriticalSectionScoped cs(critsect_);
|
CriticalSectionScoped cs(critsect_);
|
||||||
BitrateObserverConfList::iterator it = FindObserverConfigurationPair(
|
bandwidth_estimation_.SetMinMaxBitrate(min_bitrate_bps, max_bitrate_bps);
|
||||||
observer);
|
|
||||||
if (it != bitrate_observers_.end()) {
|
|
||||||
delete it->second;
|
|
||||||
bitrate_observers_.erase(it);
|
|
||||||
bitrate_observers_modified_ = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BitrateControllerImpl::EnforceMinBitrate(bool enforce_min_bitrate) {
|
|
||||||
CriticalSectionScoped cs(critsect_);
|
|
||||||
enforce_min_bitrate_ = enforce_min_bitrate;
|
|
||||||
UpdateMinMaxBitrate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BitrateControllerImpl::SetReservedBitrate(uint32_t reserved_bitrate_bps) {
|
void BitrateControllerImpl::SetReservedBitrate(uint32_t reserved_bitrate_bps) {
|
||||||
|
{
|
||||||
CriticalSectionScoped cs(critsect_);
|
CriticalSectionScoped cs(critsect_);
|
||||||
reserved_bitrate_bps_ = reserved_bitrate_bps;
|
reserved_bitrate_bps_ = reserved_bitrate_bps;
|
||||||
|
}
|
||||||
MaybeTriggerOnNetworkChanged();
|
MaybeTriggerOnNetworkChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BitrateControllerImpl::OnReceivedEstimatedBitrate(uint32_t bitrate) {
|
void BitrateControllerImpl::OnReceivedEstimatedBitrate(uint32_t bitrate) {
|
||||||
|
{
|
||||||
CriticalSectionScoped cs(critsect_);
|
CriticalSectionScoped cs(critsect_);
|
||||||
if (remb_suppressor_->SuppresNewRemb(bitrate)) {
|
if (remb_suppressor_->SuppresNewRemb(bitrate)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bandwidth_estimation_.UpdateReceiverEstimate(bitrate);
|
bandwidth_estimation_.UpdateReceiverEstimate(bitrate);
|
||||||
|
}
|
||||||
MaybeTriggerOnNetworkChanged();
|
MaybeTriggerOnNetworkChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,8 +151,8 @@ int32_t BitrateControllerImpl::Process() {
|
|||||||
{
|
{
|
||||||
CriticalSectionScoped cs(critsect_);
|
CriticalSectionScoped cs(critsect_);
|
||||||
bandwidth_estimation_.UpdateEstimate(clock_->TimeInMilliseconds());
|
bandwidth_estimation_.UpdateEstimate(clock_->TimeInMilliseconds());
|
||||||
MaybeTriggerOnNetworkChanged();
|
|
||||||
}
|
}
|
||||||
|
MaybeTriggerOnNetworkChanged();
|
||||||
last_bitrate_update_ms_ = clock_->TimeInMilliseconds();
|
last_bitrate_update_ms_ = clock_->TimeInMilliseconds();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -255,9 +162,11 @@ void BitrateControllerImpl::OnReceivedRtcpReceiverReport(
|
|||||||
int64_t rtt,
|
int64_t rtt,
|
||||||
int number_of_packets,
|
int number_of_packets,
|
||||||
int64_t now_ms) {
|
int64_t now_ms) {
|
||||||
|
{
|
||||||
CriticalSectionScoped cs(critsect_);
|
CriticalSectionScoped cs(critsect_);
|
||||||
bandwidth_estimation_.UpdateReceiverBlock(
|
bandwidth_estimation_.UpdateReceiverBlock(fraction_loss, rtt,
|
||||||
fraction_loss, rtt, number_of_packets, now_ms);
|
number_of_packets, now_ms);
|
||||||
|
}
|
||||||
MaybeTriggerOnNetworkChanged();
|
MaybeTriggerOnNetworkChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,110 +174,25 @@ void BitrateControllerImpl::MaybeTriggerOnNetworkChanged() {
|
|||||||
uint32_t bitrate;
|
uint32_t bitrate;
|
||||||
uint8_t fraction_loss;
|
uint8_t fraction_loss;
|
||||||
int64_t rtt;
|
int64_t rtt;
|
||||||
|
bool new_bitrate = false;
|
||||||
|
{
|
||||||
|
CriticalSectionScoped cs(critsect_);
|
||||||
bandwidth_estimation_.CurrentEstimate(&bitrate, &fraction_loss, &rtt);
|
bandwidth_estimation_.CurrentEstimate(&bitrate, &fraction_loss, &rtt);
|
||||||
bitrate -= std::min(bitrate, reserved_bitrate_bps_);
|
bitrate -= std::min(bitrate, reserved_bitrate_bps_);
|
||||||
|
bitrate = std::max(bitrate, bandwidth_estimation_.GetMinBitrate());
|
||||||
|
|
||||||
if (bitrate_observers_modified_ ||
|
if (bitrate != last_bitrate_bps_ || fraction_loss != last_fraction_loss_ ||
|
||||||
bitrate != last_bitrate_bps_ ||
|
|
||||||
fraction_loss != last_fraction_loss_ ||
|
|
||||||
rtt != last_rtt_ms_ ||
|
rtt != last_rtt_ms_ ||
|
||||||
last_enforce_min_bitrate_ != enforce_min_bitrate_ ||
|
|
||||||
last_reserved_bitrate_bps_ != reserved_bitrate_bps_) {
|
last_reserved_bitrate_bps_ != reserved_bitrate_bps_) {
|
||||||
last_bitrate_bps_ = bitrate;
|
last_bitrate_bps_ = bitrate;
|
||||||
last_fraction_loss_ = fraction_loss;
|
last_fraction_loss_ = fraction_loss;
|
||||||
last_rtt_ms_ = rtt;
|
last_rtt_ms_ = rtt;
|
||||||
last_enforce_min_bitrate_ = enforce_min_bitrate_;
|
|
||||||
last_reserved_bitrate_bps_ = reserved_bitrate_bps_;
|
last_reserved_bitrate_bps_ = reserved_bitrate_bps_;
|
||||||
bitrate_observers_modified_ = false;
|
new_bitrate = true;
|
||||||
OnNetworkChanged(bitrate, fraction_loss, rtt);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void BitrateControllerImpl::OnNetworkChanged(uint32_t bitrate,
|
|
||||||
uint8_t fraction_loss,
|
|
||||||
int64_t rtt) {
|
|
||||||
// Sanity check.
|
|
||||||
if (bitrate_observers_.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
uint32_t sum_min_bitrates = 0;
|
|
||||||
BitrateObserverConfList::iterator it;
|
|
||||||
for (it = bitrate_observers_.begin(); it != bitrate_observers_.end(); ++it) {
|
|
||||||
sum_min_bitrates += it->second->min_bitrate_;
|
|
||||||
}
|
|
||||||
if (bitrate <= sum_min_bitrates)
|
|
||||||
return LowRateAllocation(bitrate, fraction_loss, rtt, sum_min_bitrates);
|
|
||||||
else
|
|
||||||
return NormalRateAllocation(bitrate, fraction_loss, rtt, sum_min_bitrates);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BitrateControllerImpl::NormalRateAllocation(uint32_t bitrate,
|
|
||||||
uint8_t fraction_loss,
|
|
||||||
int64_t rtt,
|
|
||||||
uint32_t sum_min_bitrates) {
|
|
||||||
uint32_t number_of_observers = bitrate_observers_.size();
|
|
||||||
uint32_t bitrate_per_observer = (bitrate - sum_min_bitrates) /
|
|
||||||
number_of_observers;
|
|
||||||
// Use map to sort list based on max bitrate.
|
|
||||||
ObserverSortingMap list_max_bitrates;
|
|
||||||
BitrateObserverConfList::iterator it;
|
|
||||||
for (it = bitrate_observers_.begin(); it != bitrate_observers_.end(); ++it) {
|
|
||||||
list_max_bitrates.insert(std::pair<uint32_t, ObserverConfiguration*>(
|
|
||||||
it->second->max_bitrate_,
|
|
||||||
new ObserverConfiguration(it->first, it->second->min_bitrate_)));
|
|
||||||
}
|
|
||||||
ObserverSortingMap::iterator max_it = list_max_bitrates.begin();
|
|
||||||
while (max_it != list_max_bitrates.end()) {
|
|
||||||
number_of_observers--;
|
|
||||||
uint32_t observer_allowance = max_it->second->min_bitrate_ +
|
|
||||||
bitrate_per_observer;
|
|
||||||
if (max_it->first < observer_allowance) {
|
|
||||||
// We have more than enough for this observer.
|
|
||||||
// Carry the remainder forward.
|
|
||||||
uint32_t remainder = observer_allowance - max_it->first;
|
|
||||||
if (number_of_observers != 0) {
|
|
||||||
bitrate_per_observer += remainder / number_of_observers;
|
|
||||||
}
|
|
||||||
max_it->second->observer_->OnNetworkChanged(max_it->first, fraction_loss,
|
|
||||||
rtt);
|
|
||||||
} else {
|
|
||||||
max_it->second->observer_->OnNetworkChanged(observer_allowance,
|
|
||||||
fraction_loss, rtt);
|
|
||||||
}
|
|
||||||
delete max_it->second;
|
|
||||||
list_max_bitrates.erase(max_it);
|
|
||||||
// Prepare next iteration.
|
|
||||||
max_it = list_max_bitrates.begin();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BitrateControllerImpl::LowRateAllocation(uint32_t bitrate,
|
|
||||||
uint8_t fraction_loss,
|
|
||||||
int64_t rtt,
|
|
||||||
uint32_t sum_min_bitrates) {
|
|
||||||
if (enforce_min_bitrate_) {
|
|
||||||
// Min bitrate to all observers.
|
|
||||||
BitrateControllerImpl::BitrateObserverConfList::iterator it;
|
|
||||||
for (it = bitrate_observers_.begin(); it != bitrate_observers_.end();
|
|
||||||
++it) {
|
|
||||||
it->first->OnNetworkChanged(it->second->min_bitrate_, fraction_loss, rtt);
|
|
||||||
}
|
|
||||||
// Set sum of min to current send bitrate.
|
|
||||||
bandwidth_estimation_.SetSendBitrate(sum_min_bitrates);
|
|
||||||
} else {
|
|
||||||
// Allocate up to |min_bitrate_| to one observer at a time, until
|
|
||||||
// |bitrate| is depleted.
|
|
||||||
uint32_t remainder = bitrate;
|
|
||||||
BitrateControllerImpl::BitrateObserverConfList::iterator it;
|
|
||||||
for (it = bitrate_observers_.begin(); it != bitrate_observers_.end();
|
|
||||||
++it) {
|
|
||||||
uint32_t allocation = std::min(remainder, it->second->min_bitrate_);
|
|
||||||
it->first->OnNetworkChanged(allocation, fraction_loss, rtt);
|
|
||||||
remainder -= allocation;
|
|
||||||
}
|
|
||||||
// Set |bitrate| to current send bitrate.
|
|
||||||
bandwidth_estimation_.SetSendBitrate(bitrate);
|
|
||||||
}
|
}
|
||||||
|
if (new_bitrate)
|
||||||
|
observer_->OnNetworkChanged(bitrate, fraction_loss, rtt);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BitrateControllerImpl::AvailableBandwidth(uint32_t* bandwidth) const {
|
bool BitrateControllerImpl::AvailableBandwidth(uint32_t* bandwidth) const {
|
||||||
@ -379,6 +203,7 @@ bool BitrateControllerImpl::AvailableBandwidth(uint32_t* bandwidth) const {
|
|||||||
bandwidth_estimation_.CurrentEstimate(&bitrate, &fraction_loss, &rtt);
|
bandwidth_estimation_.CurrentEstimate(&bitrate, &fraction_loss, &rtt);
|
||||||
if (bitrate) {
|
if (bitrate) {
|
||||||
*bandwidth = bitrate - std::min(bitrate, reserved_bitrate_bps_);
|
*bandwidth = bitrate - std::min(bitrate, reserved_bitrate_bps_);
|
||||||
|
*bandwidth = std::max(*bandwidth, bandwidth_estimation_.GetMinBitrate());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
|
#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "webrtc/base/scoped_ptr.h"
|
#include "webrtc/base/scoped_ptr.h"
|
||||||
@ -30,61 +29,30 @@ namespace webrtc {
|
|||||||
|
|
||||||
class BitrateControllerImpl : public BitrateController {
|
class BitrateControllerImpl : public BitrateController {
|
||||||
public:
|
public:
|
||||||
BitrateControllerImpl(Clock* clock, bool enforce_min_bitrate);
|
BitrateControllerImpl(Clock* clock, BitrateObserver* observer);
|
||||||
virtual ~BitrateControllerImpl();
|
virtual ~BitrateControllerImpl();
|
||||||
|
|
||||||
virtual bool AvailableBandwidth(uint32_t* bandwidth) const OVERRIDE;
|
virtual bool AvailableBandwidth(uint32_t* bandwidth) const override;
|
||||||
|
|
||||||
virtual RtcpBandwidthObserver* CreateRtcpBandwidthObserver() OVERRIDE;
|
virtual RtcpBandwidthObserver* CreateRtcpBandwidthObserver() override;
|
||||||
|
|
||||||
virtual void SetBitrateObserver(BitrateObserver* observer,
|
virtual void SetStartBitrate(int start_bitrate_bps) override;
|
||||||
uint32_t start_bitrate,
|
virtual void SetMinMaxBitrate(int min_bitrate_bps,
|
||||||
uint32_t min_bitrate,
|
int max_bitrate_bps) override;
|
||||||
uint32_t max_bitrate) OVERRIDE;
|
|
||||||
|
|
||||||
virtual void RemoveBitrateObserver(BitrateObserver* observer) OVERRIDE;
|
virtual void SetReservedBitrate(uint32_t reserved_bitrate_bps) override;
|
||||||
|
|
||||||
virtual void EnforceMinBitrate(bool enforce_min_bitrate) OVERRIDE;
|
virtual int64_t TimeUntilNextProcess() override;
|
||||||
virtual void SetReservedBitrate(uint32_t reserved_bitrate_bps) OVERRIDE;
|
virtual int32_t Process() override;
|
||||||
|
|
||||||
virtual int64_t TimeUntilNextProcess() OVERRIDE;
|
|
||||||
virtual int32_t Process() OVERRIDE;
|
|
||||||
|
|
||||||
// Current bitrate actually being sent.
|
// Current bitrate actually being sent.
|
||||||
virtual void SetBitrateSent(uint32_t bitrate_sent_bps) OVERRIDE;
|
virtual void SetBitrateSent(uint32_t bitrate_sent_bps) override;
|
||||||
|
|
||||||
virtual void SetCodecMode(webrtc::VideoCodecMode mode) OVERRIDE;
|
virtual void SetCodecMode(webrtc::VideoCodecMode mode) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class RtcpBandwidthObserverImpl;
|
class RtcpBandwidthObserverImpl;
|
||||||
|
|
||||||
struct BitrateConfiguration {
|
|
||||||
BitrateConfiguration(uint32_t start_bitrate,
|
|
||||||
uint32_t min_bitrate,
|
|
||||||
uint32_t max_bitrate)
|
|
||||||
: start_bitrate_(start_bitrate),
|
|
||||||
min_bitrate_(min_bitrate),
|
|
||||||
max_bitrate_(max_bitrate) {
|
|
||||||
}
|
|
||||||
uint32_t start_bitrate_;
|
|
||||||
uint32_t min_bitrate_;
|
|
||||||
uint32_t max_bitrate_;
|
|
||||||
};
|
|
||||||
struct ObserverConfiguration {
|
|
||||||
ObserverConfiguration(BitrateObserver* observer,
|
|
||||||
uint32_t bitrate)
|
|
||||||
: observer_(observer),
|
|
||||||
min_bitrate_(bitrate) {
|
|
||||||
}
|
|
||||||
BitrateObserver* observer_;
|
|
||||||
uint32_t min_bitrate_;
|
|
||||||
};
|
|
||||||
typedef std::pair<BitrateObserver*, BitrateConfiguration*>
|
|
||||||
BitrateObserverConfiguration;
|
|
||||||
typedef std::list<BitrateObserverConfiguration> BitrateObserverConfList;
|
|
||||||
|
|
||||||
void UpdateMinMaxBitrate() EXCLUSIVE_LOCKS_REQUIRED(*critsect_);
|
|
||||||
|
|
||||||
// Called by BitrateObserver's direct from the RTCP module.
|
// Called by BitrateObserver's direct from the RTCP module.
|
||||||
void OnReceivedEstimatedBitrate(uint32_t bitrate);
|
void OnReceivedEstimatedBitrate(uint32_t bitrate);
|
||||||
|
|
||||||
@ -93,37 +61,20 @@ class BitrateControllerImpl : public BitrateController {
|
|||||||
int number_of_packets,
|
int number_of_packets,
|
||||||
int64_t now_ms);
|
int64_t now_ms);
|
||||||
|
|
||||||
void MaybeTriggerOnNetworkChanged() EXCLUSIVE_LOCKS_REQUIRED(*critsect_);
|
void MaybeTriggerOnNetworkChanged();
|
||||||
|
|
||||||
void OnNetworkChanged(uint32_t bitrate,
|
void OnNetworkChanged(uint32_t bitrate,
|
||||||
uint8_t fraction_loss, // 0 - 255.
|
uint8_t fraction_loss, // 0 - 255.
|
||||||
int64_t rtt)
|
int64_t rtt)
|
||||||
EXCLUSIVE_LOCKS_REQUIRED(*critsect_);
|
EXCLUSIVE_LOCKS_REQUIRED(*critsect_);
|
||||||
|
|
||||||
void NormalRateAllocation(uint32_t bitrate,
|
|
||||||
uint8_t fraction_loss,
|
|
||||||
int64_t rtt,
|
|
||||||
uint32_t sum_min_bitrates)
|
|
||||||
EXCLUSIVE_LOCKS_REQUIRED(*critsect_);
|
|
||||||
|
|
||||||
void LowRateAllocation(uint32_t bitrate,
|
|
||||||
uint8_t fraction_loss,
|
|
||||||
int64_t rtt,
|
|
||||||
uint32_t sum_min_bitrates)
|
|
||||||
EXCLUSIVE_LOCKS_REQUIRED(*critsect_);
|
|
||||||
|
|
||||||
typedef std::multimap<uint32_t, ObserverConfiguration*> ObserverSortingMap;
|
|
||||||
|
|
||||||
BitrateObserverConfList::iterator FindObserverConfigurationPair(
|
|
||||||
const BitrateObserver* observer) EXCLUSIVE_LOCKS_REQUIRED(*critsect_);
|
|
||||||
|
|
||||||
// Used by process thread.
|
// Used by process thread.
|
||||||
Clock* clock_;
|
Clock* clock_;
|
||||||
|
BitrateObserver* observer_;
|
||||||
int64_t last_bitrate_update_ms_;
|
int64_t last_bitrate_update_ms_;
|
||||||
|
|
||||||
CriticalSectionWrapper* critsect_;
|
CriticalSectionWrapper* critsect_;
|
||||||
SendSideBandwidthEstimation bandwidth_estimation_ GUARDED_BY(*critsect_);
|
SendSideBandwidthEstimation bandwidth_estimation_ GUARDED_BY(*critsect_);
|
||||||
BitrateObserverConfList bitrate_observers_ GUARDED_BY(*critsect_);
|
|
||||||
bool enforce_min_bitrate_ GUARDED_BY(*critsect_);
|
bool enforce_min_bitrate_ GUARDED_BY(*critsect_);
|
||||||
uint32_t reserved_bitrate_bps_ GUARDED_BY(*critsect_);
|
uint32_t reserved_bitrate_bps_ GUARDED_BY(*critsect_);
|
||||||
|
|
||||||
@ -131,7 +82,6 @@ class BitrateControllerImpl : public BitrateController {
|
|||||||
uint8_t last_fraction_loss_ GUARDED_BY(*critsect_);
|
uint8_t last_fraction_loss_ GUARDED_BY(*critsect_);
|
||||||
int64_t last_rtt_ms_ GUARDED_BY(*critsect_);
|
int64_t last_rtt_ms_ GUARDED_BY(*critsect_);
|
||||||
bool last_enforce_min_bitrate_ GUARDED_BY(*critsect_);
|
bool last_enforce_min_bitrate_ GUARDED_BY(*critsect_);
|
||||||
bool bitrate_observers_modified_ GUARDED_BY(*critsect_);
|
|
||||||
uint32_t last_reserved_bitrate_bps_ GUARDED_BY(*critsect_);
|
uint32_t last_reserved_bitrate_bps_ GUARDED_BY(*critsect_);
|
||||||
rtc::scoped_ptr<RembSuppressor> remb_suppressor_ GUARDED_BY(*critsect_);
|
rtc::scoped_ptr<RembSuppressor> remb_suppressor_ GUARDED_BY(*critsect_);
|
||||||
|
|
||||||
|
@ -57,12 +57,14 @@ class TestBitrateObserver: public BitrateObserver {
|
|||||||
|
|
||||||
class BitrateControllerTest : public ::testing::Test {
|
class BitrateControllerTest : public ::testing::Test {
|
||||||
protected:
|
protected:
|
||||||
BitrateControllerTest() : clock_(0), enforce_min_bitrate_(true) {}
|
BitrateControllerTest() : clock_(0) {}
|
||||||
~BitrateControllerTest() {}
|
~BitrateControllerTest() {}
|
||||||
|
|
||||||
virtual void SetUp() {
|
virtual void SetUp() {
|
||||||
controller_ = BitrateController::CreateBitrateController(
|
controller_ =
|
||||||
&clock_, enforce_min_bitrate_);
|
BitrateController::CreateBitrateController(&clock_, &bitrate_observer_);
|
||||||
|
controller_->SetStartBitrate(200000);
|
||||||
|
controller_->SetMinMaxBitrate(100000, 300000);
|
||||||
bandwidth_observer_ = controller_->CreateRtcpBandwidthObserver();
|
bandwidth_observer_ = controller_->CreateRtcpBandwidthObserver();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,47 +74,20 @@ class BitrateControllerTest : public ::testing::Test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
webrtc::SimulatedClock clock_;
|
webrtc::SimulatedClock clock_;
|
||||||
bool enforce_min_bitrate_;
|
TestBitrateObserver bitrate_observer_;
|
||||||
BitrateController* controller_;
|
BitrateController* controller_;
|
||||||
RtcpBandwidthObserver* bandwidth_observer_;
|
RtcpBandwidthObserver* bandwidth_observer_;
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(BitrateControllerTest, Basic) {
|
|
||||||
TestBitrateObserver bitrate_observer;
|
|
||||||
controller_->SetBitrateObserver(&bitrate_observer, 200000, 100000, 300000);
|
|
||||||
controller_->RemoveBitrateObserver(&bitrate_observer);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(BitrateControllerTest, UpdatingBitrateObserver) {
|
|
||||||
TestBitrateObserver bitrate_observer;
|
|
||||||
controller_->SetBitrateObserver(&bitrate_observer, 200000, 100000, 1500000);
|
|
||||||
clock_.AdvanceTimeMilliseconds(25);
|
|
||||||
controller_->Process();
|
|
||||||
EXPECT_EQ(200000u, bitrate_observer.last_bitrate_);
|
|
||||||
|
|
||||||
controller_->SetBitrateObserver(&bitrate_observer, 1500000, 100000, 1500000);
|
|
||||||
clock_.AdvanceTimeMilliseconds(25);
|
|
||||||
controller_->Process();
|
|
||||||
EXPECT_EQ(1500000u, bitrate_observer.last_bitrate_);
|
|
||||||
|
|
||||||
controller_->SetBitrateObserver(&bitrate_observer, 500000, 100000, 1500000);
|
|
||||||
clock_.AdvanceTimeMilliseconds(25);
|
|
||||||
controller_->Process();
|
|
||||||
EXPECT_EQ(1500000u, bitrate_observer.last_bitrate_);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(BitrateControllerTest, OneBitrateObserverOneRtcpObserver) {
|
TEST_F(BitrateControllerTest, OneBitrateObserverOneRtcpObserver) {
|
||||||
TestBitrateObserver bitrate_observer;
|
|
||||||
controller_->SetBitrateObserver(&bitrate_observer, 200000, 100000, 300000);
|
|
||||||
|
|
||||||
// First REMB applies immediately.
|
// First REMB applies immediately.
|
||||||
int64_t time_ms = 1001;
|
int64_t time_ms = 1001;
|
||||||
webrtc::ReportBlockList report_blocks;
|
webrtc::ReportBlockList report_blocks;
|
||||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 1));
|
report_blocks.push_back(CreateReportBlock(1, 2, 0, 1));
|
||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(200000);
|
bandwidth_observer_->OnReceivedEstimatedBitrate(200000);
|
||||||
EXPECT_EQ(200000u, bitrate_observer.last_bitrate_);
|
EXPECT_EQ(200000u, bitrate_observer_.last_bitrate_);
|
||||||
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
|
EXPECT_EQ(0, bitrate_observer_.last_fraction_loss_);
|
||||||
EXPECT_EQ(0, bitrate_observer.last_rtt_);
|
EXPECT_EQ(0, bitrate_observer_.last_rtt_);
|
||||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
|
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
|
||||||
report_blocks.clear();
|
report_blocks.clear();
|
||||||
time_ms += 2000;
|
time_ms += 2000;
|
||||||
@ -123,64 +98,60 @@ TEST_F(BitrateControllerTest, OneBitrateObserverOneRtcpObserver) {
|
|||||||
// Test bitrate increase 8% per second.
|
// Test bitrate increase 8% per second.
|
||||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 21));
|
report_blocks.push_back(CreateReportBlock(1, 2, 0, 21));
|
||||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
|
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
|
||||||
EXPECT_EQ(217000u, bitrate_observer.last_bitrate_);
|
EXPECT_EQ(217000u, bitrate_observer_.last_bitrate_);
|
||||||
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
|
EXPECT_EQ(0, bitrate_observer_.last_fraction_loss_);
|
||||||
EXPECT_EQ(50, bitrate_observer.last_rtt_);
|
EXPECT_EQ(50, bitrate_observer_.last_rtt_);
|
||||||
time_ms += 1000;
|
time_ms += 1000;
|
||||||
|
|
||||||
report_blocks.clear();
|
report_blocks.clear();
|
||||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 41));
|
report_blocks.push_back(CreateReportBlock(1, 2, 0, 41));
|
||||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
|
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
|
||||||
EXPECT_EQ(235360u, bitrate_observer.last_bitrate_);
|
EXPECT_EQ(235360u, bitrate_observer_.last_bitrate_);
|
||||||
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
|
EXPECT_EQ(0, bitrate_observer_.last_fraction_loss_);
|
||||||
EXPECT_EQ(50, bitrate_observer.last_rtt_);
|
EXPECT_EQ(50, bitrate_observer_.last_rtt_);
|
||||||
time_ms += 1000;
|
time_ms += 1000;
|
||||||
|
|
||||||
report_blocks.clear();
|
report_blocks.clear();
|
||||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 61));
|
report_blocks.push_back(CreateReportBlock(1, 2, 0, 61));
|
||||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
|
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
|
||||||
EXPECT_EQ(255189u, bitrate_observer.last_bitrate_);
|
EXPECT_EQ(255189u, bitrate_observer_.last_bitrate_);
|
||||||
time_ms += 1000;
|
time_ms += 1000;
|
||||||
|
|
||||||
report_blocks.clear();
|
report_blocks.clear();
|
||||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 81));
|
report_blocks.push_back(CreateReportBlock(1, 2, 0, 81));
|
||||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
|
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
|
||||||
EXPECT_EQ(276604u, bitrate_observer.last_bitrate_);
|
EXPECT_EQ(276604u, bitrate_observer_.last_bitrate_);
|
||||||
time_ms += 1000;
|
time_ms += 1000;
|
||||||
|
|
||||||
report_blocks.clear();
|
report_blocks.clear();
|
||||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 801));
|
report_blocks.push_back(CreateReportBlock(1, 2, 0, 801));
|
||||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
|
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
|
||||||
EXPECT_EQ(299732u, bitrate_observer.last_bitrate_);
|
EXPECT_EQ(299732u, bitrate_observer_.last_bitrate_);
|
||||||
time_ms += 1000;
|
time_ms += 1000;
|
||||||
|
|
||||||
// Reach max cap.
|
// Reach max cap.
|
||||||
report_blocks.clear();
|
report_blocks.clear();
|
||||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 101));
|
report_blocks.push_back(CreateReportBlock(1, 2, 0, 101));
|
||||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
|
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
|
||||||
EXPECT_EQ(300000u, bitrate_observer.last_bitrate_);
|
EXPECT_EQ(300000u, bitrate_observer_.last_bitrate_);
|
||||||
time_ms += 1000;
|
time_ms += 1000;
|
||||||
|
|
||||||
report_blocks.clear();
|
report_blocks.clear();
|
||||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 141));
|
report_blocks.push_back(CreateReportBlock(1, 2, 0, 141));
|
||||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
|
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
|
||||||
EXPECT_EQ(300000u, bitrate_observer.last_bitrate_);
|
EXPECT_EQ(300000u, bitrate_observer_.last_bitrate_);
|
||||||
|
|
||||||
// Test that a low REMB trigger immediately.
|
// Test that a low REMB trigger immediately.
|
||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(250000);
|
bandwidth_observer_->OnReceivedEstimatedBitrate(250000);
|
||||||
EXPECT_EQ(250000u, bitrate_observer.last_bitrate_);
|
EXPECT_EQ(250000u, bitrate_observer_.last_bitrate_);
|
||||||
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
|
EXPECT_EQ(0, bitrate_observer_.last_fraction_loss_);
|
||||||
EXPECT_EQ(50, bitrate_observer.last_rtt_);
|
EXPECT_EQ(50, bitrate_observer_.last_rtt_);
|
||||||
|
|
||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(1000);
|
bandwidth_observer_->OnReceivedEstimatedBitrate(1000);
|
||||||
EXPECT_EQ(100000u, bitrate_observer.last_bitrate_); // Min cap.
|
EXPECT_EQ(100000u, bitrate_observer_.last_bitrate_); // Min cap.
|
||||||
controller_->RemoveBitrateObserver(&bitrate_observer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(BitrateControllerTest, OneBitrateObserverTwoRtcpObservers) {
|
TEST_F(BitrateControllerTest, OneBitrateObserverTwoRtcpObservers) {
|
||||||
TestBitrateObserver bitrate_observer;
|
|
||||||
controller_->SetBitrateObserver(&bitrate_observer, 200000, 100000, 300000);
|
|
||||||
|
|
||||||
// REMBs during the first 2 seconds apply immediately.
|
// REMBs during the first 2 seconds apply immediately.
|
||||||
int64_t time_ms = 1;
|
int64_t time_ms = 1;
|
||||||
webrtc::ReportBlockList report_blocks;
|
webrtc::ReportBlockList report_blocks;
|
||||||
@ -196,9 +167,9 @@ TEST_F(BitrateControllerTest, OneBitrateObserverTwoRtcpObservers) {
|
|||||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 21));
|
report_blocks.push_back(CreateReportBlock(1, 2, 0, 21));
|
||||||
second_bandwidth_observer->OnReceivedRtcpReceiverReport(
|
second_bandwidth_observer->OnReceivedRtcpReceiverReport(
|
||||||
report_blocks, 100, 1);
|
report_blocks, 100, 1);
|
||||||
EXPECT_EQ(217000u, bitrate_observer.last_bitrate_);
|
EXPECT_EQ(217000u, bitrate_observer_.last_bitrate_);
|
||||||
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
|
EXPECT_EQ(0, bitrate_observer_.last_fraction_loss_);
|
||||||
EXPECT_EQ(100, bitrate_observer.last_rtt_);
|
EXPECT_EQ(100, bitrate_observer_.last_rtt_);
|
||||||
time_ms += 500;
|
time_ms += 500;
|
||||||
|
|
||||||
// Test bitrate increase 8% per second.
|
// Test bitrate increase 8% per second.
|
||||||
@ -208,9 +179,9 @@ TEST_F(BitrateControllerTest, OneBitrateObserverTwoRtcpObservers) {
|
|||||||
time_ms += 500;
|
time_ms += 500;
|
||||||
second_bandwidth_observer->OnReceivedRtcpReceiverReport(
|
second_bandwidth_observer->OnReceivedRtcpReceiverReport(
|
||||||
report_blocks, 100, time_ms);
|
report_blocks, 100, time_ms);
|
||||||
EXPECT_EQ(235360u, bitrate_observer.last_bitrate_);
|
EXPECT_EQ(235360u, bitrate_observer_.last_bitrate_);
|
||||||
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
|
EXPECT_EQ(0, bitrate_observer_.last_fraction_loss_);
|
||||||
EXPECT_EQ(100, bitrate_observer.last_rtt_);
|
EXPECT_EQ(100, bitrate_observer_.last_rtt_);
|
||||||
time_ms += 500;
|
time_ms += 500;
|
||||||
|
|
||||||
// Extra report should not change estimate.
|
// Extra report should not change estimate.
|
||||||
@ -218,20 +189,20 @@ TEST_F(BitrateControllerTest, OneBitrateObserverTwoRtcpObservers) {
|
|||||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 31));
|
report_blocks.push_back(CreateReportBlock(1, 2, 0, 31));
|
||||||
second_bandwidth_observer->OnReceivedRtcpReceiverReport(
|
second_bandwidth_observer->OnReceivedRtcpReceiverReport(
|
||||||
report_blocks, 100, time_ms);
|
report_blocks, 100, time_ms);
|
||||||
EXPECT_EQ(235360u, bitrate_observer.last_bitrate_);
|
EXPECT_EQ(235360u, bitrate_observer_.last_bitrate_);
|
||||||
time_ms += 500;
|
time_ms += 500;
|
||||||
|
|
||||||
report_blocks.clear();
|
report_blocks.clear();
|
||||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 41));
|
report_blocks.push_back(CreateReportBlock(1, 2, 0, 41));
|
||||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
|
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
|
||||||
EXPECT_EQ(255189u, bitrate_observer.last_bitrate_);
|
EXPECT_EQ(255189u, bitrate_observer_.last_bitrate_);
|
||||||
|
|
||||||
// Second report should not change estimate.
|
// Second report should not change estimate.
|
||||||
report_blocks.clear();
|
report_blocks.clear();
|
||||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 41));
|
report_blocks.push_back(CreateReportBlock(1, 2, 0, 41));
|
||||||
second_bandwidth_observer->OnReceivedRtcpReceiverReport(
|
second_bandwidth_observer->OnReceivedRtcpReceiverReport(
|
||||||
report_blocks, 100, time_ms);
|
report_blocks, 100, time_ms);
|
||||||
EXPECT_EQ(255189u, bitrate_observer.last_bitrate_);
|
EXPECT_EQ(255189u, bitrate_observer_.last_bitrate_);
|
||||||
time_ms += 1000;
|
time_ms += 1000;
|
||||||
|
|
||||||
// Reports from only one bandwidth observer is ok.
|
// Reports from only one bandwidth observer is ok.
|
||||||
@ -239,14 +210,14 @@ TEST_F(BitrateControllerTest, OneBitrateObserverTwoRtcpObservers) {
|
|||||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 61));
|
report_blocks.push_back(CreateReportBlock(1, 2, 0, 61));
|
||||||
second_bandwidth_observer->OnReceivedRtcpReceiverReport(
|
second_bandwidth_observer->OnReceivedRtcpReceiverReport(
|
||||||
report_blocks, 50, time_ms);
|
report_blocks, 50, time_ms);
|
||||||
EXPECT_EQ(276604u, bitrate_observer.last_bitrate_);
|
EXPECT_EQ(276604u, bitrate_observer_.last_bitrate_);
|
||||||
time_ms += 1000;
|
time_ms += 1000;
|
||||||
|
|
||||||
report_blocks.clear();
|
report_blocks.clear();
|
||||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 81));
|
report_blocks.push_back(CreateReportBlock(1, 2, 0, 81));
|
||||||
second_bandwidth_observer->OnReceivedRtcpReceiverReport(
|
second_bandwidth_observer->OnReceivedRtcpReceiverReport(
|
||||||
report_blocks, 50, time_ms);
|
report_blocks, 50, time_ms);
|
||||||
EXPECT_EQ(299732u, bitrate_observer.last_bitrate_);
|
EXPECT_EQ(299732u, bitrate_observer_.last_bitrate_);
|
||||||
time_ms += 1000;
|
time_ms += 1000;
|
||||||
|
|
||||||
// Reach max cap.
|
// Reach max cap.
|
||||||
@ -254,37 +225,35 @@ TEST_F(BitrateControllerTest, OneBitrateObserverTwoRtcpObservers) {
|
|||||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 121));
|
report_blocks.push_back(CreateReportBlock(1, 2, 0, 121));
|
||||||
second_bandwidth_observer->OnReceivedRtcpReceiverReport(
|
second_bandwidth_observer->OnReceivedRtcpReceiverReport(
|
||||||
report_blocks, 50, time_ms);
|
report_blocks, 50, time_ms);
|
||||||
EXPECT_EQ(300000u, bitrate_observer.last_bitrate_);
|
EXPECT_EQ(300000u, bitrate_observer_.last_bitrate_);
|
||||||
time_ms += 1000;
|
time_ms += 1000;
|
||||||
|
|
||||||
report_blocks.clear();
|
report_blocks.clear();
|
||||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 141));
|
report_blocks.push_back(CreateReportBlock(1, 2, 0, 141));
|
||||||
second_bandwidth_observer->OnReceivedRtcpReceiverReport(
|
second_bandwidth_observer->OnReceivedRtcpReceiverReport(
|
||||||
report_blocks, 50, time_ms);
|
report_blocks, 50, time_ms);
|
||||||
EXPECT_EQ(300000u, bitrate_observer.last_bitrate_);
|
EXPECT_EQ(300000u, bitrate_observer_.last_bitrate_);
|
||||||
|
|
||||||
// Test that a low REMB trigger immediately.
|
// Test that a low REMB trigger immediately.
|
||||||
// We don't care which bandwidth observer that delivers the REMB.
|
// We don't care which bandwidth observer that delivers the REMB.
|
||||||
second_bandwidth_observer->OnReceivedEstimatedBitrate(250000);
|
second_bandwidth_observer->OnReceivedEstimatedBitrate(250000);
|
||||||
EXPECT_EQ(250000u, bitrate_observer.last_bitrate_);
|
EXPECT_EQ(250000u, bitrate_observer_.last_bitrate_);
|
||||||
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
|
EXPECT_EQ(0, bitrate_observer_.last_fraction_loss_);
|
||||||
EXPECT_EQ(50, bitrate_observer.last_rtt_);
|
EXPECT_EQ(50, bitrate_observer_.last_rtt_);
|
||||||
|
|
||||||
// Min cap.
|
// Min cap.
|
||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(1000);
|
bandwidth_observer_->OnReceivedEstimatedBitrate(1000);
|
||||||
EXPECT_EQ(100000u, bitrate_observer.last_bitrate_);
|
EXPECT_EQ(100000u, bitrate_observer_.last_bitrate_);
|
||||||
controller_->RemoveBitrateObserver(&bitrate_observer);
|
|
||||||
delete second_bandwidth_observer;
|
delete second_bandwidth_observer;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(BitrateControllerTest, OneBitrateObserverMultipleReportBlocks) {
|
TEST_F(BitrateControllerTest, OneBitrateObserverMultipleReportBlocks) {
|
||||||
TestBitrateObserver bitrate_observer;
|
|
||||||
uint32_t sequence_number[2] = {0, 0xFF00};
|
uint32_t sequence_number[2] = {0, 0xFF00};
|
||||||
const uint32_t kStartBitrate = 200000;
|
const uint32_t kStartBitrate = 200000;
|
||||||
const uint32_t kMinBitrate = 100000;
|
const uint32_t kMinBitrate = 100000;
|
||||||
const uint32_t kMaxBitrate = 300000;
|
const uint32_t kMaxBitrate = 300000;
|
||||||
controller_->SetBitrateObserver(&bitrate_observer, kStartBitrate, kMinBitrate,
|
controller_->SetStartBitrate(kStartBitrate);
|
||||||
kMaxBitrate);
|
controller_->SetMinMaxBitrate(kMinBitrate, kMaxBitrate);
|
||||||
|
|
||||||
// REMBs during the first 2 seconds apply immediately.
|
// REMBs during the first 2 seconds apply immediately.
|
||||||
int64_t time_ms = 1001;
|
int64_t time_ms = 1001;
|
||||||
@ -305,26 +274,26 @@ TEST_F(BitrateControllerTest, OneBitrateObserverMultipleReportBlocks) {
|
|||||||
report_blocks.push_back(CreateReportBlock(1, 3, 0, sequence_number[1]));
|
report_blocks.push_back(CreateReportBlock(1, 3, 0, sequence_number[1]));
|
||||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50,
|
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50,
|
||||||
time_ms);
|
time_ms);
|
||||||
EXPECT_GT(bitrate_observer.last_bitrate_, last_bitrate);
|
EXPECT_GT(bitrate_observer_.last_bitrate_, last_bitrate);
|
||||||
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
|
EXPECT_EQ(0, bitrate_observer_.last_fraction_loss_);
|
||||||
EXPECT_EQ(50, bitrate_observer.last_rtt_);
|
EXPECT_EQ(50, bitrate_observer_.last_rtt_);
|
||||||
last_bitrate = bitrate_observer.last_bitrate_;
|
last_bitrate = bitrate_observer_.last_bitrate_;
|
||||||
time_ms += 1000;
|
time_ms += 1000;
|
||||||
sequence_number[0] += 20;
|
sequence_number[0] += 20;
|
||||||
sequence_number[1] += 1;
|
sequence_number[1] += 1;
|
||||||
report_blocks.clear();
|
report_blocks.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPECT_EQ(kMaxBitrate, bitrate_observer.last_bitrate_);
|
EXPECT_EQ(kMaxBitrate, bitrate_observer_.last_bitrate_);
|
||||||
|
|
||||||
// Packet loss on the first stream. Verify that bitrate decreases.
|
// Packet loss on the first stream. Verify that bitrate decreases.
|
||||||
report_blocks.push_back(CreateReportBlock(1, 2, 50, sequence_number[0]));
|
report_blocks.push_back(CreateReportBlock(1, 2, 50, sequence_number[0]));
|
||||||
report_blocks.push_back(CreateReportBlock(1, 3, 0, sequence_number[1]));
|
report_blocks.push_back(CreateReportBlock(1, 3, 0, sequence_number[1]));
|
||||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
|
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
|
||||||
EXPECT_LT(bitrate_observer.last_bitrate_, last_bitrate);
|
EXPECT_LT(bitrate_observer_.last_bitrate_, last_bitrate);
|
||||||
EXPECT_EQ(WeightedLoss(20, 50, 1, 0), bitrate_observer.last_fraction_loss_);
|
EXPECT_EQ(WeightedLoss(20, 50, 1, 0), bitrate_observer_.last_fraction_loss_);
|
||||||
EXPECT_EQ(50, bitrate_observer.last_rtt_);
|
EXPECT_EQ(50, bitrate_observer_.last_rtt_);
|
||||||
last_bitrate = bitrate_observer.last_bitrate_;
|
last_bitrate = bitrate_observer_.last_bitrate_;
|
||||||
sequence_number[0] += 20;
|
sequence_number[0] += 20;
|
||||||
sequence_number[1] += 20;
|
sequence_number[1] += 20;
|
||||||
time_ms += 1000;
|
time_ms += 1000;
|
||||||
@ -334,10 +303,10 @@ TEST_F(BitrateControllerTest, OneBitrateObserverMultipleReportBlocks) {
|
|||||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, sequence_number[0]));
|
report_blocks.push_back(CreateReportBlock(1, 2, 0, sequence_number[0]));
|
||||||
report_blocks.push_back(CreateReportBlock(1, 3, 75, sequence_number[1]));
|
report_blocks.push_back(CreateReportBlock(1, 3, 75, sequence_number[1]));
|
||||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
|
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
|
||||||
EXPECT_LT(bitrate_observer.last_bitrate_, last_bitrate);
|
EXPECT_LT(bitrate_observer_.last_bitrate_, last_bitrate);
|
||||||
EXPECT_EQ(WeightedLoss(20, 0, 20, 75), bitrate_observer.last_fraction_loss_);
|
EXPECT_EQ(WeightedLoss(20, 0, 20, 75), bitrate_observer_.last_fraction_loss_);
|
||||||
EXPECT_EQ(50, bitrate_observer.last_rtt_);
|
EXPECT_EQ(50, bitrate_observer_.last_rtt_);
|
||||||
last_bitrate = bitrate_observer.last_bitrate_;
|
last_bitrate = bitrate_observer_.last_bitrate_;
|
||||||
sequence_number[0] += 20;
|
sequence_number[0] += 20;
|
||||||
sequence_number[1] += 1;
|
sequence_number[1] += 1;
|
||||||
time_ms += 1000;
|
time_ms += 1000;
|
||||||
@ -347,295 +316,61 @@ TEST_F(BitrateControllerTest, OneBitrateObserverMultipleReportBlocks) {
|
|||||||
report_blocks.push_back(CreateReportBlock(1, 2, 1, sequence_number[0]));
|
report_blocks.push_back(CreateReportBlock(1, 2, 1, sequence_number[0]));
|
||||||
report_blocks.push_back(CreateReportBlock(1, 3, 255, sequence_number[1]));
|
report_blocks.push_back(CreateReportBlock(1, 3, 255, sequence_number[1]));
|
||||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
|
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
|
||||||
EXPECT_EQ(bitrate_observer.last_bitrate_, last_bitrate);
|
EXPECT_EQ(bitrate_observer_.last_bitrate_, last_bitrate);
|
||||||
EXPECT_EQ(WeightedLoss(20, 1, 1, 255), bitrate_observer.last_fraction_loss_);
|
EXPECT_EQ(WeightedLoss(20, 1, 1, 255), bitrate_observer_.last_fraction_loss_);
|
||||||
EXPECT_EQ(50, bitrate_observer.last_rtt_);
|
EXPECT_EQ(50, bitrate_observer_.last_rtt_);
|
||||||
last_bitrate = bitrate_observer.last_bitrate_;
|
last_bitrate = bitrate_observer_.last_bitrate_;
|
||||||
sequence_number[0] += 20;
|
sequence_number[0] += 20;
|
||||||
sequence_number[1] += 1;
|
sequence_number[1] += 1;
|
||||||
report_blocks.clear();
|
report_blocks.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(BitrateControllerTest, TwoBitrateObserversOneRtcpObserver) {
|
|
||||||
TestBitrateObserver bitrate_observer_1;
|
|
||||||
TestBitrateObserver bitrate_observer_2;
|
|
||||||
controller_->SetBitrateObserver(&bitrate_observer_2, 200000, 200000, 300000);
|
|
||||||
controller_->SetBitrateObserver(&bitrate_observer_1, 200000, 100000, 300000);
|
|
||||||
|
|
||||||
// REMBs during the first 2 seconds apply immediately.
|
|
||||||
int64_t time_ms = 1001;
|
|
||||||
webrtc::ReportBlockList report_blocks;
|
|
||||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 1));
|
|
||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(200000);
|
|
||||||
EXPECT_EQ(100000u, bitrate_observer_1.last_bitrate_);
|
|
||||||
EXPECT_EQ(0, bitrate_observer_1.last_fraction_loss_);
|
|
||||||
EXPECT_EQ(0, bitrate_observer_1.last_rtt_);
|
|
||||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
|
|
||||||
report_blocks.clear();
|
|
||||||
time_ms += 2000;
|
|
||||||
|
|
||||||
// Receive a high remb, test bitrate inc.
|
|
||||||
// Test too low start bitrate, hence lower than sum of min.
|
|
||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(400000);
|
|
||||||
|
|
||||||
// Test bitrate increase 8% per second, distributed equally.
|
|
||||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 21));
|
|
||||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
|
|
||||||
EXPECT_EQ(112500u, bitrate_observer_1.last_bitrate_);
|
|
||||||
EXPECT_EQ(0, bitrate_observer_1.last_fraction_loss_);
|
|
||||||
EXPECT_EQ(50, bitrate_observer_1.last_rtt_);
|
|
||||||
time_ms += 1000;
|
|
||||||
|
|
||||||
EXPECT_EQ(212500u, bitrate_observer_2.last_bitrate_);
|
|
||||||
EXPECT_EQ(0, bitrate_observer_2.last_fraction_loss_);
|
|
||||||
EXPECT_EQ(50, bitrate_observer_2.last_rtt_);
|
|
||||||
|
|
||||||
report_blocks.clear();
|
|
||||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 41));
|
|
||||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
|
|
||||||
EXPECT_EQ(126000u, bitrate_observer_1.last_bitrate_);
|
|
||||||
EXPECT_EQ(226000u, bitrate_observer_2.last_bitrate_);
|
|
||||||
time_ms += 1000;
|
|
||||||
|
|
||||||
report_blocks.clear();
|
|
||||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 61));
|
|
||||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
|
|
||||||
EXPECT_EQ(140580u, bitrate_observer_1.last_bitrate_);
|
|
||||||
EXPECT_EQ(240580u, bitrate_observer_2.last_bitrate_);
|
|
||||||
time_ms += 1000;
|
|
||||||
|
|
||||||
// Check that the bitrate sum honor our REMB.
|
|
||||||
report_blocks.clear();
|
|
||||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 101));
|
|
||||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
|
|
||||||
EXPECT_EQ(150000u, bitrate_observer_1.last_bitrate_);
|
|
||||||
EXPECT_EQ(250000u, bitrate_observer_2.last_bitrate_);
|
|
||||||
time_ms += 1000;
|
|
||||||
|
|
||||||
// Remove REMB cap, higher than sum of max.
|
|
||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(700000);
|
|
||||||
|
|
||||||
report_blocks.clear();
|
|
||||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 121));
|
|
||||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
|
|
||||||
EXPECT_EQ(166500u, bitrate_observer_1.last_bitrate_);
|
|
||||||
EXPECT_EQ(266500u, bitrate_observer_2.last_bitrate_);
|
|
||||||
time_ms += 1000;
|
|
||||||
|
|
||||||
report_blocks.clear();
|
|
||||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 141));
|
|
||||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
|
|
||||||
EXPECT_EQ(184320u, bitrate_observer_1.last_bitrate_);
|
|
||||||
EXPECT_EQ(284320u, bitrate_observer_2.last_bitrate_);
|
|
||||||
time_ms += 1000;
|
|
||||||
|
|
||||||
report_blocks.clear();
|
|
||||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 161));
|
|
||||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
|
|
||||||
EXPECT_EQ(207130u, bitrate_observer_1.last_bitrate_);
|
|
||||||
EXPECT_EQ(300000u, bitrate_observer_2.last_bitrate_); // Max cap.
|
|
||||||
time_ms += 1000;
|
|
||||||
|
|
||||||
report_blocks.clear();
|
|
||||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 181));
|
|
||||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
|
|
||||||
EXPECT_EQ(248700u, bitrate_observer_1.last_bitrate_);
|
|
||||||
EXPECT_EQ(300000u, bitrate_observer_2.last_bitrate_);
|
|
||||||
time_ms += 1000;
|
|
||||||
|
|
||||||
report_blocks.clear();
|
|
||||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 201));
|
|
||||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
|
|
||||||
EXPECT_EQ(293596u, bitrate_observer_1.last_bitrate_);
|
|
||||||
EXPECT_EQ(300000u, bitrate_observer_2.last_bitrate_);
|
|
||||||
time_ms += 1000;
|
|
||||||
|
|
||||||
report_blocks.clear();
|
|
||||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 221));
|
|
||||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
|
|
||||||
EXPECT_EQ(300000u, bitrate_observer_1.last_bitrate_); // Max cap.
|
|
||||||
EXPECT_EQ(300000u, bitrate_observer_2.last_bitrate_);
|
|
||||||
|
|
||||||
// Test that a low REMB trigger immediately.
|
|
||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(350000);
|
|
||||||
EXPECT_EQ(125000u, bitrate_observer_1.last_bitrate_);
|
|
||||||
EXPECT_EQ(0, bitrate_observer_1.last_fraction_loss_);
|
|
||||||
EXPECT_EQ(50, bitrate_observer_1.last_rtt_);
|
|
||||||
EXPECT_EQ(225000u, bitrate_observer_2.last_bitrate_);
|
|
||||||
EXPECT_EQ(0, bitrate_observer_2.last_fraction_loss_);
|
|
||||||
EXPECT_EQ(50, bitrate_observer_2.last_rtt_);
|
|
||||||
|
|
||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(1000);
|
|
||||||
EXPECT_EQ(100000u, bitrate_observer_1.last_bitrate_); // Min cap.
|
|
||||||
EXPECT_EQ(200000u, bitrate_observer_2.last_bitrate_); // Min cap.
|
|
||||||
controller_->RemoveBitrateObserver(&bitrate_observer_1);
|
|
||||||
controller_->RemoveBitrateObserver(&bitrate_observer_2);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(BitrateControllerTest, SetReservedBitrate) {
|
TEST_F(BitrateControllerTest, SetReservedBitrate) {
|
||||||
TestBitrateObserver bitrate_observer;
|
|
||||||
controller_->SetBitrateObserver(&bitrate_observer, 200000, 100000, 300000);
|
|
||||||
|
|
||||||
// Receive successively lower REMBs, verify the reserved bitrate is deducted.
|
// Receive successively lower REMBs, verify the reserved bitrate is deducted.
|
||||||
|
|
||||||
controller_->SetReservedBitrate(0);
|
controller_->SetReservedBitrate(0);
|
||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(400000);
|
bandwidth_observer_->OnReceivedEstimatedBitrate(400000);
|
||||||
EXPECT_EQ(200000u, bitrate_observer.last_bitrate_);
|
EXPECT_EQ(200000u, bitrate_observer_.last_bitrate_);
|
||||||
controller_->SetReservedBitrate(50000);
|
controller_->SetReservedBitrate(50000);
|
||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(400000);
|
bandwidth_observer_->OnReceivedEstimatedBitrate(400000);
|
||||||
EXPECT_EQ(150000u, bitrate_observer.last_bitrate_);
|
EXPECT_EQ(150000u, bitrate_observer_.last_bitrate_);
|
||||||
|
|
||||||
controller_->SetReservedBitrate(0);
|
controller_->SetReservedBitrate(0);
|
||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(250000);
|
bandwidth_observer_->OnReceivedEstimatedBitrate(250000);
|
||||||
EXPECT_EQ(200000u, bitrate_observer.last_bitrate_);
|
EXPECT_EQ(200000u, bitrate_observer_.last_bitrate_);
|
||||||
controller_->SetReservedBitrate(50000);
|
controller_->SetReservedBitrate(50000);
|
||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(250000);
|
bandwidth_observer_->OnReceivedEstimatedBitrate(250000);
|
||||||
EXPECT_EQ(150000u, bitrate_observer.last_bitrate_);
|
EXPECT_EQ(150000u, bitrate_observer_.last_bitrate_);
|
||||||
|
|
||||||
controller_->SetReservedBitrate(0);
|
controller_->SetReservedBitrate(0);
|
||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(200000);
|
bandwidth_observer_->OnReceivedEstimatedBitrate(200000);
|
||||||
EXPECT_EQ(200000u, bitrate_observer.last_bitrate_);
|
EXPECT_EQ(200000u, bitrate_observer_.last_bitrate_);
|
||||||
controller_->SetReservedBitrate(30000);
|
controller_->SetReservedBitrate(30000);
|
||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(200000);
|
bandwidth_observer_->OnReceivedEstimatedBitrate(200000);
|
||||||
EXPECT_EQ(170000u, bitrate_observer.last_bitrate_);
|
EXPECT_EQ(170000u, bitrate_observer_.last_bitrate_);
|
||||||
|
|
||||||
controller_->SetReservedBitrate(0);
|
controller_->SetReservedBitrate(0);
|
||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(160000);
|
bandwidth_observer_->OnReceivedEstimatedBitrate(160000);
|
||||||
EXPECT_EQ(160000u, bitrate_observer.last_bitrate_);
|
EXPECT_EQ(160000u, bitrate_observer_.last_bitrate_);
|
||||||
controller_->SetReservedBitrate(30000);
|
controller_->SetReservedBitrate(30000);
|
||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(160000);
|
bandwidth_observer_->OnReceivedEstimatedBitrate(160000);
|
||||||
EXPECT_EQ(130000u, bitrate_observer.last_bitrate_);
|
EXPECT_EQ(130000u, bitrate_observer_.last_bitrate_);
|
||||||
|
|
||||||
controller_->SetReservedBitrate(0);
|
controller_->SetReservedBitrate(0);
|
||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(120000);
|
bandwidth_observer_->OnReceivedEstimatedBitrate(120000);
|
||||||
EXPECT_EQ(120000u, bitrate_observer.last_bitrate_);
|
EXPECT_EQ(120000u, bitrate_observer_.last_bitrate_);
|
||||||
controller_->SetReservedBitrate(10000);
|
controller_->SetReservedBitrate(10000);
|
||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(120000);
|
bandwidth_observer_->OnReceivedEstimatedBitrate(120000);
|
||||||
EXPECT_EQ(110000u, bitrate_observer.last_bitrate_);
|
EXPECT_EQ(110000u, bitrate_observer_.last_bitrate_);
|
||||||
|
|
||||||
controller_->SetReservedBitrate(0);
|
controller_->SetReservedBitrate(0);
|
||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(120000);
|
bandwidth_observer_->OnReceivedEstimatedBitrate(120000);
|
||||||
EXPECT_EQ(120000u, bitrate_observer.last_bitrate_);
|
EXPECT_EQ(120000u, bitrate_observer_.last_bitrate_);
|
||||||
controller_->SetReservedBitrate(50000);
|
controller_->SetReservedBitrate(50000);
|
||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(120000);
|
bandwidth_observer_->OnReceivedEstimatedBitrate(120000);
|
||||||
EXPECT_EQ(100000u, bitrate_observer.last_bitrate_);
|
// Limited by min bitrate.
|
||||||
|
EXPECT_EQ(100000u, bitrate_observer_.last_bitrate_);
|
||||||
|
|
||||||
controller_->SetReservedBitrate(10000);
|
controller_->SetReservedBitrate(10000);
|
||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(0);
|
bandwidth_observer_->OnReceivedEstimatedBitrate(1);
|
||||||
EXPECT_EQ(100000u, bitrate_observer.last_bitrate_);
|
EXPECT_EQ(100000u, bitrate_observer_.last_bitrate_);
|
||||||
|
|
||||||
controller_->RemoveBitrateObserver(&bitrate_observer);
|
|
||||||
}
|
|
||||||
|
|
||||||
class BitrateControllerTestNoEnforceMin : public BitrateControllerTest {
|
|
||||||
protected:
|
|
||||||
BitrateControllerTestNoEnforceMin() : BitrateControllerTest() {
|
|
||||||
enforce_min_bitrate_ = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// The following three tests verify that the EnforceMinBitrate() method works
|
|
||||||
// as intended.
|
|
||||||
TEST_F(BitrateControllerTestNoEnforceMin, OneBitrateObserver) {
|
|
||||||
TestBitrateObserver bitrate_observer_1;
|
|
||||||
controller_->SetBitrateObserver(&bitrate_observer_1, 200000, 100000, 400000);
|
|
||||||
|
|
||||||
// High REMB.
|
|
||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(150000);
|
|
||||||
EXPECT_EQ(150000u, bitrate_observer_1.last_bitrate_);
|
|
||||||
|
|
||||||
// Low REMB.
|
|
||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(10000);
|
|
||||||
EXPECT_EQ(10000u, bitrate_observer_1.last_bitrate_);
|
|
||||||
|
|
||||||
// Keeps at least 10 kbps.
|
|
||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(9000);
|
|
||||||
EXPECT_EQ(10000u, bitrate_observer_1.last_bitrate_);
|
|
||||||
|
|
||||||
controller_->RemoveBitrateObserver(&bitrate_observer_1);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(BitrateControllerTestNoEnforceMin, SetReservedBitrate) {
|
|
||||||
TestBitrateObserver bitrate_observer_1;
|
|
||||||
controller_->SetBitrateObserver(&bitrate_observer_1, 200000, 100000, 400000);
|
|
||||||
controller_->SetReservedBitrate(10000);
|
|
||||||
|
|
||||||
// High REMB.
|
|
||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(150000);
|
|
||||||
EXPECT_EQ(140000u, bitrate_observer_1.last_bitrate_);
|
|
||||||
|
|
||||||
// Low REMB.
|
|
||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(15000);
|
|
||||||
EXPECT_EQ(5000u, bitrate_observer_1.last_bitrate_);
|
|
||||||
|
|
||||||
// Keeps at least 10 kbps.
|
|
||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(9000);
|
|
||||||
EXPECT_EQ(0u, bitrate_observer_1.last_bitrate_);
|
|
||||||
|
|
||||||
controller_->RemoveBitrateObserver(&bitrate_observer_1);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(BitrateControllerTestNoEnforceMin, ThreeBitrateObservers) {
|
|
||||||
TestBitrateObserver bitrate_observer_1;
|
|
||||||
TestBitrateObserver bitrate_observer_2;
|
|
||||||
TestBitrateObserver bitrate_observer_3;
|
|
||||||
// Set up the observers with min bitrates at 100000, 200000, and 300000.
|
|
||||||
// Note: The start bitrate of bitrate_observer_1 (700000) is used as the
|
|
||||||
// overall start bitrate.
|
|
||||||
controller_->SetBitrateObserver(&bitrate_observer_1, 700000, 100000, 400000);
|
|
||||||
controller_->SetBitrateObserver(&bitrate_observer_2, 200000, 200000, 400000);
|
|
||||||
controller_->SetBitrateObserver(&bitrate_observer_3, 200000, 300000, 400000);
|
|
||||||
|
|
||||||
// High REMB. Make sure the controllers get a fair share of the surplus
|
|
||||||
// (i.e., what is left after each controller gets its min rate).
|
|
||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(690000);
|
|
||||||
// Verify that each observer gets its min rate (sum of min rates is 600000),
|
|
||||||
// and that the remaining 90000 is divided equally among the three.
|
|
||||||
EXPECT_EQ(130000u, bitrate_observer_1.last_bitrate_);
|
|
||||||
EXPECT_EQ(230000u, bitrate_observer_2.last_bitrate_);
|
|
||||||
EXPECT_EQ(330000u, bitrate_observer_3.last_bitrate_);
|
|
||||||
|
|
||||||
// High REMB, but below the sum of min bitrates.
|
|
||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(500000);
|
|
||||||
// Verify that the first and second observers get their min bitrates, and the
|
|
||||||
// third gets the remainder.
|
|
||||||
EXPECT_EQ(100000u, bitrate_observer_1.last_bitrate_); // Min bitrate.
|
|
||||||
EXPECT_EQ(200000u, bitrate_observer_2.last_bitrate_); // Min bitrate.
|
|
||||||
EXPECT_EQ(200000u, bitrate_observer_3.last_bitrate_); // Remainder.
|
|
||||||
|
|
||||||
// Low REMB.
|
|
||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(10000);
|
|
||||||
// Verify that the first observer gets all the rate, and the rest get zero.
|
|
||||||
EXPECT_EQ(10000u, bitrate_observer_1.last_bitrate_);
|
|
||||||
EXPECT_EQ(0u, bitrate_observer_2.last_bitrate_);
|
|
||||||
EXPECT_EQ(0u, bitrate_observer_3.last_bitrate_);
|
|
||||||
|
|
||||||
// Verify it keeps an estimate of at least 10kbps.
|
|
||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(9000);
|
|
||||||
EXPECT_EQ(10000u, bitrate_observer_1.last_bitrate_);
|
|
||||||
EXPECT_EQ(0u, bitrate_observer_2.last_bitrate_);
|
|
||||||
EXPECT_EQ(0u, bitrate_observer_3.last_bitrate_);
|
|
||||||
|
|
||||||
controller_->RemoveBitrateObserver(&bitrate_observer_1);
|
|
||||||
controller_->RemoveBitrateObserver(&bitrate_observer_2);
|
|
||||||
controller_->RemoveBitrateObserver(&bitrate_observer_3);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(BitrateControllerTest, ThreeBitrateObserversLowRembEnforceMin) {
|
|
||||||
TestBitrateObserver bitrate_observer_1;
|
|
||||||
TestBitrateObserver bitrate_observer_2;
|
|
||||||
TestBitrateObserver bitrate_observer_3;
|
|
||||||
controller_->SetBitrateObserver(&bitrate_observer_1, 200000, 100000, 300000);
|
|
||||||
controller_->SetBitrateObserver(&bitrate_observer_2, 200000, 200000, 300000);
|
|
||||||
controller_->SetBitrateObserver(&bitrate_observer_3, 200000, 300000, 300000);
|
|
||||||
|
|
||||||
// Low REMB. Verify that all observers still get their respective min bitrate.
|
|
||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(1000);
|
|
||||||
EXPECT_EQ(100000u, bitrate_observer_1.last_bitrate_); // Min cap.
|
|
||||||
EXPECT_EQ(200000u, bitrate_observer_2.last_bitrate_); // Min cap.
|
|
||||||
EXPECT_EQ(300000u, bitrate_observer_3.last_bitrate_); // Min cap.
|
|
||||||
|
|
||||||
controller_->RemoveBitrateObserver(&bitrate_observer_1);
|
|
||||||
controller_->RemoveBitrateObserver(&bitrate_observer_2);
|
|
||||||
controller_->RemoveBitrateObserver(&bitrate_observer_3);
|
|
||||||
}
|
}
|
||||||
|
108
webrtc/modules/bitrate_controller/include/bitrate_allocator.h
Normal file
108
webrtc/modules/bitrate_controller/include/bitrate_allocator.h
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license
|
||||||
|
* that can be found in the LICENSE file in the root of the source
|
||||||
|
* tree. An additional intellectual property rights grant can be found
|
||||||
|
* in the file PATENTS. All contributing project authors may
|
||||||
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*
|
||||||
|
* Usage: this class will register multiple RtcpBitrateObserver's one at each
|
||||||
|
* RTCP module. It will aggregate the results and run one bandwidth estimation
|
||||||
|
* and push the result to the encoders via BitrateObserver(s).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WEBRTC_MODULES_BITRATE_CONTROLLER_INCLUDE_BITRATE_ALLOCATOR_H_
|
||||||
|
#define WEBRTC_MODULES_BITRATE_CONTROLLER_INCLUDE_BITRATE_ALLOCATOR_H_
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <map>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include "webrtc/base/scoped_ptr.h"
|
||||||
|
#include "webrtc/base/thread_annotations.h"
|
||||||
|
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
|
||||||
|
class BitrateObserver;
|
||||||
|
|
||||||
|
class BitrateAllocator {
|
||||||
|
public:
|
||||||
|
BitrateAllocator();
|
||||||
|
virtual ~BitrateAllocator();
|
||||||
|
|
||||||
|
void OnNetworkChanged(uint32_t target_bitrate,
|
||||||
|
uint8_t fraction_loss,
|
||||||
|
int64_t rtt);
|
||||||
|
|
||||||
|
// Set the start and max send bitrate used by the bandwidth management.
|
||||||
|
//
|
||||||
|
// observer, updates bitrates if already in use.
|
||||||
|
// min_bitrate_kbit = 0 equals no min bitrate.
|
||||||
|
// max_bitrate_kit = 0 equals no max bitrate.
|
||||||
|
//
|
||||||
|
// Returns a new suggested start bitrate computed from the start and min
|
||||||
|
// bitrates of the observers, or -1 if the start bitrate shouldn't be changed.
|
||||||
|
virtual int AddBitrateObserver(BitrateObserver* observer,
|
||||||
|
uint32_t start_bitrate,
|
||||||
|
uint32_t min_bitrate,
|
||||||
|
uint32_t max_bitrate);
|
||||||
|
|
||||||
|
virtual void RemoveBitrateObserver(BitrateObserver* observer);
|
||||||
|
|
||||||
|
void GetMinMaxBitrateSumBps(int* min_bitrate_sum_bps,
|
||||||
|
int* max_bitrate_sum_bps) const;
|
||||||
|
|
||||||
|
// This method controls the behavior when the available bitrate is lower than
|
||||||
|
// the minimum bitrate, or the sum of minimum bitrates.
|
||||||
|
// When true, the bitrate will never be set lower than the minimum bitrate(s).
|
||||||
|
// When false, the bitrate observers will be allocated rates up to their
|
||||||
|
// respective minimum bitrate, satisfying one observer after the other.
|
||||||
|
void EnforceMinBitrate(bool enforce_min_bitrate);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct BitrateConfiguration {
|
||||||
|
BitrateConfiguration(uint32_t start_bitrate,
|
||||||
|
uint32_t min_bitrate,
|
||||||
|
uint32_t max_bitrate)
|
||||||
|
: start_bitrate_(start_bitrate),
|
||||||
|
min_bitrate_(min_bitrate),
|
||||||
|
max_bitrate_(max_bitrate) {}
|
||||||
|
uint32_t start_bitrate_;
|
||||||
|
uint32_t min_bitrate_;
|
||||||
|
uint32_t max_bitrate_;
|
||||||
|
};
|
||||||
|
struct ObserverConfiguration {
|
||||||
|
ObserverConfiguration(BitrateObserver* observer, uint32_t bitrate)
|
||||||
|
: observer_(observer), min_bitrate_(bitrate) {}
|
||||||
|
BitrateObserver* observer_;
|
||||||
|
uint32_t min_bitrate_;
|
||||||
|
};
|
||||||
|
typedef std::pair<BitrateObserver*, BitrateConfiguration*>
|
||||||
|
BitrateObserverConfiguration;
|
||||||
|
typedef std::list<BitrateObserverConfiguration> BitrateObserverConfList;
|
||||||
|
typedef std::multimap<uint32_t, ObserverConfiguration*> ObserverSortingMap;
|
||||||
|
|
||||||
|
void NormalRateAllocation(uint32_t bitrate,
|
||||||
|
uint8_t fraction_loss,
|
||||||
|
int64_t rtt,
|
||||||
|
uint32_t sum_min_bitrates)
|
||||||
|
EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
|
||||||
|
|
||||||
|
void LowRateAllocation(uint32_t bitrate,
|
||||||
|
uint8_t fraction_loss,
|
||||||
|
int64_t rtt,
|
||||||
|
uint32_t sum_min_bitrates)
|
||||||
|
EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
|
||||||
|
|
||||||
|
BitrateObserverConfList::iterator FindObserverConfigurationPair(
|
||||||
|
const BitrateObserver* observer) EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
|
||||||
|
|
||||||
|
rtc::scoped_ptr<CriticalSectionWrapper> crit_sect_;
|
||||||
|
BitrateObserverConfList bitrate_observers_ GUARDED_BY(crit_sect_);
|
||||||
|
bool bitrate_observers_modified_ GUARDED_BY(crit_sect_);
|
||||||
|
bool enforce_min_bitrate_ GUARDED_BY(crit_sect_);
|
||||||
|
};
|
||||||
|
} // namespace webrtc
|
||||||
|
#endif // WEBRTC_MODULES_BITRATE_CONTROLLER_INCLUDE_BITRATE_ALLOCATOR_H_
|
@ -15,67 +15,50 @@
|
|||||||
#ifndef WEBRTC_MODULES_BITRATE_CONTROLLER_INCLUDE_BITRATE_CONTROLLER_H_
|
#ifndef WEBRTC_MODULES_BITRATE_CONTROLLER_INCLUDE_BITRATE_CONTROLLER_H_
|
||||||
#define WEBRTC_MODULES_BITRATE_CONTROLLER_INCLUDE_BITRATE_CONTROLLER_H_
|
#define WEBRTC_MODULES_BITRATE_CONTROLLER_INCLUDE_BITRATE_CONTROLLER_H_
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include "webrtc/modules/interface/module.h"
|
#include "webrtc/modules/interface/module.h"
|
||||||
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
|
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
|
class CriticalSectionWrapper;
|
||||||
|
|
||||||
class BitrateObserver {
|
class BitrateObserver {
|
||||||
/*
|
// Observer class for bitrate changes announced due to change in bandwidth
|
||||||
* Observer class for the encoders, each encoder should implement this class
|
// estimate or due to bitrate allocation changes. Fraction loss and rtt is
|
||||||
* to get the target bitrate. It also get the fraction loss and rtt to
|
// also part of this callback to allow the obsevrer to optimize its settings
|
||||||
* optimize its settings for this type of network. |target_bitrate| is the
|
// for different types of network environments. The bitrate does not include
|
||||||
* target media/payload bitrate excluding packet headers, measured in bits
|
// packet headers and is measured in bits per second.
|
||||||
* per second.
|
|
||||||
*/
|
|
||||||
public:
|
public:
|
||||||
virtual void OnNetworkChanged(uint32_t target_bitrate,
|
virtual void OnNetworkChanged(uint32_t bitrate_bps,
|
||||||
uint8_t fraction_loss, // 0 - 255.
|
uint8_t fraction_loss, // 0 - 255.
|
||||||
int64_t rtt) = 0;
|
int64_t rtt_ms) = 0;
|
||||||
|
|
||||||
virtual ~BitrateObserver() {}
|
virtual ~BitrateObserver() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class BitrateController : public Module {
|
class BitrateController : public Module {
|
||||||
/*
|
// This class collects feedback from all streams sent to a peer (via
|
||||||
* This class collects feedback from all streams sent to a peer (via
|
// RTCPBandwidthObservers). It does one aggregated send side bandwidth
|
||||||
* RTCPBandwidthObservers). It does one aggregated send side bandwidth
|
// estimation and divide the available bitrate between all its registered
|
||||||
* estimation and divide the available bitrate between all its registered
|
// BitrateObservers.
|
||||||
* BitrateObservers.
|
|
||||||
*/
|
|
||||||
public:
|
public:
|
||||||
// The argument |enforce_min_bitrate| controls the behavior when the available
|
static const int kDefaultStartBitrateKbps = 300;
|
||||||
// bitrate is lower than the minimum bitrate, or the sum of minimum bitrates.
|
|
||||||
// When true, the bitrate will never be set lower than the minimum bitrate(s).
|
|
||||||
// When false, the bitrate observers will be allocated rates up to their
|
|
||||||
// respective minimum bitrate, satisfying one observer after the other.
|
|
||||||
static BitrateController* CreateBitrateController(Clock* clock,
|
static BitrateController* CreateBitrateController(Clock* clock,
|
||||||
bool enforce_min_bitrate);
|
BitrateObserver* observer);
|
||||||
virtual ~BitrateController() {}
|
virtual ~BitrateController() {}
|
||||||
|
|
||||||
virtual RtcpBandwidthObserver* CreateRtcpBandwidthObserver() = 0;
|
virtual RtcpBandwidthObserver* CreateRtcpBandwidthObserver() = 0;
|
||||||
|
|
||||||
|
virtual void SetStartBitrate(int start_bitrate_bps) = 0;
|
||||||
|
virtual void SetMinMaxBitrate(int min_bitrate_bps, int max_bitrate_bps) = 0;
|
||||||
|
|
||||||
// Gets the available payload bandwidth in bits per second. Note that
|
// Gets the available payload bandwidth in bits per second. Note that
|
||||||
// this bandwidth excludes packet headers.
|
// this bandwidth excludes packet headers.
|
||||||
virtual bool AvailableBandwidth(uint32_t* bandwidth) const = 0;
|
virtual bool AvailableBandwidth(uint32_t* bandwidth) const = 0;
|
||||||
|
|
||||||
/*
|
|
||||||
* Set the start and max send bitrate used by the bandwidth management.
|
|
||||||
*
|
|
||||||
* observer, updates bitrates if already in use.
|
|
||||||
* min_bitrate_kbit = 0 equals no min bitrate.
|
|
||||||
* max_bitrate_kit = 0 equals no max bitrate.
|
|
||||||
*/
|
|
||||||
virtual void SetBitrateObserver(BitrateObserver* observer,
|
|
||||||
uint32_t start_bitrate,
|
|
||||||
uint32_t min_bitrate,
|
|
||||||
uint32_t max_bitrate) = 0;
|
|
||||||
|
|
||||||
virtual void RemoveBitrateObserver(BitrateObserver* observer) = 0;
|
|
||||||
|
|
||||||
// Changes the mode that was set in the constructor.
|
|
||||||
virtual void EnforceMinBitrate(bool enforce_min_bitrate) = 0;
|
|
||||||
|
|
||||||
virtual void SetReservedBitrate(uint32_t reserved_bitrate_bps) = 0;
|
virtual void SetReservedBitrate(uint32_t reserved_bitrate_bps) = 0;
|
||||||
|
|
||||||
virtual void SetBitrateSent(uint32_t bitrate_sent_bps) = 0;
|
virtual void SetBitrateSent(uint32_t bitrate_sent_bps) = 0;
|
||||||
|
@ -96,8 +96,8 @@ void SendSideBandwidthEstimation::SetMinMaxBitrate(uint32_t min_bitrate,
|
|||||||
max_bitrate_configured_ = max_bitrate;
|
max_bitrate_configured_ = max_bitrate;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendSideBandwidthEstimation::SetMinBitrate(uint32_t min_bitrate) {
|
uint32_t SendSideBandwidthEstimation::GetMinBitrate() const {
|
||||||
min_bitrate_configured_ = min_bitrate;
|
return min_bitrate_configured_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendSideBandwidthEstimation::CurrentEstimate(uint32_t* bitrate,
|
void SendSideBandwidthEstimation::CurrentEstimate(uint32_t* bitrate,
|
||||||
|
@ -40,7 +40,7 @@ class SendSideBandwidthEstimation {
|
|||||||
|
|
||||||
void SetSendBitrate(uint32_t bitrate);
|
void SetSendBitrate(uint32_t bitrate);
|
||||||
void SetMinMaxBitrate(uint32_t min_bitrate, uint32_t max_bitrate);
|
void SetMinMaxBitrate(uint32_t min_bitrate, uint32_t max_bitrate);
|
||||||
void SetMinBitrate(uint32_t min_bitrate);
|
uint32_t GetMinBitrate() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum UmaState { kNoUpdate, kFirstDone, kDone };
|
enum UmaState { kNoUpdate, kFirstDone, kDone };
|
||||||
|
@ -185,6 +185,7 @@
|
|||||||
'audio_processing/transient/wpd_node_unittest.cc',
|
'audio_processing/transient/wpd_node_unittest.cc',
|
||||||
'audio_processing/transient/wpd_tree_unittest.cc',
|
'audio_processing/transient/wpd_tree_unittest.cc',
|
||||||
'audio_processing/utility/delay_estimator_unittest.cc',
|
'audio_processing/utility/delay_estimator_unittest.cc',
|
||||||
|
'bitrate_controller/bitrate_allocator_unittest.cc',
|
||||||
'bitrate_controller/bitrate_controller_unittest.cc',
|
'bitrate_controller/bitrate_controller_unittest.cc',
|
||||||
'bitrate_controller/remb_suppressor_unittest.cc',
|
'bitrate_controller/remb_suppressor_unittest.cc',
|
||||||
'bitrate_controller/send_side_bandwidth_estimation_unittest.cc',
|
'bitrate_controller/send_side_bandwidth_estimation_unittest.cc',
|
||||||
|
@ -24,13 +24,14 @@ namespace bwe {
|
|||||||
|
|
||||||
RembBweSender::RembBweSender(int kbps, BitrateObserver* observer, Clock* clock)
|
RembBweSender::RembBweSender(int kbps, BitrateObserver* observer, Clock* clock)
|
||||||
: bitrate_controller_(
|
: bitrate_controller_(
|
||||||
BitrateController::CreateBitrateController(clock, false)),
|
BitrateController::CreateBitrateController(clock, observer)),
|
||||||
feedback_observer_(bitrate_controller_->CreateRtcpBandwidthObserver()),
|
feedback_observer_(bitrate_controller_->CreateRtcpBandwidthObserver()),
|
||||||
clock_(clock) {
|
clock_(clock) {
|
||||||
assert(kbps >= kMinBitrateKbps);
|
assert(kbps >= kMinBitrateKbps);
|
||||||
assert(kbps <= kMaxBitrateKbps);
|
assert(kbps <= kMaxBitrateKbps);
|
||||||
bitrate_controller_->SetBitrateObserver(
|
bitrate_controller_->SetStartBitrate(1000 * kbps);
|
||||||
observer, 1000 * kbps, 1000 * kMinBitrateKbps, 1000 * kMaxBitrateKbps);
|
bitrate_controller_->SetMinMaxBitrate(1000 * kMinBitrateKbps,
|
||||||
|
1000 * kMaxBitrateKbps);
|
||||||
}
|
}
|
||||||
|
|
||||||
RembBweSender::~RembBweSender() {
|
RembBweSender::~RembBweSender() {
|
||||||
|
@ -16,15 +16,16 @@ namespace bwe {
|
|||||||
|
|
||||||
FullBweSender::FullBweSender(int kbps, BitrateObserver* observer, Clock* clock)
|
FullBweSender::FullBweSender(int kbps, BitrateObserver* observer, Clock* clock)
|
||||||
: bitrate_controller_(
|
: bitrate_controller_(
|
||||||
BitrateController::CreateBitrateController(clock, false)),
|
BitrateController::CreateBitrateController(clock, observer)),
|
||||||
rbe_(AbsoluteSendTimeRemoteBitrateEstimatorFactory()
|
rbe_(AbsoluteSendTimeRemoteBitrateEstimatorFactory()
|
||||||
.Create(this, clock, kAimdControl, 1000 * kMinBitrateKbps)),
|
.Create(this, clock, kAimdControl, 1000 * kMinBitrateKbps)),
|
||||||
feedback_observer_(bitrate_controller_->CreateRtcpBandwidthObserver()),
|
feedback_observer_(bitrate_controller_->CreateRtcpBandwidthObserver()),
|
||||||
clock_(clock) {
|
clock_(clock) {
|
||||||
assert(kbps >= kMinBitrateKbps);
|
assert(kbps >= kMinBitrateKbps);
|
||||||
assert(kbps <= kMaxBitrateKbps);
|
assert(kbps <= kMaxBitrateKbps);
|
||||||
bitrate_controller_->SetBitrateObserver(
|
bitrate_controller_->SetStartBitrate(1000 * kbps);
|
||||||
observer, 1000 * kbps, 1000 * kMinBitrateKbps, 1000 * kMaxBitrateKbps);
|
bitrate_controller_->SetMinMaxBitrate(1000 * kMinBitrateKbps,
|
||||||
|
1000 * kMaxBitrateKbps);
|
||||||
}
|
}
|
||||||
|
|
||||||
FullBweSender::~FullBweSender() {
|
FullBweSender::~FullBweSender() {
|
||||||
|
@ -28,7 +28,7 @@ namespace webrtc {
|
|||||||
class MockVieEncoder : public ViEEncoder {
|
class MockVieEncoder : public ViEEncoder {
|
||||||
public:
|
public:
|
||||||
explicit MockVieEncoder(ProcessThread* process_thread)
|
explicit MockVieEncoder(ProcessThread* process_thread)
|
||||||
: ViEEncoder(1, 1, config_, *process_thread, NULL, false) {}
|
: ViEEncoder(1, 1, config_, *process_thread, NULL, NULL, false) {}
|
||||||
~MockVieEncoder() {}
|
~MockVieEncoder() {}
|
||||||
|
|
||||||
MOCK_METHOD1(OnReceivedIntraFrameRequest,
|
MOCK_METHOD1(OnReceivedIntraFrameRequest,
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
#include "webrtc/base/thread_annotations.h"
|
#include "webrtc/base/thread_annotations.h"
|
||||||
#include "webrtc/common.h"
|
#include "webrtc/common.h"
|
||||||
#include "webrtc/experiments.h"
|
#include "webrtc/experiments.h"
|
||||||
#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
|
|
||||||
#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
|
#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
|
||||||
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
|
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
|
||||||
#include "webrtc/modules/utility/interface/process_thread.h"
|
#include "webrtc/modules/utility/interface/process_thread.h"
|
||||||
@ -137,12 +136,12 @@ class WrappingBitrateEstimator : public RemoteBitrateEstimator {
|
|||||||
};
|
};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
ChannelGroup::ChannelGroup(ProcessThread* process_thread,
|
ChannelGroup::ChannelGroup(ProcessThread* process_thread, const Config* config)
|
||||||
const Config* config)
|
|
||||||
: remb_(new VieRemb()),
|
: remb_(new VieRemb()),
|
||||||
|
bitrate_allocator_(new BitrateAllocator()),
|
||||||
bitrate_controller_(
|
bitrate_controller_(
|
||||||
BitrateController::CreateBitrateController(Clock::GetRealTimeClock(),
|
BitrateController::CreateBitrateController(Clock::GetRealTimeClock(),
|
||||||
true)),
|
this)),
|
||||||
call_stats_(new CallStats()),
|
call_stats_(new CallStats()),
|
||||||
encoder_state_feedback_(new EncoderStateFeedback()),
|
encoder_state_feedback_(new EncoderStateFeedback()),
|
||||||
config_(config),
|
config_(config),
|
||||||
@ -192,6 +191,10 @@ bool ChannelGroup::Empty() {
|
|||||||
return channels_.empty();
|
return channels_.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BitrateAllocator* ChannelGroup::GetBitrateAllocator() {
|
||||||
|
return bitrate_allocator_.get();
|
||||||
|
}
|
||||||
|
|
||||||
BitrateController* ChannelGroup::GetBitrateController() {
|
BitrateController* ChannelGroup::GetBitrateController() {
|
||||||
return bitrate_controller_.get();
|
return bitrate_controller_.get();
|
||||||
}
|
}
|
||||||
@ -227,4 +230,10 @@ void ChannelGroup::SetChannelRembStatus(int channel_id,
|
|||||||
remb_->RemoveReceiveChannel(rtp_module);
|
remb_->RemoveReceiveChannel(rtp_module);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ChannelGroup::OnNetworkChanged(uint32_t target_bitrate_bps,
|
||||||
|
uint8_t fraction_loss,
|
||||||
|
int64_t rtt) {
|
||||||
|
bitrate_allocator_->OnNetworkChanged(target_bitrate_bps, fraction_loss, rtt);
|
||||||
|
}
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -14,10 +14,11 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
#include "webrtc/base/scoped_ptr.h"
|
#include "webrtc/base/scoped_ptr.h"
|
||||||
|
#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
class BitrateController;
|
class BitrateAllocator;
|
||||||
class CallStats;
|
class CallStats;
|
||||||
class Config;
|
class Config;
|
||||||
class EncoderStateFeedback;
|
class EncoderStateFeedback;
|
||||||
@ -29,7 +30,7 @@ class VieRemb;
|
|||||||
|
|
||||||
// Channel group contains data common for several channels. All channels in the
|
// Channel group contains data common for several channels. All channels in the
|
||||||
// group are assumed to send/receive data to the same end-point.
|
// group are assumed to send/receive data to the same end-point.
|
||||||
class ChannelGroup {
|
class ChannelGroup : public BitrateObserver {
|
||||||
public:
|
public:
|
||||||
ChannelGroup(ProcessThread* process_thread, const Config* config);
|
ChannelGroup(ProcessThread* process_thread, const Config* config);
|
||||||
~ChannelGroup();
|
~ChannelGroup();
|
||||||
@ -44,15 +45,22 @@ class ChannelGroup {
|
|||||||
bool receiver,
|
bool receiver,
|
||||||
ViEChannel* channel);
|
ViEChannel* channel);
|
||||||
|
|
||||||
|
BitrateAllocator* GetBitrateAllocator();
|
||||||
BitrateController* GetBitrateController();
|
BitrateController* GetBitrateController();
|
||||||
CallStats* GetCallStats();
|
CallStats* GetCallStats();
|
||||||
RemoteBitrateEstimator* GetRemoteBitrateEstimator();
|
RemoteBitrateEstimator* GetRemoteBitrateEstimator();
|
||||||
EncoderStateFeedback* GetEncoderStateFeedback();
|
EncoderStateFeedback* GetEncoderStateFeedback();
|
||||||
|
|
||||||
|
// Implements BitrateObserver.
|
||||||
|
void OnNetworkChanged(uint32_t target_bitrate_bps,
|
||||||
|
uint8_t fraction_loss,
|
||||||
|
int64_t rtt) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::set<int> ChannelSet;
|
typedef std::set<int> ChannelSet;
|
||||||
|
|
||||||
rtc::scoped_ptr<VieRemb> remb_;
|
rtc::scoped_ptr<VieRemb> remb_;
|
||||||
|
rtc::scoped_ptr<BitrateAllocator> bitrate_allocator_;
|
||||||
rtc::scoped_ptr<BitrateController> bitrate_controller_;
|
rtc::scoped_ptr<BitrateController> bitrate_controller_;
|
||||||
rtc::scoped_ptr<CallStats> call_stats_;
|
rtc::scoped_ptr<CallStats> call_stats_;
|
||||||
rtc::scoped_ptr<RemoteBitrateEstimator> remote_bitrate_estimator_;
|
rtc::scoped_ptr<RemoteBitrateEstimator> remote_bitrate_estimator_;
|
||||||
|
@ -89,13 +89,11 @@ int ViEChannelManager::CreateChannel(int* channel_id,
|
|||||||
// Create a new channel group and add this channel.
|
// Create a new channel group and add this channel.
|
||||||
ChannelGroup* group = new ChannelGroup(module_process_thread_,
|
ChannelGroup* group = new ChannelGroup(module_process_thread_,
|
||||||
channel_group_config);
|
channel_group_config);
|
||||||
|
BitrateAllocator* bitrate_allocator = group->GetBitrateAllocator();
|
||||||
BitrateController* bitrate_controller = group->GetBitrateController();
|
BitrateController* bitrate_controller = group->GetBitrateController();
|
||||||
ViEEncoder* vie_encoder = new ViEEncoder(new_channel_id,
|
ViEEncoder* vie_encoder = new ViEEncoder(
|
||||||
number_of_cores_,
|
new_channel_id, number_of_cores_, engine_config_, *module_process_thread_,
|
||||||
engine_config_,
|
bitrate_allocator, bitrate_controller, false);
|
||||||
*module_process_thread_,
|
|
||||||
bitrate_controller,
|
|
||||||
false);
|
|
||||||
|
|
||||||
RtcpBandwidthObserver* bandwidth_observer =
|
RtcpBandwidthObserver* bandwidth_observer =
|
||||||
bitrate_controller->CreateRtcpBandwidthObserver();
|
bitrate_controller->CreateRtcpBandwidthObserver();
|
||||||
@ -153,6 +151,7 @@ int ViEChannelManager::CreateChannel(int* channel_id,
|
|||||||
if (new_channel_id == -1) {
|
if (new_channel_id == -1) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
BitrateAllocator* bitrate_allocator = channel_group->GetBitrateAllocator();
|
||||||
BitrateController* bitrate_controller = channel_group->GetBitrateController();
|
BitrateController* bitrate_controller = channel_group->GetBitrateController();
|
||||||
RtcpBandwidthObserver* bandwidth_observer =
|
RtcpBandwidthObserver* bandwidth_observer =
|
||||||
bitrate_controller->CreateRtcpBandwidthObserver();
|
bitrate_controller->CreateRtcpBandwidthObserver();
|
||||||
@ -166,11 +165,10 @@ int ViEChannelManager::CreateChannel(int* channel_id,
|
|||||||
ViEEncoder* vie_encoder = NULL;
|
ViEEncoder* vie_encoder = NULL;
|
||||||
if (sender) {
|
if (sender) {
|
||||||
// We need to create a new ViEEncoder.
|
// We need to create a new ViEEncoder.
|
||||||
vie_encoder = new ViEEncoder(new_channel_id, number_of_cores_,
|
vie_encoder =
|
||||||
engine_config_,
|
new ViEEncoder(new_channel_id, number_of_cores_, engine_config_,
|
||||||
*module_process_thread_,
|
*module_process_thread_, bitrate_allocator,
|
||||||
bitrate_controller,
|
bitrate_controller, disable_default_encoder);
|
||||||
disable_default_encoder);
|
|
||||||
if (!(vie_encoder->Init() &&
|
if (!(vie_encoder->Init() &&
|
||||||
CreateChannelObject(
|
CreateChannelObject(
|
||||||
new_channel_id,
|
new_channel_id,
|
||||||
|
@ -131,6 +131,7 @@ ViEEncoder::ViEEncoder(int32_t channel_id,
|
|||||||
uint32_t number_of_cores,
|
uint32_t number_of_cores,
|
||||||
const Config& config,
|
const Config& config,
|
||||||
ProcessThread& module_process_thread,
|
ProcessThread& module_process_thread,
|
||||||
|
BitrateAllocator* bitrate_allocator,
|
||||||
BitrateController* bitrate_controller,
|
BitrateController* bitrate_controller,
|
||||||
bool disable_default_encoder)
|
bool disable_default_encoder)
|
||||||
: channel_id_(channel_id),
|
: channel_id_(channel_id),
|
||||||
@ -142,6 +143,7 @@ ViEEncoder::ViEEncoder(int32_t channel_id,
|
|||||||
vcm_protection_callback_(NULL),
|
vcm_protection_callback_(NULL),
|
||||||
callback_cs_(CriticalSectionWrapper::CreateCriticalSection()),
|
callback_cs_(CriticalSectionWrapper::CreateCriticalSection()),
|
||||||
data_cs_(CriticalSectionWrapper::CreateCriticalSection()),
|
data_cs_(CriticalSectionWrapper::CreateCriticalSection()),
|
||||||
|
bitrate_allocator_(bitrate_allocator),
|
||||||
bitrate_controller_(bitrate_controller),
|
bitrate_controller_(bitrate_controller),
|
||||||
time_of_last_incoming_frame_ms_(0),
|
time_of_last_incoming_frame_ms_(0),
|
||||||
send_padding_(false),
|
send_padding_(false),
|
||||||
@ -245,9 +247,8 @@ void ViEEncoder::StopThreadsAndRemoveSharedMembers() {
|
|||||||
|
|
||||||
ViEEncoder::~ViEEncoder() {
|
ViEEncoder::~ViEEncoder() {
|
||||||
UpdateHistograms();
|
UpdateHistograms();
|
||||||
if (bitrate_controller_) {
|
if (bitrate_allocator_)
|
||||||
bitrate_controller_->RemoveBitrateObserver(bitrate_observer_.get());
|
bitrate_allocator_->RemoveBitrateObserver(bitrate_observer_.get());
|
||||||
}
|
|
||||||
VideoCodingModule::Destroy(&vcm_);
|
VideoCodingModule::Destroy(&vcm_);
|
||||||
VideoProcessingModule::Destroy(&vpm_);
|
VideoProcessingModule::Destroy(&vpm_);
|
||||||
delete qm_callback_;
|
delete qm_callback_;
|
||||||
@ -388,22 +389,33 @@ int32_t ViEEncoder::SetEncoder(const webrtc::VideoCodec& video_codec) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bitrate_controller_->SetBitrateObserver(bitrate_observer_.get(),
|
// Add the a bitrate observer to the allocator and update the start, max and
|
||||||
video_codec.startBitrate * 1000,
|
// min bitrates of the bitrate controller as needed.
|
||||||
|
int new_bwe_candidate_bps = bitrate_allocator_->AddBitrateObserver(
|
||||||
|
bitrate_observer_.get(), video_codec.startBitrate * 1000,
|
||||||
video_codec.minBitrate * 1000,
|
video_codec.minBitrate * 1000,
|
||||||
kTransmissionMaxBitrateMultiplier *
|
kTransmissionMaxBitrateMultiplier * video_codec.maxBitrate * 1000);
|
||||||
video_codec.maxBitrate * 1000);
|
if (new_bwe_candidate_bps > 0) {
|
||||||
|
uint32_t current_bwe_bps = 0;
|
||||||
|
bitrate_controller_->AvailableBandwidth(¤t_bwe_bps);
|
||||||
|
bitrate_controller_->SetStartBitrate(std::max(
|
||||||
|
static_cast<uint32_t>(new_bwe_candidate_bps), current_bwe_bps));
|
||||||
|
}
|
||||||
|
|
||||||
|
int new_bwe_min_bps = 0;
|
||||||
|
int new_bwe_max_bps = 0;
|
||||||
|
bitrate_allocator_->GetMinMaxBitrateSumBps(&new_bwe_min_bps,
|
||||||
|
&new_bwe_max_bps);
|
||||||
|
bitrate_controller_->SetMinMaxBitrate(new_bwe_min_bps, new_bwe_max_bps);
|
||||||
|
|
||||||
bitrate_controller_->SetCodecMode(video_codec.mode);
|
bitrate_controller_->SetCodecMode(video_codec.mode);
|
||||||
|
|
||||||
CriticalSectionScoped crit(data_cs_.get());
|
int pad_up_to_bitrate_bps =
|
||||||
int pad_up_to_bitrate_kbps = video_codec.startBitrate;
|
GetPaddingNeededBps(1000 * video_codec.startBitrate);
|
||||||
if (pad_up_to_bitrate_kbps < min_transmit_bitrate_kbps_)
|
|
||||||
pad_up_to_bitrate_kbps = min_transmit_bitrate_kbps_;
|
|
||||||
|
|
||||||
paced_sender_->UpdateBitrate(
|
paced_sender_->UpdateBitrate(
|
||||||
video_codec.startBitrate,
|
video_codec.startBitrate,
|
||||||
PacedSender::kDefaultPaceMultiplier * video_codec.startBitrate,
|
PacedSender::kDefaultPaceMultiplier * video_codec.startBitrate,
|
||||||
pad_up_to_bitrate_kbps);
|
pad_up_to_bitrate_bps / 1000);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -448,16 +460,67 @@ bool ViEEncoder::TimeToSendPacket(uint32_t ssrc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t ViEEncoder::TimeToSendPadding(size_t bytes) {
|
size_t ViEEncoder::TimeToSendPadding(size_t bytes) {
|
||||||
bool send_padding;
|
return send_payload_router_->TimeToSendPadding(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ViEEncoder::GetPaddingNeededBps(int bitrate_bps) const {
|
||||||
|
int64_t time_of_last_incoming_frame_ms;
|
||||||
|
int min_transmit_bitrate_bps;
|
||||||
{
|
{
|
||||||
CriticalSectionScoped cs(data_cs_.get());
|
CriticalSectionScoped cs(data_cs_.get());
|
||||||
send_padding =
|
bool send_padding =
|
||||||
send_padding_ || video_suspended_ || min_transmit_bitrate_kbps_ > 0;
|
send_padding_ || video_suspended_ || min_transmit_bitrate_kbps_ > 0;
|
||||||
}
|
if (!send_padding)
|
||||||
if (send_padding) {
|
|
||||||
return send_payload_router_->TimeToSendPadding(bytes);
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
|
time_of_last_incoming_frame_ms = time_of_last_incoming_frame_ms_;
|
||||||
|
min_transmit_bitrate_bps = 1000 * min_transmit_bitrate_kbps_;
|
||||||
|
}
|
||||||
|
|
||||||
|
VideoCodec send_codec;
|
||||||
|
if (vcm_.SendCodec(&send_codec) != 0)
|
||||||
|
return 0;
|
||||||
|
SimulcastStream* stream_configs = send_codec.simulcastStream;
|
||||||
|
// Allocate the bandwidth between the streams.
|
||||||
|
std::vector<uint32_t> stream_bitrates = AllocateStreamBitrates(
|
||||||
|
bitrate_bps, stream_configs, send_codec.numberOfSimulcastStreams);
|
||||||
|
|
||||||
|
bool video_is_suspended = vcm_.VideoSuspended();
|
||||||
|
|
||||||
|
// Find the max amount of padding we can allow ourselves to send at this
|
||||||
|
// point, based on which streams are currently active and what our current
|
||||||
|
// available bandwidth is.
|
||||||
|
int pad_up_to_bitrate_bps = 0;
|
||||||
|
if (send_codec.numberOfSimulcastStreams == 0) {
|
||||||
|
pad_up_to_bitrate_bps = send_codec.minBitrate * 1000;
|
||||||
|
} else {
|
||||||
|
pad_up_to_bitrate_bps =
|
||||||
|
stream_configs[send_codec.numberOfSimulcastStreams - 1].minBitrate *
|
||||||
|
1000;
|
||||||
|
for (int i = 0; i < send_codec.numberOfSimulcastStreams - 1; ++i) {
|
||||||
|
pad_up_to_bitrate_bps += stream_configs[i].targetBitrate * 1000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable padding if only sending one stream and video isn't suspended and
|
||||||
|
// min-transmit bitrate isn't used (applied later).
|
||||||
|
if (!video_is_suspended && send_codec.numberOfSimulcastStreams <= 1)
|
||||||
|
pad_up_to_bitrate_bps = 0;
|
||||||
|
|
||||||
|
// The amount of padding should decay to zero if no frames are being
|
||||||
|
// captured unless a min-transmit bitrate is used.
|
||||||
|
int64_t now_ms = TickTime::MillisecondTimestamp();
|
||||||
|
if (now_ms - time_of_last_incoming_frame_ms > kStopPaddingThresholdMs)
|
||||||
|
pad_up_to_bitrate_bps = 0;
|
||||||
|
|
||||||
|
// Pad up to min bitrate.
|
||||||
|
if (pad_up_to_bitrate_bps < min_transmit_bitrate_bps)
|
||||||
|
pad_up_to_bitrate_bps = min_transmit_bitrate_bps;
|
||||||
|
|
||||||
|
// Padding may never exceed bitrate estimate.
|
||||||
|
if (pad_up_to_bitrate_bps > bitrate_bps)
|
||||||
|
pad_up_to_bitrate_bps = bitrate_bps;
|
||||||
|
|
||||||
|
return pad_up_to_bitrate_bps;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ViEEncoder::EncoderPaused() const {
|
bool ViEEncoder::EncoderPaused() const {
|
||||||
@ -853,7 +916,7 @@ void ViEEncoder::OnNetworkChanged(uint32_t bitrate_bps,
|
|||||||
DCHECK(send_payload_router_ != NULL);
|
DCHECK(send_payload_router_ != NULL);
|
||||||
vcm_.SetChannelParameters(bitrate_bps, fraction_lost, round_trip_time_ms);
|
vcm_.SetChannelParameters(bitrate_bps, fraction_lost, round_trip_time_ms);
|
||||||
bool video_is_suspended = vcm_.VideoSuspended();
|
bool video_is_suspended = vcm_.VideoSuspended();
|
||||||
int bitrate_kbps = bitrate_bps / 1000;
|
|
||||||
VideoCodec send_codec;
|
VideoCodec send_codec;
|
||||||
if (vcm_.SendCodec(&send_codec) != 0) {
|
if (vcm_.SendCodec(&send_codec) != 0) {
|
||||||
return;
|
return;
|
||||||
@ -861,54 +924,21 @@ void ViEEncoder::OnNetworkChanged(uint32_t bitrate_bps,
|
|||||||
SimulcastStream* stream_configs = send_codec.simulcastStream;
|
SimulcastStream* stream_configs = send_codec.simulcastStream;
|
||||||
// Allocate the bandwidth between the streams.
|
// Allocate the bandwidth between the streams.
|
||||||
std::vector<uint32_t> stream_bitrates = AllocateStreamBitrates(
|
std::vector<uint32_t> stream_bitrates = AllocateStreamBitrates(
|
||||||
bitrate_bps,
|
bitrate_bps, stream_configs, send_codec.numberOfSimulcastStreams);
|
||||||
stream_configs,
|
send_payload_router_->SetTargetSendBitrates(stream_bitrates);
|
||||||
send_codec.numberOfSimulcastStreams);
|
|
||||||
// Find the max amount of padding we can allow ourselves to send at this
|
|
||||||
// point, based on which streams are currently active and what our current
|
|
||||||
// available bandwidth is.
|
|
||||||
int pad_up_to_bitrate_kbps = 0;
|
|
||||||
if (send_codec.numberOfSimulcastStreams == 0) {
|
|
||||||
pad_up_to_bitrate_kbps = send_codec.minBitrate;
|
|
||||||
} else {
|
|
||||||
pad_up_to_bitrate_kbps =
|
|
||||||
stream_configs[send_codec.numberOfSimulcastStreams - 1].minBitrate;
|
|
||||||
for (int i = 0; i < send_codec.numberOfSimulcastStreams - 1; ++i) {
|
|
||||||
pad_up_to_bitrate_kbps += stream_configs[i].targetBitrate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable padding if only sending one stream and video isn't suspended and
|
int pad_up_to_bitrate_bps = GetPaddingNeededBps(bitrate_bps);
|
||||||
// min-transmit bitrate isn't used (applied later).
|
paced_sender_->UpdateBitrate(
|
||||||
if (!video_is_suspended && send_codec.numberOfSimulcastStreams <= 1)
|
bitrate_bps / 1000,
|
||||||
pad_up_to_bitrate_kbps = 0;
|
PacedSender::kDefaultPaceMultiplier * bitrate_bps / 1000,
|
||||||
|
pad_up_to_bitrate_bps / 1000);
|
||||||
|
|
||||||
{
|
{
|
||||||
CriticalSectionScoped cs(data_cs_.get());
|
CriticalSectionScoped cs(data_cs_.get());
|
||||||
// The amount of padding should decay to zero if no frames are being
|
|
||||||
// captured unless a min-transmit bitrate is used.
|
|
||||||
int64_t now_ms = TickTime::MillisecondTimestamp();
|
|
||||||
if (now_ms - time_of_last_incoming_frame_ms_ > kStopPaddingThresholdMs)
|
|
||||||
pad_up_to_bitrate_kbps = 0;
|
|
||||||
|
|
||||||
// Pad up to min bitrate.
|
|
||||||
if (pad_up_to_bitrate_kbps < min_transmit_bitrate_kbps_)
|
|
||||||
pad_up_to_bitrate_kbps = min_transmit_bitrate_kbps_;
|
|
||||||
|
|
||||||
// Padding may never exceed bitrate estimate.
|
|
||||||
if (pad_up_to_bitrate_kbps > bitrate_kbps)
|
|
||||||
pad_up_to_bitrate_kbps = bitrate_kbps;
|
|
||||||
|
|
||||||
paced_sender_->UpdateBitrate(
|
|
||||||
bitrate_kbps,
|
|
||||||
PacedSender::kDefaultPaceMultiplier * bitrate_kbps,
|
|
||||||
pad_up_to_bitrate_kbps);
|
|
||||||
send_payload_router_->SetTargetSendBitrates(stream_bitrates);
|
|
||||||
if (video_suspended_ == video_is_suspended)
|
if (video_suspended_ == video_is_suspended)
|
||||||
return;
|
return;
|
||||||
video_suspended_ = video_is_suspended;
|
video_suspended_ = video_is_suspended;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Video suspend-state changed, inform codec observer.
|
// Video suspend-state changed, inform codec observer.
|
||||||
CriticalSectionScoped crit(callback_cs_.get());
|
CriticalSectionScoped crit(callback_cs_.get());
|
||||||
if (codec_observer_) {
|
if (codec_observer_) {
|
||||||
@ -942,7 +972,13 @@ int ViEEncoder::StopDebugRecording() {
|
|||||||
|
|
||||||
void ViEEncoder::SuspendBelowMinBitrate() {
|
void ViEEncoder::SuspendBelowMinBitrate() {
|
||||||
vcm_.SuspendBelowMinBitrate();
|
vcm_.SuspendBelowMinBitrate();
|
||||||
bitrate_controller_->EnforceMinBitrate(false);
|
bitrate_allocator_->EnforceMinBitrate(false);
|
||||||
|
int min_bitrate_sum_bps;
|
||||||
|
int max_bitrate_sum_bps;
|
||||||
|
bitrate_allocator_->GetMinMaxBitrateSumBps(&min_bitrate_sum_bps,
|
||||||
|
&max_bitrate_sum_bps);
|
||||||
|
bitrate_controller_->SetMinMaxBitrate(min_bitrate_sum_bps,
|
||||||
|
max_bitrate_sum_bps);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViEEncoder::RegisterPreEncodeCallback(
|
void ViEEncoder::RegisterPreEncodeCallback(
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "webrtc/base/scoped_ptr.h"
|
#include "webrtc/base/scoped_ptr.h"
|
||||||
#include "webrtc/base/thread_annotations.h"
|
#include "webrtc/base/thread_annotations.h"
|
||||||
#include "webrtc/common_types.h"
|
#include "webrtc/common_types.h"
|
||||||
|
#include "webrtc/modules/bitrate_controller/include/bitrate_allocator.h"
|
||||||
#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
|
#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
|
||||||
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
|
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
|
||||||
#include "webrtc/modules/video_coding/main/interface/video_coding_defines.h"
|
#include "webrtc/modules/video_coding/main/interface/video_coding_defines.h"
|
||||||
@ -58,6 +59,7 @@ class ViEEncoder
|
|||||||
uint32_t number_of_cores,
|
uint32_t number_of_cores,
|
||||||
const Config& config,
|
const Config& config,
|
||||||
ProcessThread& module_process_thread,
|
ProcessThread& module_process_thread,
|
||||||
|
BitrateAllocator* bitrate_allocator,
|
||||||
BitrateController* bitrate_controller,
|
BitrateController* bitrate_controller,
|
||||||
bool disable_default_encoder);
|
bool disable_default_encoder);
|
||||||
~ViEEncoder();
|
~ViEEncoder();
|
||||||
@ -194,6 +196,7 @@ class ViEEncoder
|
|||||||
int64_t capture_time_ms, bool retransmission);
|
int64_t capture_time_ms, bool retransmission);
|
||||||
size_t TimeToSendPadding(size_t bytes);
|
size_t TimeToSendPadding(size_t bytes);
|
||||||
private:
|
private:
|
||||||
|
int GetPaddingNeededBps(int bitrate_bps) const;
|
||||||
bool EncoderPaused() const EXCLUSIVE_LOCKS_REQUIRED(data_cs_);
|
bool EncoderPaused() const EXCLUSIVE_LOCKS_REQUIRED(data_cs_);
|
||||||
void TraceFrameDropStart() EXCLUSIVE_LOCKS_REQUIRED(data_cs_);
|
void TraceFrameDropStart() EXCLUSIVE_LOCKS_REQUIRED(data_cs_);
|
||||||
void TraceFrameDropEnd() EXCLUSIVE_LOCKS_REQUIRED(data_cs_);
|
void TraceFrameDropEnd() EXCLUSIVE_LOCKS_REQUIRED(data_cs_);
|
||||||
@ -215,7 +218,8 @@ class ViEEncoder
|
|||||||
rtc::scoped_ptr<PacedSender> paced_sender_;
|
rtc::scoped_ptr<PacedSender> paced_sender_;
|
||||||
rtc::scoped_ptr<ViEPacedSenderCallback> pacing_callback_;
|
rtc::scoped_ptr<ViEPacedSenderCallback> pacing_callback_;
|
||||||
|
|
||||||
BitrateController* bitrate_controller_;
|
BitrateAllocator* const bitrate_allocator_;
|
||||||
|
BitrateController* const bitrate_controller_;
|
||||||
|
|
||||||
int64_t time_of_last_incoming_frame_ms_ GUARDED_BY(data_cs_);
|
int64_t time_of_last_incoming_frame_ms_ GUARDED_BY(data_cs_);
|
||||||
bool send_padding_ GUARDED_BY(data_cs_);
|
bool send_padding_ GUARDED_BY(data_cs_);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user