diff options
Diffstat (limited to 'webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_unittest_helper.cc')
-rw-r--r-- | webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_unittest_helper.cc | 667 |
1 files changed, 667 insertions, 0 deletions
diff --git a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_unittest_helper.cc b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_unittest_helper.cc new file mode 100644 index 0000000000..315f5422d9 --- /dev/null +++ b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_unittest_helper.cc @@ -0,0 +1,667 @@ +/* + * 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 <utility> + +namespace webrtc { + +const size_t kMtu = 1200; +const unsigned int kAcceptedBitrateErrorBps = 50000; + +namespace testing { + +void TestBitrateObserver::OnReceiveBitrateChanged( + const std::vector<unsigned int>& ssrcs, + unsigned int bitrate) { + latest_bitrate_ = bitrate; + updated_ = true; +} + +RtpStream::RtpStream(int fps, + int bitrate_bps, + unsigned int ssrc, + unsigned int 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. +double 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_; +} + +unsigned int RtpStream::ssrc() const { + return ssrc_; +} + +bool RtpStream::Compare(const std::pair<unsigned int, RtpStream*>& left, + const std::pair<unsigned int, RtpStream*>& right) { + return left.second->next_rtp_time_ < right.second->next_rtp_time_; +} + +StreamGenerator::StreamGenerator(int capacity, double 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(unsigned int 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 (*it).second->next_rtp_time(); +} +} // namespace testing + +RemoteBitrateEstimatorTest::RemoteBitrateEstimatorTest() + : clock_(0), + bitrate_observer_(new testing::TestBitrateObserver), + stream_generator_(new testing::StreamGenerator( + 1e6, // Capacity. + clock_.TimeInMicroseconds())) {} + +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 unsigned int 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, + bool was_paced) { + RTPHeader header; + memset(&header, 0, sizeof(header)); + header.ssrc = ssrc; + header.timestamp = rtp_timestamp; + header.extension.hasAbsoluteSendTime = true; + header.extension.absoluteSendTime = absolute_send_time; + bitrate_estimator_->IncomingPacket(arrival_time + kArrivalTimeClockOffsetMs, + payload_size, header, was_paced); +} + +// 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(unsigned int ssrc, + unsigned int bitrate_bps) { + 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), true); + if (bitrate_observer_->updated()) { + // Verify that new estimates only are triggered by an overuse and a + // rate decrease. + overuse = true; + EXPECT_LE(bitrate_observer_->latest_bitrate(), bitrate_bps); + } + 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. +unsigned int RemoteBitrateEstimatorTest::SteadyStateRun( + unsigned int ssrc, + int max_number_of_frames, + unsigned int start_bitrate, + unsigned int min_bitrate, + unsigned int max_bitrate, + unsigned int target_bitrate) { + unsigned int 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( + 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 5 seconds. + IncomingPacket(kDefaultSsrc, kMtu, clock_.TimeInMilliseconds(), timestamp, + absolute_send_time, true); + 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 5 seconds to get a valid estimate. + for (int i = 0; i < 5 * kFramerate + 1; ++i) { + IncomingPacket(kDefaultSsrc, kMtu, clock_.TimeInMilliseconds(), timestamp, + absolute_send_time, true); + 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; + IncomingPacket(kDefaultSsrc, 1000, clock_.TimeInMilliseconds(), timestamp, + absolute_send_time, true); + 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 < 5 * kFramerate + 1; ++i) { + IncomingPacket(kDefaultSsrc, kMtu, clock_.TimeInMilliseconds(), timestamp, + absolute_send_time, true); + 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, true); + IncomingPacket( + kDefaultSsrc, 1000, clock_.TimeInMilliseconds(), + timestamp - 90 * kFrameIntervalMs, + AddAbsSendTime(absolute_send_time, -int(kFrameIntervalAbsSendTime)), + true); + } + 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. + 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, expected_iterations); + } + ASSERT_EQ(expected_iterations, iterations); +} + +void RemoteBitrateEstimatorTest::CapacityDropTestHelper( + int number_of_streams, + bool wrap_time_stamp, + 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; + 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; + } + 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_NEAR(kInitialCapacityBps, bitrate_bps, 110000u); + bitrate_observer_->Reset(); + + // 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); + // 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_NEAR(expected_bitrate_drop_delta, + bitrate_drop_time - overuse_start_time, 33); + + // Remove stream one by one. + unsigned int latest_bps = 0; + std::vector<unsigned int> 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), -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, true); + 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, true); + 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, -int(kTimestampGroupLengthAbsSendTime))); + bitrate_estimator_->Process(); + } + EXPECT_TRUE(bitrate_observer_->updated()); + // Should have reduced the estimate. + EXPECT_LT(bitrate_observer_->latest_bitrate(), 400000u); +} + +void RemoteBitrateEstimatorTest::TestGetStatsHelper() { + const int kFramerate = 100; + const int kFrameIntervalMs = 1000 / kFramerate; + const int kBurstThresholdMs = 5; + 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), + -(50 * static_cast<int>(kFrameIntervalAbsSendTime))); + + // Inject propagation_time_delta of kFrameIntervalMs. + for (size_t i = 0; i < 3; ++i) { + IncomingPacket(kDefaultSsrc, 1000, clock_.TimeInMilliseconds(), timestamp, + absolute_send_time, true); + timestamp += kFrameIntervalMs; + // Insert a kFrameIntervalMs propagation_time_delta. + clock_.AdvanceTimeMilliseconds(kFrameIntervalMs * 2); + absolute_send_time = AddAbsSendTime(absolute_send_time, + kFrameIntervalAbsSendTime); + } + ReceiveBandwidthEstimatorStats stats; + EXPECT_TRUE(bitrate_estimator_->GetStats(&stats)); + EXPECT_EQ(1U, stats.recent_propagation_time_delta_ms.size()); + EXPECT_EQ(kFrameIntervalMs, stats.recent_propagation_time_delta_ms[0]); + EXPECT_EQ(1U, stats.recent_arrival_time_ms.size()); + EXPECT_EQ(kFrameIntervalMs, stats.total_propagation_time_delta_ms); + + // Inject negative propagation_time_deltas. The total propagation_time_delta + // should be adjusted to 0. + for (size_t i = 0; i < 3; ++i) { + IncomingPacket(kDefaultSsrc, 1000, clock_.TimeInMilliseconds(), timestamp, + absolute_send_time, true); + timestamp += 10 * kFrameIntervalMs; + clock_.AdvanceTimeMilliseconds(kBurstThresholdMs + 1); + absolute_send_time = AddAbsSendTime(absolute_send_time, + 10 * kFrameIntervalAbsSendTime); + } + EXPECT_TRUE(bitrate_estimator_->GetStats(&stats)); + EXPECT_EQ(0, stats.total_propagation_time_delta_ms); + + // Send more than 1000 frames and make sure the stats queues stays within + // limits. + for (size_t i = 0; i < 1001; ++i) { + IncomingPacket(kDefaultSsrc, 1000, clock_.TimeInMilliseconds(), timestamp, + absolute_send_time, true); + timestamp += kFrameIntervalMs; + absolute_send_time = AddAbsSendTime(absolute_send_time, + kFrameIntervalAbsSendTime); + } + EXPECT_TRUE(bitrate_estimator_->GetStats(&stats)); + EXPECT_LE(stats.recent_propagation_time_delta_ms.size(), 1000U); + EXPECT_LE(stats.recent_arrival_time_ms.size(), 1000U); + + // Move the clock over the 1000ms limit. + clock_.AdvanceTimeMilliseconds(2000); + EXPECT_TRUE(bitrate_estimator_->GetStats(&stats)); + EXPECT_EQ(0U, stats.recent_propagation_time_delta_ms.size()); +} + +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, true); + timestamp += kFrameIntervalMs; + clock_.AdvanceTimeMilliseconds(kFrameIntervalMs); + absolute_send_time = AddAbsSendTime(absolute_send_time, + kFrameIntervalAbsSendTime); + bitrate_estimator_->Process(); + } + unsigned int bitrate_before = 0; + std::vector<unsigned int> 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 < 100; ++i) { + IncomingPacket(kDefaultSsrc, 1000, clock_.TimeInMilliseconds(), timestamp, + absolute_send_time, true); + timestamp += kFrameIntervalMs; + clock_.AdvanceTimeMilliseconds(2 * kFrameIntervalMs); + absolute_send_time = AddAbsSendTime(absolute_send_time, + kFrameIntervalAbsSendTime); + bitrate_estimator_->Process(); + } + unsigned int bitrate_after = 0; + bitrate_estimator_->LatestEstimate(&ssrcs, &bitrate_after); + EXPECT_LT(bitrate_after, bitrate_before); +} +} // namespace webrtc |