blob: 3c1a914d284390774df88e46d0cd0ba03037316f [file] [log] [blame]
/*
* 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 "webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_unittest_helper.h"
#include <algorithm>
#include <limits>
#include <utility>
#include "webrtc/base/checks.h"
namespace webrtc {
const size_t kMtu = 1200;
const uint32_t kAcceptedBitrateErrorBps = 50000;
// Number of packets needed before we have a valid estimate.
const int kNumInitialPackets = 2;
namespace testing {
void TestBitrateObserver::OnReceiveBitrateChanged(
const std::vector<uint32_t>& ssrcs,
uint32_t bitrate) {
latest_bitrate_ = bitrate;
updated_ = true;
}
RtpStream::RtpStream(int fps,
int bitrate_bps,
uint32_t ssrc,
uint32_t frequency,
uint32_t timestamp_offset,
int64_t rtcp_receive_time)
: fps_(fps),
bitrate_bps_(bitrate_bps),
ssrc_(ssrc),
frequency_(frequency),
next_rtp_time_(0),
next_rtcp_time_(rtcp_receive_time),
rtp_timestamp_offset_(timestamp_offset),
kNtpFracPerMs(4.294967296E6) {
assert(fps_ > 0);
}
void RtpStream::set_rtp_timestamp_offset(uint32_t offset) {
rtp_timestamp_offset_ = offset;
}
// Generates a new frame for this stream. If called too soon after the
// previous frame, no frame will be generated. The frame is split into
// packets.
int64_t RtpStream::GenerateFrame(int64_t time_now_us, PacketList* packets) {
if (time_now_us < next_rtp_time_) {
return next_rtp_time_;
}
assert(packets != NULL);
size_t bits_per_frame = (bitrate_bps_ + fps_ / 2) / fps_;
size_t n_packets =
std::max<size_t>((bits_per_frame + 4 * kMtu) / (8 * kMtu), 1u);
size_t packet_size = (bits_per_frame + 4 * n_packets) / (8 * n_packets);
for (size_t i = 0; i < n_packets; ++i) {
RtpPacket* packet = new RtpPacket;
packet->send_time = time_now_us + kSendSideOffsetUs;
packet->size = packet_size;
packet->rtp_timestamp = rtp_timestamp_offset_ + static_cast<uint32_t>(
((frequency_ / 1000) * packet->send_time + 500) / 1000);
packet->ssrc = ssrc_;
packets->push_back(packet);
}
next_rtp_time_ = time_now_us + (1000000 + fps_ / 2) / fps_;
return next_rtp_time_;
}
// The send-side time when the next frame can be generated.
int64_t RtpStream::next_rtp_time() const {
return next_rtp_time_;
}
// Generates an RTCP packet.
RtpStream::RtcpPacket* RtpStream::Rtcp(int64_t time_now_us) {
if (time_now_us < next_rtcp_time_) {
return NULL;
}
RtcpPacket* rtcp = new RtcpPacket;
int64_t send_time_us = time_now_us + kSendSideOffsetUs;
rtcp->timestamp = rtp_timestamp_offset_ + static_cast<uint32_t>(
((frequency_ / 1000) * send_time_us + 500) / 1000);
rtcp->ntp_secs = send_time_us / 1000000;
rtcp->ntp_frac = static_cast<int64_t>((send_time_us % 1000000) *
kNtpFracPerMs);
rtcp->ssrc = ssrc_;
next_rtcp_time_ = time_now_us + kRtcpIntervalUs;
return rtcp;
}
void RtpStream::set_bitrate_bps(int bitrate_bps) {
ASSERT_GE(bitrate_bps, 0);
bitrate_bps_ = bitrate_bps;
}
int RtpStream::bitrate_bps() const {
return bitrate_bps_;
}
uint32_t RtpStream::ssrc() const {
return ssrc_;
}
bool RtpStream::Compare(const std::pair<uint32_t, RtpStream*>& left,
const std::pair<uint32_t, RtpStream*>& right) {
return left.second->next_rtp_time_ < right.second->next_rtp_time_;
}
StreamGenerator::StreamGenerator(int capacity, int64_t time_now)
: capacity_(capacity),
prev_arrival_time_us_(time_now) {}
StreamGenerator::~StreamGenerator() {
for (StreamMap::iterator it = streams_.begin(); it != streams_.end();
++it) {
delete it->second;
}
streams_.clear();
}
// Add a new stream.
void StreamGenerator::AddStream(RtpStream* stream) {
streams_[stream->ssrc()] = stream;
}
// Set the link capacity.
void StreamGenerator::set_capacity_bps(int capacity_bps) {
ASSERT_GT(capacity_bps, 0);
capacity_ = capacity_bps;
}
// Divides |bitrate_bps| among all streams. The allocated bitrate per stream
// is decided by the current allocation ratios.
void StreamGenerator::SetBitrateBps(int bitrate_bps) {
ASSERT_GE(streams_.size(), 0u);
int total_bitrate_before = 0;
for (StreamMap::iterator it = streams_.begin(); it != streams_.end(); ++it) {
total_bitrate_before += it->second->bitrate_bps();
}
int64_t bitrate_before = 0;
int total_bitrate_after = 0;
for (StreamMap::iterator it = streams_.begin(); it != streams_.end(); ++it) {
bitrate_before += it->second->bitrate_bps();
int64_t bitrate_after = (bitrate_before * bitrate_bps +
total_bitrate_before / 2) / total_bitrate_before;
it->second->set_bitrate_bps(bitrate_after - total_bitrate_after);
total_bitrate_after += it->second->bitrate_bps();
}
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|.
void StreamGenerator::set_rtp_timestamp_offset(uint32_t ssrc, uint32_t offset) {
streams_[ssrc]->set_rtp_timestamp_offset(offset);
}
// TODO(holmer): Break out the channel simulation part from this class to make
// it possible to simulate different types of channels.
int64_t StreamGenerator::GenerateFrame(RtpStream::PacketList* packets,
int64_t time_now_us) {
assert(packets != NULL);
assert(packets->empty());
assert(capacity_ > 0);
StreamMap::iterator it = std::min_element(streams_.begin(), streams_.end(),
RtpStream::Compare);
(*it).second->GenerateFrame(time_now_us, packets);
int i = 0;
for (RtpStream::PacketList::iterator packet_it = packets->begin();
packet_it != packets->end(); ++packet_it) {
int capacity_bpus = capacity_ / 1000;
int64_t required_network_time_us =
(8 * 1000 * (*packet_it)->size + capacity_bpus / 2) / capacity_bpus;
prev_arrival_time_us_ = std::max(time_now_us + required_network_time_us,
prev_arrival_time_us_ + required_network_time_us);
(*packet_it)->arrival_time = prev_arrival_time_us_;
++i;
}
it = std::min_element(streams_.begin(), streams_.end(), RtpStream::Compare);
return std::max((*it).second->next_rtp_time(), time_now_us);
}
} // namespace testing
RemoteBitrateEstimatorTest::RemoteBitrateEstimatorTest()
: clock_(100000000),
bitrate_observer_(new testing::TestBitrateObserver),
stream_generator_(new testing::StreamGenerator(
1e6, // Capacity.
clock_.TimeInMicroseconds())),
arrival_time_offset_ms_(0) {}
RemoteBitrateEstimatorTest::~RemoteBitrateEstimatorTest() {}
void RemoteBitrateEstimatorTest::AddDefaultStream() {
stream_generator_->AddStream(new testing::RtpStream(
30, // Frames per second.
3e5, // Bitrate.
1, // SSRC.
90000, // RTP frequency.
0xFFFFF000, // Timestamp offset.
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 uint32_t RemoteBitrateEstimatorTest::kDefaultSsrc = 1;
void RemoteBitrateEstimatorTest::IncomingPacket(uint32_t ssrc,
size_t payload_size,
int64_t arrival_time,
uint32_t rtp_timestamp,
uint32_t absolute_send_time) {
RTPHeader header;
memset(&header, 0, sizeof(header));
header.ssrc = ssrc;
header.timestamp = rtp_timestamp;
header.extension.hasAbsoluteSendTime = true;
header.extension.absoluteSendTime = absolute_send_time;
RTC_CHECK_GE(arrival_time + arrival_time_offset_ms_, 0);
bitrate_estimator_->IncomingPacket(arrival_time + arrival_time_offset_ms_,
payload_size, header);
}
// 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
// network, and is then given to the receive-side bandwidth estimator.
// Returns true if an over-use was seen, false otherwise.
// The StreamGenerator::updated() should be used to check for any changes in
// target bitrate after the call to this function.
bool RemoteBitrateEstimatorTest::GenerateAndProcessFrame(uint32_t ssrc,
uint32_t bitrate_bps) {
RTC_DCHECK_GT(bitrate_bps, 0u);
stream_generator_->SetBitrateBps(bitrate_bps);
testing::RtpStream::PacketList packets;
int64_t next_time_us = stream_generator_->GenerateFrame(
&packets, clock_.TimeInMicroseconds());
bool overuse = false;
while (!packets.empty()) {
testing::RtpStream::RtpPacket* packet = packets.front();
bitrate_observer_->Reset();
// The simulated clock should match the time of packet->arrival_time
// since both are used in IncomingPacket().
clock_.AdvanceTimeMicroseconds(packet->arrival_time -
clock_.TimeInMicroseconds());
IncomingPacket(packet->ssrc, packet->size,
(packet->arrival_time + 500) / 1000, packet->rtp_timestamp,
AbsSendTime(packet->send_time, 1000000));
if (bitrate_observer_->updated()) {
if (bitrate_observer_->latest_bitrate() < bitrate_bps)
overuse = true;
}
delete packet;
packets.pop_front();
}
bitrate_estimator_->Process();
clock_.AdvanceTimeMicroseconds(next_time_us - clock_.TimeInMicroseconds());
return overuse;
}
// Run the bandwidth estimator with a stream of |number_of_frames| frames, or
// until it reaches |target_bitrate|.
// Can for instance be used to run the estimator for some time to get it
// into a steady state.
uint32_t RemoteBitrateEstimatorTest::SteadyStateRun(uint32_t ssrc,
int max_number_of_frames,
uint32_t start_bitrate,
uint32_t min_bitrate,
uint32_t max_bitrate,
uint32_t target_bitrate) {
uint32_t bitrate_bps = start_bitrate;
bool bitrate_update_seen = false;
// Produce |number_of_frames| frames and give them to the estimator.
for (int i = 0; i < max_number_of_frames; ++i) {
bool overuse = GenerateAndProcessFrame(ssrc, bitrate_bps);
if (overuse) {
EXPECT_LT(bitrate_observer_->latest_bitrate(), max_bitrate);
EXPECT_GT(bitrate_observer_->latest_bitrate(), min_bitrate);
bitrate_bps = bitrate_observer_->latest_bitrate();
bitrate_update_seen = true;
} else if (bitrate_observer_->updated()) {
bitrate_bps = bitrate_observer_->latest_bitrate();
bitrate_observer_->Reset();
}
if (bitrate_update_seen && bitrate_bps > target_bitrate) {
break;
}
}
EXPECT_TRUE(bitrate_update_seen);
return bitrate_bps;
}
void RemoteBitrateEstimatorTest::InitialBehaviorTestHelper(
uint32_t 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);
uint32_t bitrate_bps = 0;
uint32_t timestamp = 0;
uint32_t absolute_send_time = 0;
std::vector<uint32_t> 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 packets for 5 seconds to get a valid estimate.
for (int i = 0; i < 5 * kFramerate + 1 + kNumInitialPackets; ++i) {
if (i == kNumInitialPackets) {
bitrate_estimator_->Process();
EXPECT_FALSE(bitrate_estimator_->LatestEstimate(&ssrcs, &bitrate_bps));
EXPECT_EQ(0u, ssrcs.size());
EXPECT_FALSE(bitrate_observer_->updated());
bitrate_observer_->Reset();
}
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_NEAR(expected_converge_bitrate, bitrate_bps, kAcceptedBitrateErrorBps);
EXPECT_TRUE(bitrate_observer_->updated());
bitrate_observer_->Reset();
EXPECT_EQ(bitrate_observer_->latest_bitrate(), bitrate_bps);
bitrate_estimator_->RemoveStream(kDefaultSsrc);
EXPECT_TRUE(bitrate_estimator_->LatestEstimate(&ssrcs, &bitrate_bps));
ASSERT_EQ(0u, ssrcs.size());
EXPECT_EQ(0u, bitrate_bps);
}
void RemoteBitrateEstimatorTest::RateIncreaseReorderingTestHelper(
uint32_t expected_bitrate_bps) {
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;
// Inserting packets for five seconds to get a valid estimate.
for (int i = 0; i < 5 * kFramerate + 1 + kNumInitialPackets; ++i) {
// TODO(sprang): Remove this hack once the single stream estimator is gone,
// as it doesn't do anything in Process().
if (i == kNumInitialPackets) {
// Process after we have enough frames to get a valid input rate estimate.
bitrate_estimator_->Process();
EXPECT_FALSE(bitrate_observer_->updated()); // No valid estimate.
}
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_NEAR(expected_bitrate_bps,
bitrate_observer_->latest_bitrate(),
kAcceptedBitrateErrorBps);
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,
-static_cast<int>(kFrameIntervalAbsSendTime)));
}
bitrate_estimator_->Process();
EXPECT_TRUE(bitrate_observer_->updated());
EXPECT_NEAR(expected_bitrate_bps,
bitrate_observer_->latest_bitrate(),
kAcceptedBitrateErrorBps);
}
// Make sure we initially increase the bitrate as expected.
void RemoteBitrateEstimatorTest::RateIncreaseRtpTimestampsTestHelper(
int expected_iterations) {
// This threshold corresponds approximately to increasing linearly with
// bitrate(i) = 1.04 * bitrate(i-1) + 1000
// until bitrate(i) > 500000, with bitrate(1) ~= 30000.
uint32_t 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, expected_iterations);
}
ASSERT_EQ(expected_iterations, iterations);
}
void RemoteBitrateEstimatorTest::CapacityDropTestHelper(
int number_of_streams,
bool wrap_time_stamp,
uint32_t expected_bitrate_drop_delta,
int64_t receiver_clock_offset_change_ms) {
const int kFramerate = 30;
const int kStartBitrate = 900e3;
const int kMinExpectedBitrate = 800e3;
const int kMaxExpectedBitrate = 1100e3;
const uint32_t kInitialCapacityBps = 1000e3;
const uint32_t kReducedCapacityBps = 500e3;
int steady_state_time = 0;
if (number_of_streams <= 1) {
steady_state_time = 10;
AddDefaultStream();
} else {
steady_state_time = 10 * number_of_streams;
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;
}
uint32_t mask = ~0ull << (32 - i);
stream_generator_->AddStream(
new testing::RtpStream(kFramerate, // Frames per second.
bitrate, // Bitrate.
kDefaultSsrc + i, // SSRC.
90000, // RTP frequency.
0xFFFFF000u ^ mask, // 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);
uint32_t bitrate_bps = SteadyStateRun(
kDefaultSsrc, steady_state_time * kFramerate, kStartBitrate,
kMinExpectedBitrate, kMaxExpectedBitrate, kInitialCapacityBps);
EXPECT_NEAR(kInitialCapacityBps, bitrate_bps, 130000u);
bitrate_observer_->Reset();
// Add an offset to make sure the BWE can handle it.
arrival_time_offset_ms_ += receiver_clock_offset_change_ms;
// Reduce the capacity and verify the decrease time.
stream_generator_->set_capacity_bps(kReducedCapacityBps);
int64_t overuse_start_time = clock_.TimeInMilliseconds();
int64_t bitrate_drop_time = -1;
for (int i = 0; i < 100 * number_of_streams; ++i) {
GenerateAndProcessFrame(kDefaultSsrc, bitrate_bps);
if (bitrate_drop_time == -1 &&
bitrate_observer_->latest_bitrate() <= kReducedCapacityBps) {
bitrate_drop_time = clock_.TimeInMilliseconds();
}
if (bitrate_observer_->updated())
bitrate_bps = bitrate_observer_->latest_bitrate();
}
EXPECT_NEAR(expected_bitrate_drop_delta,
bitrate_drop_time - overuse_start_time, 33);
// Remove stream one by one.
uint32_t latest_bps = 0;
std::vector<uint32_t> ssrcs;
for (int i = 0; i < number_of_streams; i++) {
EXPECT_TRUE(bitrate_estimator_->LatestEstimate(&ssrcs, &latest_bps));
EXPECT_EQ(number_of_streams - i, static_cast<int>(ssrcs.size()));
EXPECT_EQ(bitrate_bps, latest_bps);
for (int j = i; j < number_of_streams; j++) {
EXPECT_EQ(kDefaultSsrc + j, ssrcs[j - i]);
}
bitrate_estimator_->RemoveStream(kDefaultSsrc + i);
}
EXPECT_TRUE(bitrate_estimator_->LatestEstimate(&ssrcs, &latest_bps));
EXPECT_EQ(0u, ssrcs.size());
EXPECT_EQ(0u, latest_bps);
}
void RemoteBitrateEstimatorTest::TestTimestampGroupingTestHelper() {
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;
// Initialize absolute_send_time (24 bits) so that it will definitely wrap
// during the test.
uint32_t absolute_send_time = AddAbsSendTime(
(1 << 24), -static_cast<int>(50 * kFrameIntervalAbsSendTime));
// Initial set of frames to increase the bitrate. 6 seconds to have enough
// time for the first estimate to be generated and for Process() to be called.
for (int i = 0; i <= 6 * kFramerate; ++i) {
IncomingPacket(kDefaultSsrc, 1000, clock_.TimeInMilliseconds(), timestamp,
absolute_send_time);
bitrate_estimator_->Process();
clock_.AdvanceTimeMilliseconds(kFrameIntervalMs);
timestamp += 90 * kFrameIntervalMs;
absolute_send_time = AddAbsSendTime(absolute_send_time,
kFrameIntervalAbsSendTime);
}
EXPECT_TRUE(bitrate_observer_->updated());
EXPECT_GE(bitrate_observer_->latest_bitrate(), 400000u);
// Insert batches of frames which were sent very close in time. Also simulate
// capacity over-use to see that we back off correctly.
const int kTimestampGroupLength = 15;
const uint32_t kTimestampGroupLengthAbsSendTime =
AbsSendTime(kTimestampGroupLength, 90000);
const uint32_t kSingleRtpTickAbsSendTime = AbsSendTime(1, 90000);
for (int i = 0; i < 100; ++i) {
for (int j = 0; j < kTimestampGroupLength; ++j) {
// Insert |kTimestampGroupLength| frames with just 1 timestamp ticks in
// between. Should be treated as part of the same group by the estimator.
IncomingPacket(kDefaultSsrc, 100, clock_.TimeInMilliseconds(), timestamp,
absolute_send_time);
clock_.AdvanceTimeMilliseconds(kFrameIntervalMs / kTimestampGroupLength);
timestamp += 1;
absolute_send_time = AddAbsSendTime(absolute_send_time,
kSingleRtpTickAbsSendTime);
}
// Increase time until next batch to simulate over-use.
clock_.AdvanceTimeMilliseconds(10);
timestamp += 90 * kFrameIntervalMs - kTimestampGroupLength;
absolute_send_time = AddAbsSendTime(
absolute_send_time,
AddAbsSendTime(kFrameIntervalAbsSendTime,
-static_cast<int>(kTimestampGroupLengthAbsSendTime)));
bitrate_estimator_->Process();
}
EXPECT_TRUE(bitrate_observer_->updated());
// Should have reduced the estimate.
EXPECT_LT(bitrate_observer_->latest_bitrate(), 400000u);
}
void RemoteBitrateEstimatorTest::TestWrappingHelper(
int silence_time_s) {
const int kFramerate = 100;
const int kFrameIntervalMs = 1000 / kFramerate;
const uint32_t kFrameIntervalAbsSendTime = AbsSendTime(1, kFramerate);
uint32_t absolute_send_time = 0;
uint32_t timestamp = 0;
for (size_t i = 0; i < 3000; ++i) {
IncomingPacket(kDefaultSsrc, 1000, clock_.TimeInMilliseconds(), timestamp,
absolute_send_time);
timestamp += kFrameIntervalMs;
clock_.AdvanceTimeMilliseconds(kFrameIntervalMs);
absolute_send_time = AddAbsSendTime(absolute_send_time,
kFrameIntervalAbsSendTime);
bitrate_estimator_->Process();
}
uint32_t bitrate_before = 0;
std::vector<uint32_t> ssrcs;
bitrate_estimator_->LatestEstimate(&ssrcs, &bitrate_before);
clock_.AdvanceTimeMilliseconds(silence_time_s * 1000);
absolute_send_time = AddAbsSendTime(absolute_send_time,
AbsSendTime(silence_time_s, 1));
bitrate_estimator_->Process();
for (size_t i = 0; i < 21; ++i) {
IncomingPacket(kDefaultSsrc, 1000, clock_.TimeInMilliseconds(), timestamp,
absolute_send_time);
timestamp += kFrameIntervalMs;
clock_.AdvanceTimeMilliseconds(2 * kFrameIntervalMs);
absolute_send_time = AddAbsSendTime(absolute_send_time,
kFrameIntervalAbsSendTime);
bitrate_estimator_->Process();
}
uint32_t bitrate_after = 0;
bitrate_estimator_->LatestEstimate(&ssrcs, &bitrate_after);
EXPECT_LT(bitrate_after, bitrate_before);
}
} // namespace webrtc