diff --git a/webrtc/modules/remote_bitrate_estimator/include/mock/mock_remote_bitrate_observer.h b/webrtc/modules/remote_bitrate_estimator/include/mock/mock_remote_bitrate_observer.h index 30af7d6d0e..2bb8d09a91 100644 --- a/webrtc/modules/remote_bitrate_estimator/include/mock/mock_remote_bitrate_observer.h +++ b/webrtc/modules/remote_bitrate_estimator/include/mock/mock_remote_bitrate_observer.h @@ -22,7 +22,7 @@ namespace webrtc { class MockRemoteBitrateObserver : public RemoteBitrateObserver { public: MOCK_METHOD2(OnReceiveBitrateChanged, - void(std::vector* ssrcs, unsigned int bitrate)); + void(const std::vector& ssrcs, unsigned int bitrate)); }; } // namespace webrtc diff --git a/webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h b/webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h index 80b2759cf4..a6e0d3a0fc 100644 --- a/webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h +++ b/webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h @@ -31,7 +31,7 @@ class RemoteBitrateObserver { public: // Called when a receive channel group has a new bitrate estimate for the // incoming streams. - virtual void OnReceiveBitrateChanged(std::vector* ssrcs, + virtual void OnReceiveBitrateChanged(const std::vector& ssrcs, unsigned int bitrate) = 0; virtual ~RemoteBitrateObserver() {} @@ -41,7 +41,6 @@ class RemoteBitrateEstimator : public CallStatsObserver, public Module { public: virtual ~RemoteBitrateEstimator() {} - // 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 // 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 // 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 - // packet size excluding headers. - virtual void IncomingPacket(unsigned int ssrc, + // packet size excluding headers. The estimator can only count on the + // "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, - int64_t arrival_time, - uint32_t rtp_timestamp) = 0; + const WebRtcRTPHeader& header) = 0; // Removes all data for |ssrc|. virtual void RemoveStream(unsigned int ssrc) = 0; diff --git a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator.gypi b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator.gypi index c5c3cfe0e7..829adf1a01 100644 --- a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator.gypi +++ b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator.gypi @@ -59,7 +59,8 @@ 'sources': [ 'include/mock/mock_remote_bitrate_observer.h', '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.h', 'rtp_to_ntp_unittest.cc', diff --git a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_multi_stream.cc b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_multi_stream.cc index cebe48b436..ae7132022e 100644 --- a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_multi_stream.cc +++ b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_multi_stream.cc @@ -28,14 +28,13 @@ class RemoteBitrateEstimatorMultiStream : public RemoteBitrateEstimator { public: RemoteBitrateEstimatorMultiStream(RemoteBitrateObserver* observer, Clock* clock); - - ~RemoteBitrateEstimatorMultiStream() {} + virtual ~RemoteBitrateEstimatorMultiStream() {} // 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 // two tuples the RemoteBitrateEstimator will switch to multi-stream mode. - void IncomingRtcp(unsigned int ssrc, uint32_t ntp_secs, uint32_t ntp_frac, - uint32_t rtp_timestamp); + virtual void IncomingRtcp(unsigned int ssrc, uint32_t ntp_secs, + uint32_t ntp_frac, uint32_t rtp_timestamp); // 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 @@ -43,10 +42,9 @@ class RemoteBitrateEstimatorMultiStream : public RemoteBitrateEstimator { // incoming payload bitrate 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 packet size excluding headers. - void IncomingPacket(unsigned int ssrc, - int payload_size, - int64_t arrival_time, - uint32_t rtp_timestamp); + virtual void IncomingPacket(int64_t arrival_time_ms, + int payload_size, + const WebRtcRTPHeader& header); // Triggers a new estimate calculation. // Implements the Module interface. @@ -57,13 +55,13 @@ class RemoteBitrateEstimatorMultiStream : public RemoteBitrateEstimator { virtual void OnRttUpdate(uint32_t rtt); // 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 // 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. - bool LatestEstimate(std::vector* ssrcs, - unsigned int* bitrate_bps) const; + virtual bool LatestEstimate(std::vector* ssrcs, + unsigned int* bitrate_bps) const; private: typedef std::map StreamMap; @@ -138,12 +136,15 @@ void RemoteBitrateEstimatorMultiStream::IncomingRtcp(unsigned int ssrc, rtcp_list->push_front(measurement); } -void RemoteBitrateEstimatorMultiStream::IncomingPacket(unsigned int ssrc, - int payload_size, - int64_t arrival_time, - uint32_t rtp_timestamp) { +void RemoteBitrateEstimatorMultiStream::IncomingPacket( + int64_t arrival_time_ms, + int payload_size, + const WebRtcRTPHeader& header) { + uint32_t ssrc = header.header.ssrc; + uint32_t rtp_timestamp = header.header.timestamp + + header.extension.transmissionTimeOffset; 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. std::pair stream_insert_result = 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); } overuse_detector_.Update(payload_size, timestamp_in_ms, rtp_timestamp, - arrival_time); + arrival_time_ms); 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 || - remote_rate_.TimeToReduceFurther(arrival_time, incoming_bitrate)) { + remote_rate_.TimeToReduceFurther(arrival_time_ms, incoming_bitrate)) { // The first overuse should immediately trigger a new estimate. // 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. - UpdateEstimate(arrival_time); + UpdateEstimate(arrival_time_ms); } } } @@ -216,7 +217,7 @@ void RemoteBitrateEstimatorMultiStream::UpdateEstimate(int64_t time_now) { std::vector ssrcs; GetSsrcs(&ssrcs); if (!ssrcs.empty()) { - observer_->OnReceiveBitrateChanged(&ssrcs, target_bitrate); + observer_->OnReceiveBitrateChanged(ssrcs, target_bitrate); } } overuse_detector_.SetRateControlRegion(region); diff --git a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_multi_stream_unittest.cc b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_multi_stream_unittest.cc new file mode 100644 index 0000000000..72c1d2db4d --- /dev/null +++ b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_multi_stream_unittest.cc @@ -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 + +#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 diff --git a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.cc b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.cc index d79aad8ee1..6f0e80a7d5 100644 --- a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.cc +++ b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.cc @@ -25,19 +25,19 @@ class RemoteBitrateEstimatorSingleStream : public RemoteBitrateEstimator { public: RemoteBitrateEstimatorSingleStream(RemoteBitrateObserver* observer, Clock* clock); + virtual ~RemoteBitrateEstimatorSingleStream() {} - void IncomingRtcp(unsigned int ssrc, uint32_t ntp_secs, uint32_t ntp_frac, - uint32_t rtp_timestamp) {} + virtual void IncomingRtcp(unsigned int ssrc, uint32_t ntp_secs, + uint32_t ntp_frac, uint32_t rtp_timestamp) {} // Called for each incoming packet. If this is a new SSRC, a new // BitrateControl will be created. Updates the incoming payload bitrate // 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 // packet size excluding headers. - void IncomingPacket(unsigned int ssrc, - int payload_size, - int64_t arrival_time, - uint32_t rtp_timestamp); + virtual void IncomingPacket(int64_t arrival_time_ms, + int payload_size, + const WebRtcRTPHeader& header); // Triggers a new estimate calculation. // Implements the Module interface. @@ -48,13 +48,13 @@ class RemoteBitrateEstimatorSingleStream : public RemoteBitrateEstimator { virtual void OnRttUpdate(uint32_t rtt); // 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 // 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. - bool LatestEstimate(std::vector* ssrcs, - unsigned int* bitrate_bps) const; + virtual bool LatestEstimate(std::vector* ssrcs, + unsigned int* bitrate_bps) const; private: typedef std::map SsrcOveruseDetectorMap; @@ -84,10 +84,12 @@ RemoteBitrateEstimatorSingleStream::RemoteBitrateEstimatorSingleStream( } void RemoteBitrateEstimatorSingleStream::IncomingPacket( - unsigned int ssrc, + int64_t arrival_time_ms, int payload_size, - int64_t arrival_time, - 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()); SsrcOveruseDetectorMap::iterator it = overuse_detectors_.find(ssrc); if (it == overuse_detectors_.end()) { @@ -103,17 +105,17 @@ void RemoteBitrateEstimatorSingleStream::IncomingPacket( it = insert_result.first; } 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(); - 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) { - unsigned int incoming_bitrate = incoming_bitrate_.BitRate(arrival_time); + unsigned int incoming_bitrate = incoming_bitrate_.BitRate(arrival_time_ms); 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. // 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. - UpdateEstimate(arrival_time); + UpdateEstimate(arrival_time_ms); } } } @@ -172,7 +174,7 @@ void RemoteBitrateEstimatorSingleStream::UpdateEstimate(int64_t time_now) { if (remote_rate_.ValidEstimate()) { std::vector ssrcs; GetSsrcs(&ssrcs); - observer_->OnReceiveBitrateChanged(&ssrcs, target_bitrate); + observer_->OnReceiveBitrateChanged(ssrcs, target_bitrate); } for (it = overuse_detectors_.begin(); it != overuse_detectors_.end(); ++it) { it->second.SetRateControlRegion(region); diff --git a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream_unittest.cc b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream_unittest.cc new file mode 100644 index 0000000000..f0780c9a55 --- /dev/null +++ b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream_unittest.cc @@ -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 + +#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 diff --git a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_unittest.cc b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_unittest.cc deleted file mode 100644 index 3a71999ae3..0000000000 --- a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_unittest.cc +++ /dev/null @@ -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 - -#include -#include - -#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 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::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::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::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::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 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 index 3c87e4d0b8..1c1d597ed6 100644 --- a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_unittest_helper.cc +++ b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_unittest_helper.cc @@ -13,6 +13,9 @@ #include namespace webrtc { + +enum { kMtu = 1200 }; + namespace testing { 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 -// is decided by the initial allocation ratios. -void StreamGenerator::set_bitrate_bps(int bitrate_bps) { +// is decided by the current allocation ratios. +void StreamGenerator::SetBitrateBps(int bitrate_bps) { ASSERT_GE(streams_.size(), 0u); - double total_bitrate_before = 0; - for (StreamMap::iterator it = streams_.begin(); it != streams_.end(); - ++it) { + 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) { - double ratio = it->second->bitrate_bps() / total_bitrate_before; - it->second->set_bitrate_bps(ratio * bitrate_bps + 0.5); + 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(); } - 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|. @@ -186,22 +191,11 @@ void StreamGenerator::Rtcps(RtcpList* rtcps, int64_t time_now_us) const { RemoteBitrateEstimatorTest::RemoteBitrateEstimatorTest() : clock_(0), - align_streams_(false) {} - -RemoteBitrateEstimatorTest::RemoteBitrateEstimatorTest(bool align_streams) - : clock_(0), - align_streams_(align_streams) {} - -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())); -} + align_streams_(false), + bitrate_observer_(new testing::TestBitrateObserver), + stream_generator_(new testing::StreamGenerator( + 1e6, // Capacity. + clock_.TimeInMicroseconds())) {} void RemoteBitrateEstimatorTest::AddDefaultStream() { stream_generator_->AddStream(new testing::RtpStream( @@ -213,8 +207,29 @@ void RemoteBitrateEstimatorTest::AddDefaultStream() { 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, + 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 // with a given ssrc. The stream is pushed through a very simple simulated // 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. bool RemoteBitrateEstimatorTest::GenerateAndProcessFrame(unsigned int ssrc, unsigned int bitrate_bps) { - stream_generator_->set_bitrate_bps(bitrate_bps); + stream_generator_->SetBitrateBps(bitrate_bps); testing::RtpStream::PacketList packets; int64_t next_time_us = stream_generator_->GenerateFrame( &packets, clock_.TimeInMicroseconds()); @@ -243,10 +258,11 @@ bool RemoteBitrateEstimatorTest::GenerateAndProcessFrame(unsigned int ssrc, } } bitrate_observer_->Reset(); - bitrate_estimator_->IncomingPacket(packet->ssrc, - packet->size, - (packet->arrival_time + 500) / 1000, - packet->rtp_timestamp); + IncomingPacket(packet->ssrc, + packet->size, + (packet->arrival_time + 500) / 1000, + packet->rtp_timestamp, + AbsSendTime(packet->send_time, 1000000)); if (bitrate_observer_->updated()) { // Verify that new estimates only are triggered by an overuse and a // rate decrease. @@ -295,4 +311,193 @@ unsigned int RemoteBitrateEstimatorTest::SteadyStateRun( 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 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::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 diff --git a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_unittest_helper.h b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_unittest_helper.h index eb05e8f19b..0dc0ce8e6b 100644 --- a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_unittest_helper.h +++ b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_unittest_helper.h @@ -23,17 +23,15 @@ #include "webrtc/system_wrappers/interface/scoped_ptr.h" namespace webrtc { - -enum { kMtu = 1200 }; - namespace testing { class TestBitrateObserver : public RemoteBitrateObserver { public: TestBitrateObserver() : updated_(false), latest_bitrate_(0) {} + virtual ~TestBitrateObserver() {} - void OnReceiveBitrateChanged(std::vector* ssrcs, - unsigned int bitrate) { + virtual void OnReceiveBitrateChanged(const std::vector& ssrcs, + unsigned int bitrate) { latest_bitrate_ = bitrate; updated_ = true; } @@ -55,7 +53,6 @@ class TestBitrateObserver : public RemoteBitrateObserver { unsigned int latest_bitrate_; }; - class RtpStream { public: struct RtpPacket { @@ -132,7 +129,7 @@ class StreamGenerator { // Divides |bitrate_bps| among all streams. The allocated bitrate per stream // 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|. void set_rtp_timestamp_offset(unsigned int ssrc, uint32_t offset); @@ -160,13 +157,30 @@ class StreamGenerator { class RemoteBitrateEstimatorTest : public ::testing::Test { public: RemoteBitrateEstimatorTest(); - explicit RemoteBitrateEstimatorTest(bool align_streams); protected: - virtual void SetUp(); + virtual void SetUp() = 0; 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 // with a given ssrc. The stream is pushed through a very simple simulated // 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 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; SimulatedClock clock_; // Time at the receiver. - OverUseDetectorOptions overuse_detector_options_; - scoped_ptr bitrate_estimator_; + bool align_streams_; scoped_ptr bitrate_observer_; + scoped_ptr bitrate_estimator_; scoped_ptr stream_generator_; - const bool align_streams_; DISALLOW_COPY_AND_ASSIGN(RemoteBitrateEstimatorTest); }; - -class RemoteBitrateEstimatorTestAlign : public RemoteBitrateEstimatorTest { - public: - RemoteBitrateEstimatorTestAlign() : RemoteBitrateEstimatorTest(true) {} - - private: - DISALLOW_COPY_AND_ASSIGN(RemoteBitrateEstimatorTestAlign); -}; -} // namespace testing +} // namespace webrtc #endif // WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_REMOTE_BITRATE_ESTIMATOR_UNITTEST_HELPER_H_ diff --git a/webrtc/modules/remote_bitrate_estimator/remote_rate_control.cc b/webrtc/modules/remote_bitrate_estimator/remote_rate_control.cc index 1236ea06e0..6e6a1b3928 100644 --- a/webrtc/modules/remote_bitrate_estimator/remote_rate_control.cc +++ b/webrtc/modules/remote_bitrate_estimator/remote_rate_control.cc @@ -268,12 +268,12 @@ double RemoteRateControl::RateIncreaseFactor(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) { - changePeriod = now_ms - last_change_ms_; + change_period = now_ms - last_change_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) { @@ -288,8 +288,8 @@ void RemoteRateControl::UpdateMaxBitRateEstimate(float incoming_bit_rate_kbps) { // with the average max bit rate. const float norm = std::max(avg_max_bit_rate_, 1.0f); var_max_bit_rate_ = (1 - alpha) * var_max_bit_rate_ + - alpha * (avg_max_bit_rate_ - incoming_bit_rate_kbps) * - (avg_max_bit_rate_ - incoming_bit_rate_kbps) / norm; + alpha * (avg_max_bit_rate_ - incoming_bit_rate_kbps) * + (avg_max_bit_rate_ - incoming_bit_rate_kbps) / norm; // 0.4 ~= 14 kbit/s at 500 kbit/s if (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(current_input_._bwState, state3); 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) { diff --git a/webrtc/video_engine/vie_receiver.cc b/webrtc/video_engine/vie_receiver.cc index ca8ec1490f..508ae45b05 100644 --- a/webrtc/video_engine/vie_receiver.cc +++ b/webrtc/video_engine/vie_receiver.cc @@ -115,11 +115,8 @@ int32_t ViEReceiver::OnReceivedPayloadData( // TODO(holmer): Make sure packets reconstructed using FEC are not passed to // the bandwidth estimator. const int packet_size = payload_size + rtp_header->header.paddingLength; - uint32_t compensated_timestamp = rtp_header->header.timestamp + - rtp_header->extension.transmissionTimeOffset; - remote_bitrate_estimator_->IncomingPacket( - rtp_header->header.ssrc, packet_size, - TickTime::MillisecondTimestamp(), compensated_timestamp); + remote_bitrate_estimator_->IncomingPacket(TickTime::MillisecondTimestamp(), + packet_size, *rtp_header); if (vcm_->IncomingPacket(payload_data, payload_size, *rtp_header) != 0) { // Check this... return -1; diff --git a/webrtc/video_engine/vie_remb.cc b/webrtc/video_engine/vie_remb.cc index 534d6438b4..4b6f234436 100644 --- a/webrtc/video_engine/vie_remb.cc +++ b/webrtc/video_engine/vie_remb.cc @@ -104,11 +104,10 @@ bool VieRemb::InUse() const { return true; } -void VieRemb::OnReceiveBitrateChanged(std::vector* ssrcs, +void VieRemb::OnReceiveBitrateChanged(const std::vector& ssrcs, unsigned int bitrate) { WEBRTC_TRACE(kTraceStream, kTraceVideo, -1, "VieRemb::UpdateBitrateEstimate(bitrate: %u)", bitrate); - assert(ssrcs); list_crit_->Enter(); // If we already have an estimate, check if the new total estimate is below // kSendThresholdPercent of the previous estimate. @@ -132,7 +131,7 @@ void VieRemb::OnReceiveBitrateChanged(std::vector* ssrcs, } last_remb_time_ = now; - if (ssrcs->empty() || receive_modules_.empty()) { + if (ssrcs.empty() || receive_modules_.empty()) { list_crit_->Leave(); return; } @@ -154,8 +153,8 @@ void VieRemb::OnReceiveBitrateChanged(std::vector* ssrcs, list_crit_->Leave(); if (sender) { - // TODO(holmer): Change RTP module API to take a vector pointer. - sender->SetREMBData(bitrate_, ssrcs->size(), &(*ssrcs)[0]); + // TODO(holmer): Change RTP module API to take a const vector reference. + sender->SetREMBData(bitrate_, ssrcs.size(), &ssrcs[0]); } } diff --git a/webrtc/video_engine/vie_remb.h b/webrtc/video_engine/vie_remb.h index 649c8bc600..66e1c8e689 100644 --- a/webrtc/video_engine/vie_remb.h +++ b/webrtc/video_engine/vie_remb.h @@ -51,7 +51,7 @@ class VieRemb : public RemoteBitrateObserver { // estimate has decreased or if no RTCP REMB packet has been sent for // a certain time interval. // Implements RtpReceiveBitrateUpdate. - virtual void OnReceiveBitrateChanged(std::vector* ssrcs, + virtual void OnReceiveBitrateChanged(const std::vector& ssrcs, unsigned int bitrate); private: diff --git a/webrtc/video_engine/vie_remb_unittest.cc b/webrtc/video_engine/vie_remb_unittest.cc index 0cec272790..0fd9e51097 100644 --- a/webrtc/video_engine/vie_remb_unittest.cc +++ b/webrtc/video_engine/vie_remb_unittest.cc @@ -59,17 +59,17 @@ TEST_F(ViERembTest, OneModuleTestForSendingRemb) { unsigned int ssrc = 1234; std::vector ssrcs(&ssrc, &ssrc + 1); - vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate); + vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate); TickTime::AdvanceFakeClock(1000); EXPECT_CALL(rtp, SetREMBData(bitrate_estimate, 1, _)) .Times(1); - vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate); + vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate); // Lower bitrate to send another REMB packet. EXPECT_CALL(rtp, SetREMBData(bitrate_estimate - 100, 1, _)) .Times(1); - vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate - 100); + vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate - 100); vie_remb_->RemoveReceiveChannel(&rtp); vie_remb_->RemoveRembSender(&rtp); @@ -84,19 +84,19 @@ TEST_F(ViERembTest, LowerEstimateToSendRemb) { unsigned int ssrc = 1234; std::vector ssrcs(&ssrc, &ssrc + 1); - vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate); + vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate); // Call OnReceiveBitrateChanged twice to get a first estimate. TickTime::AdvanceFakeClock(1000); EXPECT_CALL(rtp, SetREMBData(bitrate_estimate, 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 // away. bitrate_estimate = bitrate_estimate - 100; EXPECT_CALL(rtp, SetREMBData(bitrate_estimate, 1, _)) .Times(1); - vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate); + vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate); } TEST_F(ViERembTest, VerifyIncreasingAndDecreasing) { @@ -110,20 +110,20 @@ TEST_F(ViERembTest, VerifyIncreasingAndDecreasing) { unsigned int ssrc[] = { 1234, 5678 }; std::vector 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. EXPECT_CALL(rtp_0, SetREMBData(bitrate_estimate[0], 2, _)) .Times(1); 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. EXPECT_CALL(rtp_0, SetREMBData(bitrate_estimate[1], 2, _)) .Times(1); - vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate[1]); + vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate[1]); vie_remb_->RemoveReceiveChannel(&rtp_0); vie_remb_->RemoveRembSender(&rtp_0); @@ -141,23 +141,23 @@ TEST_F(ViERembTest, NoRembForIncreasedBitrate) { unsigned int ssrc[] = { 1234, 5678 }; std::vector 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. TickTime::AdvanceFakeClock(1000); EXPECT_CALL(rtp_0, SetREMBData(bitrate_estimate, 2, _)) .Times(1); - vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate); + vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate); // Increased estimate shouldn't trigger a callback right away. EXPECT_CALL(rtp_0, SetREMBData(_, _, _)) .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. EXPECT_CALL(rtp_0, SetREMBData(_, _, _)) .Times(0); 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_0); @@ -175,29 +175,29 @@ TEST_F(ViERembTest, ChangeSendRtpModule) { unsigned int ssrc[] = { 1234, 5678 }; std::vector 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. TickTime::AdvanceFakeClock(1000); EXPECT_CALL(rtp_0, SetREMBData(bitrate_estimate, 2, _)) .Times(1); - vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate); + vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate); // Decrease estimate to trigger a REMB. bitrate_estimate = bitrate_estimate - 100; EXPECT_CALL(rtp_0, SetREMBData(bitrate_estimate, 2, _)) .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 // module. vie_remb_->RemoveRembSender(&rtp_0); vie_remb_->AddRembSender(&rtp_1); - vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate); + vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate); bitrate_estimate = bitrate_estimate - 100; EXPECT_CALL(rtp_1, SetREMBData(bitrate_estimate, 2, _)) .Times(1); - vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate); + vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate); vie_remb_->RemoveReceiveChannel(&rtp_0); vie_remb_->RemoveReceiveChannel(&rtp_1); @@ -211,23 +211,23 @@ TEST_F(ViERembTest, OnlyOneRembForDoubleProcess) { vie_remb_->AddReceiveChannel(&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. TickTime::AdvanceFakeClock(1000); EXPECT_CALL(rtp, SetREMBData(_, _, _)) .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. bitrate_estimate = bitrate_estimate - 100; EXPECT_CALL(rtp, SetREMBData(bitrate_estimate, 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. EXPECT_CALL(rtp, SetREMBData(_, _, _)) .Times(0); - vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate); + vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate); vie_remb_->RemoveReceiveChannel(&rtp); vie_remb_->RemoveRembSender(&rtp); } @@ -242,19 +242,19 @@ TEST_F(ViERembTest, NoSendingRtpModule) { unsigned int ssrc = 1234; std::vector ssrcs(&ssrc, &ssrc + 1); - vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate); + vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate); // Call OnReceiveBitrateChanged twice to get a first estimate. TickTime::AdvanceFakeClock(1000); EXPECT_CALL(rtp, SetREMBData(_, _, _)) .Times(1); - vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate); + vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate); // Lower the estimate to trigger a new packet REMB packet. bitrate_estimate = bitrate_estimate - 100; EXPECT_CALL(rtp, SetREMBData(_, _, _)) .Times(1); - vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate); + vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate); } } // namespace webrtc