Index: webrtc/modules/congestion_controller/transport_feedback_adapter_unittest.cc |
diff --git a/webrtc/modules/congestion_controller/transport_feedback_adapter_unittest.cc b/webrtc/modules/congestion_controller/transport_feedback_adapter_unittest.cc |
index bf4dbcae84103f401a43cf33dbbefc030410865a..42effebcf9d1d0fccd3c39a9a4c60048ded6e1c5 100644 |
--- a/webrtc/modules/congestion_controller/transport_feedback_adapter_unittest.cc |
+++ b/webrtc/modules/congestion_controller/transport_feedback_adapter_unittest.cc |
@@ -15,7 +15,6 @@ |
#include "webrtc/base/checks.h" |
#include "webrtc/base/safe_conversions.h" |
#include "webrtc/modules/bitrate_controller/include/mock/mock_bitrate_controller.h" |
-#include "webrtc/modules/congestion_controller/congestion_controller_unittests_helper.h" |
#include "webrtc/modules/congestion_controller/transport_feedback_adapter.h" |
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" |
#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h" |
@@ -40,22 +39,68 @@ |
class TransportFeedbackAdapterTest : public ::testing::Test { |
public: |
- TransportFeedbackAdapterTest() : clock_(0) {} |
+ TransportFeedbackAdapterTest() |
+ : clock_(0), bitrate_controller_(this), target_bitrate_bps_(0) {} |
virtual ~TransportFeedbackAdapterTest() {} |
virtual void SetUp() { |
- adapter_.reset(new TransportFeedbackAdapter(&clock_)); |
+ adapter_.reset( |
+ new TransportFeedbackAdapter(nullptr, &clock_, &bitrate_controller_)); |
+ adapter_->InitBwe(); |
+ adapter_->SetStartBitrate(300000); |
} |
virtual void TearDown() { adapter_.reset(); } |
protected: |
+ // Proxy class used since TransportFeedbackAdapter will own the instance |
+ // passed at construction. |
+ class MockBitrateControllerAdapter : public MockBitrateController { |
+ public: |
+ explicit MockBitrateControllerAdapter(TransportFeedbackAdapterTest* owner) |
+ : MockBitrateController(), owner_(owner) {} |
+ |
+ ~MockBitrateControllerAdapter() override {} |
+ |
+ void OnDelayBasedBweResult(const DelayBasedBwe::Result& result) override { |
+ owner_->target_bitrate_bps_ = result.target_bitrate_bps; |
+ } |
+ |
+ TransportFeedbackAdapterTest* const owner_; |
+ }; |
+ |
void OnReceivedEstimatedBitrate(uint32_t bitrate) {} |
void OnReceivedRtcpReceiverReport(const ReportBlockList& report_blocks, |
int64_t rtt, |
int64_t now_ms) {} |
+ |
+ void ComparePacketVectors(const std::vector<PacketFeedback>& truth, |
+ const std::vector<PacketFeedback>& input) { |
+ ASSERT_EQ(truth.size(), input.size()); |
+ size_t len = truth.size(); |
+ // truth contains the input data for the test, and input is what will be |
+ // sent to the bandwidth estimator. truth.arrival_tims_ms is used to |
+ // populate the transport feedback messages. As these times may be changed |
+ // (because of resolution limits in the packets, and because of the time |
+ // base adjustment performed by the TransportFeedbackAdapter at the first |
+ // packet, the truth[x].arrival_time and input[x].arrival_time may not be |
+ // equal. However, the difference must be the same for all x. |
+ int64_t arrival_time_delta = |
+ truth[0].arrival_time_ms - input[0].arrival_time_ms; |
+ for (size_t i = 0; i < len; ++i) { |
+ RTC_CHECK(truth[i].arrival_time_ms != PacketFeedback::kNotReceived); |
+ if (input[i].arrival_time_ms != PacketFeedback::kNotReceived) { |
+ EXPECT_EQ(truth[i].arrival_time_ms, |
+ input[i].arrival_time_ms + arrival_time_delta); |
+ } |
+ EXPECT_EQ(truth[i].send_time_ms, input[i].send_time_ms); |
+ EXPECT_EQ(truth[i].sequence_number, input[i].sequence_number); |
+ EXPECT_EQ(truth[i].payload_size, input[i].payload_size); |
+ EXPECT_EQ(truth[i].pacing_info, input[i].pacing_info); |
+ } |
+ } |
void OnSentPacket(const PacketFeedback& packet_feedback) { |
adapter_->AddPacket(packet_feedback.sequence_number, |
@@ -66,7 +111,10 @@ |
} |
SimulatedClock clock_; |
+ MockBitrateControllerAdapter bitrate_controller_; |
std::unique_ptr<TransportFeedbackAdapter> adapter_; |
+ |
+ uint32_t target_bitrate_bps_; |
}; |
TEST_F(TransportFeedbackAdapterTest, AdaptsFeedbackAndPopulatesSendTimes) { |
@@ -92,7 +140,7 @@ |
feedback.Build(); |
adapter_->OnTransportFeedback(feedback); |
- ComparePacketFeedbackVectors(packets, adapter_->GetTransportFeedbackVector()); |
+ ComparePacketVectors(packets, adapter_->GetTransportFeedbackVector()); |
} |
TEST_F(TransportFeedbackAdapterTest, FeedbackVectorReportsUnreceived) { |
@@ -127,8 +175,91 @@ |
feedback.Build(); |
adapter_->OnTransportFeedback(feedback); |
- ComparePacketFeedbackVectors(sent_packets, |
- adapter_->GetTransportFeedbackVector()); |
+ ComparePacketVectors(sent_packets, adapter_->GetTransportFeedbackVector()); |
+} |
+ |
+TEST_F(TransportFeedbackAdapterTest, LongFeedbackDelays) { |
+ const int64_t kFeedbackTimeoutMs = 60001; |
+ const int kMaxConsecutiveFailedLookups = 5; |
+ for (int i = 0; i < kMaxConsecutiveFailedLookups; ++i) { |
+ std::vector<PacketFeedback> packets; |
+ packets.push_back( |
+ PacketFeedback(i * 100, 2 * i * 100, 0, 1500, kPacingInfo0)); |
+ packets.push_back( |
+ PacketFeedback(i * 100 + 10, 2 * i * 100 + 10, 1, 1500, kPacingInfo0)); |
+ packets.push_back( |
+ PacketFeedback(i * 100 + 20, 2 * i * 100 + 20, 2, 1500, kPacingInfo0)); |
+ packets.push_back( |
+ PacketFeedback(i * 100 + 30, 2 * i * 100 + 30, 3, 1500, kPacingInfo1)); |
+ packets.push_back( |
+ PacketFeedback(i * 100 + 40, 2 * i * 100 + 40, 4, 1500, kPacingInfo1)); |
+ |
+ for (const PacketFeedback& packet : packets) |
+ OnSentPacket(packet); |
+ |
+ rtcp::TransportFeedback feedback; |
+ feedback.SetBase(packets[0].sequence_number, |
+ packets[0].arrival_time_ms * 1000); |
+ |
+ for (const PacketFeedback& packet : packets) { |
+ EXPECT_TRUE(feedback.AddReceivedPacket(packet.sequence_number, |
+ packet.arrival_time_ms * 1000)); |
+ } |
+ |
+ feedback.Build(); |
+ |
+ clock_.AdvanceTimeMilliseconds(kFeedbackTimeoutMs); |
+ PacketFeedback later_packet(kFeedbackTimeoutMs + i * 100 + 40, |
+ kFeedbackTimeoutMs + i * 200 + 40, 5, 1500, |
+ kPacingInfo1); |
+ OnSentPacket(later_packet); |
+ |
+ adapter_->OnTransportFeedback(feedback); |
+ |
+ // Check that packets have timed out. |
+ for (PacketFeedback& packet : packets) { |
+ packet.send_time_ms = -1; |
+ packet.payload_size = 0; |
+ packet.pacing_info = PacedPacketInfo(); |
+ } |
+ ComparePacketVectors(packets, adapter_->GetTransportFeedbackVector()); |
+ } |
+ |
+ // Target bitrate should have halved due to feedback delays. |
+ EXPECT_EQ(150000u, target_bitrate_bps_); |
+ |
+ // Test with feedback that isn't late enough to time out. |
+ { |
+ std::vector<PacketFeedback> packets; |
+ packets.push_back(PacketFeedback(100, 200, 0, 1500, kPacingInfo0)); |
+ packets.push_back(PacketFeedback(110, 210, 1, 1500, kPacingInfo0)); |
+ packets.push_back(PacketFeedback(120, 220, 2, 1500, kPacingInfo0)); |
+ packets.push_back(PacketFeedback(130, 230, 3, 1500, kPacingInfo1)); |
+ packets.push_back(PacketFeedback(140, 240, 4, 1500, kPacingInfo1)); |
+ |
+ for (const PacketFeedback& packet : packets) |
+ OnSentPacket(packet); |
+ |
+ rtcp::TransportFeedback feedback; |
+ feedback.SetBase(packets[0].sequence_number, |
+ packets[0].arrival_time_ms * 1000); |
+ |
+ for (const PacketFeedback& packet : packets) { |
+ EXPECT_TRUE(feedback.AddReceivedPacket(packet.sequence_number, |
+ packet.arrival_time_ms * 1000)); |
+ } |
+ |
+ feedback.Build(); |
+ |
+ clock_.AdvanceTimeMilliseconds(kFeedbackTimeoutMs - 1); |
+ PacketFeedback later_packet(kFeedbackTimeoutMs + 140, |
+ kFeedbackTimeoutMs + 240, 5, 1500, |
+ kPacingInfo1); |
+ OnSentPacket(later_packet); |
+ |
+ adapter_->OnTransportFeedback(feedback); |
+ ComparePacketVectors(packets, adapter_->GetTransportFeedbackVector()); |
+ } |
} |
TEST_F(TransportFeedbackAdapterTest, HandlesDroppedPackets) { |
@@ -171,8 +302,8 @@ |
} |
adapter_->OnTransportFeedback(feedback); |
- ComparePacketFeedbackVectors(expected_packets, |
- adapter_->GetTransportFeedbackVector()); |
+ ComparePacketVectors(expected_packets, |
+ adapter_->GetTransportFeedbackVector()); |
} |
TEST_F(TransportFeedbackAdapterTest, SendTimeWrapsBothWays) { |
@@ -207,8 +338,8 @@ |
expected_packets.push_back(packets[i]); |
adapter_->OnTransportFeedback(*feedback.get()); |
- ComparePacketFeedbackVectors(expected_packets, |
- adapter_->GetTransportFeedbackVector()); |
+ ComparePacketVectors(expected_packets, |
+ adapter_->GetTransportFeedbackVector()); |
} |
} |
@@ -236,7 +367,7 @@ |
// assigned by the order of transmission). Reordering by some other criteria, |
// eg. arrival time, is up to the observers. |
adapter_->OnTransportFeedback(feedback); |
- ComparePacketFeedbackVectors(packets, adapter_->GetTransportFeedbackVector()); |
+ ComparePacketVectors(packets, adapter_->GetTransportFeedbackVector()); |
} |
TEST_F(TransportFeedbackAdapterTest, TimestampDeltas) { |
@@ -299,8 +430,7 @@ |
EXPECT_TRUE(feedback.get() != nullptr); |
adapter_->OnTransportFeedback(*feedback.get()); |
- ComparePacketFeedbackVectors(sent_packets, |
- adapter_->GetTransportFeedbackVector()); |
+ ComparePacketVectors(sent_packets, adapter_->GetTransportFeedbackVector()); |
// Create a new feedback message and add the trailing item. |
feedback.reset(new rtcp::TransportFeedback()); |
@@ -317,9 +447,39 @@ |
{ |
std::vector<PacketFeedback> expected_packets; |
expected_packets.push_back(packet_feedback); |
- ComparePacketFeedbackVectors(expected_packets, |
- adapter_->GetTransportFeedbackVector()); |
- } |
-} |
+ ComparePacketVectors(expected_packets, |
+ adapter_->GetTransportFeedbackVector()); |
+ } |
+} |
+ |
+TEST_F(TransportFeedbackAdapterTest, UpdatesDelayBasedEstimate) { |
+ uint16_t seq_num = 0; |
+ size_t kPayloadSize = 1000; |
+ // The test must run and insert packets/feedback long enough that the |
+ // BWE computes a valid estimate. |
+ const int64_t kRunTimeMs = 6000; |
+ int64_t start_time_ms = clock_.TimeInMilliseconds(); |
+ while (clock_.TimeInMilliseconds() - start_time_ms < kRunTimeMs) { |
+ PacketFeedback packet(clock_.TimeInMilliseconds(), |
+ clock_.TimeInMilliseconds(), seq_num, kPayloadSize, |
+ PacedPacketInfo()); |
+ OnSentPacket(packet); |
+ // Create expected feedback and send into adapter. |
+ std::unique_ptr<rtcp::TransportFeedback> feedback( |
+ new rtcp::TransportFeedback()); |
+ feedback->SetBase(packet.sequence_number, packet.arrival_time_ms * 1000); |
+ EXPECT_TRUE(feedback->AddReceivedPacket(packet.sequence_number, |
+ packet.arrival_time_ms * 1000)); |
+ rtc::Buffer raw_packet = feedback->Build(); |
+ feedback = rtcp::TransportFeedback::ParseFrom(raw_packet.data(), |
+ raw_packet.size()); |
+ EXPECT_TRUE(feedback.get() != nullptr); |
+ adapter_->OnTransportFeedback(*feedback.get()); |
+ clock_.AdvanceTimeMilliseconds(50); |
+ ++seq_num; |
+ } |
+ EXPECT_GT(target_bitrate_bps_, 0u); |
+} |
+ |
} // namespace test |
} // namespace webrtc |