- Changed RemoteBitrateEstimator::IncomingPacket() to include a const WebRtcRTPHeader& and remove ssrc, rtp_timestamp.
- Changed RemoteBitrateObserver::OnReceivedBitrateChanged() to use a const & instead of non-const *, to avoid unnecessary copying. - Refactored RemoteBitrateEstimatorTest so it can be instantiated for both single and multi stream BWE (first using a parameterized test, but then as a standard test fixture and a few helper functions). - Refactored some tests in RemoteBitrateEstimatorTest into a common function CapacityDropTestHelper(). BUG= R=andresp@webrtc.org, mflodman@webrtc.org, stefan@webrtc.org Review URL: https://webrtc-codereview.appspot.com/1521004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@4086 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
6ec25073e3
commit
561990fd73
@ -22,7 +22,7 @@ namespace webrtc {
|
|||||||
class MockRemoteBitrateObserver : public RemoteBitrateObserver {
|
class MockRemoteBitrateObserver : public RemoteBitrateObserver {
|
||||||
public:
|
public:
|
||||||
MOCK_METHOD2(OnReceiveBitrateChanged,
|
MOCK_METHOD2(OnReceiveBitrateChanged,
|
||||||
void(std::vector<unsigned int>* ssrcs, unsigned int bitrate));
|
void(const std::vector<unsigned int>& ssrcs, unsigned int bitrate));
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -31,7 +31,7 @@ class RemoteBitrateObserver {
|
|||||||
public:
|
public:
|
||||||
// Called when a receive channel group has a new bitrate estimate for the
|
// Called when a receive channel group has a new bitrate estimate for the
|
||||||
// incoming streams.
|
// incoming streams.
|
||||||
virtual void OnReceiveBitrateChanged(std::vector<unsigned int>* ssrcs,
|
virtual void OnReceiveBitrateChanged(const std::vector<unsigned int>& ssrcs,
|
||||||
unsigned int bitrate) = 0;
|
unsigned int bitrate) = 0;
|
||||||
|
|
||||||
virtual ~RemoteBitrateObserver() {}
|
virtual ~RemoteBitrateObserver() {}
|
||||||
@ -41,7 +41,6 @@ class RemoteBitrateEstimator : public CallStatsObserver, public Module {
|
|||||||
public:
|
public:
|
||||||
virtual ~RemoteBitrateEstimator() {}
|
virtual ~RemoteBitrateEstimator() {}
|
||||||
|
|
||||||
|
|
||||||
// Stores an RTCP SR (NTP, RTP timestamp) tuple for a specific SSRC to be used
|
// Stores an RTCP SR (NTP, RTP timestamp) tuple for a specific SSRC to be used
|
||||||
// in future RTP timestamp to NTP time conversions. As soon as any SSRC has
|
// in future RTP timestamp to NTP time conversions. As soon as any SSRC has
|
||||||
// two tuples the RemoteBitrateEstimator will switch to multi-stream mode.
|
// two tuples the RemoteBitrateEstimator will switch to multi-stream mode.
|
||||||
@ -51,11 +50,12 @@ class RemoteBitrateEstimator : public CallStatsObserver, public Module {
|
|||||||
// Called for each incoming packet. Updates the incoming payload bitrate
|
// Called for each incoming packet. Updates the incoming payload bitrate
|
||||||
// estimate and the over-use detector. If an over-use is detected the
|
// estimate and the over-use detector. If an over-use is detected the
|
||||||
// remote bitrate estimate will be updated. Note that |payload_size| is the
|
// remote bitrate estimate will be updated. Note that |payload_size| is the
|
||||||
// packet size excluding headers.
|
// packet size excluding headers. The estimator can only count on the
|
||||||
virtual void IncomingPacket(unsigned int ssrc,
|
// "header" (an RTPHeader) and "extension" (an RTPHeaderExtension) fields of
|
||||||
|
// the WebRtcRTPHeader to be initialized.
|
||||||
|
virtual void IncomingPacket(int64_t arrival_time_ms,
|
||||||
int payload_size,
|
int payload_size,
|
||||||
int64_t arrival_time,
|
const WebRtcRTPHeader& header) = 0;
|
||||||
uint32_t rtp_timestamp) = 0;
|
|
||||||
|
|
||||||
// Removes all data for |ssrc|.
|
// Removes all data for |ssrc|.
|
||||||
virtual void RemoveStream(unsigned int ssrc) = 0;
|
virtual void RemoveStream(unsigned int ssrc) = 0;
|
||||||
|
@ -59,7 +59,8 @@
|
|||||||
'sources': [
|
'sources': [
|
||||||
'include/mock/mock_remote_bitrate_observer.h',
|
'include/mock/mock_remote_bitrate_observer.h',
|
||||||
'bitrate_estimator_unittest.cc',
|
'bitrate_estimator_unittest.cc',
|
||||||
'remote_bitrate_estimator_unittest.cc',
|
'remote_bitrate_estimator_multi_stream_unittest.cc',
|
||||||
|
'remote_bitrate_estimator_single_stream_unittest.cc',
|
||||||
'remote_bitrate_estimator_unittest_helper.cc',
|
'remote_bitrate_estimator_unittest_helper.cc',
|
||||||
'remote_bitrate_estimator_unittest_helper.h',
|
'remote_bitrate_estimator_unittest_helper.h',
|
||||||
'rtp_to_ntp_unittest.cc',
|
'rtp_to_ntp_unittest.cc',
|
||||||
|
@ -28,14 +28,13 @@ class RemoteBitrateEstimatorMultiStream : public RemoteBitrateEstimator {
|
|||||||
public:
|
public:
|
||||||
RemoteBitrateEstimatorMultiStream(RemoteBitrateObserver* observer,
|
RemoteBitrateEstimatorMultiStream(RemoteBitrateObserver* observer,
|
||||||
Clock* clock);
|
Clock* clock);
|
||||||
|
virtual ~RemoteBitrateEstimatorMultiStream() {}
|
||||||
~RemoteBitrateEstimatorMultiStream() {}
|
|
||||||
|
|
||||||
// Stores an RTCP SR (NTP, RTP timestamp) tuple for a specific SSRC to be used
|
// Stores an RTCP SR (NTP, RTP timestamp) tuple for a specific SSRC to be used
|
||||||
// in future RTP timestamp to NTP time conversions. As soon as any SSRC has
|
// in future RTP timestamp to NTP time conversions. As soon as any SSRC has
|
||||||
// two tuples the RemoteBitrateEstimator will switch to multi-stream mode.
|
// two tuples the RemoteBitrateEstimator will switch to multi-stream mode.
|
||||||
void IncomingRtcp(unsigned int ssrc, uint32_t ntp_secs, uint32_t ntp_frac,
|
virtual void IncomingRtcp(unsigned int ssrc, uint32_t ntp_secs,
|
||||||
uint32_t rtp_timestamp);
|
uint32_t ntp_frac, uint32_t rtp_timestamp);
|
||||||
|
|
||||||
// Called for each incoming packet. The first SSRC will immediately be used
|
// Called for each incoming packet. The first SSRC will immediately be used
|
||||||
// for over-use detection. Subsequent SSRCs will only be used when at least
|
// for over-use detection. Subsequent SSRCs will only be used when at least
|
||||||
@ -43,10 +42,9 @@ class RemoteBitrateEstimatorMultiStream : public RemoteBitrateEstimator {
|
|||||||
// incoming payload bitrate estimate and the over-use detector.
|
// incoming payload bitrate estimate and the over-use detector.
|
||||||
// If an over-use is detected the remote bitrate estimate will be updated.
|
// If an over-use is detected the remote bitrate estimate will be updated.
|
||||||
// Note that |payload_size| is the packet size excluding headers.
|
// Note that |payload_size| is the packet size excluding headers.
|
||||||
void IncomingPacket(unsigned int ssrc,
|
virtual void IncomingPacket(int64_t arrival_time_ms,
|
||||||
int payload_size,
|
int payload_size,
|
||||||
int64_t arrival_time,
|
const WebRtcRTPHeader& header);
|
||||||
uint32_t rtp_timestamp);
|
|
||||||
|
|
||||||
// Triggers a new estimate calculation.
|
// Triggers a new estimate calculation.
|
||||||
// Implements the Module interface.
|
// Implements the Module interface.
|
||||||
@ -57,13 +55,13 @@ class RemoteBitrateEstimatorMultiStream : public RemoteBitrateEstimator {
|
|||||||
virtual void OnRttUpdate(uint32_t rtt);
|
virtual void OnRttUpdate(uint32_t rtt);
|
||||||
|
|
||||||
// Removes all data for |ssrc|.
|
// Removes all data for |ssrc|.
|
||||||
void RemoveStream(unsigned int ssrc);
|
virtual void RemoveStream(unsigned int ssrc);
|
||||||
|
|
||||||
// Returns true if a valid estimate exists and sets |bitrate_bps| to the
|
// Returns true if a valid estimate exists and sets |bitrate_bps| to the
|
||||||
// estimated payload bitrate in bits per second. |ssrcs| is the list of ssrcs
|
// estimated payload bitrate in bits per second. |ssrcs| is the list of ssrcs
|
||||||
// currently being received and of which the bitrate estimate is based upon.
|
// currently being received and of which the bitrate estimate is based upon.
|
||||||
bool LatestEstimate(std::vector<unsigned int>* ssrcs,
|
virtual bool LatestEstimate(std::vector<unsigned int>* ssrcs,
|
||||||
unsigned int* bitrate_bps) const;
|
unsigned int* bitrate_bps) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::map<unsigned int, synchronization::RtcpList> StreamMap;
|
typedef std::map<unsigned int, synchronization::RtcpList> StreamMap;
|
||||||
@ -138,12 +136,15 @@ void RemoteBitrateEstimatorMultiStream::IncomingRtcp(unsigned int ssrc,
|
|||||||
rtcp_list->push_front(measurement);
|
rtcp_list->push_front(measurement);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteBitrateEstimatorMultiStream::IncomingPacket(unsigned int ssrc,
|
void RemoteBitrateEstimatorMultiStream::IncomingPacket(
|
||||||
int payload_size,
|
int64_t arrival_time_ms,
|
||||||
int64_t arrival_time,
|
int payload_size,
|
||||||
uint32_t rtp_timestamp) {
|
const WebRtcRTPHeader& header) {
|
||||||
|
uint32_t ssrc = header.header.ssrc;
|
||||||
|
uint32_t rtp_timestamp = header.header.timestamp +
|
||||||
|
header.extension.transmissionTimeOffset;
|
||||||
CriticalSectionScoped cs(crit_sect_.get());
|
CriticalSectionScoped cs(crit_sect_.get());
|
||||||
incoming_bitrate_.Update(payload_size, arrival_time);
|
incoming_bitrate_.Update(payload_size, arrival_time_ms);
|
||||||
// Add this stream to the map of streams if it doesn't already exist.
|
// Add this stream to the map of streams if it doesn't already exist.
|
||||||
std::pair<StreamMap::iterator, bool> stream_insert_result =
|
std::pair<StreamMap::iterator, bool> stream_insert_result =
|
||||||
streams_.insert(std::make_pair(ssrc, synchronization::RtcpList()));
|
streams_.insert(std::make_pair(ssrc, synchronization::RtcpList()));
|
||||||
@ -167,15 +168,15 @@ void RemoteBitrateEstimatorMultiStream::IncomingPacket(unsigned int ssrc,
|
|||||||
synchronization::RtpToNtpMs(rtp_timestamp, *rtcp_list, ×tamp_in_ms);
|
synchronization::RtpToNtpMs(rtp_timestamp, *rtcp_list, ×tamp_in_ms);
|
||||||
}
|
}
|
||||||
overuse_detector_.Update(payload_size, timestamp_in_ms, rtp_timestamp,
|
overuse_detector_.Update(payload_size, timestamp_in_ms, rtp_timestamp,
|
||||||
arrival_time);
|
arrival_time_ms);
|
||||||
if (overuse_detector_.State() == kBwOverusing) {
|
if (overuse_detector_.State() == kBwOverusing) {
|
||||||
unsigned int incoming_bitrate = incoming_bitrate_.BitRate(arrival_time);
|
unsigned int incoming_bitrate = incoming_bitrate_.BitRate(arrival_time_ms);
|
||||||
if (prior_state != kBwOverusing ||
|
if (prior_state != kBwOverusing ||
|
||||||
remote_rate_.TimeToReduceFurther(arrival_time, incoming_bitrate)) {
|
remote_rate_.TimeToReduceFurther(arrival_time_ms, incoming_bitrate)) {
|
||||||
// The first overuse should immediately trigger a new estimate.
|
// The first overuse should immediately trigger a new estimate.
|
||||||
// We also have to update the estimate immediately if we are overusing
|
// We also have to update the estimate immediately if we are overusing
|
||||||
// and the target bitrate is too high compared to what we are receiving.
|
// and the target bitrate is too high compared to what we are receiving.
|
||||||
UpdateEstimate(arrival_time);
|
UpdateEstimate(arrival_time_ms);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -216,7 +217,7 @@ void RemoteBitrateEstimatorMultiStream::UpdateEstimate(int64_t time_now) {
|
|||||||
std::vector<unsigned int> ssrcs;
|
std::vector<unsigned int> ssrcs;
|
||||||
GetSsrcs(&ssrcs);
|
GetSsrcs(&ssrcs);
|
||||||
if (!ssrcs.empty()) {
|
if (!ssrcs.empty()) {
|
||||||
observer_->OnReceiveBitrateChanged(&ssrcs, target_bitrate);
|
observer_->OnReceiveBitrateChanged(ssrcs, target_bitrate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
overuse_detector_.SetRateControlRegion(region);
|
overuse_detector_.SetRateControlRegion(region);
|
||||||
|
@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 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 "modules/remote_bitrate_estimator/remote_bitrate_estimator_unittest_helper.h"
|
||||||
|
#include "webrtc/system_wrappers/interface/constructor_magic.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
|
||||||
|
class RemoteBitrateEstimatorMultiTest : public RemoteBitrateEstimatorTest {
|
||||||
|
public:
|
||||||
|
RemoteBitrateEstimatorMultiTest() {}
|
||||||
|
virtual void SetUp() {
|
||||||
|
bitrate_estimator_.reset(MultiStreamRemoteBitrateEstimatorFactory().Create(
|
||||||
|
bitrate_observer_.get(),
|
||||||
|
&clock_));
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(RemoteBitrateEstimatorMultiTest);
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(RemoteBitrateEstimatorMultiTest, InitialBehavior) {
|
||||||
|
InitialBehaviorTestHelper(497919);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(RemoteBitrateEstimatorMultiTest, RateIncreaseReordering) {
|
||||||
|
RateIncreaseReorderingTestHelper();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(RemoteBitrateEstimatorMultiTest, RateIncreaseRtpTimestamps) {
|
||||||
|
RateIncreaseRtpTimestampsTestHelper();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(RemoteBitrateEstimatorMultiTest, CapacityDropOneStream) {
|
||||||
|
CapacityDropTestHelper(1, false, 956214, 367);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(RemoteBitrateEstimatorMultiTest, CapacityDropOneStreamWrap) {
|
||||||
|
CapacityDropTestHelper(1, true, 956214, 367);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(RemoteBitrateEstimatorMultiTest, CapacityDropOneStreamWrapAlign) {
|
||||||
|
align_streams_ = true;
|
||||||
|
CapacityDropTestHelper(1, true, 838645, 533);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(RemoteBitrateEstimatorMultiTest, CapacityDropTwoStreamsWrapAlign) {
|
||||||
|
align_streams_ = true;
|
||||||
|
CapacityDropTestHelper(2, true, 810646, 433);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(RemoteBitrateEstimatorMultiTest, CapacityDropThreeStreamsWrapAlign) {
|
||||||
|
align_streams_ = true;
|
||||||
|
CapacityDropTestHelper(3, true, 868522, 2067);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(RemoteBitrateEstimatorMultiTest, CapacityDropThirteenStreamsWrap) {
|
||||||
|
CapacityDropTestHelper(13, true, 918810, 433);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(RemoteBitrateEstimatorMultiTest, CapacityDropNineteenStreamsWrap) {
|
||||||
|
CapacityDropTestHelper(19, true, 919119, 433);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(RemoteBitrateEstimatorMultiTest, CapacityDropThirtyStreamsWrap) {
|
||||||
|
CapacityDropTestHelper(30, true, 918724, 433);
|
||||||
|
}
|
||||||
|
} // namespace webrtc
|
@ -25,19 +25,19 @@ class RemoteBitrateEstimatorSingleStream : public RemoteBitrateEstimator {
|
|||||||
public:
|
public:
|
||||||
RemoteBitrateEstimatorSingleStream(RemoteBitrateObserver* observer,
|
RemoteBitrateEstimatorSingleStream(RemoteBitrateObserver* observer,
|
||||||
Clock* clock);
|
Clock* clock);
|
||||||
|
virtual ~RemoteBitrateEstimatorSingleStream() {}
|
||||||
|
|
||||||
void IncomingRtcp(unsigned int ssrc, uint32_t ntp_secs, uint32_t ntp_frac,
|
virtual void IncomingRtcp(unsigned int ssrc, uint32_t ntp_secs,
|
||||||
uint32_t rtp_timestamp) {}
|
uint32_t ntp_frac, uint32_t rtp_timestamp) {}
|
||||||
|
|
||||||
// Called for each incoming packet. If this is a new SSRC, a new
|
// Called for each incoming packet. If this is a new SSRC, a new
|
||||||
// BitrateControl will be created. Updates the incoming payload bitrate
|
// BitrateControl will be created. Updates the incoming payload bitrate
|
||||||
// estimate and the over-use detector. If an over-use is detected the
|
// estimate and the over-use detector. If an over-use is detected the
|
||||||
// remote bitrate estimate will be updated. Note that |payload_size| is the
|
// remote bitrate estimate will be updated. Note that |payload_size| is the
|
||||||
// packet size excluding headers.
|
// packet size excluding headers.
|
||||||
void IncomingPacket(unsigned int ssrc,
|
virtual void IncomingPacket(int64_t arrival_time_ms,
|
||||||
int payload_size,
|
int payload_size,
|
||||||
int64_t arrival_time,
|
const WebRtcRTPHeader& header);
|
||||||
uint32_t rtp_timestamp);
|
|
||||||
|
|
||||||
// Triggers a new estimate calculation.
|
// Triggers a new estimate calculation.
|
||||||
// Implements the Module interface.
|
// Implements the Module interface.
|
||||||
@ -48,13 +48,13 @@ class RemoteBitrateEstimatorSingleStream : public RemoteBitrateEstimator {
|
|||||||
virtual void OnRttUpdate(uint32_t rtt);
|
virtual void OnRttUpdate(uint32_t rtt);
|
||||||
|
|
||||||
// Removes all data for |ssrc|.
|
// Removes all data for |ssrc|.
|
||||||
void RemoveStream(unsigned int ssrc);
|
virtual void RemoveStream(unsigned int ssrc);
|
||||||
|
|
||||||
// Returns true if a valid estimate exists and sets |bitrate_bps| to the
|
// Returns true if a valid estimate exists and sets |bitrate_bps| to the
|
||||||
// estimated payload bitrate in bits per second. |ssrcs| is the list of ssrcs
|
// estimated payload bitrate in bits per second. |ssrcs| is the list of ssrcs
|
||||||
// currently being received and of which the bitrate estimate is based upon.
|
// currently being received and of which the bitrate estimate is based upon.
|
||||||
bool LatestEstimate(std::vector<unsigned int>* ssrcs,
|
virtual bool LatestEstimate(std::vector<unsigned int>* ssrcs,
|
||||||
unsigned int* bitrate_bps) const;
|
unsigned int* bitrate_bps) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::map<unsigned int, OveruseDetector> SsrcOveruseDetectorMap;
|
typedef std::map<unsigned int, OveruseDetector> SsrcOveruseDetectorMap;
|
||||||
@ -84,10 +84,12 @@ RemoteBitrateEstimatorSingleStream::RemoteBitrateEstimatorSingleStream(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RemoteBitrateEstimatorSingleStream::IncomingPacket(
|
void RemoteBitrateEstimatorSingleStream::IncomingPacket(
|
||||||
unsigned int ssrc,
|
int64_t arrival_time_ms,
|
||||||
int payload_size,
|
int payload_size,
|
||||||
int64_t arrival_time,
|
const WebRtcRTPHeader& header) {
|
||||||
uint32_t rtp_timestamp) {
|
uint32_t ssrc = header.header.ssrc;
|
||||||
|
uint32_t rtp_timestamp = header.header.timestamp +
|
||||||
|
header.extension.transmissionTimeOffset;
|
||||||
CriticalSectionScoped cs(crit_sect_.get());
|
CriticalSectionScoped cs(crit_sect_.get());
|
||||||
SsrcOveruseDetectorMap::iterator it = overuse_detectors_.find(ssrc);
|
SsrcOveruseDetectorMap::iterator it = overuse_detectors_.find(ssrc);
|
||||||
if (it == overuse_detectors_.end()) {
|
if (it == overuse_detectors_.end()) {
|
||||||
@ -103,17 +105,17 @@ void RemoteBitrateEstimatorSingleStream::IncomingPacket(
|
|||||||
it = insert_result.first;
|
it = insert_result.first;
|
||||||
}
|
}
|
||||||
OveruseDetector* overuse_detector = &it->second;
|
OveruseDetector* overuse_detector = &it->second;
|
||||||
incoming_bitrate_.Update(payload_size, arrival_time);
|
incoming_bitrate_.Update(payload_size, arrival_time_ms);
|
||||||
const BandwidthUsage prior_state = overuse_detector->State();
|
const BandwidthUsage prior_state = overuse_detector->State();
|
||||||
overuse_detector->Update(payload_size, -1, rtp_timestamp, arrival_time);
|
overuse_detector->Update(payload_size, -1, rtp_timestamp, arrival_time_ms);
|
||||||
if (overuse_detector->State() == kBwOverusing) {
|
if (overuse_detector->State() == kBwOverusing) {
|
||||||
unsigned int incoming_bitrate = incoming_bitrate_.BitRate(arrival_time);
|
unsigned int incoming_bitrate = incoming_bitrate_.BitRate(arrival_time_ms);
|
||||||
if (prior_state != kBwOverusing ||
|
if (prior_state != kBwOverusing ||
|
||||||
remote_rate_.TimeToReduceFurther(arrival_time, incoming_bitrate)) {
|
remote_rate_.TimeToReduceFurther(arrival_time_ms, incoming_bitrate)) {
|
||||||
// The first overuse should immediately trigger a new estimate.
|
// The first overuse should immediately trigger a new estimate.
|
||||||
// We also have to update the estimate immediately if we are overusing
|
// We also have to update the estimate immediately if we are overusing
|
||||||
// and the target bitrate is too high compared to what we are receiving.
|
// and the target bitrate is too high compared to what we are receiving.
|
||||||
UpdateEstimate(arrival_time);
|
UpdateEstimate(arrival_time_ms);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -172,7 +174,7 @@ void RemoteBitrateEstimatorSingleStream::UpdateEstimate(int64_t time_now) {
|
|||||||
if (remote_rate_.ValidEstimate()) {
|
if (remote_rate_.ValidEstimate()) {
|
||||||
std::vector<unsigned int> ssrcs;
|
std::vector<unsigned int> ssrcs;
|
||||||
GetSsrcs(&ssrcs);
|
GetSsrcs(&ssrcs);
|
||||||
observer_->OnReceiveBitrateChanged(&ssrcs, target_bitrate);
|
observer_->OnReceiveBitrateChanged(ssrcs, target_bitrate);
|
||||||
}
|
}
|
||||||
for (it = overuse_detectors_.begin(); it != overuse_detectors_.end(); ++it) {
|
for (it = overuse_detectors_.begin(); it != overuse_detectors_.end(); ++it) {
|
||||||
it->second.SetRateControlRegion(region);
|
it->second.SetRateControlRegion(region);
|
||||||
|
@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 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 "modules/remote_bitrate_estimator/remote_bitrate_estimator_unittest_helper.h"
|
||||||
|
#include "webrtc/system_wrappers/interface/constructor_magic.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
|
||||||
|
class RemoteBitrateEstimatorSingleTest : public RemoteBitrateEstimatorTest {
|
||||||
|
public:
|
||||||
|
RemoteBitrateEstimatorSingleTest() {}
|
||||||
|
virtual void SetUp() {
|
||||||
|
bitrate_estimator_.reset(RemoteBitrateEstimatorFactory().Create(
|
||||||
|
bitrate_observer_.get(),
|
||||||
|
&clock_));
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(RemoteBitrateEstimatorSingleTest);
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(RemoteBitrateEstimatorSingleTest, InitialBehavior) {
|
||||||
|
InitialBehaviorTestHelper(498075);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(RemoteBitrateEstimatorSingleTest, RateIncreaseReordering) {
|
||||||
|
RateIncreaseReorderingTestHelper();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(RemoteBitrateEstimatorSingleTest, RateIncreaseRtpTimestamps) {
|
||||||
|
RateIncreaseRtpTimestampsTestHelper();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the time it takes for the estimator to reduce the bitrate when
|
||||||
|
// the capacity is tightened stays the same.
|
||||||
|
TEST_F(RemoteBitrateEstimatorSingleTest, CapacityDropOneStream) {
|
||||||
|
CapacityDropTestHelper(1, false, 956214, 367);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the time it takes for the estimator to reduce the bitrate when
|
||||||
|
// the capacity is tightened stays the same. This test also verifies that we
|
||||||
|
// handle wrap-arounds in this scenario.
|
||||||
|
TEST_F(RemoteBitrateEstimatorSingleTest, CapacityDropOneStreamWrap) {
|
||||||
|
CapacityDropTestHelper(1, true, 956214, 367);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the time it takes for the estimator to reduce the bitrate when
|
||||||
|
// the capacity is tightened stays the same. This test also verifies that we
|
||||||
|
// handle wrap-arounds in this scenario.
|
||||||
|
TEST_F(RemoteBitrateEstimatorSingleTest, CapacityDropOneStreamWrapAlign) {
|
||||||
|
align_streams_ = true;
|
||||||
|
CapacityDropTestHelper(1, true, 956214, 367);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the time it takes for the estimator to reduce the bitrate when
|
||||||
|
// the capacity is tightened stays the same. This test also verifies that we
|
||||||
|
// handle wrap-arounds in this scenario. This is a multi-stream test.
|
||||||
|
TEST_F(RemoteBitrateEstimatorSingleTest, CapacityDropTwoStreamsWrapAlign) {
|
||||||
|
align_streams_ = true;
|
||||||
|
CapacityDropTestHelper(2, true, 927088, 267);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the time it takes for the estimator to reduce the bitrate when
|
||||||
|
// the capacity is tightened stays the same. This test also verifies that we
|
||||||
|
// handle wrap-arounds in this scenario. This is a multi-stream test.
|
||||||
|
TEST_F(RemoteBitrateEstimatorSingleTest, CapacityDropThreeStreamsWrapAlign) {
|
||||||
|
align_streams_ = true;
|
||||||
|
CapacityDropTestHelper(3, true, 920944, 333);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(RemoteBitrateEstimatorSingleTest, CapacityDropThirteenStreamsWrap) {
|
||||||
|
CapacityDropTestHelper(13, true, 938944, 300);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(RemoteBitrateEstimatorSingleTest, CapacityDropNineteenStreamsWrap) {
|
||||||
|
CapacityDropTestHelper(19, true, 926718, 300);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(RemoteBitrateEstimatorSingleTest, CapacityDropThirtyStreamsWrap) {
|
||||||
|
CapacityDropTestHelper(30, true, 927016, 300);
|
||||||
|
}
|
||||||
|
} // namespace webrtc
|
@ -1,367 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This file includes unit tests for RemoteBitrateEstimator.
|
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
|
|
||||||
#include "modules/remote_bitrate_estimator/remote_bitrate_estimator_unittest_helper.h"
|
|
||||||
#include "system_wrappers/interface/constructor_magic.h"
|
|
||||||
#include "system_wrappers/interface/scoped_ptr.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
|
||||||
|
|
||||||
TEST_F(RemoteBitrateEstimatorTest, TestInitialBehavior) {
|
|
||||||
const int kFramerate = 50; // 50 fps to avoid rounding errors.
|
|
||||||
const int kFrameIntervalMs = 1000 / kFramerate;
|
|
||||||
unsigned int bitrate_bps = 0;
|
|
||||||
uint32_t timestamp = 0;
|
|
||||||
std::vector<unsigned int> ssrcs;
|
|
||||||
EXPECT_FALSE(bitrate_estimator_->LatestEstimate(&ssrcs, &bitrate_bps));
|
|
||||||
EXPECT_EQ(0u, ssrcs.size());
|
|
||||||
clock_.AdvanceTimeMilliseconds(1000);
|
|
||||||
bitrate_estimator_->Process();
|
|
||||||
EXPECT_FALSE(bitrate_estimator_->LatestEstimate(&ssrcs, &bitrate_bps));
|
|
||||||
EXPECT_FALSE(bitrate_observer_->updated());
|
|
||||||
bitrate_observer_->Reset();
|
|
||||||
clock_.AdvanceTimeMilliseconds(1000);
|
|
||||||
// Inserting a packet. Still no valid estimate. We need to wait 1 second.
|
|
||||||
bitrate_estimator_->IncomingPacket(kDefaultSsrc, kMtu,
|
|
||||||
clock_.TimeInMilliseconds(), timestamp);
|
|
||||||
bitrate_estimator_->Process();
|
|
||||||
EXPECT_FALSE(bitrate_estimator_->LatestEstimate(&ssrcs, &bitrate_bps));
|
|
||||||
EXPECT_EQ(0u, ssrcs.size());
|
|
||||||
EXPECT_FALSE(bitrate_observer_->updated());
|
|
||||||
bitrate_observer_->Reset();
|
|
||||||
// Inserting packets for one second to get a valid estimate.
|
|
||||||
for (int i = 0; i < kFramerate; ++i) {
|
|
||||||
bitrate_estimator_->IncomingPacket(kDefaultSsrc, kMtu,
|
|
||||||
clock_.TimeInMilliseconds(), timestamp);
|
|
||||||
clock_.AdvanceTimeMilliseconds(1000 / kFramerate);
|
|
||||||
timestamp += 90 * kFrameIntervalMs;
|
|
||||||
}
|
|
||||||
bitrate_estimator_->Process();
|
|
||||||
EXPECT_TRUE(bitrate_estimator_->LatestEstimate(&ssrcs, &bitrate_bps));
|
|
||||||
ASSERT_EQ(1u, ssrcs.size());
|
|
||||||
EXPECT_EQ(kDefaultSsrc, ssrcs.front());
|
|
||||||
EXPECT_EQ(498075u, bitrate_bps);
|
|
||||||
EXPECT_TRUE(bitrate_observer_->updated());
|
|
||||||
bitrate_observer_->Reset();
|
|
||||||
EXPECT_EQ(bitrate_observer_->latest_bitrate(), bitrate_bps);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(RemoteBitrateEstimatorTest, TestRateIncreaseReordering) {
|
|
||||||
uint32_t timestamp = 0;
|
|
||||||
const int kFramerate = 50; // 50 fps to avoid rounding errors.
|
|
||||||
const int kFrameIntervalMs = 1000 / kFramerate;
|
|
||||||
bitrate_estimator_->IncomingPacket(kDefaultSsrc, 1000,
|
|
||||||
clock_.TimeInMilliseconds(), timestamp);
|
|
||||||
bitrate_estimator_->Process();
|
|
||||||
EXPECT_FALSE(bitrate_observer_->updated()); // No valid estimate.
|
|
||||||
// Inserting packets for one second to get a valid estimate.
|
|
||||||
for (int i = 0; i < kFramerate; ++i) {
|
|
||||||
bitrate_estimator_->IncomingPacket(kDefaultSsrc, kMtu,
|
|
||||||
clock_.TimeInMilliseconds(), timestamp);
|
|
||||||
clock_.AdvanceTimeMilliseconds(kFrameIntervalMs);
|
|
||||||
timestamp += 90 * kFrameIntervalMs;
|
|
||||||
}
|
|
||||||
bitrate_estimator_->Process();
|
|
||||||
EXPECT_TRUE(bitrate_observer_->updated());
|
|
||||||
EXPECT_EQ(498136u, bitrate_observer_->latest_bitrate());
|
|
||||||
for (int i = 0; i < 10; ++i) {
|
|
||||||
clock_.AdvanceTimeMilliseconds(2 * kFrameIntervalMs);
|
|
||||||
timestamp += 2 * 90 * kFrameIntervalMs;
|
|
||||||
bitrate_estimator_->IncomingPacket(kDefaultSsrc, 1000,
|
|
||||||
clock_.TimeInMilliseconds(), timestamp);
|
|
||||||
bitrate_estimator_->IncomingPacket(kDefaultSsrc,
|
|
||||||
1000,
|
|
||||||
clock_.TimeInMilliseconds(),
|
|
||||||
timestamp - 90 * kFrameIntervalMs);
|
|
||||||
}
|
|
||||||
bitrate_estimator_->Process();
|
|
||||||
EXPECT_TRUE(bitrate_observer_->updated());
|
|
||||||
EXPECT_EQ(498136u, bitrate_observer_->latest_bitrate());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure we initially increase the bitrate as expected.
|
|
||||||
TEST_F(RemoteBitrateEstimatorTest, TestRateIncreaseRtpTimestamps) {
|
|
||||||
// This threshold corresponds approximately to increasing linearly with
|
|
||||||
// bitrate(i) = 1.04 * bitrate(i-1) + 1000
|
|
||||||
// until bitrate(i) > 500000, with bitrate(1) ~= 30000.
|
|
||||||
const int kExpectedIterations = 1621;
|
|
||||||
unsigned int bitrate_bps = 30000;
|
|
||||||
int iterations = 0;
|
|
||||||
AddDefaultStream();
|
|
||||||
// Feed the estimator with a stream of packets and verify that it reaches
|
|
||||||
// 500 kbps at the expected time.
|
|
||||||
while (bitrate_bps < 5e5) {
|
|
||||||
bool overuse = GenerateAndProcessFrame(kDefaultSsrc, bitrate_bps);
|
|
||||||
if (overuse) {
|
|
||||||
EXPECT_GT(bitrate_observer_->latest_bitrate(), bitrate_bps);
|
|
||||||
bitrate_bps = bitrate_observer_->latest_bitrate();
|
|
||||||
bitrate_observer_->Reset();
|
|
||||||
} else if (bitrate_observer_->updated()) {
|
|
||||||
bitrate_bps = bitrate_observer_->latest_bitrate();
|
|
||||||
bitrate_observer_->Reset();
|
|
||||||
}
|
|
||||||
++iterations;
|
|
||||||
ASSERT_LE(iterations, kExpectedIterations);
|
|
||||||
}
|
|
||||||
ASSERT_EQ(kExpectedIterations, iterations);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify that the time it takes for the estimator to reduce the bitrate when
|
|
||||||
// the capacity is tightened stays the same.
|
|
||||||
TEST_F(RemoteBitrateEstimatorTest, TestCapacityDropRtpTimestamps) {
|
|
||||||
const int kNumberOfFrames = 300;
|
|
||||||
const int kStartBitrate = 900e3;
|
|
||||||
const int kMinExpectedBitrate = 800e3;
|
|
||||||
const int kMaxExpectedBitrate = 1100e3;
|
|
||||||
AddDefaultStream();
|
|
||||||
// Run in steady state to make the estimator converge.
|
|
||||||
unsigned int capacity_bps = 1000e3;
|
|
||||||
stream_generator_->set_capacity_bps(1000e3);
|
|
||||||
unsigned int bitrate_bps = SteadyStateRun(kDefaultSsrc, kNumberOfFrames,
|
|
||||||
kStartBitrate, kMinExpectedBitrate,
|
|
||||||
kMaxExpectedBitrate, capacity_bps);
|
|
||||||
// Reduce the capacity and verify the decrease time.
|
|
||||||
capacity_bps = 500e3;
|
|
||||||
stream_generator_->set_capacity_bps(capacity_bps);
|
|
||||||
int64_t overuse_start_time = clock_.TimeInMilliseconds();
|
|
||||||
int64_t bitrate_drop_time = -1;
|
|
||||||
for (int i = 0; i < 200; ++i) {
|
|
||||||
GenerateAndProcessFrame(kDefaultSsrc, bitrate_bps);
|
|
||||||
// Check for either increase or decrease.
|
|
||||||
if (bitrate_observer_->updated()) {
|
|
||||||
if (bitrate_drop_time == -1 &&
|
|
||||||
bitrate_observer_->latest_bitrate() <= capacity_bps) {
|
|
||||||
bitrate_drop_time = clock_.TimeInMilliseconds();
|
|
||||||
}
|
|
||||||
bitrate_bps = bitrate_observer_->latest_bitrate();
|
|
||||||
bitrate_observer_->Reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EXPECT_EQ(367, bitrate_drop_time - overuse_start_time);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify that the time it takes for the estimator to reduce the bitrate when
|
|
||||||
// the capacity is tightened stays the same. This test also verifies that we
|
|
||||||
// handle wrap-arounds in this scenario.
|
|
||||||
TEST_F(RemoteBitrateEstimatorTest, TestCapacityDropRtpTimestampsWrap) {
|
|
||||||
const int kFramerate= 30;
|
|
||||||
const int kStartBitrate = 900e3;
|
|
||||||
const int kMinExpectedBitrate = 800e3;
|
|
||||||
const int kMaxExpectedBitrate = 1100e3;
|
|
||||||
const int kSteadyStateTime = 8; // Seconds.
|
|
||||||
AddDefaultStream();
|
|
||||||
// Trigger wrap right after the steady state run.
|
|
||||||
stream_generator_->set_rtp_timestamp_offset(kDefaultSsrc,
|
|
||||||
std::numeric_limits<uint32_t>::max() - kSteadyStateTime * 90000);
|
|
||||||
// Run in steady state to make the estimator converge.
|
|
||||||
unsigned int capacity_bps = 1000e3;
|
|
||||||
stream_generator_->set_capacity_bps(1000e3);
|
|
||||||
unsigned int bitrate_bps = SteadyStateRun(kDefaultSsrc,
|
|
||||||
kSteadyStateTime * kFramerate,
|
|
||||||
kStartBitrate,
|
|
||||||
kMinExpectedBitrate,
|
|
||||||
kMaxExpectedBitrate,
|
|
||||||
capacity_bps);
|
|
||||||
bitrate_observer_->Reset();
|
|
||||||
// Reduce the capacity and verify the decrease time.
|
|
||||||
capacity_bps = 500e3;
|
|
||||||
stream_generator_->set_capacity_bps(capacity_bps);
|
|
||||||
int64_t overuse_start_time = clock_.TimeInMilliseconds();
|
|
||||||
int64_t bitrate_drop_time = -1;
|
|
||||||
for (int i = 0; i < 200; ++i) {
|
|
||||||
GenerateAndProcessFrame(kDefaultSsrc, bitrate_bps);
|
|
||||||
// Check for either increase or decrease.
|
|
||||||
if (bitrate_observer_->updated()) {
|
|
||||||
if (bitrate_drop_time == -1 &&
|
|
||||||
bitrate_observer_->latest_bitrate() <= capacity_bps) {
|
|
||||||
bitrate_drop_time = clock_.TimeInMilliseconds();
|
|
||||||
}
|
|
||||||
bitrate_bps = bitrate_observer_->latest_bitrate();
|
|
||||||
bitrate_observer_->Reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EXPECT_EQ(367, bitrate_drop_time - overuse_start_time);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify that the time it takes for the estimator to reduce the bitrate when
|
|
||||||
// the capacity is tightened stays the same. This test also verifies that we
|
|
||||||
// handle wrap-arounds in this scenario. This test also converts the timestamps
|
|
||||||
// to NTP time.
|
|
||||||
TEST_F(RemoteBitrateEstimatorTestAlign, TestCapacityDropRtpTimestampsWrap) {
|
|
||||||
const int kFramerate= 30;
|
|
||||||
const int kStartBitrate = 900e3;
|
|
||||||
const int kMinExpectedBitrate = 800e3;
|
|
||||||
const int kMaxExpectedBitrate = 1100e3;
|
|
||||||
const int kSteadyStateTime = 8; // Seconds.
|
|
||||||
AddDefaultStream();
|
|
||||||
// Trigger wrap right after the steady state run.
|
|
||||||
stream_generator_->set_rtp_timestamp_offset(kDefaultSsrc,
|
|
||||||
std::numeric_limits<uint32_t>::max() - kSteadyStateTime * 90000);
|
|
||||||
// Run in steady state to make the estimator converge.
|
|
||||||
unsigned int capacity_bps = 1000e3;
|
|
||||||
stream_generator_->set_capacity_bps(capacity_bps);
|
|
||||||
unsigned int bitrate_bps = SteadyStateRun(kDefaultSsrc,
|
|
||||||
kSteadyStateTime * kFramerate,
|
|
||||||
kStartBitrate,
|
|
||||||
kMinExpectedBitrate,
|
|
||||||
kMaxExpectedBitrate,
|
|
||||||
capacity_bps);
|
|
||||||
bitrate_observer_->Reset();
|
|
||||||
// Reduce the capacity and verify the decrease time.
|
|
||||||
capacity_bps = 500e3;
|
|
||||||
stream_generator_->set_capacity_bps(capacity_bps);
|
|
||||||
int64_t overuse_start_time = clock_.TimeInMilliseconds();
|
|
||||||
int64_t bitrate_drop_time = -1;
|
|
||||||
for (int i = 0; i < 200; ++i) {
|
|
||||||
GenerateAndProcessFrame(kDefaultSsrc, bitrate_bps);
|
|
||||||
// Check for either increase or decrease.
|
|
||||||
if (bitrate_observer_->updated()) {
|
|
||||||
if (bitrate_drop_time == -1 &&
|
|
||||||
bitrate_observer_->latest_bitrate() <= capacity_bps) {
|
|
||||||
bitrate_drop_time = clock_.TimeInMilliseconds();
|
|
||||||
}
|
|
||||||
bitrate_bps = bitrate_observer_->latest_bitrate();
|
|
||||||
bitrate_observer_->Reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EXPECT_EQ(367, bitrate_drop_time - overuse_start_time);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify that the time it takes for the estimator to reduce the bitrate when
|
|
||||||
// the capacity is tightened stays the same. This test also verifies that we
|
|
||||||
// handle wrap-arounds in this scenario. This is a multi-stream test.
|
|
||||||
TEST_F(RemoteBitrateEstimatorTestAlign, TwoStreamsCapacityDropWithWrap) {
|
|
||||||
const int kFramerate= 30;
|
|
||||||
const int kStartBitrate = 900e3;
|
|
||||||
const int kMinExpectedBitrate = 800e3;
|
|
||||||
const int kMaxExpectedBitrate = 1100e3;
|
|
||||||
const int kSteadyStateFrames = 9 * kFramerate;
|
|
||||||
stream_generator_->AddStream(new testing::RtpStream(
|
|
||||||
30, // Frames per second.
|
|
||||||
kStartBitrate/2, // Bitrate.
|
|
||||||
1, // SSRC.
|
|
||||||
90000, // RTP frequency.
|
|
||||||
0xFFFFF000, // Timestamp offset.
|
|
||||||
0)); // RTCP receive time.
|
|
||||||
|
|
||||||
stream_generator_->AddStream(new testing::RtpStream(
|
|
||||||
15, // Frames per second.
|
|
||||||
kStartBitrate/2, // Bitrate.
|
|
||||||
2, // SSRC.
|
|
||||||
90000, // RTP frequency.
|
|
||||||
0x00000FFF, // Timestamp offset.
|
|
||||||
0)); // RTCP receive time.
|
|
||||||
// Trigger wrap right after the steady state run.
|
|
||||||
stream_generator_->set_rtp_timestamp_offset(kDefaultSsrc,
|
|
||||||
std::numeric_limits<uint32_t>::max() - kSteadyStateFrames * 90000);
|
|
||||||
// Run in steady state to make the estimator converge.
|
|
||||||
unsigned int capacity_bps = 1000e3;
|
|
||||||
stream_generator_->set_capacity_bps(capacity_bps);
|
|
||||||
unsigned int bitrate_bps = SteadyStateRun(kDefaultSsrc,
|
|
||||||
kSteadyStateFrames,
|
|
||||||
kStartBitrate,
|
|
||||||
kMinExpectedBitrate,
|
|
||||||
kMaxExpectedBitrate,
|
|
||||||
capacity_bps);
|
|
||||||
bitrate_observer_->Reset();
|
|
||||||
// Reduce the capacity and verify the decrease time.
|
|
||||||
capacity_bps = 500e3;
|
|
||||||
stream_generator_->set_capacity_bps(capacity_bps);
|
|
||||||
int64_t overuse_start_time = clock_.TimeInMilliseconds();
|
|
||||||
int64_t bitrate_drop_time = -1;
|
|
||||||
for (int i = 0; i < 200; ++i) {
|
|
||||||
GenerateAndProcessFrame(kDefaultSsrc, bitrate_bps);
|
|
||||||
// Check for either increase or decrease.
|
|
||||||
if (bitrate_observer_->updated()) {
|
|
||||||
if (bitrate_drop_time == -1 &&
|
|
||||||
bitrate_observer_->latest_bitrate() <= capacity_bps) {
|
|
||||||
bitrate_drop_time = clock_.TimeInMilliseconds();
|
|
||||||
}
|
|
||||||
bitrate_bps = bitrate_observer_->latest_bitrate();
|
|
||||||
bitrate_observer_->Reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EXPECT_EQ(567, bitrate_drop_time - overuse_start_time);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify that the time it takes for the estimator to reduce the bitrate when
|
|
||||||
// the capacity is tightened stays the same. This test also verifies that we
|
|
||||||
// handle wrap-arounds in this scenario. This is a multi-stream test.
|
|
||||||
TEST_F(RemoteBitrateEstimatorTestAlign, ThreeStreams) {
|
|
||||||
const int kFramerate= 30;
|
|
||||||
const int kStartBitrate = 900e3;
|
|
||||||
const int kMinExpectedBitrate = 800e3;
|
|
||||||
const int kMaxExpectedBitrate = 1100e3;
|
|
||||||
const int kSteadyStateFrames = 12 * kFramerate;
|
|
||||||
stream_generator_->AddStream(new testing::RtpStream(
|
|
||||||
kFramerate, // Frames per second.
|
|
||||||
kStartBitrate/2, // Bitrate.
|
|
||||||
1, // SSRC.
|
|
||||||
90000, // RTP frequency.
|
|
||||||
0xFFFFF000, // Timestamp offset.
|
|
||||||
0)); // RTCP receive time.
|
|
||||||
|
|
||||||
stream_generator_->AddStream(new testing::RtpStream(
|
|
||||||
kFramerate, // Frames per second.
|
|
||||||
kStartBitrate/3, // Bitrate.
|
|
||||||
2, // SSRC.
|
|
||||||
90000, // RTP frequency.
|
|
||||||
0x00000FFF, // Timestamp offset.
|
|
||||||
0)); // RTCP receive time.
|
|
||||||
|
|
||||||
stream_generator_->AddStream(new testing::RtpStream(
|
|
||||||
kFramerate, // Frames per second.
|
|
||||||
kStartBitrate/6, // Bitrate.
|
|
||||||
3, // SSRC.
|
|
||||||
90000, // RTP frequency.
|
|
||||||
0x00000FFF, // Timestamp offset.
|
|
||||||
0)); // RTCP receive time.
|
|
||||||
// Trigger wrap right after the steady state run.
|
|
||||||
stream_generator_->set_rtp_timestamp_offset(kDefaultSsrc,
|
|
||||||
std::numeric_limits<uint32_t>::max() - kSteadyStateFrames * 90000);
|
|
||||||
// Run in steady state to make the estimator converge.
|
|
||||||
unsigned int capacity_bps = 1000e3;
|
|
||||||
stream_generator_->set_capacity_bps(capacity_bps);
|
|
||||||
unsigned int bitrate_bps = SteadyStateRun(kDefaultSsrc,
|
|
||||||
kSteadyStateFrames,
|
|
||||||
kStartBitrate,
|
|
||||||
kMinExpectedBitrate,
|
|
||||||
kMaxExpectedBitrate,
|
|
||||||
capacity_bps);
|
|
||||||
bitrate_observer_->Reset();
|
|
||||||
// Reduce the capacity and verify the decrease time.
|
|
||||||
capacity_bps = 500e3;
|
|
||||||
stream_generator_->set_capacity_bps(capacity_bps);
|
|
||||||
int64_t overuse_start_time = clock_.TimeInMilliseconds();
|
|
||||||
int64_t bitrate_drop_time = -1;
|
|
||||||
for (int i = 0; i < 200; ++i) {
|
|
||||||
GenerateAndProcessFrame(kDefaultSsrc, bitrate_bps);
|
|
||||||
// Check for either increase or decrease.
|
|
||||||
if (bitrate_observer_->updated()) {
|
|
||||||
if (bitrate_drop_time == -1 &&
|
|
||||||
bitrate_observer_->latest_bitrate() <= capacity_bps) {
|
|
||||||
bitrate_drop_time = clock_.TimeInMilliseconds();
|
|
||||||
}
|
|
||||||
bitrate_bps = bitrate_observer_->latest_bitrate();
|
|
||||||
bitrate_observer_->Reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EXPECT_EQ(433, bitrate_drop_time - overuse_start_time);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace webrtc
|
|
@ -13,6 +13,9 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
|
enum { kMtu = 1200 };
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
|
|
||||||
RtpStream::RtpStream(int fps,
|
RtpStream::RtpStream(int fps,
|
||||||
@ -124,22 +127,24 @@ void StreamGenerator::set_capacity_bps(int capacity_bps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Divides |bitrate_bps| among all streams. The allocated bitrate per stream
|
// Divides |bitrate_bps| among all streams. The allocated bitrate per stream
|
||||||
// is decided by the initial allocation ratios.
|
// is decided by the current allocation ratios.
|
||||||
void StreamGenerator::set_bitrate_bps(int bitrate_bps) {
|
void StreamGenerator::SetBitrateBps(int bitrate_bps) {
|
||||||
ASSERT_GE(streams_.size(), 0u);
|
ASSERT_GE(streams_.size(), 0u);
|
||||||
double total_bitrate_before = 0;
|
int total_bitrate_before = 0;
|
||||||
for (StreamMap::iterator it = streams_.begin(); it != streams_.end();
|
for (StreamMap::iterator it = streams_.begin(); it != streams_.end(); ++it) {
|
||||||
++it) {
|
|
||||||
total_bitrate_before += it->second->bitrate_bps();
|
total_bitrate_before += it->second->bitrate_bps();
|
||||||
}
|
}
|
||||||
|
int64_t bitrate_before = 0;
|
||||||
int total_bitrate_after = 0;
|
int total_bitrate_after = 0;
|
||||||
for (StreamMap::iterator it = streams_.begin(); it != streams_.end();
|
for (StreamMap::iterator it = streams_.begin(); it != streams_.end(); ++it) {
|
||||||
++it) {
|
bitrate_before += it->second->bitrate_bps();
|
||||||
double ratio = it->second->bitrate_bps() / total_bitrate_before;
|
int64_t bitrate_after = (bitrate_before * bitrate_bps +
|
||||||
it->second->set_bitrate_bps(ratio * bitrate_bps + 0.5);
|
total_bitrate_before / 2) / total_bitrate_before;
|
||||||
|
it->second->set_bitrate_bps(bitrate_after - total_bitrate_after);
|
||||||
total_bitrate_after += it->second->bitrate_bps();
|
total_bitrate_after += it->second->bitrate_bps();
|
||||||
}
|
}
|
||||||
EXPECT_NEAR(total_bitrate_after, bitrate_bps, 1);
|
ASSERT_EQ(bitrate_before, total_bitrate_before);
|
||||||
|
EXPECT_EQ(total_bitrate_after, bitrate_bps);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the RTP timestamp offset for the stream identified by |ssrc|.
|
// Set the RTP timestamp offset for the stream identified by |ssrc|.
|
||||||
@ -186,22 +191,11 @@ void StreamGenerator::Rtcps(RtcpList* rtcps, int64_t time_now_us) const {
|
|||||||
|
|
||||||
RemoteBitrateEstimatorTest::RemoteBitrateEstimatorTest()
|
RemoteBitrateEstimatorTest::RemoteBitrateEstimatorTest()
|
||||||
: clock_(0),
|
: clock_(0),
|
||||||
align_streams_(false) {}
|
align_streams_(false),
|
||||||
|
bitrate_observer_(new testing::TestBitrateObserver),
|
||||||
RemoteBitrateEstimatorTest::RemoteBitrateEstimatorTest(bool align_streams)
|
stream_generator_(new testing::StreamGenerator(
|
||||||
: clock_(0),
|
1e6, // Capacity.
|
||||||
align_streams_(align_streams) {}
|
clock_.TimeInMicroseconds())) {}
|
||||||
|
|
||||||
void RemoteBitrateEstimatorTest::SetUp() {
|
|
||||||
bitrate_observer_.reset(new testing::TestBitrateObserver);
|
|
||||||
bitrate_estimator_.reset(
|
|
||||||
RemoteBitrateEstimatorFactory().Create(
|
|
||||||
bitrate_observer_.get(),
|
|
||||||
&clock_));
|
|
||||||
stream_generator_.reset(new testing::StreamGenerator(
|
|
||||||
1e6, // Capacity.
|
|
||||||
clock_.TimeInMicroseconds()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void RemoteBitrateEstimatorTest::AddDefaultStream() {
|
void RemoteBitrateEstimatorTest::AddDefaultStream() {
|
||||||
stream_generator_->AddStream(new testing::RtpStream(
|
stream_generator_->AddStream(new testing::RtpStream(
|
||||||
@ -213,8 +207,29 @@ void RemoteBitrateEstimatorTest::AddDefaultStream() {
|
|||||||
0)); // RTCP receive time.
|
0)); // RTCP receive time.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t RemoteBitrateEstimatorTest::AbsSendTime(int64_t t, int64_t denom) {
|
||||||
|
return (((t << 18) + (denom >> 1)) / denom) & 0x00fffffful;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t RemoteBitrateEstimatorTest::AddAbsSendTime(uint32_t t1, uint32_t t2) {
|
||||||
|
return (t1 + t2) & 0x00fffffful;
|
||||||
|
}
|
||||||
|
|
||||||
const unsigned int RemoteBitrateEstimatorTest::kDefaultSsrc = 1;
|
const unsigned int RemoteBitrateEstimatorTest::kDefaultSsrc = 1;
|
||||||
|
|
||||||
|
void RemoteBitrateEstimatorTest::IncomingPacket(uint32_t ssrc,
|
||||||
|
uint32_t payload_size,
|
||||||
|
int64_t arrival_time,
|
||||||
|
uint32_t rtp_timestamp,
|
||||||
|
uint32_t absolute_send_time) {
|
||||||
|
WebRtcRTPHeader header;
|
||||||
|
memset(&header, 0, sizeof(header));
|
||||||
|
header.header.ssrc = ssrc;
|
||||||
|
header.header.timestamp = rtp_timestamp;
|
||||||
|
header.extension.absoluteSendTime = absolute_send_time;
|
||||||
|
bitrate_estimator_->IncomingPacket(arrival_time, payload_size, header);
|
||||||
|
}
|
||||||
|
|
||||||
// Generates a frame of packets belonging to a stream at a given bitrate and
|
// Generates a frame of packets belonging to a stream at a given bitrate and
|
||||||
// with a given ssrc. The stream is pushed through a very simple simulated
|
// with a given ssrc. The stream is pushed through a very simple simulated
|
||||||
// network, and is then given to the receive-side bandwidth estimator.
|
// network, and is then given to the receive-side bandwidth estimator.
|
||||||
@ -223,7 +238,7 @@ const unsigned int RemoteBitrateEstimatorTest::kDefaultSsrc = 1;
|
|||||||
// target bitrate after the call to this function.
|
// target bitrate after the call to this function.
|
||||||
bool RemoteBitrateEstimatorTest::GenerateAndProcessFrame(unsigned int ssrc,
|
bool RemoteBitrateEstimatorTest::GenerateAndProcessFrame(unsigned int ssrc,
|
||||||
unsigned int bitrate_bps) {
|
unsigned int bitrate_bps) {
|
||||||
stream_generator_->set_bitrate_bps(bitrate_bps);
|
stream_generator_->SetBitrateBps(bitrate_bps);
|
||||||
testing::RtpStream::PacketList packets;
|
testing::RtpStream::PacketList packets;
|
||||||
int64_t next_time_us = stream_generator_->GenerateFrame(
|
int64_t next_time_us = stream_generator_->GenerateFrame(
|
||||||
&packets, clock_.TimeInMicroseconds());
|
&packets, clock_.TimeInMicroseconds());
|
||||||
@ -243,10 +258,11 @@ bool RemoteBitrateEstimatorTest::GenerateAndProcessFrame(unsigned int ssrc,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
bitrate_observer_->Reset();
|
bitrate_observer_->Reset();
|
||||||
bitrate_estimator_->IncomingPacket(packet->ssrc,
|
IncomingPacket(packet->ssrc,
|
||||||
packet->size,
|
packet->size,
|
||||||
(packet->arrival_time + 500) / 1000,
|
(packet->arrival_time + 500) / 1000,
|
||||||
packet->rtp_timestamp);
|
packet->rtp_timestamp,
|
||||||
|
AbsSendTime(packet->send_time, 1000000));
|
||||||
if (bitrate_observer_->updated()) {
|
if (bitrate_observer_->updated()) {
|
||||||
// Verify that new estimates only are triggered by an overuse and a
|
// Verify that new estimates only are triggered by an overuse and a
|
||||||
// rate decrease.
|
// rate decrease.
|
||||||
@ -295,4 +311,193 @@ unsigned int RemoteBitrateEstimatorTest::SteadyStateRun(
|
|||||||
EXPECT_TRUE(bitrate_update_seen);
|
EXPECT_TRUE(bitrate_update_seen);
|
||||||
return bitrate_bps;
|
return bitrate_bps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RemoteBitrateEstimatorTest::InitialBehaviorTestHelper(
|
||||||
|
unsigned int expected_converge_bitrate) {
|
||||||
|
const int kFramerate = 50; // 50 fps to avoid rounding errors.
|
||||||
|
const int kFrameIntervalMs = 1000 / kFramerate;
|
||||||
|
const uint32_t kFrameIntervalAbsSendTime = AbsSendTime(1, kFramerate);
|
||||||
|
unsigned int bitrate_bps = 0;
|
||||||
|
uint32_t timestamp = 0;
|
||||||
|
uint32_t absolute_send_time = 0;
|
||||||
|
std::vector<unsigned int> ssrcs;
|
||||||
|
EXPECT_FALSE(bitrate_estimator_->LatestEstimate(&ssrcs, &bitrate_bps));
|
||||||
|
EXPECT_EQ(0u, ssrcs.size());
|
||||||
|
clock_.AdvanceTimeMilliseconds(1000);
|
||||||
|
bitrate_estimator_->Process();
|
||||||
|
EXPECT_FALSE(bitrate_estimator_->LatestEstimate(&ssrcs, &bitrate_bps));
|
||||||
|
EXPECT_FALSE(bitrate_observer_->updated());
|
||||||
|
bitrate_observer_->Reset();
|
||||||
|
clock_.AdvanceTimeMilliseconds(1000);
|
||||||
|
// Inserting a packet. Still no valid estimate. We need to wait 1 second.
|
||||||
|
IncomingPacket(kDefaultSsrc, kMtu, clock_.TimeInMilliseconds(), timestamp,
|
||||||
|
absolute_send_time);
|
||||||
|
bitrate_estimator_->Process();
|
||||||
|
EXPECT_FALSE(bitrate_estimator_->LatestEstimate(&ssrcs, &bitrate_bps));
|
||||||
|
EXPECT_EQ(0u, ssrcs.size());
|
||||||
|
EXPECT_FALSE(bitrate_observer_->updated());
|
||||||
|
bitrate_observer_->Reset();
|
||||||
|
// Inserting packets for one second to get a valid estimate.
|
||||||
|
for (int i = 0; i < kFramerate; ++i) {
|
||||||
|
IncomingPacket(kDefaultSsrc, kMtu, clock_.TimeInMilliseconds(), timestamp,
|
||||||
|
absolute_send_time);
|
||||||
|
clock_.AdvanceTimeMilliseconds(1000 / kFramerate);
|
||||||
|
timestamp += 90 * kFrameIntervalMs;
|
||||||
|
absolute_send_time = AddAbsSendTime(absolute_send_time,
|
||||||
|
kFrameIntervalAbsSendTime);
|
||||||
|
}
|
||||||
|
bitrate_estimator_->Process();
|
||||||
|
EXPECT_TRUE(bitrate_estimator_->LatestEstimate(&ssrcs, &bitrate_bps));
|
||||||
|
ASSERT_EQ(1u, ssrcs.size());
|
||||||
|
EXPECT_EQ(kDefaultSsrc, ssrcs.front());
|
||||||
|
EXPECT_EQ(expected_converge_bitrate, bitrate_bps);
|
||||||
|
EXPECT_TRUE(bitrate_observer_->updated());
|
||||||
|
bitrate_observer_->Reset();
|
||||||
|
EXPECT_EQ(bitrate_observer_->latest_bitrate(), bitrate_bps);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoteBitrateEstimatorTest::RateIncreaseReorderingTestHelper() {
|
||||||
|
const int kFramerate = 50; // 50 fps to avoid rounding errors.
|
||||||
|
const int kFrameIntervalMs = 1000 / kFramerate;
|
||||||
|
const uint32_t kFrameIntervalAbsSendTime = AbsSendTime(1, kFramerate);
|
||||||
|
uint32_t timestamp = 0;
|
||||||
|
uint32_t absolute_send_time = 0;
|
||||||
|
IncomingPacket(kDefaultSsrc, 1000, clock_.TimeInMilliseconds(), timestamp,
|
||||||
|
absolute_send_time);
|
||||||
|
bitrate_estimator_->Process();
|
||||||
|
EXPECT_FALSE(bitrate_observer_->updated()); // No valid estimate.
|
||||||
|
// Inserting packets for one second to get a valid estimate.
|
||||||
|
for (int i = 0; i < kFramerate; ++i) {
|
||||||
|
IncomingPacket(kDefaultSsrc, kMtu, clock_.TimeInMilliseconds(), timestamp,
|
||||||
|
absolute_send_time);
|
||||||
|
clock_.AdvanceTimeMilliseconds(kFrameIntervalMs);
|
||||||
|
timestamp += 90 * kFrameIntervalMs;
|
||||||
|
absolute_send_time = AddAbsSendTime(absolute_send_time,
|
||||||
|
kFrameIntervalAbsSendTime);
|
||||||
|
}
|
||||||
|
bitrate_estimator_->Process();
|
||||||
|
EXPECT_TRUE(bitrate_observer_->updated());
|
||||||
|
EXPECT_EQ(498136u, bitrate_observer_->latest_bitrate());
|
||||||
|
for (int i = 0; i < 10; ++i) {
|
||||||
|
clock_.AdvanceTimeMilliseconds(2 * kFrameIntervalMs);
|
||||||
|
timestamp += 2 * 90 * kFrameIntervalMs;
|
||||||
|
absolute_send_time = AddAbsSendTime(absolute_send_time,
|
||||||
|
2 * kFrameIntervalAbsSendTime);
|
||||||
|
IncomingPacket(kDefaultSsrc, 1000, clock_.TimeInMilliseconds(), timestamp,
|
||||||
|
absolute_send_time);
|
||||||
|
IncomingPacket(kDefaultSsrc, 1000, clock_.TimeInMilliseconds(),
|
||||||
|
timestamp - 90 * kFrameIntervalMs,
|
||||||
|
AddAbsSendTime(absolute_send_time,
|
||||||
|
-int(kFrameIntervalAbsSendTime)));
|
||||||
|
}
|
||||||
|
bitrate_estimator_->Process();
|
||||||
|
EXPECT_TRUE(bitrate_observer_->updated());
|
||||||
|
EXPECT_EQ(498136u, bitrate_observer_->latest_bitrate());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we initially increase the bitrate as expected.
|
||||||
|
void RemoteBitrateEstimatorTest::RateIncreaseRtpTimestampsTestHelper() {
|
||||||
|
// This threshold corresponds approximately to increasing linearly with
|
||||||
|
// bitrate(i) = 1.04 * bitrate(i-1) + 1000
|
||||||
|
// until bitrate(i) > 500000, with bitrate(1) ~= 30000.
|
||||||
|
const int kExpectedIterations = 1621;
|
||||||
|
unsigned int bitrate_bps = 30000;
|
||||||
|
int iterations = 0;
|
||||||
|
AddDefaultStream();
|
||||||
|
// Feed the estimator with a stream of packets and verify that it reaches
|
||||||
|
// 500 kbps at the expected time.
|
||||||
|
while (bitrate_bps < 5e5) {
|
||||||
|
bool overuse = GenerateAndProcessFrame(kDefaultSsrc, bitrate_bps);
|
||||||
|
if (overuse) {
|
||||||
|
EXPECT_GT(bitrate_observer_->latest_bitrate(), bitrate_bps);
|
||||||
|
bitrate_bps = bitrate_observer_->latest_bitrate();
|
||||||
|
bitrate_observer_->Reset();
|
||||||
|
} else if (bitrate_observer_->updated()) {
|
||||||
|
bitrate_bps = bitrate_observer_->latest_bitrate();
|
||||||
|
bitrate_observer_->Reset();
|
||||||
|
}
|
||||||
|
++iterations;
|
||||||
|
ASSERT_LE(iterations, kExpectedIterations);
|
||||||
|
}
|
||||||
|
ASSERT_EQ(kExpectedIterations, iterations);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoteBitrateEstimatorTest::CapacityDropTestHelper(
|
||||||
|
int number_of_streams,
|
||||||
|
bool wrap_time_stamp,
|
||||||
|
unsigned int expected_converge_bitrate,
|
||||||
|
unsigned int expected_bitrate_drop_delta) {
|
||||||
|
const int kFramerate = 30;
|
||||||
|
const int kStartBitrate = 900e3;
|
||||||
|
const int kMinExpectedBitrate = 800e3;
|
||||||
|
const int kMaxExpectedBitrate = 1100e3;
|
||||||
|
const unsigned int kInitialCapacityBps = 1000e3;
|
||||||
|
const unsigned int kReducedCapacityBps = 500e3;
|
||||||
|
|
||||||
|
int steady_state_time = 0;
|
||||||
|
int expected_overuse_start_time = 0;
|
||||||
|
if (number_of_streams <= 1) {
|
||||||
|
steady_state_time = 10;
|
||||||
|
expected_overuse_start_time = 10000;
|
||||||
|
AddDefaultStream();
|
||||||
|
} else {
|
||||||
|
steady_state_time = 8 * number_of_streams;
|
||||||
|
expected_overuse_start_time = 8000;
|
||||||
|
int bitrate_sum = 0;
|
||||||
|
int kBitrateDenom = number_of_streams * (number_of_streams - 1);
|
||||||
|
for (int i = 0; i < number_of_streams; i++) {
|
||||||
|
// First stream gets half available bitrate, while the rest share the
|
||||||
|
// remaining half i.e.: 1/2 = Sum[n/(N*(N-1))] for n=1..N-1 (rounded up)
|
||||||
|
int bitrate = kStartBitrate / 2;
|
||||||
|
if (i > 0) {
|
||||||
|
bitrate = (kStartBitrate * i + kBitrateDenom / 2) / kBitrateDenom;
|
||||||
|
}
|
||||||
|
stream_generator_->AddStream(new testing::RtpStream(
|
||||||
|
kFramerate, // Frames per second.
|
||||||
|
bitrate, // Bitrate.
|
||||||
|
kDefaultSsrc + i, // SSRC.
|
||||||
|
90000, // RTP frequency.
|
||||||
|
0xFFFFF000 ^ (~0 << (32 - i)), // Timestamp offset.
|
||||||
|
0)); // RTCP receive time.
|
||||||
|
bitrate_sum += bitrate;
|
||||||
|
}
|
||||||
|
ASSERT_EQ(bitrate_sum, kStartBitrate);
|
||||||
|
}
|
||||||
|
if (wrap_time_stamp) {
|
||||||
|
stream_generator_->set_rtp_timestamp_offset(kDefaultSsrc,
|
||||||
|
std::numeric_limits<uint32_t>::max() - steady_state_time * 90000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run in steady state to make the estimator converge.
|
||||||
|
stream_generator_->set_capacity_bps(kInitialCapacityBps);
|
||||||
|
unsigned int bitrate_bps = SteadyStateRun(kDefaultSsrc,
|
||||||
|
steady_state_time * kFramerate,
|
||||||
|
kStartBitrate,
|
||||||
|
kMinExpectedBitrate,
|
||||||
|
kMaxExpectedBitrate,
|
||||||
|
kInitialCapacityBps);
|
||||||
|
EXPECT_EQ(expected_converge_bitrate, bitrate_bps);
|
||||||
|
bitrate_observer_->Reset();
|
||||||
|
|
||||||
|
// Reduce the capacity and verify the decrease time.
|
||||||
|
stream_generator_->set_capacity_bps(kReducedCapacityBps);
|
||||||
|
int64_t overuse_start_time = clock_.TimeInMilliseconds();
|
||||||
|
EXPECT_EQ(expected_overuse_start_time, overuse_start_time);
|
||||||
|
int64_t bitrate_drop_time = -1;
|
||||||
|
for (int i = 0; i < 100 * number_of_streams; ++i) {
|
||||||
|
GenerateAndProcessFrame(kDefaultSsrc, bitrate_bps);
|
||||||
|
// Check for either increase or decrease.
|
||||||
|
if (bitrate_observer_->updated()) {
|
||||||
|
if (bitrate_drop_time == -1 &&
|
||||||
|
bitrate_observer_->latest_bitrate() <= kReducedCapacityBps) {
|
||||||
|
bitrate_drop_time = clock_.TimeInMilliseconds();
|
||||||
|
}
|
||||||
|
bitrate_bps = bitrate_observer_->latest_bitrate();
|
||||||
|
bitrate_observer_->Reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_EQ(expected_bitrate_drop_delta,
|
||||||
|
bitrate_drop_time - overuse_start_time);
|
||||||
|
}
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -23,17 +23,15 @@
|
|||||||
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
enum { kMtu = 1200 };
|
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
|
|
||||||
class TestBitrateObserver : public RemoteBitrateObserver {
|
class TestBitrateObserver : public RemoteBitrateObserver {
|
||||||
public:
|
public:
|
||||||
TestBitrateObserver() : updated_(false), latest_bitrate_(0) {}
|
TestBitrateObserver() : updated_(false), latest_bitrate_(0) {}
|
||||||
|
virtual ~TestBitrateObserver() {}
|
||||||
|
|
||||||
void OnReceiveBitrateChanged(std::vector<unsigned int>* ssrcs,
|
virtual void OnReceiveBitrateChanged(const std::vector<unsigned int>& ssrcs,
|
||||||
unsigned int bitrate) {
|
unsigned int bitrate) {
|
||||||
latest_bitrate_ = bitrate;
|
latest_bitrate_ = bitrate;
|
||||||
updated_ = true;
|
updated_ = true;
|
||||||
}
|
}
|
||||||
@ -55,7 +53,6 @@ class TestBitrateObserver : public RemoteBitrateObserver {
|
|||||||
unsigned int latest_bitrate_;
|
unsigned int latest_bitrate_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class RtpStream {
|
class RtpStream {
|
||||||
public:
|
public:
|
||||||
struct RtpPacket {
|
struct RtpPacket {
|
||||||
@ -132,7 +129,7 @@ class StreamGenerator {
|
|||||||
|
|
||||||
// Divides |bitrate_bps| among all streams. The allocated bitrate per stream
|
// Divides |bitrate_bps| among all streams. The allocated bitrate per stream
|
||||||
// is decided by the initial allocation ratios.
|
// is decided by the initial allocation ratios.
|
||||||
void set_bitrate_bps(int bitrate_bps);
|
void SetBitrateBps(int bitrate_bps);
|
||||||
|
|
||||||
// Set the RTP timestamp offset for the stream identified by |ssrc|.
|
// Set the RTP timestamp offset for the stream identified by |ssrc|.
|
||||||
void set_rtp_timestamp_offset(unsigned int ssrc, uint32_t offset);
|
void set_rtp_timestamp_offset(unsigned int ssrc, uint32_t offset);
|
||||||
@ -160,13 +157,30 @@ class StreamGenerator {
|
|||||||
class RemoteBitrateEstimatorTest : public ::testing::Test {
|
class RemoteBitrateEstimatorTest : public ::testing::Test {
|
||||||
public:
|
public:
|
||||||
RemoteBitrateEstimatorTest();
|
RemoteBitrateEstimatorTest();
|
||||||
explicit RemoteBitrateEstimatorTest(bool align_streams);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void SetUp();
|
virtual void SetUp() = 0;
|
||||||
|
|
||||||
void AddDefaultStream();
|
void AddDefaultStream();
|
||||||
|
|
||||||
|
// Helper to convert some time format to resolution used in absolute send time
|
||||||
|
// header extension, rounded upwards. |t| is the time to convert, in some
|
||||||
|
// resolution. |denom| is the value to divide |t| by to get whole seconds,
|
||||||
|
// e.g. |denom| = 1000 if |t| is in milliseconds.
|
||||||
|
static uint32_t AbsSendTime(int64_t t, int64_t denom);
|
||||||
|
|
||||||
|
// Helper to add two absolute send time values and keep it less than 1<<24.
|
||||||
|
static uint32_t AddAbsSendTime(uint32_t t1, uint32_t t2);
|
||||||
|
|
||||||
|
// Helper to create a WebRtcRTPHeader containing the relevant data for the
|
||||||
|
// estimator (all other fields are cleared) and call IncomingPacket on the
|
||||||
|
// estimator.
|
||||||
|
void IncomingPacket(uint32_t ssrc,
|
||||||
|
uint32_t payload_size,
|
||||||
|
int64_t arrival_time,
|
||||||
|
uint32_t rtp_timestamp,
|
||||||
|
uint32_t absolute_send_time);
|
||||||
|
|
||||||
// Generates a frame of packets belonging to a stream at a given bitrate and
|
// Generates a frame of packets belonging to a stream at a given bitrate and
|
||||||
// with a given ssrc. The stream is pushed through a very simple simulated
|
// with a given ssrc. The stream is pushed through a very simple simulated
|
||||||
// network, and is then given to the receive-side bandwidth estimator.
|
// network, and is then given to the receive-side bandwidth estimator.
|
||||||
@ -186,25 +200,24 @@ class RemoteBitrateEstimatorTest : public ::testing::Test {
|
|||||||
unsigned int max_bitrate,
|
unsigned int max_bitrate,
|
||||||
unsigned int target_bitrate);
|
unsigned int target_bitrate);
|
||||||
|
|
||||||
|
void InitialBehaviorTestHelper(unsigned int expected_converge_bitrate);
|
||||||
|
void RateIncreaseReorderingTestHelper();
|
||||||
|
void RateIncreaseRtpTimestampsTestHelper();
|
||||||
|
void CapacityDropTestHelper(int number_of_streams,
|
||||||
|
bool wrap_time_stamp,
|
||||||
|
unsigned int expected_converge_bitrate,
|
||||||
|
unsigned int expected_bitrate_drop_delta);
|
||||||
|
|
||||||
static const unsigned int kDefaultSsrc;
|
static const unsigned int kDefaultSsrc;
|
||||||
|
|
||||||
SimulatedClock clock_; // Time at the receiver.
|
SimulatedClock clock_; // Time at the receiver.
|
||||||
OverUseDetectorOptions overuse_detector_options_;
|
bool align_streams_;
|
||||||
scoped_ptr<RemoteBitrateEstimator> bitrate_estimator_;
|
|
||||||
scoped_ptr<testing::TestBitrateObserver> bitrate_observer_;
|
scoped_ptr<testing::TestBitrateObserver> bitrate_observer_;
|
||||||
|
scoped_ptr<RemoteBitrateEstimator> bitrate_estimator_;
|
||||||
scoped_ptr<testing::StreamGenerator> stream_generator_;
|
scoped_ptr<testing::StreamGenerator> stream_generator_;
|
||||||
const bool align_streams_;
|
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(RemoteBitrateEstimatorTest);
|
DISALLOW_COPY_AND_ASSIGN(RemoteBitrateEstimatorTest);
|
||||||
};
|
};
|
||||||
|
} // namespace webrtc
|
||||||
class RemoteBitrateEstimatorTestAlign : public RemoteBitrateEstimatorTest {
|
|
||||||
public:
|
|
||||||
RemoteBitrateEstimatorTestAlign() : RemoteBitrateEstimatorTest(true) {}
|
|
||||||
|
|
||||||
private:
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(RemoteBitrateEstimatorTestAlign);
|
|
||||||
};
|
|
||||||
} // namespace testing
|
|
||||||
|
|
||||||
#endif // WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_REMOTE_BITRATE_ESTIMATOR_UNITTEST_HELPER_H_
|
#endif // WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_REMOTE_BITRATE_ESTIMATOR_UNITTEST_HELPER_H_
|
||||||
|
@ -268,12 +268,12 @@ double RemoteRateControl::RateIncreaseFactor(int64_t now_ms,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RemoteRateControl::UpdateChangePeriod(int64_t now_ms) {
|
void RemoteRateControl::UpdateChangePeriod(int64_t now_ms) {
|
||||||
int64_t changePeriod = 0;
|
int64_t change_period = 0;
|
||||||
if (last_change_ms_ > -1) {
|
if (last_change_ms_ > -1) {
|
||||||
changePeriod = now_ms - last_change_ms_;
|
change_period = now_ms - last_change_ms_;
|
||||||
}
|
}
|
||||||
last_change_ms_ = now_ms;
|
last_change_ms_ = now_ms;
|
||||||
avg_change_period_ = 0.9f * avg_change_period_ + 0.1f * changePeriod;
|
avg_change_period_ = 0.9f * avg_change_period_ + 0.1f * change_period;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteRateControl::UpdateMaxBitRateEstimate(float incoming_bit_rate_kbps) {
|
void RemoteRateControl::UpdateMaxBitRateEstimate(float incoming_bit_rate_kbps) {
|
||||||
@ -288,8 +288,8 @@ void RemoteRateControl::UpdateMaxBitRateEstimate(float incoming_bit_rate_kbps) {
|
|||||||
// with the average max bit rate.
|
// with the average max bit rate.
|
||||||
const float norm = std::max(avg_max_bit_rate_, 1.0f);
|
const float norm = std::max(avg_max_bit_rate_, 1.0f);
|
||||||
var_max_bit_rate_ = (1 - alpha) * var_max_bit_rate_ +
|
var_max_bit_rate_ = (1 - alpha) * var_max_bit_rate_ +
|
||||||
alpha * (avg_max_bit_rate_ - incoming_bit_rate_kbps) *
|
alpha * (avg_max_bit_rate_ - incoming_bit_rate_kbps) *
|
||||||
(avg_max_bit_rate_ - incoming_bit_rate_kbps) / norm;
|
(avg_max_bit_rate_ - incoming_bit_rate_kbps) / norm;
|
||||||
// 0.4 ~= 14 kbit/s at 500 kbit/s
|
// 0.4 ~= 14 kbit/s at 500 kbit/s
|
||||||
if (var_max_bit_rate_ < 0.4f) {
|
if (var_max_bit_rate_ < 0.4f) {
|
||||||
var_max_bit_rate_ = 0.4f;
|
var_max_bit_rate_ = 0.4f;
|
||||||
@ -347,7 +347,7 @@ void RemoteRateControl::ChangeState(RateControlState new_state) {
|
|||||||
StateStr(rate_control_state_, state2);
|
StateStr(rate_control_state_, state2);
|
||||||
StateStr(current_input_._bwState, state3);
|
StateStr(current_input_._bwState, state3);
|
||||||
WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1,
|
WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1,
|
||||||
"\t%s => %s due to %s\n", state1, state2, state3);
|
"\t%s => %s due to %s\n", state1, state2, state3);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteRateControl::StateStr(RateControlState state, char* str) {
|
void RemoteRateControl::StateStr(RateControlState state, char* str) {
|
||||||
|
@ -115,11 +115,8 @@ int32_t ViEReceiver::OnReceivedPayloadData(
|
|||||||
// TODO(holmer): Make sure packets reconstructed using FEC are not passed to
|
// TODO(holmer): Make sure packets reconstructed using FEC are not passed to
|
||||||
// the bandwidth estimator.
|
// the bandwidth estimator.
|
||||||
const int packet_size = payload_size + rtp_header->header.paddingLength;
|
const int packet_size = payload_size + rtp_header->header.paddingLength;
|
||||||
uint32_t compensated_timestamp = rtp_header->header.timestamp +
|
remote_bitrate_estimator_->IncomingPacket(TickTime::MillisecondTimestamp(),
|
||||||
rtp_header->extension.transmissionTimeOffset;
|
packet_size, *rtp_header);
|
||||||
remote_bitrate_estimator_->IncomingPacket(
|
|
||||||
rtp_header->header.ssrc, packet_size,
|
|
||||||
TickTime::MillisecondTimestamp(), compensated_timestamp);
|
|
||||||
if (vcm_->IncomingPacket(payload_data, payload_size, *rtp_header) != 0) {
|
if (vcm_->IncomingPacket(payload_data, payload_size, *rtp_header) != 0) {
|
||||||
// Check this...
|
// Check this...
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -104,11 +104,10 @@ bool VieRemb::InUse() const {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VieRemb::OnReceiveBitrateChanged(std::vector<unsigned int>* ssrcs,
|
void VieRemb::OnReceiveBitrateChanged(const std::vector<unsigned int>& ssrcs,
|
||||||
unsigned int bitrate) {
|
unsigned int bitrate) {
|
||||||
WEBRTC_TRACE(kTraceStream, kTraceVideo, -1,
|
WEBRTC_TRACE(kTraceStream, kTraceVideo, -1,
|
||||||
"VieRemb::UpdateBitrateEstimate(bitrate: %u)", bitrate);
|
"VieRemb::UpdateBitrateEstimate(bitrate: %u)", bitrate);
|
||||||
assert(ssrcs);
|
|
||||||
list_crit_->Enter();
|
list_crit_->Enter();
|
||||||
// If we already have an estimate, check if the new total estimate is below
|
// If we already have an estimate, check if the new total estimate is below
|
||||||
// kSendThresholdPercent of the previous estimate.
|
// kSendThresholdPercent of the previous estimate.
|
||||||
@ -132,7 +131,7 @@ void VieRemb::OnReceiveBitrateChanged(std::vector<unsigned int>* ssrcs,
|
|||||||
}
|
}
|
||||||
last_remb_time_ = now;
|
last_remb_time_ = now;
|
||||||
|
|
||||||
if (ssrcs->empty() || receive_modules_.empty()) {
|
if (ssrcs.empty() || receive_modules_.empty()) {
|
||||||
list_crit_->Leave();
|
list_crit_->Leave();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -154,8 +153,8 @@ void VieRemb::OnReceiveBitrateChanged(std::vector<unsigned int>* ssrcs,
|
|||||||
list_crit_->Leave();
|
list_crit_->Leave();
|
||||||
|
|
||||||
if (sender) {
|
if (sender) {
|
||||||
// TODO(holmer): Change RTP module API to take a vector pointer.
|
// TODO(holmer): Change RTP module API to take a const vector reference.
|
||||||
sender->SetREMBData(bitrate_, ssrcs->size(), &(*ssrcs)[0]);
|
sender->SetREMBData(bitrate_, ssrcs.size(), &ssrcs[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ class VieRemb : public RemoteBitrateObserver {
|
|||||||
// estimate has decreased or if no RTCP REMB packet has been sent for
|
// estimate has decreased or if no RTCP REMB packet has been sent for
|
||||||
// a certain time interval.
|
// a certain time interval.
|
||||||
// Implements RtpReceiveBitrateUpdate.
|
// Implements RtpReceiveBitrateUpdate.
|
||||||
virtual void OnReceiveBitrateChanged(std::vector<unsigned int>* ssrcs,
|
virtual void OnReceiveBitrateChanged(const std::vector<unsigned int>& ssrcs,
|
||||||
unsigned int bitrate);
|
unsigned int bitrate);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -59,17 +59,17 @@ TEST_F(ViERembTest, OneModuleTestForSendingRemb) {
|
|||||||
unsigned int ssrc = 1234;
|
unsigned int ssrc = 1234;
|
||||||
std::vector<unsigned int> ssrcs(&ssrc, &ssrc + 1);
|
std::vector<unsigned int> ssrcs(&ssrc, &ssrc + 1);
|
||||||
|
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
|
||||||
|
|
||||||
TickTime::AdvanceFakeClock(1000);
|
TickTime::AdvanceFakeClock(1000);
|
||||||
EXPECT_CALL(rtp, SetREMBData(bitrate_estimate, 1, _))
|
EXPECT_CALL(rtp, SetREMBData(bitrate_estimate, 1, _))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
|
||||||
|
|
||||||
// Lower bitrate to send another REMB packet.
|
// Lower bitrate to send another REMB packet.
|
||||||
EXPECT_CALL(rtp, SetREMBData(bitrate_estimate - 100, 1, _))
|
EXPECT_CALL(rtp, SetREMBData(bitrate_estimate - 100, 1, _))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate - 100);
|
vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate - 100);
|
||||||
|
|
||||||
vie_remb_->RemoveReceiveChannel(&rtp);
|
vie_remb_->RemoveReceiveChannel(&rtp);
|
||||||
vie_remb_->RemoveRembSender(&rtp);
|
vie_remb_->RemoveRembSender(&rtp);
|
||||||
@ -84,19 +84,19 @@ TEST_F(ViERembTest, LowerEstimateToSendRemb) {
|
|||||||
unsigned int ssrc = 1234;
|
unsigned int ssrc = 1234;
|
||||||
std::vector<unsigned int> ssrcs(&ssrc, &ssrc + 1);
|
std::vector<unsigned int> ssrcs(&ssrc, &ssrc + 1);
|
||||||
|
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
|
||||||
// Call OnReceiveBitrateChanged twice to get a first estimate.
|
// Call OnReceiveBitrateChanged twice to get a first estimate.
|
||||||
TickTime::AdvanceFakeClock(1000);
|
TickTime::AdvanceFakeClock(1000);
|
||||||
EXPECT_CALL(rtp, SetREMBData(bitrate_estimate, 1, _))
|
EXPECT_CALL(rtp, SetREMBData(bitrate_estimate, 1, _))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
|
||||||
|
|
||||||
// Lower the estimate with more than 3% to trigger a call to SetREMBData right
|
// Lower the estimate with more than 3% to trigger a call to SetREMBData right
|
||||||
// away.
|
// away.
|
||||||
bitrate_estimate = bitrate_estimate - 100;
|
bitrate_estimate = bitrate_estimate - 100;
|
||||||
EXPECT_CALL(rtp, SetREMBData(bitrate_estimate, 1, _))
|
EXPECT_CALL(rtp, SetREMBData(bitrate_estimate, 1, _))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ViERembTest, VerifyIncreasingAndDecreasing) {
|
TEST_F(ViERembTest, VerifyIncreasingAndDecreasing) {
|
||||||
@ -110,20 +110,20 @@ TEST_F(ViERembTest, VerifyIncreasingAndDecreasing) {
|
|||||||
unsigned int ssrc[] = { 1234, 5678 };
|
unsigned int ssrc[] = { 1234, 5678 };
|
||||||
std::vector<unsigned int> ssrcs(ssrc, ssrc + sizeof(ssrc) / sizeof(ssrc[0]));
|
std::vector<unsigned int> ssrcs(ssrc, ssrc + sizeof(ssrc) / sizeof(ssrc[0]));
|
||||||
|
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate[0]);
|
vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate[0]);
|
||||||
|
|
||||||
// Call OnReceiveBitrateChanged twice to get a first estimate.
|
// Call OnReceiveBitrateChanged twice to get a first estimate.
|
||||||
EXPECT_CALL(rtp_0, SetREMBData(bitrate_estimate[0], 2, _))
|
EXPECT_CALL(rtp_0, SetREMBData(bitrate_estimate[0], 2, _))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
TickTime::AdvanceFakeClock(1000);
|
TickTime::AdvanceFakeClock(1000);
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate[0]);
|
vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate[0]);
|
||||||
|
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate[1] + 100);
|
vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate[1] + 100);
|
||||||
|
|
||||||
// Lower the estimate to trigger a callback.
|
// Lower the estimate to trigger a callback.
|
||||||
EXPECT_CALL(rtp_0, SetREMBData(bitrate_estimate[1], 2, _))
|
EXPECT_CALL(rtp_0, SetREMBData(bitrate_estimate[1], 2, _))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate[1]);
|
vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate[1]);
|
||||||
|
|
||||||
vie_remb_->RemoveReceiveChannel(&rtp_0);
|
vie_remb_->RemoveReceiveChannel(&rtp_0);
|
||||||
vie_remb_->RemoveRembSender(&rtp_0);
|
vie_remb_->RemoveRembSender(&rtp_0);
|
||||||
@ -141,23 +141,23 @@ TEST_F(ViERembTest, NoRembForIncreasedBitrate) {
|
|||||||
unsigned int ssrc[] = { 1234, 5678 };
|
unsigned int ssrc[] = { 1234, 5678 };
|
||||||
std::vector<unsigned int> ssrcs(ssrc, ssrc + sizeof(ssrc) / sizeof(ssrc[0]));
|
std::vector<unsigned int> ssrcs(ssrc, ssrc + sizeof(ssrc) / sizeof(ssrc[0]));
|
||||||
|
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
|
||||||
// Call OnReceiveBitrateChanged twice to get a first estimate.
|
// Call OnReceiveBitrateChanged twice to get a first estimate.
|
||||||
TickTime::AdvanceFakeClock(1000);
|
TickTime::AdvanceFakeClock(1000);
|
||||||
EXPECT_CALL(rtp_0, SetREMBData(bitrate_estimate, 2, _))
|
EXPECT_CALL(rtp_0, SetREMBData(bitrate_estimate, 2, _))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
|
||||||
|
|
||||||
// Increased estimate shouldn't trigger a callback right away.
|
// Increased estimate shouldn't trigger a callback right away.
|
||||||
EXPECT_CALL(rtp_0, SetREMBData(_, _, _))
|
EXPECT_CALL(rtp_0, SetREMBData(_, _, _))
|
||||||
.Times(0);
|
.Times(0);
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate + 1);
|
vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate + 1);
|
||||||
|
|
||||||
// Decreasing the estimate less than 3% shouldn't trigger a new callback.
|
// Decreasing the estimate less than 3% shouldn't trigger a new callback.
|
||||||
EXPECT_CALL(rtp_0, SetREMBData(_, _, _))
|
EXPECT_CALL(rtp_0, SetREMBData(_, _, _))
|
||||||
.Times(0);
|
.Times(0);
|
||||||
int lower_estimate = bitrate_estimate * 98 / 100;
|
int lower_estimate = bitrate_estimate * 98 / 100;
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, lower_estimate);
|
vie_remb_->OnReceiveBitrateChanged(ssrcs, lower_estimate);
|
||||||
|
|
||||||
vie_remb_->RemoveReceiveChannel(&rtp_1);
|
vie_remb_->RemoveReceiveChannel(&rtp_1);
|
||||||
vie_remb_->RemoveReceiveChannel(&rtp_0);
|
vie_remb_->RemoveReceiveChannel(&rtp_0);
|
||||||
@ -175,29 +175,29 @@ TEST_F(ViERembTest, ChangeSendRtpModule) {
|
|||||||
unsigned int ssrc[] = { 1234, 5678 };
|
unsigned int ssrc[] = { 1234, 5678 };
|
||||||
std::vector<unsigned int> ssrcs(ssrc, ssrc + sizeof(ssrc) / sizeof(ssrc[0]));
|
std::vector<unsigned int> ssrcs(ssrc, ssrc + sizeof(ssrc) / sizeof(ssrc[0]));
|
||||||
|
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
|
||||||
// Call OnReceiveBitrateChanged twice to get a first estimate.
|
// Call OnReceiveBitrateChanged twice to get a first estimate.
|
||||||
TickTime::AdvanceFakeClock(1000);
|
TickTime::AdvanceFakeClock(1000);
|
||||||
EXPECT_CALL(rtp_0, SetREMBData(bitrate_estimate, 2, _))
|
EXPECT_CALL(rtp_0, SetREMBData(bitrate_estimate, 2, _))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
|
||||||
|
|
||||||
// Decrease estimate to trigger a REMB.
|
// Decrease estimate to trigger a REMB.
|
||||||
bitrate_estimate = bitrate_estimate - 100;
|
bitrate_estimate = bitrate_estimate - 100;
|
||||||
EXPECT_CALL(rtp_0, SetREMBData(bitrate_estimate, 2, _))
|
EXPECT_CALL(rtp_0, SetREMBData(bitrate_estimate, 2, _))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
|
||||||
|
|
||||||
// Remove the sending module, add it again -> should get remb on the second
|
// Remove the sending module, add it again -> should get remb on the second
|
||||||
// module.
|
// module.
|
||||||
vie_remb_->RemoveRembSender(&rtp_0);
|
vie_remb_->RemoveRembSender(&rtp_0);
|
||||||
vie_remb_->AddRembSender(&rtp_1);
|
vie_remb_->AddRembSender(&rtp_1);
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
|
||||||
|
|
||||||
bitrate_estimate = bitrate_estimate - 100;
|
bitrate_estimate = bitrate_estimate - 100;
|
||||||
EXPECT_CALL(rtp_1, SetREMBData(bitrate_estimate, 2, _))
|
EXPECT_CALL(rtp_1, SetREMBData(bitrate_estimate, 2, _))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
|
||||||
|
|
||||||
vie_remb_->RemoveReceiveChannel(&rtp_0);
|
vie_remb_->RemoveReceiveChannel(&rtp_0);
|
||||||
vie_remb_->RemoveReceiveChannel(&rtp_1);
|
vie_remb_->RemoveReceiveChannel(&rtp_1);
|
||||||
@ -211,23 +211,23 @@ TEST_F(ViERembTest, OnlyOneRembForDoubleProcess) {
|
|||||||
|
|
||||||
vie_remb_->AddReceiveChannel(&rtp);
|
vie_remb_->AddReceiveChannel(&rtp);
|
||||||
vie_remb_->AddRembSender(&rtp);
|
vie_remb_->AddRembSender(&rtp);
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
|
||||||
// Call OnReceiveBitrateChanged twice to get a first estimate.
|
// Call OnReceiveBitrateChanged twice to get a first estimate.
|
||||||
TickTime::AdvanceFakeClock(1000);
|
TickTime::AdvanceFakeClock(1000);
|
||||||
EXPECT_CALL(rtp, SetREMBData(_, _, _))
|
EXPECT_CALL(rtp, SetREMBData(_, _, _))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
|
||||||
|
|
||||||
// Lower the estimate, should trigger a call to SetREMBData right away.
|
// Lower the estimate, should trigger a call to SetREMBData right away.
|
||||||
bitrate_estimate = bitrate_estimate - 100;
|
bitrate_estimate = bitrate_estimate - 100;
|
||||||
EXPECT_CALL(rtp, SetREMBData(bitrate_estimate, 1, _))
|
EXPECT_CALL(rtp, SetREMBData(bitrate_estimate, 1, _))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
|
||||||
|
|
||||||
// Call OnReceiveBitrateChanged again, this should not trigger a new callback.
|
// Call OnReceiveBitrateChanged again, this should not trigger a new callback.
|
||||||
EXPECT_CALL(rtp, SetREMBData(_, _, _))
|
EXPECT_CALL(rtp, SetREMBData(_, _, _))
|
||||||
.Times(0);
|
.Times(0);
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
|
||||||
vie_remb_->RemoveReceiveChannel(&rtp);
|
vie_remb_->RemoveReceiveChannel(&rtp);
|
||||||
vie_remb_->RemoveRembSender(&rtp);
|
vie_remb_->RemoveRembSender(&rtp);
|
||||||
}
|
}
|
||||||
@ -242,19 +242,19 @@ TEST_F(ViERembTest, NoSendingRtpModule) {
|
|||||||
unsigned int ssrc = 1234;
|
unsigned int ssrc = 1234;
|
||||||
std::vector<unsigned int> ssrcs(&ssrc, &ssrc + 1);
|
std::vector<unsigned int> ssrcs(&ssrc, &ssrc + 1);
|
||||||
|
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
|
||||||
|
|
||||||
// Call OnReceiveBitrateChanged twice to get a first estimate.
|
// Call OnReceiveBitrateChanged twice to get a first estimate.
|
||||||
TickTime::AdvanceFakeClock(1000);
|
TickTime::AdvanceFakeClock(1000);
|
||||||
EXPECT_CALL(rtp, SetREMBData(_, _, _))
|
EXPECT_CALL(rtp, SetREMBData(_, _, _))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
|
||||||
|
|
||||||
// Lower the estimate to trigger a new packet REMB packet.
|
// Lower the estimate to trigger a new packet REMB packet.
|
||||||
bitrate_estimate = bitrate_estimate - 100;
|
bitrate_estimate = bitrate_estimate - 100;
|
||||||
EXPECT_CALL(rtp, SetREMBData(_, _, _))
|
EXPECT_CALL(rtp, SetREMBData(_, _, _))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
Loading…
x
Reference in New Issue
Block a user