Break out of send side bandwidth estimation and controll.
Review URL: https://webrtc-codereview.appspot.com/490010 git-svn-id: http://webrtc.googlecode.com/svn/trunk@2064 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
b2bd1e05f8
commit
1cd1162c7a
5
src/modules/bitrate_controller/OWNERS
Normal file
5
src/modules/bitrate_controller/OWNERS
Normal file
@ -0,0 +1,5 @@
|
||||
pwestin@webrtc.org
|
||||
stefan@webrtc.org
|
||||
henrik.lundin@webrtc.org
|
||||
mflodman@webrtc.org
|
||||
asapersson@webrtc.org
|
41
src/modules/bitrate_controller/bitrate_controller.gypi
Normal file
41
src/modules/bitrate_controller/bitrate_controller.gypi
Normal file
@ -0,0 +1,41 @@
|
||||
# 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.
|
||||
|
||||
{
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'bitrate_controller',
|
||||
'type': '<(library)',
|
||||
'dependencies': [
|
||||
'<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers',
|
||||
],
|
||||
'include_dirs': [
|
||||
'../interface',
|
||||
],
|
||||
'direct_dependent_settings': {
|
||||
'include_dirs': [
|
||||
'../interface',
|
||||
'<(webrtc_root)/modules/rtp_rtcp/interface',
|
||||
],
|
||||
},
|
||||
'sources': [
|
||||
'send_side_bandwidth_estimation.h',
|
||||
'send_side_bandwidth_estimation.cc',
|
||||
'bitrate_controller.h',
|
||||
'bitrate_controller_impl.h',
|
||||
'bitrate_controller_impl.cc',
|
||||
], # source
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
# Local Variables:
|
||||
# tab-width:2
|
||||
# indent-tabs-mode:nil
|
||||
# End:
|
||||
# vim: set expandtab tabstop=2 shiftwidth=2:
|
211
src/modules/bitrate_controller/bitrate_controller_impl.cc
Normal file
211
src/modules/bitrate_controller/bitrate_controller_impl.cc
Normal file
@ -0,0 +1,211 @@
|
||||
/*
|
||||
* 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 "modules/bitrate_controller/bitrate_controller_impl.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class RtcpBandwidthObserverImpl : public RtcpBandwidthObserver {
|
||||
public:
|
||||
explicit RtcpBandwidthObserverImpl(BitrateControllerImpl* owner)
|
||||
: owner_(owner) {
|
||||
}
|
||||
virtual ~RtcpBandwidthObserverImpl() {
|
||||
}
|
||||
// Received RTCP REMB or TMMBR.
|
||||
virtual void OnReceivedEstimatedBitrate(const uint32_t bitrate) {
|
||||
owner_->OnReceivedEstimatedBitrate(bitrate);
|
||||
}
|
||||
// Received RTCP receiver block.
|
||||
virtual void OnReceivedRtcpReceiverReport(
|
||||
const uint32_t ssrc,
|
||||
const uint8_t fraction_loss,
|
||||
const uint32_t rtt,
|
||||
const uint32_t last_received_extended_high_seq_num,
|
||||
const uint32_t now_ms) {
|
||||
uint32_t number_of_packets = 0;
|
||||
std::map<uint32_t, uint32_t>::iterator it =
|
||||
ssrc_to_last_received_extended_high_seq_num_.find(ssrc);
|
||||
|
||||
if (it != ssrc_to_last_received_extended_high_seq_num_.end()) {
|
||||
number_of_packets = last_received_extended_high_seq_num - it->second;
|
||||
}
|
||||
// Update last received for this SSRC.
|
||||
ssrc_to_last_received_extended_high_seq_num_[ssrc] =
|
||||
last_received_extended_high_seq_num;
|
||||
|
||||
owner_->OnReceivedRtcpReceiverReport(fraction_loss, rtt, number_of_packets,
|
||||
now_ms);
|
||||
}
|
||||
private:
|
||||
std::map<uint32_t, uint32_t> ssrc_to_last_received_extended_high_seq_num_;
|
||||
BitrateControllerImpl* owner_;
|
||||
};
|
||||
|
||||
BitrateController* BitrateController::CreateBitrateController() {
|
||||
return new BitrateControllerImpl();
|
||||
}
|
||||
|
||||
BitrateControllerImpl::BitrateControllerImpl()
|
||||
: critsect_(CriticalSectionWrapper::CreateCriticalSection()) {
|
||||
}
|
||||
|
||||
BitrateControllerImpl::~BitrateControllerImpl() {
|
||||
delete critsect_;
|
||||
}
|
||||
|
||||
RtcpBandwidthObserver* BitrateControllerImpl::CreateRtcpBandwidthObserver() {
|
||||
return new RtcpBandwidthObserverImpl(this);
|
||||
}
|
||||
|
||||
void BitrateControllerImpl::SetBitrateObserver(
|
||||
BitrateObserver* observer,
|
||||
const uint32_t start_bitrate,
|
||||
const uint32_t min_bitrate,
|
||||
const uint32_t max_bitrate) {
|
||||
CriticalSectionScoped cs(critsect_);
|
||||
|
||||
std::map<BitrateObserver*, BitrateConfiguration*>::iterator it =
|
||||
bitrate_observers_.find(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;
|
||||
} else {
|
||||
// Add new settings.
|
||||
bitrate_observers_[observer] = new BitrateConfiguration(start_bitrate,
|
||||
min_bitrate,
|
||||
max_bitrate);
|
||||
}
|
||||
uint32_t sum_start_bitrate = 0;
|
||||
uint32_t sum_min_bitrate = 0;
|
||||
uint32_t sum_max_bitrate = 0;
|
||||
|
||||
// Summarize all configurations.
|
||||
for (it = bitrate_observers_.begin(); it != bitrate_observers_.end(); ++it) {
|
||||
sum_start_bitrate += it->second->start_bitrate_;
|
||||
sum_min_bitrate += it->second->min_bitrate_;
|
||||
sum_max_bitrate += it->second->max_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(sum_start_bitrate);
|
||||
}
|
||||
bandwidth_estimation_.SetMinMaxBitrate(sum_min_bitrate,
|
||||
sum_max_bitrate);
|
||||
}
|
||||
|
||||
void BitrateControllerImpl::RemoveBitrateObserver(BitrateObserver* observer) {
|
||||
CriticalSectionScoped cs(critsect_);
|
||||
std::map<BitrateObserver*, BitrateConfiguration*>::iterator it =
|
||||
bitrate_observers_.find(observer);
|
||||
if (it != bitrate_observers_.end()) {
|
||||
delete it->second;
|
||||
bitrate_observers_.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void BitrateControllerImpl::OnReceivedEstimatedBitrate(const uint32_t bitrate) {
|
||||
uint32_t new_bitrate = 0;
|
||||
uint8_t fraction_lost = 0;
|
||||
uint16_t rtt = 0;
|
||||
CriticalSectionScoped cs(critsect_);
|
||||
if (bandwidth_estimation_.UpdateBandwidthEstimate(bitrate,
|
||||
&new_bitrate,
|
||||
&fraction_lost,
|
||||
&rtt)) {
|
||||
OnNetworkChanged(new_bitrate, fraction_lost, rtt);
|
||||
}
|
||||
}
|
||||
|
||||
void BitrateControllerImpl::OnReceivedRtcpReceiverReport(
|
||||
const uint8_t fraction_loss,
|
||||
const uint32_t rtt,
|
||||
const int number_of_packets,
|
||||
const uint32_t now_ms) {
|
||||
uint32_t new_bitrate = 0;
|
||||
uint8_t loss = fraction_loss;
|
||||
CriticalSectionScoped cs(critsect_);
|
||||
if (bandwidth_estimation_.UpdatePacketLoss(number_of_packets, rtt, now_ms,
|
||||
&loss, &new_bitrate)) {
|
||||
OnNetworkChanged(new_bitrate, loss, rtt);
|
||||
}
|
||||
}
|
||||
|
||||
// We have the lock here.
|
||||
void BitrateControllerImpl::OnNetworkChanged(const uint32_t bitrate,
|
||||
const uint8_t fraction_loss,
|
||||
const uint32_t rtt) {
|
||||
// Sanity check.
|
||||
uint32_t number_of_observers = bitrate_observers_.size();
|
||||
if (number_of_observers == 0) {
|
||||
return;
|
||||
}
|
||||
uint32_t sum_min_bitrates = 0;
|
||||
std::map<BitrateObserver*, BitrateConfiguration*>::iterator it;
|
||||
for (it = bitrate_observers_.begin(); it != bitrate_observers_.end(); ++it) {
|
||||
sum_min_bitrates += it->second->min_bitrate_;
|
||||
}
|
||||
if (bitrate <= sum_min_bitrates) {
|
||||
// Min bitrate to all observers.
|
||||
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);
|
||||
return;
|
||||
}
|
||||
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;
|
||||
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();
|
||||
}
|
||||
}
|
||||
} // namespace webrtc
|
||||
|
88
src/modules/bitrate_controller/bitrate_controller_impl.h
Normal file
88
src/modules/bitrate_controller/bitrate_controller_impl.h
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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 encoder via VideoEncoderCallback.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_MODULES_BITRATE_CONTROLLER_BITRATE_CONTROLLER_IMPL_H_
|
||||
#define WEBRTC_MODULES_BITRATE_CONTROLLER_BITRATE_CONTROLLER_IMPL_H_
|
||||
|
||||
#include "modules/bitrate_controller/include/bitrate_controller.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "system_wrappers/interface/critical_section_wrapper.h"
|
||||
#include "modules/bitrate_controller/send_side_bandwidth_estimation.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class RtcpBandwidthObserverImpl;
|
||||
|
||||
class BitrateControllerImpl : public BitrateController {
|
||||
public:
|
||||
friend class RtcpBandwidthObserverImpl;
|
||||
|
||||
explicit BitrateControllerImpl();
|
||||
virtual ~BitrateControllerImpl();
|
||||
|
||||
virtual RtcpBandwidthObserver* CreateRtcpBandwidthObserver();
|
||||
|
||||
virtual void SetBitrateObserver(BitrateObserver* observer,
|
||||
const uint32_t start_bitrate,
|
||||
const uint32_t min_bitrate,
|
||||
const uint32_t max_bitrate);
|
||||
|
||||
virtual void RemoveBitrateObserver(BitrateObserver* observer);
|
||||
|
||||
protected:
|
||||
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_;
|
||||
};
|
||||
|
||||
// Called by BitrateObserver's direct from the RTCP module.
|
||||
void OnReceivedEstimatedBitrate(const uint32_t bitrate);
|
||||
|
||||
void OnReceivedRtcpReceiverReport(const uint8_t fraction_loss,
|
||||
const uint32_t rtt,
|
||||
const int number_of_packets,
|
||||
const uint32_t now_ms);
|
||||
|
||||
private:
|
||||
typedef std::multimap<uint32_t, ObserverConfiguration*> ObserverSortingMap;
|
||||
|
||||
void OnNetworkChanged(const uint32_t bitrate,
|
||||
const uint8_t fraction_loss, // 0 - 255.
|
||||
const uint32_t rtt);
|
||||
|
||||
CriticalSectionWrapper* critsect_;
|
||||
SendSideBandwidthEstimation bandwidth_estimation_;
|
||||
std::map<BitrateObserver*, BitrateConfiguration*> bitrate_observers_;
|
||||
};
|
||||
} // namespace webrtc
|
||||
#endif // WEBRTC_MODULES_BITRATE_CONTROLLER_BITRATE_CONTROLLER_IMPL_H_
|
67
src/modules/bitrate_controller/include/bitrate_controller.h
Normal file
67
src/modules/bitrate_controller/include/bitrate_controller.h
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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_CONTROLLER_H_
|
||||
#define WEBRTC_MODULES_BITRATE_CONTROLLER_INCLUDE_BITRATE_CONTROLLER_H_
|
||||
|
||||
#include "modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
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.
|
||||
*/
|
||||
public:
|
||||
virtual void OnNetworkChanged(const uint32_t targer_bitrate,
|
||||
const uint8_t fraction_loss, // 0 - 255.
|
||||
const uint32_t rtt) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~BitrateObserver() {}
|
||||
};
|
||||
|
||||
// TODO(pwestin) move code from vie_remb in here
|
||||
|
||||
class BitrateController {
|
||||
/*
|
||||
* 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:
|
||||
static BitrateController* CreateBitrateController();
|
||||
virtual ~BitrateController() {}
|
||||
|
||||
virtual RtcpBandwidthObserver* CreateRtcpBandwidthObserver() = 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,
|
||||
const uint32_t start_bitrate,
|
||||
const uint32_t min_bitrate,
|
||||
const uint32_t max_bitrate) = 0;
|
||||
|
||||
virtual void RemoveBitrateObserver(BitrateObserver* observer) = 0;
|
||||
};
|
||||
} // namespace webrtc
|
||||
#endif // WEBRTC_MODULES_BITRATE_CONTROLLER_INCLUDE_BITRATE_CONTROLLER_H_
|
223
src/modules/bitrate_controller/send_side_bandwidth_estimation.cc
Normal file
223
src/modules/bitrate_controller/send_side_bandwidth_estimation.cc
Normal file
@ -0,0 +1,223 @@
|
||||
/*
|
||||
* 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 "modules/bitrate_controller/send_side_bandwidth_estimation.h"
|
||||
|
||||
#include <math.h> // sqrt()
|
||||
|
||||
#include "system_wrappers/interface/trace.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
SendSideBandwidthEstimation::SendSideBandwidthEstimation()
|
||||
: critsect_(CriticalSectionWrapper::CreateCriticalSection()),
|
||||
accumulate_lost_packets_Q8_(0),
|
||||
accumulate_expected_packets_(0),
|
||||
bitrate_(0),
|
||||
min_bitrate_configured_(0),
|
||||
max_bitrate_configured_(0),
|
||||
last_fraction_loss_(0),
|
||||
last_round_trip_time_(0),
|
||||
bwe_incoming_(0),
|
||||
time_last_increase_(0),
|
||||
time_last_decrease_(0) {
|
||||
}
|
||||
|
||||
SendSideBandwidthEstimation::~SendSideBandwidthEstimation() {
|
||||
delete critsect_;
|
||||
}
|
||||
|
||||
void SendSideBandwidthEstimation::SetSendBitrate(const uint32_t bitrate) {
|
||||
CriticalSectionScoped cs(critsect_);
|
||||
bitrate_ = bitrate;
|
||||
}
|
||||
|
||||
void SendSideBandwidthEstimation::SetMinMaxBitrate(const uint32_t min_bitrate,
|
||||
const uint32_t max_bitrate) {
|
||||
CriticalSectionScoped cs(critsect_);
|
||||
min_bitrate_configured_ = min_bitrate;
|
||||
if (max_bitrate == 0) {
|
||||
// no max configured use 1Gbit/s
|
||||
max_bitrate_configured_ = 1000000000;
|
||||
} else {
|
||||
max_bitrate_configured_ = max_bitrate;
|
||||
}
|
||||
}
|
||||
|
||||
bool SendSideBandwidthEstimation::UpdateBandwidthEstimate(
|
||||
const uint32_t bandwidth,
|
||||
uint32_t* new_bitrate,
|
||||
uint8_t* fraction_lost,
|
||||
uint16_t* rtt) {
|
||||
*new_bitrate = 0;
|
||||
CriticalSectionScoped cs(critsect_);
|
||||
|
||||
bwe_incoming_ = bandwidth;
|
||||
|
||||
if (bitrate_ == 0) {
|
||||
// SendSideBandwidthEstimation off
|
||||
return false;
|
||||
}
|
||||
if (bwe_incoming_ > 0 && bitrate_ > bwe_incoming_) {
|
||||
bitrate_ = bwe_incoming_;
|
||||
*new_bitrate = bitrate_;
|
||||
*fraction_lost = last_fraction_loss_;
|
||||
*rtt = last_round_trip_time_;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SendSideBandwidthEstimation::UpdatePacketLoss(
|
||||
const int number_of_packets,
|
||||
const uint32_t rtt,
|
||||
const uint32_t now_ms,
|
||||
uint8_t* loss,
|
||||
uint32_t* new_bitrate) {
|
||||
CriticalSectionScoped cs(critsect_);
|
||||
|
||||
if (bitrate_ == 0) {
|
||||
// SendSideBandwidthEstimation off
|
||||
return false;
|
||||
}
|
||||
// Update RTT.
|
||||
last_round_trip_time_ = rtt;
|
||||
|
||||
// Check sequence number diff and weight loss report
|
||||
if (number_of_packets > 0) {
|
||||
// Calculate number of lost packets.
|
||||
const int num_lost_packets_Q8 = *loss * number_of_packets;
|
||||
// Accumulate reports.
|
||||
accumulate_lost_packets_Q8_ += num_lost_packets_Q8;
|
||||
accumulate_expected_packets_ += number_of_packets;
|
||||
|
||||
// Report loss if the total report is based on sufficiently many packets.
|
||||
if (accumulate_expected_packets_ >= kLimitNumPackets) {
|
||||
*loss = accumulate_lost_packets_Q8_ / accumulate_expected_packets_;
|
||||
|
||||
// Reset accumulators
|
||||
accumulate_lost_packets_Q8_ = 0;
|
||||
accumulate_expected_packets_ = 0;
|
||||
} else {
|
||||
// Report zero loss until we have enough data to estimate
|
||||
// the loss rate.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Keep for next time.
|
||||
last_fraction_loss_ = *loss;
|
||||
|
||||
uint32_t bitrate = ShapeSimple(*loss, rtt, now_ms);
|
||||
if (bitrate == 0) {
|
||||
// No change.
|
||||
return false;
|
||||
}
|
||||
bitrate_ = bitrate;
|
||||
*new_bitrate = bitrate;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SendSideBandwidthEstimation::AvailableBandwidth(
|
||||
uint32_t* bandwidth) const {
|
||||
CriticalSectionScoped cs(critsect_);
|
||||
if (bitrate_ == 0) {
|
||||
return false;
|
||||
}
|
||||
*bandwidth = bitrate_;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the rate that TCP-Friendly Rate Control (TFRC) would apply.
|
||||
* The formula in RFC 3448, Section 3.1, is used.
|
||||
*/
|
||||
uint32_t SendSideBandwidthEstimation::CalcTFRCbps(uint16_t rtt, uint8_t loss) {
|
||||
if (rtt == 0 || loss == 0) {
|
||||
// input variables out of range
|
||||
return 0;
|
||||
}
|
||||
double R = static_cast<double>(rtt) / 1000; // RTT in seconds
|
||||
int b = 1; // number of packets acknowledged by a single TCP acknowledgement;
|
||||
// recommended = 1
|
||||
double t_RTO = 4.0 * R; // TCP retransmission timeout value in seconds
|
||||
// recommended = 4*R
|
||||
double p = static_cast<double>(loss) / 255; // packet loss rate in [0, 1)
|
||||
double s = static_cast<double>(kAvgPacketSizeBytes);
|
||||
|
||||
// calculate send rate in bytes/second
|
||||
double X = s / (R * sqrt(2 * b * p / 3) +
|
||||
(t_RTO * (3 * sqrt(3 * b * p / 8) * p * (1 + 32 * p * p))));
|
||||
|
||||
return (static_cast<uint32_t>(X * 8)); // bits/second
|
||||
}
|
||||
|
||||
uint32_t SendSideBandwidthEstimation::ShapeSimple(uint8_t loss, uint32_t rtt,
|
||||
uint32_t now_ms) {
|
||||
uint32_t new_bitrate = 0;
|
||||
bool reducing = false;
|
||||
|
||||
// Limit the rate increases to once a kBWEIncreaseIntervalMs.
|
||||
if (loss <= 5) {
|
||||
if ((now_ms - time_last_increase_) < kBWEIncreaseIntervalMs) {
|
||||
return bitrate_;
|
||||
}
|
||||
time_last_increase_ = now_ms;
|
||||
}
|
||||
// Limit the rate decreases to once a kBWEDecreaseIntervalMs + rtt.
|
||||
if (loss > 26) {
|
||||
if ((now_ms - time_last_decrease_) < kBWEDecreaseIntervalMs + rtt) {
|
||||
return bitrate_;
|
||||
}
|
||||
time_last_decrease_ = now_ms;
|
||||
}
|
||||
|
||||
if (loss > 5 && loss <= 26) {
|
||||
// 2% - 10%
|
||||
new_bitrate = bitrate_;
|
||||
} else if (loss > 26) {
|
||||
// 26/256 ~= 10%
|
||||
// reduce rate: newRate = rate * (1 - 0.5*lossRate)
|
||||
// packetLoss = 256*lossRate
|
||||
new_bitrate = static_cast<uint32_t>((bitrate_ *
|
||||
static_cast<double>(512 - loss)) / 512.0);
|
||||
reducing = true;
|
||||
} else {
|
||||
// increase rate by 8%
|
||||
new_bitrate = static_cast<uint32_t>(bitrate_ * 1.08 + 0.5);
|
||||
|
||||
// add 1 kbps extra, just to make sure that we do not get stuck
|
||||
// (gives a little extra increase at low rates, negligible at higher rates)
|
||||
new_bitrate += 1000;
|
||||
}
|
||||
if (reducing) {
|
||||
// Calculate what rate TFRC would apply in this situation
|
||||
// scale loss to Q0 (back to [0, 255])
|
||||
uint32_t tfrc_bitrate = CalcTFRCbps(rtt, loss);
|
||||
if (tfrc_bitrate > new_bitrate) {
|
||||
// do not reduce further if rate is below TFRC rate
|
||||
new_bitrate = tfrc_bitrate;
|
||||
}
|
||||
}
|
||||
if (bwe_incoming_ > 0 && new_bitrate > bwe_incoming_) {
|
||||
new_bitrate = bwe_incoming_;
|
||||
}
|
||||
if (new_bitrate > max_bitrate_configured_) {
|
||||
new_bitrate = max_bitrate_configured_;
|
||||
}
|
||||
if (new_bitrate < min_bitrate_configured_) {
|
||||
WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, -1,
|
||||
"The configured min bitrate (%u kbps) is greater than the "
|
||||
"estimated available bandwidth (%u kbps).\n",
|
||||
min_bitrate_configured_ / 1000, new_bitrate / 1000);
|
||||
new_bitrate = min_bitrate_configured_;
|
||||
}
|
||||
return new_bitrate;
|
||||
}
|
||||
} // namespace webrtc
|
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* FEC and NACK added bitrate is handled outside class
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_MODULES_BITRATE_CONTROLLER_SEND_SIDE_BANDWIDTH_ESTIMATION_H_
|
||||
#define WEBRTC_MODULES_BITRATE_CONTROLLER_SEND_SIDE_BANDWIDTH_ESTIMATION_H_
|
||||
|
||||
#include "modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
|
||||
#include "system_wrappers/interface/critical_section_wrapper.h"
|
||||
|
||||
namespace webrtc {
|
||||
class SendSideBandwidthEstimation {
|
||||
public:
|
||||
SendSideBandwidthEstimation();
|
||||
virtual ~SendSideBandwidthEstimation();
|
||||
|
||||
// Call when we receive a RTCP message with TMMBR or REMB
|
||||
// Return true if new_bitrate is valid.
|
||||
bool UpdateBandwidthEstimate(const uint32_t bandwidth,
|
||||
uint32_t* new_bitrate,
|
||||
uint8_t* fraction_lost,
|
||||
uint16_t* rtt);
|
||||
|
||||
// Call when we receive a RTCP message with a ReceiveBlock
|
||||
// Return true if new_bitrate is valid.
|
||||
bool UpdatePacketLoss(const int number_of_packets,
|
||||
const uint32_t rtt,
|
||||
const uint32_t now_ms,
|
||||
uint8_t* loss,
|
||||
uint32_t* new_bitrate);
|
||||
|
||||
// Return false if no bandwidth estimate is available
|
||||
bool AvailableBandwidth(uint32_t* bandwidth) const;
|
||||
void SetSendBitrate(const uint32_t bitrate);
|
||||
void SetMinMaxBitrate(const uint32_t min_bitrate, const uint32_t max_bitrate);
|
||||
|
||||
private:
|
||||
uint32_t ShapeSimple(uint8_t loss, uint32_t rtt, uint32_t now_ms);
|
||||
|
||||
uint32_t CalcTFRCbps(uint16_t rtt, uint8_t loss);
|
||||
|
||||
enum { kBWEIncreaseIntervalMs = 1000 };
|
||||
enum { kBWEDecreaseIntervalMs = 300 };
|
||||
enum { kLimitNumPackets = 20 };
|
||||
enum { kAvgPacketSizeBytes = 1000 };
|
||||
|
||||
CriticalSectionWrapper* critsect_;
|
||||
|
||||
// incoming filters
|
||||
int accumulate_lost_packets_Q8_;
|
||||
int accumulate_expected_packets_;
|
||||
|
||||
uint32_t bitrate_;
|
||||
uint32_t min_bitrate_configured_;
|
||||
uint32_t max_bitrate_configured_;
|
||||
|
||||
uint8_t last_fraction_loss_;
|
||||
uint16_t last_round_trip_time_;
|
||||
|
||||
uint32_t bwe_incoming_;
|
||||
uint32_t time_last_increase_;
|
||||
uint32_t time_last_decrease_;
|
||||
};
|
||||
} // namespace webrtc
|
||||
#endif // WEBRTC_MODULES_BITRATE_CONTROLLER_SEND_SIDE_BANDWIDTH_ESTIMATION_H_
|
255
src/modules/bitrate_controller/test/test_bitrate_controller.cc
Normal file
255
src/modules/bitrate_controller/test/test_bitrate_controller.cc
Normal file
@ -0,0 +1,255 @@
|
||||
/*
|
||||
* 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 <gtest/gtest.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include "modules/bitrate_controller/include/bitrate_controller.h"
|
||||
#include "modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
|
||||
|
||||
using webrtc::RtcpBandwidthObserver;
|
||||
using webrtc::BitrateObserver;
|
||||
using webrtc::BitrateController;
|
||||
|
||||
class TestBitrateObserver: public BitrateObserver {
|
||||
public:
|
||||
TestBitrateObserver()
|
||||
: last_bitrate(0),
|
||||
last_fraction_loss(0),
|
||||
last_rtt(0) {
|
||||
}
|
||||
|
||||
virtual void OnNetworkChanged(const uint32_t bitrate,
|
||||
const uint8_t fraction_loss,
|
||||
const uint32_t rtt) {
|
||||
last_bitrate = bitrate;
|
||||
last_fraction_loss = fraction_loss;
|
||||
last_rtt = rtt;
|
||||
}
|
||||
uint32_t last_bitrate;
|
||||
uint8_t last_fraction_loss;
|
||||
uint32_t last_rtt;
|
||||
};
|
||||
|
||||
class BitrateControllerTest : public ::testing::Test {
|
||||
protected:
|
||||
BitrateControllerTest() {
|
||||
}
|
||||
~BitrateControllerTest() {}
|
||||
|
||||
virtual void SetUp() {
|
||||
controller_ = BitrateController::CreateBitrateController();
|
||||
bandwidth_observer_ = controller_->CreateRtcpBandwidthObserver();
|
||||
}
|
||||
|
||||
virtual void TearDown() {
|
||||
delete bandwidth_observer_;
|
||||
delete controller_;
|
||||
}
|
||||
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, OneBitrateObserverOneRtcpObserver) {
|
||||
TestBitrateObserver bitrate_observer;
|
||||
controller_->SetBitrateObserver(&bitrate_observer, 200000, 100000, 300000);
|
||||
|
||||
// Receive a high remb, test bitrate inc.
|
||||
bandwidth_observer_->OnReceivedEstimatedBitrate(400000);
|
||||
|
||||
// Test start bitrate.
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 1, 1);
|
||||
EXPECT_EQ(bitrate_observer.last_bitrate, 200000u);
|
||||
EXPECT_EQ(bitrate_observer.last_fraction_loss, 0);
|
||||
EXPECT_EQ(bitrate_observer.last_rtt, 50u);
|
||||
|
||||
// Test bitrate increase 8% per second.
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 21, 1001);
|
||||
EXPECT_EQ(bitrate_observer.last_bitrate, 217000u);
|
||||
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 41, 2001);
|
||||
EXPECT_EQ(bitrate_observer.last_bitrate, 235360u);
|
||||
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 61, 3001);
|
||||
EXPECT_EQ(bitrate_observer.last_bitrate, 255189u);
|
||||
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 81, 4001);
|
||||
EXPECT_EQ(bitrate_observer.last_bitrate, 276604u);
|
||||
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 101, 5001);
|
||||
EXPECT_EQ(bitrate_observer.last_bitrate, 299732u);
|
||||
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 121, 6001);
|
||||
EXPECT_EQ(bitrate_observer.last_bitrate, 300000u); // Max cap.
|
||||
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 141, 7001);
|
||||
EXPECT_EQ(bitrate_observer.last_bitrate, 300000u); // Max cap.
|
||||
|
||||
// Test that a low REMB trigger immediately.
|
||||
bandwidth_observer_->OnReceivedEstimatedBitrate(250000);
|
||||
EXPECT_EQ(bitrate_observer.last_bitrate, 250000u);
|
||||
EXPECT_EQ(bitrate_observer.last_fraction_loss, 0);
|
||||
EXPECT_EQ(bitrate_observer.last_rtt, 50u);
|
||||
|
||||
bandwidth_observer_->OnReceivedEstimatedBitrate(1000);
|
||||
EXPECT_EQ(bitrate_observer.last_bitrate, 100000u); // Min cap.
|
||||
controller_->RemoveBitrateObserver(&bitrate_observer);
|
||||
}
|
||||
|
||||
TEST_F(BitrateControllerTest, OneBitrateObserverTwoRtcpObservers) {
|
||||
TestBitrateObserver bitrate_observer;
|
||||
controller_->SetBitrateObserver(&bitrate_observer, 200000, 100000, 300000);
|
||||
|
||||
RtcpBandwidthObserver* second_bandwidth_observer =
|
||||
controller_->CreateRtcpBandwidthObserver();
|
||||
|
||||
// Receive a high remb, test bitrate inc.
|
||||
bandwidth_observer_->OnReceivedEstimatedBitrate(400000);
|
||||
|
||||
// Test start bitrate.
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 1, 1);
|
||||
second_bandwidth_observer->OnReceivedRtcpReceiverReport(1, 0, 100, 1, 1);
|
||||
EXPECT_EQ(bitrate_observer.last_bitrate, 200000u);
|
||||
EXPECT_EQ(bitrate_observer.last_fraction_loss, 0);
|
||||
EXPECT_EQ(bitrate_observer.last_rtt, 100u);
|
||||
|
||||
// Test bitrate increase 8% per second.
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 21, 1001);
|
||||
second_bandwidth_observer->OnReceivedRtcpReceiverReport(1, 0, 100, 21, 1001);
|
||||
EXPECT_EQ(bitrate_observer.last_bitrate, 217000u);
|
||||
|
||||
// Extra report should not change estimate.
|
||||
second_bandwidth_observer->OnReceivedRtcpReceiverReport(1, 0, 100, 31, 1501);
|
||||
EXPECT_EQ(bitrate_observer.last_bitrate, 217000u);
|
||||
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 41, 2001);
|
||||
EXPECT_EQ(bitrate_observer.last_bitrate, 235360u);
|
||||
// Second report should not change estimate.
|
||||
second_bandwidth_observer->OnReceivedRtcpReceiverReport(1, 0, 100, 41, 2001);
|
||||
EXPECT_EQ(bitrate_observer.last_bitrate, 235360u);
|
||||
|
||||
// Reports from only one bandwidth observer is ok.
|
||||
second_bandwidth_observer->OnReceivedRtcpReceiverReport(1, 0, 50, 61, 3001);
|
||||
EXPECT_EQ(bitrate_observer.last_bitrate, 255189u);
|
||||
|
||||
second_bandwidth_observer->OnReceivedRtcpReceiverReport(1, 0, 50, 81, 4001);
|
||||
EXPECT_EQ(bitrate_observer.last_bitrate, 276604u);
|
||||
|
||||
second_bandwidth_observer->OnReceivedRtcpReceiverReport(1, 0, 50, 101, 5001);
|
||||
EXPECT_EQ(bitrate_observer.last_bitrate, 299732u);
|
||||
|
||||
second_bandwidth_observer->OnReceivedRtcpReceiverReport(1, 0, 50, 121, 6001);
|
||||
EXPECT_EQ(bitrate_observer.last_bitrate, 300000u); // Max cap.
|
||||
|
||||
second_bandwidth_observer->OnReceivedRtcpReceiverReport(1, 0, 50, 141, 7001);
|
||||
EXPECT_EQ(bitrate_observer.last_bitrate, 300000u); // Max cap.
|
||||
|
||||
// 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(bitrate_observer.last_bitrate, 250000u);
|
||||
EXPECT_EQ(bitrate_observer.last_fraction_loss, 0);
|
||||
EXPECT_EQ(bitrate_observer.last_rtt, 50u);
|
||||
|
||||
bandwidth_observer_->OnReceivedEstimatedBitrate(1000);
|
||||
EXPECT_EQ(bitrate_observer.last_bitrate, 100000u); // Min cap.
|
||||
controller_->RemoveBitrateObserver(&bitrate_observer);
|
||||
delete second_bandwidth_observer;
|
||||
}
|
||||
|
||||
TEST_F(BitrateControllerTest, TwoBitrateObserversOneRtcpObserver) {
|
||||
TestBitrateObserver bitrate_observer_1;
|
||||
TestBitrateObserver bitrate_observer_2;
|
||||
controller_->SetBitrateObserver(&bitrate_observer_1, 200000, 100000, 300000);
|
||||
controller_->SetBitrateObserver(&bitrate_observer_2, 200000, 200000, 300000);
|
||||
|
||||
// Receive a high remb, test bitrate inc.
|
||||
bandwidth_observer_->OnReceivedEstimatedBitrate(400000);
|
||||
|
||||
// Test too low start bitrate, hence lower than sum of min.
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 1, 1);
|
||||
EXPECT_EQ(bitrate_observer_1.last_bitrate, 100000u);
|
||||
EXPECT_EQ(bitrate_observer_1.last_fraction_loss, 0);
|
||||
EXPECT_EQ(bitrate_observer_1.last_rtt, 50u);
|
||||
|
||||
EXPECT_EQ(bitrate_observer_2.last_bitrate, 200000u);
|
||||
EXPECT_EQ(bitrate_observer_2.last_fraction_loss, 0);
|
||||
EXPECT_EQ(bitrate_observer_2.last_rtt, 50u);
|
||||
|
||||
// Test bitrate increase 8% per second, distributed equaly.
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 21, 1001);
|
||||
EXPECT_EQ(bitrate_observer_1.last_bitrate, 112500u);
|
||||
EXPECT_EQ(bitrate_observer_2.last_bitrate, 212500u);
|
||||
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 41, 2001);
|
||||
EXPECT_EQ(bitrate_observer_1.last_bitrate, 126000u);
|
||||
EXPECT_EQ(bitrate_observer_2.last_bitrate, 226000u);
|
||||
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 61, 3001);
|
||||
EXPECT_EQ(bitrate_observer_1.last_bitrate, 140580u);
|
||||
EXPECT_EQ(bitrate_observer_2.last_bitrate, 240580u);
|
||||
|
||||
// Check that the bitrate sum honor our REMB.
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 81, 4001);
|
||||
EXPECT_EQ(bitrate_observer_1.last_bitrate, 150000u);
|
||||
EXPECT_EQ(bitrate_observer_2.last_bitrate, 250000u);
|
||||
|
||||
// Remove REMB cap, higher than sum of max.
|
||||
bandwidth_observer_->OnReceivedEstimatedBitrate(700000);
|
||||
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 101, 5001);
|
||||
EXPECT_EQ(bitrate_observer_1.last_bitrate, 166500u);
|
||||
EXPECT_EQ(bitrate_observer_2.last_bitrate, 266500u);
|
||||
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 121, 6001);
|
||||
EXPECT_EQ(bitrate_observer_1.last_bitrate, 184320u);
|
||||
EXPECT_EQ(bitrate_observer_2.last_bitrate, 284320u);
|
||||
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 141, 7001);
|
||||
EXPECT_EQ(bitrate_observer_1.last_bitrate, 207130u);
|
||||
EXPECT_EQ(bitrate_observer_2.last_bitrate, 300000u); // Max cap.
|
||||
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 161, 8001);
|
||||
EXPECT_EQ(bitrate_observer_1.last_bitrate, 248700u);
|
||||
EXPECT_EQ(bitrate_observer_2.last_bitrate, 300000u);
|
||||
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 181, 9001);
|
||||
EXPECT_EQ(bitrate_observer_1.last_bitrate, 293596u);
|
||||
EXPECT_EQ(bitrate_observer_2.last_bitrate, 300000u);
|
||||
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 201, 10001);
|
||||
EXPECT_EQ(bitrate_observer_1.last_bitrate, 300000u); // Max cap.
|
||||
EXPECT_EQ(bitrate_observer_2.last_bitrate, 300000u);
|
||||
|
||||
// Test that a low REMB trigger immediately.
|
||||
bandwidth_observer_->OnReceivedEstimatedBitrate(350000);
|
||||
EXPECT_EQ(bitrate_observer_1.last_bitrate, 125000u);
|
||||
EXPECT_EQ(bitrate_observer_1.last_fraction_loss, 0);
|
||||
EXPECT_EQ(bitrate_observer_1.last_rtt, 50u);
|
||||
EXPECT_EQ(bitrate_observer_2.last_bitrate, 225000u);
|
||||
EXPECT_EQ(bitrate_observer_2.last_fraction_loss, 0);
|
||||
EXPECT_EQ(bitrate_observer_2.last_rtt, 50u);
|
||||
|
||||
bandwidth_observer_->OnReceivedEstimatedBitrate(1000);
|
||||
EXPECT_EQ(bitrate_observer_1.last_bitrate, 100000u); // Min cap.
|
||||
EXPECT_EQ(bitrate_observer_2.last_bitrate, 200000u); // Min cap.
|
||||
controller_->RemoveBitrateObserver(&bitrate_observer_1);
|
||||
controller_->RemoveBitrateObserver(&bitrate_observer_2);
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,37 @@
|
||||
# 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.
|
||||
|
||||
{
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'test_bitrate_controller',
|
||||
'type': 'executable',
|
||||
'dependencies': [
|
||||
'bitrate_controller',
|
||||
'<(webrtc_root)/../test/test.gyp:test_support_main',
|
||||
'<(webrtc_root)/../testing/gtest.gyp:gtest',
|
||||
],
|
||||
|
||||
'include_dirs': [
|
||||
'../include',
|
||||
'../',
|
||||
'../../../system_wrappers/interface',
|
||||
],
|
||||
|
||||
'sources': [
|
||||
'test_bitrate_controller.cc',
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
# Local Variables:
|
||||
# tab-width:2
|
||||
# indent-tabs-mode:nil
|
||||
# End:
|
||||
# vim: set expandtab tabstop=2 shiftwidth=2:
|
@ -26,6 +26,7 @@
|
||||
'audio_processing/agc/agc.gypi',
|
||||
'audio_processing/ns/ns.gypi',
|
||||
'audio_processing/utility/util.gypi',
|
||||
'bitrate_controller/bitrate_controller.gypi',
|
||||
'media_file/source/media_file.gypi',
|
||||
'udp_transport/source/udp_transport.gypi',
|
||||
'utility/source/utility.gypi',
|
||||
@ -46,6 +47,7 @@
|
||||
'audio_coding/codecs/iSAC/isac_test.gypi',
|
||||
'audio_coding/codecs/iSAC/isacfix_test.gypi',
|
||||
'audio_processing/apm_tests.gypi',
|
||||
'bitrate_controller/test/test_bitrate_controller.gypi',
|
||||
'rtp_rtcp/source/rtp_rtcp_tests.gypi',
|
||||
'rtp_rtcp/test/test_bwe/test_bwe.gypi',
|
||||
'rtp_rtcp/test/testFec/test_fec.gypi',
|
||||
|
@ -213,23 +213,43 @@ protected:
|
||||
virtual ~RtpFeedback() {}
|
||||
};
|
||||
|
||||
class RtpAudioFeedback
|
||||
{
|
||||
public:
|
||||
virtual void OnReceivedTelephoneEvent(const WebRtc_Word32 id,
|
||||
const WebRtc_UWord8 event,
|
||||
const bool endOfEvent) = 0;
|
||||
class RtpAudioFeedback {
|
||||
public:
|
||||
virtual void OnReceivedTelephoneEvent(const WebRtc_Word32 id,
|
||||
const WebRtc_UWord8 event,
|
||||
const bool endOfEvent) = 0;
|
||||
|
||||
virtual void OnPlayTelephoneEvent(const WebRtc_Word32 id,
|
||||
const WebRtc_UWord8 event,
|
||||
const WebRtc_UWord16 lengthMs,
|
||||
const WebRtc_UWord8 volume) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~RtpAudioFeedback() {}
|
||||
virtual void OnPlayTelephoneEvent(const WebRtc_Word32 id,
|
||||
const WebRtc_UWord8 event,
|
||||
const WebRtc_UWord16 lengthMs,
|
||||
const WebRtc_UWord8 volume) = 0;
|
||||
protected:
|
||||
virtual ~RtpAudioFeedback() {}
|
||||
};
|
||||
|
||||
class RtcpIntraFrameObserver {
|
||||
public:
|
||||
virtual void OnReceivedIntraFrameRequest(const uint32_t ssrc) = 0;
|
||||
protected:
|
||||
virtual ~RtcpIntraFrameObserver() {}
|
||||
};
|
||||
|
||||
class RtcpBandwidthObserver {
|
||||
public:
|
||||
// REMB or TMMBR
|
||||
virtual void OnReceivedEstimatedBitrate(const uint32_t bitrate) = 0;
|
||||
|
||||
virtual void OnReceivedRtcpReceiverReport(
|
||||
const uint32_t ssrc,
|
||||
const uint8_t fraction_loss,
|
||||
const uint32_t rtt,
|
||||
const uint32_t last_received_extended_high_seqNum,
|
||||
const uint32_t now_ms) = 0;
|
||||
|
||||
virtual ~RtcpBandwidthObserver() {}
|
||||
};
|
||||
|
||||
// TODO(pwestin) To be depricated...
|
||||
class RtpVideoFeedback
|
||||
{
|
||||
public:
|
||||
@ -250,33 +270,31 @@ protected:
|
||||
// A clock interface that allows reading of absolute and relative
|
||||
// timestamps in an RTP/RTCP module.
|
||||
class RtpRtcpClock {
|
||||
public:
|
||||
virtual ~RtpRtcpClock() {}
|
||||
public:
|
||||
virtual ~RtpRtcpClock() {}
|
||||
|
||||
// Return a timestamp in milliseconds relative to some arbitrary
|
||||
// source; the source is fixed for this clock.
|
||||
virtual WebRtc_UWord32 GetTimeInMS() = 0;
|
||||
// Return a timestamp in milliseconds relative to some arbitrary
|
||||
// source; the source is fixed for this clock.
|
||||
virtual WebRtc_UWord32 GetTimeInMS() = 0;
|
||||
|
||||
// Retrieve an NTP absolute timestamp.
|
||||
virtual void CurrentNTP(WebRtc_UWord32& secs, WebRtc_UWord32& frac) = 0;
|
||||
// Retrieve an NTP absolute timestamp.
|
||||
virtual void CurrentNTP(WebRtc_UWord32& secs, WebRtc_UWord32& frac) = 0;
|
||||
};
|
||||
|
||||
// RtpReceiveBitrateUpdate is used to signal changes in bitrate estimates for
|
||||
// the incoming stream.
|
||||
class RtpRemoteBitrateObserver
|
||||
{
|
||||
class RtpRemoteBitrateObserver {
|
||||
public:
|
||||
// Called when a receive channel has a new bitrate estimate for the incoming
|
||||
// stream.
|
||||
virtual void OnReceiveBitrateChanged(unsigned int ssrc,
|
||||
unsigned int bitrate) = 0;
|
||||
// Called when a receive channel has a new bitrate estimate for the incoming
|
||||
// stream.
|
||||
virtual void OnReceiveBitrateChanged(uint32_t ssrc,
|
||||
uint32_t bitrate) = 0;
|
||||
|
||||
// Called when a REMB packet has been received.
|
||||
virtual void OnReceivedRemb(unsigned int bitrate) = 0;
|
||||
// TODO(pwestin)To be depricated...
|
||||
// Called when a REMB packet has been received.
|
||||
virtual void OnReceivedRemb(uint32_t bitrate) = 0;
|
||||
|
||||
virtual ~RtpRemoteBitrateObserver() {}
|
||||
virtual ~RtpRemoteBitrateObserver() {}
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_MODULES_RTP_RTCP_INTERFACE_RTP_RTCP_DEFINES_H_
|
||||
|
Loading…
x
Reference in New Issue
Block a user