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:
stefan@webrtc.org 2015-03-04 12:24:26 +00:00
parent 61c22aca5f
commit 792f1a14e2
20 changed files with 831 additions and 779 deletions

View File

@ -10,8 +10,10 @@ import("../../build/webrtc.gni")
source_set("bitrate_controller") {
sources = [
"bitrate_allocator.cc",
"bitrate_controller_impl.cc",
"bitrate_controller_impl.h",
"include/bitrate_allocator.h",
"include/bitrate_controller.h",
"remb_suppressor.cc",
"remb_suppressor.h",

View 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

View 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

View File

@ -15,9 +15,11 @@
'<(webrtc_root)/system_wrappers/system_wrappers.gyp:system_wrappers',
],
'sources': [
'bitrate_allocator.cc',
'bitrate_controller_impl.cc',
'bitrate_controller_impl.h',
'include/bitrate_controller.h',
'include/bitrate_allocator.h',
'remb_suppressor.cc',
'remb_suppressor.h',
'send_side_bandwidth_estimation.cc',

View File

@ -79,35 +79,26 @@ class BitrateControllerImpl::RtcpBandwidthObserverImpl
BitrateController* BitrateController::CreateBitrateController(
Clock* clock,
bool enforce_min_bitrate) {
return new BitrateControllerImpl(clock, enforce_min_bitrate);
BitrateObserver* observer) {
return new BitrateControllerImpl(clock, observer);
}
BitrateControllerImpl::BitrateControllerImpl(Clock* clock,
bool enforce_min_bitrate)
BitrateObserver* observer)
: clock_(clock),
observer_(observer),
last_bitrate_update_ms_(clock_->TimeInMilliseconds()),
critsect_(CriticalSectionWrapper::CreateCriticalSection()),
bandwidth_estimation_(),
bitrate_observers_(),
enforce_min_bitrate_(enforce_min_bitrate),
reserved_bitrate_bps_(0),
last_bitrate_bps_(0),
last_fraction_loss_(0),
last_rtt_ms_(0),
last_enforce_min_bitrate_(!enforce_min_bitrate_),
bitrate_observers_modified_(false),
last_reserved_bitrate_bps_(0),
remb_suppressor_(new RembSuppressor(clock)) {
}
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_;
}
@ -115,117 +106,33 @@ RtcpBandwidthObserver* BitrateControllerImpl::CreateRtcpBandwidthObserver() {
return new RtcpBandwidthObserverImpl(this);
}
BitrateControllerImpl::BitrateObserverConfList::iterator
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) {
void BitrateControllerImpl::SetStartBitrate(int start_bitrate_bps) {
CriticalSectionScoped cs(critsect_);
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(&current_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();
bandwidth_estimation_.SetSendBitrate(start_bitrate_bps);
}
void BitrateControllerImpl::UpdateMinMaxBitrate() {
uint32_t sum_min_bitrate = 0;
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) {
void BitrateControllerImpl::SetMinMaxBitrate(int min_bitrate_bps,
int max_bitrate_bps) {
CriticalSectionScoped cs(critsect_);
BitrateObserverConfList::iterator it = FindObserverConfigurationPair(
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();
bandwidth_estimation_.SetMinMaxBitrate(min_bitrate_bps, max_bitrate_bps);
}
void BitrateControllerImpl::SetReservedBitrate(uint32_t reserved_bitrate_bps) {
{
CriticalSectionScoped cs(critsect_);
reserved_bitrate_bps_ = reserved_bitrate_bps;
}
MaybeTriggerOnNetworkChanged();
}
void BitrateControllerImpl::OnReceivedEstimatedBitrate(uint32_t bitrate) {
{
CriticalSectionScoped cs(critsect_);
if (remb_suppressor_->SuppresNewRemb(bitrate)) {
return;
}
bandwidth_estimation_.UpdateReceiverEstimate(bitrate);
}
MaybeTriggerOnNetworkChanged();
}
@ -244,8 +151,8 @@ int32_t BitrateControllerImpl::Process() {
{
CriticalSectionScoped cs(critsect_);
bandwidth_estimation_.UpdateEstimate(clock_->TimeInMilliseconds());
MaybeTriggerOnNetworkChanged();
}
MaybeTriggerOnNetworkChanged();
last_bitrate_update_ms_ = clock_->TimeInMilliseconds();
return 0;
}
@ -255,9 +162,11 @@ void BitrateControllerImpl::OnReceivedRtcpReceiverReport(
int64_t rtt,
int number_of_packets,
int64_t now_ms) {
{
CriticalSectionScoped cs(critsect_);
bandwidth_estimation_.UpdateReceiverBlock(
fraction_loss, rtt, number_of_packets, now_ms);
bandwidth_estimation_.UpdateReceiverBlock(fraction_loss, rtt,
number_of_packets, now_ms);
}
MaybeTriggerOnNetworkChanged();
}
@ -265,110 +174,25 @@ void BitrateControllerImpl::MaybeTriggerOnNetworkChanged() {
uint32_t bitrate;
uint8_t fraction_loss;
int64_t rtt;
bool new_bitrate = false;
{
CriticalSectionScoped cs(critsect_);
bandwidth_estimation_.CurrentEstimate(&bitrate, &fraction_loss, &rtt);
bitrate -= std::min(bitrate, reserved_bitrate_bps_);
bitrate = std::max(bitrate, bandwidth_estimation_.GetMinBitrate());
if (bitrate_observers_modified_ ||
bitrate != last_bitrate_bps_ ||
fraction_loss != last_fraction_loss_ ||
if (bitrate != last_bitrate_bps_ || fraction_loss != last_fraction_loss_ ||
rtt != last_rtt_ms_ ||
last_enforce_min_bitrate_ != enforce_min_bitrate_ ||
last_reserved_bitrate_bps_ != reserved_bitrate_bps_) {
last_bitrate_bps_ = bitrate;
last_fraction_loss_ = fraction_loss;
last_rtt_ms_ = rtt;
last_enforce_min_bitrate_ = enforce_min_bitrate_;
last_reserved_bitrate_bps_ = reserved_bitrate_bps_;
bitrate_observers_modified_ = false;
OnNetworkChanged(bitrate, fraction_loss, rtt);
new_bitrate = true;
}
}
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 {
@ -379,6 +203,7 @@ bool BitrateControllerImpl::AvailableBandwidth(uint32_t* bandwidth) const {
bandwidth_estimation_.CurrentEstimate(&bitrate, &fraction_loss, &rtt);
if (bitrate) {
*bandwidth = bitrate - std::min(bitrate, reserved_bitrate_bps_);
*bandwidth = std::max(*bandwidth, bandwidth_estimation_.GetMinBitrate());
return true;
}
return false;

View File

@ -18,7 +18,6 @@
#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
#include <list>
#include <map>
#include <utility>
#include "webrtc/base/scoped_ptr.h"
@ -30,61 +29,30 @@ namespace webrtc {
class BitrateControllerImpl : public BitrateController {
public:
BitrateControllerImpl(Clock* clock, bool enforce_min_bitrate);
BitrateControllerImpl(Clock* clock, BitrateObserver* observer);
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,
uint32_t start_bitrate,
uint32_t min_bitrate,
uint32_t max_bitrate) OVERRIDE;
virtual void SetStartBitrate(int start_bitrate_bps) override;
virtual void SetMinMaxBitrate(int min_bitrate_bps,
int max_bitrate_bps) 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 void SetReservedBitrate(uint32_t reserved_bitrate_bps) OVERRIDE;
virtual int64_t TimeUntilNextProcess() OVERRIDE;
virtual int32_t Process() OVERRIDE;
virtual int64_t TimeUntilNextProcess() override;
virtual int32_t Process() override;
// 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:
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.
void OnReceivedEstimatedBitrate(uint32_t bitrate);
@ -93,37 +61,20 @@ class BitrateControllerImpl : public BitrateController {
int number_of_packets,
int64_t now_ms);
void MaybeTriggerOnNetworkChanged() EXCLUSIVE_LOCKS_REQUIRED(*critsect_);
void MaybeTriggerOnNetworkChanged();
void OnNetworkChanged(uint32_t bitrate,
uint8_t fraction_loss, // 0 - 255.
int64_t rtt)
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.
Clock* clock_;
BitrateObserver* observer_;
int64_t last_bitrate_update_ms_;
CriticalSectionWrapper* critsect_;
SendSideBandwidthEstimation bandwidth_estimation_ GUARDED_BY(*critsect_);
BitrateObserverConfList bitrate_observers_ GUARDED_BY(*critsect_);
bool enforce_min_bitrate_ 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_);
int64_t last_rtt_ms_ 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_);
rtc::scoped_ptr<RembSuppressor> remb_suppressor_ GUARDED_BY(*critsect_);

View File

@ -57,12 +57,14 @@ class TestBitrateObserver: public BitrateObserver {
class BitrateControllerTest : public ::testing::Test {
protected:
BitrateControllerTest() : clock_(0), enforce_min_bitrate_(true) {}
BitrateControllerTest() : clock_(0) {}
~BitrateControllerTest() {}
virtual void SetUp() {
controller_ = BitrateController::CreateBitrateController(
&clock_, enforce_min_bitrate_);
controller_ =
BitrateController::CreateBitrateController(&clock_, &bitrate_observer_);
controller_->SetStartBitrate(200000);
controller_->SetMinMaxBitrate(100000, 300000);
bandwidth_observer_ = controller_->CreateRtcpBandwidthObserver();
}
@ -72,47 +74,20 @@ class BitrateControllerTest : public ::testing::Test {
}
webrtc::SimulatedClock clock_;
bool enforce_min_bitrate_;
TestBitrateObserver bitrate_observer_;
BitrateController* controller_;
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) {
TestBitrateObserver bitrate_observer;
controller_->SetBitrateObserver(&bitrate_observer, 200000, 100000, 300000);
// First REMB applies 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(200000u, bitrate_observer.last_bitrate_);
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
EXPECT_EQ(0, bitrate_observer.last_rtt_);
EXPECT_EQ(200000u, bitrate_observer_.last_bitrate_);
EXPECT_EQ(0, bitrate_observer_.last_fraction_loss_);
EXPECT_EQ(0, bitrate_observer_.last_rtt_);
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
report_blocks.clear();
time_ms += 2000;
@ -123,64 +98,60 @@ TEST_F(BitrateControllerTest, OneBitrateObserverOneRtcpObserver) {
// Test bitrate increase 8% per second.
report_blocks.push_back(CreateReportBlock(1, 2, 0, 21));
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
EXPECT_EQ(217000u, bitrate_observer.last_bitrate_);
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
EXPECT_EQ(50, bitrate_observer.last_rtt_);
EXPECT_EQ(217000u, bitrate_observer_.last_bitrate_);
EXPECT_EQ(0, bitrate_observer_.last_fraction_loss_);
EXPECT_EQ(50, bitrate_observer_.last_rtt_);
time_ms += 1000;
report_blocks.clear();
report_blocks.push_back(CreateReportBlock(1, 2, 0, 41));
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
EXPECT_EQ(235360u, bitrate_observer.last_bitrate_);
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
EXPECT_EQ(50, bitrate_observer.last_rtt_);
EXPECT_EQ(235360u, bitrate_observer_.last_bitrate_);
EXPECT_EQ(0, bitrate_observer_.last_fraction_loss_);
EXPECT_EQ(50, bitrate_observer_.last_rtt_);
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(255189u, bitrate_observer.last_bitrate_);
EXPECT_EQ(255189u, bitrate_observer_.last_bitrate_);
time_ms += 1000;
report_blocks.clear();
report_blocks.push_back(CreateReportBlock(1, 2, 0, 81));
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;
report_blocks.clear();
report_blocks.push_back(CreateReportBlock(1, 2, 0, 801));
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;
// Reach max cap.
report_blocks.clear();
report_blocks.push_back(CreateReportBlock(1, 2, 0, 101));
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;
report_blocks.clear();
report_blocks.push_back(CreateReportBlock(1, 2, 0, 141));
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.
bandwidth_observer_->OnReceivedEstimatedBitrate(250000);
EXPECT_EQ(250000u, bitrate_observer.last_bitrate_);
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
EXPECT_EQ(50, bitrate_observer.last_rtt_);
EXPECT_EQ(250000u, bitrate_observer_.last_bitrate_);
EXPECT_EQ(0, bitrate_observer_.last_fraction_loss_);
EXPECT_EQ(50, bitrate_observer_.last_rtt_);
bandwidth_observer_->OnReceivedEstimatedBitrate(1000);
EXPECT_EQ(100000u, bitrate_observer.last_bitrate_); // Min cap.
controller_->RemoveBitrateObserver(&bitrate_observer);
EXPECT_EQ(100000u, bitrate_observer_.last_bitrate_); // Min cap.
}
TEST_F(BitrateControllerTest, OneBitrateObserverTwoRtcpObservers) {
TestBitrateObserver bitrate_observer;
controller_->SetBitrateObserver(&bitrate_observer, 200000, 100000, 300000);
// REMBs during the first 2 seconds apply immediately.
int64_t time_ms = 1;
webrtc::ReportBlockList report_blocks;
@ -196,9 +167,9 @@ TEST_F(BitrateControllerTest, OneBitrateObserverTwoRtcpObservers) {
report_blocks.push_back(CreateReportBlock(1, 2, 0, 21));
second_bandwidth_observer->OnReceivedRtcpReceiverReport(
report_blocks, 100, 1);
EXPECT_EQ(217000u, bitrate_observer.last_bitrate_);
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
EXPECT_EQ(100, bitrate_observer.last_rtt_);
EXPECT_EQ(217000u, bitrate_observer_.last_bitrate_);
EXPECT_EQ(0, bitrate_observer_.last_fraction_loss_);
EXPECT_EQ(100, bitrate_observer_.last_rtt_);
time_ms += 500;
// Test bitrate increase 8% per second.
@ -208,9 +179,9 @@ TEST_F(BitrateControllerTest, OneBitrateObserverTwoRtcpObservers) {
time_ms += 500;
second_bandwidth_observer->OnReceivedRtcpReceiverReport(
report_blocks, 100, time_ms);
EXPECT_EQ(235360u, bitrate_observer.last_bitrate_);
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
EXPECT_EQ(100, bitrate_observer.last_rtt_);
EXPECT_EQ(235360u, bitrate_observer_.last_bitrate_);
EXPECT_EQ(0, bitrate_observer_.last_fraction_loss_);
EXPECT_EQ(100, bitrate_observer_.last_rtt_);
time_ms += 500;
// Extra report should not change estimate.
@ -218,20 +189,20 @@ TEST_F(BitrateControllerTest, OneBitrateObserverTwoRtcpObservers) {
report_blocks.push_back(CreateReportBlock(1, 2, 0, 31));
second_bandwidth_observer->OnReceivedRtcpReceiverReport(
report_blocks, 100, time_ms);
EXPECT_EQ(235360u, bitrate_observer.last_bitrate_);
EXPECT_EQ(235360u, bitrate_observer_.last_bitrate_);
time_ms += 500;
report_blocks.clear();
report_blocks.push_back(CreateReportBlock(1, 2, 0, 41));
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.
report_blocks.clear();
report_blocks.push_back(CreateReportBlock(1, 2, 0, 41));
second_bandwidth_observer->OnReceivedRtcpReceiverReport(
report_blocks, 100, time_ms);
EXPECT_EQ(255189u, bitrate_observer.last_bitrate_);
EXPECT_EQ(255189u, bitrate_observer_.last_bitrate_);
time_ms += 1000;
// 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));
second_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;
report_blocks.clear();
report_blocks.push_back(CreateReportBlock(1, 2, 0, 81));
second_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;
// Reach max cap.
@ -254,37 +225,35 @@ TEST_F(BitrateControllerTest, OneBitrateObserverTwoRtcpObservers) {
report_blocks.push_back(CreateReportBlock(1, 2, 0, 121));
second_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;
report_blocks.clear();
report_blocks.push_back(CreateReportBlock(1, 2, 0, 141));
second_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.
// We don't care which bandwidth observer that delivers the REMB.
second_bandwidth_observer->OnReceivedEstimatedBitrate(250000);
EXPECT_EQ(250000u, bitrate_observer.last_bitrate_);
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
EXPECT_EQ(50, bitrate_observer.last_rtt_);
EXPECT_EQ(250000u, bitrate_observer_.last_bitrate_);
EXPECT_EQ(0, bitrate_observer_.last_fraction_loss_);
EXPECT_EQ(50, bitrate_observer_.last_rtt_);
// Min cap.
bandwidth_observer_->OnReceivedEstimatedBitrate(1000);
EXPECT_EQ(100000u, bitrate_observer.last_bitrate_);
controller_->RemoveBitrateObserver(&bitrate_observer);
EXPECT_EQ(100000u, bitrate_observer_.last_bitrate_);
delete second_bandwidth_observer;
}
TEST_F(BitrateControllerTest, OneBitrateObserverMultipleReportBlocks) {
TestBitrateObserver bitrate_observer;
uint32_t sequence_number[2] = {0, 0xFF00};
const uint32_t kStartBitrate = 200000;
const uint32_t kMinBitrate = 100000;
const uint32_t kMaxBitrate = 300000;
controller_->SetBitrateObserver(&bitrate_observer, kStartBitrate, kMinBitrate,
kMaxBitrate);
controller_->SetStartBitrate(kStartBitrate);
controller_->SetMinMaxBitrate(kMinBitrate, kMaxBitrate);
// REMBs during the first 2 seconds apply immediately.
int64_t time_ms = 1001;
@ -305,26 +274,26 @@ TEST_F(BitrateControllerTest, OneBitrateObserverMultipleReportBlocks) {
report_blocks.push_back(CreateReportBlock(1, 3, 0, sequence_number[1]));
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50,
time_ms);
EXPECT_GT(bitrate_observer.last_bitrate_, last_bitrate);
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
EXPECT_EQ(50, bitrate_observer.last_rtt_);
last_bitrate = bitrate_observer.last_bitrate_;
EXPECT_GT(bitrate_observer_.last_bitrate_, last_bitrate);
EXPECT_EQ(0, bitrate_observer_.last_fraction_loss_);
EXPECT_EQ(50, bitrate_observer_.last_rtt_);
last_bitrate = bitrate_observer_.last_bitrate_;
time_ms += 1000;
sequence_number[0] += 20;
sequence_number[1] += 1;
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.
report_blocks.push_back(CreateReportBlock(1, 2, 50, sequence_number[0]));
report_blocks.push_back(CreateReportBlock(1, 3, 0, sequence_number[1]));
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
EXPECT_LT(bitrate_observer.last_bitrate_, last_bitrate);
EXPECT_EQ(WeightedLoss(20, 50, 1, 0), bitrate_observer.last_fraction_loss_);
EXPECT_EQ(50, bitrate_observer.last_rtt_);
last_bitrate = bitrate_observer.last_bitrate_;
EXPECT_LT(bitrate_observer_.last_bitrate_, last_bitrate);
EXPECT_EQ(WeightedLoss(20, 50, 1, 0), bitrate_observer_.last_fraction_loss_);
EXPECT_EQ(50, bitrate_observer_.last_rtt_);
last_bitrate = bitrate_observer_.last_bitrate_;
sequence_number[0] += 20;
sequence_number[1] += 20;
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, 3, 75, sequence_number[1]));
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
EXPECT_LT(bitrate_observer.last_bitrate_, last_bitrate);
EXPECT_EQ(WeightedLoss(20, 0, 20, 75), bitrate_observer.last_fraction_loss_);
EXPECT_EQ(50, bitrate_observer.last_rtt_);
last_bitrate = bitrate_observer.last_bitrate_;
EXPECT_LT(bitrate_observer_.last_bitrate_, last_bitrate);
EXPECT_EQ(WeightedLoss(20, 0, 20, 75), bitrate_observer_.last_fraction_loss_);
EXPECT_EQ(50, bitrate_observer_.last_rtt_);
last_bitrate = bitrate_observer_.last_bitrate_;
sequence_number[0] += 20;
sequence_number[1] += 1;
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, 3, 255, sequence_number[1]));
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
EXPECT_EQ(bitrate_observer.last_bitrate_, last_bitrate);
EXPECT_EQ(WeightedLoss(20, 1, 1, 255), bitrate_observer.last_fraction_loss_);
EXPECT_EQ(50, bitrate_observer.last_rtt_);
last_bitrate = bitrate_observer.last_bitrate_;
EXPECT_EQ(bitrate_observer_.last_bitrate_, last_bitrate);
EXPECT_EQ(WeightedLoss(20, 1, 1, 255), bitrate_observer_.last_fraction_loss_);
EXPECT_EQ(50, bitrate_observer_.last_rtt_);
last_bitrate = bitrate_observer_.last_bitrate_;
sequence_number[0] += 20;
sequence_number[1] += 1;
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) {
TestBitrateObserver bitrate_observer;
controller_->SetBitrateObserver(&bitrate_observer, 200000, 100000, 300000);
// Receive successively lower REMBs, verify the reserved bitrate is deducted.
controller_->SetReservedBitrate(0);
bandwidth_observer_->OnReceivedEstimatedBitrate(400000);
EXPECT_EQ(200000u, bitrate_observer.last_bitrate_);
EXPECT_EQ(200000u, bitrate_observer_.last_bitrate_);
controller_->SetReservedBitrate(50000);
bandwidth_observer_->OnReceivedEstimatedBitrate(400000);
EXPECT_EQ(150000u, bitrate_observer.last_bitrate_);
EXPECT_EQ(150000u, bitrate_observer_.last_bitrate_);
controller_->SetReservedBitrate(0);
bandwidth_observer_->OnReceivedEstimatedBitrate(250000);
EXPECT_EQ(200000u, bitrate_observer.last_bitrate_);
EXPECT_EQ(200000u, bitrate_observer_.last_bitrate_);
controller_->SetReservedBitrate(50000);
bandwidth_observer_->OnReceivedEstimatedBitrate(250000);
EXPECT_EQ(150000u, bitrate_observer.last_bitrate_);
EXPECT_EQ(150000u, bitrate_observer_.last_bitrate_);
controller_->SetReservedBitrate(0);
bandwidth_observer_->OnReceivedEstimatedBitrate(200000);
EXPECT_EQ(200000u, bitrate_observer.last_bitrate_);
EXPECT_EQ(200000u, bitrate_observer_.last_bitrate_);
controller_->SetReservedBitrate(30000);
bandwidth_observer_->OnReceivedEstimatedBitrate(200000);
EXPECT_EQ(170000u, bitrate_observer.last_bitrate_);
EXPECT_EQ(170000u, bitrate_observer_.last_bitrate_);
controller_->SetReservedBitrate(0);
bandwidth_observer_->OnReceivedEstimatedBitrate(160000);
EXPECT_EQ(160000u, bitrate_observer.last_bitrate_);
EXPECT_EQ(160000u, bitrate_observer_.last_bitrate_);
controller_->SetReservedBitrate(30000);
bandwidth_observer_->OnReceivedEstimatedBitrate(160000);
EXPECT_EQ(130000u, bitrate_observer.last_bitrate_);
EXPECT_EQ(130000u, bitrate_observer_.last_bitrate_);
controller_->SetReservedBitrate(0);
bandwidth_observer_->OnReceivedEstimatedBitrate(120000);
EXPECT_EQ(120000u, bitrate_observer.last_bitrate_);
EXPECT_EQ(120000u, bitrate_observer_.last_bitrate_);
controller_->SetReservedBitrate(10000);
bandwidth_observer_->OnReceivedEstimatedBitrate(120000);
EXPECT_EQ(110000u, bitrate_observer.last_bitrate_);
EXPECT_EQ(110000u, bitrate_observer_.last_bitrate_);
controller_->SetReservedBitrate(0);
bandwidth_observer_->OnReceivedEstimatedBitrate(120000);
EXPECT_EQ(120000u, bitrate_observer.last_bitrate_);
EXPECT_EQ(120000u, bitrate_observer_.last_bitrate_);
controller_->SetReservedBitrate(50000);
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);
bandwidth_observer_->OnReceivedEstimatedBitrate(0);
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);
bandwidth_observer_->OnReceivedEstimatedBitrate(1);
EXPECT_EQ(100000u, bitrate_observer_.last_bitrate_);
}

View 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_

View File

@ -15,67 +15,50 @@
#ifndef 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/rtp_rtcp/interface/rtp_rtcp_defines.h"
namespace webrtc {
class CriticalSectionWrapper;
class BitrateObserver {
/*
* Observer class for the encoders, each encoder should implement this class
* to get the target bitrate. It also get the fraction loss and rtt to
* optimize its settings for this type of network. |target_bitrate| is the
* target media/payload bitrate excluding packet headers, measured in bits
* per second.
*/
// Observer class for bitrate changes announced due to change in bandwidth
// estimate or due to bitrate allocation changes. Fraction loss and rtt is
// also part of this callback to allow the obsevrer to optimize its settings
// for different types of network environments. The bitrate does not include
// packet headers and is measured in bits per second.
public:
virtual void OnNetworkChanged(uint32_t target_bitrate,
virtual void OnNetworkChanged(uint32_t bitrate_bps,
uint8_t fraction_loss, // 0 - 255.
int64_t rtt) = 0;
int64_t rtt_ms) = 0;
virtual ~BitrateObserver() {}
};
class BitrateController : public Module {
/*
* This class collects feedback from all streams sent to a peer (via
* RTCPBandwidthObservers). It does one aggregated send side bandwidth
* estimation and divide the available bitrate between all its registered
* BitrateObservers.
*/
// This class collects feedback from all streams sent to a peer (via
// RTCPBandwidthObservers). It does one aggregated send side bandwidth
// estimation and divide the available bitrate between all its registered
// BitrateObservers.
public:
// The argument |enforce_min_bitrate| 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.
static const int kDefaultStartBitrateKbps = 300;
static BitrateController* CreateBitrateController(Clock* clock,
bool enforce_min_bitrate);
BitrateObserver* observer);
virtual ~BitrateController() {}
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
// this bandwidth excludes packet headers.
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 SetBitrateSent(uint32_t bitrate_sent_bps) = 0;

View File

@ -96,8 +96,8 @@ void SendSideBandwidthEstimation::SetMinMaxBitrate(uint32_t min_bitrate,
max_bitrate_configured_ = max_bitrate;
}
void SendSideBandwidthEstimation::SetMinBitrate(uint32_t min_bitrate) {
min_bitrate_configured_ = min_bitrate;
uint32_t SendSideBandwidthEstimation::GetMinBitrate() const {
return min_bitrate_configured_;
}
void SendSideBandwidthEstimation::CurrentEstimate(uint32_t* bitrate,

View File

@ -40,7 +40,7 @@ class SendSideBandwidthEstimation {
void SetSendBitrate(uint32_t bitrate);
void SetMinMaxBitrate(uint32_t min_bitrate, uint32_t max_bitrate);
void SetMinBitrate(uint32_t min_bitrate);
uint32_t GetMinBitrate() const;
private:
enum UmaState { kNoUpdate, kFirstDone, kDone };

View File

@ -185,6 +185,7 @@
'audio_processing/transient/wpd_node_unittest.cc',
'audio_processing/transient/wpd_tree_unittest.cc',
'audio_processing/utility/delay_estimator_unittest.cc',
'bitrate_controller/bitrate_allocator_unittest.cc',
'bitrate_controller/bitrate_controller_unittest.cc',
'bitrate_controller/remb_suppressor_unittest.cc',
'bitrate_controller/send_side_bandwidth_estimation_unittest.cc',

View File

@ -24,13 +24,14 @@ namespace bwe {
RembBweSender::RembBweSender(int kbps, BitrateObserver* observer, Clock* clock)
: bitrate_controller_(
BitrateController::CreateBitrateController(clock, false)),
BitrateController::CreateBitrateController(clock, observer)),
feedback_observer_(bitrate_controller_->CreateRtcpBandwidthObserver()),
clock_(clock) {
assert(kbps >= kMinBitrateKbps);
assert(kbps <= kMaxBitrateKbps);
bitrate_controller_->SetBitrateObserver(
observer, 1000 * kbps, 1000 * kMinBitrateKbps, 1000 * kMaxBitrateKbps);
bitrate_controller_->SetStartBitrate(1000 * kbps);
bitrate_controller_->SetMinMaxBitrate(1000 * kMinBitrateKbps,
1000 * kMaxBitrateKbps);
}
RembBweSender::~RembBweSender() {

View File

@ -16,15 +16,16 @@ namespace bwe {
FullBweSender::FullBweSender(int kbps, BitrateObserver* observer, Clock* clock)
: bitrate_controller_(
BitrateController::CreateBitrateController(clock, false)),
BitrateController::CreateBitrateController(clock, observer)),
rbe_(AbsoluteSendTimeRemoteBitrateEstimatorFactory()
.Create(this, clock, kAimdControl, 1000 * kMinBitrateKbps)),
feedback_observer_(bitrate_controller_->CreateRtcpBandwidthObserver()),
clock_(clock) {
assert(kbps >= kMinBitrateKbps);
assert(kbps <= kMaxBitrateKbps);
bitrate_controller_->SetBitrateObserver(
observer, 1000 * kbps, 1000 * kMinBitrateKbps, 1000 * kMaxBitrateKbps);
bitrate_controller_->SetStartBitrate(1000 * kbps);
bitrate_controller_->SetMinMaxBitrate(1000 * kMinBitrateKbps,
1000 * kMaxBitrateKbps);
}
FullBweSender::~FullBweSender() {

View File

@ -28,7 +28,7 @@ namespace webrtc {
class MockVieEncoder : public ViEEncoder {
public:
explicit MockVieEncoder(ProcessThread* process_thread)
: ViEEncoder(1, 1, config_, *process_thread, NULL, false) {}
: ViEEncoder(1, 1, config_, *process_thread, NULL, NULL, false) {}
~MockVieEncoder() {}
MOCK_METHOD1(OnReceivedIntraFrameRequest,

View File

@ -13,7 +13,6 @@
#include "webrtc/base/thread_annotations.h"
#include "webrtc/common.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/rtp_rtcp/interface/rtp_rtcp.h"
#include "webrtc/modules/utility/interface/process_thread.h"
@ -137,12 +136,12 @@ class WrappingBitrateEstimator : public RemoteBitrateEstimator {
};
} // namespace
ChannelGroup::ChannelGroup(ProcessThread* process_thread,
const Config* config)
ChannelGroup::ChannelGroup(ProcessThread* process_thread, const Config* config)
: remb_(new VieRemb()),
bitrate_allocator_(new BitrateAllocator()),
bitrate_controller_(
BitrateController::CreateBitrateController(Clock::GetRealTimeClock(),
true)),
this)),
call_stats_(new CallStats()),
encoder_state_feedback_(new EncoderStateFeedback()),
config_(config),
@ -192,6 +191,10 @@ bool ChannelGroup::Empty() {
return channels_.empty();
}
BitrateAllocator* ChannelGroup::GetBitrateAllocator() {
return bitrate_allocator_.get();
}
BitrateController* ChannelGroup::GetBitrateController() {
return bitrate_controller_.get();
}
@ -227,4 +230,10 @@ void ChannelGroup::SetChannelRembStatus(int channel_id,
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

View File

@ -14,10 +14,11 @@
#include <set>
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
namespace webrtc {
class BitrateController;
class BitrateAllocator;
class CallStats;
class Config;
class EncoderStateFeedback;
@ -29,7 +30,7 @@ class VieRemb;
// Channel group contains data common for several channels. All channels in the
// group are assumed to send/receive data to the same end-point.
class ChannelGroup {
class ChannelGroup : public BitrateObserver {
public:
ChannelGroup(ProcessThread* process_thread, const Config* config);
~ChannelGroup();
@ -44,15 +45,22 @@ class ChannelGroup {
bool receiver,
ViEChannel* channel);
BitrateAllocator* GetBitrateAllocator();
BitrateController* GetBitrateController();
CallStats* GetCallStats();
RemoteBitrateEstimator* GetRemoteBitrateEstimator();
EncoderStateFeedback* GetEncoderStateFeedback();
// Implements BitrateObserver.
void OnNetworkChanged(uint32_t target_bitrate_bps,
uint8_t fraction_loss,
int64_t rtt) override;
private:
typedef std::set<int> ChannelSet;
rtc::scoped_ptr<VieRemb> remb_;
rtc::scoped_ptr<BitrateAllocator> bitrate_allocator_;
rtc::scoped_ptr<BitrateController> bitrate_controller_;
rtc::scoped_ptr<CallStats> call_stats_;
rtc::scoped_ptr<RemoteBitrateEstimator> remote_bitrate_estimator_;

View File

@ -89,13 +89,11 @@ int ViEChannelManager::CreateChannel(int* channel_id,
// Create a new channel group and add this channel.
ChannelGroup* group = new ChannelGroup(module_process_thread_,
channel_group_config);
BitrateAllocator* bitrate_allocator = group->GetBitrateAllocator();
BitrateController* bitrate_controller = group->GetBitrateController();
ViEEncoder* vie_encoder = new ViEEncoder(new_channel_id,
number_of_cores_,
engine_config_,
*module_process_thread_,
bitrate_controller,
false);
ViEEncoder* vie_encoder = new ViEEncoder(
new_channel_id, number_of_cores_, engine_config_, *module_process_thread_,
bitrate_allocator, bitrate_controller, false);
RtcpBandwidthObserver* bandwidth_observer =
bitrate_controller->CreateRtcpBandwidthObserver();
@ -153,6 +151,7 @@ int ViEChannelManager::CreateChannel(int* channel_id,
if (new_channel_id == -1) {
return -1;
}
BitrateAllocator* bitrate_allocator = channel_group->GetBitrateAllocator();
BitrateController* bitrate_controller = channel_group->GetBitrateController();
RtcpBandwidthObserver* bandwidth_observer =
bitrate_controller->CreateRtcpBandwidthObserver();
@ -166,11 +165,10 @@ int ViEChannelManager::CreateChannel(int* channel_id,
ViEEncoder* vie_encoder = NULL;
if (sender) {
// We need to create a new ViEEncoder.
vie_encoder = new ViEEncoder(new_channel_id, number_of_cores_,
engine_config_,
*module_process_thread_,
bitrate_controller,
disable_default_encoder);
vie_encoder =
new ViEEncoder(new_channel_id, number_of_cores_, engine_config_,
*module_process_thread_, bitrate_allocator,
bitrate_controller, disable_default_encoder);
if (!(vie_encoder->Init() &&
CreateChannelObject(
new_channel_id,

View File

@ -131,6 +131,7 @@ ViEEncoder::ViEEncoder(int32_t channel_id,
uint32_t number_of_cores,
const Config& config,
ProcessThread& module_process_thread,
BitrateAllocator* bitrate_allocator,
BitrateController* bitrate_controller,
bool disable_default_encoder)
: channel_id_(channel_id),
@ -142,6 +143,7 @@ ViEEncoder::ViEEncoder(int32_t channel_id,
vcm_protection_callback_(NULL),
callback_cs_(CriticalSectionWrapper::CreateCriticalSection()),
data_cs_(CriticalSectionWrapper::CreateCriticalSection()),
bitrate_allocator_(bitrate_allocator),
bitrate_controller_(bitrate_controller),
time_of_last_incoming_frame_ms_(0),
send_padding_(false),
@ -245,9 +247,8 @@ void ViEEncoder::StopThreadsAndRemoveSharedMembers() {
ViEEncoder::~ViEEncoder() {
UpdateHistograms();
if (bitrate_controller_) {
bitrate_controller_->RemoveBitrateObserver(bitrate_observer_.get());
}
if (bitrate_allocator_)
bitrate_allocator_->RemoveBitrateObserver(bitrate_observer_.get());
VideoCodingModule::Destroy(&vcm_);
VideoProcessingModule::Destroy(&vpm_);
delete qm_callback_;
@ -388,22 +389,33 @@ int32_t ViEEncoder::SetEncoder(const webrtc::VideoCodec& video_codec) {
return -1;
}
bitrate_controller_->SetBitrateObserver(bitrate_observer_.get(),
video_codec.startBitrate * 1000,
// Add the a bitrate observer to the allocator and update the start, max and
// 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,
kTransmissionMaxBitrateMultiplier *
video_codec.maxBitrate * 1000);
kTransmissionMaxBitrateMultiplier * video_codec.maxBitrate * 1000);
if (new_bwe_candidate_bps > 0) {
uint32_t current_bwe_bps = 0;
bitrate_controller_->AvailableBandwidth(&current_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);
CriticalSectionScoped crit(data_cs_.get());
int pad_up_to_bitrate_kbps = video_codec.startBitrate;
if (pad_up_to_bitrate_kbps < min_transmit_bitrate_kbps_)
pad_up_to_bitrate_kbps = min_transmit_bitrate_kbps_;
int pad_up_to_bitrate_bps =
GetPaddingNeededBps(1000 * video_codec.startBitrate);
paced_sender_->UpdateBitrate(
video_codec.startBitrate,
PacedSender::kDefaultPaceMultiplier * video_codec.startBitrate,
pad_up_to_bitrate_kbps);
pad_up_to_bitrate_bps / 1000);
return 0;
}
@ -448,16 +460,67 @@ bool ViEEncoder::TimeToSendPacket(uint32_t ssrc,
}
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());
send_padding =
bool send_padding =
send_padding_ || video_suspended_ || min_transmit_bitrate_kbps_ > 0;
}
if (send_padding) {
return send_payload_router_->TimeToSendPadding(bytes);
}
if (!send_padding)
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 {
@ -853,7 +916,7 @@ void ViEEncoder::OnNetworkChanged(uint32_t bitrate_bps,
DCHECK(send_payload_router_ != NULL);
vcm_.SetChannelParameters(bitrate_bps, fraction_lost, round_trip_time_ms);
bool video_is_suspended = vcm_.VideoSuspended();
int bitrate_kbps = bitrate_bps / 1000;
VideoCodec send_codec;
if (vcm_.SendCodec(&send_codec) != 0) {
return;
@ -861,54 +924,21 @@ void ViEEncoder::OnNetworkChanged(uint32_t bitrate_bps,
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);
// 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;
}
}
bitrate_bps, stream_configs, send_codec.numberOfSimulcastStreams);
send_payload_router_->SetTargetSendBitrates(stream_bitrates);
// 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_kbps = 0;
int pad_up_to_bitrate_bps = GetPaddingNeededBps(bitrate_bps);
paced_sender_->UpdateBitrate(
bitrate_bps / 1000,
PacedSender::kDefaultPaceMultiplier * bitrate_bps / 1000,
pad_up_to_bitrate_bps / 1000);
{
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)
return;
video_suspended_ = video_is_suspended;
}
// Video suspend-state changed, inform codec observer.
CriticalSectionScoped crit(callback_cs_.get());
if (codec_observer_) {
@ -942,7 +972,13 @@ int ViEEncoder::StopDebugRecording() {
void ViEEncoder::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(

View File

@ -18,6 +18,7 @@
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/base/thread_annotations.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/rtp_rtcp/interface/rtp_rtcp_defines.h"
#include "webrtc/modules/video_coding/main/interface/video_coding_defines.h"
@ -58,6 +59,7 @@ class ViEEncoder
uint32_t number_of_cores,
const Config& config,
ProcessThread& module_process_thread,
BitrateAllocator* bitrate_allocator,
BitrateController* bitrate_controller,
bool disable_default_encoder);
~ViEEncoder();
@ -194,6 +196,7 @@ class ViEEncoder
int64_t capture_time_ms, bool retransmission);
size_t TimeToSendPadding(size_t bytes);
private:
int GetPaddingNeededBps(int bitrate_bps) const;
bool EncoderPaused() const EXCLUSIVE_LOCKS_REQUIRED(data_cs_);
void TraceFrameDropStart() 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<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_);
bool send_padding_ GUARDED_BY(data_cs_);