Index: webrtc/modules/remote_bitrate_estimator/transport_feedback_adapter_unittest.cc |
diff --git a/webrtc/modules/remote_bitrate_estimator/transport_feedback_adapter_unittest.cc b/webrtc/modules/remote_bitrate_estimator/transport_feedback_adapter_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..5d63b899a35ea0069fcda55cb7fe9deb9e4c42ba |
--- /dev/null |
+++ b/webrtc/modules/remote_bitrate_estimator/transport_feedback_adapter_unittest.cc |
@@ -0,0 +1,222 @@ |
+/* |
+ * Copyright (c) 2015 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 <vector> |
+ |
+#include "testing/gmock/include/gmock/gmock.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+#include "webrtc/base/checks.h" |
+#include "webrtc/base/scoped_ptr.h" |
+#include "webrtc/modules/remote_bitrate_estimator/include/mock/mock_remote_bitrate_estimator.h" |
+#include "webrtc/modules/remote_bitrate_estimator/transport_feedback_adapter.h" |
+#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" |
+#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h" |
+#include "webrtc/modules/utility/interface/mock/mock_process_thread.h" |
+#include "webrtc/system_wrappers/interface/clock.h" |
+ |
+using ::testing::_; |
+using ::testing::Invoke; |
+ |
+namespace webrtc { |
+namespace test { |
+ |
+class TransportFeedbackAdapterTest : public ::testing::Test { |
+ public: |
+ TransportFeedbackAdapterTest() |
+ : clock_(0), |
+ bitrate_estimator_(nullptr), |
+ receiver_estimated_bitrate_(0) {} |
+ |
+ virtual ~TransportFeedbackAdapterTest() {} |
+ |
+ virtual void SetUp() { |
+ adapter_.reset(new TransportFeedbackAdapter( |
+ new RtcpBandwidthObserverAdapter(this), &clock_, &process_thread_)); |
+ |
+ bitrate_estimator_ = new MockRemoteBitrateEstimator(); |
+ EXPECT_CALL(process_thread_, RegisterModule(bitrate_estimator_)).Times(1); |
+ adapter_->SetBitrateEstimator(bitrate_estimator_); |
+ } |
+ |
+ virtual void TearDown() { |
+ EXPECT_CALL(process_thread_, DeRegisterModule(bitrate_estimator_)).Times(1); |
+ adapter_.reset(); |
+ } |
+ |
+ protected: |
+ // Proxy class used since TransportFeedbackAdapter will own the instance |
+ // passed at construction. |
+ class RtcpBandwidthObserverAdapter : public RtcpBandwidthObserver { |
+ public: |
+ explicit RtcpBandwidthObserverAdapter(TransportFeedbackAdapterTest* owner) |
+ : owner_(owner) {} |
+ |
+ void OnReceivedEstimatedBitrate(uint32_t bitrate) override { |
+ owner_->receiver_estimated_bitrate_ = bitrate; |
+ } |
+ |
+ void OnReceivedRtcpReceiverReport(const ReportBlockList& report_blocks, |
+ int64_t rtt, |
+ int64_t now_ms) override { |
+ RTC_NOTREACHED(); |
+ } |
+ |
+ 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<PacketInfo>& truth, |
+ const std::vector<PacketInfo>& input) { |
+ ASSERT_EQ(truth.size(), input.size()); |
+ size_t len = truth.size(); |
+ int64_t arrival_time_delta = |
+ truth[0].arrival_time_ms - input[0].arrival_time_ms; |
stefan-webrtc
2015/09/11 08:15:12
Just from reading this code I don't fully understa
sprang_webrtc
2015/09/11 12:33:47
Done.
|
+ for (size_t i = 0; i < len; ++i) { |
+ 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].was_paced, input[i].was_paced); |
+ } |
+ } |
+ |
+ SimulatedClock clock_; |
+ MockProcessThread process_thread_; |
+ MockRemoteBitrateEstimator* bitrate_estimator_; |
stefan-webrtc
2015/09/11 08:15:12
Do you have to allocate it on the heap? Would save
sprang_webrtc
2015/09/11 12:33:48
Yes, the instance will be owned by TransportFeedba
|
+ rtc::scoped_ptr<TransportFeedbackAdapter> adapter_; |
+ |
+ uint32_t receiver_estimated_bitrate_; |
+}; |
+ |
+TEST_F(TransportFeedbackAdapterTest, AdaptsFeedbackAndPopulatesSendTimes) { |
+ std::vector<PacketInfo> packets; |
+ packets.push_back(PacketInfo(100, 200, 0, 1500, true)); |
+ packets.push_back(PacketInfo(110, 210, 1, 1500, true)); |
+ packets.push_back(PacketInfo(120, 220, 2, 1500, true)); |
+ packets.push_back(PacketInfo(130, 230, 3, 1500, true)); |
+ packets.push_back(PacketInfo(140, 240, 4, 1500, true)); |
+ |
+ for (const PacketInfo& packet : packets) { |
+ adapter_->OnPacketSent(packet.sequence_number, packet.send_time_ms, |
+ packet.payload_size, packet.was_paced); |
stefan-webrtc
2015/09/11 08:15:12
Makes me wonder why we don't pass in a PacketInfo
sprang_webrtc
2015/09/11 12:33:47
Done.
|
+ } |
+ |
+ rtcp::TransportFeedback feedback; |
+ feedback.WithBase(packets[0].sequence_number, |
+ packets[0].arrival_time_ms * 1000); |
+ |
+ for (const PacketInfo& packet : packets) { |
+ EXPECT_TRUE(feedback.WithReceivedPacket(packet.sequence_number, |
+ packet.arrival_time_ms * 1000)); |
+ } |
+ |
+ feedback.Build(); |
+ |
+ EXPECT_CALL(*bitrate_estimator_, IncomingPacketFeedbackVector(_)) |
+ .Times(1) |
+ .WillOnce(Invoke( |
+ [packets, this](const std::vector<PacketInfo>& feedback_vector) { |
+ ComparePacketVectors(packets, feedback_vector); |
+ })); |
+ adapter_->OnTransportFeedback(feedback); |
+} |
+ |
+TEST_F(TransportFeedbackAdapterTest, HandlesDroppedPackets) { |
+ std::vector<PacketInfo> packets; |
+ packets.push_back(PacketInfo(100, 200, 0, 1500, true)); |
+ packets.push_back(PacketInfo(110, 210, 1, 1500, true)); |
+ packets.push_back(PacketInfo(120, 220, 2, 1500, true)); |
+ packets.push_back(PacketInfo(130, 230, 3, 1500, true)); |
+ packets.push_back(PacketInfo(140, 240, 4, 1500, true)); |
+ |
+ const uint16_t kSendSideDropBefore = 1; |
+ const uint16_t kReceiveSideDropAfter = 3; |
+ |
+ for (const PacketInfo& packet : packets) { |
+ if (packet.sequence_number >= kSendSideDropBefore) { |
+ adapter_->OnPacketSent(packet.sequence_number, packet.send_time_ms, |
+ packet.payload_size, packet.was_paced); |
+ } |
+ } |
+ |
+ rtcp::TransportFeedback feedback; |
+ feedback.WithBase(packets[0].sequence_number, |
+ packets[0].arrival_time_ms * 1000); |
+ |
+ for (const PacketInfo& packet : packets) { |
+ if (packet.sequence_number <= kReceiveSideDropAfter) { |
+ EXPECT_TRUE(feedback.WithReceivedPacket(packet.sequence_number, |
+ packet.arrival_time_ms * 1000)); |
+ } |
+ } |
+ |
+ feedback.Build(); |
+ |
+ std::vector<PacketInfo> expected_packets( |
+ packets.begin() + kSendSideDropBefore, |
+ packets.begin() + kReceiveSideDropAfter + 1); |
+ |
+ EXPECT_CALL(*bitrate_estimator_, IncomingPacketFeedbackVector(_)) |
+ .Times(1) |
+ .WillOnce(Invoke([expected_packets, |
+ this](const std::vector<PacketInfo>& feedback_vector) { |
+ ComparePacketVectors(expected_packets, feedback_vector); |
+ })); |
+ adapter_->OnTransportFeedback(feedback); |
+} |
+ |
+TEST_F(TransportFeedbackAdapterTest, SendTimeWrapsBothWays) { |
+ int64_t kHighArrivalTimeMs = rtcp::TransportFeedback::kDeltaScaleFactor * |
+ (1L << 8) * ((1L << 23) - 1) / 1000; |
+ std::vector<PacketInfo> packets; |
+ packets.push_back(PacketInfo(kHighArrivalTimeMs - 64, 200, 0, 1500, true)); |
+ packets.push_back(PacketInfo(kHighArrivalTimeMs + 64, 210, 1, 1500, true)); |
+ packets.push_back(PacketInfo(kHighArrivalTimeMs, 220, 2, 1500, true)); |
+ |
+ for (const PacketInfo& packet : packets) { |
+ adapter_->OnPacketSent(packet.sequence_number, packet.send_time_ms, |
+ packet.payload_size, packet.was_paced); |
+ } |
+ |
+ for (size_t i = 0; i < packets.size(); ++i) { |
+ rtc::scoped_ptr<rtcp::TransportFeedback> feedback( |
+ new rtcp::TransportFeedback()); |
+ feedback->WithBase(packets[i].sequence_number, |
+ packets[i].arrival_time_ms * 1000); |
+ |
+ EXPECT_TRUE(feedback->WithReceivedPacket( |
+ packets[i].sequence_number, packets[i].arrival_time_ms * 1000)); |
+ |
+ rtc::scoped_ptr<rtcp::RawPacket> raw_packet = feedback->Build(); |
+ feedback = rtcp::TransportFeedback::ParseFrom(raw_packet->Buffer(), |
+ raw_packet->Length()); |
+ |
+ std::vector<PacketInfo> expected_packets; |
+ expected_packets.push_back(packets[i]); |
+ |
+ EXPECT_CALL(*bitrate_estimator_, IncomingPacketFeedbackVector(_)) |
+ .Times(1) |
+ .WillOnce(Invoke([expected_packets, this]( |
+ const std::vector<PacketInfo>& feedback_vector) { |
+ ComparePacketVectors(expected_packets, feedback_vector); |
+ })); |
+ adapter_->OnTransportFeedback(*feedback.get()); |
+ } |
+} |
+ |
stefan-webrtc
2015/09/11 08:15:12
Should we have a test for the limit on time deltas
sprang_webrtc
2015/09/11 12:33:48
Done.
|
+} // namespace test |
+} // namespace webrtc |